From 5e2eb7d67ae933b7566f1944d0bb7744da03d586 Mon Sep 17 00:00:00 2001 From: aura Date: Tue, 17 Feb 2026 23:42:09 +0100 Subject: move source stuff to its own folder --- source/sourcemod/scripting/include/GlobalAPI.inc | 822 ++++++ .../scripting/include/GlobalAPI/iterable.inc | 55 + .../scripting/include/GlobalAPI/request.inc | 185 ++ .../scripting/include/GlobalAPI/requestdata.inc | 534 ++++ .../scripting/include/GlobalAPI/responses.inc | 575 ++++ .../scripting/include/GlobalAPI/stocks.inc | 67 + source/sourcemod/scripting/include/SteamWorks.inc | 413 +++ source/sourcemod/scripting/include/admin.inc | 832 ++++++ source/sourcemod/scripting/include/adminmenu.inc | 152 + source/sourcemod/scripting/include/adt.inc | 40 + source/sourcemod/scripting/include/adt_array.inc | 469 +++ source/sourcemod/scripting/include/adt_stack.inc | 251 ++ source/sourcemod/scripting/include/adt_trie.inc | 332 +++ .../sourcemod/scripting/include/autoexecconfig.inc | 765 +++++ source/sourcemod/scripting/include/banning.inc | 156 + source/sourcemod/scripting/include/basecomm.inc | 109 + source/sourcemod/scripting/include/bitbuffer.inc | 470 +++ source/sourcemod/scripting/include/clientprefs.inc | 372 +++ source/sourcemod/scripting/include/clients.inc | 831 ++++++ source/sourcemod/scripting/include/colors.inc | 945 ++++++ .../sourcemod/scripting/include/commandfilters.inc | 171 ++ source/sourcemod/scripting/include/commandline.inc | 86 + source/sourcemod/scripting/include/console.inc | 780 +++++ source/sourcemod/scripting/include/convars.inc | 514 ++++ source/sourcemod/scripting/include/core.inc | 320 ++ source/sourcemod/scripting/include/cstrike.inc | 488 ++++ source/sourcemod/scripting/include/datapack.inc | 255 ++ source/sourcemod/scripting/include/dbi.inc | 1073 +++++++ source/sourcemod/scripting/include/dhooks.inc | 1100 +++++++ source/sourcemod/scripting/include/distbugfix.inc | 261 ++ source/sourcemod/scripting/include/entity.inc | 769 +++++ .../scripting/include/entity_prop_stocks.inc | 594 ++++ source/sourcemod/scripting/include/entitylump.inc | 157 + source/sourcemod/scripting/include/events.inc | 343 +++ source/sourcemod/scripting/include/files.inc | 628 ++++ source/sourcemod/scripting/include/float.inc | 460 +++ source/sourcemod/scripting/include/functions.inc | 631 ++++ source/sourcemod/scripting/include/gamechaos.inc | 20 + .../scripting/include/gamechaos/arrays.inc | 52 + .../scripting/include/gamechaos/client.inc | 300 ++ .../scripting/include/gamechaos/debug.inc | 19 + .../scripting/include/gamechaos/isvalidclient.inc | 16 + .../scripting/include/gamechaos/kreedzclimbing.inc | 226 ++ .../scripting/include/gamechaos/maths.inc | 362 +++ .../sourcemod/scripting/include/gamechaos/misc.inc | 245 ++ .../scripting/include/gamechaos/strings.inc | 367 +++ .../scripting/include/gamechaos/tempents.inc | 62 + .../scripting/include/gamechaos/tracing.inc | 242 ++ .../scripting/include/gamechaos/vectors.inc | 66 + source/sourcemod/scripting/include/geoip.inc | 241 ++ .../scripting/include/glib/addressutils.inc | 54 + .../scripting/include/glib/assertutils.inc | 61 + .../sourcemod/scripting/include/glib/memutils.inc | 232 ++ source/sourcemod/scripting/include/gokz.inc | 1097 +++++++ .../sourcemod/scripting/include/gokz/anticheat.inc | 168 ++ source/sourcemod/scripting/include/gokz/chat.inc | 45 + source/sourcemod/scripting/include/gokz/core.inc | 1920 ++++++++++++ source/sourcemod/scripting/include/gokz/global.inc | 317 ++ source/sourcemod/scripting/include/gokz/hud.inc | 468 +++ .../sourcemod/scripting/include/gokz/jumpbeam.inc | 148 + .../sourcemod/scripting/include/gokz/jumpstats.inc | 442 +++ .../sourcemod/scripting/include/gokz/kzplayer.inc | 584 ++++ .../sourcemod/scripting/include/gokz/localdb.inc | 353 +++ .../scripting/include/gokz/localranks.inc | 176 ++ .../scripting/include/gokz/momsurffix.inc | 23 + source/sourcemod/scripting/include/gokz/paint.inc | 114 + source/sourcemod/scripting/include/gokz/pistol.inc | 93 + .../sourcemod/scripting/include/gokz/profile.inc | 291 ++ source/sourcemod/scripting/include/gokz/quiet.inc | 205 ++ source/sourcemod/scripting/include/gokz/racing.inc | 189 ++ .../sourcemod/scripting/include/gokz/replays.inc | 275 ++ .../sourcemod/scripting/include/gokz/slayonend.inc | 43 + source/sourcemod/scripting/include/gokz/tips.inc | 59 + .../scripting/include/gokz/tpanglefix.inc | 40 + .../sourcemod/scripting/include/gokz/version.inc | 12 + source/sourcemod/scripting/include/halflife.inc | 711 +++++ source/sourcemod/scripting/include/handles.inc | 98 + source/sourcemod/scripting/include/helpers.inc | 287 ++ source/sourcemod/scripting/include/json.inc | 473 +++ .../scripting/include/json/decode_helpers.inc | 312 ++ .../scripting/include/json/definitions.inc | 103 + .../scripting/include/json/encode_helpers.inc | 164 ++ .../scripting/include/json/helpers/decode.inc | 502 ++++ .../scripting/include/json/helpers/encode.inc | 200 ++ .../scripting/include/json/helpers/string.inc | 133 + source/sourcemod/scripting/include/json/object.inc | 1014 +++++++ .../scripting/include/json/string_helpers.inc | 77 + source/sourcemod/scripting/include/keyvalues.inc | 707 +++++ source/sourcemod/scripting/include/lang.inc | 134 + source/sourcemod/scripting/include/logging.inc | 135 + source/sourcemod/scripting/include/mapchooser.inc | 164 ++ source/sourcemod/scripting/include/menus.inc | 1154 ++++++++ source/sourcemod/scripting/include/morecolors.inc | 674 +++++ source/sourcemod/scripting/include/movement.inc | 530 ++++ source/sourcemod/scripting/include/movementapi.inc | 663 +++++ source/sourcemod/scripting/include/nextmap.inc | 82 + source/sourcemod/scripting/include/profiler.inc | 123 + source/sourcemod/scripting/include/protobuf.inc | 602 ++++ source/sourcemod/scripting/include/regex.inc | 291 ++ source/sourcemod/scripting/include/sdkhooks.inc | 457 +++ source/sourcemod/scripting/include/sdktools.inc | 232 ++ .../scripting/include/sdktools_client.inc | 52 + .../scripting/include/sdktools_engine.inc | 66 + .../scripting/include/sdktools_entinput.inc | 51 + .../scripting/include/sdktools_entoutput.inc | 108 + .../scripting/include/sdktools_functions.inc | 418 +++ .../scripting/include/sdktools_gamerules.inc | 199 ++ .../sourcemod/scripting/include/sdktools_hooks.inc | 112 + .../sourcemod/scripting/include/sdktools_sound.inc | 719 +++++ .../scripting/include/sdktools_stocks.inc | 75 + .../scripting/include/sdktools_stringtables.inc | 180 ++ .../scripting/include/sdktools_tempents.inc | 232 ++ .../scripting/include/sdktools_tempents_stocks.inc | 443 +++ .../sourcemod/scripting/include/sdktools_trace.inc | 716 +++++ .../scripting/include/sdktools_variant_t.inc | 93 + .../sourcemod/scripting/include/sdktools_voice.inc | 143 + source/sourcemod/scripting/include/smjansson.inc | 1328 +++++++++ source/sourcemod/scripting/include/smlib.inc | 32 + .../sourcemod/scripting/include/smlib/arrays.inc | 157 + .../sourcemod/scripting/include/smlib/clients.inc | 3077 ++++++++++++++++++++ .../sourcemod/scripting/include/smlib/colors.inc | 575 ++++ .../scripting/include/smlib/concommands.inc | 45 + .../sourcemod/scripting/include/smlib/convars.inc | 71 + source/sourcemod/scripting/include/smlib/crypt.inc | 625 ++++ source/sourcemod/scripting/include/smlib/debug.inc | 28 + .../scripting/include/smlib/dynarrays.inc | 24 + .../sourcemod/scripting/include/smlib/edicts.inc | 127 + .../sourcemod/scripting/include/smlib/effects.inc | 722 +++++ .../sourcemod/scripting/include/smlib/entities.inc | 2098 +++++++++++++ source/sourcemod/scripting/include/smlib/files.inc | 451 +++ source/sourcemod/scripting/include/smlib/game.inc | 57 + .../sourcemod/scripting/include/smlib/general.inc | 251 ++ source/sourcemod/scripting/include/smlib/math.inc | 346 +++ source/sourcemod/scripting/include/smlib/menus.inc | 37 + .../sourcemod/scripting/include/smlib/server.inc | 135 + source/sourcemod/scripting/include/smlib/sql.inc | 107 + .../sourcemod/scripting/include/smlib/strings.inc | 228 ++ source/sourcemod/scripting/include/smlib/teams.inc | 317 ++ .../sourcemod/scripting/include/smlib/vehicles.inc | 137 + .../sourcemod/scripting/include/smlib/weapons.inc | 393 +++ source/sourcemod/scripting/include/smlib/world.inc | 16 + source/sourcemod/scripting/include/sorting.inc | 169 ++ .../sourcemod/scripting/include/sourcebanspp.inc | 106 + .../scripting/include/sourcemod-colors.inc | 921 ++++++ source/sourcemod/scripting/include/sourcemod.inc | 772 +++++ source/sourcemod/scripting/include/string.inc | 590 ++++ source/sourcemod/scripting/include/testing.inc | 95 + source/sourcemod/scripting/include/textparse.inc | 255 ++ source/sourcemod/scripting/include/tf2.inc | 501 ++++ source/sourcemod/scripting/include/tf2_stocks.inc | 643 ++++ source/sourcemod/scripting/include/timers.inc | 200 ++ source/sourcemod/scripting/include/topmenus.inc | 446 +++ source/sourcemod/scripting/include/updater.inc | 97 + .../sourcemod/scripting/include/usermessages.inc | 270 ++ source/sourcemod/scripting/include/vector.inc | 179 ++ source/sourcemod/scripting/include/version.inc | 49 + .../sourcemod/scripting/include/version_auto.inc | 15 + 157 files changed, 56953 insertions(+) create mode 100644 source/sourcemod/scripting/include/GlobalAPI.inc create mode 100644 source/sourcemod/scripting/include/GlobalAPI/iterable.inc create mode 100644 source/sourcemod/scripting/include/GlobalAPI/request.inc create mode 100644 source/sourcemod/scripting/include/GlobalAPI/requestdata.inc create mode 100644 source/sourcemod/scripting/include/GlobalAPI/responses.inc create mode 100644 source/sourcemod/scripting/include/GlobalAPI/stocks.inc create mode 100644 source/sourcemod/scripting/include/SteamWorks.inc create mode 100644 source/sourcemod/scripting/include/admin.inc create mode 100644 source/sourcemod/scripting/include/adminmenu.inc create mode 100644 source/sourcemod/scripting/include/adt.inc create mode 100644 source/sourcemod/scripting/include/adt_array.inc create mode 100644 source/sourcemod/scripting/include/adt_stack.inc create mode 100644 source/sourcemod/scripting/include/adt_trie.inc create mode 100644 source/sourcemod/scripting/include/autoexecconfig.inc create mode 100644 source/sourcemod/scripting/include/banning.inc create mode 100644 source/sourcemod/scripting/include/basecomm.inc create mode 100644 source/sourcemod/scripting/include/bitbuffer.inc create mode 100644 source/sourcemod/scripting/include/clientprefs.inc create mode 100644 source/sourcemod/scripting/include/clients.inc create mode 100644 source/sourcemod/scripting/include/colors.inc create mode 100644 source/sourcemod/scripting/include/commandfilters.inc create mode 100644 source/sourcemod/scripting/include/commandline.inc create mode 100644 source/sourcemod/scripting/include/console.inc create mode 100644 source/sourcemod/scripting/include/convars.inc create mode 100644 source/sourcemod/scripting/include/core.inc create mode 100644 source/sourcemod/scripting/include/cstrike.inc create mode 100644 source/sourcemod/scripting/include/datapack.inc create mode 100644 source/sourcemod/scripting/include/dbi.inc create mode 100644 source/sourcemod/scripting/include/dhooks.inc create mode 100644 source/sourcemod/scripting/include/distbugfix.inc create mode 100644 source/sourcemod/scripting/include/entity.inc create mode 100644 source/sourcemod/scripting/include/entity_prop_stocks.inc create mode 100644 source/sourcemod/scripting/include/entitylump.inc create mode 100644 source/sourcemod/scripting/include/events.inc create mode 100644 source/sourcemod/scripting/include/files.inc create mode 100644 source/sourcemod/scripting/include/float.inc create mode 100644 source/sourcemod/scripting/include/functions.inc create mode 100644 source/sourcemod/scripting/include/gamechaos.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/arrays.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/client.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/debug.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/isvalidclient.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/kreedzclimbing.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/maths.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/misc.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/strings.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/tempents.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/tracing.inc create mode 100644 source/sourcemod/scripting/include/gamechaos/vectors.inc create mode 100644 source/sourcemod/scripting/include/geoip.inc create mode 100644 source/sourcemod/scripting/include/glib/addressutils.inc create mode 100644 source/sourcemod/scripting/include/glib/assertutils.inc create mode 100644 source/sourcemod/scripting/include/glib/memutils.inc create mode 100644 source/sourcemod/scripting/include/gokz.inc create mode 100644 source/sourcemod/scripting/include/gokz/anticheat.inc create mode 100644 source/sourcemod/scripting/include/gokz/chat.inc create mode 100644 source/sourcemod/scripting/include/gokz/core.inc create mode 100644 source/sourcemod/scripting/include/gokz/global.inc create mode 100644 source/sourcemod/scripting/include/gokz/hud.inc create mode 100644 source/sourcemod/scripting/include/gokz/jumpbeam.inc create mode 100644 source/sourcemod/scripting/include/gokz/jumpstats.inc create mode 100644 source/sourcemod/scripting/include/gokz/kzplayer.inc create mode 100644 source/sourcemod/scripting/include/gokz/localdb.inc create mode 100644 source/sourcemod/scripting/include/gokz/localranks.inc create mode 100644 source/sourcemod/scripting/include/gokz/momsurffix.inc create mode 100644 source/sourcemod/scripting/include/gokz/paint.inc create mode 100644 source/sourcemod/scripting/include/gokz/pistol.inc create mode 100644 source/sourcemod/scripting/include/gokz/profile.inc create mode 100644 source/sourcemod/scripting/include/gokz/quiet.inc create mode 100644 source/sourcemod/scripting/include/gokz/racing.inc create mode 100644 source/sourcemod/scripting/include/gokz/replays.inc create mode 100644 source/sourcemod/scripting/include/gokz/slayonend.inc create mode 100644 source/sourcemod/scripting/include/gokz/tips.inc create mode 100644 source/sourcemod/scripting/include/gokz/tpanglefix.inc create mode 100644 source/sourcemod/scripting/include/gokz/version.inc create mode 100644 source/sourcemod/scripting/include/halflife.inc create mode 100644 source/sourcemod/scripting/include/handles.inc create mode 100644 source/sourcemod/scripting/include/helpers.inc create mode 100644 source/sourcemod/scripting/include/json.inc create mode 100644 source/sourcemod/scripting/include/json/decode_helpers.inc create mode 100644 source/sourcemod/scripting/include/json/definitions.inc create mode 100644 source/sourcemod/scripting/include/json/encode_helpers.inc create mode 100644 source/sourcemod/scripting/include/json/helpers/decode.inc create mode 100644 source/sourcemod/scripting/include/json/helpers/encode.inc create mode 100644 source/sourcemod/scripting/include/json/helpers/string.inc create mode 100644 source/sourcemod/scripting/include/json/object.inc create mode 100644 source/sourcemod/scripting/include/json/string_helpers.inc create mode 100644 source/sourcemod/scripting/include/keyvalues.inc create mode 100644 source/sourcemod/scripting/include/lang.inc create mode 100644 source/sourcemod/scripting/include/logging.inc create mode 100644 source/sourcemod/scripting/include/mapchooser.inc create mode 100644 source/sourcemod/scripting/include/menus.inc create mode 100644 source/sourcemod/scripting/include/morecolors.inc create mode 100644 source/sourcemod/scripting/include/movement.inc create mode 100644 source/sourcemod/scripting/include/movementapi.inc create mode 100644 source/sourcemod/scripting/include/nextmap.inc create mode 100644 source/sourcemod/scripting/include/profiler.inc create mode 100644 source/sourcemod/scripting/include/protobuf.inc create mode 100644 source/sourcemod/scripting/include/regex.inc create mode 100644 source/sourcemod/scripting/include/sdkhooks.inc create mode 100644 source/sourcemod/scripting/include/sdktools.inc create mode 100644 source/sourcemod/scripting/include/sdktools_client.inc create mode 100644 source/sourcemod/scripting/include/sdktools_engine.inc create mode 100644 source/sourcemod/scripting/include/sdktools_entinput.inc create mode 100644 source/sourcemod/scripting/include/sdktools_entoutput.inc create mode 100644 source/sourcemod/scripting/include/sdktools_functions.inc create mode 100644 source/sourcemod/scripting/include/sdktools_gamerules.inc create mode 100644 source/sourcemod/scripting/include/sdktools_hooks.inc create mode 100644 source/sourcemod/scripting/include/sdktools_sound.inc create mode 100644 source/sourcemod/scripting/include/sdktools_stocks.inc create mode 100644 source/sourcemod/scripting/include/sdktools_stringtables.inc create mode 100644 source/sourcemod/scripting/include/sdktools_tempents.inc create mode 100644 source/sourcemod/scripting/include/sdktools_tempents_stocks.inc create mode 100644 source/sourcemod/scripting/include/sdktools_trace.inc create mode 100644 source/sourcemod/scripting/include/sdktools_variant_t.inc create mode 100644 source/sourcemod/scripting/include/sdktools_voice.inc create mode 100644 source/sourcemod/scripting/include/smjansson.inc create mode 100644 source/sourcemod/scripting/include/smlib.inc create mode 100644 source/sourcemod/scripting/include/smlib/arrays.inc create mode 100644 source/sourcemod/scripting/include/smlib/clients.inc create mode 100644 source/sourcemod/scripting/include/smlib/colors.inc create mode 100644 source/sourcemod/scripting/include/smlib/concommands.inc create mode 100644 source/sourcemod/scripting/include/smlib/convars.inc create mode 100644 source/sourcemod/scripting/include/smlib/crypt.inc create mode 100644 source/sourcemod/scripting/include/smlib/debug.inc create mode 100644 source/sourcemod/scripting/include/smlib/dynarrays.inc create mode 100644 source/sourcemod/scripting/include/smlib/edicts.inc create mode 100644 source/sourcemod/scripting/include/smlib/effects.inc create mode 100644 source/sourcemod/scripting/include/smlib/entities.inc create mode 100644 source/sourcemod/scripting/include/smlib/files.inc create mode 100644 source/sourcemod/scripting/include/smlib/game.inc create mode 100644 source/sourcemod/scripting/include/smlib/general.inc create mode 100644 source/sourcemod/scripting/include/smlib/math.inc create mode 100644 source/sourcemod/scripting/include/smlib/menus.inc create mode 100644 source/sourcemod/scripting/include/smlib/server.inc create mode 100644 source/sourcemod/scripting/include/smlib/sql.inc create mode 100644 source/sourcemod/scripting/include/smlib/strings.inc create mode 100644 source/sourcemod/scripting/include/smlib/teams.inc create mode 100644 source/sourcemod/scripting/include/smlib/vehicles.inc create mode 100644 source/sourcemod/scripting/include/smlib/weapons.inc create mode 100644 source/sourcemod/scripting/include/smlib/world.inc create mode 100644 source/sourcemod/scripting/include/sorting.inc create mode 100644 source/sourcemod/scripting/include/sourcebanspp.inc create mode 100644 source/sourcemod/scripting/include/sourcemod-colors.inc create mode 100644 source/sourcemod/scripting/include/sourcemod.inc create mode 100644 source/sourcemod/scripting/include/string.inc create mode 100644 source/sourcemod/scripting/include/testing.inc create mode 100644 source/sourcemod/scripting/include/textparse.inc create mode 100644 source/sourcemod/scripting/include/tf2.inc create mode 100644 source/sourcemod/scripting/include/tf2_stocks.inc create mode 100644 source/sourcemod/scripting/include/timers.inc create mode 100644 source/sourcemod/scripting/include/topmenus.inc create mode 100644 source/sourcemod/scripting/include/updater.inc create mode 100644 source/sourcemod/scripting/include/usermessages.inc create mode 100644 source/sourcemod/scripting/include/vector.inc create mode 100644 source/sourcemod/scripting/include/version.inc create mode 100644 source/sourcemod/scripting/include/version_auto.inc (limited to 'source/sourcemod/scripting/include') diff --git a/source/sourcemod/scripting/include/GlobalAPI.inc b/source/sourcemod/scripting/include/GlobalAPI.inc new file mode 100644 index 0000000..8813645 --- /dev/null +++ b/source/sourcemod/scripting/include/GlobalAPI.inc @@ -0,0 +1,822 @@ +// ================== DOUBLE INCLUDE ========================= // + +#if defined _GlobalAPI_included_ +#endinput +#endif +#define _GlobalAPI_included_ + +// ======================= DEFINITIONS ======================= // + +#define DEFAULT_DATA 0 +#define DEFAULT_INT -1 +#define DEFAULT_STRING "" +#define DEFAULT_FLOAT -1.0 +#define DEFAULT_BOOL view_as(-1) + +#define GlobalAPI_Plugin_Version "2.0.0" +#define GlobalAPI_Plugin_Desc "Plugin helper for GlobalAPI Production & Staging" +#define GlobalAPI_Plugin_Url "https://bitbucket.org/kztimerglobalteam/GlobalAPI-SMPlugin" +#define GlobalAPI_Plugin_NameVersion "GlobalAPI Plugin " ... GlobalAPI_Plugin_Version + +#define GlobalAPI_Backend_Version "v2.0" +#define GlobalAPI_Backend_Staging_Version "v2.0" +#define GlobalAPI_BaseUrl "https://kztimerglobal.com/api/" ... GlobalAPI_Backend_Version +#define GlobalAPI_Staging_BaseUrl "https://globalapi.ruto.sh/api/" ... GlobalAPI_Backend_Staging_Version + +#define GlobalAPI_Max_BaseUrl_Length 128 +#define GlobalAPI_Max_QueryParam_Num 20 +#define GlobalAPI_Max_QueryParam_Length 64 +#define GlobalAPI_Max_QueryParams_Length (GlobalAPI_Max_QueryParam_Num * GlobalAPI_Max_QueryParam_Length) +#define GlobalAPI_Max_QueryUrl_Length (GlobalAPI_Max_QueryParams_Length + GlobalAPI_Max_BaseUrl_Length) +#define GlobalAPI_Max_QueryParam_Array_Length 64 + +#define GlobalAPI_Max_APIKey_Length 128 +#define GlobalAPI_Max_PluginName_Length 64 +#define GlobalAPI_Max_PluginVersion_Length 32 +#define GlobalAPI_Data_File_Extension "GAPI" + +// ======================= INCLUDES ========================== // + +#include +#include +#include + +// ======================= ENUMS ============================= // + +/** + * Defines what request method is used on requests + */ +enum +{ + GlobalAPIRequestType_GET = 0, /**< Request uses GET HTTP method */ + GlobalAPIRequestType_POST /**< Request uses POST HTTP method */ +}; + +/** + * Defines what accept type is used on requests + */ +enum +{ + GlobalAPIRequestAcceptType_JSON = 0, /**< Request uses application/json HTTP accept type */ + GlobalAPIRequestAcceptType_OctetStream /**< Request uses application/octet-stream HTTP accept type */ +}; + +/** + * Defines what content type is used on requests + */ +enum +{ + GlobalAPIRequestContentType_JSON = 0, /**< Request uses application/json HTTP content type */ + GlobalAPIRequestContentType_OctetStream /**< Request uses application/octet-stream HTTP content type */ +}; + +// ======================= TYPEDEFS ========================== // + +/* + Function types when API call finishes +*/ +typeset OnAPICallFinished +{ + /** + * Called when an API call has finished + * + * @param hResponse JSON_Object handle to the response + * @param hData GlobalAPIRequestData handle for the request + * @noreturn + */ + function void(JSON_Object hResponse, GlobalAPIRequestData hData); + + /** + * Called when an API call has finished + * + * @param hResponse JSON_Object handle to the response + * @param hData GlobalAPIRequestData handle for the request + * @param data Optional data that was passed + * @noreturn + */ + function void(JSON_Object hResponse, GlobalAPIRequestData hData, any data); +}; + +// ======================= FORWARDS ========================== // + +/** + * Called when GlobalAPI plugin is initialized, + * this means API Key is loaded and all the cvars are loaded + * + * @noreturn + */ +forward void GlobalAPI_OnInitialized(); + +/** + * Called when GlobalAPI plugin has failed a request + * + * @param request Handle to the request failed + * @param hData Handle to request's GlobalAPIRequestData + * @noreturn + */ +forward void GlobalAPI_OnRequestFailed(Handle request, GlobalAPIRequestData hData); + +/** + * Called when GlobalAPI plugin has started a request + * + * @param request Handle to the request started + * @param hData Handle to request's GlobalAPIRequestData + * @noreturn + */ +forward void GlobalAPI_OnRequestStarted(Handle request, GlobalAPIRequestData hData); + +/** + * Called when GlobalAPI plugin has finished a request + * + * @param request Handle to the request finished + * @param hData Handle to request's GlobalAPIRequestData + * @noreturn + */ +forward void GlobalAPI_OnRequestFinished(Handle request, GlobalAPIRequestData hData); + +// ======================= NATIVES =========================== // + +/** + * Gets a boolean of whether GlobalAPI plugin is initialized. + * + * @note See GlobalAPI_OnInitialized for the event version. + * @return Whether GlobalAPI plugin is initialized. + */ +native bool GlobalAPI_IsInit(); + +/** + * Gets the API Key used by GlobalAPI plugin + * + * @param buffer Buffer to store result in + * @param maxlength Max length of the buffer + * @noreturn + */ +native void GlobalAPI_GetAPIKey(char[] buffer, int maxlength); + +/** + * Gets whether GlobalAPI is using an API Key + * + * @note This does not mean the API Key is valid! + * @return Whether API Key is used by GlobalAPI plugin + */ +native bool GlobalAPI_HasAPIKey(); + +/** + * Gets whether GlobalAPI is using the staging endpoint + * + * @note It is not safe to call this before GlobalAPI_OnInitialized! + * @return Whether staging endpoint is used by GlobalAPI plugin + */ +native bool GlobalAPI_IsStaging(); + +/** + * Gets whether GlobalAPI is in debug mode + * + * @note It is not safe to call this before GlobalAPI_OnInitialized! + * @return Whether GlobalAPI plugin is in debug mode + */ +native bool GlobalAPI_IsDebugging(); + +/** + * Sends a request in GlobalAPI plugin format + * + * @param hData Handle to GlobalAPIRequestData + * @return Whether the request was sent successfully + */ +native bool GlobalAPI_SendRequest(GlobalAPIRequestData hData); + +/** + * Sends a debug message to GlobalAPI plugin logs if debugging is enabled + * + * @param message Formatting rules + * @param ... Variable number of format parameters + * @note This is not safe to use before convars have loaded + * @return Whether the message was logged + */ +native bool GlobalAPI_DebugMessage(const char[] message, any ...); + +/** + * Starts a GET HTTP Request to /api/{version}/auth/status + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetAuthStatus(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA); + +/** + * Starts a GET HTTP Request to /api/{version}/bans + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param banTypes Ban types to query + * @param banTypesList -Unsupported at the moment- + * @param isExpired Whether to query for isExpired or not + * @param ipAddress IP address to query + * @param steamId64 SteamID64 to query + * @param steamId SteamID2 to query + * @param notesContain Notes to query + * @param statsContain Stats to query + * @param serverId Server ID to query + * @param createdSince Created since date to query + * @param updatedSince Updated since date to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetBans(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] banTypes = DEFAULT_STRING, + const char[] banTypesList = DEFAULT_STRING, bool isExpired = DEFAULT_BOOL, const char[] ipAddress = DEFAULT_STRING, + const char[] steamId64 = DEFAULT_STRING, const char[] steamId = DEFAULT_STRING, const char[] notesContain = DEFAULT_STRING, + const char[] statsContain = DEFAULT_STRING, int serverId = DEFAULT_INT, const char[] createdSince = DEFAULT_STRING, + const char[] updatedSince = DEFAULT_STRING, int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a POST HTTP Request to /api/{version}/bans + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 of the user + * @param banType Type of the ban + * @param stats Stats of the ban + * @param notes Notes of the ban + * @param ipAddress IP address of the user + * @return Whether request was successfully sent + */ +native bool GlobalAPI_CreateBan(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + const char[] steamId, const char[] banType, const char[] stats, + const char[] notes, const char[] ipAddress); + +/** + * Starts a GET HTTP Request to /api/{version}/jumpstats + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param id Id to query + * @param serverId Server id to query + * @param steamId64 SteamID64 to query + * @param steamId SteamID2 to query + * @param jumpType Jump type to query + * @param steamId64List -Unsupported at the moment- + * @param jumpTypeList -Unsupported at the moment- + * @param greaterThanDistance Greater than distance to query + * @param lessThanDistance Less than distance to query + * @param isMsl Whether to query for isMsl or not + * @param isCrouchBind Whether to query for isCrouchBind or not + * @param isForwardBind Whether to query for isForwardBind or not + * @param isCrouchBoost Whether to query for isCrouchBoost or not + * @param updatedById Updated by id to query + * @param createdSince Created since date to query + * @param updatedSince Updated since date to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetJumpstats(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int id = DEFAULT_INT, + int serverId = DEFAULT_INT, const char[] steamId64 = DEFAULT_STRING, const char[] steamId = DEFAULT_STRING, + const char[] jumpType = DEFAULT_STRING, const char[] steamId64List = DEFAULT_STRING, + const char[] jumpTypeList = DEFAULT_STRING, float greaterThanDistance = DEFAULT_FLOAT, + float lessThanDistance = DEFAULT_FLOAT, bool isMsl = DEFAULT_BOOL, bool isCrouchBind = DEFAULT_BOOL, + bool isForwardBind = DEFAULT_BOOL, bool isCrouchBoost = DEFAULT_BOOL, int updatedById = DEFAULT_INT, + const char[] createdSince = DEFAULT_STRING, const char[] updatedSince = DEFAULT_STRING, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a POST HTTP Request to /api/{version}/jumpstats + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 of the user + * @param jumpType Type of the jump + * @param distance Distance of the jump + * @param jumpJsonInfo Data of the jump + * @param tickRate Tickrate of the server + * @param mslCount Msl count of the jump + * @param isCrouchBind Whether crouch bind was used + * @param isForwardBind Whether forward bind was used + * @param isCrouchBoost Whether crouch boost was used + * @param strafeCount Strafe count of the jump + * @return Whether request was successfully sent + */ +native bool GlobalAPI_CreateJumpstat(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] steamId, + int jumpType, float distance, const char[] jumpJsonInfo, int tickRate, int mslCount, + bool isCrouchBind, bool isForwardBind, bool isCrouchBoost, int strafeCount); + +/** + * Starts a GET HTTP Request to /api/{version}/jumpstats/{jump_type}/top + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param jumpType Jump type to query + * @param id Id to query + * @param serverId Server Id to query + * @param steamId64 SteamID64 to query + * @param steamId SteamID2 to query + * @param steamId64List -Unsupported at the moment- + * @param jumpTypeList -Unsupported at the moment- + * @param greaterThanDistance Greater than distance to query + * @param lessThanDistance Less than distance to query + * @param isMsl Whether to query for isMsl or not + * @param isCrouchBind Whether to query for isCrouchBind or not + * @param isForwardBind Whether to query for isForwardBind or not + * @param isCrouchBoost Whether to query for isCrouchBoost or not + * @param updatedById Updated by id to query + * @param createdSince Created since date to query + * @param updatedSince Updated since date to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetJumpstatTop(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] jumpType, + int id = DEFAULT_INT, int serverId = DEFAULT_INT, const char[] steamId64 = DEFAULT_STRING, + const char[] steamId = DEFAULT_STRING, const char[] steamId64List = DEFAULT_STRING, + const char[] jumpTypeList = DEFAULT_STRING, float greaterThanDistance = DEFAULT_FLOAT, + float lessThanDistance = DEFAULT_FLOAT, bool isMsl = DEFAULT_BOOL, bool isCrouchBind = DEFAULT_BOOL, + bool isForwardBind = DEFAULT_BOOL, bool isCrouchBoost = DEFAULT_BOOL, int updatedById = DEFAULT_INT, + const char[] createdSince = DEFAULT_STRING, const char[] updatedSince = DEFAULT_STRING, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/jumpstats/{jump_type}/top30 + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param jumpType Jump type to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetJumpstatTop30(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] jumpType); + +/** + * Starts a GET HTTP Request to /api/{version}/maps + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param name Map name to query + * @param largerThanFilesize Larger than filesize to query + * @param smallerThanFilesize Smaller than filesize to query + * @param isValidated Whether to query for isValidated or not + * @param difficulty Map difficulty to query + * @param createdSince Created since date to query + * @param updatedSince Updated since date to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetMaps(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] name = DEFAULT_STRING, + int largerThanFilesize = DEFAULT_INT, int smallerThanFilesize = DEFAULT_INT, bool isValidated = DEFAULT_BOOL, + int difficulty = DEFAULT_INT, const char[] createdSince = DEFAULT_STRING, const char[] updatedSince = DEFAULT_STRING, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/maps/{id} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param id Map id to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetMapById(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int id); + +/** + * Starts a GET HTTP Request to /api/{version}/maps/name/{map_name} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param name Map name to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetMapByName(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] name); + +/** + * Starts a GET HTTP Request to /api/{version}/modes + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetModes(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA); + +/** + * Starts a GET HTTP Request to /api/{version}/modes/id/{id} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param id Mode id to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetModeById(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int id); + +/** + * Starts a GET HTTP Request to /api/{version}/modes/name/{mode_name} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param name Mode name to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetModeByName(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] name); + +/** + * Starts a GET HTTP Request to /api/{version}/players + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 to query + * @param isBanned Whether to query for isBanned or not + * @param totalRecords Total records to query + * @param ipAddress IP address to query + * @param steamId64List -Unsupported at the moment- + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetPlayers(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] steamId = DEFAULT_STRING, + bool isBanned = DEFAULT_BOOL, int totalRecords = DEFAULT_INT, const char[] ipAddress = DEFAULT_STRING, + const char[] steamId64List = DEFAULT_STRING); + +/** + * Starts a GET HTTP Request to /api/{version}/players/steamid/{steamid} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetPlayerBySteamId(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] steamId); + +/** + * Starts a GET HTTP Request to /api/{version}/players/steamid/{steamid}/ip/{ip} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 to query + * @param ipAddress IP address to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetPlayerBySteamIdAndIp(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + const char[] steamId, const char[] ipAddress); + +/** + * Starts a POST HTTP Request to /api/{version}/records + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 of the user + * @param mapId Map id of the record + * @param mode Mode of the record + * @param stage Stage of the record + * @param tickRate Tickrate of the server + * @param teleports Teleport count of the record + * @param time Elapsed time of the record + * @return Whether request was successfully sent + */ +native bool GlobalAPI_CreateRecord(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] steamId, + int mapId, const char[] mode, int stage, int tickRate, int teleports, float time); + +/** + * Starts a GET HTTP Request to /api/{version}/records/place/{id} + * + * @note This is deprecated! + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param id Id to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetRecordPlaceById(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int id); + +/** + * Starts a GET HTTP Request to /api/{version}/records/top + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 to query + * @param steamId64 SteamID64 to query + * @param mapId Map id to query + * @param mapName Map name to query + * @param tickRate Tickrate to query + * @param stage Stage to query + * @param modes Mode(s) to query + * @param hasTeleports Whether to query for hasTeleports or not + * @param playerName Player name to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetRecordsTop(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + const char[] steamId = DEFAULT_STRING, const char[] steamId64 = DEFAULT_STRING, int mapId = DEFAULT_INT, + const char[] mapName = DEFAULT_STRING, int tickRate = DEFAULT_INT, int stage = DEFAULT_INT, + const char[] modes = DEFAULT_STRING, bool hasTeleports = DEFAULT_BOOL, + const char[] playerName = DEFAULT_STRING, int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/records/top/recent + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param steamId SteamID2 to query + * @param steamId64 SteamID64 to query + * @param mapId Map id to query + * @param mapName Map name to query + * @param tickRate Tickrate to query + * @param stage Stage to query + * @param modes Mode(s) to query + * @param topAtLeast Place top at least to query + * @param topOverallAtLeast Place top overall at least to query + * @param hasTeleports Whether to query for hasTeleports or not + * @param createdSince Created since date to query + * @param playerName Player name to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetRecordsTopRecent(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + const char[] steamId = DEFAULT_STRING, const char[] steamId64 = DEFAULT_STRING, + int mapId = DEFAULT_INT, const char[] mapName = DEFAULT_STRING, + int tickRate = DEFAULT_INT, int stage = DEFAULT_INT, + const char[] modes = DEFAULT_STRING, int topAtLeast = DEFAULT_INT, + int topOverallAtLeast = DEFAULT_INT, bool hasTeleports = DEFAULT_BOOL, + const char[] createdSince = DEFAULT_STRING, const char[] playerName = DEFAULT_STRING, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/records/top/world_records + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param ids Array of ids to query + * @param idsLength Length of the ids array + * @param mapIds Array of map ids to query + * @param mapIdsLength Length of the map ids array + * @param stages Array of stages to query + * @param stagesLength Length of the stages array + * @param modeIds Array of mode ids to query + * @param modeIdsLength Length of the mode ids array + * @param tickRates Array of tickrates to query + * @param tickRatesLength Length of the tickrates array + * @param hasTeleports Whether to query for hasTeleports or not + * @param mapTag Map tags to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetRecordsTopWorldRecords(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int[] ids = {}, int idsLength = DEFAULT_INT, + int[] mapIds = {}, int mapIdsLength = DEFAULT_INT, + int[] stages = {}, int stagesLength = DEFAULT_INT, + int[] modeIds = {}, int modeIdsLength = DEFAULT_INT, + int[] tickRates = {}, int tickRatesLength = DEFAULT_INT, + bool hasTeleports = DEFAULT_BOOL, char[] mapTag = DEFAULT_STRING, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/servers + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param id Id to query + * @param port Port to query + * @param ip IP address to query + * @param name Server name to query + * @param ownerSteamId64 Owner's steamid64 to query + * @param approvalStatus Approval status to query + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetServers(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int id = DEFAULT_INT, int port = DEFAULT_INT, const char[] ip = DEFAULT_STRING, + const char[] name = DEFAULT_STRING, const char[] ownerSteamId64 = DEFAULT_STRING, + int approvalStatus = DEFAULT_INT, int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/servers/{id} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param id Id to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetServerById(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int id); + +/** + * Starts a GET HTTP Request to /api/{version}/servers/name/{server_name} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param serverName Server name to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetServersByName(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, const char[] serverName); + +/** + * Starts a GET HTTP Request to /api/{version}/player_ranks + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param pointsGreaterThan Points greater than to query + * @param averageGreaterThan Average greater than to query + * @param ratingGreaterThan Rating greater than to query + * @param finishesGreaterThan Finishes greater than to query + * @param steamId64List Comma-separated stirng of steamid64s to query + * @param recordFilterIds Array of record filter ids to query + * @param recordFilterIdsLength Length of the record filter ids array + * @param mapIds Array of map ids to query + * @param mapIdsLength Length of the map ids array + * @param stages Array of stages to query + * @param stagesLength Length of the stages array + * @param modeIds Array of mode ids to query + * @param modeIdsLength Length of the mode ids array + * @param tickRates Array of tickrates to query + * @param tickRatesLength Length of the tickrates array + * @param hasTeleports Whether to query for hasTeleports or not + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetPlayerRanks(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int pointsGreaterThan = DEFAULT_INT, float averageGreaterThan = DEFAULT_FLOAT, + float ratingGreaterThan = DEFAULT_FLOAT, int finishesGreaterThan = DEFAULT_INT, + const char[] steamId64List = DEFAULT_STRING, + int[] recordFilterIds = {}, int recordFilterIdsLength = DEFAULT_INT, + int[] mapIds = {}, int mapIdsLength = DEFAULT_INT, + int[] stages = {}, int stagesLength = DEFAULT_INT, + int[] modeIds = {}, int modeIdsLength = DEFAULT_INT, + int[] tickRates = {}, int tickRatesLength = DEFAULT_INT, + bool hasTeleports = DEFAULT_BOOL, int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/record_filters + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param ids Array of ids to query + * @param idsLength Length of the ids array + * @param mapIds Array of map ids to query + * @param mapIdsLength Length of the map ids array + * @param stages Array of stages to query + * @param stagesLength Length of the stages array + * @param modeIds Array of mode ids to query + * @param modeIdsLength Length of the mode ids array + * @param tickRates Array of tickrates to query + * @param tickRatesLength Length of the tickrates array + * @param hasTeleports Whether to query for hasTeleports or not + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetRecordFilters(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int[] ids = {}, int idsLength = DEFAULT_INT, + int[] mapIds = {}, int mapIdsLength = DEFAULT_INT, + int[] stages = {}, int stagesLength = DEFAULT_INT, + int[] modeIds = {}, int modeIdsLength = DEFAULT_INT, + int[] tickRates = {}, int tickRatesLength = DEFAULT_INT, + bool hasTeleports = DEFAULT_BOOL, bool isOverall = DEFAULT_BOOL, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/record_filters/distributions + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param ids Array of ids to query + * @param idsLength Length of the ids array + * @param mapIds Array of map ids to query + * @param mapIdsLength Length of the map ids array + * @param stages Array of stages to query + * @param stagesLength Length of the stages array + * @param modeIds Array of mode ids to query + * @param modeIdsLength Length of the mode ids array + * @param tickRates Array of tickrates to query + * @param tickRatesLength Length of the tickrates array + * @param hasTeleports Whether to query for hasTeleports or not + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetRecordFilterDistributions(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int[] ids = {}, int idsLength = DEFAULT_INT, + int[] mapIds = {}, int mapIdsLength = DEFAULT_INT, + int[] stages = {}, int stagesLength = DEFAULT_INT, + int[] modeIds = {}, int modeIdsLength = DEFAULT_INT, + int[] tickRates = {}, int tickRatesLength = DEFAULT_INT, + bool hasTeleports = DEFAULT_BOOL, bool isOverall = DEFAULT_BOOL, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/records/replay/list + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param offset Offset of the dataset to query + * @param limit Amount of items returned for the query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetReplayList(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int offset = DEFAULT_INT, int limit = DEFAULT_INT); + +/** + * Starts a GET HTTP Request to /api/{version}/records/{recordId}/replay + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param recordId Record id to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetReplayByRecordId(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int recordId); +/** + * Starts a GET HTTP Request to /api/{version}/records/replay/{replayId} + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param replayId Replay id to query + * @return Whether request was successfully sent + */ +native bool GlobalAPI_GetReplayByReplayId(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, int replayId); + +/** + * Starts a POST HTTP Request to /api/{version}/records/{recordId}/replay + * + * @param callback Callback when request has finished + * @param data Optional data to pass + * @param recordId Id of the record + * @param replayFile Path to the replay file + * @return Whether request was successfully sent + */ +native bool GlobalAPI_CreateReplayForRecordId(OnAPICallFinished callback = INVALID_FUNCTION, any data = DEFAULT_DATA, + int recordId, const char[] replayFile); + +// ======================= PLUGIN INFO ======================= // + +public SharedPlugin __pl_GlobalAPI = +{ + name = "GlobalAPI", + file = "GlobalAPI.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_GlobalAPI_SetNTVOptional() +{ + // Plugin + MarkNativeAsOptional("GlobalAPI_IsInit"); + MarkNativeAsOptional("GlobalAPI_GetAPIKey"); + MarkNativeAsOptional("GlobalAPI_HasAPIKey"); + MarkNativeAsOptional("GlobalAPI_IsStaging"); + MarkNativeAsOptional("GlobalAPI_IsDebugging"); + MarkNativeAsOptional("GlobalAPI_SendRequest"); + MarkNativeAsOptional("GlobalAPI_DebugMessage"); + + // Auth + MarkNativeAsOptional("GlobalAPI_GetAuthStatus"); + + // Bans + MarkNativeAsOptional("GlobalAPI_GetBans"); + MarkNativeAsOptional("GlobalAPI_CreateBan"); + + // Jumpstats + MarkNativeAsOptional("GlobalAPI_GetJumpstats"); + MarkNativeAsOptional("GlobalAPI_GetJumpstatTop"); + MarkNativeAsOptional("GlobalAPI_GetJumpstatTop30"); + + // Maps + MarkNativeAsOptional("GlobalAPI_GetMaps"); + MarkNativeAsOptional("GlobalAPI_GetMapById"); + MarkNativeAsOptional("GlobalAPI_GetMapByName"); + + // Modes + MarkNativeAsOptional("GlobalAPI_GetModes"); + MarkNativeAsOptional("GlobalAPI_GetModeById"); + MarkNativeAsOptional("GlobalAPI_GetModeByName"); + + // Players + MarkNativeAsOptional("GlobalAPI_GetPlayers"); + MarkNativeAsOptional("GlobalAPI_GetPlayerBySteamId"); + MarkNativeAsOptional("GlobalAPI_GetPlayerBySteamIdAndIp"); + + // Records + MarkNativeAsOptional("GlobalAPI_CreateRecord"); + MarkNativeAsOptional("GlobalAPI_GetRecordPlaceById"); + MarkNativeAsOptional("GlobalAPI_GetRecordsTop"); + MarkNativeAsOptional("GlobalAPI_GetRecordsTopRecent"); + MarkNativeAsOptional("GlobalAPI_GetRecordsTopWorldRecords"); + + // Servers + MarkNativeAsOptional("GlobalAPI_GetServers"); + MarkNativeAsOptional("GlobalAPI_GetServerById"); + MarkNativeAsOptional("GlobalAPI_GetServersByName"); + + // Ranks + MarkNativeAsOptional("GlobalAPI_GetPlayerRanks"); + + // Record Filters + MarkNativeAsOptional("GlobalAPI_GetRecordFilters"); + MarkNativeAsOptional("GlobalAPI_GetRecordFilterDistributions"); + + // Replays + MarkNativeAsOptional("GlobalAPI_GetReplayList"); + MarkNativeAsOptional("GlobalAPI_GetReplayByRecordId"); + MarkNativeAsOptional("GlobalAPI_GetReplayByReplayId"); + MarkNativeAsOptional("GlobalAPI_CreateReplayForRecordId"); +} +#endif diff --git a/source/sourcemod/scripting/include/GlobalAPI/iterable.inc b/source/sourcemod/scripting/include/GlobalAPI/iterable.inc new file mode 100644 index 0000000..585873b --- /dev/null +++ b/source/sourcemod/scripting/include/GlobalAPI/iterable.inc @@ -0,0 +1,55 @@ +// ================== DOUBLE INCLUDE ========================= // + +#if defined _GlobalAPI_Iterable_included_ +#endinput +#endif +#define _GlobalAPI_Iterable_included_ + +// =========================================================== // + +#include + +// =========================================================== // + +/* + Helper methodmap for JSON_Object arrays +*/ +methodmap APIIterable < JSON_Object +{ + /** + * Creates a new APIIterable + * + * @param hItems JSON_Object array handle + * @return A new APIIterable handle + */ + public APIIterable(JSON_Object hItems) + { + if (hItems.HasKey("result")) + { + return view_as(hItems.GetObject("result")); + } + return view_as(hItems); + } + + /* + Gets count of the items in the array + */ + property int Count + { + public get() { return this.Length; } + } + + /** + * Gets an object from the array by index + * + * @note This is an alias to GetObjectIndexed + * @param index Index of the object we want to retrieve + * @return JSON_Object handle to the object retrieved + */ + public JSON_Object GetById(int index) + { + return this.GetObjectIndexed(index); + } +} + +// =========================================================== // \ No newline at end of file diff --git a/source/sourcemod/scripting/include/GlobalAPI/request.inc b/source/sourcemod/scripting/include/GlobalAPI/request.inc new file mode 100644 index 0000000..e683125 --- /dev/null +++ b/source/sourcemod/scripting/include/GlobalAPI/request.inc @@ -0,0 +1,185 @@ +// ================== DOUBLE INCLUDE ========================= // + +#if defined _GlobalAPI_Request_included_ +#endinput +#endif +#define _GlobalAPI_Request_included_ + +// =========================================================== // + +static char gC_acceptTypePhrases[][] = +{ + "application/json", + "application/octet-stream" +}; + +static char gC_contentTypePhrases[][] = +{ + "application/json", + "application/octet-stream" +}; + +// =========================================================== // + +methodmap GlobalAPIRequest < Handle +{ + /** + * Creates a new GlobalAPIRequest + * + * @param url URL of the request + * @param method SteamWorks k_ETTPMethod of the request + * @return A new GlobalAPIRequest handle + */ + public GlobalAPIRequest(char[] url, EHTTPMethod method) + { + Handle request = SteamWorks_CreateHTTPRequest(method, url); + return view_as(request); + } + + /** + * Sets request timeout + * + * @param seconds Timeout in seconds + * @return Whether the operation was successful + */ + public bool SetTimeout(int seconds) + { + return SteamWorks_SetHTTPRequestAbsoluteTimeoutMS(this, seconds * 1000); + } + + /** + * Sets request body + * + * @param hData GlobalAPIRequestData containing contentType + * @param body Request body to set + * @param maxlength Maxlength of the body + * @return Whether the operation was successful + */ + public bool SetBody(GlobalAPIRequestData hData, char[] body, int maxlength) + { + return SteamWorks_SetHTTPRequestRawPostBody(this, gC_contentTypePhrases[hData.ContentType], body, maxlength); + } + + /** + * Sets request body from a file + * + * @param hData GlobalAPIRequestData containing contentType + * @return Whether the operation was successful + */ + public bool SetBodyFromFile(GlobalAPIRequestData hData, char[] file) + { + return SteamWorks_SetHTTPRequestRawPostBodyFromFile(this, gC_contentTypePhrases[hData.ContentType], file); + } + + /** + * Sets a request context value + * + * @param data Any data to pass + * @return Whether the operation was successful + */ + public bool SetData(any data1, any data2 = 0) + { + return SteamWorks_SetHTTPRequestContextValue(this, data1, data2); + } + + /** + * Sets predefined HTTP callbacks + * + * @note Predefined values respectively: + * @note Global_HTTP_Completed, Global_HTTP_Headers and Global_HTTP_DataReceived + * @noreturn + */ + public void SetCallbacks() + { + SteamWorks_SetHTTPCallbacks(this, Global_HTTP_Completed, Global_HTTP_Headers, Global_HTTP_DataReceived); + } + + /** + * Sets "Accept" header + * + * @param hData GlobalAPIRequestData containing acceptType + * @return Whether the operation was successful + */ + public bool SetAcceptHeaders(GlobalAPIRequestData hData) + { + return SteamWorks_SetHTTPRequestHeaderValue(this, "Accept", gC_acceptTypePhrases[hData.AcceptType]); + } + + /** + * Sets "powered by" header + * + * @return Whether the operation was successful + */ + public bool SetPoweredByHeader() + { + return SteamWorks_SetHTTPRequestHeaderValue(this, "X-Powered-By", GlobalAPI_Plugin_NameVersion); + } + + /** + * Sets authentication header + * + * @return Whether the operation was successful + */ + public bool SetAuthenticationHeader(char[] apiKey) + { + return SteamWorks_SetHTTPRequestHeaderValue(this, "X-ApiKey", apiKey); + } + + /** + * Sets envinroment headers (MetaMod & SourceMod) + * + * @param mmVersion MetaMod version string + * @param smVersion SourceMod version string + * @return Whether the operation was successful + */ + public bool SetEnvironmentHeaders(char[] mmVersion, char[] smVersion) + { + return SteamWorks_SetHTTPRequestHeaderValue(this, "X-MetaMod-Version", mmVersion) + && SteamWorks_SetHTTPRequestHeaderValue(this, "X-SourceMod-Version", smVersion); + } + + /** + * Sets content type header + * + * @param hData GlobalAPIRequestData containing contentType + * @return Whether the operation was successful + */ + public bool SetContentTypeHeader(GlobalAPIRequestData hData) + { + return SteamWorks_SetHTTPRequestHeaderValue(this, "Content-Type", gC_contentTypePhrases[hData.ContentType]); + } + + /** + * Sets request origin header + * + * @param hData GlobalAPIRequestData containing pluginName + * @return Whether the operation was successful + */ + public bool SetRequestOriginHeader(GlobalAPIRequestData hData) + { + char pluginName[GlobalAPI_Max_PluginName_Length]; + hData.GetString("pluginName", pluginName, sizeof(pluginName)); + + char pluginVersion[GlobalAPI_Max_PluginVersion_Length + 2]; + hData.GetString("pluginVersion", pluginVersion, sizeof(pluginVersion)); + + char fullPluginDisplay[sizeof(pluginName) + sizeof(pluginVersion) + 6]; + Format(fullPluginDisplay, sizeof(fullPluginDisplay), "%s (V.%s)", pluginName, pluginVersion); + + return SteamWorks_SetHTTPRequestHeaderValue(this, "X-Request-Origin", fullPluginDisplay); + } + + /** + * Sends our request with all available data + * + * @param hData GlobalAPIRequestData handle with all required keys + * @return Whether the operation was successful + */ + public bool Send(GlobalAPIRequestData hData) + { + Call_Private_OnHTTPStart(this, hData); + return SteamWorks_SendHTTPRequest(this); + } +} + +// =========================================================== // \ No newline at end of file diff --git a/source/sourcemod/scripting/include/GlobalAPI/requestdata.inc b/source/sourcemod/scripting/include/GlobalAPI/requestdata.inc new file mode 100644 index 0000000..f055ee8 --- /dev/null +++ b/source/sourcemod/scripting/include/GlobalAPI/requestdata.inc @@ -0,0 +1,534 @@ +// ================== DOUBLE INCLUDE ========================= // + +#if defined _GlobalAPI_RequestData_included_ +#endinput +#endif +#define _GlobalAPI_RequestData_included_ + +// =========================================================== // + +#include + +// =========================================================== // + +/* + Helper methodmap for wrapping data related to requests +*/ +methodmap GlobalAPIRequestData < JSON_Object +{ + /** + * Creates a new GlobalAPIRequestData + * + * @note You can pass a plugin handle or name and/or version + * @note Plugin handle is always preferred + * @param plugin Handle to calling plugin + * @param pluginName Name of the calling plugin + * @param pluginVersion Version of the calling plugin + * @return A new GlobalAPIRequestData handle + */ + public GlobalAPIRequestData(Handle plugin = null, char[] pluginName = "Unknown", char[] pluginVersion = "Unknown") + { + JSON_Object requestData = new JSON_Object(); + + if (plugin == null) + { + requestData.SetString("pluginName", pluginName); + requestData.SetString("pluginVersion", pluginVersion); + } + else + { + requestData.SetString("pluginName", GetPluginDisplayName(plugin)); + requestData.SetString("pluginVersion", GetPluginVersion(plugin)); + } + + requestData.SetKeyHidden("pluginName", true); + requestData.SetKeyHidden("pluginVersion", true); + + requestData.SetInt("acceptType", 0); + requestData.SetKeyHidden("acceptType", true); + + requestData.SetInt("contentType", 0); + requestData.SetKeyHidden("contentType", true); + + return view_as(requestData); + } + + /** + * Sets a key as default + * + * @note This sets them as "Handle" type + * @note - See GlobalAPI.inc for default values + * @param key Key to set as default + * @noreturn + */ + public void SetDefault(char[] key) + { + this.SetHandle(key); + this.SetKeyHidden(key, true); + } + + /** + * Sets url to the request data + * + * @param url Url to set + * @noreturn + */ + public void AddUrl(char[] url) + { + this.SetString("url", url); + this.SetKeyHidden("url", true); + } + + /** + * Sets endpoint to the request data + * + * @param endpoint Endpoint to set + * @noreturn + */ + public void AddEndpoint(char[] endpoint) + { + this.SetString("endpoint", endpoint); + this.SetKeyHidden("endpoint", true); + } + + /** + * Sets body file path to the request data + * + * @note Path to file with data to be posted + * @param path Body file (path) to set + * @noreturn + */ + public void AddBodyFile(char[] path) + { + this.SetString("bodyFile", path); + this.SetKeyHidden("bodyFile", true); + } + + /** + * Sets data file path to the request data + * + * @note Path for downloaded files + * @param path Data path to set + * @noreturn + */ + public void AddDataPath(char[] path) + { + this.SetString("dataFilePath", path); + this.SetKeyHidden("dataFilePath", true); + } + + /* + Get or set the request's "acceptType" + */ + property int AcceptType + { + public get() + { + return this.GetInt("acceptType"); + } + public set(int type) + { + this.SetInt("acceptType", type); + } + } + + /* + Get or set the request's "contentType" + */ + property int ContentType + { + public get() + { + return this.GetInt("contentType"); + } + public set(int type) + { + this.SetInt("contentType", type); + } + } + + /* + Get or set the request's "keyRequired" + */ + property bool KeyRequired + { + public get() + { + return this.GetBool("keyRequired"); + } + public set(bool required) + { + this.SetBool("keyRequired", required); + this.SetKeyHidden("keyRequired", true); + } + } + + /* + Get or set the request's "isRetried" + */ + property bool IsRetried + { + public get() + { + return this.GetBool("isRetried"); + } + public set(bool retried) + { + this.SetBool("isRetried", retried); + this.SetKeyHidden("isRetried", true); + } + } + + /* + Get or set the request's "bodyLength" + */ + property int BodyLength + { + public get() + { + return this.GetInt("bodyLength"); + } + public set(int length) + { + this.SetInt("bodyLength", length); + this.SetKeyHidden("bodyLength", true); + } + } + + /* + Get or set the request's "status" + */ + property int Status + { + public get() + { + return this.GetInt("status"); + } + public set(int status) + { + this.SetInt("status", status); + this.SetKeyHidden("status", true); + } + } + + /* + Get or set the request's "responseTime" + */ + property int ResponseTime + { + public get() + { + return this.GetInt("responseTime"); + } + public set(int responseTime) + { + this.SetInt("responseTime", responseTime); + this.SetKeyHidden("responseTime", true); + } + } + + /* + Get or set the request's "requestType" + */ + property int RequestType + { + public get() + { + return this.GetInt("requestType"); + } + public set(int type) + { + this.SetInt("requestType", type); + this.SetKeyHidden("requestType", true); + } + } + + /* + Get or set the request's "failure" + */ + property bool Failure + { + public get() + { + return this.GetBool("failure"); + } + public set(bool failure) + { + this.SetBool("failure", failure); + this.SetKeyHidden("failure", true); + } + } + + /* + Get or set the request's "callback" + */ + property Handle Callback + { + public get() + { + return view_as(this.GetInt("callback")); + } + public set(Handle hFwd) + { + this.SetHandle("callback", hFwd); + this.SetKeyType("callback", Type_Int); + this.SetKeyHidden("callback", true); + } + } + + /* + Get or set the request's "data" + */ + property any Data + { + public get() + { + return this.GetInt("data"); + } + public set(any data) + { + this.SetInt("data", data); + this.SetKeyHidden("data", true); + } + } + + /** + * Adds a number to the request data + * + * @note Default values are added as "defaults" + * @note See GlobalAPI.inc for the default values + * @param key Key name to set + * @param value Value of the key + * @noreturn + */ + public void AddNum(char[] key, int value) + { + if (value == -1) + { + this.SetDefault(key); + } + else + { + this.SetInt(key, value); + } + } + + /** + * Adds a float to the request data + * + * @note Default values are added as "defaults" + * @note See GlobalAPI.inc for the default values + * @param key Key name to set + * @param value Value of the key + * @noreturn + */ + public void AddFloat(char[] key, float value) + { + if (value == -1.000000) + { + this.SetDefault(key); + } + else + { + this.SetFloat(key, value); + } + } + + /** + * Adds a string to the request data + * + * @note Default values are added as "defaults" + * @note See GlobalAPI.inc for the default values + * @param key Key name to set + * @param value Value of the key + * @noreturn + */ + public void AddString(char[] key, char[] value) + { + if (StrEqual(value, "")) + { + this.SetDefault(key); + } + else + { + this.SetString(key, value); + } + } + + /** + * Adds a boolean to the request data + * + * @note Default values are added as "defaults" + * @note See GlobalAPI.inc for the default values + * @param key Key name to set + * @param value Value of the key + * @noreturn + */ + public void AddBool(char[] key, bool value) + { + if (value != true && value != false) + { + this.SetDefault(key); + } + else + { + this.SetBool(key, value); + } + } + + /** + * Adds integer array to the request data + * + * @note Max length <= 0 are added as defaults + * @param key Key name to set + * @param value Values (array) of the key + * @param maxlength Max length of the values array + * @noreturn + */ + public void AddIntArray(char[] key, int[] value, int maxlength) + { + if (maxlength <= 0) + { + this.SetDefault(key); + } + else + { + JSON_Object hArray = new JSON_Object(true); + + for (int i = 0; i < maxlength; i++) + { + hArray.PushInt(value[i]); + } + + this.SetObject(key, hArray); + } + } + + /** + * Adds string array to the request data + * + * @note Item count <= 0 are added as defaults + * @param key Key name to set + * @param itemCount Amount of strings in the array + * @noreturn + */ + public void AddStringArray(char[] key, char[][] value, int itemCount) + { + if (itemCount <= 0) + { + this.SetDefault(key); + } + else + { + JSON_Object hArray = new JSON_Object(true); + + for (int i = 0; i < itemCount; i++) + { + hArray.PushString(value[i]); + } + + this.SetObject(key, hArray); + } + } + + /** + * Converts all of the request data into a query string representation + * + * @note This ignores "hidden" keys + * @param queryString Buffer to store the result in + * @param maxlength Max length of the buffer + * @noreturn + */ + public void ToString(char[] queryString, int maxlength) + { + StringMapSnapshot paramsMap = this.Snapshot(); + + char key[64]; + char value[1024]; + + int paramCount = 0; + + for (int i = 0; i < paramsMap.Length; i++) + { + paramsMap.GetKey(i, key, sizeof(key)); + if (this.GetKeyHidden(key) || json_is_meta_key(key)) + { + continue; + } + + switch(this.GetKeyType(key)) + { + case Type_String: + { + this.GetString(key, value, sizeof(value)); + AppendToQueryString(paramCount, queryString, maxlength, key, value); + } + case Type_Float: + { + float temp = this.GetFloat(key); + FloatToString(temp, value, sizeof(value)); + AppendToQueryString(paramCount, queryString, maxlength, key, value); + } + case Type_Int: + { + int temp = this.GetInt(key); + IntToString(temp, value, sizeof(value)); + AppendToQueryString(paramCount, queryString, maxlength, key, value); + } + case Type_Bool: + { + bool temp = this.GetBool(key); + BoolToString(temp, value, sizeof(value)); + AppendToQueryString(paramCount, queryString, maxlength, key, value); + } + case Type_Object: + { + JSON_Object hObject = this.GetObject(key); + + if (!hObject.IsArray) continue; + + for (int x = 0; x < hObject.Length; x++) + { + switch (hObject.GetKeyTypeIndexed(x)) + { + case Type_Int: + { + int temp = hObject.GetIntIndexed(x); + IntToString(temp, value, sizeof(value)); + AppendToQueryString(paramCount, queryString, maxlength, key, value); + } + case Type_String: + { + hObject.GetStringIndexed(x, value, sizeof(value)); + AppendToQueryString(paramCount, queryString, maxlength, key, value); + } + } + } + } + } + } + + delete paramsMap; + } +} + +// =====[ PRIVATE ]===== + +static void BoolToString(bool value, char[] buffer, int maxlength) +{ + FormatEx(buffer, maxlength, "%s", value ? "true" : "false"); +} + +static void AppendToQueryString(int &index, char[] buffer, int maxlength, char[] key, char[] value) +{ + if (index == 0) + { + index++; + Format(buffer, maxlength, "?%s=%s", key, value); + } + else + { + index++; + Format(buffer, maxlength, "%s&%s=%s", buffer, key, value); + } +} diff --git a/source/sourcemod/scripting/include/GlobalAPI/responses.inc b/source/sourcemod/scripting/include/GlobalAPI/responses.inc new file mode 100644 index 0000000..62ebfd2 --- /dev/null +++ b/source/sourcemod/scripting/include/GlobalAPI/responses.inc @@ -0,0 +1,575 @@ +// ================== DOUBLE INCLUDE ========================= // + +#if defined _GlobalAPI_Responses_included_ +#endinput +#endif +#define _GlobalAPI_Responses_included_ + +// =========================================================== // + +#include +#include + +// =========================================================== // + +methodmap APIAuth < JSON_Object +{ + public APIAuth(JSON_Object hAuth) + { + return view_as(hAuth); + } + + public bool GetType(char[] buffer, int maxlength) + { + return this.GetString("Type", buffer, maxlength); + } + + property bool IsValid + { + public get() { return this.GetBool("IsValid"); } + } + + property int Identity + { + public get() { return this.GetInt("Identity"); } + } +} + +// =========================================================== // + +methodmap APIBan < JSON_Object +{ + public APIBan(JSON_Object hBan) + { + return view_as(hBan); + } + + property int Id + { + public get() { return this.GetInt("id"); } + } + + property int UpdatedById + { + public get() { return this.GetInt("updated_by_id"); } + } + + public void GetStats(char[] buffer, int maxlength) + { + this.GetString("stats", buffer, maxlength); + } + + public void GetBanType(char[] buffer, int maxlength) + { + this.GetString("ban_type", buffer, maxlength); + } + + public void GetExpiresOn(char[] buffer, int maxlength) + { + this.GetString("expires_on", buffer, maxlength); + } + + public void GetSteamId64(char[] buffer, int maxlength) + { + this.GetString("steamid64", buffer, maxlength); + } + + public void GetPlayerName(char[] buffer, int maxlength) + { + this.GetString("player_name", buffer, maxlength); + } + + public void GetNotes(char[] buffer, int maxlength) + { + this.GetString("notes", buffer, maxlength); + } + + public void GetSteamId(char[] buffer, int maxlength) + { + this.GetString("steam_id", buffer, maxlength); + } + + public void GetUpdatedOn(char[] buffer, int maxlength) + { + this.GetString("updated_on", buffer, maxlength); + } + + property int ServerId + { + public get() { return this.GetInt("server_id"); } + } + + public void GetCreatedOn(char[] buffer, int maxlength) + { + this.GetString("created_on", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIJumpstat < JSON_Object +{ + public APIJumpstat(JSON_Object hJump) + { + return view_as(hJump); + } + + property int Id + { + public get() { return this.GetInt("id"); } + } + + property int ServerId + { + public get() { return this.GetInt("server_id"); } + } + + public void GetSteamId64(char[] buffer, int maxlength) + { + this.GetString("steamid64", buffer, maxlength); + } + + public void GetName(char[] buffer, int maxlength) + { + this.GetString("player_name", buffer, maxlength); + } + + public void GetSteamId(char[] buffer, int maxlength) + { + this.GetString("steam_id", buffer, maxlength); + } + + property int JumpType + { + public get() { return this.GetInt("jump_type"); } + } + + property float Distance + { + public get() { return this.GetFloat("distance"); } + } + + property int TickRate + { + public get() { return this.GetInt("tickrate"); } + } + + property int MslCount + { + public get() { return this.GetInt("msl_count"); } + } + + property int StrafeCount + { + public get() { return this.GetInt("strafe_count"); } + } + + property bool IsCrouchBind + { + public get() { return this.GetBool("is_crouch_bind"); } + } + + property bool IsForwardBind + { + public get() { return this.GetBool("is_forward_bind"); } + } + + property bool IsCrouchBoost + { + public get() { return this.GetBool("is_crouch_boost"); } + } + + property int UpdatedById + { + public get() { return this.GetInt("updated_by_id"); } + } + + public void GetCreatedOn(char[] buffer, int maxlength) + { + this.GetString("created_on", buffer, maxlength); + } + + public void GetUpdatedOn(char[] buffer, int maxlength) + { + this.GetString("updated_on", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIMap < JSON_Object +{ + public APIMap(JSON_Object hMap) + { + return view_as(hMap); + } + + property int Id + { + public get() { return this.GetInt("id"); } + } + + public void GetName(char[] buffer, int maxlength) + { + this.GetString("name", buffer, maxlength); + } + + property int Filesize + { + public get() { return this.GetInt("filesize"); } + } + + property bool IsValidated + { + public get() { return this.GetBool("validated"); } + } + + property int Difficulty + { + public get() { return this.GetInt("difficulty"); } + } + + public void GetCreatedOn(char[] buffer, int maxlength) + { + this.GetString("created_on", buffer, maxlength); + } + + public void GetUpdatedOn(char[] buffer, int maxlength) + { + this.GetString("updated_on", buffer, maxlength); + } + + public void GetApprovedBySteamId64(char[] buffer, int maxlength) + { + this.GetString("approved_by_steamid64", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIMode < JSON_Object +{ + public APIMode(JSON_Object hMode) + { + return view_as(hMode); + } + + property int Id + { + public get() { return this.GetInt("id"); } + } + + public void GetName(char[] buffer, int maxlength) + { + this.GetString("name", buffer, maxlength); + } + + public void GetDescription(char[] buffer, int maxlength) + { + this.GetString("description", buffer, maxlength); + } + + property int LatestVersion + { + public get() { return this.GetInt("latest_version"); } + } + + public void GetLatestVersionDesc(char[] buffer, int maxlength) + { + this.GetString("latest_version_description", buffer, maxlength); + } + + public void GetWebsite(char[] buffer, int maxlength) + { + this.GetString("website", buffer, maxlength); + } + + public void GetRepository(char[] buffer, int maxlength) + { + this.GetString("repo", buffer, maxlength); + } + + public void GetContactSteamId64(char[] buffer, int maxlength) + { + this.GetString("contact_steamid64", buffer, maxlength); + } + + // TODO: Add supported_tickrates + + public void GetCreatedOn(char[] buffer, int maxlength) + { + this.GetString("created_on", buffer, maxlength); + } + + public void GetUpdatedOn(char[] buffer, int maxlength) + { + this.GetString("updated_on", buffer, maxlength); + } + + public void GetUpdatedById(char[] buffer, int maxlength) + { + this.GetString("updated_by_id", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIPlayerRank < JSON_Object +{ + public APIPlayerRank(JSON_Object hPlayerRank) + { + return view_as(hPlayerRank); + } + + property int Points + { + public get() { return this.GetInt("points"); } + } + + property int PointsOverall + { + public get() { return this.GetInt("points_overall"); } + } + + property float Average + { + public get() { return this.GetFloat("average"); } + } + + property float Rating + { + public get() { return this.GetFloat("rating"); } + } + + property int Finishes + { + public get() { return this.GetInt("finishes"); } + } + + public void GetSteamId64(char[] buffer, int maxlength) + { + this.GetString("steamid64", buffer, maxlength); + } + + public void GetSteamId(char[] buffer, int maxlength) + { + this.GetString("steamid", buffer, maxlength); + } + + public void GetPlayerName(char[] buffer, int maxlength) + { + this.GetString("player_name", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIPlayer < JSON_Object +{ + public APIPlayer(JSON_Object hPlayer) + { + return view_as(hPlayer); + } + + public void GetSteamId64(char[] buffer, int maxlength) + { + this.GetString("steamid64", buffer, maxlength); + } + + public void GetSteamId(char[] buffer, int maxlength) + { + this.GetString("steam_id", buffer, maxlength); + } + + property bool IsBanned + { + public get() { return this.GetBool("is_banned"); } + } + + property int TotalRecords + { + public get() { return this.GetInt("total_records"); } + } + + public void GetName(char[] buffer, int maxlength) + { + this.GetString("name", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIRecord < JSON_Object +{ + public APIRecord(JSON_Object hRecord) + { + return view_as(hRecord); + } + + property int Id + { + public get() { return this.GetInt("id"); } + } + + public void GetSteamId64(char[] buffer, int maxlength) + { + this.GetString("steamid64", buffer, maxlength); + } + + public void GetPlayerName(char[] buffer, int maxlength) + { + this.GetString("player_name", buffer, maxlength); + } + + public void GetSteamId(char[] buffer, int maxlength) + { + this.GetString("steam_id", buffer, maxlength); + } + + property int ServerId + { + public get() { return this.GetInt("server_id"); } + } + + property int MapId + { + public get() { return this.GetInt("map_id"); } + } + + property int Stage + { + public get() { return this.GetInt("stage"); } + } + + public void GetMode(char[] buffer, int maxlength) + { + this.GetString("mode", buffer, maxlength); + } + + property int TickRate + { + public get() { return this.GetInt("tickrate"); } + } + + property float Time + { + public get() { return this.GetFloat("time"); } + } + + property int Teleports + { + public get() { return this.GetInt("teleports"); } + } + + public void GetCreatedOn(char[] buffer, int maxlength) + { + this.GetString("created_on", buffer, maxlength); + } + + public void GetUpdatedOn(char[] buffer, int maxlength) + { + this.GetString("updated_on", buffer, maxlength); + } + + property int UpdatedBy + { + public get() { return this.GetInt("updated_by"); } + } + + public void GetServerName(char[] buffer, int maxlength) + { + this.GetString("server_name", buffer, maxlength); + } + + public void GetMapName(char[] buffer, int maxlength) + { + this.GetString("map_name", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIServer < JSON_Object +{ + public APIServer(JSON_Object hServer) + { + return view_as(hServer); + } + + property int Port + { + public get() { return this.GetInt("port"); } + } + + public void GetIPAddress(char[] buffer, int maxlength) + { + this.GetString("ip", buffer, maxlength); + } + + public void GetName(char[] buffer, int maxlength) + { + this.GetString("name", buffer, maxlength); + } + + public void GetOwnerSteamId64(char[] buffer, int maxlength) + { + this.GetString("owner_steamid64", buffer, maxlength); + } +} + +// =========================================================== // + +methodmap APIRecordFilter < JSON_Object +{ + public APIRecordFilter(JSON_Object hRecordFilter) + { + return view_as(hRecordFilter); + } + + property int Id + { + public get() { return this.GetInt("id"); } + } + + property int MapId + { + public get() { return this.GetInt("map_id"); } + } + + property int Stage + { + public get() { return this.GetInt("stage"); } + } + + property int ModeId + { + public get() { return this.GetInt("mode_id"); } + } + + property int TickRate + { + public get() { return this.GetInt("tickrate"); } + } + + property bool HasTeleports + { + public get() { return this.GetBool("has_teleports"); } + } + + public void GetCreatedOn(char[] buffer, int maxlength) + { + this.GetString("created_on", buffer, maxlength); + } + + public void GetUpdatedOn(char[] buffer, int maxlength) + { + this.GetString("updated_on", buffer, maxlength); + } + + public void GetUpdatedById(char[] buffer, int maxlength) + { + this.GetString("updated_by_id", buffer, maxlength); + } +} + +// =========================================================== // diff --git a/source/sourcemod/scripting/include/GlobalAPI/stocks.inc b/source/sourcemod/scripting/include/GlobalAPI/stocks.inc new file mode 100644 index 0000000..52596c4 --- /dev/null +++ b/source/sourcemod/scripting/include/GlobalAPI/stocks.inc @@ -0,0 +1,67 @@ +// ================== DOUBLE INCLUDE ========================= // + +#if defined _GlobalAPI_Stocks_included_ +#endinput +#endif +#define _GlobalAPI_Stocks_included_ + +// =========================================================== // + +/** + * Gets plugin's display name from its handle + * + * @param plugin Plugin handle to retrieve name from + * @return String representation of the plugin name + */ +stock char[] GetPluginDisplayName(Handle plugin) +{ + char pluginName[GlobalAPI_Max_PluginName_Length] = "Unknown"; + GetPluginInfo(plugin, PlInfo_Name, pluginName, sizeof(pluginName)); + + return pluginName; +} + +/** + * Gets plugin's version from its handle + * + * @param plugin Plugin handle to retrieve version from + * @return String representation of the plugin version + */ +stock char[] GetPluginVersion(Handle plugin) +{ + char pluginVersion[GlobalAPI_Max_PluginVersion_Length] = "Unknown"; + GetPluginInfo(plugin, PlInfo_Version, pluginVersion, sizeof(pluginVersion)); + + return pluginVersion; +} + +/** + * Gets current map's "display name" + * + * @param buffer Buffer to store the result in + * @param maxlength Max length of the buffer + * @noreturn + */ +stock void GetMapDisplay(char[] buffer, int maxlength) +{ + char map[PLATFORM_MAX_PATH]; + GetCurrentMap(map, sizeof(map)); + GetMapDisplayName(map, map, sizeof(map)); + + FormatEx(buffer, maxlength, map); +} + +/** + * Gets current map's full (game dir) path + * + * @param buffer Buffer to store result in + * @param maxlength Max length of the buffer + * @noreturn + */ +stock void GetMapFullPath(char[] buffer, int maxlength) +{ + char mapPath[PLATFORM_MAX_PATH]; + GetCurrentMap(mapPath, sizeof(mapPath)); + + Format(buffer, maxlength, "maps/%s.bsp", mapPath); +} diff --git a/source/sourcemod/scripting/include/SteamWorks.inc b/source/sourcemod/scripting/include/SteamWorks.inc new file mode 100644 index 0000000..0e4aec3 --- /dev/null +++ b/source/sourcemod/scripting/include/SteamWorks.inc @@ -0,0 +1,413 @@ +#if defined _SteamWorks_Included + #endinput +#endif +#define _SteamWorks_Included + +/* results from UserHasLicenseForApp */ +enum EUserHasLicenseForAppResult +{ + k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app + k_EUserHasLicenseResultDoesNotHaveLicense = 1, // User does not have a license for the specified app + k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated +}; + +/* General result codes */ +enum EResult +{ + k_EResultOK = 1, // success + k_EResultFail = 2, // generic failure + k_EResultNoConnection = 3, // no/failed network connection +// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed + k_EResultInvalidPassword = 5, // password/ticket is invalid + k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere + k_EResultInvalidProtocolVer = 7, // protocol version is incorrect + k_EResultInvalidParam = 8, // a parameter is incorrect + k_EResultFileNotFound = 9, // file was not found + k_EResultBusy = 10, // called method busy - action not taken + k_EResultInvalidState = 11, // called object was in an invalid state + k_EResultInvalidName = 12, // name is invalid + k_EResultInvalidEmail = 13, // email is invalid + k_EResultDuplicateName = 14, // name is not unique + k_EResultAccessDenied = 15, // access is denied + k_EResultTimeout = 16, // operation timed out + k_EResultBanned = 17, // VAC2 banned + k_EResultAccountNotFound = 18, // account not found + k_EResultInvalidSteamID = 19, // steamID is invalid + k_EResultServiceUnavailable = 20, // The requested service is currently unavailable + k_EResultNotLoggedOn = 21, // The user is not logged on + k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party) + k_EResultEncryptionFailure = 23, // Encryption or Decryption failed + k_EResultInsufficientPrivilege = 24, // Insufficient privilege + k_EResultLimitExceeded = 25, // Too much of a good thing + k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes) + k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired + k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again + k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time + k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user + k_EResultIPNotFound = 31, // IP address not found + k_EResultPersistFailed = 32, // failed to write change to the data store + k_EResultLockingFailed = 33, // failed to acquire access lock for this operation + k_EResultLogonSessionReplaced = 34, + k_EResultConnectFailed = 35, + k_EResultHandshakeFailed = 36, + k_EResultIOFailure = 37, + k_EResultRemoteDisconnect = 38, + k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested + k_EResultBlocked = 40, // a user didn't allow it + k_EResultIgnored = 41, // target is ignoring sender + k_EResultNoMatch = 42, // nothing matching the request found + k_EResultAccountDisabled = 43, + k_EResultServiceReadOnly = 44, // this service is not accepting content changes right now + k_EResultAccountNotFeatured = 45, // account doesn't have value, so this feature isn't available + k_EResultAdministratorOK = 46, // allowed to take this action, but only because requester is admin + k_EResultContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol. + k_EResultTryAnotherCM = 48, // The current CM can't service the user making a request, user should try another. + k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed. + k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait + k_EResultSuspended = 51, // Long running operation (content download) suspended/paused + k_EResultCancelled = 52, // Operation canceled (typically by user: content download) + k_EResultDataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable + k_EResultDiskFull = 54, // Operation canceled - not enough disk space. + k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed + k_EResultPasswordUnset = 56, // Password could not be verified as it's unset server side + k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account + k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid + k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first + k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files + k_EResultIllegalPassword = 61, // The requested new password is not legal + k_EResultSameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer ) + k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure + k_EResultCannotUseOldPassword = 64, // The requested new password is not legal + k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code invalid + k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent + k_EResultHardwareNotCapableOfIPT = 67, // + k_EResultIPTInitError = 68, // + k_EResultParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user + k_EResultFacebookQueryError = 70, // Facebook query returned an error + k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth code expired + k_EResultIPLoginRestrictionFailed = 72, + k_EResultAccountLockedDown = 73, + k_EResultAccountLogonDeniedVerifiedEmailRequired = 74, + k_EResultNoMatchingURL = 75, + k_EResultBadResponse = 76, // parse failure, missing field, etc. + k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password + k_EResultValueOutOfRange = 78, // the value entered is outside the acceptable range + k_EResultUnexpectedError = 79, // something happened that we didn't expect to ever happen + k_EResultDisabled = 80, // The requested service has been configured to be unavailable + k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid ! + k_EResultRestrictedDevice = 82, // The device being used is not allowed to perform this action + k_EResultRegionLocked = 83, // The action could not be complete because it is region restricted + k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent + k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login + k_EResultItemDeleted = 86, // The thing we're trying to access has been deleted + k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker + k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch + k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match + k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners + k_EResultNotModified = 91, // data not modified + k_EResultNoMobileDevice = 92, // the account does not have a mobile device associated with it + k_EResultTimeNotSynced = 93, // the time presented is out of range or tolerance + k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.) + k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource + k_EResultAccountActivityLimitExceeded = 96, // Too many changes to this account + k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone + k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use wallet + k_EResultEmailSendFailure = 99, // Cannot send an email + k_EResultNotSettled = 100, // Can't perform operation till payment has settled + k_EResultNeedCaptcha = 101, // Needs to provide a valid captcha + k_EResultGSLTDenied = 102, // a game server login token owned by this token's owner has been banned + k_EResultGSOwnerDenied = 103, // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone) + k_EResultInvalidItemType = 104 // the type of thing we were requested to act on is invalid +}; + +/* This enum is used in client API methods, do not re-number existing values. */ +enum EHTTPMethod +{ + k_EHTTPMethodInvalid = 0, + k_EHTTPMethodGET, + k_EHTTPMethodHEAD, + k_EHTTPMethodPOST, + k_EHTTPMethodPUT, + k_EHTTPMethodDELETE, + k_EHTTPMethodOPTIONS, + k_EHTTPMethodPATCH, + + // The remaining HTTP methods are not yet supported, per rfc2616 section 5.1.1 only GET and HEAD are required for + // a compliant general purpose server. We'll likely add more as we find uses for them. + + // k_EHTTPMethodTRACE, + // k_EHTTPMethodCONNECT +}; + + +/* HTTP Status codes that the server can send in response to a request, see rfc2616 section 10.3 for descriptions + of each of these. */ +enum EHTTPStatusCode +{ + // Invalid status code (this isn't defined in HTTP, used to indicate unset in our code) + k_EHTTPStatusCodeInvalid = 0, + + // Informational codes + k_EHTTPStatusCode100Continue = 100, + k_EHTTPStatusCode101SwitchingProtocols = 101, + + // Success codes + k_EHTTPStatusCode200OK = 200, + k_EHTTPStatusCode201Created = 201, + k_EHTTPStatusCode202Accepted = 202, + k_EHTTPStatusCode203NonAuthoritative = 203, + k_EHTTPStatusCode204NoContent = 204, + k_EHTTPStatusCode205ResetContent = 205, + k_EHTTPStatusCode206PartialContent = 206, + + // Redirection codes + k_EHTTPStatusCode300MultipleChoices = 300, + k_EHTTPStatusCode301MovedPermanently = 301, + k_EHTTPStatusCode302Found = 302, + k_EHTTPStatusCode303SeeOther = 303, + k_EHTTPStatusCode304NotModified = 304, + k_EHTTPStatusCode305UseProxy = 305, + //k_EHTTPStatusCode306Unused = 306, (used in old HTTP spec, now unused in 1.1) + k_EHTTPStatusCode307TemporaryRedirect = 307, + + // Error codes + k_EHTTPStatusCode400BadRequest = 400, + k_EHTTPStatusCode401Unauthorized = 401, // You probably want 403 or something else. 401 implies you're sending a WWW-Authenticate header and the client can sent an Authorization header in response. + k_EHTTPStatusCode402PaymentRequired = 402, // This is reserved for future HTTP specs, not really supported by clients + k_EHTTPStatusCode403Forbidden = 403, + k_EHTTPStatusCode404NotFound = 404, + k_EHTTPStatusCode405MethodNotAllowed = 405, + k_EHTTPStatusCode406NotAcceptable = 406, + k_EHTTPStatusCode407ProxyAuthRequired = 407, + k_EHTTPStatusCode408RequestTimeout = 408, + k_EHTTPStatusCode409Conflict = 409, + k_EHTTPStatusCode410Gone = 410, + k_EHTTPStatusCode411LengthRequired = 411, + k_EHTTPStatusCode412PreconditionFailed = 412, + k_EHTTPStatusCode413RequestEntityTooLarge = 413, + k_EHTTPStatusCode414RequestURITooLong = 414, + k_EHTTPStatusCode415UnsupportedMediaType = 415, + k_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, + k_EHTTPStatusCode417ExpectationFailed = 417, + k_EHTTPStatusCode4xxUnknown = 418, // 418 is reserved, so we'll use it to mean unknown + k_EHTTPStatusCode429TooManyRequests = 429, + + // Server error codes + k_EHTTPStatusCode500InternalServerError = 500, + k_EHTTPStatusCode501NotImplemented = 501, + k_EHTTPStatusCode502BadGateway = 502, + k_EHTTPStatusCode503ServiceUnavailable = 503, + k_EHTTPStatusCode504GatewayTimeout = 504, + k_EHTTPStatusCode505HTTPVersionNotSupported = 505, + k_EHTTPStatusCode5xxUnknown = 599, +}; + +/* list of possible return values from the ISteamGameCoordinator API */ +enum EGCResults +{ + k_EGCResultOK = 0, + k_EGCResultNoMessage = 1, // There is no message in the queue + k_EGCResultBufferTooSmall = 2, // The buffer is too small for the requested message + k_EGCResultNotLoggedOn = 3, // The client is not logged onto Steam + k_EGCResultInvalidMessage = 4, // Something was wrong with the message being sent with SendMessage +}; + +native bool:SteamWorks_IsVACEnabled(); +native bool:SteamWorks_GetPublicIP(ipaddr[4]); +native SteamWorks_GetPublicIPCell(); +native bool:SteamWorks_IsLoaded(); +native bool:SteamWorks_SetGameData(const String:sData[]); +native bool:SteamWorks_SetGameDescription(const String:sDesc[]); +native bool:SteamWorks_SetMapName(const String:sMapName[]); +native bool:SteamWorks_IsConnected(); +native bool:SteamWorks_SetRule(const String:sKey[], const String:sValue[]); +native bool:SteamWorks_ClearRules(); +native bool:SteamWorks_ForceHeartbeat(); +native bool:SteamWorks_GetUserGroupStatus(client, groupid); +native bool:SteamWorks_GetUserGroupStatusAuthID(authid, groupid); + +native EUserHasLicenseForAppResult:SteamWorks_HasLicenseForApp(client, app); +native EUserHasLicenseForAppResult:SteamWorks_HasLicenseForAppId(authid, app); +native SteamWorks_GetClientSteamID(client, String:sSteamID[], length); + +native bool:SteamWorks_RequestStatsAuthID(authid, appid); +native bool:SteamWorks_RequestStats(client, appid); +native bool:SteamWorks_GetStatCell(client, const String:sKey[], &value); +native bool:SteamWorks_GetStatAuthIDCell(authid, const String:sKey[], &value); +native bool:SteamWorks_GetStatFloat(client, const String:sKey[], &Float:value); +native bool:SteamWorks_GetStatAuthIDFloat(authid, const String:sKey[], &Float:value); + +native Handle:SteamWorks_CreateHTTPRequest(EHTTPMethod:method, const String:sURL[]); +native bool:SteamWorks_SetHTTPRequestContextValue(Handle:hHandle, any:data1, any:data2=0); +native bool:SteamWorks_SetHTTPRequestNetworkActivityTimeout(Handle:hHandle, timeout); +native bool:SteamWorks_SetHTTPRequestHeaderValue(Handle:hHandle, const String:sName[], const String:sValue[]); +native bool:SteamWorks_SetHTTPRequestGetOrPostParameter(Handle:hHandle, const String:sName[], const String:sValue[]); +native bool:SteamWorks_SetHTTPRequestUserAgentInfo(Handle:hHandle, const String:sUserAgentInfo[]); +native bool:SteamWorks_SetHTTPRequestRequiresVerifiedCertificate(Handle:hHandle, bool:bRequireVerifiedCertificate); +native bool:SteamWorks_SetHTTPRequestAbsoluteTimeoutMS(Handle:hHandle, unMilliseconds); + +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 9 +typeset SteamWorksHTTPRequestCompleted +{ + function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode); + function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any data1); + function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any data1, any data2); +}; + +typeset SteamWorksHTTPHeadersReceived +{ + function void (Handle hRequest, bool bFailure); + function void (Handle hRequest, bool bFailure, any data1); + function void (Handle hRequest, bool bFailure, any data1, any data2); +}; + +typeset SteamWorksHTTPDataReceived +{ + function void (Handle hRequest, bool bFailure, int offset, int bytesreceived); + function void (Handle hRequest, bool bFailure, int offset, int bytesreceived, any data1); + function void (Handle hRequest, bool bFailure, int offset, int bytesreceived, any data1, any data2); +}; + +typeset SteamWorksHTTPBodyCallback +{ + function void (const char[] sData); + function void (const char[] sData, any value); + function void (const int[] data, any value, int datalen); +}; + +#else + +funcenum SteamWorksHTTPRequestCompleted +{ + public(Handle:hRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode), + public(Handle:hRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode, any:data1), + public(Handle:hRequest, bool:bFailure, bool:bRequestSuccessful, EHTTPStatusCode:eStatusCode, any:data1, any:data2) +}; + +funcenum SteamWorksHTTPHeadersReceived +{ + public(Handle:hRequest, bool:bFailure), + public(Handle:hRequest, bool:bFailure, any:data1), + public(Handle:hRequest, bool:bFailure, any:data1, any:data2) +}; + +funcenum SteamWorksHTTPDataReceived +{ + public(Handle:hRequest, bool:bFailure, offset, bytesreceived), + public(Handle:hRequest, bool:bFailure, offset, bytesreceived, any:data1), + public(Handle:hRequest, bool:bFailure, offset, bytesreceived, any:data1, any:data2) +}; + +funcenum SteamWorksHTTPBodyCallback +{ + public(const String:sData[]), + public(const String:sData[], any:value), + public(const data[], any:value, datalen) +}; + +#endif + +native bool:SteamWorks_SetHTTPCallbacks(Handle:hHandle, SteamWorksHTTPRequestCompleted:fCompleted = INVALID_FUNCTION, SteamWorksHTTPHeadersReceived:fHeaders = INVALID_FUNCTION, SteamWorksHTTPDataReceived:fData = INVALID_FUNCTION, Handle:hCalling = INVALID_HANDLE); +native bool:SteamWorks_SendHTTPRequest(Handle:hRequest); +native bool:SteamWorks_SendHTTPRequestAndStreamResponse(Handle:hRequest); +native bool:SteamWorks_DeferHTTPRequest(Handle:hRequest); +native bool:SteamWorks_PrioritizeHTTPRequest(Handle:hRequest); +native bool:SteamWorks_GetHTTPResponseHeaderSize(Handle:hRequest, const String:sHeader[], &size); +native bool:SteamWorks_GetHTTPResponseHeaderValue(Handle:hRequest, const String:sHeader[], String:sValue[], size); +native bool:SteamWorks_GetHTTPResponseBodySize(Handle:hRequest, &size); +native bool:SteamWorks_GetHTTPResponseBodyData(Handle:hRequest, String:sBody[], length); +native bool:SteamWorks_GetHTTPStreamingResponseBodyData(Handle:hRequest, cOffset, String:sBody[], length); +native bool:SteamWorks_GetHTTPDownloadProgressPct(Handle:hRequest, &Float:percent); +native bool:SteamWorks_GetHTTPRequestWasTimedOut(Handle:hRequest, &bool:bWasTimedOut); +native bool:SteamWorks_SetHTTPRequestRawPostBody(Handle:hRequest, const String:sContentType[], const String:sBody[], bodylen); +native bool:SteamWorks_SetHTTPRequestRawPostBodyFromFile(Handle:hRequest, const String:sContentType[], const String:sFileName[]); + +native bool:SteamWorks_GetHTTPResponseBodyCallback(Handle:hRequest, SteamWorksHTTPBodyCallback:fCallback, any:data = 0, Handle:hPlugin = INVALID_HANDLE); /* Look up, moved definition for 1.7+ compat. */ +native bool:SteamWorks_WriteHTTPResponseBodyToFile(Handle:hRequest, const String:sFileName[]); + +forward SW_OnValidateClient(ownerauthid, authid); +forward SteamWorks_OnValidateClient(ownerauthid, authid); +forward SteamWorks_SteamServersConnected(); +forward SteamWorks_SteamServersConnectFailure(EResult:result); +forward SteamWorks_SteamServersDisconnected(EResult:result); + +forward Action:SteamWorks_RestartRequested(); +forward SteamWorks_TokenRequested(String:sToken[], maxlen); + +forward SteamWorks_OnClientGroupStatus(authid, groupid, bool:isMember, bool:isOfficer); + +forward EGCResults:SteamWorks_GCSendMessage(unMsgType, const String:pubData[], cubData); +forward SteamWorks_GCMsgAvailable(cubData); +forward EGCResults:SteamWorks_GCRetrieveMessage(punMsgType, const String:pubDest[], cubDest, pcubMsgSize); + +native EGCResults:SteamWorks_SendMessageToGC(unMsgType, const String:pubData[], cubData); + +public Extension:__ext_SteamWorks = +{ + name = "SteamWorks", + file = "SteamWorks.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_SteamWorks_SetNTVOptional() +{ + MarkNativeAsOptional("SteamWorks_IsVACEnabled"); + MarkNativeAsOptional("SteamWorks_GetPublicIP"); + MarkNativeAsOptional("SteamWorks_GetPublicIPCell"); + MarkNativeAsOptional("SteamWorks_IsLoaded"); + MarkNativeAsOptional("SteamWorks_SetGameData"); + MarkNativeAsOptional("SteamWorks_SetGameDescription"); + MarkNativeAsOptional("SteamWorks_IsConnected"); + MarkNativeAsOptional("SteamWorks_SetRule"); + MarkNativeAsOptional("SteamWorks_ClearRules"); + MarkNativeAsOptional("SteamWorks_ForceHeartbeat"); + MarkNativeAsOptional("SteamWorks_GetUserGroupStatus"); + MarkNativeAsOptional("SteamWorks_GetUserGroupStatusAuthID"); + + MarkNativeAsOptional("SteamWorks_HasLicenseForApp"); + MarkNativeAsOptional("SteamWorks_HasLicenseForAppId"); + MarkNativeAsOptional("SteamWorks_GetClientSteamID"); + + MarkNativeAsOptional("SteamWorks_RequestStatsAuthID"); + MarkNativeAsOptional("SteamWorks_RequestStats"); + MarkNativeAsOptional("SteamWorks_GetStatCell"); + MarkNativeAsOptional("SteamWorks_GetStatAuthIDCell"); + MarkNativeAsOptional("SteamWorks_GetStatFloat"); + MarkNativeAsOptional("SteamWorks_GetStatAuthIDFloat"); + + MarkNativeAsOptional("SteamWorks_SendMessageToGC"); + + MarkNativeAsOptional("SteamWorks_CreateHTTPRequest"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestContextValue"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestNetworkActivityTimeout"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestHeaderValue"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestGetOrPostParameter"); + + MarkNativeAsOptional("SteamWorks_SetHTTPCallbacks"); + MarkNativeAsOptional("SteamWorks_SendHTTPRequest"); + MarkNativeAsOptional("SteamWorks_SendHTTPRequestAndStreamResponse"); + MarkNativeAsOptional("SteamWorks_DeferHTTPRequest"); + MarkNativeAsOptional("SteamWorks_PrioritizeHTTPRequest"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseHeaderSize"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseHeaderValue"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodySize"); + MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyData"); + MarkNativeAsOptional("SteamWorks_GetHTTPStreamingResponseBodyData"); + MarkNativeAsOptional("SteamWorks_GetHTTPDownloadProgressPct"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestRawPostBody"); + MarkNativeAsOptional("SteamWorks_SetHTTPRequestRawPostBodyFromFile"); + + MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyCallback"); + MarkNativeAsOptional("SteamWorks_WriteHTTPResponseBodyToFile"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/admin.inc b/source/sourcemod/scripting/include/admin.inc new file mode 100644 index 0000000..3fbf886 --- /dev/null +++ b/source/sourcemod/scripting/include/admin.inc @@ -0,0 +1,832 @@ +/** + * 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/non-existent group */ +}; + +/** + * Identifies a unique entry in the admin permissions cache. These are not Handles. + */ +enum AdminId +{ + INVALID_ADMIN_ID = -1 /**< An invalid/non-existent 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 */ +}; + +methodmap AdminId { + // 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 name String buffer to store name. + // @param maxlength Maximum size of string buffer. + // @return Number of bytes written. + public native void GetUsername(char[] name, int maxlength); + + // Binds an admin to an identity for fast lookup later on. The bind must be unique. + // + // @param authMethod 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, + // ident was already taken, or ident invalid for auth method. + public native bool BindIdentity(const char[] authMethod, const char[] ident); + + // Sets whether or not a flag is enabled on an admin. + // + // @param flag Admin flag to use. + // @param enabled True to enable, false to disable. + public native void SetFlag(AdminFlag flag, bool enabled); + + // Sets multiple bitwise flags to be enabled/disabled on an admin. + // + // @param flags Bitwise admin flags (ADMFLAG_*). + // @param enabled True to set the flag, false to unset/disable. + public void SetBitFlags(int flags, bool enabled) + { + AdminFlag flagArray[AdminFlags_TOTAL]; + int num = FlagBitsToArray(flags, flagArray, sizeof(flagArray)); + for (int i = 0; i < num; i++) + { + this.SetFlag(flagArray[i], enabled); + } + } + + // Returns whether or not a flag is enabled on an admin. + // + // @param flag Admin flag to use. + // @param mode Access mode to check. + // @return True if enabled, false otherwise. + public native bool HasFlag(AdminFlag flag, AdmAccessMode mode=Access_Effective); + + // Returns the bitstring of access flags on an admin. + // + // @param mode Access mode to use. + // @return A bitstring containing which flags are enabled. + public native int GetFlags(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 gid GroupId index of the group. + // @return True on success, false on invalid input or duplicate membership. + public native bool InheritGroup(GroupId gid); + + // Returns group information from an admin. + // + // @param index Group number to retrieve, from 0 to N-1, where N + // is the value of the GroupCount property. + // @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. + public native GroupId GetGroup(int index, char[] name, int maxlength); + + // Sets a password on an admin. + // + // @param password String containing the password. + public native void SetPassword(const char[] password); + + // Gets an admin's password. + // + // @param buffer 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. + public native bool GetPassword(char[] buffer="", int maxlength=0); + + // Tests whether one admin can target another. + // + // The heuristics 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 target Target admin (may be INVALID_ADMIN_ID). + // @return True if targetable, false if immune. + public native bool CanTarget(AdminId other); + + // The number of groups of which this admin is a member. + property int GroupCount { + public native get(); + } + + // Immunity level used for targetting. + property int ImmunityLevel { + public native get(); + public native set(int level); + } +} + +methodmap GroupId { + // Gets whether or not a flag is enabled on a group's flag set. + // + // @param flag Admin flag to retrieve. + // @return True if enabled, false otherwise, + public native bool HasFlag(AdminFlag flag); + + // Adds or removes a flag from a group's flag set. + // + // @param flag Admin flag to toggle. + // @param enabled True to set the flag, false to unset/disable. + public native void SetFlag(AdminFlag flag, bool enabled); + + // Adds or removes multiple bitwise flags from a group's flag set. + // + // @param flags Bitwise admin flags (ADMFLAG_*). + // @param enabled True to set the flag, false to unset/disable. + public void SetBitFlags(int flags, bool enabled) + { + AdminFlag flagArray[AdminFlags_TOTAL]; + int num = FlagBitsToArray(flags, flagArray, sizeof(flagArray)); + for (int i = 0; i < num; i++) + { + this.SetFlag(flagArray[i], enabled); + } + } + + // Returns the flag set that is added to users from this group. + // + // @return Bitstring containing the flags enabled. + public native int GetFlags(); + + // Returns a group that this group is immune to given an index. + // + // @param number Index from 0 to N-1, from GroupImmunitiesCount. + // @return GroupId that this group is immune to, or INVALID_GROUP_ID on failure. + public native GroupId GetGroupImmunity(int index); + + // Adds immunity to a specific group. + // + // @param other Group id to receive immunity to. + public native void AddGroupImmunity(GroupId other); + + // Retrieves a group-specific command override. + // + // @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. + public native bool GetCommandOverride(const char[] name, OverrideType type, OverrideRule &rule); + + // Adds a group-specific override type. + // + // @param name String containing command name (case sensitive). + // @param type Override type (specific command or group). + // @param rule Override allow/deny setting. + public native void AddCommandOverride(const char[] name, OverrideType type, OverrideRule rule); + + // Number of specific group immunities + property int GroupImmunitiesCount { + public native get(); + } + + // Immunity level used for targetting. + property int ImmunityLevel { + public native get(); + public native set(int level); + } +} + +/** + * Called when part of the cache needs to be rebuilt. + * + * @param part Part of the admin cache to rebuild. + */ +forward void 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. + */ +native void 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. + */ +native void AddCommandOverride(const char[] cmd, OverrideType type, int 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 char[] cmd, OverrideType type, int &flags); + +/** + * Unsets a command override. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + */ +native void UnsetCommandOverride(const char[] 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 char[] 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 char[] 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. + */ +native void 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 int GetAdmGroupAddFlags(GroupId id); + +/** + * @deprecated Functionality removed. + */ +#pragma deprecated Use SetAdmGroupImmunityLevel() instead. +native void 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. + */ +native void SetAdmGroupImmuneFrom(GroupId id, GroupId other_id); + +/** + * Returns the number of specific group immunities. + * + * @param id Group id. + * @return Number of group immunities. + */ +native int 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, int 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. + */ +native void AddAdmGroupCmdOverride(GroupId id, const char[] 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 char[] name, OverrideType type, OverrideRule &rule); + +/** + * Registers an authentication identity type. You normally never need to call this except for + * very specific systems. + * + * @param name Codename to use for your authentication type. + */ +native void RegisterAuthIdentType(const char[] name); + +/** + * Creates a new admin entry in the permissions cache and returns the generated AdminId index. + * + * @param name Name for this entry (does not have to be unique). + * Specify an empty string for an anonymous admin. + * @return New AdminId index or INVALID_ADMIN_ID if name is empty + */ +native AdminId CreateAdmin(const char[] 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 int GetAdminUsername(AdminId id, char[] name, int 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, + * ident was already taken, or ident invalid for auth method. + */ +native bool BindAdminIdentity(AdminId id, const char[] auth, const char[] 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. + */ +native void 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 int 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 int 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, int index, char[] name, int maxlength); + +/** + * Sets a password on an admin. + * + * @param id AdminId index of the admin. + * @param password String containing the password. + */ +native void SetAdminPassword(AdminId id, const char[] password); + +/** + * Gets an admin's password. + * + * @param id AdminId index of the admin. + * @param buffer 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, char[] buffer="", int 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 char[] auth, const char[] 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 int FlagBitsToBitArray(int bits, bool[] array, int 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 int FlagBitArrayToBits(const bool[] array, int 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 int FlagArrayToBits(const AdminFlag[] array, int 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 int FlagBitsToArray(int bits, AdminFlag[] array, int 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 char[] 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(int c, AdminFlag &flag); + +/** + * Finds the flag char for a given admin flag. + * + * @param flag Flag to look up. + * @param c Variable to store flag char. + * @return True on success, false if not found. + */ +native bool FindFlagChar(AdminFlag flag, int &c); + +/** + * 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 int ReadFlagString(const char[] flags, int &numchars=0); + +/** + * Tests whether one admin can target another. + * + * The heuristics 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 bool 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 char[] method); + +/** + * Sets a group's immunity level. + * + * @param gid Group Id. + * @param level Immunity level value. + * @return Old immunity level value. + */ +native int SetAdmGroupImmunityLevel(GroupId gid, int level); + +/** + * Gets a group's immunity level (defaults to 0). + * + * @param gid Group Id. + * @return Immunity level value. + */ +native int GetAdmGroupImmunityLevel(GroupId gid); + +/** + * Sets an admin's immunity level. + * + * @param id Admin Id. + * @param level Immunity level value. + * @return Old immunity level value. + */ +native int SetAdminImmunityLevel(AdminId id, int level); + +/** + * Gets an admin's immunity level. + * + * @param id Admin Id. + * @return Immunity level value. + */ +native int GetAdminImmunityLevel(AdminId id); + +/** + * Converts a flag to its single bit. + * + * @param flag Flag to convert. + * @return Bit representation of the flag. + */ +stock int FlagToBit(AdminFlag flag) +{ + return (1 << view_as(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(int bit, AdminFlag &flag) +{ + AdminFlag array[1]; + + if (FlagBitsToArray(bit, array, 1)) + { + flag = array[0]; + return true; + } + + return false; +} + +/** + * Converts a bit string to a string of flag characters. + * + * @param bits Bit string containing the flags. + * @param flags Output array to write a string of flag characters. + * @param maxSize Maximum size of the string array. + * @return Number of flag characters written. + */ +stock int FlagBitsToString(const int bits, char[] flags, const int maxSize) +{ + AdminFlag array[AdminFlags_TOTAL]; + int numFlags = FlagBitsToArray(bits, array, AdminFlags_TOTAL); + if (numFlags > maxSize) + { + numFlags = maxSize; + } + int i, c, numId = 0; + for (i = 0; i < numFlags; ++i) + { + if(FindFlagChar(array[i], c)) + { + flags[numId++] = c; + } + } + flags[numId] = '\0'; + + return numId; +} diff --git a/source/sourcemod/scripting/include/adminmenu.inc b/source/sourcemod/scripting/include/adminmenu.inc new file mode 100644 index 0000000..e82323e --- /dev/null +++ b/source/sourcemod/scripting/include/adminmenu.inc @@ -0,0 +1,152 @@ +/** + * 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. + */ +forward void OnAdminMenuCreated(Handle topmenu); + +/** + * Called when the admin menu is ready to have items added. + * + * @param topmenu Handle to the admin menu's TopMenu. + */ +forward void 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 TopMenu 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 int AddTargetsToMenu(Handle menu, + int 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 int AddTargetsToMenu2(Handle menu, int source_client, int 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, int 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 void __pl_adminmenu_SetNTVOptional() +{ + MarkNativeAsOptional("GetAdminTopMenu"); + MarkNativeAsOptional("AddTargetsToMenu"); + MarkNativeAsOptional("AddTargetsToMenu2"); +} +#endif diff --git a/source/sourcemod/scripting/include/adt.inc b/source/sourcemod/scripting/include/adt.inc new file mode 100644 index 0000000..75051bf --- /dev/null +++ b/source/sourcemod/scripting/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/source/sourcemod/scripting/include/adt_array.inc b/source/sourcemod/scripting/include/adt_array.inc new file mode 100644 index 0000000..00598fe --- /dev/null +++ b/source/sourcemod/scripting/include/adt_array.inc @@ -0,0 +1,469 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 int ByteCountToCells(int size) +{ + if (!size) + { + return 1; + } + + return (size + 3) / 4; +} + +methodmap ArrayList < Handle { + // 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-initialized. + // @return New Handle to the array object. + public native ArrayList(int blocksize=1, int startsize=0); + + // Clears an array of all entries. This is the same as Resize(0). + public native void Clear(); + + // 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. It should + // closed when no longer needed. + // + // @return New handle to the cloned array object + public native ArrayList Clone(); + + // Resizes an array. If the size is smaller than the current size, the + // array is truncated. If the size is larger than the current size, + // the data at the additional indexes will not be initialized. + // + // @param newsize New size. + public native void Resize(int newsize); + + // 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 value Value to push. + // @return Index of the new entry. + // @error Invalid Handle or out of memory. + public native int Push(any value); + + // Pushes a string onto the end of an array, truncating it if it is too big. + // + // @param value String to push. + // @return Index of the new entry. + public native int PushString(const char[] 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 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. + public native int PushArray(const any[] values, int size=-1); + + // Retrieves a cell value from an array. + // + // @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 index. + public native any Get(int index, int block=0, bool asChar=false); + + // Retrieves a string value from an array. + // + // @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 index. + public native int GetString(int index, char[] buffer, int maxlength); + + // Retrieves an array of cells from an array. + // + // @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 index. + public native int GetArray(int index, any[] buffer, int size=-1); + + // Sets a cell value in an array. + // + // @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. + // @error Invalid index, or invalid block. + public native void Set(int index, any value, int block=0, bool asChar=false); + + // Sets a string value in an array. + // + // @param index Index in the array. + // @param value String value to set. + // @return Number of characters copied. + // @error Invalid index. + public native int SetString(int index, const char[] value); + + // Sets an array of cells in an array. + // + // @param index Index in the array. + // @param values 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 index. + public native int SetArray(int index, const any[] values, int 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 index Index in the array to shift up from. + // @error Invalid index. + public native void ShiftUp(int 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 index Index in the array to remove at. + // @error Invalid index. + public native void Erase(int index); + + // Swaps two items in the array. + // + // @param index1 First index. + // @param index2 Second index. + // @error Invalid index. + public native void SwapAt(int index1, int index2); + + // Returns the index for the first occurrence of the provided string. If + // the string cannot be located, -1 will be returned. + // + // @param item String to search for + // @return Array index, or -1 on failure + public native int FindString(const char[] item); + + // Returns the index for the first occurrence of the provided value. If the + // value cannot be located, -1 will be returned. + // + // @param item Value to search for + // @param block Optionally which block to search in + // @return Array index, or -1 on failure + // @error Invalid block index + public native int FindValue(any item, int block=0); + + // Sort an ADT Array. Specify the type as Integer, Float, or String. + // + // @param order Sort order to use, same as other sorts. + // @param type Data type stored in the ADT Array + public native void Sort(SortOrder order, SortType type); + + // Custom sorts an ADT Array. You must pass in a comparison function. + // + // @param sortfunc Sort comparison function to use + // @param hndl Optional Handle to pass through the comparison calls. + public native void SortCustom(SortFuncADTArray sortfunc, Handle hndl=INVALID_HANDLE); + + // Retrieve the size of the array. + property int Length { + public native get(); + } + + // Retrieve the blocksize the array was created with. + property int BlockSize { + public native get(); + } +}; + +/** + * 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-initialized. + * @return New Handle to the array object. + */ +native ArrayList CreateArray(int blocksize=1, int startsize=0); + +/** + * Clears an array of all entries. This is the same as ResizeArray(0). + * + * @param array Array Handle. + * @error Invalid Handle. + */ +native void 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. If the size is larger than the current size, + * the data at the additional indexes will not be initialized. + * + * @param array Array Handle. + * @param newsize New size. + * @error Invalid Handle or out of memory. + */ +native void ResizeArray(Handle array, int newsize); + +/** + * Returns the array size. + * + * @param array Array Handle. + * @return Number of elements in the array. + * @error Invalid Handle. + */ +native int 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 int 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 int PushArrayString(Handle array, const char[] 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 int PushArrayArray(Handle array, const any[] values, int 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, int index, int 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 int GetArrayString(Handle array, int index, char[] buffer, int 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 int GetArrayArray(Handle array, int index, any[] buffer, int 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. + * @error Invalid Handle, invalid index, or invalid block. + */ +native void SetArrayCell(Handle array, int index, any value, int 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 int SetArrayString(Handle array, int index, const char[] value); + +/** + * Sets an array of cells in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param values 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 int SetArrayArray(Handle array, int index, const any[] values, int 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. + * @error Invalid Handle or invalid index. + */ +native void ShiftArrayUp(Handle array, int 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. + * @error Invalid Handle or invalid index. + */ +native void RemoveFromArray(Handle array, int index); + +/** + * Swaps two items in the array. + * + * @param array Array Handle. + * @param index1 First index. + * @param index2 Second index. + * @error Invalid Handle or invalid index. + */ +native void SwapArrayItems(Handle array, int index1, int index2); + +/** + * Returns the index for the first occurrence 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 int FindStringInArray(Handle array, const char[] item); + +/** + * Returns the index for the first occurrence of the provided value. If the value + * cannot be located, -1 will be returned. + * + * @param array Array Handle. + * @param item Value to search for + * @param block Optionally which block to search in + * @return Array index, or -1 on failure + * @error Invalid Handle or invalid block + */ +native int FindValueInArray(Handle array, any item, int block=0); + +/** + * Returns the blocksize the array was created with. + * + * @param array Array Handle. + * @return The blocksize of the array. + * @error Invalid Handle + */ +native int GetArrayBlockSize(Handle array); diff --git a/source/sourcemod/scripting/include/adt_stack.inc b/source/sourcemod/scripting/include/adt_stack.inc new file mode 100644 index 0000000..dfa668a --- /dev/null +++ b/source/sourcemod/scripting/include/adt_stack.inc @@ -0,0 +1,251 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 + +methodmap ArrayStack < Handle +{ + // 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] + public native ArrayStack(int blocksize=1); + + // Clears a stack of all entries. + public native void Clear(); + + // Clones an stack, 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. It should + // closed when no longer needed. + // + // @return New handle to the cloned stack object + public native ArrayStack Clone(); + + // 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 value Value to push. + public native void Push(any value); + + // Pushes a copy of a string onto the end of a stack, truncating it if it + // is too big. + // + // @param value String to push. + public native void PushString(const char[] value); + + // Pushes a copy of 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. + public native void PushArray(const any[] values, int size=-1); + + // Pops a cell value from a stack. + // + // @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 popped from the stack. + // @error The stack is empty. + public native any Pop(int block=0, bool asChar=false); + + // Pops a string value from a stack. + // + // @param buffer Buffer to store string. + // @param maxlength Maximum size of the buffer. + // @param written Number of characters written to buffer, not including + // the null terminator. + // @error The stack is empty. + public native void PopString(char[] buffer, int maxlength, int &written = 0); + + // Pops an array of cells from a stack. + // + // @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. + // @error The stack is empty. + public native void PopArray(any[] buffer, int size=-1); + + // Returns true if the stack is empty, false otherwise. + property bool Empty { + public native get(); + } + + // Retrieve the blocksize the stack was created with. + property int BlockSize { + public native get(); + } +}; + +/** + * 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 ArrayStack CreateStack(int 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. + * @error Invalid Handle or out of memory. + */ +native void PushStackCell(Handle stack, any value); + +/** + * Pushes a copy of a string onto the end of a stack, truncating it if it is + * too big. + * + * @param stack Stack Handle. + * @param value String to push. + * @error Invalid Handle or out of memory. + */ +native void PushStackString(Handle stack, const char[] value); + +/** + * Pushes a copy of 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. + * @error Invalid Handle or out of memory. + */ +native void PushStackArray(Handle stack, const any[] values, int 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, int 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, char[] buffer, int maxlength, int &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, int 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 bool PopStack(Handle stack) +{ + int value; + return PopStackCell(stack, value); +} + +/** + * Returns the blocksize the stack was created with. + * + * @param stack Stack Handle. + * @return The blocksize of the stack. + * @error Invalid Handle + */ +native int GetStackBlockSize(Handle stack); diff --git a/source/sourcemod/scripting/include/adt_trie.inc b/source/sourcemod/scripting/include/adt_trie.inc new file mode 100644 index 0000000..9e9eb34 --- /dev/null +++ b/source/sourcemod/scripting/include/adt_trie.inc @@ -0,0 +1,332 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 + +/* Object-oriented wrapper for maps. */ +methodmap StringMap < Handle +{ + // Creates a hash map. A hash map is a container that can map strings (called + // "keys") to arbitrary values (cells, arrays, or strings). Keys in a hash map + // are unique. That is, there is at most one entry in the map for a given key. + // + // Insertion, deletion, and lookup in a hash map are all considered to be fast + // operations, amortized to O(1), or constant time. + // + // The word "Trie" in this API is historical. As of SourceMod 1.6, tries have + // been internally replaced with hash tables, which have O(1) insertion time + // instead of O(n). + // + // The StringMap must be freed via delete or CloseHandle(). + public native StringMap(); + + // Clones a string map, 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. It should be + // closed when no longer needed with delete or CloseHandle(). + // + // @return New handle to the cloned string map + public native StringMap Clone(); + + // Sets a value in a hash map, either inserting a new entry or replacing an old one. + // + // @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. + public native bool SetValue(const char[] key, any value, bool replace=true); + + // Sets an array value in a Map, either inserting a new entry or replacing an old one. + // + // @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. + public native bool SetArray(const char[] key, const any[] array, int num_items, bool replace=true); + + // Sets a string value in a Map, either inserting a new entry or replacing an old one. + // + // @param key Key string. + // @param value String to store. + // @param replace If false, operation will fail if the key is already set. + // @return True on success, false on failure. + public native bool SetString(const char[] key, const char[] value, bool replace=true); + + // Retrieves a value in a Map. + // + // @param key Key string. + // @param value 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). + public native bool GetValue(const char[] key, any &value); + + // Retrieves an array in a Map. + // + // @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). + public native bool GetArray(const char[] key, any[] array, int max_size, int &size=0); + + // Retrieves a string in a Map. + // + // @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). + public native bool GetString(const char[] key, char[] value, int max_size, int &size=0); + + // Checks whether a key is present in a Map. + // + // @param key Key string. + // @return True if the key has been found, else false. + public native bool ContainsKey(const char[] key); + + // Removes a key entry from a Map. + // + // @param key Key string. + // @return True on success, false if the value was never set. + public native bool Remove(const char[] key); + + // Clears all entries from a Map. + public native void Clear(); + + // Create a snapshot of the map's keys. See StringMapSnapshot. + public native StringMapSnapshot Snapshot(); + + // Retrieves the number of elements in a map. + property int Size { + public native get(); + } +}; + +/** + * A StringMapSnapshot is created via StringMap.Snapshot(). It captures the + * keys on a map so they can be read. Snapshots must be freed with delete or + * CloseHandle(). + */ +methodmap StringMapSnapshot < Handle +{ + // Returns the number of keys in the map snapshot. + property int Length { + public native get(); + } + + // Returns the buffer size required to store a given key. That is, it + // returns the length of the key plus one. + // + // @param index Key index (starting from 0). + // @return Buffer size required to store the key string. + // @error Index out of range. + public native int KeyBufferSize(int index); + + // Retrieves the key string of a given key in a map snapshot. + // + // @param index Key index (starting from 0). + // @param buffer String buffer. + // @param maxlength Maximum buffer length. + // @return Number of bytes written to the buffer. + // @error Index out of range. + public native int GetKey(int index, char[] buffer, int maxlength); +}; + +/** + * Creates a hash map. A hash map is a container that can map strings (called + * "keys") to arbitrary values (cells, arrays, or strings). Keys in a hash map + * are unique. That is, there is at most one entry in the map for a given key. + * + * Insertion, deletion, and lookup in a hash map are all considered to be fast + * operations, amortized to O(1), or constant time. + * + * The word "Trie" in this API is historical. As of SourceMod 1.6, tries have + * been internally replaced with hash tables, which have O(1) insertion time + * instead of O(n). + * + * @return New Map Handle, which must be freed via CloseHandle(). + */ +native StringMap CreateTrie(); + +/** + * Sets a value in a hash map, either inserting a new entry or replacing an old one. + * + * @param map Map 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 map, const char[] key, any value, bool replace=true); + +/** + * Sets an array value in a Map, either inserting a new entry or replacing an old one. + * + * @param map Map 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 map, const char[] key, const any[] array, int num_items, bool replace=true); + +/** + * Sets a string value in a Map, either inserting a new entry or replacing an old one. + * + * @param map Map Handle. + * @param key Key string. + * @param value String to store. + * @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 map, const char[] key, const char[] value, bool replace=true); + +/** + * Retrieves a value in a Map. + * + * @param map Map Handle. + * @param key Key string. + * @param value 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 map, const char[] key, any &value); + +/** + * Retrieves an array in a Map. + * + * @param map Map 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 map, const char[] key, any[] array, int max_size, int &size=0); + +/** + * Retrieves a string in a Map. + * + * @param map Map 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 map, const char[] key, char[] value, int max_size, int &size=0); + +/** + * Removes a key entry from a Map. + * + * @param map Map Handle. + * @param key Key string. + * @return True on success, false if the value was never set. + * @error Invalid Handle. + */ +native bool RemoveFromTrie(Handle map, const char[] key); + +/** + * Clears all entries from a Map. + * + * @param map Map Handle. + * @error Invalid Handle. + */ +native void ClearTrie(Handle map); + +/** + * Retrieves the number of elements in a map. + * + * @param map Map Handle. + * @return Number of elements in the trie. + * @error Invalid Handle. + */ +native int GetTrieSize(Handle map); + +/** + * Creates a snapshot of all keys in the map. If the map is changed after this + * call, the changes are not reflected in the snapshot. Keys are not sorted. + * + * @param map Map Handle. + * @return New Map Snapshot Handle, which must be closed via CloseHandle(). + * @error Invalid Handle. + */ +native Handle CreateTrieSnapshot(Handle map); + +/** + * Returns the number of keys in a map snapshot. Note that this may be + * different from the size of the map, since the map can change after the + * snapshot of its keys was taken. + * + * @param snapshot Map snapshot. + * @return Number of keys. + * @error Invalid Handle. + */ +native int TrieSnapshotLength(Handle snapshot); + +/** + * Returns the buffer size required to store a given key. That is, it returns + * the length of the key plus one. + * + * @param snapshot Map snapshot. + * @param index Key index (starting from 0). + * @return Buffer size required to store the key string. + * @error Invalid Handle or index out of range. + */ +native int TrieSnapshotKeyBufferSize(Handle snapshot, int index); + +/** + * Retrieves the key string of a given key in a map snapshot. + * + * @param snapshot Map snapshot. + * @param index Key index (starting from 0). + * @param buffer String buffer. + * @param maxlength Maximum buffer length. + * @return Number of bytes written to the buffer. + * @error Invalid Handle or index out of range. + */ +native int GetTrieSnapshotKey(Handle snapshot, int index, char[] buffer, int maxlength); diff --git a/source/sourcemod/scripting/include/autoexecconfig.inc b/source/sourcemod/scripting/include/autoexecconfig.inc new file mode 100644 index 0000000..e057b1b --- /dev/null +++ b/source/sourcemod/scripting/include/autoexecconfig.inc @@ -0,0 +1,765 @@ +/** + * AutoExecConfig + * + * Copyright (C) 2013-2017 Impact + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * 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 + */ + +#if defined _autoexecconfig_included + #endinput +#endif +#define _autoexecconfig_included + + +#include + +#define AUTOEXECCONFIG_VERSION "0.1.5" +#define AUTOEXECCONFIG_URL "https://forums.alliedmods.net/showthread.php?t=204254" + +// Append +#define AUTOEXEC_APPEND_BAD_FILENAME 0 +#define AUTOEXEC_APPEND_FILE_NOT_FOUND 1 +#define AUTOEXEC_APPEND_BAD_HANDLE 2 +#define AUTOEXEC_APPEND_SUCCESS 3 + + + +// Find +#define AUTOEXEC_FIND_BAD_FILENAME 10 +#define AUTOEXEC_FIND_FILE_NOT_FOUND 11 +#define AUTOEXEC_FIND_BAD_HANDLE 12 +#define AUTOEXEC_FIND_NOT_FOUND 13 +#define AUTOEXEC_FIND_SUCCESS 14 + + + +// Clean +#define AUTOEXEC_CLEAN_FILE_NOT_FOUND 20 +#define AUTOEXEC_CLEAN_BAD_HANDLE 21 +#define AUTOEXEC_CLEAN_SUCCESS 22 + + + +// General +#define AUTOEXEC_NO_CONFIG 30 + + + +// Formatter +#define AUTOEXEC_FORMAT_BAD_FILENAME 40 +#define AUTOEXEC_FORMAT_SUCCESS 41 + + + +// Global variables +static char g_sConfigFile[PLATFORM_MAX_PATH]; +static char g_sRawFileName[PLATFORM_MAX_PATH]; +static char g_sFolderPath[PLATFORM_MAX_PATH]; + +static bool g_bCreateFile = false; +static Handle g_hPluginHandle = null; + +static bool g_bCreateDirectory = false; +static int g_bCreateDirectoryMode = FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC|FPERM_G_READ|FPERM_G_EXEC|FPERM_O_READ|FPERM_O_EXEC; + + +// Workaround for now +static int g_iLastFindResult; +static int g_iLastAppendResult; + + + + +/** + * Returns the last result from the parser. + * + * @return Returns one of the AUTOEXEC_FIND values or -1 if not set. +*/ +stock int AutoExecConfig_GetFindResult() +{ + return g_iLastFindResult; +} + + + + + +/** + * Returns the last result from the appender. + * + * @return Returns one of the AUTOEXEC_APPEND values or -1 if not set. +*/ +stock int AutoExecConfig_GetAppendResult() +{ + return g_iLastAppendResult; +} + + +/** + * Set if the config file should be created by the autoexecconfig include itself if it doesn't exist. + * + * @param create True if config file should be created, false otherwise. + * @noreturn + */ +stock void AutoExecConfig_SetCreateFile(bool create) +{ + g_bCreateFile = create; +} + + +/** + * Set if the config file's folder should be created by the autoexecconfig include itself if it doesn't exist. + * Note: Must be used before AutoExecConfig_SetFile as the potential creation of it happens there + * + * @param create True if config file should be created, false otherwise. + * @param mode Folder permission mode, default is u=rwx,g=rx,o=rx. + * @noreturn + */ +stock void AutoExecConfig_SetCreateDirectory(bool create, int mode=FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC|FPERM_G_READ|FPERM_G_EXEC|FPERM_O_READ|FPERM_O_EXEC) +{ + g_bCreateDirectory = create; + g_bCreateDirectoryMode = mode; +} + + +/** + * Returns if the config file should be created if it doesn't exist. + * + * @return Returns true, if the config file should be created or false if it should not. + */ +stock bool AutoExecConfig_GetCreateFile() +{ + return g_bCreateFile; +} + + +/** + * Set the plugin for which the config file should be created. + * Set to null to use the calling plugin. + * Used to print the correct filename in the top comment when creating the file. + * + * @param plugin The plugin to create convars for or null to use the calling plugin. + * @noreturn + */ +stock void AutoExecConfig_SetPlugin(Handle plugin) +{ + g_hPluginHandle = plugin; +} + + +/** + * Returns the plugin's handle for which the config file is created. + * + * @return The plugin handle + */ +stock Handle AutoExecConfig_GetPlugin() +{ + return g_hPluginHandle; +} + + +/** + * Set the global autoconfigfile used by functions of this file. + * Note: does not support subfolders like folder1/folder2 + * + * @param file Name of the config file, path and .cfg extension is being added if not given. + * @param folder Folder under cfg/ to use. By default this is "sourcemod." + * @return True if formatter returned success, false otherwise. +*/ +stock bool AutoExecConfig_SetFile(char[] file, char[] folder="sourcemod") +{ + Format(g_sConfigFile, sizeof(g_sConfigFile), "%s", file); + + // Global buffers for cfg execution + strcopy(g_sRawFileName, sizeof(g_sRawFileName), file); + strcopy(g_sFolderPath, sizeof(g_sFolderPath), folder); + + + // Format the filename + return AutoExecConfig_FormatFileName(g_sConfigFile, sizeof(g_sConfigFile), folder) == AUTOEXEC_FORMAT_SUCCESS; +} + + + + + + +/** + * Get the formatted autoconfigfile used by functions of this file. + * + * @param buffer String to format. + * @param size Maximum size of buffer + * @return True if filename was set, false otherwise. +*/ +stock bool AutoExecConfig_GetFile(char[] buffer,int size) +{ + if (strlen(g_sConfigFile) > 0) + { + strcopy(buffer, size, g_sConfigFile); + + return true; + } + + // Security for decl users + buffer[0] = '\0'; + + return false; +} + + + + + + +/** + * Creates a convar and appends it to the autoconfigfile if not found. + * FCVAR_DONTRECORD will be skipped. + * + * @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. +*/ +stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] defaultValue, const char[] description="", int flags=0, bool hasMin=false, float min=0.0, bool hasMax=false, float max=0.0) +{ + // If configfile was set and convar has no dontrecord flag + if (!(flags & FCVAR_DONTRECORD) && strlen(g_sConfigFile) > 0) + { + // Reset the results + g_iLastFindResult = -1; + g_iLastAppendResult = -1; + + + // Add it if not found + char buffer[64]; + + g_iLastFindResult = AutoExecConfig_FindValue(name, buffer, sizeof(buffer), true); + + // We only add this convar if it doesn't exist, or the file doesn't exist and it should be auto-generated + if (g_iLastFindResult == AUTOEXEC_FIND_NOT_FOUND || (g_iLastFindResult == AUTOEXEC_FIND_FILE_NOT_FOUND && g_bCreateFile)) + { + g_iLastAppendResult = AutoExecConfig_AppendValue(name, defaultValue, description, flags, hasMin, min, hasMax, max); + } + } + + + // Create the convar + return CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); +} + + + + +/** + * Executes the autoconfigfile and adds it to the OnConfigsExecuted forward. + * If we didn't create it ourselves we let SourceMod create it. + * + * @noreturn +*/ +stock void AutoExecConfig_ExecuteFile() +{ + // Only let sourcemod create the file, if we didn't do that already. + AutoExecConfig(!g_bCreateFile, g_sRawFileName, g_sFolderPath); +} + + + + + +/** + * Formats a autoconfigfile, prefixes path and adds .cfg extension if missing. + * + * @param buffer String to format. + * @param size Maximum size of buffer. + * @return Returns one of the AUTOEXEC_FORMAT values.. +*/ +stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] folder="sourcemod") +{ + // No config set + if (strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + // Can't be an cfgfile + if (StrContains(g_sConfigFile, ".cfg") != -1 && strlen(g_sConfigFile) < 4) + { + return AUTOEXEC_FORMAT_BAD_FILENAME; + } + + + // Pathprefix + char pathprefixbuffer[PLATFORM_MAX_PATH]; + if (strlen(folder) > 0) + { + Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/%s/", folder); + + if (g_bCreateDirectory && !DirExists(pathprefixbuffer)) + { + CreateDirectory(pathprefixbuffer, g_bCreateDirectoryMode); + } + } + else + { + Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/"); + } + + + char filebuffer[PLATFORM_MAX_PATH]; + filebuffer[0] = '\0'; + + // Add path if file doesn't begin with it + if (StrContains(buffer, pathprefixbuffer) != 0) + { + StrCat(filebuffer, sizeof(filebuffer), pathprefixbuffer); + } + + StrCat(filebuffer, sizeof(filebuffer), g_sConfigFile); + + + // Add .cfg extension if file doesn't end with it + if (StrContains(filebuffer[strlen(filebuffer) - 4], ".cfg") != 0) + { + StrCat(filebuffer, sizeof(filebuffer), ".cfg"); + } + + strcopy(buffer, size, filebuffer); + + return AUTOEXEC_FORMAT_SUCCESS; +} + + + + + + +/** + * Appends a convar to the global autoconfigfile + * + * @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 Returns one of the AUTOEXEC_APPEND values +*/ +stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValue, const char[] description, int flags, bool hasMin, float min, bool hasMax, float max) +{ + // No config set + if (strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + char filebuffer[PLATFORM_MAX_PATH]; + strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile); + + + //PrintToServer("pathbuffer: %s", filebuffer); + + bool bFileExists = FileExists(filebuffer); + + if (g_bCreateFile || bFileExists) + { + // If the file already exists we open it in append mode, otherwise we use a write mode which creates the file + File fFile = OpenFile(filebuffer, (bFileExists ? "a" : "w")); + char writebuffer[2048]; + + + if (fFile == null) + { + return AUTOEXEC_APPEND_BAD_HANDLE; + } + + // We just created the file, so add some header about version and stuff + if (g_bCreateFile && !bFileExists) + { + fFile.WriteLine( "// This file was auto-generated by AutoExecConfig v%s (%s)", AUTOEXECCONFIG_VERSION, AUTOEXECCONFIG_URL); + + GetPluginFilename(g_hPluginHandle, writebuffer, sizeof(writebuffer)); + Format(writebuffer, sizeof(writebuffer), "// ConVars for plugin \"%s\"", writebuffer); + fFile.WriteLine(writebuffer); + } + + // Spacer + fFile.WriteLine("\n"); + + + // This is used for multiline comments + int newlines = GetCharCountInStr('\n', description); + if (newlines == 0) + { + // We have no newlines, we can write the description to the file as is + Format(writebuffer, sizeof(writebuffer), "// %s", description); + fFile.WriteLine(writebuffer); + } + else + { + char[][] newlineBuf = new char[newlines +1][2048]; + ExplodeString(description, "\n", newlineBuf, newlines +1, 2048, false); + + // Each newline gets a commented newline + for (int i; i <= newlines; i++) + { + if (strlen(newlineBuf[i]) > 0) + { + fFile.WriteLine("// %s", newlineBuf[i]); + } + } + } + + + // Descspacer + fFile.WriteLine("// -"); + + + // Default + Format(writebuffer, sizeof(writebuffer), "// Default: \"%s\"", defaultValue); + fFile.WriteLine(writebuffer); + + + // Minimum + if (hasMin) + { + Format(writebuffer, sizeof(writebuffer), "// Minimum: \"%f\"", min); + fFile.WriteLine(writebuffer); + } + + + // Maximum + if (hasMax) + { + Format(writebuffer, sizeof(writebuffer), "// Maximum: \"%f\"", max); + fFile.WriteLine(writebuffer); + } + + + // Write end and defaultvalue + Format(writebuffer, sizeof(writebuffer), "%s \"%s\"", name, defaultValue); + fFile.WriteLine(writebuffer); + + + fFile.Close(); + + return AUTOEXEC_APPEND_SUCCESS; + } + + return AUTOEXEC_APPEND_FILE_NOT_FOUND; +} + + + + + + +/** + * Returns a convar's value from the global autoconfigfile + * + * @param cvar Cvar to search for. + * @param value Buffer to store result into. + * @param size Maximum size of buffer. + * @param caseSensitive Whether or not the search should be case sensitive. + * @return Returns one of the AUTOEXEC_FIND values +*/ +stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bool caseSensitive=false) +{ + // Security for decl users + value[0] = '\0'; + + + // No config set + if (strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + char filebuffer[PLATFORM_MAX_PATH]; + strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile); + + + + //PrintToServer("pathbuffer: %s", filebuffer); + + bool bFileExists = FileExists(filebuffer); + + // We want to create the config file and it doesn't exist yet. + if (g_bCreateFile && !bFileExists) + { + return AUTOEXEC_FIND_FILE_NOT_FOUND; + } + + + if (bFileExists) + { + File fFile = OpenFile(filebuffer, "r"); + int valuestart; + int valueend; + int cvarend; + + // Just an reminder to self, leave the values that high + char sConvar[64]; + char sValue[64]; + char readbuffer[2048]; + char copybuffer[2048]; + + if (fFile == null) + { + return AUTOEXEC_FIND_BAD_HANDLE; + } + + + while (!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer))) + { + // Is a comment or not valid + if (IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || (!IsCharNumeric(readbuffer[0]) && !IsCharAlpha(readbuffer[0])) ) + { + continue; + } + + + // Has not enough spaces, must have at least 1 + if (GetCharCountInStr(' ', readbuffer) < 1) + { + continue; + } + + + // Ignore cvars which aren't quoted + if (GetCharCountInStr('"', readbuffer) != 2) + { + continue; + } + + + + // Get the start of the value + if ( (valuestart = StrContains(readbuffer, "\"")) == -1 ) + { + continue; + } + + + // Get the end of the value + if ( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 ) + { + continue; + } + + + // Get the start of the cvar, + if ( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart) + { + continue; + } + + + // Skip if cvarendindex is before valuestartindex + if (cvarend >= valuestart) + { + continue; + } + + + // Convar + // Tempcopy for security + strcopy(copybuffer, sizeof(copybuffer), readbuffer); + copybuffer[cvarend] = '\0'; + + strcopy(sConvar, sizeof(sConvar), copybuffer); + + + // Value + // Tempcopy for security + strcopy(copybuffer, sizeof(copybuffer), readbuffer[valuestart+1]); + copybuffer[valueend] = '\0'; + + strcopy(sValue, sizeof(sValue), copybuffer); + + + //PrintToServer("Cvar %s has a value of %s", sConvar, sValue); + + if (StrEqual(sConvar, cvar, caseSensitive)) + { + Format(value, size, "%s", sConvar); + + fFile.Close(); + return AUTOEXEC_FIND_SUCCESS; + } + } + + fFile.Close(); + return AUTOEXEC_FIND_NOT_FOUND; + } + + + return AUTOEXEC_FIND_FILE_NOT_FOUND; +} + + + + + + +/** + * Cleans the global autoconfigfile from too much spaces + * + * @return One of the AUTOEXEC_CLEAN values. +*/ +stock int AutoExecConfig_CleanFile() +{ + // No config set + if (strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + char sfile[PLATFORM_MAX_PATH]; + strcopy(sfile, sizeof(sfile), g_sConfigFile); + + + // Security + if (!FileExists(sfile)) + { + return AUTOEXEC_CLEAN_FILE_NOT_FOUND; + } + + + + char sfile2[PLATFORM_MAX_PATH]; + Format(sfile2, sizeof(sfile2), "%s_tempcopy", sfile); + + + char readbuffer[2048]; + int count; + bool firstreached; + + + // Open files + File fFile1 = OpenFile(sfile, "r"); + File fFile2 = OpenFile(sfile2, "w"); + + + + // Check filehandles + if (fFile1 == null || fFile2 == null) + { + if (fFile1 != null) + { + //PrintToServer("Handle1 invalid"); + fFile1.Close(); + } + + if (fFile2 != null) + { + //PrintToServer("Handle2 invalid"); + fFile2.Close(); + } + + return AUTOEXEC_CLEAN_BAD_HANDLE; + } + + + + while (!fFile1.EndOfFile() && fFile1.ReadLine(readbuffer, sizeof(readbuffer))) + { + // Is space + if (IsCharSpace(readbuffer[0])) + { + count++; + } + // No space, count from start + else + { + count = 0; + } + + + // Don't write more than 1 space if seperation after informations have been reached + if (count < 2 || !firstreached) + { + ReplaceString(readbuffer, sizeof(readbuffer), "\n", ""); + fFile2.WriteLine(readbuffer); + } + + + // First bigger seperation after informations has been reached + if (count == 2) + { + firstreached = true; + } + } + + + fFile1.Close(); + fFile2.Close(); + + + // This might be a risk, for now it works + DeleteFile(sfile); + RenameFile(sfile, sfile2); + + return AUTOEXEC_CLEAN_SUCCESS; +} + + + + + + +/** + * Returns how many times the given char occures in the given string. + * + * @param str String to search for in. + * @return Occurences of the given char found in string. +*/ +stock static int GetCharCountInStr(int character, const char[] str) +{ + int len = strlen(str); + int count; + + for (int i; i < len; i++) + { + if (str[i] == character) + { + count++; + } + } + + return count; +} + + + + + + +#pragma deprecated +stock bool AutoExecConfig_CacheConvars() +{ + return false; +} diff --git a/source/sourcemod/scripting/include/banning.inc b/source/sourcemod/scripting/include/banning.inc new file mode 100644 index 0000000..e22f641 --- /dev/null +++ b/source/sourcemod/scripting/include/banning.inc @@ -0,0 +1,156 @@ +/** + * 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(int client, + int time, + int flags, + const char[] reason, + const char[] kick_message, + const char[] 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 char[] identity, + int time, + int flags, + const char[] reason, + const char[] 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 unbanning. + */ +forward Action OnRemoveBan(const char[] identity, + int flags, + const char[] 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(int client, + int time, + int flags, + const char[] reason, + const char[] kick_message="", + const char[] 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 char[] identity, + int time, + int flags, + const char[] reason, + const char[] 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 char[] identity, + int flags, + const char[] command="", + any source=0); diff --git a/source/sourcemod/scripting/include/basecomm.inc b/source/sourcemod/scripting/include/basecomm.inc new file mode 100644 index 0000000..7b7a4c7 --- /dev/null +++ b/source/sourcemod/scripting/include/basecomm.inc @@ -0,0 +1,109 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2011 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 _basecomm_included + #endinput +#endif +#define _basecomm_included + +/** + * Called when a client is muted or unmuted + * + * @param client Client index + * @param muteState True if client was muted, false otherwise + */ +forward void BaseComm_OnClientMute(int client, bool muteState); + + /** + * Called when a client is gagged or ungagged + * + * @param client Client index + * @param gagState True if client was gaged, false otherwise + */ +forward void BaseComm_OnClientGag(int client, bool gagState); + +/** + * Returns whether or not a client is gagged + * + * @param client Client index. + * @return True if client is gagged, false otherwise. + */ +native bool BaseComm_IsClientGagged(int client); + +/** + * Returns whether or not a client is muted + * + * @param client Client index. + * @return True if client is muted, false otherwise. + */ +native bool BaseComm_IsClientMuted(int client); + +/** + * Sets a client's gag state + * + * @param client Client index. + * @param gagState True to gag client, false to ungag. + * @return True if this caused a change in gag state, false otherwise. + */ +native bool BaseComm_SetClientGag(int client, bool gagState); + +/** + * Sets a client's mute state + * + * @param client Client index. + * @param muteState True to mute client, false to unmute. + * @return True if this caused a change in mute state, false otherwise. + */ +native bool BaseComm_SetClientMute(int client, bool muteState); + +/* DO NOT EDIT BELOW THIS LINE */ + +public SharedPlugin __pl_basecomm = +{ + name = "basecomm", + file = "basecomm.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_basecomm_SetNTVOptional() +{ + MarkNativeAsOptional("BaseComm_IsClientGagged"); + MarkNativeAsOptional("BaseComm_IsClientMuted"); + MarkNativeAsOptional("BaseComm_SetClientGag"); + MarkNativeAsOptional("BaseComm_SetClientMute"); +} +#endif diff --git a/source/sourcemod/scripting/include/bitbuffer.inc b/source/sourcemod/scripting/include/bitbuffer.inc new file mode 100644 index 0000000..635958b --- /dev/null +++ b/source/sourcemod/scripting/include/bitbuffer.inc @@ -0,0 +1,470 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 + +methodmap BfWrite < Handle +{ + // Writes a single bit to a writable bitbuffer (bf_write). + // + // @param bit Bit to write (true for 1, false for 0). + public native void WriteBool(bool bit); + + // Writes a byte to a writable bitbuffer (bf_write). + // + // @param byte Byte to write (value will be written as 8bit). + public native void WriteByte(int byte); + + // Writes a byte to a writable bitbuffer (bf_write). + // + // @param chr Character to write. + public native void WriteChar(int chr); + + // Writes a 16bit integer to a writable bitbuffer (bf_write). + // + // @param num Integer to write (value will be written as 16bit). + public native void WriteShort(int num); + + // Writes a 16bit unsigned integer to a writable bitbuffer (bf_write). + // + // @param num Integer to write (value will be written as 16bit). + public native void WriteWord(int num); + + // Writes a normal integer to a writable bitbuffer (bf_write). + // + // @param num Integer to write (value will be written as 32bit). + public native void WriteNum(int num); + + // Writes a floating point number to a writable bitbuffer (bf_write). + // + // @param num Number to write. + public native void WriteFloat(float num); + + // Writes a string to a writable bitbuffer (bf_write). + // + // @param string Text string to write. + public native void WriteString(const char[] string); + + // Writes an entity to a writable bitbuffer (bf_write). + // + // @param ent Entity index to write. + public native void WriteEntity(int ent); + + // Writes a bit angle to a writable bitbuffer (bf_write). + // + // @param angle Angle to write. + // @param numBits Optional number of bits to use. + public native void WriteAngle(float angle, int numBits=8); + + // Writes a coordinate to a writable bitbuffer (bf_write). + // + // @param coord Coordinate to write. + public native void WriteCoord(float coord); + + // Writes a 3D vector of coordinates to a writable bitbuffer (bf_write). + // + // @param coord Coordinate array to write. + public native void WriteVecCoord(float coord[3]); + + // Writes a 3D normal vector to a writable bitbuffer (bf_write). + // + // @param vec Vector to write. + public native void WriteVecNormal(float vec[3]); + + // Writes a 3D angle vector to a writable bitbuffer (bf_write). + // + // @param angles Angle vector to write. + public native void WriteAngles(float angles[3]); +}; + +methodmap BfRead < Handle +{ + // Reads a single bit from a readable bitbuffer (bf_read). + // + // @return Bit value read. + public native bool ReadBool(); + + // Reads a byte from a readable bitbuffer (bf_read). + // + // @return Byte value read (read as 8bit). + public native int ReadByte(); + + // Reads a character from a readable bitbuffer (bf_read). + // + // @return Character value read. + public native int ReadChar(); + + // 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). + public native int ReadShort(); + + // 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). + public native int ReadWord(); + + // Reads a normal integer to a readable bitbuffer (bf_read). + // + // @return Integer value read (read as 32bit). + public native int ReadNum(); + + // Reads a floating point number from a readable bitbuffer (bf_read). + // + // @return Floating point value read. + public native float ReadFloat(); + + // Reads a string from a readable bitbuffer (bf_read). + // + // @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. + public native int ReadString(char[] buffer, int maxlength, bool line=false); + + // Reads an entity from a readable bitbuffer (bf_read). + // + // @return Entity index read. + public native int ReadEntity(); + + // Reads a bit angle from a readable bitbuffer (bf_read). + // + // @param numBits Optional number of bits to use. + // @return Angle read. + public native float ReadAngle(int numBits=8); + + // Reads a coordinate from a readable bitbuffer (bf_read). + // + // @return Coordinate read. + public native float ReadCoord(); + + // Reads a 3D vector of coordinates from a readable bitbuffer (bf_read). + // + // @param coord Destination coordinate array. + public native void ReadVecCoord(float coord[3]); + + // Reads a 3D normal vector from a readable bitbuffer (bf_read). + // + // @param vec Destination vector array. + public native void ReadVecNormal(float vec[3]); + + // Reads a 3D angle vector from a readable bitbuffer (bf_read). + // + // @param angles Destination angle vector. + public native void ReadAngles(float angles[3]); + + // Returns the number of bytes left in a readable bitbuffer (bf_read). + property int BytesLeft { + public native get(); + } +}; + +/** + * 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). + * @error Invalid or incorrect Handle. + */ +native void 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). + * @error Invalid or incorrect Handle. + */ +native void BfWriteByte(Handle bf, int byte); + +/** + * Writes a byte to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param chr Character to write. + * @error Invalid or incorrect Handle. + */ +native void BfWriteChar(Handle bf, int 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). + * @error Invalid or incorrect Handle. + */ +native void BfWriteShort(Handle bf, int 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). + * @error Invalid or incorrect Handle. + */ +native void BfWriteWord(Handle bf, int 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). + * @error Invalid or incorrect Handle. + */ +native void BfWriteNum(Handle bf, int 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. + * @error Invalid or incorrect Handle. + */ +native void 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. + * @error Invalid or incorrect Handle. + */ +native void BfWriteString(Handle bf, const char[] 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. + * @error Invalid or incorrect Handle, or invalid entity. + */ +native void BfWriteEntity(Handle bf, int 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. + * @error Invalid or incorrect Handle. + */ +native void BfWriteAngle(Handle bf, float angle, int numBits=8); + +/** + * Writes a coordinate to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param coord Coordinate to write. + * @error Invalid or incorrect Handle. + */ +native void 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. + * @error Invalid or incorrect Handle. + */ +native void 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. + * @error Invalid or incorrect Handle. + */ +native void 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. + * @error Invalid or incorrect Handle. + */ +native void 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 int 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 int 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 int 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 int 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 int 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 int BfReadString(Handle bf, char[] buffer, int 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 int 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, int 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. + * @error Invalid or incorrect Handle. + */ +native void 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. + * @error Invalid or incorrect Handle. + */ +native void 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. + * @error Invalid or incorrect Handle. + */ +native void 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 int BfGetNumBytesLeft(Handle bf); diff --git a/source/sourcemod/scripting/include/clientprefs.inc b/source/sourcemod/scripting/include/clientprefs.inc new file mode 100644 index 0000000..bf71c8c --- /dev/null +++ b/source/sourcemod/scripting/include/clientprefs.inc @@ -0,0 +1,372 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2011 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 +}; + +#define COOKIE_MAX_NAME_LENGTH 30 /**< Maximum Cookie name length. */ +#define COOKIE_MAX_DESCRIPTION_LENGTH 255 /**< Maximum Cookie description length. */ + +/** + * Cookie Menu Callback prototype + * + * @param client Client index. + * @param action CookieMenuAction being performed. + * @param info Info data passed. + * @param buffer Outbut buffer. + * @param maxlen Max length of the output buffer. + */ +typedef CookieMenuHandler = function void ( + int client, + CookieMenuAction action, + any info, + char[] buffer, + int maxlen +); + +/** + * 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. + */ + +methodmap Cookie < Handle { + // Creates a new Client preference cookie. + // + // Handles returned 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. + public native Cookie(const char[] name, const char[] description, CookieAccess access); + + // Searches for a Client preference cookie. + // + // Handles returned by Cookie.Find 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, null otherwise. + + public static native Cookie Find(const char[] name); + + // Set the value of a Client preference cookie. + // + // @param client Client index. + // @param value String value to set. + // @error Invalid cookie handle or invalid client index. + public native void Set(int client, const char[] value); + + // Retrieve the value of a Client preference cookie. + // + // @param client Client index. + // @param buffer Copyback buffer for value. + // @param maxlen Maximum length of the buffer. + // @error Invalid cookie handle or invalid client index. + public native void Get(int client, char[] buffer, int maxlen); + + // Sets the value of a Client preference cookie based on an authID string. + // + // @param authID String Auth/STEAM ID of player to set. + // @param value String value to set. + // @error Invalid cookie handle. + public native void SetByAuthId(const char[] authID, const char[] value); + + // Add a new prefab item to the client cookie settings menu. + // + // Note: This handles everything automatically and does not require a callback + // + // @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. + // @error Invalid cookie handle. + public native void SetPrefabMenu(CookieMenu type, const char[] display, CookieMenuHandler handler=INVALID_FUNCTION, any info=0); + + // Returns the last updated timestamp for a client cookie + // + // @param client Client index. + // @return Last updated timestamp. + public native int GetClientTime(int client); + + // Returns the access level of a cookie + // + // @return CookieAccess access level. + // @error Invalid cookie handle. + property CookieAccess AccessLevel { + public native get(); + } +}; + +/** + * 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 Cookie RegClientCookie(const char[] name, const char[] 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, null otherwise. + + */ +native Cookie FindClientCookie(const char[] 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. + * @error Invalid cookie handle or invalid client index. + */ +native void SetClientCookie(int client, Handle cookie, const char[] 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. + * @error Invalid cookie handle or invalid client index. + */ +native void GetClientCookie(int client, Handle cookie, char[] buffer, int maxlen); + +/** + * Sets the value of a Client preference cookie based on an authID string. + * + * @param authID String Auth/STEAM ID of player to set. + * @param cookie Client preference cookie handle. + * @param value String value to set. + * @error Invalid cookie handle. + */ +native void SetAuthIdCookie(const char[] authID, Handle cookie, const char[] value); + +/** + * 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(int client); + +/** + * Called once a client's saved cookies have been loaded from the database. + * + * @param client Client index. + */ +forward void OnClientCookiesCached(int client); + +/** + * 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. + * @error Invalid cookie handle. + */ +native void SetCookiePrefabMenu(Handle cookie, CookieMenu type, const char[] display, CookieMenuHandler handler=INVALID_FUNCTION, any 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. + * @error Invalid cookie handle. + */ +native void SetCookieMenuItem(CookieMenuHandler handler, any info, const char[] display); + +/** + * Displays the settings menu to a client. + * + * @param client Client index. + */ +native void ShowCookieMenu(int 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. + * @return True on success, false if there are no more commands. + */ +native bool ReadCookieIterator(Handle iter, + char[] name, + int nameLen, + CookieAccess &access, + char[] desc="", + int 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 int GetClientCookieTime(int client, Handle cookie); + +/** + * Do not edit below this line! + */ +public Extension __ext_cprefs = +{ + name = "Client Preferences", + file = "clientprefs.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 void __ext_cprefs_SetNTVOptional() +{ + MarkNativeAsOptional("RegClientCookie"); + MarkNativeAsOptional("FindClientCookie"); + MarkNativeAsOptional("SetClientCookie"); + MarkNativeAsOptional("GetClientCookie"); + MarkNativeAsOptional("SetAuthIdCookie"); + MarkNativeAsOptional("AreClientCookiesCached"); + MarkNativeAsOptional("SetCookiePrefabMenu"); + MarkNativeAsOptional("SetCookieMenuItem"); + MarkNativeAsOptional("ShowCookieMenu"); + MarkNativeAsOptional("GetCookieIterator"); + MarkNativeAsOptional("ReadCookieIterator"); + MarkNativeAsOptional("GetCookieAccess"); + MarkNativeAsOptional("GetClientCookieTime"); + + MarkNativeAsOptional("Cookie.Cookie"); + MarkNativeAsOptional("Cookie.Find"); + MarkNativeAsOptional("Cookie.Set"); + MarkNativeAsOptional("Cookie.Get"); + MarkNativeAsOptional("Cookie.SetByAuthId"); + MarkNativeAsOptional("Cookie.SetPrefabMenu"); + MarkNativeAsOptional("Cookie.GetClientTime"); + MarkNativeAsOptional("Cookie.AccessLevel.get"); +} +#endif diff --git a/source/sourcemod/scripting/include/clients.inc b/source/sourcemod/scripting/include/clients.inc new file mode 100644 index 0000000..8f98080 --- /dev/null +++ b/source/sourcemod/scripting/include/clients.inc @@ -0,0 +1,831 @@ +/** + * 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 */ +}; + +/** + * Auth string types. + * + * Note that for the Steam2 and Steam3 types, the following ids are + * also valid values: + * "STEAM_ID_PENDING" - Authentication is pending. + * "STEAM_ID_LAN" - Authentication is disabled because of being on a LAN server. + * "BOT" - The client is a bot. + */ +enum AuthIdType +{ + AuthId_Engine = 0, /**< The game-specific auth string as returned from the engine */ + + // The following are only available on games that support Steam authentication. + AuthId_Steam2, /**< Steam2 rendered format, ex "STEAM_1:1:4153990" */ + AuthId_Steam3, /**< Steam3 rendered format, ex "[U:1:8307981]" */ + AuthId_SteamID64 /**< A SteamID64 (uint64) as a String, ex "76561197968573709" */ +}; + +/** + * MAXPLAYERS is not the same as MaxClients. + * MAXPLAYERS is a hardcoded value as an upper limit. MaxClients changes based on the server. + */ + +#define MAXPLAYERS 65 /**< Maximum number of players SourceMod supports */ +#define MAX_NAME_LENGTH 128 /**< Maximum buffer required to store a client name */ +#define MAX_AUTHID_LENGTH 64 /**< Maximum buffer required to store any AuthID type */ + +public const int 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(int client, char[] rejectmsg, int maxlen); + +/** + * Called once a client successfully connects. This callback is paired with OnClientDisconnect. + * + * @param client Client index. + */ +forward void OnClientConnected(int 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. + */ +forward void OnClientPutInServer(int client); + +/** + * Called when a client is disconnecting from the server. + * + * @param client Client index. + */ +forward void OnClientDisconnect(int client); + +/** + * Called when a client is disconnected from the server. + * + * @param client Client index. + */ +forward void OnClientDisconnect_Post(int 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. + * @return Plugin_Handled blocks the command from being sent, + * and Plugin_Continue resumes normal functionality. + */ +forward Action OnClientCommand(int client, int args); + +/** + * Called when a client is sending a KeyValues command. + * + * @param client Client index. + * @param kv Editable KeyValues data to be sent as the command. + * (This handle should not be stored and will be closed + * after this forward completes.) + * @return Plugin_Handled blocks the command from being sent, + * and Plugin_Continue resumes normal functionality. + */ +forward Action OnClientCommandKeyValues(int client, KeyValues kv); + +/** + * Called after a client has sent a KeyValues command. + * + * @param client Client index. + * @param kv KeyValues data sent as the command. + * (This handle should not be stored and will be closed + * after this forward completes.) + */ +forward void OnClientCommandKeyValues_Post(int client, KeyValues kv); + +/** + * Called whenever the client's settings are changed. + * + * @param client Client index. + */ +forward void OnClientSettingsChanged(int client); + +/** + * Called when a client receives an auth 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 Steam2 id, if available, else engine auth id. + */ +forward void OnClientAuthorized(int client, const char[] 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 guaranteed 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(int 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. + */ +forward void OnClientPostAdminFilter(int client); + +/** + * Called once a client is authorized and fully in-game, and + * after all post-connection authorizations have been performed. + * + * This callback is guaranteed to occur on all clients, and always + * after each OnClientPutInServer() call. + * + * @param client Client index. + */ +forward void OnClientPostAdminCheck(int client); + +/** + * Called when the language was received from the player. + * + * @param client Client index. + * @param language Language number. + */ +forward void OnClientLanguageChanged(int client, int language); + +/** + * This function is deprecated. 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. + * @deprecated Use MaxClients variable instead. + */ +#pragma deprecated Use MaxClients variable instead. +native int GetMaxClients(); + +/** + * Returns the maximum number of human players allowed on the server. This is + * a game-specific function used on newer games to limit the number of humans + * that can join a game and can be lower than MaxClients. It is the number often + * reflected in the server browser or when viewing the output of the status command. + * On unsupported games or modes without overrides, it will return the same value + * as MaxClients. + * + * You should not globally cache the value to GetMaxHumanPlayers() because it can change across + * game modes. You may still cache it locally. + * + * @return Maximum number of humans allowed. + */ +native int GetMaxHumanPlayers(); + +/** + * Returns the client count put in the server. + * + * @param inGameOnly If false connecting players are also counted. + * @return Client count in the server. + */ +native int 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(int client, char[] name, int maxlen); + +/** + * Retrieves a client's IP address. + * + * @param client Player index. + * @param ip 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(int client, char[] ip, int 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). + * @param validate Check backend validation status. + * DO NOT PASS FALSE UNLESS YOU UNDERSTAND THE CONSEQUENCES, + * You WILL KNOW if you need to use this, MOST WILL NOT. + * @return True on success, false otherwise. + * @error If the client is not connected or the index is invalid. + * @deprecated Use GetClientAuthId + */ +#pragma deprecated Use GetClientAuthId +native bool GetClientAuthString(int client, char[] auth, int maxlen, bool validate=true); + +/** + * Retrieves a client's authentication string (SteamID). + * + * @param client Player index. + * @param authType Auth id type and format to use. + * @param auth Buffer to store the client's auth id. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @param validate Check backend validation status. + * DO NOT PASS FALSE UNLESS YOU UNDERSTAND THE CONSEQUENCES, + * You WILL KNOW if you need to use this, MOST WILL NOT. + * @return True on success, false otherwise. + * @error If the client is not connected or the index is invalid. + */ +native bool GetClientAuthId(int client, AuthIdType authType, char[] auth, int maxlen, bool validate=true); + +/** + * Returns the client's Steam account ID, a number uniquely identifying a given Steam account. + * This number is the basis for the various display SteamID forms, see the AuthIdType enum for examples. + * + * @param client Client Index. + * @param validate Check backend validation status. + * DO NOT PASS FALSE UNLESS YOU UNDERSTAND THE CONSEQUENCES, + * You WILL KNOW if you need to use this, MOST WILL NOT. + * @return Steam account ID or 0 if not available. + * @error If the client is not connected or the index is invalid. + */ +native int GetSteamAccountID(int client, bool validate=true); + +/** + * 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 int GetClientUserId(int client); + +/** + * Returns if a certain player is connected. + * + * @param client Player index. + * @return True if player is connected to the server, false otherwise. + * @error Invalid client index. + */ +native bool IsClientConnected(int 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(int 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(int client); + +/** + * Backwards compatibility stock - use IsClientInGame + * @deprecated Renamed to IsClientInGame + */ +#pragma deprecated Use IsClientInGame() instead +stock bool IsPlayerInGame(int 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. + * @error Invalid client index. + */ +native bool IsClientAuthorized(int client); + +/** + * Returns if a certain player is a fake client. + * + * @param client Player index. + * @return True if player is a fake client, false otherwise. + * @error Invalid client index, or client not connected. + */ +native bool IsFakeClient(int client); + +/** + * Returns if a certain player is the SourceTV bot. + * + * @param client Player index. + * @return True if player is the SourceTV bot, false otherwise. + * @error Invalid client index, or client not connected. + */ +native bool IsClientSourceTV(int client); + +/** + * Returns if a certain player is the Replay bot. + * + * @param client Player index. + * @return True if player is the Replay bot, false otherwise. + * @error Invalid client index, or client not connected. + */ +native bool IsClientReplay(int client); + +/** + * Returns if a certain player is an observer/spectator. + * + * @param client Player index. + * @return True if player is an observer, false otherwise. + * @error Invalid client index, client not in game, or no mod support. + */ +native bool IsClientObserver(int 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(int 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(int client, const char[] key, char[] value, int 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 int GetClientTeam(int 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. + * @error Invalid client index, client not connected, or bogus AdminId. + */ +native void SetUserAdmin(int 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(int 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. + * @error Invalid client index, or client not connected. + */ +native void AddUserFlags(int 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. + * @error Invalid client index, or client not connected. + */ +native void RemoveUserFlags(int 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. + * @error Invalid client index, or client not connected. + */ +native void SetUserFlagBits(int client, int 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 int GetUserFlagBits(int 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(int client, int 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(int 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. + * @error Invalid client index or client not in-game AND authorized. + */ +native void NotifyPostAdminCheck(int client); + +/** + * Creates a fake client. + * + * @param name Name to use. + * @return Client index on success, 0 otherwise. + * @error No map is active. + */ +native int CreateFakeClient(const char[] name); + +/** + * Sets a convar value on a fake client. + * + * @param client Client index. + * @param cvar ConVar name. + * @param value ConVar value. + * @error Invalid client index, client not connected, + * or client not a fake client. + */ +native void SetFakeClientConVar(int client, const char[] cvar, const char[] 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 int GetClientHealth(int 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). + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientModel(int client, char[] model, int 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). + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientWeapon(int client, char[] weapon, int maxlen); + +/** + * Returns the client's max size vector. + * + * @param client Player's index. + * @param vec Destination vector to store the client's max size. + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientMaxs(int 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. + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientMins(int 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. + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientAbsAngles(int 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. + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientAbsOrigin(int 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 int GetClientArmor(int 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 int GetClientDeaths(int 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 int GetClientFrags(int 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 connected, or fake client. + */ +native int GetClientDataRate(int 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 connected, or fake client. + */ +native bool IsClientTimingOut(int client); + +/** + * Returns the client's connection time in seconds. + * + * @param client Player's index. + * @return Connection time. + * @error Invalid client index, client not connected, or fake client. + */ +native float GetClientTime(int 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, or -1 if network info is not available. + * @error Invalid client index, client not connected, or fake client. + */ +native float GetClientLatency(int client, NetFlow flow); + +/** + * Returns the client's average packet latency in seconds. + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Latency, or -1 if network info is not available. + * @error Invalid client index, client not connected, or fake client. + */ +native float GetClientAvgLatency(int 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, or -1 if network info is not available. + * @error Invalid client index, client not connected, or fake client. + */ +native float GetClientAvgLoss(int 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 loss, or -1 if network info is not available. + * @error Invalid client index, client not connected, or fake client. + */ +native float GetClientAvgChoke(int 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 connected, or fake client. + */ +native float GetClientAvgData(int 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 connected, or fake client. + */ +native float GetClientAvgPackets(int 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 int GetClientOfUserId(int 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. + * @error Invalid client index, or client not connected. + */ +native void KickClient(int client, const char[] 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. + * @error Invalid client index, or client not connected. + */ +native void KickClientEx(int client, const char[] 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. + * @error Invalid client index, client not in game, or lack of + * mod support. + */ +native void ChangeClientTeam(int client, int team); + +/** + * Returns the clients unique serial identifier. + * + * @param client Client index. + * @return Serial number. + * @error Invalid client index, or client not connected. + */ +native int GetClientSerial(int client); + +/** + * Returns the client index by its serial number. + * + * @param serial Serial number. + * @return Client index, or 0 for invalid serial. + */ +native int GetClientFromSerial(int serial); diff --git a/source/sourcemod/scripting/include/colors.inc b/source/sourcemod/scripting/include/colors.inc new file mode 100644 index 0000000..3ce8b6a --- /dev/null +++ b/source/sourcemod/scripting/include/colors.inc @@ -0,0 +1,945 @@ +/************************************************************************** + * * + * Colored Chat Functions * + * Author: exvel, Editor: Popoklopsi, Powerlord, Bara * + * Version: 1.2.3 * + * by modified by 1NutWunDeR * + **************************************************************************/ + +/*Info: purple works only with CPrintToChat and CPrintToChatAll and without {blue} in the same string + (volvo gave them the same color code and saytext2 overrides purple with your current teamcolor.)*/ + +#if defined _colors_included + #endinput +#endif +#define _colors_included + +#define MAX_MESSAGE_LENGTH 320 +#define MAX_COLORS 17 + +#define SERVER_INDEX 0 +#define NO_INDEX -1 +#define NO_PLAYER -2 + +enum Colors +{ + Color_Default = 0, + Color_Darkred, + Color_Green, + Color_Lightgreen, + Color_Red, + Color_Blue, + Color_Olive, + Color_Lime, + Color_Orange, + Color_Purple, + Color_Grey, + Color_Yellow, + Color_Lightblue, + Color_Steelblue, + Color_Darkblue, + Color_Pink, + Color_Lightred, +} + +/* Colors' properties */ +// {"{default}", "{darkred}", "{green}", "{lightgreen}", "{orange}", "{blue}", "{olive}", "{lime}", "{red}", "{purple}", "{grey}", "{yellow}", "{lightblue}", "{steelblue}", "{darkblue}", "{pink}", "{lightred}"}; +new String:CTag[][] = {"{d}", "{dr}", "{gr}", "{lg}", "{o}", "{b}", "{ol}", "{l}", "{r}", "{p}", "{g}", "{y}", "{lb}", "{sb}", "{db}", "{pi}", "{lr}"}; +new String:CTagCode[][] = {"\x01", "\x02", "\x04", "\x03", "\x03", "\x03", "\x05", "\x06", "\x07", "\x03", "\x08", "\x09","\x0A","\x0B","\x0C","\x0E","\x0F"}; +new bool:CTagReqSayText2[] = {false, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false, false}; +new bool:CEventIsHooked = false; +new bool:CSkipList[MAXPLAYERS+1] = {false,...}; + +/* Game default profile */ +new bool:CProfile_Colors[] = {true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; +new CProfile_TeamIndex[] = {NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX}; +new bool:CProfile_SayText2 = false; + + +static Handle:sm_show_activity = INVALID_HANDLE; + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param szMessage Message (formatting rules). + * @return No return + * + * On error/Errors: If the client is not connected an error will be thrown. + */ +stock CPrintToChat(client, const String:szMessage[], any:...) +{ + if (client <= 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (!IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + decl String:szCMessage[MAX_MESSAGE_LENGTH]; + + SetGlobalTransTarget(client); + + Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); + VFormat(szCMessage, sizeof(szCMessage), szBuffer, 3); + + new index = CFormat(szCMessage, sizeof(szCMessage)); + + if (index == NO_INDEX) + PrintToChat(client, "%s", szCMessage); + else + CSayText2(client, index, szCMessage); +} + +/** + * 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, CPrintToChat() is used. + * Supports color tags. + * + * @param client Client index, or 0 for server. + * @param szMessage Formatting rules. + * @param ... Variable number of format parameters. + * @return No return + * + * On error/Errors: If the client is not connected or invalid. + */ +stock CReplyToCommand(client, const String:szMessage[], any:...) +{ + decl String:szCMessage[MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(client); + VFormat(szCMessage, sizeof(szCMessage), szMessage, 3); + + if (client == 0) + { + CRemoveTags(szCMessage, sizeof(szCMessage)); + PrintToServer("%s", szCMessage); + } + else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) + { + CRemoveTags(szCMessage, sizeof(szCMessage)); + PrintToConsole(client, "%s", szCMessage); + } + else + { + CPrintToChat(client, "%s", szCMessage); + } +} + +/** + * 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, CPrintToChat() is used. + * Supports color tags. + * + * @param client Client index, or 0 for server. + * @param author Author index whose color will be used for teamcolor tag. + * @param szMessage Formatting rules. + * @param ... Variable number of format parameters. + * @return No return + * + * On error/Errors: If the client is not connected or invalid. + */ +stock CReplyToCommandEx(client, author, const String:szMessage[], any:...) +{ + decl String:szCMessage[MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(client); + VFormat(szCMessage, sizeof(szCMessage), szMessage, 4); + + if (client == 0) + { + CRemoveTags(szCMessage, sizeof(szCMessage)); + PrintToServer("%s", szCMessage); + } + else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) + { + CRemoveTags(szCMessage, sizeof(szCMessage)); + PrintToConsole(client, "%s", szCMessage); + } + else + { + CPrintToChatEx(client, author, "%s", szCMessage); + } +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param szMessage Message (formatting rules) + * @return No return + */ +stock CPrintToChatAll(const String:szMessage[], any:...) +{ + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + + for (new i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i) && !IsFakeClient(i) && !CSkipList[i]) + { + SetGlobalTransTarget(i); + VFormat(szBuffer, sizeof(szBuffer), szMessage, 2); + + CPrintToChat(i, "%s", szBuffer); + } + + CSkipList[i] = false; + } +} + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags and teamcolor tag. + * + * @param client Client index. + * @param author Author index whose color will be used for teamcolor tag. + * @param szMessage Message (formatting rules). + * @return No return + * + * On error/Errors: If the client or author are not connected an error will be thrown. + */ +stock CPrintToChatEx(client, author, const String:szMessage[], any:...) +{ + if (client <= 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (!IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + if (author < 0 || author > MaxClients) + ThrowError("Invalid client index %d", author); + + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + decl String:szCMessage[MAX_MESSAGE_LENGTH]; + + SetGlobalTransTarget(client); + + Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); + VFormat(szCMessage, sizeof(szCMessage), szBuffer, 4); + + new index = CFormat(szCMessage, sizeof(szCMessage), author); + + if (index == NO_INDEX) + PrintToChat(client, "%s", szCMessage); + else + CSayText2(client, author, szCMessage); +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags and teamcolor tag. + * + * @param author Author index whos color will be used for teamcolor tag. + * @param szMessage Message (formatting rules). + * @return No return + * + * On error/Errors: If the author is not connected an error will be thrown. + */ +stock CPrintToChatAllEx(author, const String:szMessage[], any:...) +{ + if (author < 0 || author > MaxClients) + ThrowError("Invalid client index %d", author); + + if (!IsClientInGame(author)) + ThrowError("Client %d is not in game", author); + + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + + for (new i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i) && !IsFakeClient(i) && !CSkipList[i]) + { + SetGlobalTransTarget(i); + VFormat(szBuffer, sizeof(szBuffer), szMessage, 3); + + CPrintToChatEx(i, author, "%s", szBuffer); + } + + CSkipList[i] = false; + } +} + +/** + * Removes color tags from the string. + * + * @param szMessage String. + * @return No return + */ +stock CRemoveTags(String:szMessage[], maxlength) +{ + for (new i = 0; i < MAX_COLORS; i++) + ReplaceString(szMessage, maxlength, CTag[i], "", false); + + ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); +} + +/** + * Checks whether a color is allowed or not + * + * @param tag Color Tag. + * @return True when color is supported, otherwise false + */ +stock CColorAllowed(Colors:color) +{ + if (!CEventIsHooked) + { + CSetupProfile(); + + CEventIsHooked = true; + } + + return CProfile_Colors[color]; +} + +/** + * Replace the color with another color + * Handle with care! + * + * @param color color to replace. + * @param newColor color to replace with. + * @noreturn + */ +stock CReplaceColor(Colors:color, Colors:newColor) +{ + if (!CEventIsHooked) + { + CSetupProfile(); + + CEventIsHooked = true; + } + + CProfile_Colors[color] = CProfile_Colors[newColor]; + CProfile_TeamIndex[color] = CProfile_TeamIndex[newColor]; + + CTagReqSayText2[color] = CTagReqSayText2[newColor]; + Format(CTagCode[color], sizeof(CTagCode[]), CTagCode[newColor]) +} + +/** + * This function should only be used right in front of + * CPrintToChatAll or CPrintToChatAllEx and it tells + * to those funcions to skip specified client when printing + * message to all clients. After message is printed client will + * no more be skipped. + * + * @param client Client index + * @return No return + */ +stock CSkipNextClient(client) +{ + if (client <= 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + CSkipList[client] = true; +} + +/** + * Replaces color tags in a string with color codes + * + * @param szMessage String. + * @param maxlength Maximum length of the string buffer. + * @return Client index that can be used for SayText2 author index + * + * On error/Errors: If there is more then one team color is used an error will be thrown. + */ +stock CFormat(String:szMessage[], maxlength, author=NO_INDEX) +{ + decl String:szGameName[30]; + + GetGameFolderName(szGameName, sizeof(szGameName)); + + /* Hook event for auto profile setup on map start */ + if (!CEventIsHooked) + { + CSetupProfile(); + HookEvent("server_spawn", CEvent_MapStart, EventHookMode_PostNoCopy); + + CEventIsHooked = true; + } + + new iRandomPlayer = NO_INDEX; + + // On CS:GO set invisible precolor + if (StrEqual(szGameName, "csgo", false)) + Format(szMessage, maxlength, " \x01\x0B\x01%s", szMessage); + + /* If author was specified replace {teamcolor} tag */ + if (author != NO_INDEX) + { + if (CProfile_SayText2) + { + ReplaceString(szMessage, maxlength, "{teamcolor}", "\x03", false); + + iRandomPlayer = author; + } + /* If saytext2 is not supported by game replace {teamcolor} with green tag */ + else + ReplaceString(szMessage, maxlength, "{teamcolor}", CTagCode[Color_Green], false); + } + else + ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); + + /* For other color tags we need a loop */ + for (new i = 0; i < MAX_COLORS; i++) + { + /* If tag not found - skip */ + if (StrContains(szMessage, CTag[i], false) == -1) + continue; + + /* If tag is not supported by game replace it with green tag */ + else if (!CProfile_Colors[i]) + ReplaceString(szMessage, maxlength, CTag[i], CTagCode[Color_Green], false); + + /* If tag doesn't need saytext2 simply replace */ + else if (!CTagReqSayText2[i]) + ReplaceString(szMessage, maxlength, CTag[i], CTagCode[i], false); + + /* Tag needs saytext2 */ + else + { + /* If saytext2 is not supported by game replace tag with green tag */ + if (!CProfile_SayText2) + ReplaceString(szMessage, maxlength, CTag[i], CTagCode[Color_Green], false); + + /* Game supports saytext2 */ + else + { + /* If random player for tag wasn't specified replace tag and find player */ + if (iRandomPlayer == NO_INDEX) + { + /* Searching for valid client for tag */ + iRandomPlayer = CFindRandomPlayerByTeam(CProfile_TeamIndex[i]); + + /* If player not found replace tag with green color tag */ + if (iRandomPlayer == NO_PLAYER) + ReplaceString(szMessage, maxlength, CTag[i], CTagCode[Color_Green], false); + + /* If player was found simply replace */ + else + ReplaceString(szMessage, maxlength, CTag[i], CTagCode[i], false); + + } + /* If found another team color tag throw error */ + else + { + //ReplaceString(szMessage, maxlength, CTag[i], ""); + ThrowError("Using two team colors in one message is not allowed"); + } + } + + } + } + + return iRandomPlayer; +} + +/** + * Founds a random player with specified team + * + * @param color_team Client team. + * @return Client index or NO_PLAYER if no player found + */ +stock CFindRandomPlayerByTeam(color_team) +{ + if (color_team == SERVER_INDEX) + return 0; + else + { + for (new i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i) && GetClientTeam(i) == color_team) + return i; + } + } + + return NO_PLAYER; +} + +/** + * Sends a SayText2 usermessage to a client + * + * @param szMessage Client index + * @param maxlength Author index + * @param szMessage Message + * @return No return. + */ +stock CSayText2(client, author, const String:szMessage[]) +{ + new Handle:hBuffer = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); + + if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) + { + PbSetInt(hBuffer, "ent_idx", author); + PbSetBool(hBuffer, "chat", true); + PbSetString(hBuffer, "msg_name", szMessage); + PbAddString(hBuffer, "params", ""); + PbAddString(hBuffer, "params", ""); + PbAddString(hBuffer, "params", ""); + PbAddString(hBuffer, "params", ""); + } + else + { + BfWriteByte(hBuffer, author); + BfWriteByte(hBuffer, true); + BfWriteString(hBuffer, szMessage); + } + + EndMessage(); +} + +/** + * Creates game color profile + * This function must be edited if you want to add more games support + * + * @return No return. + */ +stock CSetupProfile() +{ + decl String:szGameName[30]; + GetGameFolderName(szGameName, sizeof(szGameName)); + + if (StrEqual(szGameName, "cstrike", false)) + { + CProfile_Colors[Color_Lightgreen] = true; + CProfile_Colors[Color_Orange] = true; + CProfile_Colors[Color_Blue] = true; + CProfile_Colors[Color_Olive] = true; + CProfile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; + CProfile_TeamIndex[Color_Orange] = 2; + CProfile_TeamIndex[Color_Blue] = 3; + CProfile_SayText2 = true; + } + else if (StrEqual(szGameName, "csgo", false)) + { + CProfile_Colors[Color_Red] = true; + CProfile_Colors[Color_Blue] = true; + CProfile_Colors[Color_Olive] = true; + CProfile_Colors[Color_Darkred] = true; + CProfile_Colors[Color_Lime] = true; + CProfile_Colors[Color_Purple] = true; + CProfile_Colors[Color_Grey] = true; + CProfile_Colors[Color_Yellow] = true; + CProfile_Colors[Color_Lightblue] = true; + CProfile_Colors[Color_Steelblue] = true; + CProfile_Colors[Color_Darkblue] = true; + CProfile_Colors[Color_Pink] = true; + CProfile_Colors[Color_Lightred] = true; + CProfile_TeamIndex[Color_Orange] = 2; + CProfile_TeamIndex[Color_Blue] = 3; + CProfile_SayText2 = true; + } + else if (StrEqual(szGameName, "tf", false)) + { + CProfile_Colors[Color_Lightgreen] = true; + CProfile_Colors[Color_Orange] = true; + CProfile_Colors[Color_Blue] = true; + CProfile_Colors[Color_Olive] = true; + CProfile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; + CProfile_TeamIndex[Color_Orange] = 2; + CProfile_TeamIndex[Color_Blue] = 3; + CProfile_SayText2 = true; + } + else if (StrEqual(szGameName, "left4dead", false) || StrEqual(szGameName, "left4dead2", false)) + { + CProfile_Colors[Color_Lightgreen] = true; + CProfile_Colors[Color_Orange] = true; + CProfile_Colors[Color_Blue] = true; + CProfile_Colors[Color_Olive] = true; + CProfile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; + CProfile_TeamIndex[Color_Orange] = 3; + CProfile_TeamIndex[Color_Blue] = 2; + CProfile_SayText2 = true; + } + else if (StrEqual(szGameName, "hl2mp", false)) + { + /* hl2mp profile is based on mp_teamplay convar */ + if (GetConVarBool(FindConVar("mp_teamplay"))) + { + CProfile_Colors[Color_Orange] = true; + CProfile_Colors[Color_Blue] = true; + CProfile_Colors[Color_Olive] = true; + CProfile_TeamIndex[Color_Orange] = 3; + CProfile_TeamIndex[Color_Blue] = 2; + CProfile_SayText2 = true; + } + else + { + CProfile_SayText2 = false; + CProfile_Colors[Color_Olive] = true; + } + } + else if (StrEqual(szGameName, "dod", false)) + { + CProfile_Colors[Color_Olive] = true; + CProfile_SayText2 = false; + } + /* Profile for other games */ + else + { + if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) + { + CProfile_SayText2 = false; + } + else + { + CProfile_Colors[Color_Orange] = true; + CProfile_Colors[Color_Blue] = true; + CProfile_TeamIndex[Color_Orange] = 2; + CProfile_TeamIndex[Color_Blue] = 3; + CProfile_SayText2 = true; + } + } +} + +public Action:CEvent_MapStart(Handle:event, const String:name[], bool:dontBroadcast) +{ + CSetupProfile(); + + for (new i = 1; i <= MaxClients; i++) + CSkipList[i] = false; +} + +/** + * 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, + * CShowActivity2() is slightly more useful. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock CShowActivity(client, const String:format[], any:...) +{ + if (sm_show_activity == INVALID_HANDLE) + sm_show_activity = FindConVar("sm_show_activity"); + + new String:tag[] = "[SM] "; + + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + //decl String:szCMessage[MAX_MESSAGE_LENGTH]; + new value = GetConVarInt(sm_show_activity); + new ReplySource:replyto = GetCmdReplySource(); + + new String:name[MAX_NAME_LENGTH] = "Console"; + new String:sign[MAX_NAME_LENGTH] = "ADMIN"; + new bool:display_in_chat = false; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + new AdminId:id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + /* Display the message to the client? */ + if (replyto == SM_REPLY_TO_CONSOLE) + { + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + CRemoveTags(szBuffer, sizeof(szBuffer)); + PrintToConsole(client, "%s%s\n", tag, szBuffer); + display_in_chat = true; + } + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + CRemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + for (new i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i) + || IsFakeClient(i) + || (display_in_chat && i == client)) + { + continue; + } + new AdminId:id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + new String:newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + CPrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + new bool:is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + new String:newsign[MAX_NAME_LENGTH] + newsign = sign; + if ((value & 8) || ((value & 16) && is_root) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + CPrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * Same as CShowActivity(), except the tag parameter is used instead of "[SM] " (note that you must supply any spacing). + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to display with. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock CShowActivityEx(client, const String:tag[], const String:format[], any:...) +{ + if (sm_show_activity == INVALID_HANDLE) + sm_show_activity = FindConVar("sm_show_activity"); + + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + //decl String:szCMessage[MAX_MESSAGE_LENGTH]; + new value = GetConVarInt(sm_show_activity); + new ReplySource:replyto = GetCmdReplySource(); + + new String:name[MAX_NAME_LENGTH] = "Console"; + new String:sign[MAX_NAME_LENGTH] = "ADMIN"; + new bool:display_in_chat = false; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + new AdminId:id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + /* Display the message to the client? */ + if (replyto == SM_REPLY_TO_CONSOLE) + { + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CRemoveTags(szBuffer, sizeof(szBuffer)); + PrintToConsole(client, "%s%s\n", tag, szBuffer); + display_in_chat = true; + } + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CRemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + for (new i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i) + || IsFakeClient(i) + || (display_in_chat && i == client)) + { + continue; + } + new AdminId:id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + new String:newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CPrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + new bool:is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + new String:newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CPrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * 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. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to prepend to the message. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock CShowActivity2(client, const String:tag[], const String:format[], any:...) +{ + if (sm_show_activity == INVALID_HANDLE) + sm_show_activity = FindConVar("sm_show_activity"); + + decl String:szBuffer[MAX_MESSAGE_LENGTH]; + //decl String:szCMessage[MAX_MESSAGE_LENGTH]; + new value = GetConVarInt(sm_show_activity); + GetCmdReplySource(); + + new String:name[MAX_NAME_LENGTH] = "Console"; + new String:sign[MAX_NAME_LENGTH] = "ADMIN"; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + new AdminId:id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + /* We don't display directly to the console because the chat text + * simply gets added to the console, so we don't want it to print + * twice. + */ + CPrintToChatEx(client, client, "%s%s", tag, szBuffer); + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CRemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + for (new i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i) + || IsFakeClient(i) + || i == client) + { + continue; + } + new AdminId:id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + new String:newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CPrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + new bool:is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + new String:newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + CPrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/commandfilters.inc b/source/sourcemod/scripting/include/commandfilters.inc new file mode 100644 index 0000000..de8ebb1 --- /dev/null +++ b/source/sourcemod/scripting/include/commandfilters.inc @@ -0,0 +1,171 @@ +/** + * 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 int ProcessTargetString(const char[] pattern, + int admin, + int[] targets, + int max_targets, + int filter_flags, + char[] target_name, + int 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. + */ +stock void ReplyToTargetError(int client, int 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"); + } + } +} + +#define FEATURECAP_MULTITARGETFILTER_CLIENTPARAM "SourceMod MultiTargetFilter ClientParam" + +/** + * Adds clients to a multi-target filter. + * + * @param pattern Pattern name. + * @param clients Array to fill with unique, valid client indexes. + * @param client Client that triggered this filter. + * @return True if pattern was recognized, false otherwise. + * + * @note To see if the client param is available, use FeatureType_Capability and FEATURECAP_MULTITARGETFILTER_CLIENTPARAM. + */ +typeset MultiTargetFilter { + function bool (const char[] pattern, Handle clients); + function bool (const char[] pattern, ArrayList clients); + function bool (const char[] pattern, Handle clients, int client); + function bool (const char[] pattern, ArrayList clients, int client); +} + +/** + * Adds a multi-target filter function for ProcessTargetString(). + * + * @param pattern Pattern to match (case sensitive). + * @param filter Filter function. + * @param phrase Descriptive phrase to display on successful match. + * @param phraseIsML True if phrase is multi-lingual, false otherwise. + */ +native void AddMultiTargetFilter(const char[] pattern, MultiTargetFilter filter, + const char[] phrase, bool phraseIsML); + +/** + * Removes a multi-target filter function from ProcessTargetString(). + * + * @param pattern Pattern to match (case sensitive). + * @param filter Filter function. + */ +native void RemoveMultiTargetFilter(const char[] pattern, MultiTargetFilter filter); diff --git a/source/sourcemod/scripting/include/commandline.inc b/source/sourcemod/scripting/include/commandline.inc new file mode 100644 index 0000000..33e4a13 --- /dev/null +++ b/source/sourcemod/scripting/include/commandline.inc @@ -0,0 +1,86 @@ +/** + * 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 _commandline_included_ + #endinput +#endif +#define _commandline_included_ + +/** + * Gets the full command line the server was launched with. + * + * @param commandLine Buffer to store the command line in. + * @param maxlen Maximum length of the command line buffer. + * @return True if the command line is valid; otherwise, false. + * @error No command line available, or no mod support. + */ +native bool GetCommandLine(char[] commandLine, int maxlen); + +/** + * Gets the value of a command line parameter the server was launched with. + * + * @param param The command line parameter to get the value of. + * @param value Buffer to store the parameter value in. + * @param maxlen Maximum length of the value buffer. + * @param defValue The default value to return if the parameter wasn't specified. + * @error No command line available, or no mod support. + */ +native void GetCommandLineParam(const char[] param, char[] value, int maxlen, const char[] defValue=""); + +/** + * Gets the value of a command line parameter the server was launched with. + * + * @param param The command line parameter to get the value of. + * @param defValue The default value to return if the parameter wasn't specified. + * @return The integer value of the command line parameter value. + * @error No command line available, or no mod support. + */ +native int GetCommandLineParamInt(const char[] param, int defValue=0); + +/** + * Gets the value of a command line parameter the server was launched with. + * + * @param param The command line parameter to get the value of. + * @param defValue The default value to return if the parameter wasn't specified. + * @return The floating point value of the command line parameter value. + * @error No command line available, or no mod support. + */ +native float GetCommandLineParamFloat(const char[] param, float defValue=0.0); + +/** + * Determines if a specific command line parameter is present. + * + * @param param The command line parameter to test. + * @return True if the command line parameter is specified; otherwise, false. + * @error No command line available, or no mod support. + */ +native bool FindCommandLineParam(const char[] param); diff --git a/source/sourcemod/scripting/include/console.inc b/source/sourcemod/scripting/include/console.inc new file mode 100644 index 0000000..2e42c79 --- /dev/null +++ b/source/sourcemod/scripting/include/console.inc @@ -0,0 +1,780 @@ +/** + * 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 query helper values. + */ +enum QueryCookie +{ + QUERYCOOKIE_FAILED = 0 +}; + +/** + * Reply sources for commands. + */ +enum ReplySource +{ + SM_REPLY_TO_CONSOLE = 0, + SM_REPLY_TO_CHAT = 1 +}; + +/** + * @section Flags for console commands and console variables. The descriptions + * for each constant come directly from the Source SDK. + */ + +#pragma deprecated No logic using this flag ever existed in a released game. It only ever appeared in the first hl2sdk. +#define FCVAR_PLUGIN 0 // Actual value is same as FCVAR_SS_ADDED in Left 4 Dead and later. +#pragma deprecated Did you mean FCVAR_DEVELOPMENTONLY? (No logic using this flag ever existed in a released game. It only ever appeared in the first hl2sdk.) +#define FCVAR_LAUNCHER (1<<1) // Same value as FCVAR_DEVELOPMENTONLY, which is what most usages of this were intending to use. + + +#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_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined. (OB+) +#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. (EP1-only) +#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or autocomplete. Like DEVELOPMENTONLY, but can't be compiled out.1 (OB+) +#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_SS (1<<15) // causes varnameN where N 2 through max splitscreen slots for mod to be autogenerated (L4D+) +#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_SS_ADDED (1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players (L4D+) +#define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars available to customers (L4D+) +#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload (OB+) +#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload (OB+) +#define FCVAR_NOT_CONNECTED (1<<22) // Cvar cannot be changed by a client that is connected to a server. +#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread (OB+) +#define FCVAR_ARCHIVE_XBOX (1<<24) // Cvar written to config.cfg on the Xbox. +#define FCVAR_ARCHIVE_GAMECONSOLE (1<<24) // Cvar written to config.cfg on the Xbox. +#define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars (OB+) +#define FCVAR_SERVER_CAN_EXECUTE (1<<28) // the server is allowed to execute this command on clients via + // ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd. (OB+) +#define FCVAR_SERVER_CANNOT_QUERY (1<<29) // If this is set, then the server is not allowed to query this cvar's value (via + // IServerPluginHelpers::StartQueryCvarValue). +#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command. + // Note: IVEngineClient::ClientCmd_Unrestricted can run any client command. + +/** + * @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. + */ +native void ServerCommand(const char[] format, any ...); + +/** + * Executes a server command as if it were on the server console (or RCON) + * and stores the printed text into buffer. + * + * Warning: This calls ServerExecute internally and may have issues if + * certain commands are in the buffer, only use when you really need + * the response. + * Also, on L4D2 this will not print the command output to the server console. + * + * @param buffer String to store command result into. + * @param maxlen Length of buffer. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +native void ServerCommandEx(char[] buffer, int maxlen, const char[] format, any ...); + +/** + * Inserts a server command at the beginning of the server command buffer. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +native void InsertServerCommand(const char[] format, any ...); + +/** + * Executes every command in the server's command buffer, rather than once per frame. + */ +native void 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 + * @error Invalid client index, or client not connected. + */ +native void ClientCommand(int client, const char[] 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 + * @error Invalid client index, or client not connected. + */ +native void FakeClientCommand(int client, const char[] 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 + * @error Invalid client index, or client not connected. + */ +native void FakeClientCommandEx(int client, const char[] fmt, any ...); + +/** + * Executes a KeyValues client command on the server without being networked. + * + * @param client Index of the client. + * @param kv KeyValues data to be sent. + * @error Invalid client index, client not connected, + * or unsupported on current game. + */ +native void FakeClientCommandKeyValues(int client, KeyValues kv); + +/** + * Sends a message to the server console. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +native void PrintToServer(const char[] format, any ...); + +/** + * Sends a message to a client's console. + * + * @param client Client index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @error If the client is not connected an error will be thrown. + */ +native void PrintToConsole(int client, const char[] format, any ...); + + +/** + * Sends a message to every client's console. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void PrintToConsoleAll(const char[] format, any ...) +{ + char buffer[254]; + + for (int i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i)) + { + SetGlobalTransTarget(i); + VFormat(buffer, sizeof(buffer), format, 2); + PrintToConsole(i, "%s", buffer); + } + } +} + +/** + * Replies 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. + * @error If the client is not connected or invalid. + */ +native void ReplyToCommand(int client, const char[] 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. + * @error + */ +native void ShowActivity2(int client, const char[] tag, const char[] 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. + * @error + */ +native void ShowActivity(int client, const char[] 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. + * @error + */ +native void ShowActivityEx(int client, const char[] tag, const char[] 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 bool FormatActivitySource(int client, int target, const char[] namebuf, int maxlength); + +/** + * Called when a server-only command is invoked. + * + * @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." + */ +typedef SrvCmd = function Action (int 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. + * @error Command name is the same as an existing convar. + */ +native void RegServerCmd(const char[] cmd, SrvCmd callback, const char[] description="", int 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." + */ +typedef ConCmd = function Action (int client, int 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, + * 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. + * @error Command name is the same as an existing convar. + */ +native void RegConsoleCmd(const char[] cmd, ConCmd callback, const char[] description="", int 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. + * @error Command name is the same as an existing convar. + */ +native void RegAdminCmd(const char[] cmd, + ConCmd callback, + int adminflags, + const char[] description="", + const char[] group="", + int 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 int 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 int GetCmdArg(int argnum, char[] buffer, int maxlength); + +/** + * Retrieves a numeric command argument given its index, from the current + * console or server command. Will return 0 if the argument can not be + * parsed as a number. Use GetCmdArgIntEx to handle that explicitly. + * + * @param argnum Argument number to retrieve. + * @return Value of the command argument. + */ +stock int GetCmdArgInt(int argnum) +{ + char str[12]; + GetCmdArg(argnum, str, sizeof(str)); + + return StringToInt(str); +} + +/** + * Retrieves a numeric command argument given its index, from the current + * console or server command. Returns false if the argument can not be + * completely parsed as an integer. + * + * @param argnum Argument number to retrieve. + * @param value Populated with the value of the command argument. + * @return Whether the argument was entirely a numeric value. + */ +stock bool GetCmdArgIntEx(int argnum, int &value) +{ + char str[12]; + int len = GetCmdArg(argnum, str, sizeof(str)); + + return StringToIntEx(str, value) == len && len > 0; +} + +/** + * Retrieves a float command argument given its index, from the current + * console or server command. Will return 0.0 if the argument can not be + * parsed as a number. Use GetCmdArgFloatEx to handle that explicitly. + * + * @param argnum Argument number to retrieve. + * @return Value of the command argument. + */ +stock float GetCmdArgFloat(int argnum) +{ + char str[18]; + GetCmdArg(argnum, str, sizeof(str)); + + return StringToFloat(str); +} + +/** + * Retrieves a float command argument given its index, from the current + * console or server command. Returns false if the argument can not be + * completely parsed as a floating point. + * + * @param argnum Argument number to retrieve. + * @param value Populated with the value of the command argument. + * @return Whether the argument was entirely a floating point value. + */ +stock bool GetCmdArgFloatEx(int argnum, float &value) +{ + char str[18]; + int len = GetCmdArg(argnum, str, sizeof(str)); + + return StringToFloatEx(str, value) == len && len > 0; +} + +/** + * 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 int GetCmdArgString(char[] buffer, int maxlength); + +methodmap CommandIterator < Handle { + // Creates a new CommandIterator. Must be freed with delete or + // CloseHandle(). + // + // The CommandIterator can be used to iterate commands created by + // SourceMod plugins and allows inspection of properties associated + // with the command. + // + // @return New CommandIterator Handle. + public native CommandIterator(); + + // Determines if there is a next command. If one is found, the + // iterator is advanced to it. + // + // @return true if found and iterator is advanced. + public native bool Next(); + + // Retrieves the command's description. + // + // @param buffer Buffer to copy to. + // @param maxlen Maximum size of the buffer. + // @error Invalid iterator position. + public native void GetDescription(char[] buffer, int maxlen); + + // Retrieves the command's name. + // + // @param buffer Buffer to copy to. + // @param maxlen Maximum size of the buffer. + // @error Invalid iterator position. + public native void GetName(char[] buffer, int maxlen); + + // Retrieves the plugin handle of the command's creator + // + // @error Invalid iterator position. + property Handle Plugin { + public native get(); + } + + // Retrieves the command's default flags + // + // @error Invalid iterator position. + property int Flags { + public native get(); + } +} + +/** + * 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, + char[] name, + int nameLen, + int &eflags=0, + char[] desc="", + int descLen=0); + +/** + * Returns whether a client has access to a given command string. The string + * can be any override string, as overrides can be independent of + * commands. This 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(int client, + const char[] command, + int flags, + bool override_only=false); + +/** + * Returns whether an admin has access to a given command string. The string + * can be any override string, as overrides can be independent of + * commands. This feature essentially allows you to create custom flags + * using the override system. + * + * @param id AdminId of the admin. + * @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 admin has access, false otherwise. + */ +native bool CheckAccess(AdminId id, + const char[] command, + int flags, + bool override_only=false); + +/** + * 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 int GetCommandFlags(const char[] 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 char[] name, int 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(char[] buffer, int max_size, bool &isCommand, int &flags=0, char[] description="", int 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, char[] buffer, int max_size, bool &isCommand, int &flags=0, char[] description="", int descrmax_size=0); + +/** + * 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. + */ +native void AddServerTag(const char[] tag); + +/** + * Removes a tag previously added by the calling plugin. + * + * @param tag Tag string to remove. + */ +native void RemoveServerTag(const char[] tag); + +/** + * Callback for command listeners. This is invoked whenever any command + * reaches the server, from the server console itself or a player. + * + * Clients may be in the process of connecting when they are executing commands + * IsClientConnected(client) is not guaranteed to return true. Other functions + * such as GetClientIP() may not work at this point either. + * + * 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 may not be connected or 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). + */ +typedef CommandListener = function Action (int client, const char[] command, int 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 char[] 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 void RemoveCommandListener(CommandListener callback, const char[] command=""); + +/** + * Returns true if the supplied command exists. + * + * @param command Command to find. + * @return True if command is found, false otherwise. + */ +stock bool CommandExists(const char[] command) +{ + return (GetCommandFlags(command) != INVALID_FCVAR_FLAGS); +} +/** + * Global listener for the chat commands. + * + * @param client Client index. + * @param command Command name. + * @param sArgs Chat argument string. + * + * @return An Action value. Returning Plugin_Handled bypasses the game function call. + * Returning Plugin_Stop bypasses the post hook as well as the game function. + */ +forward Action OnClientSayCommand(int client, const char[] command, const char[] sArgs); + +/** + * Global post listener for the chat commands. + * + * @param client Client index. + * @param command Command name. + * @param sArgs Chat argument string. + */ +forward void OnClientSayCommand_Post(int client, const char[] command, const char[] sArgs); diff --git a/source/sourcemod/scripting/include/convars.inc b/source/sourcemod/scripting/include/convars.inc new file mode 100644 index 0000000..907ed4d --- /dev/null +++ b/source/sourcemod/scripting/include/convars.inc @@ -0,0 +1,514 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 _convars_included + #endinput +#endif +#define _convars_included + +/** + * Console variable bound values used with Get/SetConVarBounds() + */ +enum ConVarBounds +{ + ConVarBound_Upper = 0, + ConVarBound_Lower +}; + +/** + * Console variable query result values. + */ +enum ConVarQueryResult +{ + ConVarQuery_Cancelled = -1, //< Client disconnected during query */ + 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. */ +}; + +/** + * 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. + */ +typedef ConVarChanged = function void (ConVar convar, const char[] oldValue, const char[] newValue); + +/** + * 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 ConVar CreateConVar( + const char[] name, + const char[] defaultValue, + const char[] description="", + int 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 ConVar object if found; null otherwise. + */ +native ConVar FindConVar(const char[] name); + +// A ConVar is a configurable, named setting in the srcds console. +methodmap ConVar < Handle +{ + // Retrieves or sets a boolean value for the convar. + property bool BoolValue { + public native get(); + public native set(bool b); + } + + // Retrieves or sets an integer value for the convar. + property int IntValue { + public native get(); + public native set(int value); + } + + // Retrieves or sets a float value for the convar. + property float FloatValue { + public native get(); + public native set(float value); + } + + // Gets or sets the flag bits (FCVAR_*) on the convar. + property int Flags { + public native get(); + public native set(int flags); + } + + // Retrieves the plugin handle of the convar's creator + property Handle Plugin { + public native get(); + } + + // Sets the boolean value of a console variable. + // + // Note: The replicate and notify params are only relevant for the + // original, Dark Messiah, and Episode 1 engines. Newer engines + // automatically do these things when the convar value is changed. + // + // @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. + public native void SetBool(bool value, bool replicate=false, bool notify=false); + + // Sets the integer value of a console variable. + // + // Note: The replicate and notify params are only relevant for the + // original, Dark Messiah, and Episode 1 engines. Newer engines + // automatically do these things when the convar value is changed. + // + // @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. + public native void SetInt(int value, bool replicate=false, bool notify=false); + + // Sets the floating point value of a console variable. + // + // Note: The replicate and notify params are only relevant for the + // original, Dark Messiah, and Episode 1 engines. Newer engines + // automatically do these things when the convar value is changed. + // + // @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. + public native void SetFloat(float value, bool replicate=false, bool notify=false); + + // Retrieves the string value of a console variable. + // + // @param value Buffer to store the value of the convar. + // @param maxlength Maximum length of string buffer. + public native void GetString(char[] value, int maxlength); + + // Sets the string value of a console variable. + // + // Note: The replicate and notify params are only relevant for the + // original, Dark Messiah, and Episode 1 engines. Newer engines + // automatically do these things when the convar value is changed. + // + // @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. + public native void SetString(const char[] value, bool replicate=false, bool notify=false); + + // Resets the console variable to its default value. + // + // Note: The replicate and notify params are only relevant for the + // original, Dark Messiah, and Episode 1 engines. Newer engines + // automatically do these things when the convar value is changed. + // + // @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. + public native void RestoreDefault(bool replicate=false, bool notify=false); + + // Retrieves the default string value of a console variable. + // + // @param value Buffer to store the default value of the convar. + // @param maxlength Maximum length of string buffer. + // @return Number of bytes written to the buffer (UTF-8 safe). + public native int GetDefault(char[] value, int maxlength); + + // Retrieves the specified bound of a console variable. + // + // @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. + public native bool GetBounds(ConVarBounds type, float &value); + + // Sets the specified bound of a console variable. + // + // @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. + public native void SetBounds(ConVarBounds type, bool set, float value=0.0); + + // Retrieves the name of a console variable. + // + // @param name Buffer to store the name of the convar. + // @param maxlength Maximum length of string buffer. + public native void GetName(char[] name, int maxlength); + + // Retrieves the description of a console variable. + // + // @param buffer Buffer to store the description of the convar. + // @param maxlength Maximum length of string buffer. + public native void GetDescription(char[] buffer, int maxlength); + + // Replicates a convar value to a specific client. This does not change the actual convar value. + // + // @param client Client index + // @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 + public native bool ReplicateToClient(int client, const char[] value); + + // Creates a hook for when a console variable's value is changed. + // + // @param callback An OnConVarChanged function pointer. + public native void AddChangeHook(ConVarChanged callback); + + // Removes a hook for when a console variable's value is changed. + // + // @param callback An OnConVarChanged function pointer. + // @error No active hook on convar. + public native void RemoveChangeHook(ConVarChanged callback); +} + +/** + * Creates a hook for when a console variable's value is changed. + * + * @param convar Handle to the convar. + * @param callback An OnConVarChanged function pointer. + * @error Invalid or corrupt Handle or invalid callback function. + */ +native void 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. + * @error Invalid or corrupt Handle, invalid callback function, or no active hook on convar. + */ +native void 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 only relevant for the original, Dark Messiah, and + * Episode 1 engines. Newer engines automatically do these things when the convar value 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. + * @error Invalid or corrupt Handle. + */ +native void 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 int GetConVarInt(Handle convar); + +/** + * Sets the integer value of a console variable. + * + * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and + * Episode 1 engines. Newer engines automatically do these things when the convar value 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. + * @error Invalid or corrupt Handle. + */ +native void SetConVarInt(Handle convar, int 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 only relevant for the original, Dark Messiah, and + * Episode 1 engines. Newer engines automatically do these things when the convar value 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. + * @error Invalid or corrupt Handle. + */ +native void 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. + * @error Invalid or corrupt Handle. + */ +native void GetConVarString(Handle convar, char[] value, int maxlength); + +/** + * Sets the string value of a console variable. + * + * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and + * Episode 1 engines. Newer engines automatically do these things when the convar value 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. + * @error Invalid or corrupt Handle. + */ +native void SetConVarString(Handle convar, const char[] value, bool replicate=false, bool notify=false); + +/** + * Resets the console variable to its default value. + * + * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and + * Episode 1 engines. Newer engines automatically do these things when the convar value 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. + * @error Invalid or corrupt Handle. + */ +native void ResetConVar(Handle convar, bool replicate=false, bool notify=false); + +/** + * Retrieves the default string value of a console variable. + * + * @param convar Handle to the convar. + * @param value Buffer to store the default value of the convar. + * @param maxlength Maximum length of string buffer. + * @return Number of bytes written to the buffer (UTF-8 safe). + * @error Invalid or corrupt Handle. + */ +native int GetConVarDefault(Handle convar, char[] value, int maxlength); + +/** + * 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 int 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. + * @error Invalid or corrupt Handle. + */ +native void SetConVarFlags(Handle convar, int 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. + * @error Invalid or corrupt Handle. + */ +native void 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 name Buffer to store the name of the convar. + * @param maxlength Maximum length of string buffer. + * @error Invalid or corrupt Handle. + */ +native void GetConVarName(Handle convar, char[] name, int maxlength); + +/** + * 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(int client, Handle convar, const char[] value); + +typeset 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. + function void (QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] 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. + function void (QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue); +}; + +/** + * Starts a query to retrieve the value of a client's console variable. + * + * @param client Player index. + * @param cvarName 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(int client, const char[] cvarName, ConVarQueryFinished callback, any value=0); + +/** + * 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(int c) +{ + return (c == '_' || IsCharAlpha(c) || IsCharNumeric(c)); +} diff --git a/source/sourcemod/scripting/include/core.inc b/source/sourcemod/scripting/include/core.inc new file mode 100644 index 0000000..8fed55c --- /dev/null +++ b/source/sourcemod/scripting/include/core.inc @@ -0,0 +1,320 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet: + * ============================================================================= + * 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 +{ + public int version; + public const char[] filevers; + public const char[] date; + public const char[] time; +}; + +/** + * 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_Evicted /**< Plugin was unloaded due to an error */ +}; + +/** + * Plugin information properties. Plugins can declare a global variable with + * their info. Example, + * + * public Plugin myinfo = { + * name = "Admin Help", + * author = "AlliedModders LLC", + * description = "Display command information", + * version = "1.0", + * url = "http://www.sourcemod.net/" + * }; + * + * SourceMod will display this information when a user inspects plugins in the + * console. + */ +enum PluginInfo +{ + PlInfo_Name, /**< Plugin name */ + PlInfo_Author, /**< Plugin author */ + PlInfo_Description, /**< Plugin description */ + PlInfo_Version, /**< Plugin version */ + PlInfo_URL /**< Plugin URL */ +}; + +/** + * Defines how an extension must expose itself for autoloading. + */ +struct Extension +{ + public const char[] name; /**< Short name */ + public const char[] file; /**< Default file name */ + public bool autoload; /**< Whether or not to auto-load */ + public bool required; /**< Whether or not to require */ +}; + +/** + * Defines how a plugin must expose itself for native requiring. + */ +struct SharedPlugin +{ + public const char[] name; /**< Short name */ + public const char[] file; /**< File name */ + public 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 char NULL_STRING[1]; /**< pass this into certain functions to act as a C++ NULL */ + +/** + * Check if the given vector is the NULL_VECTOR. + * + * @param vec The vector to test. + * @return True if NULL_VECTOR, false otherwise. + */ +native bool IsNullVector(const float vec[3]); + +/** + * Check if the given string is the NULL_STRING. + * + * @param str The string to test. + * @return True if NULL_STRING, false otherwise. + */ +native bool IsNullString(const char[] str); + +/** + * Horrible compatibility shim. + */ +public Extension __ext_core = +{ + name = "Core", + file = "core", + autoload = 0, + required = 0, +}; + +native int 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. + */ +native void MarkNativeAsOptional(const char[] name); + +public void __ext_core_SetNTVOptional() +{ + MarkNativeAsOptional("GetFeatureStatus"); + MarkNativeAsOptional("RequireFeature"); + MarkNativeAsOptional("AddCommandListener"); + MarkNativeAsOptional("RemoveCommandListener"); + + MarkNativeAsOptional("BfWriteBool"); + MarkNativeAsOptional("BfWriteByte"); + MarkNativeAsOptional("BfWriteChar"); + MarkNativeAsOptional("BfWriteShort"); + MarkNativeAsOptional("BfWriteWord"); + MarkNativeAsOptional("BfWriteNum"); + MarkNativeAsOptional("BfWriteFloat"); + MarkNativeAsOptional("BfWriteString"); + MarkNativeAsOptional("BfWriteEntity"); + MarkNativeAsOptional("BfWriteAngle"); + MarkNativeAsOptional("BfWriteCoord"); + MarkNativeAsOptional("BfWriteVecCoord"); + MarkNativeAsOptional("BfWriteVecNormal"); + MarkNativeAsOptional("BfWriteAngles"); + MarkNativeAsOptional("BfReadBool"); + MarkNativeAsOptional("BfReadByte"); + MarkNativeAsOptional("BfReadChar"); + MarkNativeAsOptional("BfReadShort"); + MarkNativeAsOptional("BfReadWord"); + MarkNativeAsOptional("BfReadNum"); + MarkNativeAsOptional("BfReadFloat"); + MarkNativeAsOptional("BfReadString"); + MarkNativeAsOptional("BfReadEntity"); + MarkNativeAsOptional("BfReadAngle"); + MarkNativeAsOptional("BfReadCoord"); + MarkNativeAsOptional("BfReadVecCoord"); + MarkNativeAsOptional("BfReadVecNormal"); + MarkNativeAsOptional("BfReadAngles"); + MarkNativeAsOptional("BfGetNumBytesLeft"); + + MarkNativeAsOptional("BfWrite.WriteBool"); + MarkNativeAsOptional("BfWrite.WriteByte"); + MarkNativeAsOptional("BfWrite.WriteChar"); + MarkNativeAsOptional("BfWrite.WriteShort"); + MarkNativeAsOptional("BfWrite.WriteWord"); + MarkNativeAsOptional("BfWrite.WriteNum"); + MarkNativeAsOptional("BfWrite.WriteFloat"); + MarkNativeAsOptional("BfWrite.WriteString"); + MarkNativeAsOptional("BfWrite.WriteEntity"); + MarkNativeAsOptional("BfWrite.WriteAngle"); + MarkNativeAsOptional("BfWrite.WriteCoord"); + MarkNativeAsOptional("BfWrite.WriteVecCoord"); + MarkNativeAsOptional("BfWrite.WriteVecNormal"); + MarkNativeAsOptional("BfWrite.WriteAngles"); + MarkNativeAsOptional("BfRead.ReadBool"); + MarkNativeAsOptional("BfRead.ReadByte"); + MarkNativeAsOptional("BfRead.ReadChar"); + MarkNativeAsOptional("BfRead.ReadShort"); + MarkNativeAsOptional("BfRead.ReadWord"); + MarkNativeAsOptional("BfRead.ReadNum"); + MarkNativeAsOptional("BfRead.ReadFloat"); + MarkNativeAsOptional("BfRead.ReadString"); + MarkNativeAsOptional("BfRead.ReadEntity"); + MarkNativeAsOptional("BfRead.ReadAngle"); + MarkNativeAsOptional("BfRead.ReadCoord"); + MarkNativeAsOptional("BfRead.ReadVecCoord"); + MarkNativeAsOptional("BfRead.ReadVecNormal"); + MarkNativeAsOptional("BfRead.ReadAngles"); + MarkNativeAsOptional("BfRead.BytesLeft.get"); + + MarkNativeAsOptional("PbReadInt"); + MarkNativeAsOptional("PbReadFloat"); + MarkNativeAsOptional("PbReadBool"); + MarkNativeAsOptional("PbReadString"); + MarkNativeAsOptional("PbReadColor"); + MarkNativeAsOptional("PbReadAngle"); + MarkNativeAsOptional("PbReadVector"); + MarkNativeAsOptional("PbReadVector2D"); + MarkNativeAsOptional("PbGetRepeatedFieldCount"); + MarkNativeAsOptional("PbSetInt"); + MarkNativeAsOptional("PbSetFloat"); + MarkNativeAsOptional("PbSetBool"); + MarkNativeAsOptional("PbSetString"); + MarkNativeAsOptional("PbSetColor"); + MarkNativeAsOptional("PbSetAngle"); + MarkNativeAsOptional("PbSetVector"); + MarkNativeAsOptional("PbSetVector2D"); + MarkNativeAsOptional("PbAddInt"); + MarkNativeAsOptional("PbAddFloat"); + MarkNativeAsOptional("PbAddBool"); + MarkNativeAsOptional("PbAddString"); + MarkNativeAsOptional("PbAddColor"); + MarkNativeAsOptional("PbAddAngle"); + MarkNativeAsOptional("PbAddVector"); + MarkNativeAsOptional("PbAddVector2D"); + MarkNativeAsOptional("PbRemoveRepeatedFieldValue"); + MarkNativeAsOptional("PbReadMessage"); + MarkNativeAsOptional("PbReadRepeatedMessage"); + MarkNativeAsOptional("PbAddMessage"); + + MarkNativeAsOptional("Protobuf.ReadInt"); + MarkNativeAsOptional("Protobuf.ReadInt64"); + MarkNativeAsOptional("Protobuf.ReadFloat"); + MarkNativeAsOptional("Protobuf.ReadBool"); + MarkNativeAsOptional("Protobuf.ReadString"); + MarkNativeAsOptional("Protobuf.ReadColor"); + MarkNativeAsOptional("Protobuf.ReadAngle"); + MarkNativeAsOptional("Protobuf.ReadVector"); + MarkNativeAsOptional("Protobuf.ReadVector2D"); + MarkNativeAsOptional("Protobuf.GetRepeatedFieldCount"); + MarkNativeAsOptional("Protobuf.SetInt"); + MarkNativeAsOptional("Protobuf.SetInt64"); + MarkNativeAsOptional("Protobuf.SetFloat"); + MarkNativeAsOptional("Protobuf.SetBool"); + MarkNativeAsOptional("Protobuf.SetString"); + MarkNativeAsOptional("Protobuf.SetColor"); + MarkNativeAsOptional("Protobuf.SetAngle"); + MarkNativeAsOptional("Protobuf.SetVector"); + MarkNativeAsOptional("Protobuf.SetVector2D"); + MarkNativeAsOptional("Protobuf.AddInt"); + MarkNativeAsOptional("Protobuf.AddInt64"); + MarkNativeAsOptional("Protobuf.AddFloat"); + MarkNativeAsOptional("Protobuf.AddBool"); + MarkNativeAsOptional("Protobuf.AddString"); + MarkNativeAsOptional("Protobuf.AddColor"); + MarkNativeAsOptional("Protobuf.AddAngle"); + MarkNativeAsOptional("Protobuf.AddVector"); + MarkNativeAsOptional("Protobuf.AddVector2D"); + MarkNativeAsOptional("Protobuf.RemoveRepeatedFieldValue"); + MarkNativeAsOptional("Protobuf.ReadMessage"); + MarkNativeAsOptional("Protobuf.ReadRepeatedMessage"); + MarkNativeAsOptional("Protobuf.AddMessage"); + + VerifyCoreVersion(); +} + + +#define AUTOLOAD_EXTENSIONS +#define REQUIRE_EXTENSIONS +#define REQUIRE_PLUGIN diff --git a/source/sourcemod/scripting/include/cstrike.inc b/source/sourcemod/scripting/include/cstrike.inc new file mode 100644 index 0000000..38321bd --- /dev/null +++ b/source/sourcemod/scripting/include/cstrike.inc @@ -0,0 +1,488 @@ +/** + * 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_KNIFE 2 /**< Knife slot. */ +#define CS_SLOT_GRENADE 3 /**< Grenade slot (will only return one grenade). */ +#define CS_SLOT_C4 4 /**< C4 slot. */ +#define CS_SLOT_BOOST 11 /**< Slot for healthshot and shield (will only return one weapon/item). */ +#define CS_SLOT_UTILITY 12 /**< Slot for tablet. */ + +#define CS_DMG_HEADSHOT (1 << 30) /**< Headshot */ + +enum CSRoundEndReason +{ + CSRoundEnd_TargetBombed = 0, /**< Target Successfully Bombed! */ + CSRoundEnd_VIPEscaped, /**< The VIP has escaped! - Doesn't exist on CS:GO */ + CSRoundEnd_VIPKilled, /**< VIP has been assassinated! - Doesn't exist on CS:GO */ + CSRoundEnd_TerroristsEscaped, /**< The terrorists have escaped! */ + CSRoundEnd_CTStoppedEscape, /**< The CTs have prevented most of the terrorists from escaping! */ + CSRoundEnd_TerroristsStopped, /**< Escaping terrorists have all been neutralized! */ + CSRoundEnd_BombDefused, /**< The bomb has been defused! */ + CSRoundEnd_CTWin, /**< Counter-Terrorists Win! */ + CSRoundEnd_TerroristWin, /**< Terrorists Win! */ + CSRoundEnd_Draw, /**< Round Draw! */ + CSRoundEnd_HostagesRescued, /**< All Hostages have been rescued! */ + CSRoundEnd_TargetSaved, /**< Target has been saved! */ + CSRoundEnd_HostagesNotRescued, /**< Hostages have not been rescued! */ + CSRoundEnd_TerroristsNotEscaped, /**< Terrorists have not escaped! */ + CSRoundEnd_VIPNotEscaped, /**< VIP has not escaped! - Doesn't exist on CS:GO */ + CSRoundEnd_GameStart, /**< Game Commencing! */ + + // The below only exist on CS:GO + CSRoundEnd_TerroristsSurrender, /**< Terrorists Surrender */ + CSRoundEnd_CTSurrender, /**< CTs Surrender */ + CSRoundEnd_TerroristsPlanted, /**< Terrorists Planted the bomb */ + CSRoundEnd_CTsReachedHostage /**< CTs Reached the hostage */ +}; + +enum CSWeaponID +{ + CSWeapon_NONE = 0, + CSWeapon_P228, + CSWeapon_GLOCK, + CSWeapon_SCOUT, + CSWeapon_HEGRENADE, + CSWeapon_XM1014, + CSWeapon_C4, + CSWeapon_MAC10, + CSWeapon_AUG, + CSWeapon_SMOKEGRENADE, + CSWeapon_ELITE, + CSWeapon_FIVESEVEN, + CSWeapon_UMP45, + CSWeapon_SG550, + CSWeapon_GALIL, + CSWeapon_FAMAS, + CSWeapon_USP, + CSWeapon_AWP, + CSWeapon_MP5NAVY, + CSWeapon_M249, + CSWeapon_M3, + CSWeapon_M4A1, + CSWeapon_TMP, + CSWeapon_G3SG1, + CSWeapon_FLASHBANG, + CSWeapon_DEAGLE, + CSWeapon_SG552, + CSWeapon_AK47, + CSWeapon_KNIFE, + CSWeapon_P90, + CSWeapon_SHIELD, + CSWeapon_KEVLAR, + CSWeapon_ASSAULTSUIT, + CSWeapon_NIGHTVISION, //Anything below is CS:GO ONLY + CSWeapon_GALILAR, + CSWeapon_BIZON, + CSWeapon_MAG7, + CSWeapon_NEGEV, + CSWeapon_SAWEDOFF, + CSWeapon_TEC9, + CSWeapon_TASER, + CSWeapon_HKP2000, + CSWeapon_MP7, + CSWeapon_MP9, + CSWeapon_NOVA, + CSWeapon_P250, + CSWeapon_SCAR17, + CSWeapon_SCAR20, + CSWeapon_SG556, + CSWeapon_SSG08, + CSWeapon_KNIFE_GG, + CSWeapon_MOLOTOV, + CSWeapon_DECOY, + CSWeapon_INCGRENADE, + CSWeapon_DEFUSER, + CSWeapon_HEAVYASSAULTSUIT, + //The rest are actual item definition indexes for CS:GO + CSWeapon_CUTTERS = 56, + CSWeapon_HEALTHSHOT = 57, + CSWeapon_KNIFE_T = 59, + CSWeapon_M4A1_SILENCER = 60, + CSWeapon_USP_SILENCER = 61, + CSWeapon_CZ75A = 63, + CSWeapon_REVOLVER = 64, + CSWeapon_TAGGRENADE = 68, + CSWeapon_FISTS = 69, + CSWeapon_BREACHCHARGE = 70, + CSWeapon_TABLET = 72, + CSWeapon_MELEE = 74, + CSWeapon_AXE = 75, + CSWeapon_HAMMER = 76, + CSWeapon_SPANNER = 78, + CSWeapon_KNIFE_GHOST = 80, + CSWeapon_FIREBOMB = 81, + CSWeapon_DIVERSION = 82, + CSWeapon_FRAGGRENADE = 83, + CSWeapon_SNOWBALL = 84, + CSWeapon_BUMPMINE = 85, + CSWeapon_MAX_WEAPONS_NO_KNIFES, // Max without the knife item defs, useful when treating all knives as a regular knife. + CSWeapon_BAYONET = 500, + CSWeapon_KNIFE_CLASSIC = 503, + CSWeapon_KNIFE_FLIP = 505, + CSWeapon_KNIFE_GUT = 506, + CSWeapon_KNIFE_KARAMBIT = 507, + CSWeapon_KNIFE_M9_BAYONET = 508, + CSWeapon_KNIFE_TATICAL = 509, + CSWeapon_KNIFE_FALCHION = 512, + CSWeapon_KNIFE_SURVIVAL_BOWIE = 514, + CSWeapon_KNIFE_BUTTERFLY = 515, + CSWeapon_KNIFE_PUSH = 516, + CSWeapon_KNIFE_CORD = 517, + CSWeapon_KNIFE_CANIS = 518, + CSWeapon_KNIFE_URSUS = 519, + CSWeapon_KNIFE_GYPSY_JACKKNIFE = 520, + CSWeapon_KNIFE_OUTDOOR = 521, + CSWeapon_KNIFE_STILETTO = 522, + CSWeapon_KNIFE_WIDOWMAKER = 523, + CSWeapon_KNIFE_SKELETON = 525, + CSWeapon_MAX_WEAPONS //THIS MUST BE LAST, EASY WAY TO CREATE LOOPS. When looping, do CS_IsValidWeaponID(i), to check. +}; + +/** + * Called when a player attempts to purchase an item. + * Return Plugin_Continue to allow the purchase or return a + * higher action to deny. + * + * @param client Client index + * @param weapon User input for weapon name + */ +forward Action CS_OnBuyCommand(int client, const char[] weapon); + +/** + * Called when CSWeaponDrop is called + * Return Plugin_Continue to allow the call or return a + * higher action to block. + * + * @param client Client index + * @param weaponIndex Weapon index + * @param donated Was weapon donated (Bought from a buy menu while ctrl was pressed) + * (Note: This param is for CS:GO only, will be false on other games) + */ +forward Action CS_OnCSWeaponDrop(int client, int weaponIndex, bool donated); + +/** + * Called when game retrieves a weapon's price for a player. + * Return Plugin_Continue to use default value or return a higher + * action to use a newly-set price. + * + * @note This can be called multiple times per weapon purchase + * + * @param client Client index + * @param weapon Weapon classname + * @param price Buffer param for the price of the weapon + * + * @note Not all "weapons" call GetWeaponPrice. Example: c4, knife, vest, vest helmet, night vision. + */ +forward Action CS_OnGetWeaponPrice(int client, const char[] weapon, int &price); + +/** + * Called when TerminateRound is called. + * Return Plugin_Continue to ignore, return Plugin_Changed to continue, + * using the given delay and reason, or return Plugin_Handled or a higher + * action to block TerminateRound from firing. + * + * @param delay Time (in seconds) until new round starts + * @param reason Reason for round end + */ +forward Action CS_OnTerminateRound(float &delay, CSRoundEndReason &reason); + +/** + * Respawns a player. + * + * @param client Player's index. + * @error Invalid client index, client not in game. + */ +native void CS_RespawnPlayer(int client); + +/** + * Switches the player's team. + * + * @param client Player's index. + * @param team Team index. + * @error Invalid client index, client not in game. + */ +native void CS_SwitchTeam(int client, int team); + +/** + * Forces a player to drop or toss their weapon + * + * @param client Player's index. + * @param weaponIndex Index of weapon to drop. + * @param toss True to toss weapon (with velocity) or false to just drop weapon + * @param blockhook Set to true to stop the corresponding CS_OnCSWeaponDrop + * @error Invalid client index, client not in game, or invalid weapon index. + */ +native void CS_DropWeapon(int client, int weaponIndex, bool toss, bool blockhook = false); + +/** + * Forces round to end with a reason + * + * @param delay Time (in seconds) to delay before new round starts + * @param reason Reason for the round ending + * @param blockhook Set to true to stop the corresponding CS_OnTerminateRound + * forward from being called. + */ +native void CS_TerminateRound(float delay, CSRoundEndReason reason, bool blockhook = false); + +/** + * Gets a weapon name from a weapon alias + * + * @param alias Weapons alias to get weapon name for. + * @param weapon Buffer to store weapons name + * @param size Size of buffer to store the weapons name. + * + * @note Will set the buffer to the original alias if it is not an alias to a weapon. + */ +native void CS_GetTranslatedWeaponAlias(const char[] alias, char[] weapon, int size); + +/** + * Gets a weapon's price + * + * @param client Client to check weapon price for. + * @param id Weapon id for the weapon to check + * @param defaultprice Set to true to get defaultprice. + * @return Returns price of the weapon (even if modified) + * @error Invalid client, failing to get weapon info, or failing to get price offset. + * + * @note c4, knife and shield will always return 0. vest, vest helmet and night vision will always return default price. + */ +native int CS_GetWeaponPrice(int client, CSWeaponID id, bool defaultprice = false); + +/** + * Gets a clients clan tag + * + * @param client Client index to get clan tag for. + * @param buffer Buffer to store clients clan tag in. + * @param size Size of the buffer. + * @return Number of non-null bytes written. + * @error Invalid client. + */ +native int CS_GetClientClanTag(int client, char[] buffer, int size); + +/** + * Sets a clients clan tag + * + * @param client Client index to set clan tag for. + * @param tag Tag to set clients clan tag as. + * @error Invalid client. + */ +native void CS_SetClientClanTag(int client, const char[] tag); + +/** + * Gets a team's score + * + * @param team Team index to get score for. + * @return Returns the internal team score. + * @error Invalid team index. + */ +native int CS_GetTeamScore(int team); + +/** + * Sets a team's score + * + * @param team Team index to set score for. + * @param value Value to set teams score as. + * @error Invalid team index. + * + * @note This will update the scoreboard only after the scoreboard update function is called. + * Use SetTeamScore plus this to update the scoreboard instantly and save values correctly. + */ +native void CS_SetTeamScore(int team, int value); + +/** + * Gets a client's mvp count + * + * @param client Client index to get mvp count of. + * @return Returns the client's internal MVP count. + * @error Invalid client. + */ +native int CS_GetMVPCount(int client); + +/** + * Sets a client's mvp count + * + * @param client Client index to set mvp count for. + * @param value Value to set client's mvp count as. + * @error Invalid client. + */ +native void CS_SetMVPCount(int client, int value); + +/** + * Gets a client's contribution score (CS:GO only) + * + * @param client Client index to get score of. + * @return Returns the client's score. + * @error Invalid client. + */ +native int CS_GetClientContributionScore(int client); + +/** + * Sets a client's contribution score (CS:GO only) + * + * @param client Client index to set score for. + * @param value Value to set client's score as. + * @error Invalid client. + */ +native void CS_SetClientContributionScore(int client, int value); + +/** + * Gets a client's assists (CS:GO only) + * + * @param client Client index to get assists of. + * @return Returns the client's assists. + * @error Invalid client. + */ +native int CS_GetClientAssists(int client); + +/** + * Sets a client's assists (CS:GO only) + * + * @param client Client index to set assists for. + * @param value Value to set client's assists as. + * @error Invalid client. + */ +native void CS_SetClientAssists(int client, int value); + +/** + * Gets a weaponID from a alias + * + * @param alias Weapon alias to attempt to get an id for. + * @return Returns a weapon id or 0 if failed to find a match. + * + * @note For best results use CS_GetTranslatedWeaponAlias on the weapon name before passing it. + */ +native CSWeaponID CS_AliasToWeaponID(const char[] alias); + +/** + * Gets a alias from a weaponID + * + * @param weaponID WeaponID to get alias for. + * @param destination Destination string to hold the weapon alias. + * @param len Length of the destination array. + * @return Returns number of cells written. + */ +native int CS_WeaponIDToAlias(CSWeaponID weaponID, char[] destination, int len); + +/** + * Returns weather a WeaponID is valid on the current mod (css or csgo) + * + * @param weaponID WeaponID to check + * @return Returns true if its a valid WeaponID false otherwise. + * + * @note This will return false always for CSWeapon_NONE. Should only be called after OnMapStart since weapon info isnt intialized before. + */ +native bool CS_IsValidWeaponID(CSWeaponID id); + +/** + * Sets a player's model based on their current class + * + * @param client Player's index. + * @error Invalid client index, client not in game. + */ +native void CS_UpdateClientModel(int client); + +/** + * Returns a CSWeaponID equivalent based on the item definition index. + * + * @param iDefIndex Definition index to get the CSWeaponID value for. + * @return Returns CSWeaponID value for the definition index. + * @error Invalid definition index. + * + * @note In most cases the id will be the item definition index. Works for CS:GO ONLY. + */ +native CSWeaponID CS_ItemDefIndexToID(int iDefIndex); + +/** + * Returns a item definition index equivalent based on the CSWeaponID. + * + * @param id CSWeaponID to get the item definition for. + * @return Returns item definition index value for the weapon id. + * @error Invalid weapon id. + * + * @note In most cases the item deinition index will be the id. Works for CS:GO ONLY. + */ +native int CS_WeaponIDToItemDefIndex(CSWeaponID id); + +/** + * 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 void __ext_cstrike_SetNTVOptional() +{ + MarkNativeAsOptional("CS_RespawnPlayer"); + MarkNativeAsOptional("CS_SwitchTeam"); + MarkNativeAsOptional("CS_DropWeapon"); + MarkNativeAsOptional("CS_TerminateRound"); + MarkNativeAsOptional("CS_GetTranslatedWeaponAlias"); + MarkNativeAsOptional("CS_GetWeaponPrice"); + MarkNativeAsOptional("CS_GetClientClanTag"); + MarkNativeAsOptional("CS_SetClientClanTag"); + MarkNativeAsOptional("CS_GetTeamScore"); + MarkNativeAsOptional("CS_SetTeamScore"); + MarkNativeAsOptional("CS_GetMVPCount"); + MarkNativeAsOptional("CS_SetMVPCount"); + MarkNativeAsOptional("CS_GetClientContributionScore"); + MarkNativeAsOptional("CS_SetClientContributionScore"); + MarkNativeAsOptional("CS_GetClientAssists"); + MarkNativeAsOptional("CS_SetClientAssists"); + MarkNativeAsOptional("CS_AliasToWeaponID"); + MarkNativeAsOptional("CS_WeaponIDToAlias"); + MarkNativeAsOptional("CS_IsValidWeaponID"); + MarkNativeAsOptional("CS_UpdateClientModel"); + MarkNativeAsOptional("CS_ItemDefIndexToID"); + MarkNativeAsOptional("CS_WeaponIDToItemDefIndex"); +} +#endif diff --git a/source/sourcemod/scripting/include/datapack.inc b/source/sourcemod/scripting/include/datapack.inc new file mode 100644 index 0000000..ae8b4d9 --- /dev/null +++ b/source/sourcemod/scripting/include/datapack.inc @@ -0,0 +1,255 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * 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 + + +/** + * Opaque handle to a datapack position. + */ +enum DataPackPos: {}; + +// A DataPack allows serializing multiple variables into a single stream. +methodmap DataPack < Handle +{ + // Creates a new data pack. + public native DataPack(); + + // Packs a normal cell into a data pack. + // + // @param cell Cell to add. + // @param insert Determines whether mid-pack writes will insert instead of overwrite. + public native void WriteCell(any cell, bool insert = false); + + // Packs a float into a data pack. + // + // @param val Float to add. + // @param insert Determines whether mid-pack writes will insert instead of overwrite. + public native void WriteFloat(float val, bool insert = false); + + // Packs a string into a data pack. + // + // @param str String to add. + // @param insert Determines whether mid-pack writes will insert instead of overwrite. + public native void WriteString(const char[] str, bool insert = false); + + // Packs a function pointer into a data pack. + // + // @param fktptr Function pointer to add. + // @param insert Determines whether mid-pack writes will insert instead of overwrite. + public native void WriteFunction(Function fktptr, bool insert = false); + + // Packs an array of cells into a data pack. + // + // @param array Array to add. + // @param count Number of elements + // @param insert Determines whether mid-pack writes will insert instead of overwrite. + public native void WriteCellArray(const any[] array, int count, bool insert = false); + + // Packs an array of floats into a data pack. + // + // @param array Array to add. + // @param count Number of elements + // @param insert Determines whether mid-pack writes will insert instead of overwrite. + public native void WriteFloatArray(const float[] array, int count, bool insert = false); + + // Reads a cell from a data pack. + // + // @return A cell at this position + public native any ReadCell(); + + // Reads a float from a data pack. + // + // @return Float at this position + public native float ReadFloat(); + + // Reads a string from a data pack. + // + // @param buffer Destination string buffer. + // @param maxlen Maximum length of output string buffer. + public native void ReadString(char[] buffer, int maxlen); + + // Reads a function pointer from a data pack. + // + // @return Function pointer. + public native Function ReadFunction(); + + // Reads an array of cells a data pack. + // + // @param buffer Destination buffer. + // @param count Maximum length of output buffer. + public native void ReadCellArray(any[] buffer, int count); + + // Reads an array of floats from a data pack. + // + // @param buffer Destination buffer. + // @param count Maximum length of output buffer. + public native void ReadFloatArray(float[] buffer, int count); + + // Resets the position in a data pack. + // + // @param clear If true, clears the contained data. + public native void Reset(bool clear=false); + + // Returns whether or not a specified number of bytes from the data pack + // position to the end can be read. + // + // @param unused Unused variable. Exists for backwards compatability. + public native bool IsReadable(int unused = 0); + + // The read or write position in a data pack. + property DataPackPos Position { + public native get(); + public native set(DataPackPos pos); + } +}; + +/** + * Creates a new data pack. + * + * @return A Handle to the data pack. Must be closed with CloseHandle(). + */ +native DataPack CreateDataPack(); + +/** + * Packs a normal cell into a data pack. + * + * @param pack Handle to the data pack. + * @param cell Cell to add. + * @error Invalid handle. + */ +native void WritePackCell(Handle pack, any cell); + +/** + * Packs a float into a data pack. + * + * @param pack Handle to the data pack. + * @param val Float to add. + * @error Invalid handle. + */ +native void WritePackFloat(Handle pack, float val); + +/** + * Packs a string into a data pack. + * + * @param pack Handle to the data pack. + * @param str String to add. + * @error Invalid handle. + */ +native void WritePackString(Handle pack, const char[] str); + +/** + * Packs a function pointer into a data pack. + * + * @param pack Handle to the data pack. + * @param fktptr Function pointer to add. + * @error Invalid handle. + */ +native void WritePackFunction(Handle pack, Function fktptr); + +/** + * Reads a cell from a data pack. + * + * @param pack Handle to the data pack. + * @return Cell value. + * @error Invalid handle, or bounds error. + */ +native any 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. + * @error Invalid handle, or bounds error. + */ +native void ReadPackString(Handle pack, char[] buffer, int maxlen); + +/** + * Reads a function pointer from a data pack. + * + * @param pack Handle to the data pack. + * @return Function pointer. + * @error Invalid handle, or bounds error. + */ +native Function ReadPackFunction(Handle pack); + +/** + * Resets the position in a data pack. + * + * @param pack Handle to the data pack. + * @param clear If true, clears the contained data. + * @error Invalid handle. + */ +native void ResetPack(Handle pack, bool clear=false); + +/** + * Returns the read or write position in a data pack. + * + * @param pack Handle to the data pack. + * @return Position in the data pack, only usable with calls to SetPackPosition. + * @error Invalid handle. + */ +native DataPackPos 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. Must have been previously retrieved from a call to GetPackPosition. + * @error Invalid handle, or position is beyond the pack bounds. + */ +native void SetPackPosition(Handle pack, DataPackPos 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, int bytes); diff --git a/source/sourcemod/scripting/include/dbi.inc b/source/sourcemod/scripting/include/dbi.inc new file mode 100644 index 0000000..3c54ac7 --- /dev/null +++ b/source/sourcemod/scripting/include/dbi.inc @@ -0,0 +1,1073 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 + +/** + * 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. */ +}; + +// A Driver represents a database backend, currently MySQL or SQLite. +// +// Driver handles cannot be closed. +methodmap DBDriver < Handle +{ + // Finds the driver associated with a name. + // + // Supported driver strings: + // mysql + // sqlite + // + // @param name Driver identification string, or an empty string + // to return the default driver. + // @return Driver handle, or null on failure. + public static native DBDriver Find(const char[] name = ""); + + // Retrieves a driver's identification string. + // + // Example: "mysql", "sqlite" + // + // @param ident Identification string buffer. + // @param maxlength Maximum length of the buffer. + public native void GetIdentifier(char[] ident, int maxlength); + + // Retrieves a driver's product string. + // + // Example: "MySQL", "SQLite" + // + // @param product Product string buffer. + // @param maxlength Maximum length of the buffer. + public native void GetProduct(char[] product, int maxlength); +}; + +// Represents a set of results returned from executing a query. +methodmap DBResultSet < Handle +{ + // 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. + // + // @return True if there was another result set, false otherwise. + public native bool FetchMoreResults(); + + // 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. + property bool HasResults { + public native get(); + } + + // 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. + property int RowCount { + public native get(); + } + + // Retrieves the number of fields in the last result set. + property int FieldCount { + public native get(); + } + + // Returns the number of affected rows from the query that generated this + // result set. + property int AffectedRows { + public native get(); + } + + // Returns the insert id from the query that generated this result set. + property int InsertId { + public native get(); + } + + // Retrieves the name of a field by index. + // + // @param field Field number (starting from 0). + // @param name Name buffer. + // @param maxlength Maximum length of the name buffer. + // @error Invalid field index, or no current result set. + public native void FieldNumToName(int field, char[] name, int maxlength); + + // Retrieves a field index by name. + // + // @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 No current result set. + public native bool FieldNameToNum(const char[] name, int &field); + + // Fetches a row from the current result set. This must be + // successfully called before any results are fetched. + // + // If this function fails, MoreRows can be used to + // tell if there was an error or the result set is finished. + // + // @return True if a row was fetched, false otherwise. + public native bool FetchRow(); + + // Returns if there are more rows. + // + // @return True if there are more rows, false otherwise. + property bool MoreRows { + public native get(); + } + + // Rewinds a result set back to the first result. + // + // @return True on success, false otherwise. + // @error No current result set. + public native bool Rewind(); + + // 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 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 field index, invalid type conversion requested + // from the database, or no current result set. + public native int FetchString(int field, char[] buffer, int 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 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 field index, invalid type conversion requested + // from the database, or no current result set. + public native float FetchFloat(int 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 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 field index, invalid type conversion requested + // from the database, or no current result set. + public native int FetchInt(int 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 field The field index (starting from 0). + // @return True if data is NULL, false otherwise. + // @error Invalid field index, or no current result set. + public native bool IsFieldNull(int 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 field The field index (starting from 0). + // @return Number of bytes for the field's data size. + // @error Invalid field index or no current result set. + public native int FetchSize(int field); +}; + +typeset SQLTxnSuccess +{ + // Callback for a successful transaction. + // + // @param db Database handle. + // @param data Data value passed to SQL_ExecuteTransaction(). + // @param numQueries Number of queries executed in the transaction. + // @param results An array of Query handle results, one for each of numQueries. They are closed automatically. + // @param queryData An array of each data value passed to SQL_AddQuery(). + function void (Database db, any data, int numQueries, Handle[] results, any[] queryData); + + // Callback for a successful transaction. + // + // @param db Database handle. + // @param data Data value passed to SQL_ExecuteTransaction(). + // @param numQueries Number of queries executed in the transaction. + // @param results An array of DBResultSet results, one for each of numQueries. They are closed automatically. + // @param queryData An array of each data value passed to SQL_AddQuery(). + function void (Database db, any data, int numQueries, DBResultSet[] results, any[] queryData); +} + +/** + * Callback for a failed transaction. + * + * @param db Database handle. + * @param data Data value passed to SQL_ExecuteTransaction(). + * @param numQueries Number of queries executed in the transaction. + * @param error Error message. + * @param failIndex Index of the query that failed, or -1 if something else. + * @param queryData An array of each data value passed to SQL_AddQuery(). + */ +typedef SQLTxnFailure = function void (Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData); + +// A Transaction is a collection of SQL statements that must all execute +// successfully or not at all. +methodmap Transaction < Handle +{ + // Create a new transaction. + public native Transaction(); + + // Adds a query to the transaction. + // + // @param query Query string. + // @param data Extra data value to pass to the final callback. + // @return The index of the query in the transaction's query list. + public native int AddQuery(const char[] query, any data=0); +}; + +// A DBStatement is a pre-compiled SQL query that may be executed multiple +// times with different parameters. A DBStatement holds a reference to the +// Database that prepared it. +methodmap DBStatement < Handle +{ + // Binds a parameter in a prepared statement to a given integer value. + // + // @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. + // @error Invalid parameter index, or SQL error. + public native void BindInt(int param, int number, bool signed=true); + + // Binds a parameter in a prepared statement to a given float value. + // + // @param param The parameter index (starting from 0). + // @param value The float number to bind. + // @error Invalid parameter index, or SQL error. + public native void BindFloat(int param, float value); + + // Binds a parameter in a prepared statement to a given string value. + // + // @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. + // @error Invalid parameter index, or SQL error. + public native void BindString(int param, const char[] value, bool copy); +}; + +/** + * Callback for receiving asynchronous database connections. + * + * @param db Handle to the database connection. + * @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. + */ +typedef SQLConnectCallback = function void (Database db, const char[] error, any data); + +/** + * Callback for receiving asynchronous database query results. + * + * @param db Cloned handle to the database connection. + * @param results Result object, or null on failure. + * @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 results value instead. + * @param data Data passed in via the original threaded invocation. + */ +typedef SQLQueryCallback = function void (Database db, DBResultSet results, const char[] error, any data); + +// A Database represents a live connection to a database, either over the +// wire, through a unix domain socket, or over an open file. +methodmap Database < Handle +{ + // Connects to a database asynchronously, so the game thread is not blocked. + // + // @param callback Callback. If no driver was found, the owner is null. + // @param name Database configuration name. + // @param data Extra data value to pass to the callback. + public static native void Connect(SQLConnectCallback callback, const char[] name="default", any data=0); + + // Returns the driver for this database connection. + property DBDriver Driver { + public native get(); + } + + // Sets the character set of the connection. + // Like SET NAMES .. in mysql, but stays after connection problems. + // + // Example: "utf8", "latin1" + // + // @param charset The character set string to change to. + // @return True, if character set was changed, false otherwise. + public native bool SetCharset(const char[] charset); + + // 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 single quotes. While drivers tend to allow double + // quotes (") instead, the string may be not be escaped (for example, on SQLite)! + // + // @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. + public native bool Escape(const char[] string, char[] buffer, int maxlength, int &written=0); + + // Formats a string according to the SourceMod format rules (see documentation). + // All format specifiers are escaped (see SQL_EscapeString) unless the '!' flag is used. + // + // @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. + public native int Format(char[] buffer, int maxlength, const char[] format, any ...); + + // Returns whether a database is the same connection as another database. + public native bool IsSameConnection(Database other); + + // Executes a query via a thread. The result handle is passed through the + // callback. + // + // The database handle returned through the callback is always a new Handle, + // and if necessary, IsSameConnection() should be used to test against other + // connections. + // + // The result handle returned through the callback is temporary and destroyed + // at the end of the callback. + // + // @param callback Callback. + // @param query Query string. + // @param data Extra data value to pass to the callback. + // @param prio Priority queue to use. + public native void Query(SQLQueryCallback callback, const char[] query, + any data = 0, + DBPriority prio = DBPrio_Normal); + + // Sends a transaction to the database thread. The transaction handle is + // automatically closed. When the transaction completes, the optional + // callback is invoked. + // + // @param txn A transaction handle. + // @param onSuccess An optional callback to receive a successful transaction. + // @param onError An optional callback to receive an error message. + // @param data An optional value to pass to callbacks. + // @param prio Priority queue to use. + public native void Execute(Transaction txn, + SQLTxnSuccess onSuccess = INVALID_FUNCTION, + SQLTxnFailure onError = INVALID_FUNCTION, + any data = 0, + DBPriority priority = DBPrio_Normal); +}; + +/** + * 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 Database SQL_Connect(const char[] confname, bool persistent, char[] error, int 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 Database SQL_DefConnect(char[] error, int 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 omitted 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. + * @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. + * @error Invalid KeyValues handle. + */ +native Database SQL_ConnectCustom(Handle keyvalues, + char[] error, + int 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 Database SQLite_UseDatabase(const char[] database, char[] error, int maxlength) +{ + KeyValues kv = new KeyValues(""); + kv.SetString("driver", "sqlite"); + kv.SetString("database", database); + + Database db = SQL_ConnectCustom(kv, error, maxlength, false); + + delete kv; + + return db; +} + +/** + * This function is deprecated. Use SQL_ConnectCustom or SQLite_UseDatabase instead. + * @deprecated + */ +#pragma deprecated Use SQL_ConnectCustom instead. +native Handle SQL_ConnectEx(Handle driver, + const char[] host, + const char[] user, + const char[] pass, + const char[] database, + char[] error, + int maxlength, + bool persistent=true, + int port=0, + int 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 char[] 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 DBDriver SQL_GetDriver(const char[] 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 DBDriver SQL_ReadDriver(Handle database, char[] ident="", int 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. + * @error Invalid Handle other than INVALID_HANDLE. + */ +native void SQL_GetDriverIdent(Handle driver, char[] ident, int 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. + * @error Invalid Handle other than INVALID_HANDLE. + */ +native void SQL_GetDriverProduct(Handle driver, char[] product, int maxlength); + +/** + * Sets the character set of the current connection. + * Like SET NAMES .. in mysql, but stays after connection problems. + * + * Example: "utf8", "latin1" + * + * @param database Database Handle. + * @param charset The character set string to change to. + * @return True, if character set was changed, false otherwise. + */ +native bool SQL_SetCharset(Handle database, const char[] charset); + +/** + * 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 int SQL_GetAffectedRows(Handle hndl); + +/** + * Returns the last query's insertion id. + * + * @param hndl A database, query, OR statement Handle. + * @return Last query's insertion id. + * @error Invalid database, query, or statement Handle. + */ +native int SQL_GetInsertId(Handle hndl); + +/** + * Returns the error reported by the last query. + * + * @param hndl A database, query, 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, query, or statement Handle. + */ +native bool SQL_GetError(Handle hndl, char[] error, int 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 single quotes. While drivers tend to allow double + * quotes (") instead, the string may be not be escaped (for example, on SQLite)! + * + * @param database 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 char[] string, + char[] buffer, + int maxlength, + int &written=0); + +/** + * Formats a string according to the SourceMod format rules (see documentation). + * All format specifiers are escaped (see SQL_EscapeString) unless the '!' flag is used. + * + * @param database A database Handle. + * @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 int SQL_FormatQuery(Handle database, char[] buffer, int maxlength, const char[] format, any ...); + +/** + * This function is deprecated. Use SQL_EscapeString instead. + * @deprecated + */ +#pragma deprecated Use SQL_EscapeString instead. +stock bool SQL_QuoteString(Handle database, + const char[] string, + char[] buffer, + int maxlength, + int &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 char[] query, int 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 DBResultSet SQL_Query(Handle database, const char[] query, int 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 DBStatement SQL_PrepareQuery(Handle database, const char[] query, char[] error, int 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 int 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 int 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. + * @error Invalid query Handle, invalid field index, or + * no current result set. + */ +native void SQL_FieldNumToName(Handle query, int field, char[] name, int 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 char[] name, int &field); + +/** + * Fetches a row from the current result set. This must be + * successfully called before any results are fetched. + * + * If this function fails, SQL_MoreRows() 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 int SQL_FetchString(Handle query, int field, char[] buffer, int 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, int 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 int SQL_FetchInt(Handle query, int 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, int 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 int SQL_FetchSize(Handle query, int 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. + * @error Invalid statement Handle or parameter index, or + * SQL error. + */ +native void SQL_BindParamInt(Handle statement, int param, int 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 value The float number to bind. + * @error Invalid statement Handle or parameter index, or + * SQL error. + */ +native void SQL_BindParamFloat(Handle statement, int 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. + * @error Invalid statement Handle or parameter index, or + * SQL error. + */ +native void SQL_BindParamString(Handle statement, int param, const char[] 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. + * @error Invalid database Handle. + */ +native void SQL_LockDatabase(Handle database); + +/** + * Unlocks a database so threading operations may continue. + * + * @param database A database Handle. + * @error Invalid database Handle. + */ +native void SQL_UnlockDatabase(Handle database); + +/** + * General callback for threaded SQL stuff. + * + * @param owner 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. + */ +typedef SQLTCallback = function void (Handle owner, Handle hndl, const char[] 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. + * @param data Extra data value to pass to the callback. + */ +native void SQL_TConnect(SQLTCallback callback, const char[] 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 connections. + * + * 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. + * @error Invalid database Handle. + */ +native void SQL_TQuery(Handle database, SQLTCallback callback, const char[] query, any data=0, DBPriority prio=DBPrio_Normal); + +/** + * Creates a new transaction object. A transaction object is a list of queries + * that can be sent to the database thread and executed as a single transaction. + * + * @return A transaction handle. + */ +native Transaction SQL_CreateTransaction(); + +/** + * Adds a query to a transaction object. + * + * @param txn A transaction handle. + * @param query Query string. + * @param data Extra data value to pass to the final callback. + * @return The index of the query in the transaction's query list. + * @error Invalid transaction handle. + */ +native int SQL_AddQuery(Transaction txn, const char[] query, any data=0); + +/** + * Sends a transaction to the database thread. The transaction handle is + * automatically closed. When the transaction completes, the optional + * callback is invoked. + * + * @param db A database handle. + * @param txn A transaction handle. + * @param onSuccess An optional callback to receive a successful transaction. + * @param onError An optional callback to receive an error message. + * @param data An optional value to pass to callbacks. + * @param prio Priority queue to use. + * @error An invalid handle. + */ +native void SQL_ExecuteTransaction( + Handle db, + Transaction txn, + SQLTxnSuccess onSuccess = INVALID_FUNCTION, + SQLTxnFailure onError = INVALID_FUNCTION, + any data=0, + DBPriority priority=DBPrio_Normal); diff --git a/source/sourcemod/scripting/include/dhooks.inc b/source/sourcemod/scripting/include/dhooks.inc new file mode 100644 index 0000000..76ff8c4 --- /dev/null +++ b/source/sourcemod/scripting/include/dhooks.inc @@ -0,0 +1,1100 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2021 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 _dhooks_included +#endinput +#endif +#define _dhooks_included + +// Needed for the SDKFuncConfSource enum. +#include + +#define INVALID_HOOK_ID 0 + +enum ObjectValueType +{ + ObjectValueType_Int = 0, + ObjectValueType_Bool, + ObjectValueType_Ehandle, + ObjectValueType_Float, + ObjectValueType_CBaseEntityPtr, + ObjectValueType_IntPtr, + ObjectValueType_BoolPtr, + ObjectValueType_EhandlePtr, + ObjectValueType_FloatPtr, + ObjectValueType_Vector, + ObjectValueType_VectorPtr, + ObjectValueType_CharPtr, + ObjectValueType_String +}; + +enum ListenType +{ + ListenType_Created, + ListenType_Deleted +}; + +enum ReturnType +{ + ReturnType_Unknown, + ReturnType_Void, + ReturnType_Int, + ReturnType_Bool, + ReturnType_Float, + ReturnType_String, // Note this is a string_t + ReturnType_StringPtr, // Note this is a string_t * + ReturnType_CharPtr, + ReturnType_Vector, + ReturnType_VectorPtr, + ReturnType_CBaseEntity, + ReturnType_Edict +}; + +enum HookParamType +{ + HookParamType_Unknown, + HookParamType_Int, + HookParamType_Bool, + HookParamType_Float, + HookParamType_String, // Note this is a string_t + HookParamType_StringPtr, // Note this is a string_t * + HookParamType_CharPtr, + HookParamType_VectorPtr, + HookParamType_CBaseEntity, + HookParamType_ObjectPtr, + HookParamType_Edict, + HookParamType_Object +}; + +enum ThisPointerType +{ + ThisPointer_Ignore, + ThisPointer_CBaseEntity, + ThisPointer_Address +}; + +enum HookType +{ + HookType_Entity, + HookType_GameRules, + HookType_Raw +}; + +enum CallingConvention +{ + CallConv_CDECL, + CallConv_THISCALL, + CallConv_STDCALL, + CallConv_FASTCALL, +}; + +enum HookMode +{ + Hook_Pre, /**< Callback will be executed BEFORE the original function. */ + Hook_Post /**< Callback will be executed AFTER the original function. */ +}; + +enum MRESReturn +{ + MRES_ChangedHandled = -2, /**< Use changed values and return MRES_Handled */ + MRES_ChangedOverride, /**< Use changed values and return MRES_Override */ + MRES_Ignored, /**< plugin didn't take any action */ + MRES_Handled, /**< plugin did something, but real function should still be called */ + MRES_Override, /**< call real function, but use my return value */ + MRES_Supercede /**< skip real function; use my return value */ +}; + +enum DHookPassFlag +{ + DHookPass_ByVal = (1<<0), /**< Passing by value */ + DHookPass_ByRef = (1<<1), /**< Passing by reference */ + DHookPass_ODTOR = (1<<2), /**< Object has a destructor */ + DHookPass_OCTOR = (1<<3), /**< Object has a constructor */ + DHookPass_OASSIGNOP = (1<<4), /**< Object has an assignment operator */ +}; + +enum DHookRegister +{ + // Don't change the register and use the default for the calling convention. + DHookRegister_Default, + + // 8-bit general purpose registers + DHookRegister_AL, + DHookRegister_CL, + DHookRegister_DL, + DHookRegister_BL, + DHookRegister_AH, + DHookRegister_CH, + DHookRegister_DH, + DHookRegister_BH, + + // 32-bit general purpose registers + DHookRegister_EAX, + DHookRegister_ECX, + DHookRegister_EDX, + DHookRegister_EBX, + DHookRegister_ESP, + DHookRegister_EBP, + DHookRegister_ESI, + DHookRegister_EDI, + + // 128-bit XMM registers + DHookRegister_XMM0, + DHookRegister_XMM1, + DHookRegister_XMM2, + DHookRegister_XMM3, + DHookRegister_XMM4, + DHookRegister_XMM5, + DHookRegister_XMM6, + DHookRegister_XMM7, + + // 80-bit FPU registers + DHookRegister_ST0 +}; + +typeset ListenCB +{ + // Deleted + function void (int entity); + + // Created + function void (int entity, const char[] classname); +}; + +typeset DHookRemovalCB +{ + function void (int hookid); +}; + +typeset DHookCallback +{ + // Function Example: void Ham::Test() with this pointer ignore + function MRESReturn (); + + // Function Example: void Ham::Test() with this pointer passed + function MRESReturn (int pThis); + + // Function Example: void Ham::Test(int cake) with this pointer ignore + function MRESReturn (DHookParam hParams); + + // Function Example: void Ham::Test(int cake) with this pointer passed + function MRESReturn (int pThis, DHookParam hParams); + + // Function Example: int Ham::Test() with this pointer ignore + function MRESReturn (DHookReturn hReturn); + + // Function Example: int Ham::Test() with this pointer passed + function MRESReturn (int pThis, DHookReturn hReturn); + + // Function Example: int Ham::Test(int cake) with this pointer ignore + function MRESReturn (DHookReturn hReturn, DHookParam hParams); + + // Function Example: int Ham::Test(int cake) with this pointer passed + function MRESReturn (int pThis, DHookReturn hReturn, DHookParam hParams); + + // Address NOW + + // Function Example: void Ham::Test() with this pointer passed + function MRESReturn (Address pThis); + + // Function Example: void Ham::Test(int cake) with this pointer passed + function MRESReturn (Address pThis, DHookParam hParams); + + // Function Example: int Ham::Test() with this pointer passed + function MRESReturn (Address pThis, DHookReturn hReturn); + + // Function Example: int Ham::Test(int cake) with this pointer passed + function MRESReturn (Address pThis, DHookReturn hReturn, DHookParam hParams); + +}; + +// Represents the parameters of the hooked function. +methodmap DHookParam < Handle +{ + // Get the value of a parameter. + // Use only for: int, entity, edict, bool or float parameter types. + // + // @param num Parameter number to get, starting at 1. Parameter number 0 returns + // the number of parameters. + // + // @return Value if num greater than 0. If 0 returns parameter count. + // If CBaseEntity returns entity index. + // @error Invalid handle, invalid param number or invalid param type. + public native any Get(int num); + + // Get the value of a vector parameter. + // Use only for: vector or vectorptr parameter types. + // + // @param num Parameter number to get, starting at 1. + // @param vec Vector buffer to store result. + // + // @error Invalid handle, invalid param number or invalid param type. + public native void GetVector(int num, float vec[3]); + + // Get the value of a string parameter. + // Use only for: string, stringptr or charptr parameter types. + // + // @param num Parameter number to get, starting at 1. + // @param buffer String buffer to store result. + // @param size Buffer size. + // + // @error Invalid handle, invalid param number or invalid param type. + public native void GetString(int num, char[] buffer, int size); + + // Set the value of a parameter. + // Use only for: int, entity, edict, bool or float parameter types. + // + // An entity parameter type can be set to NULL using INVALID_ENT_REFERENCE (-1). + // + // The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride + // is returned in the callback. + // + // @param num Parameter number to set starting at 1. + // @param value Value to set it as (only pass int, bool, float or entity index). + // + // @error Invalid handle, invalid param number or invalid param type. + public native void Set(int num, any value); + + // Set the value of a vector parameter. + // Use only for: vector or vectorptr parameter types. + // + // The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride + // is returned in the callback. + // + // @param num Parameter number to set, starting at 1. + // @param vec Value to set vector as. + // + // @error Invalid handle, invalid param number or invalid param type. + public native void SetVector(int num, const float vec[3]); + + // Set the value of a string parameter. + // Use only for: string, stringptr or charptr parameter types. + // + // The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride + // is returned in the callback. + // + // @param num Parameter number to set, starting at 1. + // @param value Value to set string as. + // + // @error Invalid handle, invalid param number or invalid param type. + public native void SetString(int num, const char[] value); + + // Gets an object's variable value. + // + // @param num Parameter number to get, starting at 1. + // @param offset Byte offset within the object to the var to get. + // @param type Type of var it is. + // + // @return Value of the objects var. If EHANDLE type or entity returns entity index. + // @error Invalid handle, invalid param number, invalid param type or invalid Object type. + public native any GetObjectVar(int num, int offset, ObjectValueType type); + + // Gets an object's vector variable value. + // + // @param num Parameter number to get, starting at 1. + // @param offset Byte offset within the object to the var to get. + // @param type Type of var it is. + // @param vec Buffer to store the result vector. + // + // @error Invalid handle, invalid param number, invalid param type or invalid Object type. + public native void GetObjectVarVector(int num, int offset, ObjectValueType type, float vec[3]); + + // Gets an object's string variable value. + // + // @param num Parameter number to get, starting at 1. + // @param offset Byte offset within the object to the var to get. + // @param type Type of var it is. + // @param buffer Buffer to store the result string. + // @param size Size of the buffer. + // + // @error Invalid handle, invalid param number, invalid param type or invalid Object type. + public native void GetObjectVarString(int num, int offset, ObjectValueType type, char[] buffer, int size); + + // Sets an object's variable value. + // + // The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride + // is returned in the callback. + // + // @param num Parameter number to set, starting at 1. + // @param offset Byte offset within the object to the var to set. + // @param type Type of var it is. + // @param value The value to set the var to. + // + // @error Invalid handle, invalid param number, invalid param type or invalid Object type. + public native void SetObjectVar(int num, int offset, ObjectValueType type, any value); + + // Sets an object's vector variable value. + // + // The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride + // is returned in the callback. + // + // @param num Parameter number to set, starting at 1. + // @param offset Byte offset within the object to the var to set. + // @param type Type of var it is. + // @param vec The value to set the vector var to. + // + // @error Invalid handle, invalid param number, invalid param type or invalid Object type. + public native void SetObjectVarVector(int num, int offset, ObjectValueType type, const float vec[3]); + + // No setter for object strings yet. Open an issue if you really need it. + + // Checks if a pointer parameter is null. + // + // @param num Parameter number to check, starting at 1. + // + // @return true if null, false otherwise. + // @error Non-pointer parameter. + public native bool IsNull(int num); + + // Get param address (Use only for ptr param types) + // + // @param num Param number to get. (Example if the function has 2 params and you need the value + // of the first param num would be 1.) + // + // @return Address of the parameter. + // @error Invalid handle. Invalid param number. Invalid param type. + public native Address GetAddress(int num); +}; + + +// Represents the return value of the hooked function. +methodmap DHookReturn < Handle +{ + // Retrieves or sets the return value. + // Use only for: int, entity, edict, bool or float return types. + // + // An entity return type can be set to NULL using INVALID_ENT_REFERENCE (-1). + // + // The return value is only readable in a post hook. + // The value is only applied when MRES_Override or MRES_Supercede is returned + // in the callback. + property any Value { + public native get(); + public native set(any value); + } + + // Get return vector value. + // Use only for: vector or vectorptr return types. + // + // Only useful in post hooks. + // + // @param vec Vector buffer to store result in. + // + // @error Invalid Handle or invalid type. + public native void GetVector(float vec[3]); + + // Get return string value. + // Use only for: string, stringptr or charptr return types. + // + // Only useful in post hooks. + // + // @param buffer String buffer to store result in. + // @param size String buffer size. + // + // @error Invalid Handle or invalid type. + public native void GetString(char[] buffer, int size); + + // Set return vector value. + // Use only for: vector or vectorptr return types. + // + // The value is only applied when MRES_Override or MRES_Supercede is returned + // in the callback. + // + // @param vec Value to set return vector to. + // + // @error Invalid Handle or invalid type. + public native void SetVector(const float vec[3]); + + // Set return string value. + // Use only for: string, stringptr or charptr return types. + // + // The value is only applied when MRES_Override or MRES_Supercede is returned + // in the callback. + // + // @param buffer Value to set return string to. + // + // @error Invalid Handle or invalid type. + public native void SetString(const char[] buffer); +}; + +// Base method map for common functions between virtual hooks and detours. +methodmap DHookSetup < Handle +{ + // Load address or offset for a vtable hook or detour from a gamedata file. + // + // @param gameconf GameData handle. + // @param source Whether to look in Offsets, Signatures, or Addresses. + // @param name Name of the property to find. + // + // @return true on success, false if nothing was found. + // @error Invalid setup or gamedata handle. + public native bool SetFromConf(Handle gameconf, SDKFuncConfSource source, const char[] name); + + // Adds a parameter to a hook setup. + // + // @param type Parameter type. + // @param size Used for Objects (not Object ptr) to define the size of the object. + // @param flag Used to change the pass type (ignored by detours). + // @param custom_register The register this argument is passed in instead of the stack (ignored by vhooks). + // + // @error Invalid setup handle or too many params added (request upping the max in thread). + public native void AddParam(HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal, DHookRegister custom_register=DHookRegister_Default); +}; + +// A DynamicHook allows to hook a virtual function on any C++ object. +// Currently CBaseEntity and CGameRules have a convenience API for easy entity hooking, +// but it's possible to provide a raw this-pointer to hook any object in memory too. +// +// Internally this intercepts function calls by replacing the function pointer +// in the virtual table of the object with our own function. +methodmap DynamicHook < DHookSetup +{ + // Creates a vtable hook. + // + // @param offset Virtual table offset of function to hook. + // @param hooktype Type of hook. + // @param returntype Type of return value. + // @param thistype Type of this pointer or ignore (ignore can be used if not needed). + // + // @error Failed to create hook setup handle or invalid callback function. + public native DynamicHook(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype); + + // Setup a vtable hook for a function as described in a "Functions" section in gamedata. + // The "Functions" section is parsed once the gamedata file is loaded and cached globally. + // + // @param gameconf GameData handle to use for address lookup. + // Doesn't have to be the same as the one with the "Functions" section. + // @param name Name of the function in a "Functions" section to load. + // + // @return Setup handle for the detour or null if offset wasn't found. + // @error Failed to create detour setup handle, invalid gamedata handle, + // invalid callback function or failed to find function in cached "Functions" sections. + public static native DynamicHook FromConf(Handle gameconf, const char[] name); + + // Hook an entity. + // + // Entity hooks are auto-removed when the entity is destroyed. + // If you need to read the return value of the function, choose a post hook. + // + // @param mode The desired hook mode - pre or post. + // A pre hook calls your callback BEFORE the original function is called. + // You can access the parameters, set the return value, and skip the original function. + // A post hook calls your callback AFTER the original function executed. + // You can access the parameters and get/set the return value. + // @param entity Entity index to hook on. + // @param callback Callback function. + // @param removalcb Optional callback for when the hook is removed. + // + // @return A hookid on success, INVALID_HOOK_ID otherwise. + // @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + public native int HookEntity(HookMode mode, int entity, DHookCallback callback, DHookRemovalCB removalcb=INVALID_FUNCTION); + + // Hook gamerules object. + // + // Game rules hooks are auto-removed on map end. + // If you need to read the return value of the function, choose a post hook. + // + // @param mode The desired hook mode - pre or post. + // A pre hook calls your callback BEFORE the original function is called. + // You can access the parameters, set the return value, and skip the original function. + // A post hook calls your callback AFTER the original function executed. + // You can access the parameters and get/set the return value. + // @param callback Callback function. + // @param removalcb Optional callback for when the hook is removed. + // + // @return A hookid on success, INVALID_HOOK_ID otherwise. + // @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + public native int HookGamerules(HookMode mode, DHookCallback callback, DHookRemovalCB removalcb=INVALID_FUNCTION); + + // Hook a raw this-pointer. + // If you need to read the return value of the function, choose a post hook. + // + // @param mode The desired hook mode - pre or post. + // A pre hook calls your callback BEFORE the original function is called. + // You can access the parameters, set the return value, and skip the original function. + // A post hook calls your callback AFTER the original function executed. + // You can access the parameters and get/set the return value. + // @param addr This pointer address. + // @param callback Callback function. + // + // @return A hookid on success, INVALID_HOOK_ID otherwise. + // @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + public native int HookRaw(HookMode mode, Address addr, DHookCallback callback); + + // Remove hook by hook id. + // + // @param hookid Hook id to remove. + // + // @return true on success, false otherwise + public static native bool RemoveHook(int hookid); +}; + +// A DynamicDetour is a way to hook and block any function in memory. +// Given the address of a function, it can call a callback in your script whenever +// the function gets called. The callback has access to all parameters of the function +// as well as the return value. +// +// Internally this works by replacing the first instructions of the function +// with a jump to our own code. This means that the signature used to find +// the function address in the first place might not match anymore after a detour. +// If you need to detour the same function in different plugins make sure to +// wildcard \x2a the first 6 bytes of the signature to accommodate for the patched +// jump introduced by the detour. +methodmap DynamicDetour < DHookSetup +{ + // Creates a detour. + // + // @param funcaddr The address of the function to detour. + // Can be Address_Null if you want to load the address from gamedata using DHookSetFromConf. + // @param callConv Calling convention of the function. + // @param returnType Type of the return value. + // @param thisType Type of this pointer or ignore (ignore can be used if not needed). + // Only used for thiscall detours. + // + // @error Failed to create detour setup handle. + public native DynamicDetour(Address funcaddr, CallingConvention callConv, ReturnType returntype, ThisPointerType thisType=ThisPointer_Ignore); + + // Setup a detour for a function as described in a "Functions" section in gamedata. + // The "Functions" section is parsed once the gamedata file is loaded and cached globally. + // + // @param gameconf GameData handle to use for address lookup. + // Doesn't have to be the same as the one with the "Functions" section. + // @param name Name of the function in a "Functions" section to load. + // + // @return Setup handle for the detour or null if offset wasn't found. + // @error Failed to create detour setup handle, invalid gamedata handle, + // invalid callback function or failed to find function in cached "Functions" sections. + public static native DynamicDetour FromConf(Handle gameconf, const char[] name); + + // Enable the detour of the function described in this detour setup. + // If you need to read the return value of the function, choose a post hook. + // + // @param mode The desired hook mode - pre or post. + // A pre hook calls your callback BEFORE the original function is called. + // You can access the parameters, set the return value, and skip the original function. + // A post hook calls your callback AFTER the original function executed. + // You can access the parameters and get/set the return value. + // @param callback Callback function. + // + // @return true if detour was enabled, false otherwise. + // @error Hook handle is not setup for a detour. + public native bool Enable(HookMode mode, DHookCallback callback); + + // Disable the detour of the function described in this detour setup. + // + // @param mode The hook mode to disable - pre or post. + // @param callback Callback function. + // + // @return true if detour was disabled, false otherwise. + // @error Hook handle is not setup for a detour or function is not detoured. + public native bool Disable(HookMode mode, DHookCallback callback); +}; + +/** + * Adds an entity listener hook + * + * @param type Type of listener to add + * @param callback Callback to use + */ +native void DHookAddEntityListener(ListenType type, ListenCB callback); + +/** + * Removes an entity listener hook + * + * @param type Type of listener to remove + * @param callback Callback this listener was using + * + * @return true if one was removed, false otherwise + */ +native bool DHookRemoveEntityListener(ListenType type, ListenCB callback); + +/** + * Creates a hook + * + * @param offset vtable offset of function to hook + * @param hooktype Type of hook + * @param returntype Type of return value + * @param thistype Type of this pointer or ignore (ignore can be used if not needed) + * @param callback Optional callback function, if not set here must be set when hooking. + * + * @return Returns setup handle for the hook. + * @error Failed to create hook setup handle or invalid callback function. + */ +native DynamicHook DHookCreate(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype, DHookCallback callback=INVALID_FUNCTION); + +/** + * Creates a detour + * + * @param funcaddr The address of the function to detour. + * Can be Address_Null if you want to load the address from gamedata using DHookSetFromConf. + * @param callConv Calling convention of the function. + * @param returnType Type of the return value. + * @param thisType Type of this pointer or ignore (ignore can be used if not needed) + * + * @return Setup handle for the detour. + * @error Failed to create detour setup handle. + */ +native DynamicDetour DHookCreateDetour(Address funcaddr, CallingConvention callConv, ReturnType returntype, ThisPointerType thisType); + +/** + * Setup a detour or hook for a function as described in a "Functions" section in gamedata. + * + * @param gameconf GameConfig handle + * @param name Name of the function in the gamedata to load. + * + * @return Setup handle for the detour or INVALID_HANDLE if offset/signature/address wasn't found. + * @error Failed to create detour setup handle, invalid gamedata handle, invalid callback function or + * failed to find function in gamedata. + */ +native DHookSetup DHookCreateFromConf(Handle gameconf, const char[] name); + +/** + * Load details for a vhook or detour from a gamedata file. + * + * @param setup Hook setup handle to set the offset or address on. + * @param gameconf GameConfig handle + * @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. + * @error Invalid setup or gamedata handle. + */ +native bool DHookSetFromConf(Handle setup, Handle gameconf, SDKFuncConfSource source, const char[] name); + +/** + * Enable the detour of the function described in the hook setup handle. + * + * @param setup Hook setup handle + * @param post true to make the hook a post hook. (If you need to change the return value or need the return + * value use a post hook! If you need to change params and return use a pre and post hook!) + * @param callback Callback function + * + * @return true if detour was enabled, false otherwise. + * @error Hook handle is not setup for a detour. + */ +native bool DHookEnableDetour(Handle setup, bool post, DHookCallback callback); + +/** + * Disable the detour of the function described in the hook setup handle. + * + * @param setup Hook setup handle + * @param post true to disable a post hook. + * @param callback Callback function + * + * @return true if detour was disabled, false otherwise. + * @error Hook handle is not setup for a detour or function is not detoured. + */ +native bool DHookDisableDetour(Handle setup, bool post, DHookCallback callback); + +/** + * Adds param to a hook setup + * + * @param setup Setup handle to add the param to. + * @param type Param type + * @param size Used for Objects (not Object ptr) to define the size of the object. + * @param flag Used to change the pass type. + * @param custom_register The register this argument is passed in instead of the stack. + * + * @error Invalid setup handle or too many params added (request upping the max in thread) + */ +native void DHookAddParam(Handle setup, HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal, DHookRegister custom_register=DHookRegister_Default); + +/** + * Hook entity + * + * @param setup Setup handle to use to add the hook. + * @param post true to make the hook a post hook. (If you need to change the return value or need the return + * value use a post hook! If you need to change params and return use a pre and post hook!) + * @param entity Entity index to hook on. + * @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and + * will call this callback) + * @param callback Optional callback function, if not set here must be set when creating the hook. + * + * @return INVALID_HOOK_ID on fail a hookid on success + * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + */ +native int DHookEntity(Handle setup, bool post, int entity, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION); + +/** + * Hook gamerules + * + * @param setup Setup handle to use to add the hook. + * @param post true to make the hook a post hook. (If you need to change the return value or need the return + * value use a post hook! If you need to change params and return use a pre and post hook!) + * @param removalcb Callback for when the hook is removed (Game rules hooks are auto-removed on map end and will + * call this callback) + * @param callback Optional callback function, if not set here must be set when creating the hook. + * + * @return INVALID_HOOK_ID on fail a hookid on success + * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + */ +native int DHookGamerules(Handle setup, bool post, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION); + +/** + * Hook a raw pointer + * + * @param setup Setup handle to use to add the hook. + * @param post true to make the hook a post hook. (If you need to change the return value or need the return + * alue use a post hook! If you need to change params and return use a pre and post hook!) + * @param addr This pointer address. + * @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and + * will call this callback) + * @param callback Optional callback function, if not set here must be set when creating the hook. + * + * @return INVALID_HOOK_ID on fail a hookid on success + * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + */ +native int DHookRaw(Handle setup, bool post, Address addr, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION); + +/** + * Remove hook by hook id + * + * @param hookid Hook id to remove + * + * @return true on success, false otherwise + */ +native bool DHookRemoveHookID(int hookid); + +/** + * Get param value (Use only for: int, entity, edict, bool or float param types) + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first + * param num would be 1. 0 Will return the number of params stored) + * + * @return value if num greater than 0. If 0 returns paramcount. + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native any DHookGetParam(Handle hParams, int num); + +/** + * Get vector param value + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first + * param num would be 1.) + * @param vec Vector buffer to store result. + * + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native void DHookGetParamVector(Handle hParams, int num, float vec[3]); + +/** + * Get string param value + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first + * param num would be 1.) + * @param buffer String buffer to store result + * @param size Buffer size + * + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native void DHookGetParamString(Handle hParams, int num, char[] buffer, int size); + +/** + * Set param value (Use only for: int, entity, edict, bool or float param types) + * + * An entity param type can be set to NULL using INVALID_ENT_REFERENCE (-1). + * + * @param hParams Handle to params structure + * @param num Param number to set (Example if the function has 2 params and you need to set the value of the + * first param num would be 1.) + * @param value Value to set it as (only pass int, bool, float or entity index) + * + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native void DHookSetParam(Handle hParams, int num, any value); + +/** + * Set vector param value + * + * @param hParams Handle to params structure + * @param num Param number to set (Example if the function has 2 params and you need to set the value of the + * first param num would be 1.) + * @param vec Value to set vector as. + * + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native void DHookSetParamVector(Handle hParams, int num, float vec[3]); + +/** + * Set string param value + * + * @param hParams Handle to params structure + * @param num Param number to set (Example if the function has 2 params and you need to set the value of the + * first param num would be 1.) + * @param value Value to set string as. + * + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native void DHookSetParamString(Handle hParams, int num, char[] value); + +/** + * Get return value (Use only for: int, entity, bool or float return types) + * + * @param hReturn Handle to return structure + * + * @error Invalid Handle, invalid type. + * @return Returns default value if prehook returns actual value if post hook. + */ +native any DHookGetReturn(Handle hReturn); + +/** + * Get return vector value + * + * @param hReturn Handle to return structure + * @param vec Vector buffer to store result in. (In pre hooks will be default value (0.0,0.0,0.0)) + * + * @error Invalid Handle, invalid type. + */ +native void DHookGetReturnVector(Handle hReturn, float vec[3]); + +/** + * Get return string value + * + * @param hReturn Handle to return structure + * @param buffer String buffer to store result in. (In pre hooks will be default value "") + * @param size String buffer size + * + * @error Invalid Handle, invalid type. + */ +native void DHookGetReturnString(Handle hReturn, char[] buffer, int size); + +/** + * Set return value (Use only for: int, entity, bool or float return types) + * + * An entity return type can be set to NULL using INVALID_ENT_REFERENCE (-1). + * + * @param hReturn Handle to return structure + * @param value Value to set return as + * + * @error Invalid Handle, invalid type. + */ +native void DHookSetReturn(Handle hReturn, any value); + +/** + * Set return vector value + * + * @param hReturn Handle to return structure + * @param vec Value to set return vector as + * + * @error Invalid Handle, invalid type. + */ +native void DHookSetReturnVector(Handle hReturn, float vec[3]); + +/** + * Set return string value + * + * @param hReturn Handle to return structure + * @param value Value to set return string as + * + * @error Invalid Handle, invalid type. + */ +native void DHookSetReturnString(Handle hReturn, char[] value); + +//WE SHOULD WRAP THESE AROUND STOCKS FOR NON PTR AS WE SUPPORT BOTH WITH THESE NATIVE'S + +/** + * Gets an objects variable value + * + * @param hParams Handle to params structure + * @param num Param number to get. + * @param offset Offset within the object to the var to get. + * @param type Type of var it is + * + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + * @return Value of the objects var. If EHANDLE type or entity returns entity index. + */ +native any DHookGetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type); + +/** + * Sets an objects variable value + * + * @param hParams Handle to params structure + * @param num Param number to set. + * @param offset Offset within the object to the var to set. + * @param type Type of var it is + * @param value The value to set the var to. + * + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + */ +native void DHookSetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type, any value); + +/** + * Gets an objects vector variable value + * + * @param hParams Handle to params structure + * @param num Param number to get. + * @param offset Offset within the object to the var to get. + * @param type Type of var it is + * @param buffer Buffer to store the result vector + * + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + */ +native void DHookGetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float buffer[3]); + +/** + * Sets an objects vector variable value + * + * @param hParams Handle to params structure + * @param num Param number to set. + * @param offset Offset within the object to the var to set. + * @param type Type of var it is + * @param value The value to set the vector var to. + * + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + */ +native void DHookSetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float value[3]); + +/** + * Gets an objects string variable value + * + * @param hParams Handle to params structure + * @param num Param number to get. + * @param offset Offset within the object to the var to get. + * @param type Type of var it is + * @param buffer Buffer to store the result vector + * @param size Size of the buffer + * + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + */ +native void DHookGetParamObjectPtrString(Handle hParams, int num, int offset, ObjectValueType type, char[] buffer, int size); + +/** + * Checks if a pointer param is null + * + * @param hParams Handle to params structure + * @param num Param number to check. + * + * @return true if null, false otherwise. + * @error Non pointer param + */ +native bool DHookIsNullParam(Handle hParams, int num); + +/** + * Get param address (Use only for ptr param types) + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first + * param num would be 1.) + * + * @return Address of the parameter. + * @error Invalid handle. Invalid param number. Invalid param type. + */ +native Address DHookGetParamAddress(Handle hParams, int num); + +public Extension __ext_dhooks = +{ + name = "dhooks", + file = "dhooks.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_dhooks_SetNTVOptional() +{ + MarkNativeAsOptional("DHookAddEntityListener"); + MarkNativeAsOptional("DHookRemoveEntityListener"); + MarkNativeAsOptional("DHookCreate"); + MarkNativeAsOptional("DHookCreateDetour"); + MarkNativeAsOptional("DHookCreateFromConf"); + MarkNativeAsOptional("DHookSetFromConf"); + MarkNativeAsOptional("DHookEnableDetour"); + MarkNativeAsOptional("DHookDisableDetour"); + MarkNativeAsOptional("DHookAddParam"); + MarkNativeAsOptional("DHookEntity"); + MarkNativeAsOptional("DHookGamerules"); + MarkNativeAsOptional("DHookRaw"); + MarkNativeAsOptional("DHookRemoveHookID"); + MarkNativeAsOptional("DHookGetParam"); + MarkNativeAsOptional("DHookGetParamVector"); + MarkNativeAsOptional("DHookGetParamString"); + MarkNativeAsOptional("DHookSetParam"); + MarkNativeAsOptional("DHookSetParamVector"); + MarkNativeAsOptional("DHookSetParamString"); + MarkNativeAsOptional("DHookGetReturn"); + MarkNativeAsOptional("DHookGetReturnVector"); + MarkNativeAsOptional("DHookGetReturnString"); + MarkNativeAsOptional("DHookSetReturn"); + MarkNativeAsOptional("DHookSetReturnVector"); + MarkNativeAsOptional("DHookSetReturnString"); + MarkNativeAsOptional("DHookGetParamObjectPtrVar"); + MarkNativeAsOptional("DHookSetParamObjectPtrVar"); + MarkNativeAsOptional("DHookGetParamObjectPtrVarVector"); + MarkNativeAsOptional("DHookSetParamObjectPtrVarVector"); + MarkNativeAsOptional("DHookIsNullParam"); + MarkNativeAsOptional("DHookGetParamObjectPtrString"); + MarkNativeAsOptional("DHookGetParamAddress"); + + MarkNativeAsOptional("DHookParam.IsNull"); + MarkNativeAsOptional("DHookParam.Get"); + MarkNativeAsOptional("DHookParam.GetVector"); + MarkNativeAsOptional("DHookParam.GetString"); + MarkNativeAsOptional("DHookParam.Set"); + MarkNativeAsOptional("DHookParam.SetVector"); + MarkNativeAsOptional("DHookParam.SetString"); + MarkNativeAsOptional("DHookParam.GetObjectVar"); + MarkNativeAsOptional("DHookParam.GetObjectVarVector"); + MarkNativeAsOptional("DHookParam.GetObjectVarString"); + MarkNativeAsOptional("DHookParam.SetObjectVar"); + MarkNativeAsOptional("DHookParam.SetObjectVarVector"); + MarkNativeAsOptional("DHookParam.GetAddress"); + MarkNativeAsOptional("DHookReturn.Value.get"); + MarkNativeAsOptional("DHookReturn.Value.set"); + MarkNativeAsOptional("DHookReturn.GetVector"); + MarkNativeAsOptional("DHookReturn.GetString"); + MarkNativeAsOptional("DHookReturn.SetVector"); + MarkNativeAsOptional("DHookReturn.SetString"); + MarkNativeAsOptional("DHookSetup.SetFromConf"); + MarkNativeAsOptional("DHookSetup.AddParam"); + MarkNativeAsOptional("DynamicHook.DynamicHook"); + MarkNativeAsOptional("DynamicHook.FromConf"); + MarkNativeAsOptional("DynamicHook.HookEntity"); + MarkNativeAsOptional("DynamicHook.HookGamerules"); + MarkNativeAsOptional("DynamicHook.HookRaw"); + MarkNativeAsOptional("DynamicHook.RemoveHook"); + MarkNativeAsOptional("DynamicDetour.DynamicDetour"); + MarkNativeAsOptional("DynamicDetour.FromConf"); + MarkNativeAsOptional("DynamicDetour.Enable"); + MarkNativeAsOptional("DynamicDetour.Disable"); +} +#endif diff --git a/source/sourcemod/scripting/include/distbugfix.inc b/source/sourcemod/scripting/include/distbugfix.inc new file mode 100644 index 0000000..6a7ed18 --- /dev/null +++ b/source/sourcemod/scripting/include/distbugfix.inc @@ -0,0 +1,261 @@ + +#if defined _distbug_included + #endinput +#endif +#define _distbug_included + +#define DISTBUG_CONFIG_NAME "distbugfix" + +#define CHAT_PREFIX "{d}[{l}GC{d}]" +#define CONSOLE_PREFIX "[GC]" +#define CHAT_SPACER " {d}|{g} " +#define DISTBUG_VERSION "2.0.0" + +#define MAX_STRAFES 32 +#define MAX_EDGE 32.0 +#define MAX_JUMP_FRAMES 150 // for frame based arrays +#define MAX_BHOP_FRAMES 8 + +#define MAX_COOKIE_SIZE 32 + +enum +{ + SETTINGS_DISTBUG_ENABLED = (1 << 0), + SETTINGS_SHOW_VEER_BEAM = (1 << 1), + SETTINGS_SHOW_JUMP_BEAM = (1 << 2), + SETTINGS_SHOW_HUD_GRAPH = (1 << 3), + SETTINGS_DISABLE_STRAFE_STATS = (1 << 4), + SETTINGS_DISABLE_STRAFE_GRAPH = (1 << 5), + SETTINGS_ADV_CHAT_STATS = (1 << 6), +} + +enum JumpType +{ + // unprintable jumptypes. only for tracking + JUMPTYPE_NONE, + + JUMPTYPE_LJ, // longjump + JUMPTYPE_WJ, // weirdjump + JUMPTYPE_LAJ, // ladderjump + JUMPTYPE_BH, // bunnyhop + JUMPTYPE_CBH, // crouched bunnyhop +}; + +enum JumpDir +{ + JUMPDIR_FORWARDS, + JUMPDIR_BACKWARDS, + JUMPDIR_LEFT, + JUMPDIR_RIGHT, +}; + +enum StrafeType +{ + STRAFETYPE_OVERLAP, // IN_MOVELEFT and IN_MOVERIGHT are overlapping and sidespeed is 0 + STRAFETYPE_NONE, // IN_MOVELEFT and IN_MOVERIGHT are both not pressed and sidespeed is 0 + + STRAFETYPE_LEFT, // only IN_MOVELEFT is down and sidespeed isn't 0. + STRAFETYPE_OVERLAP_LEFT, // IN_MOVELEFT and IN_MOVERIGHT are overlapping, but sidespeed is smaller than 0 (not 0) + STRAFETYPE_NONE_LEFT, // IN_MOVELEFT and IN_MOVERIGHT are both not pressed and sidespeed is smaller than 0 (not 0) + + STRAFETYPE_RIGHT, // only IN_MOVERIGHT is down and sidespeed isn't 0. + STRAFETYPE_OVERLAP_RIGHT, // IN_MOVELEFT and IN_MOVERIGHT are overlapping, but sidespeed is bigger than 0 (not 0) + STRAFETYPE_NONE_RIGHT, // IN_MOVELEFT and IN_MOVERIGHT are both not pressed and sidespeed is bigger than 0 (not 0) +}; + +enum JumpBeamColour +{ + JUMPBEAM_NEUTRAL, // speed stays the same + JUMPBEAM_LOSS, // speed loss + JUMPBEAM_GAIN, // speed gain + JUMPBEAM_DUCK, // duck key down +}; + +enum struct PlayerData +{ + int tickCount; + int buttons; + int lastButtons; + int flags; + int lastFlags; + int framesOnGround; + int framesInAir; + MoveType movetype; + MoveType lastMovetype; + float stamina; + float lastStamina; + float forwardmove; + float lastForwardmove; + float sidemove; + float lastSidemove; + float gravity; + float angles[3]; + float lastAngles[3]; + float position[3]; + float lastPosition[3]; + float velocity[3]; + float lastVelocity[3]; + float lastGroundPos[3]; // last position where the player left the ground. + float ladderNormal[3]; + bool lastGroundPosWalkedOff; + bool landedDucked; + + int prespeedFog; + float prespeedStamina; + + float jumpGroundZ; + float jumpPos[3]; + float jumpAngles[3]; + float landGroundZ; + float landPos[3]; + + int fwdReleaseFrame; + int jumpFrame; + bool trackingJump; + bool failedJump; + bool jumpGotFailstats; + + // jump data + JumpType jumpType; + JumpType lastJumpType; + JumpDir jumpDir; + float jumpDistance; + float jumpPrespeed; + float jumpMaxspeed; + float jumpVeer; + float jumpAirpath; + float jumpSync; + float jumpEdge; + float jumpLandEdge; + float jumpBlockDist; + float jumpHeight; + float jumpJumpoffAngle; + int jumpAirtime; + int jumpFwdRelease; + int jumpOverlap; + int jumpDeadair; + + // strafes! + int strafeCount; + float strafeSync[MAX_STRAFES]; + float strafeGain[MAX_STRAFES]; + float strafeLoss[MAX_STRAFES]; + float strafeMax[MAX_STRAFES]; + int strafeAirtime[MAX_STRAFES]; + int strafeOverlap[MAX_STRAFES]; + int strafeDeadair[MAX_STRAFES]; + float strafeAvgGain[MAX_STRAFES]; + + float strafeAvgEfficiency[MAX_STRAFES]; + int strafeAvgEfficiencyCount[MAX_STRAFES]; // how many samples are in strafeAvgEfficiency + float strafeMaxEfficiency[MAX_STRAFES]; + + StrafeType strafeGraph[MAX_JUMP_FRAMES]; + float mouseGraph[MAX_JUMP_FRAMES]; + float jumpBeamX[MAX_JUMP_FRAMES]; + float jumpBeamY[MAX_JUMP_FRAMES]; + JumpBeamColour jumpBeamColour[MAX_JUMP_FRAMES]; +} + +/** + * Check if player is overlapping their MOVERIGHT and MOVELEFT buttons. + * + * @param x Buttons; + * @return True if overlapping, false otherwise. + */ +stock bool IsOverlapping(int buttons, JumpDir jumpDir) +{ + if (jumpDir == JUMPDIR_FORWARDS || jumpDir == JUMPDIR_BACKWARDS) + { + return (buttons & IN_MOVERIGHT) && (buttons & IN_MOVELEFT); + } + // else if (jumpDir == JUMPDIR_LEFT || jumpDir == JUMPDIR_RIGHT) + return (buttons & IN_FORWARD) && (buttons & IN_BACK); +} + +/** + * Checks if the player is not holding down their MOVERIGHT and MOVELEFT buttons. + * + * @param x Buttons. + * @return True if they're not holding either, false otherwise. + */ +stock bool IsDeadAirtime(int buttons, JumpDir jumpDir) +{ + if (jumpDir == JUMPDIR_FORWARDS || jumpDir == JUMPDIR_BACKWARDS) + { + return (!(buttons & IN_MOVERIGHT) && !(buttons & IN_MOVELEFT)); + } + // else if (jumpDir == JUMPDIR_LEFT || jumpDir == JUMPDIR_RIGHT) + return (!(buttons & IN_FORWARD) && !(buttons & IN_BACK)); +} + +stock void ToggleCVar(ConVar cvar) +{ + cvar.BoolValue = !cvar.BoolValue; +} + +stock void GetRealLandingOrigin(float landGroundZ, const float origin[3], const float velocity[3], float result[3]) +{ + if ((origin[2] - landGroundZ) == 0.0) + { + result = origin; + return; + } + + // this is like this because it works + float frametime = GetTickInterval(); + float verticalDistance = origin[2] - (origin[2] + velocity[2] * frametime); + float fraction = (origin[2] - landGroundZ) / verticalDistance; + + float addDistance[3]; + addDistance = velocity; + ScaleVector(addDistance, frametime * fraction); + + AddVectors(origin, addDistance, result); +} + +stock int FloatSign(float value) +{ + if (value > 0.0) + { + return 1; + } + else if (value < 0.0) + { + return -1; + } + return 0; +} + +stock int FloatSign2(float value) +{ + if (value >= 0.0) + { + return 1; + } + // else if (value < 0.0) + return -1; +} + +stock void ShowPanel(int client, int duration, const char[] message) +{ + Event show_survival_respawn_status = CreateEvent("show_survival_respawn_status"); + if (show_survival_respawn_status == INVALID_HANDLE) + { + return; + } + + show_survival_respawn_status.SetString("loc_token", message); + show_survival_respawn_status.SetInt("duration", duration); + show_survival_respawn_status.SetInt("userid", -1); + + if (client == -1) + { + show_survival_respawn_status.Fire(); + } + else + { + show_survival_respawn_status.FireToClient(client); + show_survival_respawn_status.Cancel(); + } +} diff --git a/source/sourcemod/scripting/include/entity.inc b/source/sourcemod/scripting/include/entity.inc new file mode 100644 index 0000000..cb76e83 --- /dev/null +++ b/source/sourcemod/scripting/include/entity.inc @@ -0,0 +1,769 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2011 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). */ + PropField_Variant /**< Valid for Data fields only Type is not known at the field level, + (for this call), but dependent on current field value. */ +}; + +/** + * @endsection + */ + +/** + * Returns the maximum number of networked entities. + * + * Note: For legacy reasons, this only returns the maximum + * networked entities (maximum edicts), rather than total + * maximum entities. + * + * @return Maximum number of networked entities. + */ +native int GetMaxEntities(); + +/** + * Returns the number of networked entities in the server. + * + * Note: For legacy reasons, this only returns the current count + * of networked entities (current edicts), rather than total + * count of current entities. + * + * @return Number of entities in the server. + */ +native int GetEntityCount(); + +/** + * Returns whether or not an entity is valid. Returns false + * if there is no matching CBaseEntity for this entity index. + * + * @param entity Index of the entity. + * @return True if valid, false otherwise. + */ +native bool IsValidEntity(int entity); + +/** + * Returns whether or not an edict index is valid. + * + * @param edict Index of the edict. + * @return True if valid, false otherwise. + */ +native bool IsValidEdict(int edict); + +/** + * Returns whether or not an entity has a valid networkable edict. + * + * @param entity Index of the entity. + * @return True if networkable, false if invalid or not networkable. + */ +native bool IsEntNetworkable(int entity); + +/** + * Creates a new edict (the basis of a networkable entity) + * + * @return Index of the edict, 0 on failure. + */ +native int CreateEdict(); + +/** + * Removes an edict from the world. + * + * @param edict Index of the edict. + * @error Invalid edict index. + */ +native void RemoveEdict(int edict); + +/** + * Marks an entity for deletion. + * + * @param entity Index of the entity. + * @error Invalid entity index. + */ +native void RemoveEntity(int entity); + +/** + * 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 int GetEdictFlags(int 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. + * @error Invalid edict index. + */ +native void SetEdictFlags(int edict, int 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(int edict, char[] clsname, int 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 length of the buffer. + * @return True on success, false if the edict is not networkable. + * @error Invalid edict index. + */ +native bool GetEntityNetClass(int edict, char[] clsname, int 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 behavior 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. + * @error Invalid entity or offset out of bounds. + */ +native void ChangeEdictState(int edict, int 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 int GetEntData(int entity, int offset, int 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 value Value to set. + * @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. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void SetEntData(int entity, int offset, any value, int 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(int entity, int offset); + +/** + * Peeks into an entity's object data and sets the float value at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param value Value to set. + * @param changeState If true, change will be sent over the network. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void SetEntDataFloat(int entity, int 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. + * @deprecated Use GetEntDataEnt2() instead. + */ +#pragma deprecated Use GetEntDataEnt2() instead. +native int GetEntDataEnt(int entity, int 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, 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. + * @error Invalid entity or offset out of reasonable bounds. + * @deprecated Use SetEntDataEnt2() instead. + */ +#pragma deprecated Use SetEntDataEnt2() instead. +native void SetEntDataEnt(int entity, int offset, int 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 int GetEntDataEnt2(int entity, int 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. + * @error Invalid input entity, or offset out of reasonable bounds. + */ +native void SetEntDataEnt2(int entity, int offset, int 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. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void GetEntDataVector(int entity, int 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. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void SetEntDataVector(int entity, int 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 int GetEntDataString(int entity, int offset, char[] buffer, int 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 int SetEntDataString(int entity, int offset, const char[] buffer, int 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. + * @deprecated Use FindSendPropInfo instead, or HasEntProp if you just want to check for existence. + */ +#pragma deprecated Use FindSendPropInfo instead, or HasEntProp if you just want to check for existence. +native int FindSendPropOffs(const char[] cls, const char[] prop); + +/** + * Given a ServerClass name, finds a networkable send property offset. + * This information is cached for future calls. + * + * @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. + * @param array_size Optional parameter to store array size, 0 if not an array. + * @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 int FindSendPropInfo(const char[] cls, + const char[] prop, + PropFieldType &type=view_as(0), + int &num_bits=0, + int &local_offset=0, + int &array_size=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. + * @deprecated Use FindDataMapInfo instead, or HasEntProp if you just want to check for existence. + */ +#pragma deprecated Use FindDataMapInfo instead, or HasEntProp if you just want to check for existence. +native int FindDataMapOffs(int entity, + const char[] prop, + PropFieldType &type=view_as(0), + int &num_bits=0); + +/** + * Given an entity, finds a nested 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). + * @param local_offset Optional parameter to store the local offset, as + * FindDataMapOffs() would return. + * @return An offset, or -1 on failure. + */ +native int FindDataMapInfo(int entity, + const char[] prop, + PropFieldType &type=view_as(0), + int &num_bits=0, + int &local_offset=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 int GetEntSendPropOffs(int ent, const char[] prop, bool actual=false) +{ + char cls[64]; + + if (!GetEntityNetClass(ent, cls, sizeof(cls))) + { + return -1; + } + + int local = -1; + int offset = FindSendPropInfo(cls, prop, _, _, local); + + if (actual) + { + return offset; + } + + return local; +} + +/** + * Checks if an entity property exists on an entity. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @return Whether the property exists on the entity. + * @error Invalid entity. + */ +stock bool HasEntProp(int entity, PropType type, const char[] prop) +{ + if (type == Prop_Data) + { + return (FindDataMapInfo(entity, prop) != -1); + } + + if (type != Prop_Send) + { + return false; + } + + char cls[64]; + if (!GetEntityNetClass(entity, cls, sizeof(cls))) + { + return false; + } + + return (FindSendPropInfo(cls, prop) != -1); +} + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @return Value at the given property offset. + * @error Invalid entity or property not found. + */ +native int GetEntProp(int entity, PropType type, const char[] prop, int size=4, int element=0); + +/** + * 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 value Value to set. + * @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. + * @param element Element # (starting from 0) if property is an array. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void SetEntProp(int entity, PropType type, const char[] prop, any value, int size=4, int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @return Value at the given property offset. + * @error Invalid entity or offset out of reasonable bounds. + */ +native float GetEntPropFloat(int entity, PropType type, const char[] prop, int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void SetEntPropFloat(int entity, PropType type, const char[] prop, float value, int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @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 int GetEntPropEnt(int entity, PropType type, const char[] prop, int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @error Invalid entity or offset out of reasonable bounds. + */ +native void SetEntPropEnt(int entity, PropType type, const char[] prop, int other, int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @error Invalid entity, property not found, or property not + * actually a vector data type. + */ +native void GetEntPropVector(int entity, PropType type, const char[] prop, float vec[3], int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @error Invalid entity, property not found, or property not + * actually a vector data type. + */ +native void SetEntPropVector(int entity, PropType type, const char[] prop, const float vec[3], int element=0); + +/** + * 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. + * @param element Element # (starting from 0) if property is an array. + * @return Number of non-null bytes written. + * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string. + */ +native int GetEntPropString(int entity, PropType type, const char[] prop, char[] buffer, int maxlen, int element=0); + +/** + * Sets a network property as a string. + * + * @param entity Edict index. + * @param type Property type. + * @param prop Property to use. + * @param buffer String to set. + * @param element Element # (starting from 0) if property is an array. + * @return Number of non-null bytes written. + * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string. + */ +native int SetEntPropString(int entity, PropType type, const char[] prop, const char[] buffer, int element=0); + +/** + * Retrieves the count of values that an entity property's array can store. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @return Size of array (in elements) or 0 if property is not an array. + * @error Invalid entity or property not found. + */ +native int GetEntPropArraySize(int entity, PropType type, const char[] prop); + +/** + * 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). + * @error Invalid entity or offset out of reasonable bounds. + */ +stock void GetEntDataArray(int entity, int offset, any[] array, int arraySize, int dataSize=4) +{ + for (int i = 0; i < arraySize; i++) + { + array[i] = GetEntData(entity, offset + i*dataSize, dataSize); + } +} + +/** + * Copies an array of cells to an entity at a given offset. + * + * @param entity Entity index. + * @param offset Offset to use. + * @param array Array of values to copy. + * @param arraySize Number of values to copy. + * @param dataSize Size of each value in bytes (1, 2, or 4). + * @param changeState True to set the network state as changed; false otherwise. + * @error Invalid entity or offset out of reasonable bounds. + */ +stock void SetEntDataArray(int entity, int offset, const any[] array, int arraySize, int dataSize=4, bool changeState=false) +{ + for (int i = 0; i < arraySize; i++) + { + SetEntData(entity, offset + i*dataSize, array[i], dataSize, changeState); + } +} + +/** + * Gets the memory address of an entity. + * + * @param entity Entity index. + * @return Address of the entity. + * @error Invalid entity. + */ +native Address GetEntityAddress(int entity); + +/** + * Retrieves the classname of an entity. + * This is like GetEdictClassname(), except it works for ALL + * entities, not just edicts. + * + * @param entity 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. + */ +stock bool GetEntityClassname(int entity, char[] clsname, int maxlength) +{ + return !!GetEntPropString(entity, Prop_Data, "m_iClassname", clsname, maxlength); +} diff --git a/source/sourcemod/scripting/include/entity_prop_stocks.inc b/source/sourcemod/scripting/include/entity_prop_stocks.inc new file mode 100644 index 0000000..c0bc6ff --- /dev/null +++ b/source/sourcemod/scripting/include/entity_prop_stocks.inc @@ -0,0 +1,594 @@ +/** + * 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_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 */ +#define IN_ATTACK3 (1 << 25) + +// Note: these are only for use with GetEntityFlags and SetEntityFlags +// and may not match the game's actual, internal m_fFlags values. +// 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 */ +#define FL_FREEZING (1 << 31) /**< We're becoming frozen! */ +#define FL_EP2V_UNKNOWN1 (1 << 31) /**< Unknown */ +// END entity flag #defines + +/** + * Get an entity's flags. + * + * @note The game's actual flags are internally translated by SM + * to match the entity flags defined above as the actual values + * can differ per engine. + * + * @param entity Entity index. + * @return Entity's flags, see entity flag defines above. + * @error Invalid entity index, or lack of mod compliance. + */ +native int GetEntityFlags(int entity); + +/** + * Sets an entity's flags. + * + * @note The entity flags as defined above are internally translated by SM + * to match the current game's expected value for the flags as + * the actual values can differ per engine. + * + * @param entity Entity index. + * @param flags Entity flags, see entity flag defines above. + * @error Invalid entity index, or lack of mod compliance. + */ +native void SetEntityFlags(int entity, int flags); + + +/** + * 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(int entity) +{ + static bool gotconfig = false; + static char datamap[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_MoveType", datamap, sizeof(datamap)); + delete gc; + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_MoveType"); + } + + gotconfig = true; + } + + return view_as(GetEntProp(entity, Prop_Data, datamap)); +} + +/** + * Sets an entity's movetype. + * + * @param entity Entity index. + * @param mt Movetype, see enum above. + * @error Invalid entity index, or lack of mod compliance. + */ +stock void SetEntityMoveType(int entity, MoveType mt) +{ + static bool gotconfig = false; + static char datamap[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_MoveType", datamap, sizeof(datamap)); + delete 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(int entity) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_nRenderMode", prop, sizeof(prop)); + delete gc; + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderMode"); + } + + gotconfig = true; + } + + return view_as(GetEntProp(entity, Prop_Send, prop, 1)); +} + +/** + * Sets an entity's render mode. + * + * @param entity Entity index. + * @param mode RenderMode value. + * @error Invalid entity index, or lack of mod compliance. + */ +stock void SetEntityRenderMode(int entity, RenderMode mode) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_nRenderMode", prop, sizeof(prop)); + delete 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(int entity) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_nRenderFX", prop, sizeof(prop)); + delete gc; + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderFX"); + } + + gotconfig = true; + } + + return view_as(GetEntProp(entity, Prop_Send, prop, 1)); +} + +/** + * Sets an entity's render Fx. + * + * @param entity Entity index. + * @param fx RenderFx value. + * @error Invalid entity index, or lack of mod compliance. + */ +stock void SetEntityRenderFx(int entity, RenderFx fx) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_nRenderFX", prop, sizeof(prop)); + delete gc; + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderFX"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Send, prop, fx, 1); +} + +/** + * Gets 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) + * @error Invalid entity index, or lack of mod compliance. + */ +stock void GetEntityRenderColor(int entity, int &r, int &g, int &b, int &a) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_clrRender", prop, sizeof(prop)); + delete gc; + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + int offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) + { + ThrowError("GetEntityRenderColor not supported by this mod"); + } + + r = GetEntData(entity, offset, 1); + g = GetEntData(entity, offset + 1, 1); + b = GetEntData(entity, offset + 2, 1); + a = GetEntData(entity, offset + 3, 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) + * @error Invalid entity index, or lack of mod compliance. + */ +stock void SetEntityRenderColor(int entity, int r=255, int g=255, int b=255, int a=255) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_clrRender", prop, sizeof(prop)); + delete gc; + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + int 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(int entity) +{ + static bool gotconfig = false; + static char datamap[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_flGravity", datamap, sizeof(datamap)); + delete 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). + * @error Invalid entity index, or lack of mod compliance. + */ +stock void SetEntityGravity(int entity, float amount) +{ + static bool gotconfig = false; + static char datamap[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_flGravity", datamap, sizeof(datamap)); + delete 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. + * @error Invalid entity index, or lack of mod compliance. + */ +stock void SetEntityHealth(int entity, int amount) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_iHealth", prop, sizeof(prop)); + delete gc; + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_iHealth"); + } + + gotconfig = true; + } + + char cls[64]; + PropFieldType type; + int 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 int GetClientButtons(int client) +{ + static bool gotconfig = false; + static char datamap[32]; + + if (!gotconfig) + { + GameData gc = new GameData("core.games"); + bool exists = gc.GetKeyValue("m_nButtons", datamap, sizeof(datamap)); + delete gc; + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_nButtons"); + } + + gotconfig = true; + } + + return GetEntProp(client, Prop_Data, datamap); +} diff --git a/source/sourcemod/scripting/include/entitylump.inc b/source/sourcemod/scripting/include/entitylump.inc new file mode 100644 index 0000000..9d269e6 --- /dev/null +++ b/source/sourcemod/scripting/include/entitylump.inc @@ -0,0 +1,157 @@ +#if defined _entitylump_included + #endinput +#endif + +#define _entitylump_included + +/** + * An ordered list of key / value pairs for a map entity. + * If the entry in the EntityLump is removed, the handle will error on all operations. + * (The handle will remain valid on the scripting side, and will still need to be deleted.) + * + * Write operations (update, insert, erase, append) are only allowed during OnMapInit. + */ +methodmap EntityLumpEntry < Handle { + /** + * Copies the key / value at the given index into buffers. + * + * @param index Position, starting from 0. + * @param keybuf Key name buffer. + * @param keylen Maximum length of the key name buffer. + * @param valbuf Value buffer. + * @param vallen Maximum length of the value buffer. + * @error Index is out of bounds. + */ + public native void Get(int index, char[] keybuf = "", int keylen = 0, char[] valbuf = "", int vallen = 0); + + /** + * Updates the key / value pair at the given index. + * + * @param index Position, starting from 0. + * @param key New key name, or NULL_STRING to preserve the existing key name. + * @param value New value, or NULL_STRING to preserve the existing value. + * @error Index is out of bounds or entity lump is read-only. + */ + public native void Update(int index, const char[] key = NULL_STRING, const char[] value = NULL_STRING); + + /** + * Inserts a new key / value pair at the given index, shifting the pair at that index and beyond up. + * If EntityLumpEntry.Length is passed in, this is an append operation. + * + * @param index Position, starting from 0. + * @param key New key name. + * @param value New value. + * @error Index is out of bounds or entity lump is read-only. + */ + public native void Insert(int index, const char[] key, const char[] value); + + /** + * Removes the key / value pair at the given index, shifting all entries past it down. + * + * @param index Position, starting from 0. + * @error Index is out of bounds or entity lump is read-only. + */ + public native void Erase(int index); + + /** + * Inserts a new key / value pair at the end of the entry's list. + * + * @param key New key name. + * @param value New value. + * @error Index is out of bounds or entity lump is read-only. + */ + public native void Append(const char[] key, const char[] value); + + /** + * Searches the entry list for an index matching a key starting from a position. + * + * @param key Key name to search. + * @param start A position after which to begin searching from. Use -1 to start from the + * first entry. + * @return Position after start with an entry matching the given key, or -1 if no + * match was found. + * @error Invalid start position; must be a value between -1 and one less than the + * length of the entry. + */ + public native int FindKey(const char[] key, int start = -1); + + /** + * Searches the entry list for an index matching a key starting from a position. + * This also copies the value from that index into the given buffer. + * + * This can be used to find the first / only value matching a key, or to iterate over all + * the values that match said key. + * + * @param key Key name to search. + * @param buffer Value buffer. This will contain the result of the next match, or empty + * if no match was found. + * @param maxlen Maximum length of the value buffer. + * @param start An index after which to begin searching from. Use -1 to start from the + * first entry. + * @return Position after start with an entry matching the given key, or -1 if no + * match was found. + * @error Invalid start position; must be a value between -1 and one less than the + * length of the entry. + */ + public int GetNextKey(const char[] key, char[] buffer, int maxlen, int start = -1) { + int result = this.FindKey(key, start); + if (result != -1) { + this.Get(result, .valbuf = buffer, .vallen = maxlen); + } else { + buffer[0] = '\0'; + } + return result; + } + + /** + * Retrieves the number of key / value pairs in the entry. + */ + property int Length { + public native get(); + } +}; + +/** + * A group of natives for a singleton entity lump, representing all the entities defined in the map. + * + * Write operations (insert, erase, append) are only allowed during OnMapInit. + */ +methodmap EntityLump { + /** + * Returns the EntityLumpEntry at the given index. + * This handle should be freed by the calling plugin. + * + * @param index Position, starting from 0. + * @error Index is out of bounds. + */ + public static native EntityLumpEntry Get(int index); + + /** + * Erases an EntityLumpEntry at the given index, shifting all entries past it down. + * Any handles referencing the erased EntityLumpEntry will throw on any operations aside from delete. + * + * @param index Position, starting from 0. + * @error Index is out of bounds or entity lump is read-only. + */ + public static native void Erase(int index); + + /** + * Inserts an empty EntityLumpEntry at the given index, shifting the existing entry and ones past it up. + * + * @param index Position, starting from 0. + * @error Index is out of bounds or entity lump is read-only. + */ + public static native void Insert(int index); + + /** + * Creates an empty EntityLumpEntry, returning its index. + * + * @error Entity lump is read-only. + */ + public static native int Append(); + + /** + * Returns the number of entities currently in the lump. + */ + public static native int Length(); +}; diff --git a/source/sourcemod/scripting/include/events.inc b/source/sourcemod/scripting/include/events.inc new file mode 100644 index 0000000..6bba666 --- /dev/null +++ b/source/sourcemod/scripting/include/events.inc @@ -0,0 +1,343 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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. + */ +typeset 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. + // May not correspond to the real value. Use the property BroadcastDisabled. + // @return Ignored for post hooks. Plugin_Handled will block event if hooked as pre. + /// + function Action (Event event, const char[] 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. + /// + function void (Event event, const char[] name, bool dontBroadcast); +}; + +methodmap Event < Handle +{ + // Fires a game event. + // + // This function closes the event Handle after completing. + // + // @param dontBroadcast Optional boolean that determines if event should be broadcast to clients. + public native void Fire(bool dontBroadcast=false); + + // Fires a game event to only the specified client. + // + // Unlike Fire, this function DOES NOT close the event Handle. + // + // @param client Index of client to receive the event.. + public native void FireToClient(int client); + + // Cancels a previously created game event that has not been fired. This + // is necessary to avoid leaking memory when an event isn't fired. + public native void Cancel(); + + // Returns the boolean value of a game event's key. + // + // @param key Name of event key. + // @param defValue Optional default value to use if the key is not found. + // @return The boolean value of the specified event key. + public native bool GetBool(const char[] key, bool defValue=false); + + // Sets the boolean value of a game event's key. + // + // @param key Name of event key. + // @param value New boolean value. + public native void SetBool(const char[] key, bool value); + + // Returns the integer value of a game event's key. + // + // @param key Name of event key. + // @param defValue Optional default value to use if the key is not found. + // @return The integer value of the specified event key. + public native int GetInt(const char[] key, int defValue=0); + + // 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 key Name of event key. + // @param value New integer value. + public native void SetInt(const char[] key, int value); + + // Returns the floating point value of a game event's key. + // + // @param key Name of event key. + // @param defValue Optional default value to use if the key is not found. + // @return The floating point value of the specified event key. + public native float GetFloat(const char[] key, float defValue=0.0); + + // Sets the floating point value of a game event's key. + // + // @param key Name of event key. + // @param value New floating point value. + public native void SetFloat(const char[] key, float value); + + // Retrieves the string value of a game event's key. + // + // @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. + // @param defValue Optional default value to use if the key is not found. + public native void GetString(const char[] key, char[] value, int maxlength, const char[] defvalue=""); + + // Sets the string value of a game event's key. + // + // @param key Name of event key. + // @param value New string value. + public native void SetString(const char[] key, const char[] value); + + // Retrieves the name of a game event. + // + // @param name Buffer to store the name of the event. + // @param maxlength Maximum length of string buffer. + public native void GetName(char[] name, int 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. + property bool BroadcastDisabled { + public native set(bool dontBroadcast); + public native get(); + } +} + +/** + * 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. + * @error Invalid event name or invalid callback function. + */ +native void HookEvent(const char[] 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 char[] 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. + * @error Invalid callback function or no active hook for specified event. + */ +native void UnhookEvent(const char[] 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 + * event.Fire() or event.Cancel(). + * + * @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 Event CreateEvent(const char[] 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. + * @error Invalid or corrupt Handle. + */ +native void FireEvent(Handle event, bool dontBroadcast=false); + +/** + * Cancels a previously created game event that has not been fired. + * + * @param event Handled to the event. + * @error Invalid or corrupt Handle. + */ +native void 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. + * @param defValue Optional default value to use if the key is not found. + * @return The boolean value of the specified event key. + * @error Invalid or corrupt Handle. + */ +native bool GetEventBool(Handle event, const char[] key, bool defValue=false); + +/** + * 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. + * @error Invalid or corrupt Handle. + */ +native void SetEventBool(Handle event, const char[] 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. + * @param defValue Optional default value to use if the key is not found. + * @return The integer value of the specified event key. + * @error Invalid or corrupt Handle. + */ +native int GetEventInt(Handle event, const char[] key, int defValue=0); + +/** + * 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. + * @error Invalid or corrupt Handle. + */ +native void SetEventInt(Handle event, const char[] key, int value); + +/** + * Returns the floating point value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @param defValue Optional default value to use if the key is not found. + * @return The floating point value of the specified event key. + * @error Invalid or corrupt Handle. + */ +native float GetEventFloat(Handle event, const char[] key, float defValue=0.0); + +/** + * 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. + * @error Invalid or corrupt Handle. + */ +native void SetEventFloat(Handle event, const char[] 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. + * @param defValue Optional default value to use if the key is not found. + * @error Invalid or corrupt Handle. + */ +native void GetEventString(Handle event, const char[] key, char[] value, int maxlength, const char[] defvalue=""); + +/** + * 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. + * @error Invalid or corrupt Handle. + */ +native void SetEventString(Handle event, const char[] key, const char[] value); + +/** + * Retrieves the name of a game event. + * + * @param event Handle to the event. + * @param name Buffer to store the name of the event. + * @param maxlength Maximum length of string buffer. + * @error Invalid or corrupt Handle. + */ +native void GetEventName(Handle event, char[] name, int 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. + * @error Invalid Handle. + */ +native void SetEventBroadcast(Handle event, bool dontBroadcast); diff --git a/source/sourcemod/scripting/include/files.inc b/source/sourcemod/scripting/include/files.inc new file mode 100644 index 0000000..e265e9e --- /dev/null +++ b/source/sourcemod/scripting/include/files.inc @@ -0,0 +1,628 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 */ +}; + +// A DirectoryListing iterates over the contents of a directory. To obtain a +// DirectoryListing handle, call OpenDirectory(). +methodmap DirectoryListing < Handle +{ + // Reads the current directory entry as a local filename, then moves to the + // next file. + // + // Note: Both the '.' and '..' automatic directory entries will be retrieved. + // + // @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. + public native bool GetNext(char[] buffer, int maxlength, FileType &type=FileType_Unknown); +}; + +// A File object can be obtained by calling OpenFile(). File objects should be +// closed with delete or Close(). Note that, "delete file" does not +// actually delete the file, it just closes the handle. +methodmap File < Handle +{ + // Close the file handle. This is the same as using CloseHandle() or delete. + public void Close() { + CloseHandle(this); + } + + // Reads a line of text from a file. + // + // @param buffer String buffer to hold the line. + // @param maxlength Maximum size of string buffer. + // @return True on success, false otherwise. + public native bool ReadLine(char[] buffer, int maxlength); + + // Reads binary data from a 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. + public native int Read(any[] items, int num_items, int size); + + // Reads a UTF8 or ANSI string from a 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 read_count > max_size. + public native int ReadString(char[] buffer, int max_size, int read_count=-1); + + // Writes binary data to a 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. + public native bool Write(const any[] items, int num_items, int size); + + // Writes a binary string to a file. + // + // @param buffer String to write. + // @param term True to append NUL terminator, false otherwise. + // @return True on success, false on error. + public native bool WriteString(const char[] 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. + public native bool WriteLine(const char[] format, any ...); + + // Reads a single int8 (byte) from a file. The returned value is sign- + // extended to an int32. + // + // @param data Variable to store the data read. + // @return True on success, false on failure. + public native bool ReadInt8(int &data); + + // Reads a single uint8 (unsigned byte) from a file. The returned value is + // zero-extended to an int32. + // + // @param data Variable to store the data read. + // @return True on success, false on failure. + public native bool ReadUint8(int &data); + + // Reads a single int16 (short) from a file. The value is sign-extended to + // an int32. + // + // @param data Variable to store the data read. + // @return True on success, false on failure. + public native bool ReadInt16(int &data); + + // Reads a single unt16 (unsigned short) from a file. The value is zero- + // extended to an int32. + // + // @param data Variable to store the data read. + // @return True on success, false on failure. + public native bool ReadUint16(int &data); + + // Reads a single int32 (int/cell) from a file. + // + // @param data Variable to store the data read. + // @return True on success, false on failure. + public native bool ReadInt32(int &data); + + // Writes a single int8 (byte) to a file. + // + // @param data Data to write (truncated to an int8). + // @return True on success, false on failure. + public native bool WriteInt8(int data); + + // Writes a single int16 (short) to a file. + // + // @param data Data to write (truncated to an int16). + // @return True on success, false on failure. + public native bool WriteInt16(int data); + + // Writes a single int32 (int/cell) to a file. + // + // @param data Data to write. + // @return True on success, false on failure. + public native bool WriteInt32(int data); + + // Tests if the end of file has been reached. + // + // @return True if end of file has been reached, false otherwise. + public native bool EndOfFile(); + + // Sets the file position indicator. + // + // @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. + public native bool Seek(int position, int where); + + // Flushes a file's buffered output; any buffered output + // is immediately written to the file. + // + // @return True on success or use_valve_fs specified with OpenFile, + // otherwise false on failure. + public native bool Flush(); + + // Get the current position in the file; returns -1 on failure. + property int Position { + public native get(); + } +} + +/** + * 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 int BuildPath(PathType type, char[] buffer, int maxlength, const char[] fmt, any ...); + +/** + * Opens a directory/folder for contents enumeration. + * + * @note Directories are closed with CloseHandle() or delete. + * @note Directories Handles can be cloned. + * @note OpenDirectory() supports the "file://" notation. + * + * @param path Path to open. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in any of + * the Valve search paths, rather than solely files + * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return A Handle to the directory, null on error. + */ +native DirectoryListing OpenDirectory(const char[] path, bool use_valve_fs=false, const char[] valve_path_id="GAME"); + +/** + * 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, char[] buffer, int maxlength, FileType &type=FileType_Unknown); + +/** + * Opens or creates a file, returning a File handle on success. File handles + * should be closed with delete or CloseHandle(). + * + * The open mode may be one of the following strings: + * "r": Open an existing file for reading. + * "w": Create a file for writing, or truncate (delete the contents of) an + * existing file and then open it for writing. + * "a": Create a file for writing, or open an existing file such that writes + * will be appended to the end. + * "r+": Open an existing file for both reading and writing. + * "w+": Create a file for reading and writing, or truncate an existing file + * and then open it for reading and writing. + * "a+": Create a file for both reading and writing, or open an existing file + * such that writes will be appended to the end. + * + * The open mode may also contain an additional character after "r", "w", or "a", + * but before any "+" sign. This character may be "b" (indicating binary mode) or + * "t" (indicating text mode). By default, "text" mode is implied. On Linux and + * Mac, this has no distinction from binary mode. On Windows, it causes the '\n' + * character (0xA) to be written as "\r\n" (0xD, 0xA). + * + * Example: "rb" opens a binary file for reading; "at" opens a text file for + * appending. + * + * @param file File to open. + * @param mode Open mode. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in valve + * search paths, rather than solely files existing directly + * in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return A File handle, or null if the file could not be opened. + */ +native File OpenFile(const char[] file, const char[] mode, bool use_valve_fs=false, const char[] valve_path_id="GAME"); + +/** + * Deletes a file. + * + * @param path Path of the file to delete. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to delete files existing in the Valve + * search path, rather than solely files existing directly + * in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return True on success, false on failure or if file not immediately removed. + */ +native bool DeleteFile(const char[] path, bool use_valve_fs=false, const char[] valve_path_id="DEFAULT_WRITE_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, char[] buffer, int 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 int ReadFile(Handle hndl, any[] items, int num_items, int 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 int ReadFileString(Handle hndl, char[] buffer, int max_size, int 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 any[] items, int num_items, int size); + +/** + * Writes a binary string to a file. + * + * @param hndl Handle to the file. + * @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 char[] 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 char[] 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 int ReadFileCell(Handle hndl, int &data, int size) +{ + int ret; + int array[1]; + + 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, int data, int size) +{ + int 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, int position, int where); + +/** + * Get current position in the file. + * + * @param file Handle to the file. + * @return Value for the file position indicator. + * @error Invalid Handle. + */ +native int 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 find files existing in any of + * the Valve search paths, rather than solely files + * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return True if the file exists, false otherwise. + */ +native bool FileExists(const char[] path, bool use_valve_fs=false, const char[] valve_path_id="GAME"); + +/** + * Renames a file. + * + * @param newpath New path to the file. + * @param oldpath Path to the existing file. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to rename files in the game's + * Valve search paths, rather than directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return True on success or use_valve_fs specified, false otherwise. + */ +native bool RenameFile(const char[] newpath, const char[] oldpath, bool use_valve_fs=false, const char[] valve_path_id="DEFAULT_WRITE_PATH"); + +/** + * Checks if a directory exists. + * + * @param path Path to the directory. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in any of + * the Valve search paths, rather than solely files + * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return True if the directory exists, false otherwise. + */ +native bool DirExists(const char[] path, bool use_valve_fs=false, const char[] valve_path_id="GAME"); + +/** + * Get the file size in bytes. + * + * @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 find files existing in any of + * the Valve search paths, rather than solely files + * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. + * @return File size in bytes, -1 if file not found. + */ +native int FileSize(const char[] path, bool use_valve_fs=false, const char[] valve_path_id="GAME"); + +/** + * 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 or use_valve_fs specified with OpenFile, + * otherwise false on failure. + */ +native bool 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 char[] 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. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to create folders in the game's + * Valve search paths, rather than directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default. + * In this case, mode is ignored. + * @return True on success, false otherwise. + */ +native bool CreateDirectory(const char[] path, int mode, bool use_valve_fs=false, const char[] valve_path_id="DEFAULT_WRITE_PATH"); + +/** + * Changes a file or directories permissions. + * + * @param path Path to the file. + * @param mode Permissions to set. + * @return True on success, false otherwise. + */ +native bool SetFilePermissions(const char[] path, int 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 int GetFileTime(const char[] 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. + * @error Invalid Handle. + */ +native void LogToOpenFile(Handle hndl, const char[] 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. + * @error Invalid Handle. + */ +native void LogToOpenFileEx(Handle hndl, const char[] message, any ...); diff --git a/source/sourcemod/scripting/include/float.inc b/source/sourcemod/scripting/include/float.inc new file mode 100644 index 0000000..0106827 --- /dev/null +++ b/source/sourcemod/scripting/include/float.inc @@ -0,0 +1,460 @@ +/** + * 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 + +#if !defined __sourcepawn2__ +/** + * Converts an integer into a floating point value. + * + * @param value Integer to convert. + * @return Floating point value. + */ +native float float(int value); +#endif + +/** + * Multiplies two floats together. + * + * Note: This native is internal implementation. For multiplication use the '*' operator. + * + * @param oper1 First value. + * @param oper2 Second value. + * @return oper1*oper2. + * @deprecated This native is internal implementation. For multiplication use the '*' operator. + */ +#pragma deprecated This native is internal implementation. For multiplication use the '*' operator. +native float FloatMul(float oper1, float oper2); + +/** + * Divides the dividend by the divisor. + * + * Note: This native is internal implementation. For division use the '/' operator. + * + * @param dividend First value. + * @param divisor Second value. + * @return dividend/divisor. + * @deprecated This native is internal implementation. For division use the '/' operator. + */ +#pragma deprecated This native is internal implementation. For division use the '/' operator. +native float FloatDiv(float dividend, float divisor); + +/** + * Adds two floats together. + * + * Note: This native is internal implementation. For addition use the '+' operator. + * + * @param oper1 First value. + * @param oper2 Second value. + * @return oper1+oper2. + * @deprecated This native is internal implementation. For addition use the '+' operator. + */ +#pragma deprecated This native is internal implementation. For addition use the '+' operator. +native float FloatAdd(float oper1, float oper2); + +/** + * Subtracts oper2 from oper1. + * + * Note: This native is internal implementation. For subtraction use the '-' operator. + * + * @param oper1 First value. + * @param oper2 Second value. + * @return oper1-oper2. + * @deprecated This native is internal implementation. For subtraction use the '-' operator. + */ +#pragma deprecated This native is internal implementation. For subtraction use the '-' operator. +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 int RoundToZero(float value); + +/** + * Rounds a float to the next highest integer value. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native int RoundToCeil(float value); + +/** + * Rounds a float to the next lowest integer value. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native int RoundToFloor(float value); + +/** + * Standard IEEE rounding. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native int 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 int 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 int RoundFloat(float value) +{ + return RoundToNearest(value); +} + +/** + * User defined operators. + */ +#if !defined __sourcepawn2__ +#pragma rational Float + +// Internal aliases for backwards compatibility. +native float __FLOAT_MUL__(float a, float b) = FloatMul; +native float __FLOAT_DIV__(float a, float b) = FloatDiv; +native float __FLOAT_ADD__(float a, float b) = FloatAdd; +native float __FLOAT_SUB__(float a, float b) = FloatSub; + +native bool __FLOAT_GT__(float a, float b); +native bool __FLOAT_GE__(float a, float b); +native bool __FLOAT_LT__(float a, float b); +native bool __FLOAT_LE__(float a, float b); +native bool __FLOAT_EQ__(float a, float b); +native bool __FLOAT_NE__(float a, float b); +native bool __FLOAT_NOT__(float a); + +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; +native bool operator!(float oper1) = __FLOAT_NOT__; +native bool operator>(float oper1, float oper2) = __FLOAT_GT__; +native bool operator>=(float oper1, float oper2) = __FLOAT_GE__; +native bool operator<(float oper1, float oper2) = __FLOAT_LT__; +native bool operator<=(float oper1, float oper2) = __FLOAT_LE__; +native bool operator!=(float oper1, float oper2) = __FLOAT_NE__; +native bool operator==(float oper1, float oper2) = __FLOAT_EQ__; + +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^view_as(cellmin); /* IEEE values are sign/magnitude */ +} + +// The stocks below are int->float converting versions of the above natives. + +stock float operator*(float oper1, int oper2) +{ + return __FLOAT_MUL__(oper1, float(oper2)); /* "*" is commutative */ +} + +stock float operator/(float oper1, int oper2) +{ + return __FLOAT_DIV__(oper1, float(oper2)); +} + +stock float operator/(int oper1, float oper2) +{ + return __FLOAT_DIV__(float(oper1), oper2); +} + +stock float operator+(float oper1, int oper2) +{ + return __FLOAT_ADD__(oper1, float(oper2)); /* "+" is commutative */ +} + +stock float operator-(float oper1, int oper2) +{ + return __FLOAT_SUB__(oper1, float(oper2)); +} + +stock float operator-(int oper1, float oper2) +{ + return __FLOAT_SUB__(float(oper1), oper2); +} + +stock bool operator==(float oper1, int oper2) +{ + return __FLOAT_EQ__(oper1, float(oper2)); +} + +stock bool operator!=(float oper1, int oper2) +{ + return __FLOAT_NE__(oper1, float(oper2)); +} + +stock bool operator>(float oper1, int oper2) +{ + return __FLOAT_GT__(oper1, float(oper2)); +} + +stock bool operator>(int oper1, float oper2) +{ + return __FLOAT_GT__(float(oper1), oper2); +} + +stock bool operator>=(float oper1, int oper2) +{ + return __FLOAT_GE__(oper1, float(oper2)); +} + +stock bool operator>=(int oper1, float oper2) +{ + return __FLOAT_GE__(float(oper1), oper2); +} + +stock bool operator<(float oper1, int oper2) +{ + return __FLOAT_LT__(oper1, float(oper2)); +} + +stock bool operator<(int oper1, float oper2) +{ + return __FLOAT_LT__(float(oper1), oper2); +} + +stock bool operator<=(float oper1, int oper2) +{ + return __FLOAT_LE__(oper1, float(oper2)); +} + +stock bool operator<=(int oper1, float oper2) +{ + return __FLOAT_LE__(float(oper1), oper2); +} + +/** + * Forbidden operators. + */ +forward operator%(float oper1, float oper2); +forward operator%(float oper1, int oper2); +forward operator%(int oper1, float oper2); +#endif // __sourcepawn2__ + +#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 radians to degrees. + * + * @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 int 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. + */ +native void SetURandomSeed(const int[] seeds, int 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. + */ +stock void SetURandomSeedSimple(int seed) +{ + int seeds[1]; + seeds[0] = seed; + SetURandomSeed(seeds, 1); +} diff --git a/source/sourcemod/scripting/include/functions.inc b/source/sourcemod/scripting/include/functions.inc new file mode 100644 index 0000000..402ed8c --- /dev/null +++ b/source/sourcemod/scripting/include/functions.inc @@ -0,0 +1,631 @@ +/** + * 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 _functions_included + #endinput +#endif +#define _functions_included + +#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 /**< Not 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 + */ + +methodmap GlobalForward < Handle { + // 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 parameter types passed. + public native GlobalForward(const char[] name, ExecType type, ParamType ...); + + // Returns the number of functions in a global or private forward's call list. + property int FunctionCount { + public native get(); + } +}; + +methodmap PrivateForward < GlobalForward { + // 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 parameter types passed. + public native PrivateForward(ExecType type, ParamType ...); + + // Adds a function to a private forward's call list. + // + // @note Cannot be used during an incomplete call. + // + // @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. + public native bool AddFunction(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 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. + public native bool RemoveFunction(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 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. + public native int RemoveAllFunctions(Handle plugin); +}; + +/** + * 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 char[] 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 parameter types passed. + */ +native GlobalForward CreateGlobalForward(const char[] 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 parameter types passed. + */ +native PrivateForward 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 int GetForwardFunctionCount(Handle fwd); + +/** + * Adds a function to a private forward's call list. + * + * @note Cannot be used during an incomplete 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 int RemoveAllFromForward(Handle fwd, Handle plugin); + +/** + * Starts a call to functions in a forward's call list. + * + * @note Cannot be used during an incomplete call. + * + * @param fwd Handle to global or private forward. + * @error Invalid or corrupt forward handle or called before another call has completed. + */ +native void Call_StartForward(Handle fwd); + +/** + * Starts a call to a function. + * + * @note Cannot be used during an incomplete call. + * + * @param plugin Handle of the plugin that contains the function. + * Pass INVALID_HANDLE to specify the calling plugin. + * @param func Function to call. + * @error Invalid or corrupt plugin handle, invalid function, or called before another call has completed. + */ +native void 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. + * @error Called before a call has been started. + */ +native void 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. + * @error Called before a call has been started. + */ +native void 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. + * @error Called before a call has been started. + */ +native void 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. + * @error Called before a call has been started. + */ +native void 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. + * @error Called before a call has been started. + */ +native void Call_PushArray(const any[] value, int 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 SM_PARAM_* constants for details. + * @error Called before a call has been started. + */ +native void Call_PushArrayEx(any[] value, int size, int cpflags); + +/** + * Pushes the NULL_VECTOR onto the current call. + * @see IsNullVector + * + * @note Cannot be used before a call has been started. + * + * @error Called before a call has been started. + */ +native void Call_PushNullVector(); + +/** + * 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. + * @error Called before a call has been started. + */ +native void Call_PushString(const char[] 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 SM_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 SM_PARAM_* constants for details. + * @error Called before a call has been started. + */ +native void Call_PushStringEx(char[] value, int length, int szflags, int cpflags); + +/** + * Pushes the NULL_STRING onto the current call. + * @see IsNullString + * + * @note Cannot be used before a call has been started. + * + * @error Called before a call has been started. + */ +native void Call_PushNullString(); + +/** + * 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 int 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. + * + * @error Called before a call has been started. + */ +native void Call_Cancel(); + +typeset NativeCall +{ + /** + * 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. + */ + function int (Handle plugin, int numParams); + + /** + * 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. + */ + function any (Handle plugin, int 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 among + * all other registered dynamic natives. + * @param func Function to use as the dynamic native. + */ +native void CreateNative(const char[] 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. + * @noreturn + * @error Always! + */ +native int ThrowNativeError(int error, const char[] fmt, any ...); + +/** + * Retrieves the string length from a native parameter string. This is useful for + * 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 int GetNativeStringLength(int param, int &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 int GetNativeString(int param, char[] buffer, int maxlength, int &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 int SetNativeString(int param, const char[] source, int maxlength, bool utf8=true, int &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(int param); + +/** + * Gets a function pointer from a native parameter. + * + * @param param Parameter number, starting from 1. + * @return Function pointer at the given parameter number. + * @error Invalid parameter number, or calling from a non-native function. + */ +native Function GetNativeFunction(int 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(int 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. + * @error Invalid parameter number or calling from a non-native function. + */ +native void SetNativeCellRef(int 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 int GetNativeArray(int param, any[] local, int 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 int SetNativeArray(int param, const any[] local, int size); + +/** + * Check if the native parameter is the NULL_VECTOR. + * + * @param param Parameter number, starting from 1. + * @return True if NULL_VECTOR, false otherwise. + */ +native bool IsNativeParamNullVector(int param); + +/** + * Check if the native parameter is the NULL_STRING. + * + * @param param Parameter number, starting from 1. + * @return True if NULL_STRING, false otherwise. + */ +native bool IsNativeParamNullString(int param); + +/** + * 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 int FormatNativeString(int out_param, + int fmt_param, + int vararg_param, + int out_len, + int &written=0, + char[] out_string="", + const char[] fmt_string=""); + +/** + * Defines a RequestFrame Callback. + * + * @param data Data passed to the RequestFrame native. + */ +typeset RequestFrameCallback { + function void (); + function void (any data); +} + +/** + * Creates a single use Next Frame hook. + * + * @param Function Function to call on the next frame. + * @param data Value to be passed on the invocation of the Function. + */ +native void RequestFrame(RequestFrameCallback Function, any data=0); diff --git a/source/sourcemod/scripting/include/gamechaos.inc b/source/sourcemod/scripting/include/gamechaos.inc new file mode 100644 index 0000000..eeaf040 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos.inc @@ -0,0 +1,20 @@ + +// GameChaos's includes for various specific stuff + +#if defined _gamechaos_stocks_included + #endinput +#endif +#define _gamechaos_stocks_included + +#define GC_INCLUDES_VERSION 0x01_00_00 +#define GC_INCLUDES_VERSION_STRING "1.0.0" + +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/arrays.inc b/source/sourcemod/scripting/include/gamechaos/arrays.inc new file mode 100644 index 0000000..eba62bb --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/arrays.inc @@ -0,0 +1,52 @@ + +#if defined _gamechaos_stocks_arrays_included + #endinput +#endif +#define _gamechaos_stocks_arrays_included + +#define GC_ARRAYS_VERSION 0x01_00_00 +#define GC_ARRAYS_VERSION_STRING "1.0.0" + +/** + * Copies an array into an arraylist. + * + * @param array Arraylist Handle. + * @param index Index in the arraylist. + * @param values Array to copy. + * @param size Size of the array to copy. + * @param offset Arraylist offset to set. + * @return Number of cells copied. + * @error Invalid Handle or invalid index. + */ +stock int GCSetArrayArrayIndexOffset(ArrayList array, int index, const any[] values, int size, int offset) +{ + int cells; + for (int i; i < size; i++) + { + array.Set(index, values[i], offset + i); + cells++; + } + return cells; +} + +/** + * Copies an arraylist's specified cells to an array. + * + * @param array Arraylist Handle. + * @param index Index in the arraylist. + * @param result Array to copy to. + * @param size Size of the array to copy to. + * @param offset Arraylist offset. + * @return Number of cells copied. + * @error Invalid Handle or invalid index. + */ +stock int GCCopyArrayArrayIndex(const ArrayList array, int index, any[] result, int size, int offset) +{ + int cells; + for (int i = offset; i < (size + offset); i++) + { + result[i] = array.Get(index, i); + cells++; + } + return cells; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/client.inc b/source/sourcemod/scripting/include/gamechaos/client.inc new file mode 100644 index 0000000..cb2114a --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/client.inc @@ -0,0 +1,300 @@ + +#if defined _gamechaos_stocks_client_included + #endinput +#endif +#define _gamechaos_stocks_client_included + +#define GC_CLIENT_VERSION 0x01_00_00 +#define GC_CLIENT_VERSION_STRING "1.0.0" + +/** + * Credit: Don't remember. + * Removes a player's weapon from the specified slot. + * + * @param client Client index. + * @param slot Weapon slot. + * @return True if removed, false otherwise. + */ +stock bool GCRemoveWeaponBySlot(int client, int slot) +{ + int entity = GetPlayerWeaponSlot(client, slot); + if (IsValidEdict(entity)) + { + RemovePlayerItem(client, entity); + AcceptEntityInput(entity, "kill"); + return true; + } + return false; +} + +/** + * Checks if a client is valid and not the server and optionally, whether he's alive. + * + * @param client Client index. + * @param alive Whether to check alive. + * @return True if valid, false otherwise. + */ +stock bool GCIsValidClient(int client, bool alive = false) +{ + return (client >= 1 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsClientSourceTV(client) && (!alive || IsPlayerAlive(client))); +} + + + +/** + * Gets the value of m_flForwardMove. + * + * @param client Client index. + * @return Value of m_flForwardMove. + */ +stock float GCGetClientForwardMove(int client) +{ + return GetEntPropFloat(client, Prop_Data, "m_flForwardMove"); +} + +/** + * Gets the value of m_flSideMove. + * + * @param client Client index. + * @return Value of m_flSideMove. + */ +stock float GCGetClientSideMove(int client) +{ + return GetEntPropFloat(client, Prop_Data, "m_flSideMove"); +} + +/** + * Gets the client's abs origin. + * + * @param client Client index. + * @return result Player's origin. + */ +stock float[] GCGetClientAbsOriginRet(int client) +{ + float result[3] + GetClientAbsOrigin(client, result); + return result; +} + +/** + * Copies the client's velocity to a vector. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void GCGetClientVelocity(int client, float result[3]) +{ + GetEntPropVector(client, Prop_Data, "m_vecVelocity", result); +} + +/** + * Gets the client's velocity (m_vecVelocity). + * + * @param client Client index. + * @return result m_vecVelocity. + */ +stock float[] GCGetClientVelocityRet(int client) +{ + float result[3] + GetEntPropVector(client, Prop_Data, "m_vecVelocity", result); + return result +} + +/** + * Copies the client's basevelocity to a vector. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void GCGetClientBaseVelocity(int client, float result[3]) +{ + GetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", result); +} + +/** + * Gets the client's basevelocity (m_vecBaseVelocity). + * + * @param client Client index. + * @return result m_vecBaseVelocity. + */ +stock float[] GCGetClientBaseVelocityRet(int client) +{ + float result[3]; + GetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", result); + return result; +} + + +/** + * Gets the client's "m_flDuckSpeed" value. + * + * @param client Client index. + * @return "m_flDuckSpeed". + */ +stock float GCGetClientDuckSpeed(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flDuckSpeed"); +} + +/** + * Gets the client's "m_flDuckAmount" value. + * + * @param client Client index. + * @return "m_flDuckAmount". + */ +stock float GCGetClientDuckAmount(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flDuckAmount"); +} + +/** + * Gets the client's "m_bDucking" value. + * + * @param client Client index. + * @return "m_bDucking". + */ +stock int GCGetClientDucking(int client) +{ + return GetEntProp(client, Prop_Data, "m_bDucking"); +} + +/** + * Gets the client's "m_flMaxspeed" value. + * + * @param client Client index. + * @return "m_flMaxspeed". + */ +stock float GCGetClientMaxspeed(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flMaxspeed"); +} + +/** + * Gets the client's "m_afButtonPressed" value. + * + * @param client Client index. + * @return "m_afButtonPressed". + */ +stock int GCGetClientButtonPressed(int client) +{ + return GetEntProp(client, Prop_Data, "m_afButtonPressed"); +} + +/** + * Gets the client's "m_afButtonReleased" value. + * + * @param client Client index. + * @return "m_afButtonReleased". + */ +stock int GCGetClientButtonReleased(int client) +{ + return GetEntProp(client, Prop_Data, "m_afButtonReleased"); +} + +/** + * Gets the client's "m_afButtonLast" value. + * + * @param client Client index. + * @return "m_afButtonLast". + */ +stock int GCGetClientButtonLast(int client) +{ + return GetEntProp(client, Prop_Data, "m_afButtonLast"); +} + +/** + * Gets the client's "m_afButtonForced" value. + * + * @param client Client index. + * @return "m_afButtonForced". + */ +stock int GCGetClientForcedButtons(int client) +{ + return GetEntProp(client, Prop_Data, "m_afButtonForced"); +} + +/** + * Gets the client's "m_flStamina" value. + * + * @param client Client index. + * @return "m_flStamina". + */ +stock float GCGetClientStamina(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flStamina"); +} + + + +/** + * Sets the client's origin. + * + * @param client Client index. + * @param origin New origin. + */ +stock void GCSetClientAbsOrigin(int client, const float origin[3]) +{ + SetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", origin); +} + +/** + * Sets the client's velocity. + * + * @param client Client index. + * @param velocity New velocity. + */ +stock void GCSetClientVelocity(int client, const float velocity[3]) +{ + SetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity); +} + +/** + * Sets the client's "m_vecAbsVelocity". + * + * @param client Client index. + * @param velocity New "m_vecAbsVelocity". + */ +stock void GCSetClientAbsVelocity(int client, const float velocity[3]) +{ + SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", velocity); +} + +/** + * Sets the client's eye angles. + * Ang has to be a 2 member array or more + * + * @param client Client index. + * @param ang New eyeangles. + */ +stock void GCSetClientEyeAngles(int client, const float[] ang) +{ + SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[0]", ang[0]); + SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[1]", ang[1]); +} + + +/** + * Sets the client's "m_flDuckSpeed". + * + * @param client Client index. + * @param value New "m_flDuckSpeed". + */ +stock void GCSetClientDuckSpeed(int client, float value) +{ + SetEntPropFloat(client, Prop_Send, "m_flDuckSpeed", value); +} + +stock void GCSetClientDuckAmount(int client, float value) +{ + SetEntPropFloat(client, Prop_Send, "m_flDuckAmount", value); +} + +stock void GCSetClientForcedButtons(int client, int buttons) +{ + SetEntProp(client, Prop_Data, "m_afButtonForced", buttons); +} + +stock void GCSetClientStamina(int client, float stamina) +{ + SetEntPropFloat(client, Prop_Send, "m_flStamina", stamina) +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/debug.inc b/source/sourcemod/scripting/include/gamechaos/debug.inc new file mode 100644 index 0000000..4e5b7e7 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/debug.inc @@ -0,0 +1,19 @@ + +// gamechaos's debug stocks +// useful stocks for debugging + +#if defined _gamechaos_debug_included + #endinput +#endif +#define _gamechaos_debug_included + +#define GC_DEBUG_VERSION 0x1_00_00 +#define GC_DEBUG_VERSION_STRING "1.0.0" + +#if defined GC_DEBUG + #define GC_ASSERT(%1) if (!(%1))SetFailState("Assertion failed: \""...#%1..."\"") + #define GC_DEBUGPRINT(%1) PrintToChatAll(%1) +#else + #define GC_ASSERT(%1)%2; + #define GC_DEBUGPRINT(%1)%2; +#endif diff --git a/source/sourcemod/scripting/include/gamechaos/isvalidclient.inc b/source/sourcemod/scripting/include/gamechaos/isvalidclient.inc new file mode 100644 index 0000000..bf80246 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/isvalidclient.inc @@ -0,0 +1,16 @@ + +#if defined _gamechaos_isvalidclient_client_included + #endinput +#endif +#define _gamechaos_isvalidclient_client_included + +/** + * Checks if a client is valid. + * + * @param client Client index. + * @return True if valid, false otherwise. + */ +stock bool IsValidClient(int client) +{ + return (client >= 0 && client <= MaxClients && IsValidEntity(client) && IsClientConnected(client) && IsClientInGame(client)); +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/kreedzclimbing.inc b/source/sourcemod/scripting/include/gamechaos/kreedzclimbing.inc new file mode 100644 index 0000000..0cbb828 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/kreedzclimbing.inc @@ -0,0 +1,226 @@ +// +// Useful things for making plugins for Kreedz Climbing +// + +#if defined _gamechaos_kreedzclimbing_included + #endinput +#endif +#define _gamechaos_kreedzclimbing_included + +#define GC_KREEDZCLIMBING_VERSION 0x01_00_00 +#define GC_KREEDZCLIMBING_VERSION_STRING "1.0.0" + + +#define MAX_COURSE_SIZE 128 // Reasonable maximum characters a course name can have +#define COURSE_CVAR_COUNT 20 // the amount of Course cvars + +// Kreedz Climbing Client Commands: +// These may be executed by a player via the console, with / in chat, or via binds. + +// specmode - Cycles spectator mode (F3 by default). +// kz_pause - Pauses the timer. +// flare - Fires a flare. +// gototimer | start - Returns to the last pressed start timer. +// spectate | spec - Enters spectator mode. +// forcespectator - Becomes a spectator no matter what (force respawns a dead player as well). +// stoptimer - Instantly stops the player's timer. +// climb | ct - Respawns at the map spawnpoint. +// InvalidateTimer - Invalidates the player's timer. An invalid timer can't earn rewards for completing the course. InvalidateTimer 1 displays the message, without the 1 it does not. + +// Kreedz Climbing Constants + +// Timer state (player->m_Local->Timer_Active) +#define TIMER_STATE_INVISIBLE 0 +#define TIMER_STATE_ACTIVE 1 +#define TIMER_STATE_INACTIVE 2 +#define TIMER_STATE_PAUSED 3 + +// Timer flags (player_manager->m_iTimerFlags[32]) +// These are replicated flags for player's timer (most timer data is local to it's own player). +// Note that these flags are mirrors of data local to the player - they are set to the player's +// state every frame and cannot be changed. + +#define TIMER_FLAG_INVALID (1 << 0) +#define TIMER_FLAG_ACTIVE (1 << 1) // We need to broadcast this because Timer_State is local only. +#define TIMER_FLAG_PAUSED (1 << 2) // A paused timer cannot be active and vice versa. + +// Environmental Attributes (player->m_iEnvironmentalAttributes) +#define PLAYER_ENV_ATTRIBUTES_BHOP (1 << 0) +#define PLAYER_ENV_ATTRIBUTES_SURF (1 << 1) +#define PLAYER_ENV_ATTRIBUTES_AUTOBHOP (1 << 2) +#define PLAYER_ENV_ATTRIBUTES_CSGOMOVEMENT (1 << 3) +#define PLAYER_ENV_ATTRIBUTES_CSGODUCKHULL (1 << 4) + +// Movement restriction flags (player->m_iMovementRestrictions) (new version of Environmental Restrictions below) +#define PLAYER_MOVEMENT_RESTRICTION_NOJUMP (1 << 0) +#define PLAYER_MOVEMENT_RESTRICTION_NOBHOP (1 << 1) +#define PLAYER_MOVEMENT_RESTRICTION_NODOUBLEDUCK (1 << 2) + +// OBSOLETE: ONLY IN OLD MAPS: Environmental Restrictions (player->m_iEnvironmentalRestrictions), note not flags, complete integer. +#define PLAYER_ENV_RESTRICTION_NOJUMP 1 +#define PLAYER_ENV_RESTRICTION_NOBHOP 2 +#define PLAYER_ENV_RESTRICTION_BOTH 3 + +// Cooperative status (player->m_Local.m_multiplayercoursedata.Player1Status, Player2Status etc) +#define COOPERATIVE_STATUS_NONE 0 +#define COOPERATIVE_STATUS_WAITING 1 +#define COOPERATIVE_STATUS_READY 2 +#define COOPERATIVE_STATUS_TIMER_ACTIVE 3 +#define COOPERATIVE_STATUS_TIMER_COMPLETE 4 +#define COOPERATIVE_STATUS_PLAYER_DISCONNECTED 5 // Player disconnected from server, waiting for them to reconnect. +#define COOPERATIVE_STATUS_TIMER_PAUSED 6 + +// Kreedz Climbing Button Constants +#define IN_CHECKPOINT (1 << 25) +#define IN_TELEPORT (1 << 26) +#define IN_SPECTATE (1 << 27) +//#define IN_AVAILABLE (1 << 28) // Unused +#define IN_HOOK (1 << 29) + +// converts the course id from the obsolete "player_starttimer" event into the course name +stock void GCCourseidToString(int courseid, char[] course, int size) +{ + char szCourseid[16]; + if (courseid < 1 || courseid > COURSE_CVAR_COUNT) + { + return; + } + FormatEx(szCourseid, sizeof(szCourseid), "Course%i", courseid); + FindConVar(szCourseid).GetString(course, size); +} + +stock void GCGetCurrentMapCourses(ArrayList &array) +{ + if (array == null) + { + // 1 for endurance bool + array = new ArrayList(ByteCountToCells(MAX_COURSE_SIZE) + 1); + } + else + { + array.Clear(); + } + + char course[MAX_COURSE_SIZE]; + + int ent; + while((ent = FindEntityByClassname(ent, "func_stoptimer")) != -1) + { + int courseid = GetEntProp(ent, Prop_Data, "CourseID"); + GCCourseidToString(courseid, course, sizeof(course)); + array.PushString(course); + + bool endurance = GCIsCourseEndurance(course, ent); + array.Set(array.Length - 1, endurance, ByteCountToCells(MAX_COURSE_SIZE)); + } + + int courseStringtableCount; + int courseNamesIdx = FindStringTable("CourseNames"); + courseStringtableCount = GetStringTableNumStrings(courseNamesIdx); + + for (int i; i < courseStringtableCount; i++) + { + ReadStringTable(courseNamesIdx, i, course, sizeof(course)); + array.PushString(course); + + bool endurance = GCIsCourseEndurance(course, ent); + array.Set(array.Length - 1, endurance, ByteCountToCells(MAX_COURSE_SIZE)); + } +} + +stock int GCGetTimerState(int client) +{ + return GetEntProp(client, Prop_Send, "Timer_Active"); +} + +stock void GCSetTimerState(int client, int timerstate) +{ + SetEntProp(client, Prop_Send, "Timer_Active", timerstate); +} + +stock int GCGetPlayerEnvAttributes(int client) +{ + return GetEntProp(client, Prop_Send, "m_iEnvironmentalAttributes"); +} + +stock void GCSetPlayerEnvAttributes(int client, int attributes) +{ + SetEntProp(client, Prop_Send, "m_iEnvironmentalAttributes", attributes); +} + +stock int GCGetPlayerMovementRestrictions(int client) +{ + return GetEntProp(client, Prop_Send, "m_iMovementRestrictions"); +} + +stock void GCSetPlayerMovementRestrictions(int client, int restrictions) +{ + SetEntProp(client, Prop_Send, "m_iMovementRestrictions", restrictions); +} + +stock void GCSetActiveCourse(int client, int course) +{ + int ent = FindEntityByClassname(0, "player_manager"); + int courseOffset = FindSendPropInfo("CPlayerResource", "m_iActiveCourse"); + SetEntData(ent, courseOffset + (client * 4), course); +} + +stock int GCGetTimerFlags(int client) +{ + int ent = FindEntityByClassname(0, "player_manager"); + int courseOffset = FindSendPropInfo("CPlayerResource", "m_iTimerFlags"); + return GetEntData(ent, courseOffset + (client * 4)); +} + +stock bool GCInvalidateTimer(int client) +{ + if (~GCGetTimerFlags(client) & TIMER_FLAG_INVALID) + { + FakeClientCommand(client, "InvalidateTimer 1"); + return true; + } + + return false; +} + +stock bool GCIsCourseEndurance(char[] course, int ent = -1) +{ + if (ent != -1) + { + if (IsValidEntity(ent)) + { + return !!(GetEntProp(ent, Prop_Data, "m_bEnduranceCourse")); + } + } + + while ((ent = FindEntityByClassname(ent, "point_climbtimer")) != -1) + { + if (IsValidEntity(ent)) + { + char buffer[MAX_COURSE_SIZE]; + GetEntPropString(ent, Prop_Data, "m_strCourseName", buffer, sizeof(buffer)); + + if (StrEqual(buffer, course)) + { + return !!(GetEntProp(ent, Prop_Data, "m_bEnduranceCourse")); + } + } + } + + while ((ent = FindEntityByClassname(ent, "func_stoptimer")) != -1) + { + if (IsValidEntity(ent)) + { + char buffer[MAX_COURSE_SIZE]; + int courseid = GetEntProp(ent, Prop_Data, "CourseID"); + GCCourseidToString(courseid, buffer, sizeof(buffer)); + + if (StrEqual(buffer, course)) + { + return !!(GetEntProp(ent, Prop_Data, "m_bEnduranceCourse")); + } + } + } + + return false; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/maths.inc b/source/sourcemod/scripting/include/gamechaos/maths.inc new file mode 100644 index 0000000..f3c94af --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/maths.inc @@ -0,0 +1,362 @@ + +#if defined _gamechaos_stocks_maths_included + #endinput +#endif +#define _gamechaos_stocks_maths_included + +#define GC_MATHS_VERSION 0x02_00_00 +#define GC_MATHS_VERSION_STRING "2.0.0" + +#include + +#define GC_PI 3.14159265359 + +#define GC_DEGREES(%1) ((%1) * 180.0 / GC_PI) // convert radians to degrees +#define GC_RADIANS(%1) ((%1) * GC_PI / 180.0) // convert degrees to radians + +#define GC_FLOAT_NAN view_as(0xffffffff) +#define GC_FLOAT_INFINITY view_as(0x7f800000) +#define GC_FLOAT_NEGATIVE_INFINITY view_as(0xff800000) + +#define GC_FLOAT_LARGEST_POSITIVE view_as(0x7f7fffff) +#define GC_FLOAT_SMALLEST_NEGATIVE view_as(0xff7fffff) + +#define GC_FLOAT_SMALLEST_POSITIVE view_as(0x00000001) +#define GC_FLOAT_LARGEST_NEGATIVE view_as(0x80000001) + +#define GC_INT_MAX 0x7fffffff +#define GC_INT_MIN 0xffffffff + + +/** + * Credit: https://stackoverflow.com/questions/5666222/3d-line-plane-intersection + * Determines the point of intersection between a plane defined by a point and a normal vector and a line defined by a point and a direction vector. + * + * @param planePoint A point on the plane. + * @param planeNormal Normal vector of the plane. + * @param linePoint A point on the line. + * @param lineDirection Direction vector of the line. + * @param result Resultant vector. + */ +stock void GCLineIntersection(const float planePoint[3], const float planeNormal[3], const float linePoint[3], const float lineDirection[3], float result[3]) +{ + if (GetVectorDotProduct(planeNormal, lineDirection) == 0) + { + return; + } + + float t = (GetVectorDotProduct(planeNormal, planePoint) + - GetVectorDotProduct(planeNormal, linePoint)) + / GetVectorDotProduct(planeNormal, lineDirection); + + float lineDir[3]; + lineDir = lineDirection; + NormalizeVector(lineDir, lineDir); + + ScaleVector(lineDir, t); + + AddVectors(linePoint, lineDir, result); +} + +/** + * Calculates a point according to angles supplied that is a certain distance away. + * + * @param client Client index. + * @param result Resultant vector. + * @param distance Maximum distance to trace. + * @return True on success, false otherwise. + */ +stock void GCCalcPointAngleDistance(const float start[3], const float angle[3], float distance, float result[3]) +{ + float zsine = Sine(DegToRad(-angle[0])); + float zcos = Cosine(DegToRad(-angle[0])); + + result[0] = Cosine(DegToRad(angle[1])) * zcos; + result[1] = Sine(DegToRad(angle[1])) * zcos; + result[2] = zsine; + + ScaleVector(result, distance); + AddVectors(start, result, result); +} + +/** + * Compares how close 2 floats are. + * + * @param z1 Float 1 + * @param z2 Float 2 + * @param tolerance How close the floats have to be to return true. + * @return True on success, false otherwise. + */ +stock bool GCIsRoughlyEqual(float z1, float z2, float tolerance) +{ + return FloatAbs(z1 - z2) < tolerance; +} + +/** + * Checks if a float is within a range + * + * @param number Float to check. + * @param min Minimum range. + * @param max Maximum range. + * @return True on success, false otherwise. + */ +stock bool GCIsFloatInRange(float number, float min, float max) +{ + return number >= min && number <= max; +} + +/** + * Keeps the yaw angle within the range of -180 to 180. + * + * @param angle Angle. + * @return Normalised angle. + */ +stock float GCNormaliseYaw(float angle) +{ + if (angle <= -180.0) + { + angle += 360.0; + } + + if (angle > 180.0) + { + angle -= 360.0; + } + + return angle; +} + +/** + * Keeps the yaw angle within the range of -180 to 180. + * + * @param angle Angle. + * @return Normalised angle. + */ +stock float GCNormaliseYawRad(float angle) +{ + if (angle <= -FLOAT_PI) + { + angle += FLOAT_PI * 2; + } + + if (angle > FLOAT_PI) + { + angle -= FLOAT_PI * 2; + } + + return angle; +} + +/** + * Linearly interpolates between 2 values. + * + * @param f1 Float 1. + * @param f2 Float 2. + * @param fraction Amount to interpolate. + * @return Interpolated value. + */ +stock float GCInterpLinear(float f1, float f2, float fraction) +{ + float diff = f2 - f1; + + return diff * fraction + f1; +} + +/** + * Calculates the linear fraction from a value that was interpolated and 2 values it was interpolated from. + * + * @param f1 Float 1. + * @param f2 Float 2. + * @param fraction Interpolated value. + * @return Fraction. + */ +stock float GCCalcLerpFraction(float f1, float f2, float lerped) +{ + float diff = f2 - f1; + + float fraction = lerped - f1 / diff; + return fraction; +} + +/** + * Calculate absolute value of an integer. + * + * @param x Integer. + * @return Absolute value of integer. + */ +stock int GCIntAbs(int x) +{ + return x >= 0 ? x : -x; +} + +/** + * Get the maximum of 2 integers. + * + * @param n1 Integer. + * @param n2 Integer. + * @return The biggest of n1 and n2. + */ +stock int GCIntMax(int n1, int n2) +{ + return n1 > n2 ? n1 : n2; +} + +/** + * Get the minimum of 2 integers. + * + * @param n1 Integer. + * @param n2 Integer. + * @return The smallest of n1 and n2. + */ +stock int GCIntMin(int n1, int n2) +{ + return n1 < n2 ? n1 : n2; +} + +/** + * Checks if an integer is within a range + * + * @param number Integer to check. + * @param min Minimum range. + * @param max Maximum range. + * @return True on success, false otherwise. + */ +stock bool GCIsIntInRange(int number, int min, int max) +{ + return number >= min && number <= max; +} + +/** + * Calculates a float percentage from a common fraction. + * + * @param numerator Numerator. + * @param denominator Denominator. + * @return Float percentage. -1.0 on failure. + */ +stock float GCCalcIntPercentage(int numerator, int denominator) +{ + return float(numerator) / float(denominator) * 100.0; +} + +/** + * Integer power. + * Returns the base raised to the power of the exponent. + * Returns 0 if exponent is negative. + * + * @param base Base to be raised. + * @param exponent Value to raise the base. + * @return Value to the power of exponent. + */ +stock int GCIntPow(int base, int exponent) +{ + if (exponent < 0) + { + return 0; + } + + int result = 1; + for (;;) + { + if (exponent & 1) + { + result *= base + } + + exponent >>= 1; + + if (!exponent) + { + break; + } + + base *= base; + } + return result; +} + +/** + * Swaps the values of 2 variables. + * + * @param cell1 Cell 1. + * @param cell2 Cell 2. + */ +stock void GCSwapCells(any &cell1, any &cell2) +{ + any temp = cell1; + cell1 = cell2; + cell2 = temp; +} + +/** + * Clamps an int between min and max. + * + * @param value Float to clamp. + * @param min Minimum range. + * @param max Maximum range. + * @return Clamped value. + */ +stock int GCIntClamp(int value, int min, int max) +{ + if (value < min) + { + return min; + } + if (value > max) + { + return max; + } + return value; +} + +/** + * Returns the biggest of 2 values. + * + * @param num1 Number 1. + * @param num2 Number 2. + * @return Biggest number. + */ +stock float GCFloatMax(float num1, float num2) +{ + if (num1 > num2) + { + return num1; + } + return num2; +} + +/** + * Returns the smallest of 2 values. + * + * @param num1 Number 1. + * @param num2 Number 2. + * @return Smallest number. + */ +stock float GCFloatMin(float num1, float num2) +{ + if (num1 < num2) + { + return num1; + } + return num2; +} + +/** + * Clamps a float between min and max. + * + * @param value Float to clamp. + * @param min Minimum range. + * @param max Maximum range. + * @return Clamped value. + */ +stock float GCFloatClamp(float value, float min, float max) +{ + if (value < min) + { + return min; + } + if (value > max) + { + return max; + } + return value; +} diff --git a/source/sourcemod/scripting/include/gamechaos/misc.inc b/source/sourcemod/scripting/include/gamechaos/misc.inc new file mode 100644 index 0000000..f964862 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/misc.inc @@ -0,0 +1,245 @@ + +#if defined _gamechaos_stocks_misc_included + #endinput +#endif +#define _gamechaos_stocks_misc_included + +#define GC_MISC_VERSION 0x01_00_00 +#define GC_MISC_VERSION_STRING "1.0.0" + +/** + * Check if player is overlapping their MOVERIGHT and MOVELEFT buttons. + * + * @param x Buttons; + * @return True if overlapping, false otherwise. + */ +stock bool GCIsOverlapping(int buttons) +{ + return buttons & IN_MOVERIGHT && buttons & IN_MOVELEFT +} + +/** + * Checks if player gained speed. + * + * @param speed Current player speed. + * @param lastspeed Player speed from previous tick. + * @return True if player gained speed, false otherwise. + */ +stock bool GCIsStrafeSynced(float speed, float lastspeed) +{ + return speed > lastspeed; +} + +/** + * Checks if the player is not holding down their MOVERIGHT and MOVELEFT buttons. + * + * @param x Buttons. + * @return True if they're not holding either, false otherwise. + */ +stock bool GCIsDeadAirtime(int buttons) +{ + return !(buttons & IN_MOVERIGHT) && !(buttons & IN_MOVELEFT); +} + +/** +* Source: https://forums.alliedmods.net/showthread.php?p=2535972 +* Runs a single line of vscript code. +* NOTE: Dont use the "script" console command, it startes a new instance and leaks memory. Use this instead! +* +* @param code The code to run. +* @noreturn +*/ +stock void GCRunScriptCode(const char[] code, any ...) +{ + static int scriptLogic = INVALID_ENT_REFERENCE; + + if (scriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(scriptLogic)) + { + scriptLogic = EntIndexToEntRef(CreateEntityByName("logic_script")); + if (scriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(scriptLogic)) + { + SetFailState("Could not create a 'logic_script' entity."); + } + + DispatchSpawn(scriptLogic); + } + + char buffer[512]; + VFormat(buffer, sizeof(buffer), code, 2); + + SetVariantString(buffer); + AcceptEntityInput(scriptLogic, "RunScriptCode"); +} + +stock void GCTE_SendBeamBox(int client, + const float origin[3], + const float mins[3], + const float maxs[3], + int ModelIndex, + int HaloIndex = 0, + float Life = 3.0, + float Width = 2.0, + const int Colour[4] = { 255, 255, 255, 255 }, + float EndWidth = 2.0, + int StartFrame = 0, + int FrameRate = 0, + int FadeLength = 0, + float Amplitude = 0.0, + int Speed = 0) +{ + // credit to some bhop timer by shavit? thanks + int pairs[8][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } }; + int edges[12][2] = { { 0, 1 }, { 0, 3 }, { 0, 4 }, { 2, 1 }, { 2, 3 }, { 2, 6 }, { 5, 4 }, { 5, 6 }, { 5, 1 }, { 7, 4 }, { 7, 6 }, { 7, 3 } }; + + float corners[8][3]; + float corner[2][3]; + + AddVectors(origin, mins, corner[0]); + AddVectors(origin, maxs, corner[1]); + + for (int i = 0; i < 8; i++) + { + corners[i][0] = corner[pairs[i][0]][0]; + corners[i][1] = corner[pairs[i][1]][1]; + corners[i][2] = corner[pairs[i][2]][2]; + } + + for (int i = 0; i < 12; i++) + { + TE_SetupBeamPoints(corners[edges[i][0]], + corners[edges[i][1]], + ModelIndex, + HaloIndex, + StartFrame, + FrameRate, + Life, + Width, + EndWidth, + FadeLength, + Amplitude, + Colour, + Speed); + TE_SendToClient(client); + } +} + +stock void GCTE_SendBeamCross(int client, + const float origin[3], + int ModelIndex, + int HaloIndex = 0, + float Life = 3.0, + float Width = 2.0, + const int Colour[4] = { 255, 255, 255, 255 }, + float EndWidth = 2.0, + int StartFrame = 0, + int FrameRate = 0, + int FadeLength = 0, + float Amplitude = 0.0, + int Speed = 0) +{ + float points[4][3]; + + for (int i; i < 4; i++) + { + points[i][2] = origin[2]; + } + + // -x; -y + points[0][0] = origin[0] - 8.0; + points[0][1] = origin[1] - 8.0; + + // +x; -y + points[1][0] = origin[0] + 8.0; + points[1][1] = origin[1] - 8.0; + + // +x; +y + points[2][0] = origin[0] + 8.0; + points[2][1] = origin[1] + 8.0; + + // -x; +y + points[3][0] = origin[0] - 8.0; + points[3][1] = origin[1] + 8.0; + + //draw cross + for (int corner; corner < 4; corner++) + { + TE_SetupBeamPoints(origin, points[corner], ModelIndex, HaloIndex, StartFrame, FrameRate, Life, Width, EndWidth, FadeLength, Amplitude, Colour, Speed); + TE_SendToClient(client); + } +} + +stock void GCTE_SendBeamRectangle(int client, + const float origin[3], + const float mins[3], + const float maxs[3], + int modelIndex, + int haloIndex = 0, + float life = 3.0, + float width = 2.0, + const int colour[4] = { 255, 255, 255, 255 }, + float endWidth = 2.0, + int startFrame = 0, + int frameRate = 0, + int fadeLength = 0, + float amplitude = 0.0, + int speed = 0) +{ + float vertices[4][3]; + GCRectangleVerticesFromPoint(vertices, origin, mins, maxs); + + // send the square + for (int i; i < 4; i++) + { + int j = (i == 3) ? (0) : (i + 1); + TE_SetupBeamPoints(vertices[i], + vertices[j], + modelIndex, + haloIndex, + startFrame, + frameRate, + life, + width, + endWidth, + fadeLength, + amplitude, + colour, + speed); + TE_SendToClient(client); + } +} + +/** + * Calculates vertices for a rectangle from a point, mins and maxs. + * + * @param result Vertex array result. + * @param origin Origin to offset mins and maxs by. + * @param mins Minimum size of the rectangle. + * @param maxs Maximum size of the rectangle. + * @return True if overlapping, false otherwise. + */ +stock void GCRectangleVerticesFromPoint(float result[4][3], const float origin[3], const float mins[3], const float maxs[3]) +{ + // Vertices are set clockwise starting from top left (-x; -y) + + // -x; -y + result[0][0] = origin[0] + mins[0]; + result[0][1] = origin[1] + mins[1]; + + // +x; -y + result[1][0] = origin[0] + maxs[0]; + result[1][1] = origin[1] + mins[1]; + + // +x; +y + result[2][0] = origin[0] + maxs[0]; + result[2][1] = origin[1] + maxs[1]; + + // -x; +y + result[3][0] = origin[0] + mins[0]; + result[3][1] = origin[1] + maxs[1]; + + // z is the same for every vertex + for (int vertex; vertex < 4; vertex++) + { + result[vertex][2] = origin[2]; + } +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/strings.inc b/source/sourcemod/scripting/include/gamechaos/strings.inc new file mode 100644 index 0000000..8ffcb60 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/strings.inc @@ -0,0 +1,367 @@ + +#if defined _gamechaos_stocks_strings_included + #endinput +#endif +#define _gamechaos_stocks_strings_included + +// these are used for functions that return strings. +// you can change these if they're too small/big. +#define GC_FIXED_BUFFER_SIZE_SMALL 64 +#define GC_FIXED_BUFFER_SIZE_LARGE 4096 + +/** + * Puts the values from a string of integers into an array + * + * @param string + * @param separator + * @param array + * @param arraysize + */ +stock void GCSeparateIntsFromString(const char[] string, const char[] separator, int[] array, int arraysize) +{ + char[][] explodedbuffer = new char[arraysize][32]; + + ExplodeString(string, separator, explodedbuffer, arraysize, 32); + + for (int i; i < arraysize; i++) + { + array[i] = StringToInt(explodedbuffer[i]); + } +} + +/** + * Prints a message to all admins in the chat area. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void GCPrintToChatAdmins(const char[] format, any ...) +{ + char buffer[256]; + + for (int i = 1; i <= MaxClients; i++) + { + if (GCIsValidClient(i)) + { + AdminId id = GetUserAdmin(i); + if (!GetAdminFlag(id, Admin_Generic)) + { + continue; + } + SetGlobalTransTarget(i); + VFormat(buffer, sizeof(buffer), format, 2); + PrintToChat(i, "%s", buffer); + } + } +} + +/** + * Removes trailings zeroes from a string. Also removes the decimal point if it can. + * + * @param buffer Buffer to trim. + * @return Whether anything was removed. + */ +stock bool GCRemoveTrailing0s(char[] buffer) +{ + bool removed; + int maxlen = strlen(buffer); + + if (maxlen == 0) + { + return removed; + } + + for (int i = maxlen - 1; i > 0 && (buffer[i] == '0' || buffer[i] == '.' || buffer[i] == 0); i--) + { + if (buffer[i] == 0) + { + continue; + } + if (buffer[i] == '.') + { + buffer[i] = 0; + removed = true; + break; + } + buffer[i] = 0; + removed = true; + } + return removed; +} + +/** + * Formats time by HHMMSS. Uses ticks for the time. + * + * @param timeInTicks Time in ticks. + * @param tickRate Tickrate. + * @param formattedTime String to use for formatting. + * @param size String size. + */ +stock void GCFormatTickTimeHHMMSS(int timeInTicks, float tickRate, char[] formattedTime, int size) +{ + if (timeInTicks <= 0) + { + FormatEx(formattedTime, size, "-00:00:00"); + return; + } + + int time = RoundFloat(float(timeInTicks) / tickRate * 100.0); // centiseconds + int iHours = time / 360000; + int iMinutes = time / 6000 - iHours * 6000; + int iSeconds = (time - iHours * 360000 - iMinutes * 6000) / 100; + int iCentiSeconds = time % 100; + + if (iHours != 0) + { + FormatEx(formattedTime, size, "%02i:", iHours); + } + if (iMinutes != 0) + { + Format(formattedTime, size, "%s%02i:", formattedTime, iMinutes); + } + + Format(formattedTime, size, "%s%02i.%02i", formattedTime, iSeconds, iCentiSeconds); +} + +/** + * Formats time by HHMMSS. Uses seconds. + * + * @param seconds Time in seconds. + * @param formattedTime String to use for formatting. + * @param size String size. + * @param decimals Amount of decimals to use for the fractional part. + */ +stock void GCFormatTimeHHMMSS(float seconds, char[] formattedTime, int size, int decimals) +{ + int iFlooredTime = RoundToFloor(seconds); + int iHours = iFlooredTime / 3600; + int iMinutes = iFlooredTime / 60 - iHours * 60; + int iSeconds = iFlooredTime - iHours * 3600 - iMinutes * 60; + int iFraction = RoundToFloor(FloatFraction(seconds) * Pow(10.0, float(decimals))); + + if (iHours != 0) + { + FormatEx(formattedTime, size, "%02i:", iHours); + } + if (iMinutes != 0) + { + Format(formattedTime, size, "%s%02i:", formattedTime, iMinutes); + } + char szFraction[32]; + FormatEx(szFraction, sizeof(szFraction), "%i", iFraction); + + int iTest = strlen(szFraction); + for (int i; i < decimals - iTest; i++) + { + Format(szFraction, sizeof(szFraction), "%s%s", "0", szFraction); + } + + Format(formattedTime, size, "%s%02i.%s", formattedTime, iSeconds, szFraction); +} + +/** + * Encodes and appends a number onto the end of a UTF-8 string. + * + * @param string String to append to. + * @param strsize String size. + * @param number Unicode codepoint to encode. + */ +stock void GCEncodeUtf8(char[] string, char strsize, int number) +{ + // UTF-8 octet sequence (only change digits marked with x) + /* + Char. number range | UTF-8 octet sequence + (hexadecimal) | (binary) + --------------------+--------------------------------------------- + 0000 0000-0000 007F | 0xxxxxxx + 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // byte 4 | byte 3 | byte 2 | byte 1*/ + + //char encodedChar = 0b_11110000_10000000_10000000_10000000; + + int zeropos = strlen(string); + + if (zeropos >= strsize - 1) // need one byte for null terminator + { + return; + } + + if (number < 0) + { + //PrintToServer("ERROR: Encode() - Can't encode negative numbers"); + return; + } + + if (number >= 0x110_000) + { + //PrintToServer("ERROR: Encode() - Number is too big to encode"); + return; + } + + // 1 byte + if (number < 0x80) + { + string[zeropos] = number; + string[zeropos + 1] = '\0'; + } + // 2 bytes + else if (number < 0x800) + { + // can't encode if we don't have enough room + if (zeropos + 2 >= strsize) + { + return; + } + + string[zeropos] = 0b_1100_0000 | (number >> 6); // don't need to mask out bits over 0x7FF + string[zeropos + 1] = 0b_1000_0000 | (number & 0b_0011_1111); + + string[zeropos + 2] = '\0'; + } + // 3 bytes + else if (number < 0x10_000) + { + // can't encode if we don't have enough room + if (zeropos + 3 >= strsize) + { + return; + } + + string[zeropos] = 0b_1110_0000 | (number >> 12); // don't need to mask out bits over 0xFFFF + string[zeropos + 1] = 0b_1000_0000 | ((number >> 6) & 0b_0011_1111); + string[zeropos + 2] = 0b_1000_0000 | (number & 0b_0011_1111); + + string[zeropos + 3] = '\0'; + } + // 4 bytes + else if (number < 0x110_000) + { + // can't encode if we don't have enough room + if (zeropos + 4 >= strsize) + { + return; + } + + string[zeropos] = 0b_1111_0000 | (number >> 18); // don't need to mask out bits over 0x10FFFF + string[zeropos + 1] = 0b_1000_0000 | ((number >> 12) & 0b_0011_1111); + string[zeropos + 2] = 0b_1000_0000 | ((number >> 6) & 0b_0011_1111); + string[zeropos + 3] = 0b_1000_0000 | (number & 0b_0011_1111); + + string[zeropos + 4] = '\0'; + } +} + +// decode a UTF-8 string into an array of unicode codepoints +/** + * Decodes a UTF-8 string into an array of unicode codepoints. + * + * @param string String to decode. + * @param strsize String size. + * @param codepoints Array to use to store the codepoints. + * @param cplength Array length. + */ +stock void GCDecodeUtf8(char[] string, int strsize, int[] codepoints, int cplength) +{ + int charindex; + int cpindex; + + while (charindex < strsize && cpindex < cplength) + { + if (string[charindex] == '\0') + { + break; + } + + int bytes = GetCharBytes(string[charindex]); + + switch (bytes) + { + case 1: + { + codepoints[cpindex] = string[charindex]; + } + case 2: + { + codepoints[cpindex] = (string[charindex++] & 0b_0001_1111) << 6; // byte 2 + codepoints[cpindex] |= string[charindex] & 0b_0011_1111; // byte 1 + } + case 3: + { + codepoints[cpindex] = (string[charindex++] & 0b_0000_1111) << 12; // byte 3 + codepoints[cpindex] |= (string[charindex++] & 0b_0011_1111) << 6; // byte 2 + codepoints[cpindex] |= string[charindex] & 0b_0011_1111; // byte 1 + } + case 4: + { + codepoints[cpindex] = (string[charindex++] & 0b_0000_0111) << 18; // byte 4 + codepoints[cpindex] |= (string[charindex++] & 0b_0011_1111) << 12; // byte 3 + codepoints[cpindex] |= (string[charindex++] & 0b_0011_1111) << 6; // byte 2 + codepoints[cpindex] |= string[charindex] & 0b_0011_1111; // byte 1 + } + } + + charindex++; + cpindex++; + } +} + +/** + * Converts an integer to a string. + * Same as IntToString, but it returns the string. + * + * @param num Integer to convert. + * @return String of the number. + */ +stock char[] GCIntToStringRet(int num) +{ + char string[GC_FIXED_BUFFER_SIZE_SMALL]; + IntToString(num, string, sizeof string); + return string; +} + + /** + * Converts a floating point number to a string. + * Same as FloatToString, but it returns the string. + * + * @param num Floating point number to convert. + * @return String of the number. + */ +stock char[] GCFloatToStringRet(float num) +{ + char string[GC_FIXED_BUFFER_SIZE_SMALL]; + FloatToString(num, string, sizeof string); + return string; +} + +/** + * Formats a string according to the SourceMod format rules (see documentation). + * Same as Format, except it returns the formatted string. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return Formatted string. + */ +stock char[] GCFormatReturn(const char[] format, any ...) +{ + char string[GC_FIXED_BUFFER_SIZE_LARGE]; + VFormat(string, sizeof string, format, 2); + return string; +} + +/** + * Removes whitespace characters from the beginning and end of a string. + * Same as TrimString, except it returns the formatted string and + * it doesn't modify the passed string. + * + * @param str The string to trim. + * @return Number of bytes written (UTF-8 safe). + */ +stock char[] GCTrimStringReturn(char[] str) +{ + char string[GC_FIXED_BUFFER_SIZE_LARGE]; + strcopy(string, sizeof string, str); + TrimString(string); + return string; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/tempents.inc b/source/sourcemod/scripting/include/gamechaos/tempents.inc new file mode 100644 index 0000000..7ec9b5a --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/tempents.inc @@ -0,0 +1,62 @@ + +#if defined _gamechaos_stocks_tempents_included + #endinput +#endif +#define _gamechaos_stocks_tempents_included + +// improved api of some tempents + +#define GC_TEMPENTS_VERSION 0x01_00_00 +#define GC_TEMPENTS_VERSION_STRING "1.0.0" + +#include + +/** + * 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 life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param colour Color array (r, g, b, a). + * @param haloIndex Precached model index. + * @param amplitude Beam amplitude. + * @param speed Speed of the beam. + * @param fadeLength Beam fade time duration. + * @param frameRate Beam frame rate. + * @param startFrame Initial frame to render. + */ +stock void GCTE_SetupBeamPoints(const float start[3], + const float end[3], + int modelIndex, + float life = 2.0, + float width = 2.0, + float endWidth = 2.0, + const int colour[4] = {255, 255, 255, 255}, + int haloIndex = 0, + float amplitude = 0.0, + int speed = 0, + int fadeLength = 0, + int frameRate = 0, + int startFrame = 0) +{ + 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", colour[0]); + TE_WriteNum("g", colour[1]); + TE_WriteNum("b", colour[2]); + TE_WriteNum("a", colour[3]); + TE_WriteNum("m_nSpeed", speed); + TE_WriteNum("m_nFadeLength", fadeLength); +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/tracing.inc b/source/sourcemod/scripting/include/gamechaos/tracing.inc new file mode 100644 index 0000000..65d54a8 --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/tracing.inc @@ -0,0 +1,242 @@ + +#if defined _gamechaos_stocks_tracing_included + #endinput +#endif +#define _gamechaos_stocks_tracing_included + +#include + +#define GC_TRACING_VERSION 0x01_00_00 +#define GC_TRACING_VERSION_STRING "1.0.0" + +/** + * Trace ray filter that filters players from being traced. + * + * @param entity Entity. + * @param data Data. + * @return True on success, false otherwise. + */ +stock bool GCTraceEntityFilterPlayer(int entity, any data) +{ + return entity > MAXPLAYERS; +} + +/** + * Traces the player hull beneath the player in the direction of + * the player's velocity. This should be used on the tick when the player lands + * + * @param client Player's index. + * @param pos Player's position vector. + * @param velocity Player's velocity vector. This shuold have the current tick's x and y velocities, but the previous tick's z velocity, since when you're on ground, your z velocity is 0. + * @param result Trace endpoint on success, player's position on failure. + * @param bugged Whether to add gravity to the player's velocity or not. + * @return True on success, false otherwise. + */ +stock bool GCTraceLandPos(int client, const float pos[3], const float velocity[3], float result[3], float fGravity, bool bugged = false) +{ + float newVel[3]; + newVel = velocity; + + if (bugged) + { + // add 0.5 gravity + newVel[2] -= fGravity * GetTickInterval() * 0.5; + } + else + { + // add 1.5 gravity + newVel[2] -= fGravity * GetTickInterval() * 1.5; + } + + ScaleVector(newVel, GetTickInterval() * 2.0); + float pos2[3]; + AddVectors(pos, newVel, pos2); + + float mins[3]; + float maxs[3]; + GetClientMins(client, mins); + GetClientMaxs(client, maxs); + + Handle trace = TR_TraceHullFilterEx(pos, pos2, mins, maxs, MASK_PLAYERSOLID, GCTraceEntityFilterPlayer); + + if (!TR_DidHit(trace)) + { + result = pos; + CloseHandle(trace); + return false; + } + + TR_GetEndPosition(result, trace); + CloseHandle(trace); + + return true; +} + +/** + * Traces the player hull 2 units straight down beneath the player. + * + * @param client Player's index. + * @param pos Player's position vector. + * @param result Trace endpoint on success, player's position on failure. + * @return True on success, false otherwise. + */ +stock bool GCTraceGround(int client, const float pos[3], float result[3]) +{ + float mins[3]; + float maxs[3]; + + GetClientMins(client, mins); + GetClientMaxs(client, maxs); + + float startpos[3]; + float endpos[3]; + + startpos = pos; + endpos = pos; + + endpos[2] -= 2.0; + + TR_TraceHullFilter(startpos, endpos, mins, maxs, MASK_PLAYERSOLID, GCTraceEntityFilterPlayer); + + if (TR_DidHit()) + { + TR_GetEndPosition(result); + return true; + } + else + { + result = endpos; + return false; + } +} + +/** + * Traces a hull between 2 positions. + * + * @param pos1 Position 1. + * @param pos2 Position 2 + * @param result Trace endpoint on success, player's position on failure. + * @return True on success, false otherwise. + */ +stock bool GCTraceBlock(const float pos1[3], const float pos2[3], float result[3]) +{ + float mins[3] = {-16.0, -16.0, -1.0}; + float maxs[3] = { 16.0, 16.0, 0.0}; + + TR_TraceHullFilter(pos1, pos2, mins, maxs, MASK_PLAYERSOLID, GCTraceEntityFilterPlayer); + + if (TR_DidHit()) + { + TR_GetEndPosition(result); + return true; + } + else + { + return false; + } +} + +/** + * Traces from player eye position in the direction of where the player is looking. + * + * @param client Client index. + * @param result Resultant vector. + * @return True on success, false otherwise. + */ +stock bool GCGetEyeRayPosition(int client, float result[3], TraceEntityFilter filter, any data = 0, int flags = MASK_PLAYERSOLID) +{ + float start[3]; + float angle[3]; + + GetClientEyePosition(client, start); + GetClientEyeAngles(client, angle); + + TR_TraceRayFilter(start, angle, flags, RayType_Infinite, filter, data); + + if (TR_DidHit(INVALID_HANDLE)) + { + TR_GetEndPosition(result, INVALID_HANDLE); + return true; + } + return false; +} + +/** + * Traces from player eye position in the direction of where the player is looking, up to a certain distance. + * + * @param client Client index. + * @param result Resultant vector. + * @param distance Maximum distance to trace. + * @return True on success, false otherwise. + */ +stock bool GCTraceEyeRayPositionDistance(int client, float result[3], float distance) +{ + float start[3]; + float angle[3]; + + GetClientEyePosition(client, start); + GetClientEyeAngles(client, angle); + + float endpoint[3]; + float zsine = Sine(DegToRad(-angle[0])); + float zcos = Cosine(DegToRad(-angle[0])); + + endpoint[0] = Cosine(DegToRad(angle[1])) * zcos; + endpoint[1] = Sine(DegToRad(angle[1])) * zcos; + endpoint[2] = zsine; + + ScaleVector(endpoint, distance); + AddVectors(start, endpoint, endpoint); + + TR_TraceRayFilter(start, endpoint, MASK_PLAYERSOLID, RayType_EndPoint, GCTraceEntityFilterPlayer, client); + + if (TR_DidHit()) + { + TR_GetEndPosition(result); + return true; + } + + result = endpoint; + return false; +} + +/** + * Traces a hull in a certain direction and distance. + * + * @param origin Position to trace from. + * @param direction Trace direction. + * @param mins Minimum size of the hull. + * @param maxs Maximum size of the hull. + * @param result Resultant vector. + * @return True on success, false otherwise. + */ +stock bool GCTraceHullDirection(const float origin[3], + const float direction[3], + const float mins[3], + const float maxs[3], + float result[3], + float distance, + TraceEntityFilter filter, + any data = 0, + int flags = MASK_PLAYERSOLID) +{ + float pos2[3]; + float zsine = Sine(DegToRad(-direction[0])); + float zcos = Cosine(DegToRad(-direction[0])); + + pos2[0] = Cosine(DegToRad(direction[1])) * zcos; + pos2[1] = Sine(DegToRad(direction[1])) * zcos; + pos2[2] = zsine; + + ScaleVector(pos2, distance); + AddVectors(origin, pos2, pos2); + + TR_TraceHullFilter(origin, pos2, mins, maxs, flags, filter, data); + if (TR_DidHit()) + { + TR_GetEndPosition(result); + return true; + } + result = pos2; + return false; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gamechaos/vectors.inc b/source/sourcemod/scripting/include/gamechaos/vectors.inc new file mode 100644 index 0000000..79d5e8f --- /dev/null +++ b/source/sourcemod/scripting/include/gamechaos/vectors.inc @@ -0,0 +1,66 @@ + +#if defined _gamechaos_stocks_vectors_included + #endinput +#endif +#define _gamechaos_stocks_vectors_included + +#define GC_VECTORS_VERSION 0x01_00_01 +#define GC_VECTORS_VERSION_STRING "1.0.1" + +/** + * Calculates the horizontal (x, y) length of a vector. + * + * @param vec Vector. + * @return Vector length (magnitude). + */ +stock float GCGetVectorLength2D(const float vec[3]) +{ + float tempVec[3]; + tempVec = vec; + tempVec[2] = 0.0; + + return GetVectorLength(tempVec); +} + +/** + * Calculates the horizontal (x, y) distance between 2 vectors. + * + * @param x Vector 1. + * @param y Vector 2. + * @param tolerance How close the floats have to be to return true. + * @return True on success, false otherwise. + */ +stock float GCGetVectorDistance2D(const float x[3], const float y[3]) +{ + float x2[3]; + float y2[3]; + + x2 = x; + y2 = y; + + x2[2] = 0.0; + y2[2] = 0.0; + + return GetVectorDistance(x2, y2); +} + +/** + * Checks if 2 vectors are exactly equal. + * + * @param a Vector 1. + * @param b Vector 2. + * @return True on success, false otherwise. + */ +stock bool GCVectorsEqual(const float a[3], const float b[3]) +{ + bool result = true; + for (int i = 0; i < 3; i++) + { + if (a[i] != b[i]) + { + result = false; + break; + } + } + return result; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/geoip.inc b/source/sourcemod/scripting/include/geoip.inc new file mode 100644 index 0000000..0676f75 --- /dev/null +++ b/source/sourcemod/scripting/include/geoip.inc @@ -0,0 +1,241 @@ +/** + * 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 + +enum Continent +{ + CONTINENT_UNKNOWN = 0, + CONTINENT_AFRICA, + CONTINENT_ANTARCTICA, + CONTINENT_ASIA, + CONTINENT_EUROPE, + CONTINENT_NORTH_AMERICA, + CONTINENT_OCEANIA, + CONTINENT_SOUTH_AMERICA, +}; + +// The system of measurement for calculate the distance between geographical coordinates +#define SYSTEM_METRIC 0 // kilometers +#define SYSTEM_IMPERIAL 1 // statute miles + +#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 otherwise. + */ +native bool GeoipCode2(const char[] ip, char 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 otherwise. + */ +native bool GeoipCode3(const char[] ip, char ccode[4]); + +/** + * Gets the region code with country code from an IP address. (US-IL, CH-CHE, etc) + * + * @param ip Ip to determine the region code. + * @param ccode Destination string buffer to store the code. + * @return True on success, false otherwise. + */ +native bool GeoipRegionCode(const char[] ip, char ccode[12]); + +/** + * Gets the two character continent code from an IP address. (EU, AS, etc) + * + * @param ip Ip to determine the continent code. + * @param ccode Destination string buffer to store the code. + * @return The continent id on success, 0 otherwise. + */ +native Continent GeoipContinentCode(const char[] ip, char ccode[3]); + +/** + * Gets the full country name. + * + * @param ip Ip to determine the country code. + * @param name Destination string buffer to store the country name. + * @param maxlength Maximum length of output string buffer. + * @return True on success, false otherwise. + */ +native bool GeoipCountry(const char[] ip, char[] name, int maxlength); + +/** + * Gets the full country name. + * + * @param ip Ip to determine the country code. + * @param name Destination string buffer to store the country name. + * @param maxlength Maximum length of output string buffer. + * @param client Client index in order to return the result in the player's language + * -1: the default language, which is english. + * 0: the server language. You can use LANG_SERVER define. + * >=1: the player's language. + * @return True on success, false otherwise. + */ +native bool GeoipCountryEx(const char[] ip, char[] name, int maxlength, int client = -1); + +/** + * Gets the full continent name. + * + * @param ip Ip to determine the continent code. + * @param name Destination string buffer to store the continent name. + * @param maxlength Maximum length of output string buffer. + * @param client Client index in order to return the result in the player's language + * -1: the default language, which is english. + * 0: the server language. You can use LANG_SERVER define. + * >=1: the player's language. + * @return True on success, false otherwise. + */ +native bool GeoipContinent(const char[] ip, char[] name, int maxlength, int client = -1); + +/** + * Gets the full region name. + * + * @param ip Ip to determine the region code. + * @param name Destination string buffer to store the region name. + * @param maxlength Maximum length of output string buffer. + * @param client Client index in order to return the result in the player's language + * -1: the default language, which is english. + * 0: the server language. You can use LANG_SERVER define. + * >=1: the player's language. + * @return True on success, false otherwise. + */ +native bool GeoipRegion(const char[] ip, char[] name, int maxlength, int client = -1); + +/** + * Gets the city name. + * + * @param ip Ip to determine the city code. + * @param name Destination string buffer to store the city name. + * @param maxlength Maximum length of output string buffer. + * @param client Client index in order to return the result in the player's language + * -1: the default language, which is english. + * 0: the server language. You can use LANG_SERVER define. + * >=1: the player's language. + * @return True on success, false otherwise. + */ +native bool GeoipCity(const char[] ip, char[] name, int maxlength, int client = -1); + +/** + * Gets the timezone. + * + * @param ip Ip to determine the timezone. + * @param name Destination string buffer to store the timezone. + * @param maxlength Maximum length of output string buffer. + * @return True on success, false otherwise. + */ +native bool GeoipTimezone(const char[] ip, char[] name, int maxlength); + +/** + * Gets the city's latitude + * + * @param ip Ip to determine the city latitude. + * @return The result of the latitude, 0 if latitude is not found + */ +native float GeoipLatitude(const char[] ip); + +/** + * Gets the city's longitude + * + * @param ip Ip to determine the city longitude. + * @return The result of the longitude, 0 if longitude is not found + */ +native float GeoipLongitude(const char[] ip); + +/* + * Calculate the distance between geographical coordinates, latitude and longitude. + * + * @param lat1 The first IP latitude. + * @param lon1 The first IP longitude. + * @param lat2 The second IP latitude. + * @param lon2 The second IP longitude. + * @param system The system of measurement, 0 = Metric(kilometers) or 1 = English(miles). + * + * @return The distance as result in specified system of measurement. + */ +native float GeoipDistance(float lat1, float lon1, float lat2, float lon2, int system = SYSTEM_METRIC); + +/** + * @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 void __ext_geoip_SetNTVOptional() +{ + MarkNativeAsOptional("GeoipCode2"); + MarkNativeAsOptional("GeoipCode3"); + MarkNativeAsOptional("GeoipRegionCode"); + MarkNativeAsOptional("GeoipContinentCode"); + MarkNativeAsOptional("GeoipCountry"); + MarkNativeAsOptional("GeoipCountryEx"); + MarkNativeAsOptional("GeoipContinent"); + MarkNativeAsOptional("GeoipRegion"); + MarkNativeAsOptional("GeoipCity"); + MarkNativeAsOptional("GeoipTimezone"); + MarkNativeAsOptional("GeoipLatitude"); + MarkNativeAsOptional("GeoipLongitude"); + MarkNativeAsOptional("GeoipDistance"); +} +#endif diff --git a/source/sourcemod/scripting/include/glib/addressutils.inc b/source/sourcemod/scripting/include/glib/addressutils.inc new file mode 100644 index 0000000..bbe8f14 --- /dev/null +++ b/source/sourcemod/scripting/include/glib/addressutils.inc @@ -0,0 +1,54 @@ +#if defined _addressutils_included +#endinput +#endif +#define _addressutils_included + +methodmap AddressBase +{ + property Address Address + { + public get() { return view_as
(this); } + } +} + +//-==Operator overloadings +stock Address operator+(Address l, int r) +{ + return l + view_as
(r); +} + +stock Address operator+(int l, Address r) +{ + return view_as
(l) + r; +} + +stock Address operator-(Address l, int r) +{ + return l - view_as
(r); +} + +stock Address operator-(int l, Address r) +{ + return view_as
(l) - r; +} + +stock Address operator*(Address l, int r) +{ + return l * view_as
(r); +} + +stock Address operator*(int l, Address r) +{ + return view_as
(l) * r; +} + +stock Address operator/(Address l, int r) +{ + return l / view_as
(r); +} + +stock Address operator/(int l, Address r) +{ + return view_as
(l) / r; +} +//Operator overloadings==- \ No newline at end of file diff --git a/source/sourcemod/scripting/include/glib/assertutils.inc b/source/sourcemod/scripting/include/glib/assertutils.inc new file mode 100644 index 0000000..83cd90d --- /dev/null +++ b/source/sourcemod/scripting/include/glib/assertutils.inc @@ -0,0 +1,61 @@ +#if defined _assertutils_included +#endinput +#endif +#define _assertutils_included + +/* Compile time settings for this include. Should be defined before including this file. +* #define ASSERTUTILS_DISABLE //Disables all assertions +* #define ASSERTUTILS_FAILSTATE_FUNC //Define the name of the function that should be called when assertion is hit +*/ + +#if !defined SNAME +#define __SNAME "" +#else +#define __SNAME SNAME +#endif + +#define ASSERT_FMT_STRING_LEN 512 + +#if defined ASSERTUTILS_DISABLE + +#define ASSERT(%1)%2; +#define ASSERT_MSG(%1,%2)%3; +#define ASSERT_FMT(%1,%2)%3; +#define ASSERT_FINAL(%1)%2; +#define ASSERT_FINAL_MSG(%1,%2)%3; + +#elseif defined ASSERTUTILS_FAILSTATE_FUNC + +#define ASSERT(%1) if(!(%1)) ASSERTUTILS_FAILSTATE_FUNC(__SNAME..."Assertion failed: \""...#%1..."\"") +#define ASSERT_MSG(%1,%2) if(!(%1)) ASSERTUTILS_FAILSTATE_FUNC(__SNAME...%2) +#define ASSERT_FMT(%1,%2) if(!(%1)) ASSERTUTILS_FAILSTATE_FUNC(__SNAME...%2) +#define ASSERT_FINAL(%1) if(!(%1)) SetFailState(__SNAME..."Assertion failed: \""...#%1..."\"") +#define ASSERT_FINAL_MSG(%1,%2) if(!(%1)) SetFailState(__SNAME...%2) + +#else + +#define ASSERT(%1) if(!(%1)) SetFailState(__SNAME..."Assertion failed: \""...#%1..."\"") +#define ASSERT_MSG(%1,%2) if(!(%1)) SetFailState(__SNAME...%2) +#define ASSERT_FMT(%1,%2) if(!(%1)) SetFailState(__SNAME...%2) +#define ASSERT_FINAL(%1) ASSERT(%1) +#define ASSERT_FINAL_MSG(%1,%2) ASSERT_MSG(%1,%2) + +#endif + +// Might be redundant as default ASSERT_MSG accept format arguments just fine. +#if 0 +stock void ASSERT_FMT(bool result, char[] fmt, any ...) +{ +#if !defined ASSERTUTILS_DISABLE + if(!result) + { + char buff[ASSERT_FMT_STRING_LEN]; + VFormat(buff, sizeof(buff), fmt, 3); + + SetFailState(__SNAME..."%s", buff); + } +#endif +} +#endif + +#undef ASSERT_FMT_STRING_LEN \ No newline at end of file diff --git a/source/sourcemod/scripting/include/glib/memutils.inc b/source/sourcemod/scripting/include/glib/memutils.inc new file mode 100644 index 0000000..5813d92 --- /dev/null +++ b/source/sourcemod/scripting/include/glib/memutils.inc @@ -0,0 +1,232 @@ +#if defined _memutils_included +#endinput +#endif +#define _memutils_included + +#include "glib/assertutils" +#include "glib/addressutils" + +/* Compile time settings for this include. Should be defined before including this file. +* #define MEMUTILS_PLUGINENDCALL //This should be defined if main plugin has OnPluginEnd() forward used. +*/ + +#define MEM_LEN_SAFE_THRESHOLD 2000 + +//-==PatchHandling methodmap +static StringMap gPatchStack; + +methodmap PatchHandler < AddressBase +{ + public PatchHandler(Address addr) + { + ASSERT(addr != Address_Null); + + if(!gPatchStack) + gPatchStack = new StringMap(); + + return view_as(addr); + } + + property any Any + { + public get() { return view_as(this); } + } + + public void Save(int len) + { + ASSERT(gPatchStack); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + len++; + + int[] arr = new int[len]; + arr[0] = len; + + for(int i = 0; i < len - 1; i++) + arr[i + 1] = LoadFromAddress(this.Address + i, NumberType_Int8); + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + gPatchStack.SetArray(buff, arr, len); + } + + public void PatchNSave(int len, char byte = 0x90) + { + ASSERT(gPatchStack); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + len++; + + int[] arr = new int[len]; + arr[0] = len; + + for(int i = 0; i < len - 1; i++) + { + arr[i + 1] = LoadFromAddress(this.Address + i, NumberType_Int8); + StoreToAddress(this.Address + i, byte, NumberType_Int8); + } + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + gPatchStack.SetArray(buff, arr, len); + } + + public void PatchNSaveSeq(const char[] data, int len) + { + ASSERT(gPatchStack); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + len++; + + int[] arr = new int[len]; + arr[0] = len; + + for(int i = 0; i < len - 1; i++) + { + arr[i + 1] = LoadFromAddress(this.Address + i, NumberType_Int8); + StoreToAddress(this.Address + i, data[i], NumberType_Int8); + } + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + gPatchStack.SetArray(buff, arr, len); + } + + public void Restore() + { + if(!gPatchStack) + return; + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + + int arrSize[1]; + if(!gPatchStack.GetArray(buff, arrSize, sizeof(arrSize))) + return; + + int[] arr = new int[arrSize[0]]; + gPatchStack.GetArray(buff, arr, arrSize[0]); + gPatchStack.Remove(buff); + + for(int i = 0; i < arrSize[0] - 1; i++) + StoreToAddress(this.Address + i, arr[i + 1], NumberType_Int8); + + if(gPatchStack.Size == 0) + delete gPatchStack; + } +} + +public void OnPluginEnd() +{ + if(gPatchStack) + { + StringMapSnapshot sms = gPatchStack.Snapshot(); + char buff[32]; + Address addr; + + for(int i = 0; i < sms.Length; i++) + { + sms.GetKey(i, buff, sizeof(buff)); + addr = view_as
(StringToInt(buff)); + view_as(addr).Restore(); + } + } + +#if defined MEMUTILS_PLUGINENDCALL + OnPluginEnd_MemUtilsRedefined(); +#endif +} +#undef OnPluginEnd +#if defined MEMUTILS_PLUGINENDCALL +#define OnPluginEnd OnPluginEnd_MemUtilsRedefined +#else +#define OnPluginEnd OnPluginEnd_Redifined(){}\ +void MEMUTILS_INCLUDE_WARNING_OnPluginEnd_REDIFINITION +#endif +//PatchHandling methodmap==- + +//-==Other util functions +stock int LoadStringFromAddress(Address addr, char[] buff, int length) +{ + int i; + for(i = 0; i < length && (buff[i] = LoadFromAddress(addr + i, NumberType_Int8)) != '\0'; i++) { } + buff[i == length ? i - 1 : i] = '\0'; + return i; +} + +stock void DumpOnAddress(Address addr, int len, int columns = 10) +{ + char buff[128], buff2[128]; + + ASSERT(addr != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + Format(buff, sizeof(buff), "[0x%08X]", addr); + char chr; + for(int i = 0; i < len; i++) + { + chr = LoadFromAddress(addr + i, NumberType_Int8); + Format(buff, sizeof(buff), "%s %02X", buff, chr); + Format(buff2, sizeof(buff2), "%s%c", buff2, (chr > ' ' && chr != 0x7F && chr != 0xFF ? chr : '.')); + if(i % columns == columns - 1) + { + PrintToServer(__SNAME..."%s %s", buff, buff2); + Format(buff, sizeof(buff), "[0x%08X]", addr + i); + buff2[0] = '\0'; + } + } + + if((len - 1) % columns != columns - 1) + PrintToServer(__SNAME..."%s %s", buff, buff2); +} + +//NO OVERLAPPING!! +stock void MoveBytes(Address from, Address to, int len, char replace_with = 0x90) +{ + ASSERT(from != Address_Null); + ASSERT(to != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + ASSERT(to < from || to > from + len); + + if(from == to) + return; + + for(int i = 0; i < len; i++) + { + StoreToAddress(to + i, LoadFromAddress(from + i, NumberType_Int8), NumberType_Int8); + StoreToAddress(from + i, replace_with, NumberType_Int8); + } +} + +stock void CutNCopyBytes(Address from, Address to, int len, char replace_with = 0x90) +{ + ASSERT(from != Address_Null); + ASSERT(to != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + if(from == to) + return; + + int[] arr = new int[len]; + + for(int i = 0; i < len; i++) + { + arr[i] = LoadFromAddress(from + i, NumberType_Int8); + StoreToAddress(from + i, replace_with, NumberType_Int8); + } + + for(int i = 0; i < len; i++) + StoreToAddress(to + i, arr[i], NumberType_Int8); +} + +stock void PatchArea(Address addr, int len, char byte = 0x90) +{ + ASSERT(addr != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + for(int i = 0; i < len; i++) + StoreToAddress(addr + i, byte, NumberType_Int8); +} +//Other util functions==- + +#undef MEM_LEN_SAFE_THRESHOLD \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz.inc b/source/sourcemod/scripting/include/gokz.inc new file mode 100644 index 0000000..edbd896 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz.inc @@ -0,0 +1,1097 @@ +/* + GOKZ General Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_included_ +#endinput +#endif +#define _gokz_included_ +#include +#include + +#include + + + +// =====[ ENUMS ]===== + +enum ObsMode +{ + ObsMode_None = 0, // Not in spectator mode + ObsMode_DeathCam, // Special mode for death cam animation + ObsMode_FreezeCam, // Zooms to a target, and freeze-frames on them + ObsMode_Fixed, // View from a fixed camera position + ObsMode_InEye, // Follow a player in first person view + ObsMode_Chase, // Follow a player in third person view + ObsMode_Roaming // Free roaming +}; + + + +// =====[ CONSTANTS ]===== + +#define GOKZ_SOURCE_URL "https://github.com/KZGlobalTeam/gokz" +#define GOKZ_UPDATER_BASE_URL "http://updater.gokz.org/v2/" +#define GOKZ_COLLISION_GROUP_STANDARD 2 +#define GOKZ_COLLISION_GROUP_NOTRIGGER 1 +#define GOKZ_TP_FREEZE_TICKS 5 +#define EPSILON 0.000001 +#define PI 3.14159265359 +#define SPEED_NORMAL 250.0 +#define SPEED_NO_WEAPON 260.0 +#define FLOAT_MAX view_as(0x7F7FFFFF) +#define SF_BUTTON_USE_ACTIVATES 1024 +#define IGNORE_JUMP_TIME 0.2 +stock float PLAYER_MINS[3] = {-16.0, -16.0, 0.0}; +stock float PLAYER_MAXS[3] = {16.0, 16.0, 72.0}; +stock float PLAYER_MAXS_DUCKED[3] = {16.0, 16.0, 54.0}; + + + +// =====[ STOCKS ]===== + +/** + * Represents a time float as a string e.g. 01:23.45. + * + * @param time Time in seconds. + * @param precise Whether to include fractional seconds. + * @return String representation of time. + */ +stock char[] GOKZ_FormatTime(float time, bool precise = true) +{ + char formattedTime[12]; + + int roundedTime = RoundFloat(time * 100); // Time rounded to number of centiseconds + + int centiseconds = roundedTime % 100; + roundedTime = (roundedTime - centiseconds) / 100; + int seconds = roundedTime % 60; + roundedTime = (roundedTime - seconds) / 60; + int minutes = roundedTime % 60; + roundedTime = (roundedTime - minutes) / 60; + int hours = roundedTime; + + if (hours == 0) + { + if (precise) + { + FormatEx(formattedTime, sizeof(formattedTime), "%02d:%02d.%02d", minutes, seconds, centiseconds); + } + else + { + FormatEx(formattedTime, sizeof(formattedTime), "%d:%02d", minutes, seconds); + } + } + else + { + if (precise) + { + FormatEx(formattedTime, sizeof(formattedTime), "%d:%02d:%02d.%02d", hours, minutes, seconds, centiseconds); + } + else + { + FormatEx(formattedTime, sizeof(formattedTime), "%d:%02d:%02d", hours, minutes, seconds); + } + } + return formattedTime; +} + +/** + * Checks if the value is a valid client entity index, if they are in-game and not GOTV. + * + * @param client Client index. + * @return Whether client is valid. + */ +stock bool IsValidClient(int client) +{ + return client >= 1 && client <= MaxClients && IsClientInGame(client) && !IsClientSourceTV(client); +} + +/** + * Returns the greater of two float values. + * + * @param value1 First value. + * @param value2 Second value. + * @return Greatest value. + */ +stock float FloatMax(float value1, float value2) +{ + if (value1 >= value2) + { + return value1; + } + return value2; +} + +/** + * Returns the lesser of two float values. + * + * @param value1 First value. + * @param value2 Second value. + * @return Lesser value. + */ +stock float FloatMin(float value1, float value2) +{ + if (value1 <= value2) + { + return value1; + } + return value2; +} + +/** + * Clamp a float value between an upper and lower bound. + * + * @param value Preferred value. + * @param min Minimum value. + * @param max Maximum value. + * @return The closest value to the preferred value. + */ +stock float FloatClamp(float value, float min, float max) +{ + if (value >= max) + { + return max; + } + if (value <= min) + { + return min; + } + return value; +} + + +/** + * Returns the greater of two int values. + * + * @param value1 First value. + * @param value2 Second value. + * @return Greatest value. + */ +stock int IntMax(int value1, int value2) +{ + if (value1 >= value2) + { + return value1; + } + return value2; +} + +/** + * Returns the lesser of two int values. + * + * @param value1 First value. + * @param value2 Second value. + * @return Lesser value. + */ +stock int IntMin(int value1, int value2) +{ + if (value1 <= value2) + { + return value1; + } + return value2; +} + +/** + * Rounds a float to the nearest specified power of 10. + * + * @param value Value to round. + * @param power Power of 10 to round to. + * @return Rounded value. + */ +stock float RoundToPowerOfTen(float value, int power) +{ + float pow = Pow(10.0, float(power)); + return RoundFloat(value / pow) * pow; +} + +/** + * Sets all characters in a string to lower case. + * + * @param input Input string. + * @param output Output buffer. + * @param size Maximum size of output. + */ +stock void String_ToLower(const char[] input, char[] output, int size) +{ + size--; + int i = 0; + while (input[i] != '\0' && i < size) + { + output[i] = CharToLower(input[i]); + i++; + } + output[i] = '\0'; +} + +/** + * Gets the client's observer mode. + * + * @param client Client index. + * @return Current observer mode. + */ +stock ObsMode GetObserverMode(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_iObserverMode")); +} + +/** + * Gets the player a client is spectating. + * + * @param client Client index. + * @return Client index of target, or -1 if not spectating anyone. + */ +stock int GetObserverTarget(int client) +{ + if (!IsValidClient(client)) + { + return -1; + } + ObsMode mode = GetObserverMode(client); + if (mode == ObsMode_InEye || mode == ObsMode_Chase) + { + return GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); + } + return -1; +} + +/** + * Emits a sound to other players that are spectating the client. + * + * @param client Client being spectated. + * @param sound Sound to play. + */ +stock void EmitSoundToClientSpectators(int client, const char[] sound) +{ + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && GetObserverTarget(i) == client) + { + EmitSoundToClient(i, sound); + } + } +} + +/** + * Calculates the lowest angle from angle A to angle B. + * Input and result angles are between -180 and 180. + * + * @param angleA Angle A. + * @param angleB Angle B. + * @return Delta angle. + */ +stock float CalcDeltaAngle(float angleA, float angleB) +{ + float difference = angleB - angleA; + + if (difference > 180.0) + { + difference = difference - 360.0; + } + else if (difference <= -180.0) + { + difference = difference + 360.0; + } + + return difference; +} + +/** + * Strips all color control characters in a string. + * The Output buffer can be the same as the input buffer. + * Original code by Psychonic, thanks. + * Source: smlib + * + * @param input Input String. + * @param output Output String. + * @param size Max Size of the Output string + */ +stock void Color_StripFromChatText(const char[] input, char[] output, int size) +{ + int x = 0; + for (int i = 0; input[i] != '\0'; i++) { + + if (x + 1 == size) + { + break; + } + + int character = input[i]; + + if (character > 0x08) + { + output[x++] = character; + } + } + + output[x] = '\0'; +} + +/** + * Returns an integer as a string. + * + * @param num Integer to stringify. + * @return Integer as a string. + */ +stock char[] IntToStringEx(int num) +{ + char string[12]; + IntToString(num, string, sizeof(string)); + return string; +} + +/** + * Returns a float as a string. + * + * @param num Float to stringify. + * @return Float as a string. + */ +stock char[] FloatToStringEx(float num) +{ + char string[32]; + FloatToString(num, string, sizeof(string)); + return string; +} + +/** + * Increment an index, looping back to 0 if the max value is reached. + * + * @param index Current index. + * @param buffer Max value of index. + * @return Current index incremented, or 0 if max value is reached. + */ +stock int NextIndex(int index, int max) +{ + index++; + if (index == max) + { + return 0; + } + return index; +} + +/** + * Reorders an array with current index at the front, and previous + * values after, including looping back to the end after reaching + * the start of the array. + * + * @param input Array to reorder. + * @param inputSize Size of input array. + * @param buffer Output buffer. + * @param bufferSize Size of buffer. + * @param index Index of current/most recent value of input array. + */ +stock void SortByRecent(const int[] input, int inputSize, int[] buffer, int bufferSize, int index) +{ + int reorderedIndex = 0; + for (int i = index; reorderedIndex < bufferSize && i >= 0; i--) + { + buffer[reorderedIndex] = input[i]; + reorderedIndex++; + } + for (int i = inputSize - 1; reorderedIndex < bufferSize && i > index; i--) + { + buffer[reorderedIndex] = input[i]; + reorderedIndex++; + } +} + +/** + * Returns the Steam account ID for a given SteamID2. + * Checks for invalid input are not very extensive. + * + * @param steamID2 SteamID2 to convert. + * @return Steam account ID, or -1 if invalid. + */ +stock int Steam2ToSteamAccountID(const char[] steamID2) +{ + char pieces[3][16]; + if (ExplodeString(steamID2, ":", pieces, sizeof(pieces), sizeof(pieces[])) != 3) + { + return -1; + } + + int IDNumberPart1 = StringToInt(pieces[1]); + int IDNumberPart2 = StringToInt(pieces[2]); + if (pieces[1][0] != '0' && IDNumberPart1 == 0 || IDNumberPart1 != 0 && IDNumberPart1 != 1 || IDNumberPart2 <= 0) + { + return -1; + } + + return IDNumberPart1 + (IDNumberPart2 << 1); +} + +/** + * Teleports a player and removes their velocity and base velocity + * immediately and also every tick for the next 5 ticks. Automatically + * makes the player crouch if there is a ceiling above them. + * + * @param client Client index. + * @param origin Origin to teleport to. + * @param angles Eye angles to set. + */ +stock void TeleportPlayer(int client, const float origin[3], const float angles[3], bool setAngles = true, bool holdStill = true) +{ + // Clear the player's parent before teleporting to fix being + // teleported into seemingly random places if the player has a parent. + AcceptEntityInput(client, "ClearParent"); + + Movement_SetOrigin(client, origin); + Movement_SetVelocity(client, view_as( { 0.0, 0.0, 0.0 } )); + Movement_SetBaseVelocity(client, view_as( { 0.0, 0.0, 0.0 } )); + if (setAngles) + { + // NOTE: changing angles with TeleportEntity can fail due to packet loss!!! + // (Movement_SetEyeAngles is a thin wrapper of TeleportEntity) + Movement_SetEyeAngles(client, angles); + } + // Duck the player if there is something blocking them from above + Handle trace = TR_TraceHullFilterEx(origin, + origin, + view_as( { -16.0, -16.0, 0.0 } ), // Standing players are 32 x 32 x 72 + view_as( { 16.0, 16.0, 72.0 } ), + MASK_PLAYERSOLID, + TraceEntityFilterPlayers, + client); + bool ducked = TR_DidHit(trace); + + if (holdStill) + { + // Prevent noclip exploit + SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD); + + // Intelligently hold player still to prevent booster and trigger exploits + StartHoldStill(client, ducked); + } + else if (ducked) + { + ForcePlayerDuck(client); + } + + delete trace; +} + +static void StartHoldStill(int client, bool ducked) +{ + DataPack data = new DataPack(); + data.WriteCell(GetClientUserId(client)); + data.WriteCell(0); // tick counter + data.WriteCell(GOKZ_TP_FREEZE_TICKS); // number of ticks to hold still + data.WriteCell(ducked); + ContinueHoldStill(data); +} + +public void ContinueHoldStill(DataPack data) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int ticks = data.ReadCell(); + int tickCount = data.ReadCell(); + bool ducked = data.ReadCell(); + delete data; + + if (!IsValidClient(client)) + { + return; + } + + if (ticks < tickCount) + { + Movement_SetVelocity(client, view_as( { 0.0, 0.0, 0.0 } )); + Movement_SetBaseVelocity(client, view_as( { 0.0, 0.0, 0.0 } )); + Movement_SetGravity(client, 1.0); + + // Don't drop the player off of ladders. + // The game will automatically change the movetype back to MOVETYPE_WALK if it can't find a ladder. + // Don't change the movetype if it's currently MOVETYPE_NONE, as that means the player is paused. + if (Movement_GetMovetype(client) != MOVETYPE_NONE) + { + Movement_SetMovetype(client, MOVETYPE_LADDER); + } + + // Prevent noclip exploit + SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD); + + // Force duck on player and make sure that the player can't trigger triggers above them. + // they can still trigger triggers even when we force ducking. + if (ducked) + { + ForcePlayerDuck(client); + + if (ticks < tickCount - 1) + { + // Don't trigger triggers + SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_NOTRIGGER); + } + else + { + // Let the player trigger triggers on the last tick + SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD); + } + } + + ++ticks; + data = new DataPack(); + data.WriteCell(GetClientUserId(client)); + data.WriteCell(ticks); + data.WriteCell(tickCount); + data.WriteCell(ducked); + RequestFrame(ContinueHoldStill, data); + } +} + +/** + * Forces the player to instantly duck. + * + * @param client Client index. + */ +stock void ForcePlayerDuck(int client) +{ + // these are both necessary, because on their own the player will sometimes still be in a state that isn't fully ducked. + SetEntPropFloat(client, Prop_Send, "m_flDuckAmount", 1.0, 0); + SetEntProp(client, Prop_Send, "m_bDucking", false); + SetEntProp(client, Prop_Send, "m_bDucked", true); +} + +/** + * Returns whether the player is stuck e.g. in a wall after noclipping. + * + * @param client Client index. + * @return Whether player is stuck. + */ +stock bool IsPlayerStuck(int client) +{ + float vecMin[3], vecMax[3], vecOrigin[3]; + + GetClientMins(client, vecMin); + GetClientMaxs(client, vecMax); + GetClientAbsOrigin(client, vecOrigin); + + TR_TraceHullFilter(vecOrigin, vecOrigin, vecMin, vecMax, MASK_PLAYERSOLID, TraceEntityFilterPlayers); + return TR_DidHit(); // head in wall ? +} + +/** + * Retrieves the absolute origin of an entity. + * + * @param entity Index of the entity. + * @param result Entity's origin if successful. + * @return Returns true if successful. + */ +stock bool GetEntityAbsOrigin(int entity, float result[3]) +{ + if (!IsValidEntity(entity)) + { + return false; + } + + if (!HasEntProp(entity, Prop_Data, "m_vecAbsOrigin")) + { + return false; + } + + GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", result); + return true; +} + +/** + * Retrieves the name of an entity. + * + * @param entity Index of the entity. + * @param buffer Buffer to store the name. + * @param maxlength Maximum length of the buffer. + * @return Number of non-null bytes written. + */ +stock int GetEntityName(int entity, char[] buffer, int maxlength) +{ + return GetEntPropString(entity, Prop_Data, "m_iName", buffer, maxlength); +} + +/** + * Finds an entity by name or by name and classname. + * Taken from smlib https://github.com/bcserv/smlib + * This can take anywhere from ~0.2% to ~11% of frametime (i5-7600k) in the worst case scenario where + * every entity which has a name (4096 of them) is iterated over. Your mileage may vary. + * + * @param name Name of the entity to find. + * @param className Optional classname to match along with name. + * @param ignorePlayers Ignore player entities. + * @return Entity index if successful, INVALID_ENT_REFERENCE if not. + */ +stock int GOKZFindEntityByName(const char[] name, const char[] className = "", bool ignorePlayers = false) +{ + int result = INVALID_ENT_REFERENCE; + if (className[0] == '\0') + { + // HACK: Double the limit to get non-networked entities too. + // https://developer.valvesoftware.com/wiki/Entity_limit + int realMaxEntities = GetMaxEntities() * 2; + int startEntity = 1; + if (ignorePlayers) + { + startEntity = MaxClients + 1; + } + for (int entity = startEntity; entity < realMaxEntities; entity++) + { + if (!IsValidEntity(entity)) + { + continue; + } + + char entName[65]; + GetEntityName(entity, entName, sizeof(entName)); + if (StrEqual(entName, name)) + { + result = entity; + break; + } + } + } + else + { + int entity = INVALID_ENT_REFERENCE; + while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) + { + char entName[65]; + GetEntityName(entity, entName, sizeof(entName)); + if (StrEqual(entName, name)) + { + result = entity; + break; + } + } + } + return result; +} + +/** + * Gets the current map's display name in lower case. + * + * @param buffer Buffer to store the map name. + * @param maxlength Maximum length of buffer. + */ +stock void GetCurrentMapDisplayName(char[] buffer, int maxlength) +{ + char map[PLATFORM_MAX_PATH]; + GetCurrentMap(map, sizeof(map)); + GetMapDisplayName(map, map, sizeof(map)); + String_ToLower(map, buffer, maxlength); +} + +/** + * Gets the current map's file size. + */ +stock int GetCurrentMapFileSize() +{ + char mapBuffer[PLATFORM_MAX_PATH]; + GetCurrentMap(mapBuffer, sizeof(mapBuffer)); + Format(mapBuffer, sizeof(mapBuffer), "maps/%s.bsp", mapBuffer); + return FileSize(mapBuffer); +} + +/** + * Copies the elements of a source vector to a destination vector. + * + * @param src Source vector. + * @param dest Destination vector. + */ +stock void CopyVector(const any src[3], any dest[3]) +{ + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; +} + +/** + * Returns whether the player is spectating. + * + * @param client Client index. + */ +stock bool IsSpectating(int client) +{ + int team = GetClientTeam(client); + return team == CS_TEAM_SPECTATOR || team == CS_TEAM_NONE; +} + +/** + * Rotate a vector on an axis. + * + * @param vec Vector to rotate. + * @param axis Axis to rotate around. + * @param theta Angle in radians. + * @param result Rotated vector. + */ +stock void RotateVectorAxis(float vec[3], float axis[3], float theta, float result[3]) +{ + float cosTheta = Cosine(theta); + float sinTheta = Sine(theta); + + float axisVecCross[3]; + GetVectorCrossProduct(axis, vec, axisVecCross); + + for (int i = 0; i < 3; i++) + { + result[i] = (vec[i] * cosTheta) + (axisVecCross[i] * sinTheta) + (axis[i] * GetVectorDotProduct(axis, vec)) * (1.0 - cosTheta); + } +} + +/** + * Rotate a vector by pitch and yaw. + * + * @param vec Vector to rotate. + * @param pitch Pitch angle (in degrees). + * @param yaw Yaw angle (in degrees). + * @param result Rotated vector. + */ +stock void RotateVectorPitchYaw(float vec[3], float pitch, float yaw, float result[3]) +{ + if (pitch != 0.0) + { + RotateVectorAxis(vec, view_as({0.0, 1.0, 0.0}), DegToRad(pitch), result); + } + if (yaw != 0.0) + { + RotateVectorAxis(result, view_as({0.0, 0.0, 1.0}), DegToRad(yaw), result); + } +} + +/** + * Attempts to return a valid spawn location. + * + * @param origin Spawn origin if found. + * @param angles Spawn angles if found. + * @return Whether a valid spawn point is found. + */ +stock bool GetValidSpawn(float origin[3], float angles[3]) +{ + // Return true if the spawn found is truly valid (not in the ground or out of bounds) + bool foundValidSpawn; + bool searchCT; + float spawnOrigin[3]; + float spawnAngles[3]; + int spawnEntity = -1; + while (!foundValidSpawn) + { + if (searchCT) + { + spawnEntity = FindEntityByClassname(spawnEntity, "info_player_counterterrorist"); + } + else + { + spawnEntity = FindEntityByClassname(spawnEntity, "info_player_terrorist"); + } + + if (spawnEntity != -1) + { + GetEntPropVector(spawnEntity, Prop_Data, "m_vecOrigin", spawnOrigin); + GetEntPropVector(spawnEntity, Prop_Data, "m_angRotation", spawnAngles); + if (IsSpawnValid(spawnOrigin)) + { + origin = spawnOrigin; + angles = spawnAngles; + foundValidSpawn = true; + } + } + else if (!searchCT) + { + searchCT = true; + } + else + { + break; + } + } + return foundValidSpawn; +} + +/** + * Check whether a position is a valid spawn location. + * A spawn location is considered valid if it is in bounds and not stuck inside the ground. + * + * @param origin Origin vector. + * @return Whether the origin is a valid spawn location. + */ +stock bool IsSpawnValid(float origin[3]) +{ + Handle trace = TR_TraceHullFilterEx(origin, origin, PLAYER_MINS, PLAYER_MAXS, MASK_PLAYERSOLID, TraceEntityFilterPlayers); + if (!TR_StartSolid(trace) && !TR_AllSolid(trace) && TR_GetFraction(trace) == 1.0) + { + delete trace; + return true; + } + delete trace; + return false; +} + +/** + * Get an entity's origin, angles, its bounding box's center and the distance from the center to its bounding box's edges. + * + * @param entity Index of the entity. + * @param origin Entity's origin. + * @param center Center of the entity's bounding box. + * @param angles Entity's angles. + * @param distFromCenter The distance between the center of the entity's bounding box and its edges. + */ +stock void GetEntityPositions(int entity, float origin[3], float center[3], float angles[3], float distFromCenter[3]) +{ + int ent = entity; + float maxs[3], mins[3]; + GetEntPropVector(ent, Prop_Send, "m_vecOrigin", origin); + // Take parent entities into account. + while (GetEntPropEnt(ent, Prop_Send, "moveparent") != -1) + { + ent = GetEntPropEnt(ent, Prop_Send, "moveparent"); + float tempOrigin[3]; + GetEntPropVector(ent, Prop_Send, "m_vecOrigin", tempOrigin); + for (int i = 0; i < 3; i++) + { + origin[i] += tempOrigin[i]; + } + } + + GetEntPropVector(ent, Prop_Data, "m_angRotation", angles); + + GetEntPropVector(ent, Prop_Send, "m_vecMaxs", maxs); + GetEntPropVector(ent, Prop_Send, "m_vecMins", mins); + for (int i = 0; i < 3; i++) + { + center[i] = origin[i] + (maxs[i] + mins[i]) / 2; + distFromCenter[i] = (maxs[i] - mins[i]) / 2; + } +} + +/** + * Find a valid position around a timer. + * + * @param entity Index of the timer entity. + * @param originDest Result origin if a valid position is found. + * @param anglesDest Result angles if a valid position is found. + * @return Whether a valid position is found. + */ +stock bool FindValidPositionAroundTimerEntity(int entity, float originDest[3], float anglesDest[3], bool isButton) +{ + float origin[3], center[3], angles[3], distFromCenter[3]; + GetEntityPositions(entity, origin, center, angles, distFromCenter); + float extraOffset[3]; + if (isButton) // Test several positions within button press range. + { + extraOffset[0] = 32.0; + extraOffset[1] = 32.0; + extraOffset[2] = 32.0; + } + else // Test positions at the inner surface of the zone. + { + extraOffset[0] = -(PLAYER_MAXS[0] - PLAYER_MINS[0]) - 1.03125; + extraOffset[1] = -(PLAYER_MAXS[1] - PLAYER_MINS[1]) - 1.03125; + extraOffset[2] = -(PLAYER_MAXS[2] - PLAYER_MINS[2]) - 1.03125; + } + if (FindValidPositionAroundCenter(center, distFromCenter, extraOffset, originDest, anglesDest)) + { + return true; + } + // Test the positions right next to the timer button/zones if the tests above fail. + // This can fail when the timer has a cover brush over it. + extraOffset[0] = 0.03125; + extraOffset[1] = 0.03125; + extraOffset[2] = 0.03125; + return FindValidPositionAroundCenter(center, distFromCenter, extraOffset, originDest, anglesDest); +} + +static bool FindValidPositionAroundCenter(float center[3], float distFromCenter[3], float extraOffset[3], float originDest[3], float anglesDest[3]) +{ + float testOrigin[3]; + int x, y; + + for (int i = 0; i < 3; i++) + { + // The search starts from the center then outwards to opposite directions. + x = i == 2 ? -1 : i; + for (int j = 0; j < 3; j++) + { + y = j == 2 ? -1 : j; + for (int z = -1; z <= 1; z++) + { + testOrigin = center; + testOrigin[0] = testOrigin[0] + (distFromCenter[0] + extraOffset[0]) * x + (PLAYER_MAXS[0] - PLAYER_MINS[0]) * x * 0.5; + testOrigin[1] = testOrigin[1] + (distFromCenter[1] + extraOffset[1]) * y + (PLAYER_MAXS[1] - PLAYER_MINS[1]) * y * 0.5; + testOrigin[2] = testOrigin[2] + (distFromCenter[2] + extraOffset[2]) * z + (PLAYER_MAXS[2] - PLAYER_MINS[2]) * z; + + // Check if there's a line of sight towards the zone as well. + if (IsSpawnValid(testOrigin) && CanSeeBox(testOrigin, center, distFromCenter)) + { + originDest = testOrigin; + // Always look towards the center. + float offsetVector[3]; + offsetVector[0] = -(distFromCenter[0] + extraOffset[0]) * x; + offsetVector[1] = -(distFromCenter[1] + extraOffset[1]) * y; + offsetVector[2] = -(distFromCenter[2] + extraOffset[2]) * z; + GetVectorAngles(offsetVector, anglesDest); + anglesDest[2] = 0.0; // Roll should always be 0.0 + return true; + } + } + } + } + return false; +} + +static bool CanSeeBox(float origin[3], float center[3], float distFromCenter[3]) +{ + float traceOrigin[3], traceDest[3], mins[3], maxs[3]; + + CopyVector(origin, traceOrigin); + + + SubtractVectors(center, distFromCenter, mins); + AddVectors(center, distFromCenter, maxs); + + for (int i = 0; i < 3; i++) + { + mins[i] += 0.03125; + maxs[i] -= 0.03125; + traceDest[i] = FloatClamp(traceOrigin[i], mins[i], maxs[i]); + } + int mask = (MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS) & ~CONTENTS_OPAQUE; + Handle trace = TR_TraceRayFilterEx(traceOrigin, traceDest, mask, RayType_EndPoint, TraceEntityFilterPlayers); + if (TR_DidHit(trace)) + { + float end[3]; + TR_GetEndPosition(end, trace); + for (int i = 0; i < 3; i++) + { + if (end[i] != traceDest[i]) + { + delete trace; + return false; + } + } + } + delete trace; + return true; +} + +/** + * Gets entity index from the address to an entity. + * + * @param pEntity Entity address. + * @return Entity index. + * @error Couldn't find offset for m_angRotation, m_vecViewOffset, couldn't confirm offset of m_RefEHandle. + */ +stock int GOKZGetEntityFromAddress(Address pEntity) +{ + static int offs_RefEHandle; + if (offs_RefEHandle) + { + return EntRefToEntIndex(LoadFromAddress(pEntity + view_as
(offs_RefEHandle), NumberType_Int32) | (1 << 31)); + } + + // if we don't have it already, attempt to lookup offset based on SDK information + // CWorld is derived from CBaseEntity so it should have both offsets + int offs_angRotation = FindDataMapInfo(0, "m_angRotation"), offs_vecViewOffset = FindDataMapInfo(0, "m_vecViewOffset"); + if (offs_angRotation == -1) + { + SetFailState("Could not find offset for ((CBaseEntity) CWorld)::m_angRotation"); + } + else if (offs_vecViewOffset == -1) + { + SetFailState("Could not find offset for ((CBaseEntity) CWorld)::m_vecViewOffset"); + } + else if ((offs_angRotation + 0x0C) != (offs_vecViewOffset - 0x04)) + { + char game[32]; + GetGameFolderName(game, sizeof(game)); + SetFailState("Could not confirm offset of CBaseEntity::m_RefEHandle (incorrect assumption for game '%s'?)", game); + } + + // offset seems right, cache it for the next call + offs_RefEHandle = offs_angRotation + 0x0C; + return GOKZGetEntityFromAddress(pEntity); +} + +/** + * Gets client index from CGameMovement class. + * + * @param addr Address of CGameMovement class. + * @param offsetCGameMovement_player Offset of CGameMovement::player. + * @return Client index. + * @error Couldn't find offset for m_angRotation, m_vecViewOffset, couldn't confirm offset of m_RefEHandle. + */ +stock int GOKZGetClientFromGameMovementAddress(Address addr, int offsetCGameMovement_player) +{ + Address playerAddr = view_as
(LoadFromAddress(view_as
(view_as(addr) + offsetCGameMovement_player), NumberType_Int32)); + return GOKZGetEntityFromAddress(playerAddr); +} + +/** + * Gets the nearest point in the oriented bounding box of an entity to a point. + * + * @param entity Entity index. + * @param origin Point's origin. + * @param result Result point. + */ +stock void CalcNearestPoint(int entity, float origin[3], float result[3]) +{ + float entOrigin[3], entMins[3], entMaxs[3], trueMins[3], trueMaxs[3]; + GetEntPropVector(entity, Prop_Send, "m_vecOrigin", entOrigin); + GetEntPropVector(entity, Prop_Send, "m_vecMaxs", entMaxs); + GetEntPropVector(entity, Prop_Send, "m_vecMins", entMins); + + AddVectors(entOrigin, entMins, trueMins); + AddVectors(entOrigin, entMaxs, trueMaxs); + + for (int i = 0; i < 3; i++) + { + result[i] = FloatClamp(origin[i], trueMins[i], trueMaxs[i]); + } +} + +/** + * Get the shortest distance from P to the (infinite) line through vLineA and vLineB. + * + * @param P Point's origin. + * @param vLineA Origin of the first point of the line. + * @param vLineB Origin of the first point of the line. + * @return The shortest distance from the point to the line. + */ +stock float CalcDistanceToLine(float P[3], float vLineA[3], float vLineB[3]) +{ + float vClosest[3]; + float vDir[3]; + float t; + float delta[3]; + SubtractVectors(vLineB, vLineA, vDir); + float div = GetVectorDotProduct(vDir, vDir); + if (div < EPSILON) + { + t = 0.0; + } + else + { + t = (GetVectorDotProduct(vDir, P) - GetVectorDotProduct(vDir, vLineA)) / div; + } + for (int i = 0; i < 3; i++) + { + vClosest[i] = vLineA[i] + vDir[i]*t; + } + SubtractVectors(P, vClosest, delta); + return GetVectorLength(delta); +} + +/** + * Gets the ideal amount of time the text should be held for HUD messages. + * + * The message buffer is only 16 slots long, and it is shared between 6 channels maximum. + * Assuming a message is sent every game frame, each channel used should be only taking around 2.5 slots on average. + * This also assumes all channels are used equally (so no other plugin taking all the channel buffer for itself). + * We want to use as much of the message buffer as possible to take into account latency variances. + * + * @param interval HUD message update interval, in tick intervals. + * @return How long the text should be held for. + */ +stock float GetTextHoldTime(int interval) +{ + return 3 * interval * GetTickInterval(); +} diff --git a/source/sourcemod/scripting/include/gokz/anticheat.inc b/source/sourcemod/scripting/include/gokz/anticheat.inc new file mode 100644 index 0000000..7fa5409 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/anticheat.inc @@ -0,0 +1,168 @@ +/* + gokz-anticheat Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_anticheat_included_ +#endinput +#endif +#define _gokz_anticheat_included_ + + + +// =====[ ENUMS ]===== + +enum ACReason: +{ + ACReason_BhopMacro = 0, + ACReason_BhopHack, + ACREASON_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define AC_MAX_BUTTON_SAMPLES 40 +#define AC_MAX_BHOP_GROUND_TICKS 8 +#define AC_MAX_BHOP_SAMPLES 30 +#define AC_BINDEXCEPTION_SAMPLES 5 +#define AC_LOG_PATH "logs/gokz-anticheat.log" + +stock char gC_ACReasons[ACREASON_COUNT][] = +{ + "BHop Macro", + "BHop Hack" +}; + + + +// =====[ FORWARDS ]===== + +/** + * Called when gokz-anticheat suspects a player of cheating. + * + * @param client Client index. + * @param reason Reason for suspicion. + * @param notes Additional reasoning, description etc. + * @param stats Data supporting the suspicion e.g. scroll pattern. + */ +forward void GOKZ_AC_OnPlayerSuspected(int client, ACReason reason, const char[] notes, const char[] stats); + + + +// =====[ NATIVES ]===== + +/** + * Gets the number of recent bhop samples available for a player. + * + * @param client Client index. + * @return Number of bhop samples available. + */ +native int GOKZ_AC_GetSampleSize(int client); + +/** + * Gets whether a player hit a perfect bhop for a number of + * recent bhops. Buffer must be large enough to fit the sample + * size. + * + * @param client Client index. + * @param buffer Buffer for perfect bhop booleans, with the first element being the most recent bhop. + * @param sampleSize Maximum recent bhop samples. + * @return Number of bhop samples. + */ +native int GOKZ_AC_GetHitPerf(int client, bool[] buffer, int sampleSize); + +/** + * Gets a player's number of perfect bhops out of a sample + * size of bhops. + * + * @param client Client index. + * @param sampleSize Maximum recent bhop samples to include in calculation. + * @return Player's number of perfect bhops. + */ +native int GOKZ_AC_GetPerfCount(int client, int sampleSize); + +/** + * Gets a player's ratio of perfect bhops to normal bhops. + * + * @param client Client index. + * @param sampleSize Maximum recent bhop samples to include in calculation. + * @return Player's ratio of perfect bhops to normal bhops. + */ +native float GOKZ_AC_GetPerfRatio(int client, int sampleSize); + +/** + * Gets a player's jump input counts for a number of recent + * bhops. Buffer must be large enough to fit the sample size. + * + * @param client Client index. + * @param buffer Buffer for jump input counts, with the first element being the most recent bhop. + * @param sampleSize Maximum recent bhop samples. + * @return Number of bhop samples. + */ +native int GOKZ_AC_GetJumpInputs(int client, int[] buffer, int sampleSize); + +/** + * Gets a player's average number of jump inputs for a number + * of recent bhops. + * + * @param client Client index. + * @param sampleSize Maximum recent bhop samples to include in calculation. + * @return Player's average number of jump inputs. + */ +native float GOKZ_AC_GetAverageJumpInputs(int client, int sampleSize); + +/** + * Gets a player's jump input counts prior to a number of recent + * bhops. Buffer must be large enough to fit the sample size. + * Includes the jump input that resulted in the jump. + * + * @param client Client index. + * @param buffer Buffer for jump input counts, with the first element being the most recent bhop. + * @param sampleSize Maximum recent bhop samples. + * @return Number of bhop samples. + */ +native int GOKZ_AC_GetPreJumpInputs(int client, int[] buffer, int sampleSize); + +/** + * Gets a player's jump input counts after a number of recent + * bhops. Buffer must be large enough to fit the sample size. + * Excludes the jump input that resulted in the jump. + * + * @param client Client index. + * @param buffer Buffer for jump input counts, with the first element being the most recent bhop. + * @param sampleSize Maximum recent bhop samples. + * @return Number of bhop samples. + */ +native int GOKZ_AC_GetPostJumpInputs(int client, int[] buffer, int sampleSize); + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_anticheat = +{ + name = "gokz-anticheat", + file = "gokz-anticheat.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_anticheat_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_AC_GetSampleSize"); + MarkNativeAsOptional("GOKZ_AC_GetHitPerf"); + MarkNativeAsOptional("GOKZ_AC_GetPerfCount"); + MarkNativeAsOptional("GOKZ_AC_GetPerfRatio"); + MarkNativeAsOptional("GOKZ_AC_GetJumpInputs"); + MarkNativeAsOptional("GOKZ_AC_GetAverageJumpInputs"); + MarkNativeAsOptional("GOKZ_AC_GetPreJumpInputs"); + MarkNativeAsOptional("GOKZ_AC_GetPostJumpInputs"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/chat.inc b/source/sourcemod/scripting/include/gokz/chat.inc new file mode 100644 index 0000000..0264a57 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/chat.inc @@ -0,0 +1,45 @@ +/* + gokz-chat Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_chat_included_ +#endinput +#endif +#define _gokz_chat_included_ + + + +// =====[ NATIVES ]===== + +/** + * Gets whether a mode is loaded. + * + * @param client Client. + * @param tag Tag to prepend to the player name in chat. + * @param color Color to use for the tag. + */ +native void GOKZ_CH_SetChatTag(int client, const char[] tag, const char[] color); + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_chat = +{ + name = "gokz-chat", + file = "gokz-chat.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_chat_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_CH_SetChatTag"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/core.inc b/source/sourcemod/scripting/include/gokz/core.inc new file mode 100644 index 0000000..fb450d1 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/core.inc @@ -0,0 +1,1920 @@ +/* + gokz-core Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_core_included_ +#endinput +#endif +#define _gokz_core_included_ + +#include +#include +#include + +#include + + + +// =====[ ENUMS ]===== + +enum +{ + TimeType_Nub = 0, + TimeType_Pro, + TIMETYPE_COUNT +}; + +enum +{ + MapPrefix_Other = 0, + MapPrefix_KZPro, + MAPPREFIX_COUNT +}; + +enum StartPositionType: +{ + StartPositionType_Spawn, + StartPositionType_Custom, + StartPositionType_MapButton, + StartPositionType_MapStart, + STARTPOSITIONTYPE_COUNT +}; + +enum CourseTimerType: +{ + CourseTimerType_None, + CourseTimerType_Default, + CourseTimerType_Button, + CourseTimerType_ZoneLegacy, + CourseTimerType_ZoneNew, + CourseTimerType_COUNT +}; + +enum OptionProp: +{ + OptionProp_Cookie = 0, + OptionProp_Type, + OptionProp_DefaultValue, + OptionProp_MinValue, + OptionProp_MaxValue, + OPTIONPROP_COUNT +}; + +enum OptionType: +{ + OptionType_Int = 0, + OptionType_Float +}; + +enum Option: +{ + OPTION_INVALID = -1, + Option_Mode, + Option_Style, + Option_CheckpointMessages, + Option_CheckpointSounds, + Option_TeleportSounds, + Option_ErrorSounds, + Option_VirtualButtonIndicators, + Option_TimerButtonZoneType, + Option_ButtonThroughPlayers, + Option_Safeguard, + OPTION_COUNT +}; + +enum +{ + Mode_Vanilla = 0, + Mode_SimpleKZ, + Mode_KZTimer, + MODE_COUNT +}; + +enum +{ + Style_Normal = 0, + STYLE_COUNT +}; + +enum +{ + CheckpointMessages_Disabled = 0, + CheckpointMessages_Enabled, + CHECKPOINTMESSAGES_COUNT +}; + +enum +{ + CheckpointSounds_Disabled = 0, + CheckpointSounds_Enabled, + CHECKPOINTSOUNDS_COUNT +}; + +enum +{ + TeleportSounds_Disabled = 0, + TeleportSounds_Enabled, + TELEPORTSOUNDS_COUNT +}; + +enum +{ + ErrorSounds_Disabled = 0, + ErrorSounds_Enabled, + ERRORSOUNDS_COUNT +}; + +enum +{ + VirtualButtonIndicators_Disabled = 0, + VirtualButtonIndicators_Enabled, + VIRTUALBUTTONINDICATORS_COUNT +}; + +enum +{ + TimerButtonZoneType_BothButtons = 0, + TimerButtonZoneType_EndZone, + TimerButtonZoneType_BothZones, + TIMERBUTTONZONETYPE_COUNT +}; + +enum +{ + ButtonThroughPlayers_Disabled = 0, + ButtonThroughPlayers_Enabled, + BUTTONTHROUGHPLAYERS_COUNT +}; + +enum +{ + Safeguard_Disabled = 0, + Safeguard_EnabledNUB, + Safeguard_EnabledPRO, + SAFEGUARD_COUNT +}; + +enum +{ + ModeCVar_Accelerate = 0, + ModeCVar_AccelerateUseWeaponSpeed, + ModeCVar_AirAccelerate, + ModeCVar_AirMaxWishSpeed, + ModeCVar_EnableBunnyhopping, + ModeCVar_Friction, + ModeCVar_Gravity, + ModeCVar_JumpImpulse, + ModeCVar_LadderScaleSpeed, + ModeCVar_LedgeMantleHelper, + ModeCVar_MaxSpeed, + ModeCVar_MaxVelocity, + ModeCVar_StaminaJumpCost, + ModeCVar_StaminaLandCost, + ModeCVar_StaminaMax, + ModeCVar_StaminaRecoveryRate, + ModeCVar_StandableNormal, + ModeCVar_TimeBetweenDucks, + ModeCVar_WalkableNormal, + ModeCVar_WaterAccelerate, + MoveCVar_WaterMoveSpeedMultiplier, + MoveCVar_WaterSwimMode, + MoveCVar_WeaponEncumbrancePerItem, + ModeCVar_WeaponEncumbranceScale, + MODECVAR_COUNT +}; + +// NOTE: gokz-core/map/entlump.sp +enum EntlumpTokenType +{ + EntlumpTokenType_OpenBrace, // { + EntlumpTokenType_CloseBrace, // } + EntlumpTokenType_Identifier, // everything that's inside quotations + EntlumpTokenType_Unknown, + EntlumpTokenType_EndOfStream +}; + +// NOTE: gokz-core/map/triggers.sp +// NOTE: corresponds to climb_teleport_type in kz_mapping_api.fgd +enum TeleportType +{ + TeleportType_Invalid = -1, + TeleportType_Normal, + TeleportType_MultiBhop, + TeleportType_SingleBhop, + TeleportType_SequentialBhop, + TELEPORTTYPE_COUNT +}; + +enum TriggerType +{ + TriggerType_Invalid = 0, + TriggerType_Teleport, + TriggerType_Antibhop +}; + + + +// =====[ CONSTANTS ]===== + +#define GOKZ_CHECKPOINT_VERSION 2 +#define GOKZ_MAX_CHECKPOINTS 2048 +#define GOKZ_MAX_COURSES 100 + +#define GOKZ_BHOP_NO_CHECKPOINT_TIME 0.15 +#define GOKZ_MULT_NO_CHECKPOINT_TIME 0.11 +#define GOKZ_LADDER_NO_CHECKPOINT_TIME 1.5 +#define GOKZ_PAUSE_COOLDOWN 1.0 +#define GOKZ_TIMER_START_NO_TELEPORT_TICKS 4 +#define GOKZ_TIMER_START_GROUND_TICKS 4 +#define GOKZ_TIMER_START_NOCLIP_TICKS 4 +#define GOKZ_JUMPSTATS_NOCLIP_RESET_TICKS 4 +#define GOKZ_TIMER_SOUND_COOLDOWN 0.15 +#define GOKZ_VIRTUAL_BUTTON_USE_DETECTION_TIME 2.0 +#define GOKZ_TURNBIND_COOLDOWN 0.3 + +#define GOKZ_MAPPING_API_VERSION_NONE 0 // the map doesn't have a mapping api version +#define GOKZ_MAPPING_API_VERSION 1 + +#define GOKZ_ANTI_BHOP_TRIGGER_DEFAULT_DELAY 0.2 +#define GOKZ_TELEPORT_TRIGGER_DEFAULT_TYPE TeleportType_Normal +#define GOKZ_TELEPORT_TRIGGER_DEFAULT_DELAY 0.0 +#define GOKZ_TELEPORT_TRIGGER_DEFAULT_USE_DEST_ANGLES true +#define GOKZ_TELEPORT_TRIGGER_DEFAULT_RESET_SPEED true +#define GOKZ_TELEPORT_TRIGGER_DEFAULT_RELATIVE_DESTINATION false +#define GOKZ_TELEPORT_TRIGGER_DEFAULT_REORIENT_PLAYER false +#define GOKZ_TELEPORT_TRIGGER_BHOP_MIN_DELAY 0.08 + +#define GOKZ_SOUND_CHECKPOINT "buttons/blip1.wav" +#define GOKZ_SOUND_TELEPORT "buttons/blip1.wav" +#define GOKZ_SOUND_TIMER_STOP "buttons/button18.wav" + +#define GOKZ_START_NAME "climb_start" +#define GOKZ_BONUS_START_NAME_REGEX "^climb_bonus(\\d+)_start$" +#define GOKZ_BONUS_END_NAME_REGEX "^climb_bonus(\\d+)_end$" + +#define GOKZ_START_BUTTON_NAME "climb_startbutton" +#define GOKZ_END_BUTTON_NAME "climb_endbutton" +#define GOKZ_BONUS_START_BUTTON_NAME_REGEX "^climb_bonus(\\d+)_startbutton$" +#define GOKZ_BONUS_END_BUTTON_NAME_REGEX "^climb_bonus(\\d+)_endbutton$" +#define GOKZ_ANTI_BHOP_TRIGGER_NAME "climb_anti_bhop" +#define GOKZ_ANTI_CP_TRIGGER_NAME "climb_anti_checkpoint" +#define GOKZ_ANTI_PAUSE_TRIGGER_NAME "climb_anti_pause" +#define GOKZ_ANTI_JUMPSTAT_TRIGGER_NAME "climb_anti_jumpstat" +#define GOKZ_BHOP_RESET_TRIGGER_NAME "climb_bhop_reset" +#define GOKZ_TELEPORT_TRIGGER_NAME "climb_teleport" + +#define GOKZ_START_ZONE_NAME "climb_startzone" +#define GOKZ_END_ZONE_NAME "climb_endzone" +#define GOKZ_BONUS_START_ZONE_NAME_REGEX "^climb_bonus(\\d+)_startzone$" +#define GOKZ_BONUS_END_ZONE_NAME_REGEX "^climb_bonus(\\d+)_endzone$" + +#define GOKZ_CFG_SERVER "sourcemod/gokz/gokz.cfg" +#define GOKZ_CFG_OPTIONS "cfg/sourcemod/gokz/options.cfg" +#define GOKZ_CFG_OPTIONS_SORTING "cfg/sourcemod/gokz/options_menu_sorting.cfg" +#define GOKZ_CFG_OPTIONS_ROOT "Options" +#define GOKZ_CFG_OPTIONS_DESCRIPTION "description" +#define GOKZ_CFG_OPTIONS_DEFAULT "default" + +#define GOKZ_OPTION_MAX_NAME_LENGTH 30 +#define GOKZ_OPTION_MAX_DESC_LENGTH 255 +#define GENERAL_OPTION_CATEGORY "General" + +// TODO: where do i put the defines? +#define GOKZ_BSP_HEADER_IDENTIFIER (('P' << 24) | ('S' << 16) | ('B' << 8) | 'V') +#define GOKZ_ENTLUMP_MAX_KEY 32 +#define GOKZ_ENTLUMP_MAX_VALUE 1024 + +#define GOKZ_MAX_MAPTRIGGERS_ERROR_LENGTH 256 + +#define CHAR_ESCAPE view_as(27) + +#define GOKZ_SAFEGUARD_RESTART_MIN_DELAY 0.6 +#define GOKZ_SAFEGUARD_RESTART_MAX_DELAY 5.0 + +// Prevents the player from retouching a trigger too often. +#define GOKZ_MAX_RETOUCH_TRIGGER_COUNT 4 + +stock char gC_TimeTypeNames[TIMETYPE_COUNT][] = +{ + "NUB", + "PRO" +}; + +stock char gC_ModeNames[MODE_COUNT][] = +{ + "Vanilla", + "SimpleKZ", + "KZTimer" +}; + +stock char gC_ModeNamesShort[MODE_COUNT][] = +{ + "VNL", + "SKZ", + "KZT" +}; + +stock char gC_ModeKeys[MODE_COUNT][] = +{ + "vanilla", + "simplekz", + "kztimer" +}; + +stock float gF_ModeVirtualButtonRanges[MODE_COUNT] = +{ + 0.0, + 32.0, + 70.0 +}; + +stock char gC_ModeStartSounds[MODE_COUNT][] = +{ + "common/wpn_select.wav", + "buttons/button9.wav", + "buttons/button3.wav" +}; + +stock char gC_ModeEndSounds[MODE_COUNT][] = +{ + "common/wpn_select.wav", + "buttons/bell1.wav", + "buttons/button3.wav" +}; + +stock char gC_ModeFalseEndSounds[MODE_COUNT][] = +{ + "common/wpn_select.wav", + "buttons/button11.wav", + "buttons/button2.wav" +}; + +stock char gC_StyleNames[STYLE_COUNT][] = +{ + "Normal" +}; + +stock char gC_StyleNamesShort[STYLE_COUNT][] = +{ + "NRM" +}; + +stock char gC_CoreOptionNames[OPTION_COUNT][] = +{ + "GOKZ - Mode", + "GOKZ - Style", + "GOKZ - Checkpoint Messages", + "GOKZ - Checkpoint Sounds", + "GOKZ - Teleport Sounds", + "GOKZ - Error Sounds", + "GOKZ - VB Indicators", + "GOKZ - Timer Button Zone Type", + "GOKZ - Button Through Players", + "GOKZ - Safeguard" +}; + +stock char gC_CoreOptionDescriptions[OPTION_COUNT][] = +{ + "Movement Mode - 0 = Vanilla, 1 = SimpleKZ, 2 = KZTimer", + "Movement Style - 0 = Normal", + "Checkpoint Messages - 0 = Disabled, 1 = Enabled", + "Checkpoint Sounds - 0 = Disabled, 1 = Enabled", + "Teleport Sounds - 0 = Disabled, 1 = Enabled", + "Error Sounds - 0 = Disabled, 1 = Enabled", + "Virtual Button Indicators - 0 = Disabled, 1 = Enabled", + "Timer Button Zone Type - 0 = Both buttons, 1 = Only end zone, 2 = Both zones", + "Button Through Players - 0 = Disabled, 1 = Enabled", + "Safeguard - 0 = Disabled, 1 = Enabled (NUB), 2 = Enabled (PRO)" +}; + +stock char gC_CoreOptionPhrases[OPTION_COUNT][] = +{ + "Options Menu - Mode", + "Options Menu - Style", + "Options Menu - Checkpoint Messages", + "Options Menu - Checkpoint Sounds", + "Options Menu - Teleport Sounds", + "Options Menu - Error Sounds", + "Options Menu - Virtual Button Indicators", + "Options Menu - Timer Button Zone Type", + "Options Menu - Button Through Players", + "Options Menu - Safeguard" +}; + +stock char gC_TimerButtonZoneTypePhrases[TIMERBUTTONZONETYPE_COUNT][] = +{ + "Timer Button Zone Type - Both Buttons", + "Timer Button Zone Type - Only End Zone", + "Timer Button Zone Type - Both Zones" +}; + +stock char gC_SafeGuardPhrases[SAFEGUARD_COUNT][] = +{ + "Options Menu - Disabled", + "Safeguard - Enabled NUB", + "Safeguard - Enabled PRO" +} + +stock int gI_CoreOptionCounts[OPTION_COUNT] = +{ + MODE_COUNT, + STYLE_COUNT, + CHECKPOINTMESSAGES_COUNT, + CHECKPOINTSOUNDS_COUNT, + TELEPORTSOUNDS_COUNT, + ERRORSOUNDS_COUNT, + VIRTUALBUTTONINDICATORS_COUNT, + TIMERBUTTONZONETYPE_COUNT, + BUTTONTHROUGHPLAYERS_COUNT, + SAFEGUARD_COUNT +}; + +stock int gI_CoreOptionDefaults[OPTION_COUNT] = +{ + Mode_KZTimer, + Style_Normal, + CheckpointMessages_Disabled, + CheckpointSounds_Enabled, + TeleportSounds_Disabled, + ErrorSounds_Enabled, + VirtualButtonIndicators_Disabled, + TimerButtonZoneType_BothButtons, + ButtonThroughPlayers_Enabled, + Safeguard_Disabled +}; + +stock char gC_ModeCVars[MODECVAR_COUNT][] = +{ + "sv_accelerate", + "sv_accelerate_use_weapon_speed", + "sv_airaccelerate", + "sv_air_max_wishspeed", + "sv_enablebunnyhopping", + "sv_friction", + "sv_gravity", + "sv_jump_impulse", + "sv_ladder_scale_speed", + "sv_ledge_mantle_helper", + "sv_maxspeed", + "sv_maxvelocity", + "sv_staminajumpcost", + "sv_staminalandcost", + "sv_staminamax", + "sv_staminarecoveryrate", + "sv_standable_normal", + "sv_timebetweenducks", + "sv_walkable_normal", + "sv_wateraccelerate", + "sv_water_movespeed_multiplier", + "sv_water_swim_mode", + "sv_weapon_encumbrance_per_item", + "sv_weapon_encumbrance_scale" +}; + + +// =====[ STRUCTS ]===== + +enum struct Checkpoint +{ + float origin[3]; + float angles[3]; + float ladderNormal[3]; + bool onLadder; + int groundEnt; + + void Create(int client) + { + Movement_GetOrigin(client, this.origin); + Movement_GetEyeAngles(client, this.angles); + GetEntPropVector(client, Prop_Send, "m_vecLadderNormal", this.ladderNormal); + this.onLadder = Movement_GetMovetype(client) == MOVETYPE_LADDER; + this.groundEnt = GetEntPropEnt(client, Prop_Data, "m_hGroundEntity"); + } +} + +enum struct UndoTeleportData +{ + float tempOrigin[3]; + float tempAngles[3]; + float origin[3]; + float angles[3]; + // Undo TP properties + bool lastTeleportOnGround; + bool lastTeleportInBhopTrigger; + bool lastTeleportInAntiCpTrigger; + + void Init(int client, bool lastTeleportInBhopTrigger, bool lastTeleportOnGround, bool lastTeleportInAntiCpTrigger) + { + Movement_GetOrigin(client, this.tempOrigin); + Movement_GetEyeAngles(client, this.tempAngles); + this.lastTeleportInBhopTrigger = lastTeleportInBhopTrigger; + this.lastTeleportOnGround = lastTeleportOnGround; + this.lastTeleportInAntiCpTrigger = lastTeleportInAntiCpTrigger; + } + + void Update() + { + this.origin = this.tempOrigin; + this.angles = this.tempAngles; + } +} + + +// NOTE: gokz-core/map/entlump.sp +enum struct EntlumpToken +{ + EntlumpTokenType type; + char string[GOKZ_ENTLUMP_MAX_VALUE]; +} + +// NOTE: gokz-core/map/triggers.sp +enum struct AntiBhopTrigger +{ + int entRef; + int hammerID; + float time; +} + +enum struct TeleportTrigger +{ + int hammerID; + TeleportType type; + float delay; + char tpDestination[256]; + bool useDestAngles; + bool resetSpeed; + bool relativeDestination; + bool reorientPlayer; +} + +enum struct TouchedTrigger +{ + TriggerType triggerType; + int entRef; // entref of one of the TeleportTriggers + int startTouchTick; // tick where the player touched the trigger + int groundTouchTick; // tick where the player touched the ground +} + +// Legacy triggers that activate timer buttons. +enum struct TimerButtonTrigger +{ + int hammerID; + int course; + bool isStartTimer; +} + +// =====[ FORWARDS ]===== + +/** + * Called when a player's options values are loaded from clientprefs. + * + * @param client Client index. + */ +forward void GOKZ_OnOptionsLoaded(int client); + +/** + * Called when a player's option's value is changed. + * Only called if client is in game. + * + * @param client Client index. + * @param option Option name. + * @param newValue New value of the option. + */ +forward void GOKZ_OnOptionChanged(int client, const char[] option, any newValue); + +/** + * Called when a player starts their timer. + * + * @param client Client index. + * @param course Course number. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTimerStart(int client, int course); + +/** + * Called when a player has started their timer. + * + * @param client Client index. + * @param course Course number. + */ +forward void GOKZ_OnTimerStart_Post(int client, int course); + +/** + * Called when a player ends their timer. + * + * @param client Client index. + * @param course Course number. + * @param time Player's end time. + * @param teleportsUsed Number of teleports used by player. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTimerEnd(int client, int course, float time, int teleportsUsed); + +/** + * Called when a player has ended their timer. + * + * @param client Client index. + * @param course Course number. + * @param time Player's end time. + * @param teleportsUsed Number of teleports used by player. + */ +forward void GOKZ_OnTimerEnd_Post(int client, int course, float time, int teleportsUsed); + +/** + * Called when the end timer message is printed to chat. + * + * @param client Client index. + * @param course Course number. + * @param time Player's end time. + * @param teleportsUsed Number of teleports used by player. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTimerEndMessage(int client, int course, float time, int teleportsUsed); + +/** + * Called when a player's timer has been forcefully stopped. + * + * @param client Client index. + */ +forward void GOKZ_OnTimerStopped(int client); + +/** + * Called when a player pauses. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnPause(int client); + +/** + * Called when a player has paused. + * + * @param client Client index. + */ +forward void GOKZ_OnPause_Post(int client); + +/** + * Called when a player resumes. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnResume(int client); + +/** + * Called when a player has resumed. + * + * @param client Client index. + */ +forward void GOKZ_OnResume_Post(int client); + +/** + * Called when a player makes a checkpoint. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnMakeCheckpoint(int client); + +/** + * Called when a player has made a checkpoint. + * + * @param client Client index. + */ +forward void GOKZ_OnMakeCheckpoint_Post(int client); + +/** + * Called when a player teleports to their checkpoint. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTeleportToCheckpoint(int client); + +/** + * Called when a player has teleported to their checkpoint. + * + * @param client Client index. + */ +forward void GOKZ_OnTeleportToCheckpoint_Post(int client); + +/** + * Called when a player goes to a previous checkpoint. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnPrevCheckpoint(int client); + +/** + * Called when a player has gone to a previous checkpoint. + * + * @param client Client index. + */ +forward void GOKZ_OnPrevCheckpoint_Post(int client); + +/** + * Called when a player goes to a next checkpoint. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnNextCheckpoint(int client); + +/** + * Called when a player has gone to a next checkpoint. + * + * @param client Client index. + */ +forward void GOKZ_OnNextCheckpoint_Post(int client); + +/** + * Called when a player teleports to start. + * + * @param client Client index. + * @param course Course index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTeleportToStart(int client, int course); + +/** + * Called when a player has teleported to start. + * + * @param client Client index. + * @param course Course index. + */ +forward void GOKZ_OnTeleportToStart_Post(int client, int course); + +/** + * Called when a player teleports to end. + * + * @param client Client index. + * @param course Course index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTeleportToEnd(int client, int course); + +/** + * Called when a player has teleported to end. + * + * @param client Client index. + * @param course Course index. + */ +forward void GOKZ_OnTeleportToEnd_Post(int client, int course); + +/** + * Called when a player undoes a teleport. + * + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnUndoTeleport(int client); + +/** + * Called when a player has undone a teleport. + * + * @param client Client index. + */ +forward void GOKZ_OnUndoTeleport_Post(int client); + +/** + * Called when a player has performed a counted teleport (teleport count went up) + * i.e. a catch-all for teleport to checkpoint, teleport to start, undo teleport etc. + * + * @param client Client index. + */ +forward void GOKZ_OnCountedTeleport_Post(int client); + +/** + * Called when a player's start position is set. + * + * @param client Client index. + * @param type Start position type. + * @param origin Start position origin. + * @param angles Start position eye angles. + */ +forward void GOKZ_OnStartPositionSet_Post(int client, StartPositionType type, const float origin[3], const float angles[3]); + +/** + * Called when player's begins a jump that is deemed valid. + * A jump is deemed invalid if a player is teleported. + * + * @param client Client index. + * @param jumped Whether player jumped. + * @param ladderJump Whether it was a ladder jump. + * @param jumpbug Whether player performed a jumpbug. + */ +forward void GOKZ_OnJumpValidated(int client, bool jumped, bool ladderJump, bool jumpbug); + +/** + * Called when player's current jump is invalidated. + * A jump is deemed invalid if a player is teleported. + * + * @param client Client index. + */ +forward void GOKZ_OnJumpInvalidated(int client); + +/** + * Called when a player has been switched to a team. + * + * @param client Client index. + */ +forward void GOKZ_OnJoinTeam(int client, int team); + +/** + * Called the first time a player spawns in on a team. + * + * @param client Client index. + */ +forward void GOKZ_OnFirstSpawn(int client); + +/** + * Called when a mode has been loaded. + * + * @param mode Mode loaded. + */ +forward void GOKZ_OnModeLoaded(int mode); + +/** + * Called when a mode has been unloaded. + * + * @param mode Mode unloaded. + */ +forward void GOKZ_OnModeUnloaded(int mode); + +/** + * Called when a plugin other than gokz-core calls a native + * that may affect a player's timer or teleport count in + * their favour e.g. GOKZ_StartTimer, GOKZ_EndTimer, + * GOKZ_SetTime and GOKZ_SetTeleportCount. + * + * @param plugin Handle of the calling plugin. + * @param client Client index. + * @return Plugin_Handled or Plugin_Stop to block, Plugin_Continue to proceed. + */ +forward Action GOKZ_OnTimerNativeCalledExternally(Handle plugin, int client); + +/** + * Called when the options menu has been created and 3rd + * party plugins can grab the handle or add categories. + * + * @param topMenu Options top menu handle. + */ +forward void GOKZ_OnOptionsMenuCreated(TopMenu topMenu); + +/** + * Called when the options menu is ready to have items added. + * + * @param topMenu Options top menu handle. + */ +forward void GOKZ_OnOptionsMenuReady(TopMenu topMenu); + +/** + * Called when a course is registered. A course is registered if both the + * start and end of it (e.g. timer buttons) have been detected. + * + * @param course Course number. + */ +forward void GOKZ_OnCourseRegistered(int course); + +/** + * Called when a player's run becomes invalidated. + * An invalidated run doesn't necessarily stop the timer. + * + * @param client Client index. + */ +forward void GOKZ_OnRunInvalidated(int client); + +/** + * Called when a sound is emitted to the client via GOKZ Core. + * + * @param client Client index. + * @param sample Sound file name relative to the "sound" folder. + * @param volume Sound volume. + * @param description Optional description. + * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it, + * Plugin_Changed when any parameter has been modified. + */ +forward Action GOKZ_OnEmitSoundToClient(int client, const char[] sample, float &volume, const char[] description); + + +// =====[ NATIVES ]===== + +/** + * Gets whether a mode is loaded. + * + * @param mode Mode. + * @return Whether mode is loaded. + */ +native bool GOKZ_GetModeLoaded(int mode); + +/** + * Gets the version number of a loaded mode. + * + * @param mode Mode. + * @return Version number of the mode, or -1 if not loaded. + */ +native int GOKZ_GetModeVersion(int mode); + +/** + * Sets whether a mode is loaded. To be used by mode plugins. + * + * @param mode Mode. + * @param loaded Whether mode is loaded. + * @param version Version number of the mode. + */ +native void GOKZ_SetModeLoaded(int mode, bool loaded, int version = -1); + +/** + * Gets the total number of loaded modes. + * + * @return Number of loaded modes. + */ +native int GOKZ_GetLoadedModeCount(); + +/** + * Sets the player's current mode. + * If the player's timer is running, it will be stopped. + * + * @param client Client index. + * @param mode Mode. + * @return Whether the operation was successful. + */ +native bool GOKZ_SetMode(int client, int mode); + +/** + * Gets the Handle to the options top menu. + * + * @return Handle to the options top menu, + * or null if not created yet. + */ +native TopMenu GOKZ_GetOptionsTopMenu(); + +/** + * Gets whether a course is registered. A course is registered if both the + * start and end of it (e.g. timer buttons) have been detected. + * + * @param course Course number. + * @return Whether course has been registered. + */ +native bool GOKZ_GetCourseRegistered(int course); + +/** + * Prints a message to a client's chat, formatting colours and optionally + * adding the chat prefix. If using the chat prefix, specify a colour at + * the beginning of the message e.g. "{default}Hello!". + * + * @param client Client index. + * @param addPrefix Whether to add the chat prefix. + * @param format Formatting rules. + * @param any Variable number of format parameters. + */ +native void GOKZ_PrintToChat(int client, bool addPrefix, const char[] format, any...); + +/** + * Prints a message to a client's chat, formatting colours and optionally + * adding the chat prefix. If using the chat prefix, specify a colour at + * the beginning of the message e.g. "{default}Hello!". Also prints the + * message to the server log. + * + * @param client Client index. + * @param addPrefix Whether to add the chat prefix. + * @param format Formatting rules. + * @param any Variable number of format parameters. + */ +native void GOKZ_PrintToChatAndLog(int client, bool addPrefix, const char[] format, any...); + +/** + * Starts a player's timer for a course on the current map. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param course Course number. + * @param allowMidair Whether player is allowed to start timer midair. + * @return Whether player's timer was started. + */ +native bool GOKZ_StartTimer(int client, int course, bool allowOffGround = false); + +/** + * Ends a player's timer for a course on the current map. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param course Course number. + * @return Whether player's timer was ended. + */ +native bool GOKZ_EndTimer(int client, int course); + +/** + * Forces a player's timer to stop. Intended for run invalidation. + * + * @param client Client index. + * @param playSound Whether to play the timer stop sound. + * @return Whether player's timer was stopped. + */ +native bool GOKZ_StopTimer(int client, bool playSound = true); + +/** + * Forces all players' timers to stop. Intended for run invalidation. + * + * @param playSound Whether to play the timer stop sound. + */ +native void GOKZ_StopTimerAll(bool playSound = true); + +/** + * Gets whether or not a player's timer is running i.e. isn't 'stopped'. + * + * @param client Client index. + * @return Whether player's timer is running. + */ +native bool GOKZ_GetTimerRunning(int client); + +/** + * Gets whether or not a player's timer is valid i.e the run is a valid run. + * + * @param client Client index. + * @return Whether player's timer is running. + */ +native bool GOKZ_GetValidTimer(int client); + +/** + * Gets the course a player is currently running. + * + * @param client Client index. + * @return Course number. + */ +native int GOKZ_GetCourse(int client); + +/** + * Set the player's current course. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param course Course number. + * @return Whether native was allowed to proceed. + */ +native bool GOKZ_SetCourse(int client, int course); + +/** + * Gets whether a player is paused. + * + * @param client Client index. + * @return Whether player is paused. + */ +native bool GOKZ_GetPaused(int client); + +/** + * Gets a player's current run time. + * + * @param client Client index. + * @return Player's current run time. + */ +native float GOKZ_GetTime(int client); + +/** + * Gets a player's current run time. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param time Run time to set to. + * @return Whether native was allowed to proceed. + */ +native bool GOKZ_SetTime(int client, float time); + +/** + * Mark a player's run as invalid without stopping the timer. + * + * @param client Client index. + */ +native void GOKZ_InvalidateRun(int client); + +/** + * Gets a player's current checkpoint count. + * + * @param client Client index. + * @return Player's current checkpoint count. + */ +native int GOKZ_GetCheckpointCount(int client); + +/** + * Sets a player's current checkpoint count. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param cpCount Checkpoint count to set to. + * @return Whether native was allowed to proceed. + */ +native int GOKZ_SetCheckpointCount(int client, int cpCount); + +/** + * Gets checkpoint data of a player. + * + * @param client Client index. + * @return Client's checkpoint data. + */ +native ArrayList GOKZ_GetCheckpointData(int client); + +/** + * Sets checkpoint data of a player. The checkpoint data is assumed to be ordered. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param checkpoints Checkpoint data. + * @param version Checkpoint version. + * @return Whether native was allowed to proceed and operation was successful. + */ +native bool GOKZ_SetCheckpointData(int client, ArrayList checkpoints, int version); + +/** + * Get undo teleport data of a player. + * + * @param client Client index. + * @return ArrayList of length 1 containing player's undo teleport data. + */ +native ArrayList GOKZ_GetUndoTeleportData(int client); + +/** + * Set undo teleport data of a player. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param undoTeleportDataArray ArrayList of length 1 containing player's undo teleport data. + * @param version Checkpoint version. + * @return Whether native was allowed to proceed and operation was successful. + */ +native bool GOKZ_SetUndoTeleportData(int client, ArrayList undoTeleportDataArray, int version); + +/** + * Gets a player's current teleport count. + * + * @param client Client index. + * @return Player's current teleport count. + */ +native int GOKZ_GetTeleportCount(int client); + +/** + * Sets a player's current teleport count. + * This can be blocked by OnTimerNativeCalledExternally(). + * + * @param client Client index. + * @param tpCount Teleport count to set to. + * @return Whether native was allowed to proceed. + */ +native bool GOKZ_SetTeleportCount(int client, int tpCount); + +/** + * Teleports a player to start, or respawns them. + * + * @param client Client index. + */ +native void GOKZ_TeleportToStart(int client); + +/** + * Teleports a player to the start zone/button of the specified course. + * + * @param client Client index. + * @param course Course index. + */ +native void GOKZ_TeleportToSearchStart(int client, int course); + +/** + * Gets the virtual button position the player currently has. + * + * @param client Client index. + * @param position Returns the client's virtual button position. + * @param isStart True to get the start button position, false for the end button. + * @return The course the button belongs to. + */ +native int GOKZ_GetVirtualButtonPosition(int client, float position[3], bool isStart); + +/** + * Sets the virtual button position the player currently has. + * + * @param client Client index. + * @param position The client's virtual button position. + * @param course The course the virtual button belongs to. + * @param isStart True to get the start button position, false for the end button. + */ +native void GOKZ_SetVirtualButtonPosition(int client, const float position[3], int course, bool isStart); + +/** + * Resets the player's virtual button. + * + * @param client Client index. + * @param isStart True to get the start button position, false for the end button. + */ +native void GOKZ_ResetVirtualButtonPosition(int client, bool isStart); + +/** + * Locks the virtual button position of a player. + * + * @param client Client index. + */ +native void GOKZ_LockVirtualButtons(int client); + +/** + * Gets the start position the player currently has. + * + * @param client Client index. + * @param position Returns the client's start position. + * @param angles Returns the client's start angles. + * @return Player's current start position type. + */ +native StartPositionType GOKZ_GetStartPosition(int client, float position[3], float angles[3]); + +/** + * Sets the start position the player currently has. + * + * @param client Client index. + * @param type The start position type. + * @param position The client's start position. + * @param angles The client's start angles. + */ +native void GOKZ_SetStartPosition(int client, StartPositionType type, const float position[3], const float angles[3]); + +/** + * Gets the type of start position the player currently has. + * The "Spawn" type means teleport to start will respawn the player. + * + * @param client Client index. + * @return Player's current start position type. + */ +native StartPositionType GOKZ_GetStartPositionType(int client); + +/** + * Set the start position of the player to the start of a course. + * + * @param client Client index. + * @param course Course index. + * + * @return False if the course start was not found. + */ +native bool GOKZ_SetStartPositionToMapStart(int client, int course); + +/** + * Teleports a player to end. + * + * @param client Client index. + * @param course Course index. + */ +native void GOKZ_TeleportToEnd(int client, int course); + +/** + * Set a new checkpoint at a player's current position. + * + * @param client Client index. + */ +native void GOKZ_MakeCheckpoint(int client); + +/** + * Gets whether a player can make a new checkpoint. + * @param client Client index. + * @return Whether player can set a checkpoint. + */ +native bool GOKZ_GetCanMakeCheckpoint(int client); + +/** + * Teleports a player to their last checkpoint. + * + * @param client Client index. + */ +native void GOKZ_TeleportToCheckpoint(int client); + +/** + * Gets whether a player can teleport to their checkpoint + * e.g. will return false if player has no checkpoints. + * + * @param client Client index. + * @return Whether player can teleport to checkpoint. + */ +native bool GOKZ_GetCanTeleportToCheckpoint(int client); + +/** + * Teleport a player back to a previous checkpoint. + * + * @param client Client index. + */ +native void GOKZ_PrevCheckpoint(int client); + +/** + * Gets whether a player can go to their previous checkpoint + * e.g. will return false if player has no checkpoints. + * + * @param client Client index. + * @return Whether player can go to previous checkpoint. + */ +native bool GOKZ_GetCanPrevCheckpoint(int client); + +/** + * Teleport a player to a more recent checkpoint. + * + * @param client Client index. + */ +native void GOKZ_NextCheckpoint(int client); + +/** + * Gets whether a player can go to their next checkpoint + * e.g. will return false if player has no checkpoints. + * + * @param client Client index. + * @return Whether player can go to next checkpoint. + */ +native bool GOKZ_GetCanNextCheckpoint(int client); + +/** + * Teleport a player to where they last teleported from. + * + * @param client Client index. + */ +native void GOKZ_UndoTeleport(int client); + +/** + * Gets whether a player can undo their teleport + * e.g. will return false if teleport was from midair. + * + * @param client Client index. + * @return Whether player can undo teleport. + */ +native bool GOKZ_GetCanUndoTeleport(int client); + +/** + * Pause a player's timer and freeze them. + * + * @param client Client index. + */ +native void GOKZ_Pause(int client); + +/** + * Gets whether a player can pause. Pausing is not allowed + * under some circumstance when the timer is running. + * + * @param client Client index. + */ +native bool GOKZ_GetCanPause(int client); + +/** + * Resumes a player's timer and unfreezes them. + * + * @param client Client index. + */ +native void GOKZ_Resume(int client); + +/** + * Gets whether a player can resume. Resuming is not allowed + * under some circumstance when the timer is running. + * + * @param client Client index. + */ +native bool GOKZ_GetCanResume(int client); + +/** + * Toggles the paused state of a player. + * + * @param client Client index. + */ +native void GOKZ_TogglePause(int client); + +/** + * Gets whether a player can teleport to start. + * + * @param client Client index. + * @return Whether player can teleport to start. + */ +native bool GOKZ_GetCanTeleportToStartOrEnd(int client); + +/** + * Plays the error sound to a player if they have the option enabled. + * + * @param client Client index. + */ +native void GOKZ_PlayErrorSound(int client); + +/** + * Set the origin of a player without invalidating any jumpstats. + * + * Only use this in plugins that create a new mode! + * + * @param client Client index. + * @param origin The new origin. + */ +native void GOKZ_SetValidJumpOrigin(int client, const float origin[3]); + +/** + * Registers an option with gokz-core, which uses clientprefs to + * keep track of the option's value and to save it to a database. + * This also effectively provides natives and forwards for other + * plugins to access any options that have been registered. + * + * @param name Option name. + * @param description Option description. + * @param type Type to treat the option value as. + * @param defaultValue Default value of option. + * @param minValue Minimum value of option. + * @param maxValue Maximum value of option. + * @return Whether registration was successful. + */ +native bool GOKZ_RegisterOption(const char[] name, const char[] description, OptionType type, any defaultValue, any minValue, any maxValue); + +/** + * Gets a property of a registered option. If used outside of + * gokz-core to get the cookie, a clone of its Handle is returned. + * + * @param option Option name. + * @param prop Option property to get. + * @return Value of property, or -1 (int) if option isn't registered. + */ +native any GOKZ_GetOptionProp(const char[] option, OptionProp prop); + +/** + * Sets a property of a registered option. For safety and simplicity, + * the cookie property is read-only and will fail to be set. + * + * @param option Option name. + * @param prop Option property to set. + * @param value Value to set the property to. + * @return Whether option property was successfully set. + */ +native bool GOKZ_SetOptionProp(const char[] option, OptionProp prop, any value); + +/** + * Gets the current value of a player's option. + * + * @param client Client index. + * @param option Option name. + * @return Current value of option, or -1 (int) if option isn't registered. + */ +native any GOKZ_GetOption(int client, const char[] option); + +/** + * Sets a player's option's value. Fails if option doesn't exist, + * or if desired value is outside the registered value range. + * + * @param client Client index. + * @param option Option name. + * @param value New option value. + * @return Whether option was successfully set. + */ +native bool GOKZ_SetOption(int client, const char[] option, any value); + +/** + * Gets whether player's last takeoff was a perfect bunnyhop as adjusted by GOKZ. + * + * @param client Client index. + * @return Whether player's last takeoff was a GOKZ perfect b-hop. + */ +native bool GOKZ_GetHitPerf(int client); + +/** + * Sets whether player's last takeoff was a perfect bunnyhop as adjusted by GOKZ. + * Intended to be called by GOKZ mode plugins only. + * + * @param client Client index. + * @param hitPerf Whether player's last takeoff was a GOKZ perfect b-hop. + */ +native void GOKZ_SetHitPerf(int client, bool hitPerf); + +/** + * Gets a player's horizontal speed at the time of their last takeoff as recorded by GOKZ. + * + * @param client Client index. + * @return Player's last takeoff speed as recorded by GOKZ. + */ +native float GOKZ_GetTakeoffSpeed(int client); + +/** + * Sets a player's recorded horizontal speed at the time of their last takeoff. + * Intended to be called by GOKZ mode plugins only. + * + * @param client Client index. + * @param takeoffSpeed Player's last takeoff speed as recorded by GOKZ. + */ +native void GOKZ_SetTakeoffSpeed(int client, float takeoffSpeed); + +/** + * Gets whether a player's current or last jump/airtime is valid. + * A jump is deemed invalid if the player is teleported. + * + * @param client Client index. + * @return Validity of player's current or last jump. + */ +native bool GOKZ_GetValidJump(int client); + +/** + * Has a player switch to a team via GOKZ Core. + * + * @param client Client index. + * @param team Which team to switch to. + * @param restorePos Whether to restore saved position if leaving spectators. + * @param forceBroadcast Force JoinTeam forward calling even if client's team did not change. + */ +native void GOKZ_JoinTeam(int client, int team, bool restorePos = true, bool forceBroadcast = false); + +/** + * Emit a sound to a player via GOKZ Core. + * Sounds emitted by this native will call GOKZ_OnEmitSoundToClient forward. + * + * @param client Client index. + * @param sample Sound file name relative to the "sound" folder. + * @param volume Sound volume. + * @param description Optional description. + */ +native void GOKZ_EmitSoundToClient(int client, const char[] sample, float volume = SNDVOL_NORMAL, const char[] description = ""); + + +// =====[ STOCKS ]===== + +/** + * Makes a player join a team if they aren't on one and respawns them. + * + * @param client Client index. + * @param team Which team to switch to if not on one. + * @param restorePos Whether to restore saved position if leaving spectators. + */ +stock void GOKZ_RespawnPlayer(int client, int team = CS_TEAM_T, bool restorePos = true) +{ + if (IsSpectating(client)) + { + GOKZ_JoinTeam(client, team, restorePos); + } + else + { + CS_RespawnPlayer(client); + } +} + +/** + * Prints a message to all client's chat, formatting colours and optionally + * adding the chat prefix. If using the chat prefix, specify a colour at + * the beginning of the message e.g. "{default}Hello!". + * + * @param addPrefix Whether to add the chat prefix. + * @param format Formatting rules. + * @param any Variable number of format parameters. + */ +stock void GOKZ_PrintToChatAll(bool addPrefix, const char[] format, any...) +{ + char buffer[1024]; + for (int client = 1; client <= MaxClients; client++) + { + if (IsClientInGame(client)) + { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 3); + GOKZ_PrintToChat(client, addPrefix, buffer); + } + } +} + +/** + * Prints a chat message to those spectating the client, formatting colours + * and optionally adding the chat prefix. If using the chat prefix, specify + * a colour at the beginning of the message e.g. "{default}Hello!". + * + * @param client Client index. + * @param addPrefix Whether to add the chat prefix. + * @param format Formatting rules. + * @param any Variable number of format parameters. + */ +stock void GOKZ_PrintToChatSpectators(int client, bool addPrefix, const char[] format, any...) +{ + char buffer[1024]; + for (int target = 1; target <= MaxClients; target++) + { + if (IsClientInGame(target) && GetObserverTarget(target) == client) + { + SetGlobalTransTarget(target); + VFormat(buffer, sizeof(buffer), format, 4); + GOKZ_PrintToChat(target, addPrefix, buffer); + } + } +} + +/** + * Gets the player's current time type. + * + * @param client Client index. + * @return Player's current time type. + */ +stock int GOKZ_GetTimeType(int client) +{ + return GOKZ_GetTimeTypeEx(GOKZ_GetTeleportCount(client)); +} + +/** + * Gets the time type given a teleport count. + * + * @param teleports Teleport count. + * @return Time type. + */ +stock int GOKZ_GetTimeTypeEx(int teleportCount) +{ + if (teleportCount == 0) + { + return TimeType_Pro; + } + return TimeType_Nub; +} + +/** + * Clears and populates a menu with an item for each mode + * in order of the mode enumeration. Highlights the client's + * selected mode with an asterisk. + * + * @param client Client index to check selected mode. + * @param menu Menu to populate items with. + * @param disableUnloadedModes Draw items for unloaded modes as disabled. + */ +stock void GOKZ_MenuAddModeItems(int client, Menu menu, bool disableUnloadedModes) +{ + int selectedMode = GOKZ_GetCoreOption(client, Option_Mode); + char display[32]; + + menu.RemoveAllItems(); + + for (int mode = 0; mode < MODE_COUNT; mode++) + { + FormatEx(display, sizeof(display), "%s", gC_ModeNames[mode]); + // Add asterisk to selected mode + if (mode == selectedMode) + { + Format(display, sizeof(display), "%s*", display); + } + + if (GOKZ_GetModeLoaded(mode)) + { + menu.AddItem("", display, ITEMDRAW_DEFAULT); + } + else + { + menu.AddItem("", display, ITEMDRAW_DISABLED); + } + } +} + +/** + * Increment an (integer-type) option's value. + * Loops back to min. value if max. value is exceeded. + * + * @param client Client index. + * @param option Option name. + * @return Whether option was successfully set. + */ +stock bool GOKZ_CycleOption(int client, const char[] option) +{ + int maxValue = GOKZ_GetOptionProp(option, OptionProp_MaxValue); + if (maxValue == -1) + { + return false; + } + + int newValue = GOKZ_GetOption(client, option) + 1; + if (newValue > GOKZ_GetOptionProp(option, OptionProp_MaxValue)) + { + newValue = GOKZ_GetOptionProp(option, OptionProp_MinValue); + } + return GOKZ_SetOption(client, option, newValue); +} + +/** + * Returns whether an option is a gokz-core option. + * + * @param option Option name. + * @param optionEnum Variable to store enumerated gokz-core option (if it is one). + * @return Whether option is a gokz-core option. + */ +stock bool GOKZ_IsCoreOption(const char[] option, Option &optionEnum = OPTION_INVALID) +{ + for (Option i; i < OPTION_COUNT; i++) + { + if (StrEqual(option, gC_CoreOptionNames[i])) + { + optionEnum = i; + return true; + } + } + return false; +} + +/** + * Gets a property of a gokz-core option. + * + * @param coreOption gokz-core option. + * @param prop Option property to get. + * @return Value of property, or -1 if option isn't registered. + */ +stock any GOKZ_GetCoreOptionProp(Option option, OptionProp prop) +{ + return GOKZ_GetOptionProp(gC_CoreOptionNames[option], prop); +} + +/** + * Gets the current value of a player's gokz-core option. + * + * @param client Client index. + * @param option gokz-core option. + * @return Current value of option. + */ +stock any GOKZ_GetCoreOption(int client, Option option) +{ + return GOKZ_GetOption(client, gC_CoreOptionNames[option]); +} + +/** + * Sets the player's gokz-core option's value. + * + * @param client Client index. + * @param option gokz-core option. + * @param value New option value. + * @return Whether option was successfully set. + */ +stock bool GOKZ_SetCoreOption(int client, Option option, any value) +{ + return GOKZ_SetOption(client, gC_CoreOptionNames[option], value); +} + +/** + * Increment an integer-type gokz-core option's value. + * Loops back to '0' if max value is exceeded. + * + * @param client Client index. + * @param option gokz-core option. + * @return Whether option was successfully set. + */ +stock bool GOKZ_CycleCoreOption(int client, Option option) +{ + return GOKZ_CycleOption(client, gC_CoreOptionNames[option]); +} + +/** + * Gets the current default mode. + * + * @return Default mode. + */ +stock int GOKZ_GetDefaultMode() +{ + return GOKZ_GetCoreOptionProp(Option_Mode, OptionProp_DefaultValue); +} + +/** + * Returns whether a course number is a valid (within valid range). + * + * @param course Course number. + * @param bonus Whether to only consider bonus course numbers as valid. + * @return Whether course number is valid. + */ +stock bool GOKZ_IsValidCourse(int course, bool bonus = false) +{ + return (!bonus && course == 0) || (0 < course && course < GOKZ_MAX_COURSES); +} + +/** + * Returns an integer from an entity's name as matched using a regular expression. + * + * @param entity Entity index. + * @param re Regular expression to match the integer with. + * @param substringID ID of the substring that will contain the integer. + * @returns Integer found in the entity's name, or -1 if not found. + */ +stock int GOKZ_MatchIntFromEntityName(int entity, Regex re, int substringID) +{ + int num = -1; + char buffer[32]; + GetEntityName(entity, buffer, sizeof(buffer)); + + if (re.Match(buffer) > 0) + { + re.GetSubString(1, buffer, sizeof(buffer)); + num = StringToInt(buffer); + } + + return num; +} + +/** + * Emits a sound to other players that are spectating the client. + * Sounds emitted by this function will call GOKZ_OnEmitSoundToClient forward. + * + * @param sample Sound file name relative to the "sound" folder. + * @param volume Sound volume. + * @param description Optional description. + */ +stock void GOKZ_EmitSoundToAll(const char[] sample, float volume = SNDVOL_NORMAL, const char[] description = "") +{ + for (int client = 1; client <= MaxClients; client++) + { + if (IsClientInGame(client)) + { + GOKZ_EmitSoundToClient(client, sample, volume, description); + } + } +} + +/** + * Emits a sound to other players that are spectating the client. + * Sounds emitted by this function will call GOKZ_OnEmitSoundToClient forward. + * + * @param client Client being spectated. + * @param sample Sound file name relative to the "sound" folder. + * @param volume Sound volume. + * @param description Optional description. + */ +stock void GOKZ_EmitSoundToClientSpectators(int client, const char[] sample, float volume = SNDVOL_NORMAL, const char[] description = "") +{ + for (int i = 1; i <= MaxClients; i++) + { + if (IsValidClient(i) && GetObserverTarget(i) == client) + { + GOKZ_EmitSoundToClient(i, sample, volume); + } + } +} + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_core = +{ + name = "gokz-core", + file = "gokz-core.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_core_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_GetModeLoaded"); + MarkNativeAsOptional("GOKZ_GetModeVersion"); + MarkNativeAsOptional("GOKZ_SetModeLoaded"); + MarkNativeAsOptional("GOKZ_GetLoadedModeCount"); + MarkNativeAsOptional("GOKZ_SetMode"); + MarkNativeAsOptional("GOKZ_GetOptionsTopMenu"); + MarkNativeAsOptional("GOKZ_GetCourseRegistered"); + MarkNativeAsOptional("GOKZ_PrintToChat"); + MarkNativeAsOptional("GOKZ_PrintToChatAndLog"); + MarkNativeAsOptional("GOKZ_StartTimer"); + MarkNativeAsOptional("GOKZ_EndTimer"); + MarkNativeAsOptional("GOKZ_StopTimer"); + MarkNativeAsOptional("GOKZ_StopTimerAll"); + MarkNativeAsOptional("GOKZ_TeleportToStart"); + MarkNativeAsOptional("GOKZ_TeleportToSearchStart"); + MarkNativeAsOptional("GOKZ_GetVirtualButtonPosition"); + MarkNativeAsOptional("GOKZ_SetVirtualButtonPosition"); + MarkNativeAsOptional("GOKZ_ResetVirtualButtonPosition"); + MarkNativeAsOptional("GOKZ_LockVirtualButtons"); + MarkNativeAsOptional("GOKZ_GetStartPosition"); + MarkNativeAsOptional("GOKZ_SetStartPosition"); + MarkNativeAsOptional("GOKZ_GetStartPositionType"); + MarkNativeAsOptional("GOKZ_SetStartPositionToMapStart"); + MarkNativeAsOptional("GOKZ_TeleportToEnd"); + MarkNativeAsOptional("GOKZ_MakeCheckpoint"); + MarkNativeAsOptional("GOKZ_GetCanMakeCheckpoint"); + MarkNativeAsOptional("GOKZ_TeleportToCheckpoint"); + MarkNativeAsOptional("GOKZ_GetCanTeleportToCheckpoint"); + MarkNativeAsOptional("GOKZ_PrevCheckpoint"); + MarkNativeAsOptional("GOKZ_GetCanPrevCheckpoint"); + MarkNativeAsOptional("GOKZ_NextCheckpoint"); + MarkNativeAsOptional("GOKZ_GetCanNextCheckpoint"); + MarkNativeAsOptional("GOKZ_UndoTeleport"); + MarkNativeAsOptional("GOKZ_GetCanUndoTeleport"); + MarkNativeAsOptional("GOKZ_Pause"); + MarkNativeAsOptional("GOKZ_GetCanPause"); + MarkNativeAsOptional("GOKZ_Resume"); + MarkNativeAsOptional("GOKZ_GetCanResume"); + MarkNativeAsOptional("GOKZ_TogglePause"); + MarkNativeAsOptional("GOKZ_GetCanTeleportToStartOrEnd"); + MarkNativeAsOptional("GOKZ_PlayErrorSound"); + MarkNativeAsOptional("GOKZ_SetValidJumpOrigin"); + MarkNativeAsOptional("GOKZ_GetTimerRunning"); + MarkNativeAsOptional("GOKZ_GetCourse"); + MarkNativeAsOptional("GOKZ_SetCourse"); + MarkNativeAsOptional("GOKZ_GetPaused"); + MarkNativeAsOptional("GOKZ_GetTime"); + MarkNativeAsOptional("GOKZ_SetTime"); + MarkNativeAsOptional("GOKZ_InvalidateRun"); + MarkNativeAsOptional("GOKZ_GetCheckpointCount"); + MarkNativeAsOptional("GOKZ_SetCheckpointCount"); + MarkNativeAsOptional("GOKZ_GetCheckpointData"); + MarkNativeAsOptional("GOKZ_SetCheckpointData"); + MarkNativeAsOptional("GOKZ_GetUndoTeleportData"); + MarkNativeAsOptional("GOKZ_SetUndoTeleportData"); + MarkNativeAsOptional("GOKZ_GetTeleportCount"); + MarkNativeAsOptional("GOKZ_SetTeleportCount"); + MarkNativeAsOptional("GOKZ_RegisterOption"); + MarkNativeAsOptional("GOKZ_GetOptionProp"); + MarkNativeAsOptional("GOKZ_SetOptionProp"); + MarkNativeAsOptional("GOKZ_GetOption"); + MarkNativeAsOptional("GOKZ_SetOption"); + MarkNativeAsOptional("GOKZ_GetHitPerf"); + MarkNativeAsOptional("GOKZ_SetHitPerf"); + MarkNativeAsOptional("GOKZ_GetTakeoffSpeed"); + MarkNativeAsOptional("GOKZ_SetTakeoffSpeed"); + MarkNativeAsOptional("GOKZ_GetValidJump"); + MarkNativeAsOptional("GOKZ_JoinTeam"); + MarkNativeAsOptional("GOKZ_EmitSoundToClient"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/global.inc b/source/sourcemod/scripting/include/gokz/global.inc new file mode 100644 index 0000000..0f23a0c --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/global.inc @@ -0,0 +1,317 @@ +/* + gokz-global Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_global_included_ +#endinput +#endif +#define _gokz_global_included_ + +#include + + + +// =====[ ENUMS ]===== + +enum +{ + EnforcedCVar_Cheats = 0, + EnforcedCVar_ClampUnsafeVelocities, + EnforcedCVar_DropKnifeEnable, + EnforcedCVar_AutoBunnyhopping, + EnforcedCVar_MinUpdateRate, + EnforcedCVar_MaxUpdateRate, + EnforcedCVar_MinCmdRate, + EnforcedCVar_MaxCmdRate, + EnforcedCVar_ClientCmdrateDifference, + EnforcedCVar_Turbophysics, + ENFORCEDCVAR_COUNT +}; + +enum +{ + BannedPluginCommand_Funcommands = 0, + BannedPluginCommand_Playercommands, + BANNEDPLUGINCOMMAND_COUNT +}; + +enum +{ + BannedPlugin_Funcommands = 0, + BannedPlugin_Playercommands, + BANNEDPLUGIN_COUNT +}; + +enum GlobalMode +{ + GlobalMode_Invalid = -1, + GlobalMode_KZTimer = 200, + GlobalMode_KZSimple, + GlobalMode_Vanilla +} + + + +// =====[ CONSTANTS ]===== + +#define GL_SOUND_NEW_RECORD "gokz/holyshit.mp3" +#define GL_FPS_MAX_CHECK_INTERVAL 1.0 +#define GL_FPS_MAX_KICK_TIMEOUT 10.0 +#define GL_FPS_MAX_MIN_VALUE 120 +#define GL_MYAW_MAX_VALUE 0.3 + +stock char gC_EnforcedCVars[ENFORCEDCVAR_COUNT][] = +{ + "sv_cheats", + "sv_clamp_unsafe_velocities", + "mp_drop_knife_enable", + "sv_autobunnyhopping", + "sv_minupdaterate", + "sv_maxupdaterate", + "sv_mincmdrate", + "sv_maxcmdrate", + "sv_client_cmdrate_difference", + "sv_turbophysics" +}; + +stock char gC_BannedPluginCommands[BANNEDPLUGINCOMMAND_COUNT][] = +{ + "sm_beacon", + "sm_slap" +}; + +stock char gC_BannedPlugins[BANNEDPLUGIN_COUNT][] = +{ + "Fun Commands", + "Player Commands" +}; + +stock float gF_EnforcedCVarValues[ENFORCEDCVAR_COUNT] = +{ + 0.0, + 0.0, + 0.0, + 0.0, + 128.0, + 128.0, + 128.0, + 128.0, + 0.0, + 0.0 +}; + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player sets a new global top time. + * + * @param client Client index. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode Player's movement mode. + * @param timeType Time type i.e. NUB or PRO. + * @param rank Ranking within the same time type. + * @param rankOverall Overall (NUB and PRO) ranking (0 if not ranked high enough). + * @param runTime Player's end time. + */ +forward void GOKZ_GL_OnNewTopTime(int client, int course, int mode, int timeType, int rank, int rankOverall, float runTime); + + + +// =====[ NATIVES ]===== + +/** + * Prints to chat the global records for a map, course and mode. + * + * @param client Client index. + * @param map Map name or "" for current map. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode GOKZ mode. + */ +native void GOKZ_GL_PrintRecords(int client, const char[] map = "", int course, int mode, const char[] steamid = DEFAULT_STRING); + +/** + * Opens up the global map top menu for a map, course and mode. + * + * @param client Client index. + * @param map Map name or "" for current map. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode GOKZ mode. + * @param timeType Type of time i.e. NUB or PRO. + */ +native void GOKZ_GL_DisplayMapTopMenu(int client, const char[] map = "", int course, int mode, int timeType); + +/** + * Get the total global points of a player. + * + * @param client Client index. + * @param mode GOKZ mode. + * @param timeType Type of time i.e. NUB or PRO. + */ +native void GOKZ_GL_GetPoints(int client, int mode, int timeType); + +/** + * Get the global points on the main coruse of the current map. + * + * @param client Client index. + * @param mode GOKZ mode. + * @param timeType Type of time i.e. NUB or PRO. + */ +native void GOKZ_GL_GetMapPoints(int client, int mode, int timeType); + +/** + * Get the total global ranking points of a player. + * + * @param client Client index. + * @param mode GOKZ mode. + * @return The points. + */ +native int GOKZ_GL_GetRankPoints(int client, int mode); + +/** + * Get the amount of maps a player finished. + * + * @param client Client index. + * @param mode GOKZ mode. + * @param timeType Type of time i.e. NUB or PRO. + */ +native void GOKZ_GL_GetFinishes(int client, int mode, int timeType); + +/** + * Fetch the points a player got from the Global API. + * + * @param client Client index. -1 to update all indices. + * @param mode GOKZ mode. -1 to update all modes. + */ +native void GOKZ_GL_UpdatePoints(int client = -1, int mode = -1); + +/** + * Gets whether the Global API key is valid or not for global status. + * + * @return True if the API key is valid, false otherwise or if there is no connection to the Global API. + */ +native bool GOKZ_GL_GetAPIKeyValid(); + +/** + * Gets whether the running plugins are valid or not for global status. + * + * @return True if the plugins are valid, false otherwise. + */ +native bool GOKZ_GL_GetPluginsValid(); + +/** + * Gets whether the setting enforcer is valid or not for global status. + * + * @return True if the setting enforcer is valid, false otherwise. + */ +native bool GOKZ_GL_GetSettingsEnforcerValid(); + +/** + * Gets whether the current map is valid or not for global status. + * + * @return True if the map is valid, false otherwise or if there is no connection to the Global API. + */ +native bool GOKZ_GL_GetMapValid(); + +/** + * Gets whether the current player is valid or not for global status. + * + * @param client Client index. + * @return True if the player is valid, false otherwise or if there is no connection to the Global API. + */ +native bool GOKZ_GL_GetPlayerValid(int client); + + + +// =====[ STOCKS ]===== + +/** + * Gets the global mode enumeration equivalent for the GOKZ mode. + * + * @param mode GOKZ mode. + * @return Global mode enumeration equivalent. + */ +stock GlobalMode GOKZ_GL_GetGlobalMode(int mode) +{ + switch (mode) + { + case Mode_Vanilla:return GlobalMode_Vanilla; + case Mode_SimpleKZ:return GlobalMode_KZSimple; + case Mode_KZTimer:return GlobalMode_KZTimer; + } + return GlobalMode_Invalid; +} + +/** + * Gets the global mode enumeration equivalent for the GOKZ mode. + * + * @param mode GOKZ mode. + * @return Global mode enumeration equivalent. + */ +stock int GOKZ_GL_FromGlobalMode(GlobalMode mode) +{ + switch (mode) + { + case GlobalMode_Vanilla:return Mode_Vanilla; + case GlobalMode_KZSimple:return Mode_SimpleKZ; + case GlobalMode_KZTimer:return Mode_KZTimer; + } + return -1; +} + +/** + * Gets the string representation of a mode. + * + * @param mode GOKZ mode. + * @param mode_str String version of the mode. + * @param size Max length of mode_str. + * @return True if the conversion was successful. + */ +stock bool GOKZ_GL_GetModeString(int mode, char[] mode_str, int size) +{ + switch (mode) + { + case Mode_Vanilla:strcopy(mode_str, size, "kz_vanilla"); + case Mode_SimpleKZ:strcopy(mode_str, size, "kz_simple"); + case Mode_KZTimer:strcopy(mode_str, size, "kz_timer"); + default:return false; + } + return true; +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_global = +{ + name = "gokz-global", + file = "gokz-global.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_global_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_GL_PrintRecords"); + MarkNativeAsOptional("GOKZ_GL_DisplayMapTopMenu"); + MarkNativeAsOptional("GOKZ_GL_UpdatePoints"); + MarkNativeAsOptional("GOKZ_GL_GetAPIKeyValid"); + MarkNativeAsOptional("GOKZ_GL_GetPluginsValid"); + MarkNativeAsOptional("GOKZ_GL_GetSettingsEnforcerValid"); + MarkNativeAsOptional("GOKZ_GL_GetMapValid"); + MarkNativeAsOptional("GOKZ_GL_GetPlayerValid"); + MarkNativeAsOptional("GOKZ_GL_GetPoints"); + MarkNativeAsOptional("GOKZ_GL_GetMapPoints"); + MarkNativeAsOptional("GOKZ_GL_GetRankPoints"); + MarkNativeAsOptional("GOKZ_GL_GetFinishes"); + MarkNativeAsOptional("GOKZ_GL_UpdatePoints"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/hud.inc b/source/sourcemod/scripting/include/gokz/hud.inc new file mode 100644 index 0000000..5d658ff --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/hud.inc @@ -0,0 +1,468 @@ +/* + gokz-hud Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_hud_included_ +#endinput +#endif +#define _gokz_hud_included_ + + + +// =====[ ENUMS ]===== + +enum HUDOption: +{ + HUDOPTION_INVALID = -1, + HUDOption_TPMenu, + HUDOption_InfoPanel, + HUDOption_ShowKeys, + HUDOption_TimerText, + HUDOption_TimerStyle, + HUDOption_TimerType, + HUDOption_SpeedText, + HUDOption_ShowWeapon, + HUDOption_ShowControls, + HUDOption_DeadstrafeColor, + HUDOption_ShowSpectators, + HUDOption_SpecListPosition, + HUDOption_UpdateRate, + HUDOption_DynamicMenu, + HUDOPTION_COUNT +}; + +enum +{ + TPMenu_Disabled = 0, + TPMenu_Simple, + TPMenu_Advanced, + TPMENU_COUNT +}; + +enum +{ + InfoPanel_Disabled = 0, + InfoPanel_Enabled, + INFOPANEL_COUNT +}; + +enum +{ + ShowKeys_Spectating = 0, + ShowKeys_Always, + ShowKeys_Disabled, + SHOWKEYS_COUNT +}; + +enum +{ + TimerText_Disabled = 0, + TimerText_InfoPanel, + TimerText_TPMenu, + TimerText_Bottom, + TimerText_Top, + TIMERTEXT_COUNT +}; + +enum +{ + TimerStyle_Standard = 0, + TimerStyle_Precise, + TIMERSTYLE_COUNT +}; + +enum +{ + TimerType_Disabled = 0, + TimerType_Enabled, + TIMERTYPE_COUNT +}; + +enum +{ + SpeedText_Disabled = 0, + SpeedText_InfoPanel, + SpeedText_Bottom, + SPEEDTEXT_COUNT +}; + +enum +{ + ShowWeapon_Disabled = 0, + ShowWeapon_Enabled, + SHOWWEAPON_COUNT +}; + +enum +{ + ReplayControls_Disabled = 0, + ReplayControls_Enabled, + REPLAYCONTROLS_COUNT +}; + +enum +{ + DeadstrafeColor_Disabled = 0, + DeadstrafeColor_Enabled, + DEADSTRAFECOLOR_COUNT +}; + +enum +{ + ShowSpecs_Disabled = 0, + ShowSpecs_Number, + ShowSpecs_Full, + SHOWSPECS_COUNT +}; + +enum +{ + SpecListPosition_TPMenu = 0, + SpecListPosition_InfoPanel, + SPECLISTPOSITION_COUNT +} + +enum +{ + UpdateRate_Slow = 0, + UpdateRate_Fast, + UPDATERATE_COUNT, +}; + +enum +{ + DynamicMenu_Legacy = 0, + DynamicMenu_Disabled, + DynamicMenu_Enabled, + DYNAMICMENU_COUNT +}; + +// =====[ STRUCTS ]====== + +enum struct HUDInfo +{ + bool TimerRunning; + int TimeType; + float Time; + bool Paused; + bool OnGround; + bool OnLadder; + bool Noclipping; + bool Ducking; + bool HitBhop; + bool IsTakeoff; + float Speed; + int ID; + bool Jumped; + bool HitPerf; + bool HitJB; + float TakeoffSpeed; + int Buttons; + int CurrentTeleport; +} + + + +// =====[ CONSTANTS ]===== + +#define HUD_OPTION_CATEGORY "HUD" +#define HUD_MAX_BHOP_GROUND_TICKS 5 +#define HUD_MAX_HINT_SIZE 227 + +stock char gC_HUDOptionNames[HUDOPTION_COUNT][] = +{ + "GOKZ HUD - Teleport Menu", + "GOKZ HUD - Centre Panel", + "GOKZ HUD - Show Keys", + "GOKZ HUD - Timer Text", + "GOKZ HUD - Timer Style", + "GOKZ HUD - Show Time Type", + "GOKZ HUD - Speed Text", + "GOKZ HUD - Show Weapon", + "GOKZ HUD - Show Controls", + "GOKZ HUD - Dead Strafe", + "GOKZ HUD - Show Spectators", + "GOKZ HUD - Spec List Pos", + "GOKZ HUD - Update Rate", + "GOKZ HUD - Dynamic Menu" +}; + +stock char gC_HUDOptionDescriptions[HUDOPTION_COUNT][] = +{ + "Teleport Menu - 0 = Disabled, 1 = Simple, 2 = Advanced", + "Centre Information Panel - 0 = Disabled, 1 = Enabled", + "Key Press Display - 0 = Spectating, 1 = Always, 2 = Disabled", + "Timer Display - 0 = Disabled, 1 = Centre Panel, 2 = Teleport Menu, 3 = Bottom, 4 = Top", + "Timer Style - 0 = Standard, 1 = Precise", + "Timer Type - 0 = Disabled, 1 = Enabled", + "Speed Display - 0 = Disabled, 1 = Centre Panel, 2 = Bottom", + "Weapon Viewmodel - 0 = Disabled, 1 = Enabled", + "Replay Controls Display - 0 = Disbled, 1 = Enabled", + "Dead Strafe Indicator - 0 = Disabled, 1 = Enabled", + "Show Spectators - 0 = Disabled, 1 = Number Only, 2 = Number and Names", + "Spectator List Position - 0 = Teleport Menu, 2 = Center Panel", + "HUD Update Rate - 0 = Slow, 1 = Fast", + "Dynamic Menu - 0 = Legacy, 1 = Disabled, 2 = Enabled" +}; + +stock char gC_HUDOptionPhrases[HUDOPTION_COUNT][] = +{ + "Options Menu - Teleport Menu", + "Options Menu - Info Panel", + "Options Menu - Show Keys", + "Options Menu - Timer Text", + "Options Menu - Timer Style", + "Options Menu - Timer Type", + "Options Menu - Speed Text", + "Options Menu - Show Weapon", + "Options Menu - Show Controls", + "Options Menu - Dead Strafe Indicator", + "Options Menu - Show Spectators", + "Options Menu - Spectator List Position", + "Options Menu - Update Rate", + "Options Menu - Dynamic Menu" +}; + +stock int gI_HUDOptionCounts[HUDOPTION_COUNT] = +{ + TPMENU_COUNT, + INFOPANEL_COUNT, + SHOWKEYS_COUNT, + TIMERTEXT_COUNT, + TIMERSTYLE_COUNT, + TIMERTYPE_COUNT, + SPEEDTEXT_COUNT, + SHOWWEAPON_COUNT, + REPLAYCONTROLS_COUNT, + DEADSTRAFECOLOR_COUNT, + SHOWSPECS_COUNT, + SPECLISTPOSITION_COUNT, + UPDATERATE_COUNT, + DYNAMICMENU_COUNT +}; + +stock int gI_HUDOptionDefaults[HUDOPTION_COUNT] = +{ + TPMenu_Advanced, + InfoPanel_Enabled, + ShowKeys_Spectating, + TimerText_InfoPanel, + TimerStyle_Standard, + TimerType_Enabled, + SpeedText_InfoPanel, + ShowWeapon_Enabled, + ReplayControls_Enabled, + DeadstrafeColor_Disabled, + ShowSpecs_Disabled, + SpecListPosition_TPMenu, + UpdateRate_Slow, + DynamicMenu_Legacy +}; + +stock char gC_TPMenuPhrases[TPMENU_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Simple", + "Options Menu - Advanced" +}; + +stock char gC_ShowKeysPhrases[SHOWKEYS_COUNT][] = +{ + "Options Menu - Spectating", + "Options Menu - Always", + "Options Menu - Disabled" +}; + +stock char gC_TimerTextPhrases[TIMERTEXT_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Info Panel", + "Options Menu - Teleport Menu", + "Options Menu - Bottom", + "Options Menu - Top" +}; + +stock char gC_TimerTypePhrases[TIMERTYPE_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Enabled" +}; + +stock char gC_SpeedTextPhrases[SPEEDTEXT_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Info Panel", + "Options Menu - Bottom" +}; + +stock char gC_ShowControlsPhrases[REPLAYCONTROLS_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Enabled" +}; + +stock char gC_DeadstrafeColorPhrases[DEADSTRAFECOLOR_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Enabled" +}; + +stock char gC_ShowSpecsPhrases[SHOWSPECS_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Number", + "Options Menu - Number and Names" +}; + +stock char gC_SpecListPositionPhrases[SPECLISTPOSITION_COUNT][] = +{ + "Options Menu - Teleport Menu", + "Options Menu - Info Panel" +}; + +stock char gC_HUDUpdateRatePhrases[UPDATERATE_COUNT][]= +{ + "Options Menu - Slow", + "Options Menu - Fast" +}; + +stock char gC_DynamicMenuPhrases[DYNAMICMENU_COUNT][]= +{ + "Options Menu - Legacy", + "Options Menu - Disabled", + "Options Menu - Enabled" +}; + +// =====[ NATIVES ]===== + +/** + * Returns whether the GOKZ HUD menu is showing for a client. + * + * @param client Client index. + * @return Whether the GOKZ HUD menu is showing. + */ +native bool GOKZ_HUD_GetMenuShowing(int client); + +/** + * Sets whether the GOKZ HUD menu would be showing for a client. + * + * @param client Client index. + * @param value Whether the GOKZ HUD menu would be showing for a client. + */ +native void GOKZ_HUD_SetMenuShowing(int client, bool value); + +/** + * Gets the spectator text for the menu. Used by GOKZ-replays. + * + * @param client Client index. + * @param value Whether the GOKZ HUD menu would be showing for a client. + */ +native void GOKZ_HUD_GetMenuSpectatorText(int client, any[] info, char[] buffer, int size); + +/** + * Forces the client's TP menu to update. + * + * @param client Client index. + */ +native void GOKZ_HUD_ForceUpdateTPMenu(int client); + +// =====[ STOCKS ]===== + +/** + * Returns whether an option is a gokz-hud option. + * + * @param option Option name. + * @param optionEnum Variable to store enumerated gokz-hud option (if it is one). + * @return Whether option is a gokz-hud option. + */ +stock bool GOKZ_HUD_IsHUDOption(const char[] option, HUDOption &optionEnum = HUDOPTION_INVALID) +{ + for (HUDOption i; i < HUDOPTION_COUNT; i++) + { + if (StrEqual(option, gC_HUDOptionNames[i])) + { + optionEnum = i; + return true; + } + } + return false; +} + +/** + * Gets the current value of a player's gokz-hud option. + * + * @param client Client index. + * @param option gokz-hud option. + * @return Current value of option. + */ +stock any GOKZ_HUD_GetOption(int client, HUDOption option) +{ + return GOKZ_GetOption(client, gC_HUDOptionNames[option]); +} + +/** + * Sets a player's gokz-hud option's value. + * + * @param client Client index. + * @param option gokz-hud option. + * @param value New option value. + * @return Whether option was successfully set. + */ +stock bool GOKZ_HUD_SetOption(int client, HUDOption option, any value) +{ + return GOKZ_SetOption(client, gC_HUDOptionNames[option], value); +} + +/** + * Increment an integer-type gokz-hud option's value. + * Loops back to '0' if max value is exceeded. + * + * @param client Client index. + * @param option gokz-hud option. + * @return Whether option was successfully set. + */ +stock bool GOKZ_HUD_CycleOption(int client, HUDOption option) +{ + return GOKZ_CycleOption(client, gC_HUDOptionNames[option]); +} + +/** + * Represents a time float as a string e.g. 01:23.45 + * and according to the client's HUD options. + * + * @param client Client index. + * @param time Time in seconds. + * @return String representation of time. + */ +stock char[] GOKZ_HUD_FormatTime(int client, float time) +{ + bool precise = GOKZ_HUD_GetOption(client, HUDOption_TimerStyle) == TimerStyle_Precise; + return GOKZ_FormatTime(time, precise); +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_hud = +{ + name = "gokz-hud", + file = "gokz-hud.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_hud_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_HUD_GetMenuShowing"); + MarkNativeAsOptional("GOKZ_HUD_SetMenuShowing"); + MarkNativeAsOptional("GOKZ_HUD_GetMenuSpectatorText"); + MarkNativeAsOptional("GOKZ_HUD_ForceUpdateTPMenu"); +} +#endif diff --git a/source/sourcemod/scripting/include/gokz/jumpbeam.inc b/source/sourcemod/scripting/include/gokz/jumpbeam.inc new file mode 100644 index 0000000..1b92479 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/jumpbeam.inc @@ -0,0 +1,148 @@ +/* + gokz-jumpbeam Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_jumpbeam_included_ +#endinput +#endif +#define _gokz_jumpbeam_included_ + + + +// =====[ ENUMS ]===== + +enum JBOption: +{ + JBOPTION_INVALID = -1, + JBOption_Type, + JBOPTION_COUNT +}; + +enum +{ + JBType_Disabled = 0, + JBType_Feet, + JBType_Head, + JBType_FeetAndHead, + JBType_Ground, + JBTYPE_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define JB_BEAM_LIFETIME 4.0 + +stock char gC_JBOptionNames[JBOPTION_COUNT][] = +{ + "GOKZ JB - Jump Beam Type" +}; + +stock char gC_JBOptionDescriptions[JBOPTION_COUNT][] = +{ + "Jump Beam Type - 0 = Disabled, 1 = Feet, 2 = Head, 3 = Feet & Head, 4 = Ground" +}; + +stock int gI_JBOptionDefaultValues[JBOPTION_COUNT] = +{ + JBType_Disabled +}; + +stock int gI_JBOptionCounts[JBOPTION_COUNT] = +{ + JBTYPE_COUNT +}; + +stock char gC_JBOptionPhrases[JBOPTION_COUNT][] = +{ + "Options Menu - Jump Beam" +}; + +stock char gC_JBTypePhrases[JBTYPE_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Feet", + "Options Menu - Head", + "Options Menu - Feet and Head", + "Options Menu - Ground" +}; + + + +// =====[ STOCKS ]===== + +/** + * Returns whether an option is a gokz-jumpbeam option. + * + * @param option Option name. + * @param optionEnum Variable to store enumerated gokz-jumpbeam option (if it is one). + * @return Whether option is a gokz-jumpbeam option. + */ +stock bool GOKZ_JB_IsJBOption(const char[] option, JBOption &optionEnum = JBOPTION_INVALID) +{ + for (JBOption i; i < JBOPTION_COUNT; i++) + { + if (StrEqual(option, gC_JBOptionNames[i])) + { + optionEnum = i; + return true; + } + } + return false; +} + +/** + * Gets the current value of a player's gokz-jumpbeam option. + * + * @param client Client index. + * @param option gokz-jumpbeam option. + * @return Current value of option. + */ +stock any GOKZ_JB_GetOption(int client, JBOption option) +{ + return GOKZ_GetOption(client, gC_JBOptionNames[option]); +} + +/** + * Sets a player's gokz-jumpbeam option's value. + * + * @param client Client index. + * @param option gokz-jumpbeam option. + * @param value New option value. + * @return Whether option was successfully set. + */ +stock bool GOKZ_JB_SetOption(int client, JBOption option, any value) +{ + return GOKZ_SetOption(client, gC_JBOptionNames[option], value); +} + +/** + * Increment an integer-type gokz-jumpbeam option's value. + * Loops back to '0' if max value is exceeded. + * + * @param client Client index. + * @param option gokz-jumpbeam option. + * @return Whether option was successfully set. + */ +stock bool GOKZ_JB_CycleOption(int client, JBOption option) +{ + return GOKZ_CycleOption(client, gC_JBOptionNames[option]); +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_jumpbeam = +{ + name = "gokz-jumpbeam", + file = "gokz-jumpbeam.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/jumpstats.inc b/source/sourcemod/scripting/include/gokz/jumpstats.inc new file mode 100644 index 0000000..452ae28 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/jumpstats.inc @@ -0,0 +1,442 @@ +/* + gokz-jumpstats Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_jumpstats_included_ +#endinput +#endif +#define _gokz_jumpstats_included_ + + + +// =====[ ENUMS ]===== + +enum +{ + JumpType_FullInvalid = -1, + JumpType_LongJump, + JumpType_Bhop, + JumpType_MultiBhop, + JumpType_WeirdJump, + JumpType_LadderJump, + JumpType_Ladderhop, + JumpType_Jumpbug, + JumpType_LowpreBhop, + JumpType_LowpreWeirdJump, + JumpType_Fall, + JumpType_Other, + JumpType_Invalid, + JUMPTYPE_COUNT +}; + +enum +{ + StrafeDirection_None, + StrafeDirection_Left, + StrafeDirection_Right +}; + +enum +{ + DistanceTier_None = 0, + DistanceTier_Meh, + DistanceTier_Impressive, + DistanceTier_Perfect, + DistanceTier_Godlike, + DistanceTier_Ownage, + DistanceTier_Wrecker, + DISTANCETIER_COUNT +}; + +enum JSOption: +{ + JSOPTION_INVALID = -1, + JSOption_JumpstatsMaster, + JSOption_MinChatTier, + JSOption_MinConsoleTier, + JSOption_MinSoundTier, + JSOption_FailstatsConsole, + JSOption_FailstatsChat, + JSOption_JumpstatsAlways, + JSOption_ExtendedChatReport, + JSOption_MinChatBroadcastTier, + JSOption_MinSoundBroadcastTier, + JSOPTION_COUNT +}; + +enum +{ + JSToggleOption_Disabled = 0, + JSToggleOption_Enabled, + JSTOGGLEOPTION_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define JS_CFG_TIERS "cfg/sourcemod/gokz/gokz-jumpstats-tiers.cfg" +#define JS_CFG_SOUNDS "cfg/sourcemod/gokz/gokz-jumpstats-sounds.cfg" +#define JS_CFG_BROADCAST "cfg/sourcemod/gokz/gokz-jumpstats-broadcast.cfg" +#define JS_OPTION_CATEGORY "Jumpstats" +#define JS_MAX_LADDERJUMP_OFFSET 2.0 +#define JS_MAX_BHOP_GROUND_TICKS 5 +#define JS_MAX_DUCKBUG_RESET_TICKS 6 +#define JS_MAX_WEIRDJUMP_FALL_OFFSET 64.0 +#define JS_TOUCH_GRACE_TICKS 3 +#define JS_MAX_TRACKED_STRAFES 48 +#define JS_MIN_BLOCK_DISTANCE 186 +#define JS_MIN_LAJ_BLOCK_DISTANCE 50 +#define JS_MAX_LAJ_FAILSTAT_DISTANCE 250 +#define JS_TOP_RECORD_COUNT 20 +#define JS_MAX_JUMP_DISTANCE 500 +#define JS_FAILSTATS_MAX_TRACKED_TICKS 128 +#define JS_MIN_TELEPORT_DELAY 5 +#define JS_SPEED_MODIFICATION_TOLERANCE 0.1 +#define JS_OFFSET_EPSILON 0.03125 + +stock char gC_JumpTypes[JUMPTYPE_COUNT][] = +{ + "Long Jump", + "Bunnyhop", + "Multi Bunnyhop", + "Weird Jump", + "Ladder Jump", + "Ladderhop", + "Jumpbug", + "Lowpre Bunnyhop", + "Lowpre Weird Jump", + "Fall", + "Unknown Jump", + "Invalid Jump" +}; + +stock char gC_JumpTypesShort[JUMPTYPE_COUNT][] = +{ + "LJ", + "BH", + "MBH", + "WJ", + "LAJ", + "LAH", + "JB", + "LBH", + "LWJ", + "FL", + "UNK", + "INV" +}; + +stock char gC_JumpTypeKeys[JUMPTYPE_COUNT][] = +{ + "longjump", + "bhop", + "multibhop", + "weirdjump", + "ladderjump", + "ladderhop", + "jumpbug", + "lowprebhop", + "lowpreweirdjump", + "fall", + "unknown", + "invalid" +}; + +stock char gC_DistanceTiers[DISTANCETIER_COUNT][] = +{ + "None", + "Meh", + "Impressive", + "Perfect", + "Godlike", + "Ownage", + "Wrecker" +}; + +stock char gC_DistanceTierKeys[DISTANCETIER_COUNT][] = +{ + "none", + "meh", + "impressive", + "perfect", + "godlike", + "ownage", + "wrecker" +}; + +stock char gC_DistanceTierChatColours[DISTANCETIER_COUNT][] = +{ + "{grey}", + "{grey}", + "{blue}", + "{green}", + "{darkred}", + "{gold}", + "{orchid}" +}; + +stock char gC_JSOptionNames[JSOPTION_COUNT][] = +{ + "GOKZ JS - Master Switch", + "GOKZ JS - Chat Report", + "GOKZ JS - Console Report", + "GOKZ JS - Sounds", + "GOKZ JS - Failstats Console", + "GOKZ JS - Failstats Chat", + "GOKZ JS - Jumpstats Always", + "GOKZ JS - Ext Chat Report", + "GOKZ JS - Min Chat Broadcast", + "GOKZ JS - Min Sound Broadcast" +}; + +stock char gC_JSOptionDescriptions[JSOPTION_COUNT][] = +{ + "Master Switch for All Jumpstats Functionality - 0 = Disabled, 1 = Enabled", + "Minimum Tier for Jumpstats Chat Report - 0 = Disabled, 1 = Meh+, 2 = Impressive+, 3 = Perfect+, 4 = Godlike+, 5 = Ownage+, 6 = Wrecker", + "Minimum Tier for Jumpstats Console report - 0 = Disabled, 1 = Meh+, 2 = Impressive+, 3 = Perfect+, 4 = Godlike+, 5 = Ownage+, 6 = Wrecker", + "Minimum Tier for Jumpstats Sounds - 0 = Disabled, 2 = Impressive+, 3 = Perfect+, 4 = Godlike+, 5 = Ownage+, 6 = Wrecker", + "Print Failstats To Console - 0 = Disabled, 1 = Enabled", + "Print Failstats To Chat - 0 = Disabled, 1 = Enabled", + "Always show jumpstats, even for invalid jumps - 0 = Disabled, 1 = Enabled", + "Extended Chat Report - 0 = Disabled, 1 = Enabled", + "Minimum Jump Tier for Jumpstat Chat Broadcast - 0 = Disabled, 1 = Meh+, 2 = Impressive+, 3 = Perfect+, 4 = Godlike+, 5 = Ownage+, 6 = Wrecker", + "Minimum Jump Tier for Jumpstat Sound Broadcast - 0 = Disabled, 1 = Meh+, 2 = Impressive+, 3 = Perfect+, 4 = Godlike+, 5 = Ownage+, 6 = Wrecker" +}; + +stock char gI_JSOptionPhrases[JSOPTION_COUNT][] = +{ + "Options Menu - Jumpstats Master Switch", + "Options Menu - Jumpstats Chat Report", + "Options Menu - Jumpstats Console Report", + "Options Menu - Jumpstats Sounds", + "Options Menu - Failstats Console Report", + "Options Menu - Failstats Chat Report", + "Options Menu - Jumpstats Always", + "Options Menu - Extended Jump Chat Report", + "Options Menu - Minimal Jump Chat Broadcast Tier", + "Options Menu - Minimal Jump Sound Broadcast Tier" +}; + +stock int gI_JSOptionDefaults[JSOPTION_COUNT] = +{ + JSToggleOption_Enabled, + DistanceTier_Meh, + DistanceTier_Meh, + DistanceTier_Impressive, + JSToggleOption_Enabled, + JSToggleOption_Disabled, + JSToggleOption_Disabled, + JSToggleOption_Disabled, + DistanceTier_Ownage, + DistanceTier_None +}; + +stock int gI_JSOptionCounts[JSOPTION_COUNT] = +{ + JSTOGGLEOPTION_COUNT, + DISTANCETIER_COUNT, + DISTANCETIER_COUNT, + DISTANCETIER_COUNT, + JSTOGGLEOPTION_COUNT, + JSTOGGLEOPTION_COUNT, + JSTOGGLEOPTION_COUNT, + JSTOGGLEOPTION_COUNT, + DISTANCETIER_COUNT, + DISTANCETIER_COUNT +}; + + + +// =====[ STRUCTS ]===== + +enum struct Jump +{ + int jumper; + int block; + int crouchRelease; + int crouchTicks; + int deadair; + int duration; + int originalType; + int overlap; + int releaseW; + int strafes; + int type; + float deviation; + float distance; + float edge; + float height; + float maxSpeed; + float offset; + float preSpeed; + float sync; + float width; + + // For the 'always' stats + float miss; + + // We can't make a separate enum struct for that cause it won't let us + // index an array of enum structs. + int strafes_gainTicks[JS_MAX_TRACKED_STRAFES]; + int strafes_deadair[JS_MAX_TRACKED_STRAFES]; + int strafes_overlap[JS_MAX_TRACKED_STRAFES]; + int strafes_ticks[JS_MAX_TRACKED_STRAFES]; + float strafes_gain[JS_MAX_TRACKED_STRAFES]; + float strafes_loss[JS_MAX_TRACKED_STRAFES]; + float strafes_sync[JS_MAX_TRACKED_STRAFES]; + float strafes_width[JS_MAX_TRACKED_STRAFES]; +} + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player begins their jump. + * + * @param client Client index. + * @param jumpType Type of jump. + */ +forward void GOKZ_JS_OnTakeoff(int client, int jumpType); + +/** + * Called when a player lands their jump. + * + * @param jump The jumpstats. + */ +forward void GOKZ_JS_OnLanding(Jump jump); + +/** + * Called when player's current jump has been declared an invalid jumpstat. + * + * @param client Client index. + */ +forward void GOKZ_JS_OnJumpInvalidated(int client); + +/** + * Called when a player fails a blockjump. + * + * @param jump The jumpstats. + */ +forward void GOKZ_JS_OnFailstat(Jump jump); + +/** + * Called when a player lands a jump and has always-on jumpstats enabled. + * + * @param jump The jumpstats. + */ +forward void GOKZ_JS_OnJumpstatAlways(Jump jump); + +/** + * Called when a player fails a jump and has always-on failstats enabled. + * + * @param jump The failstats. + */ +forward void GOKZ_JS_OnFailstatAlways(Jump jump); + + + +// =====[ NATIVES ]===== + +/** + * Gets the default jumpstats option value as set by a config file. + * + * @param option GOKZ Jumpstats option. + * @return Default option value. + */ +native int GOKZ_JS_GetDefaultOption(JSOption option); + +/** + * Declare a player's current jump an invalid jumpstat. + * + * @param client Client index. + */ +native void GOKZ_JS_InvalidateJump(int client); + + + +// =====[ STOCKS ]===== + +/** + * Returns whether an option is a gokz-jumpstats option. + * + * @param option Option name. + * @param optionEnum Variable to store enumerated gokz-jumpstats option (if it is one). + * @return Whether option is a gokz-jumpstats option. + */ +stock bool GOKZ_JS_IsJSOption(const char[] option, JSOption &optionEnum = JSOPTION_INVALID) +{ + for (JSOption i; i < JSOPTION_COUNT; i++) + { + if (StrEqual(option, gC_JSOptionNames[i])) + { + optionEnum = i; + return true; + } + } + return false; +} + +/** + * Gets the current value of a player's gokz-jumpstats option. + * + * @param client Client index. + * @param option gokz-jumpstats option. + * @return Current value of option. + */ +stock any GOKZ_JS_GetOption(int client, JSOption option) +{ + return GOKZ_GetOption(client, gC_JSOptionNames[option]); +} + +/** + * Sets a player's gokz-jumpstats option's value. + * + * @param client Client index. + * @param option gokz-jumpstats option. + * @param value New option value. + * @return Whether option was successfully set. + */ +stock bool GOKZ_JS_SetOption(int client, JSOption option, any value) +{ + return GOKZ_SetOption(client, gC_JSOptionNames[option], value); +} + +/** + * Increment an integer-type gokz-jumpstats option's value. + * Loops back to '0' if max value is exceeded. + * + * @param client Client index. + * @param option gokz-jumpstats option. + * @return Whether option was successfully set. + */ +stock bool GOKZ_JS_CycleOption(int client, JSOption option) +{ + return GOKZ_CycleOption(client, gC_JSOptionNames[option]); +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_jumpstats = +{ + name = "gokz-jumpstats", + file = "gokz-jumpstats.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_jumpstats_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_JS_GetDefaultOption"); + MarkNativeAsOptional("GOKZ_JS_InvalidateJump"); +} +#endif diff --git a/source/sourcemod/scripting/include/gokz/kzplayer.inc b/source/sourcemod/scripting/include/gokz/kzplayer.inc new file mode 100644 index 0000000..8176d39 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/kzplayer.inc @@ -0,0 +1,584 @@ +/* + GOKZ KZPlayer Methodmap Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_kzplayer_included_ +#endinput +#endif +#define _gokz_kzplayer_included_ + +#include + +#include + + + +methodmap KZPlayer < MovementAPIPlayer { + + public KZPlayer(int client) { + return view_as(MovementAPIPlayer(client)); + } + + + + // =====[ GENERAL ]===== + + property bool Valid { + public get() { + return IsValidClient(this.ID); + } + } + + property bool InGame { + public get() { + return IsClientInGame(this.ID); + } + } + + property bool Authorized { + public get() { + return IsClientAuthorized(this.ID); + } + } + + property bool Fake { + public get() { + return IsFakeClient(this.ID); + } + } + + property bool Alive { + public get() { + return IsPlayerAlive(this.ID); + } + } + + property ObsMode ObserverMode { + public get() { + return GetObserverMode(this.ID); + } + } + + property int ObserverTarget { + public get() { + return GetObserverTarget(this.ID); + } + } + + + + // =====[ CORE ]===== + #if defined _gokz_core_included_ + + public void StartTimer(int course) { + GOKZ_StartTimer(this.ID, course); + } + + public void EndTimer(int course) { + GOKZ_EndTimer(this.ID, course); + } + + public bool StopTimer() { + return GOKZ_StopTimer(this.ID); + } + + public void TeleportToStart() { + GOKZ_TeleportToStart(this.ID); + } + + public void TeleportToSearchStart(int course) { + GOKZ_TeleportToSearchStart(this.ID, course); + } + + public void TeleportToEnd(int course) { + GOKZ_TeleportToEnd(this.ID, course); + } + + property StartPositionType StartPositionType { + public get() { + return GOKZ_GetStartPositionType(this.ID); + } + } + + public void MakeCheckpoint() { + GOKZ_MakeCheckpoint(this.ID); + } + + property bool CanMakeCheckpoint { + public get() { + return GOKZ_GetCanMakeCheckpoint(this.ID); + } + } + + public void TeleportToCheckpoint() { + GOKZ_TeleportToCheckpoint(this.ID); + } + + property bool CanTeleportToCheckpoint { + public get() { + return GOKZ_GetCanTeleportToCheckpoint(this.ID); + } + } + + public void PrevCheckpoint() { + GOKZ_PrevCheckpoint(this.ID); + } + + property bool CanPrevCheckpoint { + public get() { + return GOKZ_GetCanPrevCheckpoint(this.ID); + } + } + + public void NextCheckpoint() { + GOKZ_NextCheckpoint(this.ID); + } + + property bool CanNextCheckpoint { + public get() { + return GOKZ_GetCanNextCheckpoint(this.ID); + } + } + + public void UndoTeleport() { + GOKZ_UndoTeleport(this.ID); + } + + property bool CanUndoTeleport { + public get() { + return GOKZ_GetCanUndoTeleport(this.ID); + } + } + + public void Pause() { + GOKZ_Pause(this.ID); + } + + property bool CanPause { + public get() { + return GOKZ_GetCanPause(this.ID); + } + } + + public void Resume() { + GOKZ_Resume(this.ID); + } + + property bool CanResume { + public get() { + return GOKZ_GetCanResume(this.ID); + } + } + + public void TogglePause() { + GOKZ_TogglePause(this.ID); + } + + public void PlayErrorSound() { + GOKZ_PlayErrorSound(this.ID); + } + + property bool TimerRunning { + public get() { + return GOKZ_GetTimerRunning(this.ID); + } + } + + property int Course { + public get() { + return GOKZ_GetCourse(this.ID); + } + } + + property bool Paused { + public get() { + return GOKZ_GetPaused(this.ID); + } + public set(bool pause) { + if (pause) { + this.Pause(); + } + else { + this.Resume(); + } + } + } + + property bool CanTeleportToStart { + public get() { + return GOKZ_GetCanTeleportToStartOrEnd(this.ID); + } + } + + property float Time { + public get() { + return GOKZ_GetTime(this.ID); + } + public set(float value) { + GOKZ_SetTime(this.ID, value); + } + } + + property int CheckpointCount { + public get() { + return GOKZ_GetCheckpointCount(this.ID); + } + public set(int cpCount) { + GOKZ_SetCheckpointCount(this.ID, cpCount); + } + } + + property ArrayList CheckpointData { + public get() { + return GOKZ_GetCheckpointData(this.ID); + } + public set(ArrayList checkpoints) { + GOKZ_SetCheckpointData(this.ID, checkpoints, GOKZ_CHECKPOINT_VERSION); + } + } + + property int TeleportCount { + public get() { + return GOKZ_GetTeleportCount(this.ID); + } + public set(int value) { + GOKZ_SetTeleportCount(this.ID, value); + } + } + + property int TimeType { + public get() { + return GOKZ_GetTimeType(this.ID); + } + } + + property bool GOKZHitPerf { + public get() { + return GOKZ_GetHitPerf(this.ID); + } + public set(bool value) { + GOKZ_SetHitPerf(this.ID, value); + } + } + + property float GOKZTakeoffSpeed { + public get() { + return GOKZ_GetTakeoffSpeed(this.ID); + } + public set(float value) { + GOKZ_SetTakeoffSpeed(this.ID, value); + } + } + + property bool ValidJump { + public get() { + return GOKZ_GetValidJump(this.ID); + } + } + + public any GetOption(const char[] option) { + return GOKZ_GetOption(this.ID, option); + } + + public bool SetOption(const char[] option, any value) { + return GOKZ_SetOption(this.ID, option, value); + } + + public bool CycleOption(const char[] option) { + return GOKZ_CycleOption(this.ID, option); + } + + public any GetCoreOption(Option option) { + return GOKZ_GetCoreOption(this.ID, option); + } + + public bool SetCoreOption(Option option, int value) { + return GOKZ_SetCoreOption(this.ID, option, value); + } + + public bool CycleCoreOption(Option option) { + return GOKZ_CycleCoreOption(this.ID, option); + } + + property int Mode { + public get() { + return this.GetCoreOption(Option_Mode); + } + public set(int value) { + this.SetCoreOption(Option_Mode, value); + } + } + + property int Style { + public get() { + return this.GetCoreOption(Option_Style); + } + public set(int value) { + this.SetCoreOption(Option_Style, value); + } + } + + property int CheckpointMessages { + public get() { + return this.GetCoreOption(Option_CheckpointMessages); + } + public set(int value) { + this.SetCoreOption(Option_CheckpointMessages, value); + } + } + + property int CheckpointSounds { + public get() { + return this.GetCoreOption(Option_CheckpointSounds); + } + public set(int value) { + this.SetCoreOption(Option_CheckpointSounds, value); + } + } + + property int TeleportSounds { + public get() { + return this.GetCoreOption(Option_TeleportSounds); + } + public set(int value) { + this.SetCoreOption(Option_TeleportSounds, value); + } + } + + property int ErrorSounds { + public get() { + return this.GetCoreOption(Option_ErrorSounds); + } + public set(int value) { + this.SetCoreOption(Option_ErrorSounds, value); + } + } + + #endif + // =====[ END CORE ]===== + + + + // =====[ HUD ]===== + #if defined _gokz_hud_included_ + + public any GetHUDOption(HUDOption option) { + return GOKZ_HUD_GetOption(this.ID, option); + } + + public bool SetHUDOption(HUDOption option, any value) { + return GOKZ_HUD_SetOption(this.ID, option, value); + } + + public bool CycleHUDOption(HUDOption option) { + return GOKZ_HUD_CycleOption(this.ID, option); + } + + property int TPMenu { + public get() { + return this.GetHUDOption(HUDOption_TPMenu); + } + public set(int value) { + this.SetHUDOption(HUDOption_TPMenu, value); + } + } + + property int InfoPanel { + public get() { + return this.GetHUDOption(HUDOption_InfoPanel); + } + public set(int value) { + this.SetHUDOption(HUDOption_InfoPanel, value); + } + } + + property int ShowKeys { + public get() { + return this.GetHUDOption(HUDOption_ShowKeys); + } + public set(int value) { + this.SetHUDOption(HUDOption_ShowKeys, value); + } + } + + property int TimerText { + public get() { + return this.GetHUDOption(HUDOption_TimerText); + } + public set(int value) { + this.SetHUDOption(HUDOption_TimerText, value); + } + } + + property int TimerStyle { + public get() { + return this.GetHUDOption(HUDOption_TimerStyle); + } + public set(int value) { + this.SetHUDOption(HUDOption_TimerStyle, value); + } + } + + property int SpeedText { + public get() { + return this.GetHUDOption(HUDOption_SpeedText); + } + public set(int value) { + this.SetHUDOption(HUDOption_SpeedText, value); + } + } + + property int ShowWeapon { + public get() { + return this.GetHUDOption(HUDOption_ShowWeapon); + } + public set(int value) { + this.SetHUDOption(HUDOption_ShowWeapon, value); + } + } + + property int ReplayControls { + public get() { + return this.GetHUDOption(HUDOption_ShowControls); + } + public set(int value) { + this.SetHUDOption(HUDOption_ShowControls, value); + } + } + + property int ShowSpectators { + public get() { + return this.GetHUDOption(HUDOption_ShowSpectators); + } + public set(int value) { + this.SetHUDOption(HUDOption_ShowSpectators, value); + } + } + + property int SpecListPosition { + public get() { + return this.GetHUDOption(HUDOption_SpecListPosition); + } + public set(int value){ + this.SetHUDOption(HUDOption_SpecListPosition, value); + } + } + + property bool MenuShowing { + public get() { + return GOKZ_HUD_GetMenuShowing(this.ID); + } + public set(bool value) { + GOKZ_HUD_SetMenuShowing(this.ID, value); + } + } + property int DynamicMenu { + public get() { + return this.GetHUDOption(HUDOption_DynamicMenu); + } + public set(int value) { + this.SetHUDOption(HUDOption_DynamicMenu, value); + } + } + #endif + // =====[ END HUD ]===== + + + + // =====[ PISTOL ]===== + #if defined _gokz_pistol_included_ + + property int Pistol { + public get() { + return this.GetOption(PISTOL_OPTION_NAME); + } + public set(int value) { + this.SetOption(PISTOL_OPTION_NAME, value); + } + } + + #endif + // =====[ END PISTOL ]===== + + + + // =====[ JUMP BEAM ]===== + #if defined _gokz_jumpbeam_included_ + + public any GetJBOption(JBOption option) { + return GOKZ_JB_GetOption(this.ID, option); + } + + public bool SetJBOption(JBOption option, any value) { + return GOKZ_JB_SetOption(this.ID, option, value); + } + + public bool CycleJBOption(JBOption option) { + return GOKZ_JB_CycleOption(this.ID, option); + } + + property int JBType { + public get() { + return this.GetJBOption(JBOption_Type); + } + public set(int value) { + this.SetJBOption(JBOption_Type, value); + } + } + + #endif + // =====[ END JUMP BEAM ]===== + + + + // =====[ TIPS ]===== + #if defined _gokz_tips_included_ + + property int Tips { + public get() { + return this.GetOption(TIPS_OPTION_NAME); + } + public set(int value) { + this.SetOption(TIPS_OPTION_NAME, value); + } + } + + #endif + // =====[ END TIPS ]===== + + + + // =====[ QUIET ]===== + #if defined _gokz_quiet_included_ + + property int ShowPlayers { + public get() { + return this.GetOption(gC_QTOptionNames[QTOption_ShowPlayers]); + } + public set(int value) { + this.SetOption(gC_QTOptionNames[QTOption_ShowPlayers], value); + } + } + + #endif + // =====[ END QUIET ]===== + + + + // =====[ SLAY ON END ]===== + #if defined _gokz_slayonend_included_ + + property int SlayOnEnd { + public get() { + return this.GetOption(SLAYONEND_OPTION_NAME); + } + public set(int value) { + this.SetOption(SLAYONEND_OPTION_NAME, value); + } + } + + #endif + // =====[ END SLAY ON END ]===== +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/localdb.inc b/source/sourcemod/scripting/include/gokz/localdb.inc new file mode 100644 index 0000000..472a120 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/localdb.inc @@ -0,0 +1,353 @@ +/* + gokz-localdb Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_localdb_included_ +#endinput +#endif +#define _gokz_localdb_included_ + + + +// =====[ ENUMS ]===== + +enum DatabaseType +{ + DatabaseType_None = -1, + DatabaseType_MySQL, + DatabaseType_SQLite +}; + +enum +{ + JumpstatDB_Lookup_JumpID = 0, + JumpstatDB_Lookup_Distance, + JumpstatDB_Lookup_Block +}; + +enum +{ + JumpstatDB_FindPlayer_SteamID32 = 0, + JumpstatDB_FindPlayer_Alias +}; + +enum +{ + JumpstatDB_Top20_JumpID = 0, + JumpstatDB_Top20_SteamID, + JumpstatDB_Top20_Alias, + JumpstatDB_Top20_Block, + JumpstatDB_Top20_Distance, + JumpstatDB_Top20_Strafes, + JumpstatDB_Top20_Sync, + JumpstatDB_Top20_Pre, + JumpstatDB_Top20_Max, + JumpstatDB_Top20_Air +}; + +enum +{ + JumpstatDB_PBMenu_JumpID = 0, + JumpstatDB_PBMenu_JumpType, + JumpstatDB_PBMenu_Distance, + JumpstatDB_PBMenu_Strafes, + JumpstatDB_PBMenu_Sync, + JumpstatDB_PBMenu_Pre, + JumpstatDB_PBMenu_Max, + JumpstatDB_PBMenu_Air +}; + +enum +{ + JumpstatDB_BlockPBMenu_JumpID = 0, + JumpstatDB_BlockPBMenu_JumpType, + JumpstatDB_BlockPBMenu_Block, + JumpstatDB_BlockPBMenu_Distance, + JumpstatDB_BlockPBMenu_Strafes, + JumpstatDB_BlockPBMenu_Sync, + JumpstatDB_BlockPBMenu_Pre, + JumpstatDB_BlockPBMenu_Max, + JumpstatDB_BlockPBMenu_Air +}; + +enum +{ + JumpstatDB_Cache_Distance = 0, + JumpstatDB_Cache_Block, + JumpstatDB_Cache_BlockDistance, + JUMPSTATDB_CACHE_COUNT +}; + +enum +{ + TimerSetupDB_GetVBPos_SteamID = 0, + TimerSetupDB_GetVBPos_MapID, + TimerSetupDB_GetVBPos_Course, + TimerSetupDB_GetVBPos_IsStart, + TimerSetupDB_GetVBPos_PositionX, + TimerSetupDB_GetVBPos_PositionY, + TimerSetupDB_GetVBPos_PositionZ +}; + +enum +{ + TimerSetupDB_GetStartPos_SteamID = 0, + TimerSetupDB_GetStartPos_MapID, + TimerSetupDB_GetStartPos_PositionX, + TimerSetupDB_GetStartPos_PositionY, + TimerSetupDB_GetStartPos_PositionZ, + TimerSetupDB_GetStartPos_Angle0, + TimerSetupDB_GetStartPos_Angle1 +}; + +enum DBOption: +{ + DBOption_AutoLoadTimerSetup = 0, + DBOPTION_COUNT +}; + +enum +{ + DBOption_Disabled = 0, + DBOption_Enabled, + DBOPTIONBOOL_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define GOKZ_DB_JS_DISTANCE_PRECISION 10000 +#define GOKZ_DB_JS_SYNC_PRECISION 100 +#define GOKZ_DB_JS_PRE_PRECISION 100 +#define GOKZ_DB_JS_MAX_PRECISION 100 +#define GOKZ_DB_JS_AIRTIME_PRECISION 10000 +#define GOKZ_DB_JS_MAX_JUMPS_PER_PLAYER 100 + +stock char gC_DBOptionNames[DBOPTION_COUNT][] = +{ + "GOKZ DB - Auto Load Setup" +}; + +stock char gC_DBOptionDescriptions[DBOPTION_COUNT][] = +{ + "Automatically load timer setup on map start - 0 = Disabled, 1 = Enabled" +} + +stock int gI_DBOptionDefaultValues[DBOPTION_COUNT] = +{ + DBOption_Disabled +}; + +stock int gI_DBOptionCounts[DBOPTION_COUNT] = +{ + DBOPTIONBOOL_COUNT +}; + +stock char gC_DBOptionPhrases[DBOPTION_COUNT][] = +{ + "Options Menu - Auto Load Timer Setup" +}; + + + +// =====[ TYPES ]===== + +typeset GetVBPositionCallback +{ + function Action(int client, const float position[3], int course, bool isStart); +}; + +typeset GetStartPositionCallback +{ + function Action(int client, const float position[3], const float angles[3]); +}; + + + +// =====[ FORWARDS ]===== + +/** + * Called when gokz-localdb has connected to the database. + * Use GOKZ_DB_GetDatabase to get a clone of the database handle. + * + * @param DBType Database type. + */ +forward void GOKZ_DB_OnDatabaseConnect(DatabaseType DBType); + +/** + * Called when a player is ready for database interaction. + * At this point, the player is present and updated in the "Players" table. + * + * @param client Client index. + * @param steamID SteamID32 of the player (from GetSteamAccountID()). + * @param cheater Whether player is marked as a cheater in the database. + */ +forward void GOKZ_DB_OnClientSetup(int client, int steamID, bool cheater); + +/** + * Called when the current map is ready for database interaction. + * At this point, the map is present and updated in the "Maps" table. + * + * @param mapID MapID from the "Maps" table. + */ +forward void GOKZ_DB_OnMapSetup(int mapID); + +/** + * Called when a time has been inserted into the database. + * + * @param client Client index. + * @param steamID SteamID32 of the player (from GetSteamAccountID()). + * @param mapID MapID from the "Maps" table. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode Player's movement mode. + * @param style Player's movement style. + * @param runTimeMS Player's end time in milliseconds. + * @param teleportsUsed Number of teleports used by player. + */ +forward void GOKZ_DB_OnTimeInserted( + int client, + int steamID, + int mapID, + int course, + int mode, + int style, + int runTimeMS, + int teleportsUsed); + +/** + * Called when jumpstat PB has been achieved. + * + * @param client Client index. + * @param jumptype Type of the jump. + * @param mode Mode the jump was performed in. + * @param distance Distance jumped. + * @param block The size of the block jumped across. + * @param strafes The amount of strafes used. + * @param sync Keyboard/mouse synchronisation of the jump. + * @param pre Speed at takeoff. + * @param max Maximum speed during the jump. + * @param airtime Amount of time spend airborne. + */ +forward void GOKZ_DB_OnJumpstatPB( + int client, + int jumptype, + int mode, + float distance, + int block, + int strafes, + float sync, + float pre, + float max, + int airtime); + + +// =====[ NATIVES ]===== + +/** + * Gets a clone of the GOKZ local database handle. + * + * @param database Database handle, or null if connection hasn't been made. + */ +native Database GOKZ_DB_GetDatabase(); + +/** + * Gets the GOKZ local database type. + * + * @return Database type. + */ +native DatabaseType GOKZ_DB_GetDatabaseType(); + +/** + * Gets whether client has been set up for GOKZ Local DB. + * + * @param client Client index. + * @return Whether GOKZ Local DB has set up the client. + */ +native bool GOKZ_DB_IsClientSetUp(int client); + +/** + * Gets whether GOKZ Local DB is set up for the current map. + * + * @return Whether GOKZ Local DB has set up the current map. + */ +native bool GOKZ_DB_IsMapSetUp(); + +/** + * Gets the current map's MapID as in the "Maps" table. + * + * @return MapID from the "Maps" table. + */ +native int GOKZ_DB_GetCurrentMapID(); + +/** + * Gets whether player is marked as a cheater in the database. + * + * @param client Client index. + * @return Whether player is marked as a cheater in the database. + */ +native bool GOKZ_DB_IsCheater(int client); + +/** + * Sets wheter player is marked as a cheater in the database. + * + * @param client Client index. + * @param cheater Whether to mark the player as a cheater. + */ +native void GOKZ_DB_SetCheater(int client, bool cheater); + + + +// =====[ STOCKS ]===== + +/** + * Converts a time float (seconds) to an integer (milliseconds). + * + * @param time Time in seconds. + * @return Time in milliseconds. + */ +stock int GOKZ_DB_TimeFloatToInt(float time) +{ + return RoundFloat(time * 1000.0); +} + +/** + * Converts a time integer (milliseconds) to a float (seconds). + * + * @param time Time in milliseconds. + * @return Time in seconds. + */ +stock float GOKZ_DB_TimeIntToFloat(int time) +{ + return time / 1000.0; +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_localdb = +{ + name = "gokz-localdb", + file = "gokz-localdb.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_localdb_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_DB_GetDatabase"); + MarkNativeAsOptional("GOKZ_DB_GetDatabaseType"); + MarkNativeAsOptional("GOKZ_DB_IsClientSetUp"); + MarkNativeAsOptional("GOKZ_DB_IsMapSetUp"); + MarkNativeAsOptional("GOKZ_DB_GetCurrentMapID"); + MarkNativeAsOptional("GOKZ_DB_IsCheater"); + MarkNativeAsOptional("GOKZ_DB_SetCheater"); +} +#endif diff --git a/source/sourcemod/scripting/include/gokz/localranks.inc b/source/sourcemod/scripting/include/gokz/localranks.inc new file mode 100644 index 0000000..914c6cb --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/localranks.inc @@ -0,0 +1,176 @@ +/* + gokz-localranks Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_localranks_included_ +#endinput +#endif +#define _gokz_localranks_included_ + + + +// =====[ ENUMS ]===== + +enum +{ + RecordType_Nub = 0, + RecordType_Pro, + RecordType_NubAndPro, + RECORDTYPE_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define LR_CFG_MAP_POOL "cfg/sourcemod/gokz/gokz-localranks-mappool.cfg" +#define LR_CFG_SOUNDS "cfg/sourcemod/gokz/gokz-localranks-sounds.cfg" +#define LR_COMMAND_COOLDOWN 2.5 +#define LR_MAP_TOP_CUTOFF 20 +#define LR_PLAYER_TOP_CUTOFF 20 + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player's time has been processed by GOKZ Local Ranks. + * + * @param client Client index. + * @param steamID SteamID32 of the player (from GetSteamAccountID()). + * @param mapID MapID from the "Maps" database table. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode Player's movement mode. + * @param style Player's movement style. + * @param runTime Player's end time. + * @param teleportsUsed Number of teleportsUsed used by player. + * @param firstTime Whether this is player's first time on this course. + * @param pbDiff Difference between new time and PB in seconds (-'ve means beat PB). + * @param rank New rank of the player's PB time. + * @param maxRank New total number of players with times. + * @param firstTimePro Whether this is player's first PRO time on this course. + * @param pbDiffPro Difference between new time and PRO PB in seconds (-'ve means beat PB). + * @param rankPro New rank of the player's PB PRO time. + * @param maxRankPro New total number of players with PRO times. + */ +forward void GOKZ_LR_OnTimeProcessed( + int client, + int steamID, + int mapID, + int course, + int mode, + int style, + float runTime, + int teleportsUsed, + bool firstTime, + float pbDiff, + int rank, + int maxRank, + bool firstTimePro, + float pbDiffPro, + int rankPro, + int maxRankPro); + +/** + * Called when a player sets a new local record. + * + * @param client Client index. + * @param steamID SteamID32 of the player (from GetSteamAccountID()). + * @param mapID MapID from the "Maps" table. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode Player's movement mode. + * @param style Player's movement style. + * @param recordType Type of record. + */ +forward void GOKZ_LR_OnNewRecord( + int client, + int steamID, + int mapID, + int course, + int mode, + int style, + int recordType, + float pbDiff, + int teleportsUsed); + +/** + * Called when a player misses the server record time. + * Is called regardless of player's current run type. + * + * @param client Client index. + * @param recordTime Record time missed. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode Player's movement mode. + * @param style Player's movement style. + * @param recordType Type of record. + */ +forward void GOKZ_LR_OnRecordMissed(int client, float recordTime, int course, int mode, int style, int recordType); + +/** + * Called when a player misses their personal best time. + * Is called regardless of player's current run type. + * + * @param client Client index. + * @param pbTime Personal best time missed. + * @param course Course number e.g. 0=main, 1='bonus1' etc. + * @param mode Player's movement mode. + * @param style Player's movement style. + * @param recordType Type of record. + */ +forward void GOKZ_LR_OnPBMissed(int client, float pbTime, int course, int mode, int style, int recordType); + + + +// =====[ NATIVES ]===== + +/** + * Gets whether player has missed the server record time. + * + * @param client Client index. + * @param timeType Which record time i.e. NUB or PRO. + * @return Whether player has missed the server record time. + */ +native bool GOKZ_LR_GetRecordMissed(int client, int timeType); + +/** + * Gets whether player has missed their personal best time. + * + * @param client Client index. + * @param timeType Which PB time i.e. NUB or PRO. + * @return Whether player has missed their PB time. + */ +native bool GOKZ_LR_GetPBMissed(int client, int timeType); + +/** + * Reopens the map top menu with the already selected parameters. + * Don't use if the client hasn't opened the map top menu before. + * + * @param client Client index. + */ +native void GOKZ_LR_ReopenMapTopMenu(int client); + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_localranks = +{ + name = "gokz-localranks", + file = "gokz-localranks.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_localranks_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_LR_GetRecordMissed"); + MarkNativeAsOptional("GOKZ_LR_GetPBMissed"); + MarkNativeAsOptional("GOKZ_LR_ReopenMapTopMenu"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/momsurffix.inc b/source/sourcemod/scripting/include/gokz/momsurffix.inc new file mode 100644 index 0000000..65f603e --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/momsurffix.inc @@ -0,0 +1,23 @@ +/* + gokz-momsurffix Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_momsurffix_included_ +#endinput +#endif +#define _gokz_momsurffix_included_ + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_momsurffix = +{ + name = "gokz-momsurffix", + file = "gokz-momsurffix.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/paint.inc b/source/sourcemod/scripting/include/gokz/paint.inc new file mode 100644 index 0000000..19f4fb5 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/paint.inc @@ -0,0 +1,114 @@ +/* + gokz-paint Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_paint_included_ +#endinput +#endif +#define _gokz_paint_included_ + + + +// =====[ ENUMS ]===== + +enum PaintOption: +{ + PAINTOPTION_INVALID = -1, + PaintOption_Color, + PaintOption_Size, + PAINTOPTION_COUNT +}; + +enum +{ + PaintColor_Red = 0, + PaintColor_White, + PaintColor_Black, + PaintColor_Blue, + PaintColor_Brown, + PaintColor_Green, + PaintColor_Yellow, + PaintColor_Purple, + PAINTCOLOR_COUNT +}; + +enum +{ + PaintSize_Small = 0, + PaintSize_Medium, + PaintSize_Big, + PAINTSIZE_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define PAINT_OPTION_CATEGORY "Paint" +#define MIN_PAINT_SPACING 1.0 + +stock char gC_PaintOptionNames[PAINTOPTION_COUNT][] = +{ + "GOKZ Paint - Color", + "GOKZ Paint - Size" +}; + +stock char gC_PaintOptionDescriptions[PAINTOPTION_COUNT][] = +{ + "Paint Color", + "Paint Size - 0 = Small, 1 = Medium, 2 = Big" +}; + +stock char gC_PaintOptionPhrases[PAINTOPTION_COUNT][] = +{ + "Options Menu - Paint Color", + "Options Menu - Paint Size" +}; + +stock int gI_PaintOptionCounts[PAINTOPTION_COUNT] = +{ + PAINTCOLOR_COUNT, + PAINTSIZE_COUNT +}; + +stock int gI_PaintOptionDefaults[PAINTOPTION_COUNT] = +{ + PaintColor_Red, + PaintSize_Medium +}; + +stock char gC_PaintColorPhrases[PAINTCOLOR_COUNT][] = +{ + "Options Menu - Red", + "Options Menu - White", + "Options Menu - Black", + "Options Menu - Blue", + "Options Menu - Brown", + "Options Menu - Green", + "Options Menu - Yellow", + "Options Menu - Purple" +}; + +stock char gC_PaintSizePhrases[PAINTSIZE_COUNT][] = +{ + "Options Menu - Small", + "Options Menu - Medium", + "Options Menu - Big" +}; + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_paint = +{ + name = "gokz-paint", + file = "gokz-paint.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; diff --git a/source/sourcemod/scripting/include/gokz/pistol.inc b/source/sourcemod/scripting/include/gokz/pistol.inc new file mode 100644 index 0000000..1edd5f9 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/pistol.inc @@ -0,0 +1,93 @@ +/* + gokz-pistol Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_pistol_included_ +#endinput +#endif +#define _gokz_pistol_included_ + + + +// =====[ ENUMS ]===== + +enum +{ + Pistol_Disabled = 0, + Pistol_USPS, + Pistol_Glock18, + Pistol_DualBerettas, + Pistol_P250, + Pistol_FiveSeveN, + Pistol_Tec9, + Pistol_CZ75Auto, + Pistol_DesertEagle, + Pistol_R8Revolver, + PISTOL_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define PISTOL_OPTION_NAME "GOKZ - Pistol" +#define PISTOL_OPTION_DESCRIPTION "Pistol - 0 = Disabled, 1 = USP-S / P2000, 2 = Glock-18, 3 = Dual Berettas, 4 = P250, 5 = Five-SeveN, 6 = Tec-9, 7 = CZ75-Auto, 8 = Desert Eagle, 9 = R8 Revolver" + +stock char gC_PistolNames[PISTOL_COUNT][] = +{ + "", // Disabled + "USP-S / P2000", + "Glock-18", + "Dual Berettas", + "P250", + "Five-SeveN", + "Tec-9", + "CZ75-Auto", + "Desert Eagle", + "R8 Revolver" +}; + +stock char gC_PistolClassNames[PISTOL_COUNT][] = +{ + "", // Disabled + "weapon_hkp2000", + "weapon_glock", + "weapon_elite", + "weapon_p250", + "weapon_fiveseven", + "weapon_tec9", + "weapon_cz75a", + "weapon_deagle", + "weapon_revolver" +}; + +stock int gI_PistolTeams[PISTOL_COUNT] = +{ + CS_TEAM_NONE, // Disabled + CS_TEAM_CT, + CS_TEAM_T, + CS_TEAM_NONE, + CS_TEAM_NONE, + CS_TEAM_CT, + CS_TEAM_T, + CS_TEAM_NONE, + CS_TEAM_NONE, + CS_TEAM_NONE +}; + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_pistol = +{ + name = "gokz-pistol", + file = "gokz-pistol.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/profile.inc b/source/sourcemod/scripting/include/gokz/profile.inc new file mode 100644 index 0000000..70d314a --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/profile.inc @@ -0,0 +1,291 @@ +/* + gokz-profile Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_profile_included_ +#endinput +#endif +#define _gokz_profile_included_ + + +// =====[ RANKS ]===== + +#define RANK_COUNT 23 + +stock int gI_rankThreshold[MODE_COUNT][RANK_COUNT] = { + { + 0, + 1, + 500, + 1000, + + 2000, + 5000, + 10000, + + 20000, + 30000, + 40000, + + 60000, + 70000, + 80000, + + 100000, + 120000, + 140000, + + 160000, + 180000, + 200000, + + 250000, + 300000, + 400000, + 600000 + }, + { + 0, + 1, + 500, + 1000, + + 2000, + 5000, + 10000, + + 20000, + 30000, + 40000, + + 60000, + 70000, + 80000, + + 100000, + 120000, + 150000, + + 200000, + 230000, + 250000, + + 300000, + 400000, + 500000, + 800000 + }, + { + 0, + 1, + 500, + 1000, + + 2000, + 5000, + 10000, + + 20000, + 30000, + 40000, + + 60000, + 70000, + 80000, + + 100000, + 120000, + 150000, + + 200000, + 230000, + 250000, + + 400000, + 600000, + 800000, + 1000000 + }, +}; + +stock char gC_rankName[RANK_COUNT][] = { + "New", + "Beginner-", + "Beginner", + "Beginner+", + "Amateur-", + "Amateur", + "Amateur+", + "Casual-", + "Casual", + "Casual+", + "Regular-", + "Regular", + "Regular+", + "Skilled-", + "Skilled", + "Skilled+", + "Expert-", + "Expert", + "Expert+", + "Semipro", + "Pro", + "Master", + "Legend" +}; + +stock char gC_rankColor[RANK_COUNT][] = { + "{grey}", + "{default}", + "{default}", + "{default}", + "{blue}", + "{blue}", + "{blue}", + "{lightgreen}", + "{lightgreen}", + "{lightgreen}", + "{green}", + "{green}", + "{green}", + "{purple}", + "{purple}", + "{purple}", + "{orchid}", + "{orchid}", + "{orchid}", + "{lightred}", + "{lightred}", + "{red}", + "{gold}" +}; + + +// =====[ ENUMS ]===== + +enum ProfileOption: +{ + PROFILEOPTION_INVALID = -1, + ProfileOption_ShowRankChat, + ProfileOption_ShowRankClanTag, + ProfileOption_TagType, + PROFILEOPTION_COUNT +}; + +enum +{ + ProfileOptionBool_Disabled = 0, + ProfileOptionBool_Enabled, + PROFILEOPTIONBOOL_COUNT +}; + +enum +{ + ProfileTagType_Rank = 0, + ProfileTagType_Admin, + ProfileTagType_VIP, + PROFILETAGTYPE_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +stock char gC_ProfileOptionNames[PROFILEOPTION_COUNT][] = +{ + "GOKZ Profile - Show Rank Chat", + "GOKZ Profile - Show Rank Clan", + "GOKZ Profile - Tag Type" +}; + +stock char gC_ProfileOptionDescriptions[PROFILEOPTION_COUNT][] = +{ + "Show Rank Tag in Chat - 0 = Disabled, 1 = Enabled", + "Show Rank in Clan - 0 = Disabled, 1 = Enabled", + "Type of Tag to Show - 0 = Rank, 1 = Admin, 2 = VIP" +}; + +stock char gC_ProfileOptionPhrases[PROFILEOPTION_COUNT][] = +{ + "Options Menu - Show Rank Chat", + "Options Menu - Show Rank Clan", + "Options Menu - Tag Type", +}; + +stock char gC_ProfileBoolPhrases[PROFILEOPTIONBOOL_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Enabled" +}; + +stock char gC_ProfileTagTypePhrases[PROFILETAGTYPE_COUNT][] = +{ + "Options Menu - Tag Rank", + "Options Menu - Tag Admin", + "Options Menu - Tag VIP" +}; + +stock int gI_ProfileOptionCounts[PROFILEOPTION_COUNT] = +{ + PROFILEOPTIONBOOL_COUNT, + PROFILEOPTIONBOOL_COUNT, + PROFILETAGTYPE_COUNT +}; + +stock int gI_ProfileOptionDefaults[PROFILEOPTION_COUNT] = +{ + ProfileOptionBool_Enabled, + ProfileOptionBool_Enabled, + ProfileTagType_Rank +}; + +#define PROFILE_OPTION_CATEGORY "Profile" +#define TAG_COLOR_ADMIN "{red}" +#define TAG_COLOR_VIP "{purple}" + + +// =====[ FORWARDS ]===== + + +/** + * Called when the rank of a player is updated. + * + * @param client Client index. + * @param mode Game mode. + * @param rank The new rank. + */ +forward void GOKZ_PF_OnRankUpdated(int client, int mode, int rank); + +// =====[ NATIVES ]===== + +/** + * Gets whether a mode is loaded. + * + * @param client Client. + * @param tag Mode. + * @returns Integer representing the player rank. + */ +native int GOKZ_PF_GetRank(int client, int mode); + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_profile = +{ + name = "gokz-profile", + file = "gokz-profile.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_profile_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_PF_GetRank"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/quiet.inc b/source/sourcemod/scripting/include/gokz/quiet.inc new file mode 100644 index 0000000..a328b7e --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/quiet.inc @@ -0,0 +1,205 @@ +/* + gokz-quiet Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_quiet_included_ +#endinput +#endif +#define _gokz_quiet_included_ + + + +// =====[ ENUMS ]===== + +enum QTOption: +{ + QTOPTION_INVALID = -1, + QTOption_ShowPlayers, + QTOption_Soundscapes, + QTOption_FallDamageSound, + QTOption_AmbientSounds, + QTOption_CheckpointVolume, + QTOption_TeleportVolume, + QTOption_TimerVolume, + QTOption_ErrorVolume, + QTOption_ServerRecordVolume, + QTOption_WorldRecordVolume, + QTOption_JumpstatsVolume, + QTOPTION_COUNT +}; + +enum +{ + ShowPlayers_Disabled = 0, + ShowPlayers_Enabled, + SHOWPLAYERS_COUNT +}; + +enum +{ + Soundscapes_Disabled = 0, + Soundscapes_Enabled, + SOUNDSCAPES_COUNT +}; + +// =====[ CONSTANTS ]===== + +#define QUIET_OPTION_CATEGORY "Quiet" +#define DEFAULT_VOLUME 10 +#define VOLUME_COUNT 21 // Maximum of 200% + +#define EFFECT_IMPACT 8 +#define EFFECT_KNIFESLASH 2 +#define BLANK_SOUNDSCAPEINDEX 482 // Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. + +stock char gC_QTOptionNames[QTOPTION_COUNT][] = +{ + "GOKZ QT - Show Players", + "GOKZ QT - Soundscapes", + "GOKZ QT - Fall Damage Sound", + "GOKZ QT - Ambient Sounds", + "GOKZ QT - Checkpoint Volume", + "GOKZ QT - Teleport Volume", + "GOKZ QT - Timer Volume", + "GOKZ QT - Error Volume", + "GOKZ QT - Server Record Volume", + "GOKZ QT - World Record Volume", + "GOKZ QT - Jumpstats Volume" +}; + +stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = +{ + "Visibility of Other Players - 0 = Disabled, 1 = Enabled", + "Play Soundscapes - 0 = Disabled, 1 = Enabled", + "Play Fall Damage Sound - 0 to 20 = 0% to 200%", + "Play Ambient Sounds - 0 to 20 = 0% to 200%", + "Checkpoint Volume - 0 to 20 = 0% to 200%", + "Teleport Volume - 0 to 20 = 0% to 200%", + "Timer Volume - 0 to 20 = 0% to 200%", + "Error Volume - 0 to 20 = 0% to 200%", + "Server Record Volume - 0 to 20 = 0% to 200%", + "World Record Volume - 0 to 20 = 0% to 200%", + "Jumpstats Volume - 0 to 20 = 0% to 200%" +}; + +stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = +{ + ShowPlayers_Enabled, + Soundscapes_Enabled, + DEFAULT_VOLUME, // Fall damage volume + DEFAULT_VOLUME, // Ambient volume + DEFAULT_VOLUME, // Checkpoint volume + DEFAULT_VOLUME, // Teleport volume + DEFAULT_VOLUME, // Timer volume + DEFAULT_VOLUME, // Error volume + DEFAULT_VOLUME, // Server Record Volume + DEFAULT_VOLUME, // World Record Volume + DEFAULT_VOLUME // Jumpstats Volume +}; + +stock int gI_QTOptionCounts[QTOPTION_COUNT] = +{ + SHOWPLAYERS_COUNT, + SOUNDSCAPES_COUNT, + VOLUME_COUNT, // Fall damage volume + VOLUME_COUNT, // Ambient volume + VOLUME_COUNT, // Checkpoint volume + VOLUME_COUNT, // Teleport volume + VOLUME_COUNT, // Timer volume + VOLUME_COUNT, // Error volume + VOLUME_COUNT, // Server Record volume + VOLUME_COUNT, // World Record volume + VOLUME_COUNT // Jumpstats volume +}; + +stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = +{ + "Options Menu - Show Players", + "Options Menu - Soundscapes", + "Options Menu - Fall Damage Sounds", + "Options Menu - Ambient Sounds", + "Options Menu - Checkpoint Volume", + "Options Menu - Teleport Volume", + "Options Menu - Timer Volume", + "Options Menu - Error Volume", + "Options Menu - Server Record Volume", + "Options Menu - World Record Volume", + "Options Menu - Jumpstats Volume" +}; + +// =====[ STOCKS ]===== + +/** + * Returns whether an option is a gokz-quiet option. + * + * @param option Option name. + * @param optionEnum Variable to store enumerated gokz-quiet option (if it is one). + * @return Whether option is a gokz-quiet option. + */ +stock bool GOKZ_QT_IsQTOption(const char[] option, QTOption &optionEnum = QTOPTION_INVALID) +{ + for (QTOption i; i < QTOPTION_COUNT; i++) + { + if (StrEqual(option, gC_QTOptionNames[i])) + { + optionEnum = i; + return true; + } + } + return false; +} + +/** + * Gets the current value of a player's gokz-quiet option. + * + * @param client Client index. + * @param option gokz-quiet option. + * @return Current value of option. + */ +stock any GOKZ_QT_GetOption(int client, QTOption option) +{ + return GOKZ_GetOption(client, gC_QTOptionNames[option]); +} + +/** + * Sets a player's gokz-quiet option's value. + * + * @param client Client index. + * @param option gokz-quiet option. + * @param value New option value. + * @return Whether option was successfully set. + */ +stock bool GOKZ_QT_SetOption(int client, QTOption option, any value) +{ + return GOKZ_SetOption(client, gC_QTOptionNames[option], value); +} + +/** + * Increment an integer-type gokz-quiet option's value. + * Loops back to '0' if max value is exceeded. + * + * @param client Client index. + * @param option gokz-quiet option. + * @return Whether option was successfully set. + */ +stock bool GOKZ_QT_CycleOption(int client, QTOption option) +{ + return GOKZ_CycleOption(client, gC_QTOptionNames[option]); +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_quiet = +{ + name = "gokz-quiet", + file = "gokz-quiet.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/racing.inc b/source/sourcemod/scripting/include/gokz/racing.inc new file mode 100644 index 0000000..d6819ea --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/racing.inc @@ -0,0 +1,189 @@ +/* + gokz-racing Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_racing_included_ +#endinput +#endif +#define _gokz_racing_included_ + + + +// =====[ ENUMS ]===== + +enum RaceInfo: +{ + RaceInfo_ID, + RaceInfo_Status, + RaceInfo_HostUserID, + RaceInfo_FinishedRacerCount, + RaceInfo_Type, + RaceInfo_Course, + RaceInfo_Mode, + RaceInfo_CheckpointRule, + RaceInfo_CooldownRule, + RACEINFO_COUNT +}; + +enum +{ + RaceType_Normal, + RaceType_Duel, + RACETYPE_COUNT +}; + +enum +{ + RaceStatus_Pending, + RaceStatus_Countdown, + RaceStatus_Started, + RaceStatus_Aborting, + RACESTATUS_COUNT +}; + +enum +{ + RacerStatus_Available, + RacerStatus_Pending, + RacerStatus_Accepted, + RacerStatus_Racing, + RacerStatus_Finished, + RacerStatus_Surrendered, + RACERSTATUS_COUNT +}; + +enum +{ + CheckpointRule_None, + CheckpointRule_Limit, + CheckpointRule_Cooldown, + CheckpointRule_Unlimited, + CHECKPOINTRULE_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define RC_COUNTDOWN_TIME 10.0 +#define RC_REQUEST_TIMEOUT_TIME 15.0 + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player has finished their race. + * + * @param client Client index. + * @param raceID ID of the race. + * @param place Final placement in the race. + */ +forward void GOKZ_RC_OnFinish(int client, int raceID, int place); + +/** + * Called when a player has surrendered their race. + * + * @param client Client index. + * @param raceID ID of the race. + */ +forward void GOKZ_RC_OnSurrender(int client, int raceID); + +/** + * Called when a player receives a race request. + * + * @param client Client index. + * @param raceID ID of the race. + */ +forward void GOKZ_RC_OnRequestReceived(int client, int raceID) + +/** + * Called when a player accepts a race request. + * + * @param client Client index. + * @param raceID ID of the race. + */ +forward void GOKZ_RC_OnRequestAccepted(int client, int raceID) + +/** + * Called when a player declines a race request. + * + * @param client Client index. + * @param raceID ID of the race. + * @param timeout Whether the client was too late to respond. + */ +forward void GOKZ_RC_OnRequestDeclined(int client, int raceID, bool timeout) + +/** + * Called when a race has been registered. + * The initial status of a race is RaceStatus_Pending. + * + * @param raceID ID of the race. + */ +forward void GOKZ_RC_OnRaceRegistered(int raceID); + +/** + * Called when a race's info property has changed. + * + * @param raceID ID of the race. + * @param prop Info property that was changed. + * @param oldValue Previous value. + * @param newValue New value. + */ +forward void GOKZ_RC_OnRaceInfoChanged(int raceID, RaceInfo prop, int oldValue, int newValue); + + + +// =====[ NATIVES ]===== + +/** + * Gets the value of a race info property. + * + * @param raceID Race index. + * @param prop Info property to get. + * @return Value of the info property. + */ +native int GOKZ_RC_GetRaceInfo(int raceID, RaceInfo prop); + +/** + * Gets a player's racer status. + * Refer to the RacerStatus enumeration. + * + * @param client Client index. + * @return Racer status of the client. + */ +native int GOKZ_RC_GetStatus(int client); + +/** + * Gets the ID of the race a player is in. + * + * @param client Client index. + * @return ID of the race the player is in, or -1 if not in a race. + */ +native int GOKZ_RC_GetRaceID(int client); + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_racing = +{ + name = "gokz-racing", + file = "gokz-racing.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_racing_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_RC_GetRaceInfo"); + MarkNativeAsOptional("GOKZ_RC_GetStatus"); + MarkNativeAsOptional("GOKZ_RC_GetRaceID"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/replays.inc b/source/sourcemod/scripting/include/gokz/replays.inc new file mode 100644 index 0000000..6aabdbd --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/replays.inc @@ -0,0 +1,275 @@ +/* + gokz-replays Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_replays_included_ +#endinput +#endif +#define _gokz_replays_included_ + +// Bit of a hack, but need it for other plugins that depend on replays to compile +#if defined REQUIRE_PLUGIN +#undef REQUIRE_PLUGIN +#include +#define REQUIRE_PLUGIN +#else +#include +#endif + + + +// =====[ ENUMS ]===== +enum +{ + ReplayType_Run = 0, + ReplayType_Cheater, + ReplayType_Jump, + REPLAYTYPE_COUNT +}; + +enum ReplaySaveState +{ + ReplaySave_Local = 0, + ReplaySave_Temp, + ReplaySave_Disabled +}; + +// NOTE: Replays use delta compression for storage. +// This enum is the indices of the ReplayTickData enum struct. +// NOTE: This has to match the ReplayTickData enum struct!!! +enum +{ + RPDELTA_DELTAFLAGS = 0, + RPDELTA_DELTAFLAGS2, + RPDELTA_VEL_X, + RPDELTA_VEL_Y, + RPDELTA_VEL_Z, + RPDELTA_MOUSE_X, + RPDELTA_MOUSE_Y, + RPDELTA_ORIGIN_X, + RPDELTA_ORIGIN_Y, + RPDELTA_ORIGIN_Z, + RPDELTA_ANGLES_X, + RPDELTA_ANGLES_Y, + RPDELTA_ANGLES_Z, + RPDELTA_VELOCITY_X, + RPDELTA_VELOCITY_Y, + RPDELTA_VELOCITY_Z, + RPDELTA_FLAGS, + RPDELTA_PACKETSPERSECOND, + RPDELTA_LAGGEDMOVEMENTVALUE, + RPDELTA_BUTTONSFORCED, + + RP_V2_TICK_DATA_BLOCKSIZE +}; + + + +// =====[ STRUCTS ] ===== + +enum struct GeneralReplayHeader +{ + int magicNumber; + int formatVersion; + int replayType; + char gokzVersion[32]; + char mapName[64]; + int mapFileSize; + int serverIP; + int timestamp; + char playerAlias[MAX_NAME_LENGTH]; + int playerSteamID; + int mode; + int style; + float playerSensitivity; + float playerMYaw; + float tickrate; + int tickCount; + int equippedWeapon; + int equippedKnife; +} + +enum struct JumpReplayHeader +{ + int jumpType; + float distance; + int blockDistance; + int strafeCount; + float sync; + float pre; + float max; + int airtime; +} + +enum struct CheaterReplayHeader +{ + ACReason ACReason; +} + +enum struct RunReplayHeader +{ + float time; + int course; + int teleportsUsed; +} + +// NOTE: Make sure to change the RPDELTA_* enum, TickDataToArray() and TickDataFromArray() when adding/removing stuff from this!!! +enum struct ReplayTickData +{ + int deltaFlags; + int deltaFlags2; + float vel[3]; + int mouse[2]; + float origin[3]; + float angles[3]; + float velocity[3]; + int flags; + float packetsPerSecond; + float laggedMovementValue; + int buttonsForced; +} + + + +// =====[ CONSTANTS ]===== + +#define RP_DIRECTORY "data/gokz-replays" // In Path_SM +#define RP_DIRECTORY_RUNS "data/gokz-replays/_runs" // In Path_SM +#define RP_DIRECTORY_RUNS_TEMP "data/gokz-replays/_tempRuns" // In Path_SM +#define RP_DIRECTORY_CHEATERS "data/gokz-replays/_cheaters" // In Path_SM +#define RP_DIRECTORY_JUMPS "data/gokz-replays/_jumps" // In Path_SM +#define RP_DIRECTORY_BLOCKJUMPS "blocks" +#define RP_FILE_EXTENSION "replay" +#define RP_MAGIC_NUMBER 0x676F6B7A +#define RP_FORMAT_VERSION 0x02 +#define RP_NAV_FILE "maps/gokz-replays.nav" +#define RP_V1_TICK_DATA_BLOCKSIZE 7 +#define RP_CACHE_BLOCKSIZE 4 +#define RP_MAX_BOTS 4 +#define RP_PLAYBACK_BREATHER_TIME 2.0 +#define RP_MIN_CHEATER_REPLAY_LENGTH 30 // 30 seconds +#define RP_MAX_CHEATER_REPLAY_LENGTH 120 // 2 minutes +#define RP_MAX_BHOP_GROUND_TICKS 5 +#define RP_SKIP_TIME 10 // 10 seconds +#define RP_MAX_DURATION 6451200 // 14 hours on 128 tick +#define RP_JUMP_STEP_SOUND_THRESHOLD 140.0 +#define RP_PLAYER_ACCELSPEED 450.0 + +#define RP_MOVETYPE_MASK (0xF) +#define RP_IN_ATTACK (1 << 4) +#define RP_IN_ATTACK2 (1 << 5) +#define RP_IN_JUMP (1 << 6) +#define RP_IN_DUCK (1 << 7) +#define RP_IN_FORWARD (1 << 8) +#define RP_IN_BACK (1 << 9) +#define RP_IN_LEFT (1 << 10) +#define RP_IN_RIGHT (1 << 11) +#define RP_IN_MOVELEFT (1 << 12) +#define RP_IN_MOVERIGHT (1 << 13) +#define RP_IN_RELOAD (1 << 14) +#define RP_IN_SPEED (1 << 15) +#define RP_IN_USE (1 << 16) +#define RP_IN_BULLRUSH (1 << 17) +#define RP_FL_ONGROUND (1 << 18) +#define RP_FL_DUCKING (1 << 19) +#define RP_FL_SWIM (1 << 20) +#define RP_UNDER_WATER (1 << 21) +#define RP_TELEPORT_TICK (1 << 22) +#define RP_TAKEOFF_TICK (1 << 23) +#define RP_HIT_PERF (1 << 24) +#define RP_SECONDARY_EQUIPPED (1 << 25) + + + +// =====[ FORWARDS ]===== + +/** + * Called when a replay of a player is written to disk. + * This includes replays of cheaters which are saved if + * the player is marked as a cheater by gokz-localdb. + * + * @param client The client ID of the player who completed the run. + * @param replayType The type of the replay (Run/Jump/Cheater). + * @param map The name of the map the run was completed on. + * @param course The specific course on the map the run was completed on. + * @param timeType The type of time (Pro/Nub). + * @param time The time the run was completed in. + * @param filePath Replay file path. + * @param tempReplay Whether the replay file should only be temporaily stored. + * @return Plugin_Handled to take over the temporary replay deletion, Plugin_Continue to allow temporary replay deletion by the replay plugin. + */ +forward Action GOKZ_RP_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath, bool tempReplay); + +/** + * Called when a currently being recorded replay is discarded from + * memory and recording has been stopped (without writing it to disk). + * + * @param client Client index. + */ +forward void GOKZ_RP_OnReplayDiscarded(int client); + +/** + * Called when a player has ended their timer, and gokz-replays has + * processed the time and has possibly written a replay to disk. + * + * @param client Client index. + * @param filePath Replay file path, or "" if no replay saved. + * @param course Course number. + * @param time Player's end time. + * @param teleportsUsed Number of teleports used by player. + */ +forward void GOKZ_RP_OnTimerEnd_Post(int client, const char[] filePath, int course, float time, int teleportsUsed); + + + +// =====[ NATIVES ]==== + +/** + * Called by the HUD to get the state of the current replay. + * + * @param client Client index. + * @param info Struct to pass the values into. + * @return If successful + */ +native int GOKZ_RP_GetPlaybackInfo(int client, any[] info); + +/** + * Called by the LocalDB to initiate a replay of a jump + * + * @param client Client index. + * @param path Path to the replay file. + * @return The client ID of the bot performing the replay. + */ +native int GOKZ_RP_LoadJumpReplay(int client, char[] path); + +/** + * Called by the HUD to show the replay control menu. + * + * @param client Client index. + */ +native bool GOKZ_RP_UpdateReplayControlMenu(int client); + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_replays = +{ + name = "gokz-replays", + file = "gokz-replays.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_replays_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_RP_GetPlaybackInfo"); + MarkNativeAsOptional("GOKZ_RP_LoadJumpReplay"); + MarkNativeAsOptional("GOKZ_RP_UpdateReplayControlMenu"); +} +#endif diff --git a/source/sourcemod/scripting/include/gokz/slayonend.inc b/source/sourcemod/scripting/include/gokz/slayonend.inc new file mode 100644 index 0000000..2ed01e5 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/slayonend.inc @@ -0,0 +1,43 @@ +/* + gokz-slayonend Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_slayonend_included_ +#endinput +#endif +#define _gokz_slayonend_included_ + + + +// =====[ ENUMS ]===== + +enum +{ + SlayOnEnd_Disabled = 0, + SlayOnEnd_Enabled, + SLAYONEND_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define SLAYONEND_OPTION_NAME "GOKZ - Slay On End" +#define SLAYONEND_OPTION_DESCRIPTION "Automatic Slaying Upon Ending Timer - 0 = Disabled, 1 = Enabled" + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_slayonend = +{ + name = "gokz-slayonend", + file = "gokz-slayonend.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/tips.inc b/source/sourcemod/scripting/include/gokz/tips.inc new file mode 100644 index 0000000..b5e2d3e --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/tips.inc @@ -0,0 +1,59 @@ +/* + gokz-tips Plugin Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz +*/ + +#if defined _gokz_tips_included_ +#endinput +#endif +#define _gokz_tips_included_ + + + +// =====[ ENUMS ]===== + +enum +{ + Tips_Disabled = 0, + Tips_Enabled, + TIPS_COUNT +}; + + + +// =====[ CONSTANTS ]===== + +#define TIPS_PLUGINS_COUNT 9 +#define TIPS_CORE "gokz-tips-core.phrases.txt" +#define TIPS_TIPS "gokz-tips-tips.phrases.txt" +#define TIPS_OPTION_NAME "GOKZ - Tips" +#define TIPS_OPTION_DESCRIPTION "Random Tips Periodically in Chat - 0 = Disabled, 1 = Enabled" + +stock char gC_PluginsWithTips[TIPS_PLUGINS_COUNT][] = +{ + "goto", + "hud", + "jumpstats", + "localranks", + "measure", + "pistol", + "quiet", + "replays", + "spec" +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_tips = +{ + name = "gokz-tips", + file = "gokz-tips.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/tpanglefix.inc b/source/sourcemod/scripting/include/gokz/tpanglefix.inc new file mode 100644 index 0000000..fc8faa2 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/tpanglefix.inc @@ -0,0 +1,40 @@ +/* + gokz-tpanglefix Plugin Include + + Website: https://github.com/KZGlobalTeam/gokz +*/ + +#if defined _gokz_tpanglefix_included_ +#endinput +#endif +#define _gokz_tpanglefix_included_ + + +// =====[ ENUMS ]===== + +enum +{ + TPAngleFix_Disabled = 0, + TPAngleFix_Enabled, + TPANGLEFIX_COUNT +}; + + +// =====[ CONSTANTS ]===== + +#define TPANGLEFIX_OPTION_NAME "GOKZ - TPAngleFix" +#define TPANGLEFIX_OPTION_DESCRIPTION "TPAngleFix - 0 = Disabled, 1 = Enabled" + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_tpanglefix = +{ + name = "gokz-tpanglefix", + file = "gokz-tpanglefix.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz/version.inc b/source/sourcemod/scripting/include/gokz/version.inc new file mode 100644 index 0000000..34cdb19 --- /dev/null +++ b/source/sourcemod/scripting/include/gokz/version.inc @@ -0,0 +1,12 @@ +/* + GOKZ Version Include + + Website: https://bitbucket.org/kztimerglobalteam/gokz + + You should not need to edit this file. + This file is overwritten in the build pipeline for versioning. +*/ + + + +#define GOKZ_VERSION "" \ No newline at end of file diff --git a/source/sourcemod/scripting/include/halflife.inc b/source/sourcemod/scripting/include/halflife.inc new file mode 100644 index 0000000..49f55e7 --- /dev/null +++ b/source/sourcemod/scripting/include/halflife.inc @@ -0,0 +1,711 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2016 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_BLOODYGOODTIME 32 /**< Modified version of ep2 engine used by Bloody Good Time (no SDK) */ +#define SOURCE_SDK_EYE 33 /**< Modified version of ep2 engine used by E.Y.E Divine Cybermancy (no SDK) */ +#define SOURCE_SDK_CSS 34 /**< Sometime-older version of Source 2009 SDK+Engine, used for Counter-Strike: Source */ +#define SOURCE_SDK_EPISODE2VALVE 35 /**< SDK+Engine released after Episode 2/Orange Box, "Source 2009" or "Source MP" */ +#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 SOURCE_SDK_ALIENSWARM 60 /**< SDK+Engine released after Alien Swarm */ +#define SOURCE_SDK_CSGO 80 /**< Engine released after CS:GO (no SDK yet) */ +#define SOURCE_SDK_DOTA 90 /**< Engine released after Dota 2 (no SDK) */ + +#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 opened */ + +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 */ +}; + +enum EngineVersion +{ + Engine_Unknown, /**< Could not determine the engine version */ + Engine_Original, /**< Original Source Engine (used by The Ship) */ + Engine_SourceSDK2006, /**< Episode 1 Source Engine (second major SDK) */ + Engine_SourceSDK2007, /**< Orange Box Source Engine (third major SDK) */ + Engine_Left4Dead, /**< Left 4 Dead */ + Engine_DarkMessiah, /**< Dark Messiah Multiplayer (based on original engine) */ + Engine_Left4Dead2 = 7, /**< Left 4 Dead 2 */ + Engine_AlienSwarm, /**< Alien Swarm (and Alien Swarm SDK) */ + Engine_BloodyGoodTime, /**< Bloody Good Time */ + Engine_EYE, /**< E.Y.E Divine Cybermancy */ + Engine_Portal2, /**< Portal 2 */ + Engine_CSGO, /**< Counter-Strike: Global Offensive */ + Engine_CSS, /**< Counter-Strike: Source */ + Engine_DOTA, /**< Dota 2 */ + Engine_HL2DM, /**< Half-Life 2 Deathmatch */ + Engine_DODS, /**< Day of Defeat: Source */ + Engine_TF2, /**< Team Fortress 2 */ + Engine_NuclearDawn, /**< Nuclear Dawn */ + Engine_SDK2013, /**< Source SDK 2013 */ + Engine_Blade, /**< Blade Symphony */ + Engine_Insurgency, /**< Insurgency (2013 Retail version)*/ + Engine_Contagion, /**< Contagion */ + Engine_BlackMesa, /**< Black Mesa Multiplayer */ + Engine_DOI /**< Day of Infamy */ +}; + +enum FindMapResult +{ + // A direct match for this name was found + FindMap_Found, + // No match for this map name could be found. + FindMap_NotFound, + // A fuzzy match for this map name was found. + // Ex: cp_dust -> cp_dustbowl, c1m1 -> c1m1_hotel + // Only supported for maps that the engine knows about. (This excludes workshop maps on Orangebox). + FindMap_FuzzyMatch, + // A non-canonical match for this map name was found. + // Ex: workshop/1234 -> workshop/cp_qualified_name.ugc1234 + // Only supported on "Orangebox" games with workshop support. + FindMap_NonCanonical, + // No currently available match for this map name could be found, but it may be possible to load + // Only supported on "Orangebox" games with workshop support. + FindMap_PossiblyAvailable +}; + +#define INVALID_ENT_REFERENCE 0xFFFFFFFF + +/** + * Logs a generic message to the HL2 logs. + * + * @param format String format. + * @param ... Format arguments. + */ +native void LogToGame(const char[] format, any ...); + +/** + * Sets the seed value for the global Half-Life 2 Random Stream. + * + * @param seed Seed value. + */ +native void SetRandomSeed(int 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 int GetRandomInt(int nmin, int nmax); + +/** + * Returns whether a map is valid or not. + * + * @param map Map name, excluding .bsp extension. + * @return True if valid, false otherwise. + */ +native bool IsMapValid(const char[] map); + +/** + * Returns whether a full or partial map name is found or can be resolved + * + * @param map Map name (usually same as map path relative to maps/ dir, + * excluding .bsp extension). + * @param foundmap Resolved map name. If the return is FindMap_FuzzyMatch + * or FindMap_NonCanonical the buffer will be the full path. + * @param maxlen Maximum length to write to map var. + * @return Result of the find operation. Not all result types are supported on all games. + */ +native FindMapResult FindMap(const char[] map, char[] foundmap, int maxlen); + +/** + * Get the display name of a workshop map. + * + * Note: You do not need to call FindMap first. This native will call FindMap internally. + * + * @param map Map name (usually same as map path relative to maps/ dir, + * excluding .bsp extension). + * @param displayName Map's display name, i.e. cp_mymapname or de_mymapname. + * If FindMap returns FindMap_PossiblyAvailable or FindMap_NotFound, + * the map cannot be resolved and this native will return false, + * but displayName will be a copy of map. + * @param maxlen Maximum length to write to displayName var. + * @return true if FindMap returns FindMap_Found, FindMap_FuzzyMatch, or + * FindMap_NonCanonical. + * false if FindMap returns FindMap_PossiblyAvailable or FindMap_NotFound. + */ +native bool GetMapDisplayName(const char[] map, char[] displayName, int maxlen); + +/** + * 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's internal tick count. + * + * @return Game tick count. + */ +native int GetGameTickCount(); + +/** + * Returns the time the Game took processing the last frame. + * + * @return Game frame time. + */ +native float GetGameFrameTime(); + +/** + * 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 int GetGameDescription(char[] buffer, int 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 int GetGameFolderName(char[] buffer, int 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 int GetCurrentMap(char[] buffer, int 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 int PrecacheModel(const char[] 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 int PrecacheSentenceFile(const char[] 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 int PrecacheDecal(const char[] 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 int PrecacheGeneric(const char[] 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 char[] 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 char[] decal); + +/** + * Returns if a given generic file is precached. + * + * @param generic Name of the generic file to check. + * @return True if precached, false otherwise. + */ +native bool IsGenericPrecached(const char[] 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 char[] 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. + * @deprecated Doesn't work correctly, always returns true. + */ +#pragma deprecated Doesn't work correctly, always returns true. +native bool IsSoundPrecached(const char[] 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. + * @error Invalid client index, or client not in game. + */ +native void CreateDialog(int 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. + * @deprecated See GetEngineVersion() + */ +#pragma deprecated See GetEngineVersion() +native int GuessSDKVersion(); + +/** + * Gets the engine version that the currently-loaded SM core was compiled against. + * + * The engine version values are not guaranteed to be in any particular order, + * and should only be compared by (in)equality. + * + * @return An EngineVersion value. + */ +native EngineVersion GetEngineVersion(); + +/** + * 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. + * @error Invalid client index, or client not in game. + */ +native void PrintToChat(int client, const char[] format, any ...); + +/** + * Prints a message to all clients in the chat area. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void PrintToChatAll(const char[] format, any ...) +{ + char buffer[254]; + + for (int 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. + * @error Invalid client index, or client not in game. + */ +native void PrintCenterText(int client, const char[] format, any ...); + +/** + * Prints a message to all clients in the center of the screen. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void PrintCenterTextAll(const char[] format, any ...) +{ + char buffer[254]; + + for (int 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. + * @error Invalid client index, or client not in game. + */ +native void PrintHintText(int client, const char[] format, any ...); + +/** + * Prints a message to all clients with a hint box. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void PrintHintTextToAll(const char[] format, any ...) +{ + char buffer[254]; + + for (int 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. + * @error Invalid client index, or client not in game. + */ +native void ShowVGUIPanel(int client, const char[] 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. + */ +native void SetHudTextParams(float x, float y, float holdTime, int r, int g, int b, int a, int 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. + */ +native void SetHudTextParamsEx(float x, float y, float holdTime, int color1[4], + int color2[4]={255,255,255,0}, int 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 Invalid client index, client not in game, or sync object not valid. + */ +native int ShowSyncHudText(int client, Handle sync, const char[] 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. + * @error Invalid client index, client not in game, or sync object not valid. + */ +native void ClearSyncHud(int 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. + * @error Invalid client index, or client not in game. + */ +native int ShowHudText(int client, int channel, const char[] 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. + * @error Invalid client index, or client not in game. + */ +stock void ShowMOTDPanel(int client, const char[] title, const char[] msg, int type=MOTDPANEL_TYPE_INDEX) +{ + char num[3]; + IntToString(type, num, sizeof(num)); + + KeyValues kv = new KeyValues("data"); + kv.SetString("title", title); + kv.SetString("type", num); + kv.SetString("msg", msg); + ShowVGUIPanel(client, "info", kv); + delete 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 Destination IP. + * @param password Password to connect to the destination IP. The client will be able to see this. + * @error Invalid client index, or client not in game. + */ +stock void DisplayAskConnectBox(int client, float time, const char[] ip, const char[] password = "") +{ + char destination[288]; + FormatEx(destination, sizeof(destination), "%s/%s", ip, password); + + KeyValues kv = new KeyValues("data"); + kv.SetFloat("time", time); + kv.SetString("title", destination); + CreateDialog(client, kv, DialogType_AskConnect); + delete kv; +} + +/** + * Converts an entity index into a serial encoded entity reference. + * + * @param entity Entity index. + * @return Entity reference or -1 on invalid entity. + * @error Entity index >= GetMaxEntities() or < 0 + */ +native int EntIndexToEntRef(int entity); + +/** + * Retrieves the entity index from a reference. + * + * @param ref Entity reference. + * @return Entity index or -1 on invalid reference. + */ +native int EntRefToEntIndex(int ref); + +/** + * Converts a reference into a backwards compatible version. + * + * @param ref Entity reference. + * @return Bcompat reference. + */ +native int MakeCompatEntRef(int ref); + +enum ClientRangeType +{ + RangeType_Visibility = 0, + RangeType_Audibility +} + +/** + * Find clients that are potentially in range of a position. + * + * @param origin Coordinates from which to test range. + * @param rangeType Range type to use for filtering clients. + * @param clients Array to which found client indexes will be written. + * @param size Maximum size of clients array. + * @return Number of client indexes written to clients array. + */ +native int GetClientsInRange(const float origin[3], ClientRangeType rangeType, int[] clients, int size); + +/** + * Retrieves the server's authentication string (SteamID). + * + * Note: If called before server is connected to Steam, auth id + * will be invalid ([I:0:1], 1, etc.) + * + * @param authType Auth id type and format to use. + * (Only AuthId_Steam3 and AuthId_SteamID64 are supported) + * @param auth Buffer to store the server's auth id. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @error Invalid AuthIdType given. + */ +native void GetServerAuthId(AuthIdType authType, char[] auth, int maxlen); + +/** + * Returns the server's Steam account ID. + * + * @return Steam account ID or 0 if not available. + */ +native int GetServerSteamAccountId(); diff --git a/source/sourcemod/scripting/include/handles.inc b/source/sourcemod/scripting/include/handles.inc new file mode 100644 index 0000000..a6f7ebe --- /dev/null +++ b/source/sourcemod/scripting/include/handles.inc @@ -0,0 +1,98 @@ +/** + * 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 + +/** + * Preset Handle values. + */ +enum Handle // Tag disables introducing "Handle" as a symbol. +{ + 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. + * @error Invalid handles will cause a run time error. + */ +native void 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); + +using __intrinsics__.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. + * @deprecated Do not use this function. + */ +#pragma deprecated Do not use this function. +native bool IsValidHandle(Handle hndl); diff --git a/source/sourcemod/scripting/include/helpers.inc b/source/sourcemod/scripting/include/helpers.inc new file mode 100644 index 0000000..47ade5b --- /dev/null +++ b/source/sourcemod/scripting/include/helpers.inc @@ -0,0 +1,287 @@ +/** + * 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 + +/** + * This function is deprecated. Use the %L format specifier instead. + * + * Formats a user's info as log text. + * + * @param client Client index. + * @param buffer Buffer for text. + * @param maxlength Maximum length of text. + * @deprecated Use the %L format specifier instead. + */ +#pragma deprecated Use the %L format specifier instead. +stock void FormatUserLogText(int client, char[] buffer, int maxlength) +{ + FormatEx(buffer, maxlength, "\"%L\"", client); +} + +/** + * 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 char[] filename) +{ + char buffer[256]; + + Handle iter = GetPluginIterator(); + 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 int SearchForClients(const char[] pattern, int[] clients, int maxClients) +{ + int total = 0; + + if (maxClients == 0) + { + return 0; + } + + if (pattern[0] == '#') + { + int input = StringToInt(pattern[1]); + if (!input) { + char name[MAX_NAME_LENGTH]; + for (int 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 + { + int client = GetClientOfUserId(input); + if (client) + { + clients[0] = client; + return 1; + } + } + } + + char name[MAX_NAME_LENGTH]; + for (int 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. + * + * Note that you should use LoadTranslations("common.phrases") in OnPluginStart(). + * "common.phrases" contains all of the translatable phrases that FindTarget() will + * reply with in the event a target is not found (error). + * + * @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 int FindTarget(int client, const char[] target, bool nobots = false, bool immunity = true) +{ + char target_name[MAX_TARGET_LENGTH]; + int target_list[1], target_count; + bool tn_is_ml; + + int 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]; + } + + 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. + * @deprecated Use ReadMapList() instead. + */ +#pragma deprecated Use ReadMapList() instead. +stock int LoadMaps(Handle array, int &fileTime = 0, Handle fileCvar = INVALID_HANDLE) +{ + char mapPath[256], mapFile[64]; + bool fileFound = false; + + if (fileCvar != INVALID_HANDLE) + { + GetConVarString(fileCvar, mapFile, 64); + BuildPath(Path_SM, mapPath, sizeof(mapPath), mapFile); + fileFound = FileExists(mapPath); + } + + if (!fileFound) + { + 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. + int newTime = GetFileTime(mapPath, FileTime_LastChange); + if (fileTime == newTime) + { + return GetArraySize(array); + } + + fileTime = newTime; + + ClearArray(array); + + File file = OpenFile(mapPath, "rt"); + if (!file) { + LogError("Could not open file: %s", mapPath); + return 0; + } + + LogMessage("Loading maps from file: %s", mapPath); + + int len; + char buffer[64]; + while (!file.EndOfFile() && file.ReadLine(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); + } + + file.Close(); + return GetArraySize(array); +} diff --git a/source/sourcemod/scripting/include/json.inc b/source/sourcemod/scripting/include/json.inc new file mode 100644 index 0000000..ebc46e4 --- /dev/null +++ b/source/sourcemod/scripting/include/json.inc @@ -0,0 +1,473 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2019 James Dickens. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_included + #endinput +#endif +#define _json_included + +#include +#include +#include +#include +#include +#include + +/** + * Encodes a JSON instance into its string representation. + * + * @param obj Object to encode. + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + * @param pretty_print Should the output be pretty printed (newlines and spaces)? [default: false] + * @param depth The current depth of the encoder. [default: 0] + */ +stock void json_encode( + JSON_Object obj, + char[] output, + int max_size, + bool pretty_print = false, + int depth = 0 +) +{ + bool is_array = obj.IsArray; + bool is_empty = true; + int builder_size; + + // used in key iterator + int str_length = 1; + int int_value; + int cell_length = 0; + + StringMapSnapshot snap = null; + int json_size = 0; + if (is_array) { + json_size = obj.CurrentIndex; + + strcopy(output, max_size, "["); + } else { + snap = obj.Snapshot(); + json_size = snap.Length; + + strcopy(output, max_size, "{"); + } + + int key_length = 0; + for (int i = 0; i < json_size; ++i) { + key_length = (is_array) ? JSON_INDEX_BUFFER_SIZE : snap.KeyBufferSize(i); + char[] key = new char[key_length]; + + if (is_array) { + obj.GetIndexString(key, key_length, i); + } else { + snap.GetKey(i, key, key_length); + } + + // skip meta-keys + if (json_is_meta_key(key)) { + continue; + } + + // skip keys that are marked as hidden + if (obj.GetKeyHidden(key)) { + continue; + } + + JSON_CELL_TYPE type = obj.GetKeyType(key); + // skip keys of unknown type + if (type == Type_Invalid) { + continue; + } + + // if we are dealing with a string, prepare the str_value variable for fetching + if (type == Type_String) { + str_length = obj.GetKeyLength(key); + } + char[] str_value = new char[str_length + 1]; + + // determine the length of the char[] needed to represent our cell data + cell_length = 0; + switch (type) { + case Type_String: { + // get the string value early, as its cell_length is determined by its contents + obj.GetString(key, str_value, str_length + 1); + cell_length = json_cell_string_size(str_length); + } + case Type_Int: { + // get the int value early, as its cell_length is determined by its contents + int_value = obj.GetInt(key); + cell_length = json_cell_int_size(int_value); + } + case Type_Float: { + cell_length = json_cell_float_size(); + } + case Type_Bool: { + cell_length = json_cell_bool_size(); + } + case Type_Null: { + cell_length = json_cell_null_size(); + } + case Type_Object: { + cell_length = max_size; + } + } + + // fit the contents into the cell + char[] cell = new char[cell_length]; + switch (type) { + case Type_String: { + json_cell_string(str_value, cell, cell_length); + } + case Type_Int: { + json_cell_int(int_value, cell, cell_length); + } + case Type_Float: { + float value = obj.GetFloat(key); + json_cell_float(value, cell, cell_length); + } + case Type_Bool: { + bool value = obj.GetBool(key); + json_cell_bool(value, cell, cell_length); + } + case Type_Null: { + json_cell_null(cell, cell_length); + } + case Type_Object: { + JSON_Object child = obj.GetObject(key); + json_encode(child, cell, cell_length, pretty_print, depth + 1); + } + } + + // make the builder fit our key:value + // use previously determined cell length and + 1 for , + builder_size = cell_length + 1; + if (! is_array) { + // get the length of the key and + 1 for : + builder_size += json_cell_string_size(strlen(key)) + 1; + + if (pretty_print) { + builder_size += strlen(JSON_PP_AFTER_COLON); + } + } + + char[] builder = new char[builder_size]; + strcopy(builder, builder_size, ""); + + // add the key if we're working with an object + if (! is_array) { + json_cell_string(key, builder, builder_size); + StrCat(builder, builder_size, ":"); + + if (pretty_print) { + StrCat(builder, builder_size, JSON_PP_AFTER_COLON); + } + } + + // add the value and a trailing comma + StrCat(builder, builder_size, cell); + StrCat(builder, builder_size, ","); + + // prepare pretty printing then send builder to output afterwards + if (pretty_print) { + StrCat(output, max_size, JSON_PP_NEWLINE); + + for (int j = 0; j < depth + 1; ++j) { + StrCat(output, max_size, JSON_PP_INDENT); + } + } + + StrCat(output, max_size, builder); + + is_empty = false; + } + + if (snap != null) { + delete snap; + } + + if (! is_empty) { + // remove the final comma + output[strlen(output) - 1] = '\0'; + + if (pretty_print) { + StrCat(output, max_size, JSON_PP_NEWLINE); + + for (int j = 0; j < depth; ++j) { + StrCat(output, max_size, JSON_PP_INDENT); + } + } + } + + // append closing bracket + StrCat(output, max_size, (is_array) ? "]" : "}"); +} + +/** + * Decodes a JSON string into a JSON instance. + * + * @param buffer Buffer to decode. + * @param result Object to store output in. Setting this allows loading over + * an existing JSON instance, 'refreshing' it as opposed to + * creating a new one. [default: null] + * @param pos Current position of the decoder as a bytes offset into the buffer. + * @param depth Current depth of the decoder as child elements in the object. + * @returns JSON instance or null if decoding failed (buffer didn't contain valid JSON). + */ +stock JSON_Object json_decode( + const char[] buffer, + JSON_Object result = null, + int &pos = 0, + int depth = 0 +) +{ + int length = strlen(buffer); + bool is_array = false; + + // skip preceding whitespace + if (! json_skip_whitespace(buffer, length, pos)) { + LogError("json_decode: buffer ended early at position %d", pos); + + return null; + } + + if (json_is_object(buffer[pos])) { + is_array = false; + } else if (json_is_array(buffer[pos])) { + is_array = true; + } else { + LogError("json_decode: character not identified as object or array at position %d", pos); + + return null; + } + + if (result == null) { + result = new JSON_Object(is_array); + } + + bool empty_checked = false; + char[] key = new char[length]; + char[] cell = new char[length]; + + // while we haven't reached the end of our structure + while (! is_array && ! json_is_object_end(buffer[pos]) + || is_array && ! json_is_array_end(buffer[pos])) { + // pos is either an opening structure or comma, so increment past it + ++pos; + + // skip any whitespace preceding the element + if (! json_skip_whitespace(buffer, length, pos)) { + LogError("json_decode: buffer ended early at position %d", pos); + + return null; + } + + // if we are at the end of an object or array + // and haven't checked for empty yet, we can stop here (empty structure) + if ((! is_array && json_is_object_end(buffer[pos]) + || is_array && json_is_array_end(buffer[pos])) + && ! empty_checked) { + break; + } + + empty_checked = true; + + // if dealing with an object, look for the key + if (! is_array) { + if (! json_is_string(buffer[pos])) { + LogError("json_decode: expected key string at position %d", pos); + + return null; + } + + // extract the key from the buffer + json_extract_string(buffer, length, pos, key, length, is_array); + + // skip any whitespace following the key + if (! json_skip_whitespace(buffer, length, pos)) { + LogError("json_decode: buffer ended early at position %d", pos); + + return null; + } + + // ensure that we find a colon + if (buffer[pos++] != ':') { + LogError("json_decode: expected colon after key at position %d", pos); + + return null; + } + + // skip any whitespace following the colon + if (! json_skip_whitespace(buffer, length, pos)) { + LogError("json_decode: buffer ended early at position %d", pos); + + return null; + } + } + + if (json_is_object(buffer[pos]) || json_is_array(buffer[pos])) { + // if we are dealing with an object or array + // fetch the existing object if one exists at the key + JSON_Object current = (! is_array) ? result.GetObject(key) : null; + + // decode recursively + JSON_Object value = json_decode(buffer, current, pos, depth + 1); + + // decoding failed, error will be logged in json_decode + if (value == null) { + return null; + } + + if (is_array) { + result.PushObject(value); + } else { + result.SetObject(key, value); + } + } else if (json_is_string(buffer[pos])) { + // if we are dealing with a string, attempt to extract it + if (! json_extract_string(buffer, length, pos, cell, length, is_array)) { + LogError("json_decode: couldn't extract string at position %d", pos); + + return null; + } + + if (is_array) { + result.PushString(cell); + } else { + result.SetString(key, cell); + } + } else { + if (! json_extract_until_end(buffer, length, pos, cell, length, is_array)) { + LogError("json_decode: couldn't extract until end at position %d", pos); + + return null; + } + + if (strlen(cell) == 0) { + LogError("json_decode: empty cell encountered at position %d", pos); + + return null; + } + + if (json_is_int(cell)) { + int value = json_extract_int(cell); + if (is_array) { + result.PushInt(value); + } else { + result.SetInt(key, value); + } + } else if (json_is_float(cell)) { + float value = json_extract_float(cell); + if (is_array) { + result.PushFloat(value); + } else { + result.SetFloat(key, value); + } + } else if (json_is_bool(cell)) { + bool value = json_extract_bool(cell); + if (is_array) { + result.PushBool(value); + } else { + result.SetBool(key, value); + } + } else if (json_is_null(cell)) { + if (is_array) { + result.PushHandle(null); + } else { + result.SetHandle(key, null); + } + } else { + LogError("json_decode: unknown type encountered at position %d: %s", pos, cell); + + return null; + } + } + + if (! json_skip_whitespace(buffer, length, pos)) { + LogError("json_decode: buffer ended early at position %d", pos); + + return null; + } + } + + // skip remaining whitespace and ensure we're at the end of the buffer + ++pos; + if (json_skip_whitespace(buffer, length, pos) && depth == 0) { + LogError("json_decode: unexpected data after end of structure at position %d", pos); + + return null; + } + + return result; +} + +/** + * Recursively cleans up a JSON instance and any JSON instances stored within. + * + * @param obj JSON instance to clean up. + */ +stock void json_cleanup(JSON_Object obj) +{ + bool is_array = obj.IsArray; + + int key_length = 0; + StringMapSnapshot snap = obj.Snapshot(); + for (int i = 0; i < snap.Length; ++i) { + key_length = snap.KeyBufferSize(i); + char[] key = new char[key_length]; + + // ignore meta keys + snap.GetKey(i, key, key_length); + if (json_is_meta_key(key)) { + continue; + } + + // only clean up objects + JSON_CELL_TYPE type = obj.GetKeyType(key); + if (type != Type_Object) { + continue; + } + + JSON_Object nested_obj = obj.GetObject(key); + if (nested_obj != null) { + nested_obj.Cleanup(); + delete nested_obj; + } + } + + obj.Clear(); + delete snap; + + if (is_array) { + obj.SetValue(JSON_ARRAY_INDEX_KEY, 0); + } +} diff --git a/source/sourcemod/scripting/include/json/decode_helpers.inc b/source/sourcemod/scripting/include/json/decode_helpers.inc new file mode 100644 index 0000000..0032cc3 --- /dev/null +++ b/source/sourcemod/scripting/include/json/decode_helpers.inc @@ -0,0 +1,312 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2018 James D. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_decode_helpers_included + #endinput +#endif +#define _json_decode_helpers_included + +#include + +/** + * @section Analysing format of incoming JSON cells. + */ + +/** + * Checks whether the character at the given + * position in the buffer is whitespace. + * + * @param buffer String buffer of data. + * @param pos Position to check in buffer. + * @return True if buffer[pos] is whitespace, false otherwise. + */ +stock bool json_is_whitespace(const char[] buffer, int &pos) { + return buffer[pos] == ' ' || buffer[pos] == '\t' || + buffer[pos] == '\r' || buffer[pos] == '\n'; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of a string. + * + * @param buffer String buffer of data. + * @return True if buffer[0] is the start of a string, false otherwise. + */ +stock bool json_is_string(const char[] buffer) { + return buffer[0] == '"'; +} + +/** + * Checks whether the buffer provided contains an int. + * + * @param buffer String buffer of data. + * @return True if buffer contains an int, false otherwise. + */ +stock bool json_is_int(const char[] buffer) { + int length = strlen(buffer); + if (buffer[0] != '+' && buffer[0] != '-' && !IsCharNumeric(buffer[0])) { + return false; + } + + for (int i = 0; i < length; ++i) { + if (!IsCharNumeric(buffer[i])) return false; + } + + return true; +} + +/** + * Checks whether the buffer provided contains a float. + * + * @param buffer String buffer of data. + * @return True if buffer contains a float, false otherwise. + */ +stock bool json_is_float(const char[] buffer) { + bool has_decimal = false; + int length = strlen(buffer); + if (buffer[0] != '+' && buffer[0] != '-' && buffer[0] != '.' && !IsCharNumeric(buffer[0])) { + return false; + } + + for (int i = 0; i < length; ++i) { + if (buffer[i] == '.') { + if (has_decimal) { + return false; + } + + has_decimal = true; + } else if (!IsCharNumeric(buffer[i])) { + return false; + } + } + + return true; +} + +/** + * Checks whether the buffer provided contains a bool. + * + * @param buffer String buffer of data. + * @return True if buffer contains a bool, false otherwise. + */ +stock bool json_is_bool(const char[] buffer) { + return StrEqual(buffer, "true") || + StrEqual(buffer, "false"); +} + +/** + * Checks whether the buffer provided contains null. + * + * @param buffer String buffer of data. + * @return True if buffer contains null, false otherwise. + */ +stock bool json_is_null(const char[] buffer) { + return StrEqual(buffer, "null"); +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of an object. + * + * @param buffer String buffer of data. + * @return True if buffer[0] is the start of an object, false otherwise. + */ +stock bool json_is_object(const char[] buffer) { + return buffer[0] == '{'; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the end of an object. + * + * @param buffer String buffer of data. + * @return True if buffer[0] is the end of an object, false otherwise. + */ +stock bool json_is_object_end(const char[] buffer) { + return buffer[0] == '}'; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of an array. + * + * @param buffer String buffer of data. + * @return True if buffer[0] is the start of an array, false otherwise. + */ +stock bool json_is_array(const char[] buffer) { + return buffer[0] == '['; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of an array. + * + * @param buffer String buffer of data. + * @return True if buffer[0] is the start of an array, false otherwise. + */ +stock bool json_is_array_end(const char[] buffer) { + return buffer[0] == ']'; +} + +/** + * Checks whether the character at the given position in the buffer + * is considered a valid 'end point' for some data, such as a + * colon (indicating a key), a comma (indicating a new element), + * or the end of an object or array. + * + * @param buffer String buffer of data. + * @param pos Position to check in buffer. + * @return True if buffer[pos] is a valid data end point, false otherwise. + */ +stock bool json_is_at_end(const char[] buffer, int &pos, bool is_array) { + return buffer[pos] == ',' || + (!is_array && buffer[pos] == ':') || + json_is_object_end(buffer[pos]) || + json_is_array_end(buffer[pos]); +} + +/** + * Moves the position until it reaches a non-whitespace + * character or the end of the buffer's maximum size. + * + * @param buffer String buffer of data. + * @param maxlen Maximum size of string buffer. + * @param pos Position to increment. + * @return True if pos is not at the end of the buffer, false otherwise. + */ +stock bool json_skip_whitespace(const char[] buffer, int maxlen, int &pos) { + while (json_is_whitespace(buffer, pos) && pos < maxlen) { + ++pos; + } + + return pos < maxlen; +} + +/** + * Extracts a JSON cell from the buffer until + * a valid end point is reached. + * + * @param buffer String buffer of data. + * @param maxlen Maximum size of string buffer. + * @param pos Position to increment. + * @param output String buffer to store output. + * @param output_maxlen Maximum size of output string buffer. + * @param is_array Whether the decoder is currently processing an array. + * @return True if pos is not at the end of the buffer, false otherwise. + */ +stock bool json_extract_until_end(const char[] buffer, int maxlen, int &pos, char[] output, int output_maxlen, bool is_array) { + // extracts a string from current pos until a valid 'end point' + strcopy(output, output_maxlen, ""); + + int start = pos; + while (!json_is_whitespace(buffer, pos) && !json_is_at_end(buffer, pos, is_array) && pos < maxlen) { + ++pos; + } + int end = pos - 1; + + // skip trailing whitespace + json_skip_whitespace(buffer, maxlen, pos); + + if (!json_is_at_end(buffer, pos, is_array)) return false; + strcopy(output, end - start + 2, buffer[start]); + + return pos < maxlen; +} + + +/** + * Extracts a JSON string from the buffer until + * a valid end point is reached. + * + * @param buffer String buffer of data. + * @param maxlen Maximum size of string buffer. + * @param pos Position to increment. + * @param output String buffer to store output. + * @param output_maxlen Maximum size of output string buffer. + * @param is_array Whether the decoder is currently processing an array. + * @return True if pos is not at the end of the buffer, false otherwise. + */ +stock bool json_extract_string(const char[] buffer, int maxlen, int &pos, char[] output, int output_maxlen, bool is_array) { + // extracts a string which needs to be quote-escaped + strcopy(output, output_maxlen, ""); + + ++pos; + int start = pos; + while (!(buffer[pos] == '"' && buffer[pos - 1] != '\\') && pos < maxlen) { + ++pos; + } + int end = pos - 1; + + // jump 1 ahead since we ended on " instead of an ending char + ++pos; + + // skip trailing whitespace + json_skip_whitespace(buffer, maxlen, pos); + + if (!json_is_at_end(buffer, pos, is_array)) return false; + // copy only from start with length end - start + 2 (+2 for NULL terminator and something else) + strcopy(output, end - start + 2, buffer[start]); + json_unescape_string(output, maxlen); + + return pos < maxlen; +} + +/** + * Extracts an int from the buffer. + * + * @param buffer String buffer of data. + * @return Int value of the buffer. + */ +stock int json_extract_int(const char[] buffer) { + return StringToInt(buffer); +} + +/** + * Extracts a float from the buffer. + * + * @param buffer String buffer of data. + * @return Float value of the buffer. + */ +stock float json_extract_float(const char[] buffer) { + return StringToFloat(buffer); +} + +/** + * Extracts a bool from the buffer. + * + * @param buffer String buffer of data. + * @return Bool value of the buffer. + */ +stock bool json_extract_bool(const char[] buffer) { + return StrEqual(buffer, "true"); +} diff --git a/source/sourcemod/scripting/include/json/definitions.inc b/source/sourcemod/scripting/include/json/definitions.inc new file mode 100644 index 0000000..63063d3 --- /dev/null +++ b/source/sourcemod/scripting/include/json/definitions.inc @@ -0,0 +1,103 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2019 James Dickens. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_definitions_included + #endinput +#endif +#define _json_definitions_included + +#include +#include + +/** + * @section Pretty Print Constants + * + * Used to determine how pretty printed JSON should be formatted when encoded. + * You can modify these if you prefer your JSON formatted differently. + */ + +#define JSON_PP_AFTER_COLON " " +#define JSON_PP_INDENT " " +#define JSON_PP_NEWLINE "\n" + +/** + * @section Buffer Size Constants + * + * You may need to change these if you are working with very large arrays or floating point numbers. + */ + +#define JSON_FLOAT_BUFFER_SIZE 32 +#define JSON_INDEX_BUFFER_SIZE 16 + +/** + * @section Meta-key Constants + * + * Used to store metadata for each key in an object. + * You shouldn't need to change these unless working with keys that may clash with them. + */ + +#define JSON_ARRAY_INDEX_KEY "__array_index" +#define JSON_META_TYPE_KEY ":type" +#define JSON_META_LENGTH_KEY ":length" +#define JSON_META_HIDDEN_KEY ":hidden" + +/** + * @section General + */ + +/** + * Types of cells within a JSON object + */ +enum JSON_CELL_TYPE { + Type_Invalid = -1, + Type_String = 0, + Type_Int, + Type_Float, + Type_Bool, + Type_Null, + Type_Object +}; + +/** + * Checks whether the key provided is a meta-key that should only be used internally. + * + * @param key Key to check. + * @returns True when it is a meta-key, false otherwise. + */ +stock bool json_is_meta_key(char[] key) +{ + return json_string_endswith(key, JSON_META_TYPE_KEY) + || json_string_endswith(key, JSON_META_LENGTH_KEY) + || json_string_endswith(key, JSON_META_HIDDEN_KEY) + || StrEqual(key, JSON_ARRAY_INDEX_KEY); +} diff --git a/source/sourcemod/scripting/include/json/encode_helpers.inc b/source/sourcemod/scripting/include/json/encode_helpers.inc new file mode 100644 index 0000000..37cb83d --- /dev/null +++ b/source/sourcemod/scripting/include/json/encode_helpers.inc @@ -0,0 +1,164 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2018 James D. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_encode_helpers_included + #endinput +#endif +#define _json_encode_helpers_included + +#include + +/** + * @section Calculating buffer sizes for JSON cells. + */ + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of a string. + * + * @param maxlen The string's current length or buffer size. + * @return Maximum buffer length. + */ +stock int json_cell_string_size(int maxlen) { + return (maxlen * 2) + 3; // * 2 for potential escaping, + 2 for surrounding quotes + NULL +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of an int. + * + * @param input The int. + * @return Maximum buffer length. + */ +stock int json_cell_int_size(int input) { + if (input == 0) { + return 2; // "0" + NULL + } + + return ((input < 0) ? 1 : 0) + RoundToFloor(Logarithm(FloatAbs(float(input)), 10.0)) + 2; // neg sign + number of digits + NULL +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of a float. + * + * @return Maximum buffer length. + */ +stock int json_cell_float_size() { + return JSON_FLOAT_BUFFER_SIZE; // fixed-length +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of a bool. + * + * @return Maximum buffer length. + */ +stock int json_cell_bool_size() { + return 6; // "true|false" + NULL +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of null. + * + * @return Maximum buffer length. + */ +stock int json_cell_null_size() { + return 5; // "null" + NULL +} + +/** + * @section Generating JSON cells. + */ + +/** + * Generates the JSON cell representation of a string. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param maxlen Maximum size of string buffer. + */ +stock void json_cell_string(const char[] input, char[] output, int maxlen) { + strcopy(output, maxlen, "_"); // add dummy char at start so first quotation isn't escaped + StrCat(output, maxlen, input); // add input string to output + // escape everything according to JSON spec + json_escape_string(output, maxlen); + + // surround string with quotations + output[0] = '"'; + StrCat(output, maxlen, "\""); +} + +/** + * Generates the JSON cell representation of an int. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param maxlen Maximum size of string buffer. + */ +stock void json_cell_int(int input, char[] output, int maxlen) { + IntToString(input, output, maxlen); +} + +/** + * Generates the JSON cell representation of a float. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param maxlen Maximum size of string buffer. + */ +stock void json_cell_float(float input, char[] output, int maxlen) { + FloatToString(input, output, maxlen); +} + +/** + * Generates the JSON cell representation of a bool. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param maxlen Maximum size of string buffer. + */ +stock void json_cell_bool(bool input, char[] output, int maxlen) { + strcopy(output, maxlen, (input) ? "true" : "false"); +} + +/** + * Generates the JSON cell representation of null. + * + * @param output String buffer to store output. + * @param maxlen Maximum size of string buffer. + */ +stock void json_cell_null(char[] output, int maxlen) { + strcopy(output, maxlen, "null"); +} diff --git a/source/sourcemod/scripting/include/json/helpers/decode.inc b/source/sourcemod/scripting/include/json/helpers/decode.inc new file mode 100644 index 0000000..f420222 --- /dev/null +++ b/source/sourcemod/scripting/include/json/helpers/decode.inc @@ -0,0 +1,502 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2019 James Dickens. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_helpers_decode_included + #endinput +#endif +#define _json_helpers_decode_included + +#include + +/** + * @section Determine Buffer Contents + */ + +/** + * Checks whether the character at the beginning + * of the buffer is whitespace. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer + * is whitespace, false otherwise. + */ +stock bool json_is_whitespace(const char[] buffer) +{ + return buffer[0] == ' ' + || buffer[0] == '\t' + || buffer[0] == '\r' + || buffer[0] == '\n'; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of a string. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer + * is the start of a string, false otherwise. + */ +stock bool json_is_string(const char[] buffer) +{ + return buffer[0] == '"'; +} + +/** + * Checks whether the buffer provided contains an int. + * + * @param buffer String buffer of data. + * @returns True if buffer contains an int, false otherwise. + */ +stock bool json_is_int(const char[] buffer) +{ + bool starts_with_zero = false; + bool has_digit_gt_zero = false; + + int length = strlen(buffer); + for (int i = 0; i < length; ++i) { + // allow minus as first character only + if (i == 0 && buffer[i] == '-') { + continue; + } + + if (IsCharNumeric(buffer[i])) { + if (buffer[i] == '0') { + if (starts_with_zero) { + // detect repeating leading zeros + return false; + } else if (! has_digit_gt_zero) { + starts_with_zero = true; + } + } else { + has_digit_gt_zero = true; + } + } else { + return false; + } + } + + // buffer must start with zero and have no other numerics before decimal + // OR not start with zero and have other numerics + return (starts_with_zero && ! has_digit_gt_zero) + || (! starts_with_zero && has_digit_gt_zero); +} + +/** + * Checks whether the buffer provided contains a float. + * + * @param buffer String buffer of data. + * @returns True if buffer contains a float, false otherwise. + */ +stock bool json_is_float(const char[] buffer) +{ + bool starts_with_zero = false; + bool has_digit_gt_zero = false; + bool after_decimal = false; + bool has_digit_after_decimal = false; + bool after_exponent = false; + bool has_digit_after_exponent = false; + + int length = strlen(buffer); + for (int i = 0; i < length; ++i) { + // allow minus as first character only + if (i == 0 && buffer[i] == '-') { + continue; + } + + // if we haven't encountered a decimal or exponent yet + if (! after_decimal && ! after_exponent) { + if (buffer[i] == '.') { + // if we encounter a decimal before any digits + if (! starts_with_zero && ! has_digit_gt_zero) { + return false; + } + + after_decimal = true; + } else if (buffer[i] == 'e' || buffer[i] == 'E') { + // if we encounter an exponent before any non-zero digits + if (starts_with_zero && ! has_digit_gt_zero) { + return false; + } + + after_exponent = true; + } else if (IsCharNumeric(buffer[i])) { + if (buffer[i] == '0') { + if (starts_with_zero) { + // detect repeating leading zeros + return false; + } else if (! has_digit_gt_zero) { + starts_with_zero = true; + } + } else { + has_digit_gt_zero = true; + } + } else { + return false; + } + } else if (after_decimal && ! after_exponent) { + // after decimal has been encountered, allow any numerics + if (IsCharNumeric(buffer[i])) { + has_digit_after_decimal = true; + } else if (buffer[i] == 'e' || buffer[i] == 'E') { + if (! has_digit_after_decimal) { + // detect exponents directly after decimal + return false; + } + + after_exponent = true; + } else { + return false; + } + } else if (after_exponent) { + if ( + (buffer[i] == '+' || buffer[i] == '-') + && (buffer[i - 1] == 'e' || buffer[i - 1] == 'E') + ) { + // allow + or - directly after exponent + continue; + } else if (IsCharNumeric(buffer[i])) { + has_digit_after_exponent = true; + } else { + return false; + } + } + } + + if (starts_with_zero && has_digit_gt_zero) { + /* if buffer starts with zero, there should + be no other digits before the decimal */ + return false; + } + + // if we have a decimal, there should be digit(s) after it + if (after_decimal) { + if (! has_digit_after_decimal) { + return false; + } + } + + // if we have an exponent, there should be digit(s) after it + if (after_exponent) { + if (! has_digit_after_exponent) { + return false; + } + } + + /* we should have reached an exponent, decimal, or both. + otherwise, this number can be handled by the int parser */ + return after_decimal || after_exponent; +} + +/** + * Checks whether the buffer provided contains a bool. + * + * @param buffer String buffer of data. + * @returns True if buffer contains a bool, false otherwise. + */ +stock bool json_is_bool(const char[] buffer) +{ + return StrEqual(buffer, "true") || StrEqual(buffer, "false"); +} + +/** + * Checks whether the buffer provided contains null. + * + * @param buffer String buffer of data. + * @returns True if buffer contains null, false otherwise. + */ +stock bool json_is_null(const char[] buffer) +{ + return StrEqual(buffer, "null"); +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of an object. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer is + * the start of an object, false otherwise. + */ +stock bool json_is_object(const char[] buffer) +{ + return buffer[0] == '{'; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the end of an object. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer is + * the end of an object, false otherwise. + */ +stock bool json_is_object_end(const char[] buffer) +{ + return buffer[0] == '}'; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the start of an array. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer is + * the start of an array, false otherwise. + */ +stock bool json_is_array(const char[] buffer) +{ + return buffer[0] == '['; +} + +/** + * Checks whether the character at the beginning + * of the buffer is the end of an array. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer is + * the end of an array, false otherwise. + */ +stock bool json_is_array_end(const char[] buffer) +{ + return buffer[0] == ']'; +} + +/** + * Checks whether the character at the beginning of the buffer + * is considered a valid 'end point' for some data, such as a + * colon (indicating a key), a comma (indicating a new element), + * or the end of an object or array. + * + * @param buffer String buffer of data. + * @returns True if the first character in the buffer + * is a valid data end point, false otherwise. + */ +stock bool json_is_at_end(const char[] buffer, bool is_array) +{ + return buffer[0] == ',' + || (! is_array && buffer[0] == ':') + || json_is_object_end(buffer[0]) + || json_is_array_end(buffer[0]); +} + +/** + * @section Extract Contents from Buffer + */ + +/** + * Moves the position until it reaches a non-whitespace + * character or the end of the buffer's maximum size. + * + * @param buffer String buffer of data. + * @param max_size Maximum size of string buffer. + * @param pos Position to increment. + * @returns True if pos has not reached the end + * of the buffer, false otherwise. + */ +stock bool json_skip_whitespace(const char[] buffer, int max_size, int &pos) +{ + while (json_is_whitespace(buffer[pos]) && pos < max_size) { + ++pos; + } + + return pos < max_size; +} + +/** + * Extracts a JSON cell from the buffer until + * a valid end point is reached. + * + * @param buffer String buffer of data. + * @param max_size Maximum size of string buffer. + * @param pos Position to increment. + * @param output String buffer to store output. + * @param output_max_size Maximum size of output string buffer. + * @param is_array Whether the decoder is processing an array. + * @returns True if pos has not reached the end + * of the buffer, false otherwise. + */ +stock bool json_extract_until_end( + const char[] buffer, + int max_size, + int &pos, + char[] output, + int output_max_size, + bool is_array +) { + strcopy(output, output_max_size, ""); + + // set start to position of first character in cell + int start = pos; + + // while we haven't hit whitespace, an end point or the end of the buffer + while ( + ! json_is_whitespace(buffer[pos]) + && ! json_is_at_end(buffer[pos], is_array) + && pos < max_size + ) { + ++pos; + } + + // set end to the current position + int end = pos; + + // skip any following whitespace + json_skip_whitespace(buffer, max_size, pos); + + // if we aren't at a valid endpoint, extraction has failed + if (! json_is_at_end(buffer[pos], is_array)) { + return false; + } + + // copy only from start with length end - start + NULL terminator + strcopy(output, end - start + 1, buffer[start]); + + return pos < max_size; +} + +/** + * Extracts a JSON string from the buffer until + * a valid end point is reached. + * + * @param buffer String buffer of data. + * @param max_size Maximum size of string buffer. + * @param pos Position to increment. + * @param output String buffer to store output. + * @param output_max_size Maximum size of output string buffer. + * @param is_array Whether the decoder is processing an array. + * @returns True if pos has not reached the end + * of the buffer, false otherwise. + */ +stock bool json_extract_string( + const char[] buffer, + int max_size, + int &pos, + char[] output, + int output_max_size, + bool is_array +) { + strcopy(output, output_max_size, ""); + + // increment past opening quote + ++pos; + + // set start to position of first character in string + int start = pos; + + // while we haven't hit the end of the buffer + while (pos < max_size) { + // check for unescaped control characters + if ( + buffer[pos] == '\b' + || buffer[pos] == '\f' + || buffer[pos] == '\n' + || buffer[pos] == '\r' + || buffer[pos] == '\t' + ) { + return false; + } + + if (buffer[pos] == '"') { + // count preceding backslashes to check if quote is escaped + int search_pos = pos; + int preceding_backslashes = 0; + while (search_pos > 0 && buffer[--search_pos] == '\\') { + ++preceding_backslashes; + } + + // if we have an even number of backslashes, the quote is not escaped + if (preceding_backslashes % 2 == 0) { + break; + } + } + + // pass over the character as it is part of the string + ++pos; + } + + // set end to the current position + int end = pos; + + // increment past closing quote + ++pos; + + // skip trailing whitespace + if (! json_skip_whitespace(buffer, max_size, pos)) { + return false; + } + + // if we haven't reached an ending character at the end of the cell, + // there is likely junk data not encapsulated by a string + if (! json_is_at_end(buffer[pos], is_array)) { + return false; + } + + // copy only from start with length end - start + NULL terminator + strcopy(output, end - start + 1, buffer[start]); + json_unescape_string(output, max_size); + + return pos < max_size; +} + +/** + * Extracts an int from the buffer. + * + * @param buffer String buffer of data. + * @returns Int value of the buffer. + */ +stock int json_extract_int(const char[] buffer) +{ + return StringToInt(buffer); +} + +/** + * Extracts a float from the buffer. + * + * @param buffer String buffer of data. + * @returns Float value of the buffer. + */ +stock float json_extract_float(const char[] buffer) +{ + return StringToFloat(buffer); +} + +/** + * Extracts a bool from the buffer. + * + * @param buffer String buffer of data. + * @returns Bool value of the buffer. + */ +stock bool json_extract_bool(const char[] buffer) +{ + return StrEqual(buffer, "true"); +} diff --git a/source/sourcemod/scripting/include/json/helpers/encode.inc b/source/sourcemod/scripting/include/json/helpers/encode.inc new file mode 100644 index 0000000..ceae54d --- /dev/null +++ b/source/sourcemod/scripting/include/json/helpers/encode.inc @@ -0,0 +1,200 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2019 James Dickens. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_helpers_encode_included + #endinput +#endif +#define _json_helpers_encode_included + +#include + +/** + * @section Calculate Buffer Size for Value + */ + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of a string. + * + * @param length The length of the string. + * @returns Maximum buffer length. + */ +stock int json_cell_string_size(int length) +{ + // double for potential escaping, + 2 for outside quotes + NULL terminator + return (length * 2) + 3; +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of an int. + * + * @param input Value to calculate maximum buffer length for. + * @returns Maximum buffer length. + */ +stock int json_cell_int_size(int input) +{ + if (input == 0) { + // "0" + NULL terminator + return 2; + } + + int result = 0; + if (input < 0) { + // negative sign + result += 1; + } + + // calculate number of digits in number + result += RoundToFloor(Logarithm(FloatAbs(float(input)), 10.0)) + 1; + + // NULL terminator + result += 1; + + return result; +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of a float. + * + * @returns Maximum buffer length. + */ +stock int json_cell_float_size() +{ + return JSON_FLOAT_BUFFER_SIZE; +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of a bool. + * + * @returns Maximum buffer length. + */ +stock int json_cell_bool_size() +{ + // "true"|"false" + NULL terminator + return 6; +} + +/** + * Calculates the maximum buffer length required to + * store the JSON cell representation of null. + * + * @returns Maximum buffer length. + */ +stock int json_cell_null_size() +{ + // "null" + NULL terminator + return 5; +} + +/** + * @section Convert Values to JSON Cells + */ + +/** + * Generates the JSON cell representation of a string. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + */ +stock void json_cell_string(const char[] input, char[] output, int max_size) +{ + // add dummy char that won't be escaped to replace with a quote later + strcopy(output, max_size, "?"); + + // add input string to output + StrCat(output, max_size, input); + + // escape the output string + json_escape_string(output, max_size); + + // surround string with quotations + output[0] = '"'; + StrCat(output, max_size, "\""); +} + +/** + * Generates the JSON cell representation of an int. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + */ +stock void json_cell_int(int input, char[] output, int max_size) +{ + IntToString(input, output, max_size); +} + +/** + * Generates the JSON cell representation of a float. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + */ +stock void json_cell_float(float input, char[] output, int max_size) +{ + FloatToString(input, output, max_size); + + // trim trailing 0s from float output up until decimal point + int last_char = strlen(output) - 1; + while (output[last_char] == '0' && output[last_char - 1] != '.') { + output[last_char--] = '\0'; + } +} + +/** + * Generates the JSON cell representation of a bool. + * + * @param input Value to generate output for. + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + */ +stock void json_cell_bool(bool input, char[] output, int max_size) +{ + strcopy(output, max_size, (input) ? "true" : "false"); +} + +/** + * Generates the JSON cell representation of null. + * + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + */ +stock void json_cell_null(char[] output, int max_size) +{ + strcopy(output, max_size, "null"); +} diff --git a/source/sourcemod/scripting/include/json/helpers/string.inc b/source/sourcemod/scripting/include/json/helpers/string.inc new file mode 100644 index 0000000..14fe38a --- /dev/null +++ b/source/sourcemod/scripting/include/json/helpers/string.inc @@ -0,0 +1,133 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2019 James Dickens. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_helpers_string_included + #endinput +#endif +#define _json_helpers_string_included + +/** + * Mapping characters to their escaped form. + */ +char JSON_STRING_NORMAL[][] = { + "\\", "\"", "/", "\b", "\f", "\n", "\r", "\t" +}; +char JSON_STRING_ESCAPED[][] = { + "\\\\", "\\\"", "\\/", "\\b", "\\f", "\\n", "\\r", "\\t" +}; + +/** + * Escapes a string in-place in a buffer. + * + * @param buffer String buffer. + * @param max_size Maximum size of string buffer. + */ +stock void json_escape_string(char[] buffer, int max_size) +{ + for (int i = 0; i < sizeof(JSON_STRING_NORMAL); ++i) { + ReplaceString( + buffer, + max_size, + JSON_STRING_NORMAL[i], + JSON_STRING_ESCAPED[i] + ); + } +} + +/** + * Unescapes a string in-place in a buffer. + * + * @param buffer String buffer. + * @param max_size Maximum size of string buffer. + */ +stock void json_unescape_string(char[] buffer, int max_size) +{ + for (int i = 0; i < sizeof(JSON_STRING_NORMAL); ++i) { + ReplaceString( + buffer, + max_size, + JSON_STRING_ESCAPED[i], + JSON_STRING_NORMAL[i] + ); + } +} + +/** + * Checks if a string starts with another string. + * + * @param haystack String to check that starts with needle. + * @param max_size Maximum size of string buffer. + * @param needle String to check that haystack starts with. + * @returns True if haystack begins with needle, false otherwise. + */ +stock bool json_string_startswith(const char[] haystack, const char[] needle) +{ + int haystack_length = strlen(haystack); + int needle_length = strlen(needle); + if (needle_length > haystack_length) { + return false; + } + + for (int i = 0; i < needle_length; ++i) { + if (haystack[i] != needle[i]) { + return false; + } + } + + return true; +} + +/** + * Checks if a string ends with another string. + * + * @param haystack String to check that ends with needle. + * @param max_size Maximum size of string buffer. + * @param needle String to check that haystack ends with. + * @returns True if haystack ends with needle, false otherwise. + */ +stock bool json_string_endswith(const char[] haystack, const char[] needle) +{ + int haystack_length = strlen(haystack); + int needle_length = strlen(needle); + if (needle_length > haystack_length) { + return false; + } + + for (int i = 0; i < needle_length; ++i) { + if (haystack[haystack_length - needle_length + i] != needle[i]) { + return false; + } + } + + return true; +} diff --git a/source/sourcemod/scripting/include/json/object.inc b/source/sourcemod/scripting/include/json/object.inc new file mode 100644 index 0000000..8d17568 --- /dev/null +++ b/source/sourcemod/scripting/include/json/object.inc @@ -0,0 +1,1014 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2019 James Dickens. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_object_included + #endinput +#endif +#define _json_object_included + +#include +#include +#include +#include + +methodmap JSON_Object < StringMap +{ + /** + * Creates a new JSON_Object. + * + * @param is_array Should the object created be an array? [default: false] + * @returns A new JSON_Object. + */ + public JSON_Object(bool is_array = false) + { + StringMap self = CreateTrie(); + if (is_array) { + self.SetValue(JSON_ARRAY_INDEX_KEY, 0); + } + + return view_as(self); + } + + /** + * Checks whether the object has a key. + * + * @param key Key to check existence of. + * @returns True if the key exists, false otherwise. + */ + public bool HasKey(const char[] key) + { + int dummy_int; + char dummy_str[1]; + + return this.GetValue(key, dummy_int) + || this.GetString(key, dummy_str, sizeof(dummy_str)); + } + + /** + * @section Array helpers. + */ + + /** + * Whether the current object is an array. + */ + property bool IsArray { + public get() + { + return this.HasKey(JSON_ARRAY_INDEX_KEY); + } + } + + /** + * The current index of the object if it is an array, or -1 otherwise. + */ + property int CurrentIndex { + public get() + { + if (! this.IsArray) { + return -1; + } + + int result; + return (this.GetValue(JSON_ARRAY_INDEX_KEY, result)) ? result : -1; + } + + public set(int value) + { + this.SetValue(JSON_ARRAY_INDEX_KEY, value); + } + } + + /** + * The number of items in the object if it is an array, + * or the number of keys (including meta-keys) otherwise. + */ + property int Length { + public get() + { + StringMapSnapshot snap = this.Snapshot(); + int length = (this.IsArray) ? this.CurrentIndex : snap.Length; + delete snap; + + return length; + } + } + + /** + * Increments the current index of the object. + * + * @returns True on success, false if the current object is not an array. + */ + public bool IncrementIndex() + { + if (! this.HasKey(JSON_ARRAY_INDEX_KEY)) { + return false; + } + + this.CurrentIndex += 1; + + return true; + } + + /** + * Checks whether the object has an index. + * + * @param index Index to check existence of. + * @returns True if the index exists, false otherwise. + */ + public bool HasIndex(int index) + { + return index >= 0 && index < this.Length; + } + + /** + * Gets the string representation of an array index. + * + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + * @param key Key to get string for. [default: current index] + * @returns True on success, false otherwise. + */ + public int GetIndexString(char[] output, int max_size, int key = -1) + { + key = (key == -1) ? this.CurrentIndex : key; + if (key == -1) { + return false; + } + + return IntToString(key, output, max_size); + } + + /** + * @section Internal Getters + */ + + /** + * Gets the cell type stored at a key. + * + * @param key Key to get value type for. + * @returns Value type for key provided, + * or Type_Invalid if it does not exist. + */ + public JSON_CELL_TYPE GetKeyType(const char[] key) + { + int max_size = strlen(key) + strlen(JSON_META_TYPE_KEY) + 1; + char[] type_key = new char[max_size]; + Format(type_key, max_size, "%s%s", key, JSON_META_TYPE_KEY); + + JSON_CELL_TYPE type; + return (this.GetValue(type_key, type)) ? type : Type_Invalid; + } + + /** + * Gets the cell type stored at an index. + * + * @param index Index to get value type for. + * @returns Value type for index provided, or Type_Invalid if it does not exist. + */ + public JSON_CELL_TYPE GetKeyTypeIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return Type_Invalid; + } + + return this.GetKeyType(key); + } + + /** + * Gets the length of the string stored at a key. + * + * @param key Key to get string length for. + * @returns Length of string at key provided, + * or -1 if it is not a string/does not exist. + */ + public int GetKeyLength(const char[] key) + { + int max_size = strlen(key) + strlen(JSON_META_LENGTH_KEY) + 1; + char[] length_key = new char[max_size]; + Format(length_key, max_size, "%s%s", key, JSON_META_LENGTH_KEY); + + int length; + return (this.GetValue(length_key, length)) ? length : -1; + } + + /** + * Gets the length of the string stored at an index. + * + * @param index Index to get string length for. + * @returns Length of string at index provided, or -1 if it is not a string/does not exist. + */ + public int GetKeyLengthIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return -1; + } + + return this.GetKeyLength(key); + } + + /** + * Gets whether the key should be hidden from encoding. + * + * @param key Key to get hidden state for. + * @returns Whether or not the key should be hidden. + */ + public bool GetKeyHidden(const char[] key) + { + int max_size = strlen(key) + strlen(JSON_META_HIDDEN_KEY) + 1; + char[] length_key = new char[max_size]; + Format(length_key, max_size, "%s%s", key, JSON_META_HIDDEN_KEY); + + bool hidden; + return (this.GetValue(length_key, hidden)) ? hidden : false; + } + + /** + * Gets whether the index should be hidden from encoding. + * + * @param index Index to get hidden state for. + * @returns Whether or not the index should be hidden. + */ + public bool GetKeyHiddenIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.GetKeyHidden(key); + } + + /** + * @section Internal Setters + */ + + /** + * Sets the cell type stored at a key. + * + * @param key Key to set value type for. + * @param type Type to set key to. + * @returns True on success, false otherwise. + */ + public bool SetKeyType(const char[] key, JSON_CELL_TYPE type) + { + int max_size = strlen(key) + strlen(JSON_META_TYPE_KEY) + 1; + char[] type_key = new char[max_size]; + Format(type_key, max_size, "%s%s", key, JSON_META_TYPE_KEY); + + return this.SetValue(type_key, type); + } + + /** + * Sets the cell type stored at an index. + * + * @param index Index to set value type for. + * @param type Type to set index to. + * @returns True on success, false otherwise. + */ + public bool SetKeyTypeIndexed(int index, JSON_CELL_TYPE value) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetKeyType(key, value); + } + + /** + * Sets the length of the string stored at a key. + * + * @param key Key to set string length for. + * @param length Length to set string to. + * @returns True on success, false otherwise. + */ + public bool SetKeyLength(const char[] key, int length) + { + int max_size = strlen(key) + strlen(JSON_META_LENGTH_KEY) + 1; + char[] length_key = new char[max_size]; + Format(length_key, max_size, "%s%s", key, JSON_META_LENGTH_KEY); + + return this.SetValue(length_key, length); + } + + /** + * Sets the length of the string stored at an index. + * + * @param index Index to set string length for. + * @param length Length to set string to. + * @returns True on success, false otherwise. + */ + public bool SetKeyLengthIndexed(int index, int length) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetKeyLength(key, length); + } + + /** + * Sets whether the key should be hidden from encoding. + * + * @param key Key to set hidden state for. + * @param hidden Wheter or not the key should be hidden. + * @returns True on success, false otherwise. + */ + public bool SetKeyHidden(const char[] key, bool hidden) + { + int max_size = strlen(key) + strlen(JSON_META_HIDDEN_KEY) + 1; + char[] hidden_key = new char[max_size]; + Format(hidden_key, max_size, "%s%s", key, JSON_META_HIDDEN_KEY); + + return this.SetValue(hidden_key, hidden); + } + + /** + * Sets whether the index should be hidden from encoding. + * + * @param index Index to set hidden state for. + * @param hidden Wheter or not the index should be hidden. + * @returns True on success, false otherwise. + */ + public bool SetKeyHiddenIndexed(int index, bool hidden) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetKeyHidden(key, hidden); + } + + /** + * @section Getters + */ + + // GetValue is implemented natively by StringMap + + /** + * Retrieves the value stored at an index. + * + * @param index Index to retrieve value for. + * @param value Variable to store value. + * @returns Value stored at index. + */ + public bool GetValueIndexed(int index, any &value) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.GetValue(key, value); + } + + // GetString is implemented natively by StringMap + + /** + * Retrieves the string stored at an index. + * + * @param index Index to retrieve string value for. + * @param value String buffer to store output. + * @param max_size Maximum size of string buffer. + * @returns True on success. False if the key is not set, or the key is set as a value or array (not a string). + */ + public bool GetStringIndexed(int index, char[] value, int max_size) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.GetString(key, value, max_size); + } + + /** + * Retrieves the int stored at a key. + * + * @param key Key to retrieve int value for. + * @returns Value stored at key. + */ + public int GetInt(const char[] key) + { + int value; + return (this.GetValue(key, value)) ? value : -1; + } + + /** + * Retrieves the int stored at an index. + * + * @param index Index to retrieve int value for. + * @returns Value stored at index. + */ + public int GetIntIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return -1; + } + + return this.GetInt(key); + } + + /** + * Retrieves the float stored at a key. + * + * @param key Key to retrieve float value for. + * @returns Value stored at key. + */ + public float GetFloat(const char[] key) + { + float value; + return (this.GetValue(key, value)) ? value : -1.0; + } + + /** + * Retrieves the float stored at an index. + * + * @param index Index to retrieve float value for. + * @returns Value stored at index. + */ + public float GetFloatIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return -1.0; + } + + return this.GetFloat(key); + } + + /** + * Retrieves the bool stored at a key. + * + * @param key Key to retrieve bool value for. + * @returns Value stored at key. + */ + public bool GetBool(const char[] key) + { + bool value; + return (this.GetValue(key, value)) ? value : false; + } + + /** + * Retrieves the bool stored at an index. + * + * @param index Index to retrieve bool value for. + * @returns Value stored at index. + */ + public bool GetBoolIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.GetBool(key); + } + + /** + * Retrieves the handle stored at a key. + * + * @param key Key to retrieve handle value for. + * @returns Value stored at key. + */ + public Handle GetHandle(const char[] key) + { + Handle value; + return (this.GetValue(key, value)) ? value : null; + } + + /** + * Retrieves the handle stored at an index. + * + * @param index Index to retrieve handle value for. + * @returns Value stored at index. + */ + public Handle GetHandleIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return null; + } + + return this.GetHandle(key); + } + + /** + * Retrieves the JSON object stored at a key. + * + * @param key Key to retrieve object value for. + * @returns Value stored at key. + */ + public JSON_Object GetObject(const char[] key) + { + return view_as(this.GetHandle(key)); + } + + /** + * Retrieves the object stored at an index. + * + * @param index Index to retrieve object value for. + * @returns Value stored at index. + */ + public JSON_Object GetObjectIndexed(int index) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return null; + } + + return this.GetObject(key); + } + + /** + * @section Setters + */ + + /** + * Sets the string stored at a key. + * + * @param key Key to set to string value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetString(const char[] key, const char[] value, bool replace = true) + { + return this.SetString(key, value, replace) + && this.SetKeyType(key, Type_String) + && this.SetKeyLength(key, strlen(value)); + } + + /** + * Sets the string stored at an index. + * + * @param index Index to set to string value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetStringIndexed(int index, const char[] value, bool replace = true) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetString(key, value, replace); + } + + /** + * Sets the int stored at a key. + * + * @param key Key to set to int value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetInt(const char[] key, int value, bool replace = true) + { + return this.SetValue(key, value, replace) + && this.SetKeyType(key, Type_Int); + } + + /** + * Sets the int stored at an index. + * + * @param index Index to set to int value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetIntIndexed(int index, int value, bool replace = true) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetInt(key, value, replace); + } + + /** + * Sets the float stored at a key. + * + * @param key Key to set to float value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetFloat(const char[] key, float value, bool replace = true) + { + return this.SetValue(key, value, replace) + && this.SetKeyType(key, Type_Float); + } + + /** + * Sets the float stored at an index. + * + * @param index Index to set to float value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetFloatIndexed(int index, float value, bool replace = true) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetFloat(key, value, replace); + } + + /** + * Sets the bool stored at a key. + * + * @param key Key to set to bool value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetBool(const char[] key, bool value, bool replace = true) + { + return this.SetValue(key, value, replace) + && this.SetKeyType(key, Type_Bool); + } + + /** + * Sets the bool stored at an index. + * + * @param index Index to set to bool value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetBoolIndexed(int index, bool value, bool replace = true) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetBool(key, value, replace); + } + + /** + * Sets the handle stored at a key. + * + * @param key Key to set to handle value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetHandle(const char[] key, Handle value = null, bool replace = true) + { + return this.SetValue(key, value, replace) + && this.SetKeyType(key, Type_Null); + } + + /** + * Sets the handle stored at an index. + * + * @param index Index to set to handle value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetHandleIndexed(int index, Handle value = null, bool replace = true) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetHandle(key, value, replace); + } + + /** + * Sets the object stored at a key. + * + * @param key Key to set to object value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetObject(const char[] key, JSON_Object value, bool replace = true) + { + return this.SetValue(key, value, replace) + && this.SetKeyType(key, Type_Object); + } + + /** + * Sets the object stored at an index. + * + * @param index Index to set to object value. + * @param value Value to set. + * @returns True on success, false otherwise. + */ + public bool SetObjectIndexed(int index, JSON_Object value, bool replace = true) + { + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + return this.SetObject(key, value, replace); + } + + /** + * @section Array setters. + */ + + /** + * Pushes a string to the end of the array. + * + * @param value Value to push. + * @returns True on success, false otherwise. + */ + public bool PushString(const char[] value) + { + return this.SetStringIndexed(this.CurrentIndex, value) + && this.IncrementIndex(); + } + + /** + * Pushes an int to the end of the array. + * + * @param value Value to push. + * @returns True on success, false otherwise. + */ + public bool PushInt(int value) + { + return this.SetIntIndexed(this.CurrentIndex, value) + && this.IncrementIndex(); + } + + /** + * Pushes a float to the end of the array. + * + * @param value Value to push. + * @returns True on success, false otherwise. + */ + public bool PushFloat(float value) + { + return this.SetFloatIndexed(this.CurrentIndex, value) + && this.IncrementIndex(); + } + + /** + * Pushes a bool to the end of the array. + * + * @param value Value to push. + * @returns True on success, false otherwise. + */ + public bool PushBool(bool value) + { + return this.SetBoolIndexed(this.CurrentIndex, value) + && this.IncrementIndex(); + } + + /** + * Pushes a handle to the end of the array. + * + * @param value Value to push. + * @returns True on success, false otherwise. + */ + public bool PushHandle(Handle value = null) + { + return this.SetHandleIndexed(this.CurrentIndex, value) + && this.IncrementIndex(); + } + + /** + * Pushes an object to the end of the array. + * + * @param value Value to push. + * @returns True on success, false otherwise. + */ + public bool PushObject(JSON_Object value) + { + return this.SetObjectIndexed(this.CurrentIndex, value) + && this.IncrementIndex(); + } + + /** + * @section Generic. + */ + + /** + * Finds the index of a value in the array. + * + * @param value Value to search for. + * @returns The index of the value if it is found, -1 otherwise. + */ + public int IndexOf(any value) + { + any current; + for (int i = 0; i < this.CurrentIndex; ++i) { + if (this.GetValueIndexed(i, current) && value == current) { + return i; + } + } + + return -1; + } + + /** + * Finds the index of a string in the array. + * + * @param value String to search for. + * @returns The index of the string if it is found, -1 otherwise. + */ + public int IndexOfString(const char[] value) + { + for (int i = 0; i < this.CurrentIndex; ++i) { + if (this.GetKeyTypeIndexed(i) != Type_String) { + continue; + } + + int current_size = this.GetKeyLengthIndexed(i) + 1; + char[] current = new char[current_size]; + this.GetStringIndexed(i, current, current_size); + if (StrEqual(value, current)) { + return i; + } + } + + return -1; + } + + /** + * Determines whether the array contains a value. + * + * @param value Value to search for. + * @returns True if the value is found, false otherwise. + */ + public bool Contains(any value) + { + return this.IndexOf(value) != -1; + } + + /** + * Determines whether the array contains a string. + * + * @param value String to search for. + * @returns True if the string is found, false otherwise. + */ + public bool ContainsString(const char[] value) + { + return this.IndexOfString(value) != -1; + } + + /** + * Removes an item from the object by key. + * + * @param key Key of object to remove. + * @returns True on success, false if the value was never set. + */ + public bool Remove(const char[] key) { + static char meta_keys[][] = { + JSON_META_TYPE_KEY, JSON_META_LENGTH_KEY, JSON_META_HIDDEN_KEY + }; + + // create a new char[] which will fit the longest meta-key + int meta_key_size = strlen(key) + 8; + char[] meta_key = new char[meta_key_size]; + + // view ourselves as a StringMap so we can call underlying Remove() method + StringMap self = view_as(this); + + bool success = true; + for (int i = 0; i < sizeof(meta_keys); ++i) { + Format(meta_key, meta_key_size, "%s%s", key, meta_keys[i]); + + if (this.HasKey(meta_key)) { + success = success && self.Remove(meta_key); + } + } + + return success && self.Remove(key); + } + + /** + * Removes a key and its related meta-keys from the object. + * + * @param key Key to remove. + * @returns True on success, false if the value was never set. + */ + public bool RemoveIndexed(int index) + { + if (! this.HasIndex(index)) { + return false; + } + + char key[JSON_INDEX_BUFFER_SIZE]; + if (! this.GetIndexString(key, sizeof(key), index)) { + return false; + } + + if (! this.Remove(key)) { + return false; + } + + for (int i = index + 1; i < this.CurrentIndex; ++i) { + if (! this.GetIndexString(key, sizeof(key), i)) { + return false; + } + + int target = i - 1; + + JSON_CELL_TYPE type = this.GetKeyTypeIndexed(i); + + switch (type) { + case Type_String: { + int str_length = this.GetKeyLengthIndexed(i); + char[] str_value = new char[str_length]; + + this.GetStringIndexed(i, str_value, str_length + 1); + this.SetStringIndexed(target, str_value); + } + case Type_Int: { + this.SetIntIndexed(target, this.GetIntIndexed(i)); + } + case Type_Float: { + this.SetFloatIndexed(target, this.GetFloatIndexed(i)); + } + case Type_Bool: { + this.SetBoolIndexed(target, this.GetBoolIndexed(i)); + } + case Type_Null: { + this.SetHandleIndexed(target, this.GetHandleIndexed(i)); + } + case Type_Object: { + this.SetObjectIndexed(target, this.GetObjectIndexed(i)); + } + } + + if (this.GetKeyHiddenIndexed(i)) { + this.SetKeyHiddenIndexed(target, true); + } + + this.Remove(key); + } + + this.CurrentIndex -= 1; + + return true; + } + + /** + * Encodes the instance into its string representation. + * + * @param output String buffer to store output. + * @param max_size Maximum size of string buffer. + * @param pretty_print Should the output be pretty printed (newlines and spaces)? [default: false] + * @param depth The current depth of the encoder. [default: 0] + */ + public void Encode(char[] output, int max_size, bool pretty_print = false, int depth = 0) + { + json_encode(this, output, max_size, pretty_print, depth); + } + + /** + * Decodes a JSON string into this object. + * + * @param buffer Buffer to decode. + */ + public void Decode(const char[] buffer) + { + json_decode(buffer, this); + } + + /** + * Recursively cleans up the object and any objects referenced within. + */ + public void Cleanup() + { + json_cleanup(this); + } +}; diff --git a/source/sourcemod/scripting/include/json/string_helpers.inc b/source/sourcemod/scripting/include/json/string_helpers.inc new file mode 100644 index 0000000..6063d47 --- /dev/null +++ b/source/sourcemod/scripting/include/json/string_helpers.inc @@ -0,0 +1,77 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * sm-json + * Provides a pure SourcePawn implementation of JSON encoding and decoding. + * https://github.com/clugg/sm-json + * + * sm-json (C)2018 James D. (clug) + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * 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 . + */ + +#if defined _json_string_helpers_included + #endinput +#endif +#define _json_string_helpers_included + +/** + * Checks if a string starts with another string. + * + * @param haystack String to check that starts with needle. + * @param maxlen Maximum size of string buffer. + * @param needle String to check that haystack starts with. + * @return True if haystack begins with needle, false otherwise. + */ +stock bool json_string_startswith(const char[] haystack, const char[] needle) { + int haystack_length = strlen(haystack); + int needle_length = strlen(needle); + if (needle_length > haystack_length) return false; + + for (int i = 0; i < needle_length; ++i) { + if (haystack[i] != needle[i]) return false; + } + + return true; +} + +/** + * Checks if a string ends with another string. + * + * @param haystack String to check that ends with needle. + * @param maxlen Maximum size of string buffer. + * @param needle String to check that haystack ends with. + * @return True if haystack ends with needle, false otherwise. + */ +stock bool json_string_endswith(const char[] haystack, const char[] needle) { + int haystack_length = strlen(haystack); + int needle_length = strlen(needle); + if (needle_length > haystack_length) return false; + + for (int i = 0; i < needle_length; ++i) { + if (haystack[haystack_length - needle_length + i] != needle[i]) return false; + } + + return true; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/keyvalues.inc b/source/sourcemod/scripting/include/keyvalues.inc new file mode 100644 index 0000000..7318507 --- /dev/null +++ b/source/sourcemod/scripting/include/keyvalues.inc @@ -0,0 +1,707 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 +}; + +methodmap KeyValues < Handle +{ + // Creates a new KeyValues structure. The Handle must be closed with + // CloseHandle() or delete. + // + // @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. + public native KeyValues(const char[] name, const char[] firstKey="", const char[] firstValue=""); + + // Exports a KeyValues tree to a file. The tree is dumped from the current position. + // + // @param file File to dump write to. + // @return True on success, false otherwise. + public native bool ExportToFile(const char[] file); + + // Exports a KeyValues tree to a string. The string is dumped from the current position. + // + // @param buffer Buffer to write to. + // @param maxlength Max length of buffer. + // @return Number of bytes that can be written to buffer. + public native int ExportToString(char[] buffer, int maxlength); + + // Amount of bytes written by ExportToFile & ExportToString. + property int ExportLength { + public native get(); + } + + // Imports a file in KeyValues format. The file is read into the current + // position of the tree. + // + // @param file File to read from. + // @return True on success, false otherwise. + public native bool ImportFromFile(const char[] file); + + // Converts a given string to a KeyValues tree. The string is read into + // the current postion of the tree. + // + // @param buffer String buffer to load into the KeyValues. + // @param resourceName The resource name of the KeyValues, used for error tracking purposes. + // @return True on success, false otherwise. + public native bool ImportFromString(const char[] buffer, const char[] resourceName="StringToKeyValues"); + + // Imports subkeys in the given KeyValues, at the current position in that + // KeyValues, into the current position in this KeyValues. Note that this + // copies keys; it does not embed a reference to them. + // + // @param other Origin KeyValues Handle. + public native void Import(KeyValues other); + + // 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. + public native void SetString(const char[] key, const char[] value); + + // Sets an integer value of a KeyValues key. + // + // @param key Name of the key, or NULL_STRING. + // @param value Value number. + public native void SetNum(const char[] key, int value); + + // Sets a large integer value of a KeyValues key. + // + // @param key Name of the key, or NULL_STRING. + // @param value Large integer value (0=High bits, 1=Low bits) + public native void SetUInt64(const char[] key, const int value[2]); + + // Sets a floating point value of a KeyValues key. + // + // @param key Name of the key, or NULL_STRING. + // @param value Floating point value. + public native void SetFloat(const char[] key, float value); + + // Sets a set of color values of a KeyValues key. + // + // @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. + public native void SetColor(const char[] key, int r, int g, int b, int a=0); + + // Sets a set of color values of a KeyValues key. + // + // @param key Name of the key, or NULL_STRING. + // @param color Red, green, blue and alpha channels. + public void SetColor4(const char[] key, const int color[4]) { + this.SetColor(key, color[0], color[1], color[2], color[3]); + } + + // Sets a vector value of a KeyValues key. + // + // @param key Name of the key, or NULL_STRING. + // @param vec Vector value. + public native void SetVector(const char[] key, const float vec[3]); + + // Retrieves a string value from a KeyValues key. + // + // @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. + public native void GetString(const char[] key, char[] value, int maxlength, const char[] defvalue=""); + + // Retrieves an integer value from a KeyValues key. + // + // @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. + public native int GetNum(const char[] key, int defvalue=0); + + // Retrieves a floating point value from a KeyValues key. + // + // @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. + public native float GetFloat(const char[] key, float defvalue=0.0); + + // Retrieves a set of color values from a KeyValues key. + // + // @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. + public native void GetColor(const char[] key, int &r, int &g, int &b, int &a); + + // Retrieves a set of color values from a KeyValues key. + // + // @param key Name of the key, or NULL_STRING. + // @param color Red, green, blue, and alpha channels. + public void GetColor4(const char[] key, int color[4]) { + int r, g, b, a; + this.GetColor(key, r, g, b, a); + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = a; + } + + // Retrieves a large integer value from a KeyValues key. + // + // @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. + public native void GetUInt64(const char[] key, int value[2], int defvalue[2]={0,0}); + + // Retrieves a vector value from a KeyValues key. + // + // @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. + public native void GetVector(const char[] 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 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. + public native bool JumpToKey(const char[] key, bool create=false); + + // Sets the current position in the KeyValues tree to the given key. + // + // @param id KeyValues id. + // @return True if the key exists, false if it does not. + public native bool JumpToKeySymbol(int id); + + // Sets the current position in the KeyValues tree to the first sub key. + // This native adds to the internal traversal stack. + // + // @param keyOnly If false, non-keys will be traversed (values). + // @return True on success, false if there was no first sub key. + public native bool GotoFirstSubKey(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 + // GoBack() is not needed for each successive call to this function. + // + // @param keyOnly If false, non-keys will be traversed (values). + // @return True on success, false if there was no next sub key. + public native bool GotoNextKey(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. + public native void SavePosition(); + + // 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. + // + // @return True on success, false if there is no higher node. + public native bool GoBack(); + + // Removes the given key from the current position. + // + // @param key Name of the key. + // @return True on success, false if key did not exist. + public native bool DeleteKey(const char[] 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. + public native int DeleteThis(); + + // 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. + public native void Rewind(); + + // Retrieves the current section name. + // + // @param section Buffer to store the section name. + // @param maxlength Maximum length of the name buffer. + // @return True on success, false on failure. + public native bool GetSectionName(char[] section, int maxlength); + + // Sets the current section name. + // + // @param section Section name. + public native void SetSectionName(const char[] section); + + // Returns the data type at a key. + // + // @param key Key name. + // @return KvDataType value of the key. + public native KvDataTypes GetDataType(const char[] key); + + // 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 useEscapes Whether or not to read escape sequences. + public native void SetEscapeSequences(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. + // + // @return Number of non-root nodes in the jump stack. + public native int NodesInStack(); + + // Finds a KeyValues name by id. + // + // @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. + public native bool FindKeyById(int id, char[] name, int maxlength); + + // Finds a KeyValues id inside a KeyValues tree. + // + // @param key Key name. + // @param id Id of the found KeyValue. + // @return True on success, false if key not found. + public native bool GetNameSymbol(const char[] key, int &id); + + // Retrieves the current section id. + // + // @param kv KeyValues Handle. + // @param id Id of the current section. + // @return True on success, false on failure. + public native bool GetSectionSymbol(int &id); +}; + +/** + * 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 KeyValues CreateKeyValues(const char[] name, const char[] firstKey="", const char[] 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. + * @error Invalid Handle. + */ +native void KvSetString(Handle kv, const char[] key, const char[] 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. + * @error Invalid Handle. + */ +native void KvSetNum(Handle kv, const char[] key, int 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) + * @error Invalid Handle. + */ +native void KvSetUInt64(Handle kv, const char[] key, const int 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. + * @error Invalid Handle. + */ +native void KvSetFloat(Handle kv, const char[] 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. + * @error Invalid Handle. + */ +native void KvSetColor(Handle kv, const char[] key, int r, int g, int b, int 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. + * @error Invalid Handle. + */ +native void KvSetVector(Handle kv, const char[] 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. + * @error Invalid Handle. + */ +native void KvGetString(Handle kv, const char[] key, char[] value, int maxlength, const char[] 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 int KvGetNum(Handle kv, const char[] key, int 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 char[] 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. + * @error Invalid Handle. + */ +native void KvGetColor(Handle kv, const char[] key, int &r, int &g, int &b, int &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. + * @error Invalid Handle. + */ +native void KvGetUInt64(Handle kv, const char[] key, int value[2], int 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. + * @error Invalid Handle. + */ +native void KvGetVector(Handle kv, const char[] 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 char[] 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, int 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. + * @error Invalid Handle. + */ +native void 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 char[] 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 int 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. + * @error Invalid Handle. + */ +native void 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, char[] section, int maxlength); + +/** + * Sets the current section name. + * + * @param kv KeyValues Handle. + * @param section Section name. + * @error Invalid Handle. + */ +native void KvSetSectionName(Handle kv, const char[] 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 char[] 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 char[] 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 char[] file); + +/** + * Converts a given string to a KeyValues tree. The string is read into + * the current postion of the tree. + * + * @param kv KeyValues Handle. + * @param buffer String buffer to load into the KeyValues. + * @param resourceName The resource name of the KeyValues, used for error tracking purposes. + * @return True on success, false otherwise. + * @error Invalid Handle. + */ +native bool StringToKeyValues(Handle kv, const char[] buffer, const char[] resourceName="StringToKeyValues"); + +/** + * 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. + * @error Invalid Handle. + */ +native void 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 int 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 Handle. + * @error Invalid Handle. + */ +native void 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, int id, char[] name, int 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 char[] key, int &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, int &id); diff --git a/source/sourcemod/scripting/include/lang.inc b/source/sourcemod/scripting/include/lang.inc new file mode 100644 index 0000000..440b795 --- /dev/null +++ b/source/sourcemod/scripting/include/lang.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 _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 file Translation file. + */ +native void LoadTranslations(const char[] 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. + */ +native void SetGlobalTransTarget(int client); + +/** + * Retrieves the language number of a client. + * + * @param client Client index. + * @return Language number client is using. + * @error Invalid client index or client not connected. + */ +native int GetClientLanguage(int client); + +/** + * Retrieves the server's language. + * + * @return Language number server is using. + */ +native int GetServerLanguage(); + +/** + * Returns the number of languages known in languages.cfg. + * + * @return Language count. + */ +native int 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. + * @error Invalid language number. + */ +native void GetLanguageInfo(int language, char[] code="", int codeLen=0, char[] name="", int nameLen=0); + +/** + * Sets the language number of a client. + * + * @param client Client index. + * @param language Language number. + * @error Invalid client index or client not connected. + */ +native void SetClientLanguage(int client, int language); + +/** + * Retrieves the language number from a language code. + * + * @param code Language code (2-3 characters usually). + * @return Language number. -1 if not found. + */ +native int GetLanguageByCode(const char[] code); + +/** + * Retrieves the language number from a language name. + * + * @param name Language name (case insensitive). + * @return Language number. -1 if not found. + */ +native int GetLanguageByName(const char[] name); + +/** + * Determines if the specified phrase exists within the plugin's + * translation cache. + * + * @param phrase Phrase to look for. + * @return True if phrase exists. + */ +native bool TranslationPhraseExists(const char[] phrase); + +/** + * Determines if there is a translation for the specified language. + * + * @param phrase Phrase to check. + * @param language Language number. + * @return True if translation exists. + */ +native bool IsTranslatedForLanguage(const char[] phrase, int language); diff --git a/source/sourcemod/scripting/include/logging.inc b/source/sourcemod/scripting/include/logging.inc new file mode 100644 index 0000000..2ab337c --- /dev/null +++ b/source/sourcemod/scripting/include/logging.inc @@ -0,0 +1,135 @@ +/** + * 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. + */ +native void LogMessage(const char[] 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. + * @error File could not be opened/written. + */ +native void LogToFile(const char[] file, const char[] 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. + * @error File could not be opened/written. + */ +native void LogToFileEx(const char[] file, const char[] 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. + */ +native void LogAction(int client, int target, const char[] message, any ...); + +/** + * Logs a plugin error message to the SourceMod logs. + * + * @param format String format. + * @param ... Format arguments. + */ +native void LogError(const char[] 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 perform the default logging behavior. + * 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, + int client, + int target, + const char[] 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. + */ +typedef GameLogHook = function Action (const char[] message); + +/** + * Adds a game log hook. + * + * @param hook Hook function. + */ +native void AddGameLogHook(GameLogHook hook); + +/** + * Removes a game log hook. + * + * @param hook Hook function. + */ +native void RemoveGameLogHook(GameLogHook hook); diff --git a/source/sourcemod/scripting/include/mapchooser.inc b/source/sourcemod/scripting/include/mapchooser.inc new file mode 100644 index 0000000..f95e464 --- /dev/null +++ b/source/sourcemod/scripting/include/mapchooser.inc @@ -0,0 +1,164 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2014 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 _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 specified 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 nominator. If the client disconnects the nomination will be removed. + * Use 0 for constant nominations + * @return Nominate Result of the outcome + */ +native NominateResult NominateMap(const char[] map, bool force, int owner); + +/** + * Attempt to remove a map from the mapchooser map list. + * + * @param map Map to remove. + * @return True if the nomination was found and removed, or false if the nomination was not found. + */ +native bool RemoveNominationByMap(const char[] map); + +/** + * Attempt to remove a map from the mapchooser map list. + * + * @param owner Client index of the nominator. + * @return True if the nomination was found and removed, or false if the nomination was not found. + */ +native bool RemoveNominationByOwner(int owner); + +/** + * Gets the current list of excluded maps. + * + * @param array An ADT array handle to add the map strings to. + */ +native void GetExcludeMapList(ArrayList array); + +/** + * Gets the current list of nominated maps. + * + * @param maparray An ADT array handle to add the map strings to. + * @param ownerarray An optional ADT array handle to add the nominator client indexes to. + */ +native void GetNominatedMapList(ArrayList maparray, ArrayList ownerarray = null); + +/** + * 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 void InitiateMapChooserVote(MapChange when, ArrayList inputarray=null); + +/** + * 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 void OnNominationRemoved(const char[] map, int owner); + +/** + * Called when mapchooser starts a Map Vote. + */ +forward void OnMapVoteStarted(); + +/* DO NOT EDIT BELOW THIS LINE */ + +public SharedPlugin __pl_mapchooser = +{ + name = "mapchooser", + file = "mapchooser.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_mapchooser_SetNTVOptional() +{ + MarkNativeAsOptional("NominateMap"); + MarkNativeAsOptional("RemoveNominationByMap"); + MarkNativeAsOptional("RemoveNominationByOwner"); + MarkNativeAsOptional("GetExcludeMapList"); + MarkNativeAsOptional("GetNominatedMapList"); + MarkNativeAsOptional("CanMapChooserStartVote"); + MarkNativeAsOptional("InitiateMapChooserVote"); + MarkNativeAsOptional("HasEndOfMapVoteFinished"); + MarkNativeAsOptional("EndOfMapVoteEnabled"); +} +#endif diff --git a/source/sourcemod/scripting/include/menus.inc b/source/sourcemod/scripting/include/menus.inc new file mode 100644 index 0000000..a10893c --- /dev/null +++ b/source/sourcemod/scripting/include/menus.inc @@ -0,0 +1,1154 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 view_as(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 MENUFLAG_BUTTON_NOVOTE (1<<3) /**< Menu has a "No Vote" button at slot 1 */ + +#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). + */ +typedef MenuHandler = function int (Menu menu, MenuAction action, int param1, int param2); + +// Panels are used for drawing raw menus without any extra helper functions. +// Handles must be closed via delete or CloseHandle(). +methodmap Panel < Handle +{ + // Constructor for a new Panel. + // + // @param hStyle MenuStyle Handle, or null to use the default style. + public native Panel(Handle hStyle = null); + + // Sets the panel's title. + // + // @param text Text to set as the title. + // @param onlyIfEmpty If true, the title will only be set if no title is set. + public native void SetTitle(const char[] text, bool onlyIfEmpty=false); + + // Draws an item on a panel. If the item takes up a slot, the position + // is returned. + // + // @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. + public native int DrawItem(const char[] text, int style=ITEMDRAW_DEFAULT); + + // Draws a raw line of text on a panel, without any markup other than a + // newline. + // + // @param text Display text to use. + // @return True on success, false if raw lines are not supported. + public native bool DrawText(const char[] text); + + // Returns whether or not the given drawing flags are supported by + // the menu style. + // + // @param style ITEMDRAW style flags. + // @return True if item is drawable, false otherwise. + public native bool CanDrawFlags(int 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. + public native bool SetKeys(int keys); + + // Sends a panel to a client. Unlike full menus, the handler + // function will only receive the following actions, both of + // which will have null 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 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. + public native bool Send(int client, MenuHandler handler, int time); + + // 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). + property int TextRemaining { + public native get(); + } + + // Returns or sets the current key position, starting at 1. This cannot be + // used to traverse backwards. + property int CurrentKey { + public native get(); + public native set(int key); + } + + // Returns the panel's style. Style handles are global and cannot be closed. + property Handle Style { + public native get(); + } +}; + +// A menu is a helper object for managing in-game menus. +methodmap Menu < Handle +{ + // 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. + public native Menu(MenuHandler handler, MenuAction actions=MENU_ACTIONS_DEFAULT); + + // Displays a menu to a client. + // + // @param client Client index. + // @param time Maximum time to leave menu on the screen. + // @return True on success, false on failure. + // @error Client not in game. + public native bool Display(int client, int time); + + // Displays a menu to a client, starting from the given item. + // + // @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 Client not in game. + /// + public native bool DisplayAt(int client, int first_item, int time); + + // Appends a new item to the end of a menu. + // + // @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 Item limit reached. + public native bool AddItem(const char[] info, const char[] display, int 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 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 menu position. + public native bool InsertItem(int position, const char[] info, + const char[] display, int style=ITEMDRAW_DEFAULT); + + // Removes an item from the menu. + // + // @param position Position, starting from 0. + // @return True on success, false on failure. + // @error Invalid menu position. + public native bool RemoveItem(int position); + + // Removes all items from a menu. + public native void RemoveAllItems(); + + // Retrieves information about a menu item. + // + // @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. + // @param client Client index. Must be specified if menu is per-client random shuffled, -1 to ignore. + // @return True on success, false if position is invalid. + public native bool GetItem(int position, char[] infoBuf, int infoBufLen, + int &style=0, char[] dispBuf="", int dispBufLen=0, int client=0); + + // Generates a per-client random mapping for the current vote options. + // + // @param start Menu item index to start randomizing from. + // @param stop Menu item index to stop randomizing at. -1 = infinite + public native void ShufflePerClient(int start=0, int stop=-1); + + // Fills the client vote option mapping with user supplied values. + // + // @param client Client index. + // @param array Integer array with mapping. + // @param length Length of array. + public native void SetClientMapping(int client, int[] array, int length); + + // Sets the menu's default title/instruction message. + // + // @param fmt Message string format + // @param ... Message string arguments. + public native void SetTitle(const char[] fmt, any ...); + + // Returns the text of a menu's title. + // + // @param buffer Buffer to store title. + // @param maxlength Maximum length of the buffer. + // @return Number of bytes written. + public native void GetTitle(char[] buffer, int maxlength); + + // Creates a raw MenuPanel based off the menu's style. + // The Handle must be freed with CloseHandle(). + // + // @return A new MenuPanel Handle. + public native Panel ToPanel(); + + // 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. + public native void Cancel(); + + // 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 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 A vote is already in progress. + public native bool DisplayVote(int[] clients, int numClients, int time, int flags=0); + + // Sends a vote menu to all clients. See VoteMenu() for more information. + // + // @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. + public bool DisplayVoteToAll(int time, int flags=0) { + int total = 0; + int[] players = new int[MaxClients]; + for (int i = 1; i <= MaxClients; i++) { + if (!IsClientInGame(i) || IsFakeClient(i)) + { + continue; + } + players[total++] = i; + } + return this.DisplayVote(players, total, time, flags); + } + + // Get or set the menu's pagination. + // + // If pagination 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. + property int Pagination { + public native get(); + public native set(int value); + } + + // Get or set the menu's option flags. + // + // If a certain bit is not supported, it will be stripped before being set. + property int OptionFlags { + public native get(); + public native set(int value); + } + + // Returns whether or not the menu has an exit button. By default, menus + // have an exit button. + property bool ExitButton { + public native get(); + public native set(bool value); + } + + // Controls 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. + property bool ExitBackButton { + public native get(); + public native set(bool value); + } + + // Sets whether or not the menu has a "no vote" button in slot 1. + // By default, menus do not have a no vote button. + property bool NoVoteButton { + public native set(bool value); + } + + // Sets an advanced vote handling callback. If this callback is set, + // MenuAction_VoteEnd will not be called. + property VoteHandler VoteResultCallback { + public native set(VoteHandler handler); + } + + // Returns the number of items in a menu. + property int ItemCount { + public native get(); + } + + // Returns the menu style. The Handle is global and cannot be closed. + property Handle Style { + public native get(); + } + + // Returns the first item on the page of a currently selected menu. + // + // This is only valid inside a MenuAction_Select callback. + property int Selection { + public native get(); + } +} + +/** + * 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 Menu 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, int client, int 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, int client, int first_item, int 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 bool AddMenuItem(Handle menu, + const char[] info, + const char[] display, + int 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, + int position, + const char[] info, + const char[] display, + int 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, int position); + +/** + * Removes all items from a menu. + * + * @param menu Menu Handle. + * @error Invalid Handle or menu position. + */ +native void 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. + * @param client Client index. Must be specified if menu is per-client random shuffled, -1 to ignore. + * @return True on success, false if position is invalid. + * @error Invalid Handle. + */ +native bool GetMenuItem(Handle menu, + int position, + char[] infoBuf, + int infoBufLen, + int &style=0, + char[] dispBuf="", + int dispBufLen=0, + int client=0); + +/** + * Generates a per-client random mapping for the current vote options. + * + * @param menu Menu Handle. + * @param start Menu item index to start randomizing from. + * @param stop Menu item index to stop randomizing at. -1 = infinite + */ +native void MenuShufflePerClient(Handle menu, int start=0, int stop=-1); + +/* + * Fills the client vote option mapping with user supplied values. + * + * @param menu Menu Handle. + * @param client Client index. + * @param array Integer array with mapping. + * @param length Length of array. + */ +native void MenuSetClientMapping(Handle menu, int client, int[] array, int length); + +/** + * 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 int GetMenuSelectionPosition(); + +/** + * Returns the number of items in a menu. + * + * @param menu Menu Handle. + * @return Number of items in the menu. + * @error Invalid Handle. + */ +native int 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, int itemsPerPage); + +/** + * Returns a menu's pagination setting. + * + * @param menu Handle to the menu. + * @return Pagination setting. + * @error Invalid Handle. + */ +native int 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. + * @error Invalid Handle. + */ +native void SetMenuTitle(Handle menu, const char[] 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 int GetMenuTitle(Handle menu, char[] buffer, int maxlength); + +/** + * Creates a raw MenuPanel based off the menu's style. + * The Handle must be freed with CloseHandle(). + * + * @param menu Menu Handle. + * @return A new MenuPanel Handle. + * @error Invalid Handle. + */ +native Panel 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 void SetMenuExitBackButton(Handle menu, bool button); + +/** + * Sets whether or not the menu has a "no vote" button in slot 1. + * By default, menus do not have a no vote button. + * + * @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 SetMenuNoVoteButton(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. + * @error Invalid Handle. + */ +native void CancelMenu(Handle menu); + +/** + * Retrieves a menu's option flags. + * + * @param menu Menu Handle. + * @return A bitstring of MENUFLAG bits. + * @error Invalid Handle. + */ +native int 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. + * @error Invalid Handle. + */ +native void SetMenuOptionFlags(Handle menu, int 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. + * + * @error If no vote is in progress. + */ +native void 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, int[] clients, int numClients, int time, int 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 bool VoteMenuToAll(Handle menu, int time, int flags=0) +{ + int total; + int[] players = new int[MaxClients]; + + for (int i=1; i<=MaxClients; i++) + { + if (!IsClientInGame(i) || IsFakeClient(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. + */ +typeset VoteHandler +{ + // old style + function void( + Menu menu, + int num_votes, + int num_clients, + const int client_info[][2], + int num_items, + const int item_info[][2] + ); + + // new style + function void( + Menu menu, + int num_votes, + int num_clients, + const int[][] client_info, + int num_items, + const int[][] item_info + ); +}; + +/** + * 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. + * @error Invalid Handle or callback. + */ +native void 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 int 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(int 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, int client is not in the voting pool, + * or client index is invalid. + */ +native bool RedrawClientVoteMenu(int 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 Panel CreatePanel(Handle hStyle=INVALID_HANDLE); + +/** + * Creates a Menu from a MenuStyle. The Handle must be closed with + * CloseHandle(). + * + * @param 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 Menu 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 null. + */ +native MenuSource GetClientMenu(int client, Handle hStyle=null); + +/** + * Cancels a menu on a client. This will only affect non-external menus. + * + * @param client Client index. + * @param autoIgnore If true, no menus can be re-drawn on the client during + * the cancellation process. + * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style. + * @return True if a menu was cancelled, false otherwise. + */ +native bool CancelClientMenu(int 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 int 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 text Text to set as the title. + * @param onlyIfEmpty If true, the title will only be set if no title is set. + * @error Invalid Handle. + */ +native void SetPanelTitle(Handle panel, const char[] 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 int DrawPanelItem(Handle panel, const char[] text, int 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 bool DrawPanelText(Handle panel, const char[] 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 bool CanPanelDrawFlags(Handle panel, int style); + +/** + * Sets the selectable key map of a panel. This is not supported by + * all styles (only by Radio, as of this writing). + * + * @param panel A MenuPanel Handle. + * @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, int 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, int client, MenuHandler handler, int 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 int 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 int 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, int 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 int RedrawMenuItem(const char[] 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(int client, const char[] str, int time, int keys=-1, MenuHandler handler=INVALID_FUNCTION); + +/** + * 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. + */ +stock void GetMenuVoteInfo(int param2, int &winningVotes, int &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/source/sourcemod/scripting/include/morecolors.inc b/source/sourcemod/scripting/include/morecolors.inc new file mode 100644 index 0000000..3a416d8 --- /dev/null +++ b/source/sourcemod/scripting/include/morecolors.inc @@ -0,0 +1,674 @@ +// MOAR COLORS +// By Dr. McKay +// Inspired by: https://forums.alliedmods.net/showthread.php?t=96831 + +#if defined _colors_included + #endinput +#endif +#define _colors_included + +#include + +#define MORE_COLORS_VERSION "1.9.1" +#define MAX_MESSAGE_LENGTH 256 +#define MAX_BUFFER_LENGTH (MAX_MESSAGE_LENGTH * 4) + +#define COLOR_RED 0xFF4040 +#define COLOR_BLUE 0x99CCFF +#define COLOR_GRAY 0xCCCCCC +#define COLOR_GREEN 0x3EFF3E + +#define GAME_DODS 0 + +new bool:CSkipList[MAXPLAYERS + 1]; +new Handle:CTrie; +new CTeamColors[][] = {{0xCCCCCC, 0x4D7942, 0xFF4040}}; // Multi-dimensional array for games that don't support SayText2. First index is the game index (as defined by the GAME_ defines), second index is team. 0 = spectator, 1 = team1, 2 = team2 + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param message Message (formatting rules). + * @noreturn + * + * On error/Errors: If the client is not connected an error will be thrown. + */ +stock CPrintToChat(client, const String:message[], any:...) { + CCheckTrie(); + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + if(!IsClientInGame(client)) { + ThrowError("Client %i is not in game", client); + } + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 3); + CReplaceColorCodes(buffer2); + CSendMessage(client, buffer2); +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param message Message (formatting rules). + * @noreturn + */ +stock CPrintToChatAll(const String:message[], any:...) { + CCheckTrie(); + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + for(new i = 1; i <= MaxClients; i++) { + if(!IsClientInGame(i) || CSkipList[i]) { + CSkipList[i] = false; + continue; + } + SetGlobalTransTarget(i); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 2); + CReplaceColorCodes(buffer2); + CSendMessage(i, buffer2); + } +} + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags and teamcolor tag. + * + * @param client Client index. + * @param author Author index whose color will be used for teamcolor tag. + * @param message Message (formatting rules). + * @noreturn + * + * On error/Errors: If the client or author are not connected an error will be thrown + */ +stock CPrintToChatEx(client, author, const String:message[], any:...) { + CCheckTrie(); + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + if(!IsClientInGame(client)) { + ThrowError("Client %i is not in game", client); + } + if(author <= 0 || author > MaxClients) { + ThrowError("Invalid client index %i", author); + } + if(!IsClientInGame(author)) { + ThrowError("Client %i is not in game", author); + } + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 4); + CReplaceColorCodes(buffer2, author); + CSendMessage(client, buffer2, author); +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags and teamcolor tag. + * + * @param author Author index whose color will be used for teamcolor tag. + * @param message Message (formatting rules). + * @noreturn + * + * On error/Errors: If the author is not connected an error will be thrown. + */ +stock CPrintToChatAllEx(author, const String:message[], any:...) { + CCheckTrie(); + if(author <= 0 || author > MaxClients) { + ThrowError("Invalid client index %i", author); + } + if(!IsClientInGame(author)) { + ThrowError("Client %i is not in game", author); + } + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + for(new i = 1; i <= MaxClients; i++) { + if(!IsClientInGame(i) || CSkipList[i]) { + CSkipList[i] = false; + continue; + } + SetGlobalTransTarget(i); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 3); + CReplaceColorCodes(buffer2, author); + CSendMessage(i, buffer2, author); + } +} + +/** + * Sends a SayText2 usermessage + * + * @param client Client to send usermessage to + * @param message Message to send + * @noreturn + */ +stock CSendMessage(client, const String:message[], author=0) { + if(author == 0) { + author = client; + } + decl String:buffer[MAX_MESSAGE_LENGTH], String:game[16]; + GetGameFolderName(game, sizeof(game)); + strcopy(buffer, sizeof(buffer), message); + new UserMsg:index = GetUserMessageId("SayText2"); + if(index == INVALID_MESSAGE_ID) { + if(StrEqual(game, "dod")) { + new team = GetClientTeam(author); + if(team == 0) { + ReplaceString(buffer, sizeof(buffer), "\x03", "\x04", false); // Unassigned gets green + } else { + decl String:temp[16]; + Format(temp, sizeof(temp), "\x07%06X", CTeamColors[GAME_DODS][team - 1]); + ReplaceString(buffer, sizeof(buffer), "\x03", temp, false); + } + } + PrintToChat(client, "%s", buffer); + return; + } + new Handle:buf = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); + if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) { + PbSetInt(buf, "ent_idx", author); + PbSetBool(buf, "chat", true); + PbSetString(buf, "msg_name", buffer); + PbAddString(buf, "params", ""); + PbAddString(buf, "params", ""); + PbAddString(buf, "params", ""); + PbAddString(buf, "params", ""); + } else { + BfWriteByte(buf, author); // Message author + BfWriteByte(buf, true); // Chat message + BfWriteString(buf, buffer); // Message text + } + EndMessage(); +} + +/** + * This function should only be used right in front of + * CPrintToChatAll or CPrintToChatAllEx. It causes those functions + * to skip the specified client when printing the message. + * After printing the message, the client will no longer be skipped. + * + * @param client Client index + * @noreturn + */ +stock CSkipNextClient(client) { + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + CSkipList[client] = true; +} + +/** + * Checks if the colors trie is initialized and initializes it if it's not (used internally) + * + * @return No return + */ +stock CCheckTrie() { + if(CTrie == INVALID_HANDLE) { + CTrie = InitColorTrie(); + } +} + +/** + * Replaces color tags in a string with color codes (used internally by CPrintToChat, CPrintToChatAll, CPrintToChatEx, and CPrintToChatAllEx + * + * @param buffer String. + * @param author Optional client index to use for {teamcolor} tags, or 0 for none + * @param removeTags Optional boolean value to determine whether we're replacing tags with colors, or just removing tags, used by CRemoveTags + * @param maxlen Optional value for max buffer length, used by CRemoveTags + * @noreturn + * + * On error/Errors: If the client index passed for author is invalid or not in game. + */ +stock CReplaceColorCodes(String:buffer[], author=0, bool:removeTags=false, maxlen=MAX_BUFFER_LENGTH) { + CCheckTrie(); + if(!removeTags) { + ReplaceString(buffer, maxlen, "{default}", "\x01", false); + } else { + ReplaceString(buffer, maxlen, "{default}", "", false); + ReplaceString(buffer, maxlen, "{teamcolor}", "", false); + } + if(author != 0 && !removeTags) { + if(author < 0 || author > MaxClients) { + ThrowError("Invalid client index %i", author); + } + if(!IsClientInGame(author)) { + ThrowError("Client %i is not in game", author); + } + ReplaceString(buffer, maxlen, "{teamcolor}", "\x03", false); + } + new cursor = 0; + new value; + decl String:tag[32], String:buff[32], String:output[maxlen]; + strcopy(output, maxlen, buffer); + // Since the string's size is going to be changing, output will hold the replaced string and we'll search buffer + + new Handle:regex = CompileRegex("{[a-zA-Z0-9]+}"); + for(new i = 0; i < 1000; i++) { // The RegEx extension is quite flaky, so we have to loop here :/. This loop is supposed to be infinite and broken by return, but conditions have been added to be safe. + if(MatchRegex(regex, buffer[cursor]) < 1) { + CloseHandle(regex); + strcopy(buffer, maxlen, output); + return; + } + GetRegexSubString(regex, 0, tag, sizeof(tag)); + CStrToLower(tag); + cursor = StrContains(buffer[cursor], tag, false) + cursor + 1; + strcopy(buff, sizeof(buff), tag); + ReplaceString(buff, sizeof(buff), "{", ""); + ReplaceString(buff, sizeof(buff), "}", ""); + + if(!GetTrieValue(CTrie, buff, value)) { + continue; + } + + if(removeTags) { + ReplaceString(output, maxlen, tag, "", false); + } else { + Format(buff, sizeof(buff), "\x07%06X", value); + ReplaceString(output, maxlen, tag, buff, false); + } + } + LogError("[MORE COLORS] Infinite loop broken."); +} + +/** + * Gets a part of a string + * + * @param input String to get the part from + * @param output Buffer to write to + * @param maxlen Max length of output buffer + * @param start Position to start at + * @param numChars Number of characters to return, or 0 for the end of the string + * @noreturn + */ +stock CSubString(const String:input[], String:output[], maxlen, start, numChars=0) { + new i = 0; + for(;;) { + if(i == maxlen - 1 || i >= numChars || input[start + i] == '\0') { + output[i] = '\0'; + return; + } + output[i] = input[start + i]; + i++; + } +} + +/** + * Converts a string to lowercase + * + * @param buffer String to convert + * @noreturn + */ +stock CStrToLower(String:buffer[]) { + new len = strlen(buffer); + for(new i = 0; i < len; i++) { + buffer[i] = CharToLower(buffer[i]); + } +} + +/** + * Adds a color to the colors trie + * + * @param name Color name, without braces + * @param color Hexadecimal representation of the color (0xRRGGBB) + * @return True if color was added successfully, false if a color already exists with that name + */ +stock bool:CAddColor(const String:name[], color) { + CCheckTrie(); + new value; + if(GetTrieValue(CTrie, name, value)) { + return false; + } + decl String:newName[64]; + strcopy(newName, sizeof(newName), name); + CStrToLower(newName); + SetTrieValue(CTrie, newName, color); + return true; +} + +/** + * Removes color tags from a message + * + * @param message Message to remove tags from + * @param maxlen Maximum buffer length + * @noreturn + */ +stock CRemoveTags(String:message[], maxlen) { + CReplaceColorCodes(message, 0, true, maxlen); +} + +/** + * Replies to a command with colors + * + * @param client Client to reply to + * @param message Message (formatting rules) + * @noreturn + */ +stock CReplyToCommand(client, const String:message[], any:...) { + decl String:buffer[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 3); + if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { + CRemoveTags(buffer, sizeof(buffer)); + PrintToConsole(client, "%s", buffer); + } else { + CPrintToChat(client, "%s", buffer); + } +} + +/** + * Replies to a command with colors + * + * @param client Client to reply to + * @param author Client to use for {teamcolor} + * @param message Message (formatting rules) + * @noreturn + */ +stock CReplyToCommandEx(client, author, const String:message[], any:...) { + decl String:buffer[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 4); + if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { + CRemoveTags(buffer, sizeof(buffer)); + PrintToConsole(client, "%s", buffer); + } else { + CPrintToChatEx(client, author, "%s", buffer); + } +} + +/** + * Shows admin activity with colors + * + * @param client Client performing an action + * @param message Message (formatting rules) + * @noreturn + */ +stock CShowActivity(client, const String:message[], any:...) { + CCheckTrie(); + if(client < 0 || client > MaxClients) { + ThrowError("Invalid client index %d", client); + } + if(client != 0 && !IsClientInGame(client)) { + ThrowError("Client %d is not in game", client); + } + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 3); + CReplaceColorCodes(buffer2); + ShowActivity(client, "%s", buffer2); +} + +/** + * Shows admin activity with colors + * + * @param client Client performing an action + * @param tag Tag to prepend to the message (color tags supported) + * @param message Message (formatting rules) + * @noreturn + */ +stock CShowActivityEx(client, const String:tag[], const String:message[], any:...) { + CCheckTrie(); + if(client < 0 || client > MaxClients) { + ThrowError("Invalid client index %d", client); + } + if(client != 0 && !IsClientInGame(client)) { + ThrowError("Client %d is not in game", client); + } + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 4); + CReplaceColorCodes(buffer2); + strcopy(buffer, sizeof(buffer), tag); + CReplaceColorCodes(buffer); + ShowActivityEx(client, tag, "%s", buffer2); +} + +/** + * Shows admin activity with colors + * + * @param client Client performing an action + * @param tag Tag to prepend to the message (color tags supported) + * @param message Message (formatting rules) + * @noreturn + */ +stock CShowActivity2(client, const String:tag[], const String:message[], any:...) { + CCheckTrie(); + if(client < 0 || client > MaxClients) { + ThrowError("Invalid client index %d", client); + } + if(client != 0 && !IsClientInGame(client)) { + ThrowError("Client %d is not in game", client); + } + decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH]; + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 4); + CReplaceColorCodes(buffer2); + strcopy(buffer, sizeof(buffer), tag); + CReplaceColorCodes(buffer); + ShowActivity2(client, buffer, "%s", buffer2); +} + +/** + * Determines whether a color name exists + * + * @param color The color name to check + * @return True if the color exists, false otherwise + */ +stock bool:CColorExists(const String:color[]) { + CCheckTrie(); + new temp; + return GetTrieValue(CTrie, color, temp); +} + +/** + * Returns the hexadecimal representation of a client's team color (will NOT initialize the trie) + * + * @param client Client to get the team color for + * @return Client's team color in hexadecimal, or green if unknown + * On error/Errors: If the client index passed is invalid or not in game. + */ +stock CGetTeamColor(client) { + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + if(!IsClientInGame(client)) { + ThrowError("Client %i is not in game", client); + } + new value; + switch(GetClientTeam(client)) { + case 1: { + value = COLOR_GRAY; + } + case 2: { + value = COLOR_RED; + } + case 3: { + value = COLOR_BLUE; + } + default: { + value = COLOR_GREEN; + } + } + return value; +} + +stock Handle:InitColorTrie() { + new Handle:hTrie = CreateTrie(); + SetTrieValue(hTrie, "aliceblue", 0xF0F8FF); + SetTrieValue(hTrie, "allies", 0x4D7942); // same as Allies team in DoD:S + SetTrieValue(hTrie, "ancient", 0xEB4B4B); // same as Ancient item rarity in Dota 2 + SetTrieValue(hTrie, "antiquewhite", 0xFAEBD7); + SetTrieValue(hTrie, "aqua", 0x00FFFF); + SetTrieValue(hTrie, "aquamarine", 0x7FFFD4); + SetTrieValue(hTrie, "arcana", 0xADE55C); // same as Arcana item rarity in Dota 2 + SetTrieValue(hTrie, "axis", 0xFF4040); // same as Axis team in DoD:S + SetTrieValue(hTrie, "azure", 0x007FFF); + SetTrieValue(hTrie, "beige", 0xF5F5DC); + SetTrieValue(hTrie, "bisque", 0xFFE4C4); + SetTrieValue(hTrie, "black", 0x000000); + SetTrieValue(hTrie, "blanchedalmond", 0xFFEBCD); + SetTrieValue(hTrie, "blue", 0x99CCFF); // same as BLU/Counter-Terrorist team color + SetTrieValue(hTrie, "blueviolet", 0x8A2BE2); + SetTrieValue(hTrie, "brown", 0xA52A2A); + SetTrieValue(hTrie, "burlywood", 0xDEB887); + SetTrieValue(hTrie, "cadetblue", 0x5F9EA0); + SetTrieValue(hTrie, "chartreuse", 0x7FFF00); + SetTrieValue(hTrie, "chocolate", 0xD2691E); + SetTrieValue(hTrie, "collectors", 0xAA0000); // same as Collector's item quality in TF2 + SetTrieValue(hTrie, "common", 0xB0C3D9); // same as Common item rarity in Dota 2 + SetTrieValue(hTrie, "community", 0x70B04A); // same as Community item quality in TF2 + SetTrieValue(hTrie, "coral", 0xFF7F50); + SetTrieValue(hTrie, "cornflowerblue", 0x6495ED); + SetTrieValue(hTrie, "cornsilk", 0xFFF8DC); + SetTrieValue(hTrie, "corrupted", 0xA32C2E); // same as Corrupted item quality in Dota 2 + SetTrieValue(hTrie, "crimson", 0xDC143C); + SetTrieValue(hTrie, "cyan", 0x00FFFF); + SetTrieValue(hTrie, "darkblue", 0x00008B); + SetTrieValue(hTrie, "darkcyan", 0x008B8B); + SetTrieValue(hTrie, "darkgoldenrod", 0xB8860B); + SetTrieValue(hTrie, "darkgray", 0xA9A9A9); + SetTrieValue(hTrie, "darkgrey", 0xA9A9A9); + SetTrieValue(hTrie, "darkgreen", 0x006400); + SetTrieValue(hTrie, "darkkhaki", 0xBDB76B); + SetTrieValue(hTrie, "darkmagenta", 0x8B008B); + SetTrieValue(hTrie, "darkolivegreen", 0x556B2F); + SetTrieValue(hTrie, "darkorange", 0xFF8C00); + SetTrieValue(hTrie, "darkorchid", 0x9932CC); + SetTrieValue(hTrie, "darkred", 0x8B0000); + SetTrieValue(hTrie, "darksalmon", 0xE9967A); + SetTrieValue(hTrie, "darkseagreen", 0x8FBC8F); + SetTrieValue(hTrie, "darkslateblue", 0x483D8B); + SetTrieValue(hTrie, "darkslategray", 0x2F4F4F); + SetTrieValue(hTrie, "darkslategrey", 0x2F4F4F); + SetTrieValue(hTrie, "darkturquoise", 0x00CED1); + SetTrieValue(hTrie, "darkviolet", 0x9400D3); + SetTrieValue(hTrie, "deeppink", 0xFF1493); + SetTrieValue(hTrie, "deepskyblue", 0x00BFFF); + SetTrieValue(hTrie, "dimgray", 0x696969); + SetTrieValue(hTrie, "dimgrey", 0x696969); + SetTrieValue(hTrie, "dodgerblue", 0x1E90FF); + SetTrieValue(hTrie, "exalted", 0xCCCCCD); // same as Exalted item quality in Dota 2 + SetTrieValue(hTrie, "firebrick", 0xB22222); + SetTrieValue(hTrie, "floralwhite", 0xFFFAF0); + SetTrieValue(hTrie, "forestgreen", 0x228B22); + SetTrieValue(hTrie, "frozen", 0x4983B3); // same as Frozen item quality in Dota 2 + SetTrieValue(hTrie, "fuchsia", 0xFF00FF); + SetTrieValue(hTrie, "fullblue", 0x0000FF); + SetTrieValue(hTrie, "fullred", 0xFF0000); + SetTrieValue(hTrie, "gainsboro", 0xDCDCDC); + SetTrieValue(hTrie, "genuine", 0x4D7455); // same as Genuine item quality in TF2 + SetTrieValue(hTrie, "ghostwhite", 0xF8F8FF); + SetTrieValue(hTrie, "gold", 0xFFD700); + SetTrieValue(hTrie, "goldenrod", 0xDAA520); + SetTrieValue(hTrie, "gray", 0xCCCCCC); // same as spectator team color + SetTrieValue(hTrie, "grey", 0xCCCCCC); + SetTrieValue(hTrie, "green", 0x3EFF3E); + SetTrieValue(hTrie, "greenyellow", 0xADFF2F); + SetTrieValue(hTrie, "haunted", 0x38F3AB); // same as Haunted item quality in TF2 + SetTrieValue(hTrie, "honeydew", 0xF0FFF0); + SetTrieValue(hTrie, "hotpink", 0xFF69B4); + SetTrieValue(hTrie, "immortal", 0xE4AE33); // same as Immortal item rarity in Dota 2 + SetTrieValue(hTrie, "indianred", 0xCD5C5C); + SetTrieValue(hTrie, "indigo", 0x4B0082); + SetTrieValue(hTrie, "ivory", 0xFFFFF0); + SetTrieValue(hTrie, "khaki", 0xF0E68C); + SetTrieValue(hTrie, "lavender", 0xE6E6FA); + SetTrieValue(hTrie, "lavenderblush", 0xFFF0F5); + SetTrieValue(hTrie, "lawngreen", 0x7CFC00); + SetTrieValue(hTrie, "legendary", 0xD32CE6); // same as Legendary item rarity in Dota 2 + SetTrieValue(hTrie, "lemonchiffon", 0xFFFACD); + SetTrieValue(hTrie, "lightblue", 0xADD8E6); + SetTrieValue(hTrie, "lightcoral", 0xF08080); + SetTrieValue(hTrie, "lightcyan", 0xE0FFFF); + SetTrieValue(hTrie, "lightgoldenrodyellow", 0xFAFAD2); + SetTrieValue(hTrie, "lightgray", 0xD3D3D3); + SetTrieValue(hTrie, "lightgrey", 0xD3D3D3); + SetTrieValue(hTrie, "lightgreen", 0x99FF99); + SetTrieValue(hTrie, "lightpink", 0xFFB6C1); + SetTrieValue(hTrie, "lightsalmon", 0xFFA07A); + SetTrieValue(hTrie, "lightseagreen", 0x20B2AA); + SetTrieValue(hTrie, "lightskyblue", 0x87CEFA); + SetTrieValue(hTrie, "lightslategray", 0x778899); + SetTrieValue(hTrie, "lightslategrey", 0x778899); + SetTrieValue(hTrie, "lightsteelblue", 0xB0C4DE); + SetTrieValue(hTrie, "lightyellow", 0xFFFFE0); + SetTrieValue(hTrie, "lime", 0x00FF00); + SetTrieValue(hTrie, "limegreen", 0x32CD32); + SetTrieValue(hTrie, "linen", 0xFAF0E6); + SetTrieValue(hTrie, "magenta", 0xFF00FF); + SetTrieValue(hTrie, "maroon", 0x800000); + SetTrieValue(hTrie, "mediumaquamarine", 0x66CDAA); + SetTrieValue(hTrie, "mediumblue", 0x0000CD); + SetTrieValue(hTrie, "mediumorchid", 0xBA55D3); + SetTrieValue(hTrie, "mediumpurple", 0x9370D8); + SetTrieValue(hTrie, "mediumseagreen", 0x3CB371); + SetTrieValue(hTrie, "mediumslateblue", 0x7B68EE); + SetTrieValue(hTrie, "mediumspringgreen", 0x00FA9A); + SetTrieValue(hTrie, "mediumturquoise", 0x48D1CC); + SetTrieValue(hTrie, "mediumvioletred", 0xC71585); + SetTrieValue(hTrie, "midnightblue", 0x191970); + SetTrieValue(hTrie, "mintcream", 0xF5FFFA); + SetTrieValue(hTrie, "mistyrose", 0xFFE4E1); + SetTrieValue(hTrie, "moccasin", 0xFFE4B5); + SetTrieValue(hTrie, "mythical", 0x8847FF); // same as Mythical item rarity in Dota 2 + SetTrieValue(hTrie, "navajowhite", 0xFFDEAD); + SetTrieValue(hTrie, "navy", 0x000080); + SetTrieValue(hTrie, "normal", 0xB2B2B2); // same as Normal item quality in TF2 + SetTrieValue(hTrie, "oldlace", 0xFDF5E6); + SetTrieValue(hTrie, "olive", 0x9EC34F); + SetTrieValue(hTrie, "olivedrab", 0x6B8E23); + SetTrieValue(hTrie, "orange", 0xFFA500); + SetTrieValue(hTrie, "orangered", 0xFF4500); + SetTrieValue(hTrie, "orchid", 0xDA70D6); + SetTrieValue(hTrie, "palegoldenrod", 0xEEE8AA); + SetTrieValue(hTrie, "palegreen", 0x98FB98); + SetTrieValue(hTrie, "paleturquoise", 0xAFEEEE); + SetTrieValue(hTrie, "palevioletred", 0xD87093); + SetTrieValue(hTrie, "papayawhip", 0xFFEFD5); + SetTrieValue(hTrie, "peachpuff", 0xFFDAB9); + SetTrieValue(hTrie, "peru", 0xCD853F); + SetTrieValue(hTrie, "pink", 0xFFC0CB); + SetTrieValue(hTrie, "plum", 0xDDA0DD); + SetTrieValue(hTrie, "powderblue", 0xB0E0E6); + SetTrieValue(hTrie, "purple", 0x800080); + SetTrieValue(hTrie, "rare", 0x4B69FF); // same as Rare item rarity in Dota 2 + SetTrieValue(hTrie, "red", 0xFF4040); // same as RED/Terrorist team color + SetTrieValue(hTrie, "rosybrown", 0xBC8F8F); + SetTrieValue(hTrie, "royalblue", 0x4169E1); + SetTrieValue(hTrie, "saddlebrown", 0x8B4513); + SetTrieValue(hTrie, "salmon", 0xFA8072); + SetTrieValue(hTrie, "sandybrown", 0xF4A460); + SetTrieValue(hTrie, "seagreen", 0x2E8B57); + SetTrieValue(hTrie, "seashell", 0xFFF5EE); + SetTrieValue(hTrie, "selfmade", 0x70B04A); // same as Self-Made item quality in TF2 + SetTrieValue(hTrie, "sienna", 0xA0522D); + SetTrieValue(hTrie, "silver", 0xC0C0C0); + SetTrieValue(hTrie, "skyblue", 0x87CEEB); + SetTrieValue(hTrie, "slateblue", 0x6A5ACD); + SetTrieValue(hTrie, "slategray", 0x708090); + SetTrieValue(hTrie, "slategrey", 0x708090); + SetTrieValue(hTrie, "snow", 0xFFFAFA); + SetTrieValue(hTrie, "springgreen", 0x00FF7F); + SetTrieValue(hTrie, "steelblue", 0x4682B4); + SetTrieValue(hTrie, "strange", 0xCF6A32); // same as Strange item quality in TF2 + SetTrieValue(hTrie, "tan", 0xD2B48C); + SetTrieValue(hTrie, "teal", 0x008080); + SetTrieValue(hTrie, "thistle", 0xD8BFD8); + SetTrieValue(hTrie, "tomato", 0xFF6347); + SetTrieValue(hTrie, "turquoise", 0x40E0D0); + SetTrieValue(hTrie, "uncommon", 0xB0C3D9); // same as Uncommon item rarity in Dota 2 + SetTrieValue(hTrie, "unique", 0xFFD700); // same as Unique item quality in TF2 + SetTrieValue(hTrie, "unusual", 0x8650AC); // same as Unusual item quality in TF2 + SetTrieValue(hTrie, "valve", 0xA50F79); // same as Valve item quality in TF2 + SetTrieValue(hTrie, "vintage", 0x476291); // same as Vintage item quality in TF2 + SetTrieValue(hTrie, "violet", 0xEE82EE); + SetTrieValue(hTrie, "wheat", 0xF5DEB3); + SetTrieValue(hTrie, "white", 0xFFFFFF); + SetTrieValue(hTrie, "whitesmoke", 0xF5F5F5); + SetTrieValue(hTrie, "yellow", 0xFFFF00); + SetTrieValue(hTrie, "yellowgreen", 0x9ACD32); + return hTrie; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/movement.inc b/source/sourcemod/scripting/include/movement.inc new file mode 100644 index 0000000..7cc5b29 --- /dev/null +++ b/source/sourcemod/scripting/include/movement.inc @@ -0,0 +1,530 @@ +/* + MovementAPI Function Stock Library + + Website: https://github.com/danzayau/MovementAPI +*/ + +#if defined _movement_included_ + #endinput +#endif +#define _movement_included_ + +#include + + + +// =====[ STOCKS ]===== + +/** + * Calculates the horizontal distance between two vectors. + * + * @param vec1 First vector. + * @param vec2 Second vector. + * @return Vector horizontal distance. + */ +stock float GetVectorHorizontalDistance(const float vec1[3], const float vec2[3]) +{ + return SquareRoot(Pow(vec2[0] - vec1[0], 2.0) + Pow(vec2[1] - vec1[1], 2.0)); +} + +/** + * Calculates a vector's horizontal length. + * + * @param vec Vector. + * @return Vector horizontal length (magnitude). + */ +stock float GetVectorHorizontalLength(const float vec[3]) +{ + return SquareRoot(Pow(vec[0], 2.0) + Pow(vec[1], 2.0)); +} + +/** + * Scales a vector to a certain horizontal length. + * + * @param vec Vector. + * @param length New horizontal length. + */ +stock void SetVectorHorizontalLength(float vec[3], float length) +{ + float newVec[3]; + newVec = vec; + newVec[2] = 0.0; + NormalizeVector(newVec, newVec); + ScaleVector(newVec, length); + newVec[2] = vec[2]; + vec = newVec; +} + +/** + * Gets a player's currently pressed buttons. + * + * @param client Client index. + * @return Bitsum of buttons. + */ +stock int Movement_GetButtons(int client) +{ + return GetClientButtons(client); +} + +/** + * Gets a player's origin. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void Movement_GetOrigin(int client, float result[3]) +{ + GetClientAbsOrigin(client, result); +} + +/** + * Gets a player's origin. + * If the player is on the ground, a trace hull is used to find the + * exact height of the ground the player is standing on. This is thus + * more accurate than Movement_GetOrigin when player is on ground. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void Movement_GetOriginEx(int client, float result[3]) +{ + if (!Movement_GetOnGround(client)) + { + GetClientAbsOrigin(client, result); + return; + } + + // Get the coordinate of the solid beneath the player's origin + // More accurate than GetClientAbsOrigin when on ground + float startPosition[3], endPosition[3]; + GetClientAbsOrigin(client, startPosition); + endPosition = startPosition; + endPosition[2] = startPosition[2] - 2.0; // Should be less than 2.0 units away + Handle trace = TR_TraceHullFilterEx( + startPosition, + endPosition, + view_as( { -16.0, -16.0, 0.0 } ), // Players are 32 x 32 x 72 + view_as( { 16.0, 16.0, 72.0 } ), + MASK_PLAYERSOLID, + TraceEntityFilterPlayers, + client); + if (TR_DidHit(trace)) + { + TR_GetEndPosition(result, trace); + // Do not get rid of the offset. The offset is correct, as the player must be + // at least 0.03125 units away from the ground. + } + else + { + result = startPosition; // Fallback to GetClientAbsOrigin + } + delete trace; +} + +public bool TraceEntityFilterPlayers(int entity, int contentsMask) +{ + return entity > MaxClients; +} + +/** + * Sets a player's origin by teleporting them. + * + * @param client Client index. + * @param origin New origin. + */ +stock void Movement_SetOrigin(int client, const float origin[3]) +{ + TeleportEntity(client, origin, NULL_VECTOR, NULL_VECTOR); +} + +/** + * Gets a player's velocity. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void Movement_GetVelocity(int client, float result[3]) +{ + GetEntPropVector(client, Prop_Data, "m_vecVelocity", result); +} + +/** + * Sets a player's velocity by teleporting them. + * + * @param client Client index. + * @param velocity New velocity. + */ +stock void Movement_SetVelocity(int client, const float velocity[3]) +{ + TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, velocity); +} + +/** + * Gets a player's horizontal speed. + * + * @param client Client index. + * @return Player's horizontal speed. + */ +stock float Movement_GetSpeed(int client) +{ + float velocity[3]; + Movement_GetVelocity(client, velocity); + return GetVectorHorizontalLength(velocity); +} + +/** + * Sets a player's horizontal speed. + * + * @param client Client index. + * @param value New horizontal speed. + * @param applyBaseVel Whether to apply base velocity as well. + */ +stock void Movement_SetSpeed(int client, float value, bool applyBaseVel = false) +{ + float velocity[3]; + Movement_GetVelocity(client, velocity); + SetVectorHorizontalLength(velocity, value) + if (applyBaseVel) + { + float baseVelocity[3]; + Movement_GetBaseVelocity(client, baseVelocity); + AddVectors(velocity, baseVelocity, velocity); + } + Movement_SetVelocity(client, velocity); +} + +/** + * Gets a player's vertical velocity. + * + * @param client Client index. + * @return Player's vertical velocity. + */ +stock float Movement_GetVerticalVelocity(int client) +{ + float velocity[3]; + Movement_GetVelocity(client, velocity); + return velocity[2]; +} + +/** + * Sets a player's vertical velocity. + * + * @param client Client index. + * @param value New vertical velocity. + */ +stock void Movement_SetVerticalVelocity(int client, float value) +{ + float velocity[3]; + Movement_GetVelocity(client, velocity); + velocity[2] = value; + Movement_SetVelocity(client, velocity); +} + +/** + * Gets a player's base velocity. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void Movement_GetBaseVelocity(int client, float result[3]) +{ + GetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", result); +} + +/** + * Sets a player's base velocity. + * + * @param client Client index. + * @param baseVelocity New base velocity. + */ +stock void Movement_SetBaseVelocity(int client, const float baseVelocity[3]) +{ + SetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", baseVelocity); +} + +/** + * Gets a player's eye angles. + * + * @param client Client index. + * @param result Resultant vector. + */ +stock void Movement_GetEyeAngles(int client, float result[3]) +{ + GetClientEyeAngles(client, result); +} + +/** + * Sets a player's eye angles by teleporting them. + * + * @param client Client index. + * @param eyeAngles New eye angles. + */ +stock void Movement_SetEyeAngles(int client, const float eyeAngles[3]) +{ + TeleportEntity(client, NULL_VECTOR, eyeAngles, NULL_VECTOR); +} + +/** + * Gets whether a player is on the ground. + * + * @param client Client index. + * @return Whether player is on the ground. + */ +stock bool Movement_GetOnGround(int client) +{ + return view_as(GetEntityFlags(client) & FL_ONGROUND); +} + +/** + * Gets whether a player is ducking or ducked. + * + * @param client Client index. + * @return Whether player is ducking or ducked. + */ +stock bool Movement_GetDucking(int client) +{ + return GetEntProp(client, Prop_Send, "m_bDucked") || GetEntProp(client, Prop_Send, "m_bDucking"); +} + +/** + * Gets a player's "m_flDuckSpeed" value. + * + * @param client Client index. + * @return Value of "m_flDuckSpeed". + */ +stock float Movement_GetDuckSpeed(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flDuckSpeed"); +} + +/** + * Sets a player's "m_flDuckSpeed" value. + * + * @param client Client index. + * @param value New "m_flDuckSpeed" value. + */ +stock void Movement_SetDuckSpeed(int client, float value) +{ + SetEntPropFloat(client, Prop_Send, "m_flDuckSpeed", value); +} + +/** + * Gets a player's "m_flVelocityModifier" value. + * + * @param client Client index. + * @return Value of "m_flVelocityModifier". + */ +stock float Movement_GetVelocityModifier(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flVelocityModifier"); +} + +/** + * Sets a player's "m_flVelocityModifier" value. + * + * @param client Client index. + * @param value New "m_flVelocityModifier" value. + */ +stock void Movement_SetVelocityModifier(int client, float value) +{ + SetEntPropFloat(client, Prop_Send, "m_flVelocityModifier", value); +} + +/** + * Gets a player's gravity scale factor. + * + * @param client Client index. + * @return Gravity scale factor. + */ +stock float Movement_GetGravity(int client) +{ + return GetEntityGravity(client); +} + +/** + * Sets a player's gravity scale factor. + * + * @param client Client index. + * @param value Desired gravity scale factor. + */ +stock void Movement_SetGravity(int client, float value) +{ + SetEntityGravity(client, value); +} + +/** + * Gets a player's movetype. + * + * @param client Client index. + * @return Player's movetype. + */ +stock MoveType Movement_GetMovetype(int client) +{ + return GetEntityMoveType(client); +} + +/** + * Sets a player's movetype. + * + * @param client Client index. + * @param movetype New movetype. + */ +stock void Movement_SetMovetype(int client, MoveType movetype) +{ + SetEntityMoveType(client, movetype); +} + +/** + * Gets whether a player is on a ladder. + * + * @param client Client index. + * @return Whether player is on a ladder. + */ +stock bool Movement_GetOnLadder(int client) +{ + return GetEntityMoveType(client) == MOVETYPE_LADDER; +} + +/** + * Gets whether a player is noclipping. + * + * @param client Client index. + * @return Whether player is noclipping. + */ +stock bool Movement_GetNoclipping(int client) +{ + return GetEntityMoveType(client) == MOVETYPE_NOCLIP; +} + + + +// =====[ METHODMAP ]===== + +methodmap MovementPlayer { + + public MovementPlayer(int client) { + return view_as(client); + } + + property int ID { + public get() { + return view_as(this); + } + } + + property int Buttons { + public get() { + return Movement_GetButtons(this.ID); + } + } + + public void GetOrigin(float result[3]) { + Movement_GetOrigin(this.ID, result); + } + + public void SetOrigin(const float origin[3]) { + Movement_SetOrigin(this.ID, origin); + } + + public void GetVelocity(float result[3]) { + Movement_GetVelocity(this.ID, result); + } + + public void SetVelocity(const float velocity[3]) { + Movement_SetVelocity(this.ID, velocity); + } + + property float Speed { + public get() { + return Movement_GetSpeed(this.ID); + } + public set(float value) { + Movement_SetSpeed(this.ID, value); + } + } + + property float VerticalVelocity { + public get() { + return Movement_GetVerticalVelocity(this.ID); + } + public set(float value) { + Movement_SetVerticalVelocity(this.ID, value); + } + } + + public void GetBaseVelocity(float result[3]) { + Movement_GetBaseVelocity(this.ID, result); + } + + public void SetBaseVelocity(const float baseVelocity[3]) { + Movement_SetBaseVelocity(this.ID, baseVelocity); + } + + public void GetEyeAngles(float result[3]) { + Movement_GetEyeAngles(this.ID, result); + } + + public void SetEyeAngles(const float eyeAngles[3]) { + Movement_SetEyeAngles(this.ID, eyeAngles); + } + + property bool OnGround { + public get() { + return Movement_GetOnGround(this.ID); + } + } + + property bool Ducking { + public get() { + return Movement_GetDucking(this.ID); + } + } + + property float DuckSpeed { + public get() { + return Movement_GetDuckSpeed(this.ID); + } + public set(float value) { + Movement_SetDuckSpeed(this.ID, value); + } + } + + property float VelocityModifier { + public get() { + return Movement_GetVelocityModifier(this.ID); + } + public set(float value) { + Movement_SetVelocityModifier(this.ID, value); + } + } + + property float Gravity { + public get() { + return Movement_GetGravity(this.ID); + } + public set(float value) { + Movement_SetGravity(this.ID, value); + } + } + + property MoveType Movetype { + public get() { + return Movement_GetMovetype(this.ID); + } + public set(MoveType movetype) { + Movement_SetMovetype(this.ID, movetype); + } + } + + property bool OnLadder { + public get() { + return Movement_GetOnLadder(this.ID); + } + } + + property bool Noclipping { + public get() { + return Movement_GetNoclipping(this.ID); + } + } +} diff --git a/source/sourcemod/scripting/include/movementapi.inc b/source/sourcemod/scripting/include/movementapi.inc new file mode 100644 index 0000000..290c3f2 --- /dev/null +++ b/source/sourcemod/scripting/include/movementapi.inc @@ -0,0 +1,663 @@ +/* + MovementAPI Plugin Include + + Website: https://github.com/danzayau/MovementAPI +*/ + +#if defined _movementapi_included_ + #endinput +#endif +#define _movementapi_included_ + +#include + + + +/* + Terminology + + Takeoff + Becoming airborne, including jumping, falling, getting off a ladder and leaving noclip. + + Landing + Leaving the air, including landing on the ground, grabbing a ladder and entering noclip. + + Perfect Bunnyhop (Perf) + When the player has jumped in the tick after landing and keeps their speed. + + Duckbug/Crouchbug + When the player sucessfully lands due to uncrouching from mid air and not by falling + down. This causes no stamina loss or fall damage upon landing. + + Jumpbug + This is achieved by duckbugging and jumping at the same time. The player is never seen + as 'on ground' when bunnyhopping from a tick by tick perspective. A jumpbug inherits + the same behavior as a duckbug/crouchbug, along with its effects such as maintaining + speed due to no stamina loss. + + Distbug + Landing behavior varies depending on whether the player lands close to the edge of a + block or not: + + 1. If the player lands close to the edge of a block, this causes the jump duration to + be one tick longer and the player can "slide" on the ground during the landing tick, + using the position post-tick as landing position becomes inaccurate. + + 2. On the other hand, if the player does not land close to the edge, the player will + be considered on the ground one tick earlier, using this position as landing position + is not accurate as the player has yet to be fully on the ground. + + In scenario 1, GetNobugLandingOrigin calculates the correct landing position of the + player before the sliding effect takes effect. + + In scenario 2, GetNobugLandingOrigin attempts to extrapolate the player's fully on + ground position to make landing positions consistent across scenarios. +*/ + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player's movetype changes. + * + * @param client Client index. + * @param oldMovetype Player's old movetype. + * @param newMovetype Player's new movetype. + */ +forward void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype); + +/** + * Called when a player touches the ground. + * + * @param client Client index. + */ +forward void Movement_OnStartTouchGround(int client); + +/** + * Called when a player leaves the ground. + * + * @param client Client index. + * @param jumped Whether player jumped to leave ground. + * @param ladderJump Whether player jumped from a ladder. + * @param jumpbug Whether player performed a jumpbug. + */ +forward void Movement_OnStopTouchGround(int client, bool jumped, bool ladderJump, bool jumpbug); + +/** + * Called when a player starts ducking. + * + * @param client Client index. + */ +forward void Movement_OnStartDucking(int client); + +/** + * Called when a player stops ducking. + * + * @param client Client index. + */ +forward void Movement_OnStopDucking(int client); + +/** + * Called when a player jumps (player_jump event), including 'jumpbugs'. + * Setting velocity when this is called may not be effective. + * + * @param client Client index. + * @param jumpbug Whether player 'jumpbugged'. + */ +forward void Movement_OnPlayerJump(int client, bool jumpbug); + +/** + * Called before PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before Duck movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnDuckPre(int client, float origin[3], float velocity[3]); + +/** + * Called after Duck movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnDuckPost(int client, float origin[3], float velocity[3]); + +/** + * Called before LadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnLadderMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after LadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnLadderMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before FullLadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnFullLadderMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after FullLadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnFullLadderMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called after the player jumps, but before jumping stamina is applied and takeoff variables are not set yet. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]); + +/** + * Called after the player jumps and after jumping stamina is applied and takeoff variables are already set here. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnJumpPost(int client, float origin[3], float velocity[3]); + +/** + * Called before AirAccelerate movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnAirAcceleratePre(int client, float origin[3], float velocity[3]); + +/** + * Called after AirAccelerate movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnAirAcceleratePost(int client, float origin[3], float velocity[3]); + +/** + * Called before WalkMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnWalkMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after WalkMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnWalkMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before CategorizePosition movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnCategorizePositionPre(int client, float origin[3], float velocity[3]); + +/** + * Called after CategorizePosition movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]); + +// =====[ NATIVES ]===== + +/** + * Gets whether a player's last takeoff was a jump. + * + * @param client Client index. + * @return Whether player's last takeoff was a jump. + */ +native bool Movement_GetJumped(int client); + +/** + * Gets whether a player's last takeoff was a perfect bunnyhop. + * + * @param client Client index. + * @return Whether player's last takeoff was a perfect bunnyhop. + */ +native bool Movement_GetHitPerf(int client); + +/** + * Gets a player's origin at the time of their last takeoff. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetTakeoffOrigin(int client, float result[3]); + +/** + * Gets a player's velocity at the time of their last takeoff. + * + * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's + * velocity after the takeoff velocity has already been measured. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetTakeoffVelocity(int client, float result[3]); + +/** + * Gets a player's horizontal speed at the time of their last takeoff. + * + * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's + * velocity after the takeoff velocity has already been measured. + * + * @param client Client index. + * @return Player's last takeoff speed. + */ +native float Movement_GetTakeoffSpeed(int client); + +/** + * Gets a player's 'tickcount' at the time of their last takeoff. + * + * @param client Client index. + * @return Player's last takeoff 'tickcount'. + */ +native int Movement_GetTakeoffTick(int client); + +/** + * Gets a player's 'cmdnum' at the time of their last takeoff. + * + * @param client Client index. + * @return Player's last takeoff 'cmdnum'. + */ +native int Movement_GetTakeoffCmdNum(int client); + +/** + * Gets a player's origin at the time of their last landing with the distbug fixed. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetNobugLandingOrigin(int client, float result[3]); + +/** + * Gets a player's origin at the time of their last landing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetLandingOrigin(int client, float result[3]); + +/** + * Gets a player's velocity at the time of their last landing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetLandingVelocity(int client, float result[3]); + +/** + * Gets a player's horizontal speed at the time of their last landing. + * + * @param client Client index. + * @return Last landing speed of the player (horizontal). + */ +native float Movement_GetLandingSpeed(int client); + +/** + * Gets a player's 'tickcount' at the time of their last landing. + * + * @param client Client index. + * @return Player's last landing 'tickcount'. + */ +native int Movement_GetLandingTick(int client); + +/** + * Gets a player's 'cmdnum' at the time of their last landing. + * + * @param client Client index. + * @return Player's last landing 'cmdnum'. + */ +native int Movement_GetLandingCmdNum(int client); + +/** + * Gets whether a player is turning their aim horizontally. + * + * @param client Client index. + * @return Whether player is turning their aim horizontally. + */ +native bool Movement_GetTurning(int client); + +/** + * Gets whether a player is turning their aim left. + * + * @param client Client index. + * @return Whether player is turning their aim left. + */ +native bool Movement_GetTurningLeft(int client); + +/** + * Gets whether a player is turning their aim right. + * + * @param client Client index. + * @return Whether player is turning their aim right. + */ +native bool Movement_GetTurningRight(int client); + +/** + * Gets result of CCSPlayer::GetPlayerMaxSpeed(client), which + * is the player's max speed as limited by their weapon. + * + * @param client Client index. + * @return Player's max speed as limited by their weapon. + */ +native float Movement_GetMaxSpeed(int client); + +/** + * Gets whether a player duckbugged on this tick. + * + * @param client Client index. + * @return Whether a player duckbugged on this tick. + */ +native bool Movement_GetDuckbugged(int client); + +/** + * Gets whether a player jumpbugged on this tick. + * + * @param client Client index. + * @return Whether a player jumpbugged on this tick. + */ +native bool Movement_GetJumpbugged(int client); + +/** + * Get the player's origin during movement processing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetProcessingOrigin(int client, float result[3]); + +/** + * Get the player's velocity during movement processing. + * + * @param client Param description + * @param result Resultant vector. + */ +native void Movement_GetProcessingVelocity(int client, float result[3]); + +/** + * Set the player's takeoff origin. + * + * @param client Client index. + * @param origin Desired origin. + */ +native void Movement_SetTakeoffOrigin(int client, float origin[3]); + +/** + * Set the player's takeoff velocity. + * + * @param client Client index. + * @param origin Desired velocity. + */ +native void Movement_SetTakeoffVelocity(int client, float velocity[3]); + +/** + * Set the player's landing origin. + * + * @param client Client index. + * @param origin Desired origin. + */ +native void Movement_SetLandingOrigin(int client, float origin[3]); + +/** + * Set the player's landing velocity. + * + * @param client Client index. + * @param origin Desired velocity. + */ +native void Movement_SetLandingVelocity(int client, float velocity[3]); + +// =====[ METHODMAP ]===== + +methodmap MovementAPIPlayer < MovementPlayer { + + public MovementAPIPlayer(int client) { + return view_as(MovementPlayer(client)); + } + + property bool Jumped { + public get() { + return Movement_GetJumped(this.ID); + } + } + + property bool HitPerf { + public get() { + return Movement_GetHitPerf(this.ID); + } + } + + public void GetTakeoffOrigin(float buffer[3]) { + Movement_GetTakeoffOrigin(this.ID, buffer); + } + + public void GetTakeoffVelocity(float buffer[3]) { + Movement_GetTakeoffVelocity(this.ID, buffer); + } + + public void SetTakeoffOrigin(float buffer[3]) + { + Movement_SetTakeoffOrigin(this.ID, buffer); + } + + public void SetTakeoffVelocity(float buffer[3]) + { + Movement_SetTakeoffVelocity(this.ID, buffer); + } + + property float TakeoffSpeed { + public get() { + return Movement_GetTakeoffSpeed(this.ID); + } + } + + property int TakeoffTick { + public get() { + return Movement_GetTakeoffTick(this.ID); + } + } + + property int TakeoffCmdNum { + public get() { + return Movement_GetTakeoffCmdNum(this.ID); + } + } + + public void GetLandingOrigin(float buffer[3]) { + Movement_GetLandingOrigin(this.ID, buffer); + } + + public void GetLandingVelocity(float buffer[3]) { + Movement_GetLandingVelocity(this.ID, buffer); + } + + public void SetLandingOrigin(float buffer[3]) + { + Movement_SetLandingOrigin(this.ID, buffer); + } + + public void SetLandingVelocity(float buffer[3]) + { + Movement_SetLandingVelocity(this.ID, buffer); + } + + property float LandingSpeed { + public get() { + return Movement_GetLandingSpeed(this.ID); + } + } + + property int LandingTick { + public get() { + return Movement_GetLandingTick(this.ID); + } + } + + property int LandingCmdNum { + public get() { + return Movement_GetLandingCmdNum(this.ID); + } + } + + property bool Turning { + public get() { + return Movement_GetTurning(this.ID); + } + } + + property bool TurningLeft { + public get() { + return Movement_GetTurningLeft(this.ID); + } + } + + property bool TurningRight { + public get() { + return Movement_GetTurningRight(this.ID); + } + } + + property float MaxSpeed { + public get() { + return Movement_GetMaxSpeed(this.ID); + } + } + + public void GetProcessingVelocity(float buffer[3]) + { + Movement_GetProcessingVelocity(this.ID, buffer); + } + + public void GetProcessingOrigin(float buffer[3]) + { + Movement_GetProcessingOrigin(this.ID, buffer); + } +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_movementapi = +{ + name = "movementapi", + file = "movementapi.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_movementapi_SetNTVOptional() +{ + MarkNativeAsOptional("Movement_GetJumped"); + MarkNativeAsOptional("Movement_GetHitPerf"); + MarkNativeAsOptional("Movement_GetTakeoffOrigin"); + MarkNativeAsOptional("Movement_GetTakeoffVelocity"); + MarkNativeAsOptional("Movement_GetTakeoffSpeed"); + MarkNativeAsOptional("Movement_GetTakeoffTick"); + MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); + MarkNativeAsOptional("Movement_GetLandingOrigin"); + MarkNativeAsOptional("Movement_GetLandingVelocity"); + MarkNativeAsOptional("Movement_GetLandingSpeed"); + MarkNativeAsOptional("Movement_GetLandingTick"); + MarkNativeAsOptional("Movement_GetLandingCmdNum"); + MarkNativeAsOptional("Movement_GetTurning"); + MarkNativeAsOptional("Movement_GetTurningLeft"); + MarkNativeAsOptional("Movement_GetTurningRight"); + MarkNativeAsOptional("Movement_GetMaxSpeed"); + MarkNativeAsOptional("Movement_GetProcessingOrigin"); + MarkNativeAsOptional("Movement_GetProcessingVelocity"); + MarkNativeAsOptional("Movement_SetTakeoffOrigin"); + MarkNativeAsOptional("Movement_SetTakeoffVelocity"); + MarkNativeAsOptional("Movement_SetLandingOrigin"); + MarkNativeAsOptional("Movement_SetLandingVelocity"); +} +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/nextmap.inc b/source/sourcemod/scripting/include/nextmap.inc new file mode 100644 index 0000000..1039e25 --- /dev/null +++ b/source/sourcemod/scripting/include/nextmap.inc @@ -0,0 +1,82 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2014 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 char[] 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(char[] map, int 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. + */ +native void ForceChangeLevel(const char[] map, const char[] reason); + +/** + * Gets the current number of maps in the map history + * + * @return Number of maps. + */ +native int 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. + * @error Invalid item number. + */ +native void GetMapHistory(int item, char[] map, int mapLen, char[] reason, int reasonLen, int &startTime); diff --git a/source/sourcemod/scripting/include/profiler.inc b/source/sourcemod/scripting/include/profiler.inc new file mode 100644 index 0000000..df5b956 --- /dev/null +++ b/source/sourcemod/scripting/include/profiler.inc @@ -0,0 +1,123 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2018 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. + */ + +methodmap Profiler < Handle +{ + // Creates a new profile object. The Handle must be freed + // using delete or CloseHandle(). + // + // @return A new Profiler Handle. + public native Profiler(); + + // Starts a cycle for profiling. + public native void Start(); + + // Stops a cycle for profiling. + // + // @error Profiler was never started. + public native void Stop(); + + // Returns the amount of high-precision time in seconds + // that passed during the profiler's last start/stop + // cycle. + // + // @return Time elapsed in seconds. + property float Time { + public native get(); + } +}; + +/** + * Creates a new profile object. The Handle must be freed + * using delete or CloseHandle(). + * + * @return Handle to the profiler object. + */ +native Profiler CreateProfiler(); + +/** + * Starts profiling. + * + * @param prof Profiling object. + * @error Invalid Handle. + */ +native void StartProfiling(Handle prof); + +/** + * Stops profiling. + * + * @param prof Profiling object. + * @error Invalid Handle or profiling was never started. + */ +native void 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); + +/** + * Mark the start of a profiling event. + * + * @param group Budget group. This can be "all" for a default, or a short + * description like "Timers" or "Events". + * @param name A name to attribute to this profiling event. + */ +native void EnterProfilingEvent(const char[] group, const char[] name); + +/** + * Mark the end of the last profiling event. This must be called in the same + * stack frame as StartProfilingEvent(). Not doing so, or throwing errors, + * will make the resulting profile very wrong. + */ +native void LeaveProfilingEvent(); + +/** + * Returns true if the global profiler is enabled; false otherwise. It is + * not necessary to call this before Enter/LeaveProfilingEvent. + */ +native bool IsProfilingActive(); diff --git a/source/sourcemod/scripting/include/protobuf.inc b/source/sourcemod/scripting/include/protobuf.inc new file mode 100644 index 0000000..80c4337 --- /dev/null +++ b/source/sourcemod/scripting/include/protobuf.inc @@ -0,0 +1,602 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2013 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 _protobuf_included + #endinput +#endif +#define _protobuf_included + +#define PB_FIELD_NOT_REPEATED -1 + +methodmap Protobuf < Handle +{ + // Reads an int32, uint32, sint32, fixed32, sfixed32, or enum value from a protobuf message. + // + // @param field Field name. + // @param index Index into repeated field. + // @return Integer value read. + // @error Non-existent field, or incorrect field type. + public native int ReadInt(const char[] field, int index = PB_FIELD_NOT_REPEATED); + + // Reads an int64, uint64, sint64, fixed64, sfixed64 from a protobuf message. + // + // @param field Field name. + // @param value Array to represent the large integer (0=High bits, 1=Low bits). + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void ReadInt64(const char[] field, int value[2], int index = PB_FIELD_NOT_REPEATED); + + // Reads a float or downcasted double from a protobuf message. + // + // @param field Field name. + // @param index Index into repeated field. + // @return Float value read. + // @error Non-existent field, or incorrect field type. + public native float ReadFloat(const char[] field, int index = PB_FIELD_NOT_REPEATED); + + // Reads a bool from a protobuf message. + // + // @param field Field name. + // @param index Index into repeated field. + // @return Boolean value read. + // @error Non-existent field, or incorrect field type. + public native bool ReadBool(const char[] field, int index = PB_FIELD_NOT_REPEATED); + + // Reads a string from a protobuf message. + // + // @param field Field name. + // @param buffer Destination string buffer. + // @param maxlength Maximum length of output string buffer. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void ReadString(const char[] field, char[] buffer, int maxlength, int index = PB_FIELD_NOT_REPEATED); + + // Reads an RGBA color value from a protobuf message. + // + // @param field Field name. + // @param buffer Destination color buffer. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void ReadColor(const char[] field, int buffer[4], int index = PB_FIELD_NOT_REPEATED); + + // Reads an XYZ angle value from a protobuf message. + // + // @param field Field name. + // @param buffer Destination angle buffer. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void ReadAngle(const char[] field, float buffer[3], int index = PB_FIELD_NOT_REPEATED); + + // Reads an XYZ vector value from a protobuf message. + // + // @param pb protobuf handle. + // @param field Field name. + // @param buffer Destination vector buffer. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void ReadVector(const char[] field, float buffer[3], int index = PB_FIELD_NOT_REPEATED); + + // Reads an XY vector value from a protobuf message. + // + // @param field Field name. + // @param buffer Destination vector buffer. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void ReadVector2D(const char[] field, float buffer[2], int index = PB_FIELD_NOT_REPEATED); + + // Gets the number of elements in a repeated field of a protobuf message. + // + // @param field Field name. + // @return Number of elements in the field. + // @error Non-existent field, or non-repeated field. + public native int GetRepeatedFieldCount(const char[] field); + + // Returns whether or not the named, non-repeated field has a value set. + // + // @param field Field name. + // @return True if value has been set, else false. + // @error Non-existent field, or repeated field. + public native bool HasField(const char[] field); + + // Sets an int32, uint32, sint32, fixed32, sfixed32, or enum value on a protobuf message. + // + // @param field Field name. + // @param value Integer value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetInt(const char[] field, int value, int index = PB_FIELD_NOT_REPEATED); + + // Sets an int64, uint64, sint64, fixed64, sfixed64 on a protobuf message. + // + // @param field Field name. + // @param value Large integer value to set (0=High bits, 1=Low bits). + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetInt64(const char[] field, int value[2], int index = PB_FIELD_NOT_REPEATED); + + // Sets a float or double on a protobuf message. + // + // @param field Field name. + // @param value Float value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetFloat(const char[] field, float value, int index = PB_FIELD_NOT_REPEATED); + + // Sets a bool on a protobuf message. + // + // @param field Field name. + // @param value Boolean value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetBool(const char[] field, bool value, int index = PB_FIELD_NOT_REPEATED); + + // Sets a string on a protobuf message. + // + // @param field Field name. + // @param value String value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetString(const char[] field, const char[] value, int index = PB_FIELD_NOT_REPEATED); + + // Sets an RGBA color on a protobuf message. + // + // @param field Field name. + // @param color Color value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetColor(const char[] field, const int color[4], int index = PB_FIELD_NOT_REPEATED); + + // Sets an XYZ angle on a protobuf message. + // + // @param field Field name. + // @param angle Angle value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetAngle(const char[] field, const float angle[3], int index = PB_FIELD_NOT_REPEATED); + + // Sets an XYZ vector on a protobuf message. + // + // @param field Field name. + // @param vec Vector value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetVector(const char[] field, const float vec[3], int index = PB_FIELD_NOT_REPEATED); + + // Sets an XY vector on a protobuf message. + // + // @param field Field name. + // @param vec Vector value to set. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void SetVector2D(const char[] field, const float vec[2], int index = PB_FIELD_NOT_REPEATED); + + // Add an int32, uint32, sint32, fixed32, sfixed32, or enum value to a protobuf message repeated field. + // + // @param field Field name. + // @param value Integer value to add. + // @error Non-existent field, or incorrect field type. + public native void AddInt(const char[] field, int value); + + // Add an int64, uint64, sint64, fixed64, sfixed64 to a protobuf message repeated field. + // + // @param field Field name. + // @param value Large integer value to add (0=High bits, 1=Low bits). + // @error Non-existent field, or incorrect field type. + public native void AddInt64(const char[] field, int value[2]); + + // Add a float or double to a protobuf message repeated field. + // + // @param field Field name. + // @param value Float value to add. + // @error Non-existent field, or incorrect field type. + public native void AddFloat(const char[] field, float value); + + // Add a bool to a protobuf message repeated field. + // + // @param field Field name. + // @param value Boolean value to add. + // @error Non-existent field, or incorrect field type. + public native void AddBool(const char[] field, bool value); + + // Add a string to a protobuf message repeated field. + // + // @param field Field name. + // @param value String value to add. + // @error Non-existent field, or incorrect field type. + public native void AddString(const char[] field, const char[] value); + + // Add an RGBA color to a protobuf message repeated field. + // + // @param field Field name. + // @param color Color value to add. + // @error Non-existent field, or incorrect field type. + public native void AddColor(const char[] field, const int color[4]); + + // Add an XYZ angle to a protobuf message repeated field. + // + // @param field Field name. + // @param angle Angle value to add. + // @error Non-existent field, or incorrect field type. + public native void AddAngle(const char[] field, const float angle[3]); + + // Add an XYZ vector to a protobuf message repeated field. + // + // @param field Field name. + // @param vec Vector value to add. + // @error Non-existent field, or incorrect field type. + public native void AddVector(const char[] field, const float vec[3]); + + // Add an XY vector to a protobuf message repeated field. + // + // @param field Field name. + // @param vec Vector value to add. + // @error Non-existent field, or incorrect field type. + public native void AddVector2D(const char[] field, const float vec[2]); + + // Removes a value by index from a protobuf message repeated field. + // + // @param field Field name. + // @param index Index into repeated field. + // @error Non-existent field, or incorrect field type. + public native void RemoveRepeatedFieldValue(const char[] field, int index); + + // Retrieve a handle to an embedded protobuf message in a protobuf message. + // + // @param field Field name. + // @return Protobuf handle to embedded message. + // @error Non-existent field, or incorrect field type. + public native Protobuf ReadMessage(const char[] field); + + // Retrieve a handle to an embedded protobuf message in a protobuf message + // repeated field. + // + // @param field Field name. + // @param index Index in the repeated field. + // @return Protobuf handle to embedded message. + // @error Non-existent field, or incorrect field type. + public native Protobuf ReadRepeatedMessage(const char[] field, int index); + + // Adds an embedded protobuf message to a protobuf message repeated field. + // + // @param field Field name. + // @return Protobuf handle to added, embedded message. + // @error Non-existent field, or incorrect field type. + public native Protobuf AddMessage(const char[] field); +}; + +/** + * Reads an int32, uint32, sint32, fixed32, sfixed32, or enum value from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param index Index into repeated field. + * @return Integer value read. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native int PbReadInt(Handle pb, const char[] field, int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads a float or downcasted double from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param index Index into repeated field. + * @return Float value read. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native float PbReadFloat(Handle pb, const char[] field, int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads a bool from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param index Index into repeated field. + * @return Boolean value read. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native bool PbReadBool(Handle pb, const char[] field, int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads a string from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param buffer Destination string buffer. + * @param maxlength Maximum length of output string buffer. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbReadString(Handle pb, const char[] field, char[] buffer, int maxlength, int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads an RGBA color value from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param buffer Destination color buffer. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbReadColor(Handle pb, const char[] field, int buffer[4], int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads an XYZ angle value from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param buffer Destination angle buffer. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbReadAngle(Handle pb, const char[] field, float buffer[3], int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads an XYZ vector value from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param buffer Destination vector buffer. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbReadVector(Handle pb, const char[] field, float buffer[3], int index = PB_FIELD_NOT_REPEATED); + +/** + * Reads an XY vector value from a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param buffer Destination vector buffer. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbReadVector2D(Handle pb, const char[] field, float buffer[2], int index = PB_FIELD_NOT_REPEATED); + +/** + * Gets the number of elements in a repeated field of a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @return Number of elements in the field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native int PbGetRepeatedFieldCount(Handle pb, const char[] field); + +/** + * Sets an int32, uint32, sint32, fixed32, sfixed32, or enum value on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value Integer value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetInt(Handle pb, const char[] field, int value, int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets a float or double on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value Float value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetFloat(Handle pb, const char[] field, float value, int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets a bool on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value Boolean value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetBool(Handle pb, const char[] field, bool value, int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets a string on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value String value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetString(Handle pb, const char[] field, const char[] value, int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets an RGBA color on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param color Color value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetColor(Handle pb, const char[] field, const int color[4], int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets an XYZ angle on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param angle Angle value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetAngle(Handle pb, const char[] field, const float angle[3], int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets an XYZ vector on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param vec Vector value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetVector(Handle pb, const char[] field, const float vec[3], int index = PB_FIELD_NOT_REPEATED); + +/** + * Sets an XY vector on a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @param vec Vector value to set. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbSetVector2D(Handle pb, const char[] field, const float vec[2], int index = PB_FIELD_NOT_REPEATED); + +/** + * Add an int32, uint32, sint32, fixed32, sfixed32, or enum value to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value Integer value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddInt(Handle pb, const char[] field, int value); + +/** + * Add a float or double to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value Float value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddFloat(Handle pb, const char[] field, float value); + +/** + * Add a bool to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value Boolean value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddBool(Handle pb, const char[] field, bool value); + +/** + * Add a string to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param value String value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddString(Handle pb, const char[] field, const char[] value); + +/** + * Add an RGBA color to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param color Color value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddColor(Handle pb, const char[] field, const int color[4]); + +/** + * Add an XYZ angle to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param angle Angle value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddAngle(Handle pb, const char[] field, const float angle[3]); + +/** + * Add an XYZ vector to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param vec Vector value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddVector(Handle pb, const char[] field, const float vec[3]); + +/** + * Add an XY vector to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param vec Vector value to add. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbAddVector2D(Handle pb, const char[] field, const float vec[2]); + +/** + * Removes a value by index from a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param index Index into repeated field. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native void PbRemoveRepeatedFieldValue(Handle pb, const char[] field, int index); + +/** + * Retrieve a handle to an embedded protobuf message in a protobuf message. + * + * @param pb protobuf handle. + * @param field Field name. + * @return protobuf handle to embedded message. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native Handle PbReadMessage(Handle pb, const char[] field); + +/** + * Retrieve a handle to an embedded protobuf message in a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @param index Index in the repeated field. + * @return protobuf handle to embedded message. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native Handle PbReadRepeatedMessage(Handle pb, const char[] field, int index); + +/** + * Adds an embedded protobuf message to a protobuf message repeated field. + * + * @param pb protobuf handle. + * @param field Field name. + * @return protobuf handle to added, embedded message. + * @error Invalid or incorrect Handle, non-existent field, or incorrect field type. + */ +native Handle PbAddMessage(Handle pb, const char[] field); diff --git a/source/sourcemod/scripting/include/regex.inc b/source/sourcemod/scripting/include/regex.inc new file mode 100644 index 0000000..97fcc18 --- /dev/null +++ b/source/sourcemod/scripting/include/regex.inc @@ -0,0 +1,291 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * 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_ANCHORED 0x00000010 /* Force pattern anchoring. */ +#define PCRE_DOLLAR_ENDONLY 0x00000020 /* $ not to match newline at end. */ +#define PCRE_UNGREEDY 0x00000200 /* Invert greediness of quantifiers */ +#define PCRE_NOTEMPTY 0x00000400 /* An empty string is not a valid match. */ +#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) */ +#define PCRE_UCP 0x20000000 /* Use Unicode properties for \ed, \ew, etc. */ + + +/** + * Regex expression error codes. + */ +enum RegexError +{ + REGEX_ERROR_NONE = 0, /* No error */ + + REGEX_ERROR_ASSERT = 1, /* internal error ? */ + REGEX_ERROR_BADBR, /* invalid repeat counts in {} */ + REGEX_ERROR_BADPAT, /* pattern error */ + REGEX_ERROR_BADRPT, /* ? * + invalid */ + REGEX_ERROR_EBRACE, /* unbalanced {} */ + REGEX_ERROR_EBRACK, /* unbalanced [] */ + REGEX_ERROR_ECOLLATE, /* collation error - not relevant */ + REGEX_ERROR_ECTYPE, /* bad class */ + REGEX_ERROR_EESCAPE, /* bad escape sequence */ + REGEX_ERROR_EMPTY, /* empty expression */ + REGEX_ERROR_EPAREN, /* unbalanced () */ + REGEX_ERROR_ERANGE, /* bad range inside [] */ + REGEX_ERROR_ESIZE, /* expression too big */ + REGEX_ERROR_ESPACE, /* failed to get memory */ + REGEX_ERROR_ESUBREG, /* bad back reference */ + REGEX_ERROR_INVARG, /* bad argument */ + + 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, + REGEX_ERROR_BADOFFSET = -24, + REGEX_ERROR_SHORTUTF8 = -25, + REGEX_ERROR_RECURSELOOP = -26, + REGEX_ERROR_JIT_STACKLIMIT = -27, + REGEX_ERROR_BADMODE = -28, + REGEX_ERROR_BADENDIANNESS = -29, + REGEX_ERROR_DFA_BADRESTART = -30, + REGEX_ERROR_JIT_BADOPTION = -31, + REGEX_ERROR_BADLENGTH = -32 +}; + +// Regular expression objects are used to match or decompose strings based on +// patterns. +methodmap Regex < Handle +{ + // Compile a regular expression. + // + // @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. + public native Regex(const char[] pattern, int flags = 0, char[] error="", int maxLen = 0, RegexError &errcode = REGEX_ERROR_NONE); + + // Matches a string against a pre-compiled regular expression pattern. + // + // @param str The string to check. + // @param ret Error code, if applicable. + // @param offset Offset in the string to start searching from. MatchOffset returns the offset of the match. + // @return Number of captures found or -1 on failure. + // + // @note Use the regex handle passed to this function to extract + // matches with GetSubString(). + public native int Match(const char[] str, RegexError &ret = REGEX_ERROR_NONE, int offset = 0); + + // Gets all matches from a string against a pre-compiled regular expression pattern. + // + // @param str The string to check. + // @param ret Error code, if applicable. + // @return Number of matches found or -1 on failure. + // + // @note Use GetSubString() and loop from 0 -> totalmatches - 1. + public native int MatchAll(const char[] str, RegexError &ret = REGEX_ERROR_NONE); + + // Returns a matched substring from a regex handle. + // + // Substring ids start at 0 and end at captures-1, where captures is the + // number returned by Regex.Match or Regex.CaptureCount. + // + // @param str_id The index of the expression to get - starts at 0, and ends at captures - 1. + // @param buffer The buffer to set to the matching substring. + // @param maxlen The maximum string length of the buffer. + // @param match Match to get the captures for - starts at 0, and ends at MatchCount() -1 + // @return True if a substring was found, False on fail/error + // + // @note str_id = 0 is the full captured string, anything else is the capture group index. + // if Regex.Match is used match can only be 0 + public native bool GetSubString(int str_id, char[] buffer, int maxlen, int match = 0); + + // Returns number of matches + // + // When using Match this is always 1 or 0 (unless an error occured) + // @return Total number of matches found. + public native int MatchCount(); + + // Returns number of captures for a match + // + // @param match Match to get the number of captures for. Match starts at 0, and ends at MatchCount() -1 + // @return Number of captures in the match. + // + // @note Use GetSubString() and loop from 1 -> captures -1 for str_id to get all captures + public native int CaptureCount(int match = 0); + + // Returns the string offset of a match. + // + // @param match Match to get the offset of. Match starts at 0, and ends at MatchCount() -1 + // @return Offset of the match in the string. + public native int MatchOffset(int match = 0); +}; + +/** + * 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 Regex CompileRegex(const char[] pattern, int flags = 0, char[] error="", int maxLen = 0, RegexError &errcode = REGEX_ERROR_NONE); + +/** + * Matches a string against a pre-compiled regular expression pattern. + * + * @param regex Regex Handle from CompileRegex() + * @param str The string to check. + * @param ret Error code, if applicable. + * @param offset Offset in the string to start searching from. + * @return Number of captures found or -1 on failure. + * + * @note Use the regex handle passed to this function to extract + * matches with GetRegexSubString(). + */ +native int MatchRegex(Handle regex, const char[] str, RegexError &ret = REGEX_ERROR_NONE, int offset = 0); + +/** + * Returns a matched substring from a regex handle. + * Substring ids start at 0 and end at captures-1, where captures 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 captures - 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 + * + * @note str_id = 0 is the full captured string, anything else is the capture group index. + * + */ +native bool GetRegexSubString(Handle regex, int str_id, char[] buffer, int 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 int SimpleRegexMatch(const char[] str, const char[] pattern, int flags = 0, char[] error="", int maxLen = 0) +{ + Regex regex = new Regex(pattern, flags, error, maxLen); + if (!regex) + { + return -1; + } + + int substrings = regex.Match(str); + delete 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 +}; + +#if !defined REQUIRE_EXTENSIONS +public void __ext_regex_SetNTVOptional() +{ + MarkNativeAsOptional("CompileRegex"); + MarkNativeAsOptional("MatchRegex"); + MarkNativeAsOptional("GetRegexSubString"); + MarkNativeAsOptional("Regex.Regex"); + MarkNativeAsOptional("Regex.Match"); + MarkNativeAsOptional("Regex.MatchAll"); + MarkNativeAsOptional("Regex.GetSubString"); + MarkNativeAsOptional("Regex.MatchCount"); + MarkNativeAsOptional("Regex.CaptureCount"); + MarkNativeAsOptional("Regex.MatchOffset"); +} +#endif diff --git a/source/sourcemod/scripting/include/sdkhooks.inc b/source/sourcemod/scripting/include/sdkhooks.inc new file mode 100644 index 0000000..1c80cf3 --- /dev/null +++ b/source/sourcemod/scripting/include/sdkhooks.inc @@ -0,0 +1,457 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2009-2013 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 . + */ + +#if defined _sdkhooks_included + #endinput +#endif +#define _sdkhooks_included + +// this is obviously _not_ a robust check, but it will solve most conflict and is clean +#if !defined DMG_GENERIC +#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. */ +#endif + +#if !defined DMG_CRIT + #define DMG_CRIT DMG_ACID /**< TF2 crits and minicrits */ +#endif + +#if !defined DMG_RADIUS_MAX + #define DMG_RADIUS_MAX DMG_ENERGYBEAM /**< No damage falloff */ +#endif + +#if !defined DMG_NOCLOSEDISTANCEMOD + #define DMG_NOCLOSEDISTANCEMOD DMG_POISON /**< Don't do damage falloff too close */ +#endif + +#if !defined DMG_HALF_FALLOFF + #define DMG_HALF_FALLOFF DMG_RADIATION /**< 50% damage falloff */ +#endif + +#if !defined DMG_USEDISTANCEMOD + #define DMG_USEDISTANCEMOD DMG_SLOWBURN /**< Do damage falloff */ +#endif + +#if !defined DMG_IGNITE + #define DMG_IGNITE DMG_PLASMA /**< Ignite victim */ +#endif + +#if !defined DMG_USE_HITLOCATIONS + #define DMG_USE_HITLOCATIONS DMG_AIRBOAT /**< Do hit location damage (Like the sniperrifle and ambassador) */ +#endif + +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, + SDKHook_EndTouchPost, + SDKHook_GroundEntChangedPost, + SDKHook_SpawnPost, + SDKHook_StartTouchPost, + SDKHook_TouchPost, + SDKHook_VPhysicsUpdate, + SDKHook_VPhysicsUpdatePost, + SDKHook_WeaponCanSwitchToPost, + SDKHook_WeaponCanUsePost, + SDKHook_WeaponDropPost, + SDKHook_WeaponEquipPost, + SDKHook_WeaponSwitchPost, + SDKHook_Use, + SDKHook_UsePost, + SDKHook_Reload, + SDKHook_ReloadPost, + SDKHook_GetMaxHealth, /**< ep2v and later */ + SDKHook_Blocked, + SDKHook_BlockedPost, + SDKHook_OnTakeDamageAlive, + SDKHook_OnTakeDamageAlivePost, + SDKHook_CanBeAutobalanced +}; + +/* + Alphabetized for easy readability + + SDKHook_Blocked, + SDKHook_BlockedPost, + + SDKHook_CanBeAutobalanced, + + SDKHook_EndTouch, + SDKHook_EndTouchPost, + + SDKHook_FireBulletsPost, + + SDKHook_GetMaxHealth, (ep2v and later) + + SDKHook_GroundEntChangedPost, + + SDKHook_OnTakeDamage, + SDKHook_OnTakeDamagePost, + + SDKHook_OnTakeDamageAlive, + SDKHook_OnTakeDamageAlivePost, + + SDKHook_PreThink, + SDKHook_PreThinkPost, + + SDKHook_PostThink, + SDKHook_PostThinkPost, + + SDKHook_Reload, + SDKHook_ReloadPost, + + SDKHook_SetTransmit, + + SDKHook_ShouldCollide, + + SDKHook_Spawn, + SDKHook_SpawnPost, + + SDKHook_StartTouch, + SDKHook_StartTouchPost, + + SDKHook_Think, + SDKHook_ThinkPost, + + SDKHook_Touch, + SDKHook_TouchPost, + + SDKHook_TraceAttack, + SDKHook_TraceAttackPost, + + SDKHook_Use, + SDKHook_UsePost, + + SDKHook_VPhysicsUpdate, + SDKHook_VPhysicsUpdatePost, + + SDKHook_WeaponCanSwitchTo, + SDKHook_WeaponCanSwitchToPost, + + SDKHook_WeaponCanUse, + SDKHook_WeaponCanUsePost, + + SDKHook_WeaponDrop, + SDKHook_WeaponDropPost, + + SDKHook_WeaponEquip, + SDKHook_WeaponEquipPost, + + SDKHook_WeaponSwitch, + SDKHook_WeaponSwitchPost +*/ + +enum UseType +{ + Use_Off, + Use_On, + Use_Set, + Use_Toggle +}; + +typeset SDKHookCB +{ + // PreThink/Post + // PostThink/Post + function void (int client); + + // Spawn + // Think + function Action (int entity); + + // GroundEntChanged + // SpawnPost + // ThinkPost + // VPhysicsUpdate/Post + function void (int entity); + + // EndTouch + // StartTouch + // Touch + // Blocked + function Action (int entity, int other); + + // EndTouchPost + // StartTouchPost + // TouchPost + function void (int entity, int other); + + // SetTransmit + function Action (int entity, int client); + + // WeaponCanSwitchTo + // WeaponCanUse + // WeaponDrop + // WeaponEquip + // WeaponSwitch + function Action (int client, int weapon); + + // WeaponCanSwitchToPost + // WeaponCanUsePost + // WeaponDropPost + // WeaponEquipPost + // WeaponSwitchPost + function void (int client, int weapon); + + // GetMaxHealth (ep2v and later) + function Action (int entity, int &maxhealth); + + // OnTakeDamage + // OnTakeDamageAlive + // SDKHooks 1.0+ + function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype); + + // OnTakeDamage + // OnTakeDamageAlive + // Note: The weapon parameter is not used by all games and damage sources. + // Note: Force application is dependent on game and damage type(s) + // SDKHooks 2.0+ + function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3]); + + // OnTakeDamage + // OnTakeDamageAlive + // Note: The weapon parameter is not used by all games and damage sources. + // Note: Force application is dependent on game and damage type(s) + // SDKHooks 2.1+ (can check for support at runtime using GetFeatureStatus on SDKHook_DmgCustomInOTD capability. + // DON'T attempt to access 'damagecustom' var if feature status != available + function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, + float damageForce[3], float damagePosition[3], int damagecustom); + + // OnTakeDamagePost + // OnTakeDamageAlivePost + function void (int victim, int attacker, int inflictor, float damage, int damagetype); + + // OnTakeDamagePost + // OnTakeDamageAlivePost + function void (int victim, int attacker, int inflictor, float damage, int damagetype, int weapon, const float damageForce[3], const float damagePosition[3]); + + // OnTakeDamagePost + // OnTakeDamageAlivePost + function void (int victim, int attacker, int inflictor, float damage, int damagetype, int weapon, + const float damageForce[3], const float damagePosition[3], int damagecustom); + + // FireBulletsPost + function void (int client, int shots, const char[] weaponname); + + // TraceAttack + function Action (int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &ammotype, int hitbox, int hitgroup); + + // TraceAttackPost + function void (int victim, int attacker, int inflictor, float damage, int damagetype, int ammotype, int hitbox, int hitgroup); + + // ShouldCollide + function bool (int entity, int collisiongroup, int contentsmask, bool originalResult); + + // Use + function Action (int entity, int activator, int caller, UseType type, float value); + + // UsePost + function void (int entity, int activator, int caller, UseType type, float value); + + // Reload + function Action (int weapon); + + // Reload post + function void (int weapon, bool bSuccessful); + + // CanBeAutobalanced + function bool (int client, bool origRet); +}; + + +/** + * When an entity is created + * + * @param entity Entity index + * @param classname Class name + */ +forward void OnEntityCreated(int entity, const char[] classname); + +/** + * When an entity is destroyed + * + * @param entity Entity index or edict reference. + */ +forward void OnEntityDestroyed(int entity); + +/** + * When the game description is retrieved + * + * @note Not supported on ep2v. + * + * @param gameDesc Game description + * @return Plugin_Changed if gameDesc has been edited, else no change. + */ +forward Action OnGetGameDescription(char gameDesc[64]); + +/** + * When the level is initialized + * + * @param mapName Name of the map + * @param mapEntities Unused, always empty + * @return Unused, return value is ignored + */ +#pragma deprecated Use OnMapInit() instead +forward Action OnLevelInit(const char[] mapName, char mapEntities[2097152]); + +/** + * Hooks an entity + * + * @param entity Entity index + * @param type Type of function to hook + * @param callback Function to call when hook is called + */ +native void SDKHook(int entity, SDKHookType type, SDKHookCB callback); + +/** + * Hooks an entity + * + * @param entity Entity index + * @param type Type of function to hook + * @param callback Function to call when hook is called + * @return Hook Successful + */ +native bool SDKHookEx(int entity, SDKHookType type, SDKHookCB callback); + +/** + * Unhooks an entity + * + * @param entity Entity index + * @param type Type of function to unhook + * @param callback Callback function to unhook + */ +native void SDKUnhook(int entity, SDKHookType type, SDKHookCB callback); + +/** + * Applies damage to an entity + * + * @note Force application is dependent on game and damage type(s) + * + * @param entity Entity index taking damage + * @param inflictor Inflictor entity index + * @param attacker Attacker entity index + * @param damage Amount of damage + * @param damageType Bitfield of damage types + * @param weapon Weapon index (orangebox and later) or -1 for unspecified + * @param damageForce Velocity of damage force + * @param damagePosition Origin of damage + * @param bypassHooks If true, bypass SDK hooks on OnTakeDamage + * @error Invalid entity, attacker, inflictor, or weapon entity. + */ +native void SDKHooks_TakeDamage(int entity, int inflictor, int attacker, + float damage, int damageType=DMG_GENERIC, int weapon=-1, + const float damageForce[3]=NULL_VECTOR, const float damagePosition[3]=NULL_VECTOR, + bool bypassHooks = true); + +/** + * Forces a client to drop the specified weapon + * + * @param client Client index. + * @param weapon Weapon entity index. + * @param vecTarget Location to toss weapon to, or NULL_VECTOR for default. + * @param vecVelocity Velocity at which to toss weapon, or NULL_VECTOR for default. + * @param bypassHooks If true, bypass SDK hooks on Weapon Drop + * @error Invalid client or weapon entity, weapon not owned by client. + */ +native void SDKHooks_DropWeapon(int client, int weapon, const float vecTarget[3]=NULL_VECTOR, + const float vecVelocity[3]=NULL_VECTOR, bool bypassHooks = true); + +/** + * 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 +}; diff --git a/source/sourcemod/scripting/include/sdktools.inc b/source/sourcemod/scripting/include/sdktools.inc new file mode 100644 index 0000000..50fcdd3 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools.inc @@ -0,0 +1,232 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2017 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 +#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 */ + SDKCall_Raw, /**< |this| pointer with an arbitrary address */ + SDKCall_Server /**< CBaseServer 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 */ + SDKConf_Address = 2 /**< Read an address from the Addresses 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. + */ +native void StartPrepSDKCall(SDKCallType type); + +/** + * Sets the virtual index of the SDK call if it is virtual. + * + * @param vtblidx Virtual table index. + */ +native void PrepSDKCall_SetVirtual(int 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 char[] signature, int bytes); + +/** + * Uses the given function address for the SDK call. + * + * @param addr Address of function to use. + * @return True on success, false on failure. + */ +native bool PrepSDKCall_SetAddress(Address addr); + +/** + * 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. + * @error Invalid game config Handle. + */ +native bool PrepSDKCall_SetFromConf(Handle gameconf, SDKFuncConfSource source, const char[] 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. + */ +native void PrepSDKCall_SetReturnInfo(SDKType type, SDKPassMethod pass, int decflags=0, int 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. + * @error Parameter limit for SDK calls reached. + */ +native void PrepSDKCall_AddParameter(SDKType type, SDKPassMethod pass, int decflags=0, int 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 ...); + +/** + * Returns the entity index of the player resource/manager entity. + * + * @return Index of resource entity or -1 if not found. + */ +native int GetPlayerResourceEntity(); + +#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/source/sourcemod/scripting/include/sdktools_client.inc b/source/sourcemod/scripting/include/sdktools_client.inc new file mode 100644 index 0000000..885f563 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_client.inc @@ -0,0 +1,52 @@ +/** + * 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_client_included + #endinput +#endif +#define _sdktools_client_included + +/** + * Sets the client to an inactive state waiting for a new map + * + * @param client The client index + * @error Invalid client index. + */ +native void InactivateClient(int client); + +/** + * Reconnect a client without dropping the netchannel + * + * @param client The client index + * @error Invalid client index. + */ +native void ReconnectClient(int client); diff --git a/source/sourcemod/scripting/include/sdktools_engine.inc b/source/sourcemod/scripting/include/sdktools_engine.inc new file mode 100644 index 0000000..95da43a --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_engine.inc @@ -0,0 +1,66 @@ +/** + * 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. + * @error Invalid client or entity, lack of mod support, or client not in + * game. + */ +native void SetClientViewEntity(int client, int 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) + * @error Light style index is out of range. + */ +native void SetLightStyle(int style, const char[] value); + +/** + * Returns the client's eye position. + * + * @param client Player's index. + * @param pos Destination vector to store the client's eye position. + * @error Invalid client index, client not in game, or no mod support. + */ +native void GetClientEyePosition(int client, float pos[3]); diff --git a/source/sourcemod/scripting/include/sdktools_entinput.inc b/source/sourcemod/scripting/include/sdktools_entinput.inc new file mode 100644 index 0000000..64454b3 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_entinput.inc @@ -0,0 +1,51 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2017 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-initialized. + * + * @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(int dest, const char[] input, int activator=-1, int caller=-1, int outputid=0); diff --git a/source/sourcemod/scripting/include/sdktools_entoutput.inc b/source/sourcemod/scripting/include/sdktools_entoutput.inc new file mode 100644 index 0000000..eb5a915 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_entoutput.inc @@ -0,0 +1,108 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2017 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. + * @return Anything other than Plugin_Continue will supress this event, + * returning Plugin_Continue will allow it to propagate the results + * of this output to any entity inputs. + */ +typeset EntityOutput +{ + function void (const char[] output, int caller, int activator, float delay); + function Action (const char[] output, int caller, int 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. + * @error Entity Outputs disabled. + */ +native void HookEntityOutput(const char[] classname, const char[] 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 char[] classname, const char[] 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. + * @error Entity Outputs disabled or Invalid Entity index. + */ +native void HookSingleEntityOutput(int entity, const char[] 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(int entity, const char[] output, EntityOutput callback); + +/** + * Fire a named output on an entity. + * + * After completion (successful or not), the current global variant is re-initialized. + * + * @param caller Entity index from where the output is fired. + * @param output Output name. + * @param activator Entity index which initiated the sequence of actions (-1 for a NULL entity). + * @param delay Delay before firing the output. + * @error Invalid entity index or no mod support. + */ +native void FireEntityOutput(int caller, const char[] output, int activator=-1, float delay=0.0); diff --git a/source/sourcemod/scripting/include/sdktools_functions.inc b/source/sourcemod/scripting/include/sdktools_functions.inc new file mode 100644 index 0000000..742fdf5 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_functions.inc @@ -0,0 +1,418 @@ +/** + * 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(int client, int 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 int GivePlayerItem(int client, const char[] item, int 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 int GetPlayerWeaponSlot(int client, int 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. + * @error Invalid entity or client not in game, or lack of mod support. + */ +native void IgniteEntity(int entity, float time, bool npc=false, float size=0.0, bool level=false); + +/** + * Extinguishes an entity that is on fire. + * + * @param entity Entity index. + * @error Invalid entity or client not in game, or lack of mod support. + */ +native void ExtinguishEntity(int entity); + +/** + * 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. + * @error Invalid entity or client not in game, or lack of mod support. + */ +native void TeleportEntity(int entity, const float origin[3] = NULL_VECTOR, const float angles[3] = NULL_VECTOR, const float velocity[3] = NULL_VECTOR); + +/** + * Forces a player to commit suicide. + * + * @param client Client index. + * @error Invalid client or client not in game, or lack of mod support. + */ +native void ForcePlayerSuicide(int 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. + * @error Invalid client or client not in game, or lack of mod support. + */ +native void SlapPlayer(int client, int health=5, bool sound=true); + +/** + * Searches for an entity by classname. + * + * @param startEnt A valid entity's 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 Invalid start entity or lack of mod support. + */ +native int FindEntityByClassname(int startEnt, const char[] 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 lack of mod support. + */ +native bool GetClientEyeAngles(int 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 (ignored on Orangebox and above). + * @return Entity index on success, or -1 on failure. + * @error Invalid edict index, no map is running, or lack of mod support. + */ +native int CreateEntityByName(const char[] classname, int 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 lack of mod support. + */ +native bool DispatchSpawn(int 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 lack of mod support. + */ +native bool DispatchKeyValue(int entity, const char[] keyName, const char[] value); + +/** + * Dispatches a KeyValue into given entity using an integer value. + * + * @param entity Destination entity index. + * @param keyName Name of the key. + * @param value Integer value. + * @return True on success, false otherwise. + * @error Invalid entity index or lack of mod support. + */ +stock bool DispatchKeyValueInt(int entity, const char[] keyName, int value) +{ + char str[12]; + FormatEx(str, sizeof(str), "%d", value); + + return DispatchKeyValue(entity, keyName, str); +} + +/** + * 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 lack of mod support. + */ +native bool DispatchKeyValueFloat(int entity, const char[] 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 lack of mod support. + */ +native bool DispatchKeyValueVector(int entity, const char[] keyName, const float vec[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 int GetClientAimTarget(int 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 int 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. + * @error Invalid team index. + */ +native void GetTeamName(int index, char[] name, int 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 int GetTeamScore(int 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. + * @error Invalid team index. + */ +native void SetTeamScore(int index, int 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 int GetTeamClientCount(int index); + +/** + * Returns the entity index of a team. + * + * @param teamIndex Team index. + * @return Entity index of team. + * @error Invalid team index. + */ +native int GetTeamEntity(int teamIndex); + +/** + * Sets the model to a given entity. + * + * @param entity Entity index. + * @param model Model name. + * @error Invalid entity index or lack of mod support. + */ +native void SetEntityModel(int entity, const char[] model); + +/** + * Retrieves the decal file name associated with 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(int client, char[] hex, int maxlength); + +/** + * Retrieves the jingle file name associated with a given client. + * + * @param client Player's index. + * @param hex Buffer to store the jingle filename. + * @param maxlength Maximum length of string buffer. + * @return True on success, otherwise false. + * @error Invalid client or client not in game. + */ +native bool GetPlayerJingleFile(int client, char[] hex, int 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. + * @error Lack of mod support. + */ +native void GetServerNetStats(float &inAmount, float &outAmout); + +/** + * Equip's a player's weapon. + * + * @param client Client index. + * @param weapon CBaseCombatWeapon entity index. + * @error Invalid client or entity, lack of mod support, or client not in + * game. + */ +native void EquipPlayerWeapon(int client, int weapon); + +/** + * Activates an entity (CBaseAnimating::Activate) + * + * @param entity Entity index. + * @error Invalid entity or lack of mod support. + */ +native void ActivateEntity(int entity); + +/** + * Sets values to client info buffer keys and notifies the engine of the change. + * The change does not get propagated to mods until the next frame. + * + * @param client Player's index. + * @param key Key string. + * @param value Value string. + * @error Invalid client index, client not connected, or lack of mod support. + */ +native void SetClientInfo(int client, const char[] key, const char[] value); + +/** + * Changes a client's name. + * + * @param client Player's index. + * @param name New name. + * @error Invalid client index, client not connected, or lack of mod support. + */ +native void SetClientName(int client, const char[] name); + +/** + * Gives ammo of a certain type to a player. + * This natives obeys the maximum amount of ammo a player can carry per ammo type. + * + * @param client The client index. + * @param amount Amount of ammo to give. Is capped at ammotype's limit. + * @param ammotype Type of ammo to give to player. + * @param suppressSound If true, don't play the ammo pickup sound. + * @return Amount of ammo actually given. + * @error Lack of mod support. + */ +native int GivePlayerAmmo(int client, int amount, int ammotype, bool suppressSound=false); + +/** + * Changes an entity's collision group (CBaseEntity::SetCollisionGroup). + * + * @param entity The entity index. + * @param collisionGroup Collision group to use. + * @error Invalid entity or lack of mod support. + */ +native void SetEntityCollisionGroup(int entity, int collisionGroup); + +/** + * Recaculates entity collision rules (CBaseEntity::CollisionRulesChanged). + * + * @param entity The entity index. + * @error Invalid entity or lack of mod support. + */ +native void EntityCollisionRulesChanged(int entity); + +/** + * Sets an entity's owner (CBaseEntity::SetEntityOwner). + * + * @param entity The entity index. + * @param owner The owner entity index, can be invalid. + * @error Invalid entity or lack of mod support. + */ +native void SetEntityOwner(int entity, int owner=INVALID_ENT_REFERENCE); + +/** + * Returns the index number of a given named attachment. + * + * @param entity The entity index. + * @param name The attachment name. + * @return An attachment index, or 0 if the attachment name is invalid or unused. + * @error Invalid entity or lack of mod support. + */ +native int LookupEntityAttachment(int entity, const char[] name); + +/** + * Returns the world location and world angles of an attachment. + * + * @param entity The entity index. + * @param attachment The attachment index. + * @param origin Destination vector to store the attachment's origin vector. + * @param angles Destination vector to store the attachment's position angle. + * @return True on success, otherwise false. + * @error Invalid entity or lack of mod support. + */ +native bool GetEntityAttachment(int entity, int attachment, float origin[3], float angles[3]); diff --git a/source/sourcemod/scripting/include/sdktools_gamerules.inc b/source/sourcemod/scripting/include/sdktools_gamerules.inc new file mode 100644 index 0000000..6d07166 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_gamerules.inc @@ -0,0 +1,199 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2011 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_gamerules_included + #endinput +#endif +#define _sdktools_gamerules_included + +enum RoundState { + // initialize the game, create teams + RoundState_Init, + + //Before players have joined the game. Periodically checks to see if enough players are ready + //to start a game. Also reverts to this when there are no active players + RoundState_Pregame, + + //The game is about to start, wait a bit and spawn everyone + RoundState_StartGame, + + //All players are respawned, frozen in place + RoundState_Preround, + + //Round is on, playing normally + RoundState_RoundRunning, + + //Someone has won the round + RoundState_TeamWin, + + //Noone has won, manually restart the game, reset scores + RoundState_Restart, + + //Noone has won, restart the game + RoundState_Stalemate, + + //Game is over, showing the scoreboard etc + RoundState_GameOver, + + //Game is over, doing bonus round stuff + RoundState_Bonus, + + //Between rounds + RoundState_BetweenRounds +}; + +/** + * Retrieves an integer value from a property of the gamerules entity. + * + * @param prop Property name. + * @param size Number of bytes to read (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. + * @param element Element # (starting from 0) if property is an array. + * @return Value at the given property offset. + * @error Prop type is not an integer, or lack of mod support. + */ +native int GameRules_GetProp(const char[] prop, int size=4, int element=0); + +/** + * Sets an integer value for a property of the gamerules entity. + * + * @param prop Property name. + * @param value Value to set. + * @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. + * @param element Element # (starting from 0) if property is an array. + * @param changeState This parameter is ignored. + * @error Prop type is not an integer, or lack of mod support. + */ +native void GameRules_SetProp(const char[] prop, any value, int size=4, int element=0, bool changeState=false); + +/** + * Retrieves a float value from a property of the gamerules entity. + * + * @param prop Property name. + * @param element Element # (starting from 0) if property is an array. + * @return Value at the given property offset. + * @error Prop type is not a float, or lack of mod support. + */ +native float GameRules_GetPropFloat(const char[] prop, int element=0); + +/** + * Sets a float value for a property of the gamerules entity. + * + * @param prop Property name. + * @param value Value to set. + * @param element Element # (starting from 0) if property is an array. + * @param changeState This parameter is ignored. + * @error Prop type is not a float, or lack of mod support. + */ +native void GameRules_SetPropFloat(const char[] prop, float value, int element=0, bool changeState=false); + +/** + * Retrieves a entity index from a property of the gamerules entity. + * + * @param prop Property name. + * @param element Element # (starting from 0) if property is an array. + * @return Entity index at the given property. + * If there is no entity, or the entity is not valid, + * then -1 is returned. + * @error Prop type is not an entity, or lack of mod support. + */ +native int GameRules_GetPropEnt(const char[] prop, int element=0); + +/** + * Sets an entity index for a property of the gamerules entity. + * + * @param prop Property name. + * @param other Entity index to set, or -1 to unset. + * @param element Element # (starting from 0) if property is an array. + * @param changeState This parameter is ignored. + * @error Prop type is not an entity, invalid entity, or lack of mod support. + */ +native void GameRules_SetPropEnt(const char[] prop, int other, int element=0, bool changeState=false); + +/** + * Retrieves a vector of floats from the gamerules entity, given a named network property. + * + * @param prop Property name. + * @param vec Vector buffer to store data in. + * @param element Element # (starting from 0) if property is an array. + * @error Prop type is not a vector, or lack of mod support. + */ +native void GameRules_GetPropVector(const char[] prop, float vec[3], int element=0); + +/** + * Sets a vector of floats in the gamerules entity, given a named network property. + * + * @param prop Property name. + * @param vec Vector to set. + * @param element Element # (starting from 0) if property is an array. + * @param changeState This parameter is ignored. + * @error Prop type is not a vector, or lack of mod support. + */ +native void GameRules_SetPropVector(const char[] prop, const float vec[3], int element=0, bool changeState=false); + +/** + * Gets a gamerules property as a string. + * + * @param prop Property to use. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @param element Element # (starting from 0) if property is an array. + * @return Number of non-null bytes written. + * @error Prop type is not a string, or lack of mod support. + */ +native int GameRules_GetPropString(const char[] prop, char[] buffer, int maxlen, int element=0); + +/** + * Sets a gamerules property as a string. + * + * @param prop Property to use. + * @param buffer String to set. + * @param changeState This parameter is ignored. + * @param element Element # (starting from 0) if property is an array. + * @return Number of non-null bytes written. + * @error Prop type is not a string, or lack of mod support. + */ +native int GameRules_SetPropString(const char[] prop, const char[] buffer, bool changeState=false, int element=0); + +/** + * Gets the current round state. + * + * @return Round state. + * @error Game doesn't support round state. + */ +stock RoundState GameRules_GetRoundState() +{ + return view_as(GameRules_GetProp("m_iRoundState")); +} diff --git a/source/sourcemod/scripting/include/sdktools_hooks.inc b/source/sourcemod/scripting/include/sdktools_hooks.inc new file mode 100644 index 0000000..9c92772 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_hooks.inc @@ -0,0 +1,112 @@ +/** + * 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 + +#define FEATURECAP_PLAYERRUNCMD_11PARAMS "SDKTools PlayerRunCmd 11Params" + +/** + * Called when a clients movement buttons are being processed (Read Only) + * + * @param client Index of the client. + * @param buttons Current commands (as bitflags - see entity_prop_stocks.inc). + * @param impulse 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. + * @param subtype Weapon subtype when selected from a menu. + * @param cmdnum Command number. Increments from the first command sent. + * @param tickcount Tick count. A client's prediction based on the server's GetGameTickCount value. + * @param seed Random seed. Used to determine weapon recoil, spread, and other predicted elements. + * @param mouse Mouse direction (x, y). + */ +forward void OnPlayerRunCmdPre(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]); + +/** + * 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. + * @param subtype Weapon subtype when selected from a menu. + * @param cmdnum Command number. Increments from the first command sent. + * @param tickcount Tick count. A client's prediction based on the server's GetGameTickCount value. + * @param seed Random seed. Used to determine weapon recoil, spread, and other predicted elements. + * @param mouse Mouse direction (x, y). + * @return Plugin_Handled to block the commands from being processed, Plugin_Continue otherwise. + * + * @note To see if all 11 params are available, use FeatureType_Capability and FEATURECAP_PLAYERRUNCMD_11PARAMS. + */ +forward Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]); + +/** + * Called after a clients movement buttons were processed. + * + * @param client Index of the client. + * @param buttons The current commands (as bitflags - see entity_prop_stocks.inc). + * @param impulse 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. + * @param subtype Weapon subtype when selected from a menu. + * @param cmdnum Command number. Increments from the first command sent. + * @param tickcount Tick count. A client's prediction based on the server's GetGameTickCount value. + * @param seed Random seed. Used to determine weapon recoil, spread, and other predicted elements. + * @param mouse Mouse direction (x, y). + */ +forward void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]); + +/** + * Called when a client requests a file from the server. + * + * @param client Client index. + * @param sFile Requested file path. + * + * @return Plugin_Handled to block the transfer, Plugin_Continue to let it proceed. + */ +forward Action OnFileSend(int client, const char[] sFile); + +/** + * Called when a client sends a file to the server. + * + * @param client Client index. + * @param sFile Requested file path. + * + * @return Plugin_Handled to block the transfer, Plugin_Continue to let it proceed. + */ +forward Action OnFileReceive(int client, const char[] sFile); diff --git a/source/sourcemod/scripting/include/sdktools_sound.inc b/source/sourcemod/scripting/include/sdktools_sound.inc new file mode 100644 index 0000000..170b79c --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_sound.inc @@ -0,0 +1,719 @@ +/** + * 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, /**< Refrigerator */ + 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 "sound" folder. + */ +native void PrefetchSound(const char[] name); + +/** + * 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 "sound" folder. + * @return Duration in seconds. + * @deprecated Does not work, may crash. + */ +#pragma deprecated Does not work, may crash. +native float GetSoundDuration(const char[] name); + +/** + * Emits an ambient sound. + * + * @param name Sound file name relative to the "sound" 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. + */ +native void EmitAmbientSound(const char[] name, + const float pos[3], + int entity = SOUND_FROM_WORLD, + int level = SNDLEVEL_NORMAL, + int flags = SND_NOFLAGS, + float vol = SNDVOL_NORMAL, + int 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. + * @error Invalid client index or client not in game. + */ +native void FadeClientVolume(int 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 "sound" folder. + */ +native void StopSound(int entity, int channel, const char[] 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 "sound" 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. + * @error Invalid client index or client not in game. + */ +native void EmitSound(const int[] clients, + int numClients, + const char[] sample, + int entity = SOUND_FROM_PLAYER, + int channel = SNDCHAN_AUTO, + int level = SNDLEVEL_NORMAL, + int flags = SND_NOFLAGS, + float volume = SNDVOL_NORMAL, + int pitch = SNDPITCH_NORMAL, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0, + any ...); + +/** + * Emits a sound or game sound to a list of clients using the latest version of the engine sound interface. + * This native is only available in engines that are greater than or equal to Portal 2. + * + * @param clients Array of client indexes. + * @param numClients Number of clients in the array. + * @param soundEntry Sound entry name. + * @param sample Sound file name relative to the "sound" folder. + * @param entity Entity to emit from. + * @param channel Channel to emit with. + * @param level Sound level. + * @param seed Sound seed. + * @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. + * @error Invalid client index, client not in game, or lack of mod support. + */ +native void EmitSoundEntry(const int[] clients, + int numClients, + const char[] soundEntry, + const char[] sample, + int entity = SOUND_FROM_PLAYER, + int channel = SNDCHAN_AUTO, + int level = SNDLEVEL_NORMAL, + int seed = 0, + int flags = SND_NOFLAGS, + float volume = SNDVOL_NORMAL, + int pitch = SNDPITCH_NORMAL, + int 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 PrecacheSentenceFile). + * @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. + * @error Invalid client index or client not in game. + */ +native void EmitSentence(const int[] clients, + int numClients, + int sentence, + int entity, + int channel = SNDCHAN_AUTO, + int level = SNDLEVEL_NORMAL, + int flags = SND_NOFLAGS, + float volume = SNDVOL_NORMAL, + int pitch = SNDPITCH_NORMAL, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0, + any ...); + +/** + * Calculates gain of sound on given distance with given sound level in decibel + * + * @param soundlevel decibel of sound, like SNDLEVEL_NORMAL or integer value + * @param distance distance of sound to calculate, not meter or feet, but Source Engine`s normal Coordinate unit + * @return gain of sound. you can multiply this with original sound`s volume to calculate volume on given distance + */ +native float GetDistGainFromSoundLevel(int soundlevel, float distance); + +/** + * 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 "sound" 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. + */ +typedef AmbientSHook = function Action ( + char sample[PLATFORM_MAX_PATH], + int &entity, + float &volume, + int &level, + int &pitch, + float pos[3], + int &flags, + float &delay +); + +typeset NormalSHook +{ + // Called when a sound is going to be emitted to one or more clients. + // NOTICE: all params can be overwritten to modify the default behavior. + // + // @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 "sound" 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. + // @param soundEntry Game sound entry name. (Used in engines newer than Portal 2) + // @param seed Sound seed. (Used in engines newer than Portal 2) + // @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it, + // Plugin_Changed when any parameter has been modified. + function Action (int clients[MAXPLAYERS], int &numClients, char sample[PLATFORM_MAX_PATH], + int &entity, int &channel, float &volume, int &level, int &pitch, int &flags, + char soundEntry[PLATFORM_MAX_PATH], int &seed); + + // Deprecated. Use other prototype. + function Action (int clients[64], int &numClients, char sample[PLATFORM_MAX_PATH], + int &entity, int &channel, float &volume, int &level, int &pitch, int &flags, + char soundEntry[PLATFORM_MAX_PATH], int &seed); + + // Deprecated. Use other prototype. + function Action (int clients[64], int &numClients, char sample[PLATFORM_MAX_PATH], + int &entity, int &channel, float &volume, int &level, int &pitch, int &flags); +}; + +/** + * Hooks all played ambient sounds. + * + * @param hook Function to use as a hook. + * @error Invalid function hook. + */ +native void AddAmbientSoundHook(AmbientSHook hook); + +/** + * Hooks all played normal sounds. + * + * @param hook Function to use as a hook. + * @error Invalid function hook. + */ +native void AddNormalSoundHook(NormalSHook hook); + +/** + * Unhooks all played ambient sounds. + * + * @param hook Function used for the hook. + * @error Invalid function hook. + */ +native void RemoveAmbientSoundHook(AmbientSHook hook); + +/** + * Unhooks all played normal sounds. + * + * @param hook Function used for the hook. + * @error Invalid function hook. + */ +native void RemoveNormalSoundHook(NormalSHook hook); + +/** + * Wrapper to emit sound to one client. + * + * @param client Client index. + * @param sample Sound file name relative to the "sound" 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. + * @error Invalid client index or client not in game. + */ +stock void EmitSoundToClient(int client, + const char[] sample, + int entity = SOUND_FROM_PLAYER, + int channel = SNDCHAN_AUTO, + int level = SNDLEVEL_NORMAL, + int flags = SND_NOFLAGS, + float volume = SNDVOL_NORMAL, + int pitch = SNDPITCH_NORMAL, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0) +{ + int 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 "sound" 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. + * @error Invalid client index. + */ +stock void EmitSoundToAll(const char[] sample, + int entity = SOUND_FROM_PLAYER, + int channel = SNDCHAN_AUTO, + int level = SNDLEVEL_NORMAL, + int flags = SND_NOFLAGS, + float volume = SNDVOL_NORMAL, + int pitch = SNDPITCH_NORMAL, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0) +{ + int[] clients = new int[MaxClients]; + int total = 0; + + for (int i=1; i<=MaxClients; i++) + { + if (IsClientInGame(i)) + { + clients[total++] = i; + } + } + + if (total) + { + 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 int ATTN_TO_SNDLEVEL(float attn) +{ + if (attn > 0.0) + { + return RoundFloat(50.0 + (20.0 / attn)); + } + return 0; +} + +/** + * Retrieves the parameters for a game sound. + * + * Game sounds are found in a game's scripts/game_sound.txt or other files + * referenced from it + * + * Note that if a game sound has a rndwave section, one of them will be returned + * at random. + * + * @param gameSound Name of game sound. + * @param channel Channel to emit with. + * @param level Sound level. + * @param volume Sound volume. + * @param pitch Sound pitch. + * @param sample Sound file name relative to the "sound" folder. + * @param maxlength Maximum length of sample string buffer. + * @param entity Entity the sound is being emitted from. + * @return True if the sound was successfully retrieved, false if it + * was not found + */ +native bool GetGameSoundParams(const char[] gameSound, + int &channel, + int &soundLevel, + float &volume, + int &pitch, + char[] sample, + int maxlength, + int entity=SOUND_FROM_PLAYER); + +/** + * Emits a game sound to a list of clients. + * + * Game sounds are found in a game's scripts/game_sound.txt or other files + * referenced from it + * + * Note that if a game sound has a rndwave section, one of them will be returned + * at random. + * + * @param clients Array of client indexes. + * @param numClients Number of clients in the array. + * @param gameSound Name of game sound. + * @param entity Entity to emit from. + * @param flags Sound flags. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @return True if the sound was played successfully, false if it failed + * @error Invalid client index or client not in game. + */ +stock bool EmitGameSound(const int[] clients, + int numClients, + const char[] gameSound, + int entity = SOUND_FROM_PLAYER, + int flags = SND_NOFLAGS, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0) +{ + int channel; + int level; + float volume; + int pitch; + char sample[PLATFORM_MAX_PATH]; + + if (GetGameSoundParams(gameSound, channel, level, volume, pitch, sample, sizeof(sample), entity)) + { + EmitSound(clients, numClients, sample, entity, channel, level, flags, volume, pitch, speakerentity, origin, dir, updatePos, soundtime); + return true; + } + + return false; +} + +/** + * Emits an ambient game sound. + * + * Game sounds are found in a game's scripts/game_sound.txt or other files + * referenced from it + * + * Note that if a game sound has a rndwave section, one of them will be returned + * at random. + * + * @param gameSound Name of game sound. + * @param pos Origin of sound. + * @param entity Entity index to associate sound with. + * @param flags Sound flags. + * @param delay Play delay. + */ +stock bool EmitAmbientGameSound(const char[] gameSound, + const float pos[3], + int entity = SOUND_FROM_WORLD, + int flags = SND_NOFLAGS, + float delay = 0.0) +{ + int channel; // This is never actually used for Ambients, but it's a mandatory field to GetGameSoundParams + int level; + float volume; + int pitch; + char sample[PLATFORM_MAX_PATH]; + + if (GetGameSoundParams(gameSound, channel, level, volume, pitch, sample, sizeof(sample), entity)) + { + EmitAmbientSound(sample, pos, entity, level, flags, volume, pitch, delay); + return true; + } + + return false; +} + +/** + * Wrapper to emit a game sound to one client. + * + * Game sounds are found in a game's scripts/game_sound.txt or other files + * referenced from it + * + * Note that if a game sound has a rndwave section, one of them will be returned + * at random. + * + * @param client Client index. + * @param gameSound Name of game sound. + * @param entity Entity to emit from. + * @param flags Sound flags. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @error Invalid client index or client not in game. + */ +stock bool EmitGameSoundToClient(int client, + const char[] gameSound, + int entity = SOUND_FROM_PLAYER, + int flags = SND_NOFLAGS, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0) +{ + int clients[1]; + clients[0] = client; + /* Save some work for SDKTools and remove SOUND_FROM_PLAYER references */ + entity = (entity == SOUND_FROM_PLAYER) ? client : entity; + return EmitGameSound(clients, 1, gameSound, entity, flags, + speakerentity, origin, dir, updatePos, soundtime); +} + +/** + * Wrapper to emit game sound to all clients. + * + * Game sounds are found in a game's scripts/game_sound.txt or other files + * referenced from it + * + * Note that if a game sound has a rndwave section, one of them will be returned + * at random. + * + * @param gameSound Name of game sound. + * @param entity Entity to emit from. + * @param flags Sound flags. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @error Invalid client index. + */ +stock bool EmitGameSoundToAll(const char[] gameSound, + int entity = SOUND_FROM_PLAYER, + int flags = SND_NOFLAGS, + int speakerentity = -1, + const float origin[3] = NULL_VECTOR, + const float dir[3] = NULL_VECTOR, + bool updatePos = true, + float soundtime = 0.0) +{ + int[] clients = new int[MaxClients]; + int total = 0; + + for (int i=1; i<=MaxClients; i++) + { + if (IsClientInGame(i)) + { + clients[total++] = i; + } + } + + if (!total) + { + return false; + } + + return EmitGameSound(clients, total, gameSound, entity, flags, + speakerentity, origin, dir, updatePos, soundtime); +} + +/** + * Precache a game sound. + * + * Most games will precache all game sounds on map start, but this is not guaranteed... + * Team Fortress 2 is known to not pre-cache MvM game mode sounds on non-MvM maps. + * + * Due to the above, this native should be called before any calls to GetGameSoundParams, + * EmitGameSound*, or EmitAmbientGameSound. + * + * It should be safe to pass already precached game sounds to this function. + * + * Note: It precaches all files for a game sound. + * + * @param soundname Game sound to precache + * @return True if the game sound was found, false if sound did not exist + * or had no files + */ +native bool PrecacheScriptSound(const char[] soundname); diff --git a/source/sourcemod/scripting/include/sdktools_stocks.inc b/source/sourcemod/scripting/include/sdktools_stocks.inc new file mode 100644 index 0000000..9417938 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_stocks.inc @@ -0,0 +1,75 @@ +/** + * 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 int FindTeamByName(const char[] name) +{ + int name_len = strlen(name); + int num_teams = GetTeamCount(); + char team_name[32]; + int found_team = -1; + + for (int 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/source/sourcemod/scripting/include/sdktools_stringtables.inc b/source/sourcemod/scripting/include/sdktools_stringtables.inc new file mode 100644 index 0000000..346fb33 --- /dev/null +++ b/source/sourcemod/scripting/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 int FindStringTable(const char[] name); + +/** + * Returns the number of string tables that currently exist. + * + * @return Number of string tables that currently exist. + */ +native int 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 int GetStringTableNumStrings(int 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 int GetStringTableMaxStrings(int 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 int GetStringTableName(int tableidx, char[] name, int maxlength); + +/** + * Searches for the index of a given string in a string table. + * + * @param tableidx A string table index. + * @param str String to find. + * @return String index if found, INVALID_STRING_INDEX otherwise. + * @error Invalid string table index. + */ +native int FindStringIndex(int tableidx, const char[] str); + +/** + * Retrieves the string at a given index of a string table. + * + * @param tableidx A string table index. + * @param stringidx A string index. + * @param str 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 int ReadStringTable(int tableidx, int stringidx, char[] str, int 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 int GetStringTableDataLength(int tableidx, int 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 (binary safe, includes the null terminator). + * @error Invalid string table index or string index. + */ +native int GetStringTableData(int tableidx, int stringidx, char[] userdata, int 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. + * @error Invalid string table index or string index. + */ +native void SetStringTableData(int tableidx, int stringidx, const char[] userdata, int length); + +/** + * Adds a string to a given string table. + * + * @param tableidx A string table index. + * @param str 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. + * @error Invalid string table index. + */ +native void AddToStringTable(int tableidx, const char[] str, const char[] userdata="", int 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 void AddFileToDownloadsTable(const char[] filename) +{ + static int table = INVALID_STRING_TABLE; + + if (table == INVALID_STRING_TABLE) + { + table = FindStringTable("downloadables"); + } + + bool save = LockStringTables(false); + AddToStringTable(table, filename); + LockStringTables(save); +} diff --git a/source/sourcemod/scripting/include/sdktools_tempents.inc b/source/sourcemod/scripting/include/sdktools_tempents.inc new file mode 100644 index 0000000..4da84e2 --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_tempents.inc @@ -0,0 +1,232 @@ +/** + * 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. + */ +typedef TEHook = function Action (const char[] te_name, const int[] Players, int numClients, float delay); + +/** + * Hooks a temp entity. + * + * @param te_name TE name to hook. + * @param hook Function to use as a hook. + * @error Temp Entity name not available or invalid function hook. + */ +native void AddTempEntHook(const char[] te_name, TEHook hook); + +/** + * Removes a temp entity hook. + * + * @param te_name TE name to unhook. + * @param hook Function used for the hook. + * @error Temp Entity name not available or invalid function hook. + */ +native void RemoveTempEntHook(const char[] te_name, TEHook hook); + +/** + * Starts a temp entity transmission. + * + * @param te_name TE name. + * @error Temp Entity name not available. + */ +native void TE_Start(const char[] 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 char[] prop); + +/** + * Sets an integer value in the current temp entity. + * + * @param prop Property to use. + * @param value Integer value to set. + * @error Property not found. + */ +native void TE_WriteNum(const char[] prop, int value); + +/** + * Reads an integer value in the current temp entity. + * + * @param prop Property to use. + * @return Property value. + * @error Property not found. + */ +native int TE_ReadNum(const char[] prop); + +/** + * Sets a floating point number in the current temp entity. + * + * @param prop Property to use. + * @param value Floating point number to set. + * @error Property not found. + */ +native void TE_WriteFloat(const char[] prop, float value); + +/** + * Reads a floating point number in the current temp entity. + * + * @param prop Property to use. + * @return Property value. + * @error Property not found. + */ +native float TE_ReadFloat(const char[] prop); + +/** + * Sets a vector in the current temp entity. + * + * @param prop Property to use. + * @param vector Vector to set. + * @error Property not found. + */ +native void TE_WriteVector(const char[] prop, const float vector[3]); + +/** + * Reads a vector in the current temp entity. + * + * @param prop Property to use. + * @param vector Vector to read. + * @error Property not found. + */ +native void TE_ReadVector(const char[] prop, float vector[3]); + +/** + * Sets a QAngle in the current temp entity. + * + * @param prop Property to use. + * @param angles Angles to set. + * @error Property not found. + */ +native void TE_WriteAngles(const char[] 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. + * @error Property not found. + */ +native void TE_WriteFloatArray(const char[] prop, const float[] array, int 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. + * @error Invalid client index or client not in game. + */ +native void TE_Send(const int[] clients, int 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. + * @error Property not found. + */ +stock void TE_WriteEncodedEnt(const char[] prop, int value) +{ + int encvalue = (value & 0x0FFF) | ((1 & 0xF)<<12); + 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. + */ +stock void TE_SendToAll(float delay=0.0) +{ + int total = 0; + int[] clients = new int[MaxClients]; + for (int i=1; i<=MaxClients; i++) + { + if (IsClientInGame(i)) + { + clients[total++] = i; + } + } + 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. + * @error Invalid client index or client not in game. + */ +stock void TE_SendToClient(int client, float delay=0.0) +{ + int players[1]; + + players[0] = client; + + TE_Send(players, 1, delay); +} + +/** + * Sends the current TE to all clients that are in + * visible or audible range of the origin. + * @note See TE_Start(). + * @note See GetClientsInRange() + * + * @param origin Coordinates from which to test range. + * @param rangeType Range type to use for filtering clients. + * @param delay Delay in seconds to send the TE. + */ +stock void TE_SendToAllInRange(const float origin[3], ClientRangeType rangeType, float delay=0.0) +{ + int[] clients = new int[MaxClients]; + int total = GetClientsInRange(origin, rangeType, clients, MaxClients); + TE_Send(clients, total, delay); +} diff --git a/source/sourcemod/scripting/include/sdktools_tempents_stocks.inc b/source/sourcemod/scripting/include/sdktools_tempents_stocks.inc new file mode 100644 index 0000000..75dfc5e --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_tempents_stocks.inc @@ -0,0 +1,443 @@ +/** + * 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. + */ +stock void TE_SetupSparks(const float pos[3], const float dir[3], int Magnitude, int 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. + */ +stock void TE_SetupSmoke(const float pos[3], int Model, float Scale, int 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. + */ +stock void 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). + */ +stock void TE_SetupMuzzleFlash(const float pos[3], const float angles[3], float Scale, int 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. + */ +stock void 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. + */ +stock void 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 Direction of the armor ricochet. + */ +stock void 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. + */ +stock void TE_SetupGlowSprite(const float pos[3], int Model, float Life, float Size, int 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. + */ +stock void TE_SetupExplosion(const float pos[3], int Model, float Scale, int Framerate, int Flags, int Radius, int Magnitude, const float normal[3]={0.0, 0.0, 1.0}, int 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. + */ +stock void TE_SetupBloodSprite(const float pos[3], const float dir[3], const int color[4], int Size, int SprayModel, int 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 Initial 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. + */ +stock void TE_SetupBeamRingPoint(const float center[3], float Start_Radius, float End_Radius, int ModelIndex, int HaloIndex, int StartFrame, + int FrameRate, float Life, float Width, float Amplitude, const int Color[4], int Speed, int 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 Initial 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. + */ +stock void TE_SetupBeamPoints(const float start[3], const float end[3], int ModelIndex, int HaloIndex, int StartFrame, int FrameRate, float Life, + float Width, float EndWidth, int FadeLength, float Amplitude, const int Color[4], int 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 Initial 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. + */ +stock void TE_SetupBeamLaser(int StartEntity, int EndEntity, int ModelIndex, int HaloIndex, int StartFrame, int FrameRate, float Life, + float Width, float EndWidth, int FadeLength, float Amplitude, const int Color[4], int 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 Initial 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. + */ +stock void TE_SetupBeamRing(int StartEntity, int EndEntity, int ModelIndex, int HaloIndex, int StartFrame, int FrameRate, float Life, float Width, float Amplitude, const int Color[4], int Speed, int 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). + */ +stock void TE_SetupBeamFollow(int EntIndex, int ModelIndex, int HaloIndex, float Life, float Width, float EndWidth, int FadeLength, const int 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/source/sourcemod/scripting/include/sdktools_trace.inc b/source/sourcemod/scripting/include/sdktools_trace.inc new file mode 100644 index 0000000..3c4592d --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_trace.inc @@ -0,0 +1,716 @@ +/** + * 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 bsp-ing 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 + */ + +/** + * @section Surface flags. + */ + +#define SURF_LIGHT 0x0001 /**< value will hold the light strength */ +#define SURF_SKY2D 0x0002 /**< don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox */ +#define SURF_SKY 0x0004 /**< don't draw, but add to skybox */ +#define SURF_WARP 0x0008 /**< turbulent water warp */ +#define SURF_TRANS 0x0010 +#define SURF_NOPORTAL 0x0020 /**< the surface can not have a portal placed on it */ +#define SURF_TRIGGER 0x0040 /**< This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders */ +#define SURF_NODRAW 0x0080 /**< don't bother referencing the texture */ + +#define SURF_HINT 0x0100 /**< make a primary bsp splitter */ + +#define SURF_SKIP 0x0200 /**< completely ignore, allowing non-closed brushes */ +#define SURF_NOLIGHT 0x0400 /**< Don't calculate light */ +#define SURF_BUMPLIGHT 0x0800 /**< calculate three lightmaps for the surface for bumpmapping */ +#define SURF_NOSHADOWS 0x1000 /**< Don't receive shadows */ +#define SURF_NODECALS 0x2000 /**< Don't receive decals */ +#define SURF_NOCHOP 0x4000 /**< Don't subdivide patches on this surface */ +#define SURF_HITBOX 0x8000 /**< surface is part of a hitbox */ + +/** + * @endsection + */ + +/** + * @section Partition masks. + */ + +#define PARTITION_SOLID_EDICTS (1 << 1) /**< every edict_t that isn't SOLID_TRIGGER or SOLID_NOT (and static props) */ +#define PARTITION_TRIGGER_EDICTS (1 << 2) /**< every edict_t that IS SOLID_TRIGGER */ +#define PARTITION_NON_STATIC_EDICTS (1 << 5) /**< everything in solid & trigger except the static props, includes SOLID_NOTs */ +#define PARTITION_STATIC_PROPS (1 << 7) + +/** + * @endsection + */ + +/** + * @section Displacement flags. + */ + +#define DISPSURF_FLAG_SURFACE (1<<0) +#define DISPSURF_FLAG_WALKABLE (1<<1) +#define DISPSURF_FLAG_BUILDABLE (1<<2) +#define DISPSURF_FLAG_SURFPROP1 (1<<3) +#define DISPSURF_FLAG_SURFPROP2 (1<<4) + +/** + * @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. */ +}; + +typeset 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. + */ + function bool (int entity, int 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. + */ + function bool (int entity, int contentsMask, any data); +}; + +typeset TraceEntityEnumerator +{ + /** + * Called for each entity enumerated with EnumerateEntities*. + * + * @param entity Entity index. + * @return True to continue enumerating, otherwise false. + */ + function bool (int entity); + + /** + * Called for each entity enumerated with EnumerateEntities*. + * + * @param entity Entity index. + * @param data Data value, if used. + * @return True to continue enumerating, otherwise false. */ + function bool (int entity, 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 int TR_GetPointContents(const float pos[3], int &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. + * @error Invalid entity. + */ +native int TR_GetPointContentsEnt(int 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. + */ +native void TR_TraceRay(const float pos[3], + const float vec[3], + int 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. + */ +native void TR_TraceHull(const float pos[3], + const float vec[3], + const float mins[3], + const float maxs[3], + int flags); + +/** + * Enumerates over entities along a ray. This may find entities that are + * close to the ray but do not actually intersect it. Use TR_Clip*RayToEntity + * with TR_DidHit to check if the ray actually intersects the entity. + * + * @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 mask Mask to use for the trace. See PARTITION_* flags. + * @param rtype Method to calculate the ray direction. + * @param enumerator Function to use as enumerator. For each entity found + * along the ray, this function is called. + * @param data Arbitrary data value to pass through to the enumerator. + */ +native void TR_EnumerateEntities(const float pos[3], + const float vec[3], + int mask, + RayType rtype, + TraceEntityEnumerator enumerator, + any data=0); + +/** + * Enumerates over entities along a ray hull. This may find entities that are + * close to the ray but do not actually intersect it. Use TR_Clip*RayToEntity + * with TR_DidHit to check if the ray actually intersects the entity. + * + * @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 mask Mask to use for the trace. See PARTITION_* flags. + * @param enumerator Function to use as enumerator. For each entity found + * along the ray, this function is called. + * @param data Arbitrary data value to pass through to the enumerator. + */ +native void TR_EnumerateEntitiesHull(const float pos[3], + const float vec[3], + const float mins[3], + const float maxs[3], + int mask, + TraceEntityEnumerator enumerator, + any data=0); + +/** + * Enumerates over entities in a sphere. + * + * @param pos Starting position of the ray. + * @param radius Radius of the ray. + * @param mask Mask to use for the trace. See PARTITION_* flags. + * @param enumerator Function to use as enumerator. For each entity found + * along the ray, this function is called. + * @param data Arbitrary data value to pass through to the enumerator. + */ +native void TR_EnumerateEntitiesSphere(const float pos[3], + float radius, + int mask, + TraceEntityEnumerator enumerator, + any data=0); + +/** + * Enumerates over entities in a box. + * + * @param mins Box minimum size. + * @param maxs Box maximum size. + * @param mask Mask to use for the trace. See PARTITION_* flags. + * @param enumerator Function to use as enumerator. For each entity found + * along the box, this function is called. + * @param data Arbitrary data value to pass through to the enumerator. + */ +native void TR_EnumerateEntitiesBox(const float mins[3], + const float maxs[3], + int mask, + TraceEntityEnumerator enumerator, + any data=0); + +/** + * Enumerates over entities at point. + * + * @param pos Position of the point. + * @param mask Mask to use for the trace. See PARTITION_* flags. + * @param enumerator Function to use as enumerator. For each entity found + * along the point, this function is called. + * @param data Arbitrary data value to pass through to the enumerator. + */ +native void TR_EnumerateEntitiesPoint(const float pos[3], + int mask, + TraceEntityEnumerator enumerator, + any data=0); + +/** + * 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. + */ +native void TR_TraceRayFilter(const float pos[3], + const float vec[3], + int 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 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. + */ +native void TR_TraceHullFilter(const float pos[3], + const float vec[3], + const float mins[3], + const float maxs[3], + int flags, + TraceEntityFilter filter, + any data=0); + +/** + * Clips a ray to a particular entity. + * + * @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 entity Entity to clip to. + * @error Invalid entity. + */ +native void TR_ClipRayToEntity(const float pos[3], + const float vec[3], + int flags, + RayType rtype, + int entity); + +/** + * Clips a ray hull to a particular entity. + * + * @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 entity Entity to clip to. + * @error Invalid entity. + */ +native void TR_ClipRayHullToEntity(const float pos[3], + const float vec[3], + const float mins[3], + const float maxs[3], + int flags, + int entity); + +/** + * Clips the current global ray (or hull) to a particular entity. + * + * @param flags Trace flags. + * @param entity Entity to clip to. + * @error Invalid entity. + */ +native void TR_ClipCurrentRayToEntity(int flags, int entity); + +/** + * 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], + int 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], + int 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], + int 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], + int flags, + TraceEntityFilter filter, + any data=0); + +/** + * Clips a ray to a particular entity. + * + * @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 entity Entity to clip to. + * @return Ray trace handle, which must be closed via CloseHandle(). + * @error Invalid entity. + */ +native Handle TR_ClipRayToEntityEx(const float pos[3], + const float vec[3], + int flags, + RayType rtype, + int entity); + +/** + * Clips a ray hull to a particular entity. + * + * @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 entity Entity to clip to. + * @return Ray trace handle, which must be closed via CloseHandle(). + * @error Invalid entity. + */ +native Handle TR_ClipRayHullToEntityEx(const float pos[3], + const float vec[3], + const float mins[3], + const float maxs[3], + int flags, + int entity); + +/** + * Clips the current global ray (or hull) to a particular entity. + * + * @param flags Trace flags. + * @param entity Entity to clip to. + * @return Ray trace handle, which must be closed via CloseHandle(). + * @error Invalid entity. + */ +native Handle TR_ClipCurrentRayToEntityEx(int flags, int entity); + +/** + * 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 time fraction from a trace result when it left a solid. + * Only valid if trace started in solid + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Time fraction left solid value of the trace. + * @error Invalid Handle. + */ +native float TR_GetFractionLeftSolid(Handle hndl=INVALID_HANDLE); + +/** + * Returns the starting position of a trace. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @param pos Vector buffer to store data in. + * @error Invalid Handle. + */ +native void TR_GetStartPosition(Handle hndl, float pos[3]); + +/** + * 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. + * @error Invalid Handle. + */ +native void 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 int TR_GetEntityIndex(Handle hndl=INVALID_HANDLE); + +/** + * Returns the displacement flags for the surface that was hit. See DISPSURF_FLAG_*. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Displacement flags. + * @error Invalid Handle. + */ +native int TR_GetDisplacementFlags(Handle hndl=INVALID_HANDLE); + +/** + * Returns the name of the surface that was hit. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @param buffer Buffer to store surface name in + * @param maxlen Maximum length of output buffer + * @error Invalid Handle. + */ +native void TR_GetSurfaceName(Handle hndl, char[] buffer, int maxlen); + +/** + * Returns the surface properties index of the surface that was hit. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Surface props. + * @error Invalid Handle. + */ +native int TR_GetSurfaceProps(Handle hndl=INVALID_HANDLE); + +/** + * Returns the surface flags. See SURF_*. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Surface flags. + * @error Invalid Handle. + */ +native int TR_GetSurfaceFlags(Handle hndl=INVALID_HANDLE); + +/** + * Returns the index of the physics bone that was hit. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Physics bone index. + * @error Invalid Handle. + */ +native int TR_GetPhysicsBone(Handle hndl=INVALID_HANDLE); + +/** + * Returns whether the entire trace was in a solid area. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return True if entire trace was in a solid area, otherwise false. + * @error Invalid Handle. + */ +native bool TR_AllSolid(Handle hndl=INVALID_HANDLE); + +/** + * Returns whether the initial point was in a solid area. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return True if initial point was in a solid area, otherwise false. + * @error Invalid Handle. + */ +native bool TR_StartSolid(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 int TR_GetHitGroup(Handle hndl=INVALID_HANDLE); + +/** + * Returns in which hitbox the trace collided if any. + * + * Note: if the entity that collided with the trace is the world entity, + * then this function doesn't return an hitbox index but a static prop index. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Hitbox index (Or static prop index). + * @error Invalid Handle. + */ +native int TR_GetHitBoxIndex(Handle hndl=INVALID_HANDLE); + +/** + * Find the normal vector to the collision 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 + * @error Invalid Handle + */ +native void 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 bool TR_PointOutsideWorld(float pos[3]); diff --git a/source/sourcemod/scripting/include/sdktools_variant_t.inc b/source/sourcemod/scripting/include/sdktools_variant_t.inc new file mode 100644 index 0000000..71bfced --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_variant_t.inc @@ -0,0 +1,93 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2017 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_variant_t_included + #endinput +#endif +#define _sdktools_variant_t_included + +/** + * Sets a bool value in the global variant object. + * + * @param val Input value. + */ +native void SetVariantBool(bool val); + +/** + * Sets a string in the global variant object. + * + * @param str Input string. + */ +native void SetVariantString(const char[] str); + +/** + * Sets an integer value in the global variant object. + * + * @param val Input value. + */ +native void SetVariantInt(int val); + +/** + * Sets a floating point value in the global variant object. + * + * @param val Input value. + */ +native void SetVariantFloat(float val); + +/** + * Sets a 3D vector in the global variant object. + * + * @param vec Input vector. + */ +native void SetVariantVector3D(const float vec[3]); + +/** + * Sets a 3D position vector in the global variant object. + * + * @param vec Input position vector. + */ +native void SetVariantPosVector3D(const float vec[3]); + +/** + * Sets a color in the global variant object. + * + * @param color Input color. + */ +native void SetVariantColor(const int color[4]); + +/** + * Sets an entity in the global variant object. + * + * @param entity Entity index. + * @error Invalid entity index. + */ +native void SetVariantEntity(int entity); diff --git a/source/sourcemod/scripting/include/sdktools_voice.inc b/source/sourcemod/scripting/include/sdktools_voice.inc new file mode 100644 index 0000000..6bcaf3d --- /dev/null +++ b/source/sourcemod/scripting/include/sdktools_voice.inc @@ -0,0 +1,143 @@ +/** + * 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 */ +}; + +/** + * Called when a client is speaking. + * + * @param client The client index + */ +forward void OnClientSpeaking(int client); + +/** + * Called once a client speaking end. + * + * @param client The client index + */ +forward void OnClientSpeakingEnd(int client); + +/** + * Set the client listening flags. + * + * @param client The client index + * @param flags The voice flags + * @error Invalid client index or client not connected. + */ +native void SetClientListeningFlags(int client, int flags); + +/** + * Retrieve the client current listening flags. + * + * @param client The client index + * @return The current voice flags + * @error Invalid client index or client not connected. + */ +native int GetClientListeningFlags(int client); + +/** + * Set the receiver ability to listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @param bListen True if the receiver can listen to the sender, false otherwise. + * @return True if successful otherwise false. + * @deprecated Use SetListenOverride() instead. + */ +#pragma deprecated Use SetListenOverride() instead +native bool SetClientListening(int iReceiver, int 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. + * @deprecated GetListenOverride() instead. + */ +#pragma deprecated GetListenOverride() instead +native bool GetClientListening(int iReceiver, int iSender); + +/** + * Override the receiver's ability to listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @param override The override of the receiver's ability to listen to the sender. + * @return True if successful otherwise false. + * @error Listener or sender client index is invalid or not connected. + */ +native bool SetListenOverride(int iReceiver, int 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. + * @error Listener or sender client index is invalid or not connected. + */ +native ListenOverride GetListenOverride(int iReceiver, int 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. + * @error Muter or mutee client index is invalid or not connected. + */ +native bool IsClientMuted(int iMuter, int iMutee); diff --git a/source/sourcemod/scripting/include/smjansson.inc b/source/sourcemod/scripting/include/smjansson.inc new file mode 100644 index 0000000..029a492 --- /dev/null +++ b/source/sourcemod/scripting/include/smjansson.inc @@ -0,0 +1,1328 @@ +#if defined _jansson_included_ + #endinput +#endif +#define _jansson_included_ + + +/** + * --- Type + * + * The JSON specification (RFC 4627) defines the following data types: + * object, array, string, number, boolean, and null. + * JSON types are used dynamically; arrays and objects can hold any + * other data type, including themselves. For this reason, Jansson�s + * type system is also dynamic in nature. There�s one Handle type to + * represent all JSON values, and the referenced structure knows the + * type of the JSON value it holds. + * + */ +enum json_type { + JSON_OBJECT, + JSON_ARRAY, + JSON_STRING, + JSON_INTEGER, + JSON_REAL, + JSON_TRUE, + JSON_FALSE, + JSON_NULL +} + +/** + * Return the type of the JSON value. + * + * @param hObj Handle to the JSON value + * + * @return json_type of the value. + */ +native json_type:json_typeof(Handle:hObj); + +/** + * The type of a JSON value is queried and tested using these macros + * + * @param %1 Handle to the JSON value + * + * @return True if the value has the correct type. + */ +#define json_is_object(%1) ( json_typeof(%1) == JSON_OBJECT ) +#define json_is_array(%1) ( json_typeof(%1) == JSON_ARRAY ) +#define json_is_string(%1) ( json_typeof(%1) == JSON_STRING ) +#define json_is_integer(%1) ( json_typeof(%1) == JSON_INTEGER ) +#define json_is_real(%1) ( json_typeof(%1) == JSON_REAL ) +#define json_is_true(%1) ( json_typeof(%1) == JSON_TRUE ) +#define json_is_false(%1) ( json_typeof(%1) == JSON_FALSE ) +#define json_is_null(%1) ( json_typeof(%1) == JSON_NULL ) +#define json_is_number(%1) ( json_typeof(%1) == JSON_INTEGER || json_typeof(%1) == JSON_REAL ) +#define json_is_boolean(%1) ( json_typeof(%1) == JSON_TRUE || json_typeof(%1) == JSON_FALSE ) + +/** + * Saves json_type as a String in output + * + * @param input json_type value to convert to string + * @param output Buffer to store the json_type value + * @param maxlength Maximum length of string buffer. + * + * @return False if the type does not exist. + */ +stock bool:Stringify_json_type(json_type:input, String:output[], maxlength) { + switch(input) { + case JSON_OBJECT: strcopy(output, maxlength, "Object"); + case JSON_ARRAY: strcopy(output, maxlength, "Array"); + case JSON_STRING: strcopy(output, maxlength, "String"); + case JSON_INTEGER: strcopy(output, maxlength, "Integer"); + case JSON_REAL: strcopy(output, maxlength, "Real"); + case JSON_TRUE: strcopy(output, maxlength, "True"); + case JSON_FALSE: strcopy(output, maxlength, "False"); + case JSON_NULL: strcopy(output, maxlength, "Null"); + default: return false; + } + + return true; +} + + + +/** + * --- Equality + * + * - Two integer or real values are equal if their contained numeric + * values are equal. An integer value is never equal to a real value, + * though. + * - Two strings are equal if their contained UTF-8 strings are equal, + * byte by byte. Unicode comparison algorithms are not implemented. + * - Two arrays are equal if they have the same number of elements and + * each element in the first array is equal to the corresponding + * element in the second array. + * - Two objects are equal if they have exactly the same keys and the + * value for each key in the first object is equal to the value of + * the corresponding key in the second object. + * - Two true, false or null values have no "contents", so they are + * equal if their types are equal. + * + */ + +/** + * Test whether two JSON values are equal. + * + * @param hObj Handle to the first JSON object + * @param hOther Handle to the second JSON object + * + * @return Returns false if they are inequal or one + * or both of the pointers are NULL. + */ +native bool:json_equal(Handle:hObj, Handle:hOther); + + + + +/** + * --- Copying + * + * Jansson supports two kinds of copying: shallow and deep. There is + * a difference between these methods only for arrays and objects. + * + * Shallow copying only copies the first level value (array or object) + * and uses the same child values in the copied value. + * + * Deep copying makes a fresh copy of the child values, too. Moreover, + * all the child values are deep copied in a recursive fashion. + * + */ + +/** + * Get a shallow copy of the passed object + * + * @param hObj Handle to JSON object to be copied + * + * @return Returns a shallow copy of the object, + * or INVALID_HANDLE on error. + */ +native Handle:json_copy(Handle:hObj); + +/** + * Get a deep copy of the passed object + * + * @param hObj Handle to JSON object to be copied + * + * @return Returns a deep copy of the object, + * or INVALID_HANDLE on error. + */ +native Handle:json_deep_copy(Handle:hObj); + + + + +/** + * --- Objects + * + * A JSON object is a dictionary of key-value pairs, where the + * key is a Unicode string and the value is any JSON value. + * + */ + +/** + * Returns a handle to a new JSON object, or INVALID_HANDLE on error. + * Initially, the object is empty. + * + * @return Handle to a new JSON object. + */ +native Handle:json_object(); + +/** + * Returns the number of elements in hObj + * + * @param hObj Handle to JSON object + * + * @return Number of elements in hObj, + * or 0 if hObj is not a JSON object. + */ +native json_object_size(Handle:hObj); + +/** + * Get a value corresponding to sKey from hObj + * + * @param hObj Handle to JSON object to get a value from + * @param sKey Key to retrieve + * + * @return Handle to a the JSON object or + * INVALID_HANDLE on error. + */ +native Handle:json_object_get(Handle:hObj, const String:sKey[]); + +/** + * Set the value of sKey to hValue in hObj. + * If there already is a value for key, it is replaced by the new value. + * + * @param hObj Handle to JSON object to set a value on + * @param sKey Key to store in the object + * Must be a valid null terminated UTF-8 encoded + * Unicode string. + * @param hValue Value to store in the object + * + * @return True on success. + */ +native bool:json_object_set(Handle:hObj, const String:sKey[], Handle:hValue); + +/** + * Set the value of sKey to hValue in hObj. + * If there already is a value for key, it is replaced by the new value. + * This function automatically closes the Handle to the value object. + * + * @param hObj Handle to JSON object to set a value on + * @param sKey Key to store in the object + * Must be a valid null terminated UTF-8 encoded + * Unicode string. + * @param hValue Value to store in the object + * + * @return True on success. + */ +native bool:json_object_set_new(Handle:hObj, const String:sKey[], Handle:hValue); + +/** + * Delete sKey from hObj if it exists. + * + * @param hObj Handle to JSON object to delete a key from + * @param sKey Key to delete + * + * @return True on success. + */ +native bool:json_object_del(Handle:hObj, const String:sKey[]); + +/** + * Remove all elements from hObj. + * + * @param hObj Handle to JSON object to remove all + * elements from. + * + * @return True on success. + */ +native bool:json_object_clear(Handle:hObj); + +/** + * Update hObj with the key-value pairs from hOther, overwriting + * existing keys. + * + * @param hObj Handle to JSON object to update + * @param hOther Handle to JSON object to get update + * keys/values from. + * + * @return True on success. + */ +native bool:json_object_update(Handle:hObj, Handle:hOther); + +/** + * Like json_object_update(), but only the values of existing keys + * are updated. No new keys are created. + * + * @param hObj Handle to JSON object to update + * @param hOther Handle to JSON object to get update + * keys/values from. + * + * @return True on success. + */ +native bool:json_object_update_existing(Handle:hObj, Handle:hOther); + +/** + * Like json_object_update(), but only new keys are created. + * The value of any existing key is not changed. + * + * @param hObj Handle to JSON object to update + * @param hOther Handle to JSON object to get update + * keys/values from. + * + * @return True on success. + */ +native bool:json_object_update_missing(Handle:hObj, Handle:hOther); + + + + +/** + * Object iteration + * + * Example code: + * - We assume hObj is a Handle to a valid JSON object. + * + * + * new Handle:hIterator = json_object_iter(hObj); + * while(hIterator != INVALID_HANDLE) + * { + * new String:sKey[128]; + * json_object_iter_key(hIterator, sKey, sizeof(sKey)); + * + * new Handle:hValue = json_object_iter_value(hIterator); + * + * // Do something with sKey and hValue + * + * CloseHandle(hValue); + * + * hIterator = json_object_iter_next(hObj, hIterator); + * } + * + */ + +/** + * Returns a handle to an iterator which can be used to iterate over + * all key-value pairs in hObj. + * If you are not iterating to the end of hObj make sure to close the + * handle to the iterator manually. + * + * @param hObj Handle to JSON object to get an iterator + * for. + * + * @return Handle to JSON object iterator, + * or INVALID_HANDLE on error. + */ +native Handle:json_object_iter(Handle:hObj); + +/** + * Like json_object_iter(), but returns an iterator to the key-value + * pair in object whose key is equal to key. + * Iterating forward to the end of object only yields all key-value + * pairs of the object if key happens to be the first key in the + * underlying hash table. + * + * @param hObj Handle to JSON object to get an iterator + * for. + * @param sKey Start key for the iterator + * + * @return Handle to JSON object iterator, + * or INVALID_HANDLE on error. + */ +native Handle:json_object_iter_at(Handle:hObj, const String:key[]); + +/** + * Returns an iterator pointing to the next key-value pair in object. + * This automatically closes the Handle to the iterator hIter. + * + * @param hObj Handle to JSON object. + * @param hIter Handle to JSON object iterator. + * + * @return Handle to JSON object iterator, + * or INVALID_HANDLE on error, or if the + * whole object has been iterated through. + */ +native Handle:json_object_iter_next(Handle:hObj, Handle:hIter); + +/** + * Extracts the associated key of hIter as a null terminated UTF-8 + * encoded string in the passed buffer. + * + * @param hIter Handle to the JSON String object + * @param sKeyBuffer Buffer to store the value of the String. + * @param maxlength Maximum length of string buffer. + * @error Invalid JSON Object Iterator. + * @return Length of the returned string or -1 on error. + */ +native json_object_iter_key(Handle:hIter, String:sKeyBuffer[], maxlength); + +/** + * Returns a handle to the value hIter is pointing at. + * + * @param hIter Handle to JSON object iterator. + * + * @return Handle to value or INVALID_HANDLE on error. + */ +native Handle:json_object_iter_value(Handle:hIter); + +/** + * Set the value of the key-value pair in hObj, that is pointed to + * by hIter, to hValue. + * + * @param hObj Handle to JSON object. + * @param hIter Handle to JSON object iterator. + * @param hValue Handle to JSON value. + * + * @return True on success. + */ +native bool:json_object_iter_set(Handle:hObj, Handle:hIter, Handle:hValue); + +/** + * Set the value of the key-value pair in hObj, that is pointed to + * by hIter, to hValue. + * This function automatically closes the Handle to the value object. + * + * @param hObj Handle to JSON object. + * @param hIter Handle to JSON object iterator. + * @param hValue Handle to JSON value. + * + * @return True on success. + */ +native bool:json_object_iter_set_new(Handle:hObj, Handle:hIter, Handle:hValue); + + + + +/** + * Arrays + * + * A JSON array is an ordered collection of other JSON values. + * + */ + +/** + * Returns a handle to a new JSON array, or INVALID_HANDLE on error. + * + * @return Handle to the new JSON array + */ +native Handle:json_array(); + +/** + * Returns the number of elements in hArray + * + * @param hObj Handle to JSON array + * + * @return Number of elements in hArray, + * or 0 if hObj is not a JSON array. + */ +native json_array_size(Handle:hArray); + +/** + * Returns the element in hArray at position iIndex. + * + * @param hArray Handle to JSON array to get a value from + * @param iIndex Position to retrieve + * + * @return Handle to a the JSON object or + * INVALID_HANDLE on error. + */ +native Handle:json_array_get(Handle:hArray, iIndex); + +/** + * Replaces the element in array at position iIndex with hValue. + * The valid range for iIndex is from 0 to the return value of + * json_array_size() minus 1. + * + * @param hArray Handle to JSON array + * @param iIndex Position to replace + * @param hValue Value to store in the array + * + * @return True on success. + */ +native bool:json_array_set(Handle:hArray, iIndex, Handle:hValue); + +/** + * Replaces the element in array at position iIndex with hValue. + * The valid range for iIndex is from 0 to the return value of + * json_array_size() minus 1. + * This function automatically closes the Handle to the value object. + * + * @param hArray Handle to JSON array + * @param iIndex Position to replace + * @param hValue Value to store in the array + * + * @return True on success. + */ +native bool:json_array_set_new(Handle:hArray, iIndex, Handle:hValue); + +/** + * Appends value to the end of array, growing the size of array by 1. + * + * @param hArray Handle to JSON array + * @param hValue Value to append to the array + * + * @return True on success. + */ +native bool:json_array_append(Handle:hArray, Handle:hValue); + +/** + * Appends value to the end of array, growing the size of array by 1. + * This function automatically closes the Handle to the value object. + * + * @param hArray Handle to JSON array + * @param hValue Value to append to the array + * + * @return True on success. + */ +native bool:json_array_append_new(Handle:hArray, Handle:hValue); + +/** + * Inserts value to hArray at position iIndex, shifting the elements at + * iIndex and after it one position towards the end of the array. + * + * @param hArray Handle to JSON array + * @param iIndex Position to insert at + * @param hValue Value to store in the array + * + * @return True on success. + */ +native bool:json_array_insert(Handle:hArray, iIndex, Handle:hValue); + +/** + * Inserts value to hArray at position iIndex, shifting the elements at + * iIndex and after it one position towards the end of the array. + * This function automatically closes the Handle to the value object. + * + * @param hArray Handle to JSON array + * @param iIndex Position to insert at + * @param hValue Value to store in the array + * + * @return True on success. + */ +native bool:json_array_insert_new(Handle:hArray, iIndex, Handle:hValue); + +/** + * Removes the element in hArray at position iIndex, shifting the + * elements after iIndex one position towards the start of the array. + * + * @param hArray Handle to JSON array + * @param iIndex Position to insert at + * + * @return True on success. + */ +native bool:json_array_remove(Handle:hArray, iIndex); + +/** + * Removes all elements from hArray. + * + * @param hArray Handle to JSON array + * + * @return True on success. + */ +native bool:json_array_clear(Handle:hArray); + +/** + * Appends all elements in hOther to the end of hArray. + * + * @param hArray Handle to JSON array to be extended + * @param hOther Handle to JSON array, source to copy from + * + * @return True on success. + */ +native bool:json_array_extend(Handle:hArray, Handle:hOther); + + + + +/** + * Booleans & NULL + * + */ + +/** + * Returns a handle to a new JSON Boolean with value true, + * or INVALID_HANDLE on error. + * + * @return Handle to the new Boolean object + */ +native Handle:json_true(); + +/** + * Returns a handle to a new JSON Boolean with value false, + * or INVALID_HANDLE on error. + * + * @return Handle to the new Boolean object + */ +native Handle:json_false(); + +/** + * Returns a handle to a new JSON Boolean with the value passed + * in bState or INVALID_HANDLE on error. + * + * @param bState Value for the new Boolean object + * @return Handle to the new Boolean object + */ +native Handle:json_boolean(bool:bState); + +/** + * Returns a handle to a new JSON NULL or INVALID_HANDLE on error. + * + * @return Handle to the new NULL object + */ +native Handle:json_null(); + + + + +/** + * Strings + * + * Jansson uses UTF-8 as the character encoding. All JSON strings must + * be valid UTF-8 (or ASCII, as it�s a subset of UTF-8). Normal null + * terminated C strings are used, so JSON strings may not contain + * embedded null characters. + * + */ + +/** + * Returns a handle to a new JSON string, or INVALID_HANDLE on error. + * + * @param sValue Value for the new String object + * Must be a valid UTF-8 encoded Unicode string. + * @return Handle to the new String object + */ +native Handle:json_string(const String:sValue[]); + +/** + * Saves the associated value of hString as a null terminated UTF-8 + * encoded string in the passed buffer. + * + * @param hString Handle to the JSON String object + * @param sValueBuffer Buffer to store the value of the String. + * @param maxlength Maximum length of string buffer. + * @error Invalid JSON String Object. + * @return Length of the returned string or -1 on error. + */ +native json_string_value(Handle:hString, String:sValueBuffer[], maxlength); + +/** + * Sets the associated value of JSON String object to value. + * + * @param hString Handle to the JSON String object + * @param sValue Value to set the object to. + * Must be a valid UTF-8 encoded Unicode string. + * @error Invalid JSON String Object. + * @return True on success. + */ +native bool:json_string_set(Handle:hString, String:sValue[]); + + + + +/** + * Numbers + * + * The JSON specification only contains one numeric type, 'number'. + * The C (and Pawn) programming language has distinct types for integer + * and floating-point numbers, so for practical reasons Jansson also has + * distinct types for the two. They are called 'integer' and 'real', + * respectively. (Whereas 'real' is a 'Float' for Pawn). + * Therefore a number is represented by either a value of the type + * JSON_INTEGER or of the type JSON_REAL. + * + */ + +/** + * Returns a handle to a new JSON integer, or INVALID_HANDLE on error. + * + * @param iValue Value for the new Integer object + * @return Handle to the new Integer object + */ +native Handle:json_integer(iValue); + +/** + * Returns the associated value of a JSON Integer Object. + * + * @param hInteger Handle to the JSON Integer object + * @error Invalid JSON Integer Object. + * @return Value of the hInteger, + * or 0 if hInteger is not a JSON integer. + */ +native json_integer_value(Handle:hInteger); + +/** + * Sets the associated value of JSON Integer to value. + * + * @param hInteger Handle to the JSON Integer object + * @param iValue Value to set the object to. + * @error Invalid JSON Integer Object. + * @return True on success. + */ +native bool:json_integer_set(Handle:hInteger, iValue); + +/** + * Returns a handle to a new JSON real, or INVALID_HANDLE on error. + * + * @param fValue Value for the new Real object + * @return Handle to the new String object + */ +native Handle:json_real(Float:fValue); + +/** + * Returns the associated value of a JSON Real. + * + * @param hReal Handle to the JSON Real object + * @error Invalid JSON Real Object. + * @return Float value of hReal, + * or 0.0 if hReal is not a JSON Real. + */ +native Float:json_real_value(Handle:hReal); + +/** + * Sets the associated value of JSON Real to fValue. + * + * @param hReal Handle to the JSON Integer object + * @param fValue Value to set the object to. + * @error Invalid JSON Real handle. + * @return True on success. + */ +native bool:json_real_set(Handle:hReal, Float:value); + +/** + * Returns the associated value of a JSON integer or a + * JSON Real, cast to Float regardless of the actual type. + * + * @param hNumber Handle to the JSON Number + * @error Not a JSON Real or JSON Integer + * @return Float value of hNumber, + * or 0.0 on error. + */ +native Float:json_number_value(Handle:hNumber); + + + + +/** + * Decoding + * + * This sections describes the functions that can be used to decode JSON text + * to the Jansson representation of JSON data. The JSON specification requires + * that a JSON text is either a serialized array or object, and this + * requirement is also enforced with the following functions. In other words, + * the top level value in the JSON text being decoded must be either array or + * object. + * + */ + +/** + * Decodes the JSON string sJSON and returns the array or object it contains. + * Errors while decoding can be found in the sourcemod error log. + * + * @param sJSON String containing valid JSON + + * @return Handle to JSON object or array. + * or INVALID_HANDLE on error. + */ +native Handle:json_load(const String:sJSON[]); + +/** + * Decodes the JSON string sJSON and returns the array or object it contains. + * This function provides additional error feedback and does not log errors + * to the sourcemod error log. + * + * @param sJSON String containing valid JSON + * @param sErrorText This buffer will be filled with the error + * message. + * @param maxlen Size of the buffer + * @param iLine This int will contain the line of the error + * @param iColumn This int will contain the column of the error + * + * @return Handle to JSON object or array. + * or INVALID_HANDLE on error. + */ +native Handle:json_load_ex(const String:sJSON[], String:sErrorText[], maxlen, &iLine, &iColumn); + +/** + * Decodes the JSON text in file sFilePath and returns the array or object + * it contains. + * Errors while decoding can be found in the sourcemod error log. + * + * @param sFilePath Path to a file containing pure JSON + * + * @return Handle to JSON object or array. + * or INVALID_HANDLE on error. + */ +native Handle:json_load_file(const String:sFilePath[PLATFORM_MAX_PATH]); + +/** + * Decodes the JSON text in file sFilePath and returns the array or object + * it contains. + * This function provides additional error feedback and does not log errors + * to the sourcemod error log. + * + * @param sFilePath Path to a file containing pure JSON + * @param sErrorText This buffer will be filled with the error + * message. + * @param maxlen Size of the buffer + * @param iLine This int will contain the line of the error + * @param iColumn This int will contain the column of the error + * + * @return Handle to JSON object or array. + * or INVALID_HANDLE on error. + */ +native Handle:json_load_file_ex(const String:sFilePath[PLATFORM_MAX_PATH], String:sErrorText[], maxlen, &iLine, &iColumn); + + + +/** + * Encoding + * + * This sections describes the functions that can be used to encode values + * to JSON. By default, only objects and arrays can be encoded directly, + * since they are the only valid root values of a JSON text. + * + */ + +/** + * Saves the JSON representation of hObject in sJSON. + * + * @param hObject String containing valid JSON + * @param sJSON Buffer to store the created JSON string. + * @param maxlength Maximum length of string buffer. + * @param iIndentWidth Indenting with iIndentWidth spaces. + * The valid range for this is between 0 and 31 (inclusive), + * other values result in an undefined output. If this is set + * to 0, no newlines are inserted between array and object items. + * @param bEnsureAscii If this is set, the output is guaranteed + * to consist only of ASCII characters. This is achieved + * by escaping all Unicode characters outside the ASCII range. + * @param bSortKeys If this flag is used, all the objects in output are sorted + * by key. This is useful e.g. if two JSON texts are diffed + * or visually compared. + * @param bPreserveOrder If this flag is used, object keys in the output are sorted + * into the same order in which they were first inserted to + * the object. For example, decoding a JSON text and then + * encoding with this flag preserves the order of object keys. + * @return Length of the returned string or -1 on error. + */ +native json_dump(Handle:hObject, String:sJSON[], maxlength, iIndentWidth = 4, bool:bEnsureAscii = false, bool:bSortKeys = false, bool:bPreserveOrder = false); + +/** + * Write the JSON representation of hObject to the file sFilePath. + * If sFilePath already exists, it is overwritten. + * + * @param hObject String containing valid JSON + * @param sFilePath Buffer to store the created JSON string. + * @param iIndentWidth Indenting with iIndentWidth spaces. + * The valid range for this is between 0 and 31 (inclusive), + * other values result in an undefined output. If this is set + * to 0, no newlines are inserted between array and object items. + * @param bEnsureAscii If this is set, the output is guaranteed + * to consist only of ASCII characters. This is achieved + * by escaping all Unicode characters outside the ASCII range. + * @param bSortKeys If this flag is used, all the objects in output are sorted + * by key. This is useful e.g. if two JSON texts are diffed + * or visually compared. + * @param bPreserveOrder If this flag is used, object keys in the output are sorted + * into the same order in which they were first inserted to + * the object. For example, decoding a JSON text and then + * encoding with this flag preserves the order of object keys. + * @return Length of the returned string or -1 on error. + */ +native bool:json_dump_file(Handle:hObject, const String:sFilePath[], iIndentWidth = 4, bool:bEnsureAscii = false, bool:bSortKeys = false, bool:bPreserveOrder = false); + + + +/** + * Convenience stocks + * + * These are some custom functions to ease the development using this + * extension. + * + */ + +/** + * Returns a handle to a new JSON string, or INVALID_HANDLE on error. + * Formats the string according to the SourceMod format rules. + * The result must be a valid UTF-8 encoded Unicode string. + * + * @param sFormat Formatting rules. + * @param ... Variable number of format parameters. + * @return Handle to the new String object + */ +stock Handle:json_string_format(const String:sFormat[], any:...) { + new String:sTmp[4096]; + VFormat(sTmp, sizeof(sTmp), sFormat, 2); + + return json_string(sTmp); +} + +/** + * Returns a handle to a new JSON string, or INVALID_HANDLE on error. + * This stock allows to specify the size of the temporary buffer used + * to create the string. Use this if the default of 4096 is not enough + * for your string. + * Formats the string according to the SourceMod format rules. + * The result must be a valid UTF-8 encoded Unicode string. + * + * @param tmpBufferLength Size of the temporary buffer + * @param sFormat Formatting rules. + * @param ... Variable number of format parameters. + * @return Handle to the new String object + */ +stock Handle:json_string_format_ex(tmpBufferLength, const String:sFormat[], any:...) { + new String:sTmp[tmpBufferLength]; + VFormat(sTmp, sizeof(sTmp), sFormat, 3); + + return json_string(sTmp); +} + + +/** + * Returns the boolean value of the element in hArray at position iIndex. + * + * @param hArray Handle to JSON array to get a value from + * @param iIndex Position to retrieve + * + * @return True if it's a boolean and TRUE, + * false otherwise. + */ +stock bool:json_array_get_bool(Handle:hArray, iIndex) { + new Handle:hElement = json_array_get(hArray, iIndex); + + new bool:bResult = (json_is_true(hElement) ? true : false); + + CloseHandle(hElement); + return bResult; +} + +/** + * Returns the float value of the element in hArray at position iIndex. + * + * @param hArray Handle to JSON array to get a value from + * @param iIndex Position to retrieve + * + * @return Float value, + * or 0.0 if element is not a JSON Real. + */ +stock Float:json_array_get_float(Handle:hArray, iIndex) { + new Handle:hElement = json_array_get(hArray, iIndex); + + new Float:fResult = (json_is_number(hElement) ? json_number_value(hElement) : 0.0); + + CloseHandle(hElement); + return fResult; +} + +/** + * Returns the integer value of the element in hArray at position iIndex. + * + * @param hArray Handle to JSON array to get a value from + * @param iIndex Position to retrieve + * + * @return Integer value, + * or 0 if element is not a JSON Integer. + */ +stock json_array_get_int(Handle:hArray, iIndex) { + new Handle:hElement = json_array_get(hArray, iIndex); + + new iResult = (json_is_integer(hElement) ? json_integer_value(hElement) : 0); + + CloseHandle(hElement); + return iResult; +} + +/** + * Saves the associated value of the element in hArray at position iIndex + * as a null terminated UTF-8 encoded string in the passed buffer. + * + * @param hArray Handle to JSON array to get a value from + * @param iIndex Position to retrieve + * @param sBuffer Buffer to store the value of the String. + * @param maxlength Maximum length of string buffer. + * + * @error Element is not a JSON String. + * @return Length of the returned string or -1 on error. + */ +stock json_array_get_string(Handle:hArray, iIndex, String:sBuffer[], maxlength) { + new Handle:hElement = json_array_get(hArray, iIndex); + + new iResult = -1; + if(json_is_string(hElement)) { + iResult = json_string_value(hElement, sBuffer, maxlength); + } + CloseHandle(hElement); + + return iResult; +} + +/** + * Returns the boolean value of the element in hObj at entry sKey. + * + * @param hObj Handle to JSON object to get a value from + * @param sKey Entry to retrieve + * + * @return True if it's a boolean and TRUE, + * false otherwise. + */ +stock bool:json_object_get_bool(Handle:hObj, const String:sKey[]) { + new Handle:hElement = json_object_get(hObj, sKey); + + new bool:bResult = (json_is_true(hElement) ? true : false); + + CloseHandle(hElement); + return bResult; +} + +/** + * Returns the float value of the element in hObj at entry sKey. + * + * @param hObj Handle to JSON object to get a value from + * @param sKey Position to retrieve + * + * @return Float value, + * or 0.0 if element is not a JSON Real. + */ +stock Float:json_object_get_float(Handle:hObj, const String:sKey[]) { + new Handle:hElement = json_object_get(hObj, sKey); + + new Float:fResult = (json_is_number(hElement) ? json_number_value(hElement) : 0.0); + + CloseHandle(hElement); + return fResult; +} + +/** + * Returns the integer value of the element in hObj at entry sKey. + * + * @param hObj Handle to JSON object to get a value from + * @param sKey Position to retrieve + * + * @return Integer value, + * or 0 if element is not a JSON Integer. + */ +stock json_object_get_int(Handle:hObj, const String:sKey[]) { + new Handle:hElement = json_object_get(hObj, sKey); + + new iResult = (json_is_integer(hElement) ? json_integer_value(hElement) : 0); + + CloseHandle(hElement); + return iResult; +} + +/** + * Saves the associated value of the element in hObj at entry sKey + * as a null terminated UTF-8 encoded string in the passed buffer. + * + * @param hObj Handle to JSON object to get a value from + * @param sKey Entry to retrieve + * @param sBuffer Buffer to store the value of the String. + * @param maxlength Maximum length of string buffer. + * + * @error Element is not a JSON String. + * @return Length of the returned string or -1 on error. + */ +stock json_object_get_string(Handle:hObj, const String:sKey[], String:sBuffer[], maxlength) { + new Handle:hElement = json_object_get(hObj, sKey); + + new iResult = -1; + if(json_is_string(hElement)) { + iResult = json_string_value(hElement, sBuffer, maxlength); + } + CloseHandle(hElement); + + return iResult; +} + + + +/** + * Pack String Rules + * + * Here�s the full list of format characters: + * n Output a JSON null value. No argument is consumed. + * s Output a JSON string, consuming one argument. + * b Output a JSON bool value, consuming one argument. + * i Output a JSON integer value, consuming one argument. + * f Output a JSON real value, consuming one argument. + * r Output a JSON real value, consuming one argument. + * [] Build an array with contents from the inner format string, + * recursive value building is supported. + * No argument is consumed. + * {} Build an array with contents from the inner format string. + * The first, third, etc. format character represent a key, + * and must be s (as object keys are always strings). The + * second, fourth, etc. format character represent a value. + * Recursive value building is supported. + * No argument is consumed. + * + */ + +/** + * This method can be used to create json objects/arrays directly + * without having to create the structure. + * See 'Pack String Rules' for more details. + * + * @param sPackString Pack string similiar to Format()s fmt. + * See 'Pack String Rules'. + * @param hParams ADT Array containing all keys and values + * in the order they appear in the pack string. + * + * @error Invalid pack string or pack string and + * ADT Array don't match up regarding type + * or size. + * @return Handle to JSON element. + */ +stock Handle:json_pack(const String:sPackString[], Handle:hParams) { + new iPos = 0; + return json_pack_element_(sPackString, iPos, hParams); +} + + + + + +/** +* Internal stocks used by json_pack(). Don't use these directly! +* +*/ +stock Handle:json_pack_array_(const String:sFormat[], &iPos, Handle:hParams) { + new Handle:hObj = json_array(); + new iStrLen = strlen(sFormat); + for(; iPos < iStrLen;) { + new this_char = sFormat[iPos]; + + if(this_char == 32 || this_char == 58 || this_char == 44) { + // Skip whitespace, ',' and ':' + iPos++; + continue; + } + + if(this_char == 93) { + // array end + iPos++; + break; + } + + // Get the next entry as value + // This automatically increments the position! + new Handle:hValue = json_pack_element_(sFormat, iPos, hParams); + + // Append the value to the array. + json_array_append_new(hObj, hValue); + } + + return hObj; +} + +stock Handle:json_pack_object_(const String:sFormat[], &iPos, Handle:hParams) { + new Handle:hObj = json_object(); + new iStrLen = strlen(sFormat); + for(; iPos < iStrLen;) { + new this_char = sFormat[iPos]; + + if(this_char == 32 || this_char == 58 || this_char == 44) { + // Skip whitespace, ',' and ':' + iPos++; + continue; + } + + if(this_char == 125) { + // } --> object end + iPos++; + break; + } + + if(this_char != 115) { + LogError("Object keys must be strings at %d.", iPos); + return INVALID_HANDLE; + } + + // Get the key string for this object from + // the hParams array. + decl String:sKey[255]; + GetArrayString(hParams, 0, sKey, sizeof(sKey)); + RemoveFromArray(hParams, 0); + + // Advance one character in the pack string, + // because we've just read the Key string for + // this object. + iPos++; + + // Get the next entry as value + // This automatically increments the position! + new Handle:hValue = json_pack_element_(sFormat, iPos, hParams); + + // Insert into object + json_object_set_new(hObj, sKey, hValue); + } + + return hObj; +} + +stock Handle:json_pack_element_(const String:sFormat[], &iPos, Handle:hParams) { + new this_char = sFormat[iPos]; + while(this_char == 32 || this_char == 58 || this_char == 44) { + iPos++; + this_char = sFormat[iPos]; + } + + // Advance one character in the pack string + iPos++; + + switch(this_char) { + case 91: { + // { --> Array + return json_pack_array_(sFormat, iPos, hParams); + } + + case 123: { + // { --> Object + return json_pack_object_(sFormat, iPos, hParams); + + } + + case 98: { + // b --> Boolean + new iValue = GetArrayCell(hParams, 0); + RemoveFromArray(hParams, 0); + + return json_boolean(bool:iValue); + } + + case 102, 114: { + // r,f --> Real (Float) + new Float:iValue = GetArrayCell(hParams, 0); + RemoveFromArray(hParams, 0); + + return json_real(iValue); + } + + case 110: { + // n --> NULL + return json_null(); + } + + case 115: { + // s --> String + decl String:sKey[255]; + GetArrayString(hParams, 0, sKey, sizeof(sKey)); + RemoveFromArray(hParams, 0); + + return json_string(sKey); + } + + case 105: { + // i --> Integer + new iValue = GetArrayCell(hParams, 0); + RemoveFromArray(hParams, 0); + + return json_integer(iValue); + } + } + + SetFailState("Invalid pack String '%s'. Type '%s' not supported at %i", sFormat, this_char, iPos); + return json_null(); +} + + + + + +/** + * Not yet implemented + * + * native json_object_foreach(Handle:hObj, ForEachCallback:cb); + * native Handle:json_unpack(const String:sFormat[], ...); + * + */ + + + + + + +/** + * Do not edit below this line! + */ +public Extension:__ext_smjansson = +{ + name = "SMJansson", + file = "smjansson.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_smjansson_SetNTVOptional() +{ + MarkNativeAsOptional("json_typeof"); + MarkNativeAsOptional("json_equal"); + + MarkNativeAsOptional("json_copy"); + MarkNativeAsOptional("json_deep_copy"); + + MarkNativeAsOptional("json_object"); + MarkNativeAsOptional("json_object_size"); + MarkNativeAsOptional("json_object_get"); + MarkNativeAsOptional("json_object_set"); + MarkNativeAsOptional("json_object_set_new"); + MarkNativeAsOptional("json_object_del"); + MarkNativeAsOptional("json_object_clear"); + MarkNativeAsOptional("json_object_update"); + MarkNativeAsOptional("json_object_update_existing"); + MarkNativeAsOptional("json_object_update_missing"); + + MarkNativeAsOptional("json_object_iter"); + MarkNativeAsOptional("json_object_iter_at"); + MarkNativeAsOptional("json_object_iter_next"); + MarkNativeAsOptional("json_object_iter_key"); + MarkNativeAsOptional("json_object_iter_value"); + MarkNativeAsOptional("json_object_iter_set"); + MarkNativeAsOptional("json_object_iter_set_new"); + + MarkNativeAsOptional("json_array"); + MarkNativeAsOptional("json_array_size"); + MarkNativeAsOptional("json_array_get"); + MarkNativeAsOptional("json_array_set"); + MarkNativeAsOptional("json_array_set_new"); + MarkNativeAsOptional("json_array_append"); + MarkNativeAsOptional("json_array_append_new"); + MarkNativeAsOptional("json_array_insert"); + MarkNativeAsOptional("json_array_insert_new"); + MarkNativeAsOptional("json_array_remove"); + MarkNativeAsOptional("json_array_clear"); + MarkNativeAsOptional("json_array_extend"); + + MarkNativeAsOptional("json_string"); + MarkNativeAsOptional("json_string_value"); + MarkNativeAsOptional("json_string_set"); + + MarkNativeAsOptional("json_integer"); + MarkNativeAsOptional("json_integer_value"); + MarkNativeAsOptional("json_integer_set"); + + MarkNativeAsOptional("json_real"); + MarkNativeAsOptional("json_real_value"); + MarkNativeAsOptional("json_real_set"); + MarkNativeAsOptional("json_number_value"); + + MarkNativeAsOptional("json_boolean"); + MarkNativeAsOptional("json_true"); + MarkNativeAsOptional("json_false"); + MarkNativeAsOptional("json_null"); + + MarkNativeAsOptional("json_load"); + MarkNativeAsOptional("json_load_file"); + + MarkNativeAsOptional("json_dump"); + MarkNativeAsOptional("json_dump_file"); +} +#endif diff --git a/source/sourcemod/scripting/include/smlib.inc b/source/sourcemod/scripting/include/smlib.inc new file mode 100644 index 0000000..2d6413a --- /dev/null +++ b/source/sourcemod/scripting/include/smlib.inc @@ -0,0 +1,32 @@ +#if defined _smlib_included + #endinput +#endif +#define _smlib_included + +#define SMLIB_VERSION "0.9.7" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include diff --git a/source/sourcemod/scripting/include/smlib/arrays.inc b/source/sourcemod/scripting/include/smlib/arrays.inc new file mode 100644 index 0000000..87f1733 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/arrays.inc @@ -0,0 +1,157 @@ +#if defined _smlib_array_included + #endinput +#endif +#define _smlib_array_included + +#include + +/** + * Returns the index for the first occurance of the given value. + * If the value cannot be found, -1 will be returned. + * + * @param array Static Array. + * @param size Size of the Array. + * @param value Value to search for. + * @param start Optional: Offset where to start (0 - (size-1)). + * @return Array index, or -1 if the value couldn't be found. + */ +stock int Array_FindValue(const any[] array, int size, any value, int start=0) +{ + if (start < 0) { + start = 0; + } + + for (int i=start; i < size; i++) { + + if (array[i] == value) { + return i; + } + } + + return -1; +} + +/** + * Searchs for the first occurance of a string in the array. + * If the value cannot be located, -1 will be returned. + * + * @param array Static Array. + * @param size Size of the Array. + * @param value String to search for. + * @param start Optional: Offset where to start(0 - (size-1)). + * @return Array index, or -1 if the value couldn't be found. + */ +stock int Array_FindString(const char[][] array, int size, const char[] str, bool caseSensitive=true, int start=0) +{ + if (start < 0) { + start = 0; + } + + for (int i=start; i < size; i++) { + + if (StrEqual(array[i], str, caseSensitive)) { + return i; + } + } + + return -1; +} + +/** + * Returns the Index of the Lowest value in the array + * + * @param array Static Array. + * @param size Size of the Array. + * @param start Optional: Offset where to start (0 - (size-1)). + * @return Array index. + */ +stock int Array_FindLowestValue(const any[] array, int size, int start=0) +{ + if (start < 0) { + start = 0; + } + + any value = array[start]; + any tempValue; + int x = start; + + for (int i=start; i < size; i++) { + + tempValue = array[i]; + + if (tempValue < value) { + value = tempValue; + x = i; + } + + } + + return x; +} + +/** + * Returns the Index of the Highest value in the array + * + * @param array Static Array. + * @param size Size of the Array. + * @param start Optional: Offset where to start (0 - (size-1)). + * @return Array index. + */ +stock int Array_FindHighestValue(const any[] array, int size, int start=0) +{ + if (start < 0) { + start = 0; + } + + any value = array[start]; + any tempValue; + int x = start; + + for (int i=start; i < size; i++) { + + tempValue = array[i]; + + if (tempValue > value) { + value = tempValue; + x = i; + } + + } + + return x; +} + +/** + * Fills an array with a given value in a 1 dimensional static array. + * You can specify the amount of cells to be written. + * + * @param array Static Array. + * @param size Number of cells to write (eg. the array's size) + * @param value Fill value. + * @param start Optional: Offset where to start (0 - (size-1)). + */ +stock void Array_Fill(any[] array, int size, any value, int start=0) +{ + if (start < 0) { + start = 0; + } + + for (int i=start; i < size; i++) { + array[i] = value; + } +} + +/** + * Copies a 1 dimensional static array. + * + * @param array Static Array to copy from. + * @param newArray New Array to copy to. + * @param size Size of the array (or number of cells to copy) + * @noreturn + */ +stock void Array_Copy(const any[] array, any[] newArray, int size) +{ + for (int i=0; i < size; i++) { + newArray[i] = array[i]; + } +} diff --git a/source/sourcemod/scripting/include/smlib/clients.inc b/source/sourcemod/scripting/include/smlib/clients.inc new file mode 100644 index 0000000..ca5cf4c --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/clients.inc @@ -0,0 +1,3077 @@ +#if defined _smlib_client_included + #endinput +#endif +#define _smlib_client_included + +// Defined here beacause needed in teams.inc +#define CLIENTFILTER_ALL 0 // No filtering +#define CLIENTFILTER_BOTS ( 1 << 1 ) // Fake clients +#define CLIENTFILTER_NOBOTS ( 1 << 2 ) // No fake clients +#define CLIENTFILTER_AUTHORIZED ( 1 << 3 ) // SteamID validated +#define CLIENTFILTER_NOTAUTHORIZED ( 1 << 4 ) // SteamID not validated (yet) +#define CLIENTFILTER_ADMINS ( 1 << 5 ) // Generic Admins (or higher) +#define CLIENTFILTER_NOADMINS ( 1 << 6 ) // No generic admins +// All flags below require ingame checking (optimization) +#define CLIENTFILTER_INGAME ( 1 << 7 ) // Ingame +#define CLIENTFILTER_INGAMEAUTH ( 1 << 8 ) // Ingame & Authorized +#define CLIENTFILTER_NOTINGAME ( 1 << 9 ) // Not ingame (currently connecting) +#define CLIENTFILTER_ALIVE ( 1 << 10 ) // Alive +#define CLIENTFILTER_DEAD ( 1 << 11 ) // Dead +#define CLIENTFILTER_SPECTATORS ( 1 << 12 ) // Spectators +#define CLIENTFILTER_NOSPECTATORS ( 1 << 13 ) // No Spectators +#define CLIENTFILTER_OBSERVERS ( 1 << 14 ) // Observers +#define CLIENTFILTER_NOOBSERVERS ( 1 << 15 ) // No Observers +#define CLIENTFILTER_TEAMONE ( 1 << 16 ) // First Team (Terrorists, ...) +#define CLIENTFILTER_TEAMTWO ( 1 << 17 ) // Second Team (Counter-Terrorists, ...) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Very useful macro to iterate all clients + * matching the specified flags. + * + * @param 1 Name of the client index variable (will be only valid in the loop). + * @param 2 CLIENTFILTER_ flags to check. + */ +#define LOOP_CLIENTS(%1,%2) for (int %1=Client_GetNext(%2); %1 >= 1 && %1 <= MaxClients; %1=Client_GetNext(%2, ++%1)) + +/** + * Macro for iterating trough all observers of a player. + * + * @param 1 Client Index for who to get the observers. + * @param 2 Name of the observer client index variable (will be only valid in the loop). + * @param 3 CLIENTFILTER_ flags to check. + */ +#define LOOP_OBSERVERS(%1,%2,%3) for (int %2=Client_GetNextObserver(%1, 1, %3); %2 >= 1 && %2 <= MaxClients; %2=Client_GetNextObserver(%1, ++%2, %3)) + +/** + * Very useful macro to iterate all weapons of a client. + * + * @param 1 Client Index + * @param 2 Name of the weapon index variable (will be only valid in the loop). + * @param 3 Name of the client's weapon index variable (will be only valid in the loop). + */ +#define LOOP_CLIENTWEAPONS(%1,%2,%3) for (int %3, %2=Client_GetNextWeapon(%1, %3); %2 != -1; %2=Client_GetNextWeapon(%1, %3)) + +// Hud Element hiding flags (possibly outdated) +#define HIDEHUD_WEAPONSELECTION ( 1<<0 ) // Hide ammo count & weapon selection +#define HIDEHUD_FLASHLIGHT ( 1<<1 ) +#define HIDEHUD_ALL ( 1<<2 ) +#define HIDEHUD_HEALTH ( 1<<3 ) // Hide health & armor / suit battery +#define HIDEHUD_PLAYERDEAD ( 1<<4 ) // Hide when local player's dead +#define HIDEHUD_NEEDSUIT ( 1<<5 ) // Hide when the local player doesn't have the HEV suit +#define HIDEHUD_MISCSTATUS ( 1<<6 ) // Hide miscellaneous status elements (trains, pickup history, death notices, etc) +#define HIDEHUD_CHAT ( 1<<7 ) // Hide all communication elements (saytext, voice icon, etc) +#define HIDEHUD_CROSSHAIR ( 1<<8 ) // Hide crosshairs +#define HIDEHUD_VEHICLE_CROSSHAIR ( 1<<9 ) // Hide vehicle crosshair +#define HIDEHUD_INVEHICLE ( 1<<10 ) +#define HIDEHUD_BONUS_PROGRESS ( 1<<11 ) // Hide bonus progress display (for bonus map challenges) + +/** +* Sets the Hide-Hud flags of a client +* +* @param client Client index. +* @param flags Flag to set, use one of the HIDEHUD_ hiding constants +*/ +stock void Client_SetHideHud(int client, int flags) +{ + SetEntProp(client, Prop_Send, "m_iHideHUD", flags); +} + +/** +* Checks if the specified index is a player and connected. +* +* @param entity An entity index. +* @param checkConnected Set to false to skip the IsClientConnected check +* @return Returns true if the specified entity index is a player connected, false otherwise. +*/ +stock bool Client_IsValid(int client, bool checkConnected=true) +{ + if (client > 4096) { + client = EntRefToEntIndex(client); + } + + if (client < 1 || client > MaxClients) { + return false; + } + + if (checkConnected && !IsClientConnected(client)) { + return false; + } + + return true; +} + +/** +* Checks if the specified index is a player and ingame. +* +* @param entity An entity index. +* @return Returns true if the specified index is a player and ingame, false otherwise. +*/ +stock bool Client_IsIngame(int client) +{ + if (!Client_IsValid(client, false)) { + return false; + } + + return IsClientInGame(client); +} + +/** +* Checks if the specified index is a player, ingame and authorized. +* +* @param entity An entity index. +* @return Returns true if the specified index is a player, ingame and authed, false otherwise. +*/ +stock bool Client_IsIngameAuthorized(int client) +{ + if (!Client_IsIngame(client)) { + return false; + } + + return IsClientAuthorized(client); +} + +#define MAX_STEAMAUTH_LENGTH 21 + +/** +* Finds a player by his SteamID +* +* @param auth SteamID to search for +* @return Client Index or -1 +*/ +stock int Client_FindBySteamId(const char[] auth) +{ + char clientAuth[MAX_STEAMAUTH_LENGTH]; + for (int client=1; client <= MaxClients; client++) { + if (!IsClientAuthorized(client)) { + continue; + } + + GetClientAuthId(client, AuthId_Steam2, clientAuth, sizeof(clientAuth)); + + if (StrEqual(auth, clientAuth)) { + return client; + } + } + + return -1; +} + +/** +* Finds a player by his name. +* Only returns the first matching player. +* +* @param name Name to search for. +* @param partOfName Whether to search for the part of a name or compare the full name. +* @param caseSensitive If true, comparison is case sensitive. If false (default), comparison is case insensitive. +* @return Client Index or -1 +*/ +stock int Client_FindByName(const char[] name, bool partOfName=true, bool caseSensitive=false) +{ + char clientName[MAX_NAME_LENGTH]; + for (int client=1; client <= MaxClients; client++) { + if (!IsClientAuthorized(client)) { + continue; + } + + GetClientName(client, clientName, sizeof(clientName)); + + if (partOfName) { + if (StrContains(clientName, name, caseSensitive) != -1) { + return client; + } + } + else if (StrEqual(name, clientName, caseSensitive)) { + return client; + } + } + + return -1; +} + +// Spectator Movement modes +enum Obs_Mode +{ + OBS_MODE_NONE = 0, // not in spectator mode + OBS_MODE_DEATHCAM, // special mode for death cam animation + OBS_MODE_FREEZECAM, // zooms to a target, and freeze-frames on them + OBS_MODE_FIXED, // view from a fixed camera position + OBS_MODE_IN_EYE, // follow a player in first person view + OBS_MODE_CHASE, // follow a player in third person view + OBS_MODE_ROAMING, // free roaming + + NUM_OBSERVER_MODES +}; + +// Force Camera Restrictions with mp_forcecamera +enum Obs_Allow +{ + OBS_ALLOW_ALL = 0, // allow all modes, all targets + OBS_ALLOW_TEAM, // allow only own team & first person, no PIP + OBS_ALLOW_NONE, // don't allow any spectating after death (fixed & fade to black) + + OBS_ALLOW_NUM_MODES, +}; + +/** + * Gets the client's observer mode (Obs_Mode). + * + * @param client Client Index. + * @return The current observer mode (ObsMode). + */ +stock Obs_Mode Client_GetObserverMode(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_iObserverMode")); +} + + +/** + * Sets the client's observer mode. + * Use a value of the Obs_Mode enum. + * This is a rewrite of CBasePlayer::SetObserverMode(). + * + * @param client Client Index. + * @param mode New Observer mode value (Obs_Mode). + * @param updateMoveType Set to true (default) to allow this function updating the movetype, false otherwise. + */ +stock void Client_SetObserverMode(int client, Obs_Mode mode, bool updateMoveType=true) +{ + if (mode < OBS_MODE_NONE || mode >= NUM_OBSERVER_MODES) { + return; + } + + // check mp_forcecamera settings for dead players + if (mode > OBS_MODE_FIXED && GetClientTeam(client) > TEAM_SPECTATOR) + { + ConVar mp_forcecamera = FindConVar("mp_forcecamera"); + + if (mp_forcecamera != INVALID_HANDLE) { + switch (view_as(mp_forcecamera.IntValue)) + { + case OBS_ALLOW_TEAM: { + mode = OBS_MODE_IN_EYE; + } + case OBS_ALLOW_NONE: { + mode = OBS_MODE_FIXED; // don't allow anything + } + } + } + } + + Obs_Mode observerMode = Client_GetObserverMode(client); + if (observerMode > OBS_MODE_DEATHCAM) { + // remember mode if we were really spectating before + Client_SetObserverLastMode(client, observerMode); + } + + SetEntProp(client, Prop_Send, "m_iObserverMode", mode); + + switch (mode) { + case OBS_MODE_NONE, OBS_MODE_FIXED, OBS_MODE_DEATHCAM: { + Client_SetFOV(client, 0); // Reset FOV + + if (updateMoveType) { + SetEntityMoveType(client, MOVETYPE_NONE); + } + } + case OBS_MODE_CHASE, OBS_MODE_IN_EYE: { + // udpate FOV and viewmodels + Client_SetViewOffset(client, NULL_VECTOR); + + if (updateMoveType) { + SetEntityMoveType(client, MOVETYPE_OBSERVER); + } + } + case OBS_MODE_ROAMING: { + Client_SetFOV(client, 0); // Reset FOV + Client_SetViewOffset(client, NULL_VECTOR); + + if (updateMoveType) { + SetEntityMoveType(client, MOVETYPE_OBSERVER); + } + } + } +} + +/** + * Gets the client's last oberserver mode + * + * @param client Client Index. + * @return Last Observer mode + */ +stock Obs_Mode Client_GetObserverLastMode(int client) +{ + return view_as(GetEntProp(client, Prop_Data, "m_iObserverLastMode")); +} + +/** + * Sets the client's last oberserver mode + * + * @param client Client Index. + * @param mode Last Observer mode + */ +stock void Client_SetObserverLastMode(int client, Obs_Mode mode) +{ + SetEntProp(client, Prop_Data, "m_iObserverLastMode", mode); +} + +/** + * Gets the client's view offset. + * This is the position relative to the client itself. + * + * @param client Client Index. + * @param vec Vector Buffer. + */ +stock void Client_GetViewOffset(int client, float vec[3]) +{ + GetEntPropVector(client, Prop_Data, "m_vecViewOffset", vec); +} + +/** + * Sets the client's view offset. + * This is the position relative to the client itself. + * + * @param client Client Index. + * @param vec Vector buffer. + * @noreturn + */ +stock void Client_SetViewOffset(int client, float vec[3]) +{ + SetEntPropVector(client, Prop_Data, "m_vecViewOffset", vec); +} + +/** + * Gets the client's current observer target entity. + * + * @param client Client Index. + * @return Observed Entity Index. + */ +stock int Client_GetObserverTarget(int client) +{ + return GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); +} + +/** + * Sets the client's current observer target entity. + * + * @param client Client Index. + * @param entity Observed Entity Index. + * @param resetFOV If to reset the client's field of view. + */ +stock void Client_SetObserverTarget(int client, int entity, bool resetFOV=true) +{ + SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", entity); + + if (resetFOV) { + Client_SetFOV(client, 0); + } +} + +/** + * Gets the client's Field Of View. + * + * @param client Client Index. + * @return Field Of View + */ +stock int Client_GetFOV(int client) +{ + return GetEntProp(client, Prop_Send, "m_iFOV"); +} + +/** + * Sets the client's Field Of View. + * + * @param client Client Index. + * @param value Field Of View + */ +stock void Client_SetFOV(int client, int value) +{ + SetEntProp(client, Prop_Send, "m_iFOV", value); +} + +/** + * Checks if the client's View Model is drawn for the client. + * + * @param client Client Index. + * @return True if the viewmodel is drawn, false otherwise. + */ +stock bool Client_DrawViewModel(int client) +{ + return GetEntProp(client, Prop_Send, "m_bDrawViewmodel") != 0; +} + +/** + * Sets if to draw the client's view model for the client. + * + * @param client Client Index. + * @param drawViewModel Set to true if to draw, false otherwise. + */ +stock void Client_SetDrawViewModel(int client, bool drawViewModel) +{ + SetEntProp(client, Prop_Send, "m_bDrawViewmodel", drawViewModel); +} + +/** + * Puts the specified client into thirdperson or back to firstperson when false + * This doesn't work correctly in all games, it works in CS:S and DOD:S and some other games. + * Todo: Enhance this + * + * @param client Client Index. + * @param enable If set to true, the client will be put into thirdperson mode, + * if false the client will be put in firstperson mode. + */ +stock void Client_SetThirdPersonMode(int client, bool enable=true) +{ + if (enable) { + Client_SetObserverTarget(client, 0); + Client_SetObserverMode(client, OBS_MODE_DEATHCAM, false); + Client_SetDrawViewModel(client, false); + Client_SetFOV(client, 120); + } + else { + Client_SetObserverTarget(client, -1); + Client_SetObserverMode(client, OBS_MODE_NONE, false); + Client_SetDrawViewModel(client, true); + Client_SetFOV(client, 90); + } +} + +/** + * Checks if the client is in thirdperson mode + * + * @param client Cient Undex + * @return true if the client is currently in thirdperson mode, false otherwise + */ +stock bool Client_IsInThirdPersonMode(int client) +{ + // FIXME: Is this enough? + return Client_GetObserverMode(client) == OBS_MODE_DEATHCAM; +} + +#define FFADE_IN 0x0001 // Just here so we don't pass 0 into the function +#define FFADE_OUT 0x0002 // Fade out (not in) +#define FFADE_MODULATE 0x0004 // Modulate (don't blend) +#define FFADE_STAYOUT 0x0008 // ignores the duration, stays faded out until new ScreenFade message received +#define FFADE_PURGE 0x0010 // Purges all other fades, replacing them with this one + +/** + * Fades a client's screen to a specified color + * Your adviced to read the FFADE_ Comments + * + * @param client Player for which to fade the screen + * @param duration duration in seconds the effect stays + * @param mode fade mode, see FFADE_ defines + * @param holdtime holdtime in seconds + * @param r red amount + * @param g green amount + * @param b blue amount + * @param a transparency + * @return True on success, false otherwise + */ +stock bool Client_ScreenFade(int client, int duration, int mode, int holdtime=-1, int r=0, int g=0, int b=0, int a=255, bool reliable=true) +{ + Handle userMessage = StartMessageOne("Fade", client, (reliable?USERMSG_RELIABLE:0)); + + if (userMessage == INVALID_HANDLE) { + return false; + } + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && + GetUserMessageType() == UM_Protobuf) { + + int color[4]; + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = a; + + PbSetInt(userMessage, "duration", duration); + PbSetInt(userMessage, "hold_time", holdtime); + PbSetInt(userMessage, "flags", mode); + PbSetColor(userMessage, "clr", color); + } + else { + BfWriteShort(userMessage, duration); // Fade duration + BfWriteShort(userMessage, holdtime); // Fade hold time + BfWriteShort(userMessage, mode); // What to do + BfWriteByte(userMessage, r); // Color R + BfWriteByte(userMessage, g); // Color G + BfWriteByte(userMessage, b); // Color B + BfWriteByte(userMessage, a); // Color Alpha + } + EndMessage(); + + return true; +} + +/** + * This function retrieves an array that holds all clones of a client by IP check. + * Size of CloneList has to be MaxClients at least, or MAX_PLAYERS + * + * @param client Client index. + * @param closelist An array that holds all clones of a client. + * @return Returns how many clones a client has. + */ +stock int Client_GetClones(int client, int[] cloneList) +{ + int x=0; + char ip_client[16], ip_player[16]; + + GetClientIP(client, ip_client, sizeof(client)); + + for (int player=1; player <= MaxClients; player++) { + + if (IsClientInGame(player)) { + GetClientIP(player, ip_player, sizeof(ip_player)); + + if (StrEqual(ip_client, ip_player, false)) { + cloneList[x++] = player; + } + } + } + + return x; +} + +/* + * This function returns true if the client is at a ladder.. + * + * @param client Client index. + * @return Returns true if the client is on a ladder other wise false. + */ +stock bool Client_IsOnLadder(int client) +{ + MoveType movetype = GetEntityMoveType(client); + + if (movetype == MOVETYPE_LADDER) { + return true; + } + else{ + return false; + } +} + +enum Water_Level +{ + WATER_LEVEL_NOT_IN_WATER = 0, + WATER_LEVEL_FEET_IN_WATER, + WATER_LEVEL_WAIST_IN_WATER, + WATER_LEVEL_HEAD_IN_WATER +}; + +/* + * This function returns how deep a client is in water. + * + * @param client Client index. + * @return Returns 0 if not in water. 1 if feets are in water. 2 if waist is in water. 3 if head is in water. + */ +stock Water_Level Client_GetWaterLevel(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_nWaterLevel")); +} + +/* + * Returns how much suit sprint power a client has left in percent. + * + * @param client Client index. + * @return returns the actual power left in percent. + */ +stock float Client_GetSuitSprintPower(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_flSuitPower"); +} + +/* + * Sets a client suit sprint power in percent. + * + * @param client Client index. + * @param power power (0.0 to 100.0) + */ +stock void Client_SetSuitSprintPower(int client, float power) +{ + SetEntPropFloat(client, Prop_Send, "m_flSuitPower", power); +} + +/* + * Returns the client count put in the server. + * + * @param inGameOnly If false connecting players are also counted. + * @param countBots If true bots will be counted too. + * @return Client count in the server. + */ +stock int Client_GetCount(bool countInGameOnly=true, bool countFakeClients=true) +{ + int numClients = 0; + + for (int client=1; client <= MaxClients; client++) { + + if (!IsClientConnected(client)) { + continue; + } + + if (countInGameOnly && !IsClientInGame(client)) { + continue; + } + + if (!countFakeClients && IsFakeClient(client)) { + continue; + } + + numClients++; + } + + return numClients; +} + +/* + * Returns the ping of a client like it is displayed in the scoreboard. + * The weird calculation formula is taken from Valve's SDK + * hl2sdk\game\server\util.cpp: UTIL_GetPlayerConnectionInfo() + * The Scoreboard uses the goldSource corrected Ping, the net_graph doesn't + * For Fake Clients 0 is returned. + * + * @param client Client index + * @param goldSource If true, get the ping as displayed in the player's scoreboard, false returns the net_graph variant. + * @return Client's fake ping or 0 for fake clients + */ +stock int Client_GetFakePing(int client, bool goldSource=true) +{ + if (IsFakeClient(client)) { + return 0; + } + + int ping; + float latency = GetClientLatency(client, NetFlow_Outgoing); // in seconds + + // that should be the correct latency, we assume that cmdrate is higher + // then updaterate, what is the case for default settings + char cl_cmdrate[4]; + GetClientInfo(client, "cl_cmdrate", cl_cmdrate, sizeof(cl_cmdrate)); + + float tickRate = GetTickInterval(); + latency -= (0.5 / StringToInt(cl_cmdrate)) + TICKS_TO_TIME(1.0); // correct latency + + if (goldSource) { + // in GoldSrc we had a different, not fixed tickrate. so we have to adjust + // Source pings by half a tick to match the old GoldSrc pings. + latency -= tickRate * 0.5; + } + + ping = RoundFloat(latency * 1000.0); // as msecs + ping = Math_Clamp(ping, 5, 1000); // set bounds, dont show pings under 5 msecs + + return ping; +} + +/** + * Searches for the closest client in relation to the given client. + * + * @param client Client index + * @return The closest client or -1 + */ +stock int Client_GetClosestToClient(int client) +{ + return Edict_GetClosestToEdict(client, true); +} + +/** + * Gets the name of the last place (if set by the game) + * + * @param entity Entity index. + * @param buffer String buffer + * @param size Size of the String buffer + */ +stock void Client_GetLastPlaceName(int client, char[] buffer, int size) +{ + GetEntPropString(client, Prop_Send, "m_szLastPlaceName", buffer, size); +} + +/** + * Returns the client's Score. + * + * @param client Client's index. + * @return Score. + */ +stock int Client_GetScore(int client) +{ + return GetClientFrags(client); +} + +/** + * Sets the client's Score. + * + * @param client Client's index. + * @param value Score. + * @noreturn + */ +stock void Client_SetScore(int client, int value) +{ + SetEntProp(client, Prop_Data, "m_iFrags", value); +} + +/** + * Returns the client's Death count + * + * @param client Client's index. + * @return Death count + */ +stock int Client_GetDeaths(int client) +{ + return GetEntProp(client, Prop_Data, "m_iDeaths"); +} + +/** + * Sets the client's Death count. + * + * @param client Client's index. + * @param value Death count + */ +stock void Client_SetDeaths(int client, int value) +{ + SetEntProp(client, Prop_Data, "m_iDeaths", value); +} + +/** + * Returns the client's Armor + * + * @param client Client's index. + * @return Armor value + */ +stock int Client_GetArmor(int client) +{ + return GetEntProp(client, Prop_Data, "m_ArmorValue"); +} + +/** + * Sets the client's Armor. + * + * @param client Client's index. + * @param value Armor value + */ +stock void Client_SetArmor(int client, int value) +{ + SetEntProp(client, Prop_Data, "m_ArmorValue", value); +} + +/** + * Returns the client's Suitpower + * + * @param client Client's index. + * @return Suitpower + */ +stock float Client_GetSuitPower(int client) +{ + return GetEntPropFloat(client, Prop_Data, "m_flSuitPower"); +} + +/** + * Sets the client's Suitpower + * + * @param client Client's index. + * @param value Suitpower + */ +stock void Client_SetSuitPower(int client, float value) +{ + SetEntPropFloat(client, Prop_Data, "m_flSuitPower", value); +} + +// suit usage bits +#define bits_SUIT_DEVICE_SPRINT 0x00000001 +#define bits_SUIT_DEVICE_FLASHLIGHT 0x00000002 +#define bits_SUIT_DEVICE_BREATHER 0x00000004 +#define MAX_SUIT_DEVICES 3 + +/** + * Returns the client's active devices (Max MAX_SUIT_DEVICES) + * The return is a bitwise value with bits_SUIT_DEVICE_SPRINT, + * bits_SUIT_DEVICE_FLASHLIGHT and/or bits_SUIT_DEVICE_BREATHER set. + * + * @param client Client's index. + * @return The active devices (bitwise value) + */ +stock int Client_GetActiveDevices(int client) +{ + return GetEntProp(client, Prop_Send, "m_bitsActiveDevices"); +} + +/** + * Returns the time when the client is allowed to spray + * a decal again. + * + * @param client Client's index. + * @return Next decal time + */ +stock float Client_GetNextDecalTime(int client) +{ + return GetEntPropFloat(client, Prop_Data, "m_flNextDecalTime"); +} + +/** + * Returns whether the client is allowed to spray a decal or not. + * + * @param client Client's index. + * @return True if he is allowed to spray a decal, false otherwise + */ +stock bool Client_CanSprayDecal(int client) +{ + return Client_GetNextDecalTime(client) <= GetGameTime(); +} + +/** + * Returns the vehicle the client is in, if the client + * isn't in a vehicle, -1 is returned. + * + * @param client Client's index. + * @return Vehicle index, -1 if the client isn't in a vehicle. + */ +stock int Client_GetVehicle(int client) +{ + int m_hVehicle = GetEntPropEnt(client, Prop_Send, "m_hVehicle"); + + return m_hVehicle; +} + +/** + * Returns whether the client is in a vehicle or not. + * + * @param client Client's index. + * @return True if he is in a vehicle, false otherwise + */ +stock bool Client_IsInVehicle(int client) +{ + return (Client_GetVehicle(client) != -1); +} + +/** + * Removes all decals for a client + * + * @param client Client's index. + */ +stock void Client_RemoveAllDecals(int client) +{ + ClientCommand(client, "r_cleardecals"); +} + +/** + * Let's the client exit the vehicle + * + * @param vehicle Client index. + * @return True on success, false otherwise. + */ +stock bool Client_ExitVehicle(int client) +{ + int vehicle = Client_GetVehicle(client); + + if (vehicle == -1) { + return false; + } + + return AcceptEntityInput(vehicle, "ExitVehicle"); +} + +/** + * Plays a soundfile as if the player is using voicecomm for a single client. + * The voiceindicator is shown on the right, as if the players is talking. + * Thanks to Peace-Maker for the function. + * + * @param client For whom to play the sound. + * @param emitter Player/Entity the voice stream comes from. + * @param soundfile Path to the soundfile relative to the sound folder. + * @param length Length in seconds how long the hud "voiceindicator" is shown. + * @param pitch The pitch of the audiofile. + * @return True on success, false on failure. + */ +stock bool Client_RawAudio(int client, int emitter, const char[] soundfile, float length = 0.0, int pitch = 100) +{ + Handle message = StartMessageOne("RawAudio", client); + + if (message == INVALID_HANDLE) { + return false; + } + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(message, "pitch", pitch); + PbSetInt(message, "entidx", emitter); + PbSetFloat(message, "duration", length ); + PbSetString(message, "voice_filename", soundfile); + } + else { + BfWriteByte(message, pitch); + BfWriteByte(message, emitter); + BfWriteFloat(message, length); + BfWriteString(message, soundfile); + } + EndMessage(); + + return true; +} + +/** + * Plays a soundfile as if the player is using voicecomm for all players. + * The voiceindicator is shown on the right, as if the players is talking. + * Thanks to Peace-Maker for the function. + * + * @param emitter Player/Entity the voice stream comes from. + * @param soundfile Path to the soundfile relative to the sound folder. + * @param length Length in seconds how long the hud "voiceindicator" is shown. + * @param pitch The pitch of the audiofile. + * @return True on success, false on failure. + */ +stock bool Client_RawAudioToAll(int emitter, const char[] soundfile, float length = 0.0, int pitch = 100) +{ + Handle message = StartMessageAll("RawAudio"); + + if (message == INVALID_HANDLE) { + return false; + } + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(message, "pitch", pitch); + PbSetInt(message, "entidx", emitter); + PbSetFloat(message, "duration", length); + PbSetString(message, "voice_filename", soundfile); + } + else { + BfWriteByte(message, pitch); + BfWriteByte(message, emitter); + BfWriteFloat(message, length); + BfWriteString(message, soundfile); + } + EndMessage(); + + return true; +} + +/** + * Sets an Impulse value for a client (eg: "impulse 100" for flashlight, value would be 100). + * See: http://developer.valvesoftware.com/wiki/Impulse + * + * @param client Client Index + * @param value The impulse command value. + * @return True on success, false on failure. + */ +stock void Client_Impulse(int client, int value) +{ + SetEntProp(client, Prop_Data, "m_nImpulse", value); +} + +/** + * Gets the offset for a client's weapon list (m_hMyWeapons). + * The offset will saved globally for optimization. + * + * @param client Client Index. + * @return Weapon list offset or -1 on failure. + */ +stock int Client_GetWeaponsOffset(int client) +{ + static int offset = -1; + + if (offset == -1) { + offset = FindDataMapInfo(client, "m_hMyWeapons"); + } + + return offset; +} + +/** + * Gets the current/active weapon of a client + * + * @param client Client Index. + * @return Weapon Index or INVALID_ENT_REFERENCE if the client has no active weapon. + */ +stock int Client_GetActiveWeapon(int client) +{ + int weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); + + if (!Entity_IsValid(weapon)) { + return INVALID_ENT_REFERENCE; + } + + return weapon; +} + +/** + * Gets the classname and entity index of the current/active weapon of a client. + * + * @param client Client Index. + * @param buffer String Buffer to store the weapon's classname. + * @param size Max size of String: buffer. + * @return Weapon Entity Index on success or INVALID_ENT_REFERENCE otherwise + */ +stock int Client_GetActiveWeaponName(int client, char[] buffer, int size) +{ + int weapon = Client_GetActiveWeapon(client); + + if (weapon == INVALID_ENT_REFERENCE) { + buffer[0] = '\0'; + return INVALID_ENT_REFERENCE; + } + + Entity_GetClassName(weapon, buffer, size); + + return weapon; +} + +/** + * Changes the active/current weapon of a player by Index. + * Note: No changing animation will be played ! + * + * @param client Client Index. + * @param weapon Index of a valid weapon. + */ +stock void Client_SetActiveWeapon(int client, int weapon) +{ + SetEntPropEnt(client, Prop_Data, "m_hActiveWeapon", weapon); + ChangeEdictState(client, FindDataMapInfo(client, "m_hActiveWeapon")); +} + +/** + * Changes the active weapon the client is holding. + * Note: No changing animation will be played ! + * + * @param client Client Index. + * @param className Weapon Classname. + * @return True on success, false on failure. + */ +stock bool Client_ChangeWeapon(int client, const char[] className) +{ + int weapon = Client_GetWeapon(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + return false; + } + + Client_SetActiveWeapon(client,weapon); + + return true; +} + +/** + * Changes the active weapon to the last. + * If the last active weapon can't be found, the default weapon is taken. + * If the default weapon can't be found, the first weapon in the list is taken. + * If the first weapon can't be found, INVALID_ENT_REFERENCEE is returned. + * + * @param client Client Index. + * @return Entity Index or, INVALID_ENT_REFERENCE. + */ +stock int Client_ChangeToLastWeapon(int client) +{ + int weapon = Client_GetLastActiveWeapon(client); + + if (weapon == INVALID_ENT_REFERENCE) { + weapon = Client_GetDefaultWeapon(client); + + if (weapon == INVALID_ENT_REFERENCE) { + weapon = Client_GetFirstWeapon(client); + + if (weapon == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + } + } + + Client_SetActiveWeapon(client, weapon); + + return weapon; +} + +/** + * Gets the last active weapon of a client. + * + * @param client Client Index. + * @return Entity Index of the weapon on success, INVALID_ENT_REFERENCE on failure. + */ +stock int Client_GetLastActiveWeapon(int client) +{ + int weapon = GetEntPropEnt(client, Prop_Data, "m_hLastWeapon"); + + if (!Entity_IsValid(weapon)) { + return INVALID_ENT_REFERENCE; + } + + return weapon; +} + +/** + * Gets the classname of the last active weapon of a client. + * + * @param client Client Index. + * @param buffer Buffer to store the weapon classname. + * @param size Max size of String: buffer. + * @return Weapon Entity Index on success or INVALID_ENT_REFERENCE otherwise + */ +stock int Client_GetLastActiveWeaponName(int client, char[] buffer, int size) +{ + int weapon = Client_GetLastActiveWeapon(client); + + if (weapon == INVALID_ENT_REFERENCE) { + buffer[0] = '\0'; + return INVALID_ENT_REFERENCE; + } + + Entity_GetClassName(weapon, buffer, size); + + return weapon; +} + +/** + * Sets the last active weapon of a client. + * + * @param client Client Index. + * @param weapon Entity Index of a weapon. + * @noreturn + */ +stock void Client_SetLastActiveWeapon(int client, int weapon) +{ + SetEntPropEnt(client, Prop_Data, "m_hLastWeapon", weapon); + ChangeEdictState(client, FindDataMapInfo(client, "m_hLastWeapon")); +} + +/** + * Equips (attaches) a weapon to a client. + * + * @param client Client Index. + * @param weapon Entity Index of the weapon. + * @param switchTo If true, the client will switch to that weapon (make it active). + */ +stock void Client_EquipWeapon(int client, int weapon, bool switchTo=false) +{ + EquipPlayerWeapon(client, weapon); + + if (switchTo) { + Client_SetActiveWeapon(client, weapon); + } +} + +/** + * Savly detaches a clients weapon, to remove it as example. + * The client will select his last weapon when detached. + * + * @param client Client Index. + * @param weapon Entity Index of the weapon, you'd like to detach. + * @return True on success, false otherwise. + */ +stock bool Client_DetachWeapon(int client, int weapon) +{ + if (!RemovePlayerItem(client, weapon)) { + return false; + } + + if (Client_GetActiveWeapon(client) == INVALID_ENT_REFERENCE) { + Client_ChangeToLastWeapon(client); + } + + return true; +} + +/** + * Gives a client a weapon. + * + * @param client Client Index. + * @param className Weapon Classname String. + * @param switchTo If set to true, the client will switch the active weapon to the new weapon. + * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure. + */ +stock int Client_GiveWeapon(int client, const char[] className, bool switchTo=true) +{ + int weapon = Client_GetWeapon(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + weapon = Weapon_CreateForOwner(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + } + + Client_EquipWeapon(client, weapon, switchTo); + + return weapon; +} + +/** + * Gives a client a weapon and ammo for that weapon. + * + * @param client Client Index. + * @param className Weapon Classname String. + * @param switchTo If set to true, the client will switch the active weapon to the new weapon. + * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. + * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched. + * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched. + * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure. + */ +stock int Client_GiveWeaponAndAmmo(int client, const char[] className, bool switchTo=true, int primaryAmmo=-1, int secondaryAmmo=-1, int primaryClip=-1, int secondaryClip=-1) +{ + int weapon = Client_GiveWeapon(client, className, switchTo); + + if (weapon == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + + if (primaryClip != -1) { + Weapon_SetPrimaryClip(weapon, primaryClip); + } + + if (secondaryClip != -1) { + Weapon_SetSecondaryClip(weapon, secondaryClip); + } + + Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); + + return weapon; +} + +/** + * Removes a weapon from a client. + * + * @param client Client Index. + * @param className Weapon Classname String. + * @param firstOnly If false it loops trough the whole weapon list and deletes all weapons that match the specified classname. + * @param clearAmmo If true, the ammo the client carries for that weapon will be set to 0 (primary and secondary). + * @return True on success, false otherwise. + */ +stock bool Client_RemoveWeapon(int client, const char[] className, bool firstOnly=true, bool clearAmmo=false) +{ + int offset = Client_GetWeaponsOffset(client) - 4; + + for (int i=0; i < MAX_WEAPONS; i++) { + offset += 4; + + int weapon = GetEntDataEnt2(client, offset); + + if (!Weapon_IsValid(weapon)) { + continue; + } + + if (!Entity_ClassNameMatches(weapon, className)) { + continue; + } + + if (clearAmmo) { + Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0); + } + + if (Client_GetActiveWeapon(client) == weapon) { + Client_ChangeToLastWeapon(client); + } + + if (RemovePlayerItem(client, weapon)) { + Entity_Kill(weapon); + } + + if (firstOnly) { + return true; + } + } + + return false; +} + +/** + * Removes all weapons of a client. + * You can specify a weapon it shouldn't remove and if to + * clear the player's ammo for a weapon when it gets removed. + * + * @param client Client Index. + * @param exclude If not empty, this weapon won't be removed from the client. + * @param clearAmmo If true, the ammo the player carries for all removed weapons are set to 0 (primary and secondary). + * @return Number of removed weapons. + */ +stock int Client_RemoveAllWeapons(int client, const char[] exclude="", bool clearAmmo=false) +{ + int offset = Client_GetWeaponsOffset(client) - 4; + + int numWeaponsRemoved = 0; + for (int i=0; i < MAX_WEAPONS; i++) { + offset += 4; + + int weapon = GetEntDataEnt2(client, offset); + + if (!Weapon_IsValid(weapon)) { + continue; + } + + if (exclude[0] != '\0' && Entity_ClassNameMatches(weapon, exclude)) { + Client_SetActiveWeapon(client, weapon); + continue; + } + + if (clearAmmo) { + Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0); + } + + if (RemovePlayerItem(client, weapon)) { + Entity_Kill(weapon); + } + + numWeaponsRemoved++; + } + + return numWeaponsRemoved; +} + +/** + * Checks if a client has a specific weapon. + * + * @param client Client Index. + * @param className Weapon Classname. + * @return True if client has the weapon, otherwise false. + */ +stock bool Client_HasWeapon(int client, const char[] className) +{ + int weapon = Client_GetWeapon(client, className); + + return (weapon != INVALID_ENT_REFERENCE); +} + +/** + * Gets the weapon of a client by the weapon's classname. + * + * @param client Client Index. + * @param className Classname of the weapon. + * @return Entity index on success or INVALID_ENT_REFERENCE. + */ +stock int Client_GetWeapon(int client, const char[] className) +{ + int offset = Client_GetWeaponsOffset(client) - 4; + int weapon = INVALID_ENT_REFERENCE; + for (int i=0; i < MAX_WEAPONS; i++) { + offset += 4; + + weapon = GetEntDataEnt2(client, offset); + + if (!Weapon_IsValid(weapon)) { + continue; + } + + if (Entity_ClassNameMatches(weapon, className)) { + return weapon; + } + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Gets the weapon of a client by slot number. + * Note: This is incompatible to games that have multiple + * weapons in one slot (eg.: hl2dm). + * + * @param client Client Index. + * @param slot Slot Index. + * @return Entity index on success or INVALID_ENT_REFERENCE. + */ +stock int Client_GetWeaponBySlot(int client, int slot) +{ + return GetPlayerWeaponSlot(client, slot); +} + +/** + * Gets the clients default weapon (Entity Index). + * + * @param client Client Index. + * @return Entity Index on success, INVALID_ENT_REFERENCE on failure. + */ +stock int Client_GetDefaultWeapon(int client) +{ + char weaponName[MAX_WEAPON_STRING]; + if (Client_GetDefaultWeaponName(client, weaponName, sizeof(weaponName))) { + return INVALID_ENT_REFERENCE; + } + + return Client_GetWeapon(client, weaponName); +} + +/** + * Gets the clients default weapon (classname). + * This function doesn't work in all games (maybe only works in hl2dm). + * It will return an empty string if cl_defaultweapon doesn't exist. + * + * @param client Client Index. + * @param buffer Buffer to store the default weapon's classname. + * @param size Max size of string: buffer. + * @return True on success, false otherwise. + */ +stock bool Client_GetDefaultWeaponName(int client, char[] buffer, int size) +{ + if (!GetClientInfo(client, "cl_defaultweapon", buffer, size)) { + buffer[0] = '\0'; + return false; + } + + return true; +} + +/** + * Gets the first weapon of the client's weapon list (m_hMyWeapons). + * Note: This has nothing to do with weapon slots. + * + * @param client Client Index. + * @return Entity Index of the weapon or INVALID_ENT_REFERENCE. + */ +stock int Client_GetFirstWeapon(int client) +{ + int offset = Client_GetWeaponsOffset(client) - 4; + + for (int i=0; i < MAX_WEAPONS; i++) { + offset += 4; + + int weapon = GetEntDataEnt2(client, offset); + + if (!Weapon_IsValid(weapon)) { + continue; + } + + return weapon; + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Gets the number of weapons a client has. + * + * @param client Client Index. + * @return Number of weapons. + */ +stock int Client_GetWeaponCount(int client) +{ + int numWeapons = 0; + + int offset = Client_GetWeaponsOffset(client) - 4; + + for (int i=0; i < MAX_WEAPONS; i++) { + offset += 4; + + int weapon = GetEntDataEnt2(client, offset); + + if (!Weapon_IsValid(weapon)) { + continue; + } + + numWeapons++; + } + + return numWeapons; +} + +/** + * Checks whether the client is currently reloading his active weapon. + * + * @param client Client Index. + * @return True if client is reloading, false otherwise. + */ +stock bool Client_IsReloading(int client) +{ + int weapon = Client_GetActiveWeapon(client); + + if (weapon == INVALID_ENT_REFERENCE) { + return false; + } + + return Weapon_IsReloading(weapon); +} + +/** + * Sets the primary and secondary clip value of a weapon. + * + * @param client Client Index. + * @param classname Classname of a weapon. + * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched. + * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched. + * @return True on success, false on failure. + */ +stock bool Client_SetWeaponClipAmmo(int client, const char[] className, int primaryClip=-1, int secondoaryClip=-1) +{ + int weapon = Client_GetWeapon(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + return false; + } + + if (primaryClip != -1) { + Weapon_SetPrimaryClip(weapon, primaryClip); + } + + if (secondoaryClip != -1) { + Weapon_SetSecondaryClip(weapon, primaryClip); + } + + return true; +} + +/** + * Gets the primary and secondary ammo the player carries for a specific weapon classname. + * + * @param client Client Index. + * @param classname Classname of a weapon. + * @param primaryAmmo Primary ammo stock from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock from the client, if -1 the value is untouched. + * @return True on success, false on failure. + */ +stock bool Client_GetWeaponPlayerAmmo(int client, const char[] className, int &primaryAmmo=-1, int &secondaryAmmo=-1) +{ + int weapon = Client_GetWeapon(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + return false; + } + + int offset_ammo = FindDataMapInfo(client, "m_iAmmo"); + + if (primaryAmmo != -1) { + int offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); + primaryAmmo = GetEntData(client, offset); + } + + if (secondaryAmmo != -1) { + int offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); + secondaryAmmo = GetEntData(client, offset); + } + + return true; +} + +/** + * Gets the primary and secondary ammo the player carries for a specific weapon index. + * + * @param client Client Index. + * @param weapon Weapon Entity Index. + * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. + */ +stock void Client_GetWeaponPlayerAmmoEx(int client, int weapon, int &primaryAmmo=-1, int &secondaryAmmo=-1) +{ + int offset_ammo = FindDataMapInfo(client, "m_iAmmo"); + + if (primaryAmmo != -1) { + int offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); + primaryAmmo = GetEntData(client, offset); + } + + if (secondaryAmmo != -1) { + int offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); + secondaryAmmo = GetEntData(client, offset); + } +} + +/** + * Sets the primary and secondary ammo the player carries for a specific weapon classname. + * + * @param client Client Index. + * @param classname Weapon Classname String. + * @param primaryAmmo Primary ammo stock from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock from the client, if -1 the value is untouched. + * @return True on success, false on failure. + */ +stock bool Client_SetWeaponPlayerAmmo(int client, const char[] className, int primaryAmmo=-1, int secondaryAmmo=-1) +{ + int weapon = Client_GetWeapon(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + return false; + } + + Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); + + return true; +} + +/** + * Sets the primary and secondary ammo the player carries for a specific weapon index. + * + * @param client Client Index. + * @param weapon Weapon Entity Index. + * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. + */ +stock void Client_SetWeaponPlayerAmmoEx(int client, int weapon, int primaryAmmo=-1, int secondaryAmmo=-1) +{ + int offset_ammo = FindDataMapInfo(client, "m_iAmmo"); + + if (primaryAmmo != -1) { + int offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); + SetEntData(client, offset, primaryAmmo, 4, true); + } + + if (secondaryAmmo != -1) { + int offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); + SetEntData(client, offset, secondaryAmmo, 4, true); + } +} + +/** + * Sets the value from primary and secondary ammo stock, of a client. + * + * @param client Client Index. + * @param className Classname of a weapon. + * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. + * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched. + * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched. + * @return True on success, false on failure. + */ +stock bool Client_SetWeaponAmmo(int client, const char[] className, int primaryAmmo=-1, int secondaryAmmo=-1, int primaryClip=-1, int secondaryClip=-1) +{ + int weapon = Client_GetWeapon(client, className); + + if (weapon == INVALID_ENT_REFERENCE) { + return false; + } + + if (primaryClip != -1) { + Weapon_SetPrimaryClip(weapon, primaryClip); + } + if (secondaryClip != -1) { + Weapon_SetSecondaryClip(weapon, secondaryClip); + } + Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); + + return true; +} + +/** + * Gets the next weapon of a client, starting at start. + * + * @param client Client Index (must be a valid client ingame). + * @param index Reference to an index variable, will contain the index of the next weapon to check. + * @return Weapon Index or -1 if no more weapons are found. + */ +stock int Client_GetNextWeapon(int client, int &index = 0) +{ + int offset = Client_GetWeaponsOffset(client) + (index * 4); + + int weapon; + while (index < MAX_WEAPONS) { + index++; + + weapon = GetEntDataEnt2(client, offset); + + if (Weapon_IsValid(weapon)) { + return weapon; + } + + offset += 4; + } + + return -1; +} + +/** + * Prints white text to the bottom center of the screen + * for one client. Does not work in all games. + * Line Breaks can be done with "\n". + * + * @param client Client Index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return True on success, false if this usermessage doesn't exist. + */ +stock bool Client_PrintHintText(int client, const char[] format, any ...) +{ + Handle userMessage = StartMessageOne("HintText", client); + + if (userMessage == INVALID_HANDLE) { + return false; + } + + char buffer[254]; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 3); + + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetString(userMessage, "text", buffer); + } + else { + BfWriteByte(userMessage, 1); + BfWriteString(userMessage, buffer); + } + + EndMessage(); + + return true; +} + +/** + * Prints white text to the bottom center of the screen + * for all clients. Does not work in all games. + * Line Breaks can be done with "\n". + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintHintTextToAll(const char[] format, any ...) +{ + char buffer[254]; + + for (int client=1; client <= MaxClients; client++) { + + if (!IsClientInGame(client)) { + continue; + } + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 2); + Client_PrintHintText(client, buffer); + } +} + +/** + * Prints white text to the right-center side of the screen + * for one client. Does not work in all games. + * Line Breaks can be done with "\n". + * + * @param client Client Index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return True on success, false if this usermessage doesn't exist. + */ +stock bool Client_PrintKeyHintText(int client, const char[] format, any ...) +{ + Handle userMessage = StartMessageOne("KeyHintText", client); + + if (userMessage == INVALID_HANDLE) { + return false; + } + + char buffer[254]; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 3); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbAddString(userMessage, "hints", buffer); + } + else { + BfWriteByte(userMessage, 1); + BfWriteString(userMessage, buffer); + } + + EndMessage(); + + return true; +} + +/** + * Prints white text to the right-center side of the screen + * for all clients. Does not work in all games. + * Line Breaks can be done with "\n". + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +stock void Client_PrintKeyHintTextToAll(const char[] format, any ...) +{ + char buffer[254]; + + for (int client=1; client <= MaxClients; client++) { + + if (!IsClientInGame(client)) { + continue; + } + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 2); + Client_PrintKeyHintText(client, buffer); + } +} + +/** + * Prints a reliable raw chat message to a client in the chat area. + * If the client == 0, the message will printed to server console. + * + * @param client Client Index. + * @param message String Message. + * @param subject Client Index/Subject (normally used for teamcolors) + * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. + */ +stock void Client_PrintToChatRaw(int client, const char[] message, int subject=0, bool isChat=false) +{ + if (client == 0) { + char buffer[253]; + Color_StripFromChatText(message, buffer, sizeof(buffer)); + PrintToServer(buffer); + return; + } + + static bool sayText2_supported = true; + static bool sayText2_checked = false; + + if (!sayText2_checked) { + + if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) { + sayText2_supported = false; + } + + sayText2_checked = true; + } + + Handle userMessage = INVALID_HANDLE; + + if (sayText2_supported) { + userMessage = StartMessageOne("SayText2", client, USERMSG_RELIABLE); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "ent_idx", subject); + PbSetBool(userMessage, "chat", isChat); + PbSetString(userMessage, "msg_name", message); + + // psychonic: Furthermore, some usermessages with repeated field, + // such as the commonly-used SayText2, expected an undocumented + // specific number of values added, else the client will crash when receiving. + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + } + else { + BfWriteByte(userMessage , subject); + BfWriteByte(userMessage , isChat); + BfWriteString(userMessage , message); + } + } + else { + userMessage = StartMessageOne("SayText", client, USERMSG_RELIABLE); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "ent_idx", subject); + PbSetString(userMessage, "text", message); + PbSetBool(userMessage, "chat", isChat); + } + else { + BfWriteByte(userMessage , subject); + BfWriteString(userMessage , message); + // For DoD:S nickname coloring + BfWriteByte(userMessage , -1); + } + } + + EndMessage(); +} + +/** + * Prints a reliable chat message to one client in the chat area. + * Allows up to 253 Characters (including \0) to be printed. + * Supports chat color tags (see: colors.inc). + * + * @param client Client Index. + * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. + * @param format Formatting rules String. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintToChat(int client, bool isChat, const char[] format, any ...) +{ + char + buffer[512], + buffer2[253]; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 4); + int subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); + + Client_PrintToChatRaw(client, buffer2, subject, isChat); + + Color_ChatClearSubject(); +} + +static int printToChat_excludeclient = -1; + +/** + * Exclude a client from the next call to a Client_PrintToChat function. + * + * @param client Client Index. + * @noreturn + */ +stock void Client_PrintToChatExclude(int client) +{ + printToChat_excludeclient = client; +} + +/** + * Prints a reliable chat message to all clients in the chat area. + * Allows up to 253 Characters (including \0) to be printed. + * Supports chat color tags (see: colors.inc). + * + * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. + * @param format Formatting rules String. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintToChatAll(bool isChat, const char[] format, any ...) +{ + char + buffer[512], + buffer2[253]; + int + subject, + language, + lastLanguage = -1; + + for (int client=1; client <= MaxClients; client++) { + + if (!IsClientInGame(client)) { + continue; + } + + if (client == printToChat_excludeclient) { + printToChat_excludeclient = -1; + continue; + } + + language = GetClientLanguage(client); + + if (language != lastLanguage) { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 3); + subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); + + lastLanguage = language; + } + + Client_PrintToChatRaw(client, buffer2, subject, isChat); + } + + Color_ChatClearSubject(); +} + +/** + * Prints a reliable chat message to the specified clients in the chat area. + * Allows up to 253 Characters (including \0) to be print. + * Supports chat color tags (see: colors.inc). + * + * @param clients Client Array. + * @param numClients Number of clients in the client array. + * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintToChatEx(int[] clients, int numClients, bool isChat, const char[] format, any ...) +{ + char + buffer[512], + buffer2[253]; + int + client, + subject, + language, + lastLanguage = -1; + + for (int i=0; i < numClients; i++) { + + client = clients[i]; + + if (!IsClientInGame(client)) { + continue; + } + + if (client == printToChat_excludeclient) { + printToChat_excludeclient = -1; + continue; + } + + language = GetClientLanguage(client); + + if (language != lastLanguage) { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 5); + subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); + + lastLanguage = language; + } + + Client_PrintToChatRaw(client, buffer2, subject, isChat); + } + + Color_ChatClearSubject(); +} + +enum ClientHudPrint { + ClientHudPrint_Notify = 1, + ClientHudPrint_Console, + ClientHudPrint_Talk, + Client_HudPrint_Center +}; + +/** + * Prints a relieable message to the client's console. + * Allows up to 254 Characters (including \0) to be print (253 for talk). + * Supports chat color tags (see: colors.inc, only available in Left 4 Dead (2) or higher). + * Chat colors are stripped automatically if not supported. + * + * @param clients Client Array. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintToConsole(int client, const char[] format, any ...) +{ + char buffer[512]; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 3); + + Client_Print(client, ClientHudPrint_Console, buffer); +} + +/** + * Prints a relieable message to the client's console. + * Allows up to 254 Characters (including \0) to be print. + * Supports chat color tags in chat & console (see: colors.inc). + * Chat colors are stripped automatically if not supported in the destination. + * + * @param clients Client Array. + * @param destination Destination place (use onf of the ClientHudPrint_) + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void Client_Print(int client, ClientHudPrint destination, const char[] format, any ...) +{ + char buffer[512], buffer2[254]; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 4); + + int subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); + + if (destination == ClientHudPrint_Talk) { + Client_PrintToChatRaw(client, buffer2, subject, false); + return; + } + + EngineVersion engineVersion = GetEngineVersion(); + if (client == 0 || + destination != ClientHudPrint_Console || + (destination == ClientHudPrint_Console + && engineVersion != Engine_Left4Dead && engineVersion != Engine_Left4Dead2)) + { + Color_StripFromChatText(buffer2, buffer2, sizeof(buffer2)); + + if (client == 0) { + PrintToServer(buffer2); + return; + } + } + + Handle userMessage = INVALID_HANDLE; + userMessage = StartMessageOne("TextMsg", client, USERMSG_RELIABLE); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "msg_dst", view_as(destination)); + PbAddString(userMessage, "params", buffer2); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + } + else { + BfWriteByte(userMessage , view_as(destination)); + BfWriteString(userMessage , buffer2); + } + + EndMessage(); +} + +/** + * Replies to a message in a command. + * A client index of 0 will use PrintToServer(). + * If the command was from the console, Client_PrintToConsole() is used. + * If the command was from chat, Client_PrintToChat() is used. + * + * @param client Client Index. + * @param format Formatting rules String. + * @param ... Variable number of format parameters. + */ +stock void Client_Reply(int client, const char[] format, any ...) +{ + char buffer[255]; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 3); + + if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { + Client_PrintToConsole(client, buffer); + } + else { + Client_PrintToChat(client, false, buffer); + } +} + +#define SHAKE_START 0 // Starts the screen shake for all players within the radius. +#define SHAKE_STOP 1 // Stops the screen shake for all players within the radius. +#define SHAKE_AMPLITUDE 2 // Modifies the amplitude of an active screen shake for all players within the radius. +#define SHAKE_FREQUENCY 3 // Modifies the frequency of an active screen shake for all players within the radius. +#define SHAKE_START_RUMBLEONLY 4 // Starts a shake effect that only rumbles the controller, no screen effect. +#define SHAKE_START_NORUMBLE 5 // Starts a shake that does NOT rumble the controller. + +/** + * Shakes a client's screen with the specified amptitude, + * frequency & duration. + * + * @param client Client Index. + * @param command Shake Mode, use one of the SHAKE_ definitions. + * @param amplitude Shake magnitude/amplitude. + * @param frequency Shake noise frequency. + * @param duration Shake lasts this long. + * @return True on success, false otherwise. + */ +stock bool Client_Shake(int client, int command=SHAKE_START, float amplitude=50.0, float frequency=150.0, float duration=3.0) +{ + if (command == SHAKE_STOP) { + amplitude = 0.0; + } + else if (amplitude <= 0.0) { + return false; + } + + Handle userMessage = StartMessageOne("Shake", client); + + if (userMessage == INVALID_HANDLE) { + return false; + } + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "command", command); + PbSetFloat(userMessage, "local_amplitude", amplitude); + PbSetFloat(userMessage, "frequency", frequency); + PbSetFloat(userMessage, "duration", duration); + } + else { + BfWriteByte(userMessage, command); // Shake Command + BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude + BfWriteFloat(userMessage, frequency); // shake noise frequency + BfWriteFloat(userMessage, duration); // shake lasts this long + } + + EndMessage(); + + return true; +} + +/** + * Checks whether the client is a generic admin. + * + * @param Client Index. + * @return True if the client is a generic admin, false otheriwse. + */ +stock bool Client_IsAdmin(int client) +{ + AdminId adminId = GetUserAdmin(client); + + if (adminId == INVALID_ADMIN_ID) { + return false; + } + + return GetAdminFlag(adminId, Admin_Generic); +} + +/** + * Checks whether a client has certain admin flags + * + * @param Client Index. + * @return True if the client has the admin flags, false otherwise. + */ +stock bool Client_HasAdminFlags(int client, int flags=ADMFLAG_GENERIC) +{ + AdminId adminId = GetUserAdmin(client); + + if (adminId == INVALID_ADMIN_ID) { + return false; + } + + return GetAdminFlags(adminId, Access_Effective) & flags == flags; +} + +/** + * Returns whether a player is in a specific admin group. + * + * @param client Client Index. + * @param groupName Admin group name to check. + * @param caseSensitive True if the group check has to be case sensitive, false otherwise. + * @return True if the client is in the admin group, false otherwise. + */ +stock bool Client_IsInAdminGroup(int client, const char[] groupName, bool caseSensitive=true) +{ + AdminId adminId = GetUserAdmin(client); + + // Validate id. + if (adminId == INVALID_ADMIN_ID) { + return false; + } + + // Get number of groups. + int count = GetAdminGroupCount(adminId); + + // Validate number of groups. + if (count == 0) { + return false; + } + + char groupname[64]; + + // Loop through each group. + for (int i = 0; i < count; i++) { + // Get group name. + GetAdminGroup(adminId, i, groupname, sizeof(groupname)); + + // Compare names. + if (StrEqual(groupName, groupname, caseSensitive)) { + return true; + } + } + + // No match. + return false; +} + +/** + * Checks if the client is currently looking at the wall in front + * of him with the given distance as max value. + * + * @param client Client Index. + * @param distance Max Distance as Float value. + * @return True if he is looking at a wall, false otherwise. + */ +stock bool Client_IsLookingAtWall(int client, float distance=40.0) { + + float posEye[3], posEyeAngles[3]; + bool isClientLookingAtWall = false; + + GetClientEyePosition(client, posEye); + GetClientEyeAngles(client, posEyeAngles); + + posEyeAngles[0] = 0.0; + + Handle trace = TR_TraceRayFilterEx(posEye, posEyeAngles, CONTENTS_SOLID, RayType_Infinite, _smlib_TraceEntityFilter); + + if (TR_DidHit(trace)) { + + if (TR_GetEntityIndex(trace) > 0) { + delete trace; + return false; + } + + float posEnd[3]; + + TR_GetEndPosition(posEnd, trace); + + if (GetVectorDistance(posEye, posEnd, true) <= (distance * distance)) { + isClientLookingAtWall = true; + } + } + + delete trace; + + return isClientLookingAtWall; +} + +public bool _smlib_TraceEntityFilter(int entity, int contentsMask) +{ + return entity == 0; +} + +/** + * Gets a client's class. + * Currently supported games are: TF2, Dark Messiah. + * Other games maybe work too, but are not tested. + * + * @param client Client Index. + * @return Class Index. + */ +stock int Client_GetClass(int client) +{ + if (GetEngineVersion() == Engine_DarkMessiah) { + return GetEntProp(client, Prop_Send, "m_iPlayerClass"); + } + + return GetEntProp(client, Prop_Send, "m_iClass"); +} + +/** + * Sets a client's class. + * Currently supported games are: TF2, Dark Messiah. + * Other games maybe work too, but are not tested. + * + * @param client Client Index. + * @param playerClass The class number to set the player to. Depends on game. + * @param persistant If true changes the players desired class so the change stays after death (probably TF2 only). + */ +stock void Client_SetClass(int client, int playerClass, bool persistant=false) +{ + if (GetEngineVersion() == Engine_DarkMessiah) { + SetEntProp(client, Prop_Send, "m_iPlayerClass", playerClass); + } else { + SetEntProp(client, Prop_Send, "m_iClass", playerClass); + + if (persistant) { + SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", playerClass); + } + } +} + +/** + * Returns what buttons are currently pressed by the client. + * + * @param client Client Index. + * @return Buttons as bitflag. + */ +stock int Client_GetButtons(int client) +{ + return GetClientButtons(client); +} + +/** + * Sets the client buttons. + * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd. + * + * @param client Client Index. + * @param buttons Buttons as bitflag. + */ +stock void Client_SetButtons(int client, int buttons) +{ + SetEntProp(client, Prop_Data, "m_nButtons", buttons); +} + +/** + * Adds buttons to the already pressed buttons. + * Note: This will likely only work OnPreThink (sdkhooks) or OnPlayerRunCmd. + * + * @param client Client Index. + * @param buttons Buttons as bitflag. + */ +stock void Client_AddButtons(int client, int buttons) +{ + int newButtons = Client_GetButtons(client); + newButtons |= buttons; + Client_SetButtons(client, newButtons); +} + +/** + * Removes buttons from the already pressed buttons. + * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd. + * + * @param client Client Index. + * @param buttons Buttons as bitflag. + */ +stock void Client_RemoveButtons(int client, int buttons) +{ + int newButtons = Client_GetButtons(client); + newButtons &= ~buttons; + Client_SetButtons(client, newButtons); +} + +/** + * Clears all buttons. + * Note: This will likely only work OnPreThink (sdkhooks) or OnPlayerRunCmd. + * + * @param client Client Index. + */ +stock void Client_ClearButtons(int client) +{ + Client_SetButtons(client,0); +} + +/** + * Returns if the given buttons are pressed by the client or not. + * + * @param client Client Index. + * @param buttons Buttons as bitflag. + * @return True if the buttons are pressed otherwise false. + */ +stock bool Client_HasButtons(int client, int buttons) +{ + return Client_GetButtons(client) & buttons == buttons; +} + +/** + * Returns only the buttons that have changed since the last call of this. + * Example usage: Within OnPlayerRunCmd use this function to call another function only once when a player pressed or released a button. + * + * @param client Client Index. + * @param buttons Buttons as bitflag. + * @return + */ +stock int Client_GetChangedButtons(int client) +{ + static int oldButtons[MAXPLAYERS+1] = {0,...}; + + int buttons = Client_GetButtons(client); + int changedButtons = buttons ^ oldButtons[client]; + + oldButtons[client] = buttons; + + return changedButtons; +} + +/** + * Sets the client's maxspeed to the given value (in units per second) + * + * @param Client Client Index + * @param maxspeed the maximum speed the client can move + */ +stock void Client_SetMaxSpeed(int client, float value) +{ + Entity_SetMaxSpeed(client, value); +} + +/** + * Shows a screen overlay tp a client. + * There can only be one overlay at a time. + * If you want to clear the overlay, pass + * an empty string to this function. + * + * @param Client Client Index. + * @param path Overlay path (based on the game/materials/ folder) or empty String to not show any overlay. + * @noreturn + */ +stock void Client_SetScreenOverlay(int client, const char[] path) +{ + ClientCommand(client, "r_screenoverlay \"%s\"", path); +} + +/** + * Shows a screen overlay to all clients. + * There can only be one overlay at a time. + * If you want to clear the overlay, pass + * an empty string to this function. + * + * @param Client Client Index. + * @param path Overlay path (based on the game/materials/ folder) or empty String to not show any overlay. + * @noreturn + */ +stock void Client_SetScreenOverlayForAll(const char[] path) +{ + LOOP_CLIENTS(client, CLIENTFILTER_INGAME | CLIENTFILTER_NOBOTS) { + Client_SetScreenOverlay(client, path); + } +} + +/** + * Mutes a client's voice + * + * @param Client Client Index. + * @noreturn + */ +stock void Client_Mute(int client) +{ + SetClientListeningFlags(client, VOICE_MUTED); +} + +/** + * UnMutes a client's voice + * Code copied from basecomm.sp + * + * @param Client Client Index. + */ +stock void Client_UnMute(int client) +{ + static ConVar cvDeadTalk = null; + + if (cvDeadTalk == INVALID_HANDLE) { + cvDeadTalk = FindConVar("sm_deadtalk"); + } + + if (cvDeadTalk == INVALID_HANDLE) { + SetClientListeningFlags(client, VOICE_NORMAL); + } + else { + if (cvDeadTalk.IntValue == 1 && !IsPlayerAlive(client)) { + SetClientListeningFlags(client, VOICE_LISTENALL); + } + else if (cvDeadTalk.IntValue == 2 && !IsPlayerAlive(client)) { + SetClientListeningFlags(client, VOICE_TEAM); + } + else { + SetClientListeningFlags(client, VOICE_NORMAL); + } + } +} + +/** + * Checks if a client's voice is muted + * + * @param Client Client Index. + * @return True if the client is muted, false otherwise. + */ +stock bool Client_IsMuted(int client) +{ + return GetClientListeningFlags(client) & VOICE_MUTED > 0; +} + +/** + * Checks if a client matches the specified flag filter. + * Use one of the CLIENTFILTER_ constants. + * Note that this already checks if the client is ingame or connected + * so you don't have to do that yourself. + * This function is optimized to make as less native calls as possible :) + * + * @param Client Client Index. + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return True if the client if the client matches, false otherwise. + */ +stock bool Client_MatchesFilter(int client, int flags) +{ + bool isIngame = false; + + if (flags >= CLIENTFILTER_INGAME) { + isIngame = IsClientInGame(client); + + if (isIngame) { + if (flags & CLIENTFILTER_NOTINGAME) { + return false; + } + } + else { + return false; + } + } + else if (!IsClientConnected(client)) { + return false; + } + + if (!flags) { + return true; + } + + if (flags & CLIENTFILTER_INGAMEAUTH) { + flags |= CLIENTFILTER_INGAME | CLIENTFILTER_AUTHORIZED; + } + + if (flags & CLIENTFILTER_BOTS && !IsFakeClient(client)) { + return false; + } + + if (flags & CLIENTFILTER_NOBOTS && IsFakeClient(client)) { + return false; + } + + if (flags & CLIENTFILTER_ADMINS && !Client_IsAdmin(client)) { + return false; + } + + if (flags & CLIENTFILTER_NOADMINS && Client_IsAdmin(client)) { + return false; + } + + if (flags & CLIENTFILTER_AUTHORIZED && !IsClientAuthorized(client)) { + return false; + } + + if (flags & CLIENTFILTER_NOTAUTHORIZED && IsClientAuthorized(client)) { + return false; + } + + if (isIngame) { + + if (flags & CLIENTFILTER_ALIVE && !IsPlayerAlive(client)) { + return false; + } + + if (flags & CLIENTFILTER_DEAD && IsPlayerAlive(client)) { + return false; + } + + if (flags & CLIENTFILTER_SPECTATORS && GetClientTeam(client) != TEAM_SPECTATOR) { + return false; + } + + if (flags & CLIENTFILTER_NOSPECTATORS && GetClientTeam(client) == TEAM_SPECTATOR) { + return false; + } + + if (flags & CLIENTFILTER_OBSERVERS && !IsClientObserver(client)) { + return false; + } + + if (flags & CLIENTFILTER_NOOBSERVERS && IsClientObserver(client)) { + return false; + } + + if (flags & CLIENTFILTER_TEAMONE && GetClientTeam(client) != TEAM_ONE) { + return false; + } + + if (flags & CLIENTFILTER_TEAMTWO && GetClientTeam(client) != TEAM_TWO) { + return false; + } + } + + return true; +} + +/** + * Gets all clients matching the specified flags filter. + * + * @param client Client Array, size should be MaxClients or MAXPLAYERS + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return The number of clients stored in the array + */ +stock int Client_Get(int[] clients, int flags=CLIENTFILTER_ALL) +{ + int x=0; + for (int client = 1; client <= MaxClients; client++) { + + if (!Client_MatchesFilter(client, flags)) { + continue; + } + + clients[x++] = client; + } + + return x; +} + +/** + * Gets a random client matching the specified flags filter. + * + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return Client Index or -1 if no client was found + */ +stock int Client_GetRandom(int flags=CLIENTFILTER_ALL) +{ + int[] clients = new int[MaxClients]; + int num = Client_Get(clients, flags); + + if (num == 0) { + return -1; + } + else if (num == 1) { + return clients[0]; + } + + int random = Math_GetRandomInt(0, num-1); + + return clients[random]; +} + +/** + * Gets a client matching certain flags starting at start. + * + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @param start Start Index. + * @return Client Index or -1 if no client was found + */ +stock int Client_GetNext(int flags, int start=1) +{ + for (int client=start; client <= MaxClients; client++) { + + if (Client_MatchesFilter(client, flags)) { + return client; + } + } + + return -1; +} + +/** + * Retrieves the time duration a client played on the current map. + * + * @param client Client Index. + * @return Time in seconds as Float + */ +stock float Client_GetMapTime(int client) +{ + float fClientTime = GetClientTime(client); + float fGameTime = GetGameTime(); + + return (fClientTime < fGameTime) ? fClientTime : fGameTime; +} + +/** + * Gets client money value (for games like Counter-Strike:Source). + * + * @param client Client Index. + * @return Money value from the client. + */ +stock int Client_GetMoney(int client) +{ + return GetEntProp(client, Prop_Send, "m_iAccount"); +} + +/** + * Sets client money value (for games like Counter-Strike:Source). + * + * @param client Client Index. + * @param value Money value to set. + */ +stock void Client_SetMoney(int client, int value) +{ + SetEntProp(client, Prop_Send, "m_iAccount", value); +} + +/** + * Gets a client's observers. + * + * @param client Client Index. + * @param observers Array with size of MaxClients or MAXPLAYERS. + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return Number of observers found. + */ +stock int Client_GetObservers(int client, int[] observers, int flags=CLIENTFILTER_ALL) +{ + int count = 0; + + LOOP_CLIENTS(player, CLIENTFILTER_OBSERVERS | flags) { + + if (Client_GetObserverTarget(player) == client) { + observers[count++] = player; + } + } + + return count; +} + +static float getPlayersInRadius_distances[MAXPLAYERS+1]; + +/** + * Gets all players near a player in a certain radius and + * orders the players by distance (optional). + * + * @param client Client Index. + * @param clients Array with size of MaxClients or MAXPLAYERS. + * @param radius radius Float (max distance) + * @param orderByDistance Set to true to order the clients by distance, false otherwise. + * @return Number of clients found. + */ +stock int Client_GetPlayersInRadius(int client, int[] clients, float radius, bool orderByDistance=true) +{ + float origin_client[3], distance; + int count=0; + + Entity_GetAbsOrigin(client, origin_client); + + LOOP_CLIENTS(player, CLIENTFILTER_INGAME) { + + if (player == client) { + continue; + } + + distance = Entity_GetDistanceOrigin(player, origin_client); + + if (distance <= radius) { + clients[count++] = player; + + if (orderByDistance) { + getPlayersInRadius_distances[player] = distance; + } + } + } + + if (orderByDistance) { + SortCustom1D(clients, count, __smlib_GetPlayersInRadius_Sort); + } + + return count; +} + +public int __smlib_GetPlayersInRadius_Sort(int player1, int player2, const int[] clients, Handle hndl) +{ + return FloatCompare(getPlayersInRadius_distances[player1], getPlayersInRadius_distances[player2]); +} + +/** + * Gets the next player observing client starting at start. + * + * @param client Client Index (Observer Target) + * @param start Start Index. + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return Client Index or -1 if no client was found + */ +stock int Client_GetNextObserver(int client, int start=1, int flags=CLIENTFILTER_ALL) +{ + for (int player=start; player <= MaxClients; player++) { + + if (Client_MatchesFilter(player, CLIENTFILTER_OBSERVERS | flags)) { + + if (Client_GetObserverTarget(player) == client) { + return player; + } + } + } + + return -1; +} + +/** + * Searchs and returns the game's player_manager entity. + * This should be called on every map start. + * + * @return player_manager entity or INVALID_ENT_REFERENCE if not found. + */ +stock int Client_GetPlayerManager() +{ + static int player_manager = INVALID_ENT_REFERENCE; + + if (player_manager != INVALID_ENT_REFERENCE) { + + if (Entity_IsValid(player_manager)) { + return player_manager; + } + else { + player_manager = INVALID_ENT_REFERENCE; + } + } + + int maxEntities = GetMaxEntities(); + + for (int entity=MaxClients+1; entity < maxEntities; entity++) { + + if (!Entity_IsValid(entity)) { + continue; + } + + if (Entity_ClassNameMatches(entity, "player_manager", true)) { + player_manager = EntIndexToEntRef(entity); + + return player_manager; + } + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Sets the client's ping as displayed in the scoreboards. + * Should be called OnGameFrame. + * + * @param client Client Index + * @param start New ping value. + * @return True on sucess, false otherwise. + */ +stock int Client_SetPing(int client, int value) +{ + int player_manager = Client_GetPlayerManager(); + + static int offset = -1; + + if (offset== -1) { + offset = GetEntSendPropOffs(player_manager, "m_iPing", true); + + if (offset == -1) { + return false; + } + } + + SetEntData(player_manager, offset + (client * 4), value, 4, true); + + return true; +} + +static int printToTop_excludeclient = -1; + +/** + * Exclude a client from the next call to a Client_PrintToTop function. + * + * @param client Client Index. + * @noreturn + */ +stock void Client_PrintToTopExclude(int client) +{ + printToTop_excludeclient = client; +} + +/** + * Prints colored text to the top left of the screen + * for one client. Does not work in all games. + * Line Breaks can't be done. + * + * @param client Client Index. + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param text Text to print to. + * @return True on success, false if the key value for the dialog couldn't be created or closed. + */ +stock bool Client_PrintToTopRaw(int client, int r=255, int g=255, int b=255, int a=255, float duration=10.0, const char[] text) +{ + //message line max 50 + //overline: 39*_ + //underline: 44*T + KeyValues keyValue = CreateKeyValues("Stuff", "title", text); + + if (keyValue == INVALID_HANDLE) { + return false; + } + + KvSetColor(keyValue, "color", r, g, b, a); + KvSetNum(keyValue, "level", 1); + KvSetNum(keyValue, "time", RoundToFloor(duration)); + + CreateDialog(client, keyValue, DialogType_Msg); + delete keyValue; + + return true; +} + +/** + * Prints colored text to the top left of the screen + * for one client. Does not work in all games. + * Line Breaks can't be done. + * + * @param client Client Index. + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return True on success, false if the key value for the dialog couldn't be created or closed. + */ +stock bool Client_PrintToTop(int client, int r=255, int g=255, int b=255, int a=255, float duration=10.0, const char[] format, any ...) +{ + char buffer[150]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 8); + + return Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); +} + +/** + * Prints colored text to the top left of the screen + * to all clients. Does not work in all games. + * Line Breaks can't be done. + * + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintToTopAll(int r=255, int g=255, int b=255, int a=255, float duration=10.0, const char[] format, any ...) +{ + char buffer[150]; + int + language, + lastLanguage = -1; + + for (int client=1; client <= MaxClients; client++) { + + if (!IsClientInGame(client)) { + continue; + } + + if (client == printToTop_excludeclient) { + printToTop_excludeclient = -1; + continue; + } + + language = GetClientLanguage(client); + + if (language != lastLanguage) { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 7); + + lastLanguage = language; + } + + Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); + } +} + +/** + * Prints colored text to the top left of the screen + * to specified clients. Does not work in all games. + * Line Breaks can't be done. + * + * @param clients Client Array. + * @param numClients Number of clients in the clients array. + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void Client_PrintToTopEx(int[] clients, int numClients, int r=255, int g=255, int b=255, int a=255, float duration=10.0, const char[] format, any ...) +{ + char buffer[150]; + int + client, + language, + lastLanguage = -1; + + for (int i=0; i < numClients; i++) { + + client = clients[i]; + + if (!IsClientInGame(client)) { + continue; + } + + if (client == printToTop_excludeclient) { + printToTop_excludeclient = -1; + continue; + } + + language = GetClientLanguage(client); + + if (language != lastLanguage) { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 9); + + lastLanguage = language; + } + + Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); + } +} + +/** + * Opens the scoreboard for a specific client + * + * @tested csgo + * @param client Client index + */ +stock void Client_ShowScoreboard(int client, int flags=USERMSG_RELIABLE | USERMSG_BLOCKHOOKS) +{ + Handle handle = StartMessageOne("VGUIMenu", client, flags); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && + GetUserMessageType() == UM_Protobuf) { + + PbSetString(handle, "name", "scores"); + PbSetBool(handle, "show", true); + } + else { + BfWriteString(handle, "scores"); + BfWriteByte(handle, 1); // Show + BfWriteByte(handle, 0); // subkeys count + } + + EndMessage(); +} diff --git a/source/sourcemod/scripting/include/smlib/colors.inc b/source/sourcemod/scripting/include/smlib/colors.inc new file mode 100644 index 0000000..9872227 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/colors.inc @@ -0,0 +1,575 @@ +#if defined _smlib_colors_included + #endinput +#endif +#define _smlib_colors_included + +#include +#include +#include + +#define CHATCOLOR_NOSUBJECT -2 +#define SMLIB_COLORS_GAMEDATAFILE "smlib_colors.games" + +enum ChatColorSubjectType +{ + ChatColorSubjectType_none = -3, + + // Subject/Team colors + ChatColorSubjectType_player = -2, + ChatColorSubjectType_undefined = -1, + ChatColorSubjectType_world = 0 + // Anything higher is a specific team +} + +enum struct ChatColorInfo +{ + int ChatColorInfo_Code; + int ChatColorInfo_Alternative; + bool ChatColorInfo_Supported; + ChatColorSubjectType ChatColorInfo_SubjectType; +} + +enum ChatColor +{ + ChatColor_Normal, + ChatColor_Orange, + ChatColor_Red, + ChatColor_RedBlue, + ChatColor_Blue, + ChatColor_BlueRed, + ChatColor_Team, + ChatColor_Lightgreen, + ChatColor_Gray, + ChatColor_Green, + ChatColor_Olivegreen, + ChatColor_Black, + ChatColor_MAXCOLORS +} + +static char chatColorTags[][] = { + "N", // Normal + "O", // Orange + "R", // Red + "RB", // Red, Blue + "B", // Blue + "BR", // Blue, Red + "T", // Team + "L", // Light green + "GRA", // Gray + "G", // Green + "OG", // Olive green + "BLA" // Black +}; + +static char chatColorNames[][] = { + "normal", // Normal + "orange", // Orange + "red", // Red + "redblue", // Red, Blue + "blue", // Blue + "bluered", // Blue, Red + "team", // Team + "lightgreen", // Light green + "gray", // Gray + "green", // Green + "olivegreen", // Olive green + "black" // Black +}; + +static ChatColorInfo chatColorInfo[ChatColor_MAXCOLORS]; + +static bool checkTeamPlay = false; +static ConVar mp_teamplay = null; +static bool isSayText2_supported = true; +static int chatSubject = CHATCOLOR_NOSUBJECT; + +/** + * Sets the subject (a client) for the chat color parser. + * Call this before Color_ParseChatText() or Client_PrintToChat(). + * + * @param client Client Index/Subject + */ +stock void Color_ChatSetSubject(int client) +{ + chatSubject = client; +} + +/** + * Gets the subject used for the chat color parser. + * + * @return Client Index/Subject, or CHATCOLOR_NOSUBJECT if none + */ +stock int Color_ChatGetSubject() +{ + return chatSubject; +} + +/** + * Clears the subject used for the chat color parser. + * Call this after Color_ParseChatText(). + */ +stock void Color_ChatClearSubject() +{ + chatSubject = CHATCOLOR_NOSUBJECT; +} + +/** + * Parses a chat string and converts all color tags to color codes. + * This is a very powerful function that works recursively over the color information + * table. The support colors are hardcoded, but can be overriden for each game by + * creating the file gamedata/smlib_colors.games.txt. + * + * @param str Chat String + * @param subject Output Buffer + * @param size Output Buffer size + * @return Returns a value for the subject + */ +stock int Color_ParseChatText(const char[] str, char[] buffer, int size) +{ + bool inBracket = false; + int x, x_buf, x_tag; + int subject = CHATCOLOR_NOSUBJECT; + + char sTag[10] = ""; // This should be able to hold "\x08RRGGBBAA"\0 + char colorCode[10] = ""; // This should be able to hold "\x08RRGGBBAA"\0 + char currentColor[10] = "\x01"; // Initialize with normal color + + size--; + + // Every chat message has to start with a + // color code, otherwise it will ignore all colors. + buffer[x_buf++] = '\x01'; + + while (str[x] != '\0') { + + if (size == x_buf) { + break; + } + + char character = str[x++]; + + if (inBracket) { + // We allow up to 9 characters in the tag (#RRGGBBAA) + if (character == '}' || x_tag > 9) { + inBracket = false; + sTag[x_tag] = '\0'; + x_tag = 0; + + if (character == '}') { + Color_TagToCode(sTag, subject, colorCode); + + if (colorCode[0] == '\0') { + // We got an unknown tag, ignore this + // and forward it to the buffer. + + // Terminate buffer with \0 so Format can handle it. + buffer[x_buf] = '\0'; + x_buf = Format(buffer, size, "%s{%s}", buffer, sTag); + + // We 'r done here + continue; + } + else if (!StrEqual(colorCode, currentColor)) { + // If we are already using this color, + // we don't need to set it again. + + // Write the color code to our buffer. + // x_buf will be increased by the number of cells written. + x_buf += strcopy(buffer[x_buf], size - x_buf, colorCode); + + // Remember the current color. + strcopy(currentColor, sizeof(currentColor), colorCode); + } + } + else { + // If the tag character limit exceeds 9, + // we have to do something. + + // Terminate buffer with \0 so Format can handle it. + buffer[x_buf] = '\0'; + x_buf = Format(buffer, size, "%s{%s%c", buffer, sTag, character); + } + } + else if (character == '{' && !x_tag) { + buffer[x_buf++] = '{'; + inBracket = false; + } + else { + sTag[x_tag++] = character; + } + } + else if (character == '{') { + inBracket = true; + } + else { + buffer[x_buf++] = character; + } + } + + // Write remaining text to the buffer, + // if we have been inside brackets. + if (inBracket) { + buffer[x_buf] = '\0'; + x_buf = Format(buffer, size, "%s{%s", buffer, sTag); + } + + buffer[x_buf] = '\0'; + + return subject; +} + +/** + * Converts a chat color tag to its code character. + * + * @param tag Color Tag String. + * @param subject Subject variable to pass + * @param result The result as character sequence (string). This will be \0 if the tag is unkown. + */ +stock void Color_TagToCode(const char[] tag, int &subject=-1, char result[10]) +{ + // Check if the tag starts with a '#'. + // We will handle it has RGB(A)-color code then. + if (tag[0] == '#') { + int length_tag = strlen(tag); + switch (length_tag - 1) { + // #RGB -> \07RRGGBB + case 3: { + FormatEx( + result, sizeof(result), "\x07%c%c%c%c%c%c", + tag[1], tag[1], tag[2], tag[2], tag[3], tag[3] + ); + } + // #RGBA -> \08RRGGBBAA + case 4: { + FormatEx( + result, sizeof(result), "\x08%c%c%c%c%c%c%c%c", + tag[1], tag[1], tag[2], tag[2], tag[3], tag[3], tag[4], tag[4] + ); + } + // #RRGGBB -> \07RRGGBB + case 6: { + FormatEx(result, sizeof(result), "\x07%s", tag[1]); + } + // #RRGGBBAA -> \08RRGGBBAA + case 8: { + FormatEx(result, sizeof(result), "\x08%s", tag[1]); + } + default: { + result[0] = '\0'; + } + } + + return; + } + else { + // Try to handle this string as color name + int n = Array_FindString(chatColorTags, sizeof(chatColorTags), tag); + + // Check if this tag is invalid + if (n == -1) { + result[0] = '\0'; + return; + } + + // Check if the color is actually supported 'n stuff. + Color_GetChatColorInfo(n, subject); + + result[0] = chatColorInfo[n].ChatColorInfo_Code; + result[1] = '\0'; + } + + return; +} + +/** + * Strips all color control characters in a string. + * The Output buffer can be the same as the input buffer. + * Original code by Psychonic, thanks. + * + * @param input Input String. + * @param output Output String. + * @param size Max Size of the Output string + */ +stock void Color_StripFromChatText(const char[] input, char[] output, int size) +{ + int x = 0; + for (int i=0; input[i] != '\0'; i++) { + + if (x+1 == size) { + break; + } + + char character = input[i]; + + if (character > 0x08) { + output[x++] = character; + } + } + + output[x] = '\0'; +} + +/** + * Checks the gamename and sets default values. + * For example if some colors are supported, or + * if a game uses another color code for a specific color. + * All those hardcoded default values can be overriden in + * smlib's color gamedata file. + */ +static stock void Color_ChatInitialize() +{ + static bool initialized = false; + + if (initialized) { + return; + } + + initialized = true; + + // Normal + chatColorInfo[ChatColor_Normal].ChatColorInfo_Code = '\x01'; + chatColorInfo[ChatColor_Normal].ChatColorInfo_Alternative = -1; /* None */ + chatColorInfo[ChatColor_Normal].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Normal].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + + // Orange + chatColorInfo[ChatColor_Orange].ChatColorInfo_Code = '\x01'; + chatColorInfo[ChatColor_Orange].ChatColorInfo_Alternative = 0; /* None */ + chatColorInfo[ChatColor_Orange].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Orange].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + + // Red + chatColorInfo[ChatColor_Red].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_Red].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Red].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Red].ChatColorInfo_SubjectType = view_as(2); + + // Red, Blue + chatColorInfo[ChatColor_RedBlue].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_RedBlue].ChatColorInfo_Alternative = 4; /* Blue */ + chatColorInfo[ChatColor_RedBlue].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_RedBlue].ChatColorInfo_SubjectType = view_as(2); + + // Blue + chatColorInfo[ChatColor_Blue].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_Blue].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Blue].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Blue].ChatColorInfo_SubjectType = view_as(3); + + // Blue, Red + chatColorInfo[ChatColor_BlueRed].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_BlueRed].ChatColorInfo_Alternative = 2; /* Red */ + chatColorInfo[ChatColor_BlueRed].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_BlueRed].ChatColorInfo_SubjectType = view_as(3); + + // Team + chatColorInfo[ChatColor_Team].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_Team].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Team].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Team].ChatColorInfo_SubjectType = ChatColorSubjectType_player; + + // Light green + chatColorInfo[ChatColor_Lightgreen].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_Lightgreen].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Lightgreen].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Lightgreen].ChatColorInfo_SubjectType = ChatColorSubjectType_world; + + // Gray + chatColorInfo[ChatColor_Gray].ChatColorInfo_Code = '\x03'; + chatColorInfo[ChatColor_Gray].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Gray].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Gray].ChatColorInfo_SubjectType = ChatColorSubjectType_undefined; + + // Green + chatColorInfo[ChatColor_Green].ChatColorInfo_Code = '\x04'; + chatColorInfo[ChatColor_Green].ChatColorInfo_Alternative = 0; /* Normal*/ + chatColorInfo[ChatColor_Green].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Green].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + + // Olive green + chatColorInfo[ChatColor_Olivegreen].ChatColorInfo_Code = '\x05'; + chatColorInfo[ChatColor_Olivegreen].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Olivegreen].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Olivegreen].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + + // Black + chatColorInfo[ChatColor_Black].ChatColorInfo_Code = '\x06'; + chatColorInfo[ChatColor_Black].ChatColorInfo_Alternative = 9; /* Green */ + chatColorInfo[ChatColor_Black].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Black].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + + char gameFolderName[PLATFORM_MAX_PATH]; + GetGameFolderName(gameFolderName, sizeof(gameFolderName)); + + chatColorInfo[ChatColor_Black].ChatColorInfo_Supported = false; + + if (strncmp(gameFolderName, "left4dead", 9, false) != 0 && + !StrEqual(gameFolderName, "cstrike", false) && + !StrEqual(gameFolderName, "tf", false)) + { + chatColorInfo[ChatColor_Lightgreen].ChatColorInfo_Supported = false; + chatColorInfo[ChatColor_Gray].ChatColorInfo_Supported = false; + } + + if (StrEqual(gameFolderName, "tf", false)) { + chatColorInfo[ChatColor_Black].ChatColorInfo_Supported = true; + + chatColorInfo[ChatColor_Gray].ChatColorInfo_Code = '\x01'; + chatColorInfo[ChatColor_Gray].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + } + else if (strncmp(gameFolderName, "left4dead", 9, false) == 0) { + chatColorInfo[ChatColor_Red].ChatColorInfo_SubjectType = view_as(3); + chatColorInfo[ChatColor_RedBlue].ChatColorInfo_SubjectType = view_as(3); + chatColorInfo[ChatColor_Blue].ChatColorInfo_SubjectType = view_as(2); + chatColorInfo[ChatColor_BlueRed].ChatColorInfo_SubjectType = view_as(2); + + chatColorInfo[ChatColor_Orange].ChatColorInfo_Code = '\x04'; + chatColorInfo[ChatColor_Green].ChatColorInfo_Code = '\x05'; + } + else if (StrEqual(gameFolderName, "hl2mp", false)) { + chatColorInfo[ChatColor_Red].ChatColorInfo_SubjectType = view_as(3); + chatColorInfo[ChatColor_RedBlue].ChatColorInfo_SubjectType = view_as(3); + chatColorInfo[ChatColor_Blue].ChatColorInfo_SubjectType = view_as(2); + chatColorInfo[ChatColor_BlueRed].ChatColorInfo_SubjectType = view_as(2); + chatColorInfo[ChatColor_Black].ChatColorInfo_Supported = true; + + checkTeamPlay = true; + } + else if (StrEqual(gameFolderName, "dod", false)) { + chatColorInfo[ChatColor_Gray].ChatColorInfo_Code = '\x01'; + chatColorInfo[ChatColor_Gray].ChatColorInfo_SubjectType = ChatColorSubjectType_none; + + chatColorInfo[ChatColor_Black].ChatColorInfo_Supported = true; + chatColorInfo[ChatColor_Orange].ChatColorInfo_Supported = false; + } + + if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) { + isSayText2_supported = false; + } + + char path_gamedata[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, path_gamedata, sizeof(path_gamedata), "gamedata/%s.txt", SMLIB_COLORS_GAMEDATAFILE); + + if (FileExists(path_gamedata)) { + Handle gamedata = INVALID_HANDLE; + + if ((gamedata = LoadGameConfigFile(SMLIB_COLORS_GAMEDATAFILE)) != INVALID_HANDLE) { + + char keyName[32], buffer[6]; + + for (int i=0; i < sizeof(chatColorNames); i++) { + + Format(keyName, sizeof(keyName), "%s_code", chatColorNames[i]); + if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) { + chatColorInfo[i].ChatColorInfo_Code = StringToInt(buffer); + } + + Format(keyName, sizeof(keyName), "%s_alternative", chatColorNames[i]); + if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) { + chatColorInfo[i].ChatColorInfo_Alternative = buffer[0]; + } + + Format(keyName, sizeof(keyName), "%s_supported", chatColorNames[i]); + if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) { + chatColorInfo[i].ChatColorInfo_Supported = StrEqual(buffer, "true"); + } + + Format(keyName, sizeof(keyName), "%s_subjecttype", chatColorNames[i]); + if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) { + chatColorInfo[i].ChatColorInfo_SubjectType = view_as(StringToInt(buffer)); + } + } + + if (GameConfGetKeyValue(gamedata, "checkteamplay", buffer, sizeof(buffer))) { + checkTeamPlay = StrEqual(buffer, "true"); + } + + CloseHandle(gamedata); + } + } + + mp_teamplay = FindConVar("mp_teamplay"); +} + +/** + * Checks if the passed color index is actually supported + * for the current game. If not, the index will be overwritten + * The color resolving works recursively until a valid color is found. + * + * @param index + * @param subject A client index or CHATCOLOR_NOSUBJECT + */ +static stock int Color_GetChatColorInfo(int &index, int &subject=CHATCOLOR_NOSUBJECT) +{ + Color_ChatInitialize(); + + if (index == -1) { + index = 0; + } + + while (!chatColorInfo[index].ChatColorInfo_Supported) { + + int alternative = chatColorInfo[index].ChatColorInfo_Alternative; + + if (alternative == -1) { + index = 0; + break; + } + + index = alternative; + } + + if (index == -1) { + index = 0; + } + + int newSubject = CHATCOLOR_NOSUBJECT; + ChatColorSubjectType type = chatColorInfo[index].ChatColorInfo_SubjectType; + + switch (type) { + case ChatColorSubjectType_none: { + } + case ChatColorSubjectType_player: { + newSubject = chatSubject; + } + case ChatColorSubjectType_undefined: { + newSubject = -1; + } + case ChatColorSubjectType_world: { + newSubject = 0; + } + default: { + + if (!checkTeamPlay || mp_teamplay.BoolValue) { + + if (subject > 0 && subject <= MaxClients) { + + if (GetClientTeam(subject) == view_as(type)) { + newSubject = subject; + } + } + else if (subject == CHATCOLOR_NOSUBJECT) { + int client = Team_GetAnyClient(view_as(type)); + + if (client != -1) { + newSubject = client; + } + } + } + } + } + + if (type > ChatColorSubjectType_none && + ((subject != CHATCOLOR_NOSUBJECT && subject != newSubject) || newSubject == CHATCOLOR_NOSUBJECT || !isSayText2_supported)) + { + index = chatColorInfo[index].ChatColorInfo_Alternative; + newSubject = Color_GetChatColorInfo(index, subject); + } + + // Only set the subject if there is no subject set already. + if (subject == CHATCOLOR_NOSUBJECT) { + subject = newSubject; + } + + return newSubject; +} diff --git a/source/sourcemod/scripting/include/smlib/concommands.inc b/source/sourcemod/scripting/include/smlib/concommands.inc new file mode 100644 index 0000000..2bd708f --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/concommands.inc @@ -0,0 +1,45 @@ +#if defined _smlib_concommands_included + #endinput +#endif +#define _smlib_concommands_included + +#include +#include + +/** + * Checks if a ConCommand has one or more flags set. + * + * @param command ConCommand name. + * @param flags Flags to check. + * @return True if flags are set, false otherwise. + */ +stock bool ConCommand_HasFlags(const char[] command, int flags) +{ + return GetCommandFlags(command) & flags > 0; +} + +/** + * Adds one or more flags to a ConCommand. + * + * @param command ConCommand name. + * @param flags Flags to add. + */ +stock void ConCommand_AddFlags(const char[] command, int flags) +{ + int newFlags = GetCommandFlags(command); + newFlags |= flags; + SetCommandFlags(command, newFlags); +} + +/** + * Removes one ore more flags from a ConCommand. + * + * @param command ConCommand name. + * @param flags Flags to remove + */ +stock void ConCommand_RemoveFlags(const char[] command, int flags) +{ + int newFlags = GetCommandFlags(command); + newFlags &= ~flags; + SetCommandFlags(command, newFlags); +} diff --git a/source/sourcemod/scripting/include/smlib/convars.inc b/source/sourcemod/scripting/include/smlib/convars.inc new file mode 100644 index 0000000..b7f4b23 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/convars.inc @@ -0,0 +1,71 @@ +#if defined _smlib_convars_included + #endinput +#endif +#define _smlib_convars_included + +#include + +/** + * Checks if a ConVar has one or more flags set. + * + * @param convar ConVar Handle. + * @param flags Flags to check. + * @return True if flags are set, false otherwise. + */ +stock bool Convar_HasFlags(ConVar convar, int flags) +{ + return convar.Flags & flags > 0; +} + +/** + * Adds one or more flags to a ConVar. + * + * @param convar ConVar Handle. + * @param flags Flags to add. + */ +stock void Convar_AddFlags(ConVar convar, int flags) +{ + int newFlags = convar.Flags; + newFlags |= flags; + convar.Flags = newFlags; +} + +/** + * Removes one ore more flags from a ConVar. + * + * @param convar ConVar Handle. + * @param flags Flags to remove + * @noreturn + */ +stock void Convar_RemoveFlags(ConVar convar, int flags) +{ + int newFlags = convar.Flags; + newFlags &= ~flags; + convar.Flags = newFlags; +} + +/** + * Checks if a String is a valid ConVar or + * Console Command name. + * + * @param name String Name. + * @return True if the name specified is a valid ConVar or console command name, false otherwise. + */ +stock bool Convar_IsValidName(const char[] name) +{ + if (name[0] == '\0') { + return false; + } + + int n=0; + while (name[n] != '\0') { + + if (!IsValidConVarChar(name[n])) { + return false; + } + + n++; + } + + return true; +} diff --git a/source/sourcemod/scripting/include/smlib/crypt.inc b/source/sourcemod/scripting/include/smlib/crypt.inc new file mode 100644 index 0000000..21319aa --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/crypt.inc @@ -0,0 +1,625 @@ +#if defined _smlib_crypt_included + #endinput +#endif +#define _smlib_crypt_included + +#include + +/********************************************************************************** + * + * Base64 Encoding/Decoding Functions + * All Credits to to SirLamer & ScriptCoderPro + * Taken from http://forums.alliedmods.net/showthread.php?t=101764 + * + ***********************************************************************************/ + +// The Base64 encoding table +static const char base64_sTable[] = + // 0000000000111111111122222222223333333333444444444455555555556666 + // 0123456789012345678901234567890123456789012345678901234567890123 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +// The Base64 decoding table +static const int base64_decodeTable[] = { +// 0 1 2 3 4 5 6 7 8 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 - 19 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 - 29 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30 - 39 + 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, // 40 - 49 + 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, // 50 - 59 + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, // 60 - 69 + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 70 - 79 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 80 - 89 + 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, // 90 - 99 + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 100 - 109 + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 110 - 119 + 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, // 120 - 129 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 130 - 139 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140 - 149 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150 - 159 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 - 169 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170 - 179 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180 - 189 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190 - 199 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200 - 209 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210 - 219 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220 - 229 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230 - 239 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240 - 249 + 0, 0, 0, 0, 0, 0 // 250 - 256 +}; + +/* + * For some reason the standard demands a string in 24-bit (3 character) intervals. + * This fill character is used to identify unused bytes at the end of the string. + */ +static const char base64_cFillChar = '='; + +// The conversion characters between the standard and URL-compliance Base64 protocols +static const char base64_mime_chars[] = "+/="; +static const char base64_url_chars[] = "-_."; + +/* + * Encodes a string or binary data into Base64 + * + * @param sString The input string or binary data to be encoded. + * @param sResult The storage buffer for the Base64-encoded result. + * @param len The maximum length of the storage buffer, in characters/bytes. + * @param sourcelen (optional): The number of characters or length in bytes to be read from the input source. + * This is not needed for a text string, but is important for binary data since there is no end-of-line character. + * @return The length of the written Base64 string, in bytes. + */ +stock int Crypt_Base64Encode(const char[] sString, char[] sResult, int len, int sourcelen=0) +{ + int nLength; // The string length to be read from the input + int resPos; // The string position in the result buffer + + // If the read length was specified, use it; otherwise, pull the string length from the input. + if (sourcelen > 0) { + nLength = sourcelen; + } + else { + nLength = strlen(sString); + } + + // Loop through and generate the Base64 encoded string + // NOTE: This performs the standard encoding process. Do not manipulate the logic within this loop. + for (int nPos = 0; nPos < nLength; nPos++) { + int cCode; + + cCode = (sString[nPos] >> 2) & 0x3f; + + resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]); + + cCode = (sString[nPos] << 4) & 0x3f; + if (++nPos < nLength) { + cCode |= (sString[nPos] >> 4) & 0x0f; + } + resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]); + + if ( nPos < nLength ) { + cCode = (sString[nPos] << 2) & 0x3f; + if (++nPos < nLength) { + cCode |= (sString[nPos] >> 6) & 0x03; + } + + resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]); + } + else { + nPos++; + resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_cFillChar); + } + + if (nPos < nLength) { + cCode = sString[nPos] & 0x3f; + resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]); + } + else { + resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_cFillChar); + } + } + + return resPos; +} + + +/* + * Decodes a Base64 string. + * + * @param sString The input string in compliant Base64 format to be decoded. + * @param sResult The storage buffer for the decoded text strihg or binary data. + * @param len The maximum length of the storage buffer, in characters/bytes. + * @return The length of the decoded data, in bytes. + */ +stock int Crypt_Base64Decode(const char[] sString, char[] sResult, int len) +{ + int nLength = strlen(sString); // The string length to be read from the input + int resPos; // The string position in the result buffer + + // Loop through and generate the Base64 encoded string + // NOTE: This performs the standard encoding process. Do not manipulate the logic within this loop. + for (int nPos = 0; nPos < nLength; nPos++) { + + int c, c1; + + c = base64_decodeTable[sString[nPos++]]; + c1 = base64_decodeTable[sString[nPos]]; + + c = (c << 2) | ((c1 >> 4) & 0x3); + + resPos += FormatEx(sResult[resPos], len - resPos, "%c", c); + + if (++nPos < nLength) { + + c = sString[nPos]; + + if (c == base64_cFillChar) + break; + + c = base64_decodeTable[sString[nPos]]; + c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); + + resPos += FormatEx(sResult[resPos], len - resPos, "%c", c1); + } + + if (++nPos < nLength) { + + c1 = sString[nPos]; + + if (c1 == base64_cFillChar) + break; + + c1 = base64_decodeTable[sString[nPos]]; + c = ((c << 6) & 0xc0) | c1; + + resPos += FormatEx(sResult[resPos], len - resPos, "%c", c); + } + } + + return resPos; +} + + +/* + * Converts a standards-compliant Base64 string to the commonly accepted URL-compliant alternative. + * Note: The result will be the same length as the input string as long as the output buffer is large enough. + * + * @param sString The standards-compliant Base64 input string to converted. + * @param sResult The storage buffer for the URL-compliant result. + * @param len The maximum length of the storage buffer in characters/bytes. + * @return Number of cells written. + */ +stock int Crypt_Base64MimeToUrl(const char[] sString, char[] sResult, int len) +{ + int chars_len = sizeof(base64_mime_chars); // Length of the two standards vs. URL character lists + int nLength; // The string length to be read from the input + int temp_char; // Buffer character + + nLength = strlen(sString); + + char[] sTemp = new char[nLength+1]; // Buffer string + + // Loop through string + for (int i = 0; i < nLength; i++) { + temp_char = sString[i]; + + for (int j = 0; j < chars_len; j++) { + + if(temp_char == base64_mime_chars[j]) { + temp_char = base64_url_chars[j]; + break; + } + } + + sTemp[i] = temp_char; + } + + sTemp[nLength] = '\0'; + + return strcopy(sResult, len, sTemp); +} + +/* + * Base64UrlToMime(String:sResult[], len, const String:sString[], sourcelen) + * Converts a URL-compliant Base64 string to the standards-compliant version. + * Note: The result will be the same length as the input string as long as the output buffer is large enough. + * + * @param sString The URL-compliant Base64 input string to converted. + * @param sResult The storage buffer for the standards-compliant result. + * @param len The maximum length of the storage buffer in characters/bytes. + * @return Number of cells written. + */ +stock int Crypt_Base64UrlToMime(const char[] sString, char[] sResult, int len) +{ + int chars_len = sizeof(base64_mime_chars); // Length of the two standards vs. URL character lists + int nLength; // The string length to be read from the input + int temp_char; // Buffer character + + nLength = strlen(sString); + + char[] sTemp = new char[nLength+1]; // Buffer string + + // Loop through string + for (int i = 0; i < nLength; i++) { + temp_char = sString[i]; + for (int j = 0; j < chars_len; j++) { + if (temp_char == base64_url_chars[j]) { + temp_char = base64_mime_chars[j]; + break; + } + } + + sTemp[i] = temp_char; + } + + sTemp[nLength] = '\0'; + + return strcopy(sResult, len, sTemp); +} + +/********************************************************************************** + * + * MD5 Encoding Functions + * All Credits go to sslice + * RSA Data Security, Inc. MD5 Message Digest Algorithm + * Taken from http://forums.alliedmods.net/showthread.php?t=67683 + * + ***********************************************************************************/ + +/* + * Calculate the md5 hash of a string. + * + * @param str Input String + * @param output Output String Buffer + * @param maxlen Size of the Output String Buffer + */ +stock void Crypt_MD5(const char[] str, char[] output, int maxlen) +{ + int x[2]; + int buf[4]; + int input[64]; + int i, ii; + + int len = strlen(str); + + // MD5Init + x[0] = x[1] = 0; + buf[0] = 0x67452301; + buf[1] = 0xefcdab89; + buf[2] = 0x98badcfe; + buf[3] = 0x10325476; + + // MD5Update + int update[16]; + + update[14] = x[0]; + update[15] = x[1]; + + int mdi = (x[0] >>> 3) & 0x3F; + + if ((x[0] + (len << 3)) < x[0]) { + x[1] += 1; + } + + x[0] += len << 3; + x[1] += len >>> 29; + + int c = 0; + while (len--) { + input[mdi] = str[c]; + mdi += 1; + c += 1; + + if (mdi == 0x40) { + + for (i = 0, ii = 0; i < 16; ++i, ii += 4) + { + update[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; + } + + // Transform + MD5Transform(buf, update); + + mdi = 0; + } + } + + // MD5Final + int padding[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + int inx[16]; + inx[14] = x[0]; + inx[15] = x[1]; + + mdi = (x[0] >>> 3) & 0x3F; + + len = (mdi < 56) ? (56 - mdi) : (120 - mdi); + update[14] = x[0]; + update[15] = x[1]; + + mdi = (x[0] >>> 3) & 0x3F; + + if ((x[0] + (len << 3)) < x[0]) { + x[1] += 1; + } + + x[0] += len << 3; + x[1] += len >>> 29; + + c = 0; + while (len--) { + input[mdi] = padding[c]; + mdi += 1; + c += 1; + + if (mdi == 0x40) { + + for (i = 0, ii = 0; i < 16; ++i, ii += 4) { + update[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; + } + + // Transform + MD5Transform(buf, update); + + mdi = 0; + } + } + + for (i = 0, ii = 0; i < 14; ++i, ii += 4) { + inx[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; + } + + MD5Transform(buf, inx); + + int digest[16]; + for (i = 0, ii = 0; i < 4; ++i, ii += 4) { + digest[ii] = (buf[i]) & 0xFF; + digest[ii + 1] = (buf[i] >>> 8) & 0xFF; + digest[ii + 2] = (buf[i] >>> 16) & 0xFF; + digest[ii + 3] = (buf[i] >>> 24) & 0xFF; + } + + FormatEx(output, maxlen, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]); +} + +static stock void MD5Transform_FF(int &a, int &b, int &c, int &d, int x, int s, int ac) +{ + a += (((b) & (c)) | ((~b) & (d))) + x + ac; + a = (((a) << (s)) | ((a) >>> (32-(s)))); + a += b; +} + +static stock void MD5Transform_GG(int &a, int &b, int &c, int &d, int x, int s, int ac) +{ + a += (((b) & (d)) | ((c) & (~d))) + x + ac; + a = (((a) << (s)) | ((a) >>> (32-(s)))); + a += b; +} + +static stock void MD5Transform_HH(int &a, int &b, int &c, int &d, int x, int s, int ac) + { + a += ((b) ^ (c) ^ (d)) + x + ac; + a = (((a) << (s)) | ((a) >>> (32-(s)))); + a += b; +} + +static stock void MD5Transform_II(int &a, int &b, int &c, int &d, int x, int s, int ac) +{ + a += ((c) ^ ((b) | (~d))) + x + ac; + a = (((a) << (s)) | ((a) >>> (32-(s)))); + a += b; +} + +static stock void MD5Transform(int[] buf, int[] input){ + int a = buf[0]; + int b = buf[1]; + int c = buf[2]; + int d = buf[3]; + + MD5Transform_FF(a, b, c, d, input[0], 7, 0xd76aa478); + MD5Transform_FF(d, a, b, c, input[1], 12, 0xe8c7b756); + MD5Transform_FF(c, d, a, b, input[2], 17, 0x242070db); + MD5Transform_FF(b, c, d, a, input[3], 22, 0xc1bdceee); + MD5Transform_FF(a, b, c, d, input[4], 7, 0xf57c0faf); + MD5Transform_FF(d, a, b, c, input[5], 12, 0x4787c62a); + MD5Transform_FF(c, d, a, b, input[6], 17, 0xa8304613); + MD5Transform_FF(b, c, d, a, input[7], 22, 0xfd469501); + MD5Transform_FF(a, b, c, d, input[8], 7, 0x698098d8); + MD5Transform_FF(d, a, b, c, input[9], 12, 0x8b44f7af); + MD5Transform_FF(c, d, a, b, input[10], 17, 0xffff5bb1); + MD5Transform_FF(b, c, d, a, input[11], 22, 0x895cd7be); + MD5Transform_FF(a, b, c, d, input[12], 7, 0x6b901122); + MD5Transform_FF(d, a, b, c, input[13], 12, 0xfd987193); + MD5Transform_FF(c, d, a, b, input[14], 17, 0xa679438e); + MD5Transform_FF(b, c, d, a, input[15], 22, 0x49b40821); + + MD5Transform_GG(a, b, c, d, input[1], 5, 0xf61e2562); + MD5Transform_GG(d, a, b, c, input[6], 9, 0xc040b340); + MD5Transform_GG(c, d, a, b, input[11], 14, 0x265e5a51); + MD5Transform_GG(b, c, d, a, input[0], 20, 0xe9b6c7aa); + MD5Transform_GG(a, b, c, d, input[5], 5, 0xd62f105d); + MD5Transform_GG(d, a, b, c, input[10], 9, 0x02441453); + MD5Transform_GG(c, d, a, b, input[15], 14, 0xd8a1e681); + MD5Transform_GG(b, c, d, a, input[4], 20, 0xe7d3fbc8); + MD5Transform_GG(a, b, c, d, input[9], 5, 0x21e1cde6); + MD5Transform_GG(d, a, b, c, input[14], 9, 0xc33707d6); + MD5Transform_GG(c, d, a, b, input[3], 14, 0xf4d50d87); + MD5Transform_GG(b, c, d, a, input[8], 20, 0x455a14ed); + MD5Transform_GG(a, b, c, d, input[13], 5, 0xa9e3e905); + MD5Transform_GG(d, a, b, c, input[2], 9, 0xfcefa3f8); + MD5Transform_GG(c, d, a, b, input[7], 14, 0x676f02d9); + MD5Transform_GG(b, c, d, a, input[12], 20, 0x8d2a4c8a); + + MD5Transform_HH(a, b, c, d, input[5], 4, 0xfffa3942); + MD5Transform_HH(d, a, b, c, input[8], 11, 0x8771f681); + MD5Transform_HH(c, d, a, b, input[11], 16, 0x6d9d6122); + MD5Transform_HH(b, c, d, a, input[14], 23, 0xfde5380c); + MD5Transform_HH(a, b, c, d, input[1], 4, 0xa4beea44); + MD5Transform_HH(d, a, b, c, input[4], 11, 0x4bdecfa9); + MD5Transform_HH(c, d, a, b, input[7], 16, 0xf6bb4b60); + MD5Transform_HH(b, c, d, a, input[10], 23, 0xbebfbc70); + MD5Transform_HH(a, b, c, d, input[13], 4, 0x289b7ec6); + MD5Transform_HH(d, a, b, c, input[0], 11, 0xeaa127fa); + MD5Transform_HH(c, d, a, b, input[3], 16, 0xd4ef3085); + MD5Transform_HH(b, c, d, a, input[6], 23, 0x04881d05); + MD5Transform_HH(a, b, c, d, input[9], 4, 0xd9d4d039); + MD5Transform_HH(d, a, b, c, input[12], 11, 0xe6db99e5); + MD5Transform_HH(c, d, a, b, input[15], 16, 0x1fa27cf8); + MD5Transform_HH(b, c, d, a, input[2], 23, 0xc4ac5665); + + MD5Transform_II(a, b, c, d, input[0], 6, 0xf4292244); + MD5Transform_II(d, a, b, c, input[7], 10, 0x432aff97); + MD5Transform_II(c, d, a, b, input[14], 15, 0xab9423a7); + MD5Transform_II(b, c, d, a, input[5], 21, 0xfc93a039); + MD5Transform_II(a, b, c, d, input[12], 6, 0x655b59c3); + MD5Transform_II(d, a, b, c, input[3], 10, 0x8f0ccc92); + MD5Transform_II(c, d, a, b, input[10], 15, 0xffeff47d); + MD5Transform_II(b, c, d, a, input[1], 21, 0x85845dd1); + MD5Transform_II(a, b, c, d, input[8], 6, 0x6fa87e4f); + MD5Transform_II(d, a, b, c, input[15], 10, 0xfe2ce6e0); + MD5Transform_II(c, d, a, b, input[6], 15, 0xa3014314); + MD5Transform_II(b, c, d, a, input[13], 21, 0x4e0811a1); + MD5Transform_II(a, b, c, d, input[4], 6, 0xf7537e82); + MD5Transform_II(d, a, b, c, input[11], 10, 0xbd3af235); + MD5Transform_II(c, d, a, b, input[2], 15, 0x2ad7d2bb); + MD5Transform_II(b, c, d, a, input[9], 21, 0xeb86d391); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/********************************************************************************** + * + * RC4 Encoding Functions + * All Credits go to SirLamer and Raydan + * Taken from http://forums.alliedmods.net/showthread.php?t=101834 + * + ***********************************************************************************/ + +/* + * Encrypts a text string using RC4. + * Note: This function is NOT binary safe. + * Use Crypt_RC4EncodeBinary to encode binary data. + * + * @param input The source data to be encrypted. + * @param pwd The password/key used to encode and decode the data. + * @param output The encoded result. + * @param maxlen The maximum length of the output buffer. + */ +stock void Crypt_RC4Encode(const char[] input, const char[] pwd, char[] output, int maxlen) +{ + int pwd_len,str_len,i,j,a,k; + int key[256]; + int box[256]; + int tmp; + + pwd_len = strlen(pwd); + str_len = strlen(input); + + if (pwd_len > 0 && str_len > 0) { + + for (i=0; i < 256; i++) { + key[i] = pwd[i%pwd_len]; + box[i]=i; + } + + i=0; j=0; + + for (; i < 256; i++) { + j = (j + box[i] + key[i]) % 256; + tmp = box[i]; + box[i] = box[j]; + box[j] = tmp; + } + + i=0; j=0; a=0; + + for (; i < str_len; i++) { + a = (a + 1) % 256; + j = (j + box[a]) % 256; + tmp = box[a]; + box[a] = box[j]; + box[j] = tmp; + k = box[((box[a] + box[j]) % 256)]; + FormatEx(output[2*i], maxlen-2*i, "%02x", input[i] ^ k); + } + } +} + +/* + * Encrypts binary data using RC4. + * + * @param input The source data to be encrypted. + * @param str_len The length of the source data. + * @param pwd The password/key used to encode and decode the data. + * @param output The encoded result. + * @param maxlen The maximum length of the output buffer. + */ +stock int Crypt_RC4EncodeBinary(const char[] input, int str_len, const char[] pwd, char[] output, int maxlen) +{ + int pwd_len,i,j,a,k; + int key[256]; + int box[256]; + int tmp; + + pwd_len = strlen(pwd); + + if (pwd_len > 0 && str_len > 0) { + + for(i=0;i<256;i++) { + key[i] = pwd[i%pwd_len]; + box[i]=i; + } + + i=0; j=0; + + for (; i < 256; i++) { + j = (j + box[i] + key[i]) % 256; + tmp = box[i]; + box[i] = box[j]; + box[j] = tmp; + } + + i=0; j=0; a=0; + + if (str_len+1 > maxlen) { + str_len = maxlen - 1; + } + + for(; i < str_len; i++) { + a = (a + 1) % 256; + j = (j + box[a]) % 256; + tmp = box[a]; + box[a] = box[j]; + box[j] = tmp; + k = box[((box[a] + box[j]) % 256)]; + FormatEx(output[i], maxlen-i, "%c", input[i] ^ k); + } + + /* + * i = number of written bits (remember increment occurs at end of for loop, and THEN it fails the loop condition) + * Since we're working with binary data, the calling function should not depend on the escape + * character, but putting it here prevents crashes in case someone tries to read the data like a string + */ + output[i] = '\0'; + + return i; + } + else { + return -1; + } +} diff --git a/source/sourcemod/scripting/include/smlib/debug.inc b/source/sourcemod/scripting/include/smlib/debug.inc new file mode 100644 index 0000000..6a416ed --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/debug.inc @@ -0,0 +1,28 @@ +#if defined _smlib_debug_included + #endinput +#endif +#define _smlib_debug_included + +#include + +/** + * Prints the values of a static Float-Array to the server console. + * + * @param array Static Float-Array. + * @param size Size of the Array. + */ +stock void Debug_FloatArray(const float[] array, int size=3) +{ + char output[64] = ""; + + for (int i=0; i < size; ++i) { + + if (i > 0 && i < size) { + StrCat(output, sizeof(output), ", "); + } + + Format(output, sizeof(output), "%s%f", output, array[i]); + } + + PrintToServer("[DEBUG] Vector[%d] = { %s }", size, output); +} diff --git a/source/sourcemod/scripting/include/smlib/dynarrays.inc b/source/sourcemod/scripting/include/smlib/dynarrays.inc new file mode 100644 index 0000000..35a8951 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/dynarrays.inc @@ -0,0 +1,24 @@ +#if defined _smlib_dynarray_included + #endinput +#endif +#define _smlib_dynarray_included + +#include + +/** + * Retrieves a cell value from an array. + * This is a wrapper around the Sourcemod Function GetArrayCell, + * but it casts the result as bool + * + * @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. + */ +stock bool DynArray_GetBool(ArrayList array, int index, int block=0, bool asChar=false) +{ + return array.Get(index, block, asChar) != 0; +} diff --git a/source/sourcemod/scripting/include/smlib/edicts.inc b/source/sourcemod/scripting/include/smlib/edicts.inc new file mode 100644 index 0000000..86f4e2a --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/edicts.inc @@ -0,0 +1,127 @@ +#if defined _smlib_edicts_included + #endinput +#endif +#define _smlib_edicts_included + +#include +#include + +/* + * Finds an edict by it's name + * It only finds the first occurence. + * + * @param name Name of the entity you want so search. + * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found. + */ +stock int Edict_FindByName(const char[] name) +{ + int maxEntities = GetMaxEntities(); + for (int edict=0; edict < maxEntities; edict++) { + + if (!IsValidEdict(edict)) { + continue; + } + + if (Entity_NameMatches(edict, name)) { + return edict; + } + } + + return INVALID_ENT_REFERENCE; +} + +/* + * Finds an edict by its HammerID. + * The newer version of Valve's Hammer editor + * sets a unique ID for each entity in a map. + * It only finds the first occurence. + * + * @param hammerId Hammer editor ID + * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found. + */ +stock int Edict_FindByHammerId(int hammerId) +{ + int maxEntities = GetMaxEntities(); + for (int edict=0; edict < maxEntities; edict++) { + + if (!IsValidEdict(edict)) { + continue; + } + + if (Entity_GetHammerId(edict) == hammerId) { + return edict; + } + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Searches for the closest edict in relation to the given origin + * + * @param vecOrigin_center 3 dimensional origin array + * @param clientsOnly True if you only want to search for clients + * @param ignoreEntity Ignore this entity + * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found. + */ +stock int Edict_GetClosest(float vecOrigin_center[3], bool clientsOnly=false, int ignoreEntity=-1) +{ + float vecOrigin_edict[3]; + float smallestDistance = 0.0; + int closestEdict = INVALID_ENT_REFERENCE; + + int maxEntities; + + if (clientsOnly) { + maxEntities = MaxClients; + } + else { + maxEntities = GetMaxEntities(); + } + + for (int edict=1; edict <= maxEntities; edict++) { + + if (!IsValidEdict(edict)) { + continue; + } + + if (ignoreEntity >= 0 && edict == ignoreEntity) { + continue; + } + + if (GetEntSendPropOffs(edict, "m_vecOrigin") == -1) { + continue; + } + + Entity_GetAbsOrigin(edict, vecOrigin_edict); + + float edict_distance = GetVectorDistance(vecOrigin_center, vecOrigin_edict, true); + + if (edict_distance < smallestDistance || smallestDistance == 0.0) { + smallestDistance = edict_distance; + closestEdict = edict; + } + } + + return closestEdict; +} + +/** + * Searches for the closest edict in relation to the given edict. + * + * @param edict Edict index + * @param clientsOnly True if you only want to search for clients + * @return The closest edict or INVALID_ENT_REFERENCE + */ +stock int Edict_GetClosestToEdict(int edict, bool clientsOnly=false) +{ + float vecOrigin[3]; + + if (!HasEntProp(edict, Prop_Send, "m_vecOrigin")) { + return INVALID_ENT_REFERENCE; + } + + Entity_GetAbsOrigin(edict, vecOrigin); + + return Edict_GetClosest(vecOrigin, clientsOnly, edict); +} diff --git a/source/sourcemod/scripting/include/smlib/effects.inc b/source/sourcemod/scripting/include/smlib/effects.inc new file mode 100644 index 0000000..b5e9122 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/effects.inc @@ -0,0 +1,722 @@ +#if defined _smlib_effects_included + #endinput +#endif +#define _smlib_effects_included + +#include +#include +#include +#include +#include +#include +#include +#include + + + +// Entity Dissolve types +enum DissolveType +{ + DISSOLVE_NORMAL = 0, + DISSOLVE_ELECTRICAL, + DISSOLVE_ELECTRICAL_LIGHT, + DISSOLVE_CORE +}; + +/** + * Dissolves a player + * + * @param client Client Index. + * @param dissolveType Dissolve Type, use the DissolveType enum. + * @param magnitude How strongly to push away from the center. + * @return True on success, otherwise false. + */ +stock bool Effect_DissolveEntity(int entity, DissolveType dissolveType=DISSOLVE_NORMAL, int magnitude=1) +{ + int env_entity_dissolver = CreateEntityByName("env_entity_dissolver"); + + if (env_entity_dissolver == -1) { + return false; + } + + Entity_PointAtTarget(env_entity_dissolver, entity); + SetEntProp(env_entity_dissolver, Prop_Send, "m_nDissolveType", dissolveType); + SetEntProp(env_entity_dissolver, Prop_Send, "m_nMagnitude", magnitude); + AcceptEntityInput(env_entity_dissolver, "Dissolve"); + Entity_Kill(env_entity_dissolver); + + return true; +} + +/** + * Dissolves a player's Ragdoll + * + * @param client Client Index. + * @param dissolveType Dissolve Type, use the DissolveType enum. + * @return True on success, otherwise false. + */ +stock bool Effect_DissolvePlayerRagDoll(int client, DissolveType dissolveType=DISSOLVE_NORMAL) +{ + int m_hRagdoll = GetEntPropEnt(client, Prop_Send, "m_hRagdoll"); + + if (m_hRagdoll == -1) { + return false; + } + + return Effect_DissolveEntity(m_hRagdoll, dissolveType); +} + +typedef EffectCallback = function void(int entity, any data); + +/** + * Fades an entity in our out. + * You can specifiy a callback function which will get called + * when the fade is finished. + * Important: The callback will be called if it is passed, + * no matter if the entity is still valid or not. That means you + * have to check if the entity is valid yourself. + * + * @param entity Entity Index. + * @param fadeOut Optional: Fade the entity out (true) or in (false). + * @param kill Optional: If to kill the entity when the fade is finished. + * @param fast Optional: Fade the entity fast (~0.7 secs) or slow (~3 secs) + * @param callback Optional: You can specify a callback Function that will get called when the fade is finished. + * @param data Optional: You can pass any data to the callback. + */ +stock void Effect_Fade(int entity, bool fadeOut=true, bool kill=false, bool fast=true, EffectCallback callback=INVALID_FUNCTION, any data=0) +{ + float timerTime = 0.0; + + if (fast) { + timerTime = 0.6; + + if (fadeOut) { + SetEntityRenderFx(entity, RENDERFX_FADE_FAST); + } + else { + SetEntityRenderFx(entity, RENDERFX_SOLID_FAST); + } + } + else { + timerTime = 3.0; + + if (fadeOut) { + SetEntityRenderFx(entity, RENDERFX_FADE_SLOW); + } + else { + SetEntityRenderFx(entity, RENDERFX_SOLID_SLOW); + } + } + + ChangeEdictState(entity, GetEntSendPropOffs(entity, "m_nRenderFX", true)); + + if (kill || callback != INVALID_FUNCTION) { + DataPack dataPack = null; + CreateDataTimer(timerTime, _smlib_Timer_Effect_Fade, dataPack, TIMER_FLAG_NO_MAPCHANGE | TIMER_DATA_HNDL_CLOSE); + + WritePackCell(dataPack, EntIndexToEntRef(entity)); + WritePackCell(dataPack, kill); + WritePackFunction(dataPack, callback); + WritePackCell(dataPack, data); + ResetPack(dataPack); + } +} + +/** + * Fades the entity in. + * A wrapper function around Effect_Fade(). + * + * @param entity Entity Index. + * @param fast Optional: Fade the entity fast (~0.7 secs) or slow (~3 secs) + * @param callback Optional: You can specify a callback Function that will get called when the fade is finished. + * @param data Optional: You can pass any data to the callback. + */ +stock void Effect_FadeIn(int entity, bool fast=true, EffectCallback callback=INVALID_FUNCTION, any data=0) +{ + Effect_Fade(entity, false, false, fast, callback, data); +} + +/** + * Fades the entity out. + * A wrapper function around Effect_Fade(). + * + * @param entity Entity Index. + * @param fadeOut Optional: Fade the entity out (true) or in (false). + * @param kill Optional: If to kill the entity when the fade is finished. + * @param fast Optional: Fade the entity fast (~0.7 secs) or slow (~3 secs) + * @param callback Optional: You can specify a callback Function that will get called when the fade is finished. + * @param data Optional: You can pass any data to the callback. + */ +stock void Effect_FadeOut(int entity, bool kill=false, bool fast=true, EffectCallback callback=INVALID_FUNCTION, any data=0) +{ + Effect_Fade(entity, true, kill, fast, callback, data); +} + +public Action _smlib_Timer_Effect_Fade(Handle Timer, DataPack dataPack) +{ + int entity = ReadPackCell(dataPack); + int kill = ReadPackCell(dataPack); + Function callback = ReadPackFunction(dataPack); + any data = ReadPackCell(dataPack); + + if (callback != INVALID_FUNCTION) { + Call_StartFunction(INVALID_HANDLE, callback); + Call_PushCell(entity); + Call_PushCell(data); + Call_Finish(); + } + + if (kill && IsValidEntity(entity)) { + Entity_Kill(entity); + } + + return Plugin_Stop; +} + +/** + * Sends a boxed beam effect to one player. + * + * Ported from eventscripts vecmath library. + * + * @param client The client to show the box to. + * @param bottomCorner One bottom corner of the box. + * @param upperCorner One upper corner of the box. + * @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. + */ +stock void Effect_DrawBeamBoxToClient( + int client, + const float bottomCorner[3], + const float upperCorner[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + const int color[4]={ 255, 0, 0, 255 }, + int speed=0 +) { + int clients[1]; + clients[0] = client; + Effect_DrawBeamBox(clients, 1, bottomCorner, upperCorner, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); +} + +/** + * Sends a boxed beam effect to all players. + * + * Ported from eventscripts vecmath library. + * + * @param bottomCorner One bottom corner of the box. + * @param upperCorner One upper corner of the box. + * @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. + */ +stock void Effect_DrawBeamBoxToAll( + const float bottomCorner[3], + const float upperCorner[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + const int color[4]={ 255, 0, 0, 255 }, + int speed=0 +) +{ + int[] clients = new int[MaxClients]; + int numClients = Client_Get(clients, CLIENTFILTER_INGAME); + + Effect_DrawBeamBox(clients, numClients, bottomCorner, upperCorner, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); +} + +/** + * Sends a boxed beam effect to a list of players. + * + * Ported from eventscripts vecmath library. + * + * @param clients An array of clients to show the box to. + * @param numClients Number of players in the array. + * @param bottomCorner One bottom corner of the box. + * @param upperCorner One upper corner of the box. + * @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. + */ +stock void Effect_DrawBeamBox( + int[] clients, + int numClients, + const float bottomCorner[3], + const float upperCorner[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + const int color[4]={ 255, 0, 0, 255 }, + int speed=0 +) { + // Create the additional corners of the box + float corners[8][3]; + + for (int i=0; i < 4; i++) { + Array_Copy(bottomCorner, corners[i], 3); + Array_Copy(upperCorner, corners[i+4], 3); + } + + corners[1][0] = upperCorner[0]; + corners[2][0] = upperCorner[0]; + corners[2][1] = upperCorner[1]; + corners[3][1] = upperCorner[1]; + corners[4][0] = bottomCorner[0]; + corners[4][1] = bottomCorner[1]; + corners[5][1] = bottomCorner[1]; + corners[7][0] = bottomCorner[0]; + + // Draw all the edges + + // Horizontal Lines + // Bottom + for (int i=0; i < 4; i++) { + int j = ( i == 3 ? 0 : i+1 ); + TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } + + // Top + for (int i=4; i < 8; i++) { + int j = ( i == 7 ? 4 : i+1 ); + TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } + + // All Vertical Lines + for (int i=0; i < 4; i++) { + TE_SetupBeamPoints(corners[i], corners[i+4], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } +} + + +/** + * Sends a boxed beam effect to one player. + * + * Ported from eventscripts vecmath library. + * + * @param client The client to show the box to. + * @param origin Origin/center of the box. + * @param mins Min size Vector + * @param maxs Max size Vector + * @param angles Angles used to rotate the box. + * @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. + */ +stock void Effect_DrawBeamBoxRotatableToClient( + int client, + const float origin[3], + const float mins[3], + const float maxs[3], + const float angles[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + const int color[4]={ 255, 0, 0, 255 }, + int speed=0 +) { + int clients[1]; + clients[0] = client; + Effect_DrawBeamBoxRotatable(clients, 1, origin, mins, maxs, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); +} + + + +/** + * Sends a boxed beam effect to all players. + * + * Ported from eventscripts vecmath library. + * + * @param origin Origin/center of the box. + * @param mins Min size Vector + * @param maxs Max size Vector + * @param angles Angles used to rotate the box. + * @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. + */ +stock void Effect_DrawBeamBoxRotatableToAll( + const float origin[3], + const float mins[3], + const float maxs[3], + const float angles[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + const int color[4]={ 255, 0, 0, 255 }, + int speed=0 +) +{ + int[] clients = new int[MaxClients]; + int numClients = Client_Get(clients, CLIENTFILTER_INGAME); + + Effect_DrawBeamBoxRotatable(clients, numClients, origin, mins, maxs, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); +} + +/** + * Sends a boxed beam effect to a list of players. + * + * Ported from eventscripts vecmath library. + * + * @param clients An array of clients to show the box to. + * @param numClients Number of players in the array. + * @param origin Origin/center of the box. + * @param mins Min size Vector + * @param maxs Max size Vector + * @param angles Angles used to rotate the box. + * @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. + */ +stock void Effect_DrawBeamBoxRotatable( + int[] clients, + int numClients, + const float origin[3], + const float mins[3], + const float maxs[3], + const float angles[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + const int color[4]={ 255, 0, 0, 255 }, + int speed=0 +) { + // Create the additional corners of the box + float corners[8][3]; + Array_Copy(mins, corners[0], 3); + Math_MakeVector(maxs[0], mins[1], mins[2], corners[1]); + Math_MakeVector(maxs[0], maxs[1], mins[2], corners[2]); + Math_MakeVector(mins[0], maxs[1], mins[2], corners[3]); + Math_MakeVector(mins[0], mins[1], maxs[2], corners[4]); + Math_MakeVector(maxs[0], mins[1], maxs[2], corners[5]); + Array_Copy(maxs, corners[6], 3); + Math_MakeVector(mins[0], maxs[1], maxs[2], corners[7]); + + // Rotate all edges + for (int i=0; i < sizeof(corners); i++) { + Math_RotateVector(corners[i], angles, corners[i]); + } + + // Apply world offset (after rotation) + for (int i=0; i < sizeof(corners); i++) { + AddVectors(origin, corners[i], corners[i]); + } + + // Draw all the edges + // Horizontal Lines + // Bottom + for (int i=0; i < 4; i++) { + int j = ( i == 3 ? 0 : i+1 ); + TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } + + // Top + for (int i=4; i < 8; i++) { + int j = ( i == 7 ? 4 : i+1 ); + TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } + + // All Vertical Lines + for (int i=0; i < 4; i++) { + TE_SetupBeamPoints(corners[i], corners[i+4], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } +} + +/** + * Displays the given axis of rotation as beam effect to one player. + * + * @param client The client to show the box to. + * @param origin Origin/center of the box. + * @param angles Angles used to rotate the box. + * @param length The length in each direction. + * @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. + */ +stock void Effect_DrawAxisOfRotationToClient( + int client, + const float origin[3], + const float angles[3], + const float length[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + int speed=0 +) { + int clients[1]; + clients[0] = client; + Effect_DrawAxisOfRotation(clients, 1, origin, angles, length, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, speed); +} + +/** + * Displays the given axis of rotation as beam effect to all players. + * + * @param origin Origin/center of the box. + * @param angles Angles used to rotate the box. + * @param length The length in each direction. + * @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. + */ +stock void Effect_DrawAxisOfRotationToAll( + const float origin[3], + const float angles[3], + const float length[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + int speed=0 +) +{ + int[] clients = new int[MaxClients]; + int numClients = Client_Get(clients, CLIENTFILTER_INGAME); + + Effect_DrawAxisOfRotation(clients, numClients, origin, angles, length, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, speed); +} + +/** + * Displays the given axis of rotation as beam effect to a list of players. + * + * @param clients An array of clients to show the box to. + * @param numClients Number of players in the array. + * @param origin Origin/center of the box. + * @param angles Angles used to rotate the box. + * @param length The length in each direction. + * @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. + */ +stock void Effect_DrawAxisOfRotation( + int[] clients, + int numClients, + const float origin[3], + const float angles[3], + const float length[3], + int modelIndex, + int haloIndex, + int startFrame=0, + int frameRate=30, + float life=5.0, + float width=5.0, + float endWidth=5.0, + int fadeLength=2, + float amplitude=1.0, + int speed=0 +) { + // Create the additional corners of the box + float xAxis[3], yAxis[3], zAxis[3]; + xAxis[0] = length[0]; + yAxis[1] = length[1]; + zAxis[2] = length[2]; + + // Rotate all edges + Math_RotateVector(xAxis, angles, xAxis); + Math_RotateVector(yAxis, angles, yAxis); + Math_RotateVector(zAxis, angles, zAxis); + + // Apply world offset (after rotation) + AddVectors(origin, xAxis, xAxis); + AddVectors(origin, yAxis, yAxis); + AddVectors(origin, zAxis, zAxis); + + // Draw all + TE_SetupBeamPoints(origin, xAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {255, 0, 0, 255}, speed); + TE_Send(clients, numClients); + + TE_SetupBeamPoints(origin, yAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {0, 255, 0, 255}, speed); + TE_Send(clients, numClients); + + TE_SetupBeamPoints(origin, zAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {0, 0, 255, 255}, speed); + TE_Send(clients, numClients); +} + + +/** + * Creates an env_sprite. + * + * @param origin Origin of the Sprite. + * @param modelIndex Precached model index. + * @param color Color array (r, g, b, a). + * @param scale Scale (Note: many materials ignore a lower value than 0.25). + * @param targetName Targetname of the sprite. + * @param parent Entity Index of this sprite's parent in the movement hierarchy. + * @param renderMode Render mode (use the enum). + * @param renderFx Render fx (use the enum). + * @param glowProxySize Radius size of the glow when to be rendered, if inside a geometry. Ex: a block 2x2x2 units big, if the glowProxySize is between 0.0 and 2.0 the sprite will not be rendered, even if the actual size of the sprite is bigger, everything above 2.0 will render the sprite. Using an abnormal high value will render Sprites trough walls. + * @param frameRate Sprite frame rate. + * @param hdrColorScale Float value to multiply sprite color by when running with HDR. + * @param receiveShadows When false then this prevents the sprite from receiving shadows. + * @return Entity Index of the created Sprite. + */ +stock int Effect_EnvSprite( + const float origin[3], + int modelIndex, + const int color[4]={255, 255, 255, 255}, + float scale=0.25, + const char targetName[MAX_NAME_LENGTH]="", + int parent=-1, + RenderMode renderMode=RENDER_WORLDGLOW, + RenderFx renderFx=RENDERFX_NONE, + float glowProxySize=2.0, + float framerate=10.0, + float hdrColorScale=1.0, + bool receiveShadows = true +) { + int entity = Entity_Create("env_sprite"); + + if (entity == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + + DispatchKeyValue (entity, "disablereceiveshadows", (receiveShadows) ? "0" : "1"); + DispatchKeyValueFloat (entity, "framerate", framerate); + DispatchKeyValueFloat (entity, "GlowProxySize", glowProxySize); + DispatchKeyValue (entity, "spawnflags", "1"); + DispatchKeyValueFloat (entity, "HDRColorScale", hdrColorScale); + DispatchKeyValue (entity, "maxdxlevel", "0"); + DispatchKeyValue (entity, "mindxlevel", "0"); + DispatchKeyValueFloat (entity, "scale", scale); + + DispatchSpawn(entity); + + SetEntityRenderMode(entity, renderMode); + SetEntityRenderColor(entity, color[0], color[1], color[2], color[3]); + SetEntityRenderFx(entity, renderFx); + + Entity_SetName(entity, targetName); + Entity_SetModelIndex(entity, modelIndex); + Entity_SetAbsOrigin(entity, origin); + + if (parent != -1) { + Entity_SetParent(entity, parent); + } + + return entity; +} diff --git a/source/sourcemod/scripting/include/smlib/entities.inc b/source/sourcemod/scripting/include/smlib/entities.inc new file mode 100644 index 0000000..91c136b --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/entities.inc @@ -0,0 +1,2098 @@ +#if defined _smlib_entities_included + #endinput +#endif +#define _smlib_entities_included + +#include +#include +#include + +/** + * Macro for iterating trough all children (entities it is parent of) of an entity. + * + * @param 1 Entity Index of the parent. + * @param 2 Name of the children entity index variable (will be only valid in the loop). + */ +#define LOOP_CHILDREN(%1,%2) for (int %2=Entity_GetNextChild(%1); %2 != INVALID_ENT_REFERENCE; %2=Entity_GetNextChild(%1, ++%2)) + +/* + * Checks if an entity is valid and exists. + * + * @param entity Entity Index. + * @return True if the entity is valid, false otherwise. + */ +stock bool Entity_IsValid(int entity) +{ + return IsValidEntity(entity); +} + +/** + * Finds an entity by its name. + * You can optionally specify the classname to search for. + * Note: If the classname is specified it uses The Sourcemod native + * function FindEntityByClassname() which uses the engine's + * linked entity list for finding entities. This might be + * cheaper, use this if you call this function very often. + * + * @param name Name of the entity you want so search. + * @param className Optional: Classname of the entity + * @return Entity index or INVALID_ENT_REFERENCE if not matching entity was found. + */ +stock int Entity_FindByName(const char[] name, const char[] className="") +{ + if (className[0] == '\0') { + // Hack: Double the limit to gets none-networked entities too. + int realMaxEntities = GetMaxEntities() * 2; + for (int entity=0; entity < realMaxEntities; entity++) { + + if (!IsValidEntity(entity)) { + continue; + } + + if (Entity_NameMatches(entity, name)) { + return entity; + } + } + } + else { + int entity = INVALID_ENT_REFERENCE; + while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) { + + if (Entity_NameMatches(entity, name)) { + return entity; + } + } + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Finds an entity by its HammerID. + * The newer version of Valve's Hammer editor + * sets a unique ID for each entity in a map. + * It only finds the first occurence. + * Note: If the classname is specified it uses The Sourcemod native + * function FindEntityByClassname() which uses the engine's + * linked entity list for finding entities. This might be + * cheaper, use this if you call this function very often. + * + * @param hammerId Hammer editor ID + * @param className Optional: Classname of the entity + * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found. + */ +stock int Entity_FindByHammerId(int hammerId, const char[] className="") +{ + if (className[0] == '\0') { + // Hack: Double the limit to gets none-networked entities too. + int realMaxEntities = GetMaxEntities() * 2; + for (int entity=0; entity < realMaxEntities; entity++) { + + if (!IsValidEntity(entity)) { + continue; + } + + if (Entity_GetHammerId(entity) == hammerId) { + return entity; + } + } + } + else { + int entity = INVALID_ENT_REFERENCE; + while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) { + + if (Entity_GetHammerId(entity) == hammerId) { + return entity; + } + } + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Searches for an entity by classname. + * This is a wrapper around FindEntityByClassname + * and has been added for completion. + * + * @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. + */ + +stock int Entity_FindByClassName(int startEntity, const char[] className) +{ + return FindEntityByClassname(startEntity, className); +} + +/** + * Checks if an entity (partially) matches a specific entity class. + * + * @param entity Entity Index. + * @param className Classname String. + * @partialMatch If to do a partial classname check. + * @return True if the classname matches, false otherwise. + */ +stock bool Entity_ClassNameMatches(int entity, const char[] className, bool partialMatch=false) +{ + char entity_className[64]; + Entity_GetClassName(entity, entity_className, sizeof(entity_className)); + + if (partialMatch) { + return (StrContains(entity_className, className) != -1); + } + + return StrEqual(entity_className, className); +} + +/** + * Checks if an entity matches a name + * + * @param entity Entity Index. + * @param class Name String. + * @return True if the name matches, false otherwise. + */ +stock bool Entity_NameMatches(int entity, const char[] name) +{ + char entity_name[128]; + Entity_GetName(entity, entity_name, sizeof(entity_name)); + + return StrEqual(name, entity_name); +} + +/** + * Gets the Name of an entity. + * + * @param entity Entity index. + * @param buffer Return/Output buffer. + * @param size Max size of buffer. + * @return Number of non-null bytes written. + */ +stock int Entity_GetName(int entity, char[] buffer, int size) +{ + return GetEntPropString(entity, Prop_Data, "m_iName", buffer, size); +} + +/** + * Sets the Name of an entity. + * + * @param entity Entity index. + * @param name The name you want to give. + * @return True on success, false otherwise. + */ +stock bool Entity_SetName(int entity, const char[] name, any ...) +{ + char format[128]; + VFormat(format, sizeof(format), name, 3); + + return DispatchKeyValue(entity, "targetname", format); +} + +/** + * Gets the Classname of an entity. + * This is like GetEdictClassname(), except it works for ALL + * entities, not just edicts. + * + * @param entity Entity index. + * @param buffer Return/Output buffer. + * @param size Max size of buffer. + * @return Number of non-null bytes written. + */ +stock int Entity_GetClassName(int entity, char[] buffer, int size) +{ + return GetEntPropString(entity, Prop_Data, "m_iClassname", buffer, size); +} + +/** + * Sets the Classname of an entity. + * + * @param entity Entity index. + * @param name The name you want to give. + * @return True on success, false otherwise. + */ +stock bool Entity_SetClassName(int entity, const char[] className) +{ + return DispatchKeyValue(entity, "classname", className); +} + +/** + * Gets the Target name of an other entity + * + * @param entity Entity index. + * @param buffer Return/Output buffer. + * @param size Max size of buffer. + * @return Number of non-null bytes written. + */ +stock int Entity_GetTargetName(int entity, char[] buffer, int size) +{ + return GetEntPropString(entity, Prop_Data, "m_target", buffer, size); +} + +/** + * Sets the Target name of an other Entity + * + * @param entity Entity index. + * @param name The target name you want to set + * @return True on success, false otherwise. + */ +stock bool Entity_SetTargetName(int entity, const char[] name, any ...) +{ + char format[128]; + VFormat(format, sizeof(format), name, 3); + + return DispatchKeyValue(entity, "target", format); +} + +/** + * Gets the Global Name of an entity. + * + * @param entity Entity index. + * @param buffer Return/Output buffer. + * @param size Max size of buffer. + * @return Number of non-null bytes written. + */ +stock int Entity_GetGlobalName(int entity, char[] buffer, int size) +{ + return GetEntPropString(entity, Prop_Data, "m_iGlobalname", buffer, size); +} + +/** + * Sets the Global Name of an entity. + * + * @param entity Entity index. + * @param name The global name you want to set. + * @return True on success, false otherwise. + */ +stock bool Entity_SetGlobalName(int entity, const char[] name, any ...) +{ + char format[128]; + VFormat(format, sizeof(format), name, 3); + + return DispatchKeyValue(entity, "globalname", format); +} + +/** + * Gets the Parent name of an entity. + * + * @param entity Entity index. + * @param buffer Return/Output buffer. + * @param size Max size of buffer. + * @return Number of non-null bytes written. + */ +stock int Entity_GetParentName(int entity, char[] buffer, int size) +{ + return GetEntPropString(entity, Prop_Data, "m_iParent", buffer, size); +} + +/** + * Sets the Parent name of an entity. + * + * @param entity Entity index. + * @param name The parent name you want to set. + * @return True on success, false otherwise. + */ +stock bool Entity_SetParentName(int entity, const char[] name, any ...) +{ + char format[128]; + VFormat(format, sizeof(format), name, 3); + + return DispatchKeyValue(entity, "parentname", format); +} + +/** + * Gets the Hammer-ID of an entity. + * The Hammer Editor gives every entity a unique ID. + * Note: Old maps don't have Hammer-ID's set for entities + * + * @param entity Entity index. + * @return Hammer ID. + */ +stock int Entity_GetHammerId(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_iHammerID"); +} + +/** + * Gets the radius (m_flRadius) of an entity. + * + * @param entity Entity index. + * @return Radius + */ +stock float Entity_GetRadius(int entity) +{ + return GetEntPropFloat(entity, Prop_Data, "m_flRadius"); +} + +/** + * Sets the radius (m_flRadius) of an entity. + * + * @param entity Entity index. + * @param radius Radius value + */ +stock void Entity_SetRadius(int entity, float radius) +{ + SetEntPropFloat(entity, Prop_Data, "m_flRadius", radius); +} + +/** + * Gets the Mins of an entity. + * + * @param entity Entity index. + * @param vec Buffer to hold the vector. + */ +stock void Entity_GetMinSize(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Send, "m_vecMins", vec); +} + +/** + * Sets the Mins of an entity. + * + * @param entity Entity index. + * @param vec Vector. + */ +stock void Entity_SetMinSize(int entity, const float vecMins[3]) +{ + SetEntPropVector(entity, Prop_Send, "m_vecMins", vecMins); +} + +/** + * Gets the Mins of an entity. + * This functions isn't safe to use, use Entity_SetMinMaxSize() instead. + * + * @param entity Entity index + * @param vec Buffer to hold the vector + */ +stock void Entity_GetMaxSize(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Send, "m_vecMaxs", vec); +} + +/** + * Sets the Maxs of an entity. + * This functions isn't safe to use, use Entity_SetMinMaxSize() instead. + * + * @param entity Entity index. + * @param vec Buffer to hold the vector. + */ +stock void Entity_SetMaxSize(int entity, const float vecMaxs[3]) +{ + SetEntPropVector(entity, Prop_Send, "m_vecMaxs", vecMaxs); +} + +/** + * Sets the Min and Max Size of an entity. + * Code is taken from HL2SDK and rewritten for Sourcemod. + * + * @param entity Entity index. + * @param vecMins Min size Vector + * @param vecMaxs Max size Vector + */ +stock void Entity_SetMinMaxSize(int entity, float vecMins[3], float vecMaxs[3]) +{ + // Taken from hl2sdk-ob-valve\game\server\util.cpp SetMinMaxSize() + // Todo: Replace this by a SDK call + for (int i=0; i<3; i++) { + + if (vecMins[i] > vecMaxs[i]) { + ThrowError("Error: mins[%d] > maxs[%d] of entity %d", i, i, EntRefToEntIndex(entity)); + } + } + + float m_vecMins[3], m_vecMaxs[3]; + Entity_GetMinSize(entity, m_vecMins); + Entity_GetMaxSize(entity, m_vecMaxs); + + if (Math_VectorsEqual(m_vecMins, vecMins) && Math_VectorsEqual(m_vecMaxs, vecMaxs)) { + return; + } + + Entity_SetMinSize(entity, vecMins); + Entity_SetMaxSize(entity, vecMaxs); + + float vecSize[3]; + SubtractVectors(vecMaxs, vecMins, vecSize); + Entity_SetRadius(entity, GetVectorLength(vecSize) * 0.5); + + Entity_MarkSurrBoundsDirty(entity); +} + +/* + * Spawn Flags + * Many entities define their specific spawnflags, check the HL2SDK. + */ + +/* + * Phys prop spawnflags + * Taken from hl2sdk-ob-valve\game\shared\props_shared.h + */ +#define SF_PHYSPROP_START_ASLEEP 0x000001 +#define SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE 0x000002 // this prop can't be damaged by physics collisions +#define SF_PHYSPROP_DEBRIS 0x000004 +#define SF_PHYSPROP_MOTIONDISABLED 0x000008 // motion disabled at startup (flag only valid in spawn - motion can be enabled via input) +#define SF_PHYSPROP_TOUCH 0x000010 // can be 'crashed through' by running player (plate glass) +#define SF_PHYSPROP_PRESSURE 0x000020 // can be broken by a player standing on it +#define SF_PHYSPROP_ENABLE_ON_PHYSCANNON 0x000040 // enable motion only if the player grabs it with the physcannon +#define SF_PHYSPROP_NO_ROTORWASH_PUSH 0x000080 // The rotorwash doesn't push these +#define SF_PHYSPROP_ENABLE_PICKUP_OUTPUT 0x000100 // If set, allow the player to +USE this for the purposes of generating an output +#define SF_PHYSPROP_PREVENT_PICKUP 0x000200 // If set, prevent +USE/Physcannon pickup of this prop +#define SF_PHYSPROP_PREVENT_PLAYER_TOUCH_ENABLE 0x000400 // If set, the player will not cause the object to enable its motion when bumped into +#define SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS 0x000800 // Need to remove attached ragdolls on enable motion/etc +#define SF_PHYSPROP_FORCE_TOUCH_TRIGGERS 0x001000 // Override normal debris behavior and respond to triggers anyway +#define SF_PHYSPROP_FORCE_SERVER_SIDE 0x002000 // Force multiplayer physics object to be serverside +#define SF_PHYSPROP_RADIUS_PICKUP 0x004000 // For Xbox, makes small objects easier to pick up by allowing them to be found +#define SF_PHYSPROP_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply. +#define SF_PHYSPROP_NO_COLLISIONS 0x200000 // Don't enable collisions on spawn +#define SF_PHYSPROP_IS_GIB 0x400000 // Limit # of active gibs + +/* + * Physbox Spawnflags. Start at 0x01000 to avoid collision with CBreakable's + * Taken from hl2sdk-ob-valve\game\server\physobj.h + */ +#define SF_PHYSBOX_ASLEEP 0x01000 +#define SF_PHYSBOX_IGNOREUSE 0x02000 +#define SF_PHYSBOX_DEBRIS 0x04000 +#define SF_PHYSBOX_MOTIONDISABLED 0x08000 +#define SF_PHYSBOX_USEPREFERRED 0x10000 +#define SF_PHYSBOX_ENABLE_ON_PHYSCANNON 0x20000 +#define SF_PHYSBOX_NO_ROTORWASH_PUSH 0x40000 // The rotorwash doesn't push these +#define SF_PHYSBOX_ENABLE_PICKUP_OUTPUT 0x80000 +#define SF_PHYSBOX_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply. +#define SF_PHYSBOX_NEVER_PICK_UP 0x200000 // Physcannon will never be able to pick this up. +#define SF_PHYSBOX_NEVER_PUNT 0x400000 // Physcannon will never be able to punt this object. +#define SF_PHYSBOX_PREVENT_PLAYER_TOUCH_ENABLE 0x800000 // If set, the player will not cause the object to enable its motion when bumped into + +/* + * Spawnflags for func breakable + * Taken from hl2sdk-ob-valve\game\server\func_break.h + */ +#define SF_BREAK_TRIGGER_ONLY 0x0001 // may only be broken by trigger +#define SF_BREAK_TOUCH 0x0002 // can be 'crashed through' by running player (plate glass) +#define SF_BREAK_PRESSURE 0x0004 // can be broken by a player standing on it +#define SF_BREAK_PHYSICS_BREAK_IMMEDIATELY 0x0200 // the first physics collision this breakable has will immediately break it +#define SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE 0x0400 // this breakable doesn't take damage from physics collisions +#define SF_BREAK_NO_BULLET_PENETRATION 0x0800 // don't allow bullets to penetrate + +/* + * Spawnflags for func_pushable (it's also func_breakable, so don't collide with those flags) + * Taken from hl2sdk-ob-valve\game\server\func_break.h + */ +#define SF_PUSH_BREAKABLE 0x0080 +#define SF_PUSH_NO_USE 0x0100 // player cannot +use pickup this ent + +/** + * Gets the Spawnflags of an entity. + * + * @param entity Entity index. + * @return Spawnflags value + */ +stock int Entity_GetSpawnFlags(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_spawnflags"); +} + +/** + * Sets the Spawnflags of an entity. + * + * @param entity Entity index. + * @param flags Flags value + */ +stock void Entity_SetSpawnFlags(int entity, int flags) +{ + SetEntProp(entity, Prop_Data, "m_spawnflags", flags); +} + +/** + * Adds Spawnflags to an entity. + * + * @param entity Entity index. + * @param flags Flags value + */ +stock void Entity_AddSpawnFlags(int entity, int flags) +{ + int spawnFlags = Entity_GetSpawnFlags(entity); + spawnFlags |= flags; + Entity_SetSpawnFlags(entity, spawnFlags); +} + +/** + * Removes Spawnflags from an entity. + * + * @param entity Entity index. + * @param flags Flags value + */ +stock void Entity_RemoveSpawnFlags(int entity, int flags) +{ + int spawnFlags = Entity_GetSpawnFlags(entity); + spawnFlags &= ~flags; + Entity_SetSpawnFlags(entity, spawnFlags); +} + +/** + * Clears all Spawnflags of an entity. + * + * @param entity Entity index. + * @noretur */ +stock void Entity_ClearSpawnFlags(int entity) +{ + Entity_SetSpawnFlags(entity, 0); +} + +/** + * Returns whether the entity has specific Spawnflags. + * + * @param entity Entity index. + * @param flags Flags value. + * @return True if the entity has the spawnflags set, false otherwise. + */ +stock bool Entity_HasSpawnFlags(int entity, int flags) +{ + return Entity_GetSpawnFlags(entity) & flags == flags; +} + +/* + * Entity flags, CBaseEntity::m_iEFlags + * Taken from: hl2sdk-ob-valve\game\shared\shareddefs.h + */ +enum Entity_Flags +{ + EFL_KILLME = (1<<0), // This entity is marked for death -- This allows the game to actually delete ents at a safe time + EFL_DORMANT = (1<<1), // Entity is dormant, no updates to client + EFL_NOCLIP_ACTIVE = (1<<2), // Lets us know when the noclip command is active. + EFL_SETTING_UP_BONES = (1<<3), // Set while a model is setting up its bones. + EFL_KEEP_ON_RECREATE_ENTITIES = (1<<4), // This is a special entity that should not be deleted when we restart entities only + + EFL_HAS_PLAYER_CHILD= (1<<4), // One of the child entities is a player. + + EFL_DIRTY_SHADOWUPDATE = (1<<5), // Client only- need shadow manager to update the shadow... + EFL_NOTIFY = (1<<6), // Another entity is watching events on this entity (used by teleport) + + // The default behavior in ShouldTransmit is to not send an entity if it doesn't + // have a model. Certain entities want to be sent anyway because all the drawing logic + // is in the client DLL. They can set this flag and the engine will transmit them even + // if they don't have a model. + EFL_FORCE_CHECK_TRANSMIT = (1<<7), + + EFL_BOT_FROZEN = (1<<8), // This is set on bots that are frozen. + EFL_SERVER_ONLY = (1<<9), // Non-networked entity. + EFL_NO_AUTO_EDICT_ATTACH = (1<<10), // Don't attach the edict; we're doing it explicitly + + // Some dirty bits with respect to abs computations + EFL_DIRTY_ABSTRANSFORM = (1<<11), + EFL_DIRTY_ABSVELOCITY = (1<<12), + EFL_DIRTY_ABSANGVELOCITY = (1<<13), + EFL_DIRTY_SURR_COLLISION_BOUNDS = (1<<14), + EFL_DIRTY_SPATIAL_PARTITION = (1<<15), +// UNUSED = (1<<16), + + EFL_IN_SKYBOX = (1<<17), // This is set if the entity detects that it's in the skybox. + // This forces it to pass the "in PVS" for transmission. + EFL_USE_PARTITION_WHEN_NOT_SOL = (1<<18), // Entities with this flag set show up in the partition even when not solid + EFL_TOUCHING_FLUID = (1<<19), // Used to determine if an entity is floating + + // FIXME: Not really sure where I should add this... + EFL_IS_BEING_LIFTED_BY_BARNACLE = (1<<20), + EFL_NO_ROTORWASH_PUSH = (1<<21), // I shouldn't be pushed by the rotorwash + EFL_NO_THINK_FUNCTION = (1<<22), + EFL_NO_GAME_PHYSICS_SIMULATION = (1<<23), + + EFL_CHECK_UNTOUCH = (1<<24), + EFL_DONTBLOCKLOS = (1<<25), // I shouldn't block NPC line-of-sight + EFL_DONTWALKON = (1<<26), // NPC;s should not walk on this entity + EFL_NO_DISSOLVE = (1<<27), // These guys shouldn't dissolve + EFL_NO_MEGAPHYSCANNON_RAGDOLL = (1<<28), // Mega physcannon can't ragdoll these guys. + EFL_NO_WATER_VELOCITY_CHANGE = (1<<29), // Don't adjust this entity's velocity when transitioning into water + EFL_NO_PHYSCANNON_INTERACTION = (1<<30), // Physcannon can't pick these up or punt them + EFL_NO_DAMAGE_FORCES = (1<<31), // Doesn't accept forces from physics damage +}; + +/** + * Gets the Entity flags (m_iEFlags) of an entity. + * + * @param entity Entity index. + * @return Entity flags value + */ +stock Entity_Flags Entity_GetEFlags(int entity) +{ + return view_as(GetEntProp(entity, Prop_Data, "m_iEFlags")); +} + +/** + * Sets the entity's Entity flags (m_iEFlags). + * + * @param entity Entity index. + * @param flags Flags value + */ +stock void Entity_SetEFlags(int entity, Entity_Flags flags) +{ + SetEntProp(entity, Prop_Data, "m_iEFlags", flags); +} + +/** + * Adds Entity flags (m_iEFlags) to an entity. + * + * @param entity Entity index. + * @param flags Flags value + */ +stock void Entity_AddEFlags(int entity, Entity_Flags flags) +{ + Entity_Flags setFlags = Entity_GetEFlags(entity); + setFlags |= flags; + Entity_SetEFlags(entity, setFlags); +} + +/** + * Removes Entity flags (m_iEFlags) from an entity. + * + * @param entity Entity index. + * @param flags Flags value + */ +stock void Entity_RemoveEFlags(int entity, Entity_Flags flags) +{ + Entity_Flags setFlags = Entity_GetEFlags(entity); + setFlags &= ~flags; + Entity_SetEFlags(entity, setFlags); +} + +/** + * Checks if the entity has specific Entity flags (m_iEFlags) set. + * + * @param entity Entity index. + * @param flags Flags value + * @return True if the flags are set, false otherwise. + */ +stock bool Entity_HasEFlags(int entity, Entity_Flags flags) +{ + Entity_Flags currentEFlags = Entity_GetEFlags(entity); + + return currentEFlags & flags == flags; +} + +/** + * Marks the surrounding bounds of an entity as outdated. + * You normally call this when a collision setting has changed. + * + * @param entity Entity index. + */ +stock void Entity_MarkSurrBoundsDirty(int entity) +{ + Entity_AddEFlags(entity, EFL_DIRTY_SURR_COLLISION_BOUNDS); +} + +/* + * CBaseEntity::m_fFlags Functions + * Use the FL_ Defines (FL_ONGROUND, ...) or + * special entity specific flags. + * Note: The flag FL_AIMTARGET probably doesn't work as + * we have current no way of adding/removing it to the AimTarget List. + */ + +/** + * Gets the Flags of an entity. + * + * @param entity Entity Index. + * @return Entity Flags. + */ +stock int Entity_GetFlags(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_fFlags"); +} + +/** + * Sets the Flags of an entity. + * + * @param entity Entity index. + * @param flags New Flags value + */ +stock void Entity_SetFlags(int entity, int flags) +{ + SetEntProp(entity, Prop_Data, "m_fFlags", flags); +} + +/** + * Adds Flags to the entity + * + * @param entity Entity index. + * @param flags Flags to add + * @noreturn + */ +stock void Entity_AddFlags(int entity, int flags) +{ + int setFlags = Entity_GetFlags(entity); + setFlags |= flags; + Entity_SetFlags(entity, setFlags); +} + +/** + * Removes flags from the entity + * + * @param entity Entity index. + * @param flags Flags to remove + */ +stock void Entity_RemoveFlags(int entity, int flags) +{ + int setFlags = Entity_GetFlags(entity); + setFlags &= ~flags; + Entity_SetFlags(entity, setFlags); +} + +/** + * Toggles the specified flag on the entity. + * Adds the flag to the entity if it doesn't exists + * or removes it otherwise. + * + * @param entity Entity index. + * @param flags Flag to Toggle + */ +stock void Entity_ToggleFlag(int entity, int flag) +{ + int setFlag = Entity_GetFlags(entity); + setFlag ^= flag; + Entity_SetFlags(entity, setFlag); +} + +/** + * Removes all flags from the entity + * + * @param entity Entity index. + */ +stock void Entity_ClearFlags(int entity) +{ + Entity_SetFlags(entity, 0); +} + +/* edict->solid values + * NOTE: Some movetypes will cause collisions independent of SOLID_NOT/SOLID_TRIGGER when the entity moves + * SOLID only effects OTHER entities colliding with this one when they move - UGH! + * + * Solid type basically describes how the bounding volume of the object is represented + * NOTE: These numerical values are used in the FGD by the prop code (see prop_dynamic) + * Taken from: hl2sdk-ob-valve\public\const.h + */ + +enum SolidFlags_t +{ + FSOLID_CUSTOMRAYTEST = 0x0001, // Ignore solid type + always call into the entity for ray tests + FSOLID_CUSTOMBOXTEST = 0x0002, // Ignore solid type + always call into the entity for swept box tests + FSOLID_NOT_SOLID = 0x0004, // Are we currently not solid? + FSOLID_TRIGGER = 0x0008, // This is something may be collideable but fires touch functions + // even when it's not collideable (when the FSOLID_NOT_SOLID flag is set) + FSOLID_NOT_STANDABLE = 0x0010, // You can't stand on this + FSOLID_VOLUME_CONTENTS = 0x0020, // Contains volumetric contents (like water) + FSOLID_FORCE_WORLD_ALIGNED = 0x0040, // Forces the collision rep to be world-aligned even if it's SOLID_BSP or SOLID_VPHYSICS + FSOLID_USE_TRIGGER_BOUNDS = 0x0080, // Uses a special trigger bounds separate from the normal OBB + FSOLID_ROOT_PARENT_ALIGNED = 0x0100, // Collisions are defined in root parent's local coordinate space + FSOLID_TRIGGER_TOUCH_DEBRIS = 0x0200, // This trigger will touch debris objects + + FSOLID_MAX_BITS = 10 +}; + +/** + * Gets the solid flags of the entity + * + * @param entity Entity index. + * @return Solid Flags. + */ +stock SolidFlags_t Entity_GetSolidFlags(int entity) +{ + return view_as(GetEntProp(entity, Prop_Data, "m_usSolidFlags", 2)); +} + +/** + * Sets the solid flags of the entity + * + * @param entity Entity index. + * @param flags Solid Flags. + */ +stock void Entity_SetSolidFlags(int entity, SolidFlags_t flags) +{ + SolidFlags_t oldFlags = Entity_GetSolidFlags(entity); + flags = flags & view_as(0xFFFF); + + if (oldFlags == flags) { + return; + } + + SetEntProp(entity, Prop_Data, "m_usSolidFlags", flags, 2); + + // These two flags, if changed, can produce different surrounding bounds + if ((oldFlags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS)) != + (flags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS))) + { + Entity_MarkSurrBoundsDirty(entity); + } +} + +/** + * Adds solid flags to the entity + * + * @param entity Entity index. + * @param flags Solid Flags. + */ +stock void Entity_AddSolidFlags(int entity, SolidFlags_t flags) +{ + SolidFlags_t newFlags = Entity_GetSolidFlags(entity); + newFlags |= flags; + Entity_SetSolidFlags(entity, newFlags); +} + +/** + * Removes solid flags from the entity. + * + * @param entity Entity index. + * @param flags Solid Flags. + */ +stock void Entity_RemoveSolidFlags(int entity, SolidFlags_t flags) +{ + SolidFlags_t newFlags = Entity_GetSolidFlags(entity); + newFlags &= ~flags; + Entity_SetSolidFlags(entity, newFlags); +} + +/** + * Removes all solid flags from the entity. + * + * @param entity Entity index. + */ +stock void Entity_ClearSolidFlags(int entity) +{ + Entity_SetSolidFlags(entity, view_as(0)); +} + +/** + * Checks whether certain solid flags are set on the entity. + * + * @param entity Entity index. + * @param flags Solid Flags. + * @return True if the specified flags are set, false otherwise. + */ +stock bool Entity_SolidFlagsSet(int entity, SolidFlags_t flagMask) +{ + return Entity_GetSolidFlags(entity) & flagMask == flagMask; +} + +enum SolidType_t +{ + SOLID_NONE = 0, // no solid model + SOLID_BSP = 1, // a BSP tree + SOLID_BBOX = 2, // an AABB + SOLID_OBB = 3, // an OBB (not implemented yet) + SOLID_OBB_YAW = 4, // an OBB, constrained so that it can only yaw + SOLID_CUSTOM = 5, // Always call into the entity for tests + SOLID_VPHYSICS = 6, // solid vphysics object, get vcollide from the model and collide with that + SOLID_LAST, +}; + +/** + * Gets the solidity type of the entity + * + * @param entity Entity index. + * @return Solid Type + */ +stock SolidType_t Entity_GetSolidType(int entity) +{ + return view_as(GetEntProp(entity, Prop_Data, "m_nSolidType", 1)); +} + +/** + * Sets the solidity type of the entity + * + * @param entity Entity index. + * @param Solid Type value. + */ +stock void Entity_SetSolidType(int entity, SolidType_t value) +{ + SetEntProp(entity, Prop_Send, "m_nSolidType", value, 1); + Entity_MarkSurrBoundsDirty(entity); +} + +/** + * Checks whether the entity is solid or not. + * + * @param entity Entity index. + * @return True if the entity is solid, false otherwise. + */ +stock bool Entity_IsSolid(int entity) +{ + return (Entity_GetSolidType(entity) != SOLID_NONE && + !Entity_SolidFlagsSet(entity, FSOLID_NOT_SOLID)); +} + +/** + * Retrieves the model path of a given entity. + * Returns "*num" for Brush entities. + * + * @param entity entity reference or index + * @param model buffer String for the model + * @param size max size of buffer string + * @return Number of non-null bytes written. + */ +stock int Entity_GetModel(int entity, char[] buffer, int size) +{ + return GetEntPropString(entity, Prop_Data, "m_ModelName", buffer, size); +} + +/** + * Sets the model to a given entity. + * Be sure it has been precached. + * This is an alias for SetEntityModel() + * + * @param entity Entity index + * @param model Model name + */ +stock void Entity_SetModel(int entity, const char[] model) +{ + SetEntityModel(entity, model); +} + +/** + * Gets the entity's model index, if it has one set. + * + * @param entity Entity index. + * @return The Entity's model index + */ +stock int Entity_GetModelIndex(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_nModelIndex", 2); +} + +/** + * Sets the entity's model index (must be precached) + * + * @param entity Entity index. + * @param index Model Index. + */ +stock void Entity_SetModelIndex(int entity, int index) +{ + SetEntProp(entity, Prop_Data, "m_nModelIndex", index, 2); +} + +/** +* Sets the entity's maxspeed to the given value (in units per second) +* +* @param entity Entity index +* @param maxspeed the maximum speed the entity can move +* @noreturn +*/ +stock void Entity_SetMaxSpeed(int entity, float value) +{ + SetEntPropFloat(entity, Prop_Data, "m_flMaxspeed", value); +} + +/* + * Collision groups + * Taken from hl2sdk-ob-valve/public/const.h + */ +enum Collision_Group_t +{ + COLLISION_GROUP_NONE = 0, + COLLISION_GROUP_DEBRIS, // Collides with nothing but world and static stuff + COLLISION_GROUP_DEBRIS_TRIGGER, // Same as debris, but hits triggers + COLLISION_GROUP_INTERACTIVE_DEB, // Collides with everything except other interactive debris or debris + COLLISION_GROUP_INTERACTIVE, // Collides with everything except interactive debris or debris + COLLISION_GROUP_PLAYER, + COLLISION_GROUP_BREAKABLE_GLASS, + COLLISION_GROUP_VEHICLE, + COLLISION_GROUP_PLAYER_MOVEMENT, // For HL2, same as Collision_Group_Player, for + // TF2, this filters out other players and CBaseObjects + COLLISION_GROUP_NPC, // Generic NPC group + COLLISION_GROUP_IN_VEHICLE, // for any entity inside a vehicle + COLLISION_GROUP_WEAPON, // for any weapons that need collision detection + COLLISION_GROUP_VEHICLE_CLIP, // vehicle clip brush to restrict vehicle movement + COLLISION_GROUP_PROJECTILE, // Projectiles! + COLLISION_GROUP_DOOR_BLOCKER, // Blocks entities not permitted to get near moving doors + COLLISION_GROUP_PASSABLE_DOOR, // Doors that the player shouldn't collide with + COLLISION_GROUP_DISSOLVING, // Things that are dissolving are in this group + COLLISION_GROUP_PUSHAWAY, // Nonsolid on client and server, pushaway in player code + + COLLISION_GROUP_NPC_ACTOR, // Used so NPCs in scripts ignore the player. + COLLISION_GROUP_NPC_SCRIPTED // USed for NPCs in scripts that should not collide with each other +}; + +/** + * Gets the collision group of an entity. + * + * @param entity entity index + * @return Entity collision group. + */ +stock Collision_Group_t Entity_GetCollisionGroup(int entity) +{ + return view_as(GetEntProp(entity, Prop_Data, "m_CollisionGroup")); +} + +/** + * Sets the collision group of an entity. + * + * @param entity entity index + * @param value the new collision group. + */ +stock void Entity_SetCollisionGroup(int entity, Collision_Group_t value) +{ + SetEntProp(entity, Prop_Data, "m_CollisionGroup", value); +} + +/** + * Functions for getting / setting the origin (position) of an entity. + * Go to http://developer.valvesoftware.com/wiki/Origin + * if you want to learn more about origins + */ + +/** + * Gets the Absolute Origin (position) of an entity. + * + * @param entity Entity index. + * @param vec 3 dimensional vector array. + */ +stock void Entity_GetAbsOrigin(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Send, "m_vecOrigin", vec); +} + +/** + * Sets the Absolute Origin (position) of an entity. + * + * @param entity Entity index. + * @param vec 3 dimensional vector array. + */ +stock void Entity_SetAbsOrigin(int entity, const float vec[3]) +{ + // We use TeleportEntity to set the origin more safely + // Todo: Replace this with a call to UTIL_SetOrigin() or CBaseEntity::SetLocalOrigin() + TeleportEntity(entity, vec, NULL_VECTOR, NULL_VECTOR); +} + +/** + * Functions for getting / setting the angles (rotation) of an entity. + * http://developer.valvesoftware.com/wiki/Angles + * if you want to learn more about angles + */ + +/** + * Gets the Angles of an entity + * + * @param entity Entity index. + * @param vec 3 dimensional vector array. + * @noreturn + */ +stock void Entity_GetAbsAngles(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Data, "m_angAbsRotation", vec); +} + +/** + * Sets the Angles of an entity + * + * @param entity Entity index. + * @param vec 3 dimensional vector array. + */ +stock void Entity_SetAbsAngles(int entity, const float vec[3]) +{ + // We use TeleportEntity to set the angles more safely + // Todo: Replace this with a call to CBaseEntity::SetLocalAngles() + TeleportEntity(entity, NULL_VECTOR, vec, NULL_VECTOR); +} + +/** + * Functions for getting / setting the velocity of an entity. + * Go to http://developer.valvesoftware.com/wiki/Velocity + * if you want to learn more about the different kind of velocities. + */ + +/** + * Gets the Local velocity of an entity. + * The local velocity is the velocity generated by the entity. + * + * @param entity Entity index. + * @param vel An 3 dim array + */ +stock void Entity_GetLocalVelocity(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Data, "m_vecVelocity", vec); +} + +/** + * Sets the Local velocity of an entity. + * The local velocity is the velocity generated by the entity. + * Only use this if you know what you are doing, + * the entity can overwrite this value on next frame. + * + * @param entity Entity index. + * @param vel An 3 dim array + */ +stock void Entity_SetLocalVelocity(int entity, const float vec[3]) +{ + SetEntPropVector(entity, Prop_Data, "m_vecVelocity", vec); +} + +/** + * Gets the Base velocity of an entity. + * The base velocity is the velocity applied + * to the entity from other sources . + * + * @param entity Entity index. + * @param vel An 3 dim array + */ +stock void Entity_GetBaseVelocity(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Data, "m_vecBaseVelocity", vec); +} + +/** + * Sets the Base velocity of an entity. + * The base velocity is the velocity applied + * to the entity from other sources . + * + * @param entity Entity index. + * @param vel An 3 dim array + */ +stock void Entity_SetBaseVelocity(int entity, const float vec[3]) +{ + SetEntPropVector(entity, Prop_Data, "m_vecBaseVelocity", vec); +} + +/** + * Gets the Absolute velocity of an entity. + * The absolute velocity is the sum of the local + * and base velocities. It's the actual value used to move. + * + * @param entity Entity index. + * @param vel An 3 dim array + */ +stock void Entity_GetAbsVelocity(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Data, "m_vecAbsVelocity", vec); +} + +/** + * Sets the Absolute velocity of an entity. + * The absolute velocity is the sum of the local + * and base velocities. It's the actual value used to move. + * + * @param entity Entity index. + * @param vel An 3 dim array + */ +stock void Entity_SetAbsVelocity(int entity, const float vec[3]) +{ + // We use TeleportEntity to set the velocity more safely + // Todo: Replace this with a call to CBaseEntity::SetAbsVelocity() + TeleportEntity(entity, NULL_VECTOR, NULL_VECTOR, vec); +} + +/** + * Returns true if the entity is locked. + * + * @param entity Entity index. + * @return True if locked otherwise false. + */ +stock bool Entity_IsLocked(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_bLocked", 1) != 0; +} + +/** + * Locks an entity. + * + * @param entity Entity index. + */ +stock void Entity_Lock(int entity) +{ + SetEntProp(entity, Prop_Data, "m_bLocked", 1, 1); +} +/** + * Unlocks an entity. + * + * @param entity Entity index. + */ +stock void Entity_UnLock(int entity) +{ + SetEntProp(entity, Prop_Data, "m_bLocked", 0, 1); +} + +/** + * Gets the health of an entity. + * + * @param entity entity index. + * @return current health points + */ +stock int Entity_GetHealth(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_iHealth"); +} + +/** + * Sets the health of an entity. + * + * @param entity Entity index. + * @param value Health to set (anything above 511 will overload) + * @param ignoreMax Ignore the entity's maxhealth setting. + * @param kill Kill the entity if health gets to 0. + * @return The health the entity actually got set to. + */ +stock int Entity_SetHealth(int entity, int value, bool ignoreMax=false, bool kill=true) +{ + int health = value; + + if (!ignoreMax) { + int maxHealth = Entity_GetMaxHealth(entity); + + if (health > maxHealth) { + health = maxHealth; + } + } + + if (health < 0) { + health = 0; + } + + SetEntProp(entity, Prop_Data, "m_iHealth", health); + + if (health <= 0) { + Entity_Kill(entity); + } + + return health; +} + +/** + * Add health to an entity + * + * @param entity Entity index + * @param value Health to add + * @param ignoreMax Ignore the entity's maxhealth setting. + * @param kill Kill the entity if health gets to 0. + * @return Returns the new health value set + */ +stock int Entity_AddHealth(int entity, int value, bool ignoreMax=false, bool kill=true) +{ + int health = Entity_GetHealth(entity); + + health += value; + + return Entity_SetHealth(entity, health, ignoreMax, kill); +} + +/** + * Takes health from an entity + * + * @param entity entity index + * @param value health to add + * @return returns the new health value set + */ +stock int Entity_TakeHealth(int entity, int value, bool ignoreMax=false, bool kill=true) +{ + int health = Entity_GetHealth(entity); + + health -= value; + + return Entity_SetHealth(entity, health, ignoreMax, kill); +} + +/** + * Get the max health of an entity + * + * @param entity Entity Index + * @return Max health points + */ +stock int Entity_GetMaxHealth(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_iMaxHealth"); +} + + +/** + * Set the max health of an entity. + * + * @param entity Entity index + * @param value Max health to set (anything above 511 will overload) + */ +stock void Entity_SetMaxHealth(int entity, int value) +{ + SetEntProp(entity, Prop_Data, "m_iMaxHealth", value); +} + +/** + * Returns the Float distance between an entity + * and a vector origin. + * + * @param entity Entity Index. + * @param target Vector Origin. + * @return Distance Float value. + */ +stock float Entity_GetDistanceOrigin(int entity, const float vec[3]) +{ + float entityVec[3]; + Entity_GetAbsOrigin(entity, entityVec); + + return GetVectorDistance(entityVec, vec); +} + +/** + * Returns the Float distance between two entities. + * Both entities must be valid. + * + * @param entity Entity Index. + * @param target Target Entity Index. + * @return Distance Float value. + */ +stock float Entity_GetDistance(int entity, int target) +{ + float targetVec[3]; + Entity_GetAbsOrigin(target, targetVec); + + return Entity_GetDistanceOrigin(entity, targetVec); +} + +/** + * Checks if the given 2 entitys are within a given range. + * + * @param entity Entity Index. + * @param target Target Entity Index. + * @param distance Max Float distance. + * @return True if the given entities are closer than the given distance value, false otherwise. + */ +stock bool Entity_InRange(int entity, int target, float distance) +{ + if (Entity_GetDistance(entity, target) > distance) { + return false; + } + + return true; +} + +/** + * Enables the motion of an entity. + * + * @param entity Entity index. + * @return True on success, false otherwise + */ +stock bool Entity_EnableMotion(int entity) +{ + return AcceptEntityInput(entity, "enablemotion"); +} + +/** + * Disables the motion of an entity. + * + * @param entity Entity index. + * @return True on success, false otherwise + */ +stock bool Entity_DisableMotion(int entity) +{ + return AcceptEntityInput(entity, "disablemotion"); +} + +/** + * Freezes an entity by setting the FL_FROZEN flag. + * + * @param entity Entity index. + */ +stock void Entity_Freeze(int entity) +{ + Entity_AddFlags(entity, FL_FROZEN); +} + +/** + * Unfreezes an entity by removing the FL_FROZEN flag. + * + * @param entity Entity index. + */ +stock void Entity_UnFreeze(int entity) +{ + Entity_RemoveFlags(entity, FL_FROZEN); +} + + +/** + * This function points an entity to another with the targetname + * and name. Useful for allot of entities like trigger_teleport. + * If the name is not specified it will be generated automatically. + * + * @param entity Entity index. + * @param target Target entity index. + * @param Optional: target name + */ +stock void Entity_PointAtTarget(int entity, int target, const char[] name="") +{ + char targetName[128]; + Entity_GetTargetName(entity, targetName, sizeof(targetName)); + + if (name[0] == '\0') { + + if (targetName[0] == '\0') { + // Let's generate our own name + Format( + targetName, + sizeof(targetName), + "_smlib_Entity_PointAtTarget:%d", + target + ); + } + } + else { + strcopy(targetName, sizeof(targetName), name); + } + + Entity_SetTargetName(entity, targetName); + Entity_SetName(target, targetName); +} + +/** + * This function points a point_hurt entity to another damage target entity.. + * and name. Useful for allot of entities like trigger_teleport. + * If the name is not specified it will be generated automatically. + * + * @param entity Entity index. + * @param target Target entity index. + * @param Optional: target name + */ +stock void Entity_PointHurtAtTarget(int entity, int target, const char[] name="") +{ + char targetName[128]; + Entity_GetTargetName(entity, targetName, sizeof(targetName)); + + if (name[0] == '\0') { + + if (targetName[0] == '\0') { + // Let's generate our own name + Format( + targetName, + sizeof(targetName), + "_smlib_Entity_PointHurtAtTarget:%d", + target + ); + } + } + else { + strcopy(targetName, sizeof(targetName), name); + } + + DispatchKeyValue(entity, "DamageTarget", targetName); + Entity_SetName(target, targetName); +} + +/** + * Checks if an entity is a player or not. + * No checks are done if the entity is actually valid, + * the player is connected or ingame. + * + * @param entity Entity index. + * @return True if the entity is a player, false otherwise. + */ +stock bool Entity_IsPlayer(int entity) +{ + if (entity < 1 || entity > MaxClients) { + return false; + } + + return true; +} + +/** + * Creates an entity by classname. + * + * @param className Classname String. + * @param ForceEdictIndex Edict Index to use. + * @return Entity Index or INVALID_ENT_REFERENCE if the slot is already in use. + */ +stock int Entity_Create(const char[] className, int ForceEdictIndex=-1) +{ + if (ForceEdictIndex != -1 && Entity_IsValid(ForceEdictIndex)) { + return INVALID_ENT_REFERENCE; + } + + return CreateEntityByName(className, ForceEdictIndex); +} + +/** + * Kills an entity on the next frame (delayed). + * It is safe to use with entity loops. + * If the entity is is player ForcePlayerSuicide() is called. + * + * @param kenny Entity index. + * @param killChildren When true, kennys children are killed too. + * @return True on success, false otherwise. + */ +stock bool Entity_Kill(int kenny, bool killChildren=false) +{ + if (Entity_IsPlayer(kenny)) { + // Oh My God! They Killed Kenny!! + ForcePlayerSuicide(kenny); + return true; + } + + if(killChildren){ + return AcceptEntityInput(kenny, "KillHierarchy"); + } + else { + return AcceptEntityInput(kenny, "Kill"); + } +} + +/** + * Kills all entities with the given networked classname. + * It is safe to use with entity loops. + * If the entity is is player ForcePlayerSuicide() is called. + * + * @param className Entity Network Class to search for. + * @return Number of entities killed. + */ +stock int Entity_KillAllByClassName(const char[] className) +{ + int x = 0; + + int entity = INVALID_ENT_REFERENCE; + while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) { + AcceptEntityInput(entity, "kill"); + x++; + } + + return x; +} + +/** + * Gets the owner of an entity. + * For example the owner of a weapon entity. + * + * @param entity Entity index. + * @return Ground Entity or -1 + */ +stock int Entity_GetOwner(int entity) +{ + return GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity"); +} + +/** + * Sets the owner of an entity. + * For example the owner of a weapon entity. + * + * @param entity Entity index. + */ +stock void Entity_SetOwner(int entity, int newOwner) +{ + SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", newOwner); +} + +/** + * Get's the ground entity this entity stands on. + * + * @param entity Entity index. + * @return Ground Entity or -1 + */ +stock int Entity_GetGroundEntity(int entity) +{ + return GetEntPropEnt(entity, Prop_Data, "m_hGroundEntity"); +} + +/* + * Damage definitions + */ + +#if !defined DMG_GENERIC + +#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. + +#endif + +/** + * Does damage to an entity. + * This is a powerful function that allows you to specify + * who the attacker is, the damage type and also what weapon + * should be displayed in the hud kill message. + * Note that for entities that fire another entity (RPG's, Crossbow's, + * you have to pass the bullet's class, not the weapon's class ! + * It hasn't been tested how expensive this function is, as it + * uses the entity point_hurt. + * If you need a cheaper function use Entity_RemoveHealth(). + * + * @param entity Entity index. + * @param damage Amount of damage. + * @param attacker Entity Index of the attacker. + * @param damageType Use the DMG_ definations. + * @param fakeClassName Classname to fake, you can set this if you + * want a specific weapon to be shown in the HUD kill message. + * @param customOrigin Teleport point_hurt to origin before triggering hurt + * useful for damage force calculations e.g. explosions, gun fire direction, ect. + * @return True on success, false otherwise. + */ +stock bool Entity_Hurt(int entity, int damage, int attacker=0, int damageType=DMG_GENERIC, const char[] fakeClassName="", float customOrigin[3]={0.0, 0.0, 0.0}) +{ + static int point_hurt = INVALID_ENT_REFERENCE; + + if (point_hurt == INVALID_ENT_REFERENCE || !IsValidEntity(point_hurt)) { + point_hurt = EntIndexToEntRef(Entity_Create("point_hurt")); + + if (point_hurt == INVALID_ENT_REFERENCE) { + return false; + } + + DispatchSpawn(point_hurt); + } + + AcceptEntityInput(point_hurt, "TurnOn"); + SetEntProp(point_hurt, Prop_Data, "m_nDamage", damage); + SetEntProp(point_hurt, Prop_Data, "m_bitsDamageType", damageType); + + char orignalTargetName[128]; + Entity_GetName(entity, orignalTargetName, sizeof(orignalTargetName)); + Entity_PointHurtAtTarget(point_hurt, entity); + + if (fakeClassName[0] != '\0') { + Entity_SetClassName(point_hurt, fakeClassName); + } + + TeleportEntity(point_hurt, customOrigin, NULL_VECTOR, NULL_VECTOR); + + AcceptEntityInput(point_hurt, "Hurt", attacker); + AcceptEntityInput(point_hurt, "TurnOff"); + + if (fakeClassName[0] != '\0') { + Entity_SetClassName(point_hurt, "point_hurt"); + } + + DispatchKeyValue(entity, "targetname", orignalTargetName); + return true; +} + +/* + * Gets the parent entity of an entity. + * + * @param entity Entity Index. + * @return Entity Index of the parent. + */ +stock int Entity_GetParent(int entity) +{ + return GetEntPropEnt(entity, Prop_Data, "m_pParent"); +} + +/* + * Clears the parent of an entity. + * + * @param entity Entity Index. + */ +stock void Entity_ClearParent(int entity) +{ + //SetVariantString(""); + AcceptEntityInput(entity, "ClearParent"); +} + +/* + * Sets the parent entity of an entity. + * + * @param entity Entity Index. + * @param parent Entity Index of the new parent. + */ +stock void Entity_SetParent(int entity, int parent) +{ + SetVariantString("!activator"); + AcceptEntityInput(entity, "SetParent", parent); +} + + +/* + * Callback for Change_OverTime. + * Note that every parameter is a reference and can be changed during this callback. + * You can get the elapsed time since start by multiply tick with currentCall. + * + * @param entity Entity Index. + * @param interval The current interval from the current game time to execute the next call of this function. + * @param currentCall The current call number (0 is the 1st call at 0.0 seconds, 1 the 2nd call at tick*1 seconds, ...). + * @return When true this callback will be called again at the next defined tick, otherwise it won't. + */ +typedef Entity_ChangeOverTimeCallback = function bool (int &entity, float &interval, int ¤tCall); + +/* + * Creates a timer and provides a callback to change various things about an entity over time. + * + * @param entity Entity Index. + * @param interval Interval from the current game time to execute the given function. + * @noreturn + */ +stock void Entity_ChangeOverTime(int entity, float interval=0.1, Entity_ChangeOverTimeCallback valueCallback) +{ + DataPack dataPack = CreateDataPack(); + WritePackCell(dataPack, EntIndexToEntRef(entity)); + WritePackFloat(dataPack, interval); + WritePackCell(dataPack, 0); + WritePackFunction(dataPack, valueCallback); + ResetPack(dataPack); + __smlib_Timer_ChangeOverTime(INVALID_HANDLE,dataPack); +} + +public Action __smlib_Timer_ChangeOverTime(Handle Timer, DataPack dataPack) +{ + int entity = EntRefToEntIndex(ReadPackCell(dataPack)); + if(!Entity_IsValid(entity)){ + return Plugin_Stop; + } + + float interval = ReadPackFloat(dataPack); + int currentCall = ReadPackCell(dataPack); + Function callback = ReadPackFunction(dataPack); + + any result; + Call_StartFunction(INVALID_HANDLE, callback); + Call_PushCellRef(entity); + Call_PushFloatRef(interval); + Call_PushCellRef(currentCall); + Call_Finish(result); + + if(result == false){ + return Plugin_Stop; + } + + ResetPack(dataPack,true); + WritePackCell(dataPack, EntIndexToEntRef(entity)); + WritePackFloat(dataPack, interval); + WritePackCell(dataPack, currentCall+1); + WritePackFunction(dataPack, callback); + ResetPack(dataPack); + CreateTimer(interval, __smlib_Timer_ChangeOverTime, dataPack); + return Plugin_Stop; +} + + +/** + * Gets the next child, entity is parent of. + * + * @param parent Entity Index (of Parent) + * @param start Start Index. + * @return Entity Index or -1 if no entity was found. + */ +stock int Entity_GetNextChild(int parent, int start=0) +{ + int maxEntities = GetMaxEntities(); + for (int entity=start; entity < maxEntities; entity++) { + + if (!Entity_IsValid(entity)) { + continue; + } + + if (entity > 0 && entity <= MaxClients && !IsClientConnected(entity)) { + continue; + } + + if (Entity_GetParent(entity) == parent) { + return entity; + } + } + + return INVALID_ENT_REFERENCE; +} +/** + * Gets the move/open direction of an entity (only available for func_door*, prop_door* and func_movelinear). + * Ex: if vec[2] is 1.0 a func_door moves straight up. + * + * @param entity Entity index. + * @param vec Vector. + */ +stock void Entity_GetMoveDirection(int entity, float vec[3]) +{ + GetEntPropVector(entity, Prop_Data, "m_vecMoveDir", vec); +} +/** + * Sets the move/open direction of an entity (only available for func_door*, prop_door* and func_movelinear). + * Ex: if vec[2] is 1.0 a func_door moves straight up. + * + * @param entity Entity index. + * @param vec Vector. + */ +stock void Entity_SetMoveDirection(int entity, const float vec[3]) +{ + SetEntPropVector(entity, Prop_Data, "m_vecMoveDir", vec); +} + +/** + * Returns if the entity will force close (won't be blockable by players and/or objects) or not when triggered to move. + * + * @param entity Entity index. + * @return True if the door will force close, otherwise false. + */ +stock bool Entity_GetForceClose(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_bForceClosed") != 0; +} + +/** + * Sets if the door should force close (souldn't be blockable by players and/or objects) or not when triggered to move. + * + * @param entity Entity index. + * @param forceClose If true the door will force close, otherwise it won't. + */ +stock void Entity_SetForceClose(int entity, bool forceClose) +{ + SetEntProp(entity, Prop_Data, "m_bForceClosed", forceClose); +} + +/** + * Gets the speed of a moving entity (like doors: open close speed). + * + * @param entity Entity index. + * @return Speed of the entity. + */ +stock float Entity_GetSpeed(int entity) +{ + return GetEntPropFloat(entity, Prop_Data, "m_flSpeed"); +} + +/** + * Sets how fast an entity moves (like doors: open close speed). + * + * @param entity Entity index. + * @param speed The new speed of the entity. + */ +stock void Entity_SetSpeed(int entity, float speed) +{ + SetEntPropFloat(entity, Prop_Data, "m_flSpeed", speed); +} + +/** + * Gets the damage of a moving entity when blocked (like doors when open or close and players and/or objects are between the entity and something else). + * Note: Negative values add health to the blocking entity. + * + * @param entity Entity index. + * @return Damage. + */ +stock float Entity_GetBlockDamage(int entity) +{ + return GetEntPropFloat(entity, Prop_Data, "m_flBlockDamage"); +} + +/** + * Sets the damage of a moving entity when blocked (like doors when open or close and players and/or objects are between the entity and something else). + * Note: Negative values add health to the blocking entity. + * + * @param entity Entity index. + * @param damage Damage. + */ +stock void Entity_SetBlockDamage(int entity, float damage) +{ + SetEntPropFloat(entity, Prop_Data, "m_flBlockDamage", damage); +} + +/** + * Returns if the given entity is disabled or not. + * + * @param entity Entity index. + * @return True if entity is disabled, otherwise false. + */ +stock bool Entity_IsDisabled(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_bDisabled", 1) != 0; +} + +/** + * Disables the given entity. + * + * @param entity Entity index. + * @return True if successful otherwise false. + */ +stock bool Entity_Disable(int entity) +{ + return AcceptEntityInput(entity, "Disable"); +} + +/** + * Enables the given entity. + * + * @param entity Entity index. + * @return True if successful otherwise false. + */ +stock bool Entity_Enable(int entity) +{ + return AcceptEntityInput(entity, "Enable"); +} + + +// settings for m_takedamage taken from hl2sdk-ob-valve\game\shared\shareddefs.h +#define DAMAGE_NO 0 +#define DAMAGE_EVENTS_ONLY 1 // Call damage functions, but don't modify health +#define DAMAGE_YES 2 +#define DAMAGE_AIM 3 + +/** + * Sets the mode for an entity to take damage. + * Note: This is used to give a client god mode (DAMAGE_NO). + * + * @param entity Entity index. + * @param value Mode, use DAMAGE_* defines. + */ +stock void Entity_SetTakeDamage(int entity, int value) +{ + SetEntProp(entity, Prop_Data, "m_takedamage", value, 1); +} + +/** + * Gets the mode for an entity to take damage. + * Note: When the return value is DAMAGE_NO then the client is using godmode. + * + * @param entity Entity index. + * @return Take damage mode (DAMAGE_*). + */ +stock int Entity_GetTakeDamage(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_takedamage", 1); +} + +/** + * Sets the minimum of damage required to hurt this entity. + * Example: This is used to block any damage done by projectile weapons against a gun ship in Half-Life 2. + * + * @param entity Entity index. + * @param minDamage Minimum required damage. + */ +stock void Entity_SetMinHealthDamage(int entity, int minDamage) +{ + SetEntProp(entity, Prop_Data, "m_iMinHealthDmg", minDamage); +} + +/** + * Gets the minimum of damage required to hurt this entity. + * Example: This is used to block any damage done by projectile weapons against a gun ship in Half-Life 2. + * + * @param entity Entity index. + * @return Minimum required damage. + */ +stock int Entity_GetMinHealthDamage(int entity) +{ + return GetEntProp(entity, Prop_Data, "m_iMinHealthDmg"); +} + +/** + * Gets an entity's color. + * + * @param entity Entity index + * @param color 4 dimensional array where [r,g,b,a] values are stored + * @error Invalid entity index, or lack of mod compliance. + */ +stock void Entity_GetRenderColor(int entity, int color[4]) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) { + Handle gc = LoadGameConfigFile("core.games"); + bool exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop)); + delete gc; + + if (!exists) { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + int offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) { + ThrowError("SetEntityRenderColor not supported by this mod"); + } + + for (int i=0; i < 4; i++) { + color[i] = GetEntData(entity, offset + i, 1); + } +} + +/** + * Sets an entity's color. + * Doesn't change the value, if set to -1. + * + * @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) + * @error Invalid entity index, or lack of mod compliance. + */ +stock void Entity_SetRenderColor(int entity, int r=-1, int g=-1, int b=-1, int a=-1) +{ + static bool gotconfig = false; + static char prop[32]; + + if (!gotconfig) { + Handle gc = LoadGameConfigFile("core.games"); + bool exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop)); + delete gc; + + if (!exists) { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + int offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) { + ThrowError("SetEntityRenderColor not supported by this mod"); + } + + if(r != -1) { + SetEntData(entity, offset, r, 1, true); + } + + if(g != -1) { + SetEntData(entity, offset + 1, g, 1, true); + } + + if(b != -1) { + SetEntData(entity, offset + 2, b, 1, true); + } + + if(a != -1) { + SetEntData(entity, offset + 3, a, 1, true); + } +} + +/** + * Sends the 'addouput' command to an entity. + * + * @param entity Entity Index. + * @param input Input command. + * @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. + */ +stock bool Entity_AddOutput(int entity, const char[] input, int activator=-1, int caller=-1, int outputid=0) +{ + SetVariantString(input); + return AcceptEntityInput(entity, "addoutput", activator, caller, outputid); +} diff --git a/source/sourcemod/scripting/include/smlib/files.inc b/source/sourcemod/scripting/include/smlib/files.inc new file mode 100644 index 0000000..a31d606 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/files.inc @@ -0,0 +1,451 @@ +#if defined _smlib_files_included + #endinput +#endif +#define _smlib_files_included + +#include +#include +#include + +/** + * Gets the Base name of a path. + * Examples: + * blub.txt -> "blub.txt" + * /sourcemod/extensions/example.ext.so -> "example.ext.so" + * + * @param path File path + * @param buffer String buffer array + * @param size Size of string buffer + */ +stock void File_GetBaseName(const char[] path, char[] buffer, int size) +{ + if (path[0] == '\0') { + buffer[0] = '\0'; + return; + } + + int pos_start = FindCharInString(path, '/', true); + + if (pos_start == -1) { + pos_start = FindCharInString(path, '\\', true); + } + + pos_start++; + + strcopy(buffer, size, path[pos_start]); +} + +/** + * Gets the Directory of a path (without the file name). + * Does not work with "." as the path. + * Examples: + * blub.txt -> "blub.txt" + * /sourcemod/extensions/example.ext.so -> "example.ext.so" + * + * @param path File path + * @param buffer String buffer array + * @param size Size of string buffer + */ +stock void File_GetDirName(const char[] path, char[] buffer, int size) +{ + if (path[0] == '\0') { + buffer[0] = '\0'; + return; + } + + int pos_start = FindCharInString(path, '/', true); + + if (pos_start == -1) { + pos_start = FindCharInString(path, '\\', true); + + if (pos_start == -1) { + buffer[0] = '\0'; + return; + } + } + + strcopy(buffer, size, path); + buffer[pos_start] = '\0'; +} + +/** + * Gets the File name of a path. + * blub.txt -> "blub" + * /sourcemod/extensions/example.ext.so -> "example.ext" + * + * @param path File path + * @param buffer String buffer array + * @param size Size of string buffer + */ +stock void File_GetFileName(const char[] path, char[] buffer, int size) +{ + if (path[0] == '\0') { + buffer[0] = '\0'; + return; + } + + File_GetBaseName(path, buffer, size); + + int pos_ext = FindCharInString(buffer, '.', true); + + if (pos_ext != -1) { + buffer[pos_ext] = '\0'; + } +} + +/** + * Gets the Extension of a file. + * Examples: + * blub.inc.txt -> "txt" + * /sourcemod/extensions/example.ext.so -> "so" + * + * @param path Path String + * @param buffer String buffer array + * @param size Max length of string buffer + */ +stock void File_GetExtension(const char[] path, char[] buffer, int size) +{ + int extpos = FindCharInString(path, '.', true); + + if (extpos == -1) { + buffer[0] = '\0'; + return; + } + + strcopy(buffer, size, path[++extpos]); +} + +/** + * Adds a path to the downloadables network string table. + * This can be a file or directory and also works recursed. + * You can optionally specify file extensions that should be ignored. + * Bz2 and ztmp are automatically ignored. + * It only adds files that actually exist. + * You can also specify a wildcard * after the ., very useful for models. + * This forces a client to download the file if they do not already have it. + * + * @param path Path String + * @param recursive Whether to do recursion or not. + * @param ignoreExts Optional: 2 dimensional String array.You can define it like this: new String:ignore[][] = { ".ext1", ".ext2" }; + * @param size This should be set to the number of file extensions in the ignoreExts array (sizeof(ignore) for the example above) + */ + +// Damn you SourcePawn :( I didn't want to +char _smlib_empty_twodimstring_array[][] = { { '\0' } }; +stock void File_AddToDownloadsTable(const char[] path, bool recursive=true, const char[][] ignoreExts=_smlib_empty_twodimstring_array, int size=0) +{ + if (path[0] == '\0') { + return; + } + + if (FileExists(path)) { + + char fileExtension[5]; + File_GetExtension(path, fileExtension, sizeof(fileExtension)); + + if (StrEqual(fileExtension, "bz2", false) || StrEqual(fileExtension, "ztmp", false)) { + return; + } + + if (Array_FindString(ignoreExts, size, fileExtension) != -1) { + return; + } + + char path_new[PLATFORM_MAX_PATH]; + strcopy(path_new, sizeof(path_new), path); + ReplaceString(path_new, sizeof(path_new), "//", "/"); + + AddFileToDownloadsTable(path_new); + } + else if (recursive && DirExists(path)) { + + char dirEntry[PLATFORM_MAX_PATH]; + DirectoryListing __dir = OpenDirectory(path); + + while (ReadDirEntry(__dir, dirEntry, sizeof(dirEntry))) { + + if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) { + continue; + } + + Format(dirEntry, sizeof(dirEntry), "%s/%s", path, dirEntry); + File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size); + } + + delete __dir; + } + else if (FindCharInString(path, '*', true)) { + + char fileExtension[4]; + File_GetExtension(path, fileExtension, sizeof(fileExtension)); + + if (StrEqual(fileExtension, "*")) { + + char dirName[PLATFORM_MAX_PATH], + fileName[PLATFORM_MAX_PATH], + dirEntry[PLATFORM_MAX_PATH]; + + File_GetDirName(path, dirName, sizeof(dirName)); + File_GetFileName(path, fileName, sizeof(fileName)); + StrCat(fileName, sizeof(fileName), "."); + + DirectoryListing __dir = OpenDirectory(dirName); + while (ReadDirEntry(__dir, dirEntry, sizeof(dirEntry))) { + + if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) { + continue; + } + + if (strncmp(dirEntry, fileName, strlen(fileName)) == 0) { + Format(dirEntry, sizeof(dirEntry), "%s/%s", dirName, dirEntry); + File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size); + } + } + + delete __dir; + } + } +} + + +/* + * Adds all files/paths in the given text file to the download table. + * Recursive mode enabled, see File_AddToDownloadsTable() + * Comments are allowed ! Supported comment types are ; // # + * + * @param path Path to the .txt file. + */ +stock void File_ReadDownloadList(const char[] path) +{ + File file = OpenFile(path, "r"); + + if (file == INVALID_HANDLE) { + return; + } + + char buffer[PLATFORM_MAX_PATH]; + while (!IsEndOfFile(file)) { + ReadFileLine(file, buffer, sizeof(buffer)); + + int pos; + pos = StrContains(buffer, "//"); + if (pos != -1) { + buffer[pos] = '\0'; + } + + pos = StrContains(buffer, "#"); + if (pos != -1) { + buffer[pos] = '\0'; + } + + pos = StrContains(buffer, ";"); + if (pos != -1) { + buffer[pos] = '\0'; + } + + TrimString(buffer); + + if (buffer[0] == '\0') { + continue; + } + + File_AddToDownloadsTable(buffer); + } + + delete file; +} + +/* + * Attempts to load a translation file and optionally unloads the plugin if the file + * doesn't exist (also prints an error message). + * + * @param file Filename of the translations file (eg. .phrases). + * @param setFailState If true, it sets the failstate if the translations file doesn't exist + * @return True on success, false otherwise (only if setFailState is set to false) + */ +stock bool File_LoadTranslations(const char[] file, bool setFailState=true) +{ + char path[PLATFORM_MAX_PATH]; + + BuildPath(Path_SM, path, sizeof(path), "translations/%s", file); + + if (FileExists(path)) { + LoadTranslations(file); + return true; + } + + Format(path,sizeof(path), "%s.txt", path); + + if (!FileExists(path)) { + + if (setFailState) { + SetFailState("Unable to locate translation file (%s).", path); + } + + return false; + } + + LoadTranslations(file); + + return true; +} + +/* + * Reads the contents of a given file into a string buffer in binary mode. + * + * @param path Path to the file + * @param buffer String buffer + * @param size 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. + */ +stock int File_ToString(const char[] path, char[] buffer, int size) +{ + File file = OpenFile(path, "rb"); + + if (file == INVALID_HANDLE) { + buffer[0] = '\0'; + return -1; + } + + int num_bytes_written = ReadFileString(file, buffer, size); + delete file; + + return num_bytes_written; +} + +/* + * Writes a string into a file in binary mode. + * + * @param file Path to the file + * @param str String to write + * @return True on success, false otherwise + */ +stock bool File_StringToFile(const char[] path, char[] str) +{ + File file = OpenFile(path, "wb"); + + if (file == INVALID_HANDLE) { + return false; + } + + bool success = WriteFileString(file, str, false); + delete file; + + return success; +} + +/* + * Copies file source to destination + * Based on code of javalia: + * http://forums.alliedmods.net/showthread.php?t=159895 + * + * @param source Input file + * @param destination Output file + * @return True on success, false otherwise + */ +stock bool File_Copy(const char[] source, const char[] destination) +{ + File file_source = OpenFile(source, "rb"); + + if (file_source == INVALID_HANDLE) { + return false; + } + + File file_destination = OpenFile(destination, "wb"); + + if (file_destination == INVALID_HANDLE) { + delete file_source; + return false; + } + + int buffer[32]; + int cache; + + while (!IsEndOfFile(file_source)) { + cache = ReadFile(file_source, buffer, sizeof(buffer), 1); + WriteFile(file_destination, buffer, cache, 1); + } + + delete file_source; + delete file_destination; + + return true; +} + +/* + * Recursively copies (the content) of a directory or file specified + * by "path" to "destination". + * Note that because of Sourcemod API limitations this currently does not + * takeover the file permissions (it leaves them default). + * Links will be resolved. + * + * @param path Source path + * @param destination Destination directory (This can only be a directory) + * @param stop_on_error Optional: Set to true to stop on error (ie can't read a file) + * @param dirMode Optional: File mode for directories that will be created (Default = 0755), don't forget to convert FROM octal + * @return True on success, false otherwise + */ +stock bool File_CopyRecursive(const char[] path, const char[] destination, bool stop_on_error=false, int dirMode=493) +{ + if (FileExists(path)) { + return File_Copy(path, destination); + } + else if (DirExists(path)) { + return Sub_File_CopyRecursive(path, destination, stop_on_error, FileType_Directory, dirMode); + } + else { + return false; + } +} + +static stock bool Sub_File_CopyRecursive(const char[] path, const char[] destination, bool stop_on_error=false, FileType fileType, int dirMode) +{ + if (fileType == FileType_File) { + return File_Copy(path, destination); + } + else if (fileType == FileType_Directory) { + + if (!CreateDirectory(destination, dirMode) && stop_on_error) { + return false; + } + + DirectoryListing directory = OpenDirectory(path); + + if (directory == INVALID_HANDLE) { + return false; + } + + char + source_buffer[PLATFORM_MAX_PATH], + destination_buffer[PLATFORM_MAX_PATH]; + FileType type; + + while (ReadDirEntry(directory, source_buffer, sizeof(source_buffer), type)) { + + if (StrEqual(source_buffer, "..") || StrEqual(source_buffer, ".")) { + continue; + } + + Format(destination_buffer, sizeof(destination_buffer), "%s/%s", destination, source_buffer); + Format(source_buffer, sizeof(source_buffer), "%s/%s", path, source_buffer); + + if (type == FileType_File) { + File_Copy(source_buffer, destination_buffer); + } + else if (type == FileType_Directory) { + + if (!File_CopyRecursive(source_buffer, destination_buffer, stop_on_error, dirMode) && stop_on_error) { + delete directory; + return false; + } + } + } + + delete directory; + } + else if (fileType == FileType_Unknown) { + return false; + } + + return true; +} diff --git a/source/sourcemod/scripting/include/smlib/game.inc b/source/sourcemod/scripting/include/smlib/game.inc new file mode 100644 index 0000000..ee3d145 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/game.inc @@ -0,0 +1,57 @@ +#if defined _smlib_game_included + #endinput +#endif +#define _smlib_game_included + +#include +#include +#include + +/* + * End's the game and displays the scoreboard with intermission time. + * + * @return True on success, false otherwise + */ +stock bool Game_End() +{ + int game_end = FindEntityByClassname(-1, "game_end"); + + if (game_end == -1) { + game_end = CreateEntityByName("game_end"); + + if (game_end == -1) { + ThrowError("Unable to find or create entity \"game_end\""); + } + } + + return AcceptEntityInput(game_end, "EndGame"); +} + +/* + * End's the current round, allows specifying the winning + * team and more. + * This function currently works in TF2 only (it uses the game_round_win entity). + * + * @param team The winning Team, pass 0 for Sudden Death mode (no winning team) + * @param forceMapReset If to force the map to reset during the force respawn after the round is over. + * @param switchTeams If to switch the teams when the game is going to be reset. + * @return True on success, false otherwise + */ +stock bool Game_EndRound(int team=0, bool forceMapReset=false, bool switchTeams=false) +{ + int game_round_win = FindEntityByClassname(-1, "game_round_win"); + + if (game_round_win == -1) { + game_round_win = CreateEntityByName("game_round_win"); + + if (game_round_win == -1) { + ThrowError("Unable to find or create entity \"game_round_win\""); + } + } + + DispatchKeyValue(game_round_win, "TeamNum" , (team ? "true" : "false")); + DispatchKeyValue(game_round_win, "force_map_reset" , (forceMapReset? "true" : "false")); + DispatchKeyValue(game_round_win, "switch_teams" , (switchTeams ? "true" : "false")); + + return AcceptEntityInput(game_round_win, "RoundWin"); +} diff --git a/source/sourcemod/scripting/include/smlib/general.inc b/source/sourcemod/scripting/include/smlib/general.inc new file mode 100644 index 0000000..a7e4d35 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/general.inc @@ -0,0 +1,251 @@ +#if defined _smlib_general_included + #endinput +#endif +#define _smlib_general_included + +#include +#include +#include + +#define TIME_TO_TICKS(%1) ( (int)( 0.5 + (float)(%1) / GetTickInterval() ) ) +#define TICKS_TO_TIME(%1) ( GetTickInterval() * %1 ) +#define ROUND_TO_TICKS(%1) ( TICK_INTERVAL * TIME_TO_TICKS( %1 ) ) + +/* + * Precaches the given model. + * It's best to call this OnMapStart(). + * + * @param material Path of the material to precache. + * @return Returns the material index, INVALID_STRING_INDEX on error. + */ +stock int PrecacheMaterial(const char[] material) +{ + static int materialNames = INVALID_STRING_TABLE; + + if (materialNames == INVALID_STRING_TABLE) { + if ((materialNames = FindStringTable("Materials")) == INVALID_STRING_TABLE) { + return INVALID_STRING_INDEX; + } + } + + int index = FindStringIndex2(materialNames, material); + if (index == INVALID_STRING_INDEX) { + int numStrings = GetStringTableNumStrings(materialNames); + if (numStrings >= GetStringTableMaxStrings(materialNames)) { + return INVALID_STRING_INDEX; + } + + AddToStringTable(materialNames, material); + index = numStrings; + } + + return index; +} + +/* + * Checks if the material is precached. + * + * @param material Path of the material. + * @return True if it is precached, false otherwise. + */ +stock bool IsMaterialPrecached(const char[] material) +{ + static int materialNames = INVALID_STRING_TABLE; + + if (materialNames == INVALID_STRING_TABLE) { + if ((materialNames = FindStringTable("Materials")) == INVALID_STRING_TABLE) { + return false; + } + } + + return (FindStringIndex2(materialNames, material) != INVALID_STRING_INDEX); +} + +/* + * Precaches the given particle system. + * It's best to call this OnMapStart(). + * Code based on Rochellecrab's, thanks. + * + * @param particleSystem Name of the particle system to precache. + * @return Returns the particle system index, INVALID_STRING_INDEX on error. + */ +stock int PrecacheParticleSystem(const char[] particleSystem) +{ + static int particleEffectNames = INVALID_STRING_TABLE; + + if (particleEffectNames == INVALID_STRING_TABLE) { + if ((particleEffectNames = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) { + return INVALID_STRING_INDEX; + } + } + + int index = FindStringIndex2(particleEffectNames, particleSystem); + if (index == INVALID_STRING_INDEX) { + int numStrings = GetStringTableNumStrings(particleEffectNames); + if (numStrings >= GetStringTableMaxStrings(particleEffectNames)) { + return INVALID_STRING_INDEX; + } + + AddToStringTable(particleEffectNames, particleSystem); + index = numStrings; + } + + return index; +} + +/* + * Checks if the particle system is precached. + * + * @param material Name of the particle system + * @return True if it is precached, false otherwise. + */ +stock bool IsParticleSystemPrecached(const char[] particleSystem) +{ + static int particleEffectNames = INVALID_STRING_TABLE; + + if (particleEffectNames == INVALID_STRING_TABLE) { + if ((particleEffectNames = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) { + return false; + } + } + + return (FindStringIndex2(particleEffectNames, particleSystem) != INVALID_STRING_INDEX); +} + +/* + * Searches for the index of a given string in a string table. + * + * @param table String table name. + * @param str String to find. + * @return String index if found, INVALID_STRING_INDEX otherwise. + */ +stock int FindStringIndexByTableName(const char[] table, const char[] str) +{ + int tableIndex = INVALID_STRING_TABLE; + if ((tableIndex = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) { + return INVALID_STRING_INDEX; + } + + return FindStringIndex2(tableIndex, str); +} + +/* + * Rewrite of FindStringIndex, because in my tests + * FindStringIndex failed to work correctly. + * Searches for the index of a given string in a string table. + * + * @param tableidx A string table index. + * @param str String to find. + * @return String index if found, INVALID_STRING_INDEX otherwise. + */ +stock int FindStringIndex2(int tableidx, const char[] str) +{ + char buf[1024]; + + int numStrings = GetStringTableNumStrings(tableidx); + for (int i=0; i < numStrings; i++) { + ReadStringTable(tableidx, i, buf, sizeof(buf)); + + if (StrEqual(buf, str)) { + return i; + } + } + + return INVALID_STRING_INDEX; +} + +/* + * Converts a long IP to a dotted format String. + * + * @param ip IP Long + * @param buffer String Buffer (size = 16) + * @param size String Buffer size + */ +stock void LongToIP(int ip, char[] buffer, int size) +{ + Format( + buffer, size, + "%d.%d.%d.%d", + (ip >> 24) & 0xFF, + (ip >> 16) & 0xFF, + (ip >> 8 ) & 0xFF, + ip & 0xFF + ); +} + +/* + * Converts a dotted format String IP to a long. + * + * @param ip IP String + * @return Long IP + */ +stock int IPToLong(const char[] ip) +{ + char pieces[4][4]; + + if (ExplodeString(ip, ".", pieces, sizeof(pieces), sizeof(pieces[])) != 4) { + return 0; + } + + return ( + StringToInt(pieces[0]) << 24 | + StringToInt(pieces[1]) << 16 | + StringToInt(pieces[2]) << 8 | + StringToInt(pieces[3]) + ); +} + +static int localIPRanges[] = +{ + 10 << 24, // 10. + 127 << 24 | 1 , // 127.0.0.1 + 127 << 24 | 16 << 16, // 127.16. + 192 << 24 | 168 << 16, // 192.168. +}; + +/* + * Checks whether an IP is a private/internal IP + * + * @param ip IP Long + * @return True if the IP is local, false otherwise. + */ +stock bool IsIPLocal(int ip) +{ + int range, bits, move; + bool matches; + + for (int i=0; i < sizeof(localIPRanges); i++) { + + range = localIPRanges[i]; + matches = true; + + for (int j=0; j < 4; j++) { + move = j * 8; + bits = (range >> move) & 0xFF; + + if (bits && bits != ((ip >> move) & 0xFF)) { + matches = false; + } + } + + if (matches) { + return true; + } + } + + return false; +} + +/* + * Closes the given hindle and sets it to INVALID_HANDLE. + * Obsolete now. Just use |delete handle|. + * + * @param handle handle + */ +stock void ClearHandle(Handle &handle) +{ + if (handle != INVALID_HANDLE) { + CloseHandle(handle); + handle = INVALID_HANDLE; + } +} diff --git a/source/sourcemod/scripting/include/smlib/math.inc b/source/sourcemod/scripting/include/smlib/math.inc new file mode 100644 index 0000000..2e584fb --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/math.inc @@ -0,0 +1,346 @@ +#if defined _smlib_math_included + #endinput +#endif +#define _smlib_math_included + +#include + +#define SIZE_OF_INT 2147483647 // without 0 +#define INT_MAX_DIGITS 10 + +#define GAMEUNITS_TO_METERS 0.01905 +#define METERS_TO_GAMEUNITS 52.49343832020997 +#define METERS_TO_FEET 3.2808399 +#define FEET_TO_METERS 0.3048 +#define KILOMETERS_TO_MILES 0.62137 + +enum VecAngle +{ + ANG_ALPHA, + ANG_BETA, + ANG_GAMMA +}; + +/** + * Makes a negative integer number to a positive integer number. + * This is faster than Sourcemod's native FloatAbs() for integers. + * Use FloatAbs() for Float numbers. + * + * @param number A number that can be positive or negative. + * @return Positive number. + */ +stock int Math_Abs(int value) +{ + return (value ^ (value >> 31)) - (value >> 31); +} + +/** + * Checks if 2 vectors are equal. + * You can specfiy a tolerance, which is the maximum distance at which vectors are considered equals + * + * @param vec1 First vector (3 dim array) + * @param vec2 Second vector (3 dim array) + * @param tolerance If you want to check that those vectors are somewhat even. 0.0 means they are 100% even if this function returns true. + * @return True if vectors are equal, false otherwise. + */ +stock bool Math_VectorsEqual(float vec1[3], float vec2[3], float tolerance=0.0) +{ + float distance = GetVectorDistance(vec1, vec2, true); + + return distance <= (tolerance * tolerance); +} + +/** + * Sets the given value to min + * if the value is smaller than the given. + * Don't use this with float values. + * + * @param value Value + * @param min Min Value used as lower border + * @return Correct value not lower than min + */ +stock any Math_Min(any value, any min) +{ + if (value < min) { + value = min; + } + + return value; +} + +/** + * Sets the given value to max + * if the value is greater than the given. + * Don't use this with float values. + * + * @param value Value + * @param max Max Value used as upper border + * @return Correct value not upper than max + */ +stock any Math_Max(any value, any max) +{ + if (value > max) { + value = max; + } + + return value; +} + +/** + * Makes sure a value is within a certain range and + * returns the value. + * If the value is outside the range it is set to either + * min or max, if it is inside the range it will just return + * the specified value. + * Don't use this with float values. + * + * @param value Value + * @param min Min value used as lower border + * @param max Max value used as upper border + * @return Correct value not lower than min and not greater than max. + */ +stock any Math_Clamp(any value, any min, any max) +{ + value = Math_Min(value, min); + value = Math_Max(value, max); + + return value; +} + +/* + * Checks if the value is within the given bounds (min & max). + * Don't use this with float values. + * + * @param value The value you want to check. + * @param min The lower border. + * @param max The upper border. + * @return True if the value is within bounds (bigger or equal min / smaller or equal max), false otherwise. + */ +stock bool Math_IsInBounds(any value, any min, any max) +{ + if (value < min || value > max) { + return false; + } + + return true; +} + +/** + * Let's the specified value "overflow" if it is outside the given limit. + * This is like with integers when it reaches a value above the max possible + * integer size. + * Don't use this with float values. + * + * @param value Value + * @param min Min value used as lower border + * @param max Max value used as upper border + * @return Overflowed number + */ +stock any Math_Overflow(any value, any min, any max) +{ + return (value % max) + min; +} + +/** + * Returns a random, uniform Integer number in the specified (inclusive) range. + * This is safe to use multiple times in a function. + * The seed is set automatically for each plugin. + * Rewritten by MatthiasVance, thanks. + * + * @param min Min value used as lower border + * @param max Max value used as upper border + * @return Random Integer number between min and max + */ +stock int Math_GetRandomInt(int min, int max) +{ + int random = GetURandomInt(); + + if (random == 0) { + random++; + } + + return RoundToCeil(float(random) / (float(SIZE_OF_INT) / float(max - min + 1))) + min - 1; +} + +/** + * Returns a random, uniform Float number in the specified (inclusive) range. + * This is safe to use multiple times in a function. + * The seed is set automatically for each plugin. + * + * @param min Min value used as lower border + * @param max Max value used as upper border + * @return Random Float number between min and max + */ +stock float Math_GetRandomFloat(float min, float max) +{ + return (GetURandomFloat() * (max - min)) + min; +} + +/** + * Gets the percentage of amount in all as Integer where + * amount and all are numbers and amount usually + * is a subset of all. + * + * @param value Integer value + * @param all Integer value + * @return An Integer value between 0 and 100 (inclusive). + */ +stock int Math_GetPercentage(int value, int all) { + return RoundToNearest((float(value) / float(all)) * 100.0); +} + +/** + * Gets the percentage of amount in all as Float where + * amount and all are numbers and amount usually + * is a subset of all. + * + * @param value Float value + * @param all Float value + * @return A Float value between 0.0 and 100.0 (inclusive). + */ +stock float Math_GetPercentageFloat(float value, float all) { + return (value / all) * 100.0; +} + +/* + * Moves the start vector on a direct line to the end vector by the given scale. + * Note: If scale is 0.0 the output will be the same as the start vector and if scale is 1.0 the output vector will be the same as the end vector. + * Exmaple usage: Move an entity to another entity but only 12 units: Vector_MoveVector(entity1Origin,entity2Origin,(12.0 / GetVectorDistance(entity1Origin,entity2Origin)),newEntity1Origin); now only teleport your entity to newEntity1Origin. + * + * @param start The start vector where the imagined line starts. + * @param end The end vector where the imagined line ends. + * @param scale The position on the line 0.0 is the start 1.0 is the end. + * @param output Output vector + */ +stock void Math_MoveVector(const float start[3], const float end[3], float scale, float output[3]) +{ + SubtractVectors(end,start,output); + ScaleVector(output,scale); + AddVectors(start,output,output); +} + +/** + * Puts x, y and z into a vector. + * + * @param x Float value. + * @param y Float value. + * @param z Float value. + * @param result Output vector. + */ +stock void Math_MakeVector(float x, float y, float z, float result[3]) +{ + result[0] = x; + result[1] = y; + result[2] = z; +} + +/** + * Rotates a vector around its zero-point. + * Note: As example you can rotate mins and maxs of an entity and then add its origin to mins and maxs to get its bounding box in relation to the world and its rotation. + * When used with players use the following angle input: + * angles[0] = 0.0; + * angles[1] = 0.0; + * angles[2] = playerEyeAngles[1]; + * + * @param vec Vector to rotate. + * @param angles How to rotate the vector. + * @param result Output vector. + */ +stock void Math_RotateVector(const float vec[3], const float angles[3], float result[3]) +{ + // First the angle/radiant calculations + float rad[3]; + // I don't really know why, but the alpha, beta, gamma order of the angles are messed up... + // 2 = xAxis + // 0 = yAxis + // 1 = zAxis + rad[0] = DegToRad(angles[2]); + rad[1] = DegToRad(angles[0]); + rad[2] = DegToRad(angles[1]); + + // Pre-calc function calls + float cosAlpha = Cosine(rad[0]); + float sinAlpha = Sine(rad[0]); + float cosBeta = Cosine(rad[1]); + float sinBeta = Sine(rad[1]); + float cosGamma = Cosine(rad[2]); + float sinGamma = Sine(rad[2]); + + // 3D rotation matrix for more information: http://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions + float x = vec[0], y = vec[1], z = vec[2]; + float newX, newY, newZ; + newY = cosAlpha*y - sinAlpha*z; + newZ = cosAlpha*z + sinAlpha*y; + y = newY; + z = newZ; + + newX = cosBeta*x + sinBeta*z; + newZ = cosBeta*z - sinBeta*x; + x = newX; + z = newZ; + + newX = cosGamma*x - sinGamma*y; + newY = cosGamma*y + sinGamma*x; + x = newX; + y = newY; + + // Store everything... + result[0] = x; + result[1] = y; + result[2] = z; +} + +/** + * Converts Source Game Units to metric Meters + * + * @param units Float value + * @return Meters as Float value. + */ +stock float Math_UnitsToMeters(float units) +{ + return (units * GAMEUNITS_TO_METERS); +} + +/** + * Converts Source Game Units to Meters + * + * @param units Float value + * @return Feet as Float value. + */ +stock float Math_UnitsToFeet(float units) +{ + return (Math_UnitsToMeters(units) * METERS_TO_FEET); +} + +/** + * Converts Source Game Units to Centimeters + * + * @param units Float value + * @return Centimeters as Float value. + */ +stock float Math_UnitsToCentimeters(float units) +{ + return (Math_UnitsToMeters(units) * 100.0); +} + +/** + * Converts Source Game Units to Kilometers + * + * @param units Float value + * @return Kilometers as Float value. + */ +stock float Math_UnitsToKilometers(float units) +{ + return (Math_UnitsToMeters(units) / 1000.0); +} + +/** + * Converts Source Game Units to Miles + * + * @param units Float value + * @return Miles as Float value. + */ +stock float Math_UnitsToMiles(float units) +{ + return (Math_UnitsToKilometers(units) * KILOMETERS_TO_MILES); +} diff --git a/source/sourcemod/scripting/include/smlib/menus.inc b/source/sourcemod/scripting/include/smlib/menus.inc new file mode 100644 index 0000000..87f253e --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/menus.inc @@ -0,0 +1,37 @@ +#if defined _smlib_menus_included + #endinput +#endif +#define _smlib_menus_included + +#include +#include + +/** + * Adds an option to a menu with a String display but an integer + * identifying the option. + * + * @param menu Handle to the menu + * @param value Integer value for the option + * @param display Display text for the menu + */ +stock void Menu_AddIntItem(Menu menu, any value, char[] display) +{ + char buffer[INT_MAX_DIGITS + 1]; + IntToString(value, buffer, sizeof(buffer)); + menu.AddItem(buffer, display); +} + +/** + * Retrieves an integer-value choice from a menu, where the + * menu's information strings were created as integers. + * + * @param menu Handle to the menu + * @param param2 The item position selected from the menu. + * @return Integer choice from the menu, or 0 if the integer could not be parsed. + */ +stock any Menu_GetIntItem(Menu menu, any param2) +{ + char buffer[INT_MAX_DIGITS + 1]; + menu.GetItem(param2, buffer, sizeof(buffer)); + return StringToInt(buffer); +} diff --git a/source/sourcemod/scripting/include/smlib/server.inc b/source/sourcemod/scripting/include/smlib/server.inc new file mode 100644 index 0000000..ae54cc4 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/server.inc @@ -0,0 +1,135 @@ +#if defined _smlib_server_included + #endinput +#endif +#define _smlib_server_included + +#include +#include + +/* + * Gets the server's public/external (default) or + * private/local (usually server's behind a NAT) IP. + * If your server is behind a NAT Router, you need the SteamTools + * extension available at http://forums.alliedmods.net/showthread.php?t=129763 + * to get the public IP. has to be included BEFORE . + * If the server is not behind NAT, the public IP is the same as the private IP. + * + * @param public Set to true to retrieve the server's public/external IP, false otherwise. + * @return Long IP or 0 if the IP couldn't be retrieved. + */ +stock int Server_GetIP(bool public_=true) +{ + int ip = 0; + + static ConVar cvHostip = null; + + if (cvHostip == INVALID_HANDLE) { + cvHostip = FindConVar("hostip"); + MarkNativeAsOptional("Steam_GetPublicIP"); + } + + if (cvHostip != INVALID_HANDLE) { + ip = cvHostip.IntValue; + } + + if (ip != 0 && IsIPLocal(ip) == public_) { + ip = 0; + } + +#if defined _steamtools_included + if (ip == 0) { + if (CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "Steam_GetPublicIP") == FeatureStatus_Available) { + int octets[4]; + Steam_GetPublicIP(octets); + + ip = + octets[0] << 24 | + octets[1] << 16 | + octets[2] << 8 | + octets[3]; + + if (IsIPLocal(ip) == public_) { + ip = 0; + } + } + } +#endif + + return ip; +} + +/* + * Gets the server's public/external (default) or + * private/local (usually server's behind a NAT) as IP String in dotted format. + * If your server is behind a NAT Router, you need the SteamTools + * extension available at http://forums.alliedmods.net/showthread.php?t=129763 + * to get the public IP. has to be included BEFORE . + * If the public IP couldn't be found, an empty String is returned. + * If the server is not behind NAT, the public IP is the same as the private IP. + * + * @param buffer String buffer (size=16) + * @param size String buffer size. + * @param public Set to true to retrieve the server's public/external IP, false otherwise. + * @return True on success, false otherwise. + */ +stock bool Server_GetIPString(char[] buffer, int size, bool public_=true) +{ + int ip; + + if ((ip = Server_GetIP(public_)) == 0) { + buffer[0] = '\0'; + return false; + } + + LongToIP(ip, buffer, size); + + return true; +} + +/* + * Gets the server's local port. + * + * @noparam + * @return The server's port, 0 if there is no port. + */ +stock int Server_GetPort() +{ + static ConVar cvHostport = null; + + if (cvHostport == INVALID_HANDLE) { + cvHostport = FindConVar("hostport"); + } + + if (cvHostport == INVALID_HANDLE) { + return 0; + } + + int port = cvHostport.IntValue; + + return port; +} + +/* + * Gets the server's hostname + * + * @param hostname String buffer + * @param size String buffer size + * @return True on success, false otherwise. + */ +stock bool Server_GetHostName(char[] buffer, int size) +{ + static ConVar cvHostname = null; + + if (cvHostname == INVALID_HANDLE) { + cvHostname = FindConVar("hostname"); + } + + if (cvHostname == INVALID_HANDLE) { + buffer[0] = '\0'; + return false; + } + + cvHostname.GetString(buffer, size); + + return true; +} diff --git a/source/sourcemod/scripting/include/smlib/sql.inc b/source/sourcemod/scripting/include/smlib/sql.inc new file mode 100644 index 0000000..e291cfa --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/sql.inc @@ -0,0 +1,107 @@ +#if defined _smlib_sql_included + #endinput +#endif +#define _smlib_sql_included + +#include +#include + +/** + * Executes a threaded SQL Query (See: SQL_TQuery) + * This function supports the printf Syntax. + * + * + * @param database A database Handle. + * @param callback Callback; database is in "owner" and the query Handle is passed in "hndl". + * @param data Extra data value to pass to the callback. + * @param format Query string, printf syntax supported + * @param priority Priority queue to use + * @param ... Variable number of format parameters. + */ +stock void SQL_TQueryF(Database database, SQLTCallback callback, any data, DBPriority priority=DBPrio_Normal, const char[] format, any ...) { + + if (!database) { + ThrowError("[SMLIB] Error: Invalid database handle."); + return; + } + + char query[16384]; + VFormat(query, sizeof(query), format, 6); + + SQL_TQuery(database, callback, query, data, priority); +} + +/** + * Fetches an integer from a field in the current row of a result set (See: SQL_FetchInt) + * + * @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. + */ +stock int SQL_FetchIntByName(DBResultSet query, const char[] fieldName, DBResult &result=DBVal_Error) { + + int fieldNum; + SQL_FieldNameToNum(query, fieldName, fieldNum); + + return SQL_FetchInt(query, fieldNum, result); +} + +/** + * Fetches a bool from a field in the current row of a result set (See: SQL_FetchInt) + * + * @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 bool value. + * @error Invalid query Handle or field index, invalid + * type conversion requested from the database, + * or no current result set. + */ +stock bool SQL_FetchBoolByName(DBResultSet query, const char[] fieldName, DBResult &result=DBVal_Error) { + + return SQL_FetchIntByName(query, fieldName, result) != 0; +} + +/** + * Fetches a float from a field in the current row of a result set. (See: SQL_FetchFloat) + * + * @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. + */ +stock float SQL_FetchFloatByName(DBResultSet query, const char[] fieldName, DBResult &result=DBVal_Error) { + + int fieldNum; + SQL_FieldNameToNum(query, fieldName, fieldNum); + + return SQL_FetchFloat(query, fieldNum, result); +} + +/** + * Fetches a string from a field in the current row of a result set. (See: SQL_FetchString) + * + * @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. + */ +stock int SQL_FetchStringByName(DBResultSet query, const char[] fieldName, char[] buffer, int maxlength, DBResult &result=DBVal_Error) { + + int fieldNum; + SQL_FieldNameToNum(query, fieldName, fieldNum); + + return SQL_FetchString(query, fieldNum, buffer, maxlength, result); +} diff --git a/source/sourcemod/scripting/include/smlib/strings.inc b/source/sourcemod/scripting/include/smlib/strings.inc new file mode 100644 index 0000000..b7cf9b4 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/strings.inc @@ -0,0 +1,228 @@ +#if defined _smlib_strings_included + #endinput +#endif +#define _smlib_strings_included + +#include +#include + +/** + * Checks if the string is numeric. + * This correctly handles + - . in the String. + * + * @param str String to check. + * @return True if the String is numeric, false otherwise.. + */ +stock bool String_IsNumeric(const char[] str) +{ + int x=0; + int dotsFound=0; + int numbersFound=0; + + if (str[x] == '+' || str[x] == '-') { + x++; + } + + while (str[x] != '\0') { + + if (IsCharNumeric(str[x])) { + numbersFound++; + } + else if (str[x] == '.') { + dotsFound++; + + if (dotsFound > 1) { + return false; + } + } + else { + return false; + } + + x++; + } + + if (!numbersFound) { + return false; + } + + return true; +} + +/** + * Trims a string by removing the specified chars from beginning and ending. + * Removes all ' ', '\t', '\r', '\n' characters by default. + * The Output String can be the same as the Input String. + * + * @param str Input String. + * @param output Output String (Can be the as the input). + * @param size Size of the output String. + * @param chars Characters to remove. + */ +stock void String_Trim(const char[] str, char[] output, int size, const char[] chrs=" \t\r\n") +{ + int x=0; + while (str[x] != '\0' && FindCharInString(chrs, str[x]) != -1) { + x++; + } + + x = strcopy(output, size, str[x]); + x--; + + while (x >= 0 && FindCharInString(chrs, output[x]) != -1) { + x--; + } + + output[++x] = '\0'; +} + +/** + * Removes a list of strings from a string. + * + * @param buffer Input/Output buffer. + * @param removeList A list of strings which should be removed from buffer. + * @param size Number of Strings in the List. + * @param caseSensitive If true, comparison is case sensitive. If false (default), comparison is case insensitive. + */ +stock void String_RemoveList(char[] buffer, const char[][] removeList, int size, bool caseSensitive=false) +{ + for (int i=0; i < size; i++) { + ReplaceString(buffer, SIZE_OF_INT, removeList[i], "", caseSensitive); + } +} + +/** + * Converts the whole String to lower case. + * Only works with alphabetical characters (not ÖÄÜ) because Sourcemod suxx ! + * The Output String can be the same as the Input String. + * + * @param input Input String. + * @param output Output String. + * @param size Max Size of the Output string + */ +stock void String_ToLower(const char[] input, char[] output, int size) +{ + size--; + + int x=0; + while (input[x] != '\0' && x < size) { + + output[x] = CharToLower(input[x]); + + x++; + } + + output[x] = '\0'; +} + +/** + * Converts the whole String to upper case. + * Only works with alphabetical characters (not öäü) because Sourcemod suxx ! + * The Output String can be the same as the Input String. + * + * @param input Input String. + * @param output Output String. + * @param size Max Size of the Output string + */ +stock void String_ToUpper(const char[] input, char[] output, int size) +{ + size--; + + int x=0; + while (input[x] != '\0' && x < size) { + + output[x] = CharToUpper(input[x]); + + x++; + } + + output[x] = '\0'; +} + +/** + * Generates a random string. + * + * + * @param buffer String Buffer. + * @param size String Buffer size (must be length+1) + * @param length Number of characters being generated. + * @param chrs String for specifying the characters used for random character generation. + * By default it will use all letters of the alphabet (upper and lower) and all numbers. + * If you pass an empty String, it will use all readable ASCII characters (33 - 126) + */ +stock void String_GetRandom(char[] buffer, int size, int length=32, const char[] chrs="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234556789") +{ + int random, len; + size--; + + if (chrs[0] != '\0') { + len = strlen(chrs) - 1; + } + + int n = 0; + while (n < length && n < size) { + + if (chrs[0] == '\0') { + random = Math_GetRandomInt(33, 126); + buffer[n] = random; + } + else { + random = Math_GetRandomInt(0, len); + buffer[n] = chrs[random]; + } + + n++; + } + + buffer[length] = '\0'; +} + +/** + * Checks if string str starts with subString. + * + * + * @param str String to check + * @param subString Sub-String to check in str + * @return True if str starts with subString, false otherwise. + */ +stock bool String_StartsWith(const char[] str, const char[] subString) +{ + int n = 0; + while (subString[n] != '\0') { + + if (str[n] == '\0' || str[n] != subString[n]) { + return false; + } + + n++; + } + + return true; +} + +/** + * Checks if string str ends with subString. + * + * + * @param str String to check + * @param subString Sub-String to check in str + * @return True if str ends with subString, false otherwise. + */ +stock bool String_EndsWith(const char[] str, const char[] subString) +{ + int n_str = strlen(str) - 1; + int n_subString = strlen(subString) - 1; + + if(n_str < n_subString) { + return false; + } + + while (n_str != 0 && n_subString != 0) { + + if (str[n_str--] != subString[n_subString--]) { + return false; + } + } + + return true; +} diff --git a/source/sourcemod/scripting/include/smlib/teams.inc b/source/sourcemod/scripting/include/smlib/teams.inc new file mode 100644 index 0000000..621c8b1 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/teams.inc @@ -0,0 +1,317 @@ +#if defined _smlib_teams_included + #endinput +#endif +#define _smlib_teams_included + +#include +#include +#include + +#define MAX_TEAMS 32 // Max number of teams in a game +#define MAX_TEAM_NAME_LENGTH 32 // Max length of a team's name + +// Team Defines +#define TEAM_INVALID -1 +#define TEAM_UNASSIGNED 0 +#define TEAM_SPECTATOR 1 +#define TEAM_ONE 2 +#define TEAM_TWO 3 +#define TEAM_THREE 4 +#define TEAM_FOUR 5 + +/* + * If one team is empty its assumed single team mode is enabled and the game won't start. + * + * @noparam + * @return True if one team is empty, false otherwise. + */ +stock bool Team_HaveAllPlayers(bool countFakeClients=true) { + + int teamCount = GetTeamCount(); + for (int i=2; i < teamCount; i++) { + + if (Team_GetClientCount(i, ((countFakeClients) ? CLIENTFILTER_ALL : CLIENTFILTER_NOBOTS)) == 0) { + return false; + } + } + + return true; +} + +/* + * Returns the client count of the players in a team. + * + * @param team Team Index. + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return Client count in the server. + */ +stock int Team_GetClientCount(int team, int flags=0) +{ + flags |= CLIENTFILTER_INGAME; + + int numClients = 0; + for (int client=1; client <= MaxClients; client++) { + + if (!Client_MatchesFilter(client, flags)) { + continue; + } + + if (GetClientTeam(client) == team) { + numClients++; + } + } + + return numClients; +} + +/* + * Returns the client counts of the first two teams (eg.: Terrorists - Counter). + * Use this function for optimization if you have to get the counts of both teams, + * otherwise use Team_GetClientCount(). + * + * @param team1 Pass an integer variable by reference + * @param team2 Pass an integer variable by reference + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + */ +stock void Team_GetClientCounts(int &team1=0, int &team2=0, int flags=0) +{ + flags |= CLIENTFILTER_INGAME; + + for (int client=1; client <= MaxClients; client++) { + + if (!Client_MatchesFilter(client, flags)) { + continue; + } + + if (GetClientTeam(client) == TEAM_ONE) { + team1++; + } + else if (GetClientTeam(client) == TEAM_TWO) { + team2++; + } + } +} + +/* + * Gets the name of a team. + * Don't call this before OnMapStart() + * + * @param index Team Index. + * @param str String buffer + * @param size String Buffer Size + * @return True on success, false otherwise + */ +stock bool Team_GetName(int index, char[] str, int size) +{ + int edict = Team_GetEdict(index); + + if (edict == -1) { + str[0] = '\0'; + return false; + } + + GetEntPropString(edict, Prop_Send, "m_szTeamname", str, size); + + return true; +} + +/* + * Changes a team's name. + * Use this carefully ! + * Only set the teamname OnMapStart() or OnEntityCreated() + * when no players are ingame, otherwise it can crash the server. + * + * @param index Team Index. + * @param name New Name String + * @return True on success, false otherwise + */ +stock bool Team_SetName(int index, const char[] name) +{ + int edict = Team_GetEdict(index); + + if (edict == -1) { + return false; + } + + SetEntPropString(edict, Prop_Send, "m_szTeamname", name); + ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_szTeamname", true)); + + return true; +} + +/* + * Changes a team's score. + * Don't use this before OnMapStart(). + * + * @param index Team Index. + * @return Team Score or -1 if the team is not valid. + */ +stock int Team_GetScore(int index) +{ + int edict = Team_GetEdict(index); + + if (edict == -1) { + return -1; + } + + return GetEntProp(edict, Prop_Send, "m_iScore"); +} + +/* + * Changes a team's score. + * Don't use this before OnMapStart(). + * + * @param index Team Index. + * @param score Score value. + * @return True on success, false otherwise + */ +stock bool Team_SetScore(int index, int score) +{ + int edict = Team_GetEdict(index); + + if (edict == -1) { + return false; + } + + SetEntProp(edict, Prop_Send, "m_iScore", score); + + ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_iScore", true)); + + return true; +} + +/* + * Gets a team's edict (*team_manager) Team Index. + * Don't call this before OnMapStart() + * + * @param edict Edict + * @return Team Index + */ +stock int Team_EdictGetNum(int edict) +{ + return GetEntProp(edict, Prop_Send, "m_iTeamNum"); +} + +/* + * Check's whether the index is a valid team index or not. + * Don't call this before OnMapStart() + * + * @param index Index. + * @return True if the Index is a valid team, false otherwise. + */ +stock bool Team_IsValid(int index) +{ + return (Team_GetEdict(index) != -1); +} + +/* + * Gets a team's edict (team_manager) Team Index. + * Don't call this before OnMapStart() + * + * @param index Edict + * @return Team Index + */ +stock int Team_EdictIsValid(int edict) +{ + return GetEntProp(edict, Prop_Send, "m_iTeamNum"); +} + +/* + * Gets a team's edict (team_manager). + * This function caches found team edicts. + * Don't call this before OnMapStart() + * + * @param index Team Index. + * @return Team edict or -1 if not found + */ +stock int Team_GetEdict(int index) +{ + static int teams[MAX_TEAMS] = { INVALID_ENT_REFERENCE, ... }; + + if (index < 0 || index > MAX_TEAMS) { + return -1; + } + + int edict = teams[index]; + if (Entity_IsValid(edict)) { + return edict; + } + + bool foundTeamManager = false; + + int maxEntities = GetMaxEntities(); + for (int entity=MaxClients+1; entity < maxEntities; entity++) { + + if (!IsValidEntity(entity)) { + continue; + } + + if (Entity_ClassNameMatches(entity, "team_manager", true)) { + foundTeamManager = true; + } + // Do not continue when no team managers are found anymore (for optimization) + else if (foundTeamManager) { + return -1; + } + else { + continue; + } + + int num = Team_EdictGetNum(entity); + + if (num >= 0 && num <= MAX_TEAMS) { + teams[num] = EntIndexToEntRef(entity); + } + + if (num == index) { + return entity; + } + } + + return -1; +} + +/* + * Trys to find a client in the specified team. + * This function is NOT random, it returns the first + * or the cached player (Use Client_GetRandom() instead). + * + * @param index Team Index. + * @return Client Index or -1 if no client was found in the specified team. + */ +stock int Team_GetAnyClient(int index) +{ + static int client_cache[MAX_TEAMS] = {-1, ...}; + int client; + + if (index > 0) { + client = client_cache[index]; + + if (client > 0 && client <= MaxClients) { + + if (IsClientInGame(client) && GetClientTeam(client) == index) { + return client; + } + } + else { + client = -1; + } + } + + for (client=1; client <= MaxClients; client++) { + + if (!IsClientInGame(client)) { + continue; + } + + if (GetClientTeam(client) != index) { + continue; + } + + client_cache[index] = client; + + return client; + } + + return -1; +} diff --git a/source/sourcemod/scripting/include/smlib/vehicles.inc b/source/sourcemod/scripting/include/smlib/vehicles.inc new file mode 100644 index 0000000..61006fe --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/vehicles.inc @@ -0,0 +1,137 @@ +#if defined _smlib_vehicles_included + #endinput +#endif +#define _smlib_vehicles_included + +#include +#include +#include +#include + +/** + * Returns the vehicle's driver. + * If there is no driver in the vehicle, -1 is returned. + * + * @param vehicle Entity index. + * @return Client index, or -1 if there is no driver. + */ +stock int Vehicle_GetDriver(int vehicle) +{ + int m_hVehicle = GetEntPropEnt(vehicle, Prop_Send, "m_hPlayer"); + + return m_hVehicle; +} + +/** + * Returns whether there is a driver in the vehicle or not. + * + * @param vehicle Entity index. + * @return True if the vehicle has a driver, false otherwise + */ +stock bool Vehicle_HasDriver(int vehicle) +{ + return Vehicle_GetDriver(vehicle) != -1; +} + +/** + * Kicks the driver ouf of the vehicle + * + * @param vehicle Entity index. + * @return True on success, false otherwise. + */ +stock bool Vehicle_ExitDriver(int vehicle) +{ + if (!Vehicle_HasDriver(vehicle)) { + return false; + } + + return AcceptEntityInput(vehicle, "ExitVehicle"); +} + +/** + * Start's the vehicle's engine + * + * @param vehicle Entity index. + * @return True on success, false otherwise. + */ +stock bool Vehicle_TurnOn(int vehicle) +{ + return AcceptEntityInput(vehicle, "TurnOn"); +} + +/** + * Shuts down the vehicle's engine + * + * @param vehicle Entity index. + * @return True on success, false otherwise. + */ +stock bool Vehicle_TurnOff(int vehicle) +{ + return AcceptEntityInput(vehicle, "TurnOff"); +} + +/** + * Locks the vehicle. + * + * @param vehicle Entity index. + * @return True on success, false otherwise. + */ +stock bool Vehicle_Lock(int vehicle) +{ + return AcceptEntityInput(vehicle, "Lock"); +} + +/** + * Unlocks the vehicle. + * + * @param vehicle Entity index. + * @return True on success, false otherwise. + */ +stock bool Vehicle_Unlock(int vehicle) +{ + return AcceptEntityInput(vehicle, "Unlock"); +} + +/** + * Returns wether the entity is a valid vehicle or not. + * + * @param vehicle Entity index. + * @return True if it is a valid vehicle, false otherwise. + */ +stock bool Vehicle_IsValid(int vehicle) +{ + if (!Entity_IsValid(vehicle)) { + return false; + } + + return Entity_ClassNameMatches(vehicle, "prop_vehicle", true); +} + +/** + * Reads the vehicle script from a vehicle. + * This script contains all the vehicle settings like its speed + * and that stuff. + * + * @param vehicle Entity index. + * @param buffer String Buffer. + * @param size String Buffer size. + * @noreturn + */ +stock void Vehicle_GetScript(int vehicle, char[] buffer, int size) +{ + GetEntPropString(vehicle, Prop_Data, "m_vehicleScript", buffer, size); +} + +/** + * Sets the script of a vehicle. + * This script contains all the vehicle settings like its speed + * and that stuff. + * + * @param vehicle Entity index. + * @param buffer Vehicle Script path. + * @noreturn + */ +stock void Vehicle_SetScript(int vehicle, char[] script) +{ + DispatchKeyValue(vehicle, "vehiclescript", script); +} diff --git a/source/sourcemod/scripting/include/smlib/weapons.inc b/source/sourcemod/scripting/include/smlib/weapons.inc new file mode 100644 index 0000000..417053e --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/weapons.inc @@ -0,0 +1,393 @@ +#if defined _smlib_weapons_included + #endinput +#endif +#define _smlib_weapons_included + +#include +#include +#include + +#define MAX_WEAPON_OFFSET 64 +#define MAX_WEAPON_SLOTS 6 // hud item selection slots +#define MAX_WEAPON_POSITIONS 20 // max number of items within a slot +#define MAX_WEAPONS 48 // Max number of weapons availabl +#define WEAPON_NOCLIP -1 // clip sizes set to this tell the weapon it doesn't use a clip +#define MAX_AMMO_TYPES 32 +#define MAX_AMMO_SLOTS 32 // not really slots + +#define MAX_WEAPON_STRING 80 +#define MAX_WEAPON_PREFIX 16 +#define MAX_WEAPON_AMMO_NAME 32 + +/* + * Gets the owner (usually a client) of the weapon + * + * @param weapon Weapon Entity. + * @return Owner of the weapon or INVALID_ENT_REFERENCE if the weapon has no owner. + */ +stock int Weapon_GetOwner(int weapon) +{ + return GetEntPropEnt(weapon, Prop_Data, "m_hOwner"); +} + +/* + * Sets the owner (usually a client) of the weapon + * + * @param weapon Weapon Entity. + * @param entity Entity Index. + * @noreturn + */ +stock void Weapon_SetOwner(int weapon, int entity) +{ + SetEntPropEnt(weapon, Prop_Data, "m_hOwner", entity); +} + +/* + * Checks whether the entity is a valid weapon or not. + * + * @param weapon Weapon Entity. + * @return True if the entity is a valid weapon, false otherwise. + */ +stock bool Weapon_IsValid(int weapon) +{ + if (!IsValidEdict(weapon)) { + return false; + } + + return Entity_ClassNameMatches(weapon, "weapon_", true); +} + +/* + * Create's a weapon and spawns it in the world at the specified location. + * + * @param className Classname String of the weapon to spawn + * @param absOrigin Absolute Origin Vector where to spawn the weapon. + * @param absAngles Absolute Angles Vector. + * @return Weapon Index of the created weapon or INVALID_ENT_REFERENCE on error. + */ +stock int Weapon_Create(const char[] className, float absOrigin[3], float absAngles[3]) +{ + int weapon = Entity_Create(className); + + if (weapon == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + + Entity_SetAbsOrigin(weapon, absOrigin); + Entity_SetAbsAngles(weapon, absAngles); + + DispatchSpawn(weapon); + + return weapon; +} + +/* + * Create's a weapon and spawns it in the world at the specified location. + * + * @param className Classname String of the weapon to spawn + * @param absOrigin Absolute Origin Vector where to spawn the weapon. + * @param absAngles Absolute Angles Vector. + * @return Weapon Index of the created weapon or INVALID_ENT_REFERENCE on error. + */ +stock int Weapon_CreateForOwner(int client, const char[] className) +{ + float absOrigin[3], absAngles[3]; + Entity_GetAbsOrigin(client, absOrigin); + Entity_GetAbsAngles(client, absAngles); + + int weapon = Weapon_Create(className, absOrigin, absAngles); + + if (weapon == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + + Entity_SetOwner(weapon, client); + + return weapon; +} + +/* + * Gets the weapon's subtype. + * The subtype is only used when a player has multiple weapons of the same type. + * + * @param weapon Weapon Entity. + * @return Subtype of the weapon. + */ +stock int Weapon_GetSubType(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iSubType"); +} + +/* + * Is the weapon currently reloading ? + * + * @param weapon Weapon Entity. + * @return True if weapon is currently reloading, false if not. + */ +stock bool Weapon_IsReloading(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_bInReload") != 0; +} + +/* + * Weapon m_iState + */ +#define WEAPON_IS_ONTARGET 0x40 +#define WEAPON_NOT_CARRIED 0 // Weapon is on the ground +#define WEAPON_IS_CARRIED_BY_PLAYER 1 // This client is carrying this weapon. +#define WEAPON_IS_ACTIVE 2 // This client is carrying this weapon and it's the currently held weapon + +/* + * Get's the state of the weapon. + * This returns whether the weapon is currently carried by a client, + * if it is active and if it is on a target. + * + * @param weapon Weapon Entity. + * @return Weapon State. + */ +stock int Weapon_GetState(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iState"); +} + +/* + * Returns whether the weapon can fire primary ammo under water. + * + * @param weapon Weapon Entity. + * @return True or False. + */ +stock bool Weapon_FiresUnderWater(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_bFiresUnderwater") != 0; +} + +/* + * Sets if the weapon can fire primary ammo under water. + * + * @param weapon Weapon Entity. + * @param can True or False. + */ +stock void Weapon_SetFiresUnderWater(int weapon, bool can=true) +{ + SetEntProp(weapon, Prop_Data, "m_bFiresUnderwater", can); +} + +/* + * Returns whether the weapon can fire secondary ammo under water. + * + * @param weapon Weapon Entity. + * @return True or False. + */ +stock bool Weapon_FiresUnderWaterAlt(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_bAltFiresUnderwater") != 0; +} + +/* + * Sets if the weapon can fire secondary ammo under water. + * + * @param weapon Weapon Entity. + * @param can True or False. + */ +stock void Weapon_SetFiresUnderWaterAlt(int weapon, bool can=true) +{ + SetEntProp(weapon, Prop_Data, "m_bAltFiresUnderwater", can); +} + +/* + * Gets the primary ammo Type (int offset) + * + * @param weapon Weapon Entity. + * @return Primary ammo type value. + */ +stock int Weapon_GetPrimaryAmmoType(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType"); +} + +/* + * Sets the primary ammo Type (int offset) + * + * @param weapon Weapon Entity. + * @param type Primary ammo type value. + */ +stock void Weapon_SetPrimaryAmmoType(int weapon, int type) +{ + SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType", type); +} + +/* + * Gets the secondary ammo Type (int offset) + * + * @param weapon Weapon Entity. + * @return Secondary ammo type value. + */ +stock int Weapon_GetSecondaryAmmoType(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType"); +} + +/* + * Sets the secondary ammo Type (int offset) + * + * @param weapon Weapon Entity. + * @param type Secondary ammo type value. + */ +stock void Weapon_SetSecondaryAmmoType(int weapon, int type) +{ + SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType", type); +} + +/* + * Gets the primary clip count of a weapon. + * + * @param weapon Weapon Entity. + * @return Primary Clip count. + */ +stock int Weapon_GetPrimaryClip(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iClip1"); +} + +/* + * Sets the primary clip count of a weapon. + * + * @param weapon Weapon Entity. + * @param value Clip Count value. + */ +stock void Weapon_SetPrimaryClip(int weapon, int value) +{ + SetEntProp(weapon, Prop_Data, "m_iClip1", value); +} + +/* + * Gets the secondary clip count of a weapon. + * + * @param weapon Weapon Entity. + * @return Secondy Clip count. + */ +stock int Weapon_GetSecondaryClip(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iClip2"); +} + +/* + * Sets the secondary clip count of a weapon. + * + * @param weapon Weapon Entity. + * @param value Clip Count value. + */ +stock void Weapon_SetSecondaryClip(int weapon, int value) +{ + SetEntProp(weapon, Prop_Data, "m_iClip2", value); +} + +/* + * Sets the primary & secondary clip count of a weapon. + * + * @param weapon Weapon Entity. + * @param primary Primary Clip Count value. + * @param secondary Primary Clip Count value. + */ +stock void Weapon_SetClips(int weapon, int primary, int secondary) +{ + Weapon_SetPrimaryClip(weapon, primary); + Weapon_SetSecondaryClip(weapon, secondary); +} + +/* + * Gets the primary ammo count of a weapon. + * This is only used when the weapon is not carried + * by a player to give a player ammo when he picks up + * the weapon. + * + * @param weapon Weapon Entity. + * @return Primary Ammo Count. + */ +stock int Weapon_GetPrimaryAmmoCount(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount"); +} + +/* + * Sets the primary ammo count of a weapon. + * This is only used when the weapon is not carried + * by a player to give a player ammo when he picks up + * the weapon. + * + * @param weapon Weapon Entity. + * @param value Primary Ammo Count. + */ +stock void Weapon_SetPrimaryAmmoCount(int weapon, int value) +{ + SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount", value); +} + +/* + * Gets the secondary ammo count of a weapon. + * This is only used when the weapon is not carried + * by a player to give a player ammo when he picks up + * the weapon. + * + * @param weapon Weapon Entity. + * @return Secondary Ammo Count. + */ +stock int Weapon_GetSecondaryAmmoCount(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount"); +} + +/* + * Sets the secodary ammo count of a weapon. + * This is only used when the weapon is not carried + * by a player to give a player ammo when he picks up + * the weapon. + * + * @param weapon Weapon Entity. + * @param value Secondary Ammo Count. + */ +stock void Weapon_SetSecondaryAmmoCount(int weapon, int value) +{ + SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount", value); +} + +/* + * Sets both, the primary & the secondary ammo count of a weapon. + * This is only used when the weapon is not carried + * by a player to give a player ammo when he picks up + * the weapon. + * + * @param weapon Weapon Entity. + * @value primary Primary Ammo Count. + * @value secondary Secondary Ammo Count. + */ +stock void Weapon_SetAmmoCounts(int weapon, int primary, int secondary) +{ + Weapon_SetPrimaryAmmoCount(weapon, primary); + Weapon_SetSecondaryAmmoCount(weapon, secondary); +} + +/* + * Gets the Model Index of the weapon's view model. + * + * @param weapon Weapon Entity. + * @return View Model Index. + */ +stock int Weapon_GetViewModelIndex(int weapon) +{ + return GetEntProp(weapon, Prop_Data, "m_nViewModelIndex"); +} + +/* + * Sets the Model Index of the weapon's view model. + * You can get the Model Index by precaching a model with PrecacheModel(). + * + * @param weapon Weapon Entity. + * @param index Model Index. + * @noreturn + */ +stock void Weapon_SetViewModelIndex(int weapon, int index) +{ + SetEntProp(weapon, Prop_Data, "m_nViewModelIndex", index); + ChangeEdictState(weapon, FindDataMapInfo(weapon, "m_nViewModelIndex")); +} diff --git a/source/sourcemod/scripting/include/smlib/world.inc b/source/sourcemod/scripting/include/smlib/world.inc new file mode 100644 index 0000000..d438b41 --- /dev/null +++ b/source/sourcemod/scripting/include/smlib/world.inc @@ -0,0 +1,16 @@ +#if defined _smlib_world_included + #endinput +#endif +#define _smlib_world_included + +#include + +/* + * Gets the world's max size + * + * @param vec Vector buffer + */ +stock void World_GetMaxs(float vec[3]) { + + GetEntPropVector(0, Prop_Data, "m_WorldMaxs", vec); +} diff --git a/source/sourcemod/scripting/include/sorting.inc b/source/sourcemod/scripting/include/sorting.inc new file mode 100644 index 0000000..5b0c249 --- /dev/null +++ b/source/sourcemod/scripting/include/sorting.inc @@ -0,0 +1,169 @@ +/** + * 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. + */ +native void SortIntegers(int[] array, int 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. + */ +native void SortFloats(float[] array, int 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. + */ +native void SortStrings(char[][] array, int array_size, 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 + */ +typedef SortFunc1D = function int (int elem1, int elem2, const int[] 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. + */ +native void SortCustom1D(int[] array, int 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 + */ +typeset SortFunc2D +{ + function int (int[] elem1, int[] elem2, const int[][] array, Handle hndl); + function int (char[] elem1, char[] elem2, const char[][] 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. + */ +native void SortCustom2D(any[][] array, int 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 + */ +native void 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 + */ +typedef SortFuncADTArray = function int (int index1, int 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 comparison function to use + * @param hndl Optional Handle to pass through the comparison calls. + */ +native void SortADTArrayCustom(Handle array, SortFuncADTArray sortfunc, Handle hndl=INVALID_HANDLE); diff --git a/source/sourcemod/scripting/include/sourcebanspp.inc b/source/sourcemod/scripting/include/sourcebanspp.inc new file mode 100644 index 0000000..c984bff --- /dev/null +++ b/source/sourcemod/scripting/include/sourcebanspp.inc @@ -0,0 +1,106 @@ +// ************************************************************************* +// This file is part of SourceBans++. +// +// Copyright (C) 2014-2019 SourceBans++ Dev Team +// +// SourceBans++ is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, per version 3 of the License. +// +// SourceBans++ 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 SourceBans++. If not, see . +// +// This file based off work(s) covered by the following copyright(s): +// +// SourceBans 1.4.11 +// Copyright (C) 2007-2015 SourceBans Team - Part of GameConnect +// Licensed under GNU GPL version 3, or later. +// Page: - +// +// ************************************************************************* + +#if defined _sourcebanspp_included +#endinput +#endif +#define _sourcebanspp_included + +public SharedPlugin __pl_sourcebanspp = +{ + name = "sourcebans++", + file = "sbpp_main.smx", + #if defined REQUIRE_PLUGIN + required = 1 + #else + required = 0 + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_sourcebanspp_SetNTVOptional() +{ + MarkNativeAsOptional("SBBanPlayer"); + MarkNativeAsOptional("SBPP_BanPlayer"); + MarkNativeAsOptional("SBPP_ReportPlayer"); +} +#endif + + +/********************************************************* + * Ban Player from server + * + * @param iAdmin The client index of the admin who is banning the client + * @param iTarget The client index of the player to ban + * @param iTime The time to ban the player for (in minutes, 0 = permanent) + * @param sReason The reason to ban the player from the server + * @noreturn + *********************************************************/ +#pragma deprecated Use SBPP_BanPlayer() instead. +native void SBBanPlayer(int iAdmin, int iTarget, int iTime, const char[] sReason); + +/********************************************************* + * Ban Player from server + * + * @param iAdmin The client index of the admin who is banning the client + * @param iTarget The client index of the player to ban + * @param iTime The time to ban the player for (in minutes, 0 = permanent) + * @param sReason The reason to ban the player from the server + * @noreturn + *********************************************************/ +native void SBPP_BanPlayer(int iAdmin, int iTarget, int iTime, const char[] sReason); + +/********************************************************* + * Reports a player + * + * @param iReporter The client index of the reporter + * @param iTarget The client index of the player to report + * @param sReason The reason to report the player + * @noreturn + *********************************************************/ +native void SBPP_ReportPlayer(int iReporter, int iTarget, const char[] sReason); + +/********************************************************* + * Called when the admin banning the player. + * + * @param iAdmin The client index of the admin who is banning the client + * @param iTarget The client index of the player to ban + * @param iTime The time to ban the player for (in minutes, 0 = permanent) + * @param sReason The reason to ban the player from the server + *********************************************************/ +forward void SBPP_OnBanPlayer(int iAdmin, int iTarget, int iTime, const char[] sReason); + +/********************************************************* + * Called when a new report is inserted + * + * @param iReporter The client index of the reporter + * @param iTarget The client index of the player to report + * @param sReason The reason to report the player + * @noreturn + *********************************************************/ +forward void SBPP_OnReportPlayer(int iReporter, int iTarget, const char[] sReason); + +//Yarr! diff --git a/source/sourcemod/scripting/include/sourcemod-colors.inc b/source/sourcemod/scripting/include/sourcemod-colors.inc new file mode 100644 index 0000000..66bc97b --- /dev/null +++ b/source/sourcemod/scripting/include/sourcemod-colors.inc @@ -0,0 +1,921 @@ +#if defined _sourcemod_colors_included + #endinput +#endif +#define _sourcemod_colors_included "1.0" + +/* +* _____ _ _____ _ +* / ____| | | / ____| | | +* | (___ ___ _ _ _ __ ___ ___ _ __ ___ ___ __| | | | ___ | | ___ _ __ ___ +* \___ \ / _ \| | | | '__/ __/ _ \ '_ ` _ \ / _ \ / _` | | | / _ \| |/ _ \| '__/ __| +* ____) | (_) | |_| | | | (_| __/ | | | | | (_) | (_| | | |___| (_) | | (_) | | \__ \ +* |_____/ \___/ \__,_|_| \___\___|_| |_| |_|\___/ \__,_| \_____\___/|_|\___/|_| |___/ +* +* +* - Author: Keith Warren (Drixevel) +* - Original By: Raska aka KissLick (ColorVariables) +* +* This is meant to be a drop-in replacement for every Source Engine game to add colors to chat and more cheat features. +*/ + +// ---------------------------------------------------------------------------------------- +#define MAX_BUFFER_SIZE 1024 + +static bool g_bInit; +static StringMap g_hColors; +static char g_sChatPrefix[64]; + +static bool g_bIgnorePrefix; +static int g_iAuthor; +static bool g_bSkipPlayers[MAXPLAYERS + 1]; +// ---------------------------------------------------------------------------------------- + +/* +* Sets the prefix for all chat prints to use. +* +* prefix - String to use. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CSetPrefix(const char[] prefix, any ...) +{ + VFormat(g_sChatPrefix, sizeof(g_sChatPrefix), prefix, 2); +} + +/* +* Setup the next print to skip using the prefix. +* +* +* Return - N/A +*/ +stock void CSkipNextPrefix() +{ + g_bIgnorePrefix = true; +} + +/* +* Sets the author for the next print. (Mostly applies colors) +* +* client - Author index. +* +* Return - N/A +*/ +stock void CSetNextAuthor(int client) +{ + if (client < 1 || client > MaxClients || !IsClientInGame(client)) + ThrowError("Invalid client index %i", client); + + g_iAuthor = client; +} + +/* +* Setup the next chat print to not be sent to this client. +* +* client - Client index. +* +* Return - N/A +*/ +stock void CSkipNextClient(int client) +{ + if (client < 1 || client > MaxClients) + ThrowError("Invalid client index %i", client); + + g_bSkipPlayers[client] = true; +} + +/* +* Sends a chat print to the client. +* +* client - Client index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChat(int client, const char[] message, any ...) +{ + if ((client < 1 || client > MaxClients || !IsClientInGame(client) || IsFakeClient(client)) && !IsClientSourceTV(client)) + return; + + SetGlobalTransTarget(client); + + char buffer[MAX_BUFFER_SIZE]; + VFormat(buffer, sizeof(buffer), message, 3); + + AddPrefixAndDefaultColor(buffer, sizeof(buffer)); + g_bIgnorePrefix = false; + + CProcessVariables(buffer, sizeof(buffer)); + CAddWhiteSpace(buffer, sizeof(buffer)); + + SendPlayerMessage(client, buffer, g_iAuthor); + g_iAuthor = 0; +} + +/* +* Sends a chat print to the client with a specified author. +* +* client - Client index. +* author - Author index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatEx(int client, int author, const char[] message, any ...) +{ + CSetNextAuthor(author); + char buffer[MAX_BUFFER_SIZE]; + VFormat(buffer, sizeof(buffer), message, 4); + CPrintToChat(client, buffer); +} + +/* +* Sends a chat print to all clients. +* +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatAll(const char[] message, any ...) +{ + char buffer[MAX_BUFFER_SIZE]; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || g_bSkipPlayers[client]) + { + g_bSkipPlayers[client] = false; + continue; + } + + SetGlobalTransTarget(client); + + VFormat(buffer, sizeof(buffer), message, 2); + + AddPrefixAndDefaultColor(buffer, sizeof(buffer)); + g_bIgnorePrefix = false; + + CProcessVariables(buffer, sizeof(buffer)); + CAddWhiteSpace(buffer, sizeof(buffer)); + + SendPlayerMessage(client, buffer, g_iAuthor); + } + + g_iAuthor = 0; +} + +/* +* Sends a chat print to all clients with a specified author. +* +* author - Author index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatAllEx(int author, const char[] message, any ...) +{ + CSetNextAuthor(author); + char buffer[MAX_BUFFER_SIZE]; + VFormat(buffer, sizeof(buffer), message, 3); + CPrintToChatAll(buffer); +} + +/* +* Sends a chat print to a specified team. +* +* team - Team index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatTeam(int team, const char[] message, any ...) +{ + char buffer[MAX_BUFFER_SIZE]; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || GetClientTeam(client) != team || g_bSkipPlayers[client]) + { + g_bSkipPlayers[client] = false; + continue; + } + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 3); + + AddPrefixAndDefaultColor(buffer, sizeof(buffer)); + g_bIgnorePrefix = false; + + CProcessVariables(buffer, sizeof(buffer)); + CAddWhiteSpace(buffer, sizeof(buffer)); + + SendPlayerMessage(client, buffer, g_iAuthor); + } + + g_iAuthor = 0; +} + +/* +* Sends a chat print to a specified team with a specified author. +* +* team - Team index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatTeamEx(int team, int author, const char[] message, any ...) +{ + CSetNextAuthor(author); + char buffer[MAX_BUFFER_SIZE]; + VFormat(buffer, sizeof(buffer), message, 4); + CPrintToChatTeam(team, buffer); +} + +/* +* Sends a chat print to available admins. +* Example for bitflags: (ADMFLAG_RESERVATION | ADMFLAG_GENERIC) +* +* bitflags - Bit Flags. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatAdmins(int bitflags, const char[] message, any ...) +{ + char buffer[MAX_BUFFER_SIZE]; + AdminId iAdminID; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || g_bSkipPlayers[client]) + { + g_bSkipPlayers[client] = false; + continue; + } + + iAdminID = GetUserAdmin(client); + + if (iAdminID == INVALID_ADMIN_ID || !(GetAdminFlags(iAdminID, Access_Effective) & bitflags)) + continue; + + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 3); + + AddPrefixAndDefaultColor(buffer, sizeof(buffer)); + g_bIgnorePrefix = false; + + CProcessVariables(buffer, sizeof(buffer)); + CAddWhiteSpace(buffer, sizeof(buffer)); + + SendPlayerMessage(client, buffer, g_iAuthor); + } + + g_iAuthor = 0; +} + +/* +* Sends a chat print to available admins with a specified author. +* Example for bitflags: (ADMFLAG_RESERVATION | ADMFLAG_GENERIC) +* +* bitflags - Bit Flags. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CPrintToChatAdminsEx(int bitflags, int author, const char[] message, any ...) +{ + CSetNextAuthor(author); + char buffer[MAX_BUFFER_SIZE]; + VFormat(buffer, sizeof(buffer), message, 4); + CPrintToChatTeam(bitflags, buffer); +} + +/* +* Sends a reply message to the client. (This is useful because it works for console as well) +* +* client - Client index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CReplyToCommand(int client, const char[] message, any ...) +{ + if (client < 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (client != 0 && !IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + char buffer[MAX_BUFFER_SIZE]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 3); + + AddPrefixAndDefaultColor(buffer, sizeof(buffer), "engine 1"); + g_bIgnorePrefix = false; + + if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) + { + CRemoveColors(buffer, sizeof(buffer)); + PrintToConsole(client, "%s", buffer); + } + else + CPrintToChat(client, "%s", buffer); +} + +/* +* 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. +* +* client - Client index. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CShowActivity(int client, const char[] message, any ...) +{ + if (client < 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (client != 0 && !IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + char buffer[MAX_BUFFER_SIZE]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 3); + Format(buffer, sizeof(buffer), "{engine 1}%s", buffer); + CProcessVariables(buffer, sizeof(buffer)); + CAddWhiteSpace(buffer, sizeof(buffer)); + + ShowActivity(client, "%s", buffer); +} + +/* +* 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. +* +* client - Client index. +* tag - Tag to show. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CShowActivityEx(int client, const char[] tag, const char[] message, any ...) +{ + if (client < 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (client != 0 && !IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + char buffer[MAX_BUFFER_SIZE]; char sBufferTag[MAX_BUFFER_SIZE]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 4); + Format(buffer, sizeof(buffer), "{engine 1}%s", buffer); + CProcessVariables(buffer, sizeof(buffer)); + Format(sBufferTag, sizeof(sBufferTag), "{prefix}%s", tag); + CProcessVariables(sBufferTag, sizeof(sBufferTag)); + CAddWhiteSpace(buffer, sizeof(buffer)); + CAddWhiteSpace(sBufferTag, sizeof(sBufferTag)); + + ShowActivityEx(client, sBufferTag, " %s", buffer); +} + +/* +* Same as ShowActivity(), except the tag parameter is used instead of "[SM] " (note that you must supply any spacing). +* +* client - Client index. +* tag - Tag to show. +* message - Message string. +* any - Extra Parameters +* +* Return - N/A +*/ +stock void CShowActivity2(int client, const char[] tag, const char[] message, any ...) +{ + if (client < 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (client != 0 && !IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + char buffer[MAX_BUFFER_SIZE]; char sBufferTag[MAX_BUFFER_SIZE]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 4); + Format(buffer, sizeof(buffer), "{engine 2}%s", buffer); + CProcessVariables(buffer, sizeof(buffer)); + Format(sBufferTag, sizeof(sBufferTag), "{prefix}%s", tag); + CProcessVariables(sBufferTag, sizeof(sBufferTag)); + CAddWhiteSpace(buffer, sizeof(buffer)); + CAddWhiteSpace(sBufferTag, sizeof(sBufferTag)); + + ShowActivityEx(client, sBufferTag, " %s", buffer); +} + +/* +* Strips all colors from the specified string. +* +* msg - String buffer. +* size - Size of the string. +* +* Return - N/A +*/ +stock void CRemoveColors(char[] msg, int size) +{ + CProcessVariables(msg, size, true); +} + +/* +* Processes colors in a string by replacing found tags with color/hex codes. +* +* msg - String buffer. +* size - Size of the string. +* removecolors - Whether to remove colors or keep them. (same as CRemoveColors) +* +* Return - N/A +*/ +stock void CProcessVariables(char[] msg, int size, bool removecolors = false) +{ + Init(); + + char[] sOut = new char[size]; char[] sCode = new char[size]; char[] color = new char[size]; + int iOutPos = 0; int iCodePos = -1; + int iMsgLen = strlen(msg); + + for (int i = 0; i < iMsgLen; i++) + { + if (msg[i] == '{') + iCodePos = 0; + + if (iCodePos > -1) + { + sCode[iCodePos] = msg[i]; + sCode[iCodePos + 1] = '\0'; + + if (msg[i] == '}' || i == iMsgLen - 1) + { + strcopy(sCode, strlen(sCode) - 1, sCode[1]); + StringToLower(sCode); + + if (CGetColor(sCode, color, size)) + { + if (!removecolors) + { + StrCat(sOut, size, color); + iOutPos += strlen(color); + } + } + else + { + Format(sOut, size, "%s{%s}", sOut, sCode); + iOutPos += strlen(sCode) + 2; + } + + iCodePos = -1; + strcopy(sCode, size, ""); + strcopy(color, size, ""); + } + else + iCodePos++; + + continue; + } + + sOut[iOutPos] = msg[i]; + iOutPos++; + sOut[iOutPos] = '\0'; + } + + strcopy(msg, size, sOut); +} + +/* +* Retrieves the color/hex code for a specified color name. +* +* name - Color to search for. +* color - String buffer. +* size - Size of the string. +* +* Return - True if found, false otherwise. +*/ +stock bool CGetColor(const char[] name, char[] color, int size) +{ + if (name[0] == '\0') + return false; + + if (name[0] == '@') + { + int iSpace; + char sData[64]; char m_sName[64]; + strcopy(m_sName, sizeof(m_sName), name[1]); + + if ((iSpace = FindCharInString(m_sName, ' ')) != -1 && (iSpace + 1 < strlen(m_sName))) + { + strcopy(m_sName, iSpace + 1, m_sName); + strcopy(sData, sizeof(sData), m_sName[iSpace + 1]); + } + + if (color[0] != '\0') + return true; + } + else if (name[0] == '#') + { + if (strlen(name) == 7) + { + Format(color, size, "\x07%s", name[1]); + return true; + } + + if (strlen(name) == 9) + { + Format(color, size, "\x08%s", name[1]); + return true; + } + } + else if (StrContains(name, "player ", false) == 0 && strlen(name) > 7) + { + int client = StringToInt(name[7]); + + if (client < 1 || client > MaxClients || !IsClientInGame(client)) + { + strcopy(color, size, "\x01"); + LogError("Invalid client index %d", client); + return false; + } + + strcopy(color, size, "\x01"); + + switch (GetClientTeam(client)) + { + case 1: g_hColors.GetString("engine 8", color, size); + case 2: g_hColors.GetString("engine 9", color, size); + case 3: g_hColors.GetString("engine 11", color, size); + } + + return true; + } + else + return g_hColors.GetString(name, color, size); + + return false; +} + +/* +* Checks if the specified color exists. +* +* name - Color to search for. +* +* Return - True if found, false otherwise. +*/ +stock bool CExistColor(const char[] name) +{ + if (name[0] == '\0' || name[0] == '@' || name[0] == '#') + return false; + + char color[64]; + return g_hColors.GetString(name, color, sizeof(color)); +} + +/* +* Sends a raw SayText2 usermsg to the specified client with settings. +* +* client - Client index. +* message - Message string. +* author - Author index. +* chat - "0 - raw text, 1 - sets CHAT_FILTER_PUBLICCHAT " +* +* Return - N/A +*/ +stock void CSayText2(int client, const char[] message, int author, bool chat = true) +{ + if (client < 1 || client > MaxClients) + return; + + Handle hMsg = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) + { + PbSetInt(hMsg, "ent_idx", author); + PbSetBool(hMsg, "chat", chat); + PbSetString(hMsg, "msg_name", message); + PbAddString(hMsg, "params", ""); + PbAddString(hMsg, "params", ""); + PbAddString(hMsg, "params", ""); + PbAddString(hMsg, "params", ""); + } + else + { + BfWriteByte(hMsg, author); + BfWriteByte(hMsg, true); + BfWriteString(hMsg, message); + } + + EndMessage(); +} + +/* +* Adds a space to the start a string buffer. +* +* buffer - String buffer. +* size - Size of the string. +* +* Return - N/A +*/ +stock void CAddWhiteSpace(char[] buffer, int size) +{ + if (!IsSource2009()) + Format(buffer, size, " %s", buffer); +} + +// ---------------------------------------------------------------------------------------- +// Private stuff +// ---------------------------------------------------------------------------------------- + +stock bool Init() +{ + if (g_bInit) + { + LoadColors(); + return true; + } + + for (int i = 1; i <= MaxClients; i++) + g_bSkipPlayers[i] = false; + + LoadColors(); + g_bInit = true; + + return true; +} + +stock void LoadColors() +{ + if (g_hColors == null) + g_hColors = new StringMap(); + else + g_hColors.Clear(); + + g_hColors.SetString("default", "\x01"); + g_hColors.SetString("teamcolor", "\x03"); + + if (IsSource2009()) + { + g_hColors.SetString("aliceblue", "\x07F0F8FF"); + g_hColors.SetString("allies", "\x074D7942"); + g_hColors.SetString("ancient", "\x07EB4B4B"); + g_hColors.SetString("antiquewhite", "\x07FAEBD7"); + g_hColors.SetString("aqua", "\x0700FFFF"); + g_hColors.SetString("aquamarine", "\x077FFFD4"); + g_hColors.SetString("arcana", "\x07ADE55C"); + g_hColors.SetString("axis", "\x07FF4040"); + g_hColors.SetString("azure", "\x07007FFF"); + g_hColors.SetString("beige", "\x07F5F5DC"); + g_hColors.SetString("bisque", "\x07FFE4C4"); + g_hColors.SetString("black", "\x07000000"); + g_hColors.SetString("blanchedalmond", "\x07FFEBCD"); + g_hColors.SetString("blue", "\x0799CCFF"); + g_hColors.SetString("blueviolet", "\x078A2BE2"); + g_hColors.SetString("brown", "\x07A52A2A"); + g_hColors.SetString("burlywood", "\x07DEB887"); + g_hColors.SetString("cadetblue", "\x075F9EA0"); + g_hColors.SetString("chartreuse", "\x077FFF00"); + g_hColors.SetString("chocolate", "\x07D2691E"); + g_hColors.SetString("collectors", "\x07AA0000"); + g_hColors.SetString("common", "\x07B0C3D9"); + g_hColors.SetString("community", "\x0770B04A"); + g_hColors.SetString("coral", "\x07FF7F50"); + g_hColors.SetString("cornflowerblue", "\x076495ED"); + g_hColors.SetString("cornsilk", "\x07FFF8DC"); + g_hColors.SetString("corrupted", "\x07A32C2E"); + g_hColors.SetString("crimson", "\x07DC143C"); + g_hColors.SetString("cyan", "\x0700FFFF"); + g_hColors.SetString("darkblue", "\x0700008B"); + g_hColors.SetString("darkcyan", "\x07008B8B"); + g_hColors.SetString("darkgoldenrod", "\x07B8860B"); + g_hColors.SetString("darkgray", "\x07A9A9A9"); + g_hColors.SetString("darkgrey", "\x07A9A9A9"); + g_hColors.SetString("darkgreen", "\x07006400"); + g_hColors.SetString("darkkhaki", "\x07BDB76B"); + g_hColors.SetString("darkmagenta", "\x078B008B"); + g_hColors.SetString("darkolivegreen", "\x07556B2F"); + g_hColors.SetString("darkorange", "\x07FF8C00"); + g_hColors.SetString("darkorchid", "\x079932CC"); + g_hColors.SetString("darkred", "\x078B0000"); + g_hColors.SetString("darksalmon", "\x07E9967A"); + g_hColors.SetString("darkseagreen", "\x078FBC8F"); + g_hColors.SetString("darkslateblue", "\x07483D8B"); + g_hColors.SetString("darkslategray", "\x072F4F4F"); + g_hColors.SetString("darkslategrey", "\x072F4F4F"); + g_hColors.SetString("darkturquoise", "\x0700CED1"); + g_hColors.SetString("darkviolet", "\x079400D3"); + g_hColors.SetString("deeppink", "\x07FF1493"); + g_hColors.SetString("deepskyblue", "\x0700BFFF"); + g_hColors.SetString("dimgray", "\x07696969"); + g_hColors.SetString("dimgrey", "\x07696969"); + g_hColors.SetString("dodgerblue", "\x071E90FF"); + g_hColors.SetString("exalted", "\x07CCCCCD"); + g_hColors.SetString("firebrick", "\x07B22222"); + g_hColors.SetString("floralwhite", "\x07FFFAF0"); + g_hColors.SetString("forestgreen", "\x07228B22"); + g_hColors.SetString("frozen", "\x074983B3"); + g_hColors.SetString("fuchsia", "\x07FF00FF"); + g_hColors.SetString("fullblue", "\x070000FF"); + g_hColors.SetString("fullred", "\x07FF0000"); + g_hColors.SetString("gainsboro", "\x07DCDCDC"); + g_hColors.SetString("genuine", "\x074D7455"); + g_hColors.SetString("ghostwhite", "\x07F8F8FF"); + g_hColors.SetString("gold", "\x07FFD700"); + g_hColors.SetString("goldenrod", "\x07DAA520"); + g_hColors.SetString("gray", "\x07CCCCCC"); + g_hColors.SetString("grey", "\x07CCCCCC"); + g_hColors.SetString("green", "\x073EFF3E"); + g_hColors.SetString("greenyellow", "\x07ADFF2F"); + g_hColors.SetString("haunted", "\x0738F3AB"); + g_hColors.SetString("honeydew", "\x07F0FFF0"); + g_hColors.SetString("hotpink", "\x07FF69B4"); + g_hColors.SetString("immortal", "\x07E4AE33"); + g_hColors.SetString("indianred", "\x07CD5C5C"); + g_hColors.SetString("indigo", "\x074B0082"); + g_hColors.SetString("ivory", "\x07FFFFF0"); + g_hColors.SetString("khaki", "\x07F0E68C"); + g_hColors.SetString("lavender", "\x07E6E6FA"); + g_hColors.SetString("lavenderblush", "\x07FFF0F5"); + g_hColors.SetString("lawngreen", "\x077CFC00"); + g_hColors.SetString("legendary", "\x07D32CE6"); + g_hColors.SetString("lemonchiffon", "\x07FFFACD"); + g_hColors.SetString("lightblue", "\x07ADD8E6"); + g_hColors.SetString("lightcoral", "\x07F08080"); + g_hColors.SetString("lightcyan", "\x07E0FFFF"); + g_hColors.SetString("lightgoldenrodyellow", "\x07FAFAD2"); + g_hColors.SetString("lightgray", "\x07D3D3D3"); + g_hColors.SetString("lightgrey", "\x07D3D3D3"); + g_hColors.SetString("lightgreen", "\x0799FF99"); + g_hColors.SetString("lightpink", "\x07FFB6C1"); + g_hColors.SetString("lightsalmon", "\x07FFA07A"); + g_hColors.SetString("lightseagreen", "\x0720B2AA"); + g_hColors.SetString("lightskyblue", "\x0787CEFA"); + g_hColors.SetString("lightslategray", "\x07778899"); + g_hColors.SetString("lightslategrey", "\x07778899"); + g_hColors.SetString("lightsteelblue", "\x07B0C4DE"); + g_hColors.SetString("lightyellow", "\x07FFFFE0"); + g_hColors.SetString("lime", "\x0700FF00"); + g_hColors.SetString("limegreen", "\x0732CD32"); + g_hColors.SetString("linen", "\x07FAF0E6"); + g_hColors.SetString("magenta", "\x07FF00FF"); + g_hColors.SetString("maroon", "\x07800000"); + g_hColors.SetString("mediumaquamarine", "\x0766CDAA"); + g_hColors.SetString("mediumblue", "\x070000CD"); + g_hColors.SetString("mediumorchid", "\x07BA55D3"); + g_hColors.SetString("mediumpurple", "\x079370D8"); + g_hColors.SetString("mediumseagreen", "\x073CB371"); + g_hColors.SetString("mediumslateblue", "\x077B68EE"); + g_hColors.SetString("mediumspringgreen", "\x0700FA9A"); + g_hColors.SetString("mediumturquoise", "\x0748D1CC"); + g_hColors.SetString("mediumvioletred", "\x07C71585"); + g_hColors.SetString("midnightblue", "\x07191970"); + g_hColors.SetString("mintcream", "\x07F5FFFA"); + g_hColors.SetString("mistyrose", "\x07FFE4E1"); + g_hColors.SetString("moccasin", "\x07FFE4B5"); + g_hColors.SetString("mythical", "\x078847FF"); + g_hColors.SetString("navajowhite", "\x07FFDEAD"); + g_hColors.SetString("navy", "\x07000080"); + g_hColors.SetString("normal", "\x07B2B2B2"); + g_hColors.SetString("oldlace", "\x07FDF5E6"); + g_hColors.SetString("olive", "\x079EC34F"); + g_hColors.SetString("olivedrab", "\x076B8E23"); + g_hColors.SetString("orange", "\x07FFA500"); + g_hColors.SetString("orangered", "\x07FF4500"); + g_hColors.SetString("orchid", "\x07DA70D6"); + g_hColors.SetString("palegoldenrod", "\x07EEE8AA"); + g_hColors.SetString("palegreen", "\x0798FB98"); + g_hColors.SetString("paleturquoise", "\x07AFEEEE"); + g_hColors.SetString("palevioletred", "\x07D87093"); + g_hColors.SetString("papayawhip", "\x07FFEFD5"); + g_hColors.SetString("peachpuff", "\x07FFDAB9"); + g_hColors.SetString("peru", "\x07CD853F"); + g_hColors.SetString("pink", "\x07FFC0CB"); + g_hColors.SetString("plum", "\x07DDA0DD"); + g_hColors.SetString("powderblue", "\x07B0E0E6"); + g_hColors.SetString("purple", "\x07800080"); + g_hColors.SetString("rare", "\x074B69FF"); + g_hColors.SetString("red", "\x07FF4040"); + g_hColors.SetString("rosybrown", "\x07BC8F8F"); + g_hColors.SetString("royalblue", "\x074169E1"); + g_hColors.SetString("saddlebrown", "\x078B4513"); + g_hColors.SetString("salmon", "\x07FA8072"); + g_hColors.SetString("sandybrown", "\x07F4A460"); + g_hColors.SetString("seagreen", "\x072E8B57"); + g_hColors.SetString("seashell", "\x07FFF5EE"); + g_hColors.SetString("selfmade", "\x0770B04A"); + g_hColors.SetString("sienna", "\x07A0522D"); + g_hColors.SetString("silver", "\x07C0C0C0"); + g_hColors.SetString("skyblue", "\x0787CEEB"); + g_hColors.SetString("slateblue", "\x076A5ACD"); + g_hColors.SetString("slategray", "\x07708090"); + g_hColors.SetString("slategrey", "\x07708090"); + g_hColors.SetString("snow", "\x07FFFAFA"); + g_hColors.SetString("springgreen", "\x0700FF7F"); + g_hColors.SetString("steelblue", "\x074682B4"); + g_hColors.SetString("strange", "\x07CF6A32"); + g_hColors.SetString("tan", "\x07D2B48C"); + g_hColors.SetString("teal", "\x07008080"); + g_hColors.SetString("thistle", "\x07D8BFD8"); + g_hColors.SetString("tomato", "\x07FF6347"); + g_hColors.SetString("turquoise", "\x0740E0D0"); + g_hColors.SetString("uncommon", "\x07B0C3D9"); + g_hColors.SetString("unique", "\x07FFD700"); + g_hColors.SetString("unusual", "\x078650AC"); + g_hColors.SetString("valve", "\x07A50F79"); + g_hColors.SetString("vintage", "\x07476291"); + g_hColors.SetString("violet", "\x07EE82EE"); + g_hColors.SetString("wheat", "\x07F5DEB3"); + g_hColors.SetString("white", "\x07FFFFFF"); + g_hColors.SetString("whitesmoke", "\x07F5F5F5"); + g_hColors.SetString("yellow", "\x07FFFF00"); + g_hColors.SetString("yellowgreen", "\x079ACD32"); + } + else + { + g_hColors.SetString("red", "\x07"); + g_hColors.SetString("lightred", "\x0F"); + g_hColors.SetString("darkred", "\x02"); + g_hColors.SetString("bluegrey", "\x0A"); + g_hColors.SetString("blue", "\x0B"); + g_hColors.SetString("darkblue", "\x0C"); + g_hColors.SetString("purple", "\x03"); + g_hColors.SetString("orchid", "\x0E"); + g_hColors.SetString("yellow", "\x09"); + g_hColors.SetString("gold", "\x10"); + g_hColors.SetString("lightgreen", "\x05"); + g_hColors.SetString("green", "\x04"); + g_hColors.SetString("lime", "\x06"); + g_hColors.SetString("grey", "\x08"); + g_hColors.SetString("grey2", "\x0D"); + } + + g_hColors.SetString("engine 1", "\x01"); + g_hColors.SetString("engine 2", "\x02"); + g_hColors.SetString("engine 3", "\x03"); + g_hColors.SetString("engine 4", "\x04"); + g_hColors.SetString("engine 5", "\x05"); + g_hColors.SetString("engine 6", "\x06"); + g_hColors.SetString("engine 7", "\x07"); + g_hColors.SetString("engine 8", "\x08"); + g_hColors.SetString("engine 9", "\x09"); + g_hColors.SetString("engine 10", "\x0A"); + g_hColors.SetString("engine 11", "\x0B"); + g_hColors.SetString("engine 12", "\x0C"); + g_hColors.SetString("engine 13", "\x0D"); + g_hColors.SetString("engine 14", "\x0E"); + g_hColors.SetString("engine 15", "\x0F"); + g_hColors.SetString("engine 16", "\x10"); +} + +stock bool HasBrackets(const char[] sSource) +{ + return (sSource[0] == '{' && sSource[strlen(sSource) - 1] == '}'); +} + +stock void StringToLower(char[] sSource) +{ + for (int i = 0; i < strlen(sSource); i++) + { + if (sSource[i] == '\0') + break; + + sSource[i] = CharToLower(sSource[i]); + } +} + +stock bool IsSource2009() +{ + EngineVersion iEngineVersion = GetEngineVersion(); + return (iEngineVersion == Engine_CSS || iEngineVersion == Engine_TF2 || iEngineVersion == Engine_HL2DM || iEngineVersion == Engine_DODS); +} + +stock void AddPrefixAndDefaultColor(char[] message, int size, char[] sDefaultColor = "engine 1", char[] sPrefixColor = "engine 2") +{ + if (g_sChatPrefix[0] != '\0' && !g_bIgnorePrefix) + Format(message, size, "{%s}[%s]{%s} %s", sPrefixColor, g_sChatPrefix, sDefaultColor, message); + else + Format(message, size, "{%s}%s", sDefaultColor, message); +} + +stock void SendPlayerMessage(int client, char[] message, int author = 0) +{ + if (author > 0 && author <= MaxClients && IsClientInGame(author)) + CSayText2(client, message, author); + else + PrintToChat(client, message); +} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/sourcemod.inc b/source/sourcemod/scripting/include/sourcemod.inc new file mode 100644 index 0000000..4ac5e30 --- /dev/null +++ b/source/sourcemod/scripting/include/sourcemod.inc @@ -0,0 +1,772 @@ +/** + * 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 +{ + public const char[] name; /**< Plugin Name */ + public const char[] description; /**< Plugin Description */ + public const char[] author; /**< Plugin Author */ + public const char[] version; /**< Plugin Version */ + public const char[] 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 +#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 */ +}; + +methodmap GameData < Handle +{ + // 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 null on failure. + public native GameData(const char[] file); + + // Returns an offset value. + // + // @param key Key to retrieve from the offset section. + // @return An offset, or -1 on failure. + public native int GetOffset(const char[] key); + + // Gets the value of a key from the "Keys" section. + // + // @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. + public native bool GetKeyValue(const char[] key, char[] buffer, int maxlen); + + // Finds an address calculation in a GameConfig file, + // performs LoadFromAddress on it as appropriate, then returns the final address. + // + // @param name Name of the property to find. + // @return An address calculated on success, or 0 on failure. + public native Address GetAddress(const char[] name); + + // Returns a function address calculated from a signature. + // + // @param name Name of the property to find. + // @return An address calculated on success, or 0 on failure. + public native Address GetMemSig(const char[] name); +}; + +/** + * 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. + */ +forward void 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, char[] error, int 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, char[] error, int err_max); + +/** + * Called when the plugin is about to be unloaded. + * + * 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. + */ +forward void OnPluginEnd(); + +/** + * Called when the plugin's pause status is changing. + * + * @param pause True if the plugin is being paused, false otherwise. + */ +forward void OnPluginPauseChange(bool pause); + +/** + * Called before every server frame. Note that you should avoid + * doing expensive computations or declaring large local arrays. + */ +forward void OnGameFrame(); + +/** + * Called when the map starts loading. + * + * @param mapName Name of the map + */ +forward void OnMapInit(const char[] mapName); + +/** + * Called when the map is loaded. + */ +forward void OnMapStart(); + +/** + * Called right before a map ends. + */ +forward void 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(). + */ +forward void 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(). + */ +forward void OnAutoConfigsBuffered(); + +/** + * @deprecated Use OnConfigsExecuted() instead. + */ +#pragma deprecated Use OnConfigsExecuted() instead +forward void 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 void OnAllPluginsLoaded(); + +/** + * Returns the calling plugin's Handle. + * + * @return Handle of the calling plugin. + */ +native Handle GetMyHandle(); + +methodmap PluginIterator < Handle +{ + // Returns an iterator that can be used to search through plugins. + // + // @return A new Handle to a PluginIterator. + public native PluginIterator(); + + // Advances the iterator. Returns whether there are more plugins available in the iterator. + // + // @return True on more plugins, false otherwise. + // @error Invalid Handle. + public native bool Next(); + + // Returns the current plugin in the iterator. + // + // @return Current plugin the iterator is at + // @error Invalid Handle. + property Handle Plugin { + public native get(); + } +} + +/** + * 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. + * @error Invalid Handle. + */ +native void GetPluginFilename(Handle plugin, char[] buffer, int 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 plugin); + +/** + * 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, char[] buffer, int 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(int 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. + * @error Always throws SP_ERROR_ABORT. + */ +native void SetFailState(const char[] string, any ...); + +/** + * Aborts the current callback and throws an error. This function + * does not return in that no code is executed following it. + * + * @param fmt String format. + * @param ... Format arguments. + * @noreturn + * @error Always! + */ +native void ThrowError(const char[] fmt, any ...); + +/** + * Logs a stack trace from the current function call. Code + * execution continues after the call + * + * @param fmt Format string to send with the stack trace. + * @param ... Format arguments. + * @error Always logs a stack trace. + */ +native void LogStackTrace(const char[] 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 int GetTime(int 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 + * + * Note that available parameters depends on support from your operating system. + * In particular, ones highlighted in yellow on that page are not currently + * available on Windows and should be avoided for portable plugins. + * + * @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. + * @error Buffer too small or invalid time format. + */ +native void FormatTime(char[] buffer, int maxlength, const char[] format, int 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 on failure. + */ +native GameData LoadGameConfigFile(const char[] 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 int GameConfGetOffset(Handle gc, const char[] 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 char[] key, char[] buffer, int maxlen); + +/** + * Finds an address calculation in a GameConfig file, + * performs LoadFromAddress on it as appropriate, then returns the final address. + * + * @param gameconf Game config handle. + * @param name Name of the property to find. + * @return An address calculated on success, or 0 on failure. + */ +native Address GameConfGetAddress(Handle gameconf, const char[] name); + +/** + * 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 int 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." + */ +native void AutoExecConfig(bool autoCreate=true, const char[] name="", const char[] folder="sourcemod"); + +/** + * Registers a library name for identifying as a dependency to + * other plugins. + * + * @param name Library name. + */ +native void RegPluginLibrary(const char[] 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 libraries. + * + * @param name Library name of a plugin or extension. + * @return True if exists, false otherwise. + */ +native bool LibraryExists(const char[] 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 int GetExtensionFileStatus(const char[] name, char[] error="", int maxlength=0); + +/** + * Called after a library is added. + * A library is either a plugin name or extension name, as + * exposed via its include file. + * + * @param name Library name. + */ +forward void OnLibraryAdded(const char[] name); + +/** + * Called right before a library is removed. + * A library is either a plugin name or extension name, as + * exposed via its include file. + * + * @param name Library name. + */ +forward void OnLibraryRemoved(const char[] name); + +/** + * Called when a plugin unloaded. + * + * @param plugin Plugin Handle who unloaded. + */ +forward void OnNotifyPluginUnloaded(Handle plugin); + +#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 re-parse 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, + int &serial=-1, + const char[] str="default", + int 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. + */ +native void SetMapListCompatBind(const char[] name, const char[] 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(int 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. + */ +forward void OnClientFloodResult(int 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 char[] 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. + */ +native void RequireFeature(FeatureType type, const char[] name, + const char[] fmt="", any ...); + +/** + * Represents how many bytes we can read from an address with one load + */ +enum NumberType +{ + NumberType_Int8, + NumberType_Int16, + NumberType_Int32 +}; + +enum Address +{ + Address_Null = 0 // a typical invalid result when an address lookup fails +}; + +/** + * Load up to 4 bytes from a memory address. + * + * @param addr Address to a memory location. + * @param size How many bytes should be read. + * If loading a floating-point value, use NumberType_Int32. + * @return The value that is stored at that address. + * @error Address is null or pointing to reserved memory. + */ +native any LoadFromAddress(Address addr, NumberType size); + +/** + * Store up to 4 bytes to a memory address. + * + * @param addr Address to a memory location. + * @param data Value to store at the address. + * @param size How many bytes should be written. + * If storing a floating-point value, use NumberType_Int32. + * @param updateMemAccess If true, SourceMod will set read / write / exec permissions + * on the memory page being written to. + * @error Address is null or pointing to reserved memory. + */ +native void StoreToAddress(Address addr, any data, NumberType size, bool updateMemAccess = true); + +methodmap FrameIterator < Handle { + // Creates a stack frame iterator to build your own stack traces. + // @return New handle to a FrameIterator. + public native FrameIterator(); + + // Advances the iterator to the next stack frame. + // @return True if another frame was fetched and data can be successfully read. + // @error No next element exception. + public native bool Next(); + + // Resets the iterator back to it's starting position. + public native void Reset(); + + // Returns the line number of the current function call. + property int LineNumber { + public native get(); + } + + // Gets the name of the current function in the call stack. + // + // @param buffer Buffer to copy to. + // @param maxlen Max size of the buffer. + public native void GetFunctionName(char[] buffer, int maxlen); + + // Gets the file path to the current call in the call stack. + // + // @param buffer Buffer to copy to. + // @param maxlen Max size of the buffer. + public native void GetFilePath(char[] buffer, int maxlen); +} + +#include +#include +#include diff --git a/source/sourcemod/scripting/include/string.inc b/source/sourcemod/scripting/include/string.inc new file mode 100644 index 0000000..4034d45 --- /dev/null +++ b/source/sourcemod/scripting/include/string.inc @@ -0,0 +1,590 @@ +/** + * 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 int strlen(const char[] 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 int StrContains(const char[] str, const char[] 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 int strcmp(const char[] str1, const char[] 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 int strncmp(const char[] str1, const char[] str2, int num, bool caseSensitive=true); + +/** + * Backwards compatible stock - StrCompare is now strcmp + * @deprecated Renamed to strcmp + */ +#pragma deprecated Use strcmp() instead +stock int StrCompare(const char[] str1, const char[] 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 char[] str1, const char[] 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 characters written to the buffer, + * not including the null terminator. + */ +native int strcopy(char[] dest, int destLen, const char[] source); + +/** + * Backwards compatibility stock - use strcopy + * @deprecated Renamed to strcopy + */ +#pragma deprecated Use strcopy() instead +stock int StrCopy(char[] dest, int destLen, const char[] 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 characters written to the buffer, + * not including the null terminator. + */ +native int Format(char[] buffer, int maxlength, const char[] 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 characters written to the buffer, + * not including the null terminator. + */ +native int FormatEx(char[] buffer, int maxlength, const char[] 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. + * @error Invalid argument index. + */ +native int VFormat(char[] buffer, int maxlength, const char[] format, int 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 int StringToInt(const char[] str, int 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 int StringToIntEx(const char[] str, int &result, int nBase=10); + +/** + * Converts a string to a 64-bit integer. + * + * @param str String to convert. + * @param result Array to store the upper and lower + * 32-bits of the 64-bit integer. + * @param nBase Numerical base to use. 10 is default. + * @return Number of characters consumed. + */ +native int StringToInt64(const char[] str, int result[2], int 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 characters written to the buffer, + * not including the null terminator. + */ +native int IntToString(int num, char[] str, int maxlength); + +/** + * Converts a 64-bit integer to a string. + * + * @param num Array containing the upper and lower + * 32-bits of a 64-bit integer. + * @param str Buffer to store string in. + * @param maxlength Maximum length of string buffer. + * @return Number of characters written to the buffer, + * not including the null terminator. + */ +native int Int64ToString(const int num[2], char[] str, int maxlength); + +/** + * Converts a string to a floating point number. + * + * @param str String to convert to a float. + * @return Floating point result, or 0.0 on error. + */ +native float StringToFloat(const char[] str); + +/** + * Converts a string to a floating point number with some more options. + * + * @param str String to convert to a float. + * @param result Variable to store result in. + * @return Number of characters consumed. + */ +native int StringToFloatEx(const char[] 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 characters written to the buffer, + * not including the null terminator. + */ +native int FloatToString(float num, char[] str, int 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 int BreakString(const char[] source, char[] arg, int argLen); + +/** + * Backwards compatibility stock - use BreakString + * @deprecated Renamed to BreakString. + */ +#pragma deprecated Use BreakString() instead +stock int StrBreak(const char[] source, char[] arg, int 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 int TrimString(char[] 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 int SplitString(const char[] source, const char[] split, char[] part, int 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. + * @error 'search' parameter is empty. + */ +native int ReplaceString(char[] text, int maxlength, const char[] search, const char[] 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. + * @error 'search' parameter is empty. + */ +native int ReplaceStringEx(char[] text, int maxlength, const char[] search, const char[] replace, int searchLen=-1, int 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 int GetCharBytes(const char[] source); + +/** + * Returns whether a character is an ASCII alphabet character. + * + * @note Multi-byte characters will always return false. + * + * @param chr Character to test. + * @return True if character is alphabetical, otherwise false. + */ +native bool IsCharAlpha(int chr); + +/** + * Returns whether a character is numeric. + * + * @note Multi-byte characters will always return false. + * + * @param chr Character to test. + * @return True if character is numeric, otherwise false. + */ +native bool IsCharNumeric(int chr); + +/** + * Returns whether a character is whitespace. + * + * @note Multi-byte characters will always return false. + * + * @param chr Character to test. + * @return True if character is whitespace, otherwise false. + */ +native bool IsCharSpace(int chr); + +/** + * Returns if a character is multi-byte or not. + * + * @param chr Character to test. + * @return 0 for a normal 7-bit ASCII character, + * otherwise number of bytes in multi-byte character. + */ +native int IsCharMB(int chr); + +/** + * Returns whether an alphabetic character is uppercase. + * + * @note Multi-byte characters will always return false. + * + * @param chr Character to test. + * @return True if character is uppercase, otherwise false. + */ +native bool IsCharUpper(int chr); + +/** + * Returns whether an alphabetic character is lowercase. + * + * @note Multi-byte characters will always return false. + * + * @param chr Character to test. + * @return True if character is lowercase, otherwise false. + */ +native bool IsCharLower(int 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(char[] text); + +/** + * Converts a lowercase character to its uppercase counterpart. + * + * @param chr Character to convert. + * @return Uppercase character on success, + * no change on failure. + */ +stock int CharToUpper(int chr) +{ + if (IsCharLower(chr)) + { + return (chr & ~(1<<5)); + } + + return chr; +} + +/** + * Converts an uppercase character to its lowercase counterpart. + * + * @param chr Character to convert. + * @return Lowercase character on success, + * no change on failure. + */ +stock int CharToLower(int 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 int FindCharInString(const char[] str, char c, bool reverse = false) +{ + int len = strlen(str); + + if (!reverse) + { + for (int i = 0; i < len; i++) + { + if (str[i] == c) + { + return i; + } + } + } + else + { + for (int 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 int StrCat(char[] buffer, int maxlength, const char[] source) +{ + int 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. + * @param copyRemainder False (default) discard excess pieces, true to ignore + * delimiters after last piece. + * @return Number of strings retrieved. + */ +stock int ExplodeString(const char[] text, const char[] split, char[][] buffers, int maxStrings, + int maxStringLength, bool copyRemainder = false) +{ + int reloc_idx, idx, total; + + if (maxStrings < 1 || !split[0]) + { + return 0; + } + + while ((idx = SplitString(text[reloc_idx], split, buffers[total], maxStringLength)) != -1) + { + reloc_idx += idx; + if (++total == maxStrings) + { + if (copyRemainder) + { + strcopy(buffers[total-1], maxStringLength, text[reloc_idx-idx]); + } + return total; + } + } + + 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 int ImplodeStrings(const char[][] strings, int numStrings, const char[] join, char[] buffer, int maxLength) +{ + int total, length, part_length; + int join_length = strlen(join); + for (int 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$ + */ + +static int TestNumber = 0; +static char TestContext[255]; + +stock void SetTestContext(const char[] context) +{ + strcopy(TestContext, sizeof(TestContext), context); +} + +stock void AssertEq(const char[] text, int cell1, int cell2) +{ + TestNumber++; + if (cell1 == cell2) + { + PrintToServer("[%d] %s: %s == %d OK", TestNumber, TestContext, text, cell2); + } + else + { + PrintToServer("[%d] %s FAIL: %s should be %d, got %d", TestNumber, TestContext, text, cell2, cell1); + ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext); + } +} + +stock void AssertFalse(const char[] text, bool value) +{ + TestNumber++; + if (!value) + { + PrintToServer("[%d] %s: %s == false OK", TestNumber, TestContext, text, value); + } + else + { + PrintToServer("[%d] %s FAIL: %s should be false, got true", TestNumber, TestContext, text); + ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext); + } +} + +stock void AssertTrue(const char[] text, bool value) +{ + TestNumber++; + if (value) + { + PrintToServer("[%d] %s: %s == true OK", TestNumber, TestContext, text, value); + } + else + { + PrintToServer("[%d] %s FAIL: %s should be true, got false", TestNumber, TestContext, text); + ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext); + } +} + +stock void AssertStrEq(const char[] text, const char[] value, const char[] expected) +{ + TestNumber++; + if (StrEqual(value, expected)) + { + PrintToServer("[%d] %s: '%s' == '%s' OK", TestNumber, TestContext, text, expected); + } + else + { + PrintToServer("[%d] %s FAIL: %s should be '%s', got '%s'", TestNumber, TestContext, text, expected, value); + ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext); + } +} diff --git a/source/sourcemod/scripting/include/textparse.inc b/source/sourcemod/scripting/include/textparse.inc new file mode 100644 index 0000000..34e99e4 --- /dev/null +++ b/source/sourcemod/scripting/include/textparse.inc @@ -0,0 +1,255 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod (C)2004-2014 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 _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 */ +}; + +/** + * Called when parsing is started. + * + * @param smc The SMC Parse Handle. + */ +typedef SMC_ParseStart = function void (SMCParser smc); + +/** + * Called when the parser is entering a new section or sub-section. + * + * Note: Enclosing quotes are always stripped. + * + * @param smc The SMC Parser. + * @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. + */ +typedef SMC_NewSection = function SMCResult (SMCParser smc, const char[] name, bool opt_quotes); + +/** + * Called when the parser finds a new key/value pair. + * + * Note: Enclosing quotes are always stripped. + * + * @param smc The SMCParser. + * @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. + */ +typedef SMC_KeyValue = function SMCResult (SMCParser smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes); + +/** Called when the parser finds the end of the current section. + * + * @param smc The SMCParser. + * @return An SMCResult action to take. + */ +typedef SMC_EndSection = function SMCResult (SMCParser smc); + +/** + * Called when parsing is halted. + * + * @param smc The SMCParser. + * @param halted True if abnormally halted, false otherwise. + * @param failed True if parsing failed, false otherwise. + */ +typedef SMC_ParseEnd = function void (SMCParser smc, bool halted, bool failed); + +/** + * Callback for whenever a new line of text is about to be parsed. + * + * @param smc The SMCParser. + * @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. + */ +typedef SMC_RawLine = function SMCResult (SMCParser smc, const char[] line, int lineno); + +// An SMCParser is a callback-driven parser for SourceMod configuration files. +// SMC files are similar to Valve KeyValues format, with two key differences: +// (1) SMC cannot handle single-item entries (that is, a key with no value). +// (2) SMC files can have multi-line comment blocks, whereas KeyValues cannot. +methodmap SMCParser < Handle +{ + // Create a new SMC file format parser. + public native SMCParser(); + + // Parses an SMC file. + // + // @param file A string containing the file path. + // @param line An optional variable to store the last line number read. + // @param col An optional variable to store the last column number read. + // @return An SMCParseError result. + public native SMCError ParseFile(const char[] file, int &line = 0, int &col = 0); + + // Sets the callback for receiving SMC_ParseStart events. + property SMC_ParseStart OnStart { + public native set(SMC_ParseStart func); + } + + // Sets the callback for receiving SMC_ParseEnd events. + property SMC_ParseEnd OnEnd { + public native set(SMC_ParseEnd func); + } + + // Sets the callback for receiving SMC_NewSection events. + property SMC_NewSection OnEnterSection { + public native set(SMC_NewSection func); + } + + // Sets the callback for receiving SMC_EndSection events. + property SMC_EndSection OnLeaveSection { + public native set(SMC_EndSection func); + } + + // Sets the callback for receiving SMC_KeyValue events. + property SMC_KeyValue OnKeyValue { + public native set(SMC_KeyValue func); + } + + // Sets the callback for receiving SMC_RawLine events. + property SMC_RawLine OnRawLine { + public native set(SMC_RawLine func); + } + + // Gets an error string for an SMCError code. + // + // @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 The number of characters written to buffer. + public native void GetErrorString(SMCError error, char[] buffer, int buf_max); +}; + +/** + * Creates a new SMC file format parser. This is used to set parse hooks. + * + * @return A new Handle to an SMC Parse structure. + */ +native SMCParser 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 char[] file, int &line=0, int &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, char[] buffer, int buf_max); + +/** + * Sets the SMC_ParseStart function of a parse Handle. + * + * @param smc Handle to an SMC Parse. + * @param func SMC_ParseStart function. + * @error Invalid or corrupt Handle. + */ +native void SMC_SetParseStart(Handle smc, SMC_ParseStart func); + +/** + * Sets the SMC_ParseEnd of a parse handle. + * + * @param smc Handle to an SMC Parse. + * @param func SMC_ParseEnd function. + * @error Invalid or corrupt Handle. + */ +native void SMC_SetParseEnd(Handle smc, SMC_ParseEnd func); + +/** + * 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. + */ +native void SMC_SetReaders(Handle smc, SMC_NewSection ns, SMC_KeyValue kv, SMC_EndSection es); + +/** + * Sets a raw line reader on an SMC parser Handle. + * + * @param smc Handle to an SMC Parse. + * @param func SMC_RawLine function. + */ +native void SMC_SetRawLine(Handle smc, SMC_RawLine func); diff --git a/source/sourcemod/scripting/include/tf2.inc b/source/sourcemod/scripting/include/tf2.inc new file mode 100644 index 0000000..8be97de --- /dev/null +++ b/source/sourcemod/scripting/include/tf2.inc @@ -0,0 +1,501 @@ +/** + * 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 + +#define TF_STUNFLAG_SLOWDOWN (1 << 0) /**< activates slowdown modifier */ +#define TF_STUNFLAG_BONKSTUCK (1 << 1) /**< bonk sound, stuck */ +#define TF_STUNFLAG_LIMITMOVEMENT (1 << 2) /**< disable forward/backward movement */ +#define TF_STUNFLAG_CHEERSOUND (1 << 3) /**< cheering sound */ +#define TF_STUNFLAG_NOSOUNDOREFFECT (1 << 5) /**< no sound or particle */ +#define TF_STUNFLAG_THIRDPERSON (1 << 6) /**< panic animation */ +#define TF_STUNFLAG_GHOSTEFFECT (1 << 7) /**< ghost particles */ +#define TF_STUNFLAG_SOUND (1 << 8) /**< sound */ + +#define TF_STUNFLAGS_LOSERSTATE TF_STUNFLAG_SLOWDOWN|TF_STUNFLAG_NOSOUNDOREFFECT|TF_STUNFLAG_THIRDPERSON +#define TF_STUNFLAGS_GHOSTSCARE TF_STUNFLAG_GHOSTEFFECT|TF_STUNFLAG_THIRDPERSON +#define TF_STUNFLAGS_SMALLBONK TF_STUNFLAG_THIRDPERSON|TF_STUNFLAG_SLOWDOWN +#define TF_STUNFLAGS_NORMALBONK TF_STUNFLAG_BONKSTUCK +#define TF_STUNFLAGS_BIGBONK TF_STUNFLAG_CHEERSOUND|TF_STUNFLAG_BONKSTUCK + +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 +}; + +enum TFCond +{ + TFCond_Slowed = 0, //0: Revving Minigun, Sniper Rifle. Gives zoomed/revved pose + TFCond_Zoomed, //1: Sniper Rifle zooming + TFCond_Disguising, //2: Disguise smoke + TFCond_Disguised, //3: Disguise + TFCond_Cloaked, //4: Cloak effect + TFCond_Ubercharged, //5: Invulnerability, removed when being healed or by another Uber effect + TFCond_TeleportedGlow, //6: Teleport trail effect + TFCond_Taunting, //7: Used for taunting, can remove to stop taunting + TFCond_UberchargeFading, //8: Invulnerability expiration effect + TFCond_Unknown1, //9 + TFCond_CloakFlicker = 9, //9: Cloak flickering effect + TFCond_Teleporting, //10: Used for teleporting, does nothing applying + TFCond_Kritzkrieged, //11: Crit boost, removed when being healed or another Uber effect + TFCond_Unknown2, //12 + TFCond_TmpDamageBonus = 12, //12: Temporary damage buff, something along with attribute 19 + TFCond_DeadRingered, //13: Dead Ringer damage resistance, gives TFCond_Cloaked + TFCond_Bonked, //14: Bonk! Atomic Punch effect + TFCond_Dazed, //15: Slow effect, can remove to remove stun effects + TFCond_Buffed, //16: Buff Banner mini-crits, icon, and glow + TFCond_Charging, //17: Forced forward, charge effect + TFCond_DemoBuff, //18: Eyelander eye glow + TFCond_CritCola, //19: Mini-crit effect + TFCond_InHealRadius, //20: Ring effect, rings disappear after a taunt ends + TFCond_Healing, //21: Used for healing, does nothing applying + TFCond_OnFire, //22: Ignite sound and vocals, can remove to remove afterburn + TFCond_Overhealed, //23: Used for overheal, does nothing applying + TFCond_Jarated, //24: Jarate effect + TFCond_Bleeding, //25: Bleed effect + TFCond_DefenseBuffed, //26: Battalion's Backup's defense, icon, and glow + TFCond_Milked, //27: Mad Milk effect + TFCond_MegaHeal, //28: Quick-Fix Ubercharge's knockback/stun immunity and visual effect + TFCond_RegenBuffed, //29: Concheror's speed boost, heal on hit, icon, and glow + TFCond_MarkedForDeath, //30: Fan o' War marked-for-death effect + TFCond_NoHealingDamageBuff, //31: Mini-crits, blocks healing, glow, no weapon mini-crit effects + TFCond_SpeedBuffAlly, //32: Disciplinary Action speed boost + TFCond_HalloweenCritCandy, //33: Halloween pumpkin crit-boost + TFCond_CritCanteen, //34: Crit-boost and doubles Sentry Gun fire-rate + TFCond_CritDemoCharge, //35: Crit glow, adds TFCond_Charging when charge meter is below 75% + TFCond_CritHype, //36: Soda Popper multi-jump effect + TFCond_CritOnFirstBlood, //37: Arena first blood crit-boost + TFCond_CritOnWin, //38: End-of-round crit-boost (May not remove correctly?) + TFCond_CritOnFlagCapture, //39: Intelligence capture crit-boost + TFCond_CritOnKill, //40: Crit-boost from crit-on-kill weapons + TFCond_RestrictToMelee, //41: Prevents switching once melee is out + TFCond_DefenseBuffNoCritBlock, //42: MvM Bomb Carrier defense buff (TFCond_DefenseBuffed without crit resistance) + TFCond_Reprogrammed, //43: No longer functions + TFCond_CritMmmph, //44: Phlogistinator crit-boost + TFCond_DefenseBuffMmmph, //45: Old Phlogistinator defense buff + TFCond_FocusBuff, //46: Hitman's Heatmaker no-unscope and faster Sniper charge + TFCond_DisguiseRemoved, //47: Enforcer damage bonus removed + TFCond_MarkedForDeathSilent, //48: Marked-for-death without sound effect + TFCond_DisguisedAsDispenser, //49: Dispenser disguise when crouching, max movement speed, sentries ignore player + TFCond_Sapped, //50: Sapper sparkle effect in MvM + TFCond_UberchargedHidden, //51: Out-of-bounds robot invulnerability effect + TFCond_UberchargedCanteen, //52: Invulnerability effect and Sentry Gun damage resistance + TFCond_HalloweenBombHead, //53: Bomb head effect (does not explode) + TFCond_HalloweenThriller, //54: Forced Thriller taunting + TFCond_RadiusHealOnDamage, //55: Radius healing, adds TFCond_InHealRadius, TFCond_Healing. Removed when a taunt ends, but this condition stays but does nothing + TFCond_CritOnDamage, //56: Miscellaneous crit-boost + TFCond_UberchargedOnTakeDamage, //57: Miscellaneous invulnerability + TFCond_UberBulletResist, //58: Vaccinator Uber bullet resistance + TFCond_UberBlastResist, //59: Vaccinator Uber blast resistance + TFCond_UberFireResist, //60: Vaccinator Uber fire resistance + TFCond_SmallBulletResist, //61: Vaccinator healing bullet resistance + TFCond_SmallBlastResist, //62: Vaccinator healing blast resistance + TFCond_SmallFireResist, //63: Vaccinator healing fire resistance + TFCond_Stealthed, //64: Cloaked until next attack + TFCond_MedigunDebuff, //65: Unknown + TFCond_StealthedUserBuffFade, //66: Cloaked, will appear for a few seconds on attack and cloak again + TFCond_BulletImmune, //67: Full bullet immunity + TFCond_BlastImmune, //68: Full blast immunity + TFCond_FireImmune, //69: Full fire immunity + TFCond_PreventDeath, //70: Survive to 1 health, then the condition is removed + TFCond_MVMBotRadiowave, //71: Stuns bots and applies radio effect + TFCond_HalloweenSpeedBoost, //72: Speed boost, non-melee fire rate and reload, infinite air jumps + TFCond_HalloweenQuickHeal, //73: Healing effect, adds TFCond_Healing along with TFCond_MegaHeal temporarily + TFCond_HalloweenGiant, //74: Double size, x10 max health increase, ammo regeneration, and forced thirdperson + TFCond_HalloweenTiny, //75: Half size and increased head size + TFCond_HalloweenInHell, //76: Applies TFCond_HalloweenGhostMode when the player dies + TFCond_HalloweenGhostMode, //77: Becomes a ghost unable to attack but can fly + TFCond_MiniCritOnKill, //78: Mini-crits effect + TFCond_DodgeChance, //79 + TFCond_ObscuredSmoke = 79, //79: 75% chance to dodge an attack + TFCond_Parachute, //80: Parachute effect, removed when touching the ground + TFCond_BlastJumping, //81: Player is blast jumping + TFCond_HalloweenKart, //82: Player forced into a Halloween kart + TFCond_HalloweenKartDash, //83: Forced forward if in TFCond_HalloweenKart, zoom in effect, and dash animations + TFCond_BalloonHead, //84: Big head and lowered gravity + TFCond_MeleeOnly, //85: Forced melee, along with TFCond_SpeedBuffAlly and TFCond_HalloweenTiny + TFCond_SwimmingCurse, //86: Swim in the air with Jarate overlay + TFCond_HalloweenKartNoTurn, //87 + TFCond_FreezeInput = 87, //87: Prevents player from using controls + TFCond_HalloweenKartCage, //88: Puts a cage around the player if in TFCond_HalloweenKart, otherwise crashes + TFCond_HasRune, //89: Has a powerup + TFCond_RuneStrength, //90: Double damage and no damage falloff + TFCond_RuneHaste, //91: Double fire rate, reload speed, clip and ammo size, and 30% faster movement speed + TFCond_RuneRegen, //92: Regen ammo, health, and metal + TFCond_RuneResist, //93: Takes 1/2 damage and critical immunity + TFCond_RuneVampire, //94: Takes 3/4 damage, gain health on damage, and 40% increase in max health + TFCond_RuneWarlock, //95: Attacker takes damage and knockback on hitting the player and 50% increase in max health + TFCond_RunePrecision, //96: Less bullet spread, no damage falloff, 250% faster projectiles, and double damage, faster charge, and faster re-zoom for Sniper Rifles + TFCond_RuneAgility, //97: Increased movement speed, grappling hook speed, jump height, and instant weapon switch + TFCond_GrapplingHook, //98: Used when a player fires their grappling hook, no effect applying or removing + TFCond_GrapplingHookSafeFall, //99: Used when a player is pulled by their grappling hook, no effect applying or removing + TFCond_GrapplingHookLatched, //100: Used when a player latches onto a wall, no effect applying or removing + TFCond_GrapplingHookBleeding, //101: Used when a player is hit by attacker's grappling hook + TFCond_AfterburnImmune, //102: Deadringer afterburn immunity + TFCond_RuneKnockout, //103: Melee and grappling hook only, increased max health, knockback immunity, x4 more damage against buildings, and knockbacks a powerup off a victim on hit + TFCond_RuneImbalance, //104: Prevents gaining a crit-boost or Uber powerups + TFCond_CritRuneTemp, //105: Crit-boost effect + TFCond_PasstimeInterception, //106: Used when a player intercepts the Jack/Ball + TFCond_SwimmingNoEffects, //107: Swimming in the air without animations or overlay + TFCond_EyeaductUnderworld, //108: Refills max health, short Uber, escaped the underworld message on removal + TFCond_KingRune, //109: Increased max health and applies TFCond_KingAura + TFCond_PlagueRune, //110: Radius health kit stealing, increased max health, TFCond_Plague on touching a victim + TFCond_SupernovaRune, //111: Charge meter passively increasing, when charged activiated causes radius Bonk stun + TFCond_Plague, //112: Plague sound effect and message, blocks King powerup health regen + TFCond_KingAura, //113: Increased fire rate, reload speed, and health regen to players in a radius + TFCond_SpawnOutline, //114: Outline and health meter of teammates (and disguised spies) + TFCond_KnockedIntoAir, //115: Used when a player is airblasted + TFCond_CompetitiveWinner, //116: Unknown + TFCond_CompetitiveLoser, //117: Unknown + TFCond_NoTaunting_DEPRECATED, //118 + TFCond_HealingDebuff = 118, //118: Healing debuff from Medics and dispensers + TFCond_PasstimePenaltyDebuff, //119: Marked-for-death effect + TFCond_GrappledToPlayer, //120: Prevents taunting and some Grappling Hook actions + TFCond_GrappledByPlayer, //121: Unknown + TFCond_ParachuteDeployed, //122: Parachute deployed, prevents reopening it + TFCond_Gas, //123: Gas Passer effect + TFCond_BurningPyro, //124: Dragon's Fury afterburn on Pyros + TFCond_RocketPack, //125: Thermal Thruster launched effects, prevents reusing + TFCond_LostFooting, //126: Less ground friction + TFCond_AirCurrent, //127: Reduced air control and friction + TFCond_HalloweenHellHeal, // 128: Used when a player gets teleported to hell + TFCond_PowerupModeDominant, // 129: Reduces effects of certain powerups + TFCond_ImmuneToPushback // 130: Player is immune to pushback effects +}; + +const float TFCondDuration_Infinite = -1.0; + +enum TFHoliday +{ + TFHoliday_Invalid = -1 +}; + +public const TFHoliday TFHoliday_Birthday; +public const TFHoliday TFHoliday_Halloween; +public const TFHoliday TFHoliday_Christmas; +public const TFHoliday TFHoliday_EndOfTheLine; +public const TFHoliday TFHoliday_CommunityUpdate; +public const TFHoliday TFHoliday_ValentinesDay; +public const TFHoliday TFHoliday_MeetThePyro; +public const TFHoliday TFHoliday_FullMoon; +public const TFHoliday TFHoliday_HalloweenOrFullMoon; +public const TFHoliday TFHoliday_HalloweenOrFullMoonOrValentines; +public const TFHoliday TFHoliday_AprilFools; +public const TFHoliday TFHoliday_Soldier; + +enum TFObjectType +{ + TFObject_CartDispenser = 0, + TFObject_Dispenser = 0, + TFObject_Teleporter = 1, + TFObject_Sentry = 2, + TFObject_Sapper = 3 +}; + +enum TFObjectMode +{ + TFObjectMode_None = 0, + TFObjectMode_Entrance = 0, + TFObjectMode_Exit = 1 +}; + +/** + * Sets a client on fire. + * + * @note Fire duration is capped to 10 seconds. + * + * @param client Player's index. + * @param attacker Attacker's index. + * @param duration Duration of fire (in seconds). + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_IgnitePlayer(int client, int attacker, float duration=10.0); + +/** + * Respawns a client + * + * @param client Player's index. + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_RespawnPlayer(int client); + +/** + * Regenerates a client's health and ammunition + * + * @param client Player's index. + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_RegeneratePlayer(int client); + +/** + * Adds a condition to a player + * + * @param client Player's index. + * @param condition Integer identifier of condition to apply. + * @param duration Duration of condition (does not apply to all conditions). + * Pass TFCondDuration_Infinite to apply until manually removed. + * @param inflictor Condition inflictor's index (0 for no inflictor). + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_AddCondition(int client, TFCond condition, float duration=TFCondDuration_Infinite, int inflictor=0); + +/** + * Removes a condition from a player + * + * @param client Player's index. + * @param condition Integer identifier of condition to remove. + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_RemoveCondition(int client, TFCond condition); + +/** + * Enables/disables PowerPlay mode on a player. + * + * @param client Player's index. + * @param enabled Whether to enable or disable PowerPlay on player. + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_SetPlayerPowerPlay(int client, bool enabled); + +/** + * 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 classType TFClassType class to disguise the player as + * @param target Specific target player to disguise as (0 for any) + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_DisguisePlayer(int client, TFTeam team, TFClassType classType, int target=0); + +/** + * Removes the current disguise from a client. Only has an effect on spies. + * + * @param client Player's index. + * @error Invalid client index, client not in game, or no mod support. + */ +native void TF2_RemovePlayerDisguise(int client); + +/** + * Stuns a client + * + * @param client Player's index. + * @param duration Duration of stun. + * @param slowdown Slowdown percent (as decimal, 0.00-1.00) + * Ignored if TF_STUNFLAG_SLOWDOWN is not set. + * @param stunflags Stun flags. + * @param attacker Attacker's index (0 is allowed for world). + */ +native void TF2_StunPlayer(int client, float duration, float slowdown=0.0, int stunflags, int attacker=0); + +/** + * Induces the bleed effect on a client + * + * @param client Player's index. + * @param attacker Attacker's index. + * @param duration Duration of bleeding (in seconds). + */ +native void TF2_MakeBleed(int client, int attacker, float duration); + +/** + * Retrieves the entity index of the CPlayerResource entity + * + * @return The current resource entity index. + * @deprecated Use GetPlayerResourceEntity instead + */ +#pragma deprecated Use GetPlayerResourceEntity instead +native int 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 char[] 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(int client, int weapon, char[] weaponname, bool &result); + +/** + * @deprecated No longer called. Use TF2_OnIsHolidayActive. + */ +#pragma deprecated No longer called. Use TF2_OnIsHolidayActive. +forward Action TF2_OnGetHoliday(TFHoliday &holiday); + +/** + * Called at various times when the game checks to see if the given holiday is active. + * Return Plugin_Continue to let the original calculation or return a higher + * action to override the decision with the value of 'result' + * + * @param holiday Holiday being checked. + * @param result Buffer param for the result of the decision. + * @return Plugin_Continue for original calculation, higher value to use 'result'. + */ +forward Action TF2_OnIsHolidayActive(TFHoliday holiday, bool &result); + +/** + * Returns whether or not a holiday is active + * + * @param holiday Holiday being checked. + * @return Boolean of whether or not the holiday is active. + */ +native bool TF2_IsHolidayActive(TFHoliday holiday); + +/** + * Returns whether or not a client (Player) is in a duel. + * + * @param client Client Index. + * @return Boolean of whether or not the client/player is dueling. + */ +native bool TF2_IsPlayerInDuel(int client); + +/** + * Removes an econ wearable (hat, misc, etc) from a player. + * This also deletes the wearable entity. + * + * @param client Client index. + * @param wearable Index of the wearable entity. + * @error Invalid client index, client not in game, invalid wearable entity, or no mod support. +*/ +native void TF2_RemoveWearable(int client, int wearable); + +/** + * Called after a condition is added to a player + * + * @param client Index of the client to which the condition is being added. + * @param condition Condition that is being added. + */ +forward void TF2_OnConditionAdded(int client, TFCond condition); + +/** + * Called after a condition is removed from a player + * + * @param client Index of the client to which the condition is being removed. + * @param condition Condition that is being removed. + */ +forward void TF2_OnConditionRemoved(int client, TFCond condition); + +/** + * Called when the server enters the Waiting for Players round state + */ +forward void TF2_OnWaitingForPlayersStart(); + +/** + * Called when the server exits the Waiting for Players round state + */ +forward void TF2_OnWaitingForPlayersEnd(); + +/** + * Called when a player attempts to use a teleporter to decide if the player should be allowed to teleport. + * Return Plugin_Continue to let the original calculation or return a higher + * action to override the decision with the value of 'result' + * + * @param client Client index. + * @param teleporter Teleporter entity index. + * @param result Buffer param for the result of the decision. + * This is prepopulated with the game's original decision to let a player teleport. + * @return Plugin_Continue for original calculation, higher value to use 'result'. + */ +forward Action TF2_OnPlayerTeleport(int client, int teleporter, bool &result); + +/** + * Do not edit below this line! + */ +public Extension __ext_tf2 = +{ + name = "TF2 Tools", + file = "game.tf2.ext", + autoload = 0, +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_EXTENSIONS +public void __ext_tf2_SetNTVOptional() +{ + MarkNativeAsOptional("TF2_IgnitePlayer"); + MarkNativeAsOptional("TF2_RespawnPlayer"); + MarkNativeAsOptional("TF2_RegeneratePlayer"); + MarkNativeAsOptional("TF2_AddCondition"); + MarkNativeAsOptional("TF2_RemoveCondition"); + MarkNativeAsOptional("TF2_SetPlayerPowerPlay"); + MarkNativeAsOptional("TF2_DisguisePlayer"); + MarkNativeAsOptional("TF2_RemovePlayerDisguise"); + MarkNativeAsOptional("TF2_StunPlayer"); + MarkNativeAsOptional("TF2_MakeBleed"); + MarkNativeAsOptional("TF2_GetResourceEntity"); + MarkNativeAsOptional("TF2_GetClass"); + MarkNativeAsOptional("TF2_IsPlayerInDuel"); + MarkNativeAsOptional("TF2_IsHolidayActive"); + MarkNativeAsOptional("TF2_RemoveWearable"); +} +#endif diff --git a/source/sourcemod/scripting/include/tf2_stocks.inc b/source/sourcemod/scripting/include/tf2_stocks.inc new file mode 100644 index 0000000..7130332 --- /dev/null +++ b/source/sourcemod/scripting/include/tf2_stocks.inc @@ -0,0 +1,643 @@ +/** + * 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 + +#define TF_CONDFLAG_NONE 0 +#define TF_CONDFLAG_SLOWED (1 << 0) +#define TF_CONDFLAG_ZOOMED (1 << 1) +#define TF_CONDFLAG_DISGUISING (1 << 2) +#define TF_CONDFLAG_DISGUISED (1 << 3) +#define TF_CONDFLAG_CLOAKED (1 << 4) +#define TF_CONDFLAG_UBERCHARGED (1 << 5) +#define TF_CONDFLAG_TELEPORTGLOW (1 << 6) +#define TF_CONDFLAG_TAUNTING (1 << 7) +#define TF_CONDFLAG_UBERCHARGEFADE (1 << 8) +#define TF_CONDFLAG_CLOAKFLICKER (1 << 9) +#define TF_CONDFLAG_TELEPORTING (1 << 10) +#define TF_CONDFLAG_KRITZKRIEGED (1 << 11) +#define TF_CONDFLAG_DEADRINGERED (1 << 13) +#define TF_CONDFLAG_BONKED (1 << 14) +#define TF_CONDFLAG_DAZED (1 << 15) +#define TF_CONDFLAG_BUFFED (1 << 16) +#define TF_CONDFLAG_CHARGING (1 << 17) +#define TF_CONDFLAG_DEMOBUFF (1 << 18) +#define TF_CONDFLAG_CRITCOLA (1 << 19) +#define TF_CONDFLAG_INHEALRADIUS (1 << 20) +#define TF_CONDFLAG_HEALING (1 << 21) +#define TF_CONDFLAG_ONFIRE (1 << 22) +#define TF_CONDFLAG_OVERHEALED (1 << 23) +#define TF_CONDFLAG_JARATED (1 << 24) +#define TF_CONDFLAG_BLEEDING (1 << 25) +#define TF_CONDFLAG_DEFENSEBUFFED (1 << 26) +#define TF_CONDFLAG_MILKED (1 << 27) +#define TF_CONDFLAG_MEGAHEAL (1 << 28) +#define TF_CONDFLAG_REGENBUFFED (1 << 29) +#define TF_CONDFLAG_MARKEDFORDEATH (1 << 30) + +#define TF_DEATHFLAG_KILLERDOMINATION (1 << 0) +#define TF_DEATHFLAG_ASSISTERDOMINATION (1 << 1) +#define TF_DEATHFLAG_KILLERREVENGE (1 << 2) +#define TF_DEATHFLAG_ASSISTERREVENGE (1 << 3) +#define TF_DEATHFLAG_FIRSTBLOOD (1 << 4) +#define TF_DEATHFLAG_DEADRINGER (1 << 5) +#define TF_DEATHFLAG_INTERRUPTED (1 << 6) +#define TF_DEATHFLAG_GIBBED (1 << 7) +#define TF_DEATHFLAG_PURGATORY (1 << 8) +#define TF_DEATHFLAG_MINIBOSS (1 << 9) +#define TF_DEATHFLAG_AUSTRALIUM (1 << 10) + +// Custom kill identifiers for the customkill property on the player_death event +enum { + TF_CUSTOM_HEADSHOT = 1, + TF_CUSTOM_BACKSTAB, + TF_CUSTOM_BURNING, + TF_CUSTOM_WRENCH_FIX, + TF_CUSTOM_MINIGUN, + TF_CUSTOM_SUICIDE, + TF_CUSTOM_TAUNT_HADOUKEN, + TF_CUSTOM_BURNING_FLARE, + TF_CUSTOM_TAUNT_HIGH_NOON, + TF_CUSTOM_TAUNT_GRAND_SLAM, + TF_CUSTOM_PENETRATE_MY_TEAM, + TF_CUSTOM_PENETRATE_ALL_PLAYERS, + TF_CUSTOM_TAUNT_FENCING, + TF_CUSTOM_PENETRATE_HEADSHOT, + TF_CUSTOM_TAUNT_ARROW_STAB, + TF_CUSTOM_TELEFRAG, + TF_CUSTOM_BURNING_ARROW, + TF_CUSTOM_FLYINGBURN, + TF_CUSTOM_PUMPKIN_BOMB, + TF_CUSTOM_DECAPITATION, + TF_CUSTOM_TAUNT_GRENADE, + TF_CUSTOM_BASEBALL, + TF_CUSTOM_CHARGE_IMPACT, + TF_CUSTOM_TAUNT_BARBARIAN_SWING, + TF_CUSTOM_AIR_STICKY_BURST, + TF_CUSTOM_DEFENSIVE_STICKY, + TF_CUSTOM_PICKAXE, + TF_CUSTOM_ROCKET_DIRECTHIT, + TF_CUSTOM_TAUNT_UBERSLICE, + TF_CUSTOM_PLAYER_SENTRY, + TF_CUSTOM_STANDARD_STICKY, + TF_CUSTOM_SHOTGUN_REVENGE_CRIT, + TF_CUSTOM_TAUNT_ENGINEER_SMASH, + TF_CUSTOM_BLEEDING, + TF_CUSTOM_GOLD_WRENCH, + TF_CUSTOM_CARRIED_BUILDING, + TF_CUSTOM_COMBO_PUNCH, + TF_CUSTOM_TAUNT_ENGINEER_ARM, + TF_CUSTOM_FISH_KILL, + TF_CUSTOM_TRIGGER_HURT, + TF_CUSTOM_DECAPITATION_BOSS, + TF_CUSTOM_STICKBOMB_EXPLOSION, + TF_CUSTOM_AEGIS_ROUND, + TF_CUSTOM_FLARE_EXPLOSION, + TF_CUSTOM_BOOTS_STOMP, + TF_CUSTOM_PLASMA, + TF_CUSTOM_PLASMA_CHARGED, + TF_CUSTOM_PLASMA_GIB, + TF_CUSTOM_PRACTICE_STICKY, + TF_CUSTOM_EYEBALL_ROCKET, + TF_CUSTOM_HEADSHOT_DECAPITATION, + TF_CUSTOM_TAUNT_ARMAGEDDON, + TF_CUSTOM_FLARE_PELLET, + TF_CUSTOM_CLEAVER, + TF_CUSTOM_CLEAVER_CRIT, + TF_CUSTOM_SAPPER_RECORDER_DEATH, + TF_CUSTOM_MERASMUS_PLAYER_BOMB, + TF_CUSTOM_MERASMUS_GRENADE, + TF_CUSTOM_MERASMUS_ZAP, + TF_CUSTOM_MERASMUS_DECAPITATION, + TF_CUSTOM_CANNONBALL_PUSH, + TF_CUSTOM_TAUNT_ALLCLASS_GUITAR_RIFF, + TF_CUSTOM_THROWABLE, + TF_CUSTOM_THROWABLE_KILL, + TF_CUSTOM_SPELL_TELEPORT, + TF_CUSTOM_SPELL_SKELETON, + TF_CUSTOM_SPELL_MIRV, + TF_CUSTOM_SPELL_METEOR, + TF_CUSTOM_SPELL_LIGHTNING, + TF_CUSTOM_SPELL_FIREBALL, + TF_CUSTOM_SPELL_MONOCULUS, + TF_CUSTOM_SPELL_BLASTJUMP, + TF_CUSTOM_SPELL_BATS, + TF_CUSTOM_SPELL_TINY, + TF_CUSTOM_KART, + TF_CUSTOM_GIANT_HAMMER, + TF_CUSTOM_RUNE_REFLECT, + TF_CUSTOM_DRAGONS_FURY_IGNITE, + TF_CUSTOM_DRAGONS_FURY_BONUS_BURNING, + TF_CUSTOM_SLAP_KILL, + TF_CUSTOM_CROC, + TF_CUSTOM_TAUNTATK_GASBLAST, + TF_CUSTOM_AXTINGUISHER_BOOSTED +}; + +// Weapon codes as used in some events, such as player_death +// (not to be confused with Item Definition Indexes) +enum { + TF_WEAPON_NONE = 0, + TF_WEAPON_BAT, + TF_WEAPON_BAT_WOOD, + TF_WEAPON_BOTTLE, + TF_WEAPON_FIREAXE, + TF_WEAPON_CLUB, + TF_WEAPON_CROWBAR, + TF_WEAPON_KNIFE, + TF_WEAPON_FISTS, + TF_WEAPON_SHOVEL, + TF_WEAPON_WRENCH, + TF_WEAPON_BONESAW, + TF_WEAPON_SHOTGUN_PRIMARY, + TF_WEAPON_SHOTGUN_SOLDIER, + TF_WEAPON_SHOTGUN_HWG, + TF_WEAPON_SHOTGUN_PYRO, + TF_WEAPON_SCATTERGUN, + TF_WEAPON_SNIPERRIFLE, + TF_WEAPON_MINIGUN, + TF_WEAPON_SMG, + TF_WEAPON_SYRINGEGUN_MEDIC, + TF_WEAPON_TRANQ, + TF_WEAPON_ROCKETLAUNCHER, + TF_WEAPON_GRENADELAUNCHER, + TF_WEAPON_PIPEBOMBLAUNCHER, + TF_WEAPON_FLAMETHROWER, + TF_WEAPON_GRENADE_NORMAL, + TF_WEAPON_GRENADE_CONCUSSION, + TF_WEAPON_GRENADE_NAIL, + TF_WEAPON_GRENADE_MIRV, + TF_WEAPON_GRENADE_MIRV_DEMOMAN, + TF_WEAPON_GRENADE_NAPALM, + TF_WEAPON_GRENADE_GAS, + TF_WEAPON_GRENADE_EMP, + TF_WEAPON_GRENADE_CALTROP, + TF_WEAPON_GRENADE_PIPEBOMB, + TF_WEAPON_GRENADE_SMOKE_BOMB, + TF_WEAPON_GRENADE_HEAL, + TF_WEAPON_GRENADE_STUNBALL, + TF_WEAPON_GRENADE_JAR, + TF_WEAPON_GRENADE_JAR_MILK, + TF_WEAPON_PISTOL, + TF_WEAPON_PISTOL_SCOUT, + TF_WEAPON_REVOLVER, + TF_WEAPON_NAILGUN, + TF_WEAPON_PDA, + TF_WEAPON_PDA_ENGINEER_BUILD, + TF_WEAPON_PDA_ENGINEER_DESTROY, + TF_WEAPON_PDA_SPY, + TF_WEAPON_BUILDER, + TF_WEAPON_MEDIGUN, + TF_WEAPON_GRENADE_MIRVBOMB, + TF_WEAPON_FLAMETHROWER_ROCKET, + TF_WEAPON_GRENADE_DEMOMAN, + TF_WEAPON_SENTRY_BULLET, + TF_WEAPON_SENTRY_ROCKET, + TF_WEAPON_DISPENSER, + TF_WEAPON_INVIS, + TF_WEAPON_FLAREGUN, + TF_WEAPON_LUNCHBOX, + TF_WEAPON_JAR, + TF_WEAPON_COMPOUND_BOW, + TF_WEAPON_BUFF_ITEM, + TF_WEAPON_PUMPKIN_BOMB, + TF_WEAPON_SWORD, + TF_WEAPON_DIRECTHIT, + TF_WEAPON_LIFELINE, + TF_WEAPON_LASER_POINTER, + TF_WEAPON_DISPENSER_GUN, + TF_WEAPON_SENTRY_REVENGE, + TF_WEAPON_JAR_MILK, + TF_WEAPON_HANDGUN_SCOUT_PRIMARY, + TF_WEAPON_BAT_FISH, + TF_WEAPON_CROSSBOW, + TF_WEAPON_STICKBOMB, + TF_WEAPON_HANDGUN_SCOUT_SEC, + TF_WEAPON_SODA_POPPER, + TF_WEAPON_SNIPERRIFLE_DECAP, + TF_WEAPON_RAYGUN, + TF_WEAPON_PARTICLE_CANNON, + TF_WEAPON_MECHANICAL_ARM, + TF_WEAPON_DRG_POMSON, + TF_WEAPON_BAT_GIFTWRAP, + TF_WEAPON_GRENADE_ORNAMENT, + TF_WEAPON_RAYGUN_REVENGE, + TF_WEAPON_PEP_BRAWLER_BLASTER, + TF_WEAPON_CLEAVER, + TF_WEAPON_GRENADE_CLEAVER, + TF_WEAPON_STICKY_BALL_LAUNCHER, + TF_WEAPON_GRENADE_STICKY_BALL, + TF_WEAPON_SHOTGUN_BUILDING_RESCUE, + TF_WEAPON_CANNON, + TF_WEAPON_THROWABLE, + TF_WEAPON_GRENADE_THROWABLE, + TF_WEAPON_PDA_SPY_BUILD, + TF_WEAPON_GRENADE_WATERBALLOON, + TF_WEAPON_HARVESTER_SAW, + TF_WEAPON_SPELLBOOK, + TF_WEAPON_SPELLBOOK_PROJECTILE, + TF_WEAPON_SNIPERRIFLE_CLASSIC, + TF_WEAPON_PARACHUTE, + TF_WEAPON_GRAPPLINGHOOK, + TF_WEAPON_PASSTIME_GUN, + TF_WEAPON_CHARGED_SMG, + TF_WEAPON_BREAKABLE_SIGN, + TF_WEAPON_ROCKETPACK, + TF_WEAPON_SLAP, + TF_WEAPON_JAR_GAS, + TF_WEAPON_GRENADE_JAR_GAS, + TF_WEAPON_FLAME_BALL +}; + +// TF2 Weapon Loadout Slots +enum +{ + TFWeaponSlot_Primary, + TFWeaponSlot_Secondary, + TFWeaponSlot_Melee, + TFWeaponSlot_Grenade, + TFWeaponSlot_Building, + TFWeaponSlot_PDA, + TFWeaponSlot_Item1, + TFWeaponSlot_Item2 +}; + +// Identifiers for the eventtype property on the teamplay_flag_event event +enum { + TF_FLAGEVENT_PICKEDUP = 1, + TF_FLAGEVENT_CAPTURED, + TF_FLAGEVENT_DEFENDED, + TF_FLAGEVENT_DROPPED, + TF_FLAGEVENT_RETURNED +}; + +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 char TFResourceNames[][] = +{ + "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" +}; + +/** + * Gets a client's current team. + * + * @param client Client index. + * @return Current TFTeam of client. + * @error Invalid client index. + */ +stock TFTeam TF2_GetClientTeam(int client) +{ + return view_as(GetClientTeam(client)); +} + +/** + * Changes a client's current team. + * + * @param client Client index. + * @param team TFTeam team symbol. + * @error Invalid client index. + */ +stock void TF2_ChangeClientTeam(int client, TFTeam team) +{ + ChangeClientTeam(client, view_as(team)); +} + +/** + * Gets a client's current class. + * + * @param client Player's index. + * @return Current TFClassType of player. + * @error Invalid client index. + */ +stock TFClassType TF2_GetPlayerClass(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_iClass")); +} + +/** + * Sets a client's class. + * + * Note: If setting player class in a player spawn hook weapons should be set to false. + * + * @param client Player's index. + * @param classType TFClassType class symbol. + * @param weapons This parameter is ignored. + * @param persistent If true, changes the player's desired class so the change stays after death. + * @error Invalid client index. + */ +stock void TF2_SetPlayerClass(int client, TFClassType classType, bool weapons=true, bool persistent=true) +{ + SetEntProp(client, Prop_Send, "m_iClass", view_as(classType)); + + if (persistent) + { + SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", view_as(classType)); + } +} + +/** + * 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. + * @deprecated Use GetPlayerResourceEntity and GetEntProp instead. + */ +#pragma deprecated Use GetPlayerResourceEntity and GetEntProp instead +stock int TF2_GetPlayerResourceData(int client, TFResourceType type) +{ + if (!IsClientConnected(client)) + { + return -1; + } + + int offset = FindSendPropInfo("CTFPlayerResource", TFResourceNames[type]); + + if (offset < 1) + { + return -1; + } + + int entity = GetPlayerResourceEntity(); + + 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. + * @deprecated Use GetPlayerResourceEntity and SetEntProp instead. + */ +#pragma deprecated Use GetPlayerResourceEntity and SetEntProp instead +stock bool TF2_SetPlayerResourceData(int client, TFResourceType type, any value) +{ + if (!IsClientConnected(client)) + { + return false; + } + + int offset = FindSendPropInfo("CTFPlayerResource", TFResourceNames[type]); + + if (offset < 1) + { + return false; + } + + int entity = GetPlayerResourceEntity(); + + 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) + * @error Invalid client, invalid slot or lack of mod support + */ +stock void TF2_RemoveWeaponSlot(int client, int slot) +{ + int weaponIndex; + while ((weaponIndex = GetPlayerWeaponSlot(client, slot)) != -1) + { + // bug #6206 + // papering over a valve bug where a weapon's extra wearables aren't properly removed from the weapon's owner + int extraWearable = GetEntPropEnt(weaponIndex, Prop_Send, "m_hExtraWearable"); + if (extraWearable != -1) + { + TF2_RemoveWearable(client, extraWearable); + } + + extraWearable = GetEntPropEnt(weaponIndex, Prop_Send, "m_hExtraWearableViewModel"); + if (extraWearable != -1) + { + TF2_RemoveWearable(client, extraWearable); + } + + RemovePlayerItem(client, weaponIndex); + AcceptEntityInput(weaponIndex, "Kill"); + } +} + +/** + * Removes all weapons from a client + * + * @param client Player's index. + */ +stock void TF2_RemoveAllWeapons(int client) +{ + for (int i = 0; i <= 5; i++) + { + TF2_RemoveWeaponSlot(client, i); + } +} + +/** + * Gets a player's condition bits + * + * @param client Player's index. + * @return Player's condition bits + * @deprecated Use TF2_IsPlayerInCondition instead. + */ +#pragma deprecated Use TF2_IsPlayerInCondition instead. +stock int TF2_GetPlayerConditionFlags(int client) +{ + return GetEntProp(client, Prop_Send, "m_nPlayerCond")|GetEntProp(client, Prop_Send, "_condition_bits"); +} + +/** + * Check whether or not a condition is set on a player + * + * @param client Player's index. + * @param cond TFCond constant + * @return True if set, false otherwise + */ +stock bool TF2_IsPlayerInCondition(int client, TFCond cond) +{ + // Conditions are stored across multiple netprops now, one for each 32-bit segment. + int iCond = view_as(cond); + switch (iCond / 32) + { + case 0: + { + int bit = 1 << iCond; + if ((GetEntProp(client, Prop_Send, "m_nPlayerCond") & bit) == bit) + { + return true; + } + + if ((GetEntProp(client, Prop_Send, "_condition_bits") & bit) == bit) + { + return true; + } + } + case 1: + { + int bit = (1 << (iCond - 32)); + if ((GetEntProp(client, Prop_Send, "m_nPlayerCondEx") & bit) == bit) + { + return true; + } + } + case 2: + { + int bit = (1 << (iCond - 64)); + if ((GetEntProp(client, Prop_Send, "m_nPlayerCondEx2") & bit) == bit) + { + return true; + } + } + case 3: + { + int bit = (1 << (iCond - 96)); + if ((GetEntProp(client, Prop_Send, "m_nPlayerCondEx3") & bit) == bit) + { + return true; + } + } + case 4: + { + int bit = (1 << (iCond - 128)); + if ((GetEntProp(client, Prop_Send, "m_nPlayerCondEx4") & bit) == bit) + { + return true; + } + } + default: + { + ThrowError("Invalid TFCond value %d", iCond); + } + } + + return false; +} + +/** + * Gets an entity's object type. + * + * @param entity Entity index. + * @return Current TFObjectType of entity. + * @error Invalid entity index. + */ +stock TFObjectType TF2_GetObjectType(int entity) +{ + int offset = GetEntSendPropOffs(entity, "m_iObjectType"); + + if (offset <= 0) + { + ThrowError("Entity index %d is not an object", entity); + } + + return view_as(GetEntData(entity, offset)); +} + +/** + * Gets an entity's object mode. + * + * @param entity Entity index. + * @return Current TFObjectMode of entity. + * @error Invalid entity index. + */ +stock TFObjectMode TF2_GetObjectMode(int entity) +{ + int offset = GetEntSendPropOffs(entity, "m_iObjectMode"); + + if (offset <= 0) + { + ThrowError("Entity index %d is not an object", entity); + } + + return view_as(GetEntData(entity, offset)); +} diff --git a/source/sourcemod/scripting/include/timers.inc b/source/sourcemod/scripting/include/timers.inc new file mode 100644 index 0000000..0da2460 --- /dev/null +++ b/source/sourcemod/scripting/include/timers.inc @@ -0,0 +1,200 @@ +/** + * 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. + */ +typeset Timer +{ + /** + * Called when the timer interval has elapsed. + * + * @param timer Handle to the timer object. + * @param data Handle or value passed to CreateTimer() when timer was created. + * @return Plugin_Stop to stop a repeating timer, any other value for + * default behavior. + */ + function Action(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. + */ + function Action(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=0, int flags=0); + +/** + * Kills a timer. Use this instead of CloseHandle() if you need more options. + * + * @param timer Timer Handle to kill. + * @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. + * @error Invalid timer handle. + */ +native void 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. + * @error Invalid timer handle. + */ +native void 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(int &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(int &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(int 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 void 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. + * If server hibernation is disabled, once the first player has joined, even if that player + * leaves, the server's timers and entities will continue to 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, int flags=0) +{ + datapack = new DataPack(); + flags |= TIMER_DATA_HNDL_CLOSE; + return CreateTimer(interval, func, datapack, flags); +} diff --git a/source/sourcemod/scripting/include/topmenus.inc b/source/sourcemod/scripting/include/topmenus.inc new file mode 100644 index 0000000..800610c --- /dev/null +++ b/source/sourcemod/scripting/include/topmenus.inc @@ -0,0 +1,446 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet: + * ============================================================================= + * 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 topobj. + */ +enum TopMenuAction +{ + /** + * An option is being drawn for a menu (or for sorting purposes). + * + * INPUT : TopMenu Handle, topobj ID, client index. + * OUTPUT: Buffer for rendering, maxlength of buffer. + */ + TopMenuAction_DisplayOption = 0, + + /** + * The title of a menu is being drawn for a given topobj. + * + * Note: The Object ID will be INVALID_TOPMENUOBJECT if drawing the + * root title. Otherwise, the Object ID is a category. + * + * INPUT : TopMenu Handle, topobj 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, topobj ID, client index. + */ + TopMenuAction_SelectOption = 2, + + /** + * A menu option is being drawn and its flags can be overridden. + * + * INPUT : TopMenu Handle, topobj 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 topobj is being removed from the menu. + * This can be used to clean up data stored in the info string. + * + * INPUT : TopMenu Handle, topobj ID. + */ + TopMenuAction_RemoveObject = 4 +}; + +/** + * Top menu topobj 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 topobj tag for type checking. + */ +enum TopMenuObject +{ + INVALID_TOPMENUOBJECT = 0 +}; + +/** + * TopMenu callback prototype. + * + * @param topmenu Handle to the TopMenu. + * @param action TopMenuAction being performed. + * @param topobj_id The topobj ID (if used). + * @param param Extra parameter (if used). + * @param buffer Output buffer (if used). + * @param maxlength Output buffer (if used). + */ +typedef TopMenuHandler = function void ( + TopMenu topmenu, + TopMenuAction action, + TopMenuObject topobj_id, + int param, + char[] buffer, + int maxlength +); + +// TopMenu objects are used for constructing multi-layer menus. Currently, they +// support at most two levels. The first level of items are called "categories". +methodmap TopMenu < Handle +{ + // Creates a new TopMenu. + // + // @param handler Handler to use for drawing the root title. + // @return A new TopMenu. + public native TopMenu(TopMenuHandler handler); + + // Returns a TopMenu handle from a generic handle. If the given handle is + // a TopMenu, the handle is simply casted back. Otherwise, an error is + // raised. + public static native TopMenu FromHandle(Handle handle); + + // 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. + public native bool LoadConfig(const char[] file, char[] error, int maxlength); + + // Adds a category to a TopMenu. + // + // @param name Object name (MUST be unique). + // @param handler Handler for topobj. + // @param cmdname Command name (for access overrides). + // @param flags Default access flags. + // @param info_string Arbitrary storage (max 255 bytes). + // @return A new TopMenuObject ID, or INVALID_TOPMENUOBJECT on failure. + public native TopMenuObject AddCategory(const char[] name, TopMenuHandler handler, + const char[] cmdname = "", int flags = 0, + const char[] info_string = ""); + + // Adds an item to a TopMenu category. + // + // @param name Object name (MUST be unique). + // @param handler Handler for topobj. + // @param category The object of the parent category for the item. + // @param cmdname Command name (for access overrides). + // @param flags Default access flags. + // @param info_string Arbitrary storage (max 255 bytes). + // @return A new TopMenuObject ID, or INVALID_TOPMENUOBJECT on failure. + public native TopMenuObject AddItem(const char[] name, TopMenuHandler handler, + TopMenuObject parent, const char[] cmdname = "", + int flags = 0, const char[] info_string = ""); + + // Retrieves the info string of a top menu item. + // + // @param parent 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. + public native int GetInfoString(TopMenuObject parent, char[] buffer, int maxlength); + + // Retrieves the name string of a top menu item. + // + // @param topobj 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. + public native int GetObjName(TopMenuObject topobj, char[] buffer, int maxlength); + + // Removes an topobj from a TopMenu. + // + // Plugins' topobjs are automatically removed all TopMenus when the given + // plugin unloads or pauses. In the case of unpausing, all items are restored. + // + // @param topobj TopMenuObject ID. + public native void Remove(TopMenuObject topobj); + + // Displays a TopMenu to a client. + // + // @param client Client index. + // @param position Position to display from. + // @return True on success, false on failure. + public native bool Display(int client, TopMenuPosition position); + + // Displays a TopMenu category to a client. + // + // @param category Category topobj id. + // @param client Client index. + // @return True on success, false on failure. + public native bool DisplayCategory(TopMenuObject category, int client); + + // Finds a category's topobj ID in a TopMenu. + // + // @param name Object's unique name. + // @return TopMenuObject ID on success, or + // INVALID_TOPMENUOBJECT on failure. + public native TopMenuObject FindCategory(const char[] name); + + // Set the menu title caching behavior of the TopMenu. By default titles + // are cached to reduce overhead. If you need dynamic menu titles which + // change each time the menu is displayed to a user, set this to false. + property bool CacheTitles { + public native set(bool value); + } +}; + +/** + * Creates a TopMenu. + * + * @param handler Handler to use for drawing the root title. + * @return A new TopMenu Handle, or INVALID_HANDLE on failure. + */ +native TopMenu 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 char[] file, char[] error, int maxlength); + +/** + * Adds an topobj to a TopMenu. + * + * @param topmenu TopMenu Handle. + * @param name Object name (MUST be unique). + * @param type Object type. + * @param handler Handler for topobj. + * @param parent Parent topobj ID, or INVALID_TOPMENUOBJECT for none. + * Items must have a category parent. + * Categories must not have a parent. + * @param cmdname Command name (for access overrides). + * @param flags Default access flags. + * @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 char[] name, + TopMenuObjectType type, + TopMenuHandler handler, + TopMenuObject parent, + const char[] cmdname="", + int flags=0, + const char[] info_string=""); + +/** + * Retrieves the info string of a top menu item. + * + * @param topmenu TopMenu Handle. + * @param parent 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 int GetTopMenuInfoString(Handle topmenu, TopMenuObject parent, char[] buffer, int maxlength); + +/** + * Retrieves the name string of a top menu item. + * + * @param topmenu TopMenu Handle. + * @param topobj 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 int GetTopMenuObjName(Handle topmenu, TopMenuObject topobj, char[] buffer, int maxlength); + +/** + * Removes an topobj from a TopMenu. + * + * Plugins' topobjs 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 topobj TopMenuObject ID. + * @error Invalid TopMenu Handle. + */ +native void RemoveFromTopMenu(Handle topmenu, TopMenuObject topobj); + +/** + * 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, invalid client index, or client not in game. + */ +native bool DisplayTopMenu(Handle topmenu, int client, TopMenuPosition position); + +/** + * Displays a TopMenu category to a client. + * + * @param topmenu TopMenu Handle. + * @param category Category topobj id. + * @param client Client index. + * @return True on success, false on failure. + * @error Invalid TopMenu Handle, invalid client index, or client not in game. + */ +native bool DisplayTopMenuCategory(Handle topmenu, TopMenuObject category, int client); + +/** + * Finds a category's topobj 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 char[] name); + +/** + * Change the menu title caching behavior of the TopMenu. By default the + * titles are cached to reduce overhead. If you need dynamic menu titles, which + * can change everytime the menu is displayed to a user, set this to false. + * + * @param topmenu TopMenu Handle. + * @param cache_titles Cache the menu titles and don't call the handler with + * TopMenuAction_DisplayTitle everytime the menu is drawn? + * @error Invalid TopMenu Handle + */ +native void SetTopMenuTitleCaching(Handle topmenu, bool cache_titles); + + +/** + * 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 void __ext_topmenus_SetNTVOptional() +{ + MarkNativeAsOptional("CreateTopMenu"); + MarkNativeAsOptional("LoadTopMenuConfig"); + MarkNativeAsOptional("AddToTopMenu"); + MarkNativeAsOptional("RemoveFromTopMenu"); + MarkNativeAsOptional("DisplayTopMenu"); + MarkNativeAsOptional("DisplayTopMenuCategory"); + MarkNativeAsOptional("FindTopMenuCategory"); + MarkNativeAsOptional("SetTopMenuTitleCaching"); + MarkNativeAsOptional("TopMenu.TopMenu"); + MarkNativeAsOptional("TopMenu.FromHandle"); + MarkNativeAsOptional("TopMenu.LoadConfig"); + MarkNativeAsOptional("TopMenu.AddCategory"); + MarkNativeAsOptional("TopMenu.AddItem"); + MarkNativeAsOptional("TopMenu.GetInfoString"); + MarkNativeAsOptional("TopMenu.GetObjName"); + MarkNativeAsOptional("TopMenu.Remove"); + MarkNativeAsOptional("TopMenu.Display"); + MarkNativeAsOptional("TopMenu.DisplayCategory"); + MarkNativeAsOptional("TopMenu.FindCategory"); + MarkNativeAsOptional("TopMenu.CacheTitles.set"); +} +#endif diff --git a/source/sourcemod/scripting/include/updater.inc b/source/sourcemod/scripting/include/updater.inc new file mode 100644 index 0000000..f37bdf2 --- /dev/null +++ b/source/sourcemod/scripting/include/updater.inc @@ -0,0 +1,97 @@ +#if defined _updater_included + #endinput +#endif +#define _updater_included + +/** + * Adds your plugin to the updater. The URL will be updated if + * your plugin was previously added. + * + * @param url URL to your plugin's update file. + * @noreturn + */ +native Updater_AddPlugin(const String:url[]); + +/** + * Removes your plugin from the updater. This does not need to + * be called during OnPluginEnd. + * + * @noreturn + */ +native Updater_RemovePlugin(); + +/** + * Forces your plugin to be checked for updates. The behaviour + * of the update is dependant on the server's configuration. + * + * @return True if an update was triggered. False otherwise. + * @error Plugin not found in updater. + */ +native bool:Updater_ForceUpdate(); + +/** + * Called when your plugin is about to be checked for updates. + * + * @return Plugin_Handled to prevent checking, Plugin_Continue to allow it. + */ +forward Action:Updater_OnPluginChecking(); + +/** + * Called when your plugin is about to begin downloading an available update. + * + * @return Plugin_Handled to prevent downloading, Plugin_Continue to allow it. + */ +forward Action:Updater_OnPluginDownloading(); + +/** + * Called when your plugin's update files have been fully downloaded + * and are about to write to their proper location. This should be used + * to free read-only resources that require write access for your update. + * + * @note OnPluginUpdated will be called later during the same frame. + * + * @noreturn + */ +forward Updater_OnPluginUpdating(); + +/** + * Called when your plugin's update has been completed. It is safe + * to reload your plugin at this time. + * + * @noreturn + */ +forward Updater_OnPluginUpdated(); + +/** + * @brief Reloads a plugin. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @noreturn + */ +stock ReloadPlugin(Handle:plugin=INVALID_HANDLE) +{ + decl String:filename[64]; + GetPluginFilename(plugin, filename, sizeof(filename)); + ServerCommand("sm plugins reload %s", filename); +} + + +public SharedPlugin:__pl_updater = +{ + name = "updater", + file = "updater.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public __pl_updater_SetNTVOptional() +{ + MarkNativeAsOptional("Updater_AddPlugin"); + MarkNativeAsOptional("Updater_RemovePlugin"); + MarkNativeAsOptional("Updater_ForceUpdate"); +} +#endif diff --git a/source/sourcemod/scripting/include/usermessages.inc b/source/sourcemod/scripting/include/usermessages.inc new file mode 100644 index 0000000..0a43f3f --- /dev/null +++ b/source/sourcemod/scripting/include/usermessages.inc @@ -0,0 +1,270 @@ +/** + * 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 +}; + +/** + * UserMsg message serialization formats + */ +enum UserMessageType +{ + UM_BitBuf = 0, + UM_Protobuf +}; + +/** + * @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 usermessage serialization type used for the current engine + * + * @return The supported usermessage type. + */ +native UserMessageType GetUserMessageType(); + +stock Protobuf UserMessageToProtobuf(Handle msg) +{ + if (GetUserMessageType() != UM_Protobuf) + { + return null; + } + + return view_as(msg); +} + +// Make sure to only call this on writable buffers (eg from StartMessage). +stock BfWrite UserMessageToBfWrite(Handle msg) +{ + if (GetUserMessageType() == UM_Protobuf) + { + return null; + } + + return view_as(msg); +} + +// Make sure to only call this on readable buffers (eg from a message hook). +stock BfRead UserMessageToBfRead(Handle msg) +{ + if (GetUserMessageType() == UM_Protobuf) + { + return null; + } + + return view_as(msg); +} + +/** + * 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 char[] 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, char[] msg, int 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(const char[] msgname, const int[] clients, int numClients, int 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, const int[] clients, int numClients, int flags=0); + +/** + * Ends a previously started user message (network message). + */ +native void EndMessage(); + +/** + * Hook function types for user messages. +*/ +typeset MsgHook +{ + /** + * Called when a bit buffer based usermessage is hooked + * + * @param msg_id Message index. + * @param msg Handle to the input bit buffer. + * @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. + */ + function Action (UserMsg msg_id, BfRead msg, const int[] players, int playersNum, bool reliable, bool init); + /** + * Called when a protobuf based usermessage is hooked + * + * @param msg_id Message index. + * @param msg Handle to the input protobuf. + * @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. + */ + function Action (UserMsg msg_id, Protobuf msg, const int[] players, int 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. + */ +typedef MsgPostHook = function void (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 post Notification function. + * @error Invalid message index. + */ +native void HookUserMessage(UserMsg msg_id, MsgHook hook, bool intercept=false, MsgPostHook post=INVALID_FUNCTION); + +/** + * 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. + * @error Invalid message index. + */ +native void 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(const char[] msgname, int flags=0) +{ + int total = 0; + int[] clients = new int[MaxClients]; + for (int 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(const char[] msgname, int client, int flags=0) +{ + int players[1]; + players[0] = client; + + return StartMessage(msgname, players, 1, flags); +} diff --git a/source/sourcemod/scripting/include/vector.inc b/source/sourcemod/scripting/include/vector.inc new file mode 100644 index 0000000..3cfe21c --- /dev/null +++ b/source/sourcemod/scripting/include/vector.inc @@ -0,0 +1,179 @@ +/** + * 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. + */ +native void 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. + */ +native void 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. + */ +native void 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. + */ +native void 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. + */ +stock void 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. + */ +stock void 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. + */ +stock void ScaleVector(float vec[3], float scale) +{ + vec[0] *= scale; + vec[1] *= scale; + vec[2] *= scale; +} + +/** + * Negatives a vector. + * + * @param vec Vector. + */ +stock void 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. + */ +stock void 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/source/sourcemod/scripting/include/version.inc b/source/sourcemod/scripting/include/version.inc new file mode 100644 index 0000000..d7b632c --- /dev/null +++ b/source/sourcemod/scripting/include/version.inc @@ -0,0 +1,49 @@ +/** + * 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 + +#tryinclude + +#if !defined _auto_version_included + #define SOURCEMOD_V_TAG "manual" + #define SOURCEMOD_V_REV 0 + #define SOURCEMOD_V_CSET "0" + #define SOURCEMOD_V_MAJOR 1 /**< SourceMod Major version */ + #define SOURCEMOD_V_MINOR 11 /**< SourceMod Minor version */ + #define SOURCEMOD_V_RELEASE 0 /**< SourceMod Release version */ + + #define SOURCEMOD_VERSION "1.11.0-manual" /**< SourceMod version string (major.minor.release-tag) */ +#endif diff --git a/source/sourcemod/scripting/include/version_auto.inc b/source/sourcemod/scripting/include/version_auto.inc new file mode 100644 index 0000000..ffe03c1 --- /dev/null +++ b/source/sourcemod/scripting/include/version_auto.inc @@ -0,0 +1,15 @@ + +#if defined _auto_version_included + #endinput +#endif +#define _auto_version_included + +#define SOURCEMOD_V_TAG "" +#define SOURCEMOD_V_CSET "efd526f0" +#define SOURCEMOD_V_MAJOR 1 +#define SOURCEMOD_V_MINOR 11 +#define SOURCEMOD_V_RELEASE 0 +#define SOURCEMOD_V_REV 6947 + +#define SOURCEMOD_VERSION "1.11.0.6947" + \ No newline at end of file -- cgit v1.2.3