From 43cbb55ca30fa3c43a01d63a2341308b67189d24 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Tue, 3 Jan 2023 06:57:39 +0300 Subject: [PATCH 001/108] Update wrapper But not tested... --- amxmodx/scripting/VipM/JsonUtils.inc | 196 ++++++++++++++++++ amxmodx/scripting/VipM/Utils.inc | 105 +--------- amxmodx/scripting/VipM/WeaponMenu/Configs.inc | 25 +-- 3 files changed, 214 insertions(+), 112 deletions(-) create mode 100644 amxmodx/scripting/VipM/JsonUtils.inc diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc new file mode 100644 index 0000000..1a3a45c --- /dev/null +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -0,0 +1,196 @@ +#if defined __UTILS_JsonUtils_included + #endinput +#endif +#define __UTILS_JsonUtils_included + +#include +#include + +// Путь до директории, откуда начинать считать ссылки +stock const __JSON_WRAPPER_FIELD_WORKDIR[] = "_work_dir"; + +// Файл, из которого было прочитано значение +stock const __JSON_WRAPPER_FIELD_FILE[] = "_file"; + +// Само значение +stock const __JSON_WRAPPER_FIELD_VALUE[] = "_value"; + +// Префикс ссылки на файл +stock static const __JSON_WRAPPER_REF_FILE_PREFIX[] = "File:"; + +#define Json_IsWrapper(%1) \ + ( \ + %1 != Invalid_JSON \ + && json_object_has_value(%1, __JSON_WRAPPER_FIELD_FILE, JSONString) \ + && json_object_has_value(%1, __JSON_WRAPPER_FIELD_WORKDIR, JSONString) \ + && json_object_has_value(%1, __JSON_WRAPPER_FIELD_VALUE) \ + && json_get_parent(%1) == Invalid_JSON \ + ) + +static stock Json__GetFileDir(const sFile[]) { + new sDir[PLATFORM_MAX_PATH]; + copy(sDir, charsmax(sDir), sFile); + + new i = 0, iLastSlash = -1; + while (sDir[i]) { + if (sDir[i] == '/' || sDir[i] == '\') { + iLastSlash = i; + } + } + + if (iLastSlash >= 0) { + sDir[iLastSlash] = 0; // EOS + } + + return sDir; +} + +stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING) { + new JSON:jFile = json_parse(sPath, true, true); + + if (jFile == Invalid_JSON) { + log_amx("[ERROR] Can't read JSON from file '%s'.", sPath); + return Invalid_JSON; + } + + new JSON:jWrapper = json_init_object(); + json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_FILE, sPath); + json_object_set_value(jWrapper, __JSON_WRAPPER_FIELD_VALUE, jFile); + + if (sWorkDir[0]) { + json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, sWorkDir); + } else { + json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, Json__GetFileDir(sPath)); + } + + return jFile; +} + +stock JSON:Json_DeepFree(&JSON:jValue) { + new JSON:jParent; + while (jValue != Invalid_JSON) { + jParent = json_get_parent(jValue); + json_free(jValue); + jValue = jParent; + } + return jValue; +} + +stock JSON:Json_FreeRefedValue(&JSON:jValue) { + /* + * Если значение поулчено по ссылке, его родителем будет обёртка, + * удаление которой полностью удалит все данные. + * + * А если значение было получено не по ссылке, его родителем будет обычное значение, + * удаление которого гарантированно НЕ удалит сами данные, + * т.к. у значения останется родитилем как минимум обёртка. + * + * Обёртка гарантированно будет, т.к. иначе ссылки не в принципе не работают. + */ + new JSON:jParent = json_get_parent(jValue); + json_free(jValue); + json_free(jParent); + + return jValue; +} + +static stock JSON:Json__GetRoot(const JSON:jValue) { + if (jValue == Invalid_JSON) { + return Invalid_JSON; + } + + new JSON:jParent; + new JSON:jIterator = json_get_parent(jValue); + while (jIterator != Invalid_JSON) { + jParent = json_get_parent(jIterator); + if (jParent == Invalid_JSON) { + break; + } + json_free(jIterator); + jIterator = jParent; + } + + // А как освобождать хендлер обёртки без её удаления?) + return jIterator; +} + +static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { + new JSON:jRoot = Json__GetRoot(jValue); + + new sPath[PLATFORM_MAX_PATH]; + if (!Json_IsWrapper(jRoot)) { + sPath[0] = 0; // EOS + return sPath; + } + + json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath)); + copy(sOut, iOutLen, sPath); + return sPath; +} + +static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { + new JSON:jRoot = Json__GetRoot(jValue); + + new sPath[PLATFORM_MAX_PATH]; + if (!Json_IsWrapper(jRoot)) { + sPath[0] = 0; // EOS + return sPath; + } + + json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath)); + copy(sOut, iOutLen, sPath); + return sPath; +} + +new stock const __Json_LogForFile_templateFile[] = "[JSON][%s] File: %s"; +new stock const __Json_LogForFile_templateMessage[] = "[JSON][%s] Message: %s"; +stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...) { + log_amx(__Json_LogForFile_templateFile, sPrefix, Json__GetFilePath(jValue)); + + static sFormattedMessage[1024]; + if (numargs() >= 4) { + vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 4); + log_amx(__Json_LogForFile_templateMessage, sPrefix, sFormattedMessage); + } else { + log_amx(__Json_LogForFile_templateMessage, sPrefix, sMessage); + } +} + +stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = 0) { + if (!json_is_string(jValue)) { + return false; + } + + new Str[128]; + json_get_string(jValue, Str, charsmax(Str)); + if (!equali(__JSON_WRAPPER_REF_FILE_PREFIX, Str, charsmax(__JSON_WRAPPER_REF_FILE_PREFIX))) { + return false; + } + + if (iLen > 0) { + copy(sFileName, iLen, Str[charsmax(__JSON_WRAPPER_REF_FILE_PREFIX)]); + } + + return true; +} + +stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { + new sRefFilePath[PLATFORM_MAX_PATH]; + if (!Json_IsRef(jValue, sRefFilePath, charsmax(sRefFilePath))) { + return jValue; + } + + new sWorkDir[PLATFORM_MAX_PATH]; + Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); + if (!sWorkDir[0]) { + // Если у ссылки нет workdir, значит ссылаться некуда) + return jValue; + } + + new sFileName[PLATFORM_MAX_PATH]; + formatex(sFileName, charsmax(sFileName), "%s/%s.json", sWorkDir, sRefFilePath); + copy(sOut, iOutLen, sFileName); + + jValue = Json_ParseFromFileEx(sFileName, sWorkDir); + return jValue; +} diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index d323396..1e928fe 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -5,6 +5,7 @@ // Надо наверное как-то их обьединить) #include "VipM/ArrayTrieUtils" +#include "VipM/JsonUtils" #include amxmodx #include json @@ -16,12 +17,13 @@ stock const __SLANG_TEMPLATE_STR[] = "%l"; stock const __CLANG_TEMPLATE_STR[] = "%L"; stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; +stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) #define GetRound() \ - get_member_game(m_iTotalRoundsPlayed)+1 + (get_member_game(m_iTotalRoundsPlayed) + 1) #define IntToStr(%1) \ fmt(__INT_TEMPLATE_STR, %1) @@ -48,7 +50,7 @@ stock const __USER_NAME_TEMPLATE_STR[] = "%n"; fmt(__CLANG_TEMPLATE_STR, %1) #define ChatPrint(%1,%2) \ - client_print_color(%1, print_team_default, __CLANG_TEMPLATE_STR, IsUserIdValid(%1) ? %1 : -1, "MSG_LAYOUT", fmt(%2)) + client_print_color(%1, print_team_default, __CLANG_TEMPLATE_STR, IsUserIdValid(%1) ? %1 : -1, __LANG_MSG_LAYOUT_KEY, fmt(%2)) #define ChatPrintL(%1,%2) \ ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2) @@ -60,90 +62,12 @@ stock const __USER_NAME_TEMPLATE_STR[] = "%n"; GET_FILE(fmt(__JSON_FILE_TEMPLATE_STR, %1)) #define GET_FILE_JSON(%1) \ - Json_ParseFromFileEx(GET_FILE_JSON_PATH(%1)) + Json_ParseFromFileEx(GET_FILE_JSON_PATH(%1), GET_FILE(NULL_STRING)) #define JSON_FILE_EXTSTS(%1) \ file_exists(GET_FILE_JSON_PATH(%1)) -stock const __JSON_WRAPPER_FIELD_FILE[] = "_file"; -stock const __JSON_WRAPPER_FIELD_VALUE[] = "_value"; - -#define Json_IsWrapper(%1) \ - ( \ - %1 != Invalid_JSON \ - && json_object_has_value(%1, __JSON_WRAPPER_FIELD_FILE, JSONString) \ - && json_object_has_value(%1, __JSON_WRAPPER_FIELD_VALUE) \ - && json_get_parent(%1) == Invalid_JSON \ - ) - -stock JSON:Json_ParseFromFileEx(const Path[]) { - new JSON:jFile = json_parse(Path, true, true); - - if (jFile == Invalid_JSON) { - log_amx("[ERROR] Can't read JSON from file '%s'.", Path); - return Invalid_JSON; - } - - new JSON:jWrapper = json_init_object(); - json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_FILE, Path); - json_object_set_value(jWrapper, __JSON_WRAPPER_FIELD_VALUE, jFile); - return jFile; -} - -stock JSON:Json_DeepFree(&JSON:jValue) { - new JSON:jParent; - while (jValue != Invalid_JSON) { - jParent = json_get_parent(jValue); - json_free(jValue); - jValue = jParent; - } - return jValue; -} - -stock JSON:Json_GetRoot(const JSON:jValue) { - if (jValue == Invalid_JSON) { - return Invalid_JSON; - } - - new JSON:jParent; - new JSON:jIterator = json_get_parent(jValue); - while (jIterator != Invalid_JSON) { - jParent = json_get_parent(jIterator); - if (jParent == Invalid_JSON) { - break; - } - json_free(jIterator); - jIterator = jParent; - } - return jIterator; -} - -stock Json_GetFilePath(const JSON:jValue, Out[], const OutLen) { - new JSON:jRoot = Json_GetRoot(jValue); - if (!Json_IsWrapper(jRoot)) { - return formatex(Out, OutLen, "unknown_file"); - } - - return json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_FILE, Out, OutLen); -} - -new stock const __Json_LogForFile_templateFile[] = "[JSON][%s] File: %s"; -new stock const __Json_LogForFile_templateMessage[] = "[JSON][%s] Message: %s"; -stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...) { - static sFilePath[PLATFORM_MAX_PATH]; - Json_GetFilePath(jValue, sFilePath, charsmax(sFilePath)); - log_amx(__Json_LogForFile_templateFile, sPrefix, sFilePath); - - static sFormattedMessage[1024]; - if (numargs() >= 4) { - vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 4); - log_amx(__Json_LogForFile_templateMessage, sPrefix, sFormattedMessage); - } else { - log_amx(__Json_LogForFile_templateMessage, sPrefix, sMessage); - } -} - stock __CMD_NULL_ARG = 0; stock CMD_INIT_PARAMS() { __CMD_NULL_ARG = 0; @@ -200,25 +124,6 @@ stock JSON:JSON_GET_FILE_OR_OBJECT(JSON:Value) { #define SaveLastJsonObjectFile(%1) \ new %1[PLATFORM_MAX_PATH];copy(%1, charsmax(%1), GetLastJsonObjectFile()) -stock bool:Json_IsRef(const JSON:jValue, FileName[] = NULL_STRING, const Len = 0) { - if (!json_is_string(jValue)) { - return false; - } - - new Str[128]; - json_get_string(jValue, Str, charsmax(Str)); - if (!equali(JSON_FILE_VALUE_PREFIX, Str, charsmax(JSON_FILE_VALUE_PREFIX))) { - return false; - } - - if (Len > 0) { - copy(FileName, Len, Str[charsmax(JSON_FILE_VALUE_PREFIX)]); - } - - return true; -} - - #define json_array_foreach(%1:%2) \ if(json_is_array(%1)) \ for(new %2 = 0; %2 < json_array_get_count(%1); %2++) diff --git a/amxmodx/scripting/VipM/WeaponMenu/Configs.inc b/amxmodx/scripting/VipM/WeaponMenu/Configs.inc index 1136dc9..96f07d4 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Configs.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Configs.inc @@ -1,13 +1,13 @@ -#include amxmodx -#include json -#include VipModular +#include +#include +#include +#include "VipM/JsonUtils" -Array:Cfg_ReadMenus(&JSON:jMenus){ +Array:Cfg_ReadMenus(&JSON:jMenus) { new Array:aMenus = Invalid_Array; new Menu[S_WeaponMenu]; - // TODO: Заменить на Json_IsRef - jMenus = JSON_GET_FILE_OR_OBJECT(jMenus); + jMenus = Json_GetRefValue(jMenus); switch (json_get_type(jMenus)) { case JSONArray: { @@ -19,19 +19,20 @@ Array:Cfg_ReadMenus(&JSON:jMenus){ if (Cfg_ReadMenu(jMenu, Menu)) { ArrayPushArray(aMenus, Menu); } + json_free(jMenu); } - json_free(jMenus); } - case JSONObject, JSONString: { + case JSONObject: { if (Cfg_ReadMenu(jMenus, Menu)) { aMenus = ArrayCreate(S_WeaponMenu, 1); ArrayPushArray(aMenus, Menu); } } - default: - json_free(jMenus); } + + Json_FreeRefedValue(jMenus); + return aMenus; } @@ -41,7 +42,7 @@ bool:Cfg_ReadMenu(&JSON:jMenu, Menu[S_WeaponMenu]){ _FileCache = TrieCreate(); } - jMenu = JSON_GET_FILE_OR_OBJECT(jMenu); + jMenu = Json_GetRefValue(jMenu); if (jMenu == Invalid_JSON) { return false; } @@ -92,7 +93,7 @@ bool:Cfg_ReadMenu(&JSON:jMenu, Menu[S_WeaponMenu]){ new JSON:jMenuItems = JsonObjectGetItemsValue(jMenu); Menu[WeaponMenu_Items] = Cfg_ReadMenuItems(jMenuItems); - json_free(jMenu); + Json_FreeRefedValue(jMenu); if (Menu[WeaponMenu_Items] == Invalid_Array) { log_amx("[WARNING] Menu items are not specified."); From 84aec7d47b8965ea93a90b8c56d7dc063bef6cdb Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 3 Feb 2023 13:48:10 +0300 Subject: [PATCH 002/108] Add docs for utils --- amxmodx/scripting/VipM/JsonUtils.inc | 103 +++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 15 deletions(-) diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index 1a3a45c..8896f8f 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -7,25 +7,26 @@ #include // Путь до директории, откуда начинать считать ссылки -stock const __JSON_WRAPPER_FIELD_WORKDIR[] = "_work_dir"; +stock static const __JSON_WRAPPER_FIELD_WORKDIR[] = "_work_dir"; // Файл, из которого было прочитано значение -stock const __JSON_WRAPPER_FIELD_FILE[] = "_file"; +stock static const __JSON_WRAPPER_FIELD_FILE[] = "_file"; // Само значение -stock const __JSON_WRAPPER_FIELD_VALUE[] = "_value"; +stock static const __JSON_WRAPPER_FIELD_VALUE[] = "_value"; // Префикс ссылки на файл stock static const __JSON_WRAPPER_REF_FILE_PREFIX[] = "File:"; -#define Json_IsWrapper(%1) \ - ( \ - %1 != Invalid_JSON \ - && json_object_has_value(%1, __JSON_WRAPPER_FIELD_FILE, JSONString) \ - && json_object_has_value(%1, __JSON_WRAPPER_FIELD_WORKDIR, JSONString) \ - && json_object_has_value(%1, __JSON_WRAPPER_FIELD_VALUE) \ - && json_get_parent(%1) == Invalid_JSON \ - ) +static stock Json__IsWrapper(const JSON:jValue) { + return ( + jValue != Invalid_JSON + && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_FILE, JSONString) + && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_WORKDIR, JSONString) + && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_VALUE) + && json_get_parent(jValue) == Invalid_JSON + ); +} static stock Json__GetFileDir(const sFile[]) { new sDir[PLATFORM_MAX_PATH]; @@ -45,6 +46,17 @@ static stock Json__GetFileDir(const sFile[]) { return sDir; } +/** + * Парсит JSON-значение из файла, добавляя обёртку для расширения функционала. + * + * @param sPath Путь до файла. + * @param sWorkDir Корневая директория для ссылок. По умолчанию будет директория, в которой лежит читаемый файл. + * + * @note Полуечнные из этой функции хендлеры обязательно должны освобождаться при помощи Json_DeepFree. + * Иначе, из-за обёртки, данные останутся в памяти. + * + * @return Хендлер прочитанного из файла значения. + */ stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING) { new JSON:jFile = json_parse(sPath, true, true); @@ -66,6 +78,16 @@ stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING) { return jFile; } +/** + * Удаляет JSON-значение вместе с обёрткой. + * + * @param jValue Корневой (полученный из Json_ParseFromFileEx) JSON-хендлер. + * + * @note Обязательно использовать для очищения хендлеров из Json_ParseFromFileEx. + * Иначе, из-за обёртки, данные останутся в памяти. + * + * @return Invalid_JSON + */ stock JSON:Json_DeepFree(&JSON:jValue) { new JSON:jParent; while (jValue != Invalid_JSON) { @@ -76,16 +98,28 @@ stock JSON:Json_DeepFree(&JSON:jValue) { return jValue; } +/** + * Удаляет JSON-значение, которое могло быть получено по ссылке. + * + * @param jValue JSON-хендлер. + * + * @note Если значение было получено по ссылке, полностью его удаляет из памяти. + * Для обычных значений работает как json_free. + * + * @note Должно использоваться для всех значений, полученных из Json_GetRefValue. + * + * @return Invalid_JSON + */ stock JSON:Json_FreeRefedValue(&JSON:jValue) { /* - * Если значение поулчено по ссылке, его родителем будет обёртка, + * Если значение получено по ссылке, его родителем будет обёртка, * удаление которой полностью удалит все данные. * * А если значение было получено не по ссылке, его родителем будет обычное значение, * удаление которого гарантированно НЕ удалит сами данные, * т.к. у значения останется родитилем как минимум обёртка. * - * Обёртка гарантированно будет, т.к. иначе ссылки не в принципе не работают. + * Обёртка гарантированно будет, т.к. иначе ссылки в принципе не работают. */ new JSON:jParent = json_get_parent(jValue); json_free(jValue); @@ -118,7 +152,7 @@ static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iO new JSON:jRoot = Json__GetRoot(jValue); new sPath[PLATFORM_MAX_PATH]; - if (!Json_IsWrapper(jRoot)) { + if (!Json__IsWrapper(jRoot)) { sPath[0] = 0; // EOS return sPath; } @@ -132,7 +166,7 @@ static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOu new JSON:jRoot = Json__GetRoot(jValue); new sPath[PLATFORM_MAX_PATH]; - if (!Json_IsWrapper(jRoot)) { + if (!Json__IsWrapper(jRoot)) { sPath[0] = 0; // EOS return sPath; } @@ -156,6 +190,28 @@ stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any: } } +new stock const __Json_ErrForFile_template[] = "[JSON][ERROR] %s: %s"; +stock Json_ErrForFile(const JSON:jValue, const sMessage[], any:...) { + static sFormattedMessage[1024]; + if (numargs() >= 4) { + vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 3); + log_error(0, __Json_LogForFile_templateMessage, Json__GetFilePath(jValue), sFormattedMessage); + } else { + log_error(0, __Json_LogForFile_templateMessage, Json__GetFilePath(jValue), sMessage); + } +} + +/** + * Проверяет, является ли значение ссылкой. + * + * @param jValue JSON-хендлер. + * @param sFileName Буфер для записи ссылки, если значение ей является. + * @param iLen Размер буфера. + * + * @note Не требуется при использовании Json_GetRefValue. + * + * @return true, если значение является ссылкой, иначе false. + */ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = 0) { if (!json_is_string(jValue)) { return false; @@ -174,12 +230,29 @@ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = return true; } +/** + * Возвращает JSON-значение с учётом ссылки. + * + * @param jValue JSON-хендлер. + * @param sOut Буфер для записи пути до файла, если значение было ссылкой. + * @param iOutLen Размер буфера. + * + * @note Ссылка считается от WorkDir из обёртки jValue. + * Если обёртки нет, ссылка не будет обработана. + * + * @note Полученное по ссылке значение также будет иметь обёртку. + * WorkDir полученного значения будет наследован от jValue. + * + * @return jValue, если значение не являлось ссылкой, иначе значение полученное по ссылке. + */ stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { new sRefFilePath[PLATFORM_MAX_PATH]; if (!Json_IsRef(jValue, sRefFilePath, charsmax(sRefFilePath))) { return jValue; } + // TODO: Обработка абсолютных ссылок + new sWorkDir[PLATFORM_MAX_PATH]; Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); if (!sWorkDir[0]) { From 39c8eee7ad3dfe26e168f13d2ceea4a782489375 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 3 Feb 2023 22:02:08 +0300 Subject: [PATCH 003/108] Refactor info srv cmds --- amxmodx/scripting/VipM/Core/SrvCmds.inc | 59 +++++++++++++++++++++--- amxmodx/scripting/VipM/Core/Utils.inc | 61 ------------------------- 2 files changed, 53 insertions(+), 67 deletions(-) delete mode 100644 amxmodx/scripting/VipM/Core/Utils.inc diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 942dd82..e872bd4 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -4,6 +4,12 @@ #define _vipmodular_src_SrvCmds_included #include +#include "VipM/ArrayTrieUtils" +#include "VipM/ArrayMap" + +#include "VipM/Core/Modules/Main" +#include "VipM/Core/Limits/Main" +#include "VipM/Core/Structs" SrvCmds_Init(){ register_srvcmd("vipm_info", "@SrvCmd_Info"); @@ -20,10 +26,14 @@ SrvCmds_Init(){ server_print("║ %s v%s by %s:", PluginName, VIPM_VERSION, PluginAuthor); server_print("║ │"); server_print("║ ├─Contacts:"); - server_print("║ │ ├─GitHub: github.com/akraneman"); - server_print("║ │ ├─DevCS: dev-cs.ru/members/949/"); - server_print("║ │ ├─VK: vk.com/akraneman"); - server_print("║ │ └─TG: t.me/arkaneman"); + server_print("║ │ ├─GitHub: https://github.com/akraneman"); + server_print("║ │ ├─DevCS: https://dev-cs.ru/members/949/"); + server_print("║ │ ├─VK: https://vk.com/akraneman"); + server_print("║ │ └─TG: https://t.me/arkaneman"); + server_print("║ ├─Support:"); + server_print("║ │ ├─GitHub Issues: https://github.com/ArKaNeMaN/amxx-VipModular-pub/issues"); + server_print("║ │ ├─DevCS Resource: https://dev-cs.ru/resources/1466/"); + server_print("║ │ └─TG Forum: https://t.me/arkanaplugins/5"); server_print("║ │"); server_print("║ ├─Stats:"); server_print("║ │ ├─Modules:"); @@ -41,7 +51,15 @@ SrvCmds_Init(){ } @SrvCmd_Modules(){ - PrintModulesData(Modules); + server_print("╔═════╤══════════════════════════════════╤════════╗"); + server_print("║ # │ Module name │ Status ║"); + server_print("╟─────┼──────────────────────────────────┼────────╢"); + ArrayMapForeachArray2 (Modules: i => Module[S_Module]) { + server_print("║ %03d │ %-32s │ %-6s ║", i + 1, Module[Module_Name], Module[Module_Enabled] ? "On" : "Off"); + } + server_print("╟─────┴──────────────────────────────────┴────────╢"); + server_print("║ Total: %-5d ║", ArrayMapSize(Modules)); + server_print("╚═════════════════════════════════════════════════╝"); } @SrvCmd_ModuleParams(){ @@ -59,7 +77,20 @@ SrvCmds_Init(){ } @SrvCmd_Limits(){ - PrintLimitsData(Limits); + server_print("╔═════╤══════════════════════════════════╤════════╤════════╤════════════╗"); + server_print("║ # │ Limit name │ Params │ Static │ For player ║"); + server_print("╟─────┼──────────────────────────────────┼────────┼────────┼────────────╢"); + ArrayMapForeachArray2 (Limits: i => Limit[S_Limit]) { + server_print("║ %03d │ %-32s │ %-6d │ %-6s │ %-10s ║", + i + 1, Limit[Limit_Name], + ArraySizeSafe(Limit[Limit_Params]), + Limit[Limit_Static] ? "Yes" : "No", + Limit[Limit_ForPlayer] ? "Yes" : "No" + ); + } + server_print("╟─────┴──────────────────────────────────┴────────┴────────┴────────────╢"); + server_print("║ Total: %-5d ║", ArrayMapSize(Limits)); + server_print("╚═══════════════════════════════════════════════════════════════════════╝"); } @SrvCmd_LimitParams(){ @@ -75,3 +106,19 @@ SrvCmds_Init(){ PrintConfigParams(LimitType[Limit_Params]); } + +static PrintConfigParams(const Array:Params) { + server_print("╔═════╤══════════════════════════════════╤══════════╤══════════╗"); + server_print("║ # │ Param name │ Type │ Required ║"); + server_print("╟─────┼──────────────────────────────────┼──────────┼──────────╢"); + ArrayForeachArray2 (Params: i => Param[S_CfgParam]) { + server_print("║ %3d │ %-32s │ %-8s │ %-8s ║", + i + 1, Param[CfgParam_Name], + VIPM_PARAM_TYPE_NAMES[Param[CfgParam_Type]], + Param[CfgParam_Required] ? "Yes" : "No" + ); + } + server_print("╟─────┴──────────────────────────────────┴──────────┴──────────╢"); + server_print("║ Total: %-5d ║", ArraySizeSafe(Params)); + server_print("╚══════════════════════════════════════════════════════════════╝"); +} diff --git a/amxmodx/scripting/VipM/Core/Utils.inc b/amxmodx/scripting/VipM/Core/Utils.inc deleted file mode 100644 index de0dd98..0000000 --- a/amxmodx/scripting/VipM/Core/Utils.inc +++ /dev/null @@ -1,61 +0,0 @@ -#if defined _vipmodular_src_locUtils_included - #endinput -#endif -#define _vipmodular_src_locUtils_included - -/** - * Vip Modular: Utils - */ - -#include amxmodx -#include "VipM/ArrayTrieUtils" -#include "VipM/ArrayMap" - -#include "VipM/Core/Modules/Main" -#include "VipM/Core/Limits/Main" -#include "VipM/Core/Structs" - -PrintModulesData(const ArrayMap(amModules)) { - server_print("╔═════╤══════════════════════════════════╤════════╗"); - server_print("║ # │ Module name │ Status ║"); - server_print("╟─────┼──────────────────────────────────┼────────╢"); - ArrayMapForeachArray2 (amModules: i => Module[S_Module]) { - server_print("║ %03d │ %-32s │ %-6s ║", i, Module[Module_Name], Module[Module_Enabled] ? "On" : "Off"); - } - server_print("╟─────┴──────────────────────────────────┴────────╢"); - server_print("║ Total: %-5d ║", ArrayMapSize(amModules)); - server_print("╚═════════════════════════════════════════════════╝"); -} - -PrintLimitsData(const ArrayMap(amLimits)) { - server_print("╔═════╤══════════════════════════════════╤════════╤════════╤════════════╗"); - server_print("║ # │ Limit name │ Params │ Static │ For player ║"); - server_print("╟─────┼──────────────────────────────────┼────────┼────────┼────────────╢"); - ArrayMapForeachArray2 (amLimits: i => Limit[S_Limit]) { - server_print("║ %03d │ %-32s │ %-6d │ %-6s │ %-10s ║", - i, Limit[Limit_Name], - ArraySizeSafe(Limit[Limit_Params]), - Limit[Limit_Static] ? "Yes" : "No", - Limit[Limit_ForPlayer] ? "Yes" : "No" - ); - } - server_print("╟─────┴──────────────────────────────────┴────────┴────────┴────────────╢"); - server_print("║ Total: %-5d ║", ArrayMapSize(amLimits)); - server_print("╚═══════════════════════════════════════════════════════════════════════╝"); -} - -PrintConfigParams(const Array:Params) { - server_print("╔═════╤══════════════════════════════════╤══════════╤══════════╗"); - server_print("║ # │ Param name │ Type │ Required ║"); - server_print("╟─────┼──────────────────────────────────┼──────────┼──────────╢"); - ArrayForeachArray2 (Params: i => Param[S_CfgParam]) { - server_print("║ %3d │ %-32s │ %-8s │ %-8s ║", - i, Param[CfgParam_Name], - VIPM_PARAM_TYPE_NAMES[Param[CfgParam_Type]], - Param[CfgParam_Required] ? "Yes" : "No" - ); - } - server_print("╟─────┴──────────────────────────────────┴──────────┴──────────╢"); - server_print("║ Total: %-5d ║", ArraySizeSafe(Params)); - server_print("╚══════════════════════════════════════════════════════════════╝"); -} \ No newline at end of file From 954509fe267240952805989de836a531820701df Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 5 Feb 2023 20:01:04 +0300 Subject: [PATCH 004/108] Add ReadToTrite and abs refs --- amxmodx/scripting/VipM-L-Default.sma | 5 +- amxmodx/scripting/VipM/Core/Configs/Main.inc | 23 +--- amxmodx/scripting/VipM/JsonUtils.inc | 101 +++++++++++++++--- amxmodx/scripting/VipModular.sma | 2 - .../include/VipM/ItemsController.inc | 10 ++ amxmodx/scripting/include/VipM/Params.inc | 14 ++- 6 files changed, 111 insertions(+), 44 deletions(-) diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index 9df4339..fd604e6 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -365,10 +365,7 @@ public client_authorized(UserId, const AuthId[]){ } @OnNameCheck(const Trie:Params, const UserId) { - static sName[32]; - VipM_Params_GetStr(Params, "Name", sName, charsmax(sName)); - - return IsEqualUserName(UserId, sName); + return IsEqualUserName(UserId, VipM_Params_GetStri(Params, "Name")); } bool:@OnFlagsCheck(const Trie:Params, const UserId) { diff --git a/amxmodx/scripting/VipM/Core/Configs/Main.inc b/amxmodx/scripting/VipM/Core/Configs/Main.inc index 3812e2a..be17211 100644 --- a/amxmodx/scripting/VipM/Core/Configs/Main.inc +++ b/amxmodx/scripting/VipM/Core/Configs/Main.inc @@ -35,28 +35,7 @@ bool:Cfg_ReadParams( } if (List == Invalid_Array) { - new ParamName[32]; - for (new i = 0; i < json_object_get_count(jParams); i++) { - - json_object_get_name(jParams, i, ParamName, charsmax(ParamName)); - new JSON:jParam = json_object_get_value_at(jParams, i); - - switch (json_get_type(jParam)) { - case JSONString: { - new sParam[128]; - json_get_string(jParam, sParam, charsmax(sParam)); - TrieSetString(Params, ParamName, sParam); - } - - case JSONNumber: - TrieSetCell(Params, ParamName, json_get_number(jParam)); - - case JSONBoolean: - TrieSetCell(Params, ParamName, json_get_bool(jParam)); - - } - json_free(jParam); - } + Params = Json_ReadObjectToTrie(jParams, Params); } else { ArrayForeachArray (List => Param[S_CfgParam]) { if (!json_object_has_value(jParams, Param[CfgParam_Name])) { diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index 8896f8f..728350a 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -26,7 +26,21 @@ static stock Json__IsWrapper(const JSON:jValue) { && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_VALUE) && json_get_parent(jValue) == Invalid_JSON ); -} +} + +static stock Json__GetRootConfigsPath(sOut[] = NULL_STRING, const iOutLen = 0) { + static sPath[PLATFORM_MAX_PATH]; + + if (!sPath[0]) { + get_localinfo("amxx_configsdir", sPath, charsmax(sPath)); + } + + if (iOutLen) { + copy(sOut, iOutLen, sPath); + } + + return sPath; +} static stock Json__GetFileDir(const sFile[]) { new sDir[PLATFORM_MAX_PATH]; @@ -154,6 +168,7 @@ static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iO new sPath[PLATFORM_MAX_PATH]; if (!Json__IsWrapper(jRoot)) { sPath[0] = 0; // EOS + copy(sOut, iOutLen, sPath); return sPath; } @@ -168,6 +183,7 @@ static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOu new sPath[PLATFORM_MAX_PATH]; if (!Json__IsWrapper(jRoot)) { sPath[0] = 0; // EOS + copy(sOut, iOutLen, sPath); return sPath; } @@ -190,14 +206,27 @@ stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any: } } -new stock const __Json_ErrForFile_template[] = "[JSON][ERROR] %s: %s"; -stock Json_ErrForFile(const JSON:jValue, const sMessage[], any:...) { +new stock const __Json_ErrorForFile_template[] = "[JSON][ERROR] %s: %s"; +stock Json_ErrorForFile(const JSON:jValue, const sMessage[], any:...) { static sFormattedMessage[1024]; if (numargs() >= 4) { vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 3); - log_error(0, __Json_LogForFile_templateMessage, Json__GetFilePath(jValue), sFormattedMessage); } else { - log_error(0, __Json_LogForFile_templateMessage, Json__GetFilePath(jValue), sMessage); + copy(sFormattedMessage, charsmax(sFormattedMessage), sMessage); + } + + log_amx(__Json_ErrorForFile_template, Json__GetFilePath(jValue), sFormattedMessage); + log_error(0, __Json_ErrorForFile_template, Json__GetFilePath(jValue), sFormattedMessage); +} + +new stock const __Json_FatalErrorForFile_template[] = "[JSON] %s: %s"; +stock Json_FatalErrorForFile(const JSON:jValue, const sMessage[], any:...) { + static sFormattedMessage[1024]; + if (numargs() >= 4) { + vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 3); + set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue), sFormattedMessage); + } else { + set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue), sMessage); } } @@ -251,19 +280,61 @@ stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = return jValue; } - // TODO: Обработка абсолютных ссылок - + new sFileName[PLATFORM_MAX_PATH]; new sWorkDir[PLATFORM_MAX_PATH]; - Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); - if (!sWorkDir[0]) { - // Если у ссылки нет workdir, значит ссылаться некуда) - return jValue; - } - new sFileName[PLATFORM_MAX_PATH]; + if (sRefFilePath[0] == '/') { + // Если ссылка начинается со слеша, считать её от amxmodx/configs/ + Json__GetRootConfigsPath(sWorkDir, charsmax(sWorkDir)); + } else { + Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); + if (!sWorkDir[0]) { + // Если у относительной ссылки нет workdir, значит ссылаться некуда) + return jValue; + } + } + formatex(sFileName, charsmax(sFileName), "%s/%s.json", sWorkDir, sRefFilePath); - copy(sOut, iOutLen, sFileName); - jValue = Json_ParseFromFileEx(sFileName, sWorkDir); + if (iOutLen) { + copy(sOut, iOutLen, sFileName); + } + + jValue = Json_ParseFromFileEx(sFileName, sFileName); return jValue; } + +stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { + if (tTrie == Invalid_Trie) { + tTrie = TrieCreate(); + } + + if (!json_is_object(jObject)) { + // А надо ли ошибку бросать? + Json_ErrorForFile(jObject, "Json_ReadObjectToTrie: JSON-value must be an object."); + return tTrie; + } + + new sKey[128]; + for (new i = 0; i < json_object_get_count(jObject); i++) { + json_object_get_name(jObject, i, sKey, charsmax(sKey)); + new JSON:jValue = json_object_get_value_at(jObject, i); + + switch (json_get_type(jValue)) { + case JSONString: { + new sValue[256]; + json_get_string(jValue, sValue, charsmax(sValue)); + TrieSetString(tTrie, sKey, sValue); + } + + case JSONNumber: + TrieSetCell(tTrie, sKey, json_get_number(jValue)); + + case JSONBoolean: + TrieSetCell(tTrie, sKey, json_get_bool(jValue)); + } + json_free(jValue); + } + + return tTrie; +} diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index c759aa4..431aac9 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -17,8 +17,6 @@ public stock const PluginDescription[] = "Modular vip system"; new Array:Vips; // S_CfgUnit new Trie:gUserVip[MAX_PLAYERS + 1] = {Invalid_Trie, ...}; // ModuleName => Trie:Params -#include "VipM/Core/Utils" - #include "VipM/Core/Structs" #include "VipM/Core/Modules/Main" #include "VipM/Core/Limits/Main" diff --git a/amxmodx/scripting/include/VipM/ItemsController.inc b/amxmodx/scripting/include/VipM/ItemsController.inc index 0eaa7d5..b10b9bc 100644 --- a/amxmodx/scripting/include/VipM/ItemsController.inc +++ b/amxmodx/scripting/include/VipM/ItemsController.inc @@ -10,6 +10,8 @@ * Vip Modular: Items Controller */ +#include + enum VipM_IC_T_Item {VipM_IC_Invalid_Item = -1} enum E_ItemTypeEvent{ @@ -173,3 +175,11 @@ stock bool:VipM_IC_GiveItems(const UserId, const Array:aItems) { return bRes; } + +stock bool:VipM_Params_GiveItems(const UserId, const Trie:tParams, const sParam[]) { + return VipM_IC_GiveItems(UserId, VipM_Params_GetArr(tParams, sParam)); +} + +stock bool:VipM_Params_GiveItem(const UserId, const Trie:tParams, const sParam[]) { + return VipM_IC_GiveItems(UserId, VipM_Params_GetCell(tParams, sParam)); +} diff --git a/amxmodx/scripting/include/VipM/Params.inc b/amxmodx/scripting/include/VipM/Params.inc index fbb9f26..24d7eaf 100644 --- a/amxmodx/scripting/include/VipM/Params.inc +++ b/amxmodx/scripting/include/VipM/Params.inc @@ -78,7 +78,7 @@ stock VipM_Params_GetInt(const Trie:tParams, const sKey[], const iDef = 0) { } stock bool:VipM_Params_GetBool(const Trie:tParams, const sKey[], const bool:bDef = false) { - return !!VipM_Params_GetCell(tParams, sKey, bDef); + return VipM_Params_GetCell(tParams, sKey, bDef) ? true : false; } stock Float:VipM_Params_GetFloat(const Trie:tParams, const sKey[], const Float:fDef = 0.0) { @@ -97,6 +97,18 @@ stock VipM_Params_GetStr(const Trie:tParams, const sKey[], sOut[], const iOutLen return copy(sOut, iOutLen, sDef); } +stock VipM_Params_GetStri(const Trie:tParams, const sKey[], const sDef[] = NULL_STRING) { + new sStr[MAX_FMT_LENGTH] + if ( + tParams == Invalid_Trie + || !TrieGetString(tParams, sKey, sStr, charsmax(sStr)) + ) { + copy(sStr, charsmax(sStr), sDef); + } + + return sStr; +} + stock Array:VipM_Params_GetArr(const Trie:tParams, const sKey[]) { return Array:VipM_Params_GetCell(tParams, sKey, Invalid_Array); } From 12b756728e81bf516aeb22b42c6bb69c1bc63913 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 27 Mar 2023 08:23:22 +0300 Subject: [PATCH 005/108] Fix instant reload for grenades --- amxmodx/scripting/VipM/Utils.inc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 1e928fe..4e1ca87 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -19,6 +19,12 @@ stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; +const WEAPON_GRENADE = ( + BIT(WEAPON_HEGRENADE) + |BIT(WEAPON_SMOKEGRENADE) + |BIT(WEAPON_FLASHBANG) +); + #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) @@ -299,14 +305,13 @@ stock RegisterPlugin( // } stock ItemHasClip(const ItemId) { - new WeaponIdType:WeaponId = get_member(ItemId, m_iId); + new WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: return false; default: return true; } - return true; } stock InstantReloadAllWeapons(const UserId) { From 9887aef8eb8c3fba64fb13429046baf7d255d6c2 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 27 Mar 2023 08:25:55 +0300 Subject: [PATCH 006/108] Fix type warn --- amxmodx/scripting/VipM/Utils.inc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 4e1ca87..1e928fe 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -19,12 +19,6 @@ stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; -const WEAPON_GRENADE = ( - BIT(WEAPON_HEGRENADE) - |BIT(WEAPON_SMOKEGRENADE) - |BIT(WEAPON_FLASHBANG) -); - #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) @@ -305,13 +299,14 @@ stock RegisterPlugin( // } stock ItemHasClip(const ItemId) { - new WeaponId = get_member(ItemId, m_iId); + new WeaponIdType:WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: return false; default: return true; } + return true; } stock InstantReloadAllWeapons(const UserId) { From 0a9dea410f1ea80256dd031a89dffc922ec1aaab Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 8 Apr 2023 01:15:11 +0300 Subject: [PATCH 007/108] Fix wrapper free and use in IC --- .../VipM/ItemsController/Configs.inc | 95 +++++---- amxmodx/scripting/VipM/JsonUtils.inc | 194 +++++++++++++++--- amxmodx/scripting/VipM/Utils.inc | 4 +- amxmodx/scripting/include/VipModular.inc | 45 ++-- 4 files changed, 240 insertions(+), 98 deletions(-) diff --git a/amxmodx/scripting/VipM/ItemsController/Configs.inc b/amxmodx/scripting/VipM/ItemsController/Configs.inc index 2274ab0..edf0338 100644 --- a/amxmodx/scripting/VipM/ItemsController/Configs.inc +++ b/amxmodx/scripting/VipM/ItemsController/Configs.inc @@ -1,86 +1,95 @@ #include amxmodx #include json +#include "VipM/JsonUtils" -new Trie:__JsonFileCache = Invalid_Trie; +static Trie:g_ItemsCache = Invalid_Trie; -Cfg_JsonGetItem(&JSON:jItem){ - if (__JsonFileCache == Invalid_Trie) { - __JsonFileCache = TrieCreate(); +Cfg_JsonGetItem(&JSON:jItem) { + TrieCreateIfNotCreated(g_ItemsCache); + new iItem = -1; + + new sJsonRef[PLATFORM_MAX_PATH]; + if (Json_IsRef(jItem, sJsonRef, charsmax(sJsonRef))) { + if (TrieGetCell(g_ItemsCache, sJsonRef, iItem)) { + Json_FreeRefedValue(jItem); + return iItem; + } + + jItem = Json_GetRefValue(jItem, .bFreeSrcIfRef=true); } - // Use `Json_IsRef` instead deprecated `JSON_GET_FILE_OR_OBJECT` - jItem = JSON_GET_FILE_OR_OBJECT(jItem); if (jItem == Invalid_JSON) { return -1; } - - new NewItemIndex = -1; - if ( - HasLastJsonObjectFile() - && TrieGetCell(__JsonFileCache, GetLastJsonObjectFile(), NewItemIndex) - && NewItemIndex >= 0 - ) { - json_free(jItem); - return NewItemIndex; - } - - SaveLastJsonObjectFile(__FILE_NAME); - + + new sItemTypeName[32]; if ( !json_is_object(jItem) - || !json_object_has_value(jItem, "Type", JSONString) + || !Json_Object_GetItemTypeAndRemove(jItem, sItemTypeName, charsmax(sItemTypeName)) ) { - log_amx("[WARNING] Invalid item format."); + Json_LogForFile(jItem, "WARNING", "Invalid item format."); + Json_FreeRefedValue(jItem); return -1; } - - new TypeName[32]; - json_object_get_string(jItem, "Type", TypeName, charsmax(TypeName)); - json_object_remove(jItem, "Type"); - if (!TYPE_EXISTS(TypeName)) { - log_amx("[WARNING] Item type `%s` not found.", TypeName); + if (!TYPE_EXISTS(sItemTypeName)) { + Json_LogForFile(jItem, "WARNING", "Item type `%s` not found.", sItemTypeName); + Json_FreeRefedValue(jItem); return -1; } new Item[S_Item]; - Item[Item_Type] = GET_TYPE_ID(TypeName); - - new Type[S_ItemType]; - GET_TYPE_BY_ID(Item[Item_Type], Type); - + Item[Item_Type] = GET_TYPE_ID(sItemTypeName); Item[Item_Params] = TrieCreate(); if (json_object_has_value(jItem, "Name", JSONString)) { - new ItemName[32]; - json_object_get_string(jItem, "Name", ItemName, charsmax(ItemName)); - TrieSetString(Item[Item_Params], "Name", ItemName); + new sItemName[32]; + json_object_get_string(jItem, "Name", sItemName, charsmax(sItemName)); + TrieSetString(Item[Item_Params], "Name", sItemName); } Forwards_DefaultReturn(VIPM_CONTINUE); if (Forwards_CallP("ReadItem", jItem, Item[Item_Params]) == VIPM_STOP) { TrieDestroySafe(Item[Item_Params]); + Json_FreeRefedValue(jItem); return -1; } - new Ret = VIPM_CONTINUE; - EMIT_TYPE_EVENT(Type, ItemType_OnRead, Ret, jItem, Item[Item_Params]) - if (Ret == VIPM_STOP) { + new ItemType[S_ItemType]; + GET_TYPE_BY_ID(Item[Item_Type], ItemType); + + new iRet = VIPM_CONTINUE; + EMIT_TYPE_EVENT(ItemType, ItemType_OnRead, iRet, jItem, Item[Item_Params]) + Json_FreeRefedValue(jItem); + + if (iRet == VIPM_STOP) { TrieDestroySafe(Item[Item_Params]); return -1; } + // А надо ли оно? if (TrieSizeSafe(Item[Item_Params]) < 1) { TrieDestroySafe(Item[Item_Params]); } - NewItemIndex = ADD_ITEM(Item); + iItem = ADD_ITEM(Item); - if (__FILE_NAME[0]) { - TrieSetCell(__JsonFileCache, __FILE_NAME, NewItemIndex); + if (sJsonRef[0]) { + TrieSetCell(g_ItemsCache, sJsonRef, iItem); } - json_free(jItem); + return iItem; +} - return NewItemIndex; +// TODO: `Type` для совместимости, надо будет когда-нить убрать) +static Json_Object_GetItemTypeAndRemove(const JSON:jItem, sItemType[], const iItemTypeLen) { + new iRet = 0; + if (json_object_has_value(jItem, "Type", JSONString)) { + iRet = json_object_get_string(jItem, "Type", sItemType, iItemTypeLen); + json_object_remove(jItem, "Type"); + } else if (json_object_has_value(jItem, "ItemType", JSONString)) { + iRet = json_object_get_string(jItem, "ItemType", sItemType, iItemTypeLen); + json_object_remove(jItem, "ItemType"); + } + return iRet; } diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index 728350a..308b066 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -15,17 +15,40 @@ stock static const __JSON_WRAPPER_FIELD_FILE[] = "_file"; // Само значение stock static const __JSON_WRAPPER_FIELD_VALUE[] = "_value"; +// Корневой хендлер обёртки (c m_bMustBeFreed == true) +stock static const __JSON_WRAPPER_FIELD_HANDLER[] = "_handler"; + // Префикс ссылки на файл stock static const __JSON_WRAPPER_REF_FILE_PREFIX[] = "File:"; +#define JSON_UTILS__MAX_KEY_LENGTH 128 +#define JSON_UTILS__MAX_STRING_LENGTH 256 +#define JSON_UTILS__MAX_REF_LENGTH 128 + static stock Json__IsWrapper(const JSON:jValue) { - return ( - jValue != Invalid_JSON - && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_FILE, JSONString) - && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_WORKDIR, JSONString) - && json_object_has_value(jValue, __JSON_WRAPPER_FIELD_VALUE) - && json_get_parent(jValue) == Invalid_JSON - ); + // log_amx("Json__IsWrapper 1 (jValue=%d)", jValue); + if ( + jValue == Invalid_JSON + || !json_is_object(jValue) + || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_FILE, JSONString) + || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_WORKDIR, JSONString) + || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_HANDLER, JSONNumber) + || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_VALUE) + ) { + // log_amx("Json__IsWrapper 2"); + return false; + } + + // log_amx("Json__IsWrapper 3"); + new JSON:jParent = json_get_parent(jValue); + if (jParent != Invalid_JSON) { + // log_amx("Json__IsWrapper 4"); + json_free(jParent); + return false; + } + + // log_amx("Json__IsWrapper 5"); + return true; } static stock Json__GetRootConfigsPath(sOut[] = NULL_STRING, const iOutLen = 0) { @@ -43,6 +66,8 @@ static stock Json__GetRootConfigsPath(sOut[] = NULL_STRING, const iOutLen = 0) { } static stock Json__GetFileDir(const sFile[]) { + // log_amx("[DEBUG] Json__GetFileDir: sFile=%s", sFile); + new sDir[PLATFORM_MAX_PATH]; copy(sDir, charsmax(sDir), sFile); @@ -51,11 +76,16 @@ static stock Json__GetFileDir(const sFile[]) { if (sDir[i] == '/' || sDir[i] == '\') { iLastSlash = i; } + ++i; } + // log_amx("[DEBUG] Json__GetFileDir: sDir=%s", sDir); + // log_amx("[DEBUG] Json__GetFileDir: iLastSlash=%d", iLastSlash); + if (iLastSlash >= 0) { - sDir[iLastSlash] = 0; // EOS + sDir[max(iLastSlash - 1, 0)] = 0; // EOS } + // log_amx("[DEBUG] Json__GetFileDir: return=%s", sDir); return sDir; } @@ -66,29 +96,41 @@ static stock Json__GetFileDir(const sFile[]) { * @param sPath Путь до файла. * @param sWorkDir Корневая директория для ссылок. По умолчанию будет директория, в которой лежит читаемый файл. * - * @note Полуечнные из этой функции хендлеры обязательно должны освобождаться при помощи Json_DeepFree. + * @note Полученные из этой функции хендлеры обязательно должны освобождаться при помощи Json_DeepFree. * Иначе, из-за обёртки, данные останутся в памяти. * * @return Хендлер прочитанного из файла значения. */ stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING) { + if (!file_exists(sPath)) { + log_amx("[ERROR] File '%s' not found.", sPath); + return Invalid_JSON; + } + new JSON:jFile = json_parse(sPath, true, true); + // log_amx("Json_ParseFromFileEx: 1 (jFile=%d)", jFile); if (jFile == Invalid_JSON) { log_amx("[ERROR] Can't read JSON from file '%s'.", sPath); return Invalid_JSON; } + // m_bMustBeFreed == true new JSON:jWrapper = json_init_object(); json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_FILE, sPath); json_object_set_value(jWrapper, __JSON_WRAPPER_FIELD_VALUE, jFile); + json_object_set_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER, _:jWrapper); + // log_amx("Json_ParseFromFileEx: 2 (jWrapper=%d)", jWrapper); if (sWorkDir[0]) { json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, sWorkDir); + // log_amx("Json_ParseFromFileEx: sWorkDir=%s from param", sWorkDir); } else { json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, Json__GetFileDir(sPath)); + // log_amx("Json_ParseFromFileEx: sWorkDir=%s inherit", sWorkDir); } + // log_amx("Json_ParseFromFileEx: 3 (jFile=%d)", jFile); return jFile; } @@ -106,7 +148,11 @@ stock JSON:Json_DeepFree(&JSON:jValue) { new JSON:jParent; while (jValue != Invalid_JSON) { jParent = json_get_parent(jValue); - json_free(jValue); + if (jParent == Invalid_JSON) { + Json__FreeWrapper(jValue, true); + } else { + json_free(jValue); + } jValue = jParent; } return jValue; @@ -137,73 +183,111 @@ stock JSON:Json_FreeRefedValue(&JSON:jValue) { */ new JSON:jParent = json_get_parent(jValue); json_free(jValue); - json_free(jParent); + Json__FreeWrapper(jParent, true); return jValue; } +static stock JSON:Json__FreeWrapper(&JSON:jWrapper, const bool:bFreeIfNotWrapper = false) { + if (!Json__IsWrapper(jWrapper)) { + Json_FreeIf(jWrapper, bFreeIfNotWrapper); + return jWrapper; + } + + new JSON:iRootWrapperHandler = JSON:json_object_get_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER); + json_free(jWrapper); + json_free(iRootWrapperHandler); + + return Invalid_JSON; +} + static stock JSON:Json__GetRoot(const JSON:jValue) { if (jValue == Invalid_JSON) { return Invalid_JSON; } + // log_amx("Json__GetRoot 1 (jValue=%d)", jValue); new JSON:jParent; new JSON:jIterator = json_get_parent(jValue); + // log_amx("Json__GetRoot 2 (jIterator=%d)", jIterator); + if (jIterator == Invalid_JSON) { + return jValue; + } + + // log_amx("Json__GetRoot 3"); while (jIterator != Invalid_JSON) { jParent = json_get_parent(jIterator); + // log_amx("Json__GetRoot 4 (jParent=%d)", jParent); if (jParent == Invalid_JSON) { break; } json_free(jIterator); jIterator = jParent; + // log_amx("Json__GetRoot 5 (jIterator=%d)", jIterator); } - // А как освобождать хендлер обёртки без её удаления?) + // log_amx("Json__GetRoot 6 (jIterator=%d)", jIterator); + // m_bMustBeFreed == false return jIterator; } -static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { +static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { + // log_amx("Json__GetFilePath 1 (jValue=%d)", jValue); new JSON:jRoot = Json__GetRoot(jValue); + // log_amx("Json__GetFilePath 2 (jRoot=%d)", jRoot); new sPath[PLATFORM_MAX_PATH]; if (!Json__IsWrapper(jRoot)) { - sPath[0] = 0; // EOS + // log_amx("Json__GetFilePath 3"); + copy(sPath, charsmax(sPath), sDefault); + } else { + // log_amx("Json__GetFilePath 4"); + json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath)); + } + Json_FreeIf(jRoot, jRoot != jValue); + + if (iOutLen) { copy(sOut, iOutLen, sPath); - return sPath; } + // log_amx("Json__GetFilePath 5 (sOut=%s)", sOut); - json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath)); - copy(sOut, iOutLen, sPath); return sPath; } -static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { +static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { new JSON:jRoot = Json__GetRoot(jValue); - new sPath[PLATFORM_MAX_PATH]; + new sPath[PLATFORM_MAX_PATH]; if (!Json__IsWrapper(jRoot)) { - sPath[0] = 0; // EOS + copy(sPath, charsmax(sPath), sDefault); + } else { + json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath)); + } + Json_FreeIf(jRoot, jRoot != jValue); + + if (iOutLen) { copy(sOut, iOutLen, sPath); - return sPath; } - json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath)); - copy(sOut, iOutLen, sPath); return sPath; } new stock const __Json_LogForFile_templateFile[] = "[JSON][%s] File: %s"; new stock const __Json_LogForFile_templateMessage[] = "[JSON][%s] Message: %s"; stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...) { - log_amx(__Json_LogForFile_templateFile, sPrefix, Json__GetFilePath(jValue)); + // log_amx("Json_LogForFile 1"); + log_amx(__Json_LogForFile_templateFile, sPrefix, Json__GetFilePath(jValue, .sDefault="*unknown file*")); static sFormattedMessage[1024]; if (numargs() >= 4) { + // log_amx("Json_LogForFile 2"); vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 4); log_amx(__Json_LogForFile_templateMessage, sPrefix, sFormattedMessage); } else { + // log_amx("Json_LogForFile 3"); log_amx(__Json_LogForFile_templateMessage, sPrefix, sMessage); } + // log_amx("Json_LogForFile 4"); } new stock const __Json_ErrorForFile_template[] = "[JSON][ERROR] %s: %s"; @@ -215,8 +299,8 @@ stock Json_ErrorForFile(const JSON:jValue, const sMessage[], any:...) { copy(sFormattedMessage, charsmax(sFormattedMessage), sMessage); } - log_amx(__Json_ErrorForFile_template, Json__GetFilePath(jValue), sFormattedMessage); - log_error(0, __Json_ErrorForFile_template, Json__GetFilePath(jValue), sFormattedMessage); + log_amx(__Json_ErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); + log_error(0, __Json_ErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); } new stock const __Json_FatalErrorForFile_template[] = "[JSON] %s: %s"; @@ -224,9 +308,9 @@ stock Json_FatalErrorForFile(const JSON:jValue, const sMessage[], any:...) { static sFormattedMessage[1024]; if (numargs() >= 4) { vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 3); - set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue), sFormattedMessage); + set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); } else { - set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue), sMessage); + set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sMessage); } } @@ -246,7 +330,7 @@ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = return false; } - new Str[128]; + new Str[JSON_UTILS__MAX_REF_LENGTH]; json_get_string(jValue, Str, charsmax(Str)); if (!equali(__JSON_WRAPPER_REF_FILE_PREFIX, Str, charsmax(__JSON_WRAPPER_REF_FILE_PREFIX))) { return false; @@ -274,7 +358,7 @@ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = * * @return jValue, если значение не являлось ссылкой, иначе значение полученное по ссылке. */ -stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0) { +stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const bool:bFreeSrcIfRef = false) { new sRefFilePath[PLATFORM_MAX_PATH]; if (!Json_IsRef(jValue, sRefFilePath, charsmax(sRefFilePath))) { return jValue; @@ -286,22 +370,29 @@ stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = if (sRefFilePath[0] == '/') { // Если ссылка начинается со слеша, считать её от amxmodx/configs/ Json__GetRootConfigsPath(sWorkDir, charsmax(sWorkDir)); + // log_amx("[DEBUG] Json_GetRefValue: sWorkDir from root"); } else { Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); + // log_amx("[DEBUG] Json_GetRefValue: sWorkDir from wrapper"); if (!sWorkDir[0]) { // Если у относительной ссылки нет workdir, значит ссылаться некуда) return jValue; } } + Json__RightTrim(sWorkDir, '/'); formatex(sFileName, charsmax(sFileName), "%s/%s.json", sWorkDir, sRefFilePath); + // log_amx("[DEBUG] Json_GetRefValue: sWorkDir=%s", sWorkDir); + // log_amx("[DEBUG] Json_GetRefValue: sFileName=%s", sFileName); + // log_amx("[DEBUG] Json_GetRefValue: sRefFilePath=%s", sRefFilePath); + if (iOutLen) { copy(sOut, iOutLen, sFileName); } - jValue = Json_ParseFromFileEx(sFileName, sFileName); - return jValue; + Json_FreeIf(jValue, bFreeSrcIfRef); + return Json_ParseFromFileEx(sFileName, sWorkDir); } stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { @@ -315,14 +406,14 @@ stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) return tTrie; } - new sKey[128]; + new sKey[JSON_UTILS__MAX_KEY_LENGTH]; for (new i = 0; i < json_object_get_count(jObject); i++) { json_object_get_name(jObject, i, sKey, charsmax(sKey)); new JSON:jValue = json_object_get_value_at(jObject, i); switch (json_get_type(jValue)) { case JSONString: { - new sValue[256]; + new sValue[JSON_UTILS__MAX_STRING_LENGTH]; json_get_string(jValue, sValue, charsmax(sValue)); TrieSetString(tTrie, sKey, sValue); } @@ -338,3 +429,38 @@ stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) return tTrie; } + +stock bool:Json_FreeIf(&JSON:jValue, const bool:bIf) { + if (bIf) { + json_free(jValue); + } + return bIf; +} + +stock bool:Json_DeepFreeIf(&JSON:jValue, const bool:bIf) { + if (bIf) { + Json_DeepFree(jValue); + } + return bIf; +} + +static stock Json__RightTrim(sStr[], const cTrim = ' ') { + new iLen = Json__StrLen(sStr); + if (iLen <= 0) { + return; + } + + while (sStr[iLen - 1] == cTrim) { + --iLen; + } + + sStr[iLen] = 0; +} + +static stock Json__StrLen(const sStr[]) { + new iLen = 0; + while (sStr[iLen]) { + ++iLen; + } + return iLen; +} diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 1e928fe..8052d4c 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -56,13 +56,13 @@ stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2) #define GET_FILE(%1) \ - inl_VipM_GetCfgPath(%1) + VipM_iGetCfgPath(%1) #define GET_FILE_JSON_PATH(%1) \ GET_FILE(fmt(__JSON_FILE_TEMPLATE_STR, %1)) #define GET_FILE_JSON(%1) \ - Json_ParseFromFileEx(GET_FILE_JSON_PATH(%1), GET_FILE(NULL_STRING)) + Json_ParseFromFileEx(GET_FILE_JSON_PATH(%1), GET_FILE("")) #define JSON_FILE_EXTSTS(%1) \ file_exists(GET_FILE_JSON_PATH(%1)) diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 76c53ff..67b4ba3 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -19,32 +19,39 @@ stock const VIPM_CFG_PATH[] = "plugins/VipModular"; * Иначе из папки вип-системы (см. константу VIPM_CFG_PATH). * * @param Path Путь / Название файла. - * @param Out Буффер для записи полученного пути. - * @param Len Размер буфера. + * @param sOut Буффер для записи полученного пути. + * @param iOutLen Размер буфера. * * @return Кол-во записанных в буфер ячеек. */ -stock VipM_GetCfgPath(const Path[], Out[], const Len){ +stock VipM_GetCfgPath(const sPath[], sOut[], const iOutLen){ static __amxx_configsdir[PLATFORM_MAX_PATH]; if (!__amxx_configsdir[0]) { get_localinfo("amxx_configsdir", __amxx_configsdir, charsmax(__amxx_configsdir)); } - return (Path[0] == '/') - ? formatex(Out, Len, "%s%s", __amxx_configsdir, Path) - : formatex(Out, Len, "%s/%s/%s", __amxx_configsdir, VIPM_CFG_PATH, Path); + return (sPath[0] == '/') + ? formatex(sOut, iOutLen, "%s%s", __amxx_configsdir, sPath) + : formatex(sOut, iOutLen, "%s/%s/%s", __amxx_configsdir, VIPM_CFG_PATH, sPath); } -// Инлайн версия предыдущего стока. -// Сорян за извращения :)) -// TODO: Заменить на сток, возвращающий строку -stock __inl_VipM_GetCfgPath[PLATFORM_MAX_PATH] = ""; -#define inl_VipM_GetCfgPath(%1) \ - ( \ - VipM_GetCfgPath(%1, __inl_VipM_GetCfgPath, charsmax(__inl_VipM_GetCfgPath)) \ - ? __inl_VipM_GetCfgPath \ - : NULL_STRING \ - ) +/** + * Получение пути, относительно папки с конфигами вип-системы или AmxModX. + * + * @note Если название файла начинается со слеша `/`, файл будет взят из папки amxmodx/configs. + * Иначе из папки вип-системы (см. константу VIPM_CFG_PATH). + * + * @param Path Путь / Название файла. + * + * @return Полученный путь. + */ +stock VipM_iGetCfgPath(const sPath[]) { + new sRetPath[PLATFORM_MAX_PATH]; + VipM_GetCfgPath(sPath, sRetPath, charsmax(sRetPath)); + return sRetPath; +} +// inl_VipM_GetCfgPath is deprecated +#define inl_VipM_GetCfgPath VipM_iGetCfgPath enum _:VipM_FwdReturn{ /* @@ -59,7 +66,7 @@ enum _:VipM_FwdReturn{ } /** - * Вызывается в момент инициалзиации модулей, типов условных элементов и режимов доступа. + * Вызывается в момент инициалзиации модулей и лимитов. * * @note Вызывается из plugin_precache * @@ -68,7 +75,7 @@ enum _:VipM_FwdReturn{ forward VipM_OnInitModules(); /** - * Вызывается в момент чтения элемента конфига (модуля или ограничения). + * Вызывается в момент чтения элемента конфига (модуля или лимита). * * @param jUnit JSON-обьект с параметрами * @param tParams Хэш-карта с прочитанными параметрами. Может быть изменена. @@ -84,7 +91,7 @@ forward VipM_OnInitModules(); forward VipM_OnReadUnit(const JSON:jUnit, const Trie:tParams); /** - * Вызывается после полной загрузки вип-системы. + * Вызывается после полной загрузки системы привилегий. * * @note Вызывается из plugin_precache * From a98182f8278cd6ce7fe312c5d5810d196ab51f28 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 8 Apr 2023 01:52:40 +0300 Subject: [PATCH 008/108] Use JsonUtils for modules --- amxmodx/scripting/VipM/Core/Modules/Units.inc | 66 ++++++------------- .../VipM/ItemsController/Configs.inc | 2 + amxmodx/scripting/VipM/JsonUtils.inc | 5 ++ 3 files changed, 28 insertions(+), 45 deletions(-) diff --git a/amxmodx/scripting/VipM/Core/Modules/Units.inc b/amxmodx/scripting/VipM/Core/Modules/Units.inc index b8552df..ebe70de 100644 --- a/amxmodx/scripting/VipM/Core/Modules/Units.inc +++ b/amxmodx/scripting/VipM/Core/Modules/Units.inc @@ -21,30 +21,8 @@ new Array:ModuleUnits; #define ModuleUnits_Get(%1,%2) \ ArrayGetArray(ModuleUnits, _:%1, %2) - -// Cache - new Trie:__cache_ModuleUnits; -T_ModuleUnit:ModuleUnits_AddToCache(const T_ModuleUnit:iMUnit, const CacheKey[] = "") { - if (CacheKey[0]) { - TrieSetCell(__cache_ModuleUnits, CacheKey, iMUnit); - } - - return iMUnit; -} - -T_ModuleUnit:ModuleUnits_GetFromCache(const CacheKey[]){ - new T_ModuleUnit:iMUnit; - return TrieGetCell(__cache_ModuleUnits, CacheKey, iMUnit) - ? iMUnit - : Invalid_ModuleUnit; -} - -#define ModuleUnits_CacheExists(%1) \ - TrieKeyExists(__cache_ModuleUnits, %1) - - // Init Modules_InitUnits() { @@ -192,39 +170,37 @@ bool:ModuleUnits_ReadFromJson(const JSON:jMUnit, sMUnit[S_ModuleUnit]) { // Loaders -T_ModuleUnit:ModuleUnits_LoadFromFile(const FileName[]) { - if (ModuleUnits_CacheExists(FileName)) { - return ModuleUnits_GetFromCache(FileName); +T_ModuleUnit:ModuleUnits_LoadFromJson(const JSON:jModuleUnit) { + TrieCreateIfNotCreated(__cache_ModuleUnits); + + new T_ModuleUnit:iUnit = Invalid_ModuleUnit; + new JSON:jRefedValue = jModuleUnit; + new sJsonRef[PLATFORM_MAX_PATH]; + if (Json_IsRef(jModuleUnit, sJsonRef, charsmax(sJsonRef))) { + if (TrieGetCell(__cache_ModuleUnits, sJsonRef, iUnit)) { + return iUnit; + } + + jRefedValue = Json_GetRefValue(jRefedValue, .bFreeSrcIfRef=true); } - - if (!JSON_FILE_EXTSTS(FileName)) { - log_amx("[WARNING] File `%s` not found.", FileName); + + if (jRefedValue == Invalid_JSON) { return Invalid_ModuleUnit; } - new JSON:jMUnit = GET_FILE_JSON(FileName); - new T_ModuleUnit:iModuleUnit = ModuleUnits_LoadFromJson(jMUnit); - json_free(jMUnit); - - return ModuleUnits_AddToCache(iModuleUnit, FileName); -} - -T_ModuleUnit:ModuleUnits_LoadFromJson(const JSON:jModuleUnit) { - if (jModuleUnit == Invalid_JSON) { + new sModuleUnit[S_ModuleUnit]; + if (!ModuleUnits_ReadFromJson(jRefedValue, sModuleUnit)) { return Invalid_ModuleUnit; } - new Ref[128]; - if (Json_IsRef(jModuleUnit, Ref, charsmax(Ref))) { - return ModuleUnits_LoadFromFile(Ref); - } + iUnit = ModuleUnits_Push(sModuleUnit); - new sModuleUnit[S_ModuleUnit]; - if (ModuleUnits_ReadFromJson(jModuleUnit, sModuleUnit)) { - return ModuleUnits_Push(sModuleUnit); + if (sJsonRef[0]) { + TrieSetCell(__cache_ModuleUnits, sJsonRef, iUnit); + Json_FreeRefedValue(jRefedValue); } - return Invalid_ModuleUnit; + return iUnit; } Array:ModuleUnits_LoadListFromJson(const JSON:jModules, Array:aModules = Invalid_Array) { diff --git a/amxmodx/scripting/VipM/ItemsController/Configs.inc b/amxmodx/scripting/VipM/ItemsController/Configs.inc index edf0338..cc917eb 100644 --- a/amxmodx/scripting/VipM/ItemsController/Configs.inc +++ b/amxmodx/scripting/VipM/ItemsController/Configs.inc @@ -2,6 +2,8 @@ #include json #include "VipM/JsonUtils" +// TODO: Переписать на хендлеры + static Trie:g_ItemsCache = Invalid_Trie; Cfg_JsonGetItem(&JSON:jItem) { diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index 308b066..d3e6ae3 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -395,6 +395,11 @@ stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = return Json_ParseFromFileEx(sFileName, sWorkDir); } +stock JSON:Json_GetRefValueC(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const bool:bFreeSrcIfRef = false) { + new JSON:_jValue = jValue; + return Json_GetRefValue(_jValue, sOut, iOutLen, bFreeSrcIfRef); +} + stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { if (tTrie == Invalid_Trie) { tTrie = TrieCreate(); From 8ecdacd84fba7e30aefe043a09fe888404154006 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 27 Mar 2023 08:23:22 +0300 Subject: [PATCH 009/108] Fix instant reload for grenades --- amxmodx/scripting/VipM/Utils.inc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 8052d4c..f1abb1f 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -19,6 +19,12 @@ stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; +const WEAPON_GRENADE = ( + BIT(WEAPON_HEGRENADE) + |BIT(WEAPON_SMOKEGRENADE) + |BIT(WEAPON_FLASHBANG) +); + #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) @@ -299,14 +305,13 @@ stock RegisterPlugin( // } stock ItemHasClip(const ItemId) { - new WeaponIdType:WeaponId = get_member(ItemId, m_iId); + new WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: return false; default: return true; } - return true; } stock InstantReloadAllWeapons(const UserId) { @@ -314,8 +319,10 @@ stock InstantReloadAllWeapons(const UserId) { new ItemId = get_member(UserId, m_rgpPlayerItems, iSlot); while (!is_nullent(ItemId)) { if (ItemHasClip(ItemId)) { + if (ItemHasClip(ItemId)) { set_member(ItemId, m_Weapon_iClip, rg_get_iteminfo(ItemId, ItemInfo_iMaxClip)); } + } ItemId = get_member(ItemId, m_pNext); } } From 09180d454c205a01416f5098318a18a45b1252db Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 27 Mar 2023 08:25:55 +0300 Subject: [PATCH 010/108] Fix type warn --- amxmodx/scripting/VipM/Utils.inc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index f1abb1f..8760f9e 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -19,12 +19,6 @@ stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; -const WEAPON_GRENADE = ( - BIT(WEAPON_HEGRENADE) - |BIT(WEAPON_SMOKEGRENADE) - |BIT(WEAPON_FLASHBANG) -); - #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) @@ -305,13 +299,14 @@ stock RegisterPlugin( // } stock ItemHasClip(const ItemId) { - new WeaponId = get_member(ItemId, m_iId); + new WeaponIdType:WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: return false; default: return true; } + return true; } stock InstantReloadAllWeapons(const UserId) { From 73622d4aa64fc87ba5a9276c2b40431ee61fa3c1 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 27 Mar 2023 08:23:22 +0300 Subject: [PATCH 011/108] Fix instant reload for grenades --- amxmodx/scripting/VipM/Utils.inc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 8760f9e..1f9d754 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -19,6 +19,12 @@ stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; +const WEAPON_GRENADE = ( + BIT(WEAPON_HEGRENADE) + |BIT(WEAPON_SMOKEGRENADE) + |BIT(WEAPON_FLASHBANG) +); + #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) @@ -298,6 +304,16 @@ stock RegisterPlugin( // } // } +stock ItemHasClip(const ItemId) { + new WeaponId = get_member(ItemId, m_iId); + switch (WeaponId) { + case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: + return false; + default: + return true; + } +} + stock ItemHasClip(const ItemId) { new WeaponIdType:WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { From 3f3efe42433f219c668cf318ae2ccd898fb0b358 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 27 Mar 2023 08:25:55 +0300 Subject: [PATCH 012/108] Fix type warn --- amxmodx/scripting/VipM/Utils.inc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 1f9d754..8f40ff4 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -19,12 +19,6 @@ stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; -const WEAPON_GRENADE = ( - BIT(WEAPON_HEGRENADE) - |BIT(WEAPON_SMOKEGRENADE) - |BIT(WEAPON_FLASHBANG) -); - #define CompositeMacros(%1) \ do { %1 } while(is_linux_server() == 0xDEADBEEF) @@ -305,13 +299,14 @@ stock RegisterPlugin( // } stock ItemHasClip(const ItemId) { - new WeaponId = get_member(ItemId, m_iId); + new WeaponIdType:WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: return false; default: return true; } + return true; } stock ItemHasClip(const ItemId) { From d10443dfab47d422a291a53a99ffed7d19c75cb3 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 2 Dec 2023 22:39:00 +0300 Subject: [PATCH 013/108] Some fix after rebase --- amxmodx/scripting/VipM/Utils.inc | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 8f40ff4..8052d4c 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -309,26 +309,13 @@ stock ItemHasClip(const ItemId) { return true; } -stock ItemHasClip(const ItemId) { - new WeaponIdType:WeaponId = get_member(ItemId, m_iId); - switch (WeaponId) { - case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: - return false; - default: - return true; - } - return true; -} - stock InstantReloadAllWeapons(const UserId) { for (new InventorySlotType:iSlot = PRIMARY_WEAPON_SLOT; iSlot <= PISTOL_SLOT; iSlot++) { new ItemId = get_member(UserId, m_rgpPlayerItems, iSlot); while (!is_nullent(ItemId)) { if (ItemHasClip(ItemId)) { - if (ItemHasClip(ItemId)) { set_member(ItemId, m_Weapon_iClip, rg_get_iteminfo(ItemId, ItemInfo_iMaxClip)); } - } ItemId = get_member(ItemId, m_pNext); } } From 58523d224a42f834bcda1e362346f6881779e089 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Thu, 21 Dec 2023 02:34:07 +0300 Subject: [PATCH 014/108] Rewrite limits component --- amxmodx/scripting/VipM-ItemsController.sma | 2 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 53 +-- amxmodx/scripting/VipM/ArrayMap.inc | 36 +- amxmodx/scripting/VipM/ArrayTrieUtils.inc | 27 +- .../VipM/Core/{Natives => API}/Limits.inc | 109 +++-- .../VipM/Core/{Natives => API}/Modules.inc | 7 +- amxmodx/scripting/VipM/Core/Configs/Main.inc | 94 ---- amxmodx/scripting/VipM/Core/Configs/Vips.inc | 23 +- amxmodx/scripting/VipM/Core/Limits/Main.inc | 22 - amxmodx/scripting/VipM/Core/Limits/Types.inc | 184 -------- amxmodx/scripting/VipM/Core/Limits/Units.inc | 215 --------- amxmodx/scripting/VipM/Core/Modules/Units.inc | 59 +-- amxmodx/scripting/VipM/Core/Natives.inc | 31 +- .../VipM/Core/Objects/Limits/Type.inc | 206 +++++++++ .../VipM/Core/Objects/Limits/Unit.inc | 163 +++++++ .../VipM/Core/Objects/Modules/Type.inc | 7 + .../VipM/Core/Objects/Modules/Unit.inc | 9 + amxmodx/scripting/VipM/Core/Objects/Param.inc | 162 +++++++ amxmodx/scripting/VipM/Core/SrvCmds.inc | 64 +-- amxmodx/scripting/VipM/Core/Structs.inc | 14 - amxmodx/scripting/VipM/Core/Vips.inc | 4 +- .../VipM/ItemsController/Configs.inc | 12 +- .../VipM/ItemsController/SrvCmds.inc | 14 +- .../scripting/VipM/ItemsController/Utils.inc | 11 - amxmodx/scripting/VipM/JsonUtils.inc | 415 ++++++++++-------- .../scripting/VipM/ModulesLimiter/Configs.inc | 7 +- amxmodx/scripting/VipM/Utils.inc | 57 +-- amxmodx/scripting/VipM/WeaponMenu/Configs.inc | 190 -------- amxmodx/scripting/VipM/WeaponMenu/Menus.inc | 2 + .../VipM/WeaponMenu/Objects/MenuItem.inc | 104 +++++ .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 104 +++++ amxmodx/scripting/VipM/WeaponMenu/Structs.inc | 31 -- amxmodx/scripting/VipModular.sma | 10 +- .../include/VipM/ItemsController.inc | 14 + amxmodx/scripting/include/VipM/Limits.inc | 26 ++ amxmodx/scripting/include/VipM/Params.inc | 2 + 36 files changed, 1259 insertions(+), 1231 deletions(-) rename amxmodx/scripting/VipM/Core/{Natives => API}/Limits.inc (53%) rename amxmodx/scripting/VipM/Core/{Natives => API}/Modules.inc (93%) delete mode 100644 amxmodx/scripting/VipM/Core/Limits/Main.inc delete mode 100644 amxmodx/scripting/VipM/Core/Limits/Types.inc delete mode 100644 amxmodx/scripting/VipM/Core/Limits/Units.inc create mode 100644 amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc create mode 100644 amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc create mode 100644 amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc create mode 100644 amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc create mode 100644 amxmodx/scripting/VipM/Core/Objects/Param.inc delete mode 100644 amxmodx/scripting/VipM/Core/Structs.inc delete mode 100644 amxmodx/scripting/VipM/WeaponMenu/Configs.inc create mode 100644 amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc create mode 100644 amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc delete mode 100644 amxmodx/scripting/VipM/WeaponMenu/Structs.inc diff --git a/amxmodx/scripting/VipM-ItemsController.sma b/amxmodx/scripting/VipM-ItemsController.sma index c7f427a..3aa520d 100644 --- a/amxmodx/scripting/VipM-ItemsController.sma +++ b/amxmodx/scripting/VipM-ItemsController.sma @@ -16,7 +16,7 @@ public stock const PluginDescription[] = "Vip Modular`s items controller"; #include "VipM/ItemsController/Structs" #include "VipM/ItemsController/Utils" -DefineArrayMap(Types); // S_ItemType +new ArrayMap(Types); // S_ItemType new Array:Items; public plugin_precache() { diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 804699f..4e4ffe9 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -4,6 +4,9 @@ #include "VipM/Utils" #include "VipM/DebugMode" +#include "VipM/WeaponMenu/Objects/WeaponMenu" +#include "VipM/WeaponMenu/Objects/MenuItem" + #pragma semicolon 1 #pragma compress 1 @@ -36,14 +39,11 @@ new bool:gUserAutoOpen[MAX_PLAYERS + 1] = {true, ...}; new gUserExpireStatus[MAX_PLAYERS + 1][VIPM_M_WEAPONMENU_EXPIRE_STATUS_MAX_LEN]; #include "VipM/WeaponMenu/KeyValueCounter" -#include "VipM/WeaponMenu/Structs" -#include "VipM/WeaponMenu/Configs" #include "VipM/WeaponMenu/Menus" public VipM_OnInitModules() { RegisterPluginByVars(); register_dictionary("VipM-WeaponMenu.ini"); - VipM_IC_Init(); VipM_Modules_Register(MODULE_NAME, true); @@ -69,18 +69,16 @@ public VipM_OnInitModules() { VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnRead, "@OnReadConfig"); } -@OnReadConfig(const JSON:jCfg, Trie:Params) { - if (!json_object_has_value(jCfg, "Menus", JSONArray)) { - log_amx("[WARNING] Param `Menus` required for module `%s`.", MODULE_NAME); +@OnReadConfig(const JSON:jCfg, Trie:tParams) { + if (!json_object_has_value(jCfg, "Menus")) { + Json_LogForFile(jCfg, "WARNING", "Param 'Menus' required for module '%s'.", MODULE_NAME); return VIPM_STOP; } + + TrieSetCell(tParams, "Menus", Json_Object_GetWeaponMenusList(jCfg, "Menus")); - new JSON:jMenus = json_object_get_value(jCfg, "Menus"); - new Array:aMenus = Cfg_ReadMenus(jMenus); - TrieSetCell(Params, "Menus", aMenus); - - if (!TrieKeyExists(Params, "MainMenuTitle")) { - TrieSetString(Params, "MainMenuTitle", Lang("MENU_MAIN_TITLE")); + if (!TrieKeyExists(tParams, "MainMenuTitle")) { + TrieSetString(tParams, "MainMenuTitle", Lang("MENU_MAIN_TITLE")); } return VIPM_CONTINUE; @@ -209,9 +207,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { } if (!is_user_alive(UserId)) { - if (!bSilent) { - ChatPrintL(UserId, "MSG_YOU_DEAD"); - } + ChatPrintLIf(!bSilent, UserId, "MSG_YOU_DEAD"); Dbg_Log("_Cmd_Menu(%n, %s): Player is dead", UserId, bSilent ? "true" : "false"); return; @@ -221,18 +217,14 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { new Array:aMenus = VipM_Params_GetArr(Params, "Menus"); if (ArraySizeSafe(aMenus) < 1) { - if (!bSilent) { - ChatPrintL(UserId, "MSG_NO_ACCESS"); - } + ChatPrintLIf(!bSilent, UserId, "MSG_NO_ACCESS"); Dbg_Log("_Cmd_Menu(%n, %s): No access", UserId, bSilent ? "true" : "false"); return; } if (!VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND)) { - if (!bSilent) { - ChatPrintL(UserId, "MSG_MAIN_NOT_PASSED_LIMIT"); - } + ChatPrintLIf(!bSilent, UserId, "MSG_MAIN_NOT_PASSED_LIMIT"); Dbg_Log("_Cmd_Menu(%n, %s): Not passed main limits", UserId, bSilent ? "true" : "false"); return; @@ -264,18 +256,13 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { ArrayGetArray(aMenus, MenuId, Menu); if (!VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], UserId)) { - if (!bSilent) { - ChatPrintL(UserId, "MSG_MENU_NOT_PASSED_LIMIT"); - } - + ChatPrintLIf(!bSilent, UserId, "MSG_MENU_NOT_PASSED_LIMIT"); Dbg_Log("_Cmd_Menu(%n, %s): Not passed menu limits", UserId, bSilent ? "true" : "false"); return; } - if (Menu[WeaponMenu_Fake]) { - if (Menu[WeaponMenu_FakeMessage][0]) { - ChatPrint(UserId, Menu[WeaponMenu_FakeMessage]); - } + if (Menu[WeaponMenu_FakeMessage][0]) { + ChatPrint(UserId, Menu[WeaponMenu_FakeMessage]); Dbg_Log("_Cmd_Menu(%n, %s): Fake menu (%s)", UserId, bSilent ? "true" : "false", Menu[WeaponMenu_FakeMessage]); return; } @@ -303,9 +290,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { MenuItem[MenuItem_UseCounter] && iItemsLeft == 0 ) { - if (!bSilent) { - ChatPrintL(UserId, "MSG_NO_LEFT_ITEMS"); - } + ChatPrintLIf(!bSilent, UserId, "MSG_NO_LEFT_ITEMS"); Dbg_Log("_Cmd_Menu(%n, %s): No left items", UserId, bSilent ? "true" : "false"); return; @@ -316,9 +301,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { || !VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId) || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], UserId) ) { - if (!bSilent) { - ChatPrintL(UserId, "MSG_MENUITEM_NOT_PASSED_LIMIT"); - } + ChatPrintLIf(!bSilent, UserId, "MSG_MENUITEM_NOT_PASSED_LIMIT"); Dbg_Log("_Cmd_Menu(%n, %s): Not passed item limits", UserId, bSilent ? "true" : "false"); return; diff --git a/amxmodx/scripting/VipM/ArrayMap.inc b/amxmodx/scripting/VipM/ArrayMap.inc index 8dd3d76..975bb3c 100644 --- a/amxmodx/scripting/VipM/ArrayMap.inc +++ b/amxmodx/scripting/VipM/ArrayMap.inc @@ -12,36 +12,30 @@ enum ArrayMap{ #define ArrayMap(%1) \ %1[ArrayMap] -#define DefineArrayMap(%1) \ - new ArrayMap(%1) - -#define DefineStaticArrayMap(%1) \ - static ArrayMap(%1) - -stock InitArrayMap(AM[ArrayMap], const CellSize = 1, const Reserved = 32){ +stock InitArrayMap(AM[ArrayMap], const CellSize = 1, const Reserved = 1) { AM[AM_Arr] = ArrayCreate(CellSize, Reserved); AM[AM_Map] = TrieCreate(); } -stock ArrayMapPushArray(AM[ArrayMap], const any:Input[], const Key[], Size = -1){ +stock ArrayMapPushArray(AM[ArrayMap], const any:Input[], const Key[], Size = -1) { new Id = ArrayPushArray(AM[AM_Arr], Input, Size); TrieSetCell(AM[AM_Map], Key, Id, true); return Id; } -stock ArrayMapPushString(AM[ArrayMap], const Input[], const Key[]){ +stock ArrayMapPushString(AM[ArrayMap], const Input[], const Key[]) { new Id = ArrayPushString(AM[AM_Arr], Input); TrieSetCell(AM[AM_Map], Key, Id, true); return Id; } -stock ArrayMapPushCell(AM[ArrayMap], any:Input, const Key[]){ +stock ArrayMapPushCell(AM[ArrayMap], any:Input, const Key[]) { new Id = ArrayPushCell(AM[AM_Arr], Input); TrieSetCell(AM[AM_Map], Key, Id, true); return Id; } -stock ArrayMapGetIndex(AM[ArrayMap], const Key[]){ +stock ArrayMapGetIndex(AM[ArrayMap], const Key[]) { new Id = -1; TrieGetCell(AM[AM_Map], Key, Id); return Id; @@ -49,29 +43,29 @@ stock ArrayMapGetIndex(AM[ArrayMap], const Key[]){ #define ArrayMapForeach(%1,%2) \ - if(ArrayMapCreated(%1))\ - for(new %2 = 0; %2 < ArrayMapSize(%1); %2++) + if (ArrayMapCreated(%1)) \ + for (new %2 = 0; %2 < ArrayMapSize(%1); %2++) #define ArrayMapForeachArray(%1=>%2[%3]) \ ArrayMapForeachArrayEx(%1=>%2[%3], __i__) #define ArrayMapForeachArrayEx(%1=>%2[%3],%4) \ - if(ArrayMapCreated(%1))\ - for(new %2[%3], %4 = 0; %4 < ArrayMapSize(%1); %4++)\ - if(ArrayMapGetiArray(%1, %4, %2)) + if (ArrayMapCreated(%1)) \ + for (new %2[%3], %4 = 0; %4 < ArrayMapSize(%1); %4++) \ + if (ArrayMapGetiArray(%1, %4, %2)) #define ArrayMapForeachArray2(%1:%4=>%2[%3]) \ - if(ArrayMapCreated(%1)) \ - for(new %2[%3], %4 = 0; %4 < ArrayMapSize(%1); %4++) \ - if(ArrayMapGetiArray(%1, %4, %2)) + if (ArrayMapCreated(%1)) \ + for (new %2[%3], %4 = 0; %4 < ArrayMapSize(%1); %4++) \ + if (ArrayMapGetiArray(%1, %4, %2)) #define ArrayMapCreated(%1) \ (%1[AM_Arr] != Invalid_Array) #define ArrayMapDestroy(%1) \ - if(ArrayMapCreated(%1)){\ - ArrayDestroy(%1[AM_Arr]); TrieDestroy(%1[AM_Map]);\ + if (ArrayMapCreated(%1)) { \ + ArrayDestroy(%1[AM_Arr]); TrieDestroy(%1[AM_Map]); \ } #define ArrayMapSize(%1) \ diff --git a/amxmodx/scripting/VipM/ArrayTrieUtils.inc b/amxmodx/scripting/VipM/ArrayTrieUtils.inc index 6af950d..61c6ee1 100644 --- a/amxmodx/scripting/VipM/ArrayTrieUtils.inc +++ b/amxmodx/scripting/VipM/ArrayTrieUtils.inc @@ -27,19 +27,19 @@ stock TrieDestroySafe(Trie:t) { ArrayForeachArrayEx(%1 => %2[%3], __i__) #define ArrayForeachArrayEx(%1=>%2[%3],%4) \ - if(%1 != Invalid_Array)\ - for(new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++)\ - if(ArrayGetArray(%1, %4, %2)) + if (%1 != Invalid_Array)\ + for (new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++)\ + if (ArrayGetArray(%1, %4, %2)) #define ArrayForeachArray2(%1:%4=>%2[%3]) \ - if(%1 != Invalid_Array) \ - for(new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++) \ - if(ArrayGetArray(%1, %4, %2)) + if (%1 != Invalid_Array) \ + for (new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++) \ + if (ArrayGetArray(%1, %4, %2)) #define ArrayForeachString(%1:%4=>%2[%3]) \ - if(%1 != Invalid_Array) \ - for(new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++) \ - if(ArrayGetString(%1, %4, %2, charsmax(%2))) + if (%1 != Invalid_Array) \ + for (new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++) \ + if (ArrayGetString(%1, %4, %2, charsmax(%2))) #define ArrayCreateIfNotCreated(%1,%2) \ %1 = (%1 == Invalid_Array) \ @@ -51,11 +51,10 @@ stock TrieDestroySafe(Trie:t) { ? TrieCreate() \ : %1 -#define ArrayDestroyIfEmpty(%1) \ - CompositeMacros( \ - if(!ArraySizeSafe(%1)) \ - ArrayDestroy(%1); \ - ) +#define ArrayDestroyIfEmpty(%1) CompositeMacros( \ + if (!ArraySizeSafe(%1)) \ + ArrayDestroy(%1); \ +) stock Array:ArrayMergeCells(const Array:a1, const Array:a2) { new Array:aMerged = ArrayClone(a1); diff --git a/amxmodx/scripting/VipM/Core/Natives/Limits.inc b/amxmodx/scripting/VipM/Core/API/Limits.inc similarity index 53% rename from amxmodx/scripting/VipM/Core/Natives/Limits.inc rename to amxmodx/scripting/VipM/Core/API/Limits.inc index f6fa36a..39d4df3 100644 --- a/amxmodx/scripting/VipM/Core/Natives/Limits.inc +++ b/amxmodx/scripting/VipM/Core/API/Limits.inc @@ -1,7 +1,12 @@ -#include amxmodx +#include +#include #include "VipM/Natives" -Natives_Limits_Init(){ +#include "VipM/Core/Objects/Limits/Type" +#include "VipM/Core/Objects/Limits/Unit" +#include "VipM/Core/Objects/Param" + +API_Limits_Init() { Natives_Reg("Limits_RegisterType"); Natives_Reg("Limits_AddTypeParams"); Natives_Reg("Limits_RegisterTypeEvent"); @@ -16,45 +21,83 @@ Natives_Limits_Init(){ } // native VipM_Limits_RegisterType(const sName[], const bool:bForPlayer = true, const bool:bStatic = false); -@_Limits_RegisterType(const PluginId) { - enum {Arg_LimitName = 1, Arg_ForPlayer, Arg_Static} +T_LimitType:@_Limits_RegisterType() { + enum {Arg_sLimitTypeName = 1, Arg_bForPlayer, Arg_bStatic} - new sName[32]; - get_string(Arg_LimitName, sName, charsmax(sName)); + new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); - new bool:bForPlayer = bool:get_param(Arg_ForPlayer); - new bool:bStatic = bool:get_param(Arg_Static); + new bool:bForPlayer = bool:get_param(Arg_bForPlayer); + new bool:bStatic = bool:get_param(Arg_bStatic); - Limits_AddType(sName, bForPlayer, bStatic, PluginId); + new T_LimitType:iLimitType = LimitType_Construct(sLimitTypeName, bForPlayer, bStatic); + if (iLimitType == Invalid_LimitType) { + log_error(0, "Can't create limit type '%s'.", sLimitTypeName); + return Invalid_LimitType; + } + + return iLimitType; } // native VipM_Limits_AddTypeParams(const sName[], any:...); -@_Limits_AddTypeParams(const PluginId, const cParams) { +@_Limits_AddTypeParams(const PluginId, const iParamsNum) { enum {Arg_LimitName = 1, Arg_Params} - new sName[32]; + new sName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; get_string(Arg_LimitName, sName, charsmax(sName)); - - NATIVE_CHECK_LIMIT_TYPE(sName) - - new LimitType[S_Limit]; - LIMIT_TYPE_GET(sName, LimitType); - LimitType[Limit_Params] = Native_GetParamsList(Arg_Params - 1, cParams, LimitType[Limit_Params]); - SET_LIMIT_TYPE(LimitType); + + new T_LimitType:iLimitType = LimitType_Find(sName); + if (iLimitType == Invalid_LimitType) { + log_error(0, "Limit type '%s' not found.", sName); + return; + } + + new Array:aParams = CfgParam_GetFromNative(Arg_Params, iParamsNum); + if (aParams == Invalid_Array) { + return; + } + + LimitType_MergeParams(iLimitType, aParams); } // native VipM_Limits_RegisterTypeEvent(const sName[], const E_LimitEvent:iEvent, const sFunc[]); @_Limits_RegisterTypeEvent(const PluginId) { enum {Arg_LimitName = 1, Arg_Event, Arg_FuncName} - new sName[32], E_LimitEvent:iEvent, sFunc[64]; + new sName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; get_string(Arg_LimitName, sName, charsmax(sName)); - iEvent = E_LimitEvent:get_param(Arg_Event); + + new T_LimitType:iLimitType = LimitType_Find(sName); + if (iLimitType == Invalid_LimitType) { + log_error(0, "Limit type '%s' not found.", sName); + return; + } + + new E_LimitEvent:iEvent = E_LimitEvent:get_param(Arg_Event); + + new sFunc[64]; get_string(Arg_FuncName, sFunc, charsmax(sFunc)); - NATIVE_CHECK_LIMIT_TYPE(sName) + LimitType_SetEventListener(iLimitType, iEvent, PluginId, sFunc); +} + +// native VipM_Limits_Execute(const sName[], const bool:bNewValue, const UserId = 0); +@_Limits_SetStaticValue() { + enum {Arg_LimitName = 1, Arg_NewValue, Arg_UserId} + + static sName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(Arg_LimitName, sName, charsmax(sName)); + + new T_LimitType:iLimitType = LimitType_Find(sName); + if (iLimitType == Invalid_LimitType) { + log_error(0, "Limit type '%s' not found.", sName); + return; + } + + new bool:bNewValue = bool:get_param(Arg_NewValue); + new UserId = get_param(Arg_UserId); - Limits_RegisterEvent(PluginId, sName, iEvent, sFunc); + LimitType_SetStaticValue(iLimitType, bNewValue, UserId); } // native T_LimitUnit:VipM_Limits_ReadFromJson(const JSON:jLimit); @@ -63,7 +106,7 @@ T_LimitUnit:@_Limits_ReadFromJson() { new JSON:jLimit = JSON:get_param(Arg_JsonValue); - return Limits_LoadUnitFromJson(jLimit); + return LimitUnit_Read(jLimit); } // native Array:VipM_Limits_ReadListFromJson(const JSON:jLimits, Array:aLimits = Invalid_Array); @@ -73,21 +116,7 @@ Array:@_Limits_ReadListFromJson() { new JSON:jLimits = JSON:get_param(Arg_JsonValue); new Array:aLimits = Array:get_param(Arg_Array); - return Limits_LoadUnitListFromJson(jLimits, aLimits); -} - -// native VipM_Limits_Execute(const sName[], const bool:bNewValue, const UserId = 0); -@_Limits_SetStaticValue() { - enum {Arg_LimitName = 1, Arg_NewValue, Arg_UserId} - - static sName[32]; - get_string(Arg_LimitName, sName, charsmax(sName)); - new bool:bNewValue = bool:get_param(Arg_NewValue); - new UserId = get_param(Arg_UserId); - - NATIVE_CHECK_LIMIT_TYPE(sName) - - Limits_SetStaticValue(sName, bNewValue, UserId); + return LimitUnit_ReadList(jLimits, aLimits); } // native bool:VipM_Limits_Execute(const T_LimitUnit:iLimit, const UserId = 0); @@ -97,7 +126,7 @@ bool:@_Limits_Execute() { new T_LimitUnit:iLimit = T_LimitUnit:get_param(Arg_LimitUnit); new UserId = get_param(Arg_UserId); - return Limits_ExecuteUnit(iLimit, UserId); + return LimitUnit_Execute(iLimit, UserId); } // native bool:VipM_Limits_ExecuteList(const Array:aLimits, const UserId = 0, const E_LimitsExecType:iType = Limit_Exec_OR); @@ -108,5 +137,5 @@ bool:@_Limits_ExecuteList() { new UserId = get_param(Arg_UserId); new E_LimitsExecType:Type = E_LimitsExecType:get_param(Arg_Type); - return Limits_ExecuteUnitList(aLimits, UserId, Type); + return LimitUnit_ExecuteList(aLimits, UserId, Type); } diff --git a/amxmodx/scripting/VipM/Core/Natives/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc similarity index 93% rename from amxmodx/scripting/VipM/Core/Natives/Modules.inc rename to amxmodx/scripting/VipM/Core/API/Modules.inc index adf1c02..be21f61 100644 --- a/amxmodx/scripting/VipM/Core/Natives/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -1,6 +1,7 @@ #include #include "VipM/DebugMode" #include "VipM/Natives" +#include "VipM/Core/Objects/Param" Natives_Modules_Init(){ Natives_Reg("Modules_Register"); @@ -37,12 +38,8 @@ Natives_Modules_Init(){ NATIVE_CHECK_MODULE(ModuleName) GET_MODULE(ModuleName, Module); new bool:bSave = (Module[Module_Params] == Invalid_Array); - - // Dbg_PrintServer("Module_AddParams(%s): bSave = %s", ModuleName, bSave ? "+" : "-"); - - Module[Module_Params] = Native_GetParamsList(Arg_Params - 1, ParamsCount, Module[Module_Params]); - // Dbg_PrintServer(":---"); + Module[Module_Params] = CfgParam_GetFromNative(Arg_Params, ParamsCount, Module[Module_Params]); if (bSave) { SET_MODULE(Module); diff --git a/amxmodx/scripting/VipM/Core/Configs/Main.inc b/amxmodx/scripting/VipM/Core/Configs/Main.inc index be17211..c475bae 100644 --- a/amxmodx/scripting/VipM/Core/Configs/Main.inc +++ b/amxmodx/scripting/VipM/Core/Configs/Main.inc @@ -19,98 +19,4 @@ enum _:S_CfgUnit{ // Utils -bool:Cfg_ReadParams( - const JSON:jParams, - Trie:Params, - const Array:List = Invalid_Array, - ErrParam[] = "", - const Len = 0 -) { - if (!json_is_object(jParams)) { - return false; - } - if (Params == Invalid_Trie) { - Params = TrieCreate(); - } - - if (List == Invalid_Array) { - Params = Json_ReadObjectToTrie(jParams, Params); - } else { - ArrayForeachArray (List => Param[S_CfgParam]) { - if (!json_object_has_value(jParams, Param[CfgParam_Name])) { - if ( - Param[CfgParam_Required] - && Param[CfgParam_Type] != ptCustom - ) { - formatex(ErrParam, Len, Param[CfgParam_Name]); - TrieDestroy(Params); - return false; - } else { - continue; - } - } - - switch (Param[CfgParam_Type]) { - case ptCustom: - continue; - - case ptInteger: - TrieSetCell(Params, Param[CfgParam_Name], json_object_get_number(jParams, Param[CfgParam_Name])); - - case ptFloat: - TrieSetCell(Params, Param[CfgParam_Name], json_object_get_real(jParams, Param[CfgParam_Name])); - - case ptBoolean: - TrieSetCell(Params, Param[CfgParam_Name], json_object_get_bool(jParams, Param[CfgParam_Name])); - - case ptString: { - new sParam[128]; - json_object_get_string(jParams, Param[CfgParam_Name], sParam, charsmax(sParam)); - TrieSetString(Params, Param[CfgParam_Name], sParam); - } - - case ptColor: { - new JSON:jColor = json_object_get_value(jParams, Param[CfgParam_Name]); - new Color[3]; - for(new i = 0; i < 3; i++) - Color[i] = json_array_get_number(jColor, i); - TrieSetArray(Params, Param[CfgParam_Name], Color, 3); - json_free(jColor); - } - - case ptVector2: { - new JSON:jVec = json_object_get_value(jParams, Param[CfgParam_Name]); - new Float:Vec[2]; - for(new i = 0; i < 2; i++) - Vec[i] = json_array_get_real(jVec, i); - TrieSetArray(Params, Param[CfgParam_Name], Vec, 2); - json_free(jVec); - } - case ptVector3: { - new JSON:jVec = json_object_get_value(jParams, Param[CfgParam_Name]); - new Float:Vec[3]; - for(new i = 0; i < 3; i++) - Vec[i] = json_array_get_real(jVec, i); - TrieSetArray(Params, Param[CfgParam_Name], Vec, 3); - json_free(jVec); - } - - case ptLimit: { - new JSON:jLimit = json_object_get_value(jParams, Param[CfgParam_Name]); - new T_LimitUnit:iLimit = Limits_LoadUnitFromJson(jLimit); - TrieSetCell(Params, Param[CfgParam_Name], iLimit); - json_free(jLimit); - } - case ptLimits: { - new JSON:jLimits = json_object_get_value(jParams, Param[CfgParam_Name]); - new Array:aLimits = Limits_LoadUnitListFromJson(jLimits, aLimits); - TrieSetCell(Params, Param[CfgParam_Name], aLimits); - json_free(jLimits); - } - } - } - } - - return true; -} diff --git a/amxmodx/scripting/VipM/Core/Configs/Vips.inc b/amxmodx/scripting/VipM/Core/Configs/Vips.inc index aa1de88..32e1006 100644 --- a/amxmodx/scripting/VipM/Core/Configs/Vips.inc +++ b/amxmodx/scripting/VipM/Core/Configs/Vips.inc @@ -1,6 +1,8 @@ -#include amxmodx -#include json -#include regex +#include +#include +#include + +#include "VipM/Core/Objects/Limits/Unit" static stock const VIPS_CFG_FILE[] = "Vips"; static stock const VIPS_CFGS_DIR[] = "Vips"; @@ -36,14 +38,9 @@ Array:Cfg_LoadVipsConfigs(Array:aList = Invalid_Array) { } Array:Cfg_LoadVipsConfigFromFile(const sFileName[], Array:aList = Invalid_Array) { - if (!JSON_FILE_EXTSTS(sFileName)) { - set_fail_state("[ERROR] Vips config '%s' not found.", GET_FILE_JSON_PATH(sFileName)); - return Invalid_Array; - } - - new JSON:jVips = GET_FILE_JSON(sFileName); + new JSON:jVips = Json_ParseFromFileEx(sFileName); if (!json_is_array(jVips)) { - set_fail_state("[ERROR] JSON syntax error in file '%s'.", GET_FILE_JSON_PATH(sFileName)); + set_fail_state("[ERROR] File '%s' must contains a JSON-array.", GET_FILE_JSON_PATH(sFileName)); return Invalid_Array; } @@ -53,10 +50,10 @@ Array:Cfg_LoadVipsConfigFromFile(const sFileName[], Array:aList = Invalid_Array) if (Cfg_ReadVipConfig(jCfgUnit, CfgUnit)) { ArrayPushArray(aList, CfgUnit); } - json_free(jCfgUnit); + Json_FreeEx(jCfgUnit); } - Json_DeepFree(jVips); + Json_FreeEx(jVips); return aList; } @@ -66,7 +63,7 @@ bool:Cfg_ReadVipConfig(const JSON:jCfgUnit, CfgUnit[S_CfgUnit]) { return false; } - CfgUnit[CfgUnit_LimitUnits] = Limits_LoadUnitListFromJson(jAccess); + CfgUnit[CfgUnit_LimitUnits] = LimitUnit_ReadList(jAccess); json_free(jAccess); if (!ArraySizeSafe(CfgUnit[CfgUnit_LimitUnits])) { ArrayDestroy(CfgUnit[CfgUnit_LimitUnits]); diff --git a/amxmodx/scripting/VipM/Core/Limits/Main.inc b/amxmodx/scripting/VipM/Core/Limits/Main.inc deleted file mode 100644 index bd399f3..0000000 --- a/amxmodx/scripting/VipM/Core/Limits/Main.inc +++ /dev/null @@ -1,22 +0,0 @@ -#if defined _vipmodular_src_Limits_included - #endinput -#endif -#define _vipmodular_src_Limits_included - -#include amxmodx -#include json - -#define NATIVE_CHECK_LIMIT_TYPE(%1) \ - if(!LIMIT_TYPE_EXISTS(%1)){ \ - log_error(0, "[ERROR] Limit type '%s' not found.", %1); \ - } - -#include "VipM/Core/Limits/Types.inc" -#include "VipM/Core/Limits/Units.inc" - -Limits_Init(){ - InitArrayMap(Limits, S_Limit, 8); - - LimitUnits = ArrayCreate(S_LimitUnit, 16); - __cache_LimitUnits = TrieCreate(); -} diff --git a/amxmodx/scripting/VipM/Core/Limits/Types.inc b/amxmodx/scripting/VipM/Core/Limits/Types.inc deleted file mode 100644 index d0c86bf..0000000 --- a/amxmodx/scripting/VipM/Core/Limits/Types.inc +++ /dev/null @@ -1,184 +0,0 @@ -#include amxmodx -#include "VipM/ArrayMap" -#include "VipM/Utils" -#include "VipM/DebugMode" - -enum T_Limit {Invalid_Limit = -1} - -enum _:S_Limit{ - Limit_PluginId, - Limit_Name[32], - - bool:Limit_Static, - Limit_StaticValue, - - bool:Limit_ForPlayer, - - Array:Limit_Params, - Trie:Limit_Events, -} - -new ArrayMap(Limits); - -#define LIMIT_TYPE_PUSH(%1) \ - T_Limit:ArrayMapPushArray(Limits, %1, %1[Limit_Name]) - -#define LIMIT_TYPE_EXISTS(%1) \ - ArrayMapHasKey(Limits, %1) - -#define LIMIT_TYPE_GET_ID(%1) \ - T_Limit:ArrayMapGetIndex(Limits, %1) - -#define LIMIT_TYPE_GET_BY_ID(%1,%2) \ - ArrayMapGetiArray(Limits, _:(%1), %2) - -#define LIMIT_TYPE_GET(%1,%2) \ - ArrayMapGetArray(Limits, %1, %2) - -#define SET_LIMIT_TYPE(%1) \ - ArrayMapSetArray(Limits, %1[Limit_Name], %1) - -new const __CHECK_LIMIT_FOR_PLAYER_errmsg[] = "[ERROR] Limit `%s` must used for player."; -#define CHECK_LIMIT_FOR_PLAYER(%1,%2,%3) CompositeMacros( \ - if ( \ - !IsUserIdValid(%2) \ - && %1[Limit_ForPlayer] \ - ) { \ - log_error(1, __CHECK_LIMIT_FOR_PLAYER_errmsg, %1[Limit_Name]); \ - return %3; \ - } \ -) - -new const __CHECK_LIMIT_STATIC_errmsg[] = "[ERROR] Limit type `%s` isn`t static."; -#define CHECK_LIMIT_STATIC(%1,%2) \ - if (!%1[Limit_Static]) { \ - log_error(1, __CHECK_LIMIT_STATIC_errmsg, %1[Limit_Name]); \ - return %2; \ - } - -// EMIT_LIMIT_TYPE_EVENT(LimitType, E_LimitEvent:Event, Return, ...Params) -#define EMIT_LIMIT_TYPE_EVENT(%1,%2,%3) \ - if ( \ - %1[Limit_Events] != Invalid_Trie \ - && TrieKeyExists(%1[Limit_Events], IntToStr(%2)) \ - ) { \ - new ___EVENT_FWD; \ - TrieGetCell(%1[Limit_Events], IntToStr(%2), ___EVENT_FWD); \ - ExecuteForward(___EVENT_FWD, %3); \ - } - -// SET_LIMIT_TYPE_EVENT(AccessMode, E_LimitEvent:Event, FwdId) -#define SET_LIMIT_TYPE_EVENT(%1,%2,%3) \ - if (%3 >= 0) { \ - if(%1[Limit_Events] == Invalid_Trie) \ - %1[Limit_Events] = TrieCreate(); \ - TrieSetCell(%1[Limit_Events], IntToStr(%2), %3); \ - } else TrieDeleteKey(%1[Limit_Events], IntToStr(%2)) - - -T_Limit:Limits_AddType(const sName[], const bool:bForPlayer, const bool:bStatic = false, const iPluginId = -1){ - new Limit[S_Limit]; - - Limit[Limit_PluginId] = iPluginId; - copy(Limit[Limit_Name], charsmax(Limit[Limit_Name]), sName); - Limit[Limit_Static] = bStatic; - Limit[Limit_StaticValue] = 0; - Limit[Limit_ForPlayer] = bForPlayer; - - return LIMIT_TYPE_PUSH(Limit); -} - -Limits_RegisterEvent(const PluginId, const sLimitName[], const E_LimitEvent:Event, const Func[]){ - new LimitType[S_Limit]; - LIMIT_TYPE_GET(sLimitName, LimitType); - - new FwdId = -1; - switch (Event) { - case Limit_OnRead: // (const JSON:Cfg, Trie:Params) - FwdId = CreateOneForward(PluginId, Func, FP_CELL, FP_CELL); - - case Limit_OnCheck: // (const Trie:Params, const UserId) - FwdId = CreateOneForward(PluginId, Func, FP_CELL, FP_CELL); - } - - if (FwdId < 0) { - return false; - } - - SET_LIMIT_TYPE_EVENT(LimitType, Event, FwdId); - SET_LIMIT_TYPE(LimitType); - - return FwdId >= 0; -} - -Limits_SetStaticValue(const sLimitName[], const bool:bValue, const UserId = 0){ - static LimitType[S_Limit]; - LIMIT_TYPE_GET(sLimitName, LimitType); - - CHECK_LIMIT_STATIC(LimitType, 0) - CHECK_LIMIT_FOR_PLAYER(LimitType, UserId, 0); - - if (UserId > 0) { - Dbg_Log("Limits_SetStaticValue(%s, %n):", sLimitName, UserId); - } else { - Dbg_Log("Limits_SetStaticValue(%s, %d):", sLimitName, UserId); - } - - Dbg_Log(" sLimitName[] = %s", sLimitName); - Dbg_Log(" LimitType[Limit_ForPlayer] = %s", LimitType[Limit_ForPlayer] ? "true" : "false"); - Dbg_Log(" LimitType[Limit_StaticValue] (before set) = %d", LimitType[Limit_StaticValue]); - Dbg_Log(" bValue = %d", bValue); - - if (LimitType[Limit_ForPlayer]) { - BitSetIf(LimitType[Limit_StaticValue], UserId - 1, bValue); - Dbg_Log(" BitIs(LimitType[Limit_StaticValue], UserId - 1) = %d", BitIs(LimitType[Limit_StaticValue], UserId - 1)); - } else { - LimitType[Limit_StaticValue] = _:bValue; - Dbg_Log(" LimitType[Limit_StaticValue] (after set) = %d", LimitType[Limit_StaticValue]); - } - - SET_LIMIT_TYPE(LimitType); - - return 0; -} - -bool:Limits_GetStaticValue(const sLimitName[], const UserId = 0){ - static LimitType[S_Limit]; - LIMIT_TYPE_GET(sLimitName, LimitType); - - CHECK_LIMIT_STATIC(LimitType, false) - CHECK_LIMIT_FOR_PLAYER(LimitType, UserId, false); - - if (UserId > 0) { - Dbg_Log("Limits_GetStaticValue(%s, %n):", sLimitName, UserId); - } else { - Dbg_Log("Limits_GetStaticValue(%s, %d):", sLimitName, UserId); - } - - Dbg_Log(" LimitType[Limit_ForPlayer] = %s", LimitType[Limit_ForPlayer] ? "true" : "false"); - Dbg_Log(" LimitType[Limit_StaticValue] = %d", LimitType[Limit_StaticValue]); - - if (UserId > 0) { - Dbg_Log(" BitIs(LimitType[Limit_StaticValue], UserId - 1) = %d", BitIs(LimitType[Limit_StaticValue], UserId - 1)); - } - - return LimitType[Limit_ForPlayer] - ? BitIs(LimitType[Limit_StaticValue], UserId - 1) - : (bool:LimitType[Limit_StaticValue]); -} - -bool:Limits_Execute(const T_Limit:iLimitType, const Trie:Params = Invalid_Trie, const UserId = 0){ - static LimitType[S_Limit]; - LIMIT_TYPE_GET_BY_ID(iLimitType, LimitType); - - CHECK_LIMIT_FOR_PLAYER(LimitType, UserId, false); - - if (LimitType[Limit_Static]) { - return Limits_GetStaticValue(LimitType[Limit_Name], UserId); - } - - new bool:ret; - EMIT_LIMIT_TYPE_EVENT(LimitType, Limit_OnCheck, ret, Params, UserId) - - return bool:ret; -} diff --git a/amxmodx/scripting/VipM/Core/Limits/Units.inc b/amxmodx/scripting/VipM/Core/Limits/Units.inc deleted file mode 100644 index fc5048e..0000000 --- a/amxmodx/scripting/VipM/Core/Limits/Units.inc +++ /dev/null @@ -1,215 +0,0 @@ -#include -#include - -// Structs - -enum _:S_LimitUnit{ - T_Limit:LimitUnit_LimitId, - Trie:LimitUnit_Params, // S_CfgParam -} -new Array:LimitUnits; - -// Array utils - -#define Limits_PushUnit(%1) \ - T_LimitUnit:(ArrayPushArray(LimitUnits, %1)) - -#define Limits_GetUnit(%1,%2) \ - ArrayGetArray(LimitUnits, _:%1, %2) - -#define Limits_IsUnitValid(%1) \ - (_:%1 >= 0 && _:%1 < ArraySizeSafe(LimitUnits)) - -// Cache - -new Trie:__cache_LimitUnits; - -T_LimitUnit:Limits_AddUnitToCache(const T_LimitUnit:iLimit, const CacheKey[] = ""){ - if (CacheKey[0]) { - TrieSetCell(__cache_LimitUnits, CacheKey, iLimit); - } - return iLimit; -} - -T_LimitUnit:Limits_GetUnitFromCache(const CacheKey[]){ - new T_LimitUnit:iLimit; - return TrieGetCell(__cache_LimitUnits, CacheKey, iLimit) - ? iLimit - : Invalid_LimitUnit; -} - -#define Limits_CacheExists(%1) \ - TrieKeyExists(__cache_LimitUnits, %1) - -// Reader - -bool:Limits_ReadUnitFromJson(const JSON:jUnit, Unit[S_LimitUnit]){ - new LimitName[32]; - json_object_get_string(jUnit, "Limit", LimitName, charsmax(LimitName)); - json_object_remove(jUnit, "Limit"); - - if (!LIMIT_TYPE_EXISTS(LimitName)) { - log_amx("[WARNING] Limit type `%s` not found.", LimitName); - return false; - } - - new LimitType[S_Limit]; - LIMIT_TYPE_GET(LimitName, LimitType); - - Unit[LimitUnit_LimitId] = LIMIT_TYPE_GET_ID(LimitName); - Unit[LimitUnit_Params] = TrieCreate(); - if (!LimitType[Limit_Static]) { - new ErrParam[32]; - if (!Cfg_ReadParams(jUnit, Unit[LimitUnit_Params], LimitType[Limit_Params], ErrParam, charsmax(ErrParam))) { - log_amx("[WARNING] Param `%s` required for limit `%s`, but not found.", ErrParam, LimitType[Limit_Name]); - return false; - } - } - - Forwards_DefaultReturn(VIPM_CONTINUE); - if ( - Forwards_CallP("ReadUnit", jUnit, Unit[LimitUnit_Params]) == VIPM_STOP - || Forwards_CallP("ReadLimitUnit", jUnit, Unit[LimitUnit_Params]) == VIPM_STOP - ) { - TrieDestroySafe(Unit[LimitUnit_Params]); - return false; - } - - new ret; - EMIT_LIMIT_TYPE_EVENT(LimitType, Limit_OnRead, ret, jUnit, Unit[LimitUnit_Params]) - - if (ret == VIPM_STOP) { - TrieDestroySafe(Unit[LimitUnit_Params]); - return false; - } - - return true; -} - -// Loaders - -T_LimitUnit:Limits_LoadUnitFromFile(const FileName[]){ - if (Limits_CacheExists(FileName)) { - return Limits_GetUnitFromCache(FileName); - } - - if (!JSON_FILE_EXTSTS(FileName)) { - log_amx("[WARNING] File `%s` not found.", FileName); - return Invalid_LimitUnit; - } - - new JSON:jUnit = GET_FILE_JSON(FileName); - new T_LimitUnit:iLimit = Limits_LoadUnitFromJson(jUnit); - json_free(jUnit); - - return Limits_AddUnitToCache(iLimit, FileName); -} - -T_LimitUnit:Limits_LoadUnitFromJson(const JSON:jUnit){ - if (jUnit == Invalid_JSON) { - return Invalid_LimitUnit; - } - - new Ref[128]; - if (Json_IsRef(jUnit, Ref, charsmax(Ref))) { - return Limits_LoadUnitFromFile(Ref); - } - - new Unit[S_LimitUnit]; - if (Limits_ReadUnitFromJson(jUnit, Unit)) { - return Limits_PushUnit(Unit); - } - - return Invalid_LimitUnit; -} - -Array:Limits_LoadUnitListFromJson(const JSON:jLimits, Array:aLimits = Invalid_Array){ - new T_LimitUnit:iLimit; - if (!json_is_array(jLimits)) { - ArrayCreateIfNotCreated(aLimits, 1, 1); - - iLimit = Limits_LoadUnitFromJson(jLimits); - if (iLimit != Invalid_LimitUnit) { - ArrayPushCell(aLimits, iLimit); - } - } else { - ArrayCreateIfNotCreated(aLimits, 1, json_array_get_count(jLimits)); - - json_array_foreach_value(jLimits: i => jLimit){ - iLimit = Limits_LoadUnitFromJson(jLimit); - if (iLimit != Invalid_LimitUnit) { - ArrayPushCell(aLimits, iLimit); - } - json_free(jLimit); - } - } - - if (ArraySizeSafe(aLimits) < 1) { - // log_amx("[WARNING] Limit units list not loaded (invalid or empty)."); - ArrayDestroy(aLimits); - } - - return aLimits; -} - -// Usage - -bool:Limits_ExecuteUnit(const T_LimitUnit:iLimit, const UserId = 0){ - if (!Limits_IsUnitValid(iLimit)) { - log_error(0, "[ERROR] Invalid limit unit index (%d).", iLimit); - return true; - } - - new Limit[S_LimitUnit]; - Limits_GetUnit(iLimit, Limit); - - return Limits_Execute(Limit[LimitUnit_LimitId], Limit[LimitUnit_Params], UserId); -} - -bool:Limits_ExecuteUnitList(const Array:aLimits, const UserId = 0, const E_LimitsExecType:Type = Limit_Exec_OR){ - new cLimits = ArraySizeSafe(aLimits); - if (!cLimits) { - return true; - } - - new __xor_counter = 0; - for (new i = 0; i < cLimits; i++) { - new T_LimitUnit:iLimit = T_LimitUnit:ArrayGetCell(aLimits, i); - switch (Type) { - case Limit_Exec_OR: { - if (Limits_ExecuteUnit(iLimit, UserId)) { - return true; - } - } - - case Limit_Exec_AND: { - if (!Limits_ExecuteUnit(iLimit, UserId)) { - return false; - } - } - - case Limit_Exec_XOR: { - if (Limits_ExecuteUnit(iLimit, UserId)) { - __xor_counter++; - } - - if (__xor_counter > 1) { - return false; - } - } - } - } - - switch(Type){ - case Limit_Exec_OR: - return false; - - case Limit_Exec_AND: - return true; - - case Limit_Exec_XOR: - return bool:__xor_counter; - } - - return false; -} diff --git a/amxmodx/scripting/VipM/Core/Modules/Units.inc b/amxmodx/scripting/VipM/Core/Modules/Units.inc index ebe70de..24962de 100644 --- a/amxmodx/scripting/VipM/Core/Modules/Units.inc +++ b/amxmodx/scripting/VipM/Core/Modules/Units.inc @@ -21,13 +21,10 @@ new Array:ModuleUnits; #define ModuleUnits_Get(%1,%2) \ ArrayGetArray(ModuleUnits, _:%1, %2) -new Trie:__cache_ModuleUnits; - // Init Modules_InitUnits() { ModuleUnits = ArrayCreate(S_ModuleUnit, MODULE_UNITS_PRESERVED_SIZE); - __cache_ModuleUnits = TrieCreate(); } @@ -136,7 +133,7 @@ bool:ModuleUnits_ReadFromJson(const JSON:jMUnit, sMUnit[S_ModuleUnit]) { sMUnit[ModuleUnit_Params] = TrieCreate(); new ErrParam[32]; - if (!Cfg_ReadParams(jMUnit, sMUnit[ModuleUnit_Params], sModule[Module_Params], ErrParam, charsmax(ErrParam))) { + if (!CfgParam_ReadList(jMUnit, sMUnit[ModuleUnit_Params], sModule[Module_Params], ErrParam, charsmax(ErrParam))) { Json_LogForFile(jMUnit, "WARNING", "Param `%s` required for module `%s`, but not found.", ErrParam, sModule[Module_Name]); return false; } @@ -167,61 +164,37 @@ bool:ModuleUnits_ReadFromJson(const JSON:jMUnit, sMUnit[S_ModuleUnit]) { return true; } - // Loaders T_ModuleUnit:ModuleUnits_LoadFromJson(const JSON:jModuleUnit) { - TrieCreateIfNotCreated(__cache_ModuleUnits); - - new T_ModuleUnit:iUnit = Invalid_ModuleUnit; - new JSON:jRefedValue = jModuleUnit; - new sJsonRef[PLATFORM_MAX_PATH]; - if (Json_IsRef(jModuleUnit, sJsonRef, charsmax(sJsonRef))) { - if (TrieGetCell(__cache_ModuleUnits, sJsonRef, iUnit)) { - return iUnit; + static Trie:tCache = Invalid_Trie; + TrieCreateIfNotCreated(tCache); + + new JSON:jRefed, T_ModuleUnit:iUnit = Invalid_ModuleUnit; + Json_GetCachedRefValue_Begin(jModuleUnit, tCache, iUnit, jRefed) + { + new ModuleUnit[S_ModuleUnit]; + if (ModuleUnits_ReadFromJson(jRefed, ModuleUnit)) { + iUnit = ModuleUnits_Push(ModuleUnit); } - - jRefedValue = Json_GetRefValue(jRefedValue, .bFreeSrcIfRef=true); - } - - if (jRefedValue == Invalid_JSON) { - return Invalid_ModuleUnit; - } - - new sModuleUnit[S_ModuleUnit]; - if (!ModuleUnits_ReadFromJson(jRefedValue, sModuleUnit)) { - return Invalid_ModuleUnit; - } - - iUnit = ModuleUnits_Push(sModuleUnit); - - if (sJsonRef[0]) { - TrieSetCell(__cache_ModuleUnits, sJsonRef, iUnit); - Json_FreeRefedValue(jRefedValue); } - - return iUnit; + Json_GetCachedRefValue_End(jModuleUnit, tCache, iUnit, jRefed) } -Array:ModuleUnits_LoadListFromJson(const JSON:jModules, Array:aModules = Invalid_Array) { - new T_ModuleUnit:iMUnit; - ArrayCreateIfNotCreated(aModules, 1, json_get_count(jModules)); +Array:ModuleUnits_LoadListFromJson(const JSON:jModules, &Array:aModules = Invalid_Array) { + ArrayCreateIfNotCreated(aModules, 1, 1); if (!json_is_array(jModules)) { - iMUnit = ModuleUnits_LoadFromJson(jModules); + new T_ModuleUnit:iMUnit = ModuleUnits_LoadFromJson(jModules); if (iMUnit != Invalid_ModuleUnit) { ArrayPushCell(aModules, iMUnit); } } else { - json_array_foreach_value(jModules: i => jModule) { - iMUnit = ModuleUnits_LoadFromJson(jModule); - if (iMUnit != Invalid_ModuleUnit) { - ArrayPushCell(aModules, iMUnit); - } + json_array_foreach_value (jModules: i => jModule) { + aModules = ModuleUnits_LoadListFromJson(jModule, aModules); json_free(jModule); } } - ArrayDestroyIfEmpty(aModules); return aModules; } diff --git a/amxmodx/scripting/VipM/Core/Natives.inc b/amxmodx/scripting/VipM/Core/Natives.inc index a7ac0a5..6f58032 100644 --- a/amxmodx/scripting/VipM/Core/Natives.inc +++ b/amxmodx/scripting/VipM/Core/Natives.inc @@ -11,33 +11,8 @@ #include "VipM/Natives" #include "VipM/Utils" -Array:Native_GetParamsList(const NullArg, const ParamsCount, Array:aParams = Invalid_Array) { - const ARGS_NUM_PER_PARAM = 3; - - if ((ParamsCount - NullArg) % ARGS_NUM_PER_PARAM != 0) { - log_error(1, "[ERROR] Invalid parameters num."); - return Invalid_Array; - } - - if (aParams == Invalid_Array) { - aParams = ArrayCreate(S_CfgParam, max(1, (ParamsCount - NullArg) / ARGS_NUM_PER_PARAM)); - } - - new Param[S_CfgParam]; - for (new i = NullArg+1; i < ParamsCount; i += ARGS_NUM_PER_PARAM) { - get_string(i, Param[CfgParam_Name], charsmax(Param[CfgParam_Name])); - Param[CfgParam_Type] = E_ParamType:get_param_byref(i+1); - Param[CfgParam_Required] = bool:get_param_byref(i+2); - - // Dbg_PrintServer("^t- %s: %d, %s", Param[CfgParam_Name], _:Param[CfgParam_Type], Param[CfgParam_Required] ? "+" : "-"); - - ArrayPushArray(aParams, Param); - } - return aParams; -} - -#include "VipM/Core/Natives/Limits.inc" -#include "VipM/Core/Natives/Modules.inc" +#include "VipM/Core/API/Limits" +#include "VipM/Core/API/Modules" public plugin_natives() { Natives_Init("VipM"); @@ -46,7 +21,7 @@ public plugin_natives() { Natives_Reg("Json_LogForFile"); Natives_Modules_Init(); - Natives_Limits_Init(); + API_Limits_Init(); } // native VipM_Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...); diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc new file mode 100644 index 0000000..84b7b6c --- /dev/null +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -0,0 +1,206 @@ +#if defined __vipm_core_objects_limits_type_included + #endinput +#endif +#define __vipm_core_objects_limits_type_included + +#include +#include +#include +#include "VipM/Utils" +#include "VipM/ArrayMap" +#include "VipM/ArrayTrieUtils" +#include "VipM/Core/Objects/Param" + +enum _:S_LimitType { + LimitType_Name[VIPM_LIMITS_TYPE_NAME_MAX_LEN], + Array:LimitType_Params, // S_CfgParam + + bool:LimitType_Static, + LimitType_StaticValue, + + bool:LimitType_ForPlayer, + + LimitType_Events[E_LimitEvent], +} + +enum T_LimitType { Invalid_LimitType = -1 } + +static ArrayMap(g_amLimitTypes); // S_LimitType + +LimitType_Init() { + if (!ArrayMapCreated(g_amLimitTypes)) { + InitArrayMap(g_amLimitTypes, S_LimitType); + } +} + +Array:LimitType_GetAll() { + return ArrayClone(g_amLimitTypes[AM_Arr]); +} + +LimitType_GetCount() { + return ArraySizeSafe(g_amLimitTypes[AM_Arr]); +} + +T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, const bool:bStatic = false) { + if (!ArrayMapCreated(g_amLimitTypes)) { + abort(0, "Attempt to create limit type before limits controller init."); + return Invalid_LimitType; + } + + if (LimitType_Find(sName) != Invalid_LimitType) { + abort(0, "Limit type '' already exists.", sName); + return Invalid_LimitType; + } + + new LimitType[S_LimitType]; + + copy(LimitType[LimitType_Name], charsmax(LimitType[LimitType_Name]), sName); + LimitType[LimitType_Params] = Invalid_Array; + + LimitType[LimitType_Static] = bStatic; + LimitType[LimitType_StaticValue] = 0; + + LimitType[LimitType_ForPlayer] = bForPlayer; + + arrayset(LimitType[LimitType_Events], -1, sizeof(LimitType[LimitType_Events])); + + return T_LimitType:ArrayMapPushArray(g_amLimitTypes, LimitType, LimitType[LimitType_Name]); +} + +T_LimitType:LimitType_Find(const sName[]) { + return T_LimitType:ArrayMapGetIndex(g_amLimitTypes, sName); +} + +static LimitType__Get(const T_LimitType:iLimitType, LimitType[S_LimitType]) { + ArrayMapGetiArray(g_amLimitTypes, _:iLimitType, LimitType); +} + +static LimitType__Set(const LimitType[S_LimitType]) { + ArrayMapSetArray(g_amLimitTypes, LimitType[LimitType_Name], LimitType); +} + +Array:LimitType_GetParams(const T_LimitType:iLimitType) { + new LimitType[S_LimitType]; + LimitType__Get(iLimitType, LimitType); + + if (LimitType[LimitType_Params] == Invalid_Array) { + return Invalid_Array; + } + + return ArrayClone(LimitType[LimitType_Params]); +} + +LimitType_MergeParams(const T_LimitType:iLimitType, const Array:aParams) { + new LimitType[S_LimitType]; + LimitType__Get(iLimitType, LimitType); + + LimitType[LimitType_Params] = CfgParam_Merge(LimitType[LimitType_Params], aParams); + + LimitType__Set(LimitType); +} + +Trie:LimitType_ReadParams(const T_LimitType:iLimitType, const JSON:jParams) { + new LimitType[S_LimitType]; + LimitType__Get(iLimitType, LimitType); + + new Trie:tParams = TrieCreate(); + + // У статических лимитов не может быть параметров + if (LimitType[LimitType_Static]) { + return tParams; + } + + new sErrParam[VIPM_PARAM_NAME_MAX_LEN]; + if (!CfgParam_ReadList(jParams, tParams, LimitType[LimitType_Params], sErrParam, charsmax(sErrParam))) { + Json_ErrorForFile(jParams, "Param '%s' required for '%s' limit.", sErrParam, LimitType[LimitType_Name]); + TrieDestroy(tParams); + return Invalid_Trie; + } + + if (LimitType[LimitType_Events][Limit_OnRead] >= 0) { + new iRet = VIPM_STOP; + ExecuteForward(LimitType[LimitType_Events][Limit_OnRead], iRet, jParams, tParams); + + if (iRet == VIPM_STOP) { + TrieDestroy(tParams); + return Invalid_Trie; + } + } + + return tParams; +} + +LimitType_SetEventListener( + const T_LimitType:iLimitType, + const E_LimitEvent:iEvent, + const PluginId, + const sFuncName[] +) { + new LimitType[S_LimitType]; + LimitType__Get(iLimitType, LimitType); + + if (LimitType[LimitType_Events][iEvent] >= 0) { + DestroyForward(LimitType[LimitType_Events][iEvent]); + } + + LimitType[LimitType_Events][iEvent] = LimitType__MakeEventForward(iEvent, PluginId, sFuncName); + + if (LimitType[LimitType_Events][iEvent] < 0) { + abort(0, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); + } + + LimitType__Set(LimitType); +} + +static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, const sFuncName[]) { + switch (iEvent) { + case Limit_OnRead: // (const JSON:jCfg, Trie:tParams) + return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + case Limit_OnCheck: // (const Trie:tParams, const UserId) + return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + } + + abort(0, "[ERROR] Invalid event index (%d).", iEvent); + return -1; +} + +LimitType_SetStaticValue(const T_LimitType:iLimitType, const bool:bValue, const UserId = 0) { + new LimitType[S_LimitType]; + LimitType__Get(iLimitType, LimitType); + + if (!LimitType[LimitType_Static]) { + abort(0, "Trying to set static value for a non-static limit."); + return; + } + + if (UserId > 0) { + BitSetIf(LimitType[LimitType_StaticValue], UserId - 1, bValue); + } else { + LimitType[LimitType_StaticValue] = bValue; + } + + LimitType__Set(LimitType); +} + +bool:LimitType_Execute(const T_LimitType:iLimitType, const Trie:tParams, const UserId = 0) { + new LimitType[S_LimitType]; + LimitType__Get(iLimitType, LimitType); + + new bool:bRes = false; + if (LimitType[LimitType_Static]) { + if (LimitType[LimitType_ForPlayer]) { + bRes = BitIs(LimitType[LimitType_StaticValue], UserId - 1); + } else { + bRes = !!LimitType[LimitType_StaticValue]; + } + } else { + if (LimitType[LimitType_Events][Limit_OnCheck] < 0) { + abort(0, "'Limit_OnCheck' event listener for non-static limit type '%s' must be implemented.", LimitType[LimitType_Name]); + bRes = false; + } else { + ExecuteForward(LimitType[LimitType_Events][Limit_OnCheck], bRes, tParams, UserId); + } + } + + return bRes; +} diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc new file mode 100644 index 0000000..b3494c8 --- /dev/null +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -0,0 +1,163 @@ +#if defined __vipm_core_objects_limits_unit_included + #endinput +#endif +// Два кванта +#define __vipm_core_objects_limits_unit_included + +#include +#include +#include "VipM/ArrayMap" +#include "VipM/ArrayTrieUtils" + +#include "VipM/Core/Objects/Limits/Type" + +// T_LimitUnit + +enum _:S_LimitUnit { + T_LimitType:LimitUnit_Type, + Trie:LimitUnit_Params, +} + +static Array:g_aLimitUnits = Invalid_Array; + +LimitUnit_Init() { + LimitType_Init(); + + if (g_aLimitUnits == Invalid_Array) { + g_aLimitUnits = ArrayCreate(S_LimitUnit, 1); + } +} + +LimitUnit_GetCount() { + return ArraySizeSafe(g_aLimitUnits); +} + +static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie:tParams) { + if (g_aLimitUnits == Invalid_Array) { + abort(0, "Attempt to` create limit unit before init."); + return Invalid_LimitUnit; + } + + new LimitUnit[S_LimitUnit]; + + LimitUnit[LimitUnit_Type] = iLimitType; + LimitUnit[LimitUnit_Params] = tParams; + + return T_LimitUnit:ArrayPushArray(g_aLimitUnits, LimitUnit); +} + +static LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit]) { + ArrayGetArray(g_aLimitUnits, _:iLimitUnit, LimitUnit); +} + +static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { + new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + Json_Object_GetString(jLimitUnit, "Limit", sLimitTypeName, charsmax(sLimitTypeName)); + trim(sLimitTypeName); + + if (!sLimitTypeName[0]) { + Json_ErrorForFile(jLimitUnit, "ERROR", "Limit type name not specified."); + return Invalid_LimitType; + } + + new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); + + if (iLimitType == Invalid_LimitType) { + Json_ErrorForFile(jLimitUnit, "ERROR", "Limit type '%s' not found.", sLimitTypeName); + return Invalid_LimitType; + } + + return iLimitType; +} + +T_LimitUnit:LimitUnit_Read(const JSON:jLimitUnit) { + static Trie:tCache = Invalid_Trie; + TrieCreateIfNotCreated(tCache); + + new JSON:jRefed, T_LimitUnit:iLimitUnit = Invalid_LimitUnit; + Json_GetCachedRefValue_Begin(jLimitUnit, tCache, iLimitUnit, jRefed) + { + new T_LimitType:iLimitType = LimitUnit__ReadType(jRefed); + new Trie:tParams = Invalid_Trie; + + if (iLimitType != Invalid_LimitType) { + tParams = LimitType_ReadParams(iLimitType, jRefed); + } + + if (tParams != Invalid_Trie) { + iLimitUnit = LimitUnit__Construct(iLimitType, tParams); + } + } + Json_GetCachedRefValue_End(jLimitUnit, tCache, iLimitUnit, jRefed) +} + +Array:LimitUnit_ReadList(const JSON:jLimitUnits, &Array:aLimitUnits = Invalid_Array) { + ArrayCreateIfNotCreated(aLimitUnits, 1, 1); + + if (!json_is_array(jLimitUnits)) { + new T_LimitUnit:iLimitUnit = LimitUnit_Read(jLimitUnits); + if (iLimitUnit != Invalid_LimitUnit) { + ArrayPushCell(aLimitUnits, iLimitUnit); + } + } else { + json_array_foreach_value (jLimitUnits: i => jLimitUnit) { + aLimitUnits = LimitUnit_ReadList(jLimitUnit, aLimitUnits); + json_free(jLimitUnit); + } + } + + return aLimitUnits; +} + +bool:LimitUnit_Execute(const T_LimitUnit:iLimitUnit, const UserId = 0) { + new LimitUnit[S_LimitUnit]; + LimitUnit__Get(iLimitUnit, LimitUnit); + + return LimitType_Execute(LimitUnit[LimitUnit_Type], LimitUnit[LimitUnit_Params], UserId); +} + +bool:LimitUnit_ExecuteList( + const Array:aLimitUnits, + const UserId = 0, + const E_LimitsExecType:iOperator +) { + new bool:bXor = false; + + for (new i = 0, ii = ArraySizeSafe(aLimitUnits); i < ii; ++i) { + new T_LimitUnit:iLimitUnit = T_LimitUnit:ArrayGetCell(aLimitUnits, i); + new bool:bRes = LimitUnit_Execute(iLimitUnit, UserId); + + switch (iOperator) { + case Limit_Exec_OR: { + if (bRes) { + return true; + } + } + case Limit_Exec_AND: { + if (!bRes) { + return false; + } + } + case Limit_Exec_XOR: { + if (bRes && bXor) { + return false; + } + bXor = bXor || bRes; + } + } + } + + switch (iOperator) { + case Limit_Exec_OR: { + return false; + } + case Limit_Exec_AND: { + return true; + } + case Limit_Exec_XOR: { + return bXor; + } + } + + return false; +} diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc new file mode 100644 index 0000000..4f7eefd --- /dev/null +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -0,0 +1,7 @@ +#if defined __vipm_core_objects_modules_type_included + #endinput +#endif +#define __vipm_core_objects_modules_type_included + +#include +#include "VipM/ArrayMap" diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc new file mode 100644 index 0000000..433e34c --- /dev/null +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -0,0 +1,9 @@ +#if defined __vipm_core_objects_modules_unit_included + #endinput +#endif +#define __vipm_core_objects_modules_unit_included + +#include +#include "VipM/ArrayMap" + +#include "VipM/Core/Objects/Modules/Type" diff --git a/amxmodx/scripting/VipM/Core/Objects/Param.inc b/amxmodx/scripting/VipM/Core/Objects/Param.inc new file mode 100644 index 0000000..2efea77 --- /dev/null +++ b/amxmodx/scripting/VipM/Core/Objects/Param.inc @@ -0,0 +1,162 @@ +#if defined __vipm_core_objects_param_included + #endinput +#endif +#define __vipm_core_objects_param_included + +#include +#include +#include +#include +#include "VipM/ArrayTrieUtils" + +enum _:S_CfgParam { + CfgParam_Name[VIPM_PARAM_NAME_MAX_LEN], + E_ParamType:CfgParam_Type, + bool:CfgParam_Required, +} + +Array:CfgParam_GetFromNative(const iStartParam, const iNativeParamsCount, &Array:aParams = Invalid_Array) { + const ARGS_NUM_PER_PARAM = 3; + + new NullArg = iStartParam - 1; + + if ((iNativeParamsCount - NullArg) % ARGS_NUM_PER_PARAM != 0) { + log_error(0, "[ERROR] Invalid parameters num."); + return Invalid_Array; + } + + new iParamsCount = max(1, (iNativeParamsCount - NullArg) / ARGS_NUM_PER_PARAM); + if (aParams == Invalid_Array) { + aParams = ArrayCreate(S_CfgParam, iParamsCount); + } else { + ArrayResize(aParams, ArraySize(aParams) + iParamsCount); + } + + new Param[S_CfgParam]; + for (new i = NullArg + 1; i < iNativeParamsCount; i += ARGS_NUM_PER_PARAM) { + get_string(i, Param[CfgParam_Name], charsmax(Param[CfgParam_Name])); + Param[CfgParam_Type] = E_ParamType:get_param_byref(i + 1); + Param[CfgParam_Required] = bool:get_param_byref(i + 2); + + ArrayPushArray(aParams, Param); + } + + return aParams; +} + +Array:CfgParam_Merge(&Array:aParams, const Array:...) { + if (aParams == Invalid_Array) { + aParams = ArrayCreate(S_CfgParam, 1); + } + + for (new i = 1, ii = numargs(); i < ii; ++i) { + new Array:aMerge = Array:getarg(i); + + for (new j = 0, jj = ArraySizeSafe(aMerge); j < jj; ++j) { + new Param[S_CfgParam]; + ArrayGetArray(aMerge, j, Param); + + ArrayPushArray(aParams, Param); + } + } + + return aParams; +} + +bool:CfgParam_ReadList( + const JSON:jParams, + &Trie:Params, + const Array:List = Invalid_Array, + ErrParam[] = "", + const Len = 0 +) { + if (!json_is_object(jParams)) { + return false; + } + + if (Params == Invalid_Trie) { + Params = TrieCreate(); + } + + if (List == Invalid_Array) { + Params = Json_ReadObjectToTrie(jParams, Params); + } else { + ArrayForeachArray (List => Param[S_CfgParam]) { + if (!json_object_has_value(jParams, Param[CfgParam_Name])) { + if ( + Param[CfgParam_Required] + && Param[CfgParam_Type] != ptCustom + ) { + formatex(ErrParam, Len, Param[CfgParam_Name]); + return false; + } else { + continue; + } + } + + switch (Param[CfgParam_Type]) { + case ptCustom: + continue; + + case ptInteger: + TrieSetCell(Params, Param[CfgParam_Name], Json_Object_GetInt(jParams, Param[CfgParam_Name])); + + case ptFloat: + TrieSetCell(Params, Param[CfgParam_Name], Json_Object_GetFloat(jParams, Param[CfgParam_Name])); + + case ptBoolean: + TrieSetCell(Params, Param[CfgParam_Name], Json_Object_GetBool(jParams, Param[CfgParam_Name])); + + case ptString: { + new sParam[128]; + Json_Object_GetString(jParams, Param[CfgParam_Name], sParam, charsmax(sParam)); + TrieSetString(Params, Param[CfgParam_Name], sParam); + } + + case ptColor: { + new JSON:jColor = json_object_get_value(jParams, Param[CfgParam_Name]); + new Color[3]; + for (new i = 0; i < 3; ++i) { + Color[i] = json_array_get_number(jColor, i); + } + TrieSetArray(Params, Param[CfgParam_Name], Color, 3); + json_free(jColor); + } + + case ptVector2: { + new JSON:jVec = json_object_get_value(jParams, Param[CfgParam_Name]); + new Float:Vec[2]; + for (new i = 0; i < 2; ++i) { + Vec[i] = json_array_get_real(jVec, i); + } + TrieSetArray(Params, Param[CfgParam_Name], Vec, 2); + json_free(jVec); + } + case ptVector3: { + new JSON:jVec = json_object_get_value(jParams, Param[CfgParam_Name]); + new Float:Vec[3]; + for (new i = 0; i < 3; ++i) { + Vec[i] = json_array_get_real(jVec, i); + } + TrieSetArray(Params, Param[CfgParam_Name], Vec, 3); + json_free(jVec); + } + + case ptLimit: { + new JSON:jLimit = json_object_get_value(jParams, Param[CfgParam_Name]); + new T_LimitUnit:iLimit = VipM_Limits_ReadFromJson(jLimit); + TrieSetCell(Params, Param[CfgParam_Name], iLimit); + json_free(jLimit); + } + case ptLimits: { + new JSON:jLimits = json_object_get_value(jParams, Param[CfgParam_Name]); + new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits, aLimits); + TrieSetCell(Params, Param[CfgParam_Name], aLimits); + json_free(jLimits); + } + } + } + } + + return true; +} diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index e872bd4..0f6590d 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -8,10 +8,11 @@ #include "VipM/ArrayMap" #include "VipM/Core/Modules/Main" -#include "VipM/Core/Limits/Main" -#include "VipM/Core/Structs" +#include "VipM/Core/Objects/Limits/Type" +#include "VipM/Core/Objects/Limits/Unit" +#include "VipM/Core/Objects/Param" -SrvCmds_Init(){ +SrvCmds_Init() { register_srvcmd("vipm_info", "@SrvCmd_Info"); register_srvcmd("vipm_modules", "@SrvCmd_Modules"); @@ -40,8 +41,8 @@ SrvCmds_Init(){ server_print("║ │ │ ├─Modules count: %d", ArrayMapSize(Modules)); server_print("║ │ │ └─Module units count: %d", ArraySizeSafe(ModuleUnits)); server_print("║ │ ├─Limits:"); - server_print("║ │ │ ├─Types count: %d", ArrayMapSize(Limits)); - server_print("║ │ │ └─Limit units count: %d", ArraySizeSafe(LimitUnits)); + server_print("║ │ │ ├─Types count: %d", LimitType_GetCount()); + server_print("║ │ │ └─Limit units count: %d", LimitUnit_GetCount()); server_print("║ │ ├─Vips:"); server_print("║ │ │ └─Vips count: %d", ArraySizeSafe(Vips)); server_print("║ │ └─Compiled by AmxModX v%s:", AMXX_VERSION_STR); @@ -50,7 +51,7 @@ SrvCmds_Init(){ server_print("╙─────────"); } -@SrvCmd_Modules(){ +@SrvCmd_Modules() { server_print("╔═════╤══════════════════════════════════╤════════╗"); server_print("║ # │ Module name │ Status ║"); server_print("╟─────┼──────────────────────────────────┼────────╢"); @@ -62,7 +63,7 @@ SrvCmds_Init(){ server_print("╚═════════════════════════════════════════════════╝"); } -@SrvCmd_ModuleParams(){ +@SrvCmd_ModuleParams() { new Module[S_Module], ModuleName[32]; read_argv(1, ModuleName, charsmax(ModuleName)); @@ -76,49 +77,60 @@ SrvCmds_Init(){ PrintConfigParams(Module[Module_Params]); } -@SrvCmd_Limits(){ +@SrvCmd_Limits() { server_print("╔═════╤══════════════════════════════════╤════════╤════════╤════════════╗"); server_print("║ # │ Limit name │ Params │ Static │ For player ║"); server_print("╟─────┼──────────────────────────────────┼────────┼────────┼────────────╢"); - ArrayMapForeachArray2 (Limits: i => Limit[S_Limit]) { + + new Array:aLimitTypes = LimitType_GetAll(); + ArrayForeachArray2 (aLimitTypes: i => LimitType[S_LimitType]) { server_print("║ %03d │ %-32s │ %-6d │ %-6s │ %-10s ║", - i + 1, Limit[Limit_Name], - ArraySizeSafe(Limit[Limit_Params]), - Limit[Limit_Static] ? "Yes" : "No", - Limit[Limit_ForPlayer] ? "Yes" : "No" + i + 1, LimitType[LimitType_Name], + ArraySizeSafe(LimitType[LimitType_Params]), + LimitType[LimitType_Static] ? "Yes" : "No", + LimitType[LimitType_ForPlayer] ? "Yes" : "No" ); } + ArrayDestroy(aLimitTypes); + server_print("╟─────┴──────────────────────────────────┴────────┴────────┴────────────╢"); - server_print("║ Total: %-5d ║", ArrayMapSize(Limits)); + server_print("║ Total: %-5d ║", LimitType_GetCount()); server_print("╚═══════════════════════════════════════════════════════════════════════╝"); } -@SrvCmd_LimitParams(){ - new LimitType[S_Limit], LimitName[32]; - read_argv(1, LimitName, charsmax(LimitName)); +@SrvCmd_LimitParams() { + enum {Arg_sLimitTypeName = 1} - if (!LIMIT_TYPE_EXISTS(LimitName)) { - server_print("Limit `%s` not found.", LimitName); - return; + new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + read_argv(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); + + new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); + if (iLimitType == Invalid_LimitType) { + server_print("Limit type '%s' not found.", sLimitTypeName); + return PLUGIN_HANDLED; } - LIMIT_TYPE_GET(LimitName, LimitType); - - PrintConfigParams(LimitType[Limit_Params]); + new Array:aLimitTypeParams = LimitType_GetParams(iLimitType); + PrintConfigParams(aLimitTypeParams); + ArrayDestroy(aLimitTypeParams); + + return PLUGIN_HANDLED; } -static PrintConfigParams(const Array:Params) { +static PrintConfigParams(const Array:aParams) { server_print("╔═════╤══════════════════════════════════╤══════════╤══════════╗"); server_print("║ # │ Param name │ Type │ Required ║"); server_print("╟─────┼──────────────────────────────────┼──────────┼──────────╢"); - ArrayForeachArray2 (Params: i => Param[S_CfgParam]) { + + ArrayForeachArray2 (aParams: i => Param[S_CfgParam]) { server_print("║ %3d │ %-32s │ %-8s │ %-8s ║", i + 1, Param[CfgParam_Name], VIPM_PARAM_TYPE_NAMES[Param[CfgParam_Type]], Param[CfgParam_Required] ? "Yes" : "No" ); } + server_print("╟─────┴──────────────────────────────────┴──────────┴──────────╢"); - server_print("║ Total: %-5d ║", ArraySizeSafe(Params)); + server_print("║ Total: %-5d ║", ArraySizeSafe(aParams)); server_print("╚══════════════════════════════════════════════════════════════╝"); } diff --git a/amxmodx/scripting/VipM/Core/Structs.inc b/amxmodx/scripting/VipM/Core/Structs.inc deleted file mode 100644 index 4234e0c..0000000 --- a/amxmodx/scripting/VipM/Core/Structs.inc +++ /dev/null @@ -1,14 +0,0 @@ -#if defined _vipmodular_src_Structs_included - #endinput -#endif -#define _vipmodular_src_Structs_included - -/** - * Vip Modular: Structs - */ - -enum _:S_CfgParam{ - CfgParam_Name[32], - E_ParamType:CfgParam_Type, - bool:CfgParam_Required, -} diff --git a/amxmodx/scripting/VipM/Core/Vips.inc b/amxmodx/scripting/VipM/Core/Vips.inc index 0b7b39b..7afd1fb 100644 --- a/amxmodx/scripting/VipM/Core/Vips.inc +++ b/amxmodx/scripting/VipM/Core/Vips.inc @@ -9,6 +9,8 @@ #include +#include "VipM/Core/Objects/Limits/Unit" + #define Vips_CheckAndAdd(%1) \ CfgUnits_CheckAndAdd(%1, Vips) @@ -23,7 +25,7 @@ Vips_UserUpdate(const UserId) { } #define CfgUnit_CheckAccess(%1,%2) \ - Limits_ExecuteUnitList(%2[CfgUnit_LimitUnits], %1, Limit_Exec_OR) + LimitUnit_ExecuteList(%2[CfgUnit_LimitUnits], %1, Limit_Exec_OR) #define CfgUnit_AddToUser(%1,%2) \ ModuleUnits_AddListToUser(%1, %2[CfgUnit_ModuleUnits]) diff --git a/amxmodx/scripting/VipM/ItemsController/Configs.inc b/amxmodx/scripting/VipM/ItemsController/Configs.inc index cc917eb..1f920dd 100644 --- a/amxmodx/scripting/VipM/ItemsController/Configs.inc +++ b/amxmodx/scripting/VipM/ItemsController/Configs.inc @@ -13,11 +13,11 @@ Cfg_JsonGetItem(&JSON:jItem) { new sJsonRef[PLATFORM_MAX_PATH]; if (Json_IsRef(jItem, sJsonRef, charsmax(sJsonRef))) { if (TrieGetCell(g_ItemsCache, sJsonRef, iItem)) { - Json_FreeRefedValue(jItem); + Json_FreeEx(jItem); return iItem; } - jItem = Json_GetRefValue(jItem, .bFreeSrcIfRef=true); + // jItem = Json_GetRefValue(jItem, .bFreeSrcIfRef=true); } if (jItem == Invalid_JSON) { @@ -30,13 +30,13 @@ Cfg_JsonGetItem(&JSON:jItem) { || !Json_Object_GetItemTypeAndRemove(jItem, sItemTypeName, charsmax(sItemTypeName)) ) { Json_LogForFile(jItem, "WARNING", "Invalid item format."); - Json_FreeRefedValue(jItem); + Json_FreeEx(jItem); return -1; } if (!TYPE_EXISTS(sItemTypeName)) { Json_LogForFile(jItem, "WARNING", "Item type `%s` not found.", sItemTypeName); - Json_FreeRefedValue(jItem); + Json_FreeEx(jItem); return -1; } @@ -53,7 +53,7 @@ Cfg_JsonGetItem(&JSON:jItem) { Forwards_DefaultReturn(VIPM_CONTINUE); if (Forwards_CallP("ReadItem", jItem, Item[Item_Params]) == VIPM_STOP) { TrieDestroySafe(Item[Item_Params]); - Json_FreeRefedValue(jItem); + Json_FreeEx(jItem); return -1; } @@ -62,7 +62,7 @@ Cfg_JsonGetItem(&JSON:jItem) { new iRet = VIPM_CONTINUE; EMIT_TYPE_EVENT(ItemType, ItemType_OnRead, iRet, jItem, Item[Item_Params]) - Json_FreeRefedValue(jItem); + Json_FreeEx(jItem); if (iRet == VIPM_STOP) { TrieDestroySafe(Item[Item_Params]); diff --git a/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc b/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc index 983e9ee..93a54e0 100644 --- a/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc +++ b/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc @@ -1,7 +1,17 @@ -SrvCmds_Init(){ +SrvCmds_Init() { register_srvcmd("vipm_ic_types", "@SrvCmd_Types"); } -@SrvCmd_Types(){ +@SrvCmd_Types() { PrintTypesData(Types); +} + +PrintTypesData(const am[ArrayMap]) { + server_print("╔═════╤══════════════════════════════════╗"); + server_print("║ # │ Type name ║"); + server_print("╟─────┼──────────────────────────────────╢"); + ArrayMapForeachArray (am => Type[S_ItemType]) { + server_print("║ %03d │ %-32s ║", __i__, Type[ItemType_Name]); + } + server_print("╚═════╧══════════════════════════════════╝"); } \ No newline at end of file diff --git a/amxmodx/scripting/VipM/ItemsController/Utils.inc b/amxmodx/scripting/VipM/ItemsController/Utils.inc index 577f015..c7f193a 100644 --- a/amxmodx/scripting/VipM/ItemsController/Utils.inc +++ b/amxmodx/scripting/VipM/ItemsController/Utils.inc @@ -51,14 +51,3 @@ TrieSetCell(%1[ItemType_Events], IntToStr(%2), %3); \ } \ else TrieDeleteKey(%1[ItemType_Events], IntToStr(%2)) - - -PrintTypesData(const am[ArrayMap]){ - server_print("╔═════╤══════════════════════════════════╗"); - server_print("║ # │ Type name ║"); - server_print("╟─────┼──────────────────────────────────╢"); - ArrayMapForeachArray (am => Type[S_ItemType]) { - server_print("║ %03d │ %-32s ║", __i__, Type[ItemType_Name]); - } - server_print("╚═════╧══════════════════════════════════╝"); -} \ No newline at end of file diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index d3e6ae3..e227b9c 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -6,6 +6,9 @@ #include #include +// Метка для распознавания обёрток +stock static const __JSON_WRAPPER_MARK_KEY[] = "!@#--some-random-string-for-identify-wrapper--!@#"; + // Путь до директории, откуда начинать считать ссылки stock static const __JSON_WRAPPER_FIELD_WORKDIR[] = "_work_dir"; @@ -25,32 +28,106 @@ stock static const __JSON_WRAPPER_REF_FILE_PREFIX[] = "File:"; #define JSON_UTILS__MAX_STRING_LENGTH 256 #define JSON_UTILS__MAX_REF_LENGTH 128 +#define Json__CompositeMacros(%1) \ + do { %1 } while(is_linux_server() == 0xDEADBEEF) + +#define Json__VFormatEx(%1,%2,%3) Json__CompositeMacros( \ + if (numargs() > %3) { \ + vformat(%1, charsmax(%1), %2, %3); \ + } else { \ + copy(%1, charsmax(%1), %2); \ + } \ +) + static stock Json__IsWrapper(const JSON:jValue) { - // log_amx("Json__IsWrapper 1 (jValue=%d)", jValue); - if ( - jValue == Invalid_JSON - || !json_is_object(jValue) - || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_FILE, JSONString) - || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_WORKDIR, JSONString) - || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_HANDLER, JSONNumber) - || !json_object_has_value(jValue, __JSON_WRAPPER_FIELD_VALUE) - ) { - // log_amx("Json__IsWrapper 2"); + if (jValue == Invalid_JSON || !json_is_object(jValue)) { + return false; + } + + if (!json_object_has_value(jValue, __JSON_WRAPPER_MARK_KEY, JSONString)) { return false; } - // log_amx("Json__IsWrapper 3"); new JSON:jParent = json_get_parent(jValue); if (jParent != Invalid_JSON) { - // log_amx("Json__IsWrapper 4"); json_free(jParent); return false; } - // log_amx("Json__IsWrapper 5"); return true; } +static stock JSON:Json__GetWrapper(const JSON:jValue) { + new JSON:jRoot = Json__GetRoot(jValue); + + if (jRoot == jValue) { + return Invalid_JSON; + } + + if (!Json__IsWrapper(jRoot)) { + json_free(jRoot); + + return Invalid_JSON; + } + + return jRoot; +} + +static stock JSON:Json__FreeWrapper(&JSON:jWrapper, const bool:bFreeIfNotWrapper = false) { + if (!Json__IsWrapper(jWrapper)) { + Json_FreeIf(jWrapper, bFreeIfNotWrapper); + return jWrapper; + } + + new JSON:iRootWrapperHandler = JSON:json_object_get_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER); + if (iRootWrapperHandler != jWrapper) { + json_free(jWrapper); + } + json_free(iRootWrapperHandler); + + return Invalid_JSON; +} + +static stock Json__GetWrapperPathValue( + const JSON:jValue, + const sKey[], + sOut[] = NULL_STRING, + const iOutLen = 0, + const sDefault[] = NULL_STRING +) { + new JSON:jWrapper = Json__GetWrapper(jValue); + + new sPath[PLATFORM_MAX_PATH]; + if (jWrapper == Invalid_JSON) { + copy(sPath, charsmax(sPath), sDefault); + } else { + json_object_get_string(jWrapper, sKey, sPath, charsmax(sPath)); + json_free(jWrapper); + } + + if (iOutLen) { + copy(sOut, iOutLen, sPath); + } + + return sPath; +} + +static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { + new sPath[PLATFORM_MAX_PATH]; + Json__GetWrapperPathValue(jValue, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath), sDefault); + + copy(sOut, iOutLen, sPath); + return sPath; +} + +static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { + new sPath[PLATFORM_MAX_PATH]; + Json__GetWrapperPathValue(jValue, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath), sDefault); + + copy(sOut, iOutLen, sPath); + return sPath; +} + static stock Json__GetRootConfigsPath(sOut[] = NULL_STRING, const iOutLen = 0) { static sPath[PLATFORM_MAX_PATH]; @@ -66,8 +143,6 @@ static stock Json__GetRootConfigsPath(sOut[] = NULL_STRING, const iOutLen = 0) { } static stock Json__GetFileDir(const sFile[]) { - // log_amx("[DEBUG] Json__GetFileDir: sFile=%s", sFile); - new sDir[PLATFORM_MAX_PATH]; copy(sDir, charsmax(sDir), sFile); @@ -79,13 +154,9 @@ static stock Json__GetFileDir(const sFile[]) { ++i; } - // log_amx("[DEBUG] Json__GetFileDir: sDir=%s", sDir); - // log_amx("[DEBUG] Json__GetFileDir: iLastSlash=%d", iLastSlash); - if (iLastSlash >= 0) { sDir[max(iLastSlash - 1, 0)] = 0; // EOS } - // log_amx("[DEBUG] Json__GetFileDir: return=%s", sDir); return sDir; } @@ -96,222 +167,109 @@ static stock Json__GetFileDir(const sFile[]) { * @param sPath Путь до файла. * @param sWorkDir Корневая директория для ссылок. По умолчанию будет директория, в которой лежит читаемый файл. * - * @note Полученные из этой функции хендлеры обязательно должны освобождаться при помощи Json_DeepFree. + * @note Полученные из этой функции хендлеры обязательно должны освобождаться при помощи Json_FreeEx. * Иначе, из-за обёртки, данные останутся в памяти. * * @return Хендлер прочитанного из файла значения. */ -stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING) { +stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING, const bool:bWithComments = true) { if (!file_exists(sPath)) { log_amx("[ERROR] File '%s' not found.", sPath); return Invalid_JSON; } - new JSON:jFile = json_parse(sPath, true, true); - // log_amx("Json_ParseFromFileEx: 1 (jFile=%d)", jFile); - + new JSON:jFile = json_parse(sPath, true, bWithComments); if (jFile == Invalid_JSON) { log_amx("[ERROR] Can't read JSON from file '%s'.", sPath); return Invalid_JSON; } - // m_bMustBeFreed == true new JSON:jWrapper = json_init_object(); + json_object_set_string(jWrapper, __JSON_WRAPPER_MARK_KEY, __JSON_WRAPPER_MARK_KEY); json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_FILE, sPath); json_object_set_value(jWrapper, __JSON_WRAPPER_FIELD_VALUE, jFile); json_object_set_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER, _:jWrapper); - // log_amx("Json_ParseFromFileEx: 2 (jWrapper=%d)", jWrapper); if (sWorkDir[0]) { json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, sWorkDir); - // log_amx("Json_ParseFromFileEx: sWorkDir=%s from param", sWorkDir); } else { json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, Json__GetFileDir(sPath)); - // log_amx("Json_ParseFromFileEx: sWorkDir=%s inherit", sWorkDir); } - // log_amx("Json_ParseFromFileEx: 3 (jFile=%d)", jFile); return jFile; } -/** - * Удаляет JSON-значение вместе с обёрткой. - * - * @param jValue Корневой (полученный из Json_ParseFromFileEx) JSON-хендлер. - * - * @note Обязательно использовать для очищения хендлеров из Json_ParseFromFileEx. - * Иначе, из-за обёртки, данные останутся в памяти. - * - * @return Invalid_JSON - */ -stock JSON:Json_DeepFree(&JSON:jValue) { - new JSON:jParent; - while (jValue != Invalid_JSON) { - jParent = json_get_parent(jValue); - if (jParent == Invalid_JSON) { - Json__FreeWrapper(jValue, true); - } else { - json_free(jValue); - } - jValue = jParent; - } - return jValue; -} - -/** - * Удаляет JSON-значение, которое могло быть получено по ссылке. - * - * @param jValue JSON-хендлер. - * - * @note Если значение было получено по ссылке, полностью его удаляет из памяти. - * Для обычных значений работает как json_free. - * - * @note Должно использоваться для всех значений, полученных из Json_GetRefValue. - * - * @return Invalid_JSON - */ -stock JSON:Json_FreeRefedValue(&JSON:jValue) { - /* - * Если значение получено по ссылке, его родителем будет обёртка, - * удаление которой полностью удалит все данные. - * - * А если значение было получено не по ссылке, его родителем будет обычное значение, - * удаление которого гарантированно НЕ удалит сами данные, - * т.к. у значения останется родитилем как минимум обёртка. - * - * Обёртка гарантированно будет, т.к. иначе ссылки в принципе не работают. - */ +stock JSON:Json_FreeEx(&JSON:jValue) { new JSON:jParent = json_get_parent(jValue); + Json__FreeWrapper(jParent, false); json_free(jValue); - Json__FreeWrapper(jParent, true); - + return jValue; } -static stock JSON:Json__FreeWrapper(&JSON:jWrapper, const bool:bFreeIfNotWrapper = false) { - if (!Json__IsWrapper(jWrapper)) { - Json_FreeIf(jWrapper, bFreeIfNotWrapper); - return jWrapper; +stock JSON:Json_FreeExIf(&JSON:jValue, const bool:bIf) { + if (bIf) { + Json_FreeEx(jValue); } - new JSON:iRootWrapperHandler = JSON:json_object_get_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER); - json_free(jWrapper); - json_free(iRootWrapperHandler); - - return Invalid_JSON; + return jValue; } +/** + * Получение хендлера корневого JSON-значения. + * + * @param jValue JSON-хендлер, для которого надо найти корневое значение. + * + * @return JSON-хендлер найденного корневого значения. + */ static stock JSON:Json__GetRoot(const JSON:jValue) { if (jValue == Invalid_JSON) { return Invalid_JSON; } - // log_amx("Json__GetRoot 1 (jValue=%d)", jValue); new JSON:jParent; new JSON:jIterator = json_get_parent(jValue); - // log_amx("Json__GetRoot 2 (jIterator=%d)", jIterator); if (jIterator == Invalid_JSON) { return jValue; } - // log_amx("Json__GetRoot 3"); while (jIterator != Invalid_JSON) { jParent = json_get_parent(jIterator); - // log_amx("Json__GetRoot 4 (jParent=%d)", jParent); + if (jParent == Invalid_JSON) { break; } json_free(jIterator); jIterator = jParent; - // log_amx("Json__GetRoot 5 (jIterator=%d)", jIterator); } - // log_amx("Json__GetRoot 6 (jIterator=%d)", jIterator); - // m_bMustBeFreed == false return jIterator; } -static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { - // log_amx("Json__GetFilePath 1 (jValue=%d)", jValue); - new JSON:jRoot = Json__GetRoot(jValue); - // log_amx("Json__GetFilePath 2 (jRoot=%d)", jRoot); - - new sPath[PLATFORM_MAX_PATH]; - if (!Json__IsWrapper(jRoot)) { - // log_amx("Json__GetFilePath 3"); - copy(sPath, charsmax(sPath), sDefault); - } else { - // log_amx("Json__GetFilePath 4"); - json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath)); - } - Json_FreeIf(jRoot, jRoot != jValue); - - if (iOutLen) { - copy(sOut, iOutLen, sPath); - } - // log_amx("Json__GetFilePath 5 (sOut=%s)", sOut); - - return sPath; -} - -static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { - new JSON:jRoot = Json__GetRoot(jValue); - - new sPath[PLATFORM_MAX_PATH]; - if (!Json__IsWrapper(jRoot)) { - copy(sPath, charsmax(sPath), sDefault); - } else { - json_object_get_string(jRoot, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath)); - } - Json_FreeIf(jRoot, jRoot != jValue); - - if (iOutLen) { - copy(sOut, iOutLen, sPath); - } - - return sPath; -} - new stock const __Json_LogForFile_templateFile[] = "[JSON][%s] File: %s"; new stock const __Json_LogForFile_templateMessage[] = "[JSON][%s] Message: %s"; stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...) { - // log_amx("Json_LogForFile 1"); - log_amx(__Json_LogForFile_templateFile, sPrefix, Json__GetFilePath(jValue, .sDefault="*unknown file*")); - static sFormattedMessage[1024]; - if (numargs() >= 4) { - // log_amx("Json_LogForFile 2"); - vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 4); - log_amx(__Json_LogForFile_templateMessage, sPrefix, sFormattedMessage); - } else { - // log_amx("Json_LogForFile 3"); - log_amx(__Json_LogForFile_templateMessage, sPrefix, sMessage); - } - // log_amx("Json_LogForFile 4"); + Json__VFormatEx(sFormattedMessage, sMessage, 4); + + log_amx(__Json_LogForFile_templateFile, sPrefix, Json__GetFilePath(jValue, .sDefault="*unknown file*")); + log_amx(__Json_LogForFile_templateMessage, sPrefix, sFormattedMessage); } new stock const __Json_ErrorForFile_template[] = "[JSON][ERROR] %s: %s"; stock Json_ErrorForFile(const JSON:jValue, const sMessage[], any:...) { static sFormattedMessage[1024]; - if (numargs() >= 4) { - vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 3); - } else { - copy(sFormattedMessage, charsmax(sFormattedMessage), sMessage); - } + Json__VFormatEx(sFormattedMessage, sMessage, 3); - log_amx(__Json_ErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); - log_error(0, __Json_ErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); + abort(0, __Json_ErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); } new stock const __Json_FatalErrorForFile_template[] = "[JSON] %s: %s"; stock Json_FatalErrorForFile(const JSON:jValue, const sMessage[], any:...) { static sFormattedMessage[1024]; - if (numargs() >= 4) { - vformat(sFormattedMessage, charsmax(sFormattedMessage), sMessage, 3); - set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); - } else { - set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sMessage); - } + Json__VFormatEx(sFormattedMessage, sMessage, 3); + + set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); } /** @@ -358,7 +316,14 @@ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = * * @return jValue, если значение не являлось ссылкой, иначе значение полученное по ссылке. */ -stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const bool:bFreeSrcIfRef = false) { +stock JSON:Json_GetRefValue( + const JSON:jValue, + sOut[] = NULL_STRING, + const iOutLen = 0, + &bool:bIsRef = false +) { + bIsRef = false; + new sRefFilePath[PLATFORM_MAX_PATH]; if (!Json_IsRef(jValue, sRefFilePath, charsmax(sRefFilePath))) { return jValue; @@ -370,10 +335,8 @@ stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = if (sRefFilePath[0] == '/') { // Если ссылка начинается со слеша, считать её от amxmodx/configs/ Json__GetRootConfigsPath(sWorkDir, charsmax(sWorkDir)); - // log_amx("[DEBUG] Json_GetRefValue: sWorkDir from root"); } else { Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); - // log_amx("[DEBUG] Json_GetRefValue: sWorkDir from wrapper"); if (!sWorkDir[0]) { // Если у относительной ссылки нет workdir, значит ссылаться некуда) return jValue; @@ -383,23 +346,14 @@ stock JSON:Json_GetRefValue(&JSON:jValue, sOut[] = NULL_STRING, const iOutLen = Json__RightTrim(sWorkDir, '/'); formatex(sFileName, charsmax(sFileName), "%s/%s.json", sWorkDir, sRefFilePath); - // log_amx("[DEBUG] Json_GetRefValue: sWorkDir=%s", sWorkDir); - // log_amx("[DEBUG] Json_GetRefValue: sFileName=%s", sFileName); - // log_amx("[DEBUG] Json_GetRefValue: sRefFilePath=%s", sRefFilePath); - if (iOutLen) { copy(sOut, iOutLen, sFileName); } - Json_FreeIf(jValue, bFreeSrcIfRef); + bIsRef = true; return Json_ParseFromFileEx(sFileName, sWorkDir); } -stock JSON:Json_GetRefValueC(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const bool:bFreeSrcIfRef = false) { - new JSON:_jValue = jValue; - return Json_GetRefValue(_jValue, sOut, iOutLen, bFreeSrcIfRef); -} - stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { if (tTrie == Invalid_Trie) { tTrie = TrieCreate(); @@ -442,13 +396,6 @@ stock bool:Json_FreeIf(&JSON:jValue, const bool:bIf) { return bIf; } -stock bool:Json_DeepFreeIf(&JSON:jValue, const bool:bIf) { - if (bIf) { - Json_DeepFree(jValue); - } - return bIf; -} - static stock Json__RightTrim(sStr[], const cTrim = ' ') { new iLen = Json__StrLen(sStr); if (iLen <= 0) { @@ -469,3 +416,111 @@ static stock Json__StrLen(const sStr[]) { } return iLen; } + +stock bool:Json_Object_GetBool(const JSON:jObj, const sKey[], const bool:bDefault = false, const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, JSONBoolean, bDotNot)) { + return bDefault; + } + + return json_object_get_bool(jObj, sKey, bDotNot); +} + +stock Json_Object_GetInt(const JSON:jObj, const sKey[], const iDefault = 0, const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, JSONNumber, bDotNot)) { + return iDefault; + } + + return json_object_get_number(jObj, sKey, bDotNot); +} + +stock Float:Json_Object_GetFloat(const JSON:jObj, const sKey[], const Float:fDefault = 0.0, const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, JSONNumber, bDotNot)) { + return fDefault; + } + + return json_object_get_real(jObj, sKey, bDotNot); +} + +stock Json_Object_GetString( + const JSON:jObj, + const sKey[], + sOut[], + const iOutLen, + const sDefault[] = NULL_STRING, + const bool:bDotNot = false +) { + if (!json_object_has_value(jObj, sKey, JSONString, bDotNot)) { + return copy(sOut, iOutLen, sDefault); + } else { + return json_object_get_string(jObj, sKey, sOut, iOutLen, bDotNot); + } +} + +stock Json_Object_GetStr(const JSON:jObj, const sKey[], const sDefault[] = NULL_STRING, const bool:bDotNot = false) { + new sRes[MAX_FMT_LENGTH]; + Json_Object_GetString(jObj, sKey, sRes, charsmax(sRes), sDefault, bDotNot); + + return sRes; +} + +stock Json_Object_GetColoredChatMessage( + const JSON:jObj, + const sKey[], + sOut[], + const iOutLen, + const sDefault[] = NULL_STRING, + const bool:bDotNot = false +) { + new iRes = Json_Object_GetString(jObj, sKey, sOut, iOutLen, sDefault, bDotNot); + + iRes -= replace_all(sOut, iOutLen, "^^1", "^1"); + iRes -= replace_all(sOut, iOutLen, "^^3", "^3"); + iRes -= replace_all(sOut, iOutLen, "^^4", "^4"); + + return iRes; +} + +/* +Обёртка для кеширования ссылок. +! Очень извращённая штука, делал чисто под конкретные задачи ! +! Но в целом, наверное, можно ещё где-то использовать ! + +Пример использования: + +* new JSON:jRefed, T_ModuleUnit:iUnit = Invalid_ModuleUnit; +* Json_GetCachedRefValue_Begin(jModuleUnit, __cache_ModuleUnits, iUnit, jRefed) +* { +* new sModuleUnit[S_ModuleUnit]; +* if (ModuleUnits_ReadFromJson(jRefed, sModuleUnit)) { +* iUnit = ModuleUnits_Push(sModuleUnit); +* } +* } +* Json_GetCachedRefValue_End(jModuleUnit, __cache_ModuleUnits, iUnit, jRefed) + +Между *_Begin и *_End должен быть расположен код разбора +содержимого файла с последующей записью кешируемого значения. + +Обе части в ходе выполнения могут прервать выполнение функции, +при чём вторая часть делает это в любом случае. +Также, это значит что код рабора файла может быть не вызван вовсе. + +На строках обёртки ставить ; не надо. +*/ + +// (const JSON:jValue, const Trie:tCache, &any:iCachedValue, &JSON:jRefed) +#define Json_GetCachedRefValue_Begin(%1,%2,%3,%4) \ + new __Json_GetCachedRefValue_sJsonRef[PLATFORM_MAX_PATH]; \ + if ( \ + Json_IsRef(%1, __Json_GetCachedRefValue_sJsonRef, charsmax(__Json_GetCachedRefValue_sJsonRef)) \ + && TrieGetCell(%2, __Json_GetCachedRefValue_sJsonRef, %3) \ + || ((%4 = Json_GetRefValue(%1)) ? false : false) \ + ) { \ + return %3; \ + } + +// (const JSON:jValue, const Trie:tCache, &any:iCachedValue, &JSON:jRefed) +#define Json_GetCachedRefValue_End(%1,%2,%3,%4) \ + (__Json_GetCachedRefValue_sJsonRef[0] \ + && TrieSetCell(%2, __Json_GetCachedRefValue_sJsonRef, %3)); \ + Json_FreeExIf(%4, bool:__Json_GetCachedRefValue_sJsonRef[0]); \ + return %3; diff --git a/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc b/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc index 8594636..5ae5aad 100644 --- a/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc +++ b/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc @@ -7,7 +7,7 @@ Trie:Configs_LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { TrieCreateIfNotCreated(tModules); - new JSON:jFile = GET_FILE_JSON(sFileName); + new JSON:jFile = Json_ParseFromFileEx(sFileName); if (jFile == Invalid_JSON) { log_error(0, "Invalid JSON syntax. File `%s`.", GET_FILE_JSON_PATH(sFileName)); return tModules; @@ -15,7 +15,7 @@ Trie:Configs_LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invali if (!json_is_array(jFile)) { Json_LogForFile(jFile, "WARNING", "Root value must be an array."); - Json_DeepFree(jFile); + Json_FreeEx(jFile); return tModules; } @@ -35,7 +35,6 @@ Trie:Configs_LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invali continue; } - new Array:aModuleNames = json_object_get_strings_list(jItem, "Modules", VIPM_MODULE_MAX_NAME); if (!ArraySizeSafe(aModuleNames)) { Json_LogForFile(jItem, "WARNING", "Field `Modules` must have 1 or more items."); @@ -55,6 +54,6 @@ Trie:Configs_LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invali ArrayDestroy(aModuleNames); } - Json_DeepFree(jFile); + Json_FreeEx(jFile); return tModules; } diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 8052d4c..1405b1f 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -55,6 +55,9 @@ stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; #define ChatPrintL(%1,%2) \ ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2) +#define ChatPrintLIf(%3,%1,%2) \ + ((%3) && ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2)) + #define GET_FILE(%1) \ VipM_iGetCfgPath(%1) @@ -84,57 +87,17 @@ stock CMD_INIT_PARAMS() { #define CMD_ARG_NUM() \ (read_argc() - __CMD_NULL_ARG - 1) -stock static const JSON_FILE_VALUE_PREFIX[] = "File:"; -stock __JSON_LAST_FILE_OBJECT[PLATFORM_MAX_PATH]; -stock JSON:JSON_GET_FILE_OR_OBJECT(JSON:Value) { - __JSON_LAST_FILE_OBJECT[0] = 0; - - if (Value == Invalid_JSON) { - return Value; - } - - if (!json_is_string(Value)) { - return Value; - } - - new FileName[PLATFORM_MAX_PATH]; - json_get_string(Value, FileName, charsmax(FileName)); - if (!equali(JSON_FILE_VALUE_PREFIX, FileName, charsmax(JSON_FILE_VALUE_PREFIX))) { - return Value; - } - - json_free(Value); - - formatex(__JSON_LAST_FILE_OBJECT, charsmax(__JSON_LAST_FILE_OBJECT), FileName[charsmax(JSON_FILE_VALUE_PREFIX)]); - - Value = GET_FILE_JSON(__JSON_LAST_FILE_OBJECT); - if (Value == Invalid_JSON) { - log_amx("[WARNING] JSON syntax error in file `%s`.", __JSON_LAST_FILE_OBJECT); - } - - return Value; -} - -#define GetLastJsonObjectFile() \ - __JSON_LAST_FILE_OBJECT - -#define HasLastJsonObjectFile() \ - bool:(GetLastJsonObjectFile()[0]) - -#define SaveLastJsonObjectFile(%1) \ - new %1[PLATFORM_MAX_PATH];copy(%1, charsmax(%1), GetLastJsonObjectFile()) - #define json_array_foreach(%1:%2) \ - if(json_is_array(%1)) \ - for(new %2 = 0; %2 < json_array_get_count(%1); %2++) + if (json_is_array(%1)) \ + for (new %2 = 0; %2 < json_array_get_count(%1); %2++) #define json_array_foreach_vars(%1:%2,[%3]) \ - if(json_is_array(%1)) \ - for(new %3, %2 = 0; %2 < json_array_get_count(%1); %2++) + if (json_is_array(%1)) \ + for (new %3, %2 = 0; %2 < json_array_get_count(%1); %2++) #define json_array_foreach_value(%1:%2=>%3) \ json_array_foreach_vars(%1: %2, [JSON:%3]) \ - if((%3 = json_array_get_value(%1, %2)) != Invalid_JSON) + if ((%3 = json_array_get_value(%1, %2)) != Invalid_JSON) #define json_get_count(%1) \ (json_is_array(%1) ? json_array_get_count(%1) : 1) @@ -170,10 +133,10 @@ stock Array:json_object_get_strings_list( } #define BitSet(%1,%2) \ - %1 |= (1 << (%2 - 1)) + %1 |= (1 << %2) #define BitReset(%1,%2) \ - %1 &= ~(1 << (%2 - 1)) + %1 &= ~(1 << %2) // by @the_hunter1 :)) #define BitSetIf(%1,%2,%3) ( \ diff --git a/amxmodx/scripting/VipM/WeaponMenu/Configs.inc b/amxmodx/scripting/VipM/WeaponMenu/Configs.inc deleted file mode 100644 index 96f07d4..0000000 --- a/amxmodx/scripting/VipM/WeaponMenu/Configs.inc +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include -#include "VipM/JsonUtils" - -Array:Cfg_ReadMenus(&JSON:jMenus) { - new Array:aMenus = Invalid_Array; - new Menu[S_WeaponMenu]; - - jMenus = Json_GetRefValue(jMenus); - - switch (json_get_type(jMenus)) { - case JSONArray: { - new cMenus = json_array_get_count(jMenus); - aMenus = ArrayCreate(S_WeaponMenu, cMenus); - - for (new i = 0; i < cMenus; i++) { - new JSON:jMenu = json_array_get_value(jMenus, i); - if (Cfg_ReadMenu(jMenu, Menu)) { - ArrayPushArray(aMenus, Menu); - } - json_free(jMenu); - } - } - - case JSONObject: { - if (Cfg_ReadMenu(jMenus, Menu)) { - aMenus = ArrayCreate(S_WeaponMenu, 1); - ArrayPushArray(aMenus, Menu); - } - } - } - - Json_FreeRefedValue(jMenus); - - return aMenus; -} - -bool:Cfg_ReadMenu(&JSON:jMenu, Menu[S_WeaponMenu]){ - static Trie:_FileCache; - if (_FileCache == Invalid_Trie) { - _FileCache = TrieCreate(); - } - - jMenu = Json_GetRefValue(jMenu); - if (jMenu == Invalid_JSON) { - return false; - } - - json_object_get_string(jMenu, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); - - Menu[WeaponMenu_Fake] = false; - if (json_object_has_value(jMenu, "Fake", JSONBoolean)) { - Menu[WeaponMenu_Fake] = json_object_get_bool(jMenu, "Fake"); - } - - // Возможно странное решение, но пока норм) - // Один хер потом переделывать на нормальную систему меню)) - if (Menu[WeaponMenu_Fake]) { - json_object_get_string(jMenu, "FakeMessage", Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage])); - replace_all(Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]), "^^1", "^1"); - replace_all(Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]), "^^3", "^3"); - replace_all(Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]), "^^4", "^4"); - - json_free(jMenu); - return true; - } - - json_object_get_string(jMenu, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title])); - - Menu[WeaponMenu_Count] = -1; - if (json_object_has_value(jMenu, "Count", JSONNumber)) { - Menu[WeaponMenu_Count] = json_object_get_number(jMenu, "Count"); - } - - Menu[WeaponMenu_BackOnExit] = false; - if (json_object_has_value(jMenu, "BackOnExit", JSONBoolean)) { - Menu[WeaponMenu_BackOnExit] = json_object_get_bool(jMenu, "BackOnExit"); - } - - Menu[WeaponMenu_PerPage] = -1; - if (json_object_has_value(jMenu, "PerPage", JSONNumber)) { - Menu[WeaponMenu_PerPage] = json_object_get_number(jMenu, "PerPage"); - } - - Menu[WeaponMenu_ShowPage] = true; - if (json_object_has_value(jMenu, "ShowPage", JSONBoolean)) { - Menu[WeaponMenu_ShowPage] = json_object_get_bool(jMenu, "ShowPage"); - } - - Menu[WeaponMenu_Limits] = VipM_Limits_ReadListFromJson(json_object_get_value(jMenu, "Limits")); - - new JSON:jMenuItems = JsonObjectGetItemsValue(jMenu); - Menu[WeaponMenu_Items] = Cfg_ReadMenuItems(jMenuItems); - - Json_FreeRefedValue(jMenu); - - if (Menu[WeaponMenu_Items] == Invalid_Array) { - log_amx("[WARNING] Menu items are not specified."); - return false; - } - - return true; -} - -Array:Cfg_ReadMenuItems(&JSON:jMenuItems){ - new Array:aMenuItems = Invalid_Array; - new MenuItem[S_MenuItem]; - - jMenuItems = JSON_GET_FILE_OR_OBJECT(jMenuItems); - - switch (json_get_type(jMenuItems)) { - case JSONArray: { - new cMenuItems = json_array_get_count(jMenuItems); - aMenuItems = ArrayCreate(S_MenuItem, cMenuItems); - - for (new i = 0; i < cMenuItems; i++) { - new JSON:jMenuItem = json_array_get_value(jMenuItems, i); - if(Cfg_ReadMenuItem(jMenuItem, MenuItem)) - ArrayPushArray(aMenuItems, MenuItem); - } - json_free(jMenuItems); - } - - case JSONObject: { - if (Cfg_ReadMenuItem(jMenuItems, MenuItem)) { - aMenuItems = ArrayCreate(S_MenuItem, 1); - ArrayPushArray(aMenuItems, MenuItem); - } - } - default: - json_free(jMenuItems); - } - return aMenuItems; -} - -bool:Cfg_ReadMenuItem(&JSON:jMenuItem, MenuItem[S_MenuItem]){ - if (!json_is_object(jMenuItem)) { - log_amx("[WARNING] Invalid weapon menu item format."); - return false; - } - - if (!json_object_get_string(jMenuItem, "Title", MenuItem[MenuItem_Title], charsmax(MenuItem[MenuItem_Title]))) { - MenuItem[MenuItem_Type] = MenuItemType_Blank; - return true; - } - - new JSON:jItems = JsonObjectGetItemsValue(jMenuItem); - if (jItems == Invalid_JSON) { - MenuItem[MenuItem_Type] = MenuItemType_Text; - return true; - } - - MenuItem[MenuItem_Type] = MenuItemType_Default; - - MenuItem[MenuItem_ShowLimits] = VipM_Limits_ReadListFromJson(json_object_get_value(jMenuItem, "ShowLimits")); - MenuItem[MenuItem_ActiveLimits] = VipM_Limits_ReadListFromJson(json_object_get_value(jMenuItem, "ActiveLimits")); - MenuItem[MenuItem_Limits] = VipM_Limits_ReadListFromJson(json_object_get_value(jMenuItem, "Limits")); - - MenuItem[MenuItem_FakeInactive] = false; - if (json_object_has_value(jMenuItem, "FakeInactive", JSONBoolean)) { - MenuItem[MenuItem_FakeInactive] = json_object_get_bool(jMenuItem, "FakeInactive"); - } - - MenuItem[MenuItem_UseCounter] = true; - if (json_object_has_value(jMenuItem, "UseCounter", JSONBoolean)) { - MenuItem[MenuItem_UseCounter] = json_object_get_bool(jMenuItem, "UseCounter"); - } - - json_free(jMenuItem); - - MenuItem[MenuItem_Items] = VipM_IC_JsonGetItems(jItems); - if (MenuItem[MenuItem_Items] == Invalid_Array) { - log_amx("[WARNING] Invalid weapon menu item format. Empty items list."); - return false; - } - - return true; -} - -// TODO: Надо бы удалить и смотреть только на Items -JSON:JsonObjectGetItemsValue(const JSON:jObj){ - if (json_object_has_value(jObj, "Items")) { - return json_object_get_value(jObj, "Items"); - } else if (json_object_has_value(jObj, "Item")) { - return json_object_get_value(jObj, "Item"); - } else { - return Invalid_JSON; - } -} \ No newline at end of file diff --git a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc index 60817c9..6b02c5c 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc @@ -4,6 +4,8 @@ #include "VipM/ArrayTrieUtils" #include "VipM/DebugMode" +#include "VipM/WeaponMenu/Objects/WeaponMenu" + Menu_GetUserMenusCount(const UserId) { return ArraySizeSafe(VipM_Params_GetArr(VipM_Modules_GetParams(MODULE_NAME, UserId), "Menus")); } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc new file mode 100644 index 0000000..6366bb4 --- /dev/null +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -0,0 +1,104 @@ +#if defined __vipm_weaponmenu_objects_menuitem_included + #endinput +#endif +#define __vipm_weaponmenu_objects_menuitem_included + +#include +#include +#include "VipM/JsonUtils" + +enum MenuItemType { + MenuItemType_Default = 0, + MenuItemType_Text, + MenuItemType_Blank, +} + +enum _:S_MenuItem { + MenuItemType:MenuItem_Type, + + MenuItem_Title[64], + Array:MenuItem_Items, // VipM_IC_T_Item[] + bool:MenuItem_UseCounter, + bool:MenuItem_FakeInactive, + + Array:MenuItem_ShowLimits, // T_LimitUnit[] + Array:MenuItem_ActiveLimits, // T_LimitUnit[] + Array:MenuItem_Limits, // T_LimitUnit[] +} + +bool:MenuItem_Read(const JSON:jMenuItem, MenuItem[S_MenuItem]) { + new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenuItem, .bIsRef = bIsRef); + + if (!json_is_object(jRefed)) { + Json_LogForFile(jRefed, "WARNING", "Invalid menu item format."); + return false; + } + + if (!json_object_get_string(jMenuItem, "Title", MenuItem[MenuItem_Title], charsmax(MenuItem[MenuItem_Title]))) { + MenuItem[MenuItem_Type] = MenuItemType_Blank; + Json_FreeExIf(jRefed, bIsRef); + return true; + } + + MenuItem[MenuItem_Items] = Json_Object_GetItemsIC(jMenuItem, "Items"); + + if (MenuItem[MenuItem_Items] == Invalid_Array) { + MenuItem[MenuItem_Type] = MenuItemType_Text; + Json_FreeExIf(jRefed, bIsRef); + return true; + } + + MenuItem[MenuItem_Type] = MenuItemType_Default; + + MenuItem[MenuItem_ShowLimits] = Json_Object_GetLimits(jMenuItem, "ShowLimits"); + MenuItem[MenuItem_ActiveLimits] = Json_Object_GetLimits(jMenuItem, "ActiveLimits"); + MenuItem[MenuItem_Limits] = Json_Object_GetLimits(jMenuItem, "Limits"); + MenuItem[MenuItem_FakeInactive] = Json_Object_GetBool(jMenuItem, "FakeInactive", false); + MenuItem[MenuItem_UseCounter] = Json_Object_GetBool(jMenuItem, "UseCounter", true); + + Json_FreeExIf(jRefed, bIsRef); + return true; +} + +Array:MenuItem_ReadList(const JSON:jMenuItems, &Array:aMenuItems = Invalid_Array) { + ArrayCreateIfNotCreated(aMenuItems, S_MenuItem, 1); + + new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenuItems, .bIsRef = bIsRef); + switch (json_get_type(jRefed)) { + case JSONObject: { + new MenuItem[S_MenuItem]; + if (MenuItem_Read(jRefed, MenuItem)) { + ArrayPushArray(aMenuItems, MenuItem); + } + } + case JSONArray: { + json_array_foreach_value (jRefed: i => jMenuItem) { + MenuItem_ReadList(jMenuItem, aMenuItems); + json_free(jMenuItem); + } + } + default: { + Json_LogForFile(jRefed, "WARNING", "Invalid menu items format."); + } + } + + Json_FreeExIf(jRefed, bIsRef); + return aMenuItems; +} + +Array:Json_Object_GetMenuItemsList( + const JSON:jObj, + const sKey[], + &Array:aMenuItems = Invalid_Array, + const bool:bDotNot = false +) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return Invalid_Array; + } + + new JSON:jMenuItems = json_object_get_value(jObj, sKey, bDotNot); + aMenuItems = MenuItem_ReadList(jMenuItems, aMenuItems); + json_free(jMenuItems); + + return aMenuItems; +} diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc new file mode 100644 index 0000000..237d9f7 --- /dev/null +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -0,0 +1,104 @@ +#if defined __vipm_weaponmenu_objects_weaponmenu_included + #endinput +#endif +#define __vipm_weaponmenu_objects_weaponmenu_included + +#include +#include +#include +#include "VipM/JsonUtils" + +#include "VipM/WeaponMenu/Objects/MenuItem" + +// TODO: Мб на хендлеры переделать?) + +enum _:S_WeaponMenu { + WeaponMenu_Name[64], + WeaponMenu_Title[128], + + Array:WeaponMenu_Items, // S_MenuItem[] + WeaponMenu_Count, + + Array:WeaponMenu_Limits, // T_LimitUnit[] + + bool:WeaponMenu_BackOnExit, + WeaponMenu_PerPage, + bool:WeaponMenu_ShowPage, + + WeaponMenu_FakeMessage[256], +} + +bool:WeaponMenu_Read(&JSON:jMenu, Menu[S_WeaponMenu]) { + new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenu, .bIsRef = bIsRef); + + Json_Object_GetString(jRefed, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); + + if (Json_Object_GetColoredChatMessage( + jRefed, "FakeMessage", + Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]) + )) { + Json_FreeExIf(jRefed, bIsRef); + return true; + } + + Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(jRefed, "Items"); + if (Menu[WeaponMenu_Items] == Invalid_Array) { + Json_LogForFile(jRefed, "WARNING", "Menu items list are empty."); + Json_FreeExIf(jRefed, bIsRef); + return false; + } + + Json_Object_GetString(jRefed, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); + + Menu[WeaponMenu_Count] = Json_Object_GetInt(jRefed, "Count", -1); + Menu[WeaponMenu_BackOnExit] = Json_Object_GetBool(jRefed, "BackOnExit", false); + Menu[WeaponMenu_PerPage] = Json_Object_GetInt(jRefed, "PerPage", -1); + Menu[WeaponMenu_ShowPage] = Json_Object_GetBool(jRefed, "ShowPage", true); + Menu[WeaponMenu_Limits] = Json_Object_GetLimits(jRefed, "Limits"); + + Json_FreeExIf(jRefed, bIsRef); + return true; +} + +Array:WeaponMenu_ReadList(const JSON:jWeaponMenus, &Array:aWeaponMenus = Invalid_Array) { + ArrayCreateIfNotCreated(aWeaponMenus, S_WeaponMenu, 1); + + new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jWeaponMenus, .bIsRef = bIsRef); + switch (json_get_type(jRefed)) { + case JSONObject: { + new WeaponMenu[S_WeaponMenu]; + if (WeaponMenu_Read(jRefed, WeaponMenu)) { + ArrayPushArray(aWeaponMenus, WeaponMenu); + } + } + case JSONArray: { + json_array_foreach_value (jRefed: i => jWeaponMenu) { + aWeaponMenus = WeaponMenu_ReadList(jWeaponMenu, aWeaponMenus); + json_free(jWeaponMenu); + } + } + default: { + Json_LogForFile(jRefed, "WARNING", "Invalid weapon menus format."); + } + } + + Json_FreeExIf(jRefed, bIsRef); + return aWeaponMenus; +} + +Array:Json_Object_GetWeaponMenusList( + const JSON:jObj, + const sKey[], + &Array:aWeaponMenus = Invalid_Array, + const bool:bDotNot = false +) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return Invalid_Array; + } + + new JSON:jWeaponMenus = json_object_get_value(jObj, sKey, bDotNot); + aWeaponMenus = WeaponMenu_ReadList(jWeaponMenus, aWeaponMenus); + json_free(jWeaponMenus); + + return aWeaponMenus; +} diff --git a/amxmodx/scripting/VipM/WeaponMenu/Structs.inc b/amxmodx/scripting/VipM/WeaponMenu/Structs.inc deleted file mode 100644 index d219376..0000000 --- a/amxmodx/scripting/VipM/WeaponMenu/Structs.inc +++ /dev/null @@ -1,31 +0,0 @@ - -enum _:S_WeaponMenu{ - WeaponMenu_Name[64], - WeaponMenu_Title[128], - Array:WeaponMenu_Items, - Array:WeaponMenu_Limits, - WeaponMenu_Count, - bool:WeaponMenu_BackOnExit, - bool:WeaponMenu_Fake, - WeaponMenu_FakeMessage[256], - WeaponMenu_PerPage, - bool:WeaponMenu_ShowPage, -} - -enum MenuItemType{ - MenuItemType_Default = 0, - MenuItemType_Text, - MenuItemType_Blank, -} - -enum _:S_MenuItem{ - MenuItem_Title[64], - Array:MenuItem_Items, - bool:MenuItem_UseCounter, - MenuItemType:MenuItem_Type, - bool:MenuItem_FakeInactive, - - Array:MenuItem_ShowLimits, - Array:MenuItem_ActiveLimits, - Array:MenuItem_Limits, -} diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index 431aac9..b9fc684 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -17,9 +17,8 @@ public stock const PluginDescription[] = "Modular vip system"; new Array:Vips; // S_CfgUnit new Trie:gUserVip[MAX_PLAYERS + 1] = {Invalid_Trie, ...}; // ModuleName => Trie:Params -#include "VipM/Core/Structs" #include "VipM/Core/Modules/Main" -#include "VipM/Core/Limits/Main" +#include "VipM/Core/Objects/Limits/Type" #include "VipM/Core/Configs/Main" #include "VipM/Core/Vips" @@ -30,10 +29,13 @@ public plugin_precache() { RegisterPluginByVars(); register_library(VIPM_LIBRARY); CreateConstCvar("vipm_version", VIPM_VERSION); - RegisterForwards(); SrvCmds_Init(); - Limits_Init(); + + LimitType_Init(); + LimitUnit_Init(); + Forwards_RegAndCall("InitLimits", ET_IGNORE); + Modules_Init(); Forwards_RegAndCall("InitModules", ET_IGNORE); diff --git a/amxmodx/scripting/include/VipM/ItemsController.inc b/amxmodx/scripting/include/VipM/ItemsController.inc index b10b9bc..a4b9ee0 100644 --- a/amxmodx/scripting/include/VipM/ItemsController.inc +++ b/amxmodx/scripting/include/VipM/ItemsController.inc @@ -125,6 +125,8 @@ native VipM_IC_T_Item:VipM_IC_JsonGetItem(&JSON:jItem); native bool:VipM_IC_GiveItem(const UserId, const VipM_IC_T_Item:ItemId); stock Array:VipM_IC_JsonGetItems(JSON:jItems) { + // TODO: Не удалять хендлер (то же относится и к нативу) + new Array:aItems = Invalid_Array; if (jItems == Invalid_JSON) { return aItems; @@ -183,3 +185,15 @@ stock bool:VipM_Params_GiveItems(const UserId, const Trie:tParams, const sParam[ stock bool:VipM_Params_GiveItem(const UserId, const Trie:tParams, const sParam[]) { return VipM_IC_GiveItems(UserId, VipM_Params_GetCell(tParams, sParam)); } + +stock Array:Json_Object_GetItemsIC(const JSON:jObj, const sKey[], const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return Invalid_Array; + } + + new JSON:jItems = json_object_get_value(jObj, sKey, bDotNot); + new Array:aItems = VipM_IC_JsonGetItems(jItems); + json_free(jItems); + + return aItems; +} diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index b5a4348..fe2fa8b 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -3,10 +3,14 @@ #endif #define _vipmodular_l_included +#include + /** * Vip Modular: Limits */ +#define VIPM_LIMITS_TYPE_NAME_MAX_LEN 64 + enum T_LimitUnit {Invalid_LimitUnit = -1} enum E_LimitEvent{ @@ -48,6 +52,16 @@ enum E_LimitsExecType { Limit_Exec_XOR, } +/** + * Вызывается в момент, когда нужно регистрировать типы лимитов. + * Типы лимитов должны регистрироваться строго в рамках этого форварда. + * + * @note Вызывается в рамках plugin_precache. + * + * @noreturn + */ +forward VipM_OnInitLimits(); + /** * Вызывается перед чтением параметров условного элемента. * @@ -161,3 +175,15 @@ native bool:VipM_Limits_Execute(const T_LimitUnit:iLimit, const UserId = 0); * @return true, если условие выполняется, иначе false. */ native bool:VipM_Limits_ExecuteList(const Array:aLimits, const UserId = 0, const E_LimitsExecType:iType = Limit_Exec_OR); + +stock Array:Json_Object_GetLimits(const JSON:jObj, const sKey[], const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return Invalid_Array; + } + + new JSON:jLimits = json_object_get_value(jObj, sKey, bDotNot); + new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits); + json_free(jLimits); + + return aLimits; +} diff --git a/amxmodx/scripting/include/VipM/Params.inc b/amxmodx/scripting/include/VipM/Params.inc index 24d7eaf..9ec76d5 100644 --- a/amxmodx/scripting/include/VipM/Params.inc +++ b/amxmodx/scripting/include/VipM/Params.inc @@ -5,6 +5,8 @@ #include amxmodx +#define VIPM_PARAM_NAME_MAX_LEN 32 + /** * Vip Modular: Parameters */ From e7328a986b5ae9f4d9d1ac0c3ab459d2dfc46a72 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 23 Mar 2024 18:59:00 +0300 Subject: [PATCH 015/108] Complete core rewriting --- .vscode/vipm-src.code-snippets | 22 -- amxmodx/scripting/VipM-ItemsController.sma | 8 +- amxmodx/scripting/VipM-L-Default.sma | 4 +- amxmodx/scripting/VipM-M-VipInTab.sma | 2 +- amxmodx/scripting/VipM-Misc.sma | 49 +++- amxmodx/scripting/VipM-ModulesLimiter.sma | 59 ++++- amxmodx/scripting/VipM/ArrayMap.inc | 152 ++++++----- amxmodx/scripting/VipM/Core/API/Limits.inc | 50 ++-- .../VipM/Core/{Natives.inc => API/Main.inc} | 39 +-- amxmodx/scripting/VipM/Core/API/Modules.inc | 143 +++++------ amxmodx/scripting/VipM/Core/Configs/Main.inc | 22 -- amxmodx/scripting/VipM/Core/Configs/Vips.inc | 90 ------- amxmodx/scripting/VipM/Core/Modules/Main.inc | 17 -- .../scripting/VipM/Core/Modules/Modules.inc | 85 ------ amxmodx/scripting/VipM/Core/Modules/Units.inc | 200 --------------- .../VipM/Core/Objects/Limits/Type.inc | 23 +- .../VipM/Core/Objects/Limits/Unit.inc | 40 ++- .../VipM/Core/Objects/Modules/Type.inc | 241 ++++++++++++++++++ .../VipM/Core/Objects/Modules/Unit.inc | 151 +++++++++++ .../scripting/VipM/Core/Objects/VipUnit.inc | 122 +++++++++ amxmodx/scripting/VipM/Core/SrvCmds.inc | 39 +-- amxmodx/scripting/VipM/Core/Vips.inc | 53 ---- amxmodx/scripting/VipM/Core/VipsManager.inc | 128 ++++++++++ .../VipM/ItemsController/SrvCmds.inc | 10 +- .../scripting/VipM/ItemsController/Utils.inc | 8 +- amxmodx/scripting/VipM/JsonUtils.inc | 24 +- .../scripting/VipM/ModulesLimiter/Configs.inc | 59 ----- amxmodx/scripting/VipModular.sma | 59 ++--- amxmodx/scripting/include/VipM/Modules.inc | 24 +- amxmodx/scripting/include/VipModular.inc | 8 +- 30 files changed, 1081 insertions(+), 850 deletions(-) delete mode 100644 .vscode/vipm-src.code-snippets rename amxmodx/scripting/VipM/Core/{Natives.inc => API/Main.inc} (70%) delete mode 100644 amxmodx/scripting/VipM/Core/Configs/Main.inc delete mode 100644 amxmodx/scripting/VipM/Core/Configs/Vips.inc delete mode 100644 amxmodx/scripting/VipM/Core/Modules/Main.inc delete mode 100644 amxmodx/scripting/VipM/Core/Modules/Modules.inc delete mode 100644 amxmodx/scripting/VipM/Core/Modules/Units.inc create mode 100644 amxmodx/scripting/VipM/Core/Objects/VipUnit.inc delete mode 100644 amxmodx/scripting/VipM/Core/Vips.inc create mode 100644 amxmodx/scripting/VipM/Core/VipsManager.inc delete mode 100644 amxmodx/scripting/VipM/ModulesLimiter/Configs.inc diff --git a/.vscode/vipm-src.code-snippets b/.vscode/vipm-src.code-snippets deleted file mode 100644 index fa7cda3..0000000 --- a/.vscode/vipm-src.code-snippets +++ /dev/null @@ -1,22 +0,0 @@ -{ - "[VipM] AMXX Once Including": { - "scope": "amxxpawn", - "prefix": "onceincv", - "body": [ - "#if defined _vipmodular_$0_included", - " #endinput", - "#endif", - "#define _vipmodular_$0_included" - ] - }, - "[VipM src] AMXX Once Including": { - "scope": "amxxpawn", - "prefix": "onceincvs", - "body": [ - "#if defined _vipmodular_src_$0_included", - " #endinput", - "#endif", - "#define _vipmodular_src_$0_included" - ] - } -} \ No newline at end of file diff --git a/amxmodx/scripting/VipM-ItemsController.sma b/amxmodx/scripting/VipM-ItemsController.sma index 3aa520d..80cc411 100644 --- a/amxmodx/scripting/VipM-ItemsController.sma +++ b/amxmodx/scripting/VipM-ItemsController.sma @@ -13,12 +13,12 @@ public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; public stock const PluginDescription[] = "Vip Modular`s items controller"; -#include "VipM/ItemsController/Structs" -#include "VipM/ItemsController/Utils" - new ArrayMap(Types); // S_ItemType new Array:Items; +#include "VipM/ItemsController/Structs" +#include "VipM/ItemsController/Utils" + public plugin_precache() { PluginInit(); } @@ -34,7 +34,7 @@ PluginInit() { Forwards_Reg("GiveItem", ET_STOP, FP_CELL, FP_CELL); Forwards_Reg("ReadItem", ET_STOP, FP_CELL, FP_CELL); - InitArrayMap(Types, S_ItemType, 8); + ArrayMapCreate(Types, S_ItemType, 8); Forwards_RegAndCall("InitTypes", ET_IGNORE); Items = ArrayCreate(S_Item, 16); diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index fd604e6..3b1a2bf 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -22,7 +22,7 @@ new Trie:g_tUsedInGame = Invalid_Trie; new Float:g_fPlayerSpawnTime[MAX_PLAYERS + 1]; -public VipM_OnInitModules(){ +public VipM_OnInitModules() { RegisterPluginByVars(); VipM_Limits_RegisterType("ForAll", false, true); @@ -161,7 +161,7 @@ public VipM_OnInitModules(){ g_tUsedInGame = TrieCreate(); } -public client_authorized(UserId, const AuthId[]){ +public client_authorized(UserId, const AuthId[]) { VipM_Limits_SetStaticValue("Steam", is_user_steam(UserId), UserId); VipM_Limits_SetStaticValue("Bot", bool:is_user_bot(UserId), UserId); diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index c01ab46..5991441 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -24,7 +24,7 @@ public VipM_OnInitModules() { RegisterPluginByVars(); VipM_Modules_Register(MODULE_NAME, true); - VipM_SetModuleParams(MODULE_NAME, + VipM_Modules_AddParams(MODULE_NAME, "Enabled", ptBoolean, true, "Override", ptBoolean, false ); diff --git a/amxmodx/scripting/VipM-Misc.sma b/amxmodx/scripting/VipM-Misc.sma index 2319fcf..43c8819 100644 --- a/amxmodx/scripting/VipM-Misc.sma +++ b/amxmodx/scripting/VipM-Misc.sma @@ -6,28 +6,61 @@ #pragma semicolon 1 #pragma compress 1 +#define RELOAD_ON_PLAYER_SPAWN 1 +#define RELOAD_ON_ROUND_START 1 +#define RELOAD_ON_ROUND_END 1 + public stock const PluginName[] = "[VipM] Misc"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; -public stock const PluginDescription[] = "Some extentions for Vip Modular."; +public stock const PluginDescription[] = "Auto reload player's privilegies."; -public VipM_OnLoaded(){ +public VipM_OnLoaded() { RegisterPluginByVars(); - RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawned", false); + #if RELOAD_ON_PLAYER_SPAWN + RegisterHookChain(RG_CBasePlayer_Spawn, "@ReloadPlayer", false); + #endif + + #if RELOAD_ON_ROUND_START + RegisterHookChain(RG_CSGameRules_RestartRound, "@OnPlayerSpawned", false); + #endif + + #if RELOAD_ON_ROUND_END + RegisterHookChain(RG_RoundEnd, "@OnPlayerSpawned", false); + #endif - register_srvcmd("vipm_update_users", "@SrvCmd_UpdateUsers"); + register_srvcmd("vipm_update_users", "@SrvCmd_ReloadPlayers"); + register_srvcmd("vipm_reload_players", "@SrvCmd_ReloadPlayers"); } -@OnPlayerSpawned(const UserId){ +@ReloadPlayer(const UserId) { VipM_UserUpdate(UserId); } -@SrvCmd_UpdateUsers() { +@ReloadAllPlayers() { for (new UserId = 1; UserId <= MAX_PLAYERS; UserId++) { - if (is_user_connected(UserId) && !is_user_bot(UserId)) { - VipM_UserUpdate(UserId); + if (is_user_connected(UserId) && !is_user_bot(UserId) && !is_user_hltv(UserId)) { + @ReloadPlayer(UserId); } } } + +@SrvCmd_ReloadPlayers() { + @ReloadAllPlayers(); +} + +@SrvCmd_ReloadPlayer() { + enum {Arg_UserId = 1} + + if (read_argc() < Arg_UserId) { + server_print("Invalid command params."); + server_print("Usage: vipm_reload_players "); + return; + } + + new UserId = read_argv_int(Arg_UserId); + + @ReloadPlayer(UserId); +} diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 80b8607..dedeb9c 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -2,6 +2,7 @@ #include #include "VipM/Utils" #include "VipM/DebugMode" +#include "VipM/ArrayTrieUtils" public stock const PluginName[] = "[VipM] Modules Limiter"; public stock const PluginVersion[] = _VIPM_VERSION; @@ -9,8 +10,6 @@ public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; public stock const PluginDescription[] = "Modules activation controller"; -#include "VipM/ModulesLimiter/Configs" - new const MODULES_CONFIG_FILE[] = "Modules"; new Trie:g_tModulesLimits = Invalid_Trie; @@ -18,7 +17,7 @@ new Trie:g_tModulesLimits = Invalid_Trie; public VipM_OnLoaded() { RegisterPluginByVars(); - g_tModulesLimits = Configs_LoadModulesLimitsFromFile(MODULES_CONFIG_FILE, g_tModulesLimits); + g_tModulesLimits = LoadModulesLimitsFromFile(MODULES_CONFIG_FILE, g_tModulesLimits); } public VipM_OnActivateModule(const sModuleName[]) { @@ -41,3 +40,57 @@ public VipM_OnActivateModule(const sModuleName[]) { return VIPM_CONTINUE; } + +Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { + TrieCreateIfNotCreated(tModules); + + new JSON:jFile = Json_ParseFromFileEx(sFileName); + if (jFile == Invalid_JSON) { + log_error(0, "Invalid JSON syntax. File `%s`.", GET_FILE_JSON_PATH(sFileName)); + return tModules; + } + + if (!json_is_array(jFile)) { + Json_LogForFile(jFile, "WARNING", "Root value must be an array."); + Json_FreeEx(jFile); + return tModules; + } + + json_array_foreach_value (jFile: i => jItem) { + if (!json_is_object(jItem)) { + Json_LogForFile(jItem, "WARNING", "Array item #%d isn`t object.", i); + json_free(jItem); + continue; + } + + new JSON:jLimits = json_object_get_value(jItem, "Limits"); + new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits); + json_free(jLimits); + if (!ArraySizeSafe(aLimits)) { + Json_LogForFile(jItem, "WARNING", "Field `Limits` must have 1 or more items."); + json_free(jItem); + continue; + } + + new Array:aModuleNames = json_object_get_strings_list(jItem, "Modules", VIPM_MODULES_TYPE_NAME_MAX_LEN); + if (!ArraySizeSafe(aModuleNames)) { + Json_LogForFile(jItem, "WARNING", "Field `Modules` must have 1 or more items."); + continue; + } + + ArrayForeachString (aModuleNames: j => sModuleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]) { + if (TrieKeyExists(tModules, sModuleName)) { + Json_LogForFile(jItem, "WARNING", "Duplicate limits for module `%s`.", sModuleName); + continue; + } + + TrieSetCell(tModules, sModuleName, aLimits); + } + + json_free(jItem); + ArrayDestroy(aModuleNames); + } + + Json_FreeEx(jFile); + return tModules; +} diff --git a/amxmodx/scripting/VipM/ArrayMap.inc b/amxmodx/scripting/VipM/ArrayMap.inc index 975bb3c..dc42317 100644 --- a/amxmodx/scripting/VipM/ArrayMap.inc +++ b/amxmodx/scripting/VipM/ArrayMap.inc @@ -3,97 +3,125 @@ #endif #define _vipmodular_src_ArrayMap_included -#include amxmodx +#include -enum ArrayMap{ +enum ArrayMap { Array:AM_Arr, Trie:AM_Map, } -#define ArrayMap(%1) \ - %1[ArrayMap] +#define ArrayMap(%1) %1[ArrayMap] -stock InitArrayMap(AM[ArrayMap], const CellSize = 1, const Reserved = 1) { - AM[AM_Arr] = ArrayCreate(CellSize, Reserved); - AM[AM_Map] = TrieCreate(); +stock ArrayMapCreate(ArrayMap(am), const CellSize = 1, const Reserved = 1) { + am[AM_Arr] = ArrayCreate(CellSize, Reserved); + am[AM_Map] = TrieCreate(); } -stock ArrayMapPushArray(AM[ArrayMap], const any:Input[], const Key[], Size = -1) { - new Id = ArrayPushArray(AM[AM_Arr], Input, Size); - TrieSetCell(AM[AM_Map], Key, Id, true); - return Id; +stock bool:ArrayMapCreated(const ArrayMap(am)) { + return am[AM_Arr] != Invalid_Array; } -stock ArrayMapPushString(AM[ArrayMap], const Input[], const Key[]) { - new Id = ArrayPushString(AM[AM_Arr], Input); - TrieSetCell(AM[AM_Map], Key, Id, true); - return Id; +stock ArrayMapDestroy(ArrayMap(am)) { + if (ArrayMapCreated(am)) { + ArrayDestroy(am[AM_Arr]); + TrieDestroy(am[AM_Map]); + } } -stock ArrayMapPushCell(AM[ArrayMap], any:Input, const Key[]) { - new Id = ArrayPushCell(AM[AM_Arr], Input); - TrieSetCell(AM[AM_Map], Key, Id, true); - return Id; +stock ArrayMapSize(const ArrayMap(am)) { + if (ArrayMapCreated(am)) { + return ArraySize(am[AM_Arr]); + } + + return 0; } -stock ArrayMapGetIndex(AM[ArrayMap], const Key[]) { - new Id = -1; - TrieGetCell(AM[AM_Map], Key, Id); - return Id; +stock bool:ArrayMapKeyExists(const ArrayMap(am), const key[]) { + return TrieKeyExists(am[AM_Map], key); } +stock ArrayMapGetIndex(const ArrayMap(am), const key[]) { + new index = -1; + TrieGetCell(am[AM_Map], key, index); -#define ArrayMapForeach(%1,%2) \ - if (ArrayMapCreated(%1)) \ - for (new %2 = 0; %2 < ArrayMapSize(%1); %2++) + return index; +} -#define ArrayMapForeachArray(%1=>%2[%3]) \ - ArrayMapForeachArrayEx(%1=>%2[%3], __i__) +// cell -#define ArrayMapForeachArrayEx(%1=>%2[%3],%4) \ - if (ArrayMapCreated(%1)) \ - for (new %2[%3], %4 = 0; %4 < ArrayMapSize(%1); %4++) \ - if (ArrayMapGetiArray(%1, %4, %2)) +stock ArrayMapPushCell(const ArrayMap(am), any:index, const key[]) { + new index = ArrayPushCell(am[AM_Arr], index); + TrieSetCell(am[AM_Map], key, index, .replace = false); -#define ArrayMapForeachArray2(%1:%4=>%2[%3]) \ - if (ArrayMapCreated(%1)) \ - for (new %2[%3], %4 = 0; %4 < ArrayMapSize(%1); %4++) \ - if (ArrayMapGetiArray(%1, %4, %2)) + return index; +} +stock ArrayMapGetCell(const ArrayMap(am), const any:index, const block = 0, const bool:asChar = false) { + return ArrayGetCell(am[AM_Arr], index, block, asChar); +} -#define ArrayMapCreated(%1) \ - (%1[AM_Arr] != Invalid_Array) +stock ArrayMapGetCellByKey(const ArrayMap(am), const key[], const block = 0, const bool:asChar = false) { + return ArrayGetCell(am[AM_Arr], ArrayMapGetIndex(am, key), block, asChar); +} -#define ArrayMapDestroy(%1) \ - if (ArrayMapCreated(%1)) { \ - ArrayDestroy(%1[AM_Arr]); TrieDestroy(%1[AM_Map]); \ - } +stock ArrayMapSetCell(const ArrayMap(am), const any:index, const in, const block = 0, const bool:asChar = false) { + return ArraySetCell(am[AM_Arr], index, in, block, asChar); +} + +stock ArrayMapSetCellByKey(const ArrayMap(am), const key[], const in, const block = 0, const bool:asChar = false) { + return ArraySetCell(am[AM_Arr], ArrayMapGetIndex(am, key), in, block, asChar); +} + +// string -#define ArrayMapSize(%1) \ - (ArrayMapCreated(%1) ? ArraySize(%1[AM_Arr]) : 0) +stock ArrayMapPushString(const ArrayMap(am), const Input[], const sKey[]) { + new index = ArrayPushString(am[AM_Arr], Input); + TrieSetCell(am[AM_Map], sKey, index, .replace = false); -#define ArrayMapHasKey(%1,%2) \ - (%2[0] && TrieKeyExists(%1[AM_Map], %2)) - + return index; +} + +stock ArrayMapGetString(const ArrayMap(am), const any:index, out[], const outLen) { + return ArrayGetString(am[AM_Arr], index, out, outLen); +} -#define ArrayMapGetiArray(%1,%2,%3) \ - ArrayGetArray(%1[AM_Arr], %2, %3) +stock ArrayMapGetStringByKey(const ArrayMap(am), const key[], out[], const outLen) { + return ArrayGetString(am[AM_Arr], ArrayMapGetIndex(am, key), out, outLen); +} -#define ArrayMapGetArray(%1,%2,%3) \ - ArrayMapGetiArray(%1, ArrayMapGetIndex(%1, %2), %3) +stock ArrayMapSetString(const ArrayMap(am), const any:index, const in[]) { + return ArraySetString(am[AM_Arr], index, in); +} -#define ArrayMapSetArray(%1,%2,%3) \ - ArraySetArray(%1[AM_Arr], ArrayMapGetIndex(%1, %2), %3) - +stock ArrayMapSetStringByKey(const ArrayMap(am), const key[], const in[]) { + return ArraySetString(am[AM_Arr], ArrayMapGetIndex(am, key), in); +} -#define ArrayMapGetCell(%1,%2) \ - ArrayGetCell(%1[AM_Arr], ArrayMapGetIndex(%1, %2)) +// array -#define ArrayMapSetCell(%1,%2) \ - ArraySetCell(%1[AM_Arr], ArrayMapGetIndex(%1, %2), %3) +stock ArrayMapPushArray(const ArrayMap(am), const any:Input[], const sKey[], size = -1) { + new index = ArrayPushArray(am[AM_Arr], Input, size); + TrieSetCell(am[AM_Map], sKey, index, .replace = false); + return index; +} -#define ArrayMapGetString(%1,%2,%3) \ - ArrayGetString(%1[AM_Arr], ArrayMapGetIndex(%1, %2), %3) +stock ArrayMapGetArray(const ArrayMap(am), const any:index, out[], const size = -1) { + return ArrayGetArray(am[AM_Arr], index, out, size); +} -#define ArrayMapSetString(%1,%2,%3) \ - ArraySetString(%1[AM_Arr], ArrayMapGetIndex(%1, %2), %3) +stock ArrayMapGetArrayByKey(const ArrayMap(am), const key[], out[], const size = -1) { + return ArrayGetArray(am[AM_Arr], ArrayMapGetIndex(am, key), out, size); +} + +stock ArrayMapSetArray(const ArrayMap(am), const any:index, const in[], const size = -1) { + return ArraySetArray(am[AM_Arr], index, in, size); +} + +stock ArrayMapSetArrayByKey(const ArrayMap(am), const key[], const in[], const size = -1) { + return ArraySetArray(am[AM_Arr], ArrayMapGetIndex(am, key), in, size); +} + +#define ArrayMapForeachArray(%1:%4=>%2[%3]) \ + if (ArrayMapCreated(%1)) \ + for (new %2[%3], any:%4 = 0; %4 < ArrayMapSize(%1); %4++) \ + if (ArrayMapGetArray(%1, %4, %2)) diff --git a/amxmodx/scripting/VipM/Core/API/Limits.inc b/amxmodx/scripting/VipM/Core/API/Limits.inc index 39d4df3..87f48fd 100644 --- a/amxmodx/scripting/VipM/Core/API/Limits.inc +++ b/amxmodx/scripting/VipM/Core/API/Limits.inc @@ -7,6 +7,8 @@ #include "VipM/Core/Objects/Param" API_Limits_Init() { + Natives_Init("VipM"); + Natives_Reg("Limits_RegisterType"); Natives_Reg("Limits_AddTypeParams"); Natives_Reg("Limits_RegisterTypeEvent"); @@ -20,7 +22,7 @@ API_Limits_Init() { Natives_Reg("Limits_ExecuteList"); } -// native VipM_Limits_RegisterType(const sName[], const bool:bForPlayer = true, const bool:bStatic = false); +// native VipM_Limits_RegisterType(const sLimitTypeName[], const bool:bForPlayer = true, const bool:bStatic = false); T_LimitType:@_Limits_RegisterType() { enum {Arg_sLimitTypeName = 1, Arg_bForPlayer, Arg_bStatic} @@ -39,16 +41,16 @@ T_LimitType:@_Limits_RegisterType() { return iLimitType; } -// native VipM_Limits_AddTypeParams(const sName[], any:...); +// native VipM_Limits_AddTypeParams(const sLimitTypeName[], any:...); @_Limits_AddTypeParams(const PluginId, const iParamsNum) { - enum {Arg_LimitName = 1, Arg_Params} + enum {Arg_sLimitTypeName = 1, Arg_Params} - new sName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_LimitName, sName, charsmax(sName)); + new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); - new T_LimitType:iLimitType = LimitType_Find(sName); + new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); if (iLimitType == Invalid_LimitType) { - log_error(0, "Limit type '%s' not found.", sName); + log_error(0, "Limit type '%s' not found.", sLimitTypeName); return; } @@ -57,40 +59,40 @@ T_LimitType:@_Limits_RegisterType() { return; } - LimitType_MergeParams(iLimitType, aParams); + LimitType_MergeParamsList(iLimitType, aParams); } -// native VipM_Limits_RegisterTypeEvent(const sName[], const E_LimitEvent:iEvent, const sFunc[]); +// native VipM_Limits_RegisterTypeEvent(const sLimitTypeName[], const E_LimitEvent:iEvent, const sFunc[]); @_Limits_RegisterTypeEvent(const PluginId) { - enum {Arg_LimitName = 1, Arg_Event, Arg_FuncName} + enum {Arg_sLimitTypeName = 1, Arg_iEvent, Arg_sFuncName} - new sName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_LimitName, sName, charsmax(sName)); + new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); - new T_LimitType:iLimitType = LimitType_Find(sName); + new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); if (iLimitType == Invalid_LimitType) { - log_error(0, "Limit type '%s' not found.", sName); + log_error(0, "Limit type '%s' not found.", sLimitTypeName); return; } - new E_LimitEvent:iEvent = E_LimitEvent:get_param(Arg_Event); + new E_LimitEvent:iEvent = E_LimitEvent:get_param(Arg_iEvent); - new sFunc[64]; - get_string(Arg_FuncName, sFunc, charsmax(sFunc)); + new sFuncName[64]; + get_string(Arg_sFuncName, sFuncName, charsmax(sFuncName)); - LimitType_SetEventListener(iLimitType, iEvent, PluginId, sFunc); + LimitType_SetEventListener(iLimitType, iEvent, PluginId, sFuncName); } -// native VipM_Limits_Execute(const sName[], const bool:bNewValue, const UserId = 0); +// native VipM_Limits_Execute(const sLimitTypeName[], const bool:bNewValue, const UserId = 0); @_Limits_SetStaticValue() { - enum {Arg_LimitName = 1, Arg_NewValue, Arg_UserId} + enum {Arg_sLimitTypeName = 1, Arg_NewValue, Arg_UserId} - static sName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_LimitName, sName, charsmax(sName)); + static sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); - new T_LimitType:iLimitType = LimitType_Find(sName); + new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); if (iLimitType == Invalid_LimitType) { - log_error(0, "Limit type '%s' not found.", sName); + log_error(0, "Limit type '%s' not found.", sLimitTypeName); return; } diff --git a/amxmodx/scripting/VipM/Core/Natives.inc b/amxmodx/scripting/VipM/Core/API/Main.inc similarity index 70% rename from amxmodx/scripting/VipM/Core/Natives.inc rename to amxmodx/scripting/VipM/Core/API/Main.inc index 6f58032..b3c7957 100644 --- a/amxmodx/scripting/VipM/Core/Natives.inc +++ b/amxmodx/scripting/VipM/Core/API/Main.inc @@ -1,27 +1,25 @@ -#if defined _vipmodular_src_Natives_included - #endinput -#endif -#define _vipmodular_src_Natives_included - -/** - * Vip Modular: Natives - */ - #include #include "VipM/Natives" #include "VipM/Utils" +#include "VipM/JsonUtils" +#include "VipM/Core/VipsManager" -#include "VipM/Core/API/Limits" -#include "VipM/Core/API/Modules" - -public plugin_natives() { +API_Main_Init() { Natives_Init("VipM"); Natives_Reg("UserUpdate"); Natives_Reg("Json_LogForFile"); +} - Natives_Modules_Init(); - API_Limits_Init(); +@_UserUpdate() { + enum {Arg_UserId = 1} + + new UserId = get_param(Arg_UserId); + if (!is_user_connected(UserId)) { + return; + } + + VipsManager_UserReload(UserId); } // native VipM_Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...); @@ -34,14 +32,3 @@ public plugin_natives() { Json_LogForFile(JSON:get_param(Arg_jValue), sPrefix, sMessage); } - -@_UserUpdate() { - enum {Arg_UserId = 1} - - new UserId = get_param(Arg_UserId); - if (!is_user_connected(UserId)) { - return; - } - - Vips_UserUpdate(UserId); -} diff --git a/amxmodx/scripting/VipM/Core/API/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc index be21f61..5f838df 100644 --- a/amxmodx/scripting/VipM/Core/API/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -3,7 +3,9 @@ #include "VipM/Natives" #include "VipM/Core/Objects/Param" -Natives_Modules_Init(){ +API_Modules_Init(){ + Natives_Init("VipM"); + Natives_Reg("Modules_Register"); Natives_Reg("Modules_AddParams"); Natives_Reg("Modules_RegisterEvent"); @@ -11,114 +13,91 @@ Natives_Modules_Init(){ Natives_Reg("Modules_GetParams"); } -@_Modules_Register(const PluginId) { - enum {Arg_Module = 1, Arg_Once} +T_ModuleType:@_Modules_Register(const PluginId) { + enum {Arg_sModuleTypeName = 1} - new Module[S_Module]; + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); - get_string(Arg_Module, Module[Module_Name], charsmax(Module[Module_Name])); - Module[Module_PluginId] = PluginId; - Module[Module_Enabled] = false; - Module[Module_Once] = bool:get_param(Arg_Once); + new T_ModuleType:iModuleType = ModuleType_Construct(sModuleTypeName); + if (iModuleType == Invalid_ModuleType) { + log_error(0, "Can't create module type '%s'.", sModuleTypeName); + return Invalid_ModuleType; + } - Module[Module_Params] = Invalid_Array; - Module[Module_Events] = Invalid_Trie; + return iModuleType; +} - Module[Module_Used] = false; +@_Modules_AddParams(const PluginId, const iParamsNum) { + enum {Arg_sModuleTypeName = 1, Arg_Params} - ArrayMapPushArray(Modules, Module, Module[Module_Name]); -} + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); -@_Modules_AddParams(const PluginId, const ParamsCount) { - enum {Arg_Module = 1, Arg_Params} - - new ModuleName[32], Module[S_Module]; - get_string(Arg_Module, ModuleName, charsmax(ModuleName)); + new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); + if (iModuleType == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", sModuleTypeName); + return; + } - NATIVE_CHECK_MODULE(ModuleName) - GET_MODULE(ModuleName, Module); - new bool:bSave = (Module[Module_Params] == Invalid_Array); - - Module[Module_Params] = CfgParam_GetFromNative(Arg_Params, ParamsCount, Module[Module_Params]); - - if (bSave) { - SET_MODULE(Module); + new Array:aParams = CfgParam_GetFromNative(Arg_Params, iParamsNum); + if (aParams == Invalid_Array) { + return; } + + ModuleType_MergeParamsList(iModuleType, aParams); } bool:@_Modules_RegisterEvent(const PluginId) { - enum {Arg_Module = 1, Arg_Event, Arg_Func} - - new ModuleName[32], Module[S_Module]; - get_string(Arg_Module, ModuleName, charsmax(ModuleName)); - - NATIVE_CHECK_MODULE(ModuleName) - GET_MODULE(ModuleName, Module); - - new E_ModuleEvent:Event = E_ModuleEvent:get_param(Arg_Event); - - new FuncName[64]; - get_string(Arg_Func, FuncName, charsmax(FuncName)); - - new FwdId = -1; - switch (Event) { - case Module_OnRead: // (const JSON:jCfg, Trie:Params) - FwdId = CreateOneForward(PluginId, FuncName, FP_CELL, FP_CELL); + enum {Arg_sModuleTypeName = 1, Arg_iEvent, Arg_sFuncName} - case Module_OnActivated: // () - FwdId = CreateOneForward(PluginId, FuncName); + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); - case Module_OnCompareParams: // (Trie:MainParams, const Trie:NewParams) - FwdId = CreateOneForward(PluginId, FuncName, FP_CELL, FP_CELL); - } - - if (FwdId < 0) { + new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); + if (iModuleType == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", sModuleTypeName); return false; } - SET_MODULE_EVENT(Module, Event, FwdId); - SET_MODULE(Module); + new E_ModuleEvent:iEvent = E_ModuleEvent:get_param(Arg_iEvent); + + new sFuncName[64]; + get_string(Arg_sFuncName, sFuncName, charsmax(sFuncName)); - return FwdId >= 0; + ModuleType_SetEventListener(iModuleType, iEvent, PluginId, sFuncName); + return true; } -@_Modules_IsActive() { - enum {Arg_Module = 1} - - static ModuleName[32], Module[S_Module]; - get_string(Arg_Module, ModuleName, charsmax(ModuleName)); +bool:@_Modules_IsActive() { + enum {Arg_sModuleTypeName = 1} - NATIVE_CHECK_MODULE(ModuleName) - GET_MODULE(ModuleName, Module); + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); + + new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); + if (iModuleType == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", sModuleTypeName); + return false; + } - return Module[Module_Enabled]; + return ModuleType_IsActive(iModuleType); } Trie:@_Modules_GetParams() { - enum {Arg_Module = 1, Arg_UserId, Arg_Forced} - - static ModuleName[32]; - get_string(Arg_Module, ModuleName, charsmax(ModuleName)); - NATIVE_CHECK_MODULE(ModuleName) + enum {Arg_sModuleTypeName = 1, Arg_UserId} - new UserId = get_param(Arg_UserId); + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); - new bool:bCanGetParams = true; - if (!get_param(Arg_Forced)) { - static Module[S_Module]; - GET_MODULE(ModuleName, Module); - bCanGetParams = Module[Module_Enabled]; - } - - new Trie:Params = Invalid_Trie; - if ( - !is_user_connected(UserId) - || gUserVip[UserId] == Invalid_Trie - || !TrieGetCell(gUserVip[UserId], ModuleName, Params) - || !bCanGetParams - ) { + // TODO: Потом переделать сразу не хендлеры + new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); + if (iModuleType == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", sModuleTypeName); return Invalid_Trie; } + + new UserId = get_param(Arg_UserId); - return Params; + return VipsManager_GetUserParams(UserId, iModuleType); } diff --git a/amxmodx/scripting/VipM/Core/Configs/Main.inc b/amxmodx/scripting/VipM/Core/Configs/Main.inc deleted file mode 100644 index c475bae..0000000 --- a/amxmodx/scripting/VipM/Core/Configs/Main.inc +++ /dev/null @@ -1,22 +0,0 @@ -#if defined _vipmodular_src_Configs_included - #endinput -#endif -#define _vipmodular_src_Configs_included - -/** - * Vip Modular: Configs - */ - -#include amxmodx -#include json - -enum _:S_CfgUnit{ - Array:CfgUnit_LimitUnits, // S_AccessUnit - Array:CfgUnit_ModuleUnits, // S_ModuleUnit -} - -#include "VipM/Core/Configs/Vips" - -// Utils - - diff --git a/amxmodx/scripting/VipM/Core/Configs/Vips.inc b/amxmodx/scripting/VipM/Core/Configs/Vips.inc deleted file mode 100644 index 32e1006..0000000 --- a/amxmodx/scripting/VipM/Core/Configs/Vips.inc +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include - -#include "VipM/Core/Objects/Limits/Unit" - -static stock const VIPS_CFG_FILE[] = "Vips"; -static stock const VIPS_CFGS_DIR[] = "Vips"; - -Array:Cfg_LoadVipsConfigs(Array:aList = Invalid_Array) { - if (JSON_FILE_EXTSTS(VIPS_CFG_FILE)) { - aList = Cfg_LoadVipsConfigFromFile(VIPS_CFG_FILE, aList); - } - - new sFilePath[PLATFORM_MAX_PATH], iDirHandler, FileType:Type; - iDirHandler = open_dir(GET_FILE(VIPS_CFGS_DIR), sFilePath, charsmax(sFilePath), Type); - if (!iDirHandler) { - return aList; - } - - new ret, Regex:RegEx_FileName = regex_compile("(.+).json$", ret, "", 0, "i"); - do { - if ( - sFilePath[0] == '!' - || Type != FileType_File - || regex_match_c(sFilePath, RegEx_FileName) <= 0 - ) { - continue; - } - - new sFileName[64]; - regex_substr(RegEx_FileName, 1, sFileName, charsmax(sFileName)); - - aList = Cfg_LoadVipsConfigFromFile(fmt("%s/%s", VIPS_CFGS_DIR, sFileName), aList); - } while (next_file(iDirHandler, sFilePath, charsmax(sFilePath), Type)); - - return aList; -} - -Array:Cfg_LoadVipsConfigFromFile(const sFileName[], Array:aList = Invalid_Array) { - new JSON:jVips = Json_ParseFromFileEx(sFileName); - if (!json_is_array(jVips)) { - set_fail_state("[ERROR] File '%s' must contains a JSON-array.", GET_FILE_JSON_PATH(sFileName)); - return Invalid_Array; - } - - ArrayCreateIfNotCreated(aList, S_CfgUnit, json_array_get_count(jVips)); - new CfgUnit[S_CfgUnit]; - json_array_foreach_value (jVips: i => jCfgUnit) { - if (Cfg_ReadVipConfig(jCfgUnit, CfgUnit)) { - ArrayPushArray(aList, CfgUnit); - } - Json_FreeEx(jCfgUnit); - } - - Json_FreeEx(jVips); - return aList; -} - -bool:Cfg_ReadVipConfig(const JSON:jCfgUnit, CfgUnit[S_CfgUnit]) { - new JSON:jAccess = json_object_get_value(jCfgUnit, "Access"); - if (jAccess == Invalid_JSON) { - return false; - } - - CfgUnit[CfgUnit_LimitUnits] = LimitUnit_ReadList(jAccess); - json_free(jAccess); - if (!ArraySizeSafe(CfgUnit[CfgUnit_LimitUnits])) { - ArrayDestroy(CfgUnit[CfgUnit_LimitUnits]); - return false; - } - - new JSON:jModules = json_object_get_value(jCfgUnit, "Modules"); - if (jModules == Invalid_JSON) { - ArrayDestroy(CfgUnit[CfgUnit_LimitUnits]); - return false; - } - - CfgUnit[CfgUnit_ModuleUnits] = ModuleUnits_LoadListFromJson(jModules); - json_free(jModules); - if (!ArraySizeSafe(CfgUnit[CfgUnit_ModuleUnits])) { - // TODO: Тут нужен специальный дестрой для ограничений, иначе утечка говна) - // Но эта штука случается только при кривых конфигах, так что не критично))) - ArrayDestroy(CfgUnit[CfgUnit_LimitUnits]); - ArrayDestroy(CfgUnit[CfgUnit_ModuleUnits]); - return false; - } - - return true; -} diff --git a/amxmodx/scripting/VipM/Core/Modules/Main.inc b/amxmodx/scripting/VipM/Core/Modules/Main.inc deleted file mode 100644 index c1f964f..0000000 --- a/amxmodx/scripting/VipM/Core/Modules/Main.inc +++ /dev/null @@ -1,17 +0,0 @@ -#if defined _vipmodular_src_Modules_included - #endinput -#endif -#define _vipmodular_src_Modules_included - -#define NATIVE_CHECK_MODULE(%1) \ - if (!MODULE_EXISTS(%1)) {\ - log_error(1, "[ERROR] Module '%s' not found.", %1);\ - } - -#include "VipM/Core/Modules/Modules.inc" -#include "VipM/Core/Modules/Units.inc" - -Modules_Init() { - Modules_InitModules(); - Modules_InitUnits(); -} diff --git a/amxmodx/scripting/VipM/Core/Modules/Modules.inc b/amxmodx/scripting/VipM/Core/Modules/Modules.inc deleted file mode 100644 index 8cab0b5..0000000 --- a/amxmodx/scripting/VipM/Core/Modules/Modules.inc +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include "VipM/ArrayMap" -#include "VipM/Utils" -#include "VipM/Forwards" - -enum _:S_Module { - Module_PluginId, - Module_Name[32], - bool:Module_Once, - bool:Module_Enabled, - - Array:Module_Params, // S_CfgParam - Trie:Module_Events, - - bool:Module_Used, -} - -#define MODULE_EXISTS(%1) \ - ArrayMapHasKey(Modules, %1) - -#define GET_MODULE(%1,%2) \ - ArrayMapGetArray(Modules, %1, %2) - -#define GET_MODULE_ID(%1) \ - ArrayMapGetIndex(Modules, %1) - -#define GET_MODULE_BY_ID(%1,%2) \ - ArrayMapGetiArray(Modules, %1, %2) - -#define SET_MODULE(%1) \ - ArrayMapSetArray(Modules, %1[Module_Name], %1) - -// EMIT_MODULE_EVENT(Module, E_ModuleEvent:Event, Return, ...Params) -#define EMIT_MODULE_EVENT(%1,%2,%3) CompositeMacros( \ - if( \ - %1[Module_Events] != Invalid_Trie \ - && TrieKeyExists(%1[Module_Events], IntToStr(%2)) \ - ){ \ - new ___EVENT_FWD; \ - TrieGetCell(%1[Module_Events], IntToStr(%2), ___EVENT_FWD); \ - ExecuteForward(___EVENT_FWD, %3); \ - } \ -) - -// SET_MODULE_EVENT(Module, E_ModuleEvent:Event, FwdId) -#define SET_MODULE_EVENT(%1,%2,%3) CompositeMacros( \ - if(%3 >= 0){ \ - if(%1[Module_Events] == Invalid_Trie) \ - %1[Module_Events] = TrieCreate(); \ - \ - TrieSetCell(%1[Module_Events], IntToStr(%2), %3); \ - } \ - else TrieDeleteKey(%1[Module_Events], IntToStr(%2)); \ -) - -new ArrayMap(Modules); // S_Module - -Modules_Enable(const iModule) { - new Module[S_Module]; - GET_MODULE_BY_ID(iModule, Module); - - Forwards_DefaultReturn(VIPM_CONTINUE); - new ret = VIPM_CONTINUE; - - if ((ret = Forwards_CallP("ActivateModule", Module[Module_Name])) != VIPM_STOP) { - EMIT_MODULE_EVENT(Module, Module_OnActivated, ret); - } - - Module[Module_Enabled] = (ret == VIPM_CONTINUE); - SET_MODULE(Module); - - // Dbg_Log("Modules_Enable(%d): Module_Enabled = %d", iModule, Module[Module_Enabled]); -} - -Modules_EnableAllUsed() { - ArrayMapForeachArray2 (Modules: iModule => Module[S_Module]) { - if (Module[Module_Used]) { - Modules_Enable(iModule); - } - } -} - -Modules_InitModules(){ - InitArrayMap(Modules, S_Module, 8); -} \ No newline at end of file diff --git a/amxmodx/scripting/VipM/Core/Modules/Units.inc b/amxmodx/scripting/VipM/Core/Modules/Units.inc deleted file mode 100644 index 24962de..0000000 --- a/amxmodx/scripting/VipM/Core/Modules/Units.inc +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include "VipM/ArrayMap" -#include "VipM/DebugMode" - -const MODULE_UNITS_PRESERVED_SIZE = 8; -new const MODULE_PARAMS_ISTEMP_KEY[] = "__IsTemp"; - -enum T_ModuleUnit { Invalid_ModuleUnit = -1 } - -enum _:S_ModuleUnit { - ModuleUnit_ModuleId, - Trie:ModuleUnit_Params, -} - -new Array:ModuleUnits; - -#define ModuleUnits_Push(%1) \ - T_ModuleUnit:ArrayPushArray(ModuleUnits, %1) - -#define ModuleUnits_Get(%1,%2) \ - ArrayGetArray(ModuleUnits, _:%1, %2) - -// Init - -Modules_InitUnits() { - ModuleUnits = ArrayCreate(S_ModuleUnit, MODULE_UNITS_PRESERVED_SIZE); -} - - -// Actions - -ModuleUnits_ResetUser(const UserId) { - if (gUserVip[UserId] == Invalid_Trie) { - return; - } - - new TrieIter:Iter = TrieIterCreate(gUserVip[UserId]); - while (!TrieIterEnded(Iter)) { - new Trie:Params = Invalid_Trie; - if ( - TrieIterGetCell(Iter, Params) - && TrieKeyExists(Params, MODULE_PARAMS_ISTEMP_KEY) - && Params != Invalid_Trie - ) { - TrieDestroy(Params); - } - - TrieIterNext(Iter); - } - TrieIterDestroy(Iter); - - TrieDestroy(gUserVip[UserId]); -} - -ModuleUnits_AddListToUser(const UserId, const Array:aUnits) { - if (aUnits == Invalid_Array) { - return; - } - - for (new i = 0; i < ArraySize(aUnits); i++) { - ModuleUnits_AddToUser(UserId, T_ModuleUnit:ArrayGetCell(aUnits, i)); - } -} - -ModuleUnits_AddToUser(const UserId, const T_ModuleUnit:iMUnit) { - if (gUserVip[UserId] == Invalid_Trie) { - gUserVip[UserId] = TrieCreate(); - } - - new Unit[S_ModuleUnit]; - ModuleUnits_Get(iMUnit, Unit); - - new Module[S_Module]; - GET_MODULE_BY_ID(Unit[ModuleUnit_ModuleId], Module); - - if (TrieKeyExists(gUserVip[UserId], Module[Module_Name])) { - if (Module[Module_Once]) { - return; - } - - new Trie:Params; - TrieGetCell(gUserVip[UserId], Module[Module_Name], Params); - - new Trie:Ret = Invalid_Trie; - EMIT_MODULE_EVENT(Module, Module_OnCompareParams, _:Ret, Params, Unit[ModuleUnit_Params]); - if (Ret == Invalid_Trie) { - return; - } - - if (TrieKeyExists(Params, MODULE_PARAMS_ISTEMP_KEY)) { - TrieDestroy(Params); - } - - TrieSetCell(Ret, MODULE_PARAMS_ISTEMP_KEY, true); - TrieSetCell(gUserVip[UserId], Module[Module_Name], Ret); - Dbg_Log("ModuleUnits_AddToUser(#%d, '%s'): Compared", UserId, Module[Module_Name]); - } else { - TrieSetCell(gUserVip[UserId], Module[Module_Name], Unit[ModuleUnit_Params], false); - - if (IS_DEBUG) { - // А то мешает когда в консоль срёт такими сообщениями для каждого бота - if (!is_user_bot(UserId)) { - Dbg_Log("ModuleUnits_AddToUser(#%d, '%s'): First add", UserId, Module[Module_Name]); - } - } - } -} - - -// Readers - -bool:ModuleUnits_ReadFromJson(const JSON:jMUnit, sMUnit[S_ModuleUnit]) { - new ModuleName[32]; - json_object_get_string(jMUnit, "Module", ModuleName, charsmax(ModuleName)); - json_object_remove(jMUnit, "Module"); - - if (!MODULE_EXISTS(ModuleName)) { - Json_LogForFile(jMUnit, "WARNING", "Module `%s` not found.", ModuleName); - return false; - } - - new iModule = GET_MODULE_ID(ModuleName); - // Modules_Enable(iModule); - - new sModule[S_Module]; - GET_MODULE_BY_ID(iModule, sModule); - - // Пусть юниты модулей читаются вне зависимости от состояния модуля - // Чтобы позже можно было на лету переключать состояние - - sMUnit[ModuleUnit_ModuleId] = iModule; - sMUnit[ModuleUnit_Params] = TrieCreate(); - - new ErrParam[32]; - if (!CfgParam_ReadList(jMUnit, sMUnit[ModuleUnit_Params], sModule[Module_Params], ErrParam, charsmax(ErrParam))) { - Json_LogForFile(jMUnit, "WARNING", "Param `%s` required for module `%s`, but not found.", ErrParam, sModule[Module_Name]); - return false; - } - - Forwards_DefaultReturn(VIPM_CONTINUE); - if ( - Forwards_CallP("ReadUnit", jMUnit, sMUnit[ModuleUnit_Params]) == VIPM_STOP - || Forwards_CallP("ReadModuleUnit", jMUnit, sMUnit[ModuleUnit_Params]) == VIPM_STOP - ) { - TrieDestroySafe(sMUnit[ModuleUnit_Params]); - return false; - } - - new ret; - EMIT_MODULE_EVENT(sModule, Module_OnRead, ret, jMUnit, sMUnit[ModuleUnit_Params]); - - if (ret == VIPM_STOP) { - TrieDestroySafe(sMUnit[ModuleUnit_Params]); - return false; - } - - if (!sModule[Module_Used]) { - sModule[Module_Used] = true; - SET_MODULE(sModule); - Dbg_Log("Module `%s` marked as used.", ModuleName); - } - - return true; -} - -// Loaders - -T_ModuleUnit:ModuleUnits_LoadFromJson(const JSON:jModuleUnit) { - static Trie:tCache = Invalid_Trie; - TrieCreateIfNotCreated(tCache); - - new JSON:jRefed, T_ModuleUnit:iUnit = Invalid_ModuleUnit; - Json_GetCachedRefValue_Begin(jModuleUnit, tCache, iUnit, jRefed) - { - new ModuleUnit[S_ModuleUnit]; - if (ModuleUnits_ReadFromJson(jRefed, ModuleUnit)) { - iUnit = ModuleUnits_Push(ModuleUnit); - } - } - Json_GetCachedRefValue_End(jModuleUnit, tCache, iUnit, jRefed) -} - -Array:ModuleUnits_LoadListFromJson(const JSON:jModules, &Array:aModules = Invalid_Array) { - ArrayCreateIfNotCreated(aModules, 1, 1); - - if (!json_is_array(jModules)) { - new T_ModuleUnit:iMUnit = ModuleUnits_LoadFromJson(jModules); - if (iMUnit != Invalid_ModuleUnit) { - ArrayPushCell(aModules, iMUnit); - } - } else { - json_array_foreach_value (jModules: i => jModule) { - aModules = ModuleUnits_LoadListFromJson(jModule, aModules); - json_free(jModule); - } - } - - return aModules; -} diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 84b7b6c..57175a6 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -13,7 +13,7 @@ enum _:S_LimitType { LimitType_Name[VIPM_LIMITS_TYPE_NAME_MAX_LEN], - Array:LimitType_Params, // S_CfgParam + Array:LimitType_Params, // S_CfgParam[] bool:LimitType_Static, LimitType_StaticValue, @@ -28,9 +28,9 @@ enum T_LimitType { Invalid_LimitType = -1 } static ArrayMap(g_amLimitTypes); // S_LimitType LimitType_Init() { - if (!ArrayMapCreated(g_amLimitTypes)) { - InitArrayMap(g_amLimitTypes, S_LimitType); - } + CallOnce(); + + ArrayMapCreate(g_amLimitTypes, S_LimitType); } Array:LimitType_GetAll() { @@ -48,7 +48,7 @@ T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, co } if (LimitType_Find(sName) != Invalid_LimitType) { - abort(0, "Limit type '' already exists.", sName); + abort(0, "Limit type '%s' already exists.", sName); return Invalid_LimitType; } @@ -68,15 +68,19 @@ T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, co } T_LimitType:LimitType_Find(const sName[]) { - return T_LimitType:ArrayMapGetIndex(g_amLimitTypes, sName); + if (ArrayMapKeyExists(g_amLimitTypes, sName)) { + return T_LimitType:ArrayMapGetIndex(g_amLimitTypes, sName); + } else { + return Invalid_LimitType; + } } static LimitType__Get(const T_LimitType:iLimitType, LimitType[S_LimitType]) { - ArrayMapGetiArray(g_amLimitTypes, _:iLimitType, LimitType); + ArrayMapGetArray(g_amLimitTypes, _:iLimitType, LimitType); } static LimitType__Set(const LimitType[S_LimitType]) { - ArrayMapSetArray(g_amLimitTypes, LimitType[LimitType_Name], LimitType); + ArrayMapSetArrayByKey(g_amLimitTypes, LimitType[LimitType_Name], LimitType); } Array:LimitType_GetParams(const T_LimitType:iLimitType) { @@ -90,7 +94,7 @@ Array:LimitType_GetParams(const T_LimitType:iLimitType) { return ArrayClone(LimitType[LimitType_Params]); } -LimitType_MergeParams(const T_LimitType:iLimitType, const Array:aParams) { +LimitType_MergeParamsList(const T_LimitType:iLimitType, const Array:aParams) { new LimitType[S_LimitType]; LimitType__Get(iLimitType, LimitType); @@ -156,6 +160,7 @@ static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, co switch (iEvent) { case Limit_OnRead: // (const JSON:jCfg, Trie:tParams) return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + case Limit_OnCheck: // (const Trie:tParams, const UserId) return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index b3494c8..d73caab 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -6,6 +6,7 @@ #include #include +#include "VipM/Utils" #include "VipM/ArrayMap" #include "VipM/ArrayTrieUtils" @@ -21,11 +22,13 @@ enum _:S_LimitUnit { static Array:g_aLimitUnits = Invalid_Array; LimitUnit_Init() { - LimitType_Init(); + CallOnce(); - if (g_aLimitUnits == Invalid_Array) { - g_aLimitUnits = ArrayCreate(S_LimitUnit, 1); - } + LimitType_Init(); + + g_aLimitUnits = ArrayCreate(S_LimitUnit, 1); + Forwards_Reg("ReadLimitUnit", ET_IGNORE, FP_CELL, FP_CELL); // TODO: call + Forwards_RegAndCall("InitLimits", ET_IGNORE); } LimitUnit_GetCount() { @@ -34,7 +37,7 @@ LimitUnit_GetCount() { static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie:tParams) { if (g_aLimitUnits == Invalid_Array) { - abort(0, "Attempt to` create limit unit before init."); + abort(0, "Attempt to create limit unit before init."); return Invalid_LimitUnit; } @@ -46,8 +49,17 @@ static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie return T_LimitUnit:ArrayPushArray(g_aLimitUnits, LimitUnit); } -static LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit]) { +static bool:LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit], const bool:bOrFail = true) { + if (_:iLimitUnit < 0 || _:iLimitUnit >= LimitUnit_GetCount()) { + if (bOrFail) { + abort(0, "Invalid limit unit index (%d).", iLimitUnit); + } + + return false; + } + ArrayGetArray(g_aLimitUnits, _:iLimitUnit, LimitUnit); + return true; } static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { @@ -56,14 +68,14 @@ static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { trim(sLimitTypeName); if (!sLimitTypeName[0]) { - Json_ErrorForFile(jLimitUnit, "ERROR", "Limit type name not specified."); + Json_ErrorForFile(jLimitUnit, "Limit type name not specified."); return Invalid_LimitType; } new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); if (iLimitType == Invalid_LimitType) { - Json_ErrorForFile(jLimitUnit, "ERROR", "Limit type '%s' not found.", sLimitTypeName); + Json_ErrorForFile(jLimitUnit, "Limit type '%s' not found.", sLimitTypeName); return Invalid_LimitType; } @@ -109,6 +121,18 @@ Array:LimitUnit_ReadList(const JSON:jLimitUnits, &Array:aLimitUnits = Invalid_Ar return aLimitUnits; } +Array:JsonObject_GetLimitUnits(const JSON:jObj, const sKey[], const bool:bDotNot = false, &Array:aLimitUnits = Invalid_Array) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return aLimitUnits; + } + + new JSON:jLimitUnits = json_object_get_value(jObj, sKey, bDotNot); + aLimitUnits = LimitUnit_ReadList(jLimitUnits, aLimitUnits); + json_free(jLimitUnits); + + return aLimitUnits; +} + bool:LimitUnit_Execute(const T_LimitUnit:iLimitUnit, const UserId = 0) { new LimitUnit[S_LimitUnit]; LimitUnit__Get(iLimitUnit, LimitUnit); diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index 4f7eefd..e6d51ea 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -4,4 +4,245 @@ #define __vipm_core_objects_modules_type_included #include +#include +#include +#include "VipM/Forwards" +#include "VipM/Utils" #include "VipM/ArrayMap" +#include "VipM/ArrayTrieUtils" +#include "VipM/Core/Objects/Param" + +enum _:S_ModuleType { + ModuleType_Name[VIPM_MODULES_TYPE_NAME_MAX_LEN], + Array:ModuleType_Params, // S_CfgParam[] + + bool:ModuleType_Used, + bool:ModuleType_Active, + + ModuleType_Events[E_ModuleEvent], +} + +enum T_ModuleType { Invalid_ModuleType = -1 } + +static ArrayMap(g_amModuleTypes); // S_ModuleType + +ModuleType_Init() { + CallOnce(); + + ArrayMapCreate(g_amModuleTypes, S_ModuleType); + + Forwards_Reg("ActivateModule", ET_STOP, FP_STRING); +} + +Array:ModuleType_GetAll() { + return ArrayClone(g_amModuleTypes[AM_Arr]); +} + +ModuleType_GetCount() { + return ArrayMapSize(g_amModuleTypes); +} + +T_ModuleType:ModuleType_Construct(const sName[]) { + if (!ArrayMapCreated(g_amModuleTypes)) { + abort(0, "Attempt to create module type before modules init."); + return Invalid_ModuleType; + } + + if (ModuleType_Find(sName) != Invalid_ModuleType) { + abort(0, "Module type '%s' already exists.", sName); + return Invalid_ModuleType; + } + + new ModuleType[S_ModuleType]; + + copy(ModuleType[ModuleType_Name], charsmax(ModuleType[ModuleType_Name]), sName); + ModuleType[ModuleType_Params] = Invalid_Array; + + ModuleType[ModuleType_Used] = false; + ModuleType[ModuleType_Active] = false; + + arrayset(ModuleType[ModuleType_Events], -1, sizeof(ModuleType[ModuleType_Events])); + + return T_ModuleType:ArrayMapPushArray(g_amModuleTypes, ModuleType, ModuleType[ModuleType_Name]); +} + +T_ModuleType:ModuleType_Find(const sName[]) { + if (ArrayMapKeyExists(g_amModuleTypes, sName)) { + return T_ModuleType:ArrayMapGetIndex(g_amModuleTypes, sName); + } else { + return Invalid_ModuleType; + } +} + +static ModuleType__Get(const T_ModuleType:iModuleType, ModuleType[S_ModuleType]) { + ArrayMapGetArray(g_amModuleTypes, _:iModuleType, ModuleType); +} + +static ModuleType__Set(const ModuleType[S_ModuleType]) { + ArrayMapSetArrayByKey(g_amModuleTypes, ModuleType[ModuleType_Name], ModuleType); +} + +static ModuleType__SetValue(const T_ModuleType:iModuleType, const iCell, const any:iValue) { + return ArrayMapSetCell(g_amModuleTypes, iModuleType, iValue, iCell); +} + +static any:ModuleType__GetValue(const T_ModuleType:iModuleType, const iCell) { + return ArrayMapGetCell(g_amModuleTypes, iModuleType, iCell); +} + +ModuleType_GetName(const T_ModuleType:iModuleType, sOut[], const iOutLen) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + return copy(sOut, iOutLen, ModuleType[ModuleType_Name]); +} + +ModuleType_iGetName(const T_ModuleType:iModuleType) { + new sName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + ModuleType_GetName(iModuleType, sName, charsmax(sName)); + return sName; +} + +bool:ModuleType_IsActive(const T_ModuleType:iModuleType) { + return ModuleType__GetValue(iModuleType, ModuleType_Active); +} + +Trie:ModuleType_ReadParams(const T_ModuleType:iModuleType, const JSON:jParams) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + new Trie:tParams = TrieCreate(); + + new sErrParam[VIPM_PARAM_NAME_MAX_LEN]; + if (!CfgParam_ReadList(jParams, tParams, ModuleType[ModuleType_Params], sErrParam, charsmax(sErrParam))) { + Json_ErrorForFile(jParams, "Param '%s' required for '%s' module.", sErrParam, ModuleType[ModuleType_Name]); + TrieDestroy(tParams); + return Invalid_Trie; + } + + if (ModuleType[ModuleType_Events][Module_OnRead] >= 0) { + new iRet = VIPM_STOP; + ExecuteForward(ModuleType[ModuleType_Events][Module_OnRead], iRet, jParams, tParams); + + if (iRet == VIPM_STOP) { + TrieDestroy(tParams); + return Invalid_Trie; + } + } + + return tParams; +} + +Array:ModuleType_GetParams(const T_ModuleType:iModuleType) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + if (ModuleType[ModuleType_Params] == Invalid_Array) { + return Invalid_Array; + } + + return ArrayClone(ModuleType[ModuleType_Params]); +} + +ModuleType_MergeParamsList(const T_ModuleType:iModuleType, const Array:aParams) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + ModuleType[ModuleType_Params] = CfgParam_Merge(ModuleType[ModuleType_Params], aParams); + + ModuleType__Set(ModuleType); +} + +ModuleType_SetEventListener( + const T_ModuleType:iModuleType, + const E_ModuleEvent:iEvent, + const PluginId, + const sFuncName[] +) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + if (iEvent == Module_OnCompareParams) { + log_amx("[WARNING] Event 'Module_OnCompareParams' is deprecated and will not be fired."); + return; + } + + if (ModuleType[ModuleType_Events][iEvent] >= 0) { + DestroyForward(ModuleType[ModuleType_Events][iEvent]); + } + + ModuleType[ModuleType_Events][iEvent] = ModuleType__MakeEventForward(iEvent, PluginId, sFuncName); + + if (ModuleType[ModuleType_Events][iEvent] < 0) { + abort(0, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); + return; + } + + ModuleType__Set(ModuleType); +} + +static ModuleType__MakeEventForward(const E_ModuleEvent:iEvent, const PluginId, const sFuncName[]) { + switch (iEvent) { + case Module_OnRead: // (const JSON:jCfg, Trie:Params) + return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + + case Module_OnActivated: // () + return CreateOneForward(PluginId, sFuncName); + + case Module_OnMergeParams: // (const Trie:tParams1, const Trie:tParams2) + return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + } + + abort(0, "[ERROR] Invalid event index (%d).", iEvent); + return -1; +} + +ModuleType_MarkAsUsed(const T_ModuleType:iModuleType, const bool:bState = true) { + ModuleType__SetValue(iModuleType, ModuleType_Used, bState); +} + +bool:ModuleType_Activate(const T_ModuleType:iModuleType) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + if (!ModuleType[ModuleType_Active]) { + Forwards_DefaultReturn(VIPM_CONTINUE); + if (Forwards_CallP("ActivateModule", ModuleType[ModuleType_Name]) != VIPM_CONTINUE) { + return false; + } + + ModuleType[ModuleType_Active] = true; + + if (ModuleType[ModuleType_Events][Module_OnActivated] >= 0) { + ExecuteForward(ModuleType[ModuleType_Events][Module_OnActivated]); + } + + ModuleType__Set(ModuleType); + } + + return ModuleType[ModuleType_Active]; +} + +ModuleType_ActivateUsed() { + ArrayMapForeachArray (g_amModuleTypes: iModuleType => ModuleType[S_ModuleType]) { + if (ModuleType[ModuleType_Used]) { + ModuleType_Activate(iModuleType); + } + } +} + +Trie:ModuleType_MergeParams(const T_ModuleType:iModuleType, const Trie:tParams1, const Trie:tParams2) { + new ModuleType[S_ModuleType]; + ModuleType__Get(iModuleType, ModuleType); + + new Trie:tRes = tParams1; + if (ModuleType[ModuleType_Events][Module_OnMergeParams] >= 0) { + ExecuteForward(ModuleType[ModuleType_Events][Module_OnMergeParams], _:tRes, tParams1, tParams2); + + if (tRes != tParams1 && tRes != tParams2) { + TrieSetCell(tRes, VIPM_MODULES_PARAMS_TEMP_MARK_KEY, true); + } + } + + return tRes; +} diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 433e34c..07ee2de 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -4,6 +4,157 @@ #define __vipm_core_objects_modules_unit_included #include +#include "VipM/Utils" +#include #include "VipM/ArrayMap" +#include "VipM/ArrayTrieUtils" #include "VipM/Core/Objects/Modules/Type" + +enum T_ModuleUnit { Invalid_ModuleUnit = -1 } + +enum _:S_ModuleUnit { + T_ModuleType:ModuleUnit_Type, + Trie:ModuleUnit_Params, +} + +static Array:g_aModuleUnits = Invalid_Array; + +ModuleUnit_Init() { + CallOnce(); + + ModuleType_Init(); + + g_aModuleUnits = ArrayCreate(S_ModuleUnit, 1); + Forwards_Reg("ReadModuleUnit", ET_IGNORE, FP_CELL, FP_CELL); // TODO: call + Forwards_RegAndCall("InitModules", ET_IGNORE); +} + +ModuleUnit_GetCount() { + return ArraySizeSafe(g_aModuleUnits); +} + +static T_ModuleUnit:ModuleUnit__Construct(const T_ModuleType:iModuleType, const Trie:tParams) { + if (g_aModuleUnits == Invalid_Array) { + abort(0, "Attempt to create module unit before init."); + return Invalid_ModuleUnit; + } + + new ModuleUnit[S_ModuleUnit]; + + ModuleUnit[ModuleUnit_Type] = iModuleType; + ModuleUnit[ModuleUnit_Params] = tParams; + + ModuleType_MarkAsUsed(iModuleType); + + return T_ModuleUnit:ArrayPushArray(g_aModuleUnits, ModuleUnit); +} + +// static ModuleUnit__Get(const T_ModuleUnit:iModuleUnit, ModuleUnit[S_ModuleUnit]) { +// ArrayGetArray(g_aModuleUnits, _:iModuleUnit, ModuleUnit); +// } + +static any:ModuleType__GetValue(const T_ModuleUnit:iModuleUnit, const iCell) { + return ArrayGetCell(g_aModuleUnits, _:iModuleUnit, iCell); +} + +static T_ModuleType:ModuleUnit__ReadType(const JSON:jModuleUnit) { + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + Json_Object_GetString(jModuleUnit, "Module", sModuleTypeName, charsmax(sModuleTypeName)); + trim(sModuleTypeName); + + if (!sModuleTypeName[0]) { + Json_ErrorForFile(jModuleUnit, "Module type name not specified."); + return Invalid_ModuleType; + } + + new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); + + if (iModuleType == Invalid_ModuleType) { + Json_ErrorForFile(jModuleUnit, "Module type '%s' not found.", sModuleTypeName); + return Invalid_ModuleType; + } + + return iModuleType; +} + +T_ModuleUnit:ModuleUnit_Read(const JSON:jModuleUnit) { + static Trie:tCache = Invalid_Trie; + TrieCreateIfNotCreated(tCache); + + new JSON:jRefed, T_ModuleUnit:iModuleUnit = Invalid_ModuleUnit; + Json_GetCachedRefValue_Begin(jModuleUnit, tCache, iModuleUnit, jRefed) + { + new T_ModuleType:iModuleType = ModuleUnit__ReadType(jRefed); + new Trie:tParams = Invalid_Trie; + + if (iModuleType != Invalid_ModuleType) { + tParams = ModuleType_ReadParams(iModuleType, jRefed); + } + + if (tParams != Invalid_Trie) { + iModuleUnit = ModuleUnit__Construct(iModuleType, tParams); + } + } + Json_GetCachedRefValue_End(jModuleUnit, tCache, iModuleUnit, jRefed) +} + +Array:ModuleUnit_ReadList(const JSON:jModuleUnits, &Array:aModuleUnits = Invalid_Array) { + ArrayCreateIfNotCreated(aModuleUnits, 1, 1); + + if (!json_is_array(jModuleUnits)) { + new T_ModuleUnit:iModuleUnit = ModuleUnit_Read(jModuleUnits); + if (iModuleUnit != Invalid_ModuleUnit) { + ArrayPushCell(aModuleUnits, iModuleUnit); + } + } else { + json_array_foreach_value (jModuleUnits: i => jModuleUnit) { + aModuleUnits = ModuleUnit_ReadList(jModuleUnit, aModuleUnits); + json_free(jModuleUnit); + } + } + + return aModuleUnits; +} + +Array:JsonObject_GetModuleUnits(const JSON:jObj, const sKey[], const bool:bDotNot = false, &Array:aModuleUnits = Invalid_Array) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return aModuleUnits; + } + + new JSON:jModuleUnits = json_object_get_value(jObj, sKey, bDotNot); + aModuleUnits = ModuleUnit_ReadList(jModuleUnits, aModuleUnits); + json_free(jModuleUnits); + + return aModuleUnits; +} + +Trie:ModuleUnit_GetParams(const T_ModuleUnit:iModuleUnit) { + return ModuleType__GetValue(iModuleUnit, ModuleUnit_Params); +} + +ModuleUnit_GetTypeName(const T_ModuleUnit:iModuleUnit, sOut[], const iOutLen) { + return ModuleType_GetName(ModuleType__GetValue(iModuleUnit, ModuleUnit_Type), sOut, iOutLen); +} + +// ModuleUnit_iGetTypeName(const T_ModuleUnit:iModuleUnit) { +// new sName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; +// ModuleUnit_GetModuleName(iModuleUnit, sName, charsmax(sName)); +// return sName; +// } + +Trie:ModuleUnit_FreeParamsIfTemp(&Trie:tParams) { + if (tParams == Invalid_Trie) { + return tParams; + } + + if (TrieKeyExists(tParams, VIPM_MODULES_PARAMS_TEMP_MARK_KEY)) { + TrieDestroy(tParams); + } + + return tParams; +} + +Trie:ModuleUnit_Merge(const T_ModuleUnit:iModuleUnit, const Trie:tParams1, const Trie:tParams2) { + return ModuleType_MergeParams(ModuleType__GetValue(iModuleUnit, ModuleUnit_Type), tParams1, tParams2); +} diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc new file mode 100644 index 0000000..3def507 --- /dev/null +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -0,0 +1,122 @@ +#if defined __vipm_core_objects_vip_unit_included + #endinput +#endif +#define __vipm_core_objects_vip_unit_included + +#include +#include "VipM/Utils" +#include "VipM/ArrayTrieUtils" +#include "VipM/JsonUtils" + +#include "VipM/Core/Objects/Modules/Unit" +#include "VipM/Core/Objects/Limits/Unit" + +enum _:S_VipUnit { + Array:VipUnit_Access, // T_LimitUnit[] + Array:VipUnit_Modules, // T_ModuleUnit[] +} + +enum T_VipUnit { Invalid_VipUnit = -1 } + +new Array:g_aVipUnits = Invalid_Array; + +VipUnit_Init() { + CallOnce(); + + // Пока что лимиты обязательно должны быть перед модулями + // После поломки интерфейса будет отдельный форвард для лимитов, а пока только для модулей + LimitUnit_Init(); + ModuleUnit_Init(); + + g_aVipUnits = ArrayCreate(S_VipUnit, 1); +} + +VipUnit_GetCount() { + return ArraySizeSafe(g_aVipUnits); +} + +static T_VipUnit:VipUnit__Construct( + const Array:aAccess, + const Array:aModules +) { + if (g_aVipUnits == Invalid_Array) { + abort(0, "Attempt to create vip unit before init."); + return Invalid_VipUnit; + } + + new VipUnit[S_VipUnit]; + + VipUnit[VipUnit_Access] = aAccess; + VipUnit[VipUnit_Modules] = aModules; + + return T_VipUnit:ArrayPushArray(g_aVipUnits, VipUnit); +} + +// static VipUnit__Get(const T_LimitUnit:iVipUnit, VipUnit[S_VipUnit], const bool:bOrFail = true) { +// if (_:iVipUnit < 0 || _:iVipUnit >= VipUnit_GetCount()) { +// if (bOrFail) { +// abort(0, "Invalid vip unit index (%d).", iVipUnit); +// } + +// return false; +// } + +// ArrayGetArray(g_aVipUnits, _:iVipUnit, VipUnit); +// return true; +// } + +static any:VipUnit__GetValue(const T_VipUnit:iVipUnit, const iCell) { + return ArrayGetCell(g_aVipUnits, _:iVipUnit, iCell); +} + +VipUnit_CheckUserAccess(const T_VipUnit:iVipUnit, const UserId) { + return LimitUnit_ExecuteList( + VipUnit__GetValue(iVipUnit, VipUnit_Access), + UserId, + Limit_Exec_OR + ); +} + +Array:VipUnit_GetModules(const T_VipUnit:iVipUnit) { + return VipUnit__GetValue(iVipUnit, VipUnit_Modules); +} + +T_VipUnit:VipUnit_Read(const JSON:jVipUnit) { + static Trie:tCache = Invalid_Trie; + TrieCreateIfNotCreated(tCache); + + new JSON:jRefed, T_VipUnit:iVipUnit = Invalid_VipUnit; + Json_GetCachedRefValue_Begin(jVipUnit, tCache, iVipUnit, jRefed) + { + new Array:aAccess = JsonObject_GetLimitUnits(jVipUnit, "Access"); + if (aAccess == Invalid_Array) { + Json_LogForFile(jVipUnit, "ERROR", "Field 'Access' is required in vip object."); + } else { + new Array:aModules = JsonObject_GetModuleUnits(jVipUnit, "Modules"); + if (aModules == Invalid_Array) { + Json_LogForFile(jVipUnit, "ERROR", "Field 'Modules' is required in vip object."); + } else { + iVipUnit = VipUnit__Construct(aAccess, aModules); + } + } + } + Json_GetCachedRefValue_End(jVipUnit, tCache, iVipUnit, jRefed) +} + +Array:VipUnit_ReadList(const JSON:jVipUnits, &Array:aVipUnits = Invalid_Array) { + ArrayCreateIfNotCreated(aVipUnits, 1, 1); + + if (!json_is_array(jVipUnits)) { + new T_VipUnit:iVipUnit = VipUnit_Read(jVipUnits); + if (iVipUnit != Invalid_VipUnit) { + ArrayPushCell(aVipUnits, iVipUnit); + } + } else { + json_array_foreach_value (jVipUnits: i => jVipUnit) { + aVipUnits = VipUnit_ReadList(jVipUnit, aVipUnits); + json_free(jVipUnit); + } + } + + return aVipUnits; +} diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 0f6590d..3a6e363 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -7,7 +7,8 @@ #include "VipM/ArrayTrieUtils" #include "VipM/ArrayMap" -#include "VipM/Core/Modules/Main" +#include "VipM/Core/Objects/Modules/Type" +#include "VipM/Core/Objects/Modules/Unit" #include "VipM/Core/Objects/Limits/Type" #include "VipM/Core/Objects/Limits/Unit" #include "VipM/Core/Objects/Param" @@ -38,13 +39,13 @@ SrvCmds_Init() { server_print("║ │"); server_print("║ ├─Stats:"); server_print("║ │ ├─Modules:"); - server_print("║ │ │ ├─Modules count: %d", ArrayMapSize(Modules)); - server_print("║ │ │ └─Module units count: %d", ArraySizeSafe(ModuleUnits)); + server_print("║ │ │ ├─Modules count: %d", ModuleType_GetCount()); + server_print("║ │ │ └─Module units count: %d", ModuleUnit_GetCount()); server_print("║ │ ├─Limits:"); server_print("║ │ │ ├─Types count: %d", LimitType_GetCount()); server_print("║ │ │ └─Limit units count: %d", LimitUnit_GetCount()); server_print("║ │ ├─Vips:"); - server_print("║ │ │ └─Vips count: %d", ArraySizeSafe(Vips)); + server_print("║ │ │ └─Vips count: %d", VipUnit_GetCount()); server_print("║ │ └─Compiled by AmxModX v%s:", AMXX_VERSION_STR); server_print("║ │"); server_print("║ └─GitHub repo: https://github.com/ArKaNeMaN/amxx-VipModular-pub"); @@ -55,26 +56,32 @@ SrvCmds_Init() { server_print("╔═════╤══════════════════════════════════╤════════╗"); server_print("║ # │ Module name │ Status ║"); server_print("╟─────┼──────────────────────────────────┼────────╢"); - ArrayMapForeachArray2 (Modules: i => Module[S_Module]) { - server_print("║ %03d │ %-32s │ %-6s ║", i + 1, Module[Module_Name], Module[Module_Enabled] ? "On" : "Off"); + new Array:aModuleTypes = ModuleType_GetAll(); + ArrayForeachArray2 (aModuleTypes: i => ModuleType[S_ModuleType]) { + server_print("║ %03d │ %-32s │ %-6s ║", i + 1, ModuleType[ModuleType_Name], ModuleType[ModuleType_Active] ? "On" : "Off"); } server_print("╟─────┴──────────────────────────────────┴────────╢"); - server_print("║ Total: %-5d ║", ArrayMapSize(Modules)); + server_print("║ Total: %-5d ║", ModuleType_GetCount()); server_print("╚═════════════════════════════════════════════════╝"); + + return PLUGIN_HANDLED; } @SrvCmd_ModuleParams() { - new Module[S_Module], ModuleName[32]; - read_argv(1, ModuleName, charsmax(ModuleName)); + new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + read_argv(1, sModuleTypeName, charsmax(sModuleTypeName)); - if (!MODULE_EXISTS(ModuleName)) { - server_print("Module `%s` not found.", ModuleName); - return; + new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); + if (iModuleType == Invalid_ModuleType) { + server_print("Module type '%s' not found.", sModuleTypeName); + return PLUGIN_HANDLED; } - - GET_MODULE(ModuleName, Module); - PrintConfigParams(Module[Module_Params]); + new Array:aParams = ModuleType_GetParams(iModuleType); + PrintConfigParams(aParams); + ArrayDestroy(aParams); + + return PLUGIN_HANDLED; } @SrvCmd_Limits() { @@ -96,6 +103,8 @@ SrvCmds_Init() { server_print("╟─────┴──────────────────────────────────┴────────┴────────┴────────────╢"); server_print("║ Total: %-5d ║", LimitType_GetCount()); server_print("╚═══════════════════════════════════════════════════════════════════════╝"); + + return PLUGIN_HANDLED; } @SrvCmd_LimitParams() { diff --git a/amxmodx/scripting/VipM/Core/Vips.inc b/amxmodx/scripting/VipM/Core/Vips.inc deleted file mode 100644 index 7afd1fb..0000000 --- a/amxmodx/scripting/VipM/Core/Vips.inc +++ /dev/null @@ -1,53 +0,0 @@ -#if defined _vipmodular_src_Vips_included - #endinput -#endif -#define _vipmodular_src_Vips_included - -/** - * Vip Modular: Vips - */ - -#include - -#include "VipM/Core/Objects/Limits/Unit" - -#define Vips_CheckAndAdd(%1) \ - CfgUnits_CheckAndAdd(%1, Vips) - -#define Vips_Reset(%1) \ - ModuleUnits_ResetUser(%1) - -Vips_UserUpdate(const UserId) { - Vips_Reset(UserId); - Vips_CheckAndAdd(UserId); - - Forwards_CallP("UserUpdated", UserId); -} - -#define CfgUnit_CheckAccess(%1,%2) \ - LimitUnit_ExecuteList(%2[CfgUnit_LimitUnits], %1, Limit_Exec_OR) - -#define CfgUnit_AddToUser(%1,%2) \ - ModuleUnits_AddListToUser(%1, %2[CfgUnit_ModuleUnits]) - -CfgUnits_CheckAndAdd(const UserId, const Array:aUnits) { - if (aUnits == Invalid_Array) { - return; - } - - new Unit[S_CfgUnit]; - for (new i = 0; i < ArraySize(aUnits); i++) { - ArrayGetArray(aUnits, i, Unit); - - CfgUnit_CheckAndAdd(UserId, Unit); - } -} - -bool:CfgUnit_CheckAndAdd(const UserId, const Unit[S_CfgUnit]) { - if (!CfgUnit_CheckAccess(UserId, Unit)) { - return false; - } - - CfgUnit_AddToUser(UserId, Unit); - return true; -} diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc new file mode 100644 index 0000000..c5f165b --- /dev/null +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -0,0 +1,128 @@ +#if defined __vipm__core__vips_manager__included + #endinput +#endif +#define __vipm__core__vips_manager__included + +#include +#include +#include "VipM/Forwards" +#include "VipM/ArrayTrieUtils" +#include "VipM/JsonUtils" +#include "VipM/Core/Objects/VipUnit" + +static Array:g_aVips = Invalid_Array; // T_VipUnit[] +static g_sRootDir[PLATFORM_MAX_PATH] = ""; +static Trie:g_tUserModules[MAX_PLAYERS + 1] = {Invalid_Trie, ...}; + +VipsManager_Init() { + CallOnce(); + + VipUnit_Init(); + + g_aVips = ArrayCreate(1, 1); + Forwards_Reg("UserUpdated", ET_IGNORE, FP_CELL); +} + +VipsManager_VipsCount() { + return ArraySize(g_aVips); +} + +VipsManager_SetRootDir(const sRootDir[]) { + copy(g_sRootDir, charsmax(g_sRootDir), sRootDir); +} + +bool:VipsManager_LoadFromFile(const sFilePath[]) { + if (!file_exists(sFilePath)) { + return false; + } + + new JSON:jVipUnits = Json_ParseFromFileEx(sFilePath, g_sRootDir); + g_aVips = VipUnit_ReadList(jVipUnits, g_aVips); + Json_FreeEx(jVipUnits); + + return true; +} + +bool:VipsManager_LoadFromFolder(sFolderPath[]) { + if (!dir_exists(sFolderPath)) { + return false; + } + + new sFile[PLATFORM_MAX_PATH], iDirHandler, FileType:iType; + iDirHandler = open_dir(sFolderPath, sFile, charsmax(sFile), iType); + if (!iDirHandler) { + return false; + } + + new Regex:iRegEx_FileName, ret; + iRegEx_FileName = regex_compile("(.+).json$", ret, "", 0, "i"); + + do { + if (iType != FileType_File || regex_match_c(sFile, iRegEx_FileName) <= 0) { + continue; + } + + VipsManager_LoadFromFile(fmt("%s/%s", sFolderPath, sFile)); + } while (next_file(iDirHandler, sFile, charsmax(sFile), iType)); + + regex_free(iRegEx_FileName); + close_dir(iDirHandler); + + return true; +} + +VipsManager_UserReload(const UserId) { + VipsManager_UserReset(UserId); + + g_tUserModules[UserId] = TrieCreate(); + for (new i = 0, ii = ArraySize(g_aVips); i < ii; ++i) { + new T_VipUnit:iVipUnit = ArrayGetCell(g_aVips, i); + if (!VipUnit_CheckUserAccess(iVipUnit, UserId)) { + continue; + } + + new Array:aModuleUnits = VipUnit_GetModules(iVipUnit); + for (new j = 0, jj = ArraySize(aModuleUnits); j < jj; ++j) { + new T_ModuleUnit:iModuleUnit = ArrayGetCell(aModuleUnits, j); + + new sModuleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; // TODO: Посмотреть можно ли юзать просто хендлер + ModuleUnit_GetTypeName(iModuleUnit, sModuleName, charsmax(sModuleName)); + + new Trie:tParams = ModuleUnit_GetParams(iModuleUnit); + if (TrieKeyExists(g_tUserModules[UserId], sModuleName)) { + new Trie:tOldParams; + TrieGetCell(g_tUserModules[UserId], sModuleName, tOldParams); + + TrieSetCell(g_tUserModules[UserId], sModuleName, ModuleUnit_Merge(iModuleUnit, tOldParams, tParams)); + } else { + TrieSetCell(g_tUserModules[UserId], sModuleName, tParams); + } + } + } + + Forwards_CallP("UserUpdated", UserId); +} + +VipsManager_UserReset(const UserId) { + if (g_tUserModules[UserId] == Invalid_Trie) { + return; + } + + new TrieIter:Iter = TrieIterCreate(g_tUserModules[UserId]); + while (!TrieIterEnded(Iter)) { + new Trie:tParams = Invalid_Trie; + if (TrieIterGetCell(Iter, tParams)) { + ModuleUnit_FreeParamsIfTemp(tParams); + } + TrieIterNext(Iter); + } + TrieIterDestroy(Iter); + + TrieDestroy(g_tUserModules[UserId]); +} + +Trie:VipsManager_GetUserParams(const UserId, const T_ModuleType:iModuleType) { + new Trie:tParams = Invalid_Trie; + TrieGetCell(g_tUserModules[UserId], ModuleType_iGetName(iModuleType), tParams); + return tParams; +} diff --git a/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc b/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc index 93a54e0..7afd39b 100644 --- a/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc +++ b/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc @@ -1,3 +1,7 @@ +#include +#include "VipM/ArrayMap" +// #include "VipM/ItemsController/Objects/Type" + SrvCmds_Init() { register_srvcmd("vipm_ic_types", "@SrvCmd_Types"); } @@ -6,12 +10,12 @@ SrvCmds_Init() { PrintTypesData(Types); } -PrintTypesData(const am[ArrayMap]) { +PrintTypesData(const ArrayMap(am)) { server_print("╔═════╤══════════════════════════════════╗"); server_print("║ # │ Type name ║"); server_print("╟─────┼──────────────────────────────────╢"); - ArrayMapForeachArray (am => Type[S_ItemType]) { - server_print("║ %03d │ %-32s ║", __i__, Type[ItemType_Name]); + ArrayMapForeachArray (am: i => Type[S_ItemType]) { + server_print("║ %03d │ %-32s ║", i, Type[ItemType_Name]); } server_print("╚═════╧══════════════════════════════════╝"); } \ No newline at end of file diff --git a/amxmodx/scripting/VipM/ItemsController/Utils.inc b/amxmodx/scripting/VipM/ItemsController/Utils.inc index c7f193a..eaea3be 100644 --- a/amxmodx/scripting/VipM/ItemsController/Utils.inc +++ b/amxmodx/scripting/VipM/ItemsController/Utils.inc @@ -11,22 +11,22 @@ #define TYPE_EXISTS(%1) \ - ArrayMapHasKey(Types, %1) + ArrayMapKeyExists(Types, %1) #define GET_TYPE(%1,%2) \ - ArrayMapGetArray(Types, %1, %2) + ArrayMapGetArrayByKey(Types, %1, %2) #define GET_TYPE_ID(%1) \ ArrayMapGetIndex(Types, %1) #define GET_TYPE_BY_ID(%1,%2) \ - ArrayMapGetiArray(Types, %1, %2) + ArrayMapGetArray(Types, %1, %2) #define GET_ITEM_TYPE(%1,%2) \ GET_TYPE_BY_ID(%1[Item_Type], %2) #define SET_TYPE(%1) \ - ArrayMapSetArray(Types, %1[ItemType_Name], %1) + ArrayMapSetArrayByKey(Types, %1[ItemType_Name], %1) #define ADD_TYPE(%1) \ ArrayMapPushArray(Types, %1, %1[ItemType_Name]) diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index e227b9c..d7dc62f 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -32,7 +32,7 @@ stock static const __JSON_WRAPPER_REF_FILE_PREFIX[] = "File:"; do { %1 } while(is_linux_server() == 0xDEADBEEF) #define Json__VFormatEx(%1,%2,%3) Json__CompositeMacros( \ - if (numargs() > %3) { \ + if (numargs() >= %3) { \ vformat(%1, charsmax(%1), %2, %3); \ } else { \ copy(%1, charsmax(%1), %2); \ @@ -91,9 +91,9 @@ static stock JSON:Json__FreeWrapper(&JSON:jWrapper, const bool:bFreeIfNotWrapper static stock Json__GetWrapperPathValue( const JSON:jValue, const sKey[], - sOut[] = NULL_STRING, + sOut[] = "", const iOutLen = 0, - const sDefault[] = NULL_STRING + const sDefault[] = "" ) { new JSON:jWrapper = Json__GetWrapper(jValue); @@ -112,7 +112,7 @@ static stock Json__GetWrapperPathValue( return sPath; } -static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { +static stock Json__GetFilePath(const JSON:jValue, sOut[] = "", const iOutLen = 0, const sDefault[] = "") { new sPath[PLATFORM_MAX_PATH]; Json__GetWrapperPathValue(jValue, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath), sDefault); @@ -120,7 +120,7 @@ static stock Json__GetFilePath(const JSON:jValue, sOut[] = NULL_STRING, const iO return sPath; } -static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOutLen = 0, const sDefault[] = NULL_STRING) { +static stock Json__GetWorkDir(const JSON:jValue, sOut[] = "", const iOutLen = 0, const sDefault[] = "") { new sPath[PLATFORM_MAX_PATH]; Json__GetWrapperPathValue(jValue, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath), sDefault); @@ -128,7 +128,7 @@ static stock Json__GetWorkDir(const JSON:jValue, sOut[] = NULL_STRING, const iOu return sPath; } -static stock Json__GetRootConfigsPath(sOut[] = NULL_STRING, const iOutLen = 0) { +static stock Json__GetRootConfigsPath(sOut[] = "", const iOutLen = 0) { static sPath[PLATFORM_MAX_PATH]; if (!sPath[0]) { @@ -172,7 +172,7 @@ static stock Json__GetFileDir(const sFile[]) { * * @return Хендлер прочитанного из файла значения. */ -stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = NULL_STRING, const bool:bWithComments = true) { +stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = "", const bool:bWithComments = true) { if (!file_exists(sPath)) { log_amx("[ERROR] File '%s' not found.", sPath); return Invalid_JSON; @@ -283,7 +283,7 @@ stock Json_FatalErrorForFile(const JSON:jValue, const sMessage[], any:...) { * * @return true, если значение является ссылкой, иначе false. */ -stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = 0) { +stock bool:Json_IsRef(const JSON:jValue, sFileName[] = "", const iLen = 0) { if (!json_is_string(jValue)) { return false; } @@ -318,7 +318,7 @@ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = NULL_STRING, const iLen = */ stock JSON:Json_GetRefValue( const JSON:jValue, - sOut[] = NULL_STRING, + sOut[] = "", const iOutLen = 0, &bool:bIsRef = false ) { @@ -446,7 +446,7 @@ stock Json_Object_GetString( const sKey[], sOut[], const iOutLen, - const sDefault[] = NULL_STRING, + const sDefault[] = "", const bool:bDotNot = false ) { if (!json_object_has_value(jObj, sKey, JSONString, bDotNot)) { @@ -456,7 +456,7 @@ stock Json_Object_GetString( } } -stock Json_Object_GetStr(const JSON:jObj, const sKey[], const sDefault[] = NULL_STRING, const bool:bDotNot = false) { +stock Json_Object_GetStr(const JSON:jObj, const sKey[], const sDefault[] = "", const bool:bDotNot = false) { new sRes[MAX_FMT_LENGTH]; Json_Object_GetString(jObj, sKey, sRes, charsmax(sRes), sDefault, bDotNot); @@ -468,7 +468,7 @@ stock Json_Object_GetColoredChatMessage( const sKey[], sOut[], const iOutLen, - const sDefault[] = NULL_STRING, + const sDefault[] = "", const bool:bDotNot = false ) { new iRes = Json_Object_GetString(jObj, sKey, sOut, iOutLen, sDefault, bDotNot); diff --git a/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc b/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc deleted file mode 100644 index 5ae5aad..0000000 --- a/amxmodx/scripting/VipM/ModulesLimiter/Configs.inc +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include "VipM/Utils" -#include "VipM/ArrayTrieUtils" - -Trie:Configs_LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { - TrieCreateIfNotCreated(tModules); - - new JSON:jFile = Json_ParseFromFileEx(sFileName); - if (jFile == Invalid_JSON) { - log_error(0, "Invalid JSON syntax. File `%s`.", GET_FILE_JSON_PATH(sFileName)); - return tModules; - } - - if (!json_is_array(jFile)) { - Json_LogForFile(jFile, "WARNING", "Root value must be an array."); - Json_FreeEx(jFile); - return tModules; - } - - json_array_foreach_value (jFile: i => jItem) { - if (!json_is_object(jItem)) { - Json_LogForFile(jItem, "WARNING", "Array item #%d isn`t object.", i); - json_free(jItem); - continue; - } - - new JSON:jLimits = json_object_get_value(jItem, "Limits"); - new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits); - json_free(jLimits); - if (!ArraySizeSafe(aLimits)) { - Json_LogForFile(jItem, "WARNING", "Field `Limits` must have 1 or more items."); - json_free(jItem); - continue; - } - - new Array:aModuleNames = json_object_get_strings_list(jItem, "Modules", VIPM_MODULE_MAX_NAME); - if (!ArraySizeSafe(aModuleNames)) { - Json_LogForFile(jItem, "WARNING", "Field `Modules` must have 1 or more items."); - continue; - } - - ArrayForeachString (aModuleNames: j => sModuleName[VIPM_MODULE_MAX_NAME]) { - if (TrieKeyExists(tModules, sModuleName)) { - Json_LogForFile(jItem, "WARNING", "Duplicate limits for module `%s`.", sModuleName); - continue; - } - - TrieSetCell(tModules, sModuleName, aLimits); - } - - json_free(jItem); - ArrayDestroy(aModuleNames); - } - - Json_FreeEx(jFile); - return tModules; -} diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index b9fc684..2fe7037 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -14,52 +14,34 @@ public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; public stock const PluginDescription[] = "Modular vip system"; -new Array:Vips; // S_CfgUnit -new Trie:gUserVip[MAX_PLAYERS + 1] = {Invalid_Trie, ...}; // ModuleName => Trie:Params - -#include "VipM/Core/Modules/Main" -#include "VipM/Core/Objects/Limits/Type" -#include "VipM/Core/Configs/Main" -#include "VipM/Core/Vips" - +#include "VipM/Core/Objects/Modules/Type" +#include "VipM/Core/VipsManager" #include "VipM/Core/SrvCmds" -#include "VipM/Core/Natives" public plugin_precache() { RegisterPluginByVars(); register_library(VIPM_LIBRARY); - CreateConstCvar("vipm_version", VIPM_VERSION); - RegisterForwards(); - SrvCmds_Init(); + CreateConstCvar("vipm_version", PluginVersion); + + Forwards_Init("VipM"); + Forwards_Reg("ReadUnit", ET_IGNORE, FP_CELL, FP_CELL); - LimitType_Init(); - LimitUnit_Init(); - Forwards_RegAndCall("InitLimits", ET_IGNORE); + VipsManager_Init(); + SrvCmds_Init(); - Modules_Init(); - Forwards_RegAndCall("InitModules", ET_IGNORE); + VipsManager_SetRootDir(VipM_iGetCfgPath("")); + VipsManager_LoadFromFile(VipM_iGetCfgPath("Vips.json")); + VipsManager_LoadFromFolder(VipM_iGetCfgPath("Vips")); - Vips = Cfg_LoadVipsConfigs(); + ModuleType_ActivateUsed(); - server_print("[%s v%s] Loaded %d config units.", PluginName, VIPM_VERSION, ArraySizeSafe(Vips)); Forwards_RegAndCall("Loaded", ET_IGNORE); - - Modules_EnableAllUsed(); - + server_print("[%s v%s] Loaded %d config units.", PluginName, PluginVersion, VipsManager_VipsCount()); Dbg_PrintServer("Vip Modular run in debug mode!"); } -RegisterForwards() { - Forwards_Init("VipM"); - Forwards_Reg("UserUpdated", ET_IGNORE, FP_CELL); - Forwards_Reg("ReadUnit", ET_IGNORE, FP_CELL, FP_CELL); - Forwards_Reg("ActivateModule", ET_STOP, FP_STRING); - Forwards_Reg("ReadModuleUnit", ET_IGNORE, FP_CELL, FP_CELL); - Forwards_Reg("ReadLimitUnit", ET_IGNORE, FP_CELL, FP_CELL); -} - public client_disconnected(UserId) { - Vips_Reset(UserId); + VipsManager_UserReset(UserId); } public client_putinserver(UserId) { @@ -71,9 +53,16 @@ public client_putinserver(UserId) { } @CallUserUpdate(UserId) { - if (!is_user_connected(UserId)) { - return; + if (is_user_connected(UserId)) { + VipsManager_UserReload(UserId); } +} - Vips_UserUpdate(UserId); +#include "VipM/Core/API/Main" +#include "VipM/Core/API/Limits" +#include "VipM/Core/API/Modules" +public plugin_natives() { + API_Main_Init(); + API_Limits_Init(); + API_Modules_Init(); } diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index 89b5f58..42094a6 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -7,7 +7,9 @@ * Vip Modular: Modules */ -#define VIPM_MODULE_MAX_NAME 32 +#define VIPM_MODULES_TYPE_NAME_MAX_LEN 64 + +stock const VIPM_MODULES_PARAMS_TEMP_MARK_KEY[] = "___temp_module_params___"; enum E_ModuleEvent{ @@ -41,8 +43,27 @@ enum E_ModuleEvent{ * NewParams - Добавляемый набор параметров модуля. * * Примечание: Результат обьединения должен быть возвращён обработчиком события. + * + * УСТАРЕЛО! Позже будет добавлен другой механизм подобный этому. */ Module_OnCompareParams, + + /* + * Описание: Вызывается при добавлении игроку второго модуля того же типа. + * Возв. тип: Trie + * Параметры: (const Trie:tParams1, const Trie:tParams2): + * tParams1 - Первый набор параметров. + * tParams2 - Второй набор параметров. + * + * Примечание: Если обработчик для этого события не зарегистрирован, + * всегда будет выбираться tParams1 (модуль, добавленный первым) без изменений. + * + * Примечание: Очищение пришедших в параметрах Trie вызовет ошибки в работе модулей. + * + * Примечание: Обработчик может вернуть один из полученных Trie или создать новый. + * При содании нового Trie ядро само позаботится о его очищении в будущем. + */ + Module_OnMergeParams, } forward VipM_OnReadModuleUnit(const JSON:jUnit, const Trie:tParams); @@ -81,7 +102,6 @@ native bool:VipM_Modules_RegisterEvent(const Module[], const E_ModuleEvent:Event * @noreturn */ native VipM_Modules_AddParams(const Module[], const any:...); -#define VipM_SetModuleParams VipM_Modules_AddParams /** * Активен ли указанный модуль. diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 67b4ba3..f150731 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -24,11 +24,15 @@ stock const VIPM_CFG_PATH[] = "plugins/VipModular"; * * @return Кол-во записанных в буфер ячеек. */ -stock VipM_GetCfgPath(const sPath[], sOut[], const iOutLen){ +stock VipM_GetCfgPath(const sPath[] = "", sOut[], const iOutLen){ static __amxx_configsdir[PLATFORM_MAX_PATH]; if (!__amxx_configsdir[0]) { get_localinfo("amxx_configsdir", __amxx_configsdir, charsmax(__amxx_configsdir)); } + + if (!sPath[0]) { + return formatex(sOut, iOutLen, "%s/%s", __amxx_configsdir, VIPM_CFG_PATH); + } return (sPath[0] == '/') ? formatex(sOut, iOutLen, "%s%s", __amxx_configsdir, sPath) @@ -45,7 +49,7 @@ stock VipM_GetCfgPath(const sPath[], sOut[], const iOutLen){ * * @return Полученный путь. */ -stock VipM_iGetCfgPath(const sPath[]) { +stock VipM_iGetCfgPath(const sPath[] = "") { new sRetPath[PLATFORM_MAX_PATH]; VipM_GetCfgPath(sPath, sRetPath, charsmax(sRetPath)); return sRetPath; From ef6f08fc13a9801fc47d8a4ca71428f22bdad051 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 02:54:52 +0300 Subject: [PATCH 016/108] Rewrite items controller TODO: compat api & update extensions --- amxmodx/scripting/ItemsController.sma | 43 +++ .../scripting/ItemsController/API/Compat.inc | 13 + .../scripting/ItemsController/API/Items.inc | 67 ++++ .../Objects/Items/Instance.inc | 170 +++++++++ .../ItemsController/Objects/Items/Type.inc | 137 +++++++ amxmodx/scripting/VipM-ItemsController.sma | 46 --- amxmodx/scripting/VipM-L-Default.sma | 6 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 4 +- .../VipM/Core/Objects/Limits/Type.inc | 12 +- .../VipM/Core/Objects/Limits/Unit.inc | 4 +- .../VipM/Core/Objects/Modules/Type.inc | 8 +- .../VipM/Core/Objects/Modules/Unit.inc | 2 +- .../scripting/VipM/Core/Objects/VipUnit.inc | 2 +- amxmodx/scripting/VipM/Core/SrvCmds.inc | 16 +- amxmodx/scripting/VipM/Forwards.inc | 9 +- .../VipM/ItemsController/Configs.inc | 97 ----- .../VipM/ItemsController/Natives.inc | 118 ------ .../VipM/ItemsController/SrvCmds.inc | 21 -- .../VipM/ItemsController/Structs.inc | 12 - .../scripting/VipM/ItemsController/Utils.inc | 53 --- amxmodx/scripting/VipM/Utils.inc | 63 ++-- amxmodx/scripting/include/ItemsController.inc | 353 ++++++++++++++++++ .../include/VipM/ItemsController.inc | 200 +--------- amxmodx/scripting/include/VipModular.inc | 2 +- 24 files changed, 854 insertions(+), 604 deletions(-) create mode 100644 amxmodx/scripting/ItemsController.sma create mode 100644 amxmodx/scripting/ItemsController/API/Compat.inc create mode 100644 amxmodx/scripting/ItemsController/API/Items.inc create mode 100644 amxmodx/scripting/ItemsController/Objects/Items/Instance.inc create mode 100644 amxmodx/scripting/ItemsController/Objects/Items/Type.inc delete mode 100644 amxmodx/scripting/VipM-ItemsController.sma delete mode 100644 amxmodx/scripting/VipM/ItemsController/Configs.inc delete mode 100644 amxmodx/scripting/VipM/ItemsController/Natives.inc delete mode 100644 amxmodx/scripting/VipM/ItemsController/SrvCmds.inc delete mode 100644 amxmodx/scripting/VipM/ItemsController/Structs.inc delete mode 100644 amxmodx/scripting/VipM/ItemsController/Utils.inc create mode 100644 amxmodx/scripting/include/ItemsController.inc diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma new file mode 100644 index 0000000..6d18684 --- /dev/null +++ b/amxmodx/scripting/ItemsController.sma @@ -0,0 +1,43 @@ +#include +#include +#include "VipM/Utils" +#include "VipM/Forwards" + +public stock const PluginName[] = "Items Controller"; +public stock const PluginVersion[] = IC_VERSION; +public stock const PluginAuthor[] = "ArKaNeMaN"; +public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-pub"; +public stock const PluginDescription[] = "Unified interface for items giving."; + +#include "ItemsController/Objects/Items/Instance" + +public plugin_precache() { + PluginInit(); +} + +PluginInit() { + CallOnce(); + + register_plugin(PluginName, PluginVersion, PluginAuthor); + register_library(IC_LIBRARY); + CreateConstCvar(IC_VERSION_CVAR, IC_VERSION); + Forwards_Init(); + + ItemInstance_Init(); + Forwards_RegAndCall("VipM_IC_OnInitTypes", ET_IGNORE); // deprecated +} + +#include "ItemsController/API/Items" +#include "ItemsController/API/Compat" + +public plugin_natives() { + register_native("IC_Init", "@_Init"); + register_native("VipM_IC_Init", "@_Init"); // deprecated + + API_Items_Register(); + API_Compat_Register(); +} + +@_Init() { + PluginInit(); +} diff --git a/amxmodx/scripting/ItemsController/API/Compat.inc b/amxmodx/scripting/ItemsController/API/Compat.inc new file mode 100644 index 0000000..679552a --- /dev/null +++ b/amxmodx/scripting/ItemsController/API/Compat.inc @@ -0,0 +1,13 @@ +#include +#include +#include + +#include "ItemsController/Objects/Items/Type" +#include "ItemsController/Objects/Items/Instance" + +// API для совместимости со старой версией +// Все зарегистрированные тут нативы устаревшие. + +API_Compat_Register() { + // TODO: impl +} diff --git a/amxmodx/scripting/ItemsController/API/Items.inc b/amxmodx/scripting/ItemsController/API/Items.inc new file mode 100644 index 0000000..3a7034d --- /dev/null +++ b/amxmodx/scripting/ItemsController/API/Items.inc @@ -0,0 +1,67 @@ +#include +#include +#include + +#include "ItemsController/Objects/Items/Type" +#include "ItemsController/Objects/Items/Instance" + +API_Items_Register() { + register_native("IC_ItemType_Register", "@_ItemType_Register"); + register_native("IC_ItemType_SetEventListener", "@_ItemType_SetEventListener"); + + register_native("IC_Item_ReadFromJson", "@_Item_ReadFromJson"); + register_native("IC_Item_ReadArrayFromJson", "@_Item_ReadArrayFromJson"); + register_native("IC_Item_Give", "@_Item_Give"); +} + +T_IC_ItemType:@_ItemType_Register() { + enum {Arg_Name = 1} + + new name[IC_ITEM_TYPE_NAME_MAX_LEN]; + get_string(Arg_Name, name, charsmax(name)); + + return ItemType_Construct(name); +} + +@_ItemType_SetEventListener(const pluginIndex) { + enum {Arg_Type = 1, Arg_Event, Arg_FuncName} + + new T_IC_ItemType:type = T_IC_ItemType:get_param(Arg_Type); + new E_ItemTypeEvent:event = E_ItemTypeEvent:get_param(Arg_Event); + new funcName[IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN]; + get_string(Arg_FuncName, funcName, charsmax(funcName)); + + new listener = ItemType_MakeEventListener(event, pluginIndex, funcName); + ItemType_SetEventListener(type, event, listener); +} + +T_IC_Item:@_Item_ReadFromJson() { + enum {Arg_InstanceJson = 1} + + new JSON:isntanceJson = JSON:get_param(Arg_InstanceJson); + + return ItemInstance_ReadFromJsonObject(isntanceJson); +} + + +Array:@_Item_ReadArrayFromJson() { + enum {Arg_InstancesJson = 1, Arg_Array} + + new JSON:isntancesJson = JSON:get_param(Arg_InstancesJson); + new Array:array = Array:get_param_byref(Arg_Array); + + array = ItemInstance_ReadArrayFromJsonValue(isntancesJson, array); + set_param_byref(Arg_Array, _:array); + + return array; +} + + +bool:@_Item_Give() { + enum {Arg_PlayerIndex = 1, Arg_Item} + + new playerIndex = get_param(Arg_PlayerIndex); + new T_IC_Item:item = T_IC_Item:get_param(Arg_Item); + + return ItemInstance_Give(playerIndex, item); +} diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc new file mode 100644 index 0000000..303cfe0 --- /dev/null +++ b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc @@ -0,0 +1,170 @@ +#if defined __ic__objects__items_instance__included + #endinput +#endif +// Два кванта +#define __ic__objects__items_instance__included + +#include +#include +#include "VipM/Forwards" +#include "VipM/Utils" +#include "VipM/JsonUtils" + +#include "ItemsController/Objects/Items/Type" + +enum _:S_ItemInstance { + T_IC_ItemType:Item_Type, + Trie:Item_Params, +} + +static Array:ItemInstances = Invalid_Array; +static Stack:FreeItemInstanceHandlers = Invalid_Stack; +static ActiveItemInstancesCount = 0; + +ItemInstance_Init() { + CallOnce(); + + ItemType_Init(); + + ItemInstances = ArrayCreate(S_ItemInstance, 1); + FreeItemInstanceHandlers = CreateStack(); + ActiveItemInstancesCount = 0; + + Forwards_RegAndCall("IC_Item_OnInited", ET_IGNORE); +} + +T_IC_Item:ItemInstance_Construct(const T_IC_ItemType:type, const Trie:params) { + if (ItemInstances == Invalid_Array) { + abort(AMX_ERR_GENERAL, "Attempt to create item instance before items controller init."); + return Invalid_IC_Item; + } + + new instanceObject[S_ItemInstance]; + instanceObject[Item_Type] = type; + instanceObject[Item_Params] = params; + + ActiveItemInstancesCount++; + if (IsStackEmpty(FreeItemInstanceHandlers)) { + return T_IC_Item:ArrayPushArray(ItemInstances, instanceObject); + } else { + new freeInstanceHandler; + PopStackCell(FreeItemInstanceHandlers, freeInstanceHandler); + + ArraySetArray(ItemInstances, freeInstanceHandler, instanceObject); + return T_IC_Item:freeInstanceHandler; + } +} + +bool:ItemInstance_Get(const T_IC_Item:instance, instanceObject[S_ItemInstance], const bool:orFail = true) { + if (_:instance < 0 || _:instance >= ArraySize(ItemInstances)) { + if (orFail) { + abort(AMX_ERR_NOTFOUND, "Invalid item instance handler (%d, out of bounds).", instance); + } + return false; + } + + ArrayGetArray(ItemInstances, _:instance, instanceObject); + + if (instanceObject[Item_Type] == Invalid_IC_ItemType) { + if (orFail) { + abort(AMX_ERR_NOTFOUND, "Invalid item instance handler (%d, deleted).", instance); + } + return false; + } + + return true; +} + +bool:ItemInstance_Give(const playerIndex, const T_IC_Item:instance) { + new instanceObject[S_ItemInstance]; + ItemInstance_Get(instance, instanceObject); + + return ItemType_Give(playerIndex, instanceObject[Item_Type], instanceObject[Item_Params]); +} + +#pragma unused ItemInstance_Free +T_IC_Item:ItemInstance_Free(&T_IC_Item:instance, const bool:orFail = false) { + new instanceObject[S_ItemInstance]; + if (!ItemInstance_Get(instance, instanceObject, .orFail = orFail)) { + return instance = Invalid_IC_Item; + } + + instanceObject[Item_Type] = Invalid_IC_ItemType; + TrieDestroy(instanceObject[Item_Params]); // TODO: Надо что-то придумать на случай вложенных динамических штук + + ArraySetArray(ItemInstances, _:instance, instanceObject); + PushStackCell(FreeItemInstanceHandlers, instance); + + ActiveItemInstancesCount--; + return instance = Invalid_IC_Item; +} + +T_IC_Item:ItemInstance_ReadFromJsonObject(const JSON:instanceJson) { + if (!json_is_object(instanceJson)) { + Json_ErrorForFile(instanceJson, "Invalid item object (json value is not an object)."); + return Invalid_IC_Item; + } + + new typeName[IC_ITEM_TYPE_NAME_MAX_LEN]; + if (json_object_has_value(instanceJson, "Item", JSONString)) { + json_object_get_string(instanceJson, "Item", typeName, charsmax(typeName)); + } else if (json_object_has_value(instanceJson, "Type", JSONString)) { + Json_LogForFile(instanceJson, "WARNING", "Item object with field `Type` is deprecated, use `Item` field instead."); + json_object_get_string(instanceJson, "Type", typeName, charsmax(typeName)); + } else { + Json_ErrorForFile(instanceJson, "Invalid item object (must contains `Item` field)."); + return Invalid_IC_Item; + } + + trim(typeName); + if (!typeName[0]) { + Json_ErrorForFile(instanceJson, "Item type is empty."); + return Invalid_IC_Item; + } + + new T_IC_ItemType:type = ItemType_Find(typeName); + if (type == Invalid_IC_ItemType) { + Json_ErrorForFile(instanceJson, "Item type '%s' not found.", typeName); + return Invalid_IC_Item; + } + + new Trie:params = TrieCreate(); + if (!ItemType_ReadParamsFromJsonObject(type, instanceJson, params)) { + TrieDestroy(params); + return Invalid_IC_Item; + } + + return ItemInstance_Construct(type, params); +} + +Array:ItemInstance_ReadArrayFromJsonValue(const JSON:instancesJson, &Array:array = Invalid_Array) { + if (json_is_array(instancesJson)) { + if (array == Invalid_Array) { + array = ArrayCreate(1, json_array_get_count(instancesJson)); + } + + for (new i = 0, ii = json_array_get_count(instancesJson); i < ii; i++) { + new JSON:instanceJson = json_array_get_value(instancesJson, i); + + new T_IC_Item:instance = ItemInstance_ReadFromJsonObject(instanceJson); + if (instance != Invalid_IC_Item) { + ArrayPushCell(array, instance); + } + + json_free(instanceJson); + } + } else if (json_is_object(instancesJson)) { + if (array == Invalid_Array) { + array = ArrayCreate(1, 1); + } + + new T_IC_Item:instance = ItemInstance_ReadFromJsonObject(instancesJson); + if (instance != Invalid_IC_Item) { + ArrayPushCell(array, instance); + } + } else { + Json_ErrorForFile(instancesJson, "Json value must be an array or an object."); + } + + return array; +} diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc new file mode 100644 index 0000000..8ac898a --- /dev/null +++ b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc @@ -0,0 +1,137 @@ +#if defined __ic__objects__items_type__included + #endinput +#endif +#define __ic__objects__items_type__included + +#include +#include +#include "VipM/Forwards" +#include "VipM/Utils" + +enum _:S_ItemType { + ItemType_Name[IC_ITEM_TYPE_NAME_MAX_LEN], + ItemType_Events[E_ItemTypeEvent], + // Array:ItemType_Params // TODO: use params controller +} + +static Array:ItemTypes = Invalid_Array; +static Trie:ItemTypesMap = Invalid_Trie; + +ItemType_Init() { + CallOnce(); + + ItemTypes = ArrayCreate(S_ItemType, 1); + ItemTypesMap = TrieCreate(); + + Forwards_RegAndCall("IC_ItemType_OnInited", ET_IGNORE); +} + +T_IC_ItemType:ItemType_Construct(const name[]) { + if (ItemTypes == Invalid_Array) { + abort(AMX_ERR_GENERAL, "Attempt to create item type before items controller init."); + return Invalid_IC_ItemType; + } + + if (ItemType_Find(name) != Invalid_IC_ItemType) { + abort(AMX_ERR_PARAMS, "Item type '%s' already exists.", name); + return Invalid_IC_ItemType; + } + + new typeObject[S_ItemType]; + copy(typeObject[ItemType_Name], charsmax(typeObject[ItemType_Name]), name); + arrayset(typeObject[ItemType_Events], INVALID_HANDLE, sizeof(typeObject[ItemType_Events])); + + new T_IC_ItemType:type = T_IC_ItemType:ArrayPushArray(ItemTypes, typeObject); + TrieSetCell(ItemTypesMap, typeObject[ItemType_Name], type); + + return type; +} + +T_IC_ItemType:ItemType_UpdateObject(const typeObject[S_ItemType]) { + new T_IC_ItemType:type = ItemType_Find(typeObject[ItemType_Name], .orFail = true); + ArraySetArray(ItemTypes, _:type, typeObject); + return type; +} + +T_IC_ItemType:ItemType_Find(const name[], const bool:orFail = false) { + new T_IC_ItemType:type = Invalid_IC_ItemType; + TrieGetCell(ItemTypesMap, name, type); + + if (orFail && type == Invalid_IC_ItemType) { + abort(AMX_ERR_NOTFOUND, "Invalid item type '%s'.", name); + } + + return type; +} + +bool:ItemType_Get(const T_IC_ItemType:type, typeObject[S_ItemType], const bool:orFail = true) { + if (_:type < 0 || _:type >= ArraySize(ItemTypes)) { + if (orFail) { + abort(AMX_ERR_NOTFOUND, "Invalid item type handler (%d, out of bounds).", type); + } + return false; + } + + ArrayGetArray(ItemTypes, _:type, typeObject); + return true; +} + +ItemType_SetEventListener(const T_IC_ItemType:type, const E_ItemTypeEvent:event, const listener) { + new typeObject[S_ItemType]; + ItemType_Get(type, typeObject); + + if (typeObject[ItemType_Events][event] >= 0) { + abort(AMX_ERR_GENERAL, "Item type '%s' already has listener for event #%d.", typeObject[ItemType_Name], event); + return; + } + + typeObject[ItemType_Events][event] = listener; + ItemType_UpdateObject(typeObject); +} + +ItemType_MakeEventListener(const E_ItemTypeEvent:event, const pluginIndex, const functionName[]) { + new listener = INVALID_HANDLE; + switch (event) { + case ItemType_OnRead: // IC_RET_READ_*:(const JSON:itemJson, Trie:params) + listener = CreateOneForward(pluginIndex, functionName, FP_CELL, FP_CELL); + + case ItemType_OnGive: // IC_RET_GIVE_*:(const playerIndex, const Trie:params) + listener = CreateOneForward(pluginIndex, functionName, FP_CELL, FP_CELL); + } + + if (listener == INVALID_HANDLE) { + abort(AMX_ERR_PARAMS, "Can't create forward for func '%s' in plugin #%d.", functionName, pluginIndex); + } + + return listener; +} + +bool:ItemType_Give(const playerIndex, const T_IC_ItemType:type, const Trie:params) { + new typeObject[S_ItemType]; + ItemType_Get(type, typeObject); + + if (typeObject[ItemType_Events][ItemType_OnGive] == INVALID_HANDLE) { + return true; + } + + new ret = IC_RET_GIVE_FAIL; + ExecuteForward(typeObject[ItemType_Events][ItemType_OnGive], ret, playerIndex, params); + + return ret == IC_RET_GIVE_SUCCESS; +} + +bool:ItemType_ReadParamsFromJsonObject(const T_IC_ItemType:type, const JSON:paramsJson, const Trie:params) { + new typeObject[S_ItemType]; + ItemType_Get(type, typeObject); + + // TODO: Использовать ParamsController + + if (typeObject[ItemType_Events][ItemType_OnRead] != INVALID_HANDLE) { + new ret = IC_RET_READ_SUCCESS; + ExecuteForward(typeObject[ItemType_Events][ItemType_OnRead], ret, paramsJson, params); + + return ret == IC_RET_READ_SUCCESS; + } + + return true; +} \ No newline at end of file diff --git a/amxmodx/scripting/VipM-ItemsController.sma b/amxmodx/scripting/VipM-ItemsController.sma deleted file mode 100644 index 80cc411..0000000 --- a/amxmodx/scripting/VipM-ItemsController.sma +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "VipM/ArrayTrieUtils" -#include "VipM/ArrayMap" -#include "VipM/Utils" -#include "VipM/Forwards" - -#pragma semicolon 1 -#pragma compress 1 - -public stock const PluginName[] = "[VipM] Items Controller"; -public stock const PluginVersion[] = _VIPM_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = _VIPM_PLUGIN_URL; -public stock const PluginDescription[] = "Vip Modular`s items controller"; - -new ArrayMap(Types); // S_ItemType -new Array:Items; - -#include "VipM/ItemsController/Structs" -#include "VipM/ItemsController/Utils" - -public plugin_precache() { - PluginInit(); -} - -PluginInit() { - CallOnce(); - - RegisterPluginByVars(); - CreateConstCvar("vipm_ic_version", PluginVersion); - SrvCmds_Init(); - - Forwards_Init("VipM_IC"); - Forwards_Reg("GiveItem", ET_STOP, FP_CELL, FP_CELL); - Forwards_Reg("ReadItem", ET_STOP, FP_CELL, FP_CELL); - - ArrayMapCreate(Types, S_ItemType, 8); - Forwards_RegAndCall("InitTypes", ET_IGNORE); - - Items = ArrayCreate(S_Item, 16); - Forwards_RegAndCall("Loaded", ET_IGNORE); -} - -#include "VipM/ItemsController/Natives" -#include "VipM/ItemsController/Configs" -#include "VipM/ItemsController/SrvCmds" diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index 3b1a2bf..0c895e1 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -227,7 +227,7 @@ public client_authorized(UserId, const AuthId[]) { @OnTimeCheck(const Trie:tParams) { new iBefore = VipM_Params_GetInt(tParams, "Before", 0); new iAfter = VipM_Params_GetInt(tParams, "After", 0); - new iCurrent = GetTime(); + new iCurrent = GetDayTimeInSeconds(); Dbg_Log("@OnTimeCheck(%d):", tParams); Dbg_Log(" iBefore = %d", iBefore); @@ -411,7 +411,7 @@ bool:@OnFlagsCheck(const Trie:Params, const UserId) { @OnRoundCheck(const Trie:Params, const UserId){ return ( - GetRound() >= VipM_Params_GetInt(Params, "Min", -1) - && GetRound() <= VipM_Params_GetInt(Params, "Max", cellmax) + GetCurrentRoundNum() >= VipM_Params_GetInt(Params, "Min", -1) + && GetCurrentRoundNum() <= VipM_Params_GetInt(Params, "Max", cellmax) ); } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 4e4ffe9..653360b 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -123,7 +123,7 @@ public client_disconnected(UserId) { } @OnPlayerSpawn(const UserId) { - if (!IsUserValidA(UserId)) { + if (!IsPlayerAlive(UserId)) { Dbg_Log("@OnPlayerSpawn(%n): Invalid (or dead) player", UserId); return; } @@ -201,7 +201,7 @@ AbortAutoCloseMenu(const UserId) { } _Cmd_Menu(const UserId, const bool:bSilent = false) { - if (!IsUserValid(UserId)) { + if (!IsPlayerValid(UserId)) { Dbg_Log("_Cmd_Menu(%d, %s): Invalid player", UserId, bSilent ? "true" : "false"); return; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 57175a6..f3be46a 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -43,12 +43,12 @@ LimitType_GetCount() { T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, const bool:bStatic = false) { if (!ArrayMapCreated(g_amLimitTypes)) { - abort(0, "Attempt to create limit type before limits controller init."); + abort(AMX_ERR_GENERAL, "Attempt to create limit type before limits controller init."); return Invalid_LimitType; } if (LimitType_Find(sName) != Invalid_LimitType) { - abort(0, "Limit type '%s' already exists.", sName); + abort(AMX_ERR_PARAMS, "Limit type '%s' already exists.", sName); return Invalid_LimitType; } @@ -150,7 +150,7 @@ LimitType_SetEventListener( LimitType[LimitType_Events][iEvent] = LimitType__MakeEventForward(iEvent, PluginId, sFuncName); if (LimitType[LimitType_Events][iEvent] < 0) { - abort(0, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); + abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); } LimitType__Set(LimitType); @@ -165,7 +165,7 @@ static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, co return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); } - abort(0, "[ERROR] Invalid event index (%d).", iEvent); + abort(AMX_ERR_GENERAL, "[ERROR] Invalid event index (%d).", iEvent); return -1; } @@ -174,7 +174,7 @@ LimitType_SetStaticValue(const T_LimitType:iLimitType, const bool:bValue, const LimitType__Get(iLimitType, LimitType); if (!LimitType[LimitType_Static]) { - abort(0, "Trying to set static value for a non-static limit."); + abort(AMX_ERR_PARAMS, "Trying to set static value for a non-static limit."); return; } @@ -200,7 +200,7 @@ bool:LimitType_Execute(const T_LimitType:iLimitType, const Trie:tParams, const U } } else { if (LimitType[LimitType_Events][Limit_OnCheck] < 0) { - abort(0, "'Limit_OnCheck' event listener for non-static limit type '%s' must be implemented.", LimitType[LimitType_Name]); + abort(AMX_ERR_GENERAL, "'Limit_OnCheck' event listener for non-static limit type '%s' must be implemented.", LimitType[LimitType_Name]); bRes = false; } else { ExecuteForward(LimitType[LimitType_Events][Limit_OnCheck], bRes, tParams, UserId); diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index d73caab..93726d2 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -37,7 +37,7 @@ LimitUnit_GetCount() { static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie:tParams) { if (g_aLimitUnits == Invalid_Array) { - abort(0, "Attempt to create limit unit before init."); + abort(AMX_ERR_GENERAL, "Attempt to create limit unit before init."); return Invalid_LimitUnit; } @@ -52,7 +52,7 @@ static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie static bool:LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit], const bool:bOrFail = true) { if (_:iLimitUnit < 0 || _:iLimitUnit >= LimitUnit_GetCount()) { if (bOrFail) { - abort(0, "Invalid limit unit index (%d).", iLimitUnit); + abort(AMX_ERR_NOTFOUND, "Invalid limit unit index (%d).", iLimitUnit); } return false; diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index e6d51ea..f946419 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -44,12 +44,12 @@ ModuleType_GetCount() { T_ModuleType:ModuleType_Construct(const sName[]) { if (!ArrayMapCreated(g_amModuleTypes)) { - abort(0, "Attempt to create module type before modules init."); + abort(AMX_ERR_GENERAL, "Attempt to create module type before modules init."); return Invalid_ModuleType; } if (ModuleType_Find(sName) != Invalid_ModuleType) { - abort(0, "Module type '%s' already exists.", sName); + abort(AMX_ERR_PARAMS, "Module type '%s' already exists.", sName); return Invalid_ModuleType; } @@ -174,7 +174,7 @@ ModuleType_SetEventListener( ModuleType[ModuleType_Events][iEvent] = ModuleType__MakeEventForward(iEvent, PluginId, sFuncName); if (ModuleType[ModuleType_Events][iEvent] < 0) { - abort(0, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); + abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); return; } @@ -193,7 +193,7 @@ static ModuleType__MakeEventForward(const E_ModuleEvent:iEvent, const PluginId, return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); } - abort(0, "[ERROR] Invalid event index (%d).", iEvent); + abort(AMX_ERR_GENERAL, "[ERROR] Invalid event index (%d).", iEvent); return -1; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 07ee2de..cb811e5 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -36,7 +36,7 @@ ModuleUnit_GetCount() { static T_ModuleUnit:ModuleUnit__Construct(const T_ModuleType:iModuleType, const Trie:tParams) { if (g_aModuleUnits == Invalid_Array) { - abort(0, "Attempt to create module unit before init."); + abort(AMX_ERR_GENERAL, "Attempt to create module unit before init."); return Invalid_ModuleUnit; } diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index 3def507..facd64e 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -40,7 +40,7 @@ static T_VipUnit:VipUnit__Construct( const Array:aModules ) { if (g_aVipUnits == Invalid_Array) { - abort(0, "Attempt to create vip unit before init."); + abort(AMX_ERR_GENERAL, "Attempt to create vip unit before init."); return Invalid_VipUnit; } diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 3a6e363..541b71d 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -13,6 +13,11 @@ #include "VipM/Core/Objects/Limits/Unit" #include "VipM/Core/Objects/Param" +// TODO: Дописать в параметрах компиляции в экшонах +#if !defined VIPM_INFO_COMPILED_BY_GH_ACTIONS + #define VIPM_INFO_COMPILED_BY_GH_ACTIONS 0 +#endif + SrvCmds_Init() { register_srvcmd("vipm_info", "@SrvCmd_Info"); @@ -24,17 +29,20 @@ SrvCmds_Init() { } @SrvCmd_Info() { + new sAmxxVersion[32]; + get_amxx_verstring(sAmxxVersion, charmsax(sAmxxVersion)); + server_print("╓─────────"); server_print("║ %s v%s by %s:", PluginName, VIPM_VERSION, PluginAuthor); server_print("║ │"); server_print("║ ├─Contacts:"); server_print("║ │ ├─GitHub: https://github.com/akraneman"); - server_print("║ │ ├─DevCS: https://dev-cs.ru/members/949/"); + server_print("║ │ ├─Dev-CS: https://dev-cs.ru/members/949/"); server_print("║ │ ├─VK: https://vk.com/akraneman"); server_print("║ │ └─TG: https://t.me/arkaneman"); server_print("║ ├─Support:"); server_print("║ │ ├─GitHub Issues: https://github.com/ArKaNeMaN/amxx-VipModular-pub/issues"); - server_print("║ │ ├─DevCS Resource: https://dev-cs.ru/resources/1466/"); + server_print("║ │ ├─Dev-CS Resource: https://dev-cs.ru/resources/1466/"); server_print("║ │ └─TG Forum: https://t.me/arkanaplugins/5"); server_print("║ │"); server_print("║ ├─Stats:"); @@ -46,7 +54,9 @@ SrvCmds_Init() { server_print("║ │ │ └─Limit units count: %d", LimitUnit_GetCount()); server_print("║ │ ├─Vips:"); server_print("║ │ │ └─Vips count: %d", VipUnit_GetCount()); - server_print("║ │ └─Compiled by AmxModX v%s:", AMXX_VERSION_STR); + server_print("║ │ ├─Compiled by AmxModX v%s", AMXX_VERSION_STR); + server_print("║ │ ├─Runned by AmxModX v%s", sAmxxVersion); + server_print("║ │ └─Builded by GitHub Actions?: %s", VIPM_INFO_COMPILED_BY_GH_ACTIONS ? "Yes" : "No"); server_print("║ │"); server_print("║ └─GitHub repo: https://github.com/ArKaNeMaN/amxx-VipModular-pub"); server_print("╙─────────"); diff --git a/amxmodx/scripting/VipM/Forwards.inc b/amxmodx/scripting/VipM/Forwards.inc index 90b4d3c..cf1019e 100644 --- a/amxmodx/scripting/VipM/Forwards.inc +++ b/amxmodx/scripting/VipM/Forwards.inc @@ -20,18 +20,19 @@ Functions & Macroses: #include amxmodx stock const FORWARDS_NAME_TEMPLATE[] = "%s_On%s"; +stock const FORWARDS_NAME_WITHOUT_PREFIX_TEMPLATE[] = "%s%s"; stock Trie:Forwards_gMap = Invalid_Trie; -stock Forwards_gPrefix[32]; +stock Forwards_gPrefix[32] = ""; -stock Forwards_Init(const sPrefix[]) { +stock Forwards_Init(const sPrefix[] = "") { Forwards_gMap = TrieCreate(); copy(Forwards_gPrefix, charsmax(Forwards_gPrefix), sPrefix); } // []Forwards_GetFullName(const sName[]); #define Forwards_GetFullName(%1) \ - fmt(FORWARDS_NAME_TEMPLATE, Forwards_gPrefix, %1) + fmt(Forwards_gPrefix[0] == EOS ? FORWARDS_NAME_WITHOUT_PREFIX_TEMPLATE : FORWARDS_NAME_TEMPLATE, Forwards_gPrefix, %1) // Forwards_Reg(const sName[], const iStopType, const ...?param_types); #define Forwards_Reg(%1,%2) \ @@ -81,4 +82,4 @@ stock __Forwards_RegAndCall_handler; ), \ __Forwards_Call_ret \ ) ? __Forwards_RegAndCall_handler : __Forwards_RegAndCall_handler \ - ) ? __Forwards_Call_ret : __Forwards_Call_ret) + ) ? __Forwards_Call_ret : __Forwards_Call_ret) \ No newline at end of file diff --git a/amxmodx/scripting/VipM/ItemsController/Configs.inc b/amxmodx/scripting/VipM/ItemsController/Configs.inc deleted file mode 100644 index 1f920dd..0000000 --- a/amxmodx/scripting/VipM/ItemsController/Configs.inc +++ /dev/null @@ -1,97 +0,0 @@ -#include amxmodx -#include json -#include "VipM/JsonUtils" - -// TODO: Переписать на хендлеры - -static Trie:g_ItemsCache = Invalid_Trie; - -Cfg_JsonGetItem(&JSON:jItem) { - TrieCreateIfNotCreated(g_ItemsCache); - new iItem = -1; - - new sJsonRef[PLATFORM_MAX_PATH]; - if (Json_IsRef(jItem, sJsonRef, charsmax(sJsonRef))) { - if (TrieGetCell(g_ItemsCache, sJsonRef, iItem)) { - Json_FreeEx(jItem); - return iItem; - } - - // jItem = Json_GetRefValue(jItem, .bFreeSrcIfRef=true); - } - - if (jItem == Invalid_JSON) { - return -1; - } - - new sItemTypeName[32]; - if ( - !json_is_object(jItem) - || !Json_Object_GetItemTypeAndRemove(jItem, sItemTypeName, charsmax(sItemTypeName)) - ) { - Json_LogForFile(jItem, "WARNING", "Invalid item format."); - Json_FreeEx(jItem); - return -1; - } - - if (!TYPE_EXISTS(sItemTypeName)) { - Json_LogForFile(jItem, "WARNING", "Item type `%s` not found.", sItemTypeName); - Json_FreeEx(jItem); - return -1; - } - - new Item[S_Item]; - Item[Item_Type] = GET_TYPE_ID(sItemTypeName); - Item[Item_Params] = TrieCreate(); - - if (json_object_has_value(jItem, "Name", JSONString)) { - new sItemName[32]; - json_object_get_string(jItem, "Name", sItemName, charsmax(sItemName)); - TrieSetString(Item[Item_Params], "Name", sItemName); - } - - Forwards_DefaultReturn(VIPM_CONTINUE); - if (Forwards_CallP("ReadItem", jItem, Item[Item_Params]) == VIPM_STOP) { - TrieDestroySafe(Item[Item_Params]); - Json_FreeEx(jItem); - return -1; - } - - new ItemType[S_ItemType]; - GET_TYPE_BY_ID(Item[Item_Type], ItemType); - - new iRet = VIPM_CONTINUE; - EMIT_TYPE_EVENT(ItemType, ItemType_OnRead, iRet, jItem, Item[Item_Params]) - Json_FreeEx(jItem); - - if (iRet == VIPM_STOP) { - TrieDestroySafe(Item[Item_Params]); - return -1; - } - - // А надо ли оно? - if (TrieSizeSafe(Item[Item_Params]) < 1) { - TrieDestroySafe(Item[Item_Params]); - } - - iItem = ADD_ITEM(Item); - - if (sJsonRef[0]) { - TrieSetCell(g_ItemsCache, sJsonRef, iItem); - } - - return iItem; -} - -// TODO: `Type` для совместимости, надо будет когда-нить убрать) -static Json_Object_GetItemTypeAndRemove(const JSON:jItem, sItemType[], const iItemTypeLen) { - new iRet = 0; - if (json_object_has_value(jItem, "Type", JSONString)) { - iRet = json_object_get_string(jItem, "Type", sItemType, iItemTypeLen); - json_object_remove(jItem, "Type"); - } else if (json_object_has_value(jItem, "ItemType", JSONString)) { - iRet = json_object_get_string(jItem, "ItemType", sItemType, iItemTypeLen); - json_object_remove(jItem, "ItemType"); - } - return iRet; -} diff --git a/amxmodx/scripting/VipM/ItemsController/Natives.inc b/amxmodx/scripting/VipM/ItemsController/Natives.inc deleted file mode 100644 index 46c225f..0000000 --- a/amxmodx/scripting/VipM/ItemsController/Natives.inc +++ /dev/null @@ -1,118 +0,0 @@ -#include amxmodx -#include json -#include "VipM/Utils" -#include "VipM/Natives" - -enum { - ERROR_TYPE_NOT_FOUND, - ERROR_ITEM_NOT_FOUND, -} - -#define NATIVE_CHECK_ITEM(%1) CompositeMacros( \ - if (!ITEM_EXISTS(%1)) { \ - log_error(ERROR_ITEM_NOT_FOUND, "[ERROR] Item #%d not found.", %1); \ - } \ -) - -#define NATIVE_CHECK_TYPE(%1) CompositeMacros( \ - if (!TYPE_EXISTS(%1)) { \ - log_error(ERROR_TYPE_NOT_FOUND, "[ERROR] Item type '%s' not found.", %1); \ - } \ -) - -public plugin_natives() { - Natives_Init("VipM_IC"); - - Natives_Reg("Init"); - Natives_Reg("RegisterType"); - Natives_Reg("RegisterTypeEvent"); - Natives_Reg("JsonGetItem"); - Natives_Reg("GiveItem"); -} - -@_Init() { - PluginInit(); -} - -// TODO: Вынести логику из нативов в соответствующий файл - -@_RegisterType(const PluginId) { - enum {Arg_Type = 1} - - new Type[S_ItemType]; - get_string(Arg_Type, Type[ItemType_Name], charsmax(Type[ItemType_Name])); - - Type[ItemType_PluginId] = PluginId; - Type[ItemType_Events] = Invalid_Trie; - - return ADD_TYPE(Type); -} - -@_RegisterTypeEvent(const PluginId) { - enum {Arg_Type = 1, Arg_Event, Arg_Func} - - new TypeName[32], Type[S_ItemType]; - get_string(Arg_Type, TypeName, charsmax(TypeName)); - - NATIVE_CHECK_TYPE(TypeName); - GET_TYPE(TypeName, Type); - - new E_ItemTypeEvent:Event = E_ItemTypeEvent:get_param(Arg_Event); - - new FuncName[64]; - get_string(Arg_Func, FuncName, charsmax(FuncName)); - - new FwdId = -1; - switch (Event) { - case ItemType_OnRead: // VipM_FwdReturn:(const JSON:jItem, Trie:Params) - FwdId = CreateOneForward(PluginId, FuncName, FP_CELL, FP_CELL); - - case ItemType_OnGive: // VipM_FwdReturn:(const UserId, const Trie:Params) - FwdId = CreateOneForward(PluginId, FuncName, FP_CELL, FP_CELL); - } - - if (FwdId < 0) { - return false; - } - - SET_TYPE_EVENT(Type, Event, FwdId); - SET_TYPE(Type); - - return FwdId >= 0; -} - -@_JsonGetItem() { - enum {Arg_jItem = 1} - - new JSON:jItem = JSON:get_param_byref(Arg_jItem); - new ItemId = Cfg_JsonGetItem(jItem); - set_param_byref(Arg_jItem, _:Invalid_JSON); - return ItemId; -} - -bool:@_GiveItem() { - enum {Arg_UserId = 1, Arg_ItemId} - - new UserId = get_param(Arg_UserId); - new ItemId = get_param(Arg_ItemId); - - NATIVE_CHECK_ITEM(ItemId); - new Item[S_Item]; - GET_ITEM(ItemId, Item); - - new Type[S_ItemType]; - GET_ITEM_TYPE(Item, Type); - - Forwards_DefaultReturn(VIPM_CONTINUE); - if (Forwards_CallP("GiveItem", UserId, Item[Item_Params]) == VIPM_STOP) { - return false; - } - - new Ret = VIPM_CONTINUE; - EMIT_TYPE_EVENT(Type, ItemType_OnGive, Ret, UserId, Item[Item_Params]) - if (Ret == VIPM_STOP) { - return false; - } - - return true; -} diff --git a/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc b/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc deleted file mode 100644 index 7afd39b..0000000 --- a/amxmodx/scripting/VipM/ItemsController/SrvCmds.inc +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "VipM/ArrayMap" -// #include "VipM/ItemsController/Objects/Type" - -SrvCmds_Init() { - register_srvcmd("vipm_ic_types", "@SrvCmd_Types"); -} - -@SrvCmd_Types() { - PrintTypesData(Types); -} - -PrintTypesData(const ArrayMap(am)) { - server_print("╔═════╤══════════════════════════════════╗"); - server_print("║ # │ Type name ║"); - server_print("╟─────┼──────────────────────────────────╢"); - ArrayMapForeachArray (am: i => Type[S_ItemType]) { - server_print("║ %03d │ %-32s ║", i, Type[ItemType_Name]); - } - server_print("╚═════╧══════════════════════════════════╝"); -} \ No newline at end of file diff --git a/amxmodx/scripting/VipM/ItemsController/Structs.inc b/amxmodx/scripting/VipM/ItemsController/Structs.inc deleted file mode 100644 index 3ebdf7b..0000000 --- a/amxmodx/scripting/VipM/ItemsController/Structs.inc +++ /dev/null @@ -1,12 +0,0 @@ - -enum _:S_ItemType{ - ItemType_Name[32], - ItemType_PluginId, - - Trie:ItemType_Events, -} - -enum _:S_Item{ - Item_Type, - Trie:Item_Params, -} diff --git a/amxmodx/scripting/VipM/ItemsController/Utils.inc b/amxmodx/scripting/VipM/ItemsController/Utils.inc deleted file mode 100644 index eaea3be..0000000 --- a/amxmodx/scripting/VipM/ItemsController/Utils.inc +++ /dev/null @@ -1,53 +0,0 @@ -#include amxmodx - -#define GET_ITEM(%1,%2) \ - ArrayGetArray(Items, %1, %2) - -#define ADD_ITEM(%1) \ - ArrayPushArray(Items, %1) - -#define ITEM_EXISTS(%1) \ - (%1 >= 0 && %1 < ArraySizeSafe(Items)) - - -#define TYPE_EXISTS(%1) \ - ArrayMapKeyExists(Types, %1) - -#define GET_TYPE(%1,%2) \ - ArrayMapGetArrayByKey(Types, %1, %2) - -#define GET_TYPE_ID(%1) \ - ArrayMapGetIndex(Types, %1) - -#define GET_TYPE_BY_ID(%1,%2) \ - ArrayMapGetArray(Types, %1, %2) - -#define GET_ITEM_TYPE(%1,%2) \ - GET_TYPE_BY_ID(%1[Item_Type], %2) - -#define SET_TYPE(%1) \ - ArrayMapSetArrayByKey(Types, %1[ItemType_Name], %1) - -#define ADD_TYPE(%1) \ - ArrayMapPushArray(Types, %1, %1[ItemType_Name]) - - -// EMIT_TYPE_EVENT(Type, E_ItemTypeEvent:Event, Return, ...Params) -#define EMIT_TYPE_EVENT(%1,%2,%3) \ - if ( \ - %1[ItemType_Events] != Invalid_Trie \ - && TrieKeyExists(%1[ItemType_Events], IntToStr(%2)) \ - ) { \ - new ___EVENT_FWD; \ - TrieGetCell(%1[ItemType_Events], IntToStr(%2), ___EVENT_FWD); \ - ExecuteForward(___EVENT_FWD, %3); \ - } - -// SET_TYPE_EVENT(Type, E_ItemTypeEvent:Event, FwdId) -#define SET_TYPE_EVENT(%1,%2,%3) \ - if (%3 >= 0) { \ - if(%1[ItemType_Events] == Invalid_Trie) \ - %1[ItemType_Events] = TrieCreate(); \ - TrieSetCell(%1[ItemType_Events], IntToStr(%2), %3); \ - } \ - else TrieDeleteKey(%1[ItemType_Events], IntToStr(%2)) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 1405b1f..8913255 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -12,36 +12,44 @@ #include reapi #include VipModular -stock const __INT_TEMPLATE_STR[] = "%d"; stock const __SLANG_TEMPLATE_STR[] = "%l"; stock const __CLANG_TEMPLATE_STR[] = "%L"; stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; +stock const bool:__CompositeMacros_AlwaysFalse = false; #define CompositeMacros(%1) \ - do { %1 } while(is_linux_server() == 0xDEADBEEF) + do { %1 } while(__CompositeMacros_AlwaysFalse) -#define GetRound() \ - (get_member_game(m_iTotalRoundsPlayed) + 1) +stock GetCurrentRoundNum() { + return get_member_game(m_iTotalRoundsPlayed) + 1; +} -#define IntToStr(%1) \ - fmt(__INT_TEMPLATE_STR, %1) +stock IntToStr(const int) { + new str[11]; + num_to_str(int, str, charsmax(str)); -#define IsUserIdValid(%1) \ - (%1 >= 1 && %1 <= 32) + return str; +} -#define IsUserValid(%1) \ - ( \ - IsUserIdValid(%1) \ - && is_user_connected(%1) \ - ) +stock IsPlayerIndexValid(const playerIndex) { + return playerIndex >= 1 && playerIndex <= 32; +} -#define IsUserValidA(%1) \ - ( \ - IsUserIdValid(%1) \ - && is_user_alive(%1) \ - ) +stock IsPlayerValid(const playerIndex) { + return ( + IsPlayerIndexValid(playerIndex) + && is_user_connected(playerIndex) + ); +} + +stock IsPlayerAlive(const playerIndex) { + return ( + IsPlayerIndexValid(playerIndex) + && is_user_alive(playerIndex) + ); +} #define Lang(%1) \ fmt(__SLANG_TEMPLATE_STR, %1) @@ -50,7 +58,7 @@ stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; fmt(__CLANG_TEMPLATE_STR, %1) #define ChatPrint(%1,%2) \ - client_print_color(%1, print_team_default, __CLANG_TEMPLATE_STR, IsUserIdValid(%1) ? %1 : -1, __LANG_MSG_LAYOUT_KEY, fmt(%2)) + client_print_color(%1, print_team_default, __CLANG_TEMPLATE_STR, IsPlayerIndexValid(%1) ? %1 : -1, __LANG_MSG_LAYOUT_KEY, fmt(%2)) #define ChatPrintL(%1,%2) \ ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2) @@ -254,13 +262,6 @@ stock RegisterPlugin( } \ ) -// Надо чтобы переменные были определены раньше, что может быть неудобно:) -// stock RegisterPluginByVars() { -// if (GetAmxxVersionNum() < 1100) { -// register_plugin(PluginName, PluginVersion, PluginAuthor); -// } -// } - stock ItemHasClip(const ItemId) { new WeaponIdType:WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { @@ -295,10 +296,10 @@ stock InstantReloadActiveWeapon(const UserId) { } } -stock bool:StrEqualEx(const sA[], const sB[], const iCount = 0, const bool:bIgnoreCase = false) { - return bIgnoreCase - ? equali(sA, sB, iCount) - : equal(sA, sB, iCount); +stock bool:StrEqualEx(const str1[], const str2[], const checkLength = 0, const bool:ignoreCase = false) { + return ignoreCase + ? equali(str1, str2, checkLength) + : equal(str1, str2, checkLength); } stock bool:IsUserInBuyZone(const UserId) { @@ -314,6 +315,6 @@ stock ParseColonTime(const sTime[], const sColon[] = ":") { return ((clamp(str_to_num(sHours), 0, 23) * 60) + clamp(str_to_num(sMinutes), 0, 59)) * 60; } -stock GetTime() { +stock GetDayTimeInSeconds() { return get_systime() % (24 * 60 * 60); } diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc new file mode 100644 index 0000000..7b6e0c0 --- /dev/null +++ b/amxmodx/scripting/include/ItemsController.inc @@ -0,0 +1,353 @@ +#if defined __items_controller_included + #endinput +#endif +#define __items_controller_included + +#include +#include + +#define IC_VERSION "1.0.0" +stock const IC_LIBRARY[] = "items-controller"; +stock const IC_VERSION_CVAR[] = "ic_version"; + +#define IC_ITEM_TYPE_NAME_MAX_LEN 64 +#define IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN 64 + +#define IC_RET_READ_SUCCESS 0 +#define IC_RET_READ_FAIL 1 + +#define IC_RET_GIVE_SUCCESS 0 +#define IC_RET_GIVE_FAIL 1 + +enum T_IC_ItemType { Invalid_IC_ItemType = -1 } +enum T_IC_Item {Invalid_IC_Item = -1} + +// Deprecated names! +#define VipM_IC_T_Item T_IC_Item +#define VipM_IC_Invalid_Item Invalid_IC_Item +#define VIPM_IC_ITEM_TYPE_NAME_MAX_LEN IC_ITEM_TYPE_NAME_MAX_LEN + +enum E_ItemTypeEvent{ + /* + * Описание: Вызывается, когда читаются параметры предмета. + * Возв. тип: IC_RET_READ_* + * Параметры: (const JSON:instanceJson, Trie:params): + * instanceJson - JSON-обьект с параметрами предмета. + * params - key-value хранилище для записи прочитанных параметров. + * + * Примечание: Вызывается в момент чтения оружия нативом IC_Item_ReadFromJson. Скорее всего в plugin_precache. + * Примечание: Если возвращено IC_RET_READ_FAIL, предмет будет пропущен. + */ + ItemType_OnRead, + + /* + * Описание: Вызывается, когда предмет выдаётся игроку (При вызове натива IC_Item_Give). + * Возв. тип: IC_RET_GIVE_* + * Параметры: (const playerIndex, const Trie:params): + * playerIndex - Индекс игрока, которому выдаётся предмет. + * params - key-value хранилище параметров. + * + * Примечание: Если возвращено IC_RET_GIVE_FAIL, предмет не будет считаться выданным (Натив IC_Item_Give вернёт false). + */ + ItemType_OnGive, +} + +/** + * Вызывается после инициализации компонента типов предметов. + * После вызова этого форварда можно регистрировать типы предметов. + * + * @note Вызывается не позже plugin_precache. + * + * @noreturn + */ +forward IC_ItemType_OnInited(); + +/** + * Вызывается после инициализации компонента предметов. + * После вызова этого форварда можно создавать экземпляры предметов (в т.ч. читать их из JSON). + * + * @note Вызывается не позже plugin_precache. + * + * @noreturn + */ +forward IC_Item_OnInited(); + +/** + * Принудительно инициализирует контроллер предметов. + * + * @noreturn + */ +native IC_Init(); + +/** + * Регистрирует новый тип предмета. + * + * @param name Название типа. + * + * @return Хендлер зарегистрированного типа. + */ +native T_IC_ItemType:IC_ItemType_Register(const name[]); + +/** + * Регистрирует новый тип предмета. + * + * @param type Хендлер типа. + * @param event Событие, для которого устанавливается обработчик. + * @param functionName Название функции-обработчика. + * + * @noreturn + */ +native IC_ItemType_SetEventListener(const T_IC_ItemType:type, const E_ItemTypeEvent:event, const functionName[]); + +/** + * Регистрирует новый тип предмета с обработчиками событий. + * + * @param name Название типа. + * @param onRead Название функции-обработчика для события ItemType_OnRead. + * @param onGive Название функции-обработчика для события ItemType_OnGive. + * + * @return Хендлер зарегистрированного типа. + */ +stock T_IC_ItemType:IC_ItemType_SimpleRegister(const name[], const onRead[] = "", const onGive[] = "") { + new T_IC_ItemType:type = IC_ItemType_Register(name); + + if (onRead[0] != EOS) { + IC_ItemType_SetEventListener(type, ItemType_OnRead, onRead); + } + + if (onGive[0] != EOS) { + IC_ItemType_SetEventListener(type, ItemType_OnGive, onGive); + } + + return type; +} + +/** + * Читает предмет из JSON-значения. + * + * @note Поддерживает ссылки вида "File:...". // TODO: Пока не поддерживаются) + * + * @param isntanceJson JSON-значение, содержажее предмет или ссылку на него. + * + * @return Хендлер прочитанного экземпляра предмета. Invalid_IC_Item в случае ошибки. + */ +native T_IC_Item:IC_Item_ReadFromJson(const JSON:isntanceJson); + +/** + * Читает массив предметов из JSON-значения. + * + * @note Поддерживает ссылки вида "File:...". // TODO: Пока не поддерживаются) + * + * @param isntancesJson JSON-значение, содержажее массив предметов, один предмет или ссылку. + * @param array Хендлер динамического массива, в который нужно дописать прочитанные предметы. + * + * @return Хендлер динамического массива с прочитанными предметами. Если был передан параметр array, то вернётся то же значение. + */ +native Array:IC_Item_ReadArrayFromJson(const JSON:isntancesJson, &Array:array = Invalid_Array); + +stock Array:Json_Object_IC_GetItems(const JSON:jObj, const sKey[], const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return Invalid_Array; + } + + new JSON:jItems = json_object_get_value(jObj, sKey, bDotNot); + new Array:aItems = IC_Item_ReadArrayFromJson(jItems); + json_free(jItems); + + return aItems; +} + +/** + * Выдача предмета игроку. + * + * @param playerIndex Индекс игрока. + * @param item Хендлер экземпляра предмета. + * + * @return true, если предмет успешно выдан, иначе false. + */ +native bool:IC_Item_Give(const playerIndex, const T_IC_Item:item); + +/** + * Выдача игроку всех предметов из массива. + * + * @param playerIndex Индекс игрока. + * @param array Хендлер динамического массива с хендлерами экземпляров предметов. + * + * @return true, если хотя бы один предмет успешно выдан, иначе false. + */ +stock bool:IC_Item_GiveArray(const playerIndex, const Array:array) { + if (array == Invalid_Array) { + return false; + } + + new bool:success = false; + for (new i = 0; i < ArraySize(array); i++) { + if (IC_Item_Give(playerIndex, ArrayGetCell(array, i))) { + success = true; + } + } + + return success; +} + +// TODO: getters for params controller + + +/** + * Вызывается в момент инициалзиации типов предметов. + * + * @note Вызывается из VipM_OnInitModules + * + * @noreturn + * + * @deprecated Use IC_ItemType_OnInited() instead. + */ +#pragma deprecated Use IC_ItemType_OnInited() instead. +forward VipM_IC_OnInitTypes(); + +/** + * Инициализирует контроллер предметов. + * + * @noreturn + * + * @deprecated Use IC_Init() instead. + */ +#pragma deprecated Use IC_Init() instead. +native VipM_IC_Init(); + +/** + * Регистрирует новый тип предмета. + * + * @param Type Название типа. + * + * @return Индекс зарегистрированного типа + * + * @deprecated Use IC_ItemType_Register() instead. + */ +#pragma deprecated Use IC_ItemType_Register() instead. +native VipM_IC_RegisterType(const Type[]); + +/** + * Регистрирует обработчик события для указанного типа предмета. + * + * @param Type Название типа. + * @param Event Событие. + * @param Func Название функции-обработчика. + * + * @return Вернёт true, если обработчик успешно зарегистрирован. + * + * @deprecated Use IC_ItemType_SetEventListener() instead. + */ +#pragma deprecated Use IC_ItemType_SetEventListener() instead. +native VipM_IC_RegisterTypeEvent(const Type[], const E_ItemTypeEvent:Event, const Func[]); + +/** + * Загрузка предмета из JSON-обьекта. + * + * @param jItem JSON-объект, содержащий информацию о предмете. + * + * @note После загрузки предмета, JSON-объект уничтожается. + * @note Структура объекта: + * { + * "Type": "НазваниеТипа", + * "НазваниеПараметра1": "ЗначениеПараметра1", + * "НазваниеПараметра2": "ЗначениеПараметра2", + * ... + * } + * + * @return Индекс загруженного предмета. Invalid_IC_Item, если что-то пошло не так. + * + * @deprecated Use IC_Item_ReadFromJson() instead. + */ +#pragma deprecated Use IC_Item_ReadFromJson() instead. +native VipM_IC_T_Item:VipM_IC_JsonGetItem(&JSON:jItem); + +/** + * Выдача предмета игроку. + * + * @param UserId Индекс игрока. + * @param ItemId Индекс предмета, возвращённый нативом VipM_IC_JsonGetItem. + * + * @return true, если предмет успешно выдан, иначе false. + * + * @deprecated Use IC_Item_Give() instead. + */ +#pragma deprecated Use IC_Item_Give() instead. +native bool:VipM_IC_GiveItem(const UserId, const VipM_IC_T_Item:ItemId); + +#pragma deprecated Use IC_Item_ReadArrayFromJson() instead. +stock Array:VipM_IC_JsonGetItems(JSON:jItems) { + // TODO: Не удалять хендлер (то же относится и к нативу) + + new Array:aItems = Invalid_Array; + if (jItems == Invalid_JSON) { + return aItems; + } + + switch (json_get_type(jItems)) { + case JSONArray: { + new cItems = json_array_get_count(jItems); + if (cItems < 1) { + return Invalid_Array; + } + + aItems = ArrayCreate(1, cItems); + for (new i = 0; i < cItems; i++) { + new JSON:jItem = json_array_get_value(jItems, i); + new VipM_IC_T_Item:ItemId = VipM_IC_JsonGetItem(jItem); + if (ItemId != Invalid_IC_Item) { + ArrayPushCell(aItems, ItemId); + } + } + json_free(jItems); + } + + case JSONObject, JSONString: { + new VipM_IC_T_Item:ItemId = VipM_IC_JsonGetItem(jItems); + if (ItemId == Invalid_IC_Item) { + return Invalid_Array; + } + + aItems = ArrayCreate(1, 1); + ArrayPushCell(aItems, ItemId); + } + } + return aItems; +} + +#pragma deprecated Use IC_Item_GiveArray() instead. +stock bool:VipM_IC_GiveItems(const UserId, const Array:aItems) { + if (aItems == Invalid_Array) { + return false; + } + + new bool:bRes = false; + for (new i = 0; i < ArraySize(aItems); i++) { + if (VipM_IC_GiveItem(UserId, VipM_IC_T_Item:ArrayGetCell(aItems, i))) { + bRes = true; + } + } + + return bRes; +} + +stock bool:VipM_Params_GiveItems(const UserId, const Trie:tParams, const sParam[]) { + return VipM_IC_GiveItems(UserId, VipM_Params_GetArr(tParams, sParam)); +} + +stock bool:VipM_Params_GiveItem(const UserId, const Trie:tParams, const sParam[]) { + return VipM_IC_GiveItems(UserId, VipM_Params_GetCell(tParams, sParam)); +} + +#pragma deprecated Use Json_Object_IC_GetItems() instead. +stock Array:Json_Object_GetItemsIC(const JSON:jObj, const sKey[], const bool:bDotNot = false) { + if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { + return Invalid_Array; + } + + new JSON:jItems = json_object_get_value(jObj, sKey, bDotNot); + new Array:aItems = VipM_IC_JsonGetItems(jItems); + json_free(jItems); + + return aItems; +} diff --git a/amxmodx/scripting/include/VipM/ItemsController.inc b/amxmodx/scripting/include/VipM/ItemsController.inc index a4b9ee0..db06c8e 100644 --- a/amxmodx/scripting/include/VipM/ItemsController.inc +++ b/amxmodx/scripting/include/VipM/ItemsController.inc @@ -1,199 +1 @@ -#if defined _vipmodular_ic_included - #endinput -#endif -#define _vipmodular_ic_included - -#include -#include - -/** - * Vip Modular: Items Controller -*/ - -#include - -enum VipM_IC_T_Item {VipM_IC_Invalid_Item = -1} - -enum E_ItemTypeEvent{ - - /* - * Описание: Вызывается, когда читаются параметры предмета. - * Возв. тип: VipM_FwdReturn - * Параметры: (const JSON:jCfg, Trie:Params): - * jCfg - JSON-обьект с параметрами предмета. - * Params - Хеш-карта с прочитанными параметрами. Может быть изменена. - * - * Примечание: Вызывается в момент чтения оружия нативом VipM_IC_JsonGetItem. Скорее всего в plugin_precache. - * Примечание: Если возвращено VIPM_STOP, предмет будет пропущен. - */ - ItemType_OnRead, - - /* - * Описание: Вызывается, когда предмет выдаётся игроку (При вызове натива VipM_IC_GiveItem). - * Возв. тип: VipM_FwdReturn - * Параметры: (const UserId, const Trie:Params): - * UserId - Индекс игрока, которому выдаётся предмет. - * Params - Хеш-карта с параметрами. Для извлечения отдельных значений можно использовать стоковые функции VipM_Params_*. - * - * Примечание: Если возвращено VIPM_STOP, предмет не будет считаться выданным (Натив VipM_IC_GiveItem вернёт false). - */ - ItemType_OnGive, -} - -/** - * Вызывается в момент инициалзиации типов предметов. - * - * @note Вызывается из VipM_OnInitModules - * - * @noreturn - */ -forward VipM_IC_OnInitTypes(); - -/** - * Вызывается после чтения предмета из JSON. - * - * @param jItem JSON-обьект с параметрами предмета. - * @param Params Хеш-карта с прочитанными параметрами. - * - * @return Если вернёт VIPM_STOP, предмет не будет загружен. - */ -forward VipM_IC_OnReadItem(const JSON:jItem, Trie:Params); - -/** - * Вызывается перед выдачей предмета игроку. - * - * @param UserId Индекс игрока, которому выдаётся предмет. - * @param Params Хеш-карта с параметрами предмета. - * - * @return Если вернёт VIPM_STOP, предмет не будет выдан. - */ -forward VipM_IC_OnGiveItem(const UserId, const Trie:Params); - -/** - * Инициализирует контроллер предметов. - * - * @noreturn - */ -native VipM_IC_Init(); - -/** - * Регистрирует новый тип предмета. - * - * @param Type Название типа. - * - * @return Индекс зарегистрированного типа - */ -native VipM_IC_RegisterType(const Type[]); - -/** - * Регистрирует обработчик события для указанного типа предмета. - * - * @param Type Название типа. - * @param Event Событие. - * @param Func Название функции-обработчика. - * - * @return Вернёт true, если обработчик успешно зарегистрирован. - */ -native VipM_IC_RegisterTypeEvent(const Type[], const E_ItemTypeEvent:Event, const Func[]); - -/** - * Загрузка предмета из JSON-обьекта. - * - * @param jItem JSON-объект, содержащий информацию о предмете. - * - * @note После загрузки предмета, JSON-объект уничтожается. - * @note Структура объекта: - * { - * "Type": "НазваниеТипа", - * "НазваниеПараметра1": "ЗначениеПараметра1", - * "НазваниеПараметра2": "ЗначениеПараметра2", - * ... - * } - * - * @return Индекс загруженного предмета. VipM_IC_Invalid_Item, если что-то пошло не так. - */ -native VipM_IC_T_Item:VipM_IC_JsonGetItem(&JSON:jItem); - -/** - * Выдача предмета игроку. - * - * @param UserId Индекс игрока. - * @param ItemId Индекс предмета, возвращённый нативом VipM_IC_JsonGetItem. - * - * @return true, если предмет успешно выдан, иначе false. - */ -native bool:VipM_IC_GiveItem(const UserId, const VipM_IC_T_Item:ItemId); - -stock Array:VipM_IC_JsonGetItems(JSON:jItems) { - // TODO: Не удалять хендлер (то же относится и к нативу) - - new Array:aItems = Invalid_Array; - if (jItems == Invalid_JSON) { - return aItems; - } - - switch (json_get_type(jItems)) { - case JSONArray: { - new cItems = json_array_get_count(jItems); - if (cItems < 1) { - return Invalid_Array; - } - - aItems = ArrayCreate(1, cItems); - for (new i = 0; i < cItems; i++) { - new JSON:jItem = json_array_get_value(jItems, i); - new VipM_IC_T_Item:ItemId = VipM_IC_JsonGetItem(jItem); - if (ItemId != VipM_IC_Invalid_Item) { - ArrayPushCell(aItems, ItemId); - } - } - json_free(jItems); - } - - case JSONObject, JSONString: { - new VipM_IC_T_Item:ItemId = VipM_IC_JsonGetItem(jItems); - if (ItemId == VipM_IC_Invalid_Item) { - return Invalid_Array; - } - - aItems = ArrayCreate(1, 1); - ArrayPushCell(aItems, ItemId); - } - } - return aItems; -} - -stock bool:VipM_IC_GiveItems(const UserId, const Array:aItems) { - if (aItems == Invalid_Array) { - return false; - } - - new bool:bRes = false; - for (new i = 0; i < ArraySize(aItems); i++) { - if (VipM_IC_GiveItem(UserId, VipM_IC_T_Item:ArrayGetCell(aItems, i))) { - bRes = true; - } - } - - return bRes; -} - -stock bool:VipM_Params_GiveItems(const UserId, const Trie:tParams, const sParam[]) { - return VipM_IC_GiveItems(UserId, VipM_Params_GetArr(tParams, sParam)); -} - -stock bool:VipM_Params_GiveItem(const UserId, const Trie:tParams, const sParam[]) { - return VipM_IC_GiveItems(UserId, VipM_Params_GetCell(tParams, sParam)); -} - -stock Array:Json_Object_GetItemsIC(const JSON:jObj, const sKey[], const bool:bDotNot = false) { - if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { - return Invalid_Array; - } - - new JSON:jItems = json_object_get_value(jObj, sKey, bDotNot); - new Array:aItems = VipM_IC_JsonGetItems(jItems); - json_free(jItems); - - return aItems; -} +#include \ No newline at end of file diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index f150731..3b8eb41 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -137,6 +137,6 @@ native VipM_Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[] #include #include -#include +#include #include #include From 2d5b14db14f8d2a2e25ed2c5a086b31fa7b0af0d Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 03:05:18 +0300 Subject: [PATCH 017/108] Read `Name` param by default (deprecated behaviour) --- amxmodx/scripting/ItemsController/Objects/Items/Type.inc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc index 8ac898a..199c976 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc @@ -126,6 +126,11 @@ bool:ItemType_ReadParamsFromJsonObject(const T_IC_ItemType:type, const JSON:para // TODO: Использовать ParamsController + // deprecated + new nameParam[256]; + json_object_get_string(paramsJson, "Name", nameParam, charsmax(nameParam)); + TrieSetString(params, "Name", nameParam); + if (typeObject[ItemType_Events][ItemType_OnRead] != INVALID_HANDLE) { new ret = IC_RET_READ_SUCCESS; ExecuteForward(typeObject[ItemType_Events][ItemType_OnRead], ret, paramsJson, params); From 5cc25771dca93f19dd4385984a48cd748c0f4fa5 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 03:21:11 +0300 Subject: [PATCH 018/108] Update ic extensions --- amxmodx/scripting/IC-I-Default.sma | 511 ++++++++++++++++++ amxmodx/scripting/IC-I-Limits.sma | 52 ++ amxmodx/scripting/VipM-I-Default.sma | 497 ----------------- amxmodx/scripting/VipM-I-Limits.sma | 56 -- amxmodx/scripting/include/ItemsController.inc | 4 +- 5 files changed, 565 insertions(+), 555 deletions(-) create mode 100644 amxmodx/scripting/IC-I-Default.sma create mode 100644 amxmodx/scripting/IC-I-Limits.sma delete mode 100644 amxmodx/scripting/VipM-I-Default.sma delete mode 100644 amxmodx/scripting/VipM-I-Limits.sma diff --git a/amxmodx/scripting/IC-I-Default.sma b/amxmodx/scripting/IC-I-Default.sma new file mode 100644 index 0000000..01dadfa --- /dev/null +++ b/amxmodx/scripting/IC-I-Default.sma @@ -0,0 +1,511 @@ +#include +#include +#include +#include +#include +#include +#include "VipM/Utils" + +public stock const PluginName[] = "[IC-I] Default"; +public stock const PluginVersion[] = IC_VERSION; +public stock const PluginAuthor[] = "ArKaNeMaN"; +public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-pub"; +public stock const PluginDescription[] = "[ItemsController-Item] Default items."; + +new Float:g_fSpeedMult[MAX_PLAYERS + 1] = {1.0, ...}; +new Float:g_fGivenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; +new Float:g_fTakenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; + +new HookChain:g_iHook_ResetMaxSpeed_Post = INVALID_HOOKCHAIN; +new HookChain:g_iHook_TakeDamage_Pre = INVALID_HOOKCHAIN; +new HookChain:g_iHook_Spawn_Pre = INVALID_HOOKCHAIN; + +public IC_ItemType_OnInited() { + register_plugin(PluginName, PluginVersion, PluginAuthor); + + // Затычка для тех мест, где при отсутствии предметов выоезает ошибка/варн + IC_ItemType_SimpleRegister( + .name = "None" + ); + + IC_ItemType_SimpleRegister( + .name = "Random", + .onRead = "@OnRandomRead", + .onGive = "@OnRandomGive" + ); + + IC_ItemType_SimpleRegister( + .name = "InstantReloadAllWeapons", + .onGive = "@OnInstantReloadAllWeaponsGive" + ); + + IC_ItemType_SimpleRegister( + .name = "InstantReload", + .onGive = "@OnInstantReloadGive" + ); + + IC_ItemType_SimpleRegister( + .name = "RefillBpAmmo", + .onGive = "@OnRefillBpAmmoGive" + ); + + IC_ItemType_SimpleRegister( + .name = "Speed", + .onRead = "@OnSpeedRead", + .onGive = "@OnSpeedGive" + ); + + IC_ItemType_SimpleRegister( + .name = "Money", + .onRead = "@OnMoneyRead", + .onGive = "@OnMoneyGive" + ); + + IC_ItemType_SimpleRegister( + .name = "Weapon", + .onRead = "@OnWeaponRead", + .onGive = "@OnWeaponGive" + ); + + IC_ItemType_SimpleRegister( + .name = "ItemsList", + .onRead = "@OnItemsListRead", + .onGive = "@OnItemsListGive" + ); + + IC_ItemType_SimpleRegister( + .name = "Command", + .onRead = "@OnCommandRead", + .onGive = "@OnCommandGive" + ); + + IC_ItemType_SimpleRegister( + .name = "DefuseKit", + .onGive = "@OnDefuseKitGive" + ); + + IC_ItemType_SimpleRegister( + .name = "Health", + .onRead = "@OnHealthRead", + .onGive = "@OnHealthGive" + ); + + IC_ItemType_SimpleRegister( + .name = "DamageMult", + .onRead = "@OnDamageMultRead", + .onGive = "@OnDamageMultGive" + ); + + IC_ItemType_SimpleRegister( + .name = "Armor", + .onRead = "@OnArmorRead", + .onGive = "@OnArmorGive" + ); + + DisableHookChain(g_iHook_ResetMaxSpeed_Post = RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@OnPlayerResetSpeedPost", true)); + DisableHookChain(g_iHook_Spawn_Pre = RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawnPre", false)); + DisableHookChain(g_iHook_TakeDamage_Pre = RegisterHookChain(RG_CBasePlayer_TakeDamage, "@OnPlayerTakeDamage", false)); +} + +@OnPlayerSpawnPre(const playerIndex) { + g_fSpeedMult[playerIndex] = 1.0; + g_fGivenDmgMult[playerIndex] = 1.0; + g_fTakenDmgMult[playerIndex] = 1.0; +} + +@OnPlayerResetSpeedPost(const playerIndex) { + if (g_fSpeedMult[playerIndex] != 1.0) { + MultUserSpeed(playerIndex, g_fSpeedMult[playerIndex]); + } +} + +@OnPlayerTakeDamage(const victimIndex, inflictorIndex, attackerInde, Float:damage, damageType) { + if (is_user_connected(attackerInde)) { + damage *= g_fGivenDmgMult[attackerInde]; + } + + if (is_user_connected(victimIndex)) { + damage *= g_fTakenDmgMult[victimIndex]; + } + + SetHookChainArg(4, ATYPE_FLOAT, damage); + return HC_CONTINUE; +} + +@OnDamageMultRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (json_object_has_value(instanceJson, "Given", JSONNumber)) { + TrieSetCell(p, "Given", json_object_get_real(instanceJson, "Given")); + } + + if (json_object_has_value(instanceJson, "Taken", JSONNumber)) { + TrieSetCell(p, "Taken", json_object_get_real(instanceJson, "Taken")); + } + + CallOnceR(IC_RET_READ_SUCCESS); // Чтобы лишний раз не дёргать натив активации хука + + EnableHookChain(g_iHook_Spawn_Pre); + EnableHookChain(g_iHook_TakeDamage_Pre); + + return IC_RET_READ_SUCCESS; +} + +@OnDamageMultGive(const playerIndex, const Trie:p) { + g_fGivenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Given", 1.0); + g_fTakenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Taken", 1.0); +} + +@OnHealthRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Health", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Health` required for `Health` item."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Health", json_object_get_real(instanceJson, "Health")); + + if (json_object_has_value(instanceJson, "MaxHealth", JSONNumber)) { + TrieSetCell(p, "MaxHealth", json_object_get_real(instanceJson, "MaxHealth")); + } + + if (json_object_has_value(instanceJson, "SetHealth", JSONBoolean)) { + TrieSetCell(p, "SetHealth", json_object_get_bool(instanceJson, "SetHealth")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnHealthGive(const playerIndex, const Trie:p) { + if (VipM_Params_GetBool(p, "SetHealth", false)) { + set_entvar(playerIndex, var_health, VipM_Params_GetFloat(p, "Health")); + } else { + new Float:fHealth = Float:get_entvar(playerIndex, var_health); + new Float:fMaxHealth = VipM_Params_GetFloat(p, "MaxHealth", 100.0); + new Float:fAddHealth = floatclamp(VipM_Params_GetFloat(p, "Health"), 0.0, floatmax(0.0, fMaxHealth - fHealth)); + new Float:fMaxHealthCurrent = Float:get_entvar(playerIndex, var_max_health); + new bool:bNeedOverrideMaxHealth = (fHealth < fMaxHealth && fMaxHealthCurrent < fMaxHealth); + + if (bNeedOverrideMaxHealth) { + set_entvar(playerIndex, var_max_health, fMaxHealth); + } + + ExecuteHamB(Ham_TakeHealth, playerIndex, fAddHealth, DMG_GENERIC); + + if (bNeedOverrideMaxHealth) { + set_entvar(playerIndex, var_max_health, fMaxHealthCurrent); + } + } +} + +@OnArmorRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Armor", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Armor` required for `Armor` item."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Armor", json_object_get_number(instanceJson, "Armor")); + + if (json_object_has_value(instanceJson, "MaxArmor", JSONNumber)) { + TrieSetCell(p, "MaxArmor", json_object_get_number(instanceJson, "MaxArmor")); + } + + if (json_object_has_value(instanceJson, "SetArmor", JSONBoolean)) { + TrieSetCell(p, "SetArmor", json_object_get_bool(instanceJson, "SetArmor")); + } + + if (json_object_has_value(instanceJson, "Helmet", JSONBoolean)) { + TrieSetCell(p, "Helmet", json_object_get_bool(instanceJson, "Helmet")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnArmorGive(const playerIndex, const Trie:p) { + if (VipM_Params_GetBool(p, "SetArmor", false)) { + rg_set_user_armor(playerIndex, VipM_Params_GetInt(p, "Armor"), VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + } else { + new iSetArmor = min(rg_get_user_armor(playerIndex) + VipM_Params_GetInt(p, "Armor"), VipM_Params_GetInt(p, "MaxArmor", 100)); + + rg_set_user_armor(playerIndex, iSetArmor, VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + } +} + +@OnRandomRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + // TODO: Сделать как-то разные шансы + if (!json_object_has_value(instanceJson, "Items")) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `Random`."); + return IC_RET_READ_FAIL; + } + + new Array:aItems = Json_Object_IC_GetItems(instanceJson, "Items"); + if (ArraySizeSafe(aItems) <= 1) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` must have >1 items."); + ArrayDestroy(aItems); + return IC_RET_READ_FAIL; + } + + TrieSetCell(p, "Items", aItems); + + return IC_RET_READ_SUCCESS; +} + +@OnRandomGive(const playerIndex, const Trie:p) { + new Array:aItems = VipM_Params_GetArr(p, "Items"); + new iRandomIndex = random_num(0, ArraySizeSafe(aItems) - 1); + new VipM_IC_T_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); + + return IC_Item_Give(playerIndex, iRandomItem) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; +} + +@OnInstantReloadGive(const playerIndex, const Trie:p) { + InstantReloadActiveWeapon(playerIndex); +} + +@OnInstantReloadAllWeaponsGive(const playerIndex, const Trie:p) { + InstantReloadAllWeapons(playerIndex); +} + +@OnRefillBpAmmoGive(const playerIndex, const Trie:p) { + new iMaxAmmos[32] = {-1, ...}; + + // Получение дефолтных значений + for (new WeaponIdType:iWpnId = WEAPON_P228; iWpnId < WEAPON_P90; iWpnId++) { + switch (iWpnId) { + case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: + iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = -1; + default: + iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS); + } + } + + // Получение актуальных значений исходя из пушек в инвентаре + for (new InventorySlotType:iSlot = PRIMARY_WEAPON_SLOT; iSlot <= PISTOL_SLOT; iSlot++) { + new ItemId = get_member(playerIndex, m_rgpPlayerItems, iSlot); + while (ItemId > 0 && !is_nullent(ItemId)) { + new iAmmoType = get_member(ItemId, m_Weapon_iPrimaryAmmoType); + if (iAmmoType >= 0) { + iMaxAmmos[iAmmoType] = max(iMaxAmmos[iAmmoType], rg_get_iteminfo(ItemId, ItemInfo_iMaxAmmo1)); + } + ItemId = get_member(ItemId, m_pNext); + } + } + + for (new iAmmoType = 0; iAmmoType < 32; iAmmoType++) { + if (iMaxAmmos[iAmmoType] >= 0) { + set_member(playerIndex, m_rgAmmo, iMaxAmmos[iAmmoType], iAmmoType); + } + } +} + +@OnSpeedRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Multiplier", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Multiplier` required for item `Speed`."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Multiplier", json_object_get_real(instanceJson, "Multiplier")); + + CallOnceR(IC_RET_READ_SUCCESS); // Чтобы лишний раз не дёргать натив активации хука + + EnableHookChain(g_iHook_Spawn_Pre); + EnableHookChain(g_iHook_ResetMaxSpeed_Post); + + return IC_RET_READ_SUCCESS; +} + +@OnSpeedGive(const playerIndex, const Trie:p) { + g_fSpeedMult[playerIndex] = VipM_Params_GetFloat(p, "Multiplier", 1.0); + MultUserSpeed(playerIndex, g_fSpeedMult[playerIndex]); +} + +@OnMoneyRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Amount", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Amount` required for item `Money`."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Amount", json_object_get_number(instanceJson, "Amount")); + + if (json_object_has_value(instanceJson, "GiveType", JSONString)) { + new sBuffer[32]; + json_object_get_string(instanceJson, "GiveType", sBuffer, charsmax(sBuffer)); + new accountSet = StrToAccountSet(sBuffer); + if (accountSet < 0) { + Json_LogForFile(instanceJson, "ERROR", "Invalid `GiveType` value (%s). Expected `Set` or `Add`.", sBuffer); + } else { + TrieSetCell(p, "GiveType", accountSet); + } + } + + if (json_object_has_value(instanceJson, "TrackChange", JSONBoolean)) { + TrieSetCell(p, "TrackChange", json_object_get_bool(instanceJson, "TrackChange")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnMoneyGive(const playerIndex, const Trie:p) { + rg_add_account( + playerIndex, + VipM_Params_GetInt(p, "Amount"), + VipM_Params_GetCell(p, "GiveType", AS_ADD), + VipM_Params_GetBool(p, "TrackChanges", true) + ); +} + +@OnItemsListRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Items")) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `ItemsList`."); + return IC_RET_READ_FAIL; + } + + TrieSetCell(p, "Items", Json_Object_IC_GetItems(instanceJson, "Items")); + + return IC_RET_READ_SUCCESS; +} + +@OnItemsListGive(const playerIndex, const Trie:p) { + new Array:aItems = VipM_Params_GetCell(p, "Items", Invalid_Array); + + return IC_Item_GiveArray(playerIndex, aItems) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; +} + +@OnCommandRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Command", JSONString)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Command` required for item `Command`."); + return IC_RET_READ_FAIL; + } + + new Command[128]; + json_object_get_string(instanceJson, "Command", Command, charsmax(Command)); + TrieSetString(p, "Command", Command); + + if (json_object_has_value(instanceJson, "ByServer", JSONBoolean)) { + TrieSetCell(p, "ByServer", json_object_get_bool(instanceJson, "ByServer")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnCommandGive(const playerIndex, const Trie:p) { + static Command[128]; + VipM_Params_GetStr(p, "Command", Command, charsmax(Command)); + new bool:ByServer = VipM_Params_GetBool(p, "ByServer", false); + + replace_all(Command, charsmax(Command), "{playerIndex}", IntToStr(playerIndex)); + + if (ByServer) { + server_cmd(Command); + } else { + client_cmd(playerIndex, Command); + } +} + +@OnDefuseKitGive(const playerIndex, const Trie:p) { + if (get_member(playerIndex, m_iTeam) == TEAM_CT) { + rg_give_defusekit(playerIndex); + } +} + +@OnWeaponRead(const JSON:instanceJson, const Trie:p) { + new Name[32]; + json_object_get_string(instanceJson, "Name", Name, charsmax(Name)); + + // if(get_weaponid(Name) == 0){ + // log_amx("[WARNING] Weapon `%s` not found.", Name); + // return IC_RET_READ_FAIL; + // } + + TrieSetCell(p, "GiveType", _:Json_Object_GetGiveType(instanceJson, "GiveType")); + + if (json_object_has_value(instanceJson, "BpAmmo", JSONNumber)) { + TrieSetCell(p, "BpAmmo", json_object_get_number(instanceJson, "BpAmmo")); + } + + TrieSetString(p, "Name", Name); + + return IC_RET_READ_SUCCESS; +} + +@OnWeaponGive(const playerIndex, const Trie:p) { + static WeaponName[32]; + VipM_Params_GetStr(p, "Name", WeaponName, charsmax(WeaponName)); + if (!WeaponName[0]) { + return IC_RET_GIVE_FAIL; + } + + if (!get_weaponid(WeaponName)) { + log_amx("[WARNING] Default weapon `%s` not found.", WeaponName); + return IC_RET_GIVE_FAIL; + } + + new GiveType:iGiveType = GiveType:VipM_Params_GetInt(p, "GiveType", _:GT_DROP_AND_REPLACE); + new iBpAmmo = VipM_Params_GetInt(p, "BpAmmo", -1); + + new ItemId = rg_give_item(playerIndex, WeaponName, iGiveType); + if (ItemId < 0) { + return IC_RET_GIVE_FAIL; + } + + new WeaponIdType:iWpnId = rg_get_weapon_info(WeaponName, WI_ID); + new iWpnSlot = rg_get_iteminfo(ItemId, ItemInfo_iSlot); + + if ( + iBpAmmo < 0 + && !( + iWpnSlot == 0 + || iWpnSlot == 1 + ) + ) { + return IC_RET_GIVE_SUCCESS; + } + + new def_BpAmmo = (rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS)); + if (def_BpAmmo >= 0) { + rg_set_user_bpammo(playerIndex, iWpnId, iBpAmmo < 0 ? def_BpAmmo : iBpAmmo); + } + + return IC_RET_GIVE_SUCCESS; +} + +GiveType:Json_Object_GetGiveType(const JSON:Obj, const Key[], const bool:DotNot = false) { + new Str[32]; + json_object_get_string(Obj, Key, Str, charsmax(Str), DotNot); + return StrToGiveType(Str); +} + +GiveType:StrToGiveType(const Str[]) { + if (equali(Str, "GT_APPEND") || equali(Str, "Append") || equali(Str, "Add")) { + return GT_APPEND; + } else if (equali(Str, "GT_REPLACE") || equali(Str, "Replace")) { + return GT_REPLACE; + } else if (equali(Str, "GT_DROP_AND_REPLACE") || equali(Str, "Drop") || equali(Str, "DropAndReplace")) { + return GT_DROP_AND_REPLACE; + } else { + return GT_DROP_AND_REPLACE; + } +} + +StrToAccountSet(const Str[]) { + if (equali(Str, "Set")) { + return _:AS_SET; + } else if (equali(Str, "Add")) { + return _:AS_ADD; + } else { + return -1; + } +} + +MultUserSpeed(const playerIndex, const Float:fMultiplier) { + set_entvar(playerIndex, var_maxspeed, Float:get_entvar(playerIndex, var_maxspeed) * fMultiplier); +} diff --git a/amxmodx/scripting/IC-I-Limits.sma b/amxmodx/scripting/IC-I-Limits.sma new file mode 100644 index 0000000..53c7efd --- /dev/null +++ b/amxmodx/scripting/IC-I-Limits.sma @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include "VipM/Utils" + +public stock const PluginName[] = "[IC-I] Limits"; +public stock const PluginVersion[] = IC_VERSION; +public stock const PluginAuthor[] = "ArKaNeMaN"; +public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-pub"; +public stock const PluginDescription[] = "[ItemsController-Item] Items using limtis."; + +public IC_ItemType_OnInited() { + register_plugin(PluginName, PluginVersion, PluginAuthor); + + IC_ItemType_SimpleRegister( + .name = "If", + .onRead = "@OnIfRead", + .onGive = "@OnIfGive" + ); +} + +@OnIfRead(const JSON:instanceJson, const Trie:p) { + if (!json_object_has_value(instanceJson, "Items")) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `If`."); + return IC_RET_READ_FAIL; + } + + if (!json_object_has_value(instanceJson, "Limits")) { + Json_LogForFile(instanceJson, "ERROR", "Limits `Items` required for item `If`."); + return IC_RET_READ_FAIL; + } + + TrieSetCell(p, "Items", IC_Item_ReadArrayFromJson(json_object_get_value(instanceJson, "Items"))); + TrieSetCell(p, "ElseItems", IC_Item_ReadArrayFromJson(json_object_get_value(instanceJson, "ElseItems"))); + TrieSetCell(p, "Limits", VipM_Limits_ReadListFromJson(json_object_get_value(instanceJson, "Limits"))); + + return IC_RET_READ_SUCCESS; +} + +@OnIfGive(const playerIndex, const Trie:p) { + new Array:items = Invalid_Array; + if (VipM_Params_ExecuteLimitsList(p, "Limits", playerIndex, Limit_Exec_AND)) { + items = VipM_Params_GetArr(p, "Items"); + } else { + items = VipM_Params_GetArr(p, "ElseItems"); + } + + return IC_Item_GiveArray(playerIndex, items) + ? IC_RET_GIVE_SUCCESS + : IC_RET_GIVE_FAIL; +} diff --git a/amxmodx/scripting/VipM-I-Default.sma b/amxmodx/scripting/VipM-I-Default.sma deleted file mode 100644 index 3f53d3e..0000000 --- a/amxmodx/scripting/VipM-I-Default.sma +++ /dev/null @@ -1,497 +0,0 @@ -#include -#include -#include -#include -#include -#include "VipM/Utils" -#include "VipM/DebugMode" - -#pragma semicolon 1 -#pragma compress 1 - -public stock const PluginName[] = "[VipM][I] Default"; -public stock const PluginVersion[] = _VIPM_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = _VIPM_PLUGIN_URL; -public stock const PluginDescription[] = "[VipModular][Item] Default items."; - -new Float:g_fSpeedMult[MAX_PLAYERS + 1] = {1.0, ...}; -new Float:g_fGivenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; -new Float:g_fTakenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; - -new HookChain:g_iHook_ResetMaxSpeed_Post = INVALID_HOOKCHAIN; -new HookChain:g_iHook_TakeDamage_Pre = INVALID_HOOKCHAIN; -new HookChain:g_iHook_Spawn_Pre = INVALID_HOOKCHAIN; - -public VipM_IC_OnInitTypes() { - RegisterPluginByVars(); - - // Затычка для тех мест, где при отсутствии предметов вылезает ошибка/варн - VipM_IC_RegisterType("None"); - - VipM_IC_RegisterType("Random"); - VipM_IC_RegisterTypeEvent("Random", ItemType_OnRead, "@OnRandomRead"); - VipM_IC_RegisterTypeEvent("Random", ItemType_OnGive, "@OnRandomGive"); - - VipM_IC_RegisterType("InstantReloadAllWeapons"); - VipM_IC_RegisterTypeEvent("InstantReloadAllWeapons", ItemType_OnGive, "@OnInstantReloadAllWeaponsGive"); - - VipM_IC_RegisterType("InstantReload"); - VipM_IC_RegisterTypeEvent("InstantReload", ItemType_OnGive, "@OnInstantReloadGive"); - - VipM_IC_RegisterType("RefillBpAmmo"); - VipM_IC_RegisterTypeEvent("RefillBpAmmo", ItemType_OnGive, "@OnRefillBpAmmoGive"); - - VipM_IC_RegisterType("Speed"); - VipM_IC_RegisterTypeEvent("Speed", ItemType_OnRead, "@OnSpeedRead"); - VipM_IC_RegisterTypeEvent("Speed", ItemType_OnGive, "@OnSpeedGive"); - - VipM_IC_RegisterType("Money"); - VipM_IC_RegisterTypeEvent("Money", ItemType_OnRead, "@OnMoneyRead"); - VipM_IC_RegisterTypeEvent("Money", ItemType_OnGive, "@OnMoneyGive"); - - VipM_IC_RegisterType("Weapon"); - VipM_IC_RegisterTypeEvent("Weapon", ItemType_OnRead, "@OnWeaponRead"); - VipM_IC_RegisterTypeEvent("Weapon", ItemType_OnGive, "@OnWeaponGive"); - - VipM_IC_RegisterType("ItemsList"); - VipM_IC_RegisterTypeEvent("ItemsList", ItemType_OnRead, "@OnItemsListRead"); - VipM_IC_RegisterTypeEvent("ItemsList", ItemType_OnGive, "@OnItemsListGive"); - - VipM_IC_RegisterType("Command"); - VipM_IC_RegisterTypeEvent("Command", ItemType_OnRead, "@OnCommandRead"); - VipM_IC_RegisterTypeEvent("Command", ItemType_OnGive, "@OnCommandGive"); - - VipM_IC_RegisterType("DefuseKit"); - VipM_IC_RegisterTypeEvent("DefuseKit", ItemType_OnGive, "@OnDefuseKitGive"); - - VipM_IC_RegisterType("Health"); - VipM_IC_RegisterTypeEvent("Health", ItemType_OnRead, "@OnHealthRead"); - VipM_IC_RegisterTypeEvent("Health", ItemType_OnGive, "@OnHealthGive"); - - VipM_IC_RegisterType("DamageMult"); - VipM_IC_RegisterTypeEvent("DamageMult", ItemType_OnRead, "@OnDamageMultRead"); - VipM_IC_RegisterTypeEvent("DamageMult", ItemType_OnGive, "@OnDamageMultGive"); - - VipM_IC_RegisterType("Armor"); - VipM_IC_RegisterTypeEvent("Armor", ItemType_OnRead, "@OnArmorRead"); - VipM_IC_RegisterTypeEvent("Armor", ItemType_OnGive, "@OnArmorGive"); - - DisableHookChain(g_iHook_ResetMaxSpeed_Post = RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@OnPlayerResetSpeedPost", true)); - DisableHookChain(g_iHook_Spawn_Pre = RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawnPre", false)); - DisableHookChain(g_iHook_TakeDamage_Pre = RegisterHookChain(RG_CBasePlayer_TakeDamage, "@OnPlayerTakeDamage", false)); -} - -@OnPlayerSpawnPre(const UserId) { - g_fSpeedMult[UserId] = 1.0; - g_fGivenDmgMult[UserId] = 1.0; - g_fTakenDmgMult[UserId] = 1.0; -} - -@OnPlayerResetSpeedPost(const UserId) { - if (g_fSpeedMult[UserId] != 1.0) { - MultUserSpeed(UserId, g_fSpeedMult[UserId]); - } -} - -@OnPlayerTakeDamage(const VictimId, InflictorId, AttackerId, Float:fDamage, bitsDamageType) { - if (is_user_connected(AttackerId)) { - fDamage *= g_fGivenDmgMult[AttackerId]; - } - - if (is_user_connected(VictimId)) { - fDamage *= g_fTakenDmgMult[VictimId]; - } - - SetHookChainArg(4, ATYPE_FLOAT, fDamage); - return HC_CONTINUE; -} - -@OnDamageMultRead(const JSON:jItem, const Trie:tParams) { - TrieDeleteKey(tParams, "Name"); - - if (json_object_has_value(jItem, "Given", JSONNumber)) { - TrieSetCell(tParams, "Given", json_object_get_real(jItem, "Given")); - } - - if (json_object_has_value(jItem, "Taken", JSONNumber)) { - TrieSetCell(tParams, "Taken", json_object_get_real(jItem, "Taken")); - } - - CallOnceR(VIPM_CONTINUE); // Чтобы лишний раз не дёргать натив активации хука - - EnableHookChain(g_iHook_Spawn_Pre); - EnableHookChain(g_iHook_TakeDamage_Pre); - - return VIPM_CONTINUE; -} - -@OnDamageMultGive(const UserId, const Trie:tParams) { - g_fGivenDmgMult[UserId] = VipM_Params_GetFloat(tParams, "Given", 1.0); - g_fTakenDmgMult[UserId] = VipM_Params_GetFloat(tParams, "Taken", 1.0); -} - -@OnHealthRead(const JSON:jItem, const Trie:tParams) { - TrieDeleteKey(tParams, "Name"); - - if (!json_object_has_value(jItem, "Health", JSONNumber)) { - Json_LogForFile(jItem, "ERROR", "Param `Health` required for `Health` item."); - return VIPM_STOP; - } - TrieSetCell(tParams, "Health", json_object_get_real(jItem, "Health")); - - if (json_object_has_value(jItem, "MaxHealth", JSONNumber)) { - TrieSetCell(tParams, "MaxHealth", json_object_get_real(jItem, "MaxHealth")); - } - - if (json_object_has_value(jItem, "SetHealth", JSONBoolean)) { - TrieSetCell(tParams, "SetHealth", json_object_get_bool(jItem, "SetHealth")); - } - - return VIPM_CONTINUE; -} - -@OnHealthGive(const UserId, const Trie:tParams) { - if (VipM_Params_GetBool(tParams, "SetHealth", false)) { - set_entvar(UserId, var_health, VipM_Params_GetFloat(tParams, "Health")); - } else { - new Float:fHealth = Float:get_entvar(UserId, var_health); - new Float:fMaxHealth = VipM_Params_GetFloat(tParams, "MaxHealth", 100.0); - new Float:fAddHealth = floatclamp(VipM_Params_GetFloat(tParams, "Health"), 0.0, floatmax(0.0, fMaxHealth - fHealth)); - new Float:fMaxHealthCurrent = Float:get_entvar(UserId, var_max_health); - new bool:bNeedOverrideMaxHealth = (fHealth < fMaxHealth && fMaxHealthCurrent < fMaxHealth); - - if (bNeedOverrideMaxHealth) { - set_entvar(UserId, var_max_health, fMaxHealth); - } - - ExecuteHamB(Ham_TakeHealth, UserId, fAddHealth, DMG_GENERIC); - - if (bNeedOverrideMaxHealth) { - set_entvar(UserId, var_max_health, fMaxHealthCurrent); - } - } -} - -@OnArmorRead(const JSON:jItem, const Trie:tParams) { - TrieDeleteKey(tParams, "Name"); - - if (!json_object_has_value(jItem, "Armor", JSONNumber)) { - Json_LogForFile(jItem, "ERROR", "Param `Armor` required for `Armor` item."); - return VIPM_STOP; - } - TrieSetCell(tParams, "Armor", json_object_get_number(jItem, "Armor")); - - if (json_object_has_value(jItem, "MaxArmor", JSONNumber)) { - TrieSetCell(tParams, "MaxArmor", json_object_get_number(jItem, "MaxArmor")); - } - - if (json_object_has_value(jItem, "SetArmor", JSONBoolean)) { - TrieSetCell(tParams, "SetArmor", json_object_get_bool(jItem, "SetArmor")); - } - - if (json_object_has_value(jItem, "Helmet", JSONBoolean)) { - TrieSetCell(tParams, "Helmet", json_object_get_bool(jItem, "Helmet")); - } - - return VIPM_CONTINUE; -} - -@OnArmorGive(const UserId, const Trie:tParams) { - if (VipM_Params_GetBool(tParams, "SetArmor", false)) { - rg_set_user_armor(UserId, VipM_Params_GetInt(tParams, "Armor"), VipM_Params_GetBool(tParams, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); - } else { - new iSetArmor = min(rg_get_user_armor(UserId) + VipM_Params_GetInt(tParams, "Armor"), VipM_Params_GetInt(tParams, "MaxArmor", 100)); - - rg_set_user_armor(UserId, iSetArmor, VipM_Params_GetBool(tParams, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); - } -} - -@OnRandomRead(const JSON:jItem, const Trie:tParams) { - TrieDeleteKey(tParams, "Name"); - - // TODO: Сделать как-то разные шансы - if (!json_object_has_value(jItem, "Items")) { - Json_LogForFile(jItem, "ERROR", "Param `Items` required for item `Random`."); - return VIPM_STOP; - } - - new Array:aItems = VipM_IC_JsonGetItems(json_object_get_value(jItem, "Items")); - if (ArraySizeSafe(aItems) <= 1) { - Json_LogForFile(jItem, "ERROR", "Param `Items` must have >1 items."); - ArrayDestroy(aItems); - return VIPM_STOP; - } - - TrieSetCell(tParams, "Items", aItems); - - return VIPM_CONTINUE; -} - -@OnRandomGive(const UserId, const Trie:tParams) { - new Array:aItems = VipM_Params_GetArr(tParams, "Items"); - new iRandomIndex = random_num(0, ArraySizeSafe(aItems) - 1); - new VipM_IC_T_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); - - return VipM_IC_GiveItem(UserId, iRandomItem) ? VIPM_CONTINUE : VIPM_STOP; -} - -@OnInstantReloadGive(const UserId, const Trie:Params) { - InstantReloadActiveWeapon(UserId); - - return VIPM_CONTINUE; -} - -@OnInstantReloadAllWeaponsGive(const UserId, const Trie:Params) { - InstantReloadAllWeapons(UserId); - - return VIPM_CONTINUE; -} - -@OnRefillBpAmmoGive(const UserId, const Trie:Params) { - new iMaxAmmos[32] = {-1, ...}; - - // Получение дефолтных значений - for (new WeaponIdType:iWpnId = WEAPON_P228; iWpnId < WEAPON_P90; iWpnId++) { - switch (iWpnId) { - case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: - iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = -1; - default: - iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS); - } - } - - // Получение актуальных значений исходя из пушек в инвентаре - for (new InventorySlotType:iSlot = PRIMARY_WEAPON_SLOT; iSlot <= PISTOL_SLOT; iSlot++) { - new ItemId = get_member(UserId, m_rgpPlayerItems, iSlot); - while (ItemId > 0 && !is_nullent(ItemId)) { - new iAmmoType = get_member(ItemId, m_Weapon_iPrimaryAmmoType); - if (iAmmoType >= 0) { - iMaxAmmos[iAmmoType] = max(iMaxAmmos[iAmmoType], rg_get_iteminfo(ItemId, ItemInfo_iMaxAmmo1)); - } - ItemId = get_member(ItemId, m_pNext); - } - } - - for (new iAmmoType = 0; iAmmoType < 32; iAmmoType++) { - if (iMaxAmmos[iAmmoType] >= 0) { - set_member(UserId, m_rgAmmo, iMaxAmmos[iAmmoType], iAmmoType); - } - } - - return VIPM_CONTINUE; -} - -@OnSpeedRead(const JSON:jItem, const Trie:Params) { - TrieDeleteKey(Params, "Name"); - - if (!json_object_has_value(jItem, "Multiplier", JSONNumber)) { - Json_LogForFile(jItem, "ERROR", "Param `Multiplier` required for item `Speed`."); - return VIPM_STOP; - } - TrieSetCell(Params, "Multiplier", json_object_get_real(jItem, "Multiplier")); - - CallOnceR(VIPM_CONTINUE); // Чтобы лишний раз не дёргать натив активации хука - - EnableHookChain(g_iHook_Spawn_Pre); - EnableHookChain(g_iHook_ResetMaxSpeed_Post); - - return VIPM_CONTINUE; -} - -@OnSpeedGive(const UserId, const Trie:Params) { - g_fSpeedMult[UserId] = VipM_Params_GetFloat(Params, "Multiplier", 1.0); - MultUserSpeed(UserId, g_fSpeedMult[UserId]); - - return VIPM_CONTINUE; -} - -@OnMoneyRead(const JSON:jItem, const Trie:Params) { - TrieDeleteKey(Params, "Name"); - - if (!json_object_has_value(jItem, "Amount", JSONNumber)) { - Json_LogForFile(jItem, "ERROR", "Param `Amount` required for item `Money`."); - return VIPM_STOP; - } - TrieSetCell(Params, "Amount", json_object_get_number(jItem, "Amount")); - - if (json_object_has_value(jItem, "GiveType", JSONString)) { - new sBuffer[32]; - json_object_get_string(jItem, "GiveType", sBuffer, charsmax(sBuffer)); - new accountSet = StrToAccountSet(sBuffer); - if (accountSet < 0) { - Json_LogForFile(jItem, "ERROR", "Invalid `GiveType` value (%s). Expected `Set` or `Add`.", sBuffer); - } else { - TrieSetCell(Params, "GiveType", accountSet); - } - } - - if (json_object_has_value(jItem, "TrackChange", JSONBoolean)) { - TrieSetCell(Params, "TrackChange", json_object_get_bool(jItem, "TrackChange")); - } - - return VIPM_CONTINUE; -} - -@OnMoneyGive(const UserId, const Trie:Params) { - rg_add_account( - UserId, - VipM_Params_GetInt(Params, "Amount"), - VipM_Params_GetCell(Params, "GiveType", AS_ADD), - VipM_Params_GetBool(Params, "TrackChanges", true) - ); - return VIPM_CONTINUE; -} - -@OnItemsListRead(const JSON:jItem, const Trie:Params) { - TrieDeleteKey(Params, "Name"); - - if (!json_object_has_value(jItem, "Items")) { - Json_LogForFile(jItem, "ERROR", "Param `Items` required for item `ItemsList`."); - return VIPM_STOP; - } - - TrieSetCell(Params, "Items", VipM_IC_JsonGetItems(json_object_get_value(jItem, "Items"))); - - return VIPM_CONTINUE; -} - -@OnItemsListGive(const UserId, const Trie:Params) { - new Array:aItems = VipM_Params_GetCell(Params, "Items", Invalid_Array); - - return VipM_IC_GiveItems(UserId, aItems) ? VIPM_CONTINUE : VIPM_STOP; -} - -@OnCommandRead(const JSON:jItem, const Trie:Params) { - TrieDeleteKey(Params, "Name"); - - if (!json_object_has_value(jItem, "Command", JSONString)) { - Json_LogForFile(jItem, "ERROR", "Param `Command` required for item `Command`."); - return VIPM_STOP; - } - - new Command[128]; - json_object_get_string(jItem, "Command", Command, charsmax(Command)); - TrieSetString(Params, "Command", Command); - - if (json_object_has_value(jItem, "ByServer", JSONBoolean)) { - TrieSetCell(Params, "ByServer", json_object_get_bool(jItem, "ByServer")); - } - - return VIPM_CONTINUE; -} - -@OnCommandGive(const UserId, const Trie:Params) { - static Command[128]; - VipM_Params_GetStr(Params, "Command", Command, charsmax(Command)); - new bool:ByServer = VipM_Params_GetBool(Params, "ByServer", false); - - replace_all(Command, charsmax(Command), "{UserId}", IntToStr(UserId)); - - if (ByServer) { - server_cmd(Command); - } else { - client_cmd(UserId, Command); - } -} - -@OnDefuseKitGive(const UserId, const Trie:Params) { - if (get_member(UserId, m_iTeam) == TEAM_CT) { - rg_give_defusekit(UserId); - } - - return VIPM_CONTINUE; -} - -@OnWeaponRead(const JSON:jItem, const Trie:Params) { - new Name[32]; - json_object_get_string(jItem, "Name", Name, charsmax(Name)); - - // if(get_weaponid(Name) == 0){ - // log_amx("[WARNING] Weapon `%s` not found.", Name); - // return VIPM_STOP; - // } - - TrieSetCell(Params, "GiveType", _:Json_Object_GetGiveType(jItem, "GiveType")); - - if (json_object_has_value(jItem, "BpAmmo", JSONNumber)) { - TrieSetCell(Params, "BpAmmo", json_object_get_number(jItem, "BpAmmo")); - } - - TrieSetString(Params, "Name", Name); - - return VIPM_CONTINUE; -} - -@OnWeaponGive(const UserId, const Trie:Params) { - static WeaponName[32]; - VipM_Params_GetStr(Params, "Name", WeaponName, charsmax(WeaponName)); - if (!WeaponName[0]) { - return VIPM_STOP; - } - - if (!get_weaponid(WeaponName)) { - log_amx("[WARNING] Default weapon `%s` not found.", WeaponName); - return VIPM_STOP; - } - - new GiveType:iGiveType = GiveType:VipM_Params_GetInt(Params, "GiveType", _:GT_DROP_AND_REPLACE); - new iBpAmmo = VipM_Params_GetInt(Params, "BpAmmo", -1); - - new ItemId = rg_give_item(UserId, WeaponName, iGiveType); - if (ItemId < 0) { - return VIPM_STOP; - } - - new WeaponIdType:iWpnId = rg_get_weapon_info(WeaponName, WI_ID); - new iWpnSlot = rg_get_iteminfo(ItemId, ItemInfo_iSlot); - - if ( - iBpAmmo < 0 - && !( - iWpnSlot == 0 - || iWpnSlot == 1 - ) - ) { - return VIPM_CONTINUE; - } - - new def_BpAmmo = (rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS)); - if (def_BpAmmo >= 0) { - rg_set_user_bpammo(UserId, iWpnId, iBpAmmo < 0 ? def_BpAmmo : iBpAmmo); - } - - return VIPM_CONTINUE; -} - -GiveType:Json_Object_GetGiveType(const JSON:Obj, const Key[], const bool:DotNot = false) { - new Str[32]; - json_object_get_string(Obj, Key, Str, charsmax(Str), DotNot); - return StrToGiveType(Str); -} - -GiveType:StrToGiveType(const Str[]) { - if (equali(Str, "GT_APPEND") || equali(Str, "Append") || equali(Str, "Add")) { - return GT_APPEND; - } else if (equali(Str, "GT_REPLACE") || equali(Str, "Replace")) { - return GT_REPLACE; - } else if (equali(Str, "GT_DROP_AND_REPLACE") || equali(Str, "Drop") || equali(Str, "DropAndReplace")) { - return GT_DROP_AND_REPLACE; - } else { - return GT_DROP_AND_REPLACE; - } -} - -StrToAccountSet(const Str[]) { - if (equali(Str, "Set")) { - return _:AS_SET; - } else if (equali(Str, "Add")) { - return _:AS_ADD; - } else { - return -1; - } -} - -MultUserSpeed(const UserId, const Float:fMultiplier) { - set_entvar(UserId, var_maxspeed, Float:get_entvar(UserId, var_maxspeed) * fMultiplier); -} diff --git a/amxmodx/scripting/VipM-I-Limits.sma b/amxmodx/scripting/VipM-I-Limits.sma deleted file mode 100644 index 4b3802f..0000000 --- a/amxmodx/scripting/VipM-I-Limits.sma +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include "VipM/Utils" - -#pragma semicolon 1 -#pragma compress 1 - -public stock const PluginName[] = "[VipM-I] Limits"; -public stock const PluginVersion[] = _VIPM_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = _VIPM_PLUGIN_URL; -public stock const PluginDescription[] = "[VipModular-Item] Items using limtis."; - -public VipM_IC_OnInitTypes() { - RegisterPluginByVars(); - - VipM_IC_RegisterType("If"); - VipM_IC_RegisterTypeEvent("If", ItemType_OnRead, "@OnIfRead"); - VipM_IC_RegisterTypeEvent("If", ItemType_OnGive, "@OnIfGive"); -} - -@OnIfRead(const JSON:jItem, const Trie:tParams) { - TrieDeleteKey(tParams, "Name"); - - if (!json_object_has_value(jItem, "Items")) { - Json_LogForFile(jItem, "ERROR", "Param `Items` required for item `If`."); - return VIPM_STOP; - } - - if (!json_object_has_value(jItem, "Limits")) { - Json_LogForFile(jItem, "ERROR", "Limits `Items` required for item `If`."); - return VIPM_STOP; - } - - TrieSetCell(tParams, "Items", VipM_IC_JsonGetItems(json_object_get_value(jItem, "Items"))); - TrieSetCell(tParams, "ElseItems", VipM_IC_JsonGetItems(json_object_get_value(jItem, "ElseItems"))); - TrieSetCell(tParams, "Limits", VipM_Limits_ReadListFromJson(json_object_get_value(jItem, "Limits"))); - - return VIPM_CONTINUE; -} - -@OnIfGive(const UserId, const Trie:tParams) { - if (VipM_Params_ExecuteLimitsList(tParams, "Limits", UserId, Limit_Exec_AND)) { - VipM_IC_GiveItems(UserId, VipM_Params_GetArr(tParams, "Items")); - return VIPM_CONTINUE; - } - - new Array:aElseItems = VipM_Params_GetArr(tParams, "ElseItems"); - if (ArraySizeSafe(aElseItems)) { - VipM_IC_GiveItems(UserId, aElseItems); - return VIPM_CONTINUE; - } - - return VIPM_STOP; -} diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 7b6e0c0..c570a78 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -332,11 +332,11 @@ stock bool:VipM_IC_GiveItems(const UserId, const Array:aItems) { } stock bool:VipM_Params_GiveItems(const UserId, const Trie:tParams, const sParam[]) { - return VipM_IC_GiveItems(UserId, VipM_Params_GetArr(tParams, sParam)); + return IC_Item_GiveArray(UserId, VipM_Params_GetArr(tParams, sParam)); } stock bool:VipM_Params_GiveItem(const UserId, const Trie:tParams, const sParam[]) { - return VipM_IC_GiveItems(UserId, VipM_Params_GetCell(tParams, sParam)); + return IC_Item_Give(UserId, VipM_Params_GetCell(tParams, sParam)); } #pragma deprecated Use Json_Object_IC_GetItems() instead. From a0a74abba03b304c6d920ce78e5f5d0fbdbe7185 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 22:51:33 +0300 Subject: [PATCH 019/108] Refactor default item types bundle --- amxmodx/scripting/IC-I-Default.sma | 511 ------------------ amxmodx/scripting/ItemsController.sma | 2 + .../DefaultObjects/ItemType/Armor.inc | 46 ++ .../DefaultObjects/ItemType/Command.inc | 45 ++ .../DefaultObjects/ItemType/DamageMult.inc | 64 +++ .../DefaultObjects/ItemType/DefuseKit.inc | 17 + .../DefaultObjects/ItemType/Health.inc | 55 ++ .../DefaultObjects/ItemType/InstantReload.inc | 15 + .../ItemType/InstantReloadAllWeapons.inc | 15 + .../DefaultObjects/ItemType/ItemsList.inc | 31 ++ .../DefaultObjects/ItemType/Money.inc | 58 ++ .../DefaultObjects/ItemType/Random.inc | 41 ++ .../DefaultObjects/ItemType/RefillBpAmmo.inc | 43 ++ .../DefaultObjects/ItemType/Speed.inc | 55 ++ .../DefaultObjects/ItemType/Weapon.inc | 91 ++++ .../DefaultObjects/Regsitrar.inc | 34 ++ 16 files changed, 612 insertions(+), 511 deletions(-) delete mode 100644 amxmodx/scripting/IC-I-Default.sma create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DefuseKit.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReload.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReloadAllWeapons.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/RefillBpAmmo.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc diff --git a/amxmodx/scripting/IC-I-Default.sma b/amxmodx/scripting/IC-I-Default.sma deleted file mode 100644 index 01dadfa..0000000 --- a/amxmodx/scripting/IC-I-Default.sma +++ /dev/null @@ -1,511 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "VipM/Utils" - -public stock const PluginName[] = "[IC-I] Default"; -public stock const PluginVersion[] = IC_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-pub"; -public stock const PluginDescription[] = "[ItemsController-Item] Default items."; - -new Float:g_fSpeedMult[MAX_PLAYERS + 1] = {1.0, ...}; -new Float:g_fGivenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; -new Float:g_fTakenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; - -new HookChain:g_iHook_ResetMaxSpeed_Post = INVALID_HOOKCHAIN; -new HookChain:g_iHook_TakeDamage_Pre = INVALID_HOOKCHAIN; -new HookChain:g_iHook_Spawn_Pre = INVALID_HOOKCHAIN; - -public IC_ItemType_OnInited() { - register_plugin(PluginName, PluginVersion, PluginAuthor); - - // Затычка для тех мест, где при отсутствии предметов выоезает ошибка/варн - IC_ItemType_SimpleRegister( - .name = "None" - ); - - IC_ItemType_SimpleRegister( - .name = "Random", - .onRead = "@OnRandomRead", - .onGive = "@OnRandomGive" - ); - - IC_ItemType_SimpleRegister( - .name = "InstantReloadAllWeapons", - .onGive = "@OnInstantReloadAllWeaponsGive" - ); - - IC_ItemType_SimpleRegister( - .name = "InstantReload", - .onGive = "@OnInstantReloadGive" - ); - - IC_ItemType_SimpleRegister( - .name = "RefillBpAmmo", - .onGive = "@OnRefillBpAmmoGive" - ); - - IC_ItemType_SimpleRegister( - .name = "Speed", - .onRead = "@OnSpeedRead", - .onGive = "@OnSpeedGive" - ); - - IC_ItemType_SimpleRegister( - .name = "Money", - .onRead = "@OnMoneyRead", - .onGive = "@OnMoneyGive" - ); - - IC_ItemType_SimpleRegister( - .name = "Weapon", - .onRead = "@OnWeaponRead", - .onGive = "@OnWeaponGive" - ); - - IC_ItemType_SimpleRegister( - .name = "ItemsList", - .onRead = "@OnItemsListRead", - .onGive = "@OnItemsListGive" - ); - - IC_ItemType_SimpleRegister( - .name = "Command", - .onRead = "@OnCommandRead", - .onGive = "@OnCommandGive" - ); - - IC_ItemType_SimpleRegister( - .name = "DefuseKit", - .onGive = "@OnDefuseKitGive" - ); - - IC_ItemType_SimpleRegister( - .name = "Health", - .onRead = "@OnHealthRead", - .onGive = "@OnHealthGive" - ); - - IC_ItemType_SimpleRegister( - .name = "DamageMult", - .onRead = "@OnDamageMultRead", - .onGive = "@OnDamageMultGive" - ); - - IC_ItemType_SimpleRegister( - .name = "Armor", - .onRead = "@OnArmorRead", - .onGive = "@OnArmorGive" - ); - - DisableHookChain(g_iHook_ResetMaxSpeed_Post = RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@OnPlayerResetSpeedPost", true)); - DisableHookChain(g_iHook_Spawn_Pre = RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawnPre", false)); - DisableHookChain(g_iHook_TakeDamage_Pre = RegisterHookChain(RG_CBasePlayer_TakeDamage, "@OnPlayerTakeDamage", false)); -} - -@OnPlayerSpawnPre(const playerIndex) { - g_fSpeedMult[playerIndex] = 1.0; - g_fGivenDmgMult[playerIndex] = 1.0; - g_fTakenDmgMult[playerIndex] = 1.0; -} - -@OnPlayerResetSpeedPost(const playerIndex) { - if (g_fSpeedMult[playerIndex] != 1.0) { - MultUserSpeed(playerIndex, g_fSpeedMult[playerIndex]); - } -} - -@OnPlayerTakeDamage(const victimIndex, inflictorIndex, attackerInde, Float:damage, damageType) { - if (is_user_connected(attackerInde)) { - damage *= g_fGivenDmgMult[attackerInde]; - } - - if (is_user_connected(victimIndex)) { - damage *= g_fTakenDmgMult[victimIndex]; - } - - SetHookChainArg(4, ATYPE_FLOAT, damage); - return HC_CONTINUE; -} - -@OnDamageMultRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (json_object_has_value(instanceJson, "Given", JSONNumber)) { - TrieSetCell(p, "Given", json_object_get_real(instanceJson, "Given")); - } - - if (json_object_has_value(instanceJson, "Taken", JSONNumber)) { - TrieSetCell(p, "Taken", json_object_get_real(instanceJson, "Taken")); - } - - CallOnceR(IC_RET_READ_SUCCESS); // Чтобы лишний раз не дёргать натив активации хука - - EnableHookChain(g_iHook_Spawn_Pre); - EnableHookChain(g_iHook_TakeDamage_Pre); - - return IC_RET_READ_SUCCESS; -} - -@OnDamageMultGive(const playerIndex, const Trie:p) { - g_fGivenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Given", 1.0); - g_fTakenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Taken", 1.0); -} - -@OnHealthRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Health", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Health` required for `Health` item."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Health", json_object_get_real(instanceJson, "Health")); - - if (json_object_has_value(instanceJson, "MaxHealth", JSONNumber)) { - TrieSetCell(p, "MaxHealth", json_object_get_real(instanceJson, "MaxHealth")); - } - - if (json_object_has_value(instanceJson, "SetHealth", JSONBoolean)) { - TrieSetCell(p, "SetHealth", json_object_get_bool(instanceJson, "SetHealth")); - } - - return IC_RET_READ_SUCCESS; -} - -@OnHealthGive(const playerIndex, const Trie:p) { - if (VipM_Params_GetBool(p, "SetHealth", false)) { - set_entvar(playerIndex, var_health, VipM_Params_GetFloat(p, "Health")); - } else { - new Float:fHealth = Float:get_entvar(playerIndex, var_health); - new Float:fMaxHealth = VipM_Params_GetFloat(p, "MaxHealth", 100.0); - new Float:fAddHealth = floatclamp(VipM_Params_GetFloat(p, "Health"), 0.0, floatmax(0.0, fMaxHealth - fHealth)); - new Float:fMaxHealthCurrent = Float:get_entvar(playerIndex, var_max_health); - new bool:bNeedOverrideMaxHealth = (fHealth < fMaxHealth && fMaxHealthCurrent < fMaxHealth); - - if (bNeedOverrideMaxHealth) { - set_entvar(playerIndex, var_max_health, fMaxHealth); - } - - ExecuteHamB(Ham_TakeHealth, playerIndex, fAddHealth, DMG_GENERIC); - - if (bNeedOverrideMaxHealth) { - set_entvar(playerIndex, var_max_health, fMaxHealthCurrent); - } - } -} - -@OnArmorRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Armor", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Armor` required for `Armor` item."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Armor", json_object_get_number(instanceJson, "Armor")); - - if (json_object_has_value(instanceJson, "MaxArmor", JSONNumber)) { - TrieSetCell(p, "MaxArmor", json_object_get_number(instanceJson, "MaxArmor")); - } - - if (json_object_has_value(instanceJson, "SetArmor", JSONBoolean)) { - TrieSetCell(p, "SetArmor", json_object_get_bool(instanceJson, "SetArmor")); - } - - if (json_object_has_value(instanceJson, "Helmet", JSONBoolean)) { - TrieSetCell(p, "Helmet", json_object_get_bool(instanceJson, "Helmet")); - } - - return IC_RET_READ_SUCCESS; -} - -@OnArmorGive(const playerIndex, const Trie:p) { - if (VipM_Params_GetBool(p, "SetArmor", false)) { - rg_set_user_armor(playerIndex, VipM_Params_GetInt(p, "Armor"), VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); - } else { - new iSetArmor = min(rg_get_user_armor(playerIndex) + VipM_Params_GetInt(p, "Armor"), VipM_Params_GetInt(p, "MaxArmor", 100)); - - rg_set_user_armor(playerIndex, iSetArmor, VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); - } -} - -@OnRandomRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - // TODO: Сделать как-то разные шансы - if (!json_object_has_value(instanceJson, "Items")) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `Random`."); - return IC_RET_READ_FAIL; - } - - new Array:aItems = Json_Object_IC_GetItems(instanceJson, "Items"); - if (ArraySizeSafe(aItems) <= 1) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` must have >1 items."); - ArrayDestroy(aItems); - return IC_RET_READ_FAIL; - } - - TrieSetCell(p, "Items", aItems); - - return IC_RET_READ_SUCCESS; -} - -@OnRandomGive(const playerIndex, const Trie:p) { - new Array:aItems = VipM_Params_GetArr(p, "Items"); - new iRandomIndex = random_num(0, ArraySizeSafe(aItems) - 1); - new VipM_IC_T_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); - - return IC_Item_Give(playerIndex, iRandomItem) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; -} - -@OnInstantReloadGive(const playerIndex, const Trie:p) { - InstantReloadActiveWeapon(playerIndex); -} - -@OnInstantReloadAllWeaponsGive(const playerIndex, const Trie:p) { - InstantReloadAllWeapons(playerIndex); -} - -@OnRefillBpAmmoGive(const playerIndex, const Trie:p) { - new iMaxAmmos[32] = {-1, ...}; - - // Получение дефолтных значений - for (new WeaponIdType:iWpnId = WEAPON_P228; iWpnId < WEAPON_P90; iWpnId++) { - switch (iWpnId) { - case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: - iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = -1; - default: - iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS); - } - } - - // Получение актуальных значений исходя из пушек в инвентаре - for (new InventorySlotType:iSlot = PRIMARY_WEAPON_SLOT; iSlot <= PISTOL_SLOT; iSlot++) { - new ItemId = get_member(playerIndex, m_rgpPlayerItems, iSlot); - while (ItemId > 0 && !is_nullent(ItemId)) { - new iAmmoType = get_member(ItemId, m_Weapon_iPrimaryAmmoType); - if (iAmmoType >= 0) { - iMaxAmmos[iAmmoType] = max(iMaxAmmos[iAmmoType], rg_get_iteminfo(ItemId, ItemInfo_iMaxAmmo1)); - } - ItemId = get_member(ItemId, m_pNext); - } - } - - for (new iAmmoType = 0; iAmmoType < 32; iAmmoType++) { - if (iMaxAmmos[iAmmoType] >= 0) { - set_member(playerIndex, m_rgAmmo, iMaxAmmos[iAmmoType], iAmmoType); - } - } -} - -@OnSpeedRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Multiplier", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Multiplier` required for item `Speed`."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Multiplier", json_object_get_real(instanceJson, "Multiplier")); - - CallOnceR(IC_RET_READ_SUCCESS); // Чтобы лишний раз не дёргать натив активации хука - - EnableHookChain(g_iHook_Spawn_Pre); - EnableHookChain(g_iHook_ResetMaxSpeed_Post); - - return IC_RET_READ_SUCCESS; -} - -@OnSpeedGive(const playerIndex, const Trie:p) { - g_fSpeedMult[playerIndex] = VipM_Params_GetFloat(p, "Multiplier", 1.0); - MultUserSpeed(playerIndex, g_fSpeedMult[playerIndex]); -} - -@OnMoneyRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Amount", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Amount` required for item `Money`."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Amount", json_object_get_number(instanceJson, "Amount")); - - if (json_object_has_value(instanceJson, "GiveType", JSONString)) { - new sBuffer[32]; - json_object_get_string(instanceJson, "GiveType", sBuffer, charsmax(sBuffer)); - new accountSet = StrToAccountSet(sBuffer); - if (accountSet < 0) { - Json_LogForFile(instanceJson, "ERROR", "Invalid `GiveType` value (%s). Expected `Set` or `Add`.", sBuffer); - } else { - TrieSetCell(p, "GiveType", accountSet); - } - } - - if (json_object_has_value(instanceJson, "TrackChange", JSONBoolean)) { - TrieSetCell(p, "TrackChange", json_object_get_bool(instanceJson, "TrackChange")); - } - - return IC_RET_READ_SUCCESS; -} - -@OnMoneyGive(const playerIndex, const Trie:p) { - rg_add_account( - playerIndex, - VipM_Params_GetInt(p, "Amount"), - VipM_Params_GetCell(p, "GiveType", AS_ADD), - VipM_Params_GetBool(p, "TrackChanges", true) - ); -} - -@OnItemsListRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Items")) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `ItemsList`."); - return IC_RET_READ_FAIL; - } - - TrieSetCell(p, "Items", Json_Object_IC_GetItems(instanceJson, "Items")); - - return IC_RET_READ_SUCCESS; -} - -@OnItemsListGive(const playerIndex, const Trie:p) { - new Array:aItems = VipM_Params_GetCell(p, "Items", Invalid_Array); - - return IC_Item_GiveArray(playerIndex, aItems) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; -} - -@OnCommandRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Command", JSONString)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Command` required for item `Command`."); - return IC_RET_READ_FAIL; - } - - new Command[128]; - json_object_get_string(instanceJson, "Command", Command, charsmax(Command)); - TrieSetString(p, "Command", Command); - - if (json_object_has_value(instanceJson, "ByServer", JSONBoolean)) { - TrieSetCell(p, "ByServer", json_object_get_bool(instanceJson, "ByServer")); - } - - return IC_RET_READ_SUCCESS; -} - -@OnCommandGive(const playerIndex, const Trie:p) { - static Command[128]; - VipM_Params_GetStr(p, "Command", Command, charsmax(Command)); - new bool:ByServer = VipM_Params_GetBool(p, "ByServer", false); - - replace_all(Command, charsmax(Command), "{playerIndex}", IntToStr(playerIndex)); - - if (ByServer) { - server_cmd(Command); - } else { - client_cmd(playerIndex, Command); - } -} - -@OnDefuseKitGive(const playerIndex, const Trie:p) { - if (get_member(playerIndex, m_iTeam) == TEAM_CT) { - rg_give_defusekit(playerIndex); - } -} - -@OnWeaponRead(const JSON:instanceJson, const Trie:p) { - new Name[32]; - json_object_get_string(instanceJson, "Name", Name, charsmax(Name)); - - // if(get_weaponid(Name) == 0){ - // log_amx("[WARNING] Weapon `%s` not found.", Name); - // return IC_RET_READ_FAIL; - // } - - TrieSetCell(p, "GiveType", _:Json_Object_GetGiveType(instanceJson, "GiveType")); - - if (json_object_has_value(instanceJson, "BpAmmo", JSONNumber)) { - TrieSetCell(p, "BpAmmo", json_object_get_number(instanceJson, "BpAmmo")); - } - - TrieSetString(p, "Name", Name); - - return IC_RET_READ_SUCCESS; -} - -@OnWeaponGive(const playerIndex, const Trie:p) { - static WeaponName[32]; - VipM_Params_GetStr(p, "Name", WeaponName, charsmax(WeaponName)); - if (!WeaponName[0]) { - return IC_RET_GIVE_FAIL; - } - - if (!get_weaponid(WeaponName)) { - log_amx("[WARNING] Default weapon `%s` not found.", WeaponName); - return IC_RET_GIVE_FAIL; - } - - new GiveType:iGiveType = GiveType:VipM_Params_GetInt(p, "GiveType", _:GT_DROP_AND_REPLACE); - new iBpAmmo = VipM_Params_GetInt(p, "BpAmmo", -1); - - new ItemId = rg_give_item(playerIndex, WeaponName, iGiveType); - if (ItemId < 0) { - return IC_RET_GIVE_FAIL; - } - - new WeaponIdType:iWpnId = rg_get_weapon_info(WeaponName, WI_ID); - new iWpnSlot = rg_get_iteminfo(ItemId, ItemInfo_iSlot); - - if ( - iBpAmmo < 0 - && !( - iWpnSlot == 0 - || iWpnSlot == 1 - ) - ) { - return IC_RET_GIVE_SUCCESS; - } - - new def_BpAmmo = (rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS)); - if (def_BpAmmo >= 0) { - rg_set_user_bpammo(playerIndex, iWpnId, iBpAmmo < 0 ? def_BpAmmo : iBpAmmo); - } - - return IC_RET_GIVE_SUCCESS; -} - -GiveType:Json_Object_GetGiveType(const JSON:Obj, const Key[], const bool:DotNot = false) { - new Str[32]; - json_object_get_string(Obj, Key, Str, charsmax(Str), DotNot); - return StrToGiveType(Str); -} - -GiveType:StrToGiveType(const Str[]) { - if (equali(Str, "GT_APPEND") || equali(Str, "Append") || equali(Str, "Add")) { - return GT_APPEND; - } else if (equali(Str, "GT_REPLACE") || equali(Str, "Replace")) { - return GT_REPLACE; - } else if (equali(Str, "GT_DROP_AND_REPLACE") || equali(Str, "Drop") || equali(Str, "DropAndReplace")) { - return GT_DROP_AND_REPLACE; - } else { - return GT_DROP_AND_REPLACE; - } -} - -StrToAccountSet(const Str[]) { - if (equali(Str, "Set")) { - return _:AS_SET; - } else if (equali(Str, "Add")) { - return _:AS_ADD; - } else { - return -1; - } -} - -MultUserSpeed(const playerIndex, const Float:fMultiplier) { - set_entvar(playerIndex, var_maxspeed, Float:get_entvar(playerIndex, var_maxspeed) * fMultiplier); -} diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index 6d18684..642a0ef 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -10,6 +10,7 @@ public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-p public stock const PluginDescription[] = "Unified interface for items giving."; #include "ItemsController/Objects/Items/Instance" +#include "ItemsController/DefaultObjects/Regsitrar" public plugin_precache() { PluginInit(); @@ -24,6 +25,7 @@ PluginInit() { Forwards_Init(); ItemInstance_Init(); + DefaultObjects_RegisterAll(); Forwards_RegAndCall("VipM_IC_OnInitTypes", ET_IGNORE); // deprecated } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc new file mode 100644 index 0000000..65bbadd --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_Armor_Register() { + IC_ItemType_SimpleRegister( + .name = "Armor", + .onRead = "@OnArmorRead", + .onGive = "@OnArmorGive" + ); +} + +@OnArmorRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Armor", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Armor` required for `Armor` item."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Armor", json_object_get_number(instanceJson, "Armor")); + + if (json_object_has_value(instanceJson, "MaxArmor", JSONNumber)) { + TrieSetCell(p, "MaxArmor", json_object_get_number(instanceJson, "MaxArmor")); + } + + if (json_object_has_value(instanceJson, "SetArmor", JSONBoolean)) { + TrieSetCell(p, "SetArmor", json_object_get_bool(instanceJson, "SetArmor")); + } + + if (json_object_has_value(instanceJson, "Helmet", JSONBoolean)) { + TrieSetCell(p, "Helmet", json_object_get_bool(instanceJson, "Helmet")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnArmorGive(const playerIndex, const Trie:p) { + if (VipM_Params_GetBool(p, "SetArmor", false)) { + rg_set_user_armor(playerIndex, VipM_Params_GetInt(p, "Armor"), VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + } else { + new iSetArmor = min(rg_get_user_armor(playerIndex) + VipM_Params_GetInt(p, "Armor"), VipM_Params_GetInt(p, "MaxArmor", 100)); + + rg_set_user_armor(playerIndex, iSetArmor, VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc new file mode 100644 index 0000000..bccba53 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_Command_Register() { + IC_ItemType_SimpleRegister( + .name = "Command", + .onRead = "@OnCommandRead", + .onGive = "@OnCommandGive" + ); +} + +@OnCommandRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Command", JSONString)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Command` required for item `Command`."); + return IC_RET_READ_FAIL; + } + + new Command[128]; + json_object_get_string(instanceJson, "Command", Command, charsmax(Command)); + TrieSetString(p, "Command", Command); + + if (json_object_has_value(instanceJson, "ByServer", JSONBoolean)) { + TrieSetCell(p, "ByServer", json_object_get_bool(instanceJson, "ByServer")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnCommandGive(const playerIndex, const Trie:p) { + static Command[128]; + VipM_Params_GetStr(p, "Command", Command, charsmax(Command)); + new bool:ByServer = VipM_Params_GetBool(p, "ByServer", false); + + replace_all(Command, charsmax(Command), "{playerIndex}", IntToStr(playerIndex)); + + if (ByServer) { + server_cmd(Command); + } else { + client_cmd(playerIndex, Command); + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc new file mode 100644 index 0000000..3070949 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include // Для VipM_Params_* // TODO: уйти на аналог от контроллера параметров, когда он будет + +static HookChain:PlayerSpawnPreHookChain = INVALID_HOOKCHAIN; +static HookChain:PlayerTakeDamagePreHookChain = INVALID_HOOKCHAIN; + +static Float:PlayerGivenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; +static Float:PlayerTakenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; + +DefaultObjects_ItemType_DamageMult_Register() { + IC_ItemType_SimpleRegister( + .name = "DamageMult", + .onRead = "@ItemType_DamageMult_OnRead", + .onGive = "@ItemType_DamageMult_OnGive" + ); + + DisableHookChain(PlayerSpawnPreHookChain = RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_DamageMult_OnPlayerSpawnPre", false)); + DisableHookChain(PlayerTakeDamagePreHookChain = RegisterHookChain(RG_CBasePlayer_TakeDamage, "@ItemType_DamageMult_OnPlayerTakeDamage", false)); +} + +@ItemType_DamageMult_OnRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (json_object_has_value(instanceJson, "Given", JSONNumber)) { + TrieSetCell(p, "Given", json_object_get_real(instanceJson, "Given")); + } + + if (json_object_has_value(instanceJson, "Taken", JSONNumber)) { + TrieSetCell(p, "Taken", json_object_get_real(instanceJson, "Taken")); + } + + CallOnceR(IC_RET_READ_SUCCESS); // Чтобы лишний раз не дёргать натив активации хука + + EnableHookChain(PlayerSpawnPreHookChain); + EnableHookChain(PlayerTakeDamagePreHookChain); + + return IC_RET_READ_SUCCESS; +} + +@ItemType_DamageMult_OnGive(const playerIndex, const Trie:p) { + PlayerGivenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Given", 1.0); + PlayerTakenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Taken", 1.0); +} + +@ItemType_DamageMult_OnPlayerSpawnPre(const playerIndex) { + PlayerGivenDmgMult[playerIndex] = 1.0; + PlayerTakenDmgMult[playerIndex] = 1.0; +} + +@ItemType_DamageMult_OnPlayerTakeDamage(const victimIndex, inflictorIndex, attackerInde, Float:damage, damageType) { + if (is_user_connected(attackerInde)) { + damage *= PlayerGivenDmgMult[attackerInde]; + } + + if (is_user_connected(victimIndex)) { + damage *= PlayerTakenDmgMult[victimIndex]; + } + + SetHookChainArg(4, ATYPE_FLOAT, damage); + return HC_CONTINUE; +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DefuseKit.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DefuseKit.inc new file mode 100644 index 0000000..010c297 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DefuseKit.inc @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_DefuseKit_Register() { + IC_ItemType_SimpleRegister( + .name = "DefuseKit", + .onGive = "@OnDefuseKitGive" + ); +} + +@OnDefuseKitGive(const playerIndex, const Trie:p) { + if (get_member(playerIndex, m_iTeam) == TEAM_CT) { + rg_give_defusekit(playerIndex); + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc new file mode 100644 index 0000000..bb41aee --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +DefaultObjects_ItemType_Health_Register() { + IC_ItemType_SimpleRegister( + .name = "Health", + .onRead = "@OnHealthRead", + .onGive = "@OnHealthGive" + ); +} + +@OnHealthRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Health", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Health` required for `Health` item."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Health", json_object_get_real(instanceJson, "Health")); + + if (json_object_has_value(instanceJson, "MaxHealth", JSONNumber)) { + TrieSetCell(p, "MaxHealth", json_object_get_real(instanceJson, "MaxHealth")); + } + + if (json_object_has_value(instanceJson, "SetHealth", JSONBoolean)) { + TrieSetCell(p, "SetHealth", json_object_get_bool(instanceJson, "SetHealth")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnHealthGive(const playerIndex, const Trie:p) { + if (VipM_Params_GetBool(p, "SetHealth", false)) { + set_entvar(playerIndex, var_health, VipM_Params_GetFloat(p, "Health")); + } else { + new Float:fHealth = Float:get_entvar(playerIndex, var_health); + new Float:fMaxHealth = VipM_Params_GetFloat(p, "MaxHealth", 100.0); + new Float:fAddHealth = floatclamp(VipM_Params_GetFloat(p, "Health"), 0.0, floatmax(0.0, fMaxHealth - fHealth)); + new Float:fMaxHealthCurrent = Float:get_entvar(playerIndex, var_max_health); + new bool:bNeedOverrideMaxHealth = (fHealth < fMaxHealth && fMaxHealthCurrent < fMaxHealth); + + if (bNeedOverrideMaxHealth) { + set_entvar(playerIndex, var_max_health, fMaxHealth); + } + + ExecuteHamB(Ham_TakeHealth, playerIndex, fAddHealth, DMG_GENERIC); + + if (bNeedOverrideMaxHealth) { + set_entvar(playerIndex, var_max_health, fMaxHealthCurrent); + } + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReload.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReload.inc new file mode 100644 index 0000000..5b52689 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReload.inc @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_InstantReload_Register() { + IC_ItemType_SimpleRegister( + .name = "InstantReload", + .onGive = "@OnInstantReloadGive" + ); +} + +@OnInstantReloadGive(const playerIndex, const Trie:p) { + InstantReloadActiveWeapon(playerIndex); +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReloadAllWeapons.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReloadAllWeapons.inc new file mode 100644 index 0000000..f7ebd10 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/InstantReloadAllWeapons.inc @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_InstantReloadAllWeapons_Register() { + IC_ItemType_SimpleRegister( + .name = "InstantReloadAllWeapons", + .onGive = "@OnInstantReloadAllWeaponsGive" + ); +} + +@OnInstantReloadAllWeaponsGive(const playerIndex, const Trie:p) { + InstantReloadAllWeapons(playerIndex); +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc new file mode 100644 index 0000000..a75406a --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_ItemsList_Register() { + IC_ItemType_SimpleRegister( + .name = "ItemsList", + .onRead = "@OnItemsListRead", + .onGive = "@OnItemsListGive" + ); +} + +@OnItemsListRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Items")) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `ItemsList`."); + return IC_RET_READ_FAIL; + } + + TrieSetCell(p, "Items", Json_Object_IC_GetItems(instanceJson, "Items")); + + return IC_RET_READ_SUCCESS; +} + +@OnItemsListGive(const playerIndex, const Trie:p) { + new Array:aItems = VipM_Params_GetCell(p, "Items", Invalid_Array); + + return IC_Item_GiveArray(playerIndex, aItems) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc new file mode 100644 index 0000000..d6d55ac --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_Money_Register() { + IC_ItemType_SimpleRegister( + .name = "Money", + .onRead = "@OnMoneyRead", + .onGive = "@OnMoneyGive" + ); +} + +@OnMoneyRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Amount", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Amount` required for item `Money`."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Amount", json_object_get_number(instanceJson, "Amount")); + + if (json_object_has_value(instanceJson, "GiveType", JSONString)) { + new sBuffer[32]; + json_object_get_string(instanceJson, "GiveType", sBuffer, charsmax(sBuffer)); + new accountSet = ItemType_Money_StrToAccountSet(sBuffer); + if (accountSet < 0) { + Json_LogForFile(instanceJson, "ERROR", "Invalid `GiveType` value (%s). Expected `Set` or `Add`.", sBuffer); + } else { + TrieSetCell(p, "GiveType", accountSet); + } + } + + if (json_object_has_value(instanceJson, "TrackChange", JSONBoolean)) { + TrieSetCell(p, "TrackChange", json_object_get_bool(instanceJson, "TrackChange")); + } + + return IC_RET_READ_SUCCESS; +} + +@OnMoneyGive(const playerIndex, const Trie:p) { + rg_add_account( + playerIndex, + VipM_Params_GetInt(p, "Amount"), + VipM_Params_GetCell(p, "GiveType", AS_ADD), + VipM_Params_GetBool(p, "TrackChanges", true) + ); +} + +static ItemType_Money_StrToAccountSet(const Str[]) { + if (equali(Str, "Set")) { + return _:AS_SET; + } else if (equali(Str, "Add")) { + return _:AS_ADD; + } else { + return -1; + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc new file mode 100644 index 0000000..41b2430 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_Random_Register() { + IC_ItemType_SimpleRegister( + .name = "Random", + .onRead = "@OnRandomRead", + .onGive = "@OnRandomGive" + ); +} + +@OnRandomRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + // TODO: Сделать как-то разные шансы + if (!json_object_has_value(instanceJson, "Items")) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `Random`."); + return IC_RET_READ_FAIL; + } + + new Array:aItems = Json_Object_IC_GetItems(instanceJson, "Items"); + if (ArraySizeSafe(aItems) <= 1) { + Json_LogForFile(instanceJson, "ERROR", "Param `Items` must have >1 items."); + ArrayDestroy(aItems); + return IC_RET_READ_FAIL; + } + + TrieSetCell(p, "Items", aItems); + + return IC_RET_READ_SUCCESS; +} + +@OnRandomGive(const playerIndex, const Trie:p) { + new Array:aItems = VipM_Params_GetArr(p, "Items"); + new iRandomIndex = random_num(0, ArraySizeSafe(aItems) - 1); + new VipM_IC_T_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); + + return IC_Item_Give(playerIndex, iRandomItem) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/RefillBpAmmo.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/RefillBpAmmo.inc new file mode 100644 index 0000000..41796d5 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/RefillBpAmmo.inc @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_RefillBpAmmo_Register() { + IC_ItemType_SimpleRegister( + .name = "RefillBpAmmo", + .onGive = "@OnRefillBpAmmoGive" + ); +} + +@OnRefillBpAmmoGive(const playerIndex, const Trie:p) { + new iMaxAmmos[32] = {-1, ...}; + + // Получение дефолтных значений + for (new WeaponIdType:iWpnId = WEAPON_P228; iWpnId < WEAPON_P90; iWpnId++) { + switch (iWpnId) { + case WEAPON_KNIFE, WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG, WEAPON_SHIELDGUN: + iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = -1; + default: + iMaxAmmos[rg_get_weapon_info(iWpnId, WI_AMMO_TYPE)] = rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS); + } + } + + // Получение актуальных значений исходя из пушек в инвентаре + for (new InventorySlotType:iSlot = PRIMARY_WEAPON_SLOT; iSlot <= PISTOL_SLOT; iSlot++) { + new ItemId = get_member(playerIndex, m_rgpPlayerItems, iSlot); + while (ItemId > 0 && !is_nullent(ItemId)) { + new iAmmoType = get_member(ItemId, m_Weapon_iPrimaryAmmoType); + if (iAmmoType >= 0) { + iMaxAmmos[iAmmoType] = max(iMaxAmmos[iAmmoType], rg_get_iteminfo(ItemId, ItemInfo_iMaxAmmo1)); + } + ItemId = get_member(ItemId, m_pNext); + } + } + + for (new iAmmoType = 0; iAmmoType < 32; iAmmoType++) { + if (iMaxAmmos[iAmmoType] >= 0) { + set_member(playerIndex, m_rgAmmo, iMaxAmmos[iAmmoType], iAmmoType); + } + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc new file mode 100644 index 0000000..91b2214 --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include // Для VipM_Params_* // TODO: уйти на аналог от контроллера параметров, когда он будет + +static HookChain:PlayerSpawnPreHookChain = INVALID_HOOKCHAIN; +static HookChain:PlayerResetSpeedPostHookChain = INVALID_HOOKCHAIN; + +static Float:PlayerSpeedMult[MAX_PLAYERS + 1] = {1.0, ...}; + +DefaultObjects_ItemType_Speed_Register() { + IC_ItemType_SimpleRegister( + .name = "Speed", + .onRead = "@ItemType_Speed_OnRead", + .onGive = "@ItemType_Speed_OnGive" + ); + + DisableHookChain(PlayerResetSpeedPostHookChain = RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@ItemType_Speed_OnPlayerResetSpeedPost", true)); + DisableHookChain(PlayerSpawnPreHookChain = RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_Speed_OnPlayerSpawnPre", false)); +} + +@ItemType_Speed_OnRead(const JSON:instanceJson, const Trie:p) { + TrieDeleteKey(p, "Name"); + + if (!json_object_has_value(instanceJson, "Multiplier", JSONNumber)) { + Json_LogForFile(instanceJson, "ERROR", "Param `Multiplier` required for item `Speed`."); + return IC_RET_READ_FAIL; + } + TrieSetCell(p, "Multiplier", json_object_get_real(instanceJson, "Multiplier")); + + EnableHookChain(PlayerResetSpeedPostHookChain); + EnableHookChain(PlayerSpawnPreHookChain); + + return IC_RET_READ_SUCCESS; +} + +@ItemType_Speed_OnGive(const playerIndex, const Trie:p) { + PlayerSpeedMult[playerIndex] = VipM_Params_GetFloat(p, "Multiplier", 1.0); + ItemType_Speed_MultUserSpeed(playerIndex, PlayerSpeedMult[playerIndex]); +} + +@ItemType_Speed_OnPlayerSpawnPre(const playerIndex) { + PlayerSpeedMult[playerIndex] = 1.0; +} + +@ItemType_Speed_OnPlayerResetSpeedPost(const playerIndex) { + ItemType_Speed_MultUserSpeed(playerIndex, PlayerSpeedMult[playerIndex]); +} + +static ItemType_Speed_MultUserSpeed(const playerIndex, const Float:mult) { + if (mult != 1.0) { + set_entvar(playerIndex, var_maxspeed, Float:get_entvar(playerIndex, var_maxspeed) * mult); + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc new file mode 100644 index 0000000..42a87fd --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -0,0 +1,91 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_Weapon_Register() { + IC_ItemType_SimpleRegister( + .name = "Weapon", + .onRead = "@OnWeaponRead", + .onGive = "@OnWeaponGive" + ); +} + +@OnWeaponRead(const JSON:instanceJson, const Trie:p) { + new Name[32]; + json_object_get_string(instanceJson, "Name", Name, charsmax(Name)); + + // if(get_weaponid(Name) == 0){ + // log_amx("[WARNING] Weapon `%s` not found.", Name); + // return IC_RET_READ_FAIL; + // } + + TrieSetCell(p, "GiveType", _:Json_Object_GetGiveType(instanceJson, "GiveType")); + + if (json_object_has_value(instanceJson, "BpAmmo", JSONNumber)) { + TrieSetCell(p, "BpAmmo", json_object_get_number(instanceJson, "BpAmmo")); + } + + TrieSetString(p, "Name", Name); + + return IC_RET_READ_SUCCESS; +} + +@OnWeaponGive(const playerIndex, const Trie:p) { + static WeaponName[32]; + VipM_Params_GetStr(p, "Name", WeaponName, charsmax(WeaponName)); + if (!WeaponName[0]) { + return IC_RET_GIVE_FAIL; + } + + if (!get_weaponid(WeaponName)) { + log_amx("[WARNING] Default weapon `%s` not found.", WeaponName); + return IC_RET_GIVE_FAIL; + } + + new GiveType:iGiveType = GiveType:VipM_Params_GetInt(p, "GiveType", _:GT_DROP_AND_REPLACE); + new iBpAmmo = VipM_Params_GetInt(p, "BpAmmo", -1); + + new ItemId = rg_give_item(playerIndex, WeaponName, iGiveType); + if (ItemId < 0) { + return IC_RET_GIVE_FAIL; + } + + new WeaponIdType:iWpnId = rg_get_weapon_info(WeaponName, WI_ID); + new iWpnSlot = rg_get_iteminfo(ItemId, ItemInfo_iSlot); + + if ( + iBpAmmo < 0 + && !( + iWpnSlot == 0 + || iWpnSlot == 1 + ) + ) { + return IC_RET_GIVE_SUCCESS; + } + + new def_BpAmmo = (rg_get_weapon_info(iWpnId, WI_MAX_ROUNDS)); + if (def_BpAmmo >= 0) { + rg_set_user_bpammo(playerIndex, iWpnId, iBpAmmo < 0 ? def_BpAmmo : iBpAmmo); + } + + return IC_RET_GIVE_SUCCESS; +} + +GiveType:Json_Object_GetGiveType(const JSON:Obj, const Key[], const bool:DotNot = false) { + new Str[32]; + json_object_get_string(Obj, Key, Str, charsmax(Str), DotNot); + return StrToGiveType(Str); +} + +GiveType:StrToGiveType(const Str[]) { + if (equali(Str, "GT_APPEND") || equali(Str, "Append") || equali(Str, "Add")) { + return GT_APPEND; + } else if (equali(Str, "GT_REPLACE") || equali(Str, "Replace")) { + return GT_REPLACE; + } else if (equali(Str, "GT_DROP_AND_REPLACE") || equali(Str, "Drop") || equali(Str, "DropAndReplace")) { + return GT_DROP_AND_REPLACE; + } else { + return GT_DROP_AND_REPLACE; + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc new file mode 100644 index 0000000..b77cfde --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc @@ -0,0 +1,34 @@ +#include + +#include "ItemsController/DefaultObjects/ItemType/Armor" +#include "ItemsController/DefaultObjects/ItemType/Command" +#include "ItemsController/DefaultObjects/ItemType/DamageMult" +#include "ItemsController/DefaultObjects/ItemType/DefuseKit" +#include "ItemsController/DefaultObjects/ItemType/Health" +#include "ItemsController/DefaultObjects/ItemType/InstantReload" +#include "ItemsController/DefaultObjects/ItemType/InstantReloadAllWeapons" +#include "ItemsController/DefaultObjects/ItemType/ItemsList" +#include "ItemsController/DefaultObjects/ItemType/Money" +#include "ItemsController/DefaultObjects/ItemType/Random" +#include "ItemsController/DefaultObjects/ItemType/RefillBpAmmo" +#include "ItemsController/DefaultObjects/ItemType/Speed" +#include "ItemsController/DefaultObjects/ItemType/Weapon" + +DefaultObjects_RegisterAll() { + // Затычка для тех мест, где при отсутствии предметов вылезает ошибка/варн + IC_ItemType_SimpleRegister(.name = "None"); + + DefaultObjects_ItemType_Armor_Register(); + DefaultObjects_ItemType_Command_Register(); + DefaultObjects_ItemType_DamageMult_Register(); + DefaultObjects_ItemType_DefuseKit_Register(); + DefaultObjects_ItemType_Health_Register(); + DefaultObjects_ItemType_InstantReload_Register(); + DefaultObjects_ItemType_InstantReloadAllWeapons_Register(); + DefaultObjects_ItemType_ItemsList_Register(); + DefaultObjects_ItemType_Money_Register(); + DefaultObjects_ItemType_Random_Register(); + DefaultObjects_ItemType_RefillBpAmmo_Register(); + DefaultObjects_ItemType_Speed_Register(); + DefaultObjects_ItemType_Weapon_Register(); +} \ No newline at end of file From db9bd11be6c6072489c634e8a49fc2ae25ee7690 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 23:01:18 +0300 Subject: [PATCH 020/108] Update ic api usage in vipm modulaes --- README.md | 6 ++--- .../DefaultObjects/ItemType/Random.inc | 2 +- amxmodx/scripting/VipM-M-SpawnItems.sma | 24 ++++++++----------- amxmodx/scripting/VipM-M-WeaponMenu.sma | 4 ++-- .../VipM/WeaponMenu/Objects/MenuItem.inc | 4 ++-- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index de777c7..5dea087 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Modular Vip System +# Vip Modular Модульная система привилегий. @@ -22,11 +22,11 @@ | `vipm_limits` | Выводит таблицу типов проверок и некоторую информацию о них | | `vipm_limit_params ` | Выводит таблицу параметров указанного типа проверки | | | | -| `vipm_ic_types` | Выводит таблицу типов предметов | +| `ic_item_types` | Выводит таблицу типов предметов | ## Идеи - _\[Configs\]_ Добавить глобальные настройки типа ключ-значение, на которые можно ссылаться из основных конфигов как на файлы, только с префиксом Var: - _\[Modules\]_ Переработать обьедининение параметров модулей - _\[ReadMe\]_ Нарисовать схему взаимодействия компонентов системы -- _\[IC\]_ Придумать как норм отвязать IC от ядра и, возможно, вынести его в отдельный репо +- _\[IC\]_ Придумать как норм отвязать IC от ядра и, возможно, вынести его в отдельный репо (WIP) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc index 41b2430..308f898 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc @@ -35,7 +35,7 @@ DefaultObjects_ItemType_Random_Register() { @OnRandomGive(const playerIndex, const Trie:p) { new Array:aItems = VipM_Params_GetArr(p, "Items"); new iRandomIndex = random_num(0, ArraySizeSafe(aItems) - 1); - new VipM_IC_T_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); + new T_IC_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); return IC_Item_Give(playerIndex, iRandomItem) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index d77d591..23b0a40 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -8,9 +8,6 @@ #include "VipM/Utils" #include "VipM/ArrayTrieUtils" -#pragma semicolon 1 -#pragma compress 1 - public stock const PluginName[] = "[VipM-M] Spawn Items"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; @@ -19,10 +16,9 @@ public stock const PluginDescription[] = "Vip modular`s module - Spawn Items"; new const MODULE_NAME[] = "SpawnItems"; -public VipM_OnInitModules(){ - RegisterPluginByVars(); - - VipM_IC_Init(); +public VipM_OnInitModules() { + register_plugin(PluginName, PluginVersion, PluginAuthor); + IC_Init(); VipM_Modules_Register(MODULE_NAME, true); VipM_Modules_AddParams(MODULE_NAME, @@ -33,17 +29,17 @@ public VipM_OnInitModules(){ VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } -@OnReadConfig(const JSON:jCfg, Trie:Params){ - if(!json_object_has_value(jCfg, "Items")){ +@OnReadConfig(const JSON:jCfg, Trie:Params) { + if (!json_object_has_value(jCfg, "Items")) { log_amx("[WARNING] Field `Items` required."); return VIPM_STOP; } new JSON:jItems = json_object_get_value(jCfg, "Items"); - new Array:aItems = VipM_IC_JsonGetItems(jItems); + new Array:aItems = IC_Item_ReadArrayFromJson(jItems); json_free(jItems); - if(ArraySizeSafe(aItems) < 1){ + if (ArraySizeSafe(aItems) < 1) { ArrayDestroySafe(aItems); log_amx("[WARNING] Field `Items` is empty."); return VIPM_STOP; @@ -53,11 +49,11 @@ public VipM_OnInitModules(){ return VIPM_CONTINUE; } -@OnModuleActivate(){ +@OnModuleActivate() { RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawned", true); } -@OnPlayerSpawned(const UserId){ +@OnPlayerSpawned(const UserId) { RequestFrame("@GivePlayerItems", UserId); } @@ -83,7 +79,7 @@ public VipM_OnInitModules(){ return; } - if (VipM_IC_GiveItems(UserId, aItems)) { + if (IC_Item_GiveArray(UserId, aItems)) { Dbg_Log("@GivePlayerItems(%n) Items given", UserId); } else { Dbg_Log("@GivePlayerItems(%n) Items not given", UserId); diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 653360b..c61f861 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -44,7 +44,7 @@ new gUserExpireStatus[MAX_PLAYERS + 1][VIPM_M_WEAPONMENU_EXPIRE_STATUS_MAX_LEN]; public VipM_OnInitModules() { RegisterPluginByVars(); register_dictionary("VipM-WeaponMenu.ini"); - VipM_IC_Init(); + IC_Init(); VipM_Modules_Register(MODULE_NAME, true); VipM_Modules_AddParams(MODULE_NAME, @@ -308,7 +308,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { } if ( - VipM_IC_GiveItems(UserId, MenuItem[MenuItem_Items]) + IC_Item_GiveArray(UserId, MenuItem[MenuItem_Items]) && MenuItem[MenuItem_UseCounter] ) { gUserLeftItems[UserId]--; diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 6366bb4..ecbd58b 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -17,7 +17,7 @@ enum _:S_MenuItem { MenuItemType:MenuItem_Type, MenuItem_Title[64], - Array:MenuItem_Items, // VipM_IC_T_Item[] + Array:MenuItem_Items, // T_IC_Item[] bool:MenuItem_UseCounter, bool:MenuItem_FakeInactive, @@ -40,7 +40,7 @@ bool:MenuItem_Read(const JSON:jMenuItem, MenuItem[S_MenuItem]) { return true; } - MenuItem[MenuItem_Items] = Json_Object_GetItemsIC(jMenuItem, "Items"); + MenuItem[MenuItem_Items] = Json_Object_IC_GetItems(jMenuItem, "Items"); if (MenuItem[MenuItem_Items] == Invalid_Array) { MenuItem[MenuItem_Type] = MenuItemType_Text; From 00b5ebd84a36001299d90fa9d6dc721c9585d4b3 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 23:04:09 +0300 Subject: [PATCH 021/108] Fix core compile --- amxmodx/scripting/VipM/Core/SrvCmds.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 541b71d..8f1071e 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -30,7 +30,7 @@ SrvCmds_Init() { @SrvCmd_Info() { new sAmxxVersion[32]; - get_amxx_verstring(sAmxxVersion, charmsax(sAmxxVersion)); + get_amxx_verstring(sAmxxVersion, charsmax(sAmxxVersion)); server_print("╓─────────"); server_print("║ %s v%s by %s:", PluginName, VIPM_VERSION, PluginAuthor); From 0638de38abbadc67faf9b8c76669de2480d16dda Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Feb 2025 23:23:09 +0300 Subject: [PATCH 022/108] Impl compat ic api --- .../scripting/ItemsController/API/Compat.inc | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/amxmodx/scripting/ItemsController/API/Compat.inc b/amxmodx/scripting/ItemsController/API/Compat.inc index 679552a..f2188ab 100644 --- a/amxmodx/scripting/ItemsController/API/Compat.inc +++ b/amxmodx/scripting/ItemsController/API/Compat.inc @@ -9,5 +9,49 @@ // Все зарегистрированные тут нативы устаревшие. API_Compat_Register() { - // TODO: impl + register_native("VipM_IC_RegisterType", "@_VipM_IC_RegisterType"); + register_native("VipM_IC_RegisterTypeEvent", "@_VipM_IC_RegisterTypeEvent"); + register_native("VipM_IC_JsonGetItem", "@_VipM_IC_JsonGetItem"); + register_native("VipM_IC_GiveItem", "@_VipM_IC_GiveItem"); +} + +T_IC_ItemType:@_VipM_IC_RegisterType() { + enum {Arg_Name = 1} + + new name[IC_ITEM_TYPE_NAME_MAX_LEN]; + get_string(Arg_Name, name, charsmax(name)); + + return ItemType_Construct(name); +} + +@_VipM_IC_RegisterTypeEvent(const pluginIndex) { + enum {Arg_Type = 1, Arg_Event, Arg_FuncName} + + new T_IC_ItemType:type = T_IC_ItemType:get_param(Arg_Type); + new E_ItemTypeEvent:event = E_ItemTypeEvent:get_param(Arg_Event); + new funcName[IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN]; + get_string(Arg_FuncName, funcName, charsmax(funcName)); + + new listener = ItemType_MakeEventListener(event, pluginIndex, funcName); + ItemType_SetEventListener(type, event, listener); +} + +T_IC_Item:@_VipM_IC_JsonGetItem() { + enum {Arg_InstanceJson = 1} + + new JSON:isntanceJson = JSON:get_param(Arg_InstanceJson); + + new T_IC_Item:item = ItemInstance_ReadFromJsonObject(isntanceJson); + json_free(isntanceJson); + return item; +} + + +bool:@_VipM_IC_GiveItem() { + enum {Arg_PlayerIndex = 1, Arg_Item} + + new playerIndex = get_param(Arg_PlayerIndex); + new T_IC_Item:item = T_IC_Item:get_param(Arg_Item); + + return ItemInstance_Give(playerIndex, item); } From 0faba1072dc35fb888e0bbf387547240bad778fe Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 21 Feb 2025 16:56:23 +0300 Subject: [PATCH 023/108] Impl `CustomWeapon` item type --- amxmodx/scripting/ItemsController.sma | 10 + .../DefaultObjects/ItemType/Command.inc | 1 + .../DefaultObjects/ItemType/CustomWeapon.inc | 205 ++++++++++++++++++ .../DefaultObjects/ItemType/Weapon.inc | 4 +- .../DefaultObjects/Regsitrar.inc | 2 + 5 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index 642a0ef..8d0c4ba 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -33,6 +33,8 @@ PluginInit() { #include "ItemsController/API/Compat" public plugin_natives() { + set_native_filter("@NativeFilter"); + register_native("IC_Init", "@_Init"); register_native("VipM_IC_Init", "@_Init"); // deprecated @@ -43,3 +45,11 @@ public plugin_natives() { @_Init() { PluginInit(); } + +@NativeFilter(const name[], index, trap) { + if (DefaultObjects_ItemType_CustomWeapon_NativeFilter(name, trap)) { + return PLUGIN_HANDLED; + } + + return PLUGIN_CONTINUE; +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc index bccba53..8c78e7b 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -35,6 +35,7 @@ DefaultObjects_ItemType_Command_Register() { VipM_Params_GetStr(p, "Command", Command, charsmax(Command)); new bool:ByServer = VipM_Params_GetBool(p, "ByServer", false); + replace_all(Command, charsmax(Command), "{UserId}", IntToStr(playerIndex)); replace_all(Command, charsmax(Command), "{playerIndex}", IntToStr(playerIndex)); if (ByServer) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc new file mode 100644 index 0000000..1c5053c --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc @@ -0,0 +1,205 @@ +#include +#include +#include +#include + +#if !defined _cwapi_included +enum T_CustomWeapon { Invalid_CustomWeapon = -1 } +enum CWeapon_GiveType { + CWAPI_GT_SMART = -1, + CWAPI_GT_APPEND, + CWAPI_GT_REPLACE, + CWAPI_GT_DROP, +} +native T_CustomWeapon:CWAPI_Weapons_Find(const sWeaponName[]); +native CWAPI_Weapons_Give( + const UserId, + const T_CustomWeapon:iWeapon, + const CWeapon_GiveType:iGiveType = CWAPI_GT_SMART, + const bool:bForceActive = false, + const initBpAmmo = -1 +); +#endif + +#if !defined _auw_included +native __auw__native__auw_give_weapon(iPlayer, const sWeaponName[], const bool: notification = true, const uid = -1, const iUidWithOffset = true, const iBuy = 0); +#endif + +#if !defined _ultimate_weapons_included +native weapons_give_user_ultimate(id, uid=-1, buy_name[]="", replace=0, ammo=-1, bpammo=-1); +#endif + +enum E_ItemType_CustomWeapon_Controller { + ItemType_CustomWeapon_Controller_None, + + ItemType_CustomWeapon_Controller_Cwapi, + ItemType_CustomWeapon_Controller_Auw, + ItemType_CustomWeapon_Controller_Uw, +} + +enum E_ItemType_CustomWeapon_GiveType { + ItemType_CustomWeapon_GiveType_Default, + ItemType_CustomWeapon_GiveType_Append, + ItemType_CustomWeapon_GiveType_Replace, + ItemType_CustomWeapon_GiveType_DropAndReplace, +} + +static E_ItemType_CustomWeapon_Controller:UsingController = ItemType_CustomWeapon_Controller_None; +static bool:AvailableControllers[E_ItemType_CustomWeapon_Controller] = {false, ...}; + +bool:DefaultObjects_ItemType_CustomWeapon_NativeFilter(const name[], const trap) { + if (equal(name, "CWAPI_Weapons_Give")) { + AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = !!trap; + return true; + } + + if (equal(name, "__auw__native__auw_give_weapon")) { + AvailableControllers[ItemType_CustomWeapon_Controller_Auw] = !!trap; + return true; + } + + if (equal(name, "weapons_give_user_ultimate")) { + AvailableControllers[ItemType_CustomWeapon_Controller_Uw] = !!trap; + return true; + } + + return false; +} + +DefaultObjects_ItemType_CustomWeapon_Register() { + UsingController = ItemType_CustomWeapon_Controller_None; + for (new i = 0; i < _:E_ItemType_CustomWeapon_Controller; ++i) { + if (AvailableControllers[E_ItemType_CustomWeapon_Controller:i]) { + UsingController = E_ItemType_CustomWeapon_Controller:i; + } + } + + IC_ItemType_SimpleRegister( + .name = "CustomWeapon", + .onRead = "@ItemType_CustomWeapon_OnRead", + .onGive = "@ItemType_CustomWeapon_OnGive" + ); +} + +@ItemType_CustomWeapon_OnRead(const JSON:instanceJson, const Trie:p) { + if (UsingController == ItemType_CustomWeapon_Controller_None) { + log_amx("[WARNING] Custom weapons controller is not set. Item type `CustomWeapon` is not available."); + return IC_RET_READ_FAIL; + } + + new Name[32]; + json_object_get_string(instanceJson, "Name", Name, charsmax(Name)); + TrieSetString(p, "Name", Name); + + TrieSetCell(p, "GiveType", _:ItemType_CustomWeapon_ReadGiveTypeFromJsonObject(instanceJson, "GiveType")); + + return IC_RET_READ_SUCCESS; +} + +@ItemType_CustomWeapon_OnGive(const playerIndex, const Trie:p) { + if (UsingController == ItemType_CustomWeapon_Controller_None) { + log_amx("[ERROR] Custom weapons controller is not set."); + return IC_RET_GIVE_FAIL; + } + + static name[32]; + VipM_Params_GetStr(p, "Name", name, charsmax(name)); + if (!name[0]) { + log_amx("[WARNING] Custom weapon name is empty."); + return IC_RET_GIVE_FAIL; + } + + new E_ItemType_CustomWeapon_GiveType:giveType = E_ItemType_CustomWeapon_GiveType:VipM_Params_GetInt(p, "GiveType", _:ItemType_CustomWeapon_GiveType_Default); + + new bool:res = false; + switch (UsingController) { + case ItemType_CustomWeapon_Controller_Cwapi: + res = ItemType_CustomWeapon_GiveViaCwapi(playerIndex, name, giveType); + case ItemType_CustomWeapon_Controller_Auw: + res = ItemType_CustomWeapon_GiveViaAuw(playerIndex, name); + case ItemType_CustomWeapon_Controller_Uw: + res = ItemType_CustomWeapon_GiveViaUw(playerIndex, name, giveType); + default: + log_amx("[WARNING] Unknown custom weapons controller."); + } + + return res ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; +} + +static bool:ItemType_CustomWeapon_GiveViaCwapi( + const playerIndex, + const weaponName[], + const E_ItemType_CustomWeapon_GiveType:giveType = ItemType_CustomWeapon_GiveType_Default +) { + new CWeapon_GiveType:gtype; + switch (giveType) { + case ItemType_CustomWeapon_GiveType_Append: + gtype = CWAPI_GT_APPEND; + case ItemType_CustomWeapon_GiveType_Replace: + gtype = CWAPI_GT_REPLACE; + case ItemType_CustomWeapon_GiveType_DropAndReplace: + gtype = CWAPI_GT_DROP; + default: + gtype = CWAPI_GT_SMART; + } + + new T_CustomWeapon:weapon = CWAPI_Weapons_Find(weaponName); + if (weapon == Invalid_CustomWeapon) { + abort(AMX_ERR_PARAMS, "Weapon '%s' not found in Custom Wepaons API.", weaponName); + return false; + } + + return CWAPI_Weapons_Give(playerIndex, weapon, gtype) > 0; +} + +static bool:ItemType_CustomWeapon_GiveViaAuw( + const playerIndex, + const weaponName[] +) { + return !!__auw__native__auw_give_weapon(playerIndex, weaponName); +} + +static bool:ItemType_CustomWeapon_GiveViaUw( + const playerIndex, + const weaponName[], + const E_ItemType_CustomWeapon_GiveType:giveType = ItemType_CustomWeapon_GiveType_Default +) { + new replace; + switch (giveType) { + case ItemType_CustomWeapon_GiveType_Append: + replace = 0; + case ItemType_CustomWeapon_GiveType_Replace: + replace = 2; + case ItemType_CustomWeapon_GiveType_DropAndReplace: + replace = 1; + default: + replace = 0; + } + + new nonConstName[32]; + copy(nonConstName, charsmax(nonConstName), weaponName); + + // Не понятно что оно возвращает, поэтому в любом случае будет успех. + weapons_give_user_ultimate( + playerIndex, + .buy_name = nonConstName, + .replace = replace + ); + + return true; +} + +static E_ItemType_CustomWeapon_GiveType:ItemType_CustomWeapon_ReadGiveTypeFromJsonObject(const JSON:Obj, const Key[], const bool:DotNot = false) { + new Str[32]; + json_object_get_string(Obj, Key, Str, charsmax(Str), DotNot); + + if (equali(Str, "GT_APPEND") || equali(Str, "Append") || equali(Str, "Add")) { + return ItemType_CustomWeapon_GiveType_Append; + } else if (equali(Str, "GT_REPLACE") || equali(Str, "Replace")) { + return ItemType_CustomWeapon_GiveType_Replace; + } else if (equali(Str, "GT_DROP_AND_REPLACE") || equali(Str, "Drop") || equali(Str, "DropAndReplace")) { + return ItemType_CustomWeapon_GiveType_DropAndReplace; + } else { + return ItemType_CustomWeapon_GiveType_Default; + } +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc index 42a87fd..331e1be 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -75,10 +75,10 @@ DefaultObjects_ItemType_Weapon_Register() { GiveType:Json_Object_GetGiveType(const JSON:Obj, const Key[], const bool:DotNot = false) { new Str[32]; json_object_get_string(Obj, Key, Str, charsmax(Str), DotNot); - return StrToGiveType(Str); + return ItemType_Weapon_StrToGiveType(Str); } -GiveType:StrToGiveType(const Str[]) { +GiveType:ItemType_Weapon_StrToGiveType(const Str[]) { if (equali(Str, "GT_APPEND") || equali(Str, "Append") || equali(Str, "Add")) { return GT_APPEND; } else if (equali(Str, "GT_REPLACE") || equali(Str, "Replace")) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc index b77cfde..5b30a22 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc @@ -13,6 +13,7 @@ #include "ItemsController/DefaultObjects/ItemType/RefillBpAmmo" #include "ItemsController/DefaultObjects/ItemType/Speed" #include "ItemsController/DefaultObjects/ItemType/Weapon" +#include "ItemsController/DefaultObjects/ItemType/CustomWeapon" DefaultObjects_RegisterAll() { // Затычка для тех мест, где при отсутствии предметов вылезает ошибка/варн @@ -31,4 +32,5 @@ DefaultObjects_RegisterAll() { DefaultObjects_ItemType_RefillBpAmmo_Register(); DefaultObjects_ItemType_Speed_Register(); DefaultObjects_ItemType_Weapon_Register(); + DefaultObjects_ItemType_CustomWeapon_Register(); } \ No newline at end of file From 9bb2c64ec32c753c38abb2ad8236237cb8c0670f Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 21 Feb 2025 16:57:18 +0300 Subject: [PATCH 024/108] Fix type in file name --- amxmodx/scripting/ItemsController.sma | 2 +- .../DefaultObjects/{Regsitrar.inc => Registrar.inc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename amxmodx/scripting/ItemsController/DefaultObjects/{Regsitrar.inc => Registrar.inc} (100%) diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index 8d0c4ba..3a4bdf2 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -10,7 +10,7 @@ public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-p public stock const PluginDescription[] = "Unified interface for items giving."; #include "ItemsController/Objects/Items/Instance" -#include "ItemsController/DefaultObjects/Regsitrar" +#include "ItemsController/DefaultObjects/Registrar" public plugin_precache() { PluginInit(); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc similarity index 100% rename from amxmodx/scripting/ItemsController/DefaultObjects/Regsitrar.inc rename to amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc From 7e473ffc15bda1533a06064902299b18f04910ef Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 21 Feb 2025 17:15:14 +0300 Subject: [PATCH 025/108] Impl `IC_Item_Free` native --- amxmodx/scripting/ItemsController/API/Items.inc | 10 ++++++++++ .../ItemsController/Objects/Items/Instance.inc | 1 - amxmodx/scripting/include/ItemsController.inc | 13 +++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/amxmodx/scripting/ItemsController/API/Items.inc b/amxmodx/scripting/ItemsController/API/Items.inc index 3a7034d..b1fecfd 100644 --- a/amxmodx/scripting/ItemsController/API/Items.inc +++ b/amxmodx/scripting/ItemsController/API/Items.inc @@ -12,6 +12,7 @@ API_Items_Register() { register_native("IC_Item_ReadFromJson", "@_Item_ReadFromJson"); register_native("IC_Item_ReadArrayFromJson", "@_Item_ReadArrayFromJson"); register_native("IC_Item_Give", "@_Item_Give"); + register_native("IC_Item_Free", "@_Item_Free"); } T_IC_ItemType:@_ItemType_Register() { @@ -65,3 +66,12 @@ bool:@_Item_Give() { return ItemInstance_Give(playerIndex, item); } + + +bool:@_Item_Free() { + enum {Arg_Item = 1} + + new T_IC_Item:item = T_IC_Item:get_param(Arg_Item); + + return ItemInstance_Free(item); +} diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc index 303cfe0..1316875 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc @@ -82,7 +82,6 @@ bool:ItemInstance_Give(const playerIndex, const T_IC_Item:instance) { return ItemType_Give(playerIndex, instanceObject[Item_Type], instanceObject[Item_Params]); } -#pragma unused ItemInstance_Free T_IC_Item:ItemInstance_Free(&T_IC_Item:instance, const bool:orFail = false) { new instanceObject[S_ItemInstance]; if (!ItemInstance_Get(instance, instanceObject, .orFail = orFail)) { diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index c570a78..9e9412d 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -167,6 +167,19 @@ stock Array:Json_Object_IC_GetItems(const JSON:jObj, const sKey[], const bool:bD */ native bool:IC_Item_Give(const playerIndex, const T_IC_Item:item); +/** + * Удаление экземпляра предмета из памяти (освобождение хендлера). + * + * @note На данный момент может вызывать утечку памяти при некоторых обстоятельствах. + * Если в параметрах предмета находятся хендлеры каких-либо хранилищ (Array, Trie и т.п.), они не будут очищены. + * В будущем планируется решить это через ParamsController, но там пока нет нужного функционала. + * + * @param item Хендлер экземпляра предмета. Значение будет изменено на Invalid_IC_Item. + * + * @return Всегда Invalid_IC_Item. + */ +native T_IC_Item:IC_Item_Free(&T_IC_Item:item); + /** * Выдача игроку всех предметов из массива. * From 43f578aa7bf9434f33025dbd7abbcce88219ac86 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 22 Feb 2025 21:26:29 +0300 Subject: [PATCH 026/108] Fix type missmatch --- amxmodx/scripting/ItemsController/API/Items.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amxmodx/scripting/ItemsController/API/Items.inc b/amxmodx/scripting/ItemsController/API/Items.inc index b1fecfd..5e062d7 100644 --- a/amxmodx/scripting/ItemsController/API/Items.inc +++ b/amxmodx/scripting/ItemsController/API/Items.inc @@ -68,7 +68,7 @@ bool:@_Item_Give() { } -bool:@_Item_Free() { +T_IC_Item:@_Item_Free() { enum {Arg_Item = 1} new T_IC_Item:item = T_IC_Item:get_param(Arg_Item); From 15061aa3bca830e4214af1c68e2d5d0880d3b203 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 23 Feb 2025 15:44:17 +0300 Subject: [PATCH 027/108] Fix compile warn --- amxmodx/scripting/VipM/Core/SrvCmds.inc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 8f1071e..e20a1c4 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -15,7 +15,9 @@ // TODO: Дописать в параметрах компиляции в экшонах #if !defined VIPM_INFO_COMPILED_BY_GH_ACTIONS - #define VIPM_INFO_COMPILED_BY_GH_ACTIONS 0 +new bool:__VIPM_INFO_COMPILED_BY_GH_ACTIONS = false; +#else +new bool:__VIPM_INFO_COMPILED_BY_GH_ACTIONS = bool:(VIPM_INFO_COMPILED_BY_GH_ACTIONS); #endif SrvCmds_Init() { @@ -56,7 +58,7 @@ SrvCmds_Init() { server_print("║ │ │ └─Vips count: %d", VipUnit_GetCount()); server_print("║ │ ├─Compiled by AmxModX v%s", AMXX_VERSION_STR); server_print("║ │ ├─Runned by AmxModX v%s", sAmxxVersion); - server_print("║ │ └─Builded by GitHub Actions?: %s", VIPM_INFO_COMPILED_BY_GH_ACTIONS ? "Yes" : "No"); + server_print("║ │ └─Builded by GitHub Actions?: %s", __VIPM_INFO_COMPILED_BY_GH_ACTIONS ? "Yes" : "No"); server_print("║ │"); server_print("║ └─GitHub repo: https://github.com/ArKaNeMaN/amxx-VipModular-pub"); server_print("╙─────────"); From c2df74237c6e7c5c21da86621279fac2ecbd3367 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 23 Feb 2025 15:45:02 +0300 Subject: [PATCH 028/108] Make reunium not required for vipm-l-default --- amxmodx/scripting/VipM-L-Default.sma | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index 0c895e1..3bd9170 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -22,6 +22,18 @@ new Trie:g_tUsedInGame = Invalid_Trie; new Float:g_fPlayerSpawnTime[MAX_PLAYERS + 1]; +new bool:IsSteamLimitAvailable = false; + +public plugin_natives() { + set_native_filter("@NativeFilter"); +} + +@NativeFilter(const name[], const index, const bool:trap) { + if (equal(name, "REU_GetAuthtype")) { + IsSteamLimitAvailable = trap; + } +} + public VipM_OnInitModules() { RegisterPluginByVars(); @@ -162,7 +174,12 @@ public VipM_OnInitModules() { } public client_authorized(UserId, const AuthId[]) { - VipM_Limits_SetStaticValue("Steam", is_user_steam(UserId), UserId); + if (IsSteamLimitAvailable) { + VipM_Limits_SetStaticValue("Steam", is_user_steam(UserId), UserId); + } else { + VipM_Limits_SetStaticValue("Steam", true, UserId); + } + VipM_Limits_SetStaticValue("Bot", bool:is_user_bot(UserId), UserId); copy(g_sSteamIds[UserId], charsmax(g_sSteamIds[]), AuthId); From 52101f1afec964e923f7c83df56def89fad3627d Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 23 Feb 2025 16:01:39 +0300 Subject: [PATCH 029/108] Fix custom weapon item type --- .../ItemsController/DefaultObjects/ItemType/CustomWeapon.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc index 1c5053c..2f8c5e1 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc @@ -52,6 +52,9 @@ bool:DefaultObjects_ItemType_CustomWeapon_NativeFilter(const name[], const trap) AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = !!trap; return true; } + if (equal(name, "CWAPI_Weapons_Find")) { + return true; + } if (equal(name, "__auw__native__auw_give_weapon")) { AvailableControllers[ItemType_CustomWeapon_Controller_Auw] = !!trap; From c53a93ac998567180479c70745bea22e46344385 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 23 Feb 2025 16:08:19 +0300 Subject: [PATCH 030/108] Update item objects (`Type` -> `Item`) --- .../configs/plugins/VipModular/Items/AllGrenades.json | 8 ++++---- .../configs/plugins/VipModular/Items/DefuseKit.json | 2 +- .../configs/plugins/VipModular/SpawnItems/Premium.json | 6 +++--- amxmodx/configs/plugins/VipModular/SpawnItems/Vip.json | 4 ++-- .../plugins/VipModular/WeaponMenu/Menus/Premium.json | 10 +++++----- .../plugins/VipModular/WeaponMenu/Menus/Vip.json | 6 +++--- amxmodx/scripting/include/ItemsController.inc | 2 +- readme/extensions/items.md | 2 +- readme/extensions/items/command.md | 2 +- readme/extensions/items/defuse-kit.md | 2 +- readme/extensions/items/items-list.md | 6 +++--- readme/extensions/items/weapon.md | 2 +- readme/extensions/modules/spawn-items.md | 4 ++-- 13 files changed, 28 insertions(+), 28 deletions(-) diff --git a/amxmodx/configs/plugins/VipModular/Items/AllGrenades.json b/amxmodx/configs/plugins/VipModular/Items/AllGrenades.json index 4f94441..bd683ad 100644 --- a/amxmodx/configs/plugins/VipModular/Items/AllGrenades.json +++ b/amxmodx/configs/plugins/VipModular/Items/AllGrenades.json @@ -1,20 +1,20 @@ { // Выдаёт все гранаты (1 разрывную, 1 дымовую, 2 световые) - "Type": "ItemsList", + "Item": "ItemsList", "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_hegrenade", "GiveType": "Add" }, { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_smokegrenade", "GiveType": "Add" }, { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_flashbang", "BpAmmo": 2, "GiveType": "Add" diff --git a/amxmodx/configs/plugins/VipModular/Items/DefuseKit.json b/amxmodx/configs/plugins/VipModular/Items/DefuseKit.json index 5e99f36..758f665 100644 --- a/amxmodx/configs/plugins/VipModular/Items/DefuseKit.json +++ b/amxmodx/configs/plugins/VipModular/Items/DefuseKit.json @@ -1,3 +1,3 @@ { - "Type": "DefuseKit" + "Item": "DefuseKit" } \ No newline at end of file diff --git a/amxmodx/configs/plugins/VipModular/SpawnItems/Premium.json b/amxmodx/configs/plugins/VipModular/SpawnItems/Premium.json index 002ac8a..2705609 100644 --- a/amxmodx/configs/plugins/VipModular/SpawnItems/Premium.json +++ b/amxmodx/configs/plugins/VipModular/SpawnItems/Premium.json @@ -9,16 +9,16 @@ "Items": [ { // Дигл - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_deagle", "GiveType": "Replace" }, { // Осколочная граната - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_hegrenade" }, { - "Type": "Money", + "Item": "Money", "Amount": 500 }, // Набор сапёра diff --git a/amxmodx/configs/plugins/VipModular/SpawnItems/Vip.json b/amxmodx/configs/plugins/VipModular/SpawnItems/Vip.json index fad5f0d..d38205a 100644 --- a/amxmodx/configs/plugins/VipModular/SpawnItems/Vip.json +++ b/amxmodx/configs/plugins/VipModular/SpawnItems/Vip.json @@ -9,12 +9,12 @@ "Items": [ { // Дигл - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_deagle", "GiveType": "Replace" }, { // Осколочная граната - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_hegrenade" }, // Набор сапёра diff --git a/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Premium.json b/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Premium.json index fa9ed88..e90cb75 100644 --- a/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Premium.json +++ b/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Premium.json @@ -7,7 +7,7 @@ "Title": "АК-47", "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_ak47" } ] @@ -16,7 +16,7 @@ "Title": "M4A1", "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_m4a1" } ] @@ -25,7 +25,7 @@ "Title": "AUG", "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_aug" } ] @@ -34,7 +34,7 @@ "Title": "SG552", "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_sg552" } ] @@ -45,7 +45,7 @@ "FakeInactive": true, "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_awp" } ] diff --git a/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Vip.json b/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Vip.json index faa860b..11a65f2 100644 --- a/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Vip.json +++ b/amxmodx/configs/plugins/VipModular/WeaponMenu/Menus/Vip.json @@ -21,7 +21,7 @@ /* Предметы, выдаваемые при выборе этого пункта */ "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_ak47" } ] @@ -31,7 +31,7 @@ "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_m4a1" } ] @@ -46,7 +46,7 @@ "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_awp" } ] diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 9e9412d..7966b14 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -262,7 +262,7 @@ native VipM_IC_RegisterTypeEvent(const Type[], const E_ItemTypeEvent:Event, cons * @note После загрузки предмета, JSON-объект уничтожается. * @note Структура объекта: * { - * "Type": "НазваниеТипа", + * "Item": "НазваниеТипа", * "НазваниеПараметра1": "ЗначениеПараметра1", * "НазваниеПараметра2": "ЗначениеПараметра2", * ... diff --git a/readme/extensions/items.md b/readme/extensions/items.md index 7b558b5..5e763a9 100644 --- a/readme/extensions/items.md +++ b/readme/extensions/items.md @@ -10,7 +10,7 @@ TODO: Переписать ```jsonc { - "Type": "", + "Item": "", "": "", // ... diff --git a/readme/extensions/items/command.md b/readme/extensions/items/command.md index c2d3593..00a0d06 100644 --- a/readme/extensions/items/command.md +++ b/readme/extensions/items/command.md @@ -17,7 +17,7 @@ _\* - если указано "-", то параметр является обя ```jsonc { - "Type": "Command", + "Item": "Command", "Command": "HealthNade_Give {UserId}", "ByServer": true diff --git a/readme/extensions/items/defuse-kit.md b/readme/extensions/items/defuse-kit.md index 5af8197..a992f2f 100644 --- a/readme/extensions/items/defuse-kit.md +++ b/readme/extensions/items/defuse-kit.md @@ -6,7 +6,7 @@ ```jsonc { - "Type": "DefuseKit" + "Item": "DefuseKit" } ``` diff --git a/readme/extensions/items/items-list.md b/readme/extensions/items/items-list.md index b564e41..a316b0f 100644 --- a/readme/extensions/items/items-list.md +++ b/readme/extensions/items/items-list.md @@ -6,17 +6,17 @@ ```jsonc { - "Type": "ItemsList", + "Item": "ItemsList", "Items": [ { - "Type": "Cwapi", + "Item": "Cwapi", "Name": "Vip_Ak47", "GiveType": "Replace" }, { - "Type": "Cwapi", + "Item": "Cwapi", "Name": "Vip_Deagle", "GiveType": "Replace" diff --git a/readme/extensions/items/weapon.md b/readme/extensions/items/weapon.md index 1e16967..c42fff3 100644 --- a/readme/extensions/items/weapon.md +++ b/readme/extensions/items/weapon.md @@ -6,7 +6,7 @@ ```jsonc { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_ak47", "GiveType": "Replace", diff --git a/readme/extensions/modules/spawn-items.md b/readme/extensions/modules/spawn-items.md index 1ad280b..35117c6 100644 --- a/readme/extensions/modules/spawn-items.md +++ b/readme/extensions/modules/spawn-items.md @@ -26,12 +26,12 @@ _\* - если указано "-", то параметр является обя "Items": [ { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_deagle", "GiveType": "Replace" }, { - "Type": "Weapon", + "Item": "Weapon", "Name": "weapon_hegrenade", "GiveType": "Add" } From ee52bb0f0aedd632e0916f09166d37b4281905a0 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 23 Feb 2025 16:12:52 +0300 Subject: [PATCH 031/108] Fix misc --- amxmodx/scripting/VipM-Misc.sma | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/amxmodx/scripting/VipM-Misc.sma b/amxmodx/scripting/VipM-Misc.sma index 43c8819..b1a0433 100644 --- a/amxmodx/scripting/VipM-Misc.sma +++ b/amxmodx/scripting/VipM-Misc.sma @@ -3,9 +3,6 @@ #include #include "VipM/Utils" -#pragma semicolon 1 -#pragma compress 1 - #define RELOAD_ON_PLAYER_SPAWN 1 #define RELOAD_ON_ROUND_START 1 #define RELOAD_ON_ROUND_END 1 @@ -17,7 +14,7 @@ public stock const PluginURL[] = _VIPM_PLUGIN_URL; public stock const PluginDescription[] = "Auto reload player's privilegies."; public VipM_OnLoaded() { - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); #if RELOAD_ON_PLAYER_SPAWN RegisterHookChain(RG_CBasePlayer_Spawn, "@ReloadPlayer", false); @@ -28,21 +25,26 @@ public VipM_OnLoaded() { #endif #if RELOAD_ON_ROUND_END - RegisterHookChain(RG_RoundEnd, "@OnPlayerSpawned", false); + RegisterHookChain(RG_RoundEnd, "@ReloadAllPlayers", false); #endif register_srvcmd("vipm_update_users", "@SrvCmd_ReloadPlayers"); register_srvcmd("vipm_reload_players", "@SrvCmd_ReloadPlayers"); + register_srvcmd("vipm_reload_player", "@SrvCmd_ReloadPlayer"); } -@ReloadPlayer(const UserId) { - VipM_UserUpdate(UserId); +@ReloadPlayer(const playerIndex) { + VipM_UserUpdate(playerIndex); } @ReloadAllPlayers() { - for (new UserId = 1; UserId <= MAX_PLAYERS; UserId++) { - if (is_user_connected(UserId) && !is_user_bot(UserId) && !is_user_hltv(UserId)) { - @ReloadPlayer(UserId); + for (new playerIndex = 1; playerIndex <= MAX_PLAYERS; ++playerIndex) { + if ( + is_user_connected(playerIndex) + && !is_user_bot(playerIndex) + && !is_user_hltv(playerIndex) + ) { + @ReloadPlayer(playerIndex); } } } @@ -52,15 +54,15 @@ public VipM_OnLoaded() { } @SrvCmd_ReloadPlayer() { - enum {Arg_UserId = 1} + enum {Arg_PlayerIndex = 1} - if (read_argc() < Arg_UserId) { + if (read_argc() < Arg_PlayerIndex) { server_print("Invalid command params."); - server_print("Usage: vipm_reload_players "); + server_print("Usage: vipm_reload_players "); return; } - new UserId = read_argv_int(Arg_UserId); + new playerIndex = read_argv_int(Arg_PlayerIndex); - @ReloadPlayer(UserId); + @ReloadPlayer(playerIndex); } From cd22830e94315421a372300e5839e772b7f30bb5 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 2 Mar 2025 05:22:58 +0300 Subject: [PATCH 032/108] Use `PCJson_*` stocks in items controller --- amxmodx/scripting/IC-I-Limits.sma | 4 +- .../DefaultObjects/ItemType/Armor.inc | 2 +- .../DefaultObjects/ItemType/Command.inc | 2 +- .../DefaultObjects/ItemType/Health.inc | 2 +- .../DefaultObjects/ItemType/ItemsList.inc | 2 +- .../DefaultObjects/ItemType/Money.inc | 4 +- .../DefaultObjects/ItemType/Random.inc | 4 +- .../DefaultObjects/ItemType/Speed.inc | 2 +- .../Objects/Items/Instance.inc | 43 ++++--- amxmodx/scripting/VipM-M-WeaponMenu.sma | 2 +- amxmodx/scripting/VipM-ModulesLimiter.sma | 12 +- amxmodx/scripting/VipM/Core/API/Main.inc | 2 +- .../VipM/Core/Objects/Limits/Type.inc | 2 +- .../VipM/Core/Objects/Limits/Unit.inc | 4 +- .../VipM/Core/Objects/Modules/Type.inc | 2 +- .../VipM/Core/Objects/Modules/Unit.inc | 4 +- .../scripting/VipM/Core/Objects/VipUnit.inc | 4 +- amxmodx/scripting/VipM/Core/VipsManager.inc | 2 +- amxmodx/scripting/VipM/JsonUtils.inc | 110 ++---------------- amxmodx/scripting/VipM/Utils.inc | 2 +- .../VipM/WeaponMenu/Objects/MenuItem.inc | 4 +- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 4 +- 22 files changed, 62 insertions(+), 157 deletions(-) diff --git a/amxmodx/scripting/IC-I-Limits.sma b/amxmodx/scripting/IC-I-Limits.sma index 53c7efd..7c330b3 100644 --- a/amxmodx/scripting/IC-I-Limits.sma +++ b/amxmodx/scripting/IC-I-Limits.sma @@ -22,12 +22,12 @@ public IC_ItemType_OnInited() { @OnIfRead(const JSON:instanceJson, const Trie:p) { if (!json_object_has_value(instanceJson, "Items")) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `If`."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `If`."); return IC_RET_READ_FAIL; } if (!json_object_has_value(instanceJson, "Limits")) { - Json_LogForFile(instanceJson, "ERROR", "Limits `Items` required for item `If`."); + PCJson_LogForFile(instanceJson, "ERROR", "Limits `Items` required for item `If`."); return IC_RET_READ_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc index 65bbadd..dd62602 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc @@ -15,7 +15,7 @@ DefaultObjects_ItemType_Armor_Register() { TrieDeleteKey(p, "Name"); if (!json_object_has_value(instanceJson, "Armor", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Armor` required for `Armor` item."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Armor` required for `Armor` item."); return IC_RET_READ_FAIL; } TrieSetCell(p, "Armor", json_object_get_number(instanceJson, "Armor")); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc index 8c78e7b..06fe627 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -15,7 +15,7 @@ DefaultObjects_ItemType_Command_Register() { TrieDeleteKey(p, "Name"); if (!json_object_has_value(instanceJson, "Command", JSONString)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Command` required for item `Command`."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Command` required for item `Command`."); return IC_RET_READ_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc index bb41aee..44782ae 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -16,7 +16,7 @@ DefaultObjects_ItemType_Health_Register() { TrieDeleteKey(p, "Name"); if (!json_object_has_value(instanceJson, "Health", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Health` required for `Health` item."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Health` required for `Health` item."); return IC_RET_READ_FAIL; } TrieSetCell(p, "Health", json_object_get_real(instanceJson, "Health")); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc index a75406a..1a1e184 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc @@ -15,7 +15,7 @@ DefaultObjects_ItemType_ItemsList_Register() { TrieDeleteKey(p, "Name"); if (!json_object_has_value(instanceJson, "Items")) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `ItemsList`."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `ItemsList`."); return IC_RET_READ_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc index d6d55ac..791572d 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -15,7 +15,7 @@ DefaultObjects_ItemType_Money_Register() { TrieDeleteKey(p, "Name"); if (!json_object_has_value(instanceJson, "Amount", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Amount` required for item `Money`."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Amount` required for item `Money`."); return IC_RET_READ_FAIL; } TrieSetCell(p, "Amount", json_object_get_number(instanceJson, "Amount")); @@ -25,7 +25,7 @@ DefaultObjects_ItemType_Money_Register() { json_object_get_string(instanceJson, "GiveType", sBuffer, charsmax(sBuffer)); new accountSet = ItemType_Money_StrToAccountSet(sBuffer); if (accountSet < 0) { - Json_LogForFile(instanceJson, "ERROR", "Invalid `GiveType` value (%s). Expected `Set` or `Add`.", sBuffer); + PCJson_LogForFile(instanceJson, "ERROR", "Invalid `GiveType` value (%s). Expected `Set` or `Add`.", sBuffer); } else { TrieSetCell(p, "GiveType", accountSet); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc index 308f898..df01eaf 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc @@ -16,13 +16,13 @@ DefaultObjects_ItemType_Random_Register() { // TODO: Сделать как-то разные шансы if (!json_object_has_value(instanceJson, "Items")) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `Random`."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `Random`."); return IC_RET_READ_FAIL; } new Array:aItems = Json_Object_IC_GetItems(instanceJson, "Items"); if (ArraySizeSafe(aItems) <= 1) { - Json_LogForFile(instanceJson, "ERROR", "Param `Items` must have >1 items."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` must have >1 items."); ArrayDestroy(aItems); return IC_RET_READ_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc index 91b2214..c270c1f 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc @@ -24,7 +24,7 @@ DefaultObjects_ItemType_Speed_Register() { TrieDeleteKey(p, "Name"); if (!json_object_has_value(instanceJson, "Multiplier", JSONNumber)) { - Json_LogForFile(instanceJson, "ERROR", "Param `Multiplier` required for item `Speed`."); + PCJson_LogForFile(instanceJson, "ERROR", "Param `Multiplier` required for item `Speed`."); return IC_RET_READ_FAIL; } TrieSetCell(p, "Multiplier", json_object_get_real(instanceJson, "Multiplier")); diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc index 1316875..5110a7c 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc @@ -6,6 +6,7 @@ #include #include +#include #include "VipM/Forwards" #include "VipM/Utils" #include "VipM/JsonUtils" @@ -100,7 +101,7 @@ T_IC_Item:ItemInstance_Free(&T_IC_Item:instance, const bool:orFail = false) { T_IC_Item:ItemInstance_ReadFromJsonObject(const JSON:instanceJson) { if (!json_is_object(instanceJson)) { - Json_ErrorForFile(instanceJson, "Invalid item object (json value is not an object)."); + PCJson_ErrorForFile(instanceJson, "Invalid item object (json value is not an object)."); return Invalid_IC_Item; } @@ -108,22 +109,22 @@ T_IC_Item:ItemInstance_ReadFromJsonObject(const JSON:instanceJson) { if (json_object_has_value(instanceJson, "Item", JSONString)) { json_object_get_string(instanceJson, "Item", typeName, charsmax(typeName)); } else if (json_object_has_value(instanceJson, "Type", JSONString)) { - Json_LogForFile(instanceJson, "WARNING", "Item object with field `Type` is deprecated, use `Item` field instead."); + PCJson_LogForFile(instanceJson, "WARNING", "Item object with field `Type` is deprecated, use `Item` field instead."); json_object_get_string(instanceJson, "Type", typeName, charsmax(typeName)); } else { - Json_ErrorForFile(instanceJson, "Invalid item object (must contains `Item` field)."); + PCJson_ErrorForFile(instanceJson, "Invalid item object (must contains `Item` field)."); return Invalid_IC_Item; } trim(typeName); if (!typeName[0]) { - Json_ErrorForFile(instanceJson, "Item type is empty."); + PCJson_ErrorForFile(instanceJson, "Item type is empty."); return Invalid_IC_Item; } new T_IC_ItemType:type = ItemType_Find(typeName); if (type == Invalid_IC_ItemType) { - Json_ErrorForFile(instanceJson, "Item type '%s' not found.", typeName); + PCJson_ErrorForFile(instanceJson, "Item type '%s' not found.", typeName); return Invalid_IC_Item; } @@ -137,33 +138,29 @@ T_IC_Item:ItemInstance_ReadFromJsonObject(const JSON:instanceJson) { } Array:ItemInstance_ReadArrayFromJsonValue(const JSON:instancesJson, &Array:array = Invalid_Array) { - if (json_is_array(instancesJson)) { - if (array == Invalid_Array) { - array = ArrayCreate(1, json_array_get_count(instancesJson)); - } - - for (new i = 0, ii = json_array_get_count(instancesJson); i < ii; i++) { - new JSON:instanceJson = json_array_get_value(instancesJson, i); + if (array == Invalid_Array) { + array = ArrayCreate(1, 1); + } - new T_IC_Item:instance = ItemInstance_ReadFromJsonObject(instanceJson); - if (instance != Invalid_IC_Item) { - ArrayPushCell(array, instance); - } + new JSON:linkedJson; + PCJson_HandleLinkedValue(instancesJson, linkedJson); + if (json_is_array(linkedJson)) { + for (new i = 0, ii = json_array_get_count(linkedJson); i < ii; i++) { + new JSON:instanceJson = json_array_get_value(linkedJson, i); + ItemInstance_ReadArrayFromJsonValue(instanceJson, array); json_free(instanceJson); } - } else if (json_is_object(instancesJson)) { - if (array == Invalid_Array) { - array = ArrayCreate(1, 1); - } - - new T_IC_Item:instance = ItemInstance_ReadFromJsonObject(instancesJson); + } else if (json_is_object(linkedJson)) { + new T_IC_Item:instance = ItemInstance_ReadFromJsonObject(linkedJson); if (instance != Invalid_IC_Item) { ArrayPushCell(array, instance); } } else { - Json_ErrorForFile(instancesJson, "Json value must be an array or an object."); + PCJson_ErrorForFile(linkedJson, "Json value must be an array or an object."); } + + PCJson_FreeLinked(linkedJson); return array; } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index c61f861..9814109 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -71,7 +71,7 @@ public VipM_OnInitModules() { @OnReadConfig(const JSON:jCfg, Trie:tParams) { if (!json_object_has_value(jCfg, "Menus")) { - Json_LogForFile(jCfg, "WARNING", "Param 'Menus' required for module '%s'.", MODULE_NAME); + PCJson_LogForFile(jCfg, "WARNING", "Param 'Menus' required for module '%s'.", MODULE_NAME); return VIPM_STOP; } diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index dedeb9c..56be7a1 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -44,21 +44,21 @@ public VipM_OnActivateModule(const sModuleName[]) { Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { TrieCreateIfNotCreated(tModules); - new JSON:jFile = Json_ParseFromFileEx(sFileName); + new JSON:jFile = PCJson_ParseFile(sFileName); if (jFile == Invalid_JSON) { log_error(0, "Invalid JSON syntax. File `%s`.", GET_FILE_JSON_PATH(sFileName)); return tModules; } if (!json_is_array(jFile)) { - Json_LogForFile(jFile, "WARNING", "Root value must be an array."); + PCJson_LogForFile(jFile, "WARNING", "Root value must be an array."); Json_FreeEx(jFile); return tModules; } json_array_foreach_value (jFile: i => jItem) { if (!json_is_object(jItem)) { - Json_LogForFile(jItem, "WARNING", "Array item #%d isn`t object.", i); + PCJson_LogForFile(jItem, "WARNING", "Array item #%d isn`t object.", i); json_free(jItem); continue; } @@ -67,20 +67,20 @@ Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits); json_free(jLimits); if (!ArraySizeSafe(aLimits)) { - Json_LogForFile(jItem, "WARNING", "Field `Limits` must have 1 or more items."); + PCJson_LogForFile(jItem, "WARNING", "Field `Limits` must have 1 or more items."); json_free(jItem); continue; } new Array:aModuleNames = json_object_get_strings_list(jItem, "Modules", VIPM_MODULES_TYPE_NAME_MAX_LEN); if (!ArraySizeSafe(aModuleNames)) { - Json_LogForFile(jItem, "WARNING", "Field `Modules` must have 1 or more items."); + PCJson_LogForFile(jItem, "WARNING", "Field `Modules` must have 1 or more items."); continue; } ArrayForeachString (aModuleNames: j => sModuleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]) { if (TrieKeyExists(tModules, sModuleName)) { - Json_LogForFile(jItem, "WARNING", "Duplicate limits for module `%s`.", sModuleName); + PCJson_LogForFile(jItem, "WARNING", "Duplicate limits for module `%s`.", sModuleName); continue; } diff --git a/amxmodx/scripting/VipM/Core/API/Main.inc b/amxmodx/scripting/VipM/Core/API/Main.inc index b3c7957..2a9ea7c 100644 --- a/amxmodx/scripting/VipM/Core/API/Main.inc +++ b/amxmodx/scripting/VipM/Core/API/Main.inc @@ -30,5 +30,5 @@ API_Main_Init() { vdformat(sMessage, charsmax(sMessage), Arg_sMessage, Arg_fmtArgs); get_string(Arg_sPrefix, sPrefix, charsmax(sPrefix)); - Json_LogForFile(JSON:get_param(Arg_jValue), sPrefix, sMessage); + PCJson_LogForFile(JSON:get_param(Arg_jValue), sPrefix, sMessage); } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index f3be46a..72fb036 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -116,7 +116,7 @@ Trie:LimitType_ReadParams(const T_LimitType:iLimitType, const JSON:jParams) { new sErrParam[VIPM_PARAM_NAME_MAX_LEN]; if (!CfgParam_ReadList(jParams, tParams, LimitType[LimitType_Params], sErrParam, charsmax(sErrParam))) { - Json_ErrorForFile(jParams, "Param '%s' required for '%s' limit.", sErrParam, LimitType[LimitType_Name]); + PCJson_ErrorForFile(jParams, "Param '%s' required for '%s' limit.", sErrParam, LimitType[LimitType_Name]); TrieDestroy(tParams); return Invalid_Trie; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 93726d2..9a20bc9 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -68,14 +68,14 @@ static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { trim(sLimitTypeName); if (!sLimitTypeName[0]) { - Json_ErrorForFile(jLimitUnit, "Limit type name not specified."); + PCJson_ErrorForFile(jLimitUnit, "Limit type name not specified."); return Invalid_LimitType; } new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); if (iLimitType == Invalid_LimitType) { - Json_ErrorForFile(jLimitUnit, "Limit type '%s' not found.", sLimitTypeName); + PCJson_ErrorForFile(jLimitUnit, "Limit type '%s' not found.", sLimitTypeName); return Invalid_LimitType; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index f946419..c19ac7e 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -115,7 +115,7 @@ Trie:ModuleType_ReadParams(const T_ModuleType:iModuleType, const JSON:jParams) { new sErrParam[VIPM_PARAM_NAME_MAX_LEN]; if (!CfgParam_ReadList(jParams, tParams, ModuleType[ModuleType_Params], sErrParam, charsmax(sErrParam))) { - Json_ErrorForFile(jParams, "Param '%s' required for '%s' module.", sErrParam, ModuleType[ModuleType_Name]); + PCJson_ErrorForFile(jParams, "Param '%s' required for '%s' module.", sErrParam, ModuleType[ModuleType_Name]); TrieDestroy(tParams); return Invalid_Trie; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index cb811e5..fb9ae75 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -64,14 +64,14 @@ static T_ModuleType:ModuleUnit__ReadType(const JSON:jModuleUnit) { trim(sModuleTypeName); if (!sModuleTypeName[0]) { - Json_ErrorForFile(jModuleUnit, "Module type name not specified."); + PCJson_ErrorForFile(jModuleUnit, "Module type name not specified."); return Invalid_ModuleType; } new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); if (iModuleType == Invalid_ModuleType) { - Json_ErrorForFile(jModuleUnit, "Module type '%s' not found.", sModuleTypeName); + PCJson_ErrorForFile(jModuleUnit, "Module type '%s' not found.", sModuleTypeName); return Invalid_ModuleType; } diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index facd64e..a8bfccd 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -90,11 +90,11 @@ T_VipUnit:VipUnit_Read(const JSON:jVipUnit) { { new Array:aAccess = JsonObject_GetLimitUnits(jVipUnit, "Access"); if (aAccess == Invalid_Array) { - Json_LogForFile(jVipUnit, "ERROR", "Field 'Access' is required in vip object."); + PCJson_LogForFile(jVipUnit, "ERROR", "Field 'Access' is required in vip object."); } else { new Array:aModules = JsonObject_GetModuleUnits(jVipUnit, "Modules"); if (aModules == Invalid_Array) { - Json_LogForFile(jVipUnit, "ERROR", "Field 'Modules' is required in vip object."); + PCJson_LogForFile(jVipUnit, "ERROR", "Field 'Modules' is required in vip object."); } else { iVipUnit = VipUnit__Construct(aAccess, aModules); } diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc index c5f165b..a3533f9 100644 --- a/amxmodx/scripting/VipM/Core/VipsManager.inc +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -36,7 +36,7 @@ bool:VipsManager_LoadFromFile(const sFilePath[]) { return false; } - new JSON:jVipUnits = Json_ParseFromFileEx(sFilePath, g_sRootDir); + new JSON:jVipUnits = PCJson_ParseFile(sFilePath, g_sRootDir); g_aVips = VipUnit_ReadList(jVipUnits, g_aVips); Json_FreeEx(jVipUnits); diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index d7dc62f..f31226b 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -5,46 +5,18 @@ #include #include - -// Метка для распознавания обёрток -stock static const __JSON_WRAPPER_MARK_KEY[] = "!@#--some-random-string-for-identify-wrapper--!@#"; - -// Путь до директории, откуда начинать считать ссылки -stock static const __JSON_WRAPPER_FIELD_WORKDIR[] = "_work_dir"; - -// Файл, из которого было прочитано значение -stock static const __JSON_WRAPPER_FIELD_FILE[] = "_file"; - -// Само значение -stock static const __JSON_WRAPPER_FIELD_VALUE[] = "_value"; - -// Корневой хендлер обёртки (c m_bMustBeFreed == true) -stock static const __JSON_WRAPPER_FIELD_HANDLER[] = "_handler"; - -// Префикс ссылки на файл -stock static const __JSON_WRAPPER_REF_FILE_PREFIX[] = "File:"; +#include #define JSON_UTILS__MAX_KEY_LENGTH 128 #define JSON_UTILS__MAX_STRING_LENGTH 256 #define JSON_UTILS__MAX_REF_LENGTH 128 -#define Json__CompositeMacros(%1) \ - do { %1 } while(is_linux_server() == 0xDEADBEEF) - -#define Json__VFormatEx(%1,%2,%3) Json__CompositeMacros( \ - if (numargs() >= %3) { \ - vformat(%1, charsmax(%1), %2, %3); \ - } else { \ - copy(%1, charsmax(%1), %2); \ - } \ -) - static stock Json__IsWrapper(const JSON:jValue) { if (jValue == Invalid_JSON || !json_is_object(jValue)) { return false; } - if (!json_object_has_value(jValue, __JSON_WRAPPER_MARK_KEY, JSONString)) { + if (!json_object_has_value(jValue, PC_JSON_WRAPPER_FIELD_ROOT, JSONBoolean)) { return false; } @@ -79,7 +51,7 @@ static stock JSON:Json__FreeWrapper(&JSON:jWrapper, const bool:bFreeIfNotWrapper return jWrapper; } - new JSON:iRootWrapperHandler = JSON:json_object_get_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER); + new JSON:iRootWrapperHandler = JSON:json_object_get_number(jWrapper, PC_JSON_WRAPPER_FIELD_HANDLER); if (iRootWrapperHandler != jWrapper) { json_free(jWrapper); } @@ -114,7 +86,7 @@ static stock Json__GetWrapperPathValue( static stock Json__GetFilePath(const JSON:jValue, sOut[] = "", const iOutLen = 0, const sDefault[] = "") { new sPath[PLATFORM_MAX_PATH]; - Json__GetWrapperPathValue(jValue, __JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath), sDefault); + Json__GetWrapperPathValue(jValue, PC_JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath), sDefault); copy(sOut, iOutLen, sPath); return sPath; @@ -122,7 +94,7 @@ static stock Json__GetFilePath(const JSON:jValue, sOut[] = "", const iOutLen = 0 static stock Json__GetWorkDir(const JSON:jValue, sOut[] = "", const iOutLen = 0, const sDefault[] = "") { new sPath[PLATFORM_MAX_PATH]; - Json__GetWrapperPathValue(jValue, __JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath), sDefault); + Json__GetWrapperPathValue(jValue, PC_JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath), sDefault); copy(sOut, iOutLen, sPath); return sPath; @@ -161,44 +133,6 @@ static stock Json__GetFileDir(const sFile[]) { return sDir; } -/** - * Парсит JSON-значение из файла, добавляя обёртку для расширения функционала. - * - * @param sPath Путь до файла. - * @param sWorkDir Корневая директория для ссылок. По умолчанию будет директория, в которой лежит читаемый файл. - * - * @note Полученные из этой функции хендлеры обязательно должны освобождаться при помощи Json_FreeEx. - * Иначе, из-за обёртки, данные останутся в памяти. - * - * @return Хендлер прочитанного из файла значения. - */ -stock JSON:Json_ParseFromFileEx(const sPath[], const sWorkDir[] = "", const bool:bWithComments = true) { - if (!file_exists(sPath)) { - log_amx("[ERROR] File '%s' not found.", sPath); - return Invalid_JSON; - } - - new JSON:jFile = json_parse(sPath, true, bWithComments); - if (jFile == Invalid_JSON) { - log_amx("[ERROR] Can't read JSON from file '%s'.", sPath); - return Invalid_JSON; - } - - new JSON:jWrapper = json_init_object(); - json_object_set_string(jWrapper, __JSON_WRAPPER_MARK_KEY, __JSON_WRAPPER_MARK_KEY); - json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_FILE, sPath); - json_object_set_value(jWrapper, __JSON_WRAPPER_FIELD_VALUE, jFile); - json_object_set_number(jWrapper, __JSON_WRAPPER_FIELD_HANDLER, _:jWrapper); - - if (sWorkDir[0]) { - json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, sWorkDir); - } else { - json_object_set_string(jWrapper, __JSON_WRAPPER_FIELD_WORKDIR, Json__GetFileDir(sPath)); - } - - return jFile; -} - stock JSON:Json_FreeEx(&JSON:jValue) { new JSON:jParent = json_get_parent(jValue); Json__FreeWrapper(jParent, false); @@ -246,32 +180,6 @@ static stock JSON:Json__GetRoot(const JSON:jValue) { return jIterator; } -new stock const __Json_LogForFile_templateFile[] = "[JSON][%s] File: %s"; -new stock const __Json_LogForFile_templateMessage[] = "[JSON][%s] Message: %s"; -stock Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...) { - static sFormattedMessage[1024]; - Json__VFormatEx(sFormattedMessage, sMessage, 4); - - log_amx(__Json_LogForFile_templateFile, sPrefix, Json__GetFilePath(jValue, .sDefault="*unknown file*")); - log_amx(__Json_LogForFile_templateMessage, sPrefix, sFormattedMessage); -} - -new stock const __Json_ErrorForFile_template[] = "[JSON][ERROR] %s: %s"; -stock Json_ErrorForFile(const JSON:jValue, const sMessage[], any:...) { - static sFormattedMessage[1024]; - Json__VFormatEx(sFormattedMessage, sMessage, 3); - - abort(0, __Json_ErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); -} - -new stock const __Json_FatalErrorForFile_template[] = "[JSON] %s: %s"; -stock Json_FatalErrorForFile(const JSON:jValue, const sMessage[], any:...) { - static sFormattedMessage[1024]; - Json__VFormatEx(sFormattedMessage, sMessage, 3); - - set_fail_state(__Json_FatalErrorForFile_template, Json__GetFilePath(jValue, .sDefault="*unknown file*"), sFormattedMessage); -} - /** * Проверяет, является ли значение ссылкой. * @@ -290,12 +198,12 @@ stock bool:Json_IsRef(const JSON:jValue, sFileName[] = "", const iLen = 0) { new Str[JSON_UTILS__MAX_REF_LENGTH]; json_get_string(jValue, Str, charsmax(Str)); - if (!equali(__JSON_WRAPPER_REF_FILE_PREFIX, Str, charsmax(__JSON_WRAPPER_REF_FILE_PREFIX))) { + if (!equali(PC_JSON_WRAPPER_LINK_PREFIX_FILE, Str, charsmax(PC_JSON_WRAPPER_LINK_PREFIX_FILE))) { return false; } if (iLen > 0) { - copy(sFileName, iLen, Str[charsmax(__JSON_WRAPPER_REF_FILE_PREFIX)]); + copy(sFileName, iLen, Str[charsmax(PC_JSON_WRAPPER_LINK_PREFIX_FILE)]); } return true; @@ -351,7 +259,7 @@ stock JSON:Json_GetRefValue( } bIsRef = true; - return Json_ParseFromFileEx(sFileName, sWorkDir); + return PCJson_ParseFile(sFileName, sWorkDir); } stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { @@ -361,7 +269,7 @@ stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) if (!json_is_object(jObject)) { // А надо ли ошибку бросать? - Json_ErrorForFile(jObject, "Json_ReadObjectToTrie: JSON-value must be an object."); + PCJson_ErrorForFile(jObject, "Json_ReadObjectToTrie: JSON-value must be an object."); return tTrie; } diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 8913255..850c573 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -73,7 +73,7 @@ stock IsPlayerAlive(const playerIndex) { GET_FILE(fmt(__JSON_FILE_TEMPLATE_STR, %1)) #define GET_FILE_JSON(%1) \ - Json_ParseFromFileEx(GET_FILE_JSON_PATH(%1), GET_FILE("")) + PCJson_ParseFile(GET_FILE_JSON_PATH(%1), GET_FILE("")) #define JSON_FILE_EXTSTS(%1) \ file_exists(GET_FILE_JSON_PATH(%1)) diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index ecbd58b..4c6069d 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -30,7 +30,7 @@ bool:MenuItem_Read(const JSON:jMenuItem, MenuItem[S_MenuItem]) { new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenuItem, .bIsRef = bIsRef); if (!json_is_object(jRefed)) { - Json_LogForFile(jRefed, "WARNING", "Invalid menu item format."); + PCJson_LogForFile(jRefed, "WARNING", "Invalid menu item format."); return false; } @@ -78,7 +78,7 @@ Array:MenuItem_ReadList(const JSON:jMenuItems, &Array:aMenuItems = Invalid_Array } } default: { - Json_LogForFile(jRefed, "WARNING", "Invalid menu items format."); + PCJson_LogForFile(jRefed, "WARNING", "Invalid menu items format."); } } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 237d9f7..6a6fcb4 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -43,7 +43,7 @@ bool:WeaponMenu_Read(&JSON:jMenu, Menu[S_WeaponMenu]) { Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(jRefed, "Items"); if (Menu[WeaponMenu_Items] == Invalid_Array) { - Json_LogForFile(jRefed, "WARNING", "Menu items list are empty."); + PCJson_LogForFile(jRefed, "WARNING", "Menu items list are empty."); Json_FreeExIf(jRefed, bIsRef); return false; } @@ -78,7 +78,7 @@ Array:WeaponMenu_ReadList(const JSON:jWeaponMenus, &Array:aWeaponMenus = Invalid } } default: { - Json_LogForFile(jRefed, "WARNING", "Invalid weapon menus format."); + PCJson_LogForFile(jRefed, "WARNING", "Invalid weapon menus format."); } } From f7100bfeec399b293ebcf0c9183dd8ef11283e40 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 2 Mar 2025 05:25:27 +0300 Subject: [PATCH 033/108] Fix misc --- amxmodx/scripting/VipM-Misc.sma | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM-Misc.sma b/amxmodx/scripting/VipM-Misc.sma index b1a0433..cd7cdf0 100644 --- a/amxmodx/scripting/VipM-Misc.sma +++ b/amxmodx/scripting/VipM-Misc.sma @@ -21,7 +21,7 @@ public VipM_OnLoaded() { #endif #if RELOAD_ON_ROUND_START - RegisterHookChain(RG_CSGameRules_RestartRound, "@OnPlayerSpawned", false); + RegisterHookChain(RG_CSGameRules_RestartRound, "@ReloadAllPlayers", false); #endif #if RELOAD_ON_ROUND_END From f9e3ff774a0fad3862c354a50c7a7930e5cfeb20 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 2 Mar 2025 05:28:14 +0300 Subject: [PATCH 034/108] Fox modules limiter --- amxmodx/scripting/VipM-ModulesLimiter.sma | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 56be7a1..36d85d9 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -44,7 +44,7 @@ public VipM_OnActivateModule(const sModuleName[]) { Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { TrieCreateIfNotCreated(tModules); - new JSON:jFile = PCJson_ParseFile(sFileName); + new JSON:jFile = PCJson_ParseFile(GET_FILE_JSON_PATH(sFileName)); if (jFile == Invalid_JSON) { log_error(0, "Invalid JSON syntax. File `%s`.", GET_FILE_JSON_PATH(sFileName)); return tModules; From 265da3358c4014f5170d06556a41121f2e31ca7a Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 3 Mar 2025 00:55:50 +0300 Subject: [PATCH 035/108] Use cached links handle for base objects --- amxmodx/scripting/VipM-ModulesLimiter.sma | 4 +- .../VipM/Core/Objects/Limits/Unit.inc | 43 +-- .../VipM/Core/Objects/Modules/Unit.inc | 37 ++- .../scripting/VipM/Core/Objects/VipUnit.inc | 48 ++-- amxmodx/scripting/VipM/Core/VipsManager.inc | 2 +- amxmodx/scripting/VipM/JsonUtils.inc | 258 +----------------- 6 files changed, 88 insertions(+), 304 deletions(-) diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 36d85d9..3923ce9 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -52,7 +52,7 @@ Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) if (!json_is_array(jFile)) { PCJson_LogForFile(jFile, "WARNING", "Root value must be an array."); - Json_FreeEx(jFile); + PCJson_Free(jFile); return tModules; } @@ -91,6 +91,6 @@ Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) ArrayDestroy(aModuleNames); } - Json_FreeEx(jFile); + PCJson_Free(jFile); return tModules; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 9a20bc9..175c4d0 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -82,25 +82,34 @@ static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { return iLimitType; } -T_LimitUnit:LimitUnit_Read(const JSON:jLimitUnit) { - static Trie:tCache = Invalid_Trie; - TrieCreateIfNotCreated(tCache); - - new JSON:jRefed, T_LimitUnit:iLimitUnit = Invalid_LimitUnit; - Json_GetCachedRefValue_Begin(jLimitUnit, tCache, iLimitUnit, jRefed) - { - new T_LimitType:iLimitType = LimitUnit__ReadType(jRefed); - new Trie:tParams = Invalid_Trie; - - if (iLimitType != Invalid_LimitType) { - tParams = LimitType_ReadParams(iLimitType, jRefed); - } +T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { + static Trie:cache = Invalid_Trie; + TrieCreateIfNotCreated(cache); + + new JSON:linked, T_LimitUnit:cached = Invalid_LimitUnit, linkPath[PLATFORM_MAX_PATH]; + if (PCJson_HandleCachedLinkedValue(cache, valueJson, linked, cached, linkPath, charsmax(linkPath)) == PCJson_CachedLinkedValue_Cached) { + return cached; + } - if (tParams != Invalid_Trie) { - iLimitUnit = LimitUnit__Construct(iLimitType, tParams); - } + new T_LimitType:type = LimitUnit__ReadType(linked); + if (type == Invalid_LimitType) { + PCJson_FreeLinked(linked); + return Invalid_LimitUnit; } - Json_GetCachedRefValue_End(jLimitUnit, tCache, iLimitUnit, jRefed) + + new Trie:p = LimitType_ReadParams(type, linked); + if (p == Invalid_Trie) { + PCJson_FreeLinked(linked); + return Invalid_LimitUnit; + } + + cached = LimitUnit__Construct(type, p); + if (linkPath[0] != EOS && cached != Invalid_LimitUnit) { + TrieSetCell(cache, linkPath, cached); + } + + PCJson_FreeLinked(linked); + return cached; } Array:LimitUnit_ReadList(const JSON:jLimitUnits, &Array:aLimitUnits = Invalid_Array) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index fb9ae75..9d2f183 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -79,24 +79,33 @@ static T_ModuleType:ModuleUnit__ReadType(const JSON:jModuleUnit) { } T_ModuleUnit:ModuleUnit_Read(const JSON:jModuleUnit) { - static Trie:tCache = Invalid_Trie; - TrieCreateIfNotCreated(tCache); + static Trie:cache = Invalid_Trie; + TrieCreateIfNotCreated(cache); + + new JSON:linked, T_ModuleUnit:cached = Invalid_ModuleUnit, linkPath[PLATFORM_MAX_PATH]; + if (PCJson_HandleCachedLinkedValue(cache, valueJson, linked, cached, linkPath, charsmax(linkPath)) == PCJson_CachedLinkedValue_Cached) { + return cached; + } - new JSON:jRefed, T_ModuleUnit:iModuleUnit = Invalid_ModuleUnit; - Json_GetCachedRefValue_Begin(jModuleUnit, tCache, iModuleUnit, jRefed) - { - new T_ModuleType:iModuleType = ModuleUnit__ReadType(jRefed); - new Trie:tParams = Invalid_Trie; + new T_LimitType:type = ModuleUnit__ReadType(linked); + if (type == Invalid_ModuleType) { + PCJson_FreeLinked(linked); + return Invalid_ModuleUnit; + } - if (iModuleType != Invalid_ModuleType) { - tParams = ModuleType_ReadParams(iModuleType, jRefed); - } + new Trie:p = LimitType_ReadParams(type, linked); + if (p == Invalid_Trie) { + PCJson_FreeLinked(linked); + return Invalid_ModuleUnit; + } - if (tParams != Invalid_Trie) { - iModuleUnit = ModuleUnit__Construct(iModuleType, tParams); - } + cached = ModuleUnit__Construct(type, p); + if (linkPath[0] != EOS && cached != Invalid_ModuleUnit) { + TrieSetCell(cache, linkPath, cached); } - Json_GetCachedRefValue_End(jModuleUnit, tCache, iModuleUnit, jRefed) + + PCJson_FreeLinked(linked); + return cached; } Array:ModuleUnit_ReadList(const JSON:jModuleUnits, &Array:aModuleUnits = Invalid_Array) { diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index a8bfccd..4de73c7 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -81,26 +81,36 @@ Array:VipUnit_GetModules(const T_VipUnit:iVipUnit) { return VipUnit__GetValue(iVipUnit, VipUnit_Modules); } -T_VipUnit:VipUnit_Read(const JSON:jVipUnit) { - static Trie:tCache = Invalid_Trie; - TrieCreateIfNotCreated(tCache); - - new JSON:jRefed, T_VipUnit:iVipUnit = Invalid_VipUnit; - Json_GetCachedRefValue_Begin(jVipUnit, tCache, iVipUnit, jRefed) - { - new Array:aAccess = JsonObject_GetLimitUnits(jVipUnit, "Access"); - if (aAccess == Invalid_Array) { - PCJson_LogForFile(jVipUnit, "ERROR", "Field 'Access' is required in vip object."); - } else { - new Array:aModules = JsonObject_GetModuleUnits(jVipUnit, "Modules"); - if (aModules == Invalid_Array) { - PCJson_LogForFile(jVipUnit, "ERROR", "Field 'Modules' is required in vip object."); - } else { - iVipUnit = VipUnit__Construct(aAccess, aModules); - } - } +T_VipUnit:VipUnit_Read(const JSON:valueJson) { + static Trie:cache = Invalid_Trie; + TrieCreateIfNotCreated(cache); + + new JSON:linked, T_VipUnit:cached = Invalid_VipUnit, linkPath[PLATFORM_MAX_PATH]; + if (PCJson_HandleCachedLinkedValue(cache, valueJson, linked, cached, linkPath, charsmax(linkPath)) == PCJson_CachedLinkedValue_Cached) { + return cached; + } + + new Array:aAccess = JsonObject_GetLimitUnits(linked, "Access"); + if (aAccess == Invalid_Array) { + PCJson_ErrorForFile(linked, "Field 'Access' is required in vip object."); + PCJson_FreeLinked(linked); + return Invalid_VipUnit; } - Json_GetCachedRefValue_End(jVipUnit, tCache, iVipUnit, jRefed) + + new Array:aModules = JsonObject_GetModuleUnits(linked, "Modules"); + if (aModules == Invalid_Array) { + PCJson_ErrorForFile(linked, "Field 'Modules' is required in vip object."); + PCJson_FreeLinked(linked); + return Invalid_VipUnit; + } + + cached = VipUnit__Construct(aAccess, aModules); + if (linkPath[0] != EOS && cached != Invalid_VipUnit) { + TrieSetCell(cache, linkPath, cached); + } + + PCJson_FreeLinked(linked); + return cached; } Array:VipUnit_ReadList(const JSON:jVipUnits, &Array:aVipUnits = Invalid_Array) { diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc index a3533f9..803fde9 100644 --- a/amxmodx/scripting/VipM/Core/VipsManager.inc +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -38,7 +38,7 @@ bool:VipsManager_LoadFromFile(const sFilePath[]) { new JSON:jVipUnits = PCJson_ParseFile(sFilePath, g_sRootDir); g_aVips = VipUnit_ReadList(jVipUnits, g_aVips); - Json_FreeEx(jVipUnits); + PCJson_Free(jVipUnits); return true; } diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index f31226b..9431dc5 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -11,175 +11,14 @@ #define JSON_UTILS__MAX_STRING_LENGTH 256 #define JSON_UTILS__MAX_REF_LENGTH 128 -static stock Json__IsWrapper(const JSON:jValue) { - if (jValue == Invalid_JSON || !json_is_object(jValue)) { - return false; - } - - if (!json_object_has_value(jValue, PC_JSON_WRAPPER_FIELD_ROOT, JSONBoolean)) { - return false; - } - - new JSON:jParent = json_get_parent(jValue); - if (jParent != Invalid_JSON) { - json_free(jParent); - return false; - } - - return true; -} - -static stock JSON:Json__GetWrapper(const JSON:jValue) { - new JSON:jRoot = Json__GetRoot(jValue); - - if (jRoot == jValue) { - return Invalid_JSON; - } - - if (!Json__IsWrapper(jRoot)) { - json_free(jRoot); - - return Invalid_JSON; - } - - return jRoot; -} - -static stock JSON:Json__FreeWrapper(&JSON:jWrapper, const bool:bFreeIfNotWrapper = false) { - if (!Json__IsWrapper(jWrapper)) { - Json_FreeIf(jWrapper, bFreeIfNotWrapper); - return jWrapper; - } - - new JSON:iRootWrapperHandler = JSON:json_object_get_number(jWrapper, PC_JSON_WRAPPER_FIELD_HANDLER); - if (iRootWrapperHandler != jWrapper) { - json_free(jWrapper); - } - json_free(iRootWrapperHandler); - - return Invalid_JSON; -} - -static stock Json__GetWrapperPathValue( - const JSON:jValue, - const sKey[], - sOut[] = "", - const iOutLen = 0, - const sDefault[] = "" -) { - new JSON:jWrapper = Json__GetWrapper(jValue); - - new sPath[PLATFORM_MAX_PATH]; - if (jWrapper == Invalid_JSON) { - copy(sPath, charsmax(sPath), sDefault); - } else { - json_object_get_string(jWrapper, sKey, sPath, charsmax(sPath)); - json_free(jWrapper); - } - - if (iOutLen) { - copy(sOut, iOutLen, sPath); - } - - return sPath; -} - -static stock Json__GetFilePath(const JSON:jValue, sOut[] = "", const iOutLen = 0, const sDefault[] = "") { - new sPath[PLATFORM_MAX_PATH]; - Json__GetWrapperPathValue(jValue, PC_JSON_WRAPPER_FIELD_FILE, sPath, charsmax(sPath), sDefault); - - copy(sOut, iOutLen, sPath); - return sPath; -} - -static stock Json__GetWorkDir(const JSON:jValue, sOut[] = "", const iOutLen = 0, const sDefault[] = "") { - new sPath[PLATFORM_MAX_PATH]; - Json__GetWrapperPathValue(jValue, PC_JSON_WRAPPER_FIELD_WORKDIR, sPath, charsmax(sPath), sDefault); - - copy(sOut, iOutLen, sPath); - return sPath; -} - -static stock Json__GetRootConfigsPath(sOut[] = "", const iOutLen = 0) { - static sPath[PLATFORM_MAX_PATH]; - - if (!sPath[0]) { - get_localinfo("amxx_configsdir", sPath, charsmax(sPath)); - } - - if (iOutLen) { - copy(sOut, iOutLen, sPath); - } - - return sPath; -} - -static stock Json__GetFileDir(const sFile[]) { - new sDir[PLATFORM_MAX_PATH]; - copy(sDir, charsmax(sDir), sFile); - - new i = 0, iLastSlash = -1; - while (sDir[i]) { - if (sDir[i] == '/' || sDir[i] == '\') { - iLastSlash = i; - } - ++i; - } - - if (iLastSlash >= 0) { - sDir[max(iLastSlash - 1, 0)] = 0; // EOS - } - - return sDir; -} - -stock JSON:Json_FreeEx(&JSON:jValue) { - new JSON:jParent = json_get_parent(jValue); - Json__FreeWrapper(jParent, false); - json_free(jValue); - - return jValue; -} - stock JSON:Json_FreeExIf(&JSON:jValue, const bool:bIf) { if (bIf) { - Json_FreeEx(jValue); + PCJson_Free(jValue); } return jValue; } -/** - * Получение хендлера корневого JSON-значения. - * - * @param jValue JSON-хендлер, для которого надо найти корневое значение. - * - * @return JSON-хендлер найденного корневого значения. - */ -static stock JSON:Json__GetRoot(const JSON:jValue) { - if (jValue == Invalid_JSON) { - return Invalid_JSON; - } - - new JSON:jParent; - new JSON:jIterator = json_get_parent(jValue); - if (jIterator == Invalid_JSON) { - return jValue; - } - - while (jIterator != Invalid_JSON) { - jParent = json_get_parent(jIterator); - - if (jParent == Invalid_JSON) { - break; - } - json_free(jIterator); - jIterator = jParent; - } - - return jIterator; -} - /** * Проверяет, является ли значение ссылкой. * @@ -238,28 +77,18 @@ stock JSON:Json_GetRefValue( } new sFileName[PLATFORM_MAX_PATH]; - new sWorkDir[PLATFORM_MAX_PATH]; - - if (sRefFilePath[0] == '/') { - // Если ссылка начинается со слеша, считать её от amxmodx/configs/ - Json__GetRootConfigsPath(sWorkDir, charsmax(sWorkDir)); - } else { - Json__GetWorkDir(jValue, sWorkDir, charsmax(sWorkDir)); - if (!sWorkDir[0]) { - // Если у относительной ссылки нет workdir, значит ссылаться некуда) - return jValue; - } - } - - Json__RightTrim(sWorkDir, '/'); - formatex(sFileName, charsmax(sFileName), "%s/%s.json", sWorkDir, sRefFilePath); + PCPath_MakePath( + sRefFilePath, sFileName, charsmax(sFileName), + .absolutePrefix = PCJson_GetWrapperWorkdir(jValue), + .forceFileExtension = "json" + ); if (iOutLen) { copy(sOut, iOutLen, sFileName); } bIsRef = true; - return PCJson_ParseFile(sFileName, sWorkDir); + return PCJson_ParseFile(sFileName, PCJson_GetWrapperWorkdir(jValue)); } stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { @@ -297,34 +126,6 @@ stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) return tTrie; } -stock bool:Json_FreeIf(&JSON:jValue, const bool:bIf) { - if (bIf) { - json_free(jValue); - } - return bIf; -} - -static stock Json__RightTrim(sStr[], const cTrim = ' ') { - new iLen = Json__StrLen(sStr); - if (iLen <= 0) { - return; - } - - while (sStr[iLen - 1] == cTrim) { - --iLen; - } - - sStr[iLen] = 0; -} - -static stock Json__StrLen(const sStr[]) { - new iLen = 0; - while (sStr[iLen]) { - ++iLen; - } - return iLen; -} - stock bool:Json_Object_GetBool(const JSON:jObj, const sKey[], const bool:bDefault = false, const bool:bDotNot = false) { if (!json_object_has_value(jObj, sKey, JSONBoolean, bDotNot)) { return bDefault; @@ -387,48 +188,3 @@ stock Json_Object_GetColoredChatMessage( return iRes; } - -/* -Обёртка для кеширования ссылок. -! Очень извращённая штука, делал чисто под конкретные задачи ! -! Но в целом, наверное, можно ещё где-то использовать ! - -Пример использования: - -* new JSON:jRefed, T_ModuleUnit:iUnit = Invalid_ModuleUnit; -* Json_GetCachedRefValue_Begin(jModuleUnit, __cache_ModuleUnits, iUnit, jRefed) -* { -* new sModuleUnit[S_ModuleUnit]; -* if (ModuleUnits_ReadFromJson(jRefed, sModuleUnit)) { -* iUnit = ModuleUnits_Push(sModuleUnit); -* } -* } -* Json_GetCachedRefValue_End(jModuleUnit, __cache_ModuleUnits, iUnit, jRefed) - -Между *_Begin и *_End должен быть расположен код разбора -содержимого файла с последующей записью кешируемого значения. - -Обе части в ходе выполнения могут прервать выполнение функции, -при чём вторая часть делает это в любом случае. -Также, это значит что код рабора файла может быть не вызван вовсе. - -На строках обёртки ставить ; не надо. -*/ - -// (const JSON:jValue, const Trie:tCache, &any:iCachedValue, &JSON:jRefed) -#define Json_GetCachedRefValue_Begin(%1,%2,%3,%4) \ - new __Json_GetCachedRefValue_sJsonRef[PLATFORM_MAX_PATH]; \ - if ( \ - Json_IsRef(%1, __Json_GetCachedRefValue_sJsonRef, charsmax(__Json_GetCachedRefValue_sJsonRef)) \ - && TrieGetCell(%2, __Json_GetCachedRefValue_sJsonRef, %3) \ - || ((%4 = Json_GetRefValue(%1)) ? false : false) \ - ) { \ - return %3; \ - } - -// (const JSON:jValue, const Trie:tCache, &any:iCachedValue, &JSON:jRefed) -#define Json_GetCachedRefValue_End(%1,%2,%3,%4) \ - (__Json_GetCachedRefValue_sJsonRef[0] \ - && TrieSetCell(%2, __Json_GetCachedRefValue_sJsonRef, %3)); \ - Json_FreeExIf(%4, bool:__Json_GetCachedRefValue_sJsonRef[0]); \ - return %3; From ff1ef64284d369ab7452f933b0101e52a82e765f Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 3 Mar 2025 02:02:25 +0300 Subject: [PATCH 036/108] Remove unused utils --- .../DefaultObjects/ItemType/DamageMult.inc | 2 - amxmodx/scripting/VipM-L-Default.sma | 4 +- amxmodx/scripting/VipM-L-Logic.sma | 4 +- amxmodx/scripting/VipM-M-SpawnHealth.sma | 4 +- amxmodx/scripting/VipM-M-Vampire.sma | 4 +- amxmodx/scripting/VipM-M-VipInTab.sma | 2 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 5 +- amxmodx/scripting/VipM-ModulesLimiter.sma | 2 +- .../VipM/Core/Objects/Modules/Unit.inc | 6 +- amxmodx/scripting/VipM/JsonUtils.inc | 80 ----------------- amxmodx/scripting/VipM/Utils.inc | 87 +++---------------- .../VipM/WeaponMenu/Objects/MenuItem.inc | 42 +++++---- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 46 +++++----- amxmodx/scripting/VipModular.sma | 2 +- 14 files changed, 78 insertions(+), 212 deletions(-) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc index 3070949..be4c014 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc @@ -31,8 +31,6 @@ DefaultObjects_ItemType_DamageMult_Register() { if (json_object_has_value(instanceJson, "Taken", JSONNumber)) { TrieSetCell(p, "Taken", json_object_get_real(instanceJson, "Taken")); } - - CallOnceR(IC_RET_READ_SUCCESS); // Чтобы лишний раз не дёргать натив активации хука EnableHookChain(PlayerSpawnPreHookChain); EnableHookChain(PlayerTakeDamagePreHookChain); diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index 3bd9170..756e82c 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -7,7 +7,7 @@ #pragma semicolon 1 #pragma compress 1 -public stock const PluginName[] = "[VipM][L] Default"; +public stock const PluginName[] = "[VipM-L] Default"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; @@ -35,7 +35,7 @@ public plugin_natives() { } public VipM_OnInitModules() { - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Limits_RegisterType("ForAll", false, true); VipM_Limits_SetStaticValue("ForAll", true); diff --git a/amxmodx/scripting/VipM-L-Logic.sma b/amxmodx/scripting/VipM-L-Logic.sma index 4e5dfff..ed42e76 100644 --- a/amxmodx/scripting/VipM-L-Logic.sma +++ b/amxmodx/scripting/VipM-L-Logic.sma @@ -5,13 +5,13 @@ #pragma semicolon 1 #pragma compress 1 -public stock const PluginName[] = "[VipM][L] Logic"; +public stock const PluginName[] = "[VipM-L] Logic"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; public VipM_OnInitModules(){ - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Limits_RegisterType("Logic-OR", false, false); VipM_Limits_AddTypeParams("Logic-OR", diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index a14fdad..8b06e9c 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -8,7 +8,7 @@ #pragma semicolon 1 #pragma compress 1 -public stock const PluginName[] = "[VipM][M] Spawn Health"; +public stock const PluginName[] = "[VipM-M] Spawn Health"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; @@ -17,7 +17,7 @@ public stock const PluginDescription[] = "Vip modular`s module - SpawnHealth"; new const MODULE_NAME[] = "SpawnHealth"; public VipM_OnInitModules(){ - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Modules_Register(MODULE_NAME, true); VipM_Modules_AddParams(MODULE_NAME, diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index 39e2ca7..9ab2384 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -6,7 +6,7 @@ #pragma semicolon 1 #pragma compress 1 -public stock const PluginName[] = "[VipM][M] Vampire"; +public stock const PluginName[] = "[VipM-M] Vampire"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; @@ -15,7 +15,7 @@ public stock const PluginDescription[] = "Vip modular`s module - Vampire"; new const MODULE_NAME[] = "Vampire"; public VipM_OnInitModules(){ - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); register_dictionary("VipM-Vampire.ini"); VipM_Modules_Register(MODULE_NAME, true); diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index 5991441..746588a 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -21,7 +21,7 @@ new const MODULE_NAME[] = "VipInTab"; new bool:gHasTag[MAX_PLAYERS + 1][E_ModuleParams]; public VipM_OnInitModules() { - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Modules_Register(MODULE_NAME, true); VipM_Modules_AddParams(MODULE_NAME, diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 9814109..6b6e6a9 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -10,7 +10,7 @@ #pragma semicolon 1 #pragma compress 1 -public stock const PluginName[] = "[VipM][M] Weapon Menu"; +public stock const PluginName[] = "[VipM-M] Weapon Menu"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; @@ -42,7 +42,7 @@ new gUserExpireStatus[MAX_PLAYERS + 1][VIPM_M_WEAPONMENU_EXPIRE_STATUS_MAX_LEN]; #include "VipM/WeaponMenu/Menus" public VipM_OnInitModules() { - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); register_dictionary("VipM-WeaponMenu.ini"); IC_Init(); @@ -88,6 +88,7 @@ public VipM_OnInitModules() { RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawn", true); RegisterHookChain(RG_CSGameRules_RestartRound, "@OnRestartRound", false); + // TODO: Use CommandAliases plugin CommandAliases_Open(GET_FILE_JSON_PATH("Cmds/WeaponMenu"), true); CommandAliases_RegisterClient(CMD_WEAPON_MENU, "@Cmd_Menu"); // vipmenu CommandAliases_RegisterClient(CMD_WEAPON_MENU_SILENT, "@Cmd_MenuSilent"); diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 3923ce9..e11e288 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -15,7 +15,7 @@ new const MODULES_CONFIG_FILE[] = "Modules"; new Trie:g_tModulesLimits = Invalid_Trie; public VipM_OnLoaded() { - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); g_tModulesLimits = LoadModulesLimitsFromFile(MODULES_CONFIG_FILE, g_tModulesLimits); } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 9d2f183..3e5aa3a 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -78,7 +78,7 @@ static T_ModuleType:ModuleUnit__ReadType(const JSON:jModuleUnit) { return iModuleType; } -T_ModuleUnit:ModuleUnit_Read(const JSON:jModuleUnit) { +T_ModuleUnit:ModuleUnit_Read(const JSON:valueJson) { static Trie:cache = Invalid_Trie; TrieCreateIfNotCreated(cache); @@ -87,13 +87,13 @@ T_ModuleUnit:ModuleUnit_Read(const JSON:jModuleUnit) { return cached; } - new T_LimitType:type = ModuleUnit__ReadType(linked); + new T_ModuleType:type = ModuleUnit__ReadType(linked); if (type == Invalid_ModuleType) { PCJson_FreeLinked(linked); return Invalid_ModuleUnit; } - new Trie:p = LimitType_ReadParams(type, linked); + new Trie:p = ModuleType_ReadParams(type, linked); if (p == Invalid_Trie) { PCJson_FreeLinked(linked); return Invalid_ModuleUnit; diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index 9431dc5..ad53c33 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -11,86 +11,6 @@ #define JSON_UTILS__MAX_STRING_LENGTH 256 #define JSON_UTILS__MAX_REF_LENGTH 128 -stock JSON:Json_FreeExIf(&JSON:jValue, const bool:bIf) { - if (bIf) { - PCJson_Free(jValue); - } - - return jValue; -} - -/** - * Проверяет, является ли значение ссылкой. - * - * @param jValue JSON-хендлер. - * @param sFileName Буфер для записи ссылки, если значение ей является. - * @param iLen Размер буфера. - * - * @note Не требуется при использовании Json_GetRefValue. - * - * @return true, если значение является ссылкой, иначе false. - */ -stock bool:Json_IsRef(const JSON:jValue, sFileName[] = "", const iLen = 0) { - if (!json_is_string(jValue)) { - return false; - } - - new Str[JSON_UTILS__MAX_REF_LENGTH]; - json_get_string(jValue, Str, charsmax(Str)); - if (!equali(PC_JSON_WRAPPER_LINK_PREFIX_FILE, Str, charsmax(PC_JSON_WRAPPER_LINK_PREFIX_FILE))) { - return false; - } - - if (iLen > 0) { - copy(sFileName, iLen, Str[charsmax(PC_JSON_WRAPPER_LINK_PREFIX_FILE)]); - } - - return true; -} - -/** - * Возвращает JSON-значение с учётом ссылки. - * - * @param jValue JSON-хендлер. - * @param sOut Буфер для записи пути до файла, если значение было ссылкой. - * @param iOutLen Размер буфера. - * - * @note Ссылка считается от WorkDir из обёртки jValue. - * Если обёртки нет, ссылка не будет обработана. - * - * @note Полученное по ссылке значение также будет иметь обёртку. - * WorkDir полученного значения будет наследован от jValue. - * - * @return jValue, если значение не являлось ссылкой, иначе значение полученное по ссылке. - */ -stock JSON:Json_GetRefValue( - const JSON:jValue, - sOut[] = "", - const iOutLen = 0, - &bool:bIsRef = false -) { - bIsRef = false; - - new sRefFilePath[PLATFORM_MAX_PATH]; - if (!Json_IsRef(jValue, sRefFilePath, charsmax(sRefFilePath))) { - return jValue; - } - - new sFileName[PLATFORM_MAX_PATH]; - PCPath_MakePath( - sRefFilePath, sFileName, charsmax(sFileName), - .absolutePrefix = PCJson_GetWrapperWorkdir(jValue), - .forceFileExtension = "json" - ); - - if (iOutLen) { - copy(sOut, iOutLen, sFileName); - } - - bIsRef = true; - return PCJson_ParseFile(sFileName, PCJson_GetWrapperWorkdir(jValue)); -} - stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { if (tTrie == Invalid_Trie) { tTrie = TrieCreate(); diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 850c573..de65844 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -7,15 +7,14 @@ #include "VipM/ArrayTrieUtils" #include "VipM/JsonUtils" -#include amxmodx -#include json -#include reapi -#include VipModular +#include +#include +#include +#include stock const __SLANG_TEMPLATE_STR[] = "%l"; stock const __CLANG_TEMPLATE_STR[] = "%L"; stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; -stock const __USER_NAME_TEMPLATE_STR[] = "%n"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; stock const bool:__CompositeMacros_AlwaysFalse = false; @@ -66,17 +65,8 @@ stock IsPlayerAlive(const playerIndex) { #define ChatPrintLIf(%3,%1,%2) \ ((%3) && ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2)) -#define GET_FILE(%1) \ - VipM_iGetCfgPath(%1) - #define GET_FILE_JSON_PATH(%1) \ - GET_FILE(fmt(__JSON_FILE_TEMPLATE_STR, %1)) - -#define GET_FILE_JSON(%1) \ - PCJson_ParseFile(GET_FILE_JSON_PATH(%1), GET_FILE("")) - -#define JSON_FILE_EXTSTS(%1) \ - file_exists(GET_FILE_JSON_PATH(%1)) + VipM_iGetCfgPath(fmt(__JSON_FILE_TEMPLATE_STR, %1)) stock __CMD_NULL_ARG = 0; @@ -171,13 +161,15 @@ stock bool:HasBits(const bits, const bitSearch, const bool:bStrict = false) { : bitRes != 0 } -// []GetUserName(const UserId) -#define GetUserName(%1) \ - fmt(__USER_NAME_TEMPLATE_STR,%1) +stock GetUserName(const playerIndex) { + new name[32]; + get_user_name(playerIndex, name, charsmax(name)); + return name; +} -// bool:IsEqualUserName(const UserId, const sName[]) -#define IsEqualUserName(%1,%2) \ - equal(GetUserName(%1), %2) +stock IsEqualUserName(const playerIndex, const name[]) { + return equal(GetUserName(playerIndex), name); +} stock GetWeekDayIdByName(const sWeekDayName[]) { if (equali("Вс", sWeekDayName) || equali("Воскресенье", sWeekDayName) || equali("Sun", sWeekDayName) || equali("Sunday", sWeekDayName)) { @@ -209,59 +201,6 @@ stock CreateConstCvar(const sCvarName[], const sCvarValue[], const iFlags = FCVA __CallOnce_bCalled = true; \ ) -#define CallOnceR(%1) CompositeMacros( \ - static bool:__CallOnce_bCalled; \ - if (__CallOnce_bCalled) return %1; \ - __CallOnce_bCalled = true; \ -) - -// https://github.com/Nord1cWarr1or/Universal-AFK-Manager/blob/6272afbb8c27f8b7ad770e3036b5960042001e6b/scripting/UAFKManager.sma#L298-L321 -stock GetAmxxVersionNum() { - static iRes; - if (iRes) { - return iRes; - } - - new sAmxxVer[16]; - get_amxx_verstring(sAmxxVer, charsmax(sAmxxVer)); - - if (strfind(sAmxxVer, "1.10.0") != -1) { - iRes = 1100; - } else if (strfind(sAmxxVer, "1.9.0") != -1) { - iRes = 190; - } else if (strfind(sAmxxVer, "1.8.3") != -1) { - iRes = 183; - } else if (strfind(sAmxxVer, "1.8.2") != -1) { - iRes = 182; - } else { - iRes = 1; - } - - return iRes; -} - -stock RegisterPlugin( - const sName[], - const sVersion[], - const sAuthor[], - const sUrl[] = "", - const sDescription[] = "" -) { - #if AMXX_VERSION_NUM >= 1100 - if (GetAmxxVersionNum() >= 1100) { - register_plugin(sName, sVersion, sAuthor, sUrl, sDescription); - return; - } - #endif - register_plugin(sName, sVersion, sAuthor); -} - -#define RegisterPluginByVars() CompositeMacros( \ - if (GetAmxxVersionNum() < 1100) { \ - register_plugin(PluginName, PluginVersion, PluginAuthor); \ - } \ -) - stock ItemHasClip(const ItemId) { new WeaponIdType:WeaponId = get_member(ItemId, m_iId); switch (WeaponId) { diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 4c6069d..4a212fa 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -5,6 +5,7 @@ #include #include +#include #include "VipM/JsonUtils" enum MenuItemType { @@ -27,62 +28,65 @@ enum _:S_MenuItem { } bool:MenuItem_Read(const JSON:jMenuItem, MenuItem[S_MenuItem]) { - new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenuItem, .bIsRef = bIsRef); + new JSON:linkedJson; + PCJson_HandleLinkedValue(jMenuItem, linkedJson); - if (!json_is_object(jRefed)) { - PCJson_LogForFile(jRefed, "WARNING", "Invalid menu item format."); + if (!json_is_object(linkedJson)) { + PCJson_LogForFile(linkedJson, "WARNING", "Invalid menu item format."); return false; } - if (!json_object_get_string(jMenuItem, "Title", MenuItem[MenuItem_Title], charsmax(MenuItem[MenuItem_Title]))) { + if (!json_object_get_string(linkedJson, "Title", MenuItem[MenuItem_Title], charsmax(MenuItem[MenuItem_Title]))) { MenuItem[MenuItem_Type] = MenuItemType_Blank; - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return true; } - MenuItem[MenuItem_Items] = Json_Object_IC_GetItems(jMenuItem, "Items"); + MenuItem[MenuItem_Items] = Json_Object_IC_GetItems(linkedJson, "Items"); if (MenuItem[MenuItem_Items] == Invalid_Array) { MenuItem[MenuItem_Type] = MenuItemType_Text; - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return true; } MenuItem[MenuItem_Type] = MenuItemType_Default; - MenuItem[MenuItem_ShowLimits] = Json_Object_GetLimits(jMenuItem, "ShowLimits"); - MenuItem[MenuItem_ActiveLimits] = Json_Object_GetLimits(jMenuItem, "ActiveLimits"); - MenuItem[MenuItem_Limits] = Json_Object_GetLimits(jMenuItem, "Limits"); - MenuItem[MenuItem_FakeInactive] = Json_Object_GetBool(jMenuItem, "FakeInactive", false); - MenuItem[MenuItem_UseCounter] = Json_Object_GetBool(jMenuItem, "UseCounter", true); + MenuItem[MenuItem_ShowLimits] = Json_Object_GetLimits(linkedJson, "ShowLimits"); + MenuItem[MenuItem_ActiveLimits] = Json_Object_GetLimits(linkedJson, "ActiveLimits"); + MenuItem[MenuItem_Limits] = Json_Object_GetLimits(linkedJson, "Limits"); + MenuItem[MenuItem_FakeInactive] = Json_Object_GetBool(linkedJson, "FakeInactive", false); + MenuItem[MenuItem_UseCounter] = Json_Object_GetBool(linkedJson, "UseCounter", true); - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return true; } Array:MenuItem_ReadList(const JSON:jMenuItems, &Array:aMenuItems = Invalid_Array) { ArrayCreateIfNotCreated(aMenuItems, S_MenuItem, 1); + + new JSON:linkedJson; + PCJson_HandleLinkedValue(jMenuItems, linkedJson); - new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenuItems, .bIsRef = bIsRef); - switch (json_get_type(jRefed)) { + switch (json_get_type(linkedJson)) { case JSONObject: { new MenuItem[S_MenuItem]; - if (MenuItem_Read(jRefed, MenuItem)) { + if (MenuItem_Read(linkedJson, MenuItem)) { ArrayPushArray(aMenuItems, MenuItem); } } case JSONArray: { - json_array_foreach_value (jRefed: i => jMenuItem) { + json_array_foreach_value (linkedJson: i => jMenuItem) { MenuItem_ReadList(jMenuItem, aMenuItems); json_free(jMenuItem); } } default: { - PCJson_LogForFile(jRefed, "WARNING", "Invalid menu items format."); + PCJson_LogForFile(linkedJson, "WARNING", "Invalid menu items format."); } } - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return aMenuItems; } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 6a6fcb4..15dbd64 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -6,6 +6,7 @@ #include #include #include +#include #include "VipM/JsonUtils" #include "VipM/WeaponMenu/Objects/MenuItem" @@ -29,60 +30,63 @@ enum _:S_WeaponMenu { } bool:WeaponMenu_Read(&JSON:jMenu, Menu[S_WeaponMenu]) { - new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jMenu, .bIsRef = bIsRef); - - Json_Object_GetString(jRefed, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); + new JSON:linkedJson; + PCJson_HandleLinkedValue(jMenu, linkedJson); + + Json_Object_GetString(linkedJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); if (Json_Object_GetColoredChatMessage( - jRefed, "FakeMessage", + linkedJson, "FakeMessage", Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]) )) { - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return true; } - Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(jRefed, "Items"); + Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(linkedJson, "Items"); if (Menu[WeaponMenu_Items] == Invalid_Array) { - PCJson_LogForFile(jRefed, "WARNING", "Menu items list are empty."); - Json_FreeExIf(jRefed, bIsRef); + PCJson_LogForFile(linkedJson, "WARNING", "Menu items list are empty."); + PCJson_FreeLinked(linkedJson); return false; } - Json_Object_GetString(jRefed, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); + Json_Object_GetString(linkedJson, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); - Menu[WeaponMenu_Count] = Json_Object_GetInt(jRefed, "Count", -1); - Menu[WeaponMenu_BackOnExit] = Json_Object_GetBool(jRefed, "BackOnExit", false); - Menu[WeaponMenu_PerPage] = Json_Object_GetInt(jRefed, "PerPage", -1); - Menu[WeaponMenu_ShowPage] = Json_Object_GetBool(jRefed, "ShowPage", true); - Menu[WeaponMenu_Limits] = Json_Object_GetLimits(jRefed, "Limits"); + Menu[WeaponMenu_Count] = Json_Object_GetInt(linkedJson, "Count", -1); + Menu[WeaponMenu_BackOnExit] = Json_Object_GetBool(linkedJson, "BackOnExit", false); + Menu[WeaponMenu_PerPage] = Json_Object_GetInt(linkedJson, "PerPage", -1); + Menu[WeaponMenu_ShowPage] = Json_Object_GetBool(linkedJson, "ShowPage", true); + Menu[WeaponMenu_Limits] = Json_Object_GetLimits(linkedJson, "Limits"); - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return true; } Array:WeaponMenu_ReadList(const JSON:jWeaponMenus, &Array:aWeaponMenus = Invalid_Array) { ArrayCreateIfNotCreated(aWeaponMenus, S_WeaponMenu, 1); - new bool:bIsRef, JSON:jRefed = Json_GetRefValue(jWeaponMenus, .bIsRef = bIsRef); - switch (json_get_type(jRefed)) { + new JSON:linkedJson; + PCJson_HandleLinkedValue(jWeaponMenus, linkedJson); + + switch (json_get_type(linkedJson)) { case JSONObject: { new WeaponMenu[S_WeaponMenu]; - if (WeaponMenu_Read(jRefed, WeaponMenu)) { + if (WeaponMenu_Read(linkedJson, WeaponMenu)) { ArrayPushArray(aWeaponMenus, WeaponMenu); } } case JSONArray: { - json_array_foreach_value (jRefed: i => jWeaponMenu) { + json_array_foreach_value (linkedJson: i => jWeaponMenu) { aWeaponMenus = WeaponMenu_ReadList(jWeaponMenu, aWeaponMenus); json_free(jWeaponMenu); } } default: { - PCJson_LogForFile(jRefed, "WARNING", "Invalid weapon menus format."); + PCJson_LogForFile(linkedJson, "WARNING", "Invalid weapon menus format."); } } - Json_FreeExIf(jRefed, bIsRef); + PCJson_FreeLinked(linkedJson); return aWeaponMenus; } diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index 2fe7037..cdf5783 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -19,7 +19,7 @@ public stock const PluginDescription[] = "Modular vip system"; #include "VipM/Core/SrvCmds" public plugin_precache() { - RegisterPluginByVars(); + register_plugin(PluginName, PluginVersion, PluginAuthor); register_library(VIPM_LIBRARY); CreateConstCvar("vipm_version", PluginVersion); From 3226e85d27d0fdc3a13748372ca58491dd5892be Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 3 Mar 2025 02:17:34 +0300 Subject: [PATCH 037/108] Move logic limits to def bundle --- amxmodx/scripting/VipM-L-Default.sma | 40 ++++++++++++++++++++ amxmodx/scripting/VipM-L-Logic.sma | 55 ---------------------------- 2 files changed, 40 insertions(+), 55 deletions(-) delete mode 100644 amxmodx/scripting/VipM-L-Logic.sma diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index 756e82c..dc06ec3 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -165,6 +165,30 @@ public VipM_OnInitModules() { ); VipM_Limits_RegisterTypeEvent("GameTime", Limit_OnCheck, "@OnGameTimeCheck"); + VipM_Limits_RegisterType("Logic-OR", false, false); + VipM_Limits_AddTypeParams("Logic-OR", + "Limits", ptLimits, true + ); + VipM_Limits_RegisterTypeEvent("Logic-OR", Limit_OnCheck, "@OnOrCheck"); + + VipM_Limits_RegisterType("Logic-XOR", false, false); + VipM_Limits_AddTypeParams("Logic-XOR", + "Limits", ptLimits, true + ); + VipM_Limits_RegisterTypeEvent("Logic-XOR", Limit_OnCheck, "@OnXorCheck"); + + VipM_Limits_RegisterType("Logic-AND", false, false); + VipM_Limits_AddTypeParams("Logic-AND", + "Limits", ptLimits, true + ); + VipM_Limits_RegisterTypeEvent("Logic-AND", Limit_OnCheck, "@OnAndCheck"); + + VipM_Limits_RegisterType("Logic-NOT", false, false); + VipM_Limits_AddTypeParams("Logic-NOT", + "Limits", ptLimits, true + ); + VipM_Limits_RegisterTypeEvent("Logic-NOT", Limit_OnCheck, "@OnNotCheck"); + RegisterHookChain(RG_CSGameRules_RestartRound, "@OnRestartRound", true); RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawn", true); @@ -432,3 +456,19 @@ bool:@OnFlagsCheck(const Trie:Params, const UserId) { && GetCurrentRoundNum() <= VipM_Params_GetInt(Params, "Max", cellmax) ); } + +@OnOrCheck(const Trie:Params, const UserId){ + return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_OR); +} + +@OnXorCheck(const Trie:Params, const UserId){ + return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_XOR); +} + +@OnAndCheck(const Trie:Params, const UserId){ + return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND); +} + +@OnNotCheck(const Trie:Params, const UserId){ + return !VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND); +} diff --git a/amxmodx/scripting/VipM-L-Logic.sma b/amxmodx/scripting/VipM-L-Logic.sma deleted file mode 100644 index ed42e76..0000000 --- a/amxmodx/scripting/VipM-L-Logic.sma +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include "VipM/Utils" - -#pragma semicolon 1 -#pragma compress 1 - -public stock const PluginName[] = "[VipM-L] Logic"; -public stock const PluginVersion[] = _VIPM_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = _VIPM_PLUGIN_URL; - -public VipM_OnInitModules(){ - register_plugin(PluginName, PluginVersion, PluginAuthor); - - VipM_Limits_RegisterType("Logic-OR", false, false); - VipM_Limits_AddTypeParams("Logic-OR", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-OR", Limit_OnCheck, "@OnOrCheck"); - - VipM_Limits_RegisterType("Logic-XOR", false, false); - VipM_Limits_AddTypeParams("Logic-XOR", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-XOR", Limit_OnCheck, "@OnXorCheck"); - - VipM_Limits_RegisterType("Logic-AND", false, false); - VipM_Limits_AddTypeParams("Logic-AND", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-AND", Limit_OnCheck, "@OnAndCheck"); - - VipM_Limits_RegisterType("Logic-NOT", false, false); - VipM_Limits_AddTypeParams("Logic-NOT", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-NOT", Limit_OnCheck, "@OnNotCheck"); -} - -@OnOrCheck(const Trie:Params, const UserId){ - return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_OR); -} - -@OnXorCheck(const Trie:Params, const UserId){ - return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_XOR); -} - -@OnAndCheck(const Trie:Params, const UserId){ - return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND); -} - -@OnNotCheck(const Trie:Params, const UserId){ - return !VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND); -} From 77eeb1e0e308458b3ab1913fe5e53cc33350746b Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 3 Mar 2025 02:29:23 +0300 Subject: [PATCH 038/108] Fix `VipM_IC_RegisterTypeEvent` native --- amxmodx/scripting/ItemsController/API/Compat.inc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/amxmodx/scripting/ItemsController/API/Compat.inc b/amxmodx/scripting/ItemsController/API/Compat.inc index f2188ab..b258c7e 100644 --- a/amxmodx/scripting/ItemsController/API/Compat.inc +++ b/amxmodx/scripting/ItemsController/API/Compat.inc @@ -27,7 +27,10 @@ T_IC_ItemType:@_VipM_IC_RegisterType() { @_VipM_IC_RegisterTypeEvent(const pluginIndex) { enum {Arg_Type = 1, Arg_Event, Arg_FuncName} - new T_IC_ItemType:type = T_IC_ItemType:get_param(Arg_Type); + new typeName[IC_ITEM_TYPE_NAME_MAX_LEN]; + T_IC_ItemType:get_string(Arg_Type, typeName, charsmax(typeName)); + new T_IC_ItemType:type = ItemType_Find(typeName, .orFail = true); + new E_ItemTypeEvent:event = E_ItemTypeEvent:get_param(Arg_Event); new funcName[IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN]; get_string(Arg_FuncName, funcName, charsmax(funcName)); From 8c5256211d703ac2d102538ff5bdaa6fc433a031 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Mar 2025 00:57:10 +0300 Subject: [PATCH 039/108] Fix links for menus --- .../scripting/ItemsController/API/Compat.inc | 2 +- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 28 ++++++++----------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/amxmodx/scripting/ItemsController/API/Compat.inc b/amxmodx/scripting/ItemsController/API/Compat.inc index b258c7e..e16bfb6 100644 --- a/amxmodx/scripting/ItemsController/API/Compat.inc +++ b/amxmodx/scripting/ItemsController/API/Compat.inc @@ -28,7 +28,7 @@ T_IC_ItemType:@_VipM_IC_RegisterType() { enum {Arg_Type = 1, Arg_Event, Arg_FuncName} new typeName[IC_ITEM_TYPE_NAME_MAX_LEN]; - T_IC_ItemType:get_string(Arg_Type, typeName, charsmax(typeName)); + get_string(Arg_Type, typeName, charsmax(typeName)); new T_IC_ItemType:type = ItemType_Find(typeName, .orFail = true); new E_ItemTypeEvent:event = E_ItemTypeEvent:get_param(Arg_Event); diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 15dbd64..834e1d8 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -29,36 +29,30 @@ enum _:S_WeaponMenu { WeaponMenu_FakeMessage[256], } -bool:WeaponMenu_Read(&JSON:jMenu, Menu[S_WeaponMenu]) { - new JSON:linkedJson; - PCJson_HandleLinkedValue(jMenu, linkedJson); - - Json_Object_GetString(linkedJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); +bool:WeaponMenu_Read(const JSON:menuJson, Menu[S_WeaponMenu]) { + Json_Object_GetString(menuJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); if (Json_Object_GetColoredChatMessage( - linkedJson, "FakeMessage", + menuJson, "FakeMessage", Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]) )) { - PCJson_FreeLinked(linkedJson); return true; } - Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(linkedJson, "Items"); + Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(menuJson, "Items"); if (Menu[WeaponMenu_Items] == Invalid_Array) { - PCJson_LogForFile(linkedJson, "WARNING", "Menu items list are empty."); - PCJson_FreeLinked(linkedJson); + PCJson_LogForFile(menuJson, "WARNING", "Menu items list are empty."); return false; } - Json_Object_GetString(linkedJson, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); + Json_Object_GetString(menuJson, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); - Menu[WeaponMenu_Count] = Json_Object_GetInt(linkedJson, "Count", -1); - Menu[WeaponMenu_BackOnExit] = Json_Object_GetBool(linkedJson, "BackOnExit", false); - Menu[WeaponMenu_PerPage] = Json_Object_GetInt(linkedJson, "PerPage", -1); - Menu[WeaponMenu_ShowPage] = Json_Object_GetBool(linkedJson, "ShowPage", true); - Menu[WeaponMenu_Limits] = Json_Object_GetLimits(linkedJson, "Limits"); + Menu[WeaponMenu_Count] = Json_Object_GetInt(menuJson, "Count", -1); + Menu[WeaponMenu_BackOnExit] = Json_Object_GetBool(menuJson, "BackOnExit", false); + Menu[WeaponMenu_PerPage] = Json_Object_GetInt(menuJson, "PerPage", -1); + Menu[WeaponMenu_ShowPage] = Json_Object_GetBool(menuJson, "ShowPage", true); + Menu[WeaponMenu_Limits] = Json_Object_GetLimits(menuJson, "Limits"); - PCJson_FreeLinked(linkedJson); return true; } From 5546db2b81d00cb2dd89435fb7777f926921238f Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Mar 2025 01:02:56 +0300 Subject: [PATCH 040/108] Fix links for menu items --- .../VipM/WeaponMenu/Objects/MenuItem.inc | 50 ++++++++----------- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 2 - 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 4a212fa..0cad27a 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -27,58 +27,52 @@ enum _:S_MenuItem { Array:MenuItem_Limits, // T_LimitUnit[] } -bool:MenuItem_Read(const JSON:jMenuItem, MenuItem[S_MenuItem]) { - new JSON:linkedJson; - PCJson_HandleLinkedValue(jMenuItem, linkedJson); - - if (!json_is_object(linkedJson)) { - PCJson_LogForFile(linkedJson, "WARNING", "Invalid menu item format."); +bool:MenuItem_Read(const JSON:itemJson, item[S_MenuItem]) { + if (!json_is_object(itemJson)) { + PCJson_LogForFile(itemJson, "WARNING", "Invalid menu item format."); return false; } - if (!json_object_get_string(linkedJson, "Title", MenuItem[MenuItem_Title], charsmax(MenuItem[MenuItem_Title]))) { - MenuItem[MenuItem_Type] = MenuItemType_Blank; - PCJson_FreeLinked(linkedJson); + if (!json_object_get_string(itemJson, "Title", item[MenuItem_Title], charsmax(item[MenuItem_Title]))) { + item[MenuItem_Type] = MenuItemType_Blank; return true; } - MenuItem[MenuItem_Items] = Json_Object_IC_GetItems(linkedJson, "Items"); + item[MenuItem_Items] = Json_Object_IC_GetItems(itemJson, "Items"); - if (MenuItem[MenuItem_Items] == Invalid_Array) { - MenuItem[MenuItem_Type] = MenuItemType_Text; - PCJson_FreeLinked(linkedJson); + if (item[MenuItem_Items] == Invalid_Array) { + item[MenuItem_Type] = MenuItemType_Text; return true; } - MenuItem[MenuItem_Type] = MenuItemType_Default; + item[MenuItem_Type] = MenuItemType_Default; - MenuItem[MenuItem_ShowLimits] = Json_Object_GetLimits(linkedJson, "ShowLimits"); - MenuItem[MenuItem_ActiveLimits] = Json_Object_GetLimits(linkedJson, "ActiveLimits"); - MenuItem[MenuItem_Limits] = Json_Object_GetLimits(linkedJson, "Limits"); - MenuItem[MenuItem_FakeInactive] = Json_Object_GetBool(linkedJson, "FakeInactive", false); - MenuItem[MenuItem_UseCounter] = Json_Object_GetBool(linkedJson, "UseCounter", true); + item[MenuItem_ShowLimits] = Json_Object_GetLimits(itemJson, "ShowLimits"); + item[MenuItem_ActiveLimits] = Json_Object_GetLimits(itemJson, "ActiveLimits"); + item[MenuItem_Limits] = Json_Object_GetLimits(itemJson, "Limits"); + item[MenuItem_FakeInactive] = Json_Object_GetBool(itemJson, "FakeInactive", false); + item[MenuItem_UseCounter] = Json_Object_GetBool(itemJson, "UseCounter", true); - PCJson_FreeLinked(linkedJson); return true; } -Array:MenuItem_ReadList(const JSON:jMenuItems, &Array:aMenuItems = Invalid_Array) { - ArrayCreateIfNotCreated(aMenuItems, S_MenuItem, 1); +Array:MenuItem_ReadList(const JSON:itemsJson, &Array:items = Invalid_Array) { + ArrayCreateIfNotCreated(items, S_MenuItem, 1); new JSON:linkedJson; - PCJson_HandleLinkedValue(jMenuItems, linkedJson); + PCJson_HandleLinkedValue(itemsJson, linkedJson); switch (json_get_type(linkedJson)) { case JSONObject: { new MenuItem[S_MenuItem]; if (MenuItem_Read(linkedJson, MenuItem)) { - ArrayPushArray(aMenuItems, MenuItem); + ArrayPushArray(items, MenuItem); } } case JSONArray: { - json_array_foreach_value (linkedJson: i => jMenuItem) { - MenuItem_ReadList(jMenuItem, aMenuItems); - json_free(jMenuItem); + json_array_foreach_value (linkedJson: i => itemJson) { + MenuItem_ReadList(itemJson, items); + json_free(itemJson); } } default: { @@ -87,7 +81,7 @@ Array:MenuItem_ReadList(const JSON:jMenuItems, &Array:aMenuItems = Invalid_Array } PCJson_FreeLinked(linkedJson); - return aMenuItems; + return items; } Array:Json_Object_GetMenuItemsList( diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 834e1d8..a266aa1 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -11,8 +11,6 @@ #include "VipM/WeaponMenu/Objects/MenuItem" -// TODO: Мб на хендлеры переделать?) - enum _:S_WeaponMenu { WeaponMenu_Name[64], WeaponMenu_Title[128], From 0f523745fccb12ef8325bbd8e71abf4b0a2cace6 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 17 Mar 2025 23:57:45 +0300 Subject: [PATCH 041/108] Fix IsActive native in modules api --- amxmodx/scripting/VipM-ModulesLimiter.sma | 4 +++- amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index e11e288..facd8ab 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -42,7 +42,9 @@ public VipM_OnActivateModule(const sModuleName[]) { } Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { - TrieCreateIfNotCreated(tModules); + if (tModules == Invalid_Trie) { + tModules = TrieCreate(); + } new JSON:jFile = PCJson_ParseFile(GET_FILE_JSON_PATH(sFileName)); if (jFile == Invalid_JSON) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 3e5aa3a..5d500ac 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -54,7 +54,7 @@ static T_ModuleUnit:ModuleUnit__Construct(const T_ModuleType:iModuleType, const // ArrayGetArray(g_aModuleUnits, _:iModuleUnit, ModuleUnit); // } -static any:ModuleType__GetValue(const T_ModuleUnit:iModuleUnit, const iCell) { +static any:ModuleUnit__GetValue(const T_ModuleUnit:iModuleUnit, const iCell) { return ArrayGetCell(g_aModuleUnits, _:iModuleUnit, iCell); } @@ -139,11 +139,11 @@ Array:JsonObject_GetModuleUnits(const JSON:jObj, const sKey[], const bool:bDotNo } Trie:ModuleUnit_GetParams(const T_ModuleUnit:iModuleUnit) { - return ModuleType__GetValue(iModuleUnit, ModuleUnit_Params); + return ModuleUnit__GetValue(iModuleUnit, ModuleUnit_Params); } ModuleUnit_GetTypeName(const T_ModuleUnit:iModuleUnit, sOut[], const iOutLen) { - return ModuleType_GetName(ModuleType__GetValue(iModuleUnit, ModuleUnit_Type), sOut, iOutLen); + return ModuleType_GetName(ModuleUnit__GetValue(iModuleUnit, ModuleUnit_Type), sOut, iOutLen); } // ModuleUnit_iGetTypeName(const T_ModuleUnit:iModuleUnit) { @@ -165,5 +165,5 @@ Trie:ModuleUnit_FreeParamsIfTemp(&Trie:tParams) { } Trie:ModuleUnit_Merge(const T_ModuleUnit:iModuleUnit, const Trie:tParams1, const Trie:tParams2) { - return ModuleType_MergeParams(ModuleType__GetValue(iModuleUnit, ModuleUnit_Type), tParams1, tParams2); + return ModuleType_MergeParams(ModuleUnit__GetValue(iModuleUnit, ModuleUnit_Type), tParams1, tParams2); } From 545225eec5b8bd1d54457ddfee1a1e8c4b4aa1dc Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 2 Apr 2025 00:25:15 +0300 Subject: [PATCH 042/108] Update core api --- amxmodx/scripting/IC-I-Limits.sma | 1 + amxmodx/scripting/VipM-ModulesLimiter.sma | 3 +- .../VipM/Core/Objects/Limits/Unit.inc | 4 +-- .../VipM/Core/Objects/Modules/Type.inc | 4 +-- .../VipM/Core/Objects/Modules/Unit.inc | 5 +-- amxmodx/scripting/VipM/Core/VipsManager.inc | 4 +-- amxmodx/scripting/VipModular.sma | 9 +++-- amxmodx/scripting/include/VipM/Limits.inc | 15 ++++---- amxmodx/scripting/include/VipM/Modules.inc | 18 +++++++++- amxmodx/scripting/include/VipM/Params.inc | 6 ++++ amxmodx/scripting/include/VipModular.inc | 36 +++++++------------ 11 files changed, 62 insertions(+), 43 deletions(-) diff --git a/amxmodx/scripting/IC-I-Limits.sma b/amxmodx/scripting/IC-I-Limits.sma index 7c330b3..4263703 100644 --- a/amxmodx/scripting/IC-I-Limits.sma +++ b/amxmodx/scripting/IC-I-Limits.sma @@ -2,6 +2,7 @@ #include #include #include +#include #include "VipM/Utils" public stock const PluginName[] = "[IC-I] Limits"; diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index facd8ab..0eed1e2 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -1,5 +1,6 @@ #include #include +#include #include "VipM/Utils" #include "VipM/DebugMode" #include "VipM/ArrayTrieUtils" @@ -20,7 +21,7 @@ public VipM_OnLoaded() { g_tModulesLimits = LoadModulesLimitsFromFile(MODULES_CONFIG_FILE, g_tModulesLimits); } -public VipM_OnActivateModule(const sModuleName[]) { +public VipM_Modules_OnActivate(const sModuleName[]) { if ( g_tModulesLimits == Invalid_Trie || !TrieKeyExists(g_tModulesLimits, sModuleName) diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 175c4d0..d4bf911 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -27,8 +27,8 @@ LimitUnit_Init() { LimitType_Init(); g_aLimitUnits = ArrayCreate(S_LimitUnit, 1); - Forwards_Reg("ReadLimitUnit", ET_IGNORE, FP_CELL, FP_CELL); // TODO: call - Forwards_RegAndCall("InitLimits", ET_IGNORE); + + Forwards_RegAndCall("VipM_Limits_OnInited", ET_IGNORE); } LimitUnit_GetCount() { diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index c19ac7e..a36b01f 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -31,7 +31,7 @@ ModuleType_Init() { ArrayMapCreate(g_amModuleTypes, S_ModuleType); - Forwards_Reg("ActivateModule", ET_STOP, FP_STRING); + Forwards_Reg("VipM_Modules_OnActivate", ET_STOP, FP_STRING); } Array:ModuleType_GetAll() { @@ -207,7 +207,7 @@ bool:ModuleType_Activate(const T_ModuleType:iModuleType) { if (!ModuleType[ModuleType_Active]) { Forwards_DefaultReturn(VIPM_CONTINUE); - if (Forwards_CallP("ActivateModule", ModuleType[ModuleType_Name]) != VIPM_CONTINUE) { + if (Forwards_CallP("VipM_Modules_OnActivate", ModuleType[ModuleType_Name]) != VIPM_CONTINUE) { return false; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 5d500ac..6613797 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -5,6 +5,7 @@ #include #include "VipM/Utils" +#include "VipM/Forwards" #include #include "VipM/ArrayMap" #include "VipM/ArrayTrieUtils" @@ -26,8 +27,8 @@ ModuleUnit_Init() { ModuleType_Init(); g_aModuleUnits = ArrayCreate(S_ModuleUnit, 1); - Forwards_Reg("ReadModuleUnit", ET_IGNORE, FP_CELL, FP_CELL); // TODO: call - Forwards_RegAndCall("InitModules", ET_IGNORE); + + Forwards_RegAndCall("VipM_Modules_OnInited", ET_IGNORE); } ModuleUnit_GetCount() { diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc index 803fde9..fd35f46 100644 --- a/amxmodx/scripting/VipM/Core/VipsManager.inc +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -20,7 +20,7 @@ VipsManager_Init() { VipUnit_Init(); g_aVips = ArrayCreate(1, 1); - Forwards_Reg("UserUpdated", ET_IGNORE, FP_CELL); + Forwards_Reg("VipM_OnUserUpdated", ET_IGNORE, FP_CELL); } VipsManager_VipsCount() { @@ -100,7 +100,7 @@ VipsManager_UserReload(const UserId) { } } - Forwards_CallP("UserUpdated", UserId); + Forwards_CallP("VipM_OnUserUpdated", UserId); } VipsManager_UserReset(const UserId) { diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index cdf5783..3820726 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -4,6 +4,8 @@ #include "VipM/ArrayTrieUtils" #include "VipM/Utils" #include "VipM/Forwards" +#include "VipM/Core/Objects/Modules/Type" +#include "VipM/Core/Objects/Limits/Type" #pragma semicolon 1 #pragma compress 1 @@ -23,11 +25,12 @@ public plugin_precache() { register_library(VIPM_LIBRARY); CreateConstCvar("vipm_version", PluginVersion); - Forwards_Init("VipM"); - Forwards_Reg("ReadUnit", ET_IGNORE, FP_CELL, FP_CELL); + Forwards_Init(); VipsManager_Init(); + ModuleType_Init(); SrvCmds_Init(); + Forwards_RegAndCall("VipM_OnInitModules", ET_IGNORE); // deprecated VipsManager_SetRootDir(VipM_iGetCfgPath("")); VipsManager_LoadFromFile(VipM_iGetCfgPath("Vips.json")); @@ -35,7 +38,7 @@ public plugin_precache() { ModuleType_ActivateUsed(); - Forwards_RegAndCall("Loaded", ET_IGNORE); + Forwards_RegAndCall("VipM_OnLoaded", ET_IGNORE); server_print("[%s v%s] Loaded %d config units.", PluginName, PluginVersion, VipsManager_VipsCount()); Dbg_PrintServer("Vip Modular run in debug mode!"); } diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index fe2fa8b..00fb444 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -57,20 +57,23 @@ enum E_LimitsExecType { * Типы лимитов должны регистрироваться строго в рамках этого форварда. * * @note Вызывается в рамках plugin_precache. - * + * + * @deprecated Use VipM_Limits_OnInited instead. + * * @noreturn */ +#pragma deprecated Use VipM_Limits_OnInited instead. forward VipM_OnInitLimits(); /** - * Вызывается перед чтением параметров условного элемента. + * Вызывается в момент, когда нужно регистрировать типы лимитов. + * Типы лимитов должны регистрироваться строго в рамках этого форварда. * - * @param jUnit JSON-обьект с параметрами. - * @param tParams Хэш-карта с прочитанными параметрами. Может быть изменена. + * @note Вызывается в рамках plugin_precache. * - * @return Если возвращено VIPM_STOP, условный элемент будет пропущен. + * @noreturn */ -forward VipM_OnReadLimitUnit(const JSON:jUnit, const Trie:tParams); +forward VipM_Limits_OnInited(); /** * Регистрирует в системе тип условного элемента. diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index 42094a6..773b352 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -66,7 +66,23 @@ enum E_ModuleEvent{ Module_OnMergeParams, } -forward VipM_OnReadModuleUnit(const JSON:jUnit, const Trie:tParams); +/** + * Вызывается . + * + * @param moduleName Название модуля. + * + * @return VIPM_CONTINUE - модуль будет активирован, VIPM_STOP + */ +forward VipM_Modules_OnActivate(const moduleName[]); + +/** + * Вызывается перед активацией модуля. + * + * @param moduleName Название модуля. + * + * @return VIPM_CONTINUE - модуль будет активирован, VIPM_STOP - активация модуля будет прервана. + */ +forward VipM_Modules_OnActivate(const moduleName[]); /** * Регистрирует новый модуль. diff --git a/amxmodx/scripting/include/VipM/Params.inc b/amxmodx/scripting/include/VipM/Params.inc index 9ec76d5..4614c98 100644 --- a/amxmodx/scripting/include/VipM/Params.inc +++ b/amxmodx/scripting/include/VipM/Params.inc @@ -66,6 +66,7 @@ enum E_ParamType { } stock const VIPM_PARAM_TYPE_NAMES[E_ParamType][] = {"Custom", "Integer", "Float", "Bool", "String", "Color", "Vector2", "Vector3", "Limit", "Limits"}; +#pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock any:VipM_Params_GetCell(const Trie:tParams, const sKey[], const any:iDef = 0) { if (tParams == Invalid_Trie) { return iDef; @@ -75,18 +76,22 @@ stock any:VipM_Params_GetCell(const Trie:tParams, const sKey[], const any:iDef = return TrieGetCell(tParams, sKey, iVal) ? iVal : iDef; } +#pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock VipM_Params_GetInt(const Trie:tParams, const sKey[], const iDef = 0) { return _:VipM_Params_GetCell(tParams, sKey, iDef); } +#pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock bool:VipM_Params_GetBool(const Trie:tParams, const sKey[], const bool:bDef = false) { return VipM_Params_GetCell(tParams, sKey, bDef) ? true : false; } +#pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock Float:VipM_Params_GetFloat(const Trie:tParams, const sKey[], const Float:fDef = 0.0) { return Float:VipM_Params_GetCell(tParams, sKey, fDef); } +#pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock VipM_Params_GetStr(const Trie:tParams, const sKey[], sOut[], const iOutLen, const sDef[] = NULL_STRING) { new iWrittenLen = 0; if ( @@ -99,6 +104,7 @@ stock VipM_Params_GetStr(const Trie:tParams, const sKey[], sOut[], const iOutLen return copy(sOut, iOutLen, sDef); } +#pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock VipM_Params_GetStri(const Trie:tParams, const sKey[], const sDef[] = NULL_STRING) { new sStr[MAX_FMT_LENGTH] if ( diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 3b8eb41..64e1a08 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -70,38 +70,32 @@ enum _:VipM_FwdReturn{ } /** - * Вызывается в момент инициалзиации модулей и лимитов. + * Вызывается после инициалзиации модулей и лимитов. * * @note Вызывается из plugin_precache * * @noreturn */ +#pragma deprecated Use VipM_Modules_OnActivate() or VipM_Limits_OnInited() instead. forward VipM_OnInitModules(); /** - * Вызывается в момент чтения элемента конфига (модуля или лимита). - * - * @param jUnit JSON-обьект с параметрами - * @param tParams Хэш-карта с прочитанными параметрами. Может быть изменена. - * - * @note Параметр tParams содержит только прочитанные ядром параметры. + * Вызывается после полной загрузки системы привилегий. * - * @note Соответствует событиям Limit_OnRead и Module_OnRead, - * и форвардам VipM_OnReadLimitUnit и VipM_OnReadModuleUnit. - * Вызывается перед ними. + * @note Вызывается из plugin_precache * - * @return По умолчанию VIPM_CONTINUE. Если вернуть VIPM_STOP, элемент конфига будет проигнорирован. + * @noreturn */ -forward VipM_OnReadUnit(const JSON:jUnit, const Trie:tParams); +forward VipM_OnLoaded(); /** - * Вызывается после полной загрузки системы привилегий. + * Обновляет привилегии указанного пользователя. * - * @note Вызывается из plugin_precache + * @param UserId Индекс игрока, чьи привилегии надо обновить. * * @noreturn */ -forward VipM_OnLoaded(); +native VipM_UserUpdate(const UserId); /** * Вызывается после загрузки привилегий игрока. @@ -114,17 +108,10 @@ forward VipM_OnLoaded(); */ forward VipM_OnUserUpdated(const UserId); -/** - * Обновляет привилегии указанного пользователя. - * - * @param UserId Индекс игрока, чьи привилегии надо обновить. - * - * @noreturn - */ -native VipM_UserUpdate(const UserId); - /** * Выводит лог с указанием JSON-файла, из которого было прочитано указанное значене. + * + * @deprecated * * @param jValue Значение, для которого надо вывести лог. * @param sPrefix Префикс лога. Например: ERROR, WARNING, INFO @@ -133,6 +120,7 @@ native VipM_UserUpdate(const UserId); * * @noreturn */ +#pragma deprecated Use PCJson_*ForFile() instead. native VipM_Json_LogForFile(const JSON:jValue, const sPrefix[], const sMessage[], any:...); #include From 01cdc039b073927e08f116ebb73974700cba5060 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 2 Apr 2025 00:47:16 +0300 Subject: [PATCH 043/108] Use new things instead deprecated --- .../DefaultObjects/ItemType/Armor.inc | 8 ++-- .../DefaultObjects/ItemType/Command.inc | 4 +- .../DefaultObjects/ItemType/CustomWeapon.inc | 4 +- .../DefaultObjects/ItemType/DamageMult.inc | 4 +- .../DefaultObjects/ItemType/Health.inc | 8 ++-- .../DefaultObjects/ItemType/ItemsList.inc | 2 +- .../DefaultObjects/ItemType/Money.inc | 6 +-- .../DefaultObjects/ItemType/Speed.inc | 2 +- .../DefaultObjects/ItemType/Weapon.inc | 6 +-- amxmodx/scripting/VipM-L-Default.sma | 42 +++++++++---------- amxmodx/scripting/VipM-M-SpawnHealth.sma | 10 ++--- amxmodx/scripting/VipM-M-SpawnItems.sma | 4 +- amxmodx/scripting/VipM-M-Vampire.sma | 14 +++---- amxmodx/scripting/VipM-M-VipInTab.sma | 6 +-- amxmodx/scripting/VipM-M-WeaponMenu.sma | 16 +++---- amxmodx/scripting/include/ItemsController.inc | 4 +- amxmodx/scripting/include/VipM/Params.inc | 42 ++++++------------- amxmodx/scripting/include/VipModular.inc | 2 +- 18 files changed, 83 insertions(+), 101 deletions(-) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc index dd62602..c1e398a 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc @@ -36,11 +36,11 @@ DefaultObjects_ItemType_Armor_Register() { } @OnArmorGive(const playerIndex, const Trie:p) { - if (VipM_Params_GetBool(p, "SetArmor", false)) { - rg_set_user_armor(playerIndex, VipM_Params_GetInt(p, "Armor"), VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + if (PCGet_Bool(p, "SetArmor", false)) { + rg_set_user_armor(playerIndex, PCGet_Int(p, "Armor"), PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); } else { - new iSetArmor = min(rg_get_user_armor(playerIndex) + VipM_Params_GetInt(p, "Armor"), VipM_Params_GetInt(p, "MaxArmor", 100)); + new iSetArmor = min(rg_get_user_armor(playerIndex) + PCGet_Int(p, "Armor"), PCGet_Int(p, "MaxArmor", 100)); - rg_set_user_armor(playerIndex, iSetArmor, VipM_Params_GetBool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + rg_set_user_armor(playerIndex, iSetArmor, PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); } } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc index 06fe627..abac4f1 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -32,8 +32,8 @@ DefaultObjects_ItemType_Command_Register() { @OnCommandGive(const playerIndex, const Trie:p) { static Command[128]; - VipM_Params_GetStr(p, "Command", Command, charsmax(Command)); - new bool:ByServer = VipM_Params_GetBool(p, "ByServer", false); + PCGet_Str(p, "Command", Command, charsmax(Command)); + new bool:ByServer = PCGet_Bool(p, "ByServer", false); replace_all(Command, charsmax(Command), "{UserId}", IntToStr(playerIndex)); replace_all(Command, charsmax(Command), "{playerIndex}", IntToStr(playerIndex)); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc index 2f8c5e1..b0e1461 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc @@ -106,13 +106,13 @@ DefaultObjects_ItemType_CustomWeapon_Register() { } static name[32]; - VipM_Params_GetStr(p, "Name", name, charsmax(name)); + PCGet_Str(p, "Name", name, charsmax(name)); if (!name[0]) { log_amx("[WARNING] Custom weapon name is empty."); return IC_RET_GIVE_FAIL; } - new E_ItemType_CustomWeapon_GiveType:giveType = E_ItemType_CustomWeapon_GiveType:VipM_Params_GetInt(p, "GiveType", _:ItemType_CustomWeapon_GiveType_Default); + new E_ItemType_CustomWeapon_GiveType:giveType = E_ItemType_CustomWeapon_GiveType:PCGet_Int(p, "GiveType", _:ItemType_CustomWeapon_GiveType_Default); new bool:res = false; switch (UsingController) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc index be4c014..2d32d57 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc @@ -39,8 +39,8 @@ DefaultObjects_ItemType_DamageMult_Register() { } @ItemType_DamageMult_OnGive(const playerIndex, const Trie:p) { - PlayerGivenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Given", 1.0); - PlayerTakenDmgMult[playerIndex] = VipM_Params_GetFloat(p, "Taken", 1.0); + PlayerGivenDmgMult[playerIndex] = PCGet_Float(p, "Given", 1.0); + PlayerTakenDmgMult[playerIndex] = PCGet_Float(p, "Taken", 1.0); } @ItemType_DamageMult_OnPlayerSpawnPre(const playerIndex) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc index 44782ae..bd864ea 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -33,12 +33,12 @@ DefaultObjects_ItemType_Health_Register() { } @OnHealthGive(const playerIndex, const Trie:p) { - if (VipM_Params_GetBool(p, "SetHealth", false)) { - set_entvar(playerIndex, var_health, VipM_Params_GetFloat(p, "Health")); + if (PCGet_Bool(p, "SetHealth", false)) { + set_entvar(playerIndex, var_health, PCGet_Float(p, "Health")); } else { new Float:fHealth = Float:get_entvar(playerIndex, var_health); - new Float:fMaxHealth = VipM_Params_GetFloat(p, "MaxHealth", 100.0); - new Float:fAddHealth = floatclamp(VipM_Params_GetFloat(p, "Health"), 0.0, floatmax(0.0, fMaxHealth - fHealth)); + new Float:fMaxHealth = PCGet_Float(p, "MaxHealth", 100.0); + new Float:fAddHealth = floatclamp(PCGet_Float(p, "Health"), 0.0, floatmax(0.0, fMaxHealth - fHealth)); new Float:fMaxHealthCurrent = Float:get_entvar(playerIndex, var_max_health); new bool:bNeedOverrideMaxHealth = (fHealth < fMaxHealth && fMaxHealthCurrent < fMaxHealth); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc index 1a1e184..af35d41 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc @@ -25,7 +25,7 @@ DefaultObjects_ItemType_ItemsList_Register() { } @OnItemsListGive(const playerIndex, const Trie:p) { - new Array:aItems = VipM_Params_GetCell(p, "Items", Invalid_Array); + new Array:aItems = PCGet_Cell(p, "Items", Invalid_Array); return IC_Item_GiveArray(playerIndex, aItems) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc index 791572d..22749e2 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -41,9 +41,9 @@ DefaultObjects_ItemType_Money_Register() { @OnMoneyGive(const playerIndex, const Trie:p) { rg_add_account( playerIndex, - VipM_Params_GetInt(p, "Amount"), - VipM_Params_GetCell(p, "GiveType", AS_ADD), - VipM_Params_GetBool(p, "TrackChanges", true) + PCGet_Int(p, "Amount"), + PCGet_Cell(p, "GiveType", AS_ADD), + PCGet_Bool(p, "TrackChanges", true) ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc index c270c1f..0e99eb5 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc @@ -36,7 +36,7 @@ DefaultObjects_ItemType_Speed_Register() { } @ItemType_Speed_OnGive(const playerIndex, const Trie:p) { - PlayerSpeedMult[playerIndex] = VipM_Params_GetFloat(p, "Multiplier", 1.0); + PlayerSpeedMult[playerIndex] = PCGet_Float(p, "Multiplier", 1.0); ItemType_Speed_MultUserSpeed(playerIndex, PlayerSpeedMult[playerIndex]); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc index 331e1be..18e1fad 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -33,7 +33,7 @@ DefaultObjects_ItemType_Weapon_Register() { @OnWeaponGive(const playerIndex, const Trie:p) { static WeaponName[32]; - VipM_Params_GetStr(p, "Name", WeaponName, charsmax(WeaponName)); + PCGet_Str(p, "Name", WeaponName, charsmax(WeaponName)); if (!WeaponName[0]) { return IC_RET_GIVE_FAIL; } @@ -43,8 +43,8 @@ DefaultObjects_ItemType_Weapon_Register() { return IC_RET_GIVE_FAIL; } - new GiveType:iGiveType = GiveType:VipM_Params_GetInt(p, "GiveType", _:GT_DROP_AND_REPLACE); - new iBpAmmo = VipM_Params_GetInt(p, "BpAmmo", -1); + new GiveType:iGiveType = GiveType:PCGet_Int(p, "GiveType", _:GT_DROP_AND_REPLACE); + new iBpAmmo = PCGet_Int(p, "BpAmmo", -1); new ItemId = rg_give_item(playerIndex, WeaponName, iGiveType); if (ItemId < 0) { diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index dc06ec3..df28c52 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -34,7 +34,7 @@ public plugin_natives() { } } -public VipM_OnInitModules() { +public VipM_Limits_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Limits_RegisterType("ForAll", false, true); @@ -266,8 +266,8 @@ public client_authorized(UserId, const AuthId[]) { } @OnTimeCheck(const Trie:tParams) { - new iBefore = VipM_Params_GetInt(tParams, "Before", 0); - new iAfter = VipM_Params_GetInt(tParams, "After", 0); + new iBefore = PCGet_Int(tParams, "Before", 0); + new iAfter = PCGet_Int(tParams, "After", 0); new iCurrent = GetDayTimeInSeconds(); Dbg_Log("@OnTimeCheck(%d):", tParams); @@ -352,17 +352,17 @@ public client_authorized(UserId, const AuthId[]) { @OnInBuyZoneCheck(const Trie:Params, const UserId) { new bool:bInBuyZone = IsUserInBuyZone(UserId); - return VipM_Params_GetBool(Params, "Reverse", false) ? !bInBuyZone : bInBuyZone; + return PCGet_Bool(Params, "Reverse", false) ? !bInBuyZone : bInBuyZone; } @OnInFreezyTimeCheck(const Trie:Params) { new bool:bFreezyPeriod = get_member_game(m_bFreezePeriod); - return VipM_Params_GetBool(Params, "Reverse", false) ? !bFreezyPeriod : bFreezyPeriod; + return PCGet_Bool(Params, "Reverse", false) ? !bFreezyPeriod : bFreezyPeriod; } @OnRoundTimeCheck(const Trie:Params) { - new iMin = VipM_Params_GetInt(Params, "Min", 0); - new iMax = VipM_Params_GetInt(Params, "Max", 0); + new iMin = PCGet_Int(Params, "Min", 0); + new iMax = PCGet_Int(Params, "Max", 0); new iRoundTime = floatround(get_gametime() - Float:get_member_game(m_fRoundStartTime)); return ( @@ -372,8 +372,8 @@ public client_authorized(UserId, const AuthId[]) { } @OnLifeTimeCheck(const Trie:Params, const UserId) { - new iMin = VipM_Params_GetInt(Params, "Min", 0); - new iMax = VipM_Params_GetInt(Params, "Max", 0); + new iMin = PCGet_Int(Params, "Min", 0); + new iMax = PCGet_Int(Params, "Max", 0); new iLifeTime = floatround(get_gametime() - g_fPlayerSpawnTime[UserId]); return ( @@ -398,7 +398,7 @@ public client_authorized(UserId, const AuthId[]) { @OnWeekDayCheck(const Trie:Params) { new sWeekDay[4]; get_time("%w", sWeekDay, charsmax(sWeekDay)); - return str_to_num(sWeekDay) == VipM_Params_GetInt(Params, "Day", -1); + return str_to_num(sWeekDay) == PCGet_Int(Params, "Day", -1); } @OnAliveCheck(const Trie:Params, const UserId) { @@ -406,37 +406,37 @@ public client_authorized(UserId, const AuthId[]) { } @OnNameCheck(const Trie:Params, const UserId) { - return IsEqualUserName(UserId, VipM_Params_GetStri(Params, "Name")); + return IsEqualUserName(UserId, PCGet_iStr(Params, "Name")); } bool:@OnFlagsCheck(const Trie:Params, const UserId) { static sFlags[16]; - VipM_Params_GetStr(Params, "Flags", sFlags, charsmax(sFlags)); + PCGet_Str(Params, "Flags", sFlags, charsmax(sFlags)); - return HasUserFlagsStr(UserId, sFlags, VipM_Params_GetBool(Params, "Strict", false)); + return HasUserFlagsStr(UserId, sFlags, PCGet_Bool(Params, "Strict", false)); } @OnSteamIdCheck(const Trie:Params, const UserId) { static sSteamId[64]; - VipM_Params_GetStr(Params, "SteamId", sSteamId, charsmax(sSteamId)); + PCGet_Str(Params, "SteamId", sSteamId, charsmax(sSteamId)); return equali(g_sSteamIds[UserId], sSteamId); } @OnIpCheck(const Trie:Params, const UserId) { static sIp[32]; - VipM_Params_GetStr(Params, "SteamId", sIp, charsmax(sIp)); + PCGet_Str(Params, "SteamId", sIp, charsmax(sIp)); return equali(g_sIps[UserId], sIp); } @OnMapCheck(const Trie:Params) { static sMap[32]; - VipM_Params_GetStr(Params, "Map", sMap, charsmax(sMap)); + PCGet_Str(Params, "Map", sMap, charsmax(sMap)); - new iCount = VipM_Params_GetBool(Params, "Prefix", false) ? strlen(sMap) : 0; + new iCount = PCGet_Bool(Params, "Prefix", false) ? strlen(sMap) : 0; - if (VipM_Params_GetBool(Params, "Real", false)) { + if (PCGet_Bool(Params, "Real", false)) { return equali(sMap, g_sRealMapName, iCount); } else { static sSetMapName[32]; @@ -447,13 +447,13 @@ bool:@OnFlagsCheck(const Trie:Params, const UserId) { @OnHasPrimaryWeaponCheck(const Trie:Params, const UserId) { new bool:res = get_member(UserId, m_bHasPrimary); - return VipM_Params_GetBool(Params, "HasNot", false) ? !res : res; + return PCGet_Bool(Params, "HasNot", false) ? !res : res; } @OnRoundCheck(const Trie:Params, const UserId){ return ( - GetCurrentRoundNum() >= VipM_Params_GetInt(Params, "Min", -1) - && GetCurrentRoundNum() <= VipM_Params_GetInt(Params, "Max", cellmax) + GetCurrentRoundNum() >= PCGet_Int(Params, "Min", -1) + && GetCurrentRoundNum() <= PCGet_Int(Params, "Max", cellmax) ); } diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index 8b06e9c..ccea914 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -16,7 +16,7 @@ public stock const PluginDescription[] = "Vip modular`s module - SpawnHealth"; new const MODULE_NAME[] = "SpawnHealth"; -public VipM_OnInitModules(){ +public VipM_Modules_OnInited(){ register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Modules_Register(MODULE_NAME, true); @@ -51,7 +51,7 @@ public VipM_OnInitModules(){ return; } - Dbg_Log("@Event_PlayerSpawned(%d): Limits Count = %d", UserId, ArraySizeSafe(VipM_Params_GetCell(Params, "Limits", Invalid_Array))); + Dbg_Log("@Event_PlayerSpawned(%d): Limits Count = %d", UserId, ArraySizeSafe(PCGet_Cell(Params, "Limits", Invalid_Array))); if (!VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND)) { return; } @@ -59,7 +59,7 @@ public VipM_OnInitModules(){ new Health; if (TrieGetCell(Params, "Health", Health) && Health > 0) { - if (!VipM_Params_GetBool(Params, "SetHealth", true)) { + if (!PCGet_Bool(Params, "SetHealth", true)) { Health += floatround(get_entvar(UserId, var_health)); new MaxHealth; @@ -72,7 +72,7 @@ public VipM_OnInitModules(){ new Armor; if (TrieGetCell(Params, "Armor", Armor) && Armor > 0) { - if (!VipM_Params_GetBool(Params, "SetArmor", true)) { + if (!PCGet_Bool(Params, "SetArmor", true)) { Health += rg_get_user_armor(UserId); new MaxHealth; @@ -80,6 +80,6 @@ public VipM_OnInitModules(){ Health = min(Health, MaxHealth); } } - rg_set_user_armor(UserId, Armor, VipM_Params_GetBool(Params, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + rg_set_user_armor(UserId, Armor, PCGet_Bool(Params, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); } } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index 23b0a40..f9308d2 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -16,7 +16,7 @@ public stock const PluginDescription[] = "Vip modular`s module - Spawn Items"; new const MODULE_NAME[] = "SpawnItems"; -public VipM_OnInitModules() { +public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); IC_Init(); @@ -73,7 +73,7 @@ public VipM_OnInitModules() { return; } - new Array:aItems = Array:VipM_Params_GetInt(Params, "Items", _:Invalid_Array); + new Array:aItems = Array:PCGet_Int(Params, "Items", _:Invalid_Array); if (aItems == Invalid_Array) { Dbg_Log("@GivePlayerItems(%n) Items array is empty", UserId); return; diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index 9ab2384..ce1630a 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -14,7 +14,7 @@ public stock const PluginDescription[] = "Vip modular`s module - Vampire"; new const MODULE_NAME[] = "Vampire"; -public VipM_OnInitModules(){ +public VipM_Modules_OnInited(){ register_plugin(PluginName, PluginVersion, PluginAuthor); register_dictionary("VipM-Vampire.ini"); @@ -50,17 +50,17 @@ public VipM_OnInitModules(){ return; } - if (!VipM_Limits_ExecuteList(VipM_Params_GetCell(Params, "Limits", Invalid_Array), UserId)) { + if (!VipM_Limits_ExecuteList(PCGet_Cell(Params, "Limits", Invalid_Array), UserId)) { return; } - new MaxHealth = VipM_Params_GetInt(Params, "MaxHealth", 100); + new MaxHealth = PCGet_Int(Params, "MaxHealth", 100); new Health = floatround(get_entvar(UserId, var_health)); if (Health >= MaxHealth) { return; } - new ByKill = VipM_Params_GetInt(Params, "ByKill", 0); + new ByKill = PCGet_Int(Params, "ByKill", 0); new VampHealth = 0; new ActiveItem; ActiveItem = get_member(UserId, m_pActiveItem); if ( @@ -68,11 +68,11 @@ public VipM_OnInitModules(){ && is_entity(ActiveItem) && rg_get_iteminfo(ActiveItem, ItemInfo_iId) == CSW_KNIFE ) { - VampHealth = VipM_Params_GetInt(Params, "ByKnife", ByKill); + VampHealth = PCGet_Int(Params, "ByKnife", ByKill); } else if(get_member(VictimId, m_bHeadshotKilled)) { - VampHealth = VipM_Params_GetInt(Params, "ByHead", ByKill); + VampHealth = PCGet_Int(Params, "ByHead", ByKill); } else if (get_member(VictimId, m_bKilledByGrenade)) { - VampHealth = VipM_Params_GetInt(Params, "ByGrenade", ByKill); + VampHealth = PCGet_Int(Params, "ByGrenade", ByKill); } else { VampHealth = ByKill; } diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index 746588a..c94a04e 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -20,7 +20,7 @@ new const MODULE_NAME[] = "VipInTab"; new bool:gHasTag[MAX_PLAYERS + 1][E_ModuleParams]; -public VipM_OnInitModules() { +public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Modules_Register(MODULE_NAME, true); @@ -34,8 +34,8 @@ public VipM_OnInitModules() { public VipM_OnUserUpdated(const UserId) { new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); - gHasTag[UserId][Param_Enabled] = VipM_Params_GetBool(Params, "Enabled", false); - gHasTag[UserId][Param_Override] = VipM_Params_GetBool(Params, "Override", false); + gHasTag[UserId][Param_Enabled] = PCGet_Bool(Params, "Enabled", false); + gHasTag[UserId][Param_Override] = PCGet_Bool(Params, "Override", false); } @OnModuleActivate() { diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 6b6e6a9..94a52df 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -41,7 +41,7 @@ new gUserExpireStatus[MAX_PLAYERS + 1][VIPM_M_WEAPONMENU_EXPIRE_STATUS_MAX_LEN]; #include "VipM/WeaponMenu/KeyValueCounter" #include "VipM/WeaponMenu/Menus" -public VipM_OnInitModules() { +public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_dictionary("VipM-WeaponMenu.ini"); IC_Init(); @@ -99,7 +99,7 @@ public VipM_OnInitModules() { ResetUserMenuCounters(const UserId) { new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); - gUserLeftItems[UserId] = VipM_Params_GetInt(Params, "Count", -1); + gUserLeftItems[UserId] = PCGet_Int(Params, "Count", -1); g_tUserMenuItemsCounter[UserId] = KeyValueCounter_Reset(g_tUserMenuItemsCounter[UserId]); gUserShouldResetCounters[UserId] = false; @@ -151,15 +151,15 @@ public client_disconnected(UserId) { return; } - set_task(VipM_Params_GetFloat(Params, "AutoopenDelay", 0.0), "@Task_AutoOpen", TASK_OFFSET_AUTO_OPEN + UserId); + set_task(PCGet_Float(Params, "AutoopenDelay", 0.0), "@Task_AutoOpen", TASK_OFFSET_AUTO_OPEN + UserId); } @Task_AutoOpen(UserId) { UserId -= TASK_OFFSET_AUTO_OPEN; new Trie:tParams = VipM_Modules_GetParams(MODULE_NAME, UserId); - new Float:fAutoCloseDelay = VipM_Params_GetFloat(tParams, "AutoopenCloseDelay", 0.0); - new iMenuNum = VipM_Params_GetInt(tParams, "AutoopenMenuNum", -1); + new Float:fAutoCloseDelay = PCGet_Float(tParams, "AutoopenCloseDelay", 0.0); + new iMenuNum = PCGet_Int(tParams, "AutoopenMenuNum", -1); if (iMenuNum > 0) { CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU_SILENT, IntToStr(iMenuNum - 1)); @@ -238,7 +238,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU, "0"); } else { static MainMenuTitle[128]; - VipM_Params_GetStr(Params, "MainMenuTitle", MainMenuTitle, charsmax(MainMenuTitle)); + PCGet_Str(Params, "MainMenuTitle", MainMenuTitle, charsmax(MainMenuTitle)); Menu_MainMenu(UserId, MainMenuTitle, aMenus); } return; @@ -320,9 +320,9 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { } if ( - VipM_Params_GetBool(Params, "StayOpen", false) + PCGet_Bool(Params, "StayOpen", false) && ( - !VipM_Params_GetBool(Params, "StayOpen_CheckCounter", true) + !PCGet_Bool(Params, "StayOpen_CheckCounter", true) || iItemsLeft != 0 ) ) { diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 7966b14..db22646 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -209,7 +209,7 @@ stock bool:IC_Item_GiveArray(const playerIndex, const Array:array) { /** * Вызывается в момент инициалзиации типов предметов. * - * @note Вызывается из VipM_OnInitModules + * @note Вызывается не позже plugin_precache. * * @noreturn * @@ -349,7 +349,7 @@ stock bool:VipM_Params_GiveItems(const UserId, const Trie:tParams, const sParam[ } stock bool:VipM_Params_GiveItem(const UserId, const Trie:tParams, const sParam[]) { - return IC_Item_Give(UserId, VipM_Params_GetCell(tParams, sParam)); + return IC_Item_Give(UserId, PCGet_Cell(tParams, sParam)); } #pragma deprecated Use Json_Object_IC_GetItems() instead. diff --git a/amxmodx/scripting/include/VipM/Params.inc b/amxmodx/scripting/include/VipM/Params.inc index 4614c98..041cd45 100644 --- a/amxmodx/scripting/include/VipM/Params.inc +++ b/amxmodx/scripting/include/VipM/Params.inc @@ -3,7 +3,8 @@ #endif #define _vipmodular_params_included -#include amxmodx +#include +#include #define VIPM_PARAM_NAME_MAX_LEN 32 @@ -68,61 +69,42 @@ stock const VIPM_PARAM_TYPE_NAMES[E_ParamType][] = {"Custom", "Integer", "Float" #pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock any:VipM_Params_GetCell(const Trie:tParams, const sKey[], const any:iDef = 0) { - if (tParams == Invalid_Trie) { - return iDef; - } - - new any:iVal; - return TrieGetCell(tParams, sKey, iVal) ? iVal : iDef; + return PCGet_Cell(tParams, sKey, iDef); } #pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock VipM_Params_GetInt(const Trie:tParams, const sKey[], const iDef = 0) { - return _:VipM_Params_GetCell(tParams, sKey, iDef); + return PCGet_Int(tParams, sKey, iDef); } #pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock bool:VipM_Params_GetBool(const Trie:tParams, const sKey[], const bool:bDef = false) { - return VipM_Params_GetCell(tParams, sKey, bDef) ? true : false; + return PCGet_Bool(tParams, sKey, bDef) ? true : false; } #pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock Float:VipM_Params_GetFloat(const Trie:tParams, const sKey[], const Float:fDef = 0.0) { - return Float:VipM_Params_GetCell(tParams, sKey, fDef); + return PCGet_Float(tParams, sKey, fDef); } #pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock VipM_Params_GetStr(const Trie:tParams, const sKey[], sOut[], const iOutLen, const sDef[] = NULL_STRING) { - new iWrittenLen = 0; - if ( - tParams != Invalid_Trie - && TrieGetString(tParams, sKey, sOut, iOutLen, iWrittenLen) - ) { - return iWrittenLen; - } - - return copy(sOut, iOutLen, sDef); + return PCGet_Str(tParams, sKey, sOut, iOutLen, sDef); } #pragma deprecated Use PCGet_*() stocks from ParamsController instead. stock VipM_Params_GetStri(const Trie:tParams, const sKey[], const sDef[] = NULL_STRING) { - new sStr[MAX_FMT_LENGTH] - if ( - tParams == Invalid_Trie - || !TrieGetString(tParams, sKey, sStr, charsmax(sStr)) - ) { - copy(sStr, charsmax(sStr), sDef); - } - - return sStr; + new str[PARAM_VALUE_MAX_LEN]; + PCGet_Str(p, key, str, charsmax(str), def); + return str; } stock Array:VipM_Params_GetArr(const Trie:tParams, const sKey[]) { - return Array:VipM_Params_GetCell(tParams, sKey, Invalid_Array); + return Array:PCGet_Cell(tParams, sKey, Invalid_Array); } stock T_LimitUnit:VipM_Params_GetLimit(const Trie:tParams, const sKey[], const T_LimitUnit:iDef = Invalid_LimitUnit) { - return T_LimitUnit:VipM_Params_GetCell(tParams, sKey, iDef); + return T_LimitUnit:PCGet_Cell(tParams, sKey, iDef); } stock bool:VipM_Params_ExecuteLimit( diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 64e1a08..27b46da 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -76,7 +76,7 @@ enum _:VipM_FwdReturn{ * * @noreturn */ -#pragma deprecated Use VipM_Modules_OnActivate() or VipM_Limits_OnInited() instead. +#pragma deprecated Use VipM_Modules_OnInited() or VipM_Limits_OnInited() instead. forward VipM_OnInitModules(); /** From cc2d1a7be33963e966322098eda86fd2ba73e524 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 2 Apr 2025 00:56:26 +0300 Subject: [PATCH 044/108] Update requirements --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 5dea087..2c19cf5 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ Модульная система привилегий. +## Требования + +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.0.0-b5](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.0.0-b5) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). +- [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). + ## Инструкции по настройке - [Основные настройки](readme/configs.md) From 96b84b52824756caddbeb1f2cf9383344ad49d75 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 19 Apr 2025 20:40:57 +0300 Subject: [PATCH 045/108] Fix `CustomWeapon` item --- .../DefaultObjects/ItemType/CustomWeapon.inc | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc index b0e1461..ea0ea55 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc @@ -45,24 +45,27 @@ enum E_ItemType_CustomWeapon_GiveType { } static E_ItemType_CustomWeapon_Controller:UsingController = ItemType_CustomWeapon_Controller_None; -static bool:AvailableControllers[E_ItemType_CustomWeapon_Controller] = {false, ...}; + +// Почему-то через {true, ...} всё кроме первой ячейки ставится в false. +static bool:AvailableControllers[E_ItemType_CustomWeapon_Controller] = {true, true, true, true}; bool:DefaultObjects_ItemType_CustomWeapon_NativeFilter(const name[], const trap) { if (equal(name, "CWAPI_Weapons_Give")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = !!trap; + AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = false; return true; } if (equal(name, "CWAPI_Weapons_Find")) { + AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = false; return true; } if (equal(name, "__auw__native__auw_give_weapon")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Auw] = !!trap; + AvailableControllers[ItemType_CustomWeapon_Controller_Auw] = false; return true; } if (equal(name, "weapons_give_user_ultimate")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Uw] = !!trap; + AvailableControllers[ItemType_CustomWeapon_Controller_Uw] = false; return true; } @@ -71,7 +74,7 @@ bool:DefaultObjects_ItemType_CustomWeapon_NativeFilter(const name[], const trap) DefaultObjects_ItemType_CustomWeapon_Register() { UsingController = ItemType_CustomWeapon_Controller_None; - for (new i = 0; i < _:E_ItemType_CustomWeapon_Controller; ++i) { + for (new i = _:ItemType_CustomWeapon_Controller_Cwapi; i < _:E_ItemType_CustomWeapon_Controller; ++i) { if (AvailableControllers[E_ItemType_CustomWeapon_Controller:i]) { UsingController = E_ItemType_CustomWeapon_Controller:i; } @@ -90,9 +93,9 @@ DefaultObjects_ItemType_CustomWeapon_Register() { return IC_RET_READ_FAIL; } - new Name[32]; - json_object_get_string(instanceJson, "Name", Name, charsmax(Name)); - TrieSetString(p, "Name", Name); + new name[64]; + json_object_get_string(instanceJson, "Name", name, charsmax(name)); + TrieSetString(p, "Name", name); TrieSetCell(p, "GiveType", _:ItemType_CustomWeapon_ReadGiveTypeFromJsonObject(instanceJson, "GiveType")); @@ -105,7 +108,7 @@ DefaultObjects_ItemType_CustomWeapon_Register() { return IC_RET_GIVE_FAIL; } - static name[32]; + static name[64]; PCGet_Str(p, "Name", name, charsmax(name)); if (!name[0]) { log_amx("[WARNING] Custom weapon name is empty."); From d17e7b3a54a9d88eab06bac766e235bc7ab5d1c9 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 23 Apr 2025 15:59:32 +0300 Subject: [PATCH 046/108] Fix ic compat api --- amxmodx/scripting/ItemsController/API/Compat.inc | 2 +- .../DefaultObjects/ItemType/CustomWeapon.inc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/amxmodx/scripting/ItemsController/API/Compat.inc b/amxmodx/scripting/ItemsController/API/Compat.inc index e16bfb6..89046ec 100644 --- a/amxmodx/scripting/ItemsController/API/Compat.inc +++ b/amxmodx/scripting/ItemsController/API/Compat.inc @@ -42,7 +42,7 @@ T_IC_ItemType:@_VipM_IC_RegisterType() { T_IC_Item:@_VipM_IC_JsonGetItem() { enum {Arg_InstanceJson = 1} - new JSON:isntanceJson = JSON:get_param(Arg_InstanceJson); + new JSON:isntanceJson = JSON:get_param_byref(Arg_InstanceJson); new T_IC_Item:item = ItemInstance_ReadFromJsonObject(isntanceJson); json_free(isntanceJson); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc index ea0ea55..9016b2b 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/CustomWeapon.inc @@ -51,21 +51,21 @@ static bool:AvailableControllers[E_ItemType_CustomWeapon_Controller] = {true, tr bool:DefaultObjects_ItemType_CustomWeapon_NativeFilter(const name[], const trap) { if (equal(name, "CWAPI_Weapons_Give")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = false; + AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = !!trap; return true; } if (equal(name, "CWAPI_Weapons_Find")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = false; + AvailableControllers[ItemType_CustomWeapon_Controller_Cwapi] = !!trap; return true; } if (equal(name, "__auw__native__auw_give_weapon")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Auw] = false; + AvailableControllers[ItemType_CustomWeapon_Controller_Auw] = !!trap; return true; } if (equal(name, "weapons_give_user_ultimate")) { - AvailableControllers[ItemType_CustomWeapon_Controller_Uw] = false; + AvailableControllers[ItemType_CustomWeapon_Controller_Uw] = !!trap; return true; } From b6469ff38e6dc0e45dcf3a356b00f742920a9680 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 14 Jun 2025 17:22:24 +0300 Subject: [PATCH 047/108] Use PCGet and PCSingle --- amxmodx/scripting/IC-I-Limits.sma | 13 ++-- amxmodx/scripting/ItemsController.sma | 8 ++- .../API/{Items.inc => Item.inc} | 27 +------ .../ItemsController/API/ItemType.inc | 43 +++++++++++ .../DefaultObjects/ItemType/Armor.inc | 46 ++++-------- .../DefaultObjects/ItemType/Command.inc | 30 ++------ .../DefaultObjects/ItemType/DamageMult.inc | 34 +++------ .../DefaultObjects/ItemType/Health.inc | 30 ++------ .../DefaultObjects/ItemType/ItemsList.inc | 25 ++----- .../DefaultObjects/ItemType/Random.inc | 33 ++------- .../DefaultObjects/ItemType/Speed.inc | 30 ++------ .../DefaultObjects/ParamType/Item.inc | 19 +++++ .../DefaultObjects/ParamType/Items.inc | 28 ++++++++ .../DefaultObjects/Registrar.inc | 10 ++- .../ItemsController/Objects/Items/Type.inc | 35 +++++++-- amxmodx/scripting/VipM-L-Default.sma | 8 +-- amxmodx/scripting/VipM-M-SpawnHealth.sma | 2 +- amxmodx/scripting/VipM-M-SpawnItems.sma | 2 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 4 +- .../VipM/WeaponMenu/Objects/MenuItem.inc | 2 +- amxmodx/scripting/include/ItemsController.inc | 71 ++++++++++++++----- amxmodx/scripting/include/VipM/Limits.inc | 31 +++++++- amxmodx/scripting/include/VipM/Params.inc | 5 +- 23 files changed, 290 insertions(+), 246 deletions(-) rename amxmodx/scripting/ItemsController/API/{Items.inc => Item.inc} (58%) create mode 100644 amxmodx/scripting/ItemsController/API/ItemType.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc diff --git a/amxmodx/scripting/IC-I-Limits.sma b/amxmodx/scripting/IC-I-Limits.sma index 4263703..8f697f5 100644 --- a/amxmodx/scripting/IC-I-Limits.sma +++ b/amxmodx/scripting/IC-I-Limits.sma @@ -40,14 +40,9 @@ public IC_ItemType_OnInited() { } @OnIfGive(const playerIndex, const Trie:p) { - new Array:items = Invalid_Array; - if (VipM_Params_ExecuteLimitsList(p, "Limits", playerIndex, Limit_Exec_AND)) { - items = VipM_Params_GetArr(p, "Items"); - } else { - items = VipM_Params_GetArr(p, "ElseItems"); + if (!PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND)) { + return PCGet_IcItemsGive(p, "ElseItems", playerIndex) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } - - return IC_Item_GiveArray(playerIndex, items) - ? IC_RET_GIVE_SUCCESS - : IC_RET_GIVE_FAIL; + + return PCGet_IcItemsGive(p, "Items", playerIndex) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index 3a4bdf2..18ef483 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -22,14 +22,15 @@ PluginInit() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_library(IC_LIBRARY); CreateConstCvar(IC_VERSION_CVAR, IC_VERSION); + ParamsController_Init(); Forwards_Init(); ItemInstance_Init(); - DefaultObjects_RegisterAll(); Forwards_RegAndCall("VipM_IC_OnInitTypes", ET_IGNORE); // deprecated } -#include "ItemsController/API/Items" +#include "ItemsController/API/ItemType" +#include "ItemsController/API/Item" #include "ItemsController/API/Compat" public plugin_natives() { @@ -38,7 +39,8 @@ public plugin_natives() { register_native("IC_Init", "@_Init"); register_native("VipM_IC_Init", "@_Init"); // deprecated - API_Items_Register(); + API_ItemType_Register(); + API_Item_Register(); API_Compat_Register(); } diff --git a/amxmodx/scripting/ItemsController/API/Items.inc b/amxmodx/scripting/ItemsController/API/Item.inc similarity index 58% rename from amxmodx/scripting/ItemsController/API/Items.inc rename to amxmodx/scripting/ItemsController/API/Item.inc index 5e062d7..482b347 100644 --- a/amxmodx/scripting/ItemsController/API/Items.inc +++ b/amxmodx/scripting/ItemsController/API/Item.inc @@ -2,40 +2,15 @@ #include #include -#include "ItemsController/Objects/Items/Type" #include "ItemsController/Objects/Items/Instance" -API_Items_Register() { - register_native("IC_ItemType_Register", "@_ItemType_Register"); - register_native("IC_ItemType_SetEventListener", "@_ItemType_SetEventListener"); - +API_Item_Register() { register_native("IC_Item_ReadFromJson", "@_Item_ReadFromJson"); register_native("IC_Item_ReadArrayFromJson", "@_Item_ReadArrayFromJson"); register_native("IC_Item_Give", "@_Item_Give"); register_native("IC_Item_Free", "@_Item_Free"); } -T_IC_ItemType:@_ItemType_Register() { - enum {Arg_Name = 1} - - new name[IC_ITEM_TYPE_NAME_MAX_LEN]; - get_string(Arg_Name, name, charsmax(name)); - - return ItemType_Construct(name); -} - -@_ItemType_SetEventListener(const pluginIndex) { - enum {Arg_Type = 1, Arg_Event, Arg_FuncName} - - new T_IC_ItemType:type = T_IC_ItemType:get_param(Arg_Type); - new E_ItemTypeEvent:event = E_ItemTypeEvent:get_param(Arg_Event); - new funcName[IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN]; - get_string(Arg_FuncName, funcName, charsmax(funcName)); - - new listener = ItemType_MakeEventListener(event, pluginIndex, funcName); - ItemType_SetEventListener(type, event, listener); -} - T_IC_Item:@_Item_ReadFromJson() { enum {Arg_InstanceJson = 1} diff --git a/amxmodx/scripting/ItemsController/API/ItemType.inc b/amxmodx/scripting/ItemsController/API/ItemType.inc new file mode 100644 index 0000000..b4afe45 --- /dev/null +++ b/amxmodx/scripting/ItemsController/API/ItemType.inc @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "ItemsController/Objects/Items/Type" + +API_ItemType_Register() { + register_native("IC_ItemType_Register", "@_ItemType_Register"); + register_native("IC_ItemType_SetEventListener", "@_ItemType_SetEventListener"); + register_native("IC_ItemType_AddParams", "@_ItemType_AddParams"); +} + +T_IC_ItemType:@_ItemType_Register() { + enum {Arg_Name = 1} + + new name[IC_ITEM_TYPE_NAME_MAX_LEN]; + get_string(Arg_Name, name, charsmax(name)); + + return ItemType_Construct(name); +} + +@_ItemType_SetEventListener(const pluginIndex) { + enum {Arg_Type = 1, Arg_Event, Arg_FuncName} + + new T_IC_ItemType:type = T_IC_ItemType:get_param(Arg_Type); + new E_ItemTypeEvent:event = E_ItemTypeEvent:get_param(Arg_Event); + new funcName[IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN]; + get_string(Arg_FuncName, funcName, charsmax(funcName)); + + new listener = ItemType_MakeEventListener(event, pluginIndex, funcName); + ItemType_SetEventListener(type, event, listener); +} + +@_ItemType_AddParams(const pluginIndex, const paramsCount) { + enum {Arg_Type = 1, Arg_Params} + + new T_IC_ItemType:type = T_IC_ItemType:get_param(Arg_Type); + new Array:params = ParamsController_Param_ListFromNativeParams(Arg_Params, paramsCount); + + ItemType_AddParams(type, params); + + ArrayDestroy(params); +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc index c1e398a..f645986 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc @@ -1,46 +1,28 @@ #include #include -#include #include +#include DefaultObjects_ItemType_Armor_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Armor", - .onRead = "@OnArmorRead", .onGive = "@OnArmorGive" ); -} - -@OnArmorRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Armor", JSONNumber)) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Armor` required for `Armor` item."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Armor", json_object_get_number(instanceJson, "Armor")); - - if (json_object_has_value(instanceJson, "MaxArmor", JSONNumber)) { - TrieSetCell(p, "MaxArmor", json_object_get_number(instanceJson, "MaxArmor")); - } - - if (json_object_has_value(instanceJson, "SetArmor", JSONBoolean)) { - TrieSetCell(p, "SetArmor", json_object_get_bool(instanceJson, "SetArmor")); - } - - if (json_object_has_value(instanceJson, "Helmet", JSONBoolean)) { - TrieSetCell(p, "Helmet", json_object_get_bool(instanceJson, "Helmet")); - } - - return IC_RET_READ_SUCCESS; + IC_ItemType_AddParams(type, + "Armor", "Integer", true, + "MaxArmor", "Integer", false, + "SetArmor", "Boolean", false, + "Helmet", "Boolean", false + ); } @OnArmorGive(const playerIndex, const Trie:p) { - if (PCGet_Bool(p, "SetArmor", false)) { - rg_set_user_armor(playerIndex, PCGet_Int(p, "Armor"), PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); - } else { - new iSetArmor = min(rg_get_user_armor(playerIndex) + PCGet_Int(p, "Armor"), PCGet_Int(p, "MaxArmor", 100)); + new armor = PCGet_Int(p, "Armor"); + new ArmorType:helm = PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR; - rg_set_user_armor(playerIndex, iSetArmor, PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + if (!PCGet_Bool(p, "SetArmor", false)) { + armor = min(rg_get_user_armor(playerIndex) + armor, PCGet_Int(p, "MaxArmor", 100)); } + + rg_set_user_armor(playerIndex, armor, helm); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc index abac4f1..1766dfc 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -1,44 +1,26 @@ #include #include -#include #include DefaultObjects_ItemType_Command_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Command", - .onRead = "@OnCommandRead", .onGive = "@OnCommandGive" ); -} - -@OnCommandRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Command", JSONString)) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Command` required for item `Command`."); - return IC_RET_READ_FAIL; - } - - new Command[128]; - json_object_get_string(instanceJson, "Command", Command, charsmax(Command)); - TrieSetString(p, "Command", Command); - - if (json_object_has_value(instanceJson, "ByServer", JSONBoolean)) { - TrieSetCell(p, "ByServer", json_object_get_bool(instanceJson, "ByServer")); - } - - return IC_RET_READ_SUCCESS; + IC_ItemType_AddParams(type, + "Command", "String", true, + "ByServer", "Boolean", false + ); } @OnCommandGive(const playerIndex, const Trie:p) { static Command[128]; PCGet_Str(p, "Command", Command, charsmax(Command)); - new bool:ByServer = PCGet_Bool(p, "ByServer", false); replace_all(Command, charsmax(Command), "{UserId}", IntToStr(playerIndex)); replace_all(Command, charsmax(Command), "{playerIndex}", IntToStr(playerIndex)); - if (ByServer) { + if (PCGet_Bool(p, "ByServer", false)) { server_cmd(Command); } else { client_cmd(playerIndex, Command); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc index 2d32d57..4629635 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc @@ -1,41 +1,23 @@ #include #include -#include #include -#include // Для VipM_Params_* // TODO: уйти на аналог от контроллера параметров, когда он будет - -static HookChain:PlayerSpawnPreHookChain = INVALID_HOOKCHAIN; -static HookChain:PlayerTakeDamagePreHookChain = INVALID_HOOKCHAIN; +#include static Float:PlayerGivenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; static Float:PlayerTakenDmgMult[MAX_PLAYERS + 1] = {1.0, ...}; DefaultObjects_ItemType_DamageMult_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "DamageMult", - .onRead = "@ItemType_DamageMult_OnRead", .onGive = "@ItemType_DamageMult_OnGive" ); + IC_ItemType_AddParams(type, + "Given", "Float", false, + "Taken", "Float", false + ); - DisableHookChain(PlayerSpawnPreHookChain = RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_DamageMult_OnPlayerSpawnPre", false)); - DisableHookChain(PlayerTakeDamagePreHookChain = RegisterHookChain(RG_CBasePlayer_TakeDamage, "@ItemType_DamageMult_OnPlayerTakeDamage", false)); -} - -@ItemType_DamageMult_OnRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (json_object_has_value(instanceJson, "Given", JSONNumber)) { - TrieSetCell(p, "Given", json_object_get_real(instanceJson, "Given")); - } - - if (json_object_has_value(instanceJson, "Taken", JSONNumber)) { - TrieSetCell(p, "Taken", json_object_get_real(instanceJson, "Taken")); - } - - EnableHookChain(PlayerSpawnPreHookChain); - EnableHookChain(PlayerTakeDamagePreHookChain); - - return IC_RET_READ_SUCCESS; + RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_DamageMult_OnPlayerSpawnPre", false); + RegisterHookChain(RG_CBasePlayer_TakeDamage, "@ItemType_DamageMult_OnPlayerTakeDamage", false); } @ItemType_DamageMult_OnGive(const playerIndex, const Trie:p) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc index bd864ea..23a0283 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -1,35 +1,19 @@ #include #include #include -#include #include +#include DefaultObjects_ItemType_Health_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Health", - .onRead = "@OnHealthRead", .onGive = "@OnHealthGive" ); -} - -@OnHealthRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Health", JSONNumber)) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Health` required for `Health` item."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Health", json_object_get_real(instanceJson, "Health")); - - if (json_object_has_value(instanceJson, "MaxHealth", JSONNumber)) { - TrieSetCell(p, "MaxHealth", json_object_get_real(instanceJson, "MaxHealth")); - } - - if (json_object_has_value(instanceJson, "SetHealth", JSONBoolean)) { - TrieSetCell(p, "SetHealth", json_object_get_bool(instanceJson, "SetHealth")); - } - - return IC_RET_READ_SUCCESS; + IC_ItemType_AddParams(type, + "Health", "Integer", true, + "MaxHealth", "Integer", false, + "SetHealth", "Boolean", false + ); } @OnHealthGive(const playerIndex, const Trie:p) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc index af35d41..df72b43 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc @@ -1,31 +1,18 @@ #include #include -#include #include +#include DefaultObjects_ItemType_ItemsList_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "ItemsList", - .onRead = "@OnItemsListRead", .onGive = "@OnItemsListGive" ); -} - -@OnItemsListRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Items")) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `ItemsList`."); - return IC_RET_READ_FAIL; - } - - TrieSetCell(p, "Items", Json_Object_IC_GetItems(instanceJson, "Items")); - - return IC_RET_READ_SUCCESS; + IC_ItemType_AddParams(type, + "Items", "IC-Items", true + ); } @OnItemsListGive(const playerIndex, const Trie:p) { - new Array:aItems = PCGet_Cell(p, "Items", Invalid_Array); - - return IC_Item_GiveArray(playerIndex, aItems) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; + return PCGet_IcItemsGive(p, "Items", playerIndex) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc index df01eaf..f5a3076 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc @@ -4,38 +4,19 @@ #include DefaultObjects_ItemType_Random_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Random", - .onRead = "@OnRandomRead", .onGive = "@OnRandomGive" ); -} - -@OnRandomRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - // TODO: Сделать как-то разные шансы - if (!json_object_has_value(instanceJson, "Items")) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `Random`."); - return IC_RET_READ_FAIL; - } - - new Array:aItems = Json_Object_IC_GetItems(instanceJson, "Items"); - if (ArraySizeSafe(aItems) <= 1) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` must have >1 items."); - ArrayDestroy(aItems); - return IC_RET_READ_FAIL; - } - - TrieSetCell(p, "Items", aItems); - - return IC_RET_READ_SUCCESS; + IC_ItemType_AddParams(type, + "Items", "IC-Items", true + ); } @OnRandomGive(const playerIndex, const Trie:p) { - new Array:aItems = VipM_Params_GetArr(p, "Items"); - new iRandomIndex = random_num(0, ArraySizeSafe(aItems) - 1); - new T_IC_Item:iRandomItem = ArrayGetCell(aItems, iRandomIndex); + new Array:items = PCGet_IcItems(p, "Items"); + new iRandomIndex = random_num(0, ArraySizeSafe(items) - 1); + new T_IC_Item:iRandomItem = ArrayGetCell(items, iRandomIndex); return IC_Item_Give(playerIndex, iRandomItem) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc index 0e99eb5..8747288 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc @@ -2,37 +2,21 @@ #include #include #include -#include // Для VipM_Params_* // TODO: уйти на аналог от контроллера параметров, когда он будет - -static HookChain:PlayerSpawnPreHookChain = INVALID_HOOKCHAIN; -static HookChain:PlayerResetSpeedPostHookChain = INVALID_HOOKCHAIN; +#include static Float:PlayerSpeedMult[MAX_PLAYERS + 1] = {1.0, ...}; DefaultObjects_ItemType_Speed_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Speed", - .onRead = "@ItemType_Speed_OnRead", .onGive = "@ItemType_Speed_OnGive" ); + IC_ItemType_AddParams(type, + "Multiplier", "Float", true + ); - DisableHookChain(PlayerResetSpeedPostHookChain = RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@ItemType_Speed_OnPlayerResetSpeedPost", true)); - DisableHookChain(PlayerSpawnPreHookChain = RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_Speed_OnPlayerSpawnPre", false)); -} - -@ItemType_Speed_OnRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Multiplier", JSONNumber)) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Multiplier` required for item `Speed`."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Multiplier", json_object_get_real(instanceJson, "Multiplier")); - - EnableHookChain(PlayerResetSpeedPostHookChain); - EnableHookChain(PlayerSpawnPreHookChain); - - return IC_RET_READ_SUCCESS; + RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@ItemType_Speed_OnPlayerResetSpeedPost", true); + RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_Speed_OnPlayerSpawnPre", false); } @ItemType_Speed_OnGive(const playerIndex, const Trie:p) { diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc new file mode 100644 index 0000000..474b2be --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +DefaultObjects_ParamType_Item_Register() { + ParamsController_RegSimpleType(IC_PARAM_TYPE_ITEM_NAME, "@OnItemParamTypeRead"); +} + +bool:@OnItemParamTypeRead(const JSON:valueJson) { + new T_IC_Item:item = IC_Item_ReadFromJson(valueJson); + + if (item == Invalid_IC_Item) { + return false; + } + + return ParamsController_SetCell(item); +} \ No newline at end of file diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc new file mode 100644 index 0000000..0286a7d --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + +DefaultObjects_ParamType_Items_Register() { + ParamsController_RegSimpleType(IC_PARAM_TYPE_ITEMS_NAME, "@OnItemsParamTypeRead"); +} +@OnItemsParamTypeRead(const JSON:valueJson) { + new Array:items = IC_Item_ReadArrayFromJson(valueJson); + + if (items == Invalid_Array) { + return false; + } + + if ( + ( + json_is_object(valueJson) + || (json_is_array(valueJson) && json_array_get_count(valueJson) == 0) + ) && ArraySize(items) < 1 + ) { + PCJson_LogForFile(valueJson, "WARNING", "All items are invalid."); + return false; + } + + return ParamsController_SetCell(items); +} \ No newline at end of file diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc index 5b30a22..0db9442 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc @@ -15,7 +15,7 @@ #include "ItemsController/DefaultObjects/ItemType/Weapon" #include "ItemsController/DefaultObjects/ItemType/CustomWeapon" -DefaultObjects_RegisterAll() { +public IC_ItemType_OnInited() { // Затычка для тех мест, где при отсутствии предметов вылезает ошибка/варн IC_ItemType_SimpleRegister(.name = "None"); @@ -33,4 +33,12 @@ DefaultObjects_RegisterAll() { DefaultObjects_ItemType_Speed_Register(); DefaultObjects_ItemType_Weapon_Register(); DefaultObjects_ItemType_CustomWeapon_Register(); +} + +#include "ItemsController/DefaultObjects/ParamType/Item" +#include "ItemsController/DefaultObjects/ParamType/Items" + +public ParamsController_OnRegisterTypes() { + DefaultObjects_ParamType_Item_Register(); + DefaultObjects_ParamType_Items_Register(); } \ No newline at end of file diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc index 199c976..1ed53f0 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc @@ -11,7 +11,7 @@ enum _:S_ItemType { ItemType_Name[IC_ITEM_TYPE_NAME_MAX_LEN], ItemType_Events[E_ItemTypeEvent], - // Array:ItemType_Params // TODO: use params controller + Array:ItemType_Params, } static Array:ItemTypes = Invalid_Array; @@ -40,6 +40,7 @@ T_IC_ItemType:ItemType_Construct(const name[]) { new typeObject[S_ItemType]; copy(typeObject[ItemType_Name], charsmax(typeObject[ItemType_Name]), name); arrayset(typeObject[ItemType_Events], INVALID_HANDLE, sizeof(typeObject[ItemType_Events])); + typeObject[ItemType_Params]= ArrayCreate(1, 1); new T_IC_ItemType:type = T_IC_ItemType:ArrayPushArray(ItemTypes, typeObject); TrieSetCell(ItemTypesMap, typeObject[ItemType_Name], type); @@ -106,6 +107,15 @@ ItemType_MakeEventListener(const E_ItemTypeEvent:event, const pluginIndex, const return listener; } +ItemType_AddParams(const T_IC_ItemType:type, const Array:params) { + new typeObject[S_ItemType]; + ItemType_Get(type, typeObject); + + for (new i = 0, ii = ArraySize(params); i < ii; ++i) { + ArrayPushCell(typeObject[ItemType_Params], ArrayGetCell(params, i)); + } +} + bool:ItemType_Give(const playerIndex, const T_IC_ItemType:type, const Trie:params) { new typeObject[S_ItemType]; ItemType_Get(type, typeObject); @@ -120,17 +130,30 @@ bool:ItemType_Give(const playerIndex, const T_IC_ItemType:type, const Trie:param return ret == IC_RET_GIVE_SUCCESS; } -bool:ItemType_ReadParamsFromJsonObject(const T_IC_ItemType:type, const JSON:paramsJson, const Trie:params) { +bool:ItemType_ReadParamsFromJsonObject(const T_IC_ItemType:type, const JSON:paramsJson, &Trie:params) { new typeObject[S_ItemType]; ItemType_Get(type, typeObject); - // TODO: Использовать ParamsController + new errField[PARAM_KEY_MAX_LEN], E_ParamsReadErrorType:errType; + ParamsController_Param_ReadList(typeObject[ItemType_Params], paramsJson, params, errType, errField, charsmax(errField)); + if (errType != ParamsReadError_None) { + switch (errType) { + case ParamsReadError_RequiredParamNotPresented: + PCJson_ErrorForFile(paramsJson, "Param '%s' is required for item type '%s'.", errField, typeObject[ItemType_Name]); + case ParamsReadError_ParamValueIsInvalid: + PCJson_ErrorForFile(paramsJson, "Param '%s' has invalid value.", errField); + } + return false; + } // deprecated - new nameParam[256]; - json_object_get_string(paramsJson, "Name", nameParam, charsmax(nameParam)); - TrieSetString(params, "Name", nameParam); + if (!TrieKeyExists(params, "Name")) { + new nameParam[256]; + json_object_get_string(paramsJson, "Name", nameParam, charsmax(nameParam)); + TrieSetString(params, "Name", nameParam); + } + // deprecated? if (typeObject[ItemType_Events][ItemType_OnRead] != INVALID_HANDLE) { new ret = IC_RET_READ_SUCCESS; ExecuteForward(typeObject[ItemType_Events][ItemType_OnRead], ret, paramsJson, params); diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index df28c52..d53ad14 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -458,17 +458,17 @@ bool:@OnFlagsCheck(const Trie:Params, const UserId) { } @OnOrCheck(const Trie:Params, const UserId){ - return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_OR); + return PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_OR); } @OnXorCheck(const Trie:Params, const UserId){ - return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_XOR); + return PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_XOR); } @OnAndCheck(const Trie:Params, const UserId){ - return VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND); + return PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND); } @OnNotCheck(const Trie:Params, const UserId){ - return !VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND); + return !PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND); } diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index ccea914..6d51ebc 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -52,7 +52,7 @@ public VipM_Modules_OnInited(){ } Dbg_Log("@Event_PlayerSpawned(%d): Limits Count = %d", UserId, ArraySizeSafe(PCGet_Cell(Params, "Limits", Invalid_Array))); - if (!VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND)) { return; } Dbg_Log("@Event_PlayerSpawned(%d): Round №%d -> Passed", UserId, get_member_game(m_iTotalRoundsPlayed) + 1); diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index f9308d2..39a11bd 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -68,7 +68,7 @@ public VipM_Modules_OnInited() { return; } - if (!VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND)) { Dbg_Log("@GivePlayerItems(%n) Limits not passed", UserId); return; } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 94a52df..4dbe664 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -147,7 +147,7 @@ public client_disconnected(UserId) { return; } - if (!VipM_Params_ExecuteLimitsList(Params, "AutoopenLimits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(Params, "AutoopenLimits", UserId, Limit_Exec_AND)) { return; } @@ -224,7 +224,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { return; } - if (!VipM_Params_ExecuteLimitsList(Params, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND)) { ChatPrintLIf(!bSilent, UserId, "MSG_MAIN_NOT_PASSED_LIMIT"); Dbg_Log("_Cmd_Menu(%n, %s): Not passed main limits", UserId, bSilent ? "true" : "false"); diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 0cad27a..2c76d2d 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -38,7 +38,7 @@ bool:MenuItem_Read(const JSON:itemJson, item[S_MenuItem]) { return true; } - item[MenuItem_Items] = Json_Object_IC_GetItems(itemJson, "Items"); + item[MenuItem_Items] = PCSingle_ObjIcItems(itemJson, "Items"); if (item[MenuItem_Items] == Invalid_Array) { item[MenuItem_Type] = MenuItemType_Text; diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index db22646..eb3648c 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -5,11 +5,15 @@ #include #include +#include #define IC_VERSION "1.0.0" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; +stock const IC_PARAM_TYPE_ITEM_NAME[] = "IC-Item"; +stock const IC_PARAM_TYPE_ITEMS_NAME[] = "IC-Items"; + #define IC_ITEM_TYPE_NAME_MAX_LEN 64 #define IC_EVENT_LISTENER_FUNCTION_NAME_MAX_LEN 64 @@ -99,6 +103,30 @@ native T_IC_ItemType:IC_ItemType_Register(const name[]); */ native IC_ItemType_SetEventListener(const T_IC_ItemType:type, const E_ItemTypeEvent:event, const functionName[]); +/** + * Добавляет параметры для типа предмета. + * + * @param type Хендлер типа. + * @param any:... Перечисление параметров. + * + * @note Формат перечисления параметров: + * IC_ItemType_AddParams(..., const paramName[], const paramType[], const bool:paramRequired, ...); + * + * Где: + * - paramName - Название параметра; + * - paramType - Название типа параметра; + * - paramRequired - Обязателен ли параметр. + * + * Пример: + * IC_ItemType_AddParams(type, + * "Param1", "String", true, + * "Param2", "Integer", false + * ); + * + * @noreturn + */ +native IC_ItemType_AddParams(const T_IC_ItemType:type, any:...); + /** * Регистрирует новый тип предмета с обработчиками событий. * @@ -124,8 +152,6 @@ stock T_IC_ItemType:IC_ItemType_SimpleRegister(const name[], const onRead[] = "" /** * Читает предмет из JSON-значения. - * - * @note Поддерживает ссылки вида "File:...". // TODO: Пока не поддерживаются) * * @param isntanceJson JSON-значение, содержажее предмет или ссылку на него. * @@ -135,8 +161,6 @@ native T_IC_Item:IC_Item_ReadFromJson(const JSON:isntanceJson); /** * Читает массив предметов из JSON-значения. - * - * @note Поддерживает ссылки вида "File:...". // TODO: Пока не поддерживаются) * * @param isntancesJson JSON-значение, содержажее массив предметов, один предмет или ссылку. * @param array Хендлер динамического массива, в который нужно дописать прочитанные предметы. @@ -145,16 +169,9 @@ native T_IC_Item:IC_Item_ReadFromJson(const JSON:isntanceJson); */ native Array:IC_Item_ReadArrayFromJson(const JSON:isntancesJson, &Array:array = Invalid_Array); +#pragma deprecated Use PCSingle_ObjIcItems() instead. stock Array:Json_Object_IC_GetItems(const JSON:jObj, const sKey[], const bool:bDotNot = false) { - if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { - return Invalid_Array; - } - - new JSON:jItems = json_object_get_value(jObj, sKey, bDotNot); - new Array:aItems = IC_Item_ReadArrayFromJson(jItems); - json_free(jItems); - - return aItems; + return PCSingle_ObjIcItems(jObj, sKey, .dotNot = bDotNot); } /** @@ -203,9 +220,6 @@ stock bool:IC_Item_GiveArray(const playerIndex, const Array:array) { return success; } -// TODO: getters for params controller - - /** * Вызывается в момент инициалзиации типов предметов. * @@ -364,3 +378,28 @@ stock Array:Json_Object_GetItemsIC(const JSON:jObj, const sKey[], const bool:bDo return aItems; } + +stock T_IC_Item:PCSingle_ObjIcItem(const JSON:objectJson, const key[], const T_IC_Item:def = Invalid_IC_Item, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, IC_PARAM_TYPE_ITEM_NAME, def, dotNot, orFail); +} + +stock Array:PCSingle_ObjIcItems(const JSON:objectJson, const key[], const Array:def = Invalid_Array, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, IC_PARAM_TYPE_ITEMS_NAME, def, dotNot, orFail); +} + +stock T_IC_Item:PCGet_IcItem(const Trie:p, const key[], const T_IC_Item:def = Invalid_IC_Item) { + return PCGet_Cell(p, key, def); +} + +stock Array:PCGet_IcItems(const Trie:p, const key[], const Array:def = Invalid_Array) { + return PCGet_Cell(p, key, def); +} + +stock bool:PCGet_IcItemGive(const Trie:p, const key[], const playerIndex) { + new T_IC_Item:item = PCGet_IcItem(p, key); + return item != Invalid_IC_Item && IC_Item_Give(0playerIndex, item); +} + +stock bool:PCGet_IcItemsGive(const Trie:p, const key[], const playerIndex) { + return IC_Item_GiveArray(playerIndex, PCGet_IcItems(p, key)); +} diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index 00fb444..96201a2 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -1,9 +1,10 @@ -#if defined _vipmodular_l_included +#if defined __vipm_limits_included #endinput #endif -#define _vipmodular_l_included +#define __vipm_limits_included #include +#include /** * Vip Modular: Limits @@ -190,3 +191,29 @@ stock Array:Json_Object_GetLimits(const JSON:jObj, const sKey[], const bool:bDot return aLimits; } + +stock T_LimitUnit:PCGet_VipmLimit(const Trie:p, const key[], const T_LimitUnit:def = Invalid_LimitUnit) { + return PCGet_Cell(p, key, def); +} + +stock Array:PCGet_VipmLimits(const Trie:p, const key[], const Array:def = Invalid_Array) { + return PCGet_Cell(p, key, def); +} + +stock bool:PCGet_VipmLimitCheck(const Trie:p, const key[], const playerIndex = 0, const bool:def = true) { + new T_LimitUnit:limit = PCGet_VipmLimit(p, key); + if (limit == Invalid_LimitUnit) { + return def; + } + + return VipM_Limits_Execute(limit, playerIndex); +} + +stock bool:PCGet_VipmLimitsCheck(const Trie:p, const key[], const playerIndex = 0, const E_LimitsExecType:type = Limit_Exec_OR, const bool:def = true) { + new Array:limits = PCGet_VipmLimits(p, key); + if (limits == Invalid_Array || ArraySize(limits) < 1) { + return def; + } + + return VipM_Limits_ExecuteList(limits, playerIndex, type); +} diff --git a/amxmodx/scripting/include/VipM/Params.inc b/amxmodx/scripting/include/VipM/Params.inc index 041cd45..7417136 100644 --- a/amxmodx/scripting/include/VipM/Params.inc +++ b/amxmodx/scripting/include/VipM/Params.inc @@ -6,7 +6,7 @@ #include #include -#define VIPM_PARAM_NAME_MAX_LEN 32 +#define VIPM_PARAM_NAME_MAX_LEN PARAM_KEY_MAX_LEN /** * Vip Modular: Parameters @@ -103,10 +103,12 @@ stock Array:VipM_Params_GetArr(const Trie:tParams, const sKey[]) { return Array:PCGet_Cell(tParams, sKey, Invalid_Array); } +#pragma deprecated Use PCGet_VipmLimit() instead stock T_LimitUnit:VipM_Params_GetLimit(const Trie:tParams, const sKey[], const T_LimitUnit:iDef = Invalid_LimitUnit) { return T_LimitUnit:PCGet_Cell(tParams, sKey, iDef); } +#pragma deprecated Use PCGet_VipmLimitCheck() instead stock bool:VipM_Params_ExecuteLimit( const Trie:tParams, const sKey[] = "Limit", @@ -121,6 +123,7 @@ stock bool:VipM_Params_ExecuteLimit( return VipM_Limits_Execute(iLimit, UserId); } +#pragma deprecated Use PCGet_VipmLimitsCheck() instead stock bool:VipM_Params_ExecuteLimitsList( const Trie:tParams, const sKey[] = "Limits", From 1cc66744fc080bc429277c07a071c583a0f3e83c Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 14 Jun 2025 22:52:38 +0300 Subject: [PATCH 048/108] Add params for some items types --- .../DefaultObjects/ItemType/Money.inc | 16 ++++------------ .../DefaultObjects/ItemType/Weapon.inc | 18 ++++-------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc index 22749e2..13add2e 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -9,17 +9,13 @@ DefaultObjects_ItemType_Money_Register() { .onRead = "@OnMoneyRead", .onGive = "@OnMoneyGive" ); + IC_ItemType_AddParams(type, + "Amount", "Integer", true, + "TrackChange", "Boolean", false + ); } @OnMoneyRead(const JSON:instanceJson, const Trie:p) { - TrieDeleteKey(p, "Name"); - - if (!json_object_has_value(instanceJson, "Amount", JSONNumber)) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Amount` required for item `Money`."); - return IC_RET_READ_FAIL; - } - TrieSetCell(p, "Amount", json_object_get_number(instanceJson, "Amount")); - if (json_object_has_value(instanceJson, "GiveType", JSONString)) { new sBuffer[32]; json_object_get_string(instanceJson, "GiveType", sBuffer, charsmax(sBuffer)); @@ -31,10 +27,6 @@ DefaultObjects_ItemType_Money_Register() { } } - if (json_object_has_value(instanceJson, "TrackChange", JSONBoolean)) { - TrieSetCell(p, "TrackChange", json_object_get_bool(instanceJson, "TrackChange")); - } - return IC_RET_READ_SUCCESS; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc index 18e1fad..23974e4 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -9,25 +9,15 @@ DefaultObjects_ItemType_Weapon_Register() { .onRead = "@OnWeaponRead", .onGive = "@OnWeaponGive" ); + IC_ItemType_AddParams(type, + "Name", "String", true, + "BpAmmo", "Integer", false + ); } @OnWeaponRead(const JSON:instanceJson, const Trie:p) { - new Name[32]; - json_object_get_string(instanceJson, "Name", Name, charsmax(Name)); - - // if(get_weaponid(Name) == 0){ - // log_amx("[WARNING] Weapon `%s` not found.", Name); - // return IC_RET_READ_FAIL; - // } - TrieSetCell(p, "GiveType", _:Json_Object_GetGiveType(instanceJson, "GiveType")); - if (json_object_has_value(instanceJson, "BpAmmo", JSONNumber)) { - TrieSetCell(p, "BpAmmo", json_object_get_number(instanceJson, "BpAmmo")); - } - - TrieSetString(p, "Name", Name); - return IC_RET_READ_SUCCESS; } From 616f5473ac6dd1628c933ec7a8cb74582b60e6df Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 14 Jun 2025 23:41:39 +0300 Subject: [PATCH 049/108] Minor update config impl in modules --- .../DefaultObjects/ItemType/Money.inc | 2 +- .../DefaultObjects/ItemType/Weapon.inc | 2 +- amxmodx/scripting/VipM-L-Default.sma | 2 + amxmodx/scripting/VipM-M-SpawnHealth.sma | 42 +++++++------------ amxmodx/scripting/VipM-M-SpawnItems.sma | 33 ++++----------- amxmodx/scripting/VipM-M-Vampire.sma | 16 +++---- .../scripting/VipM/Core/Objects/VipUnit.inc | 1 + amxmodx/scripting/include/VipModular.inc | 2 +- 8 files changed, 37 insertions(+), 63 deletions(-) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc index 13add2e..cab2243 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -4,7 +4,7 @@ #include DefaultObjects_ItemType_Money_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Money", .onRead = "@OnMoneyRead", .onGive = "@OnMoneyGive" diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc index 23974e4..6ec4503 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -4,7 +4,7 @@ #include DefaultObjects_ItemType_Weapon_Register() { - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "Weapon", .onRead = "@OnWeaponRead", .onGive = "@OnWeaponGive" diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index d53ad14..b3737f8 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -317,6 +317,8 @@ public client_authorized(UserId, const AuthId[]) { // // P.S. Или лучше всё же пихать в параметры идентификатор, по котому их разделять? // Или оба сразу?) + // + // UPD: Устарело, не стоит рассчитывать на кэширование ссылок. if (TrieKeyExists(g_tUsedInGame, sTrieKey)) { return false; diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index 6d51ebc..79c7d84 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -45,41 +45,31 @@ public VipM_Modules_OnInited(){ if (!is_user_alive(UserId)) { return; } - - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); - if (Params == Invalid_Trie) { + + if (!VipM_Modules_HasModule(MODULE_NAME, UserId)) { return; } + + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, UserId); - Dbg_Log("@Event_PlayerSpawned(%d): Limits Count = %d", UserId, ArraySizeSafe(PCGet_Cell(Params, "Limits", Invalid_Array))); - if (!PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(p, "Limits", UserId, Limit_Exec_AND)) { return; } - Dbg_Log("@Event_PlayerSpawned(%d): Round №%d -> Passed", UserId, get_member_game(m_iTotalRoundsPlayed) + 1); - new Health; - if (TrieGetCell(Params, "Health", Health) && Health > 0) { - if (!PCGet_Bool(Params, "SetHealth", true)) { - Health += floatround(get_entvar(UserId, var_health)); - - new MaxHealth; - if (TrieGetCell(Params, "MaxHealth", MaxHealth) && MaxHealth > 0) { - Health = min(Health, MaxHealth); - } + new health = PCGet_Int(p, "Health", 0); + new maxHealth = PCGet_Int(p, "MaxHealth", floatround(Float:get_entvar(UserId, var_max_health))); + if (health > 0) { + if (!PCGet_Bool(p, "SetHealth", true)) { + health = min(floatround(get_entvar(UserId, var_health)) + health, maxHealth); } - set_entvar(UserId, var_health, float(Health)); + set_entvar(UserId, var_health, float(health)); } - new Armor; - if (TrieGetCell(Params, "Armor", Armor) && Armor > 0) { - if (!PCGet_Bool(Params, "SetArmor", true)) { - Health += rg_get_user_armor(UserId); - - new MaxHealth; - if (TrieGetCell(Params, "MaxArmor", MaxHealth) && MaxHealth > 0) { - Health = min(Health, MaxHealth); - } + new armor = PCGet_Int(p, "Armor", 0); + if (armor > 0) { + if (!PCGet_Bool(p, "SetArmor", true)) { + armor = min(rg_get_user_armor(UserId) + armor, PCGet_Int(p, "MaxArmor", 100)); } - rg_set_user_armor(UserId, Armor, PCGet_Bool(Params, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + rg_set_user_armor(UserId, armor, PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); } } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index 39a11bd..88ad7eb 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -2,6 +2,7 @@ #include #include #include +#include #include "VipM/Utils" #include "VipM/DebugMode" @@ -30,21 +31,7 @@ public VipM_Modules_OnInited() { } @OnReadConfig(const JSON:jCfg, Trie:Params) { - if (!json_object_has_value(jCfg, "Items")) { - log_amx("[WARNING] Field `Items` required."); - return VIPM_STOP; - } - - new JSON:jItems = json_object_get_value(jCfg, "Items"); - new Array:aItems = IC_Item_ReadArrayFromJson(jItems); - json_free(jItems); - - if (ArraySizeSafe(aItems) < 1) { - ArrayDestroySafe(aItems); - log_amx("[WARNING] Field `Items` is empty."); - return VIPM_STOP; - } - TrieSetCell(Params, "Items", aItems); + TrieSetCell(Params, "Items", PCSingle_ObjIcItems(jCfg, "Items", .orFail = true)); return VIPM_CONTINUE; } @@ -62,24 +49,18 @@ public VipM_Modules_OnInited() { return; } - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); - if (Params == Invalid_Trie) { - Dbg_Log("@GivePlayerItems(%n) Has not access", UserId); + if (!VipM_Modules_HasModule(MODULE_NAME, UserId)) { return; } + + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, UserId); - if (!PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(p, "Limits", UserId, Limit_Exec_AND)) { Dbg_Log("@GivePlayerItems(%n) Limits not passed", UserId); return; } - - new Array:aItems = Array:PCGet_Int(Params, "Items", _:Invalid_Array); - if (aItems == Invalid_Array) { - Dbg_Log("@GivePlayerItems(%n) Items array is empty", UserId); - return; - } - if (IC_Item_GiveArray(UserId, aItems)) { + if (PCGet_IcItemsGive(p, "Items", UserId)) { Dbg_Log("@GivePlayerItems(%n) Items given", UserId); } else { Dbg_Log("@GivePlayerItems(%n) Items not given", UserId); diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index ce1630a..f68d1be 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -45,22 +45,22 @@ public VipM_Modules_OnInited(){ return; } - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); - if (Params == Invalid_Trie) { + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, UserId); + if (p == Invalid_Trie) { return; } - if (!VipM_Limits_ExecuteList(PCGet_Cell(Params, "Limits", Invalid_Array), UserId)) { + if (!PCGet_VipmLimitsCheck(p, "Limits", UserId, Limit_Exec_AND)) { return; } - new MaxHealth = PCGet_Int(Params, "MaxHealth", 100); + new MaxHealth = PCGet_Int(p, "MaxHealth", 100); new Health = floatround(get_entvar(UserId, var_health)); if (Health >= MaxHealth) { return; } - new ByKill = PCGet_Int(Params, "ByKill", 0); + new ByKill = PCGet_Int(p, "ByKill", 0); new VampHealth = 0; new ActiveItem; ActiveItem = get_member(UserId, m_pActiveItem); if ( @@ -68,11 +68,11 @@ public VipM_Modules_OnInited(){ && is_entity(ActiveItem) && rg_get_iteminfo(ActiveItem, ItemInfo_iId) == CSW_KNIFE ) { - VampHealth = PCGet_Int(Params, "ByKnife", ByKill); + VampHealth = PCGet_Int(p, "ByKnife", ByKill); } else if(get_member(VictimId, m_bHeadshotKilled)) { - VampHealth = PCGet_Int(Params, "ByHead", ByKill); + VampHealth = PCGet_Int(p, "ByHead", ByKill); } else if (get_member(VictimId, m_bKilledByGrenade)) { - VampHealth = PCGet_Int(Params, "ByGrenade", ByKill); + VampHealth = PCGet_Int(p, "ByGrenade", ByKill); } else { VampHealth = ByKill; } diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index 4de73c7..c3f416e 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -4,6 +4,7 @@ #define __vipm_core_objects_vip_unit_included #include +#include #include "VipM/Utils" #include "VipM/ArrayTrieUtils" #include "VipM/JsonUtils" diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 27b46da..2df06e0 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-b12" +#define _VIPM_VERSION "5.0.0-b13" stock const VIPM_VERSION[] = _VIPM_VERSION; stock const VIPM_CFG_PATH[] = "plugins/VipModular"; #define _VIPM_PLUGIN_URL "https://github.com/ArKaNeMaN/amxx-VipModular-pub" From 3e954b0b1fc3e8752824d796611c6871b784e401 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 00:33:45 +0300 Subject: [PATCH 050/108] Update --- .../VipM/Core/Objects/Limits/Unit.inc | 2 +- .../VipM/Core/Objects/Modules/Unit.inc | 2 +- amxmodx/scripting/VipM/Core/Objects/Param.inc | 10 ++-- amxmodx/scripting/VipM/JsonUtils.inc | 48 +------------------ .../VipM/WeaponMenu/Objects/MenuItem.inc | 4 +- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 12 ++--- 6 files changed, 17 insertions(+), 61 deletions(-) diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index d4bf911..0bec600 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -64,7 +64,7 @@ static bool:LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit], static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - Json_Object_GetString(jLimitUnit, "Limit", sLimitTypeName, charsmax(sLimitTypeName)); + PCSingle_ObjString(jLimitUnit, "Limit", sLimitTypeName, charsmax(sLimitTypeName)); trim(sLimitTypeName); if (!sLimitTypeName[0]) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 6613797..40a344c 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -61,7 +61,7 @@ static any:ModuleUnit__GetValue(const T_ModuleUnit:iModuleUnit, const iCell) { static T_ModuleType:ModuleUnit__ReadType(const JSON:jModuleUnit) { new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - Json_Object_GetString(jModuleUnit, "Module", sModuleTypeName, charsmax(sModuleTypeName)); + PCSingle_ObjString(jModuleUnit, "Module", sModuleTypeName, charsmax(sModuleTypeName)); trim(sModuleTypeName); if (!sModuleTypeName[0]) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Param.inc b/amxmodx/scripting/VipM/Core/Objects/Param.inc index 2efea77..4e8bfb7 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Param.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Param.inc @@ -5,6 +5,7 @@ #include #include +#include #include #include #include "VipM/ArrayTrieUtils" @@ -79,6 +80,7 @@ bool:CfgParam_ReadList( } if (List == Invalid_Array) { + // deprecated Params = Json_ReadObjectToTrie(jParams, Params); } else { ArrayForeachArray (List => Param[S_CfgParam]) { @@ -99,17 +101,17 @@ bool:CfgParam_ReadList( continue; case ptInteger: - TrieSetCell(Params, Param[CfgParam_Name], Json_Object_GetInt(jParams, Param[CfgParam_Name])); + TrieSetCell(Params, Param[CfgParam_Name], PCSingle_ObjInt(jParams, Param[CfgParam_Name])); case ptFloat: - TrieSetCell(Params, Param[CfgParam_Name], Json_Object_GetFloat(jParams, Param[CfgParam_Name])); + TrieSetCell(Params, Param[CfgParam_Name], PCSingle_ObjFloat(jParams, Param[CfgParam_Name])); case ptBoolean: - TrieSetCell(Params, Param[CfgParam_Name], Json_Object_GetBool(jParams, Param[CfgParam_Name])); + TrieSetCell(Params, Param[CfgParam_Name], PCSingle_ObjBool(jParams, Param[CfgParam_Name])); case ptString: { new sParam[128]; - Json_Object_GetString(jParams, Param[CfgParam_Name], sParam, charsmax(sParam)); + PCSingle_ObjString(jParams, Param[CfgParam_Name], sParam, charsmax(sParam)); TrieSetString(Params, Param[CfgParam_Name], sParam); } diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index ad53c33..67becb9 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -46,52 +46,6 @@ stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) return tTrie; } -stock bool:Json_Object_GetBool(const JSON:jObj, const sKey[], const bool:bDefault = false, const bool:bDotNot = false) { - if (!json_object_has_value(jObj, sKey, JSONBoolean, bDotNot)) { - return bDefault; - } - - return json_object_get_bool(jObj, sKey, bDotNot); -} - -stock Json_Object_GetInt(const JSON:jObj, const sKey[], const iDefault = 0, const bool:bDotNot = false) { - if (!json_object_has_value(jObj, sKey, JSONNumber, bDotNot)) { - return iDefault; - } - - return json_object_get_number(jObj, sKey, bDotNot); -} - -stock Float:Json_Object_GetFloat(const JSON:jObj, const sKey[], const Float:fDefault = 0.0, const bool:bDotNot = false) { - if (!json_object_has_value(jObj, sKey, JSONNumber, bDotNot)) { - return fDefault; - } - - return json_object_get_real(jObj, sKey, bDotNot); -} - -stock Json_Object_GetString( - const JSON:jObj, - const sKey[], - sOut[], - const iOutLen, - const sDefault[] = "", - const bool:bDotNot = false -) { - if (!json_object_has_value(jObj, sKey, JSONString, bDotNot)) { - return copy(sOut, iOutLen, sDefault); - } else { - return json_object_get_string(jObj, sKey, sOut, iOutLen, bDotNot); - } -} - -stock Json_Object_GetStr(const JSON:jObj, const sKey[], const sDefault[] = "", const bool:bDotNot = false) { - new sRes[MAX_FMT_LENGTH]; - Json_Object_GetString(jObj, sKey, sRes, charsmax(sRes), sDefault, bDotNot); - - return sRes; -} - stock Json_Object_GetColoredChatMessage( const JSON:jObj, const sKey[], @@ -100,7 +54,7 @@ stock Json_Object_GetColoredChatMessage( const sDefault[] = "", const bool:bDotNot = false ) { - new iRes = Json_Object_GetString(jObj, sKey, sOut, iOutLen, sDefault, bDotNot); + new iRes = PCSingle_ObjString(jObj, sKey, sOut, iOutLen, sDefault, bDotNot); iRes -= replace_all(sOut, iOutLen, "^^1", "^1"); iRes -= replace_all(sOut, iOutLen, "^^3", "^3"); diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 2c76d2d..0b8ec49 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -50,8 +50,8 @@ bool:MenuItem_Read(const JSON:itemJson, item[S_MenuItem]) { item[MenuItem_ShowLimits] = Json_Object_GetLimits(itemJson, "ShowLimits"); item[MenuItem_ActiveLimits] = Json_Object_GetLimits(itemJson, "ActiveLimits"); item[MenuItem_Limits] = Json_Object_GetLimits(itemJson, "Limits"); - item[MenuItem_FakeInactive] = Json_Object_GetBool(itemJson, "FakeInactive", false); - item[MenuItem_UseCounter] = Json_Object_GetBool(itemJson, "UseCounter", true); + item[MenuItem_FakeInactive] = PCSingle_ObjBool(itemJson, "FakeInactive", false); + item[MenuItem_UseCounter] = PCSingle_ObjBool(itemJson, "UseCounter", true); return true; } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index a266aa1..43b1c87 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -28,7 +28,7 @@ enum _:S_WeaponMenu { } bool:WeaponMenu_Read(const JSON:menuJson, Menu[S_WeaponMenu]) { - Json_Object_GetString(menuJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); + PCSingle_ObjString(menuJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); if (Json_Object_GetColoredChatMessage( menuJson, "FakeMessage", @@ -43,12 +43,12 @@ bool:WeaponMenu_Read(const JSON:menuJson, Menu[S_WeaponMenu]) { return false; } - Json_Object_GetString(menuJson, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); + PCSingle_ObjString(menuJson, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); - Menu[WeaponMenu_Count] = Json_Object_GetInt(menuJson, "Count", -1); - Menu[WeaponMenu_BackOnExit] = Json_Object_GetBool(menuJson, "BackOnExit", false); - Menu[WeaponMenu_PerPage] = Json_Object_GetInt(menuJson, "PerPage", -1); - Menu[WeaponMenu_ShowPage] = Json_Object_GetBool(menuJson, "ShowPage", true); + Menu[WeaponMenu_Count] = PCSingle_ObjInt(menuJson, "Count", -1); + Menu[WeaponMenu_BackOnExit] = PCSingle_ObjBool(menuJson, "BackOnExit", false); + Menu[WeaponMenu_PerPage] = PCSingle_ObjInt(menuJson, "PerPage", -1); + Menu[WeaponMenu_ShowPage] = PCSingle_ObjBool(menuJson, "ShowPage", true); Menu[WeaponMenu_Limits] = Json_Object_GetLimits(menuJson, "Limits"); return true; From 5a42686cc460f01f3ee3789bc4ad48d84c43f4d9 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 12:13:00 +0300 Subject: [PATCH 051/108] Fix health item --- .../ItemsController/DefaultObjects/ItemType/Health.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc index 23a0283..3b31ee9 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -10,8 +10,8 @@ DefaultObjects_ItemType_Health_Register() { .onGive = "@OnHealthGive" ); IC_ItemType_AddParams(type, - "Health", "Integer", true, - "MaxHealth", "Integer", false, + "Health", "Float", true, + "MaxHealth", "Float", false, "SetHealth", "Boolean", false ); } From c936e9b418c2ccb98c90367cde8eaf4fa14097b1 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 13:38:06 +0300 Subject: [PATCH 052/108] Fix weapon menus --- amxmodx/scripting/VipM-M-WeaponMenu.sma | 14 +++++++------- amxmodx/scripting/VipM/WeaponMenu/Menus.inc | 9 +++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 4dbe664..248c69b 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -167,15 +167,15 @@ public client_disconnected(UserId) { CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU_SILENT); } - Dbg_PrintServer("@Task_AutoOpen(%d): fAutoCloseDelay = %.2f", UserId, fAutoCloseDelay); + Dbg_Log("@Task_AutoOpen(%d): fAutoCloseDelay = %.2f", UserId, fAutoCloseDelay); if (fAutoCloseDelay > 0.0) { - Dbg_PrintServer("@Task_AutoOpen(%d): Start auto close task", UserId); + Dbg_Log("@Task_AutoOpen(%d): Start auto close task", UserId); set_task(fAutoCloseDelay, "@Task_AutoClose", TASK_OFFSET_AUTO_CLOSE + UserId); } } @Task_AutoClose(UserId) { - Dbg_PrintServer("@Task_AutoClose(%d)", UserId); + Dbg_Log("@Task_AutoClose(%d)", UserId); UserId -= TASK_OFFSET_AUTO_CLOSE; menu_cancel(UserId); show_menu(UserId, 0, ""); @@ -256,7 +256,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { static Menu[S_WeaponMenu]; ArrayGetArray(aMenus, MenuId, Menu); - if (!VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], UserId)) { + if (Menu[WeaponMenu_Limits] != Invalid_Array && !VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], UserId, Limit_Exec_AND)) { ChatPrintLIf(!bSilent, UserId, "MSG_MENU_NOT_PASSED_LIMIT"); Dbg_Log("_Cmd_Menu(%n, %s): Not passed menu limits", UserId, bSilent ? "true" : "false"); return; @@ -298,9 +298,9 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { } if ( - !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId) - || !VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId) - || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], UserId) + !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId, Limit_Exec_AND) + || !VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId, Limit_Exec_AND) + || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], UserId, Limit_Exec_AND) ) { ChatPrintLIf(!bSilent, UserId, "MSG_MENUITEM_NOT_PASSED_LIMIT"); diff --git a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc index 6b02c5c..bbb3f3e 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc @@ -75,7 +75,10 @@ Menu_WeaponsMenu(const UserId, const MenuId, const Menu[S_WeaponMenu]) { new iItemIndex = 0; ArrayForeachArray(Menu[WeaponMenu_Items] => MenuItem[S_MenuItem]) { - if (!VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId)) { + if ( + MenuItem[MenuItem_ShowLimits] != Invalid_Array + && !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId, Limit_Exec_AND) + ) { continue; } @@ -84,7 +87,9 @@ Menu_WeaponsMenu(const UserId, const MenuId, const Menu[S_WeaponMenu]) { static Cmd[128]; CommandAliases_GetMainCmd(CMD_WEAPON_MENU, Cmd, charsmax(Cmd)); - new bool:bIsActive = VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId); + new bool:bIsActive = MenuItem[MenuItem_ShowLimits] == Invalid_Array + || VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId, Limit_Exec_AND); + menu_additem(iMenu, fmt("%s%s", bIsActive ? "" : "\d", MenuItem[MenuItem_Title]), fmt("%s %d %d", Cmd, MenuId, __i__)); if (!bIsActive && !MenuItem[MenuItem_FakeInactive]) { menu_item_setcall(iMenu, iItemIndex, iInactiveItemHandler); From cfc9792390c3f325d4344e19be44de889bc82504 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 13:41:37 +0300 Subject: [PATCH 053/108] Add `Function` item type --- .../DefaultObjects/ItemType/Function.inc | 99 +++++++++++++++++++ .../DefaultObjects/Registrar.inc | 2 + readme/default-extensions.md | 29 +----- readme/extensions/items.md | 2 +- readme/extensions/limits.md | 2 +- readme/json.md | 96 ------------------ 6 files changed, 104 insertions(+), 126 deletions(-) create mode 100644 amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc delete mode 100644 readme/json.md diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc new file mode 100644 index 0000000..63198cf --- /dev/null +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +DefaultObjects_ItemType_Function_Register() { + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( + .name = "Function", + .onGive = "@OnFunctionGive" + ); + IC_ItemType_AddParams(type, + "Plugin", "String", true, + "Function", "String", true + ); + + // For AES-Bonuses compat + IC_ItemType_AddParams(type, + "Value", "Integer", false, + "Flags", "ShortString", false, + "Days", "Integer", false + ); +} + +@OnFunctionGive(const playerIndex, const Trie:p) { + if (callfunc_begin(PCGet_iStr(p, "Function"), PCGet_iStr(p, "Plugin")) > 0) { + callfunc_push_int(playerIndex); + + new flags[PARAM_SHORT_STRING_MAX_LEN]; // В AES 30, но почему бы не расширить до 64) + PCGet_Str(p, "Flags", flags, charsmax(flags)); + if (flags[0] != EOS) { + callfunc_push_str(flags); + + new days = PCGet_Int(p, "Days", 0); + if (days > 0) { + callfunc_push_int(days); + } + } else { + callfunc_push_int(PCGet_Int(p, "Value", 0)); + } + + // Вообще не используется в AES + // if (psh) { + // callfunc_push_int(psh); + // } + + return callfunc_end() > 0 ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; + } + + abort(AMX_ERR_PARAMS, "Can't call function '%s' in plugin '%s'.", PCGet_iStr(p, "Function"), PCGet_iStr(p, "Plugin")); + return IC_RET_GIVE_FAIL; +} + +/** + * { + * "Item": "Function", + * "Plugin": "ItemsController.amxx", + * "Function": "@IC_ItemType_Function_TestFunc_Base" + * } + */ +@IC_ItemType_Function_TestFunc_Base(const playerIndex) { + client_print_color(playerIndex, print_team_default, "@IC_ItemType_Function_TestFunc_Base(%n)", playerIndex); +} + +/** + * { + * "Item": "Function", + * "Plugin": "ItemsController.amxx", + * "Function": "@IC_ItemType_Function_TestFunc_Value", + * "Value": 123 + * } + */ +@IC_ItemType_Function_TestFunc_Value(const playerIndex, const value) { + client_print_color(playerIndex, print_team_default, "@IC_ItemType_Function_TestFunc_Value(%n, %d)", playerIndex, value); +} + +/** + * { + * "Item": "Function", + * "Plugin": "ItemsController.amxx", + * "Function": "@IC_ItemType_Function_TestFunc_Flags", + * "Flags": "qwe" + * } + */ +@IC_ItemType_Function_TestFunc_Flags(const playerIndex, const flags[]) { + client_print_color(playerIndex, print_team_default, "@IC_ItemType_Function_TestFunc_Flags(%n, %s)", playerIndex, flags); +} + +/** + * { + * "Item": "Function", + * "Plugin": "ItemsController.amxx", + * "Function": "@IC_ItemType_Function_TestFunc_FlagsDays", + * "Flags": "qwe", + * "Days": 321 + * } + */ +@IC_ItemType_Function_TestFunc_FlagsDays(const playerIndex, const flags[], const days) { + client_print_color(playerIndex, print_team_default, "@IC_ItemType_Function_TestFunc_FlagsDays(%n, %s, %d)", playerIndex, flags, days); +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc index 0db9442..a546c6d 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc @@ -14,6 +14,7 @@ #include "ItemsController/DefaultObjects/ItemType/Speed" #include "ItemsController/DefaultObjects/ItemType/Weapon" #include "ItemsController/DefaultObjects/ItemType/CustomWeapon" +#include "ItemsController/DefaultObjects/ItemType/Function" public IC_ItemType_OnInited() { // Затычка для тех мест, где при отсутствии предметов вылезает ошибка/варн @@ -33,6 +34,7 @@ public IC_ItemType_OnInited() { DefaultObjects_ItemType_Speed_Register(); DefaultObjects_ItemType_Weapon_Register(); DefaultObjects_ItemType_CustomWeapon_Register(); + DefaultObjects_ItemType_Function_Register(); } #include "ItemsController/DefaultObjects/ParamType/Item" diff --git a/readme/default-extensions.md b/readme/default-extensions.md index 3d27dea..8726e77 100644 --- a/readme/default-extensions.md +++ b/readme/default-extensions.md @@ -74,31 +74,4 @@ ## Типы предметов -- [Weapon](extensions/items/weapon.md) - Стандартное оружие -- [ItemsList](extensions/items/items-list.md) - Несколько предметов -- [Command](extensions/items/command.md) - Клиентская/серверная команда -- [DefuseKit](extensions/items/defuse-kit.md) - Набор сапёра -- If - Выдаёт предметы только при выполнении условия - - `Items` - Предметы, которые будут выданы при выполнении условий из параметра `Limits` - - `Limits` - Условия, при выполнении которых будут выданы предметы из параметра `Items` - - `ElseItems` - Предметы, которые будут выданы при НЕвыполнении условий из параметра `Limits` -- Random - Выдаёт случайный предмет из списка - - `Items` - Предметы, из которых будет выдан один случайный -- InstantReloadAllWeapons - Мгновенная перезарядка всего оружия -- InstantReload - Мгновенная перезарядка текущего оружия -- RefillBpAmmo - Пополнение всех видов патронов -- Speed - Умножение скорости до конца раунда - - `Multiplier` - Множитель скорости относительно изначальной -- DamageMult - Умножение получаемого и/или наносимого урона - - `Given` - Множитель наносимого урона - - `Taken` - Множитель получаемого урона -- Money - Игровые деньги - - `Amount` - Сумма, которая будет выдана - - `GiveType` - Тип выдачи - - `Add` - добавить - - `Set` - установить - - `TrackChange` - Показать ли игроку анимацию зачисления денег -- Health - Очки здоровья - - `Health` - Сколько очков здоровья будет выдано - - `MaxHealth` - Максимальное число очков здоровья, выше которого выдано не будет - - `SetHealth` - Если `true` - значение `Health` будет установлено, иначе оно будет добавлено (при `true` параметр `MaxHealth` игнорируется) +Список переехал [сюда](/wiki/Встроенные-типы-предметов). \ No newline at end of file diff --git a/readme/extensions/items.md b/readme/extensions/items.md index 5e763a9..b1ed828 100644 --- a/readme/extensions/items.md +++ b/readme/extensions/items.md @@ -6,7 +6,7 @@ TODO: Переписать ## Структура обьекта предмета -*[Памятка по JSON](/readme/json.md)* +*[Памятка по JSON](/wiki/Памятка-по-JSON)* ```jsonc { diff --git a/readme/extensions/limits.md b/readme/extensions/limits.md index c9ca523..87ceebd 100644 --- a/readme/extensions/limits.md +++ b/readme/extensions/limits.md @@ -25,7 +25,7 @@ ## Структура обьекта лимита -_[Памятка по JSON](/readme/json.md)_ +_[Памятка по JSON](/wiki/Памятка-по-JSON)_ ```jsonc { diff --git a/readme/json.md b/readme/json.md deleted file mode 100644 index 18a0a2b..0000000 --- a/readme/json.md +++ /dev/null @@ -1,96 +0,0 @@ -# Памятка по формату JSON - -Ниже приведена некоторая информация про JSON, которая поможет при настройке системы привилегий и не только. - -## Типы данных - -JSON поддерживает следующие типы данных: - -- Числа (целые и дробные) - `123` или `1.23`; -- Строки - `"qwe"`; -- Булевые - `true`/`false`; -- Массивы - `[1, 2]`, могут содержать в себе значения любого типа разделённые запятой; -- Обьекты - `{"k1": "v1", "k2": 2}`, могут содержать в себе пары типа ключ:значение, где ключ - строка, а значение может быть любого типа. - -Примеры: - -```jsonc -{ - "Строка": "qwe", - "Целое число": 123, - "Дробное число": 1.23, - "Булево значение": false, - "Массив": [ - "ewq", - 321, - { - "Булево значение 2": true - } - ], - "Обьект": { - "Строка 2": "rty", - "Целое число 2": 456 - } -} -``` - -_Примечание: периодически возникают ошибки из-за лишних или недостающих скобок у обьектов и массивов, следите за тем, чтобы все открытые скобки были закрыты._ - -_Примечание: Значения типа `123` и `"123"` не являются взаимозаменяемыми, то есть, если ожидается числовое значение, то при указании второго варианта может возникнуть непредвиденная ошибка. Подобные ситуации могут обрабатываться на уровне кода, но в любом случае лучше использовать типы правильно._ - -## Запятые - -**Очень важно!** - -Формат JSON очень чувствителен к запятым. Их не должно быть там, где они не нужны, и они обязательно должны быть там, где они нужны. - -Где запятые **нужны**: - -- Между элементами массивов `[1, 2]` -- Между парами ключ:значение в обьектах `{"k1": 1, "k2": "v2"}` - -Где запятые **не нужны**: - -- После последнего элемента массива `[1, 2,]` -- После последней пары ключ:значение в обьекте `{"k1": 1, "k2": "v2",}` - -## Отступы и пробелы - -Формат JSON абсолютно не чувствителен к отступам, пробелам и пустым строкам. - -```jsonc -// Пример 1: -{ - "key1": "value 1", - "Key2": true, - - "key3": 321 -} - -// Пример 2: -{"key1":"value 1","Key2":true,"key3":321} -``` - -Оба примера спарсятся абсолютно одинаково. Разница лишь в том, что первый пример более удобен для восприятия человеком. - -Хоть сам формат JSON не чувствителен к отсупам, но очень желательно соблюдать отступы для вложенных значений, так как это - -Единственное место, где JSON учитывает пробелы - внутри строковых значений. - -## Инструменты - -Ниже приведены некоторые инструменты, которые позволят найти или не допустить ошибок при работе с JSON. - -### Visual Studio Code - -[Скачать](https://code.visualstudio.com/) - -Бесплатный мощный текстовый редактор, предназначенный для редактирования кода. Из коробки имеет поддержку многих языков, в том числе JSON. - -В ходе редактирования JSON-файла будет подсвечивать допущенные синтаксические ошибки, а также, при нажатии сочетания Shift+Alt+F может отформатировать файл, исправив в нём отступы. - -### JSONLint - -[Открыть](https://jsonlint.com/) - -Если нет желания скачивать VSCode, можно проверять JSON-файл на наличие синтаксических ошибок при помощи этого сайта. Также, сайт может помочь исправить отступы. From 1cb70f4f76fd57c545d6debfac748c5eed88ac0f Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 14:38:10 +0300 Subject: [PATCH 054/108] Update params controller version in readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 2c19cf5..3fc5e01 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Требования -- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.0.0-b5](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.0.0-b5) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.1.2](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.1.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). - [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). - [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). @@ -34,5 +34,4 @@ - _\[Configs\]_ Добавить глобальные настройки типа ключ-значение, на которые можно ссылаться из основных конфигов как на файлы, только с префиксом Var: - _\[Modules\]_ Переработать обьедининение параметров модулей -- _\[ReadMe\]_ Нарисовать схему взаимодействия компонентов системы - _\[IC\]_ Придумать как норм отвязать IC от ядра и, возможно, вынести его в отдельный репо (WIP) From 418f78eb7dbb5d81107da52d3efeb8d26faaa223 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 15:30:50 +0300 Subject: [PATCH 055/108] Cleanup utils --- .../CommandAliases/VipM-M-WeaponMenu.json | 34 ++++ .../plugins/VipModular/Cmds/WeaponMenu.json | 40 ----- amxmodx/scripting/VipM-M-WeaponMenu.sma | 40 ++--- amxmodx/scripting/VipM/ArrayTrieUtils.inc | 52 +----- amxmodx/scripting/VipM/CommandAliases.inc | 154 ------------------ amxmodx/scripting/VipM/Core/API/Limits.inc | 19 +-- amxmodx/scripting/VipM/Core/API/Main.inc | 7 +- amxmodx/scripting/VipM/Core/API/Modules.inc | 13 +- .../VipM/Core/Objects/Limits/Unit.inc | 2 +- .../VipM/Core/Objects/Modules/Unit.inc | 2 +- .../scripting/VipM/Core/Objects/VipUnit.inc | 2 +- amxmodx/scripting/VipM/Forwards.inc | 95 +++++------ amxmodx/scripting/VipM/JsonUtils.inc | 8 +- amxmodx/scripting/VipM/Natives.inc | 25 --- amxmodx/scripting/VipM/Utils.inc | 17 -- amxmodx/scripting/VipM/WeaponMenu/Menus.inc | 11 +- amxmodx/scripting/VipM/WeaponMenu/Natives.inc | 5 +- .../VipM/WeaponMenu/Objects/MenuItem.inc | 2 +- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 2 +- .../scripting/include/VipM/M/WeaponMenu.inc | 4 + 20 files changed, 131 insertions(+), 403 deletions(-) create mode 100644 amxmodx/configs/plugins/CommandAliases/VipM-M-WeaponMenu.json delete mode 100644 amxmodx/configs/plugins/VipModular/Cmds/WeaponMenu.json delete mode 100644 amxmodx/scripting/VipM/CommandAliases.inc delete mode 100644 amxmodx/scripting/VipM/Natives.inc diff --git a/amxmodx/configs/plugins/CommandAliases/VipM-M-WeaponMenu.json b/amxmodx/configs/plugins/CommandAliases/VipM-M-WeaponMenu.json new file mode 100644 index 0000000..8794f60 --- /dev/null +++ b/amxmodx/configs/plugins/CommandAliases/VipM-M-WeaponMenu.json @@ -0,0 +1,34 @@ +[ + { + "Command": "vipm_m_weaponmenu_menu", + "Alias": [ + "vm", + "say /vm", + "say_team /vm", + "vipmenu", + "say /vipmenu", + "say_team /vipmenu" + ] + }, + { + "Command": "vipm_m_weaponmenu_menu_silent", + "Alias": [ + "vm_silent", + "vipmenu_silent" + ] + }, + { + "Command": "vipm_m_weaponmenu_autoopen_toggle", + "Alias": [ + "vm_autoopen", + "say /vm_autoopen", + "say_team /vm_autoopen", + "vm_ao", + "say /vm_ao", + "say_team /vm_ao", + "vipmenu_autoopen", + "say /vipmenu_autoopen", + "say_team /vipmenu_autoopen" + ] + } +] \ No newline at end of file diff --git a/amxmodx/configs/plugins/VipModular/Cmds/WeaponMenu.json b/amxmodx/configs/plugins/VipModular/Cmds/WeaponMenu.json deleted file mode 100644 index cce069f..0000000 --- a/amxmodx/configs/plugins/VipModular/Cmds/WeaponMenu.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - /* - Тут указываются все возможные варианты - клиенских команд модуля WeaponMenu - */ - - // Команда открытия меню - "vipmenu": [ - "vm", - "say /vm", - "say_team /vm", - - "vipmenu", - "say /vipmenu", - "say_team /vipmenu" - ], - - // Команда открытия меню без вывода сообщения в случае недоступности - // Нужна для внутреннего использования, но можно и снаружи использовать - "vipmenu_silent": [ - "vm_silent", - "vipmenu_silent" - ], - - // Команда включения/отключения автооткрытия меню - // Состояние сбрасывается при выходе с сервера - "vipmenu_autoopen": [ - "vm_autoopen", - "say /vm_autoopen", - "say_team /vm_autoopen", - - "vm_ao", - "say /vm_ao", - "say_team /vm_ao", - - "vipmenu_autoopen", - "say /vipmenu_autoopen", - "say_team /vipmenu_autoopen" - ] -} \ No newline at end of file diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 248c69b..f73c05d 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -7,9 +7,6 @@ #include "VipM/WeaponMenu/Objects/WeaponMenu" #include "VipM/WeaponMenu/Objects/MenuItem" -#pragma semicolon 1 -#pragma compress 1 - public stock const PluginName[] = "[VipM-M] Weapon Menu"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; @@ -18,14 +15,6 @@ public stock const PluginDescription[] = "Vip modular`s module - Weapon Menu"; new const MODULE_NAME[] = "WeaponMenu"; -new const CMD_WEAPON_MENU[] = "vipmenu"; -new const CMD_WEAPON_MENU_SILENT[] = "vipmenu_silent"; -new const CMD_SWITCH_AUTOOPEN[] = "vipmenu_autoopen"; - -#include "VipM/ArrayTrieUtils" -#include "VipM/Utils" -#include "VipM/CommandAliases" - enum { TASK_OFFSET_AUTO_OPEN = 100, TASK_OFFSET_AUTO_CLOSE = 200, @@ -87,13 +76,10 @@ public VipM_Modules_OnInited() { @OnModuleActivate() { RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawn", true); RegisterHookChain(RG_CSGameRules_RestartRound, "@OnRestartRound", false); - - // TODO: Use CommandAliases plugin - CommandAliases_Open(GET_FILE_JSON_PATH("Cmds/WeaponMenu"), true); - CommandAliases_RegisterClient(CMD_WEAPON_MENU, "@Cmd_Menu"); // vipmenu - CommandAliases_RegisterClient(CMD_WEAPON_MENU_SILENT, "@Cmd_MenuSilent"); - CommandAliases_RegisterClient(CMD_SWITCH_AUTOOPEN, "@Cmd_SwitchAutoOpen"); - CommandAliases_Close(); + + register_clcmd(VIPM_M_WEAPONMENU_CMD_MENU, "@Cmd_Menu"); + register_clcmd(VIPM_M_WEAPONMENU_CMD_MENU_SILENT, "@Cmd_MenuSilent"); + register_clcmd(VIPM_M_WEAPONMENU_CMD_AUTOOPEN_TOGGLE, "@Cmd_SwitchAutoOpen"); } ResetUserMenuCounters(const UserId) { @@ -162,9 +148,9 @@ public client_disconnected(UserId) { new iMenuNum = PCGet_Int(tParams, "AutoopenMenuNum", -1); if (iMenuNum > 0) { - CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU_SILENT, IntToStr(iMenuNum - 1)); + client_cmd(UserId, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU_SILENT, iMenuNum - 1); } else { - CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU_SILENT); + client_cmd(UserId, VIPM_M_WEAPONMENU_CMD_MENU_SILENT); } Dbg_Log("@Task_AutoOpen(%d): fAutoCloseDelay = %.2f", UserId, fAutoCloseDelay); @@ -231,11 +217,9 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { return; } - CMD_INIT_PARAMS(); - - if (CMD_ARG_NUM() < 1) { + if (read_argc() < 2) { if (ArraySizeSafe(aMenus) == 1) { - CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU, "0"); + client_cmd(UserId, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, 0); } else { static MainMenuTitle[128]; PCGet_Str(Params, "MainMenuTitle", MainMenuTitle, charsmax(MainMenuTitle)); @@ -244,7 +228,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { return; } - new MenuId = read_argv_int(CMD_ARG(1)); + new MenuId = read_argv_int(2); if ( ArraySizeSafe(aMenus) <= MenuId || MenuId < 0 @@ -268,12 +252,12 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { return; } - if (CMD_ARG_NUM() < 2) { + if (read_argc() < 3) { Menu_WeaponsMenu(UserId, MenuId, Menu); return; } - new ItemId = read_argv_int(CMD_ARG(2)); + new ItemId = read_argv_int(3); if ( ArraySizeSafe(Menu[WeaponMenu_Items]) <= ItemId || ItemId < 0 @@ -326,7 +310,7 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { || iItemsLeft != 0 ) ) { - CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU, "%d", MenuId); + client_cmd(UserId, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, MenuId); } } diff --git a/amxmodx/scripting/VipM/ArrayTrieUtils.inc b/amxmodx/scripting/VipM/ArrayTrieUtils.inc index 61c6ee1..1f99e0b 100644 --- a/amxmodx/scripting/VipM/ArrayTrieUtils.inc +++ b/amxmodx/scripting/VipM/ArrayTrieUtils.inc @@ -3,24 +3,10 @@ #endif #define _vipmodular_src_ArrayTrieUtils_included -#include amxmodx +#include -#define ArraySizeSafe(%1) \ - (%1 == Invalid_Array ? 0 : ArraySize(%1)) - -#define TrieSizeSafe(%1) \ - (%1 == Invalid_Trie ? 0 : TrieGetSize(%1)) - -stock ArrayDestroySafe(Array:a) { - if (a != Invalid_Array) { - ArrayDestroy(a); - } -} - -stock TrieDestroySafe(Trie:t) { - if (t != Invalid_Trie) { - TrieDestroy(t); - } +stock ArraySizeSafe(const Array:h) { + return h == Invalid_Array ? 0 : ArraySize(h); } #define ArrayForeachArray(%1=>%2[%3]) \ @@ -41,32 +27,10 @@ stock TrieDestroySafe(Trie:t) { for (new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++) \ if (ArrayGetString(%1, %4, %2, charsmax(%2))) -#define ArrayCreateIfNotCreated(%1,%2) \ - %1 = (%1 == Invalid_Array) \ - ? ArrayCreate(%2) \ - : %1 - -#define TrieCreateIfNotCreated(%1) \ - %1 = (%1 == Invalid_Trie) \ - ? TrieCreate() \ - : %1 - -#define ArrayDestroyIfEmpty(%1) CompositeMacros( \ - if (!ArraySizeSafe(%1)) \ - ArrayDestroy(%1); \ -) - -stock Array:ArrayMergeCells(const Array:a1, const Array:a2) { - new Array:aMerged = ArrayClone(a1); - ArrayResize(aMerged, ArraySizeSafe(a1) + ArraySizeSafe(a2)); - - if (a2 == Invalid_Array) { - return aMerged; - } - - for (mew i = 0; iSize = ArraySizeSafe(a2); i < iSize; i++) { - ArrayPushCell(aMerged, ArrayGetCell(a2, i)); - } +stock Array:ArrayCreateIfNotCreated(&Array:h, const cellsize = 1, const reserved = 1) { + return h = (h == Invalid_Array) ? ArrayCreate(cellsize, reserved) : h; +} - return aMerged; +stock Trie:TrieCreateIfNotCreated(&Trie:h) { + return h = (h == Invalid_Trie) ? TrieCreate() : h; } diff --git a/amxmodx/scripting/VipM/CommandAliases.inc b/amxmodx/scripting/VipM/CommandAliases.inc deleted file mode 100644 index 08070cf..0000000 --- a/amxmodx/scripting/VipM/CommandAliases.inc +++ /dev/null @@ -1,154 +0,0 @@ -#if defined _command_aliases_included - #endinput -#endif -#define _command_aliases_included - -#include -#include - -#define COMMAND_ALIASES_COMMAND_MAX_LENGTH 64 -static const DEFAULT_TEMPLATE_PLACEHOLDER[] = ""; -static const DEFAULT_TEMPLATES[][] = { - "say /", - "say_team /", -}; - -enum _:{ - CommandAliases_CmdType_Client = (1 << 0), - CommandAliases_CmdType_Console = (1 << 1), - CommandAliases_CmdType_Server = (1 << 2), -} - -static JSON:jFile = Invalid_JSON; -static Trie:g_tMainCmd = Invalid_Trie; - -stock bool:CommandAliases_Open(const sFilePath[], const bool:bCreateIfNotExists = false) { - jFile = Invalid_JSON; - - if (!file_exists(sFilePath)) { - if (bCreateIfNotExists) { - new JSON:jObj = json_init_object(); - json_serial_to_file(jObj, sFilePath, true); - json_free(jObj); - } else { - return false; - } - } - - jFile = json_parse(sFilePath, true, true); - - if (jFile == Invalid_JSON) { - log_amx("[CommandAliases][Warn] Can't read from file: %s", sFilePath); - return false; - } - - if (!json_is_object(jFile)) { - jFile = Invalid_JSON; - log_amx("[CommandAliases][Warn] Invalid file format: %s", sFilePath); - return false; - } - - return true; -} - -stock CommandAliases_Close() { - json_free(jFile); -} - -static stock Array:ReadCommandsByKey(const sCmdKey[]) { - new Array:aCmds = Invalid_Array; - - if (jFile == Invalid_JSON) { - aCmds = ArrayCreate(COMMAND_ALIASES_COMMAND_MAX_LENGTH, sizeof DEFAULT_TEMPLATES); - ArrayPushString(aCmds, sCmdKey); - - for (new i = 0; i < sizeof DEFAULT_TEMPLATES; i++) { - new sCmd[COMMAND_ALIASES_COMMAND_MAX_LENGTH]; - copy(sCmd, charsmax(sCmd), DEFAULT_TEMPLATES[i]); - replace(sCmd, charsmax(sCmd), DEFAULT_TEMPLATE_PLACEHOLDER, sCmdKey); - ArrayPushString(aCmds, sCmd); - } - } else { - new JSON:jCmds = json_object_get_value(jFile, sCmdKey); - if (!json_is_array(jCmds)) { - log_amx("[CommandAliases][Warn] Invalid file format. Commands list must be an array."); - return aCmds; - } - - aCmds = ArrayCreate(COMMAND_ALIASES_COMMAND_MAX_LENGTH, json_array_get_count(jCmds)); - - for (new i = 0; i < json_array_get_count(jCmds); i++) { - new sCmd[COMMAND_ALIASES_COMMAND_MAX_LENGTH]; - json_array_get_string(jCmds, i, sCmd, charsmax(sCmd)); - ArrayPushString(aCmds, sCmd); - } - json_free(jCmds); - } - - return aCmds; -} - -stock CommandAliases_Register(const sCmdKey[], const sCallback[], const bitCmdTypes) { - new Array:aCmds = ReadCommandsByKey(sCmdKey); - if (aCmds == Invalid_Array || !ArraySize(aCmds)) { - return; - } - - if (g_tMainCmd == Invalid_Trie) { - g_tMainCmd = TrieCreate(); - } - - new sCmd[COMMAND_ALIASES_COMMAND_MAX_LENGTH]; - ArrayGetString(aCmds, 0, sCmd, charsmax(sCmd)); - TrieSetString(g_tMainCmd, sCmdKey, sCmd); - - for (new i = 0; i < ArraySize(aCmds); i++) { - ArrayGetString(aCmds, i, sCmd, charsmax(sCmd)); - - if (bitCmdTypes & CommandAliases_CmdType_Client) { - register_clcmd(sCmd, sCallback); - } - - if (bitCmdTypes & CommandAliases_CmdType_Console) { - register_concmd(sCmd, sCallback); - } - - if (bitCmdTypes & CommandAliases_CmdType_Server) { - register_srvcmd(sCmd, sCallback); - } - } - ArrayDestroy(aCmds); -} - -stock CommandAliases_RegisterClient(const sCmdKey[], const sCallback[]) { - CommandAliases_Register(sCmdKey, sCallback, CommandAliases_CmdType_Client); -} - -stock CommandAliases_RegisterConsole(const sCmdKey[], const sCallback[]) { - CommandAliases_Register(sCmdKey, sCallback, CommandAliases_CmdType_Console); -} - -stock CommandAliases_RegisterServer(const sCmdKey[], const sCallback[]) { - CommandAliases_Register(sCmdKey, sCallback, CommandAliases_CmdType_Server); -} - -stock CommandAliases_RegisterAll(const sCmdKey[], const sCallback[]) { - CommandAliases_Register(sCmdKey, sCallback, CommandAliases_CmdType_Client|CommandAliases_CmdType_Console|CommandAliases_CmdType_Server); -} - -stock bool:CommandAliases_GetMainCmd(const sCmdKey[], sOut[], const iOutLen) { - return TrieGetString(g_tMainCmd, sCmdKey, sOut, iOutLen); -} - -stock bool:CommandAliases_ClientCmd(const UserId, const sCmdKey[], const sArgsFmt[] = "", any:...) { - static sCmd[COMMAND_ALIASES_COMMAND_MAX_LENGTH], sFormattedArgs[256]; - if (CommandAliases_GetMainCmd(sCmdKey, sCmd, charsmax(sCmd))) { - if (sArgsFmt[0]) { - sFormattedArgs[0] = 0; - vformat(sFormattedArgs, charsmax(sFormattedArgs), sArgsFmt, 4); - client_cmd(UserId, "%s %s", sCmd, sFormattedArgs); - } else { - client_cmd(UserId, "%s", sCmd); - } - } -} diff --git a/amxmodx/scripting/VipM/Core/API/Limits.inc b/amxmodx/scripting/VipM/Core/API/Limits.inc index 87f48fd..871fc00 100644 --- a/amxmodx/scripting/VipM/Core/API/Limits.inc +++ b/amxmodx/scripting/VipM/Core/API/Limits.inc @@ -1,25 +1,22 @@ #include #include -#include "VipM/Natives" #include "VipM/Core/Objects/Limits/Type" #include "VipM/Core/Objects/Limits/Unit" #include "VipM/Core/Objects/Param" API_Limits_Init() { - Natives_Init("VipM"); + register_native("VipM_Limits_RegisterType", "@_Limits_RegisterType"); + register_native("VipM_Limits_AddTypeParams", "@_Limits_AddTypeParams"); + register_native("VipM_Limits_RegisterTypeEvent", "@_Limits_RegisterTypeEvent"); - Natives_Reg("Limits_RegisterType"); - Natives_Reg("Limits_AddTypeParams"); - Natives_Reg("Limits_RegisterTypeEvent"); + register_native("VipM_Limits_ReadFromJson", "@_Limits_ReadFromJson"); + register_native("VipM_Limits_ReadListFromJson", "@_Limits_ReadListFromJson"); - Natives_Reg("Limits_ReadFromJson"); - Natives_Reg("Limits_ReadListFromJson"); + register_native("VipM_Limits_SetStaticValue", "@_Limits_SetStaticValue"); - Natives_Reg("Limits_SetStaticValue"); - - Natives_Reg("Limits_Execute"); - Natives_Reg("Limits_ExecuteList"); + register_native("VipM_Limits_Execute", "@_Limits_Execute"); + register_native("VipM_Limits_ExecuteList", "@_Limits_ExecuteList"); } // native VipM_Limits_RegisterType(const sLimitTypeName[], const bool:bForPlayer = true, const bool:bStatic = false); diff --git a/amxmodx/scripting/VipM/Core/API/Main.inc b/amxmodx/scripting/VipM/Core/API/Main.inc index 2a9ea7c..57295fd 100644 --- a/amxmodx/scripting/VipM/Core/API/Main.inc +++ b/amxmodx/scripting/VipM/Core/API/Main.inc @@ -1,14 +1,11 @@ #include -#include "VipM/Natives" #include "VipM/Utils" #include "VipM/JsonUtils" #include "VipM/Core/VipsManager" API_Main_Init() { - Natives_Init("VipM"); - - Natives_Reg("UserUpdate"); - Natives_Reg("Json_LogForFile"); + register_native("VipM_UserUpdate", "@_UserUpdate"); + register_native("VipM_Json_LogForFile", "@_Json_LogForFile"); } @_UserUpdate() { diff --git a/amxmodx/scripting/VipM/Core/API/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc index 5f838df..6ec310d 100644 --- a/amxmodx/scripting/VipM/Core/API/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -1,16 +1,13 @@ #include #include "VipM/DebugMode" -#include "VipM/Natives" #include "VipM/Core/Objects/Param" API_Modules_Init(){ - Natives_Init("VipM"); - - Natives_Reg("Modules_Register"); - Natives_Reg("Modules_AddParams"); - Natives_Reg("Modules_RegisterEvent"); - Natives_Reg("Modules_IsActive"); - Natives_Reg("Modules_GetParams"); + register_native("VipM_Modules_Register", "@_Modules_Register"); + register_native("VipM_Modules_AddParams", "@_Modules_AddParams"); + register_native("VipM_Modules_RegisterEvent", "@_Modules_RegisterEvent"); + register_native("VipM_Modules_IsActive", "@_Modules_IsActive"); + register_native("VipM_Modules_GetParams", "@_Modules_GetParams"); } T_ModuleType:@_Modules_Register(const PluginId) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 0bec600..180aada 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -113,7 +113,7 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { } Array:LimitUnit_ReadList(const JSON:jLimitUnits, &Array:aLimitUnits = Invalid_Array) { - ArrayCreateIfNotCreated(aLimitUnits, 1, 1); + ArrayCreateIfNotCreated(aLimitUnits); if (!json_is_array(jLimitUnits)) { new T_LimitUnit:iLimitUnit = LimitUnit_Read(jLimitUnits); diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 40a344c..b47ffea 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -110,7 +110,7 @@ T_ModuleUnit:ModuleUnit_Read(const JSON:valueJson) { } Array:ModuleUnit_ReadList(const JSON:jModuleUnits, &Array:aModuleUnits = Invalid_Array) { - ArrayCreateIfNotCreated(aModuleUnits, 1, 1); + ArrayCreateIfNotCreated(aModuleUnits); if (!json_is_array(jModuleUnits)) { new T_ModuleUnit:iModuleUnit = ModuleUnit_Read(jModuleUnits); diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index c3f416e..2902351 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -115,7 +115,7 @@ T_VipUnit:VipUnit_Read(const JSON:valueJson) { } Array:VipUnit_ReadList(const JSON:jVipUnits, &Array:aVipUnits = Invalid_Array) { - ArrayCreateIfNotCreated(aVipUnits, 1, 1); + ArrayCreateIfNotCreated(aVipUnits); if (!json_is_array(jVipUnits)) { new T_VipUnit:iVipUnit = VipUnit_Read(jVipUnits); diff --git a/amxmodx/scripting/VipM/Forwards.inc b/amxmodx/scripting/VipM/Forwards.inc index cf1019e..b1cc400 100644 --- a/amxmodx/scripting/VipM/Forwards.inc +++ b/amxmodx/scripting/VipM/Forwards.inc @@ -6,80 +6,73 @@ /* Functions & Macroses: - Forwards_Init(const sPrefix[]); - []Forwards_GetFullName(const sName[]); - Forwards_Reg(const sName[], const iStopType, const ...?param_types); + Forwards_Init(); + Forwards_Reg(const name[], const stopType, const ...?param_types); Forwards_DefaultReturn(const iDefaultReturnValue); - Forwards_Call(const sName[]); - Forwards_CallP(const sName[], ...param_values); - Forwards_GetHandler(const sName[]); - Forwards_RegAndCallP(const sName[], const iStopType, [...param_types], [...param_values]); - Forwards_RegAndCall(const sName[], const iStopType); + Forwards_Call(const name[]); + Forwards_CallP(const name[], ...param_values); + Forwards_GetHandler(const name[]); + Forwards_RegAndCallP(const name[], const stopType, [...param_types], [...param_values]); + Forwards_RegAndCall(const name[], const stopType); */ -#include amxmodx +#include -stock const FORWARDS_NAME_TEMPLATE[] = "%s_On%s"; -stock const FORWARDS_NAME_WITHOUT_PREFIX_TEMPLATE[] = "%s%s"; +stock static Trie:Forwards_gMap = Invalid_Trie; -stock Trie:Forwards_gMap = Invalid_Trie; -stock Forwards_gPrefix[32] = ""; +stock __Forwards_Call_ret; +stock __Forwards_RegAndCall_handler; -stock Forwards_Init(const sPrefix[] = "") { +stock Forwards_Init() { Forwards_gMap = TrieCreate(); - copy(Forwards_gPrefix, charsmax(Forwards_gPrefix), sPrefix); } -// []Forwards_GetFullName(const sName[]); -#define Forwards_GetFullName(%1) \ - fmt(Forwards_gPrefix[0] == EOS ? FORWARDS_NAME_WITHOUT_PREFIX_TEMPLATE : FORWARDS_NAME_TEMPLATE, Forwards_gPrefix, %1) +stock Forwards_AddHandler(const name[], const handler) { + TrieSetCell(Forwards_gMap, name, handler, false); + return handler; +} -// Forwards_Reg(const sName[], const iStopType, const ...?param_types); -#define Forwards_Reg(%1,%2) \ - TrieSetCell(Forwards_gMap, %1, CreateMultiForward(Forwards_GetFullName(%1), %2), false) +stock Forwards_GetHandler(const name[]) { + new handler; + TrieGetCell(Forwards_gMap, name, handler); + return handler; +} -stock __Forwards_Call_ret; +stock Forwards_DefaultReturn(const val) { + __Forwards_Call_ret = val; +} -// Forwards_DefaultReturn(const iDefaultReturnValue); -#define Forwards_DefaultReturn(%1) \ - __Forwards_Call_ret = %1 +stock Forwards_GetReturn(any:...) { + return __Forwards_Call_ret; +} + +// Forwards_Reg(const name[], const stopType, const ...?param_types); +#define Forwards_Reg(%1,%2) \ + Forwards_AddHandler(%1, CreateMultiForward(%1, %2)) +#define Forwards_RegP Forwards_Reg -// Forwards_CallP(const sName[], ...param_values); +// Forwards_CallP(const name[], ...param_values); #define Forwards_CallP(%1,%2) \ - (ExecuteForward(Forwards_GetHandler(%1), __Forwards_Call_ret, %2) ? __Forwards_Call_ret : __Forwards_Call_ret) + Forwards_GetReturn(ExecuteForward(Forwards_GetHandler(%1), __Forwards_Call_ret, %2)) -// Forwards_Call(const sName[]); +// Forwards_Call(const name[]); #define Forwards_Call(%1) \ - (ExecuteForward(Forwards_GetHandler(%1), __Forwards_Call_ret) ? __Forwards_Call_ret : __Forwards_Call_ret) - -stock Forwards_GetHandler(const sName[]) { - new iHandler; - TrieGetCell(Forwards_gMap, sName, iHandler); - return iHandler; -} - -stock __Forwards_RegAndCall_handler; + Forwards_GetReturn(ExecuteForward(Forwards_GetHandler(%1), __Forwards_Call_ret)) -// Forwards_RegAndCallP(const sName[], const iStopType, [...param_types], [...param_values]); +// Forwards_RegAndCallP(const name[], const stopType, [...param_types], [...param_values]); #define Forwards_RegAndCallP(%1,%2,[%3],[%4]) \ - (DestroyForward( \ + Forwards_GetReturn(DestroyForward( \ ExecuteForward( \ - __Forwards_RegAndCall_handler = CreateMultiForward( \ - Forwards_GetFullName(%1), \ - %2, %3 \ - ), \ + __Forwards_RegAndCall_handler = CreateMultiForward(%1, %2, %3), \ __Forwards_Call_ret, %4 \ ) ? __Forwards_RegAndCall_handler : __Forwards_RegAndCall_handler \ - ) ? __Forwards_Call_ret : __Forwards_Call_ret) + )) -// Forwards_RegAndCall(const sName[], const iStopType); +// Forwards_RegAndCall(const name[], const stopType); #define Forwards_RegAndCall(%1,%2) \ - (DestroyForward( \ + Forwards_GetReturn(DestroyForward( \ ExecuteForward( \ - __Forwards_RegAndCall_handler = CreateMultiForward( \ - Forwards_GetFullName(%1), \ - %2 \ - ), \ + __Forwards_RegAndCall_handler = CreateMultiForward(%1, %2), \ __Forwards_Call_ret \ ) ? __Forwards_RegAndCall_handler : __Forwards_RegAndCall_handler \ - ) ? __Forwards_Call_ret : __Forwards_Call_ret) \ No newline at end of file + )) \ No newline at end of file diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc index 67becb9..64bd318 100644 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ b/amxmodx/scripting/VipM/JsonUtils.inc @@ -7,10 +7,11 @@ #include #include -#define JSON_UTILS__MAX_KEY_LENGTH 128 -#define JSON_UTILS__MAX_STRING_LENGTH 256 -#define JSON_UTILS__MAX_REF_LENGTH 128 +#define JSON_UTILS__MAX_KEY_LENGTH PARAM_KEY_MAX_LEN +#define JSON_UTILS__MAX_STRING_LENGTH PARAM_VALUE_MAX_LEN +// deprecated +// Все параметры надо указывать явно stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { if (tTrie == Invalid_Trie) { tTrie = TrieCreate(); @@ -46,6 +47,7 @@ stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) return tTrie; } +// TODO: Перенести в контроллер параметров stock Json_Object_GetColoredChatMessage( const JSON:jObj, const sKey[], diff --git a/amxmodx/scripting/VipM/Natives.inc b/amxmodx/scripting/VipM/Natives.inc deleted file mode 100644 index bba3f9f..0000000 --- a/amxmodx/scripting/VipM/Natives.inc +++ /dev/null @@ -1,25 +0,0 @@ -#if defined _UTILS_src_Natives_included - #endinput -#endif -#define _UTILS_src_Natives_included - -/* -Functions & Macroses: - - Natives_Init(const sPrefix[]); - Natives_Reg(const sName[]); - Natives_AutoReg(const sPrefix[], const aNativeNames[][]); -*/ - -#include amxmodx - -stock const __NATIVE_NAME_TPL[] = "%s_%s"; -stock const __NATIVE_FUNC_TPL[] = "@_%s"; -stock Natives_gPrefix[32]; - -#define Natives_Init(%1) \ - copy(Natives_gPrefix, charsmax(Natives_gPrefix), %1) - -// Natives_Reg(const sName[]); -#define Natives_Reg(%1) \ - register_native(fmt(__NATIVE_NAME_TPL, Natives_gPrefix, %1), fmt(__NATIVE_FUNC_TPL, %1)) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index de65844..3c52872 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -68,23 +68,6 @@ stock IsPlayerAlive(const playerIndex) { #define GET_FILE_JSON_PATH(%1) \ VipM_iGetCfgPath(fmt(__JSON_FILE_TEMPLATE_STR, %1)) - -stock __CMD_NULL_ARG = 0; -stock CMD_INIT_PARAMS() { - __CMD_NULL_ARG = 0; - static Cmd[32]; - read_argv(__CMD_NULL_ARG, Cmd, charsmax(Cmd)); - if (equali(Cmd, "say", 3)) { - __CMD_NULL_ARG++; - } -} - -#define CMD_ARG(%1) \ - (__CMD_NULL_ARG + %1) - -#define CMD_ARG_NUM() \ - (read_argc() - __CMD_NULL_ARG - 1) - #define json_array_foreach(%1:%2) \ if (json_is_array(%1)) \ for (new %2 = 0; %2 < json_array_get_count(%1); %2++) diff --git a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc index bbb3f3e..969c70a 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc @@ -14,9 +14,7 @@ Menu_MainMenu(const UserId, const MainMenuTitle[], const Array:aMenus) { new iMenu = menu_create(MainMenuTitle, "@MenuHandler_Command"); ArrayForeachArray(aMenus => Menu[S_WeaponMenu]) { - static Cmd[128]; - CommandAliases_GetMainCmd(CMD_WEAPON_MENU, Cmd, charsmax(Cmd)); - menu_additem(iMenu, Menu[WeaponMenu_Name], fmt("%s %d", Cmd, __i__)); + menu_additem(iMenu, Menu[WeaponMenu_Name], fmt("%s %d", VIPM_M_WEAPONMENU_CMD_MENU, __i__)); } menu_setprop(iMenu, MPROP_BACKNAME, Lang("VIPM_M_WM_MENU_BACK")); @@ -84,13 +82,10 @@ Menu_WeaponsMenu(const UserId, const MenuId, const Menu[S_WeaponMenu]) { switch (MenuItem[MenuItem_Type]) { case MenuItemType_Default: { - static Cmd[128]; - CommandAliases_GetMainCmd(CMD_WEAPON_MENU, Cmd, charsmax(Cmd)); - new bool:bIsActive = MenuItem[MenuItem_ShowLimits] == Invalid_Array || VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId, Limit_Exec_AND); - menu_additem(iMenu, fmt("%s%s", bIsActive ? "" : "\d", MenuItem[MenuItem_Title]), fmt("%s %d %d", Cmd, MenuId, __i__)); + menu_additem(iMenu, fmt("%s%s", bIsActive ? "" : "\d", MenuItem[MenuItem_Title]), fmt("%s %d %d", VIPM_M_WEAPONMENU_CMD_MENU, MenuId, __i__)); if (!bIsActive && !MenuItem[MenuItem_FakeInactive]) { menu_item_setcall(iMenu, iItemIndex, iInactiveItemHandler); } @@ -117,7 +112,7 @@ Menu_WeaponsMenu(const UserId, const MenuId, const Menu[S_WeaponMenu]) { @MenuHandler_Command(UserId, MenuId, ItemId); if (ItemId == MENU_EXIT) { - CommandAliases_ClientCmd(UserId, CMD_WEAPON_MENU); + client_cmd(UserId, "%s", VIPM_M_WEAPONMENU_CMD_MENU); } } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Natives.inc b/amxmodx/scripting/VipM/WeaponMenu/Natives.inc index 50a333c..8974cdf 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Natives.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Natives.inc @@ -1,10 +1,7 @@ #include -#include "VipM/Natives" public plugin_natives() { - Natives_Init("VipM_WeaponMenu"); - - Natives_Reg("SetExpireStatus"); + register_native("VipM_WeaponMenu_SetExpireStatus", "@_SetExpireStatus"); } @_SetExpireStatus() { diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 0b8ec49..9b8a0ff 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -57,7 +57,7 @@ bool:MenuItem_Read(const JSON:itemJson, item[S_MenuItem]) { } Array:MenuItem_ReadList(const JSON:itemsJson, &Array:items = Invalid_Array) { - ArrayCreateIfNotCreated(items, S_MenuItem, 1); + ArrayCreateIfNotCreated(items, S_MenuItem); new JSON:linkedJson; PCJson_HandleLinkedValue(itemsJson, linkedJson); diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 43b1c87..555ba00 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -55,7 +55,7 @@ bool:WeaponMenu_Read(const JSON:menuJson, Menu[S_WeaponMenu]) { } Array:WeaponMenu_ReadList(const JSON:jWeaponMenus, &Array:aWeaponMenus = Invalid_Array) { - ArrayCreateIfNotCreated(aWeaponMenus, S_WeaponMenu, 1); + ArrayCreateIfNotCreated(aWeaponMenus, S_WeaponMenu); new JSON:linkedJson; PCJson_HandleLinkedValue(jWeaponMenus, linkedJson); diff --git a/amxmodx/scripting/include/VipM/M/WeaponMenu.inc b/amxmodx/scripting/include/VipM/M/WeaponMenu.inc index 870f650..c99a0ae 100644 --- a/amxmodx/scripting/include/VipM/M/WeaponMenu.inc +++ b/amxmodx/scripting/include/VipM/M/WeaponMenu.inc @@ -5,6 +5,10 @@ #define VIPM_M_WEAPONMENU_EXPIRE_STATUS_MAX_LEN 64 +stock const VIPM_M_WEAPONMENU_CMD_MENU[] = "vipm_m_weaponmenu_menu"; +stock const VIPM_M_WEAPONMENU_CMD_MENU_SILENT[] = "vipm_m_weaponmenu_menu_silent"; +stock const VIPM_M_WEAPONMENU_CMD_AUTOOPEN_TOGGLE[] = "vipm_m_weaponmenu_autoopen_toggle"; + /** * Устанавливает статус окончания привилегий, выводимый игроку в оружейном меню. * From b6f46ee0ab82174c8d8d2f812cf597ca384336fa Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 18:29:04 +0300 Subject: [PATCH 056/108] Add param types for limits --- .../DefaultObjects/ParamType/Item.inc | 1 - .../DefaultObjects/ParamType/Items.inc | 2 +- .../VipM/DefaultObjects/ParamType/Limit.inc | 18 ++++++++++++ .../VipM/DefaultObjects/ParamType/Limits.inc | 28 +++++++++++++++++++ .../VipM/DefaultObjects/Registrar.inc | 9 ++++++ amxmodx/scripting/VipModular.sma | 1 + amxmodx/scripting/include/VipM/Limits.inc | 5 ++-- 7 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Registrar.inc diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc index 474b2be..ab1b3bf 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Item.inc @@ -1,5 +1,4 @@ #include -#include #include #include #include diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc index 0286a7d..f20a23b 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ParamType/Items.inc @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -7,6 +6,7 @@ DefaultObjects_ParamType_Items_Register() { ParamsController_RegSimpleType(IC_PARAM_TYPE_ITEMS_NAME, "@OnItemsParamTypeRead"); } + @OnItemsParamTypeRead(const JSON:valueJson) { new Array:items = IC_Item_ReadArrayFromJson(valueJson); diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc new file mode 100644 index 0000000..da1513f --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +DefaultObjects_ParamType_Limit_Register() { + ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMIT_NAME, "@OnLimitParamTypeRead"); +} + +bool:@OnLimitParamTypeRead(const JSON:valueJson) { + new T_LimitUnit:limit = VipM_Limits_ReadFromJson(valueJson); + + if (limit == Invalid_LimitUnit) { + return false; + } + + return ParamsController_SetCell(limit); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc new file mode 100644 index 0000000..4869c24 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +DefaultObjects_ParamType_Limits_Register() { + ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMITS_NAME, "@OnLimitsParamTypeRead"); +} + +@OnLimitsParamTypeRead(const JSON:valueJson) { + new Array:limits = VipM_Limits_ReadListFromJson(valueJson); + + if (limits == Invalid_Array) { + return false; + } + + if ( + ( + json_is_object(valueJson) + || (json_is_array(valueJson) && json_array_get_count(valueJson) == 0) + ) && ArraySize(limits) < 1 + ) { + PCJson_LogForFile(valueJson, "WARNING", "All limits are invalid."); + return false; + } + + return ParamsController_SetCell(limits); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc new file mode 100644 index 0000000..9b7eaa6 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc @@ -0,0 +1,9 @@ +#include + +#include "VipM/DefaultObjects/ParamType/Limit" +#include "VipM/DefaultObjects/ParamType/Limits" + +public ParamsController_OnRegisterTypes() { + DefaultObjects_ParamType_Limit_Register(); + DefaultObjects_ParamType_Limits_Register(); +} \ No newline at end of file diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index 3820726..d527899 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -19,6 +19,7 @@ public stock const PluginDescription[] = "Modular vip system"; #include "VipM/Core/Objects/Modules/Type" #include "VipM/Core/VipsManager" #include "VipM/Core/SrvCmds" +#include "VipM/DefaultObjects/Registrar" public plugin_precache() { register_plugin(PluginName, PluginVersion, PluginAuthor); diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index 96201a2..d38e0e6 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -12,10 +12,12 @@ #define VIPM_LIMITS_TYPE_NAME_MAX_LEN 64 +stock const VIPM_PARAM_TYPE_LIMIT_NAME[] = "VipM-Limit"; +stock const VIPM_PARAM_TYPE_LIMITS_NAME[] = "VipM-Limits"; + enum T_LimitUnit {Invalid_LimitUnit = -1} enum E_LimitEvent{ - /* * Описание: Вызывается после прочтения параметров условного элемента. * Возв. тип: VipM_FwdReturn @@ -42,7 +44,6 @@ enum E_LimitEvent{ } enum E_LimitsExecType { - /* ИЛИ */ Limit_Exec_OR, From bd56b832ba2d1530d9df0265fd7e5ac36467adb9 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 15 Jun 2025 19:38:33 +0300 Subject: [PATCH 057/108] Deprecate old path utils from vipm --- amxmodx/scripting/IC-I-Limits.sma | 28 ++++++----------------- amxmodx/scripting/VipM-M-SpawnHealth.sma | 6 ++--- amxmodx/scripting/VipM-M-Vampire.sma | 6 ++--- amxmodx/scripting/VipM-ModulesLimiter.sma | 25 ++++++++++---------- amxmodx/scripting/VipM/Utils.inc | 3 --- amxmodx/scripting/VipModular.sma | 10 ++++---- amxmodx/scripting/include/VipModular.inc | 14 +++++++++++- 7 files changed, 43 insertions(+), 49 deletions(-) diff --git a/amxmodx/scripting/IC-I-Limits.sma b/amxmodx/scripting/IC-I-Limits.sma index 8f697f5..7582dc4 100644 --- a/amxmodx/scripting/IC-I-Limits.sma +++ b/amxmodx/scripting/IC-I-Limits.sma @@ -9,34 +9,20 @@ public stock const PluginName[] = "[IC-I] Limits"; public stock const PluginVersion[] = IC_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-pub"; -public stock const PluginDescription[] = "[ItemsController-Item] Items using limtis."; +public stock const PluginDescription[] = "[ItemsController-Item] Items using limits."; public IC_ItemType_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); - IC_ItemType_SimpleRegister( + new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "If", - .onRead = "@OnIfRead", .onGive = "@OnIfGive" ); -} - -@OnIfRead(const JSON:instanceJson, const Trie:p) { - if (!json_object_has_value(instanceJson, "Items")) { - PCJson_LogForFile(instanceJson, "ERROR", "Param `Items` required for item `If`."); - return IC_RET_READ_FAIL; - } - - if (!json_object_has_value(instanceJson, "Limits")) { - PCJson_LogForFile(instanceJson, "ERROR", "Limits `Items` required for item `If`."); - return IC_RET_READ_FAIL; - } - - TrieSetCell(p, "Items", IC_Item_ReadArrayFromJson(json_object_get_value(instanceJson, "Items"))); - TrieSetCell(p, "ElseItems", IC_Item_ReadArrayFromJson(json_object_get_value(instanceJson, "ElseItems"))); - TrieSetCell(p, "Limits", VipM_Limits_ReadListFromJson(json_object_get_value(instanceJson, "Limits"))); - - return IC_RET_READ_SUCCESS; + IC_ItemType_AddParams(type, + "Limits", "VipM-Limits", true, + "Items", "IC-Items", false, + "ElseItems", "IC-Items", false + ); } @OnIfGive(const playerIndex, const Trie:p) { diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index 79c7d84..c1f30a4 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -16,7 +16,7 @@ public stock const PluginDescription[] = "Vip modular`s module - SpawnHealth"; new const MODULE_NAME[] = "SpawnHealth"; -public VipM_Modules_OnInited(){ +public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); VipM_Modules_Register(MODULE_NAME, true); @@ -37,11 +37,11 @@ public VipM_Modules_OnInited(){ VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } -@Event_ModuleActivate(){ +@Event_ModuleActivate() { RegisterHookChain(RG_CBasePlayer_Spawn, "@Event_PlayerSpawned", true); } -@Event_PlayerSpawned(const UserId){ +@Event_PlayerSpawned(const UserId) { if (!is_user_alive(UserId)) { return; } diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index f68d1be..8d14f6d 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -14,7 +14,7 @@ public stock const PluginDescription[] = "Vip modular`s module - Vampire"; new const MODULE_NAME[] = "Vampire"; -public VipM_Modules_OnInited(){ +public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_dictionary("VipM-Vampire.ini"); @@ -32,11 +32,11 @@ public VipM_Modules_OnInited(){ VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } -@Event_ModuleActivate(){ +@Event_ModuleActivate() { RegisterHookChain(RG_CBasePlayer_Killed, "@Event_PlayerKilled", true); } -@Event_PlayerKilled(const VictimId, UserId, InflictorId){ +@Event_PlayerKilled(const VictimId, UserId, InflictorId) { if ( UserId == VictimId || !is_user_alive(UserId) diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 0eed1e2..51e4814 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -1,6 +1,7 @@ #include #include #include +#include #include "VipM/Utils" #include "VipM/DebugMode" #include "VipM/ArrayTrieUtils" @@ -11,14 +12,14 @@ public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; public stock const PluginDescription[] = "Modules activation controller"; -new const MODULES_CONFIG_FILE[] = "Modules"; +new const CONFIG_FILE_PATH[] = "Modules.json"; new Trie:g_tModulesLimits = Invalid_Trie; public VipM_OnLoaded() { register_plugin(PluginName, PluginVersion, PluginAuthor); - g_tModulesLimits = LoadModulesLimitsFromFile(MODULES_CONFIG_FILE, g_tModulesLimits); + g_tModulesLimits = LoadModulesLimitsFromFile(PCPath_iMakePath(fmt("%s/%s", VIPM_CONFIGS_FOLDER_NAME, CONFIG_FILE_PATH))); } public VipM_Modules_OnActivate(const sModuleName[]) { @@ -42,21 +43,21 @@ public VipM_Modules_OnActivate(const sModuleName[]) { return VIPM_CONTINUE; } -Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) { - if (tModules == Invalid_Trie) { - tModules = TrieCreate(); +Trie:LoadModulesLimitsFromFile(const filePath[], &Trie:modules = Invalid_Trie) { + if (modules == Invalid_Trie) { + modules = TrieCreate(); } - new JSON:jFile = PCJson_ParseFile(GET_FILE_JSON_PATH(sFileName)); + new JSON:jFile = PCJson_ParseFile(filePath); if (jFile == Invalid_JSON) { - log_error(0, "Invalid JSON syntax. File `%s`.", GET_FILE_JSON_PATH(sFileName)); - return tModules; + log_error(0, "Invalid JSON syntax. File `%s`.", filePath); + return modules; } if (!json_is_array(jFile)) { PCJson_LogForFile(jFile, "WARNING", "Root value must be an array."); PCJson_Free(jFile); - return tModules; + return modules; } json_array_foreach_value (jFile: i => jItem) { @@ -82,12 +83,12 @@ Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) } ArrayForeachString (aModuleNames: j => sModuleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]) { - if (TrieKeyExists(tModules, sModuleName)) { + if (TrieKeyExists(modules, sModuleName)) { PCJson_LogForFile(jItem, "WARNING", "Duplicate limits for module `%s`.", sModuleName); continue; } - TrieSetCell(tModules, sModuleName, aLimits); + TrieSetCell(modules, sModuleName, aLimits); } json_free(jItem); @@ -95,5 +96,5 @@ Trie:LoadModulesLimitsFromFile(const sFileName[], Trie:tModules = Invalid_Trie) } PCJson_Free(jFile); - return tModules; + return modules; } diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 3c52872..3aac7ea 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -65,9 +65,6 @@ stock IsPlayerAlive(const playerIndex) { #define ChatPrintLIf(%3,%1,%2) \ ((%3) && ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2)) -#define GET_FILE_JSON_PATH(%1) \ - VipM_iGetCfgPath(fmt(__JSON_FILE_TEMPLATE_STR, %1)) - #define json_array_foreach(%1:%2) \ if (json_is_array(%1)) \ for (new %2 = 0; %2 < json_array_get_count(%1); %2++) diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index d527899..c52dc2a 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -1,5 +1,6 @@ #include #include +#include #include "VipM/DebugMode" #include "VipM/ArrayTrieUtils" #include "VipM/Utils" @@ -7,9 +8,6 @@ #include "VipM/Core/Objects/Modules/Type" #include "VipM/Core/Objects/Limits/Type" -#pragma semicolon 1 -#pragma compress 1 - public stock const PluginName[] = "Vip Modular"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; @@ -33,9 +31,9 @@ public plugin_precache() { SrvCmds_Init(); Forwards_RegAndCall("VipM_OnInitModules", ET_IGNORE); // deprecated - VipsManager_SetRootDir(VipM_iGetCfgPath("")); - VipsManager_LoadFromFile(VipM_iGetCfgPath("Vips.json")); - VipsManager_LoadFromFolder(VipM_iGetCfgPath("Vips")); + VipsManager_SetRootDir(PCPath_iMakePath(VIPM_CONFIGS_FOLDER_NAME)); + VipsManager_LoadFromFile(PCPath_iMakePath(fmt("%s/%s", VIPM_CONFIGS_FOLDER_NAME, VIPM_VIPS_CONFIG_FILE_PATH))); + VipsManager_LoadFromFolder(PCPath_iMakePath(fmt("%s/%s", VIPM_CONFIGS_FOLDER_NAME, VIPM_VIPS_CONFIG_DIR_PATH))); ModuleType_ActivateUsed(); diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 2df06e0..b0827fb 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -9,9 +9,15 @@ stock const VIPM_LIBRARY[] = "VipModular"; #define _VIPM_VERSION "5.0.0-b13" stock const VIPM_VERSION[] = _VIPM_VERSION; -stock const VIPM_CFG_PATH[] = "plugins/VipModular"; #define _VIPM_PLUGIN_URL "https://github.com/ArKaNeMaN/amxx-VipModular-pub" +// deprecated +stock const VIPM_CFG_PATH[] = "plugins/VipModular"; +// new +stock const VIPM_CONFIGS_FOLDER_NAME[] = "VipModular"; +stock const VIPM_VIPS_CONFIG_FILE_PATH[] = "Vips.json"; +stock const VIPM_VIPS_CONFIG_DIR_PATH[] = "Vips"; + /** * Получение пути, относительно папки с конфигами вип-системы или AmxModX. * @@ -21,9 +27,12 @@ stock const VIPM_CFG_PATH[] = "plugins/VipModular"; * @param Path Путь / Название файла. * @param sOut Буффер для записи полученного пути. * @param iOutLen Размер буфера. + * + * @deprecated Use PCPath_MakePath() from ParamsController instead * * @return Кол-во записанных в буфер ячеек. */ +#pragma deprecated Use PCPath_MakePath() from ParamsController instead stock VipM_GetCfgPath(const sPath[] = "", sOut[], const iOutLen){ static __amxx_configsdir[PLATFORM_MAX_PATH]; if (!__amxx_configsdir[0]) { @@ -46,9 +55,12 @@ stock VipM_GetCfgPath(const sPath[] = "", sOut[], const iOutLen){ * Иначе из папки вип-системы (см. константу VIPM_CFG_PATH). * * @param Path Путь / Название файла. + * + * @deprecated Use PCPath_iMakePath() from ParamsController instead * * @return Полученный путь. */ +#pragma deprecated Use PCPath_iMakePath() from ParamsController instead stock VipM_iGetCfgPath(const sPath[] = "") { new sRetPath[PLATFORM_MAX_PATH]; VipM_GetCfgPath(sPath, sRetPath, charsmax(sRetPath)); From f46b01e99d781ed543caec1b4a1cb8133895e6b8 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 7 Sep 2025 01:50:55 +0300 Subject: [PATCH 058/108] Use params controller for all params lists --- amxmodx/scripting/VipM/Core/API/Limits.inc | 142 +++++++------- amxmodx/scripting/VipM/Core/API/Modules.inc | 24 ++- .../VipM/Core/Objects/Limits/Type.inc | 95 +++++----- .../VipM/Core/Objects/Modules/Type.inc | 128 +++++++------ amxmodx/scripting/VipM/Core/Objects/Param.inc | 177 +++++------------- amxmodx/scripting/VipM/Core/SrvCmds.inc | 56 ------ amxmodx/scripting/include/ItemsController.inc | 11 ++ amxmodx/scripting/include/VipM/Modules.inc | 61 +++--- 8 files changed, 307 insertions(+), 387 deletions(-) diff --git a/amxmodx/scripting/VipM/Core/API/Limits.inc b/amxmodx/scripting/VipM/Core/API/Limits.inc index 871fc00..ba83539 100644 --- a/amxmodx/scripting/VipM/Core/API/Limits.inc +++ b/amxmodx/scripting/VipM/Core/API/Limits.inc @@ -1,5 +1,6 @@ #include #include +#include #include "VipM/Core/Objects/Limits/Type" #include "VipM/Core/Objects/Limits/Unit" @@ -8,6 +9,7 @@ API_Limits_Init() { register_native("VipM_Limits_RegisterType", "@_Limits_RegisterType"); register_native("VipM_Limits_AddTypeParams", "@_Limits_AddTypeParams"); + register_native("VipM_Limits_AddParamsEx", "@VipM_Limits_AddParamsEx"); register_native("VipM_Limits_RegisterTypeEvent", "@_Limits_RegisterTypeEvent"); register_native("VipM_Limits_ReadFromJson", "@_Limits_ReadFromJson"); @@ -19,122 +21,122 @@ API_Limits_Init() { register_native("VipM_Limits_ExecuteList", "@_Limits_ExecuteList"); } -// native VipM_Limits_RegisterType(const sLimitTypeName[], const bool:bForPlayer = true, const bool:bStatic = false); +static T_LimitType:API_Limits_GetTypeParam(const param) { + new limitName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(param, limitName, charsmax(limitName)); + + new T_LimitType:type = LimitType_Find(limitName); + if (type == Invalid_LimitType) { + abort(AMX_ERR_PARAMS, "Limit type '%s' not found.", limitName); + } + + return type; +} + +// native VipM_Limits_RegisterType(const limitName[], const bool:isForPlayer = true, const bool:isStatic = false); T_LimitType:@_Limits_RegisterType() { - enum {Arg_sLimitTypeName = 1, Arg_bForPlayer, Arg_bStatic} + enum {Arg_LimitName = 1, Arg_IsForPlayer, Arg_IsStatic} - new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); + new limitName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + get_string(Arg_LimitName, limitName, charsmax(limitName)); - new bool:bForPlayer = bool:get_param(Arg_bForPlayer); - new bool:bStatic = bool:get_param(Arg_bStatic); + new bool:isForPlayer = bool:get_param(Arg_IsForPlayer); + new bool:isStatic = bool:get_param(Arg_IsStatic); - new T_LimitType:iLimitType = LimitType_Construct(sLimitTypeName, bForPlayer, bStatic); - if (iLimitType == Invalid_LimitType) { - log_error(0, "Can't create limit type '%s'.", sLimitTypeName); + new T_LimitType:type = LimitType_Construct(limitName, isForPlayer, isStatic); + if (type == Invalid_LimitType) { + log_error(0, "Can't create limit type '%s'.", limitName); return Invalid_LimitType; } - return iLimitType; + return type; } -// native VipM_Limits_AddTypeParams(const sLimitTypeName[], any:...); -@_Limits_AddTypeParams(const PluginId, const iParamsNum) { - enum {Arg_sLimitTypeName = 1, Arg_Params} - - new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); +// native VipM_Limits_AddTypeParams(const limitName[], any:...); +@_Limits_AddTypeParams(const pluginIndex, const paramsCount) { + enum {Arg_LimitName = 1, Arg_Params} - new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); - if (iLimitType == Invalid_LimitType) { - log_error(0, "Limit type '%s' not found.", sLimitTypeName); - return; - } + new T_LimitType:type = API_Limits_GetTypeParam(Arg_LimitName); + new Array:params = CfgParam_GetFromNative(Arg_Params, paramsCount); - new Array:aParams = CfgParam_GetFromNative(Arg_Params, iParamsNum); - if (aParams == Invalid_Array) { + if (params == Invalid_Array) { return; } - LimitType_MergeParamsList(iLimitType, aParams); + LimitType_AddParams(type, params); } -// native VipM_Limits_RegisterTypeEvent(const sLimitTypeName[], const E_LimitEvent:iEvent, const sFunc[]); -@_Limits_RegisterTypeEvent(const PluginId) { - enum {Arg_sLimitTypeName = 1, Arg_iEvent, Arg_sFuncName} +// native VipM_Limits_AddParamsEx(const limitName[], any:...); +@VipM_Limits_AddParamsEx(const pluginIndex, const paramsCount) { + enum {Arg_LimitName = 1, Arg_Params} - new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); + new T_LimitType:type = API_Limits_GetTypeParam(Arg_LimitName); + new Array:params = ParamsController_Param_ListFromNativeParams(Arg_Params, paramsCount); - new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); - if (iLimitType == Invalid_LimitType) { - log_error(0, "Limit type '%s' not found.", sLimitTypeName); - return; - } + LimitType_AddParams(type, params); + ArrayDestroy(params); +} + +// native VipM_Limits_RegisterTypeEvent(const limitName[], const E_LimitEvent:event, const func[]); +@_Limits_RegisterTypeEvent(const pluginIndex) { + enum {Arg_LimitName = 1, Arg_Event, Arg_Func} - new E_LimitEvent:iEvent = E_LimitEvent:get_param(Arg_iEvent); + new T_LimitType:type = API_Limits_GetTypeParam(Arg_LimitName); + new E_LimitEvent:event = E_LimitEvent:get_param(Arg_Event); - new sFuncName[64]; - get_string(Arg_sFuncName, sFuncName, charsmax(sFuncName)); + new func[64]; + get_string(Arg_Func, func, charsmax(func)); - LimitType_SetEventListener(iLimitType, iEvent, PluginId, sFuncName); + LimitType_SetEventListener(type, event, pluginIndex, func); } -// native VipM_Limits_Execute(const sLimitTypeName[], const bool:bNewValue, const UserId = 0); +// native VipM_Limits_Execute(const limitName[], const bool:value, const playerIndex = 0); @_Limits_SetStaticValue() { - enum {Arg_sLimitTypeName = 1, Arg_NewValue, Arg_UserId} - - static sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - get_string(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); - - new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); - if (iLimitType == Invalid_LimitType) { - log_error(0, "Limit type '%s' not found.", sLimitTypeName); - return; - } + enum {Arg_LimitName = 1, Arg_Value, Arg_PlayerIndex} - new bool:bNewValue = bool:get_param(Arg_NewValue); - new UserId = get_param(Arg_UserId); + new T_LimitType:type = API_Limits_GetTypeParam(Arg_LimitName); + new bool:value = bool:get_param(Arg_Value); + new playerIndex = get_param(Arg_PlayerIndex); - LimitType_SetStaticValue(iLimitType, bNewValue, UserId); + LimitType_SetStaticValue(type, value, playerIndex); } -// native T_LimitUnit:VipM_Limits_ReadFromJson(const JSON:jLimit); +// native T_LimitUnit:VipM_Limits_ReadFromJson(const JSON:limitJson); T_LimitUnit:@_Limits_ReadFromJson() { enum {Arg_JsonValue = 1} - new JSON:jLimit = JSON:get_param(Arg_JsonValue); + new JSON:limitJson = JSON:get_param(Arg_JsonValue); - return LimitUnit_Read(jLimit); + return LimitUnit_Read(limitJson); } -// native Array:VipM_Limits_ReadListFromJson(const JSON:jLimits, Array:aLimits = Invalid_Array); +// native Array:VipM_Limits_ReadListFromJson(const JSON:limitsJson, Array:limits = Invalid_Array); Array:@_Limits_ReadListFromJson() { enum {Arg_JsonValue = 1, Arg_Array} - new JSON:jLimits = JSON:get_param(Arg_JsonValue); - new Array:aLimits = Array:get_param(Arg_Array); + new JSON:limitsJson = JSON:get_param(Arg_JsonValue); + new Array:limits = Array:get_param(Arg_Array); - return LimitUnit_ReadList(jLimits, aLimits); + return LimitUnit_ReadList(limitsJson, limits); } -// native bool:VipM_Limits_Execute(const T_LimitUnit:iLimit, const UserId = 0); +// native bool:VipM_Limits_Execute(const T_LimitUnit:limit, const playerIndex = 0); bool:@_Limits_Execute() { - enum {Arg_LimitUnit = 1, Arg_UserId} + enum {Arg_LimitUnit = 1, Arg_PlayerIndex} - new T_LimitUnit:iLimit = T_LimitUnit:get_param(Arg_LimitUnit); - new UserId = get_param(Arg_UserId); + new T_LimitUnit:limit = T_LimitUnit:get_param(Arg_LimitUnit); + new playerIndex = get_param(Arg_PlayerIndex); - return LimitUnit_Execute(iLimit, UserId); + return LimitUnit_Execute(limit, playerIndex); } -// native bool:VipM_Limits_ExecuteList(const Array:aLimits, const UserId = 0, const E_LimitsExecType:iType = Limit_Exec_OR); +// native bool:VipM_Limits_ExecuteList(const Array:limits, const playerIndex = 0, const E_LimitsExecType:type = Limit_Exec_OR); bool:@_Limits_ExecuteList() { - enum {Arg_LimitUnitList = 1, Arg_UserId, Arg_Type} + enum {Arg_LimitUnitList = 1, Arg_PlayerIndex, Arg_Type} - new Array:aLimits = Array:get_param(Arg_LimitUnitList); - new UserId = get_param(Arg_UserId); - new E_LimitsExecType:Type = E_LimitsExecType:get_param(Arg_Type); + new Array:limits = Array:get_param(Arg_LimitUnitList); + new playerIndex = get_param(Arg_PlayerIndex); + new E_LimitsExecType:type = E_LimitsExecType:get_param(Arg_Type); - return LimitUnit_ExecuteList(aLimits, UserId, Type); + return LimitUnit_ExecuteList(limits, playerIndex, type); } diff --git a/amxmodx/scripting/VipM/Core/API/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc index 6ec310d..f45feb3 100644 --- a/amxmodx/scripting/VipM/Core/API/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -1,13 +1,18 @@ #include +#include + #include "VipM/DebugMode" #include "VipM/Core/Objects/Param" API_Modules_Init(){ register_native("VipM_Modules_Register", "@_Modules_Register"); register_native("VipM_Modules_AddParams", "@_Modules_AddParams"); + register_native("VipM_Modules_AddParamsEx", "@VipM_Modules_AddParamsEx"); register_native("VipM_Modules_RegisterEvent", "@_Modules_RegisterEvent"); + register_native("VipM_Modules_IsActive", "@_Modules_IsActive"); register_native("VipM_Modules_GetParams", "@_Modules_GetParams"); + } T_ModuleType:@_Modules_Register(const PluginId) { @@ -42,7 +47,24 @@ T_ModuleType:@_Modules_Register(const PluginId) { return; } - ModuleType_MergeParamsList(iModuleType, aParams); + ModuleType_AddParams(iModuleType, aParams); +} + +@VipM_Modules_AddParamsEx(const pluginIndex, const paramsCount) { + enum {Arg_ModuleName = 1, Arg_Params} + + new modelName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_ModuleName, modelName, charsmax(modelName)); + + new T_ModuleType:module = ModuleType_Find(modelName); + if (module == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", modelName); + return; + } + + new Array:params = ParamsController_Param_ListFromNativeParams(Arg_Params, paramsCount); + ModuleType_AddParams(module, params); + ArrayDestroy(params); } bool:@_Modules_RegisterEvent(const PluginId) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 72fb036..726c005 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -13,7 +13,7 @@ enum _:S_LimitType { LimitType_Name[VIPM_LIMITS_TYPE_NAME_MAX_LEN], - Array:LimitType_Params, // S_CfgParam[] + Array:LimitType_Params, bool:LimitType_Static, LimitType_StaticValue, @@ -55,7 +55,7 @@ T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, co new LimitType[S_LimitType]; copy(LimitType[LimitType_Name], charsmax(LimitType[LimitType_Name]), sName); - LimitType[LimitType_Params] = Invalid_Array; + LimitType[LimitType_Params] = ArrayCreate(1, 1); LimitType[LimitType_Static] = bStatic; LimitType[LimitType_StaticValue] = 0; @@ -75,73 +75,80 @@ T_LimitType:LimitType_Find(const sName[]) { } } -static LimitType__Get(const T_LimitType:iLimitType, LimitType[S_LimitType]) { - ArrayMapGetArray(g_amLimitTypes, _:iLimitType, LimitType); +static LimitType__Get(const T_LimitType:type, LimitType[S_LimitType]) { + ArrayMapGetArray(g_amLimitTypes, _:type, LimitType); } static LimitType__Set(const LimitType[S_LimitType]) { ArrayMapSetArrayByKey(g_amLimitTypes, LimitType[LimitType_Name], LimitType); } -Array:LimitType_GetParams(const T_LimitType:iLimitType) { - new LimitType[S_LimitType]; - LimitType__Get(iLimitType, LimitType); - - if (LimitType[LimitType_Params] == Invalid_Array) { - return Invalid_Array; +LimitType_AddParams(const T_LimitType:type, const Array:params) { + if (params == Invalid_Array) { + return; } - return ArrayClone(LimitType[LimitType_Params]); -} - -LimitType_MergeParamsList(const T_LimitType:iLimitType, const Array:aParams) { - new LimitType[S_LimitType]; - LimitType__Get(iLimitType, LimitType); - - LimitType[LimitType_Params] = CfgParam_Merge(LimitType[LimitType_Params], aParams); - - LimitType__Set(LimitType); + new typeObject[S_LimitType]; + LimitType__Get(type, typeObject); + + for (new i = 0, ii = ArraySize(params); i < ii; ++i) { + ArrayPushCell(typeObject[LimitType_Params], ArrayGetCell(params, i)); + } } -Trie:LimitType_ReadParams(const T_LimitType:iLimitType, const JSON:jParams) { - new LimitType[S_LimitType]; - LimitType__Get(iLimitType, LimitType); - - new Trie:tParams = TrieCreate(); +Trie:LimitType_ReadParams(const T_LimitType:type, const JSON:paramsJson) { + new typeObject[S_LimitType]; + LimitType__Get(type, typeObject); // У статических лимитов не может быть параметров - if (LimitType[LimitType_Static]) { - return tParams; + if (typeObject[LimitType_Static]) { + return Invalid_Trie; } - - new sErrParam[VIPM_PARAM_NAME_MAX_LEN]; - if (!CfgParam_ReadList(jParams, tParams, LimitType[LimitType_Params], sErrParam, charsmax(sErrParam))) { - PCJson_ErrorForFile(jParams, "Param '%s' required for '%s' limit.", sErrParam, LimitType[LimitType_Name]); - TrieDestroy(tParams); + + new E_ParamsReadErrorType:errType, errParam[PARAM_KEY_MAX_LEN]; + new Trie:params = ParamsController_Param_ReadList( + typeObject[LimitType_Params], paramsJson, + .iErrType = errType, + .sErrParamName = errParam, + .iErrParamNameLen = charsmax(errParam) + ); + + if (errType != ParamsReadError_None) { + TrieDestroy(params); + + switch (errType) { + case ParamsReadError_RequiredParamNotPresented: { + PCJson_ErrorForFile(paramsJson, "Param '%s' required for '%s' limit.", errParam, typeObject[LimitType_Name]); + } + case ParamsReadError_ParamValueIsInvalid: { + PCJson_ErrorForFile(paramsJson, "Param '%s' has invalid value.", errParam); + } + } + return Invalid_Trie; } - if (LimitType[LimitType_Events][Limit_OnRead] >= 0) { - new iRet = VIPM_STOP; - ExecuteForward(LimitType[LimitType_Events][Limit_OnRead], iRet, jParams, tParams); + if (typeObject[LimitType_Events][Limit_OnRead] >= 0) { + new ret = VIPM_STOP; + ExecuteForward(typeObject[LimitType_Events][Limit_OnRead], ret, paramsJson, params); - if (iRet == VIPM_STOP) { - TrieDestroy(tParams); + if (ret == VIPM_STOP) { + TrieDestroy(params); return Invalid_Trie; } } - return tParams; + return params; } LimitType_SetEventListener( - const T_LimitType:iLimitType, + const T_LimitType:type, const E_LimitEvent:iEvent, const PluginId, const sFuncName[] ) { new LimitType[S_LimitType]; - LimitType__Get(iLimitType, LimitType); + LimitType__Get(type, LimitType); if (LimitType[LimitType_Events][iEvent] >= 0) { DestroyForward(LimitType[LimitType_Events][iEvent]); @@ -169,9 +176,9 @@ static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, co return -1; } -LimitType_SetStaticValue(const T_LimitType:iLimitType, const bool:bValue, const UserId = 0) { +LimitType_SetStaticValue(const T_LimitType:type, const bool:bValue, const UserId = 0) { new LimitType[S_LimitType]; - LimitType__Get(iLimitType, LimitType); + LimitType__Get(type, LimitType); if (!LimitType[LimitType_Static]) { abort(AMX_ERR_PARAMS, "Trying to set static value for a non-static limit."); @@ -187,9 +194,9 @@ LimitType_SetStaticValue(const T_LimitType:iLimitType, const bool:bValue, const LimitType__Set(LimitType); } -bool:LimitType_Execute(const T_LimitType:iLimitType, const Trie:tParams, const UserId = 0) { +bool:LimitType_Execute(const T_LimitType:type, const Trie:tParams, const UserId = 0) { new LimitType[S_LimitType]; - LimitType__Get(iLimitType, LimitType); + LimitType__Get(type, LimitType); new bool:bRes = false; if (LimitType[LimitType_Static]) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index a36b01f..35ce43c 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -14,7 +14,7 @@ enum _:S_ModuleType { ModuleType_Name[VIPM_MODULES_TYPE_NAME_MAX_LEN], - Array:ModuleType_Params, // S_CfgParam[] + Array:ModuleType_Params, bool:ModuleType_Used, bool:ModuleType_Active, @@ -56,7 +56,7 @@ T_ModuleType:ModuleType_Construct(const sName[]) { new ModuleType[S_ModuleType]; copy(ModuleType[ModuleType_Name], charsmax(ModuleType[ModuleType_Name]), sName); - ModuleType[ModuleType_Params] = Invalid_Array; + ModuleType[ModuleType_Params] = ArrayCreate(1, 1); ModuleType[ModuleType_Used] = false; ModuleType[ModuleType_Active] = false; @@ -78,7 +78,7 @@ static ModuleType__Get(const T_ModuleType:iModuleType, ModuleType[S_ModuleType]) ArrayMapGetArray(g_amModuleTypes, _:iModuleType, ModuleType); } -static ModuleType__Set(const ModuleType[S_ModuleType]) { +static ModuleType__Save(const ModuleType[S_ModuleType]) { ArrayMapSetArrayByKey(g_amModuleTypes, ModuleType[ModuleType_Name], ModuleType); } @@ -107,103 +107,109 @@ bool:ModuleType_IsActive(const T_ModuleType:iModuleType) { return ModuleType__GetValue(iModuleType, ModuleType_Active); } -Trie:ModuleType_ReadParams(const T_ModuleType:iModuleType, const JSON:jParams) { - new ModuleType[S_ModuleType]; - ModuleType__Get(iModuleType, ModuleType); - - new Trie:tParams = TrieCreate(); - - new sErrParam[VIPM_PARAM_NAME_MAX_LEN]; - if (!CfgParam_ReadList(jParams, tParams, ModuleType[ModuleType_Params], sErrParam, charsmax(sErrParam))) { - PCJson_ErrorForFile(jParams, "Param '%s' required for '%s' module.", sErrParam, ModuleType[ModuleType_Name]); - TrieDestroy(tParams); +Trie:ModuleType_ReadParams(const T_ModuleType:type, const JSON:paramsJson) { + new typeObject[S_ModuleType]; + ModuleType__Get(type, typeObject); + + new E_ParamsReadErrorType:errType, errParam[PARAM_KEY_MAX_LEN]; + new Trie:params = ParamsController_Param_ReadList( + typeObject[ModuleType_Params], paramsJson, + .iErrType = errType, + .sErrParamName = errParam, + .iErrParamNameLen = charsmax(errParam) + ); + + if (errType != ParamsReadError_None) { + TrieDestroy(params); + + switch (errType) { + case ParamsReadError_RequiredParamNotPresented: { + PCJson_ErrorForFile(paramsJson, "Param '%s' required for '%s' module.", errParam, typeObject[ModuleType_Name]); + } + case ParamsReadError_ParamValueIsInvalid: { + PCJson_ErrorForFile(paramsJson, "Param '%s' has invalid value.", errParam); + } + } + return Invalid_Trie; } - if (ModuleType[ModuleType_Events][Module_OnRead] >= 0) { + if (typeObject[ModuleType_Events][Module_OnRead] >= 0) { new iRet = VIPM_STOP; - ExecuteForward(ModuleType[ModuleType_Events][Module_OnRead], iRet, jParams, tParams); + ExecuteForward(typeObject[ModuleType_Events][Module_OnRead], iRet, paramsJson, params); if (iRet == VIPM_STOP) { - TrieDestroy(tParams); + TrieDestroy(params); return Invalid_Trie; } } - return tParams; + return params; } -Array:ModuleType_GetParams(const T_ModuleType:iModuleType) { - new ModuleType[S_ModuleType]; - ModuleType__Get(iModuleType, ModuleType); - - if (ModuleType[ModuleType_Params] == Invalid_Array) { - return Invalid_Array; +ModuleType_AddParams(const T_ModuleType:module, const Array:params) { + if (params == Invalid_Array) { + return; } - return ArrayClone(ModuleType[ModuleType_Params]); -} - -ModuleType_MergeParamsList(const T_ModuleType:iModuleType, const Array:aParams) { - new ModuleType[S_ModuleType]; - ModuleType__Get(iModuleType, ModuleType); - - ModuleType[ModuleType_Params] = CfgParam_Merge(ModuleType[ModuleType_Params], aParams); - - ModuleType__Set(ModuleType); + new Array:currentParams = ModuleType__GetValue(module, ModuleType_Params); + + for (new i = 0, ii = ArraySize(params); i < ii; ++i) { + ArrayPushCell(currentParams, ArrayGetCell(params, i)); + } } ModuleType_SetEventListener( - const T_ModuleType:iModuleType, - const E_ModuleEvent:iEvent, - const PluginId, - const sFuncName[] + const T_ModuleType:type, + const E_ModuleEvent:event, + const pluginIndex, + const func[] ) { - new ModuleType[S_ModuleType]; - ModuleType__Get(iModuleType, ModuleType); + new typeObject[S_ModuleType]; + ModuleType__Get(type, typeObject); - if (iEvent == Module_OnCompareParams) { + if (event == Module_OnCompareParams) { log_amx("[WARNING] Event 'Module_OnCompareParams' is deprecated and will not be fired."); return; } - if (ModuleType[ModuleType_Events][iEvent] >= 0) { - DestroyForward(ModuleType[ModuleType_Events][iEvent]); + if (typeObject[ModuleType_Events][event] >= 0) { + DestroyForward(typeObject[ModuleType_Events][event]); } - ModuleType[ModuleType_Events][iEvent] = ModuleType__MakeEventForward(iEvent, PluginId, sFuncName); + typeObject[ModuleType_Events][event] = ModuleType__MakeEventForward(event, pluginIndex, func); - if (ModuleType[ModuleType_Events][iEvent] < 0) { - abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); + if (typeObject[ModuleType_Events][event] < 0) { + abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", func, pluginIndex); return; } - ModuleType__Set(ModuleType); + ModuleType__Save(typeObject); } -static ModuleType__MakeEventForward(const E_ModuleEvent:iEvent, const PluginId, const sFuncName[]) { - switch (iEvent) { +static ModuleType__MakeEventForward(const E_ModuleEvent:event, const pluginIndex, const func[]) { + switch (event) { case Module_OnRead: // (const JSON:jCfg, Trie:Params) - return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + return CreateOneForward(pluginIndex, func, FP_CELL, FP_CELL); case Module_OnActivated: // () - return CreateOneForward(PluginId, sFuncName); + return CreateOneForward(pluginIndex, func); case Module_OnMergeParams: // (const Trie:tParams1, const Trie:tParams2) - return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + return CreateOneForward(pluginIndex, func, FP_CELL, FP_CELL); } - abort(AMX_ERR_GENERAL, "[ERROR] Invalid event index (%d).", iEvent); + abort(AMX_ERR_GENERAL, "[ERROR] Invalid event index (%d).", event); return -1; } -ModuleType_MarkAsUsed(const T_ModuleType:iModuleType, const bool:bState = true) { - ModuleType__SetValue(iModuleType, ModuleType_Used, bState); +ModuleType_MarkAsUsed(const T_ModuleType:type, const bool:bState = true) { + ModuleType__SetValue(type, ModuleType_Used, bState); } -bool:ModuleType_Activate(const T_ModuleType:iModuleType) { +bool:ModuleType_Activate(const T_ModuleType:type) { new ModuleType[S_ModuleType]; - ModuleType__Get(iModuleType, ModuleType); + ModuleType__Get(type, ModuleType); if (!ModuleType[ModuleType_Active]) { Forwards_DefaultReturn(VIPM_CONTINUE); @@ -217,23 +223,23 @@ bool:ModuleType_Activate(const T_ModuleType:iModuleType) { ExecuteForward(ModuleType[ModuleType_Events][Module_OnActivated]); } - ModuleType__Set(ModuleType); + ModuleType__Save(ModuleType); } return ModuleType[ModuleType_Active]; } ModuleType_ActivateUsed() { - ArrayMapForeachArray (g_amModuleTypes: iModuleType => ModuleType[S_ModuleType]) { + ArrayMapForeachArray (g_amModuleTypes: type => ModuleType[S_ModuleType]) { if (ModuleType[ModuleType_Used]) { - ModuleType_Activate(iModuleType); + ModuleType_Activate(type); } } } -Trie:ModuleType_MergeParams(const T_ModuleType:iModuleType, const Trie:tParams1, const Trie:tParams2) { +Trie:ModuleType_MergeParams(const T_ModuleType:type, const Trie:tParams1, const Trie:tParams2) { new ModuleType[S_ModuleType]; - ModuleType__Get(iModuleType, ModuleType); + ModuleType__Get(type, ModuleType); new Trie:tRes = tParams1; if (ModuleType[ModuleType_Events][Module_OnMergeParams] >= 0) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Param.inc b/amxmodx/scripting/VipM/Core/Objects/Param.inc index 4e8bfb7..c31d89b 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Param.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Param.inc @@ -7,16 +7,8 @@ #include #include #include -#include -#include "VipM/ArrayTrieUtils" -enum _:S_CfgParam { - CfgParam_Name[VIPM_PARAM_NAME_MAX_LEN], - E_ParamType:CfgParam_Type, - bool:CfgParam_Required, -} - -Array:CfgParam_GetFromNative(const iStartParam, const iNativeParamsCount, &Array:aParams = Invalid_Array) { +Array:CfgParam_GetFromNative(const iStartParam, const iNativeParamsCount, &Array:params = Invalid_Array) { const ARGS_NUM_PER_PARAM = 3; new NullArg = iStartParam - 1; @@ -27,138 +19,59 @@ Array:CfgParam_GetFromNative(const iStartParam, const iNativeParamsCount, &Array } new iParamsCount = max(1, (iNativeParamsCount - NullArg) / ARGS_NUM_PER_PARAM); - if (aParams == Invalid_Array) { - aParams = ArrayCreate(S_CfgParam, iParamsCount); + if (params == Invalid_Array) { + params = ArrayCreate(1, iParamsCount); } else { - ArrayResize(aParams, ArraySize(aParams) + iParamsCount); + ArrayResize(params, ArraySize(params) + iParamsCount); } - new Param[S_CfgParam]; for (new i = NullArg + 1; i < iNativeParamsCount; i += ARGS_NUM_PER_PARAM) { - get_string(i, Param[CfgParam_Name], charsmax(Param[CfgParam_Name])); - Param[CfgParam_Type] = E_ParamType:get_param_byref(i + 1); - Param[CfgParam_Required] = bool:get_param_byref(i + 2); - - ArrayPushArray(aParams, Param); - } - - return aParams; -} - -Array:CfgParam_Merge(&Array:aParams, const Array:...) { - if (aParams == Invalid_Array) { - aParams = ArrayCreate(S_CfgParam, 1); - } - - for (new i = 1, ii = numargs(); i < ii; ++i) { - new Array:aMerge = Array:getarg(i); - - for (new j = 0, jj = ArraySizeSafe(aMerge); j < jj; ++j) { - new Param[S_CfgParam]; - ArrayGetArray(aMerge, j, Param); - - ArrayPushArray(aParams, Param); - } - } - - return aParams; -} - -bool:CfgParam_ReadList( - const JSON:jParams, - &Trie:Params, - const Array:List = Invalid_Array, - ErrParam[] = "", - const Len = 0 -) { - if (!json_is_object(jParams)) { - return false; - } - - if (Params == Invalid_Trie) { - Params = TrieCreate(); - } - - if (List == Invalid_Array) { - // deprecated - Params = Json_ReadObjectToTrie(jParams, Params); - } else { - ArrayForeachArray (List => Param[S_CfgParam]) { - if (!json_object_has_value(jParams, Param[CfgParam_Name])) { - if ( - Param[CfgParam_Required] - && Param[CfgParam_Type] != ptCustom - ) { - formatex(ErrParam, Len, Param[CfgParam_Name]); - return false; - } else { - continue; - } + new paramType[PARAM_TYPE_NAME_MAX_LEN]; + switch (E_ParamType:get_param_byref(i + 1)) { + case ptInteger: { + paramType = DEFAULT_PARAMS_INT_NAME; } + case ptFloat: { + paramType = DEFAULT_PARAMS_FLOAT_NAME; + } + case ptBoolean: { + paramType = DEFAULT_PARAMS_BOOL_NAME; + } + case ptString: { + paramType = DEFAULT_PARAMS_STR_NAME; + } + case ptColor: { + paramType = DEFAULT_PARAMS_RGB_NAME; + } + case ptVector2: { + log_amx("[WARNING] Param type ptVector2 is deprecated and will be ignored."); + continue; + } + case ptVector3: { + log_amx("[WARNING] Param type ptVector3 is deprecated and will be ignored."); + continue; + } + case ptLimit: { + paramType = VIPM_PARAM_TYPE_LIMIT_NAME; + } + case ptLimits: { + paramType = VIPM_PARAM_TYPE_LIMITS_NAME; + } + default: { + log_amx("[WARNING] Invalid param type (%d).", get_param_byref(i + 1)); + continue; + } + } - switch (Param[CfgParam_Type]) { - case ptCustom: - continue; - - case ptInteger: - TrieSetCell(Params, Param[CfgParam_Name], PCSingle_ObjInt(jParams, Param[CfgParam_Name])); - - case ptFloat: - TrieSetCell(Params, Param[CfgParam_Name], PCSingle_ObjFloat(jParams, Param[CfgParam_Name])); - - case ptBoolean: - TrieSetCell(Params, Param[CfgParam_Name], PCSingle_ObjBool(jParams, Param[CfgParam_Name])); - - case ptString: { - new sParam[128]; - PCSingle_ObjString(jParams, Param[CfgParam_Name], sParam, charsmax(sParam)); - TrieSetString(Params, Param[CfgParam_Name], sParam); - } + new paramName[PARAM_KEY_MAX_LEN]; + get_string(i, paramName, charsmax(paramName)); - case ptColor: { - new JSON:jColor = json_object_get_value(jParams, Param[CfgParam_Name]); - new Color[3]; - for (new i = 0; i < 3; ++i) { - Color[i] = json_array_get_number(jColor, i); - } - TrieSetArray(Params, Param[CfgParam_Name], Color, 3); - json_free(jColor); - } + new bool:required = bool:get_param_byref(i + 2); - case ptVector2: { - new JSON:jVec = json_object_get_value(jParams, Param[CfgParam_Name]); - new Float:Vec[2]; - for (new i = 0; i < 2; ++i) { - Vec[i] = json_array_get_real(jVec, i); - } - TrieSetArray(Params, Param[CfgParam_Name], Vec, 2); - json_free(jVec); - } - case ptVector3: { - new JSON:jVec = json_object_get_value(jParams, Param[CfgParam_Name]); - new Float:Vec[3]; - for (new i = 0; i < 3; ++i) { - Vec[i] = json_array_get_real(jVec, i); - } - TrieSetArray(Params, Param[CfgParam_Name], Vec, 3); - json_free(jVec); - } + new T_Param:param = ParamsController_Param_Construct(paramName, paramType, required); - case ptLimit: { - new JSON:jLimit = json_object_get_value(jParams, Param[CfgParam_Name]); - new T_LimitUnit:iLimit = VipM_Limits_ReadFromJson(jLimit); - TrieSetCell(Params, Param[CfgParam_Name], iLimit); - json_free(jLimit); - } - case ptLimits: { - new JSON:jLimits = json_object_get_value(jParams, Param[CfgParam_Name]); - new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits, aLimits); - TrieSetCell(Params, Param[CfgParam_Name], aLimits); - json_free(jLimits); - } - } - } + ArrayPushCell(params, param); } - return true; + return params; } diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index e20a1c4..4aeebad 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -24,10 +24,8 @@ SrvCmds_Init() { register_srvcmd("vipm_info", "@SrvCmd_Info"); register_srvcmd("vipm_modules", "@SrvCmd_Modules"); - register_srvcmd("vipm_module_params", "@SrvCmd_ModuleParams"); register_srvcmd("vipm_limits", "@SrvCmd_Limits"); - register_srvcmd("vipm_limit_params", "@SrvCmd_LimitParams"); } @SrvCmd_Info() { @@ -79,23 +77,6 @@ SrvCmds_Init() { return PLUGIN_HANDLED; } -@SrvCmd_ModuleParams() { - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - read_argv(1, sModuleTypeName, charsmax(sModuleTypeName)); - - new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); - if (iModuleType == Invalid_ModuleType) { - server_print("Module type '%s' not found.", sModuleTypeName); - return PLUGIN_HANDLED; - } - - new Array:aParams = ModuleType_GetParams(iModuleType); - PrintConfigParams(aParams); - ArrayDestroy(aParams); - - return PLUGIN_HANDLED; -} - @SrvCmd_Limits() { server_print("╔═════╤══════════════════════════════════╤════════╤════════╤════════════╗"); server_print("║ # │ Limit name │ Params │ Static │ For player ║"); @@ -118,40 +99,3 @@ SrvCmds_Init() { return PLUGIN_HANDLED; } - -@SrvCmd_LimitParams() { - enum {Arg_sLimitTypeName = 1} - - new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - read_argv(Arg_sLimitTypeName, sLimitTypeName, charsmax(sLimitTypeName)); - - new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); - if (iLimitType == Invalid_LimitType) { - server_print("Limit type '%s' not found.", sLimitTypeName); - return PLUGIN_HANDLED; - } - - new Array:aLimitTypeParams = LimitType_GetParams(iLimitType); - PrintConfigParams(aLimitTypeParams); - ArrayDestroy(aLimitTypeParams); - - return PLUGIN_HANDLED; -} - -static PrintConfigParams(const Array:aParams) { - server_print("╔═════╤══════════════════════════════════╤══════════╤══════════╗"); - server_print("║ # │ Param name │ Type │ Required ║"); - server_print("╟─────┼──────────────────────────────────┼──────────┼──────────╢"); - - ArrayForeachArray2 (aParams: i => Param[S_CfgParam]) { - server_print("║ %3d │ %-32s │ %-8s │ %-8s ║", - i + 1, Param[CfgParam_Name], - VIPM_PARAM_TYPE_NAMES[Param[CfgParam_Type]], - Param[CfgParam_Required] ? "Yes" : "No" - ); - } - - server_print("╟─────┴──────────────────────────────────┴──────────┴──────────╢"); - server_print("║ Total: %-5d ║", ArraySizeSafe(aParams)); - server_print("╚══════════════════════════════════════════════════════════════╝"); -} diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index eb3648c..ff7c238 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -54,6 +54,17 @@ enum E_ItemTypeEvent{ * Примечание: Если возвращено IC_RET_GIVE_FAIL, предмет не будет считаться выданным (Натив IC_Item_Give вернёт false). */ ItemType_OnGive, + + /* + * Описание: Вызывается, при освобождении хендлера предмета. + * Возв. тип: void + * Параметры: (const T_IC_Item:item, const Trie:p): + * item - Хендлер предмета. + * p - key-value хранилище параметров. + * + * // TODO + */ + ItemType_OnFree, } /** diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index 773b352..a7cfb33 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -44,12 +44,12 @@ enum E_ModuleEvent{ * * Примечание: Результат обьединения должен быть возвращён обработчиком события. * - * УСТАРЕЛО! Позже будет добавлен другой механизм подобный этому. + * УСТАРЕЛО! Используйте Module_OnMergeParams. */ Module_OnCompareParams, /* - * Описание: Вызывается при добавлении игроку второго модуля того же типа. + * Описание: Вызывается при добавлении игроку второго и последующих модулей одного типа. * Возв. тип: Trie * Параметры: (const Trie:tParams1, const Trie:tParams2): * tParams1 - Первый набор параметров. @@ -58,7 +58,7 @@ enum E_ModuleEvent{ * Примечание: Если обработчик для этого события не зарегистрирован, * всегда будет выбираться tParams1 (модуль, добавленный первым) без изменений. * - * Примечание: Очищение пришедших в параметрах Trie вызовет ошибки в работе модулей. + * Примечание: Очищение/изменение пришедших в параметрах Trie вызовет ошибки в работе модулей. * * Примечание: Обработчик может вернуть один из полученных Trie или создать новый. * При содании нового Trie ядро само позаботится о его очищении в будущем. @@ -66,19 +66,10 @@ enum E_ModuleEvent{ Module_OnMergeParams, } -/** - * Вызывается . - * - * @param moduleName Название модуля. - * - * @return VIPM_CONTINUE - модуль будет активирован, VIPM_STOP - */ -forward VipM_Modules_OnActivate(const moduleName[]); - /** * Вызывается перед активацией модуля. * - * @param moduleName Название модуля. + * @param moduleName Название модуля. * * @return VIPM_CONTINUE - модуль будет активирован, VIPM_STOP - активация модуля будет прервана. */ @@ -87,29 +78,29 @@ forward VipM_Modules_OnActivate(const moduleName[]); /** * Регистрирует новый модуль. * - * @param Module Название модуля. - * @param Once Обьединять ли параметры элементов модуля. true - Нет, false - Да. Подразумевает использование события OnCompareParams. + * @param moduleName Название модуля. + * @param Once Обьединять ли параметры элементов модуля. true - Нет, false - Да. Подразумевает использование события OnCompareParams. * * @noreturn */ -native VipM_Modules_Register(const Module[], const bool:Once = true); +native VipM_Modules_Register(const moduleName[], const bool:Once = true); /** * Регистрирует обработчик события для указанного модуля. * - * @param Module Название модуля. - * @param Event Событие. - * @param Func Название функции-обработчика. + * @param moduleName Название модуля. + * @param event Событие. + * @param func Название функции-обработчика. * * @return Вернёт true, если обработчик успешно зарегистрирован. */ -native bool:VipM_Modules_RegisterEvent(const Module[], const E_ModuleEvent:Event, const Func[]); +native bool:VipM_Modules_RegisterEvent(const moduleName[], const E_ModuleEvent:event, const func[]); /** * Добавляет набор параметров для указанного модуля. * - * @param Module Название модуля. - * @param any:... Перечисление параметров. + * @param moduleName Название модуля. + * @param any:... Перечисление параметров. * * @note Формат указания параметров: VipM_Modules_AddParams(..., const ParamName[], const E_ParamType:ParamType, const bool:ParamRequired, ...); * @note ParamName - Название параметра / ParamType - Тип параметра / ParamRequired - Обязателен ли параметр. @@ -117,7 +108,31 @@ native bool:VipM_Modules_RegisterEvent(const Module[], const E_ModuleEvent:Event * * @noreturn */ -native VipM_Modules_AddParams(const Module[], const any:...); +native VipM_Modules_AddParams(const moduleName[], const any:...); + +/** + * Добавляет параметры для модуля. + * + * @param moduleName Название модуля. + * @param any:... Перечисление параметров. + * + * @note Формат перечисления параметров: + * VipM_Modules_AddParamsEx(..., const paramName[], const paramType[], const bool:paramRequired, ...); + * + * Где: + * - paramName - Название параметра; + * - paramType - Название типа параметра; + * - paramRequired - Обязателен ли параметр. + * + * Пример: + * VipM_Modules_AddParamsEx(module, + * "Param1", "String", true, + * "Param2", "Integer", false + * ); + * + * @noreturn + */ +native VipM_Modules_AddParamsEx(const moduleName[], const any:...); /** * Активен ли указанный модуль. From 6719a00633587423e66871d29b331f8c300a592c Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 7 Sep 2025 02:03:09 +0300 Subject: [PATCH 059/108] Reg params by AddParamsEx in all modules --- amxmodx/scripting/VipM-L-Default.sma | 2 ++ amxmodx/scripting/VipM-M-SpawnHealth.sma | 24 +++++++++--------- amxmodx/scripting/VipM-M-SpawnItems.sma | 15 +++--------- amxmodx/scripting/VipM-M-Vampire.sma | 18 +++++++------- amxmodx/scripting/VipM-M-VipInTab.sma | 8 +++--- amxmodx/scripting/VipM-M-WeaponMenu.sma | 31 ++++++++++++------------ 6 files changed, 46 insertions(+), 52 deletions(-) diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index b3737f8..160c1af 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -34,6 +34,8 @@ public plugin_natives() { } } +// TODO: AddParamsEx +// TODO: Move to core plugin public VipM_Limits_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index c1f30a4..5ab2a5d 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -19,20 +19,20 @@ new const MODULE_NAME[] = "SpawnHealth"; public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); - VipM_Modules_Register(MODULE_NAME, true); - VipM_Modules_AddParams(MODULE_NAME, - "Health", ptInteger, false, - "SetHealth", ptBoolean, false, - "MaxHealth", ptInteger, false + VipM_Modules_Register(MODULE_NAME); + VipM_Modules_AddParamsEx(MODULE_NAME, + "Health", "Integer", false, + "SetHealth", "Boolean", false, + "MaxHealth", "Integer", false ); - VipM_Modules_AddParams(MODULE_NAME, - "Armor", ptInteger, false, - "SetArmor", ptBoolean, false, - "MaxArmor", ptInteger, false + VipM_Modules_AddParamsEx(MODULE_NAME, + "Armor", "Integer", false, + "SetArmor", "Boolean", false, + "MaxArmor", "Integer", false ); - VipM_Modules_AddParams(MODULE_NAME, - "Helmet", ptBoolean, false, - "Limits", ptLimits, false + VipM_Modules_AddParamsEx(MODULE_NAME, + "Helmet", "Boolean", false, + "Limits", "VipM-Limits", false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index 88ad7eb..c2ccbf5 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -21,21 +21,14 @@ public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); IC_Init(); - VipM_Modules_Register(MODULE_NAME, true); - VipM_Modules_AddParams(MODULE_NAME, - "Items", ptCustom, false, - "Limits", ptLimits, false + VipM_Modules_Register(MODULE_NAME); + VipM_Modules_AddParamsEx(MODULE_NAME, + "Items", "IC-Items", true, + "Limits", "VipM-Limits", false ); - VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnRead, "@OnReadConfig"); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } -@OnReadConfig(const JSON:jCfg, Trie:Params) { - TrieSetCell(Params, "Items", PCSingle_ObjIcItems(jCfg, "Items", .orFail = true)); - - return VIPM_CONTINUE; -} - @OnModuleActivate() { RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawned", true); } diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index 8d14f6d..c70b077 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -18,16 +18,16 @@ public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_dictionary("VipM-Vampire.ini"); - VipM_Modules_Register(MODULE_NAME, true); - VipM_Modules_AddParams(MODULE_NAME, - "MaxHealth", ptInteger, false, - "ByKill", ptInteger, false, - "ByHead", ptInteger, false, - "ByKnife", ptInteger, false, - "ByGrenade", ptInteger, false + VipM_Modules_Register(MODULE_NAME); + VipM_Modules_AddParamsEx(MODULE_NAME, + "MaxHealth", "Integer", false, + "ByKill", "Integer", false, + "ByHead", "Integer", false, + "ByKnife", "Integer", false, + "ByGrenade", "Integer", false ); - VipM_Modules_AddParams(MODULE_NAME, - "Limits", ptLimits, false + VipM_Modules_AddParamsEx(MODULE_NAME, + "Limits", "VipM-Limits", false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index c94a04e..1541cb7 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -23,10 +23,10 @@ new bool:gHasTag[MAX_PLAYERS + 1][E_ModuleParams]; public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); - VipM_Modules_Register(MODULE_NAME, true); - VipM_Modules_AddParams(MODULE_NAME, - "Enabled", ptBoolean, true, - "Override", ptBoolean, false + VipM_Modules_Register(MODULE_NAME); + VipM_Modules_AddParamsEx(MODULE_NAME, + "Enabled", "Boolean", true, + "Override", "Boolean", false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index f73c05d..ae1c61d 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -1,6 +1,7 @@ #include #include #include +#include #include "VipM/Utils" #include "VipM/DebugMode" @@ -35,24 +36,22 @@ public VipM_Modules_OnInited() { register_dictionary("VipM-WeaponMenu.ini"); IC_Init(); - VipM_Modules_Register(MODULE_NAME, true); - VipM_Modules_AddParams(MODULE_NAME, - "MainMenuTitle", ptString, false, - "Menus", ptCustom, true, - "Count", ptInteger, false + VipM_Modules_Register(MODULE_NAME); + VipM_Modules_AddParamsEx(MODULE_NAME, + // TODO Read "Menus" as param + "MainMenuTitle", "String", false, + "Count", "Integer", false, + "Limits", "VipM-Limits", false ); - VipM_Modules_AddParams(MODULE_NAME, - "Limits", ptLimits, false + VipM_Modules_AddParamsEx(MODULE_NAME, + "AutoopenLimits", "VipM-Limits", false, + "AutoopenDelay", "Float", false, + "AutoopenCloseDelay", "Float", false, + "AutoopenMenuNum", "Integer", false ); - VipM_Modules_AddParams(MODULE_NAME, - "AutoopenLimits", ptLimits, false, - "AutoopenDelay", ptFloat, false, - "AutoopenCloseDelay", ptFloat, false, - "AutoopenMenuNum", ptInteger, false - ); - VipM_Modules_AddParams(MODULE_NAME, - "StayOpen", ptBoolean, false, - "StayOpen_CheckCounter", ptBoolean, false + VipM_Modules_AddParamsEx(MODULE_NAME, + "StayOpen", "Boolean", false, + "StayOpen_CheckCounter", "Boolean", false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnRead, "@OnReadConfig"); From 24987dc7da8f0cdd06779631d45e4f66c0a544e1 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 7 Sep 2025 13:14:25 +0300 Subject: [PATCH 060/108] Move "If" iteom type to core --- README.md | 5 ---- amxmodx/scripting/ItemsController.sma | 2 +- .../DefaultObjects/ItemType/If.inc} | 24 +++++++++++-------- .../DefaultObjects/Registrar.inc | 16 +++++++++++++ 4 files changed, 31 insertions(+), 16 deletions(-) rename amxmodx/scripting/{IC-I-Limits.sma => ItemsController/DefaultObjects/ItemType/If.inc} (60%) diff --git a/README.md b/README.md index 3fc5e01..3d192a3 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,8 @@ | :-------------------------------- | :---------------------------------------------------------- | | `vipm_update_users` | Обновляет привилегии у всех игроков | | `vipm_info` | Выводит информацию о системе привилегий | -| | | | `vipm_modules` | Выводит таблицу модулей и их статусов | -| `vipm_module_params ` | Выводит таблицу параметров указанного модуля | -| | | | `vipm_limits` | Выводит таблицу типов проверок и некоторую информацию о них | -| `vipm_limit_params ` | Выводит таблицу параметров указанного типа проверки | -| | | | `ic_item_types` | Выводит таблицу типов предметов | ## Идеи diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index 18ef483..a7a1f4e 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -49,7 +49,7 @@ public plugin_natives() { } @NativeFilter(const name[], index, trap) { - if (DefaultObjects_ItemType_CustomWeapon_NativeFilter(name, trap)) { + if (DefaultObjects_HandleNativeFilter(name, trap)) { return PLUGIN_HANDLED; } diff --git a/amxmodx/scripting/IC-I-Limits.sma b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc similarity index 60% rename from amxmodx/scripting/IC-I-Limits.sma rename to amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc index 7582dc4..47f5c5f 100644 --- a/amxmodx/scripting/IC-I-Limits.sma +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc @@ -1,18 +1,14 @@ #include -#include +#include +#include #include #include #include -#include "VipM/Utils" -public stock const PluginName[] = "[IC-I] Limits"; -public stock const PluginVersion[] = IC_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = "https://github.com/ArKaNeMaN/amxx-VipModular-pub"; -public stock const PluginDescription[] = "[ItemsController-Item] Items using limits."; - -public IC_ItemType_OnInited() { - register_plugin(PluginName, PluginVersion, PluginAuthor); +DefaultObjects_ItemType_If_Register() { + if (!LibraryExists(VIPM_LIBRARY, LibType_Library)) { + return; + } new T_IC_ItemType:type = IC_ItemType_SimpleRegister( .name = "If", @@ -32,3 +28,11 @@ public IC_ItemType_OnInited() { return PCGet_IcItemsGive(p, "Items", playerIndex) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } + +bool:DefaultObjects_ItemType_If_NativeFilter(const name[]) { + if (equal(name, "VipM_Limits_ExecuteList")) { + return true; + } + + return false; +} diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc index a546c6d..a6baa4b 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc @@ -1,5 +1,19 @@ #include +DefaultObjects_HandleNativeFilter(const name[], const trap) { + new ret = false; + + if (DefaultObjects_ItemType_CustomWeapon_NativeFilter(name, trap)) { + ret = true; + } + + if (DefaultObjects_ItemType_If_NativeFilter(name)) { + ret = true; + } + + return ret; +} + #include "ItemsController/DefaultObjects/ItemType/Armor" #include "ItemsController/DefaultObjects/ItemType/Command" #include "ItemsController/DefaultObjects/ItemType/DamageMult" @@ -15,6 +29,7 @@ #include "ItemsController/DefaultObjects/ItemType/Weapon" #include "ItemsController/DefaultObjects/ItemType/CustomWeapon" #include "ItemsController/DefaultObjects/ItemType/Function" +#include "ItemsController/DefaultObjects/ItemType/If" public IC_ItemType_OnInited() { // Затычка для тех мест, где при отсутствии предметов вылезает ошибка/варн @@ -35,6 +50,7 @@ public IC_ItemType_OnInited() { DefaultObjects_ItemType_Weapon_Register(); DefaultObjects_ItemType_CustomWeapon_Register(); DefaultObjects_ItemType_Function_Register(); + DefaultObjects_ItemType_If_Register(); } #include "ItemsController/DefaultObjects/ParamType/Item" From 5dd882eae6e7b30de5932c85907fb782df6b7f13 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 7 Sep 2025 13:43:32 +0300 Subject: [PATCH 061/108] Fix vampire module --- amxmodx/scripting/VipM-M-Vampire.sma | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index c70b077..4ea104c 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -20,13 +20,13 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "MaxHealth", "Integer", false, "ByKill", "Integer", false, "ByHead", "Integer", false, "ByKnife", "Integer", false, "ByGrenade", "Integer", false ); VipM_Modules_AddParamsEx(MODULE_NAME, + "MaxHealth", "Integer", false, "Limits", "VipM-Limits", false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); From 01710517a93b459e731b8aee9e768ca996e18aa3 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 7 Sep 2025 23:03:44 +0300 Subject: [PATCH 062/108] Fix vip's access check --- amxmodx/scripting/VipM-M-SpawnItems.sma | 3 + .../VipM/Core/Objects/Limits/Type.inc | 7 ++ .../VipM/Core/Objects/Limits/Unit.inc | 79 +++++++++---------- .../scripting/VipM/Core/Objects/VipUnit.inc | 32 +++----- amxmodx/scripting/VipM/Core/VipsManager.inc | 44 +++++++---- .../VipM/DefaultObjects/ParamType/Limits.inc | 14 ++-- amxmodx/scripting/include/VipM/Limits.inc | 8 ++ 7 files changed, 96 insertions(+), 91 deletions(-) diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index c2ccbf5..ab64b02 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -34,15 +34,18 @@ public VipM_Modules_OnInited() { } @OnPlayerSpawned(const UserId) { + Dbg_Log("@OnPlayerSpawned(%n) Spawned, request frame", UserId); RequestFrame("@GivePlayerItems", UserId); } @GivePlayerItems(const UserId) { if (!is_user_alive(UserId)) { + Dbg_Log("@GivePlayerItems(%n) Dead", UserId); return; } if (!VipM_Modules_HasModule(MODULE_NAME, UserId)) { + Dbg_Log("@GivePlayerItems(%n) Has not module", UserId); return; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 726c005..15fdcb1 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -176,6 +176,13 @@ static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, co return -1; } +bool:LimitType_IsStatic(const T_LimitType:type) { + new LimitType[S_LimitType]; + LimitType__Get(type, LimitType); + + return LimitType[LimitType_Static]; +} + LimitType_SetStaticValue(const T_LimitType:type, const bool:bValue, const UserId = 0) { new LimitType[S_LimitType]; LimitType__Get(type, LimitType); diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 180aada..c239543 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -35,7 +35,7 @@ LimitUnit_GetCount() { return ArraySizeSafe(g_aLimitUnits); } -static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie:tParams) { +static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie:params) { if (g_aLimitUnits == Invalid_Array) { abort(AMX_ERR_GENERAL, "Attempt to create limit unit before init."); return Invalid_LimitUnit; @@ -44,7 +44,7 @@ static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie new LimitUnit[S_LimitUnit]; LimitUnit[LimitUnit_Type] = iLimitType; - LimitUnit[LimitUnit_Params] = tParams; + LimitUnit[LimitUnit_Params] = params; return T_LimitUnit:ArrayPushArray(g_aLimitUnits, LimitUnit); } @@ -62,24 +62,24 @@ static bool:LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit], return true; } -static T_LimitType:LimitUnit__ReadType(const JSON:jLimitUnit) { - new sLimitTypeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - PCSingle_ObjString(jLimitUnit, "Limit", sLimitTypeName, charsmax(sLimitTypeName)); - trim(sLimitTypeName); +static T_LimitType:LimitUnit__ReadType(const JSON:limitJson) { + new typeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + PCSingle_ObjString(limitJson, "Limit", typeName, charsmax(typeName)); + trim(typeName); - if (!sLimitTypeName[0]) { - PCJson_ErrorForFile(jLimitUnit, "Limit type name not specified."); + if (!typeName[0]) { + PCJson_ErrorForFile(limitJson, "Limit type name not specified."); return Invalid_LimitType; } - new T_LimitType:iLimitType = LimitType_Find(sLimitTypeName); + new T_LimitType:type = LimitType_Find(typeName); - if (iLimitType == Invalid_LimitType) { - PCJson_ErrorForFile(jLimitUnit, "Limit type '%s' not found.", sLimitTypeName); + if (type == Invalid_LimitType) { + PCJson_ErrorForFile(limitJson, "Limit type '%s' not found.", typeName); return Invalid_LimitType; } - return iLimitType; + return type; } T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { @@ -97,13 +97,16 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { return Invalid_LimitUnit; } - new Trie:p = LimitType_ReadParams(type, linked); - if (p == Invalid_Trie) { - PCJson_FreeLinked(linked); - return Invalid_LimitUnit; + new Trie:params = Invalid_Trie; + if (!LimitType_IsStatic(type)) { + params = LimitType_ReadParams(type, linked); + if (params == Invalid_Trie) { + PCJson_FreeLinked(linked); + return Invalid_LimitUnit; + } } - cached = LimitUnit__Construct(type, p); + cached = LimitUnit__Construct(type, params); if (linkPath[0] != EOS && cached != Invalid_LimitUnit) { TrieSetCell(cache, linkPath, cached); } @@ -112,39 +115,29 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { return cached; } -Array:LimitUnit_ReadList(const JSON:jLimitUnits, &Array:aLimitUnits = Invalid_Array) { - ArrayCreateIfNotCreated(aLimitUnits); +Array:LimitUnit_ReadList(const JSON:limitsJson, &Array:limits = Invalid_Array) { + if (limits == Invalid_Array) { + limits = ArrayCreate(1, 1); + } - if (!json_is_array(jLimitUnits)) { - new T_LimitUnit:iLimitUnit = LimitUnit_Read(jLimitUnits); - if (iLimitUnit != Invalid_LimitUnit) { - ArrayPushCell(aLimitUnits, iLimitUnit); + if (!json_is_array(limitsJson)) { + new T_LimitUnit:limit = LimitUnit_Read(limitsJson); + if (limit != Invalid_LimitUnit) { + ArrayPushCell(limits, limit); } } else { - json_array_foreach_value (jLimitUnits: i => jLimitUnit) { - aLimitUnits = LimitUnit_ReadList(jLimitUnit, aLimitUnits); - json_free(jLimitUnit); + json_array_foreach_value (limitsJson: i => limitJson) { + limits = LimitUnit_ReadList(limitJson, limits); + json_free(limitJson); } } - return aLimitUnits; -} - -Array:JsonObject_GetLimitUnits(const JSON:jObj, const sKey[], const bool:bDotNot = false, &Array:aLimitUnits = Invalid_Array) { - if (!json_object_has_value(jObj, sKey, .dot_not = bDotNot)) { - return aLimitUnits; - } - - new JSON:jLimitUnits = json_object_get_value(jObj, sKey, bDotNot); - aLimitUnits = LimitUnit_ReadList(jLimitUnits, aLimitUnits); - json_free(jLimitUnits); - - return aLimitUnits; + return limits; } -bool:LimitUnit_Execute(const T_LimitUnit:iLimitUnit, const UserId = 0) { +bool:LimitUnit_Execute(const T_LimitUnit:limit, const UserId = 0) { new LimitUnit[S_LimitUnit]; - LimitUnit__Get(iLimitUnit, LimitUnit); + LimitUnit__Get(limit, LimitUnit); return LimitType_Execute(LimitUnit[LimitUnit_Type], LimitUnit[LimitUnit_Params], UserId); } @@ -157,8 +150,8 @@ bool:LimitUnit_ExecuteList( new bool:bXor = false; for (new i = 0, ii = ArraySizeSafe(aLimitUnits); i < ii; ++i) { - new T_LimitUnit:iLimitUnit = T_LimitUnit:ArrayGetCell(aLimitUnits, i); - new bool:bRes = LimitUnit_Execute(iLimitUnit, UserId); + new T_LimitUnit:limit = T_LimitUnit:ArrayGetCell(aLimitUnits, i); + new bool:bRes = LimitUnit_Execute(limit, UserId); switch (iOperator) { case Limit_Exec_OR: { diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index 2902351..03a43de 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -53,33 +53,21 @@ static T_VipUnit:VipUnit__Construct( return T_VipUnit:ArrayPushArray(g_aVipUnits, VipUnit); } -// static VipUnit__Get(const T_LimitUnit:iVipUnit, VipUnit[S_VipUnit], const bool:bOrFail = true) { -// if (_:iVipUnit < 0 || _:iVipUnit >= VipUnit_GetCount()) { -// if (bOrFail) { -// abort(0, "Invalid vip unit index (%d).", iVipUnit); -// } - -// return false; -// } - -// ArrayGetArray(g_aVipUnits, _:iVipUnit, VipUnit); -// return true; -// } - static any:VipUnit__GetValue(const T_VipUnit:iVipUnit, const iCell) { return ArrayGetCell(g_aVipUnits, _:iVipUnit, iCell); } -VipUnit_CheckUserAccess(const T_VipUnit:iVipUnit, const UserId) { - return LimitUnit_ExecuteList( - VipUnit__GetValue(iVipUnit, VipUnit_Access), - UserId, - Limit_Exec_OR - ); +VipUnit_CheckUserAccess(const T_VipUnit:vip, const playerIndex) { + Dbg_Log("VipUnit_CheckUserAccess(%d, %n) start", vip, playerIndex); + + new Array:limits = VipUnit__GetValue(vip, VipUnit_Access); + Dbg_Log("VipUnit_CheckUserAccess(%d, %n) limits = %d (side: %d)", vip, playerIndex, limits, ArraySizeSafe(limits)); + + return VipM_Limits_ExecuteList(limits, playerIndex, Limit_Exec_OR); } -Array:VipUnit_GetModules(const T_VipUnit:iVipUnit) { - return VipUnit__GetValue(iVipUnit, VipUnit_Modules); +Array:VipUnit_GetModules(const T_VipUnit:vip) { + return VipUnit__GetValue(vip, VipUnit_Modules); } T_VipUnit:VipUnit_Read(const JSON:valueJson) { @@ -91,7 +79,7 @@ T_VipUnit:VipUnit_Read(const JSON:valueJson) { return cached; } - new Array:aAccess = JsonObject_GetLimitUnits(linked, "Access"); + new Array:aAccess = PCSingle_VipmLimits(linked, "Access"); if (aAccess == Invalid_Array) { PCJson_ErrorForFile(linked, "Field 'Access' is required in vip object."); PCJson_FreeLinked(linked); diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc index fd35f46..5ba545e 100644 --- a/amxmodx/scripting/VipM/Core/VipsManager.inc +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -71,36 +71,46 @@ bool:VipsManager_LoadFromFolder(sFolderPath[]) { return true; } -VipsManager_UserReload(const UserId) { - VipsManager_UserReset(UserId); +VipsManager_UserReload(const playerIndex) { + VipsManager_UserReset(playerIndex); + + Dbg_Log("VipsManager_UserReload(%n) start", playerIndex); - g_tUserModules[UserId] = TrieCreate(); + g_tUserModules[playerIndex] = TrieCreate(); for (new i = 0, ii = ArraySize(g_aVips); i < ii; ++i) { - new T_VipUnit:iVipUnit = ArrayGetCell(g_aVips, i); - if (!VipUnit_CheckUserAccess(iVipUnit, UserId)) { + Dbg_Log("VipsManager_UserReload(%n) - vip #%d", playerIndex, i); + + new T_VipUnit:vip = ArrayGetCell(g_aVips, i); + if (!VipUnit_CheckUserAccess(vip, playerIndex)) { + Dbg_Log("VipsManager_UserReload(%n) - - no access", playerIndex); continue; } + Dbg_Log("VipsManager_UserReload(%n) - - has access", playerIndex); - new Array:aModuleUnits = VipUnit_GetModules(iVipUnit); - for (new j = 0, jj = ArraySize(aModuleUnits); j < jj; ++j) { - new T_ModuleUnit:iModuleUnit = ArrayGetCell(aModuleUnits, j); + new Array:modules = VipUnit_GetModules(vip); + for (new j = 0, jj = ArraySize(modules); j < jj; ++j) { + new T_ModuleUnit:module = ArrayGetCell(modules, j); - new sModuleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; // TODO: Посмотреть можно ли юзать просто хендлер - ModuleUnit_GetTypeName(iModuleUnit, sModuleName, charsmax(sModuleName)); + new moduleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; // TODO: Посмотреть можно ли юзать просто хендлер + ModuleUnit_GetTypeName(module, moduleName, charsmax(moduleName)); + + Dbg_Log("VipsManager_UserReload(%n) - - - module %s (#%d)", playerIndex, moduleName, j); - new Trie:tParams = ModuleUnit_GetParams(iModuleUnit); - if (TrieKeyExists(g_tUserModules[UserId], sModuleName)) { - new Trie:tOldParams; - TrieGetCell(g_tUserModules[UserId], sModuleName, tOldParams); + new Trie:params = ModuleUnit_GetParams(module); + if (TrieKeyExists(g_tUserModules[playerIndex], moduleName)) { + Dbg_Log("VipsManager_UserReload(%n) - - - - merge", playerIndex); + new Trie:oldParams; + TrieGetCell(g_tUserModules[playerIndex], moduleName, oldParams); - TrieSetCell(g_tUserModules[UserId], sModuleName, ModuleUnit_Merge(iModuleUnit, tOldParams, tParams)); + TrieSetCell(g_tUserModules[playerIndex], moduleName, ModuleUnit_Merge(module, oldParams, params)); } else { - TrieSetCell(g_tUserModules[UserId], sModuleName, tParams); + Dbg_Log("VipsManager_UserReload(%n) - - - - add", playerIndex); + TrieSetCell(g_tUserModules[playerIndex], moduleName, params); } } } - Forwards_CallP("VipM_OnUserUpdated", UserId); + Forwards_CallP("VipM_OnUserUpdated", playerIndex); } VipsManager_UserReset(const UserId) { diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc index 4869c24..c846d87 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc @@ -8,19 +8,15 @@ DefaultObjects_ParamType_Limits_Register() { } @OnLimitsParamTypeRead(const JSON:valueJson) { - new Array:limits = VipM_Limits_ReadListFromJson(valueJson); - - if (limits == Invalid_Array) { + if (json_is_array(valueJson) && json_array_get_count(valueJson) < 1) { + PCJson_LogForFile(valueJson, "WARNING", "Limits array is empty."); return false; } - if ( - ( - json_is_object(valueJson) - || (json_is_array(valueJson) && json_array_get_count(valueJson) == 0) - ) && ArraySize(limits) < 1 - ) { + new Array:limits = VipM_Limits_ReadListFromJson(valueJson); + if (limits == Invalid_Array || ArraySize(limits) < 1) { PCJson_LogForFile(valueJson, "WARNING", "All limits are invalid."); + ArrayDestroy(limits); return false; } diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index d38e0e6..d01381f 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -218,3 +218,11 @@ stock bool:PCGet_VipmLimitsCheck(const Trie:p, const key[], const playerIndex = return VipM_Limits_ExecuteList(limits, playerIndex, type); } + +stock T_LimitUnit:PCSingle_VipmLimit(const JSON:objectJson, const key[], const T_LimitUnit:def = Invalid_LimitUnit, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, VIPM_PARAM_TYPE_LIMIT_NAME, def, dotNot, orFail); +} + +stock Array:PCSingle_VipmLimits(const JSON:objectJson, const key[], const Array:def = Invalid_Array, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, VIPM_PARAM_TYPE_LIMITS_NAME, def, dotNot, orFail); +} From cd8b189c181d596a6dd5300b7f0620a282dc686f Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 14 Sep 2025 13:04:01 +0300 Subject: [PATCH 063/108] Use `ChatMessage` param type from new PC version --- README.md | 2 +- .../Objects/Items/Instance.inc | 1 - amxmodx/scripting/VipM/Core/API/Main.inc | 1 - .../scripting/VipM/Core/Objects/VipUnit.inc | 1 - amxmodx/scripting/VipM/Core/VipsManager.inc | 1 - amxmodx/scripting/VipM/JsonUtils.inc | 66 ------------------- amxmodx/scripting/VipM/Utils.inc | 1 - .../VipM/WeaponMenu/Objects/MenuItem.inc | 1 - .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 3 +- 9 files changed, 2 insertions(+), 75 deletions(-) delete mode 100644 amxmodx/scripting/VipM/JsonUtils.inc diff --git a/README.md b/README.md index 3d192a3..b6de6b5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Требования -- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.1.2](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.1.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.2.0](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.2.0) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). - [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). - [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc index 5110a7c..584afee 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc @@ -9,7 +9,6 @@ #include #include "VipM/Forwards" #include "VipM/Utils" -#include "VipM/JsonUtils" #include "ItemsController/Objects/Items/Type" diff --git a/amxmodx/scripting/VipM/Core/API/Main.inc b/amxmodx/scripting/VipM/Core/API/Main.inc index 57295fd..7d5efd9 100644 --- a/amxmodx/scripting/VipM/Core/API/Main.inc +++ b/amxmodx/scripting/VipM/Core/API/Main.inc @@ -1,6 +1,5 @@ #include #include "VipM/Utils" -#include "VipM/JsonUtils" #include "VipM/Core/VipsManager" API_Main_Init() { diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index 03a43de..2c05e13 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -7,7 +7,6 @@ #include #include "VipM/Utils" #include "VipM/ArrayTrieUtils" -#include "VipM/JsonUtils" #include "VipM/Core/Objects/Modules/Unit" #include "VipM/Core/Objects/Limits/Unit" diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc index 5ba545e..92730a0 100644 --- a/amxmodx/scripting/VipM/Core/VipsManager.inc +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -7,7 +7,6 @@ #include #include "VipM/Forwards" #include "VipM/ArrayTrieUtils" -#include "VipM/JsonUtils" #include "VipM/Core/Objects/VipUnit" static Array:g_aVips = Invalid_Array; // T_VipUnit[] diff --git a/amxmodx/scripting/VipM/JsonUtils.inc b/amxmodx/scripting/VipM/JsonUtils.inc deleted file mode 100644 index 64bd318..0000000 --- a/amxmodx/scripting/VipM/JsonUtils.inc +++ /dev/null @@ -1,66 +0,0 @@ -#if defined __UTILS_JsonUtils_included - #endinput -#endif -#define __UTILS_JsonUtils_included - -#include -#include -#include - -#define JSON_UTILS__MAX_KEY_LENGTH PARAM_KEY_MAX_LEN -#define JSON_UTILS__MAX_STRING_LENGTH PARAM_VALUE_MAX_LEN - -// deprecated -// Все параметры надо указывать явно -stock Trie:Json_ReadObjectToTrie(const JSON:jObject, &Trie:tTrie = Invalid_Trie) { - if (tTrie == Invalid_Trie) { - tTrie = TrieCreate(); - } - - if (!json_is_object(jObject)) { - // А надо ли ошибку бросать? - PCJson_ErrorForFile(jObject, "Json_ReadObjectToTrie: JSON-value must be an object."); - return tTrie; - } - - new sKey[JSON_UTILS__MAX_KEY_LENGTH]; - for (new i = 0; i < json_object_get_count(jObject); i++) { - json_object_get_name(jObject, i, sKey, charsmax(sKey)); - new JSON:jValue = json_object_get_value_at(jObject, i); - - switch (json_get_type(jValue)) { - case JSONString: { - new sValue[JSON_UTILS__MAX_STRING_LENGTH]; - json_get_string(jValue, sValue, charsmax(sValue)); - TrieSetString(tTrie, sKey, sValue); - } - - case JSONNumber: - TrieSetCell(tTrie, sKey, json_get_number(jValue)); - - case JSONBoolean: - TrieSetCell(tTrie, sKey, json_get_bool(jValue)); - } - json_free(jValue); - } - - return tTrie; -} - -// TODO: Перенести в контроллер параметров -stock Json_Object_GetColoredChatMessage( - const JSON:jObj, - const sKey[], - sOut[], - const iOutLen, - const sDefault[] = "", - const bool:bDotNot = false -) { - new iRes = PCSingle_ObjString(jObj, sKey, sOut, iOutLen, sDefault, bDotNot); - - iRes -= replace_all(sOut, iOutLen, "^^1", "^1"); - iRes -= replace_all(sOut, iOutLen, "^^3", "^3"); - iRes -= replace_all(sOut, iOutLen, "^^4", "^4"); - - return iRes; -} diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 3aac7ea..74ca1f7 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -5,7 +5,6 @@ // Надо наверное как-то их обьединить) #include "VipM/ArrayTrieUtils" -#include "VipM/JsonUtils" #include #include diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 9b8a0ff..f671573 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -6,7 +6,6 @@ #include #include #include -#include "VipM/JsonUtils" enum MenuItemType { MenuItemType_Default = 0, diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 555ba00..216069e 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -7,7 +7,6 @@ #include #include #include -#include "VipM/JsonUtils" #include "VipM/WeaponMenu/Objects/MenuItem" @@ -30,7 +29,7 @@ enum _:S_WeaponMenu { bool:WeaponMenu_Read(const JSON:menuJson, Menu[S_WeaponMenu]) { PCSingle_ObjString(menuJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); - if (Json_Object_GetColoredChatMessage( + if (PCSingle_ObjChatMessage( menuJson, "FakeMessage", Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]) )) { From b033c332420f2473a83dbe1ec39ba6b2720b17d8 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 21 Sep 2025 01:53:52 +0300 Subject: [PATCH 064/108] Move some limits to vipm core --- amxmodx/scripting/VipM-L-Default.sma | 333 ------------------ .../VipM/DefaultObjects/Limit/Always.inc | 9 + .../VipM/DefaultObjects/Limit/GameTime.inc | 30 ++ .../DefaultObjects/Limit/InFreezyTime.inc | 16 + .../VipM/DefaultObjects/Limit/Ip.inc | 24 ++ .../VipM/DefaultObjects/Limit/Logic.inc | 44 +++ .../VipM/DefaultObjects/Limit/Name.inc | 16 + .../VipM/DefaultObjects/Limit/Never.inc | 7 + .../VipM/DefaultObjects/Limit/OncePer.inc | 76 ++++ .../VipM/DefaultObjects/Limit/Round.inc | 19 + .../VipM/DefaultObjects/Limit/RoundTime.inc | 23 ++ .../VipM/DefaultObjects/Limit/Steam.inc | 26 ++ .../VipM/DefaultObjects/Limit/SteamId.inc | 24 ++ .../VipM/DefaultObjects/Limit/Time.inc | 69 ++++ .../VipM/DefaultObjects/Limit/WeekDay.inc | 33 ++ .../VipM/DefaultObjects/Registrar.inc | 50 +++ amxmodx/scripting/VipModular.sma | 23 +- amxmodx/scripting/include/VipM/Limits.inc | 60 +++- amxmodx/scripting/include/VipM/Modules.inc | 2 +- 19 files changed, 528 insertions(+), 356 deletions(-) create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Always.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Never.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma index 160c1af..484c7a3 100644 --- a/amxmodx/scripting/VipM-L-Default.sma +++ b/amxmodx/scripting/VipM-L-Default.sma @@ -12,54 +12,20 @@ public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; -new g_sSteamIds[MAX_PLAYERS + 1][64]; -new g_sIps[MAX_PLAYERS + 1][32]; new g_sRealMapName[32]; -new Trie:g_tUsedInRound = Invalid_Trie; -new Trie:g_tUsedInMap = Invalid_Trie; -new Trie:g_tUsedInGame = Invalid_Trie; - new Float:g_fPlayerSpawnTime[MAX_PLAYERS + 1]; -new bool:IsSteamLimitAvailable = false; - -public plugin_natives() { - set_native_filter("@NativeFilter"); -} - -@NativeFilter(const name[], const index, const bool:trap) { - if (equal(name, "REU_GetAuthtype")) { - IsSteamLimitAvailable = trap; - } -} - // TODO: AddParamsEx // TODO: Move to core plugin public VipM_Limits_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); - VipM_Limits_RegisterType("ForAll", false, true); - VipM_Limits_SetStaticValue("ForAll", true); - VipM_Limits_RegisterType("Always", false, true); - VipM_Limits_SetStaticValue("Always", true); - - VipM_Limits_RegisterType("Never", false, true); - VipM_Limits_SetStaticValue("Never", false); - - VipM_Limits_RegisterType("Steam", true, true); - VipM_Limits_RegisterType("Alive", true, false); VipM_Limits_RegisterTypeEvent("Alive", Limit_OnCheck, "@OnAliveCheck"); VipM_Limits_RegisterType("Bot", true, true); - VipM_Limits_RegisterType("Name", true, false); - VipM_Limits_AddTypeParams("Name", - "Name", ptString, true - ); - VipM_Limits_RegisterTypeEvent("Name", Limit_OnCheck, "@OnNameCheck"); - VipM_Limits_RegisterType("Flags", true, false); VipM_Limits_AddTypeParams("Flags", "Flags", ptString, true, @@ -67,18 +33,6 @@ public VipM_Limits_OnInited() { ); VipM_Limits_RegisterTypeEvent("Flags", Limit_OnCheck, "@OnFlagsCheck"); - VipM_Limits_RegisterType("SteamId", true, false); - VipM_Limits_AddTypeParams("SteamId", - "SteamId", ptString, true - ); - VipM_Limits_RegisterTypeEvent("SteamId", Limit_OnCheck, "@OnSteamIdCheck"); - - VipM_Limits_RegisterType("Ip", true, false); - VipM_Limits_AddTypeParams("Ip", - "Ip", ptString, true - ); - VipM_Limits_RegisterTypeEvent("Ip", Limit_OnCheck, "@OnIpCheck"); - VipM_Limits_RegisterType("Map", false, false); VipM_Limits_AddTypeParams("Map", "Map", ptString, true, @@ -94,27 +48,6 @@ public VipM_Limits_OnInited() { ); VipM_Limits_RegisterTypeEvent("HasPrimaryWeapon", Limit_OnCheck, "@OnHasPrimaryWeaponCheck"); - VipM_Limits_RegisterType("Round", false, false); - VipM_Limits_AddTypeParams("Round", - "Min", ptInteger, false, - "Max", ptInteger, false - ); - VipM_Limits_RegisterTypeEvent("Round", Limit_OnCheck, "@OnRoundCheck"); - - VipM_Limits_RegisterType("WeekDay", false, false); - VipM_Limits_AddTypeParams("WeekDay", - "Day", ptString, true - ); - VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnRead, "@OnWeekDayRead"); - VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnCheck, "@OnWeekDayCheck"); - - VipM_Limits_RegisterType("RoundTime", false, false); - VipM_Limits_AddTypeParams("RoundTime", - "Min", ptInteger, false, - "Max", ptInteger, false - ); - VipM_Limits_RegisterTypeEvent("RoundTime", Limit_OnCheck, "@OnRoundTimeCheck"); - VipM_Limits_RegisterType("LifeTime", true, false); VipM_Limits_AddTypeParams("LifeTime", "Min", ptInteger, false, @@ -122,12 +55,6 @@ public VipM_Limits_OnInited() { ); VipM_Limits_RegisterTypeEvent("LifeTime", Limit_OnCheck, "@OnLifeTimeCheck"); - VipM_Limits_RegisterType("InFreezyTime", false, false); - VipM_Limits_AddTypeParams("InFreezyTime", - "Reverse", ptBoolean, false - ); - VipM_Limits_RegisterTypeEvent("InFreezyTime", Limit_OnCheck, "@OnInFreezyTimeCheck"); - // thx for idea: https://dev-cs.ru/members/7658/ VipM_Limits_RegisterType("InBuyZone", true, false); VipM_Limits_AddTypeParams("InBuyZone", @@ -135,24 +62,6 @@ public VipM_Limits_OnInited() { ); VipM_Limits_RegisterTypeEvent("InBuyZone", Limit_OnCheck, "@OnInBuyZoneCheck"); - VipM_Limits_RegisterType("OncePerRound", true, false); - VipM_Limits_RegisterTypeEvent("OncePerRound", Limit_OnCheck, "@OnOncePerRoundCheck"); - - // thx for idea: https://dev-cs.ru/threads/24759/page-2#post-141912 - VipM_Limits_RegisterType("OncePerMap", true, false); - VipM_Limits_RegisterTypeEvent("OncePerMap", Limit_OnCheck, "@OnOncePerMapCheck"); - - VipM_Limits_RegisterType("OncePerGame", true, false); - VipM_Limits_RegisterTypeEvent("OncePerGame", Limit_OnCheck, "@OnOncePerGameCheck"); - - VipM_Limits_RegisterType("Time", false, false); - VipM_Limits_AddTypeParams("Time", - "Before", ptString, false, - "After", ptString, false - ); - VipM_Limits_RegisterTypeEvent("Time", Limit_OnRead, "@OnTimeRead"); - VipM_Limits_RegisterTypeEvent("Time", Limit_OnCheck, "@OnTimeCheck"); - VipM_Limits_RegisterType("Frags", true, false); VipM_Limits_AddTypeParams("Frags", "Min", ptInteger, false, @@ -160,85 +69,18 @@ public VipM_Limits_OnInited() { ); VipM_Limits_RegisterTypeEvent("Frags", Limit_OnCheck, "@OnFragsCheck"); - VipM_Limits_RegisterType("GameTime", true, false); - VipM_Limits_AddTypeParams("GameTime", - "Min", ptFloat, false, - "Max", ptFloat, false - ); - VipM_Limits_RegisterTypeEvent("GameTime", Limit_OnCheck, "@OnGameTimeCheck"); - - VipM_Limits_RegisterType("Logic-OR", false, false); - VipM_Limits_AddTypeParams("Logic-OR", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-OR", Limit_OnCheck, "@OnOrCheck"); - - VipM_Limits_RegisterType("Logic-XOR", false, false); - VipM_Limits_AddTypeParams("Logic-XOR", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-XOR", Limit_OnCheck, "@OnXorCheck"); - - VipM_Limits_RegisterType("Logic-AND", false, false); - VipM_Limits_AddTypeParams("Logic-AND", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-AND", Limit_OnCheck, "@OnAndCheck"); - - VipM_Limits_RegisterType("Logic-NOT", false, false); - VipM_Limits_AddTypeParams("Logic-NOT", - "Limits", ptLimits, true - ); - VipM_Limits_RegisterTypeEvent("Logic-NOT", Limit_OnCheck, "@OnNotCheck"); - - RegisterHookChain(RG_CSGameRules_RestartRound, "@OnRestartRound", true); RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawn", true); - g_tUsedInRound = TrieCreate(); - g_tUsedInMap = TrieCreate(); - g_tUsedInGame = TrieCreate(); } public client_authorized(UserId, const AuthId[]) { - if (IsSteamLimitAvailable) { - VipM_Limits_SetStaticValue("Steam", is_user_steam(UserId), UserId); - } else { - VipM_Limits_SetStaticValue("Steam", true, UserId); - } - VipM_Limits_SetStaticValue("Bot", bool:is_user_bot(UserId), UserId); - - copy(g_sSteamIds[UserId], charsmax(g_sSteamIds[]), AuthId); - get_user_ip(UserId, g_sIps[UserId], charsmax(g_sIps[]), true); -} - -@OnRestartRound() { - TrieClear(g_tUsedInRound); - if (get_member_game(m_bCompleteReset)) { - TrieClear(g_tUsedInGame); - } } @OnPlayerSpawn(const UserId) { g_fPlayerSpawnTime[UserId] = get_gametime(); } -@OnGameTimeCheck(const Trie:params) { - new Float:gameTime = get_gametime(); - - new Float:min; - if (TrieGetCell(params, "Min", min) && gameTime < min) { - return false; - } - - new Float:max; - if (TrieGetCell(params, "Max", max) && gameTime > max) { - return false; - } - - return true; -} - @OnFragsCheck(const Trie:params, const playerIndex) { new frags = get_user_frags(playerIndex); @@ -255,126 +97,11 @@ public client_authorized(UserId, const AuthId[]) { return true; } -@OnTimeRead(const JSON:jCfg, const Trie:tParams) { - new sTime[8]; - - TrieGetString(tParams, "Before", sTime, charsmax(sTime)); - TrieSetCell(tParams, "Before", ParseColonTime(sTime), .replace = true); - - TrieGetString(tParams, "After", sTime, charsmax(sTime)); - TrieSetCell(tParams, "After", ParseColonTime(sTime), .replace = true); - - return VIPM_CONTINUE; -} - -@OnTimeCheck(const Trie:tParams) { - new iBefore = PCGet_Int(tParams, "Before", 0); - new iAfter = PCGet_Int(tParams, "After", 0); - new iCurrent = GetDayTimeInSeconds(); - - Dbg_Log("@OnTimeCheck(%d):", tParams); - Dbg_Log(" iBefore = %d", iBefore); - Dbg_Log(" iAfter = %d", iAfter); - Dbg_Log(" iCurrent = %d", iCurrent); - - if (!iBefore && !iAfter) { - return true; - } - - if (!iBefore) { - return iCurrent > iAfter; - } - - if (!iAfter) { - return iCurrent < iBefore; - } - - if (iBefore == iAfter) { - return iBefore == iCurrent; - } - - if (iAfter < iBefore) { - return ( - iCurrent > iAfter - && iCurrent < iBefore - ); - } - - if (iAfter > iBefore) { - return ( - iCurrent > iAfter - || iCurrent < iBefore - ); - } - - return false; -} - -@OnOncePerGameCheck(const Trie:tParams, const UserId) { - static sTrieKey[64]; - formatex(sTrieKey, charsmax(sTrieKey), "%s|%d", g_sSteamIds[UserId], tParams); - // В случае лимитов, хендлер Trie параметров можно считать уникальным для каждого инстанса лимита - // Нужно чтобы можно было указать этот лимит в двух местах и чтобы они при этом не пересекались - // Ну а SteamID для того, чтобы после перезахода оно не сбрасывалось - // - // P.S. Или лучше всё же пихать в параметры идентификатор, по котому их разделять? - // Или оба сразу?) - // - // UPD: Устарело, не стоит рассчитывать на кэширование ссылок. - - if (TrieKeyExists(g_tUsedInGame, sTrieKey)) { - return false; - } - - TrieSetCell(g_tUsedInGame, sTrieKey, true); - return true; -} - -@OnOncePerMapCheck(const Trie:tParams, const UserId) { - static sTrieKey[64]; - formatex(sTrieKey, charsmax(sTrieKey), "%s|%d", g_sSteamIds[UserId], tParams); - - if (TrieKeyExists(g_tUsedInMap, sTrieKey)) { - return false; - } - - TrieSetCell(g_tUsedInMap, sTrieKey, true); - return true; -} - -@OnOncePerRoundCheck(const Trie:tParams, const UserId) { - static sTrieKey[64]; - formatex(sTrieKey, charsmax(sTrieKey), "%s|%d", g_sSteamIds[UserId], tParams); - - if (TrieKeyExists(g_tUsedInRound, sTrieKey)) { - return false; - } - - TrieSetCell(g_tUsedInRound, sTrieKey, true); - return true; -} - @OnInBuyZoneCheck(const Trie:Params, const UserId) { new bool:bInBuyZone = IsUserInBuyZone(UserId); return PCGet_Bool(Params, "Reverse", false) ? !bInBuyZone : bInBuyZone; } -@OnInFreezyTimeCheck(const Trie:Params) { - new bool:bFreezyPeriod = get_member_game(m_bFreezePeriod); - return PCGet_Bool(Params, "Reverse", false) ? !bFreezyPeriod : bFreezyPeriod; -} - -@OnRoundTimeCheck(const Trie:Params) { - new iMin = PCGet_Int(Params, "Min", 0); - new iMax = PCGet_Int(Params, "Max", 0); - new iRoundTime = floatround(get_gametime() - Float:get_member_game(m_fRoundStartTime)); - - return ( - (!iMin || iRoundTime >= iMin) - && (!iMax || iRoundTime <= iMax) - ); -} - @OnLifeTimeCheck(const Trie:Params, const UserId) { new iMin = PCGet_Int(Params, "Min", 0); new iMax = PCGet_Int(Params, "Max", 0); @@ -386,33 +113,10 @@ public client_authorized(UserId, const AuthId[]) { ); } -@OnWeekDayRead(const JSON:jCfg, const Trie:Params) { - new sWeekDayName[32]; - json_object_get_string(jCfg, "Day", sWeekDayName, charsmax(sWeekDayName)); - new iWeekDayIndex = GetWeekDayIdByName(sWeekDayName); - if (iWeekDayIndex < 0) { - log_amx("[WARNING] Undefined week day '%s'.", sWeekDayName); - return VIPM_STOP; - } - - TrieSetCell(Params, "Day", iWeekDayIndex); - return VIPM_CONTINUE; -} - -@OnWeekDayCheck(const Trie:Params) { - new sWeekDay[4]; - get_time("%w", sWeekDay, charsmax(sWeekDay)); - return str_to_num(sWeekDay) == PCGet_Int(Params, "Day", -1); -} - @OnAliveCheck(const Trie:Params, const UserId) { return is_user_alive(UserId); } -@OnNameCheck(const Trie:Params, const UserId) { - return IsEqualUserName(UserId, PCGet_iStr(Params, "Name")); -} - bool:@OnFlagsCheck(const Trie:Params, const UserId) { static sFlags[16]; PCGet_Str(Params, "Flags", sFlags, charsmax(sFlags)); @@ -420,20 +124,6 @@ bool:@OnFlagsCheck(const Trie:Params, const UserId) { return HasUserFlagsStr(UserId, sFlags, PCGet_Bool(Params, "Strict", false)); } -@OnSteamIdCheck(const Trie:Params, const UserId) { - static sSteamId[64]; - PCGet_Str(Params, "SteamId", sSteamId, charsmax(sSteamId)); - - return equali(g_sSteamIds[UserId], sSteamId); -} - -@OnIpCheck(const Trie:Params, const UserId) { - static sIp[32]; - PCGet_Str(Params, "SteamId", sIp, charsmax(sIp)); - - return equali(g_sIps[UserId], sIp); -} - @OnMapCheck(const Trie:Params) { static sMap[32]; PCGet_Str(Params, "Map", sMap, charsmax(sMap)); @@ -453,26 +143,3 @@ bool:@OnFlagsCheck(const Trie:Params, const UserId) { new bool:res = get_member(UserId, m_bHasPrimary); return PCGet_Bool(Params, "HasNot", false) ? !res : res; } - -@OnRoundCheck(const Trie:Params, const UserId){ - return ( - GetCurrentRoundNum() >= PCGet_Int(Params, "Min", -1) - && GetCurrentRoundNum() <= PCGet_Int(Params, "Max", cellmax) - ); -} - -@OnOrCheck(const Trie:Params, const UserId){ - return PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_OR); -} - -@OnXorCheck(const Trie:Params, const UserId){ - return PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_XOR); -} - -@OnAndCheck(const Trie:Params, const UserId){ - return PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND); -} - -@OnNotCheck(const Trie:Params, const UserId){ - return !PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND); -} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Always.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Always.inc new file mode 100644 index 0000000..2569162 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Always.inc @@ -0,0 +1,9 @@ +#include +#include + +DefaultObjects_Limit_Always_Register() { + VipM_Limits_RegisterType("ForAll", false, true); + VipM_Limits_SetStaticValue("ForAll", true); + VipM_Limits_RegisterType("Always", false, true); + VipM_Limits_SetStaticValue("Always", true); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc new file mode 100644 index 0000000..b59712f --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -0,0 +1,30 @@ +#include +#include +#include +#include "VipM/Utils" + +DefaultObjects_Limit_GameTime_Register() { + VipM_Limits_RegisterType("GameTime", true, false); + VipM_Limits_AddTypeParams("GameTime", + "Min", ptFloat, false, // TODO: Добавить типы "Time" в контроллер параметров + "Max", ptFloat, false + ); + VipM_Limits_RegisterTypeEvent("GameTime", Limit_OnCheck, "@DefaultObjects_Limit_GameTime_OnCheck"); +} + + +@DefaultObjects_Limit_GameTime_OnCheck(const Trie:p) { + new Float:gameTime = get_gametime(); + + new Float:min; + if (TrieGetCell(p, "Min", min) && gameTime < min) { + return false; + } + + new Float:max; + if (TrieGetCell(p, "Max", max) && gameTime > max) { + return false; + } + + return true; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc new file mode 100644 index 0000000..7b56d24 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc @@ -0,0 +1,16 @@ +#include +#include +#include + +DefaultObjects_Limit_InFreezyTime_Register() { + VipM_Limits_RegisterType("InFreezyTime", false, false); + VipM_Limits_AddParamsEx("InFreezyTime", + "Reverse", DEFAULT_PARAMS_BOOL_NAME, false + ); + VipM_Limits_RegisterTypeEvent("InFreezyTime", Limit_OnCheck, "@DefaultObjects_Limit_InFreezyTime_OnCheck"); +} + +@DefaultObjects_Limit_InFreezyTime_OnCheck(const Trie:p) { + new bool:bFreezyPeriod = get_member_game(m_bFreezePeriod); + return PCGet_Bool(p, "Reverse", false) ? !bFreezyPeriod : bFreezyPeriod; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc new file mode 100644 index 0000000..40606a5 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc @@ -0,0 +1,24 @@ +#include +#include +#include + +new playerIps[MAX_PLAYERS + 1][MAX_IP_LENGTH]; + +DefaultObjects_Limit_Ip_Register() { + VipM_Limits_RegisterType("Ip", true, false); + VipM_Limits_AddParamsEx("Ip", + "Ip", DEFAULT_PARAMS_SHORT_STR_NAME, true + ); + VipM_Limits_RegisterTypeEvent("Ip", Limit_OnCheck, "@DefaultObjects_Limit_Ip_OnCheck"); +} + +DefaultObjects_Limit_Ip_OnClientAuth(const playerIndex) { + get_user_ip(playerIndex, playerIps[playerIndex], charsmax(playerIps[]), true); +} + +@DefaultObjects_Limit_Ip_OnCheck(const Trie:p, const playerIndex) { + static ip[MAX_IP_LENGTH]; + PCGet_Str(p, "SteamId", ip, charsmax(ip)); + + return equali(playerIps[playerIndex], ip); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc new file mode 100644 index 0000000..866ed86 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc @@ -0,0 +1,44 @@ +#include +#include + +DefaultObjects_Limit_Logic_Register() { + VipM_Limits_RegisterType("Logic-OR", false, false); + VipM_Limits_AddParamsEx("Logic-OR", + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + ); + VipM_Limits_RegisterTypeEvent("Logic-OR", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnOrCheck"); + + VipM_Limits_RegisterType("Logic-XOR", false, false); + VipM_Limits_AddParamsEx("Logic-XOR", + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + ); + VipM_Limits_RegisterTypeEvent("Logic-XOR", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnXorCheck"); + + VipM_Limits_RegisterType("Logic-AND", false, false); + VipM_Limits_AddParamsEx("Logic-AND", + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + ); + VipM_Limits_RegisterTypeEvent("Logic-AND", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnAndCheck"); + + VipM_Limits_RegisterType("Logic-NOT", false, false); + VipM_Limits_AddParamsEx("Logic-NOT", + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + ); + VipM_Limits_RegisterTypeEvent("Logic-NOT", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnNotCheck"); +} + +@DefaultObjects_Limit_Logic_OnOrCheck(const Trie:p, const playerIndex){ + return PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_OR); +} + +@DefaultObjects_Limit_Logic_OnXorCheck(const Trie:p, const playerIndex){ + return PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_XOR); +} + +@DefaultObjects_Limit_Logic_OnAndCheck(const Trie:p, const playerIndex){ + return PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND); +} + +@DefaultObjects_Limit_Logic_OnNotCheck(const Trie:p, const playerIndex){ + return !PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc new file mode 100644 index 0000000..b43bb6e --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc @@ -0,0 +1,16 @@ +#include +#include +#include +#include "VipM/Utils" + +DefaultObjects_Limit_Name_Register() { + VipM_Limits_RegisterType("Name", true, false); + VipM_Limits_AddParamsEx("Name", + "Name", DEFAULT_PARAMS_SHORT_STR_NAME, true + ); + VipM_Limits_RegisterTypeEvent("Name", Limit_OnCheck, "@DefaultObjects_Limit_Name_OnCheck"); +} + +@DefaultObjects_Limit_Name_OnCheck(const Trie:p, const playerIndex) { + return IsEqualUserName(playerIndex, PCGet_iStr(p, "Name")); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Never.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Never.inc new file mode 100644 index 0000000..62281b0 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Never.inc @@ -0,0 +1,7 @@ +#include +#include + +DefaultObjects_Limit_Never_Register() { + VipM_Limits_RegisterType("Never", false, true); + VipM_Limits_SetStaticValue("Never", false); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc new file mode 100644 index 0000000..f0f0476 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc @@ -0,0 +1,76 @@ +#include +#include + +static Trie:UsedInRound = Invalid_Trie; +static Trie:UsedInMap = Invalid_Trie; +static Trie:UsedInGame = Invalid_Trie; + +DefaultObjects_Limit_OncePer_Register() { + UsedInRound = TrieCreate(); + UsedInMap = TrieCreate(); + UsedInGame = TrieCreate(); + RegisterHookChain(RG_CSGameRules_RestartRound, "@DefaultObjects_Limit_OncePer_OnRestartRound", true); + + VipM_Limits_RegisterType("OncePerRound", true, false); + VipM_Limits_RegisterTypeEvent("OncePerRound", Limit_OnCheck, "@DefaultObjects_Limit_OncePer_OnOncePerRoundCheck"); + + // thx for idea: https://dev-cs.ru/threads/24759/page-2#post-141912 + VipM_Limits_RegisterType("OncePerMap", true, false); + VipM_Limits_RegisterTypeEvent("OncePerMap", Limit_OnCheck, "@DefaultObjects_Limit_OncePer_OnOncePerMapCheck"); + + VipM_Limits_RegisterType("OncePerGame", true, false); + VipM_Limits_RegisterTypeEvent("OncePerGame", Limit_OnCheck, "@DefaultObjects_Limit_OncePer_OnOncePerGameCheck"); + + // TODO: Универсальный лимит "RateLimited" +} + +@DefaultObjects_Limit_OncePer_OnRestartRound() { + TrieClear(UsedInRound); + if (get_member_game(m_bCompleteReset)) { + TrieClear(UsedInGame); + } +} + +@DefaultObjects_Limit_OncePer_OnOncePerGameCheck(const Trie:p, const playerIndex) { + static sTrieKey[MAX_AUTHID_LENGTH + 12]; + formatex(sTrieKey, charsmax(sTrieKey), "%d|%d", get_user_userid(playerIndex), p); + // В случае лимитов, хендлер Trie параметров можно считать уникальным для каждого инстанса лимита + // Нужно чтобы можно было указать этот лимит в двух местах и чтобы они при этом не пересекались + // Ну а SteamID для того, чтобы после перезахода оно не сбрасывалось + // + // P.S. Или лучше всё же пихать в параметры идентификатор, по котому их разделять? + // Или оба сразу?) + // + // UPD: Устарело, не стоит рассчитывать на кэширование ссылок. + + if (TrieKeyExists(UsedInGame, sTrieKey)) { + return false; + } + + TrieSetCell(UsedInGame, sTrieKey, true); + return true; +} + +@DefaultObjects_Limit_OncePer_OnOncePerMapCheck(const Trie:p, const playerIndex) { + static sTrieKey[MAX_AUTHID_LENGTH + 12]; + formatex(sTrieKey, charsmax(sTrieKey), "%d|%d", get_user_userid(playerIndex), p); + + if (TrieKeyExists(UsedInMap, sTrieKey)) { + return false; + } + + TrieSetCell(UsedInMap, sTrieKey, true); + return true; +} + +@DefaultObjects_Limit_OncePer_OnOncePerRoundCheck(const Trie:p, const playerIndex) { + static sTrieKey[MAX_AUTHID_LENGTH + 12]; + formatex(sTrieKey, charsmax(sTrieKey), "%d|%d", get_user_userid(playerIndex), p); + + if (TrieKeyExists(UsedInRound, sTrieKey)) { + return false; + } + + TrieSetCell(UsedInRound, sTrieKey, true); + return true; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc new file mode 100644 index 0000000..587bec8 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc @@ -0,0 +1,19 @@ +#include +#include +#include + +DefaultObjects_Limit_Round_Register() { + VipM_Limits_RegisterType("Round", false, false); + VipM_Limits_AddParamsEx("Round", + "Min", DEFAULT_PARAMS_INT_NAME, false, + "Max", DEFAULT_PARAMS_INT_NAME, false + ); + VipM_Limits_RegisterTypeEvent("Round", Limit_OnCheck, "@DefaultObjects_Limit_Round_OnCheck"); +} + +@DefaultObjects_Limit_Round_OnCheck(const Trie:Params, const UserId){ + return ( + GetCurrentRoundNum() >= PCGet_Int(Params, "Min", -1) + && GetCurrentRoundNum() <= PCGet_Int(Params, "Max", cellmax) + ); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc new file mode 100644 index 0000000..07bcc5d --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc @@ -0,0 +1,23 @@ +#include +#include +#include + +DefaultObjects_Limit_RoundTime_Register() { + VipM_Limits_RegisterType("RoundTime", false, false); + VipM_Limits_AddParamsEx("RoundTime", + "Min", DEFAULT_PARAMS_INT_NAME, false, + "Max", DEFAULT_PARAMS_INT_NAME, false + ); + VipM_Limits_RegisterTypeEvent("RoundTime", Limit_OnCheck, "@DefaultObjects_Limit_RoundTime_OnCheck"); +} + +@DefaultObjects_Limit_RoundTime_OnCheck(const Trie:p) { + new iMin = PCGet_Int(p, "Min", 0); + new iMax = PCGet_Int(p, "Max", 0); + new iRoundTime = floatround(get_gametime() - Float:get_member_game(m_fRoundStartTime)); + + return ( + (!iMin || iRoundTime >= iMin) + && (!iMax || iRoundTime <= iMax) + ); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc new file mode 100644 index 0000000..5b61213 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc @@ -0,0 +1,26 @@ +#include +#include +#include + +new bool:IsSteamLimitAvailable = false; + +DefaultObjects_Limit_Steam_Register() { + VipM_Limits_RegisterType("Steam", true, true); +} + +DefaultObjects_Limit_Steam_NativeFilter(const name[], const bool:trap) { + if (equal(name, "REU_GetAuthtype")) { + IsSteamLimitAvailable = trap; + return true; + } + + return false; +} + +DefaultObjects_Limit_Steam_OnClientAuth(const playerIndex) { + if (IsSteamLimitAvailable) { + VipM_Limits_SetStaticValue("Steam", is_user_steam(playerIndex), playerIndex); + } else { + VipM_Limits_SetStaticValue("Steam", true, playerIndex); + } +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc new file mode 100644 index 0000000..c70a0d7 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc @@ -0,0 +1,24 @@ +#include +#include +#include + +new playerSteamIds[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH]; + +DefaultObjects_Limit_SteamId_Register() { + VipM_Limits_RegisterType("SteamId", true, false); + VipM_Limits_AddParamsEx("SteamId", + "SteamId", DEFAULT_PARAMS_SHORT_STR_NAME, true + ); + VipM_Limits_RegisterTypeEvent("SteamId", Limit_OnCheck, "@DefaultObjects_Limit_SteamId_OnCheck"); +} + +DefaultObjects_Limit_SteamId_OnClientAuth(const playerIndex, const steamId[]) { + copy(playerSteamIds[playerIndex], charsmax(playerSteamIds[]), steamId); +} + +@DefaultObjects_Limit_SteamId_OnCheck(const Trie:p, const playerIndex) { + static steamId[MAX_AUTHID_LENGTH]; + PCGet_Str(p, "SteamId", steamId, charsmax(steamId)); + + return equali(playerSteamIds[playerIndex], steamId); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc new file mode 100644 index 0000000..898abaa --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc @@ -0,0 +1,69 @@ +#include +#include +#include +#include "VipM/Utils" + +DefaultObjects_Limit_Time_Register() { + VipM_Limits_RegisterType("Time", false, false); + VipM_Limits_AddTypeParams("Time", + "Before", ptString, false, // TODO: Добавить тип "DayTime" в контроллер параметров + "After", ptString, false + ); + VipM_Limits_RegisterTypeEvent("Time", Limit_OnRead, "@DefaultObjects_Limit_Time_OnRead"); + VipM_Limits_RegisterTypeEvent("Time", Limit_OnCheck, "@DefaultObjects_Limit_Time_OnCheck"); +} + +@DefaultObjects_Limit_Time_OnRead(const JSON:valueJson, const Trie:p) { + new sTime[8]; + + TrieGetString(p, "Before", sTime, charsmax(sTime)); + TrieSetCell(p, "Before", ParseColonTime(sTime), .replace = true); + + TrieGetString(p, "After", sTime, charsmax(sTime)); + TrieSetCell(p, "After", ParseColonTime(sTime), .replace = true); + + return VIPM_CONTINUE; +} + +@DefaultObjects_Limit_Time_OnCheck(const Trie:p) { + new iBefore = PCGet_Int(p, "Before", 0); + new iAfter = PCGet_Int(p, "After", 0); + new iCurrent = GetDayTimeInSeconds(); + + Dbg_Log("@OnTimeCheck(%d):", p); + Dbg_Log(" iBefore = %d", iBefore); + Dbg_Log(" iAfter = %d", iAfter); + Dbg_Log(" iCurrent = %d", iCurrent); + + if (!iBefore && !iAfter) { + return true; + } + + if (!iBefore) { + return iCurrent > iAfter; + } + + if (!iAfter) { + return iCurrent < iBefore; + } + + if (iBefore == iAfter) { + return iBefore == iCurrent; + } + + if (iAfter < iBefore) { + return ( + iCurrent > iAfter + && iCurrent < iBefore + ); + } + + if (iAfter > iBefore) { + return ( + iCurrent > iAfter + || iCurrent < iBefore + ); + } + + return false; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc new file mode 100644 index 0000000..8b43d5c --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc @@ -0,0 +1,33 @@ +#include +#include +#include +#include "VipM/Utils" + +DefaultObjects_Limit_WeekDay_Register() { + VipM_Limits_RegisterType("WeekDay", false, false); + VipM_Limits_AddTypeParams("WeekDay", + "Day", ptString, true // TODO: Добавить тип "WeekDayNum" в контроллер параметров + ); + VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnRead, "@DefaultObjects_Limit_WeekDay_OnRead"); + VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnCheck, "@DefaultObjects_Limit_WeekDay_OnCheck"); +} + +@DefaultObjects_Limit_WeekDay_OnRead(const JSON:valueJson, const Trie:p) { + new sWeekDayName[32]; + json_object_get_string(valueJson, "Day", sWeekDayName, charsmax(sWeekDayName)); + + new iWeekDayIndex = GetWeekDayIdByName(sWeekDayName); + if (iWeekDayIndex < 0) { + PCJson_LogForFile(valueJson, "WARNING", "Undefined week day '%s'.", sWeekDayName); + return VIPM_STOP; + } + + TrieSetCell(p, "Day", iWeekDayIndex); + return VIPM_CONTINUE; +} + +@DefaultObjects_Limit_WeekDay_OnCheck(const Trie:p) { + new sWeekDay[4]; + get_time("%w", sWeekDay, charsmax(sWeekDay)); + return str_to_num(sWeekDay) == PCGet_Int(p, "Day", -1); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc index 9b7eaa6..0d790d2 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc @@ -6,4 +6,54 @@ public ParamsController_OnRegisterTypes() { DefaultObjects_ParamType_Limit_Register(); DefaultObjects_ParamType_Limits_Register(); +} + +#include + +#include "VipM/DefaultObjects/Limit/Always" +#include "VipM/DefaultObjects/Limit/GameTime" +#include "VipM/DefaultObjects/Limit/InFreezyTime" +#include "VipM/DefaultObjects/Limit/Ip" +#include "VipM/DefaultObjects/Limit/Logic" +#include "VipM/DefaultObjects/Limit/Name" +#include "VipM/DefaultObjects/Limit/Never" +#include "VipM/DefaultObjects/Limit/OncePer" +#include "VipM/DefaultObjects/Limit/Round" +#include "VipM/DefaultObjects/Limit/RoundTime" +#include "VipM/DefaultObjects/Limit/Steam" +#include "VipM/DefaultObjects/Limit/SteamId" +#include "VipM/DefaultObjects/Limit/Time" +#include "VipM/DefaultObjects/Limit/WeekDay" + +public VipM_Limits_OnInited() { + DefaultObjects_Limit_Always_Register(); + DefaultObjects_Limit_GameTime_Register(); + DefaultObjects_Limit_InFreezyTime_Register(); + DefaultObjects_Limit_Ip_Register(); + DefaultObjects_Limit_Logic_Register(); + DefaultObjects_Limit_Name_Register(); + DefaultObjects_Limit_Never_Register(); + DefaultObjects_Limit_OncePer_Register(); + DefaultObjects_Limit_Round_Register(); + DefaultObjects_Limit_RoundTime_Register(); + DefaultObjects_Limit_Steam_Register(); + DefaultObjects_Limit_SteamId_Register(); + DefaultObjects_Limit_Time_Register(); + DefaultObjects_Limit_WeekDay_Register(); +} + +bool:DefaultObjects_NativeFilter(const name[], const bool:trap) { + new bool:ret = false; + + if (DefaultObjects_Limit_Steam_NativeFilter(name, trap)) { + ret = true; + } + + return ret; +} + +DefaultObjects_OnClientAuth(const playerIndex, const steamId[]) { + DefaultObjects_Limit_SteamId_OnClientAuth(playerIndex, steamId); + DefaultObjects_Limit_Ip_OnClientAuth(playerIndex); + DefaultObjects_Limit_Steam_OnClientAuth(playerIndex); } \ No newline at end of file diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index c52dc2a..09771ff 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -5,8 +5,6 @@ #include "VipM/ArrayTrieUtils" #include "VipM/Utils" #include "VipM/Forwards" -#include "VipM/Core/Objects/Modules/Type" -#include "VipM/Core/Objects/Limits/Type" public stock const PluginName[] = "Vip Modular"; public stock const PluginVersion[] = _VIPM_VERSION; @@ -15,6 +13,7 @@ public stock const PluginURL[] = _VIPM_PLUGIN_URL; public stock const PluginDescription[] = "Modular vip system"; #include "VipM/Core/Objects/Modules/Type" +#include "VipM/Core/Objects/Limits/Type" #include "VipM/Core/VipsManager" #include "VipM/Core/SrvCmds" #include "VipM/DefaultObjects/Registrar" @@ -42,8 +41,8 @@ public plugin_precache() { Dbg_PrintServer("Vip Modular run in debug mode!"); } -public client_disconnected(UserId) { - VipsManager_UserReset(UserId); +public client_authorized(playerIndex, const steamId[]) { + DefaultObjects_OnClientAuth(playerIndex, steamId); } public client_putinserver(UserId) { @@ -60,6 +59,10 @@ public client_putinserver(UserId) { } } +public client_disconnected(UserId) { + VipsManager_UserReset(UserId); +} + #include "VipM/Core/API/Main" #include "VipM/Core/API/Limits" #include "VipM/Core/API/Modules" @@ -67,4 +70,16 @@ public plugin_natives() { API_Main_Init(); API_Limits_Init(); API_Modules_Init(); + + set_native_filter("@NativeFilter"); +} + +@NativeFilter(const name[], const index, const trap) { + new ret = PLUGIN_CONTINUE; + + if (DefaultObjects_NativeFilter(name, !!trap)) { + ret = PLUGIN_HANDLED; + } + + return ret; } diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index d01381f..69dbce5 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -19,14 +19,14 @@ enum T_LimitUnit {Invalid_LimitUnit = -1} enum E_LimitEvent{ /* - * Описание: Вызывается после прочтения параметров условного элемента. + * Описание: Вызывается после прочтения параметров лимита. * Возв. тип: VipM_FwdReturn * Параметры: (const JSON:jUnit, Trie:tParams): * jUnit - JSON-обьект с параметрами. * tParams - Хэш-карта с прочитанными параметрами. Может быть изменена. * * Примечание: Вызывается в plugin_precache - * Примечание: Если возвращено VIPM_STOP, условный элемент будет пропущен. + * Примечание: Если возвращено VIPM_STOP, лимит будет пропущен. */ Limit_OnRead, @@ -35,10 +35,10 @@ enum E_LimitEvent{ * Возв. тип: bool * Параметры: (const Trie:tParams, const UserId): * tParams - Хэш-карта с параметрами. Для извлечения отдельных значений можно использовать стоковые функции VipM_Params_*. - * UserId - Индекс игрока. 0, если условный элемент не зависит от игрока. + * UserId - Индекс игрока. 0, если лимит не зависит от игрока. * * Примечание: Если возвращено true, условие выполняется. - * Примечание: Не вызывается для статических условных элементов. + * Примечание: Не вызывается для статических лимитов. */ Limit_OnCheck, } @@ -78,7 +78,7 @@ forward VipM_OnInitLimits(); forward VipM_Limits_OnInited(); /** - * Регистрирует в системе тип условного элемента. + * Регистрирует в системе тип лимита. * * @param jUnit Название регистрируемого типа. * @param tParams Относится ли регистрируемый тип к игрокам. @@ -93,7 +93,7 @@ forward VipM_Limits_OnInited(); native VipM_Limits_RegisterType(const sName[], const bool:bForPlayer = true, const bool:bStatic = false); /** - * Регистрирует обработчик события для указанного типа условного элемента. + * Регистрирует обработчик события для указанного типа лимита. * * @param sName Название типа. * @param iEvent Событие. @@ -104,7 +104,7 @@ native VipM_Limits_RegisterType(const sName[], const bool:bForPlayer = true, con native VipM_Limits_RegisterTypeEvent(const sName[], const E_LimitEvent:iEvent, const sFunc[]); /** - * Добавляет параметр(ы) для типа условного элемента. + * Добавляет параметр(ы) для типа лимита. * * @param sName Название типа. * @param any:... Перечисление параметров. @@ -118,18 +118,42 @@ native VipM_Limits_RegisterTypeEvent(const sName[], const E_LimitEvent:iEvent, c native VipM_Limits_AddTypeParams(const sName[], any:...); /** - * Читает условный элемент из JSON-обьекта. + * Добавляет параметры для лимита. + * + * @param moduleName Название лимита. + * @param any:... Перечисление параметров. + * + * @note Формат перечисления параметров: + * VipM_Modules_AddParamsEx(..., const paramName[], const paramType[], const bool:paramRequired, ...); + * + * Где: + * - paramName - Название параметра; + * - paramType - Название типа параметра; + * - paramRequired - Обязателен ли параметр. + * + * Пример: + * VipM_Limits_AddParamsEx(limitName, + * "Param1", "String", true, + * "Param2", "Integer", false + * ); + * + * @noreturn + */ +native VipM_Limits_AddParamsEx(const limitName[], const any:...); + +/** + * Читает лимит из JSON-обьекта. * * @param jLimit JSON-обьект. * * @note После вызова натива, JSON-обьект не очищается. * - * @return Индекс прочтённого условного элемента. Invalid_LimitUnit, если что-то пошло не так. + * @return Индекс прочтённого лимита. Invalid_LimitUnit, если что-то пошло не так. */ native T_LimitUnit:VipM_Limits_ReadFromJson(const JSON:jLimit); /** - * Читает список условных элементов из JSON-обьекта. + * Читает список лимитов из JSON-значения. * * @param jLimits JSON-обьект. * @param aLimits Динамический массив, в который надо добавить прочтённые элементы, либо Invalid_Array, если надо создать новый. @@ -137,12 +161,12 @@ native T_LimitUnit:VipM_Limits_ReadFromJson(const JSON:jLimit); * @note После вызова натива, JSON-обьект не очищается. * @note При передаче параметра aLimits, функция вернёт этот же массив с новыми элементами. * - * @return Динамический массив с индексами прочтённых условных элементов. Invalid_Array, если не было прочтено ни одного элемента. + * @return Динамический массив с хендлерами прочтённых лимитов. Invalid_Array, если не было прочтено ни одного элемента. */ native Array:VipM_Limits_ReadListFromJson(const JSON:jLimits, Array:aLimits = Invalid_Array); /** - * Устанавливает значение для статического типа условного элемента. + * Устанавливает значение для статического лимита. * * @param sName Название типа. * @param bNewValue Новое значение. @@ -155,12 +179,12 @@ native Array:VipM_Limits_ReadListFromJson(const JSON:jLimits, Array:aLimits = In native VipM_Limits_SetStaticValue(const sName[], const bool:bNewValue, const UserId = 0); /** - * Выполняет проверку условного элемента. + * Выполняет проверку лимита. * - * @param iLimit Индекс условного элемента. + * @param iLimit Индекс лимита. * @param UserId Индекс игрока. * - * @note Если индекс игрока не передан, попытка использовать относящийся к игроку условный оператор вызовет ошибку. + * @note Если индекс игрока не передан, попытка использовать относящийся к игроку лимит вызовет ошибку. * Но это уже ошибка конфигурации. * * @return true, если условие выполняется, иначе false. @@ -168,13 +192,13 @@ native VipM_Limits_SetStaticValue(const sName[], const bool:bNewValue, const Use native bool:VipM_Limits_Execute(const T_LimitUnit:iLimit, const UserId = 0); /** - * Выполняет проверку списка условных элементов. + * Выполняет проверку списка лимитов. * - * @param aLimits Динамический массив условных элементов. + * @param aLimits Динамический массив хендлеров лимитов. * @param UserId Индекс игрока. * @param iType Логический оператор. См. перечисление E_LimitsExecType. * - * @note Если индекс игрока не передан, попытка использовать относящийся к игроку условный оператор вызовет ошибку. + * @note Если индекс игрока не передан, попытка использовать относящийся к игроку лимит вызовет ошибку. * Но это уже ошибка конфигурации. * * @return true, если условие выполняется, иначе false. diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index a7cfb33..829be41 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -125,7 +125,7 @@ native VipM_Modules_AddParams(const moduleName[], const any:...); * - paramRequired - Обязателен ли параметр. * * Пример: - * VipM_Modules_AddParamsEx(module, + * VipM_Modules_AddParamsEx(moduleName, * "Param1", "String", true, * "Param2", "Integer", false * ); From 2e45d6d278a5106d7549744ee833e7d929a1da67 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 11 Oct 2025 19:18:35 +0300 Subject: [PATCH 065/108] Impl `Counter` limit --- .../VipM/DefaultObjects/Limit/Counter.inc | 150 ++++++++++++++++++ .../VipM/DefaultObjects/Limit/GameTime.inc | 1 - .../VipM/DefaultObjects/Limit/OncePer.inc | 2 - .../DefaultObjects/ParamType/CounterType.inc | 30 ++++ .../VipM/DefaultObjects/ParamType/Limit.inc | 4 +- .../VipM/DefaultObjects/ParamType/Limits.inc | 4 +- .../VipM/DefaultObjects/Registrar.inc | 12 ++ amxmodx/scripting/VipModular.sma | 21 ++- amxmodx/scripting/include/VipM/L/Counter.inc | 52 ++++++ 9 files changed, 258 insertions(+), 18 deletions(-) create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc create mode 100644 amxmodx/scripting/include/VipM/L/Counter.inc diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc new file mode 100644 index 0000000..557b36a --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include + +static Trie:CounterTypes[VipM_L_Counter_Type]; + +DefaultObjects_Limit_Counter_Register() { + VipM_Limits_RegisterType("Counter", true, false); + VipM_Limits_AddParamsEx("Counter", + "Type", VIPM_L_COUNTER_PARAM_TYPE, true, + "Key", "ShortString", true, + "Max", "Integer", false + ); + + RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnPlayerSpawn", false); + RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnR", false); + RegisterHookChain(RG_CSGameRules_RestartRound, "@DefaultObjects_Limit_Counter_OnRestartRound", false); +} + +DefaultObjects_Limit_Counter_ResetCounters(const VipM_L_Counter_Type:type) { + if (CounterTypes[type] == Invalid_Trie) { + return; + } + + new TrieIter:iter = TrieIterCreate(CounterTypes[type]); + while (!TrieIterEnded(iter)) { + new Trie:countersByKey; + if (TrieIterGetCell(iter, countersByKey)) { + TrieDestroy(countersByKey); + } + TrieIterNext(iter); + } + TrieIterDestroy(iter); + + TrieDestroy(CounterTypes[type]); +} + +DefaultObjects_Limit_Counter_ResetCountersForPlayer(const VipM_L_Counter_Type:type, const playerIndex) { + if (CounterTypes[type] == Invalid_Trie) { + return; + } + + new TrieIter:iter = TrieIterCreate(CounterTypes[type]); + while (!TrieIterEnded(iter)) { + new Trie:countersByKey; + if (TrieIterGetCell(iter, countersByKey)) { + TrieDeleteKey(countersByKey, DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex)); + } + TrieIterNext(iter); + } + TrieIterDestroy(iter); +} + +Trie:DefaultObjects_Limit_Counter_PrepareKey(const VipM_L_Counter_Type:type, const key[]) { + if (CounterTypes[type] == Invalid_Trie) { + CounterTypes[type] = TrieCreate(); + } + + new Trie:countersByKey = Invalid_Trie; + if (!TrieGetCell(CounterTypes[type], key, countersByKey)) { + countersByKey = TrieCreate(); + TrieSetCell(CounterTypes[type], key, countersByKey); + } + + return countersByKey; +} + +DefaultObjects_Limit_Counter_GetPlayerKey(const playerIndex) { + new str[MAX_AUTHID_LENGTH]; + get_user_authid(playerIndex, str, charsmax(str)); + return str; +} + +@DefaultObjects_Limit_Counter_OnCheck(const Trie:p, const playerIndex) { + new Trie:counter = DefaultObjects_Limit_Counter_PrepareKey( + .type = PCGet_Cell(p, "Type"), + .key = PCGet_iStr(p, "Key") + ); + + new value; + if (!TrieGetCell(counter, DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex), value)) { + value = 0; + } + + if (value >= PCGet_Int(p, "Max")) { + return false; + } + + TrieSetCell(counter, DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex), ++value); + + return true; +} + +DefaultObjects_Limit_Counter_OnClientPutInServer(const playerIndex) { + DefaultObjects_Limit_Counter_ResetCountersForPlayer(VipM_L_Counter_PerSession, playerIndex); +} + +@DefaultObjects_Limit_Counter_OnPlayerSpawn(const playerIndex) { + DefaultObjects_Limit_Counter_ResetCountersForPlayer(VipM_L_Counter_PerLife, playerIndex); +} + +@DefaultObjects_Limit_Counter_OnRestartRound(const playerIndex) { + DefaultObjects_Limit_Counter_ResetCounters(VipM_L_Counter_PerRound); + if (get_member_game(m_bCompleteReset)) { + DefaultObjects_Limit_Counter_ResetCounters(VipM_L_Counter_PerGame); + } +} + +DefaultObjects_Limit_Counter_RegsiterNatives() { + register_native("VipM_L_Counter_Get", "@VipM_L_Counter_Get"); + register_native("VipM_L_Counter_Set", "@VipM_L_Counter_Set"); +} + +@VipM_L_Counter_Get() { + enum {Arg_Type = 1, Arg_Key, Arg_PlayerIndex} + + new VipM_L_Counter_Type:type = VipM_L_Counter_Type:get_param(Arg_Type); + new key[VIPM_L_COUNTER_KEY_MAX_LEN]; + get_string(Arg_Key, key, charsmax(key)); + new playerIndex = get_param(Arg_PlayerIndex); + + new value = 0; + TrieGetCell( + DefaultObjects_Limit_Counter_PrepareKey(type, key), + DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex), + value + ); + + return value; +} + +@VipM_L_Counter_Set() { + enum {Arg_Type = 1, Arg_Key, Arg_PlayerIndex, Arg_Value} + + new VipM_L_Counter_Type:type = VipM_L_Counter_Type:get_param(Arg_Type); + new key[VIPM_L_COUNTER_KEY_MAX_LEN]; + get_string(Arg_Key, key, charsmax(key)); + new playerIndex = get_param(Arg_PlayerIndex); + new value = get_param(Arg_Value); + + TrieSetCell( + DefaultObjects_Limit_Counter_PrepareKey(type, key), + DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex), + value + ); + + return value; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc index b59712f..9efb054 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -1,7 +1,6 @@ #include #include #include -#include "VipM/Utils" DefaultObjects_Limit_GameTime_Register() { VipM_Limits_RegisterType("GameTime", true, false); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc index f0f0476..ead80b3 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/OncePer.inc @@ -20,8 +20,6 @@ DefaultObjects_Limit_OncePer_Register() { VipM_Limits_RegisterType("OncePerGame", true, false); VipM_Limits_RegisterTypeEvent("OncePerGame", Limit_OnCheck, "@DefaultObjects_Limit_OncePer_OnOncePerGameCheck"); - - // TODO: Универсальный лимит "RateLimited" } @DefaultObjects_Limit_OncePer_OnRestartRound() { diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc new file mode 100644 index 0000000..756f9e9 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +DefaultObjects_ParamType_CounterType_Register() { + ParamsController_RegSimpleType(VIPM_L_COUNTER_PARAM_TYPE, "@DefaultObjects_ParamType_CounterType_OnRead"); +} + +bool:@DefaultObjects_ParamType_CounterType_OnRead(const JSON:valueJson) { + new str[VIPM_L_COUNTER_KEY_MAX_LEN]; + json_get_string(valueJson, str, charsmax(str)); + + if (equali(str, "Round") || equali(str, "PerRound")) { + return ParamsController_SetCell(VipM_L_Counter_PerRound); + } else if (equali(str, "Life") || equali(str, "PerLife")) { + return ParamsController_SetCell(VipM_L_Counter_PerLife); + } else if (equali(str, "Session") || equali(str, "PerSession")) { + return ParamsController_SetCell(VipM_L_Counter_PerSession); + } else if (equali(str, "Game") || equali(str, "PerGame")) { + return ParamsController_SetCell(VipM_L_Counter_PerGame); + } else if (equali(str, "Map") || equali(str, "PerMap")) { + return ParamsController_SetCell(VipM_L_Counter_PerMap); + } + + PCJson_LogForFile(valueJson, "WARNING", "Counter type `%s` is not defined.", str); + + return false; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc index da1513f..b6d0f5b 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc @@ -4,10 +4,10 @@ #include DefaultObjects_ParamType_Limit_Register() { - ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMIT_NAME, "@OnLimitParamTypeRead"); + ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMIT_NAME, "@DefaultObjects_ParamType_Limit_OnRead"); } -bool:@OnLimitParamTypeRead(const JSON:valueJson) { +bool:@DefaultObjects_ParamType_Limit_OnRead(const JSON:valueJson) { new T_LimitUnit:limit = VipM_Limits_ReadFromJson(valueJson); if (limit == Invalid_LimitUnit) { diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc index c846d87..6eba2b7 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc @@ -4,10 +4,10 @@ #include DefaultObjects_ParamType_Limits_Register() { - ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMITS_NAME, "@OnLimitsParamTypeRead"); + ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMITS_NAME, "@DefaultObjects_ParamType_Limits_OnRead"); } -@OnLimitsParamTypeRead(const JSON:valueJson) { +@DefaultObjects_ParamType_Limits_OnRead(const JSON:valueJson) { if (json_is_array(valueJson) && json_array_get_count(valueJson) < 1) { PCJson_LogForFile(valueJson, "WARNING", "Limits array is empty."); return false; diff --git a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc index 0d790d2..de4b7f6 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc @@ -2,10 +2,12 @@ #include "VipM/DefaultObjects/ParamType/Limit" #include "VipM/DefaultObjects/ParamType/Limits" +#include "VipM/DefaultObjects/ParamType/CounterType" public ParamsController_OnRegisterTypes() { DefaultObjects_ParamType_Limit_Register(); DefaultObjects_ParamType_Limits_Register(); + DefaultObjects_ParamType_CounterType_Register(); } #include @@ -24,6 +26,7 @@ public ParamsController_OnRegisterTypes() { #include "VipM/DefaultObjects/Limit/SteamId" #include "VipM/DefaultObjects/Limit/Time" #include "VipM/DefaultObjects/Limit/WeekDay" +#include "VipM/DefaultObjects/Limit/Counter" public VipM_Limits_OnInited() { DefaultObjects_Limit_Always_Register(); @@ -40,6 +43,7 @@ public VipM_Limits_OnInited() { DefaultObjects_Limit_SteamId_Register(); DefaultObjects_Limit_Time_Register(); DefaultObjects_Limit_WeekDay_Register(); + DefaultObjects_Limit_Counter_Register(); } bool:DefaultObjects_NativeFilter(const name[], const bool:trap) { @@ -56,4 +60,12 @@ DefaultObjects_OnClientAuth(const playerIndex, const steamId[]) { DefaultObjects_Limit_SteamId_OnClientAuth(playerIndex, steamId); DefaultObjects_Limit_Ip_OnClientAuth(playerIndex); DefaultObjects_Limit_Steam_OnClientAuth(playerIndex); +} + +DefaultObjects_OnClientPutInServer(const playerIndex) { + DefaultObjects_Limit_Counter_OnClientPutInServer(playerIndex); +} + +DefaultObjects_RegsiterNatives() { + DefaultObjects_Limit_Counter_RegsiterNatives(); } \ No newline at end of file diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index 09771ff..b7b3523 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -45,22 +45,19 @@ public client_authorized(playerIndex, const steamId[]) { DefaultObjects_OnClientAuth(playerIndex, steamId); } -public client_putinserver(UserId) { - if (is_user_bot(UserId)) { - return; - } - - RequestFrame("@CallUserUpdate", UserId); +public client_putinserver(playerIndex) { + DefaultObjects_OnClientPutInServer(playerIndex); + RequestFrame("@CallUserUpdate", playerIndex); } -@CallUserUpdate(UserId) { - if (is_user_connected(UserId)) { - VipsManager_UserReload(UserId); +@CallUserUpdate(const playerIndex) { + if (is_user_connected(playerIndex)) { + VipsManager_UserReload(playerIndex); } } -public client_disconnected(UserId) { - VipsManager_UserReset(UserId); +public client_disconnected(playerIndex) { + VipsManager_UserReset(playerIndex); } #include "VipM/Core/API/Main" @@ -71,6 +68,8 @@ public plugin_natives() { API_Limits_Init(); API_Modules_Init(); + DefaultObjects_RegsiterNatives(); + set_native_filter("@NativeFilter"); } diff --git a/amxmodx/scripting/include/VipM/L/Counter.inc b/amxmodx/scripting/include/VipM/L/Counter.inc new file mode 100644 index 0000000..2333dfc --- /dev/null +++ b/amxmodx/scripting/include/VipM/L/Counter.inc @@ -0,0 +1,52 @@ +#if defined _vipmodular_l_counter_included + #endinput +#endif +#define _vipmodular_l_counter_included + +#define VIPM_L_COUNTER_KEY_MAX_LEN 64 + +new const VIPM_L_COUNTER_PARAM_TYPE[] = "VipM-L-CounterType"; + +enum VipM_L_Counter_Type { + VipM_L_Counter_PerLife, + VipM_L_Counter_PerRound, + VipM_L_Counter_PerSession, + VipM_L_Counter_PerGame, + VipM_L_Counter_PerMap, +} + +/** + * Получение текущего значения счётчика. + * + * @param type Тип счётчика (см. VipM_L_Counter_Type). + * @param key Ключ счётчика, уникальный для каждого типа. + * @param playerIndex Индекс игрока. + * + * @return Текущее значение счётчика. + */ +native VipM_L_Counter_Get(const VipM_L_Counter_Type:type, const key[], const playerIndex); + +/** + * Перезапись текущего значения счётчика. + * + * @param type Тип счётчика (см. VipM_L_Counter_Type). + * @param key Ключ счётчика, уникальный для каждого типа. + * @param playerIndex Индекс игрока. + * @param value Новое значение счётчика. + * + * @return Новое значение счётчика. + */ +native VipM_L_Counter_Set(const VipM_L_Counter_Type:type, const key[], const playerIndex, const value); + +/** + * Перезапись текущего значения счётчика. + * + * @param type Тип счётчика (см. VipM_L_Counter_Type). + * @param key Ключ счётчика, уникальный для каждого типа. + * @param playerIndex Индекс игрока. + * + * @return Новое значение счётчика. + */ +stock VipM_Counter_Inc(const VipM_L_Counter_Type:type, const key[], const playerIndex) { + return VipM_L_Counter_Set(type, key, playerIndex, VipM_L_Counter_Get(type, key) + 1); +} From 8eaa00bc74f5b28cc7354f4622daa308afbb3ae3 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 12 Oct 2025 18:12:18 +0300 Subject: [PATCH 066/108] Refactor all limits --- amxmodx/scripting/VipM-L-Default.sma | 145 ------------------ .../VipM/DefaultObjects/Limit/Alive.inc | 21 +++ .../VipM/DefaultObjects/Limit/Bot.inc | 10 ++ .../VipM/DefaultObjects/Limit/Counter.inc | 8 +- .../VipM/DefaultObjects/Limit/Flags.inc | 25 +++ .../VipM/DefaultObjects/Limit/Frags.inc | 21 +++ .../DefaultObjects/Limit/HasPrimaryWeapon.inc | 17 ++ .../VipM/DefaultObjects/Limit/InBuyZone.inc | 19 +++ .../VipM/DefaultObjects/Limit/Ip.inc | 6 +- .../VipM/DefaultObjects/Limit/LifeTime.inc | 29 ++++ .../VipM/DefaultObjects/Limit/Map.inc | 37 +++++ .../VipM/DefaultObjects/Limit/Steam.inc | 2 +- .../VipM/DefaultObjects/Limit/SteamId.inc | 6 +- .../VipM/DefaultObjects/Registrar.inc | 18 +++ 14 files changed, 208 insertions(+), 156 deletions(-) delete mode 100644 amxmodx/scripting/VipM-L-Default.sma create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Alive.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc diff --git a/amxmodx/scripting/VipM-L-Default.sma b/amxmodx/scripting/VipM-L-Default.sma deleted file mode 100644 index 484c7a3..0000000 --- a/amxmodx/scripting/VipM-L-Default.sma +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include "VipM/Utils" -#include "VipM/DebugMode" - -#pragma semicolon 1 -#pragma compress 1 - -public stock const PluginName[] = "[VipM-L] Default"; -public stock const PluginVersion[] = _VIPM_VERSION; -public stock const PluginAuthor[] = "ArKaNeMaN"; -public stock const PluginURL[] = _VIPM_PLUGIN_URL; - -new g_sRealMapName[32]; - -new Float:g_fPlayerSpawnTime[MAX_PLAYERS + 1]; - -// TODO: AddParamsEx -// TODO: Move to core plugin -public VipM_Limits_OnInited() { - register_plugin(PluginName, PluginVersion, PluginAuthor); - - VipM_Limits_RegisterType("Alive", true, false); - VipM_Limits_RegisterTypeEvent("Alive", Limit_OnCheck, "@OnAliveCheck"); - - VipM_Limits_RegisterType("Bot", true, true); - - VipM_Limits_RegisterType("Flags", true, false); - VipM_Limits_AddTypeParams("Flags", - "Flags", ptString, true, - "Strict", ptBoolean, false - ); - VipM_Limits_RegisterTypeEvent("Flags", Limit_OnCheck, "@OnFlagsCheck"); - - VipM_Limits_RegisterType("Map", false, false); - VipM_Limits_AddTypeParams("Map", - "Map", ptString, true, - "Real", ptBoolean, false, - "Prefix", ptBoolean, false - ); - VipM_Limits_RegisterTypeEvent("Map", Limit_OnCheck, "@OnMapCheck"); - rh_get_mapname(g_sRealMapName, charsmax(g_sRealMapName), MNT_TRUE); - - VipM_Limits_RegisterType("HasPrimaryWeapon", true, false); - VipM_Limits_AddTypeParams("HasPrimaryWeapon", - "HasNot", ptBoolean, false - ); - VipM_Limits_RegisterTypeEvent("HasPrimaryWeapon", Limit_OnCheck, "@OnHasPrimaryWeaponCheck"); - - VipM_Limits_RegisterType("LifeTime", true, false); - VipM_Limits_AddTypeParams("LifeTime", - "Min", ptInteger, false, - "Max", ptInteger, false - ); - VipM_Limits_RegisterTypeEvent("LifeTime", Limit_OnCheck, "@OnLifeTimeCheck"); - - // thx for idea: https://dev-cs.ru/members/7658/ - VipM_Limits_RegisterType("InBuyZone", true, false); - VipM_Limits_AddTypeParams("InBuyZone", - "Reverse", ptBoolean, false - ); - VipM_Limits_RegisterTypeEvent("InBuyZone", Limit_OnCheck, "@OnInBuyZoneCheck"); - - VipM_Limits_RegisterType("Frags", true, false); - VipM_Limits_AddTypeParams("Frags", - "Min", ptInteger, false, - "Max", ptInteger, false - ); - VipM_Limits_RegisterTypeEvent("Frags", Limit_OnCheck, "@OnFragsCheck"); - - RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawn", true); - -} - -public client_authorized(UserId, const AuthId[]) { - VipM_Limits_SetStaticValue("Bot", bool:is_user_bot(UserId), UserId); -} - -@OnPlayerSpawn(const UserId) { - g_fPlayerSpawnTime[UserId] = get_gametime(); -} - -@OnFragsCheck(const Trie:params, const playerIndex) { - new frags = get_user_frags(playerIndex); - - new min; - if (TrieGetCell(params, "Min", min) && frags < min) { - return false; - } - - new max; - if (TrieGetCell(params, "Max", max) && frags > max) { - return false; - } - - return true; -} - -@OnInBuyZoneCheck(const Trie:Params, const UserId) { - new bool:bInBuyZone = IsUserInBuyZone(UserId); - return PCGet_Bool(Params, "Reverse", false) ? !bInBuyZone : bInBuyZone; -} - -@OnLifeTimeCheck(const Trie:Params, const UserId) { - new iMin = PCGet_Int(Params, "Min", 0); - new iMax = PCGet_Int(Params, "Max", 0); - new iLifeTime = floatround(get_gametime() - g_fPlayerSpawnTime[UserId]); - - return ( - (!iMin || iLifeTime >= iMin) - && (!iMax || iLifeTime <= iMax) - ); -} - -@OnAliveCheck(const Trie:Params, const UserId) { - return is_user_alive(UserId); -} - -bool:@OnFlagsCheck(const Trie:Params, const UserId) { - static sFlags[16]; - PCGet_Str(Params, "Flags", sFlags, charsmax(sFlags)); - - return HasUserFlagsStr(UserId, sFlags, PCGet_Bool(Params, "Strict", false)); -} - -@OnMapCheck(const Trie:Params) { - static sMap[32]; - PCGet_Str(Params, "Map", sMap, charsmax(sMap)); - - new iCount = PCGet_Bool(Params, "Prefix", false) ? strlen(sMap) : 0; - - if (PCGet_Bool(Params, "Real", false)) { - return equali(sMap, g_sRealMapName, iCount); - } else { - static sSetMapName[32]; - rh_get_mapname(sSetMapName, charsmax(sSetMapName), MNT_SET); - return equali(sMap, sSetMapName, iCount); - } -} - -@OnHasPrimaryWeaponCheck(const Trie:Params, const UserId) { - new bool:res = get_member(UserId, m_bHasPrimary); - return PCGet_Bool(Params, "HasNot", false) ? !res : res; -} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Alive.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Alive.inc new file mode 100644 index 0000000..4a00de2 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Alive.inc @@ -0,0 +1,21 @@ +#include +#include + +DefaultObjects_Limit_Alive_Register() { + VipM_Limits_RegisterType("Alive", true, true); + + RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Alive_OnPlayerSpawn", true); + RegisterHookChain(RG_CBasePlayer_Killed, "@DefaultObjects_Limit_Alive_OnPlayerKilled", true); +} + +@DefaultObjects_Limit_Alive_OnPlayerSpawn(const playerIndex) { + VipM_Limits_SetStaticValue("Alive", true, playerIndex); +} + +@DefaultObjects_Limit_Alive_OnPlayerKilled(const playerIndex) { + VipM_Limits_SetStaticValue("Alive", false, playerIndex); +} + +DefaultObjects_Limit_Alive_OnClientPutInServer(const playerIndex) { + VipM_Limits_SetStaticValue("Alive", false, playerIndex); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc new file mode 100644 index 0000000..70dbbf2 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc @@ -0,0 +1,10 @@ +#include +#include + +DefaultObjects_Limit_Bot_Register() { + VipM_Limits_RegisterType("Bot", true, true); +} + +DefaultObjects_Limit_Bot_OnClientAuth(const playerIndex) { + VipM_Limits_SetStaticValue("Bot", is_user_bot(playerIndex), playerIndex); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc index 557b36a..78495f2 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -19,7 +19,7 @@ DefaultObjects_Limit_Counter_Register() { RegisterHookChain(RG_CSGameRules_RestartRound, "@DefaultObjects_Limit_Counter_OnRestartRound", false); } -DefaultObjects_Limit_Counter_ResetCounters(const VipM_L_Counter_Type:type) { +static DefaultObjects_Limit_Counter_ResetCounters(const VipM_L_Counter_Type:type) { if (CounterTypes[type] == Invalid_Trie) { return; } @@ -37,7 +37,7 @@ DefaultObjects_Limit_Counter_ResetCounters(const VipM_L_Counter_Type:type) { TrieDestroy(CounterTypes[type]); } -DefaultObjects_Limit_Counter_ResetCountersForPlayer(const VipM_L_Counter_Type:type, const playerIndex) { +static DefaultObjects_Limit_Counter_ResetCountersForPlayer(const VipM_L_Counter_Type:type, const playerIndex) { if (CounterTypes[type] == Invalid_Trie) { return; } @@ -53,7 +53,7 @@ DefaultObjects_Limit_Counter_ResetCountersForPlayer(const VipM_L_Counter_Type:ty TrieIterDestroy(iter); } -Trie:DefaultObjects_Limit_Counter_PrepareKey(const VipM_L_Counter_Type:type, const key[]) { +static Trie:DefaultObjects_Limit_Counter_PrepareKey(const VipM_L_Counter_Type:type, const key[]) { if (CounterTypes[type] == Invalid_Trie) { CounterTypes[type] = TrieCreate(); } @@ -67,7 +67,7 @@ Trie:DefaultObjects_Limit_Counter_PrepareKey(const VipM_L_Counter_Type:type, con return countersByKey; } -DefaultObjects_Limit_Counter_GetPlayerKey(const playerIndex) { +static DefaultObjects_Limit_Counter_GetPlayerKey(const playerIndex) { new str[MAX_AUTHID_LENGTH]; get_user_authid(playerIndex, str, charsmax(str)); return str; diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc new file mode 100644 index 0000000..ea2a5ae --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc @@ -0,0 +1,25 @@ +#include +#include +#include + +new playerSteamIds[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH]; + +DefaultObjects_Limit_Flags_Register() { + VipM_Limits_RegisterType("Flags", true, false); + VipM_Limits_AddParamsEx("Flags", + "Flags", DEFAULT_PARAMS_FLAGS_NAME, true + "Strict", DEFAULT_PARAMS_BOOL_NAME, false + ); + VipM_Limits_RegisterTypeEvent("Flags", Limit_OnCheck, "@DefaultObjects_Limit_Flags_OnCheck"); +} + +@DefaultObjects_Limit_Flags_OnCheck(const Trie:p, const playerIndex) { + new playerFlags = get_user_flags(playerIndex); + new flags = PCGet_Int(p, "Flags"); + + if (PCGet_Bool(p, "Strict", false)) { + return (playerFlags & flags) == flags; + } else { + return playerFlags & flags; + } +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc new file mode 100644 index 0000000..78d6700 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc @@ -0,0 +1,21 @@ +#include +#include +#include + +DefaultObjects_Limit_Frags_Register() { + VipM_Limits_RegisterType("Frags", true, false); + VipM_Limits_AddParamsEx("Frags", + "Min", DEFAULT_PARAMS_INT_NAME, false, + "Max", DEFAULT_PARAMS_INT_NAME, false + ); + VipM_Limits_RegisterTypeEvent("Frags", Limit_OnCheck, "@DefaultObjects_Limit_Frags_OnCheck"); +} + +@DefaultObjects_Limit_Frags_OnCheck(const Trie:p, const playerIndex) { + new frags = get_user_frags(playerIndex); + + return ( + frags >= PCGet_Int(p, "Min", cellmin) + && frags <= PCGet_Int(p, "Max", cellmax) + ); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc new file mode 100644 index 0000000..bec98a6 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc @@ -0,0 +1,17 @@ +#include +#include +#include + +DefaultObjects_Limit_HasPrimaryWeapon_Register() { + VipM_Limits_RegisterType("HasPrimaryWeapon", true, false); + VipM_Limits_AddParamsEx("HasPrimaryWeapon", + "HasNot", DEFAULT_PARAMS_BOOL_NAME, false + ); + VipM_Limits_RegisterTypeEvent("HasPrimaryWeapon", Limit_OnCheck, "@DefaultObjects_Limit_HasPrimaryWeapon_OnCheck"); +} + +@DefaultObjects_Limit_HasPrimaryWeapon_OnCheck(const Trie:p, const playerIndex) { + new bool:res = get_member(playerIndex, m_bHasPrimary); + + return PCGet_Bool(p, "HasNot", false) ? !res : res; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc new file mode 100644 index 0000000..6c52132 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "VipM/Utils" + +DefaultObjects_Limit_InBuyZone_Register() { + VipM_Limits_RegisterType("InBuyZone", true, false); + VipM_Limits_AddParamsEx("InBuyZone", + "Reverse", DEFAULT_PARAMS_BOOL_NAME, false + ); + VipM_Limits_RegisterTypeEvent("InBuyZone", Limit_OnCheck, "@DefaultObjects_Limit_InBuyZone_OnCheck"); +} + +@DefaultObjects_Limit_InBuyZone_OnCheck(const Trie:p, const playerIndex) { + new bool:res = IsUserInBuyZone(playerIndex); + + return PCGet_Bool(p, "Reverse", false) ? !res : res; +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc index 40606a5..24f7363 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc @@ -2,7 +2,7 @@ #include #include -new playerIps[MAX_PLAYERS + 1][MAX_IP_LENGTH]; +static PlayerIps[MAX_PLAYERS + 1][MAX_IP_LENGTH]; DefaultObjects_Limit_Ip_Register() { VipM_Limits_RegisterType("Ip", true, false); @@ -13,12 +13,12 @@ DefaultObjects_Limit_Ip_Register() { } DefaultObjects_Limit_Ip_OnClientAuth(const playerIndex) { - get_user_ip(playerIndex, playerIps[playerIndex], charsmax(playerIps[]), true); + get_user_ip(playerIndex, PlayerIps[playerIndex], charsmax(PlayerIps[]), true); } @DefaultObjects_Limit_Ip_OnCheck(const Trie:p, const playerIndex) { static ip[MAX_IP_LENGTH]; PCGet_Str(p, "SteamId", ip, charsmax(ip)); - return equali(playerIps[playerIndex], ip); + return equali(PlayerIps[playerIndex], ip); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc new file mode 100644 index 0000000..8271523 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc @@ -0,0 +1,29 @@ +#include +#include +#include + +static Float:PlayerSpawnTime[MAX_PLAYERS + 1] = {0.0, ...}; + +DefaultObjects_Limit_LifeTime_Register() { + VipM_Limits_RegisterType("LifeTime", true, false); + VipM_Limits_AddParamsEx("LifeTime", + "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, + "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false + ); + VipM_Limits_RegisterTypeEvent("LifeTime", Limit_OnCheck, "@DefaultObjects_Limit_LifeTime_OnCheck"); + + RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_LifeTime_OnPlayerSpawn", true); +} + +@DefaultObjects_Limit_LifeTime_OnPlayerSpawn(const playerIndex) { + PlayerSpawnTime[playerIndex] = get_gametime(); +} + +@DefaultObjects_Limit_LifeTime_OnCheck(const Trie:p, const playerIndex) { + new lifeTime = floatround(get_gametime() - PlayerSpawnTime[playerIndex]); + + return ( + lifeTime >= PCGet_Int(p, "Min", cellmin) + && lifeTime <= PCGet_Int(p, "Max", cellmax) + ); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc new file mode 100644 index 0000000..9402e85 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc @@ -0,0 +1,37 @@ +#include +#include +#include + +new RealCurrentMapName[32]; + +// TODO: Указывание нескольких карт/префиксов. Возможно отдельным лимитом. + +DefaultObjects_Limit_Map_Register() { + VipM_Limits_RegisterType("Map", true, false); + VipM_Limits_AddParamsEx("Map", + "Map", DEFAULT_PARAMS_SHORT_STR_NAME, true, + "Real", DEFAULT_PARAMS_BOOL_NAME, false, + "Prefix", DEFAULT_PARAMS_BOOL_NAME, false + ); + VipM_Limits_RegisterTypeEvent("Map", Limit_OnCheck, "@DefaultObjects_Limit_Map_OnCheck"); + + rh_get_mapname(RealCurrentMapName, charsmax(RealCurrentMapName), MNT_TRUE); +} + +@DefaultObjects_Limit_Map_OnCheck(const Trie:p, const playerIndex) { + static map[32]; + new len = PCGet_Str(p, "Map", map, charsmax(map)); + + if (!PCGet_Bool(p, "Prefix", false)) { + len = 0; + } + + if (PCGet_Bool(p, "Real", false)) { + return equali(map, RealCurrentMapName, len); + } else { + static currentMapName[32]; + rh_get_mapname(currentMapName, charsmax(currentMapName), MNT_SET); + + return equali(map, currentMapName, len); + } +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc index 5b61213..358a26d 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Steam.inc @@ -2,7 +2,7 @@ #include #include -new bool:IsSteamLimitAvailable = false; +static bool:IsSteamLimitAvailable = false; DefaultObjects_Limit_Steam_Register() { VipM_Limits_RegisterType("Steam", true, true); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc index c70a0d7..12610d4 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc @@ -2,7 +2,7 @@ #include #include -new playerSteamIds[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH]; +static PlayerSteamIds[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH]; DefaultObjects_Limit_SteamId_Register() { VipM_Limits_RegisterType("SteamId", true, false); @@ -13,12 +13,12 @@ DefaultObjects_Limit_SteamId_Register() { } DefaultObjects_Limit_SteamId_OnClientAuth(const playerIndex, const steamId[]) { - copy(playerSteamIds[playerIndex], charsmax(playerSteamIds[]), steamId); + copy(PlayerSteamIds[playerIndex], charsmax(PlayerSteamIds[]), steamId); } @DefaultObjects_Limit_SteamId_OnCheck(const Trie:p, const playerIndex) { static steamId[MAX_AUTHID_LENGTH]; PCGet_Str(p, "SteamId", steamId, charsmax(steamId)); - return equali(playerSteamIds[playerIndex], steamId); + return equali(PlayerSteamIds[playerIndex], steamId); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc index de4b7f6..a5d1c64 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc @@ -27,6 +27,14 @@ public ParamsController_OnRegisterTypes() { #include "VipM/DefaultObjects/Limit/Time" #include "VipM/DefaultObjects/Limit/WeekDay" #include "VipM/DefaultObjects/Limit/Counter" +#include "VipM/DefaultObjects/Limit/Alive" +#include "VipM/DefaultObjects/Limit/LifeTime" +#include "VipM/DefaultObjects/Limit/Bot" +#include "VipM/DefaultObjects/Limit/Flags" +#include "VipM/DefaultObjects/Limit/Frags" +#include "VipM/DefaultObjects/Limit/InBuyZone" +#include "VipM/DefaultObjects/Limit/HasPrimaryWeapon" +#include "VipM/DefaultObjects/Limit/Map" public VipM_Limits_OnInited() { DefaultObjects_Limit_Always_Register(); @@ -44,6 +52,14 @@ public VipM_Limits_OnInited() { DefaultObjects_Limit_Time_Register(); DefaultObjects_Limit_WeekDay_Register(); DefaultObjects_Limit_Counter_Register(); + DefaultObjects_Limit_Alive_Register(); + DefaultObjects_Limit_LifeTime_Register(); + DefaultObjects_Limit_Bot_Register(); + DefaultObjects_Limit_Flags_Register(); + DefaultObjects_Limit_Frags_Register(); + DefaultObjects_Limit_InBuyZone_Register(); + DefaultObjects_Limit_HasPrimaryWeapon_Register(); + DefaultObjects_Limit_Map_Register(); } bool:DefaultObjects_NativeFilter(const name[], const bool:trap) { @@ -60,10 +76,12 @@ DefaultObjects_OnClientAuth(const playerIndex, const steamId[]) { DefaultObjects_Limit_SteamId_OnClientAuth(playerIndex, steamId); DefaultObjects_Limit_Ip_OnClientAuth(playerIndex); DefaultObjects_Limit_Steam_OnClientAuth(playerIndex); + DefaultObjects_Limit_Bot_OnClientAuth(playerIndex); } DefaultObjects_OnClientPutInServer(const playerIndex) { DefaultObjects_Limit_Counter_OnClientPutInServer(playerIndex); + DefaultObjects_Limit_Alive_OnClientPutInServer(playerIndex); } DefaultObjects_RegsiterNatives() { From bafabc3c898ac781a774b7a7df170254ff1dd566 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 12 Oct 2025 18:15:30 +0300 Subject: [PATCH 067/108] Fix --- amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc index 78495f2..e50104c 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -15,7 +15,6 @@ DefaultObjects_Limit_Counter_Register() { ); RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnPlayerSpawn", false); - RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnR", false); RegisterHookChain(RG_CSGameRules_RestartRound, "@DefaultObjects_Limit_Counter_OnRestartRound", false); } From a3dd2361f495fc30e7eca4da60f6e7614919330c Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 12 Oct 2025 19:02:55 +0300 Subject: [PATCH 068/108] Add `WasKilled/Alive` limits --- .../VipM/DefaultObjects/Limit/WasKilled.inc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 amxmodx/scripting/VipM/DefaultObjects/Limit/WasKilled.inc diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/WasKilled.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/WasKilled.inc new file mode 100644 index 0000000..f791051 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/WasKilled.inc @@ -0,0 +1,19 @@ +#include +#include + +DefaultObjects_Limit_WasAlive_Register() { + VipM_Limits_RegisterType("WasAlive", true, true); + VipM_Limits_RegisterType("WasKilled", true, true); + + RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_WasAlive_OnPlayerSpawn", false); +} + +@DefaultObjects_Limit_WasAlive_OnPlayerSpawn(const playerIndex) { + VipM_Limits_SetStaticValue("WasAlive", !!is_user_alive(playerIndex), playerIndex); + VipM_Limits_SetStaticValue("WasKilled", !is_user_alive(playerIndex), playerIndex); +} + +DefaultObjects_Limit_WasAlive_OnClientPutInServer(const playerIndex) { + VipM_Limits_SetStaticValue("WasAlive", false, playerIndex); + VipM_Limits_SetStaticValue("WasKilled", true, playerIndex); +} From 9e1f82a1b5f85f4d8d52fa1ffc9bdce5b0c46669 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 12 Oct 2025 19:17:04 +0300 Subject: [PATCH 069/108] Update params usage in limits --- .../VipM/DefaultObjects/Limit/Bot.inc | 2 +- .../VipM/DefaultObjects/Limit/Counter.inc | 4 ++-- .../VipM/DefaultObjects/Limit/Flags.inc | 4 +--- .../VipM/DefaultObjects/Limit/GameTime.inc | 21 ++++++------------- .../VipM/DefaultObjects/Limit/RoundTime.inc | 12 +++++------ .../VipM/DefaultObjects/Limit/Time.inc | 16 ++------------ .../VipM/DefaultObjects/Limit/WeekDay.inc | 17 ++------------- 7 files changed, 19 insertions(+), 57 deletions(-) diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc index 70dbbf2..408f814 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Bot.inc @@ -6,5 +6,5 @@ DefaultObjects_Limit_Bot_Register() { } DefaultObjects_Limit_Bot_OnClientAuth(const playerIndex) { - VipM_Limits_SetStaticValue("Bot", is_user_bot(playerIndex), playerIndex); + VipM_Limits_SetStaticValue("Bot", !!is_user_bot(playerIndex), playerIndex); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc index e50104c..bfb1d4c 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -10,8 +10,8 @@ DefaultObjects_Limit_Counter_Register() { VipM_Limits_RegisterType("Counter", true, false); VipM_Limits_AddParamsEx("Counter", "Type", VIPM_L_COUNTER_PARAM_TYPE, true, - "Key", "ShortString", true, - "Max", "Integer", false + "Key", DEFAULT_PARAMS_SHORT_STR_NAME, true, + "Max", DEFAULT_PARAMS_INT_NAME, false ); RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnPlayerSpawn", false); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc index ea2a5ae..328465b 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc @@ -2,12 +2,10 @@ #include #include -new playerSteamIds[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH]; - DefaultObjects_Limit_Flags_Register() { VipM_Limits_RegisterType("Flags", true, false); VipM_Limits_AddParamsEx("Flags", - "Flags", DEFAULT_PARAMS_FLAGS_NAME, true + "Flags", DEFAULT_PARAMS_FLAGS_NAME, true, "Strict", DEFAULT_PARAMS_BOOL_NAME, false ); VipM_Limits_RegisterTypeEvent("Flags", Limit_OnCheck, "@DefaultObjects_Limit_Flags_OnCheck"); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc index 9efb054..50ce2d2 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -5,25 +5,16 @@ DefaultObjects_Limit_GameTime_Register() { VipM_Limits_RegisterType("GameTime", true, false); VipM_Limits_AddTypeParams("GameTime", - "Min", ptFloat, false, // TODO: Добавить типы "Time" в контроллер параметров - "Max", ptFloat, false + "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, // TODO: Добавить типы "Time" в контроллер параметров + "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false ); VipM_Limits_RegisterTypeEvent("GameTime", Limit_OnCheck, "@DefaultObjects_Limit_GameTime_OnCheck"); } @DefaultObjects_Limit_GameTime_OnCheck(const Trie:p) { - new Float:gameTime = get_gametime(); - - new Float:min; - if (TrieGetCell(p, "Min", min) && gameTime < min) { - return false; - } - - new Float:max; - if (TrieGetCell(p, "Max", max) && gameTime > max) { - return false; - } - - return true; + return ( + gameTime >= PCGet_Int(p, "Min", cellmin) + && gameTime <= PCGet_Int(p, "Max", cellmax) + ); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc index 07bcc5d..64c170e 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc @@ -5,19 +5,17 @@ DefaultObjects_Limit_RoundTime_Register() { VipM_Limits_RegisterType("RoundTime", false, false); VipM_Limits_AddParamsEx("RoundTime", - "Min", DEFAULT_PARAMS_INT_NAME, false, - "Max", DEFAULT_PARAMS_INT_NAME, false + "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, + "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false ); VipM_Limits_RegisterTypeEvent("RoundTime", Limit_OnCheck, "@DefaultObjects_Limit_RoundTime_OnCheck"); } @DefaultObjects_Limit_RoundTime_OnCheck(const Trie:p) { - new iMin = PCGet_Int(p, "Min", 0); - new iMax = PCGet_Int(p, "Max", 0); - new iRoundTime = floatround(get_gametime() - Float:get_member_game(m_fRoundStartTime)); + new roundTime = floatround(get_gametime() - Float:get_member_game(m_fRoundStartTime)); return ( - (!iMin || iRoundTime >= iMin) - && (!iMax || iRoundTime <= iMax) + roundTime >= PCGet_Int(p, "Min", cellmin) + && roundTime <= PCGet_Int(p, "Max", cellmax) ); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc index 898abaa..8d53be1 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc @@ -6,25 +6,13 @@ DefaultObjects_Limit_Time_Register() { VipM_Limits_RegisterType("Time", false, false); VipM_Limits_AddTypeParams("Time", - "Before", ptString, false, // TODO: Добавить тип "DayTime" в контроллер параметров - "After", ptString, false + "Before", DEFAULT_PARAMS_TIME_NAME, false, + "After", DEFAULT_PARAMS_TIME_NAME, false ); VipM_Limits_RegisterTypeEvent("Time", Limit_OnRead, "@DefaultObjects_Limit_Time_OnRead"); VipM_Limits_RegisterTypeEvent("Time", Limit_OnCheck, "@DefaultObjects_Limit_Time_OnCheck"); } -@DefaultObjects_Limit_Time_OnRead(const JSON:valueJson, const Trie:p) { - new sTime[8]; - - TrieGetString(p, "Before", sTime, charsmax(sTime)); - TrieSetCell(p, "Before", ParseColonTime(sTime), .replace = true); - - TrieGetString(p, "After", sTime, charsmax(sTime)); - TrieSetCell(p, "After", ParseColonTime(sTime), .replace = true); - - return VIPM_CONTINUE; -} - @DefaultObjects_Limit_Time_OnCheck(const Trie:p) { new iBefore = PCGet_Int(p, "Before", 0); new iAfter = PCGet_Int(p, "After", 0); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc index 8b43d5c..cf292f2 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc @@ -6,28 +6,15 @@ DefaultObjects_Limit_WeekDay_Register() { VipM_Limits_RegisterType("WeekDay", false, false); VipM_Limits_AddTypeParams("WeekDay", - "Day", ptString, true // TODO: Добавить тип "WeekDayNum" в контроллер параметров + "Day", DEFAULT_PARAMS_WEEK_DAY_NAME, true ); VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnRead, "@DefaultObjects_Limit_WeekDay_OnRead"); VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnCheck, "@DefaultObjects_Limit_WeekDay_OnCheck"); } -@DefaultObjects_Limit_WeekDay_OnRead(const JSON:valueJson, const Trie:p) { - new sWeekDayName[32]; - json_object_get_string(valueJson, "Day", sWeekDayName, charsmax(sWeekDayName)); - - new iWeekDayIndex = GetWeekDayIdByName(sWeekDayName); - if (iWeekDayIndex < 0) { - PCJson_LogForFile(valueJson, "WARNING", "Undefined week day '%s'.", sWeekDayName); - return VIPM_STOP; - } - - TrieSetCell(p, "Day", iWeekDayIndex); - return VIPM_CONTINUE; -} - @DefaultObjects_Limit_WeekDay_OnCheck(const Trie:p) { new sWeekDay[4]; get_time("%w", sWeekDay, charsmax(sWeekDay)); + return str_to_num(sWeekDay) == PCGet_Int(p, "Day", -1); } From cedc7c87ba5135fd45dec85a449a53079c82ccc6 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 12 Oct 2025 19:41:21 +0300 Subject: [PATCH 070/108] Remove some utils --- amxmodx/scripting/ItemsController.sma | 3 +- .../VipM/DefaultObjects/Limit/Name.inc | 5 +- .../VipM/DefaultObjects/Limit/Round.inc | 9 ++- .../VipM/DefaultObjects/Limit/Time.inc | 39 +++++----- .../DefaultObjects/ParamType/CounterType.inc | 8 +- amxmodx/scripting/VipM/Utils.inc | 75 ------------------- amxmodx/scripting/VipModular.sma | 2 +- 7 files changed, 36 insertions(+), 105 deletions(-) diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index a7a1f4e..7d17b2f 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -1,4 +1,5 @@ #include +#include #include #include "VipM/Utils" #include "VipM/Forwards" @@ -21,7 +22,7 @@ PluginInit() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_library(IC_LIBRARY); - CreateConstCvar(IC_VERSION_CVAR, IC_VERSION); + PCCvar_Const(IC_VERSION_CVAR, IC_VERSION); ParamsController_Init(); Forwards_Init(); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc index b43bb6e..a444a3a 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc @@ -12,5 +12,8 @@ DefaultObjects_Limit_Name_Register() { } @DefaultObjects_Limit_Name_OnCheck(const Trie:p, const playerIndex) { - return IsEqualUserName(playerIndex, PCGet_iStr(p, "Name")); + static name[MAX_NAME_LENGTH]; + get_user_name(playerIndex, name, charsmax(name)); + + return equal(name, PCGet_iStr(p, "Name")); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc index 587bec8..fc71201 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc @@ -1,4 +1,5 @@ #include +#include #include #include @@ -11,9 +12,11 @@ DefaultObjects_Limit_Round_Register() { VipM_Limits_RegisterTypeEvent("Round", Limit_OnCheck, "@DefaultObjects_Limit_Round_OnCheck"); } -@DefaultObjects_Limit_Round_OnCheck(const Trie:Params, const UserId){ +@DefaultObjects_Limit_Round_OnCheck(const Trie:Params, const UserId) { + new currentRound = get_member_game(m_iTotalRoundsPlayed) + 1; + return ( - GetCurrentRoundNum() >= PCGet_Int(Params, "Min", -1) - && GetCurrentRoundNum() <= PCGet_Int(Params, "Max", cellmax) + currentRound >= PCGet_Int(Params, "Min", cellmin) + && currentRound <= PCGet_Int(Params, "Max", cellmax) ); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc index 8d53be1..1394729 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc @@ -1,7 +1,6 @@ #include #include #include -#include "VipM/Utils" DefaultObjects_Limit_Time_Register() { VipM_Limits_RegisterType("Time", false, false); @@ -14,42 +13,38 @@ DefaultObjects_Limit_Time_Register() { } @DefaultObjects_Limit_Time_OnCheck(const Trie:p) { - new iBefore = PCGet_Int(p, "Before", 0); - new iAfter = PCGet_Int(p, "After", 0); - new iCurrent = GetDayTimeInSeconds(); + new before = PCGet_Int(p, "Before", 0); + new after = PCGet_Int(p, "After", 0); - Dbg_Log("@OnTimeCheck(%d):", p); - Dbg_Log(" iBefore = %d", iBefore); - Dbg_Log(" iAfter = %d", iAfter); - Dbg_Log(" iCurrent = %d", iCurrent); - - if (!iBefore && !iAfter) { + if (!before && !after) { return true; } + + new currentTime = get_systime() % (24 * 60 * 60); - if (!iBefore) { - return iCurrent > iAfter; + if (!before) { + return currentTime > after; } - if (!iAfter) { - return iCurrent < iBefore; + if (!after) { + return currentTime < before; } - if (iBefore == iAfter) { - return iBefore == iCurrent; + if (before == after) { + return before == currentTime; } - if (iAfter < iBefore) { + if (after < before) { return ( - iCurrent > iAfter - && iCurrent < iBefore + currentTime > after + && currentTime < before ); } - if (iAfter > iBefore) { + if (after > before) { return ( - iCurrent > iAfter - || iCurrent < iBefore + currentTime > after + || currentTime < before ); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc index 756f9e9..4a952e7 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/CounterType.inc @@ -9,6 +9,11 @@ DefaultObjects_ParamType_CounterType_Register() { } bool:@DefaultObjects_ParamType_CounterType_OnRead(const JSON:valueJson) { + if (!json_is_string(valueJson)) { + PCJson_LogForFile(valueJson, "WARNING", "Counter type must be a string (PerRound, PerLife, PerSession, PerGame, PerMap)."); + return false; + } + new str[VIPM_L_COUNTER_KEY_MAX_LEN]; json_get_string(valueJson, str, charsmax(str)); @@ -24,7 +29,6 @@ bool:@DefaultObjects_ParamType_CounterType_OnRead(const JSON:valueJson) { return ParamsController_SetCell(VipM_L_Counter_PerMap); } - PCJson_LogForFile(valueJson, "WARNING", "Counter type `%s` is not defined.", str); - + PCJson_LogForFile(valueJson, "WARNING", "Counter type `%s` is not defined. Available types: PerRound, PerLife, PerSession, PerGame, PerMap.", str); return false; } diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 74ca1f7..6eadec7 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -13,17 +13,12 @@ stock const __SLANG_TEMPLATE_STR[] = "%l"; stock const __CLANG_TEMPLATE_STR[] = "%L"; -stock const __JSON_FILE_TEMPLATE_STR[] = "%s.json"; stock const __LANG_MSG_LAYOUT_KEY[] = "MSG_LAYOUT"; stock const bool:__CompositeMacros_AlwaysFalse = false; #define CompositeMacros(%1) \ do { %1 } while(__CompositeMacros_AlwaysFalse) -stock GetCurrentRoundNum() { - return get_member_game(m_iTotalRoundsPlayed) + 1; -} - stock IntToStr(const int) { new str[11]; num_to_str(int, str, charsmax(str)); @@ -64,10 +59,6 @@ stock IsPlayerAlive(const playerIndex) { #define ChatPrintLIf(%3,%1,%2) \ ((%3) && ChatPrint(%1, __CLANG_TEMPLATE_STR, %1, %2)) -#define json_array_foreach(%1:%2) \ - if (json_is_array(%1)) \ - for (new %2 = 0; %2 < json_array_get_count(%1); %2++) - #define json_array_foreach_vars(%1:%2,[%3]) \ if (json_is_array(%1)) \ for (new %3, %2 = 0; %2 < json_array_get_count(%1); %2++) @@ -125,55 +116,6 @@ stock Array:json_object_get_strings_list( #define BitIs(%1,%2) \ (bool:(%1 & (1 << %2))) -stock bool:HasUserFlagsStr(const UserId, const sFlags[], const bool:bStrict = false) { - return HasUserFlags(UserId, read_flags(sFlags), bStrict); -} - -stock bool:HasUserFlags(const UserId, const bitFlags, const bool:bStrict = false) { - return HasBits(get_user_flags(UserId), bitFlags, bStrict); -} - -stock bool:HasBits(const bits, const bitSearch, const bool:bStrict = false) { - new bitRes = bits & bitSearch; - return bStrict - ? bitRes == bitSearch - : bitRes != 0 -} - -stock GetUserName(const playerIndex) { - new name[32]; - get_user_name(playerIndex, name, charsmax(name)); - return name; -} - -stock IsEqualUserName(const playerIndex, const name[]) { - return equal(GetUserName(playerIndex), name); -} - -stock GetWeekDayIdByName(const sWeekDayName[]) { - if (equali("Вс", sWeekDayName) || equali("Воскресенье", sWeekDayName) || equali("Sun", sWeekDayName) || equali("Sunday", sWeekDayName)) { - return 0; - } else if (equali("Пн", sWeekDayName) || equali("Понедельник", sWeekDayName) || equali("Mon", sWeekDayName) || equali("Monday", sWeekDayName)) { - return 1; - } else if (equali("Вт", sWeekDayName) || equali("Вторник", sWeekDayName) || equali("Tue", sWeekDayName) || equali("Tuesday", sWeekDayName)) { - return 2; - } else if (equali("Ср", sWeekDayName) || equali("Среда", sWeekDayName) || equali("Wed", sWeekDayName) || equali("Wednesday", sWeekDayName)) { - return 3; - } else if (equali("Чт", sWeekDayName) || equali("Четверг", sWeekDayName) || equali("Thu", sWeekDayName) || equali("Thursday", sWeekDayName)) { - return 4; - } else if (equali("Пт", sWeekDayName) || equali("Пятница", sWeekDayName) || equali("Fri", sWeekDayName) || equali("Friday", sWeekDayName)) { - return 5; - } else if (equali("Сб", sWeekDayName) || equali("Суббота", sWeekDayName) || equali("Sat", sWeekDayName) || equali("Saturday", sWeekDayName)) { - return 6; - } else { - return -1; - } -} - -stock CreateConstCvar(const sCvarName[], const sCvarValue[], const iFlags = FCVAR_SERVER) { - set_pcvar_string(create_cvar(sCvarName, sCvarValue, iFlags), sCvarValue); -} - #define CallOnce() CompositeMacros( \ static bool:__CallOnce_bCalled; \ if (__CallOnce_bCalled) return; \ @@ -214,25 +156,8 @@ stock InstantReloadActiveWeapon(const UserId) { } } -stock bool:StrEqualEx(const str1[], const str2[], const checkLength = 0, const bool:ignoreCase = false) { - return ignoreCase - ? equali(str1, str2, checkLength) - : equal(str1, str2, checkLength); -} - stock bool:IsUserInBuyZone(const UserId) { new Signal[UnifiedSignals]; get_member(UserId, m_signals, Signal); return ((SignalState:Signal[US_State] & SIGNAL_BUY) == SIGNAL_BUY); } - -stock ParseColonTime(const sTime[], const sColon[] = ":") { - new sHours[3], sMinutes[3]; - split(sTime, sHours, charsmax(sHours), sMinutes, charsmax(sMinutes), sColon); - - return ((clamp(str_to_num(sHours), 0, 23) * 60) + clamp(str_to_num(sMinutes), 0, 59)) * 60; -} - -stock GetDayTimeInSeconds() { - return get_systime() % (24 * 60 * 60); -} diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index b7b3523..6bb98f7 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -21,7 +21,7 @@ public stock const PluginDescription[] = "Modular vip system"; public plugin_precache() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_library(VIPM_LIBRARY); - CreateConstCvar("vipm_version", PluginVersion); + PCCvar_Const("vipm_version", PluginVersion); Forwards_Init(); From 909539aafc05a7d5c74cb5c177aaf458cc4b1b90 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 12 Oct 2025 23:38:39 +0300 Subject: [PATCH 071/108] Fix --- amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc index 50ce2d2..ca89a18 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -3,9 +3,9 @@ #include DefaultObjects_Limit_GameTime_Register() { - VipM_Limits_RegisterType("GameTime", true, false); + VipM_Limits_RegisterType("GameTime", false, false); VipM_Limits_AddTypeParams("GameTime", - "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, // TODO: Добавить типы "Time" в контроллер параметров + "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false ); VipM_Limits_RegisterTypeEvent("GameTime", Limit_OnCheck, "@DefaultObjects_Limit_GameTime_OnCheck"); From f928f148b1549e62e8b496226bd6c255057b937b Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 18 Oct 2025 20:29:47 +0300 Subject: [PATCH 072/108] Use consts for param types and merge changes from legacy version --- amxmodx/scripting/VipM-M-SpawnHealth.sma | 16 +- amxmodx/scripting/VipM-M-SpawnItems.sma | 4 +- amxmodx/scripting/VipM-M-Vampire.sma | 12 +- amxmodx/scripting/VipM-M-VipInTab.sma | 4 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 201 ++++++++++++----------- readme/extensions/modules/weapon-menu.md | 5 +- 6 files changed, 122 insertions(+), 120 deletions(-) diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index 5ab2a5d..3cabc1b 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -21,18 +21,18 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "Health", "Integer", false, - "SetHealth", "Boolean", false, - "MaxHealth", "Integer", false + "Health", DEFAULT_PARAMS_INT_NAME, false, + "SetHealth", DEFAULT_PARAMS_BOOL_NAME, false, + "MaxHealth", DEFAULT_PARAMS_INT_NAME, false ); VipM_Modules_AddParamsEx(MODULE_NAME, - "Armor", "Integer", false, - "SetArmor", "Boolean", false, - "MaxArmor", "Integer", false + "Armor", DEFAULT_PARAMS_INT_NAME, false, + "SetArmor", DEFAULT_PARAMS_BOOL_NAME, false, + "MaxArmor", DEFAULT_PARAMS_INT_NAME, false ); VipM_Modules_AddParamsEx(MODULE_NAME, - "Helmet", "Boolean", false, - "Limits", "VipM-Limits", false + "Helmet", DEFAULT_PARAMS_BOOL_NAME, false, + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index ab64b02..e44c5f6 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -23,8 +23,8 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "Items", "IC-Items", true, - "Limits", "VipM-Limits", false + "Items", IC_PARAM_TYPE_ITEMS_NAME, true, + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index 4ea104c..5f1ca3d 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -20,14 +20,14 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "ByKill", "Integer", false, - "ByHead", "Integer", false, - "ByKnife", "Integer", false, - "ByGrenade", "Integer", false + "ByKill", DEFAULT_PARAMS_INT_NAME, false, + "ByHead", DEFAULT_PARAMS_INT_NAME, false, + "ByKnife", DEFAULT_PARAMS_INT_NAME, false, + "ByGrenade", DEFAULT_PARAMS_INT_NAME, false ); VipM_Modules_AddParamsEx(MODULE_NAME, - "MaxHealth", "Integer", false, - "Limits", "VipM-Limits", false + "MaxHealth", DEFAULT_PARAMS_INT_NAME, false, + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index 1541cb7..b36176a 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -25,8 +25,8 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "Enabled", "Boolean", true, - "Override", "Boolean", false + "Enabled", DEFAULT_PARAMS_BOOL_NAME, true, + "Override", DEFAULT_PARAMS_BOOL_NAME, false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index ae1c61d..10e1af8 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -39,19 +39,20 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, // TODO Read "Menus" as param - "MainMenuTitle", "String", false, - "Count", "Integer", false, - "Limits", "VipM-Limits", false + "MainMenuTitle", DEFAULT_PARAMS_STR_NAME, false, + "Count", DEFAULT_PARAMS_INT_NAME, false, + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false, + "ResetCountOnSpawn", DEFAULT_PARAMS_BOOL_NAME, false ); VipM_Modules_AddParamsEx(MODULE_NAME, - "AutoopenLimits", "VipM-Limits", false, - "AutoopenDelay", "Float", false, - "AutoopenCloseDelay", "Float", false, - "AutoopenMenuNum", "Integer", false + "AutoopenLimits", VIPM_PARAM_TYPE_LIMITS_NAME, false, + "AutoopenDelay", DEFAULT_PARAMS_FLOAT_NAME, false, + "AutoopenCloseDelay", DEFAULT_PARAMS_FLOAT_NAME, false, + "AutoopenMenuNum", DEFAULT_PARAMS_INT_NAME, false ); VipM_Modules_AddParamsEx(MODULE_NAME, - "StayOpen", "Boolean", false, - "StayOpen_CheckCounter", "Boolean", false + "StayOpen", DEFAULT_PARAMS_BOOL_NAME, false, + "StayOpen_CheckCounter", DEFAULT_PARAMS_BOOL_NAME, false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnRead, "@OnReadConfig"); @@ -81,148 +82,148 @@ public VipM_Modules_OnInited() { register_clcmd(VIPM_M_WEAPONMENU_CMD_AUTOOPEN_TOGGLE, "@Cmd_SwitchAutoOpen"); } -ResetUserMenuCounters(const UserId) { - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); +ResetUserMenuCounters(const playerIndex) { + new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, playerIndex); - gUserLeftItems[UserId] = PCGet_Int(Params, "Count", -1); - g_tUserMenuItemsCounter[UserId] = KeyValueCounter_Reset(g_tUserMenuItemsCounter[UserId]); + gUserLeftItems[playerIndex] = PCGet_Int(Params, "Count", -1); + g_tUserMenuItemsCounter[playerIndex] = KeyValueCounter_Reset(g_tUserMenuItemsCounter[playerIndex]); - gUserShouldResetCounters[UserId] = false; + gUserShouldResetCounters[playerIndex] = false; - Dbg_Log("ResetUserMenuCounters(%n): gUserLeftItems[UserId] = %d", UserId, gUserLeftItems[UserId]); + Dbg_Log("ResetUserMenuCounters(%n): gUserLeftItems[playerIndex] = %d", playerIndex, gUserLeftItems[playerIndex]); } -public client_putinserver(UserId) { - gUserShouldResetCounters[UserId] = true; - gUserExpireStatus[UserId][0] = 0; +public client_putinserver(playerIndex) { + gUserShouldResetCounters[playerIndex] = true; + gUserExpireStatus[playerIndex][0] = 0; } -public client_disconnected(UserId) { - AbortAutoCloseMenu(UserId); +public client_disconnected(playerIndex) { + AbortAutoCloseMenu(playerIndex); } @OnRestartRound() { - for (new UserId = 1; UserId <= MAX_PLAYERS; UserId++) { - gUserShouldResetCounters[UserId] = true; + for (new playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++) { + gUserShouldResetCounters[playerIndex] = true; } Dbg_Log("@OnRestartRound(): Should reset all counters."); } -@OnPlayerSpawn(const UserId) { - if (!IsPlayerAlive(UserId)) { - Dbg_Log("@OnPlayerSpawn(%n): Invalid (or dead) player", UserId); +@OnPlayerSpawn(const playerIndex) { + if (!IsPlayerAlive(playerIndex)) { + Dbg_Log("@OnPlayerSpawn(%n): Invalid (or dead) player", playerIndex); return; } - if (gUserShouldResetCounters[UserId]) { - ResetUserMenuCounters(UserId); + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); + + if (gUserShouldResetCounters[playerIndex] || PCGet_Bool(p, "ResetCountOnSpawn", false)) { + ResetUserMenuCounters(playerIndex); } else { - Dbg_Log("@OnPlayerSpawn(%n): Shouldn't reset counter", UserId); + Dbg_Log("@OnPlayerSpawn(%n): Shouldn't reset counter", playerIndex); } // TODO: Добавить квар для отключения авто-открытия - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); - - if (!gUserAutoOpen[UserId]) { + if (!gUserAutoOpen[playerIndex]) { return; } - if (VipM_Params_GetArr(Params, "Menus") == Invalid_Array) { + if (VipM_Params_GetArr(p, "Menus") == Invalid_Array) { return; } - if (!PCGet_VipmLimitsCheck(Params, "AutoopenLimits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(p, "AutoopenLimits", playerIndex, Limit_Exec_AND)) { return; } - set_task(PCGet_Float(Params, "AutoopenDelay", 0.0), "@Task_AutoOpen", TASK_OFFSET_AUTO_OPEN + UserId); + set_task(PCGet_Float(p, "AutoopenDelay", 0.0), "@Task_AutoOpen", TASK_OFFSET_AUTO_OPEN + playerIndex); } -@Task_AutoOpen(UserId) { - UserId -= TASK_OFFSET_AUTO_OPEN; +@Task_AutoOpen(playerIndex) { + playerIndex -= TASK_OFFSET_AUTO_OPEN; - new Trie:tParams = VipM_Modules_GetParams(MODULE_NAME, UserId); + new Trie:tParams = VipM_Modules_GetParams(MODULE_NAME, playerIndex); new Float:fAutoCloseDelay = PCGet_Float(tParams, "AutoopenCloseDelay", 0.0); new iMenuNum = PCGet_Int(tParams, "AutoopenMenuNum", -1); if (iMenuNum > 0) { - client_cmd(UserId, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU_SILENT, iMenuNum - 1); + client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU_SILENT, iMenuNum - 1); } else { - client_cmd(UserId, VIPM_M_WEAPONMENU_CMD_MENU_SILENT); + client_cmd(playerIndex, VIPM_M_WEAPONMENU_CMD_MENU_SILENT); } - Dbg_Log("@Task_AutoOpen(%d): fAutoCloseDelay = %.2f", UserId, fAutoCloseDelay); + Dbg_Log("@Task_AutoOpen(%d): fAutoCloseDelay = %.2f", playerIndex, fAutoCloseDelay); if (fAutoCloseDelay > 0.0) { - Dbg_Log("@Task_AutoOpen(%d): Start auto close task", UserId); - set_task(fAutoCloseDelay, "@Task_AutoClose", TASK_OFFSET_AUTO_CLOSE + UserId); + Dbg_Log("@Task_AutoOpen(%d): Start auto close task", playerIndex); + set_task(fAutoCloseDelay, "@Task_AutoClose", TASK_OFFSET_AUTO_CLOSE + playerIndex); } } -@Task_AutoClose(UserId) { - Dbg_Log("@Task_AutoClose(%d)", UserId); - UserId -= TASK_OFFSET_AUTO_CLOSE; - menu_cancel(UserId); - show_menu(UserId, 0, ""); +@Task_AutoClose(playerIndex) { + Dbg_Log("@Task_AutoClose(%d)", playerIndex); + playerIndex -= TASK_OFFSET_AUTO_CLOSE; + menu_cancel(playerIndex); + show_menu(playerIndex, 0, ""); } -AbortAutoCloseMenu(const UserId) { - remove_task(TASK_OFFSET_AUTO_CLOSE + UserId); +AbortAutoCloseMenu(const playerIndex) { + remove_task(TASK_OFFSET_AUTO_CLOSE + playerIndex); } -@Cmd_SwitchAutoOpen(const UserId) { - gUserAutoOpen[UserId] = !gUserAutoOpen[UserId]; - ChatPrintL(UserId, gUserAutoOpen[UserId] ? "MSG_AUTOOPEN_TURNED_ON" : "MSG_AUTOOPEN_TURNED_OFF"); +@Cmd_SwitchAutoOpen(const playerIndex) { + gUserAutoOpen[playerIndex] = !gUserAutoOpen[playerIndex]; + ChatPrintL(playerIndex, gUserAutoOpen[playerIndex] ? "MSG_AUTOOPEN_TURNED_ON" : "MSG_AUTOOPEN_TURNED_OFF"); return PLUGIN_HANDLED; } -@Cmd_Menu(const UserId) { - _Cmd_Menu(UserId); +@Cmd_Menu(const playerIndex) { + _Cmd_Menu(playerIndex); return PLUGIN_HANDLED; } -@Cmd_MenuSilent(const UserId) { - _Cmd_Menu(UserId, true); +@Cmd_MenuSilent(const playerIndex) { + _Cmd_Menu(playerIndex, true); return PLUGIN_HANDLED; } -_Cmd_Menu(const UserId, const bool:bSilent = false) { - if (!IsPlayerValid(UserId)) { - Dbg_Log("_Cmd_Menu(%d, %s): Invalid player", UserId, bSilent ? "true" : "false"); +_Cmd_Menu(const playerIndex, const bool:bSilent = false) { + if (!IsPlayerValid(playerIndex)) { + Dbg_Log("_Cmd_Menu(%d, %s): Invalid player", playerIndex, bSilent ? "true" : "false"); return; } - if (!is_user_alive(UserId)) { - ChatPrintLIf(!bSilent, UserId, "MSG_YOU_DEAD"); + if (!is_user_alive(playerIndex)) { + ChatPrintLIf(!bSilent, playerIndex, "MSG_YOU_DEAD"); - Dbg_Log("_Cmd_Menu(%n, %s): Player is dead", UserId, bSilent ? "true" : "false"); + Dbg_Log("_Cmd_Menu(%n, %s): Player is dead", playerIndex, bSilent ? "true" : "false"); return; } - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); + new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, playerIndex); new Array:aMenus = VipM_Params_GetArr(Params, "Menus"); if (ArraySizeSafe(aMenus) < 1) { - ChatPrintLIf(!bSilent, UserId, "MSG_NO_ACCESS"); + ChatPrintLIf(!bSilent, playerIndex, "MSG_NO_ACCESS"); - Dbg_Log("_Cmd_Menu(%n, %s): No access", UserId, bSilent ? "true" : "false"); + Dbg_Log("_Cmd_Menu(%n, %s): No access", playerIndex, bSilent ? "true" : "false"); return; } - if (!PCGet_VipmLimitsCheck(Params, "Limits", UserId, Limit_Exec_AND)) { - ChatPrintLIf(!bSilent, UserId, "MSG_MAIN_NOT_PASSED_LIMIT"); + if (!PCGet_VipmLimitsCheck(Params, "Limits", playerIndex, Limit_Exec_AND)) { + ChatPrintLIf(!bSilent, playerIndex, "MSG_MAIN_NOT_PASSED_LIMIT"); - Dbg_Log("_Cmd_Menu(%n, %s): Not passed main limits", UserId, bSilent ? "true" : "false"); + Dbg_Log("_Cmd_Menu(%n, %s): Not passed main limits", playerIndex, bSilent ? "true" : "false"); return; } if (read_argc() < 2) { if (ArraySizeSafe(aMenus) == 1) { - client_cmd(UserId, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, 0); + client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, 0); } else { static MainMenuTitle[128]; PCGet_Str(Params, "MainMenuTitle", MainMenuTitle, charsmax(MainMenuTitle)); - Menu_MainMenu(UserId, MainMenuTitle, aMenus); + Menu_MainMenu(playerIndex, MainMenuTitle, aMenus); } return; } @@ -232,27 +233,27 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { ArraySizeSafe(aMenus) <= MenuId || MenuId < 0 ) { - Dbg_Log("_Cmd_Menu(%n, %s): Invalid menu id (%d)", UserId, bSilent ? "true" : "false", MenuId); + Dbg_Log("_Cmd_Menu(%n, %s): Invalid menu id (%d)", playerIndex, bSilent ? "true" : "false", MenuId); return; } static Menu[S_WeaponMenu]; ArrayGetArray(aMenus, MenuId, Menu); - if (Menu[WeaponMenu_Limits] != Invalid_Array && !VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], UserId, Limit_Exec_AND)) { - ChatPrintLIf(!bSilent, UserId, "MSG_MENU_NOT_PASSED_LIMIT"); - Dbg_Log("_Cmd_Menu(%n, %s): Not passed menu limits", UserId, bSilent ? "true" : "false"); + if (Menu[WeaponMenu_Limits] != Invalid_Array && !VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], playerIndex, Limit_Exec_AND)) { + ChatPrintLIf(!bSilent, playerIndex, "MSG_MENU_NOT_PASSED_LIMIT"); + Dbg_Log("_Cmd_Menu(%n, %s): Not passed menu limits", playerIndex, bSilent ? "true" : "false"); return; } if (Menu[WeaponMenu_FakeMessage][0]) { - ChatPrint(UserId, Menu[WeaponMenu_FakeMessage]); - Dbg_Log("_Cmd_Menu(%n, %s): Fake menu (%s)", UserId, bSilent ? "true" : "false", Menu[WeaponMenu_FakeMessage]); + ChatPrint(playerIndex, Menu[WeaponMenu_FakeMessage]); + Dbg_Log("_Cmd_Menu(%n, %s): Fake menu (%s)", playerIndex, bSilent ? "true" : "false", Menu[WeaponMenu_FakeMessage]); return; } if (read_argc() < 3) { - Menu_WeaponsMenu(UserId, MenuId, Menu); + Menu_WeaponsMenu(playerIndex, MenuId, Menu); return; } @@ -261,44 +262,44 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { ArraySizeSafe(Menu[WeaponMenu_Items]) <= ItemId || ItemId < 0 ) { - Dbg_Log("_Cmd_Menu(%n, %s): Invalid item id (%d)", UserId, bSilent ? "true" : "false", ItemId); + Dbg_Log("_Cmd_Menu(%n, %s): Invalid item id (%d)", playerIndex, bSilent ? "true" : "false", ItemId); return; } static MenuItem[S_MenuItem]; ArrayGetArray(Menu[WeaponMenu_Items], ItemId, MenuItem); - new iItemsLeft = GetUserLeftItems(UserId, MenuId, Menu); + new iItemsLeft = GetUserLeftItems(playerIndex, MenuId, Menu); if ( MenuItem[MenuItem_UseCounter] && iItemsLeft == 0 ) { - ChatPrintLIf(!bSilent, UserId, "MSG_NO_LEFT_ITEMS"); + ChatPrintLIf(!bSilent, playerIndex, "MSG_NO_LEFT_ITEMS"); - Dbg_Log("_Cmd_Menu(%n, %s): No left items", UserId, bSilent ? "true" : "false"); + Dbg_Log("_Cmd_Menu(%n, %s): No left items", playerIndex, bSilent ? "true" : "false"); return; } if ( - !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId, Limit_Exec_AND) - || !VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId, Limit_Exec_AND) - || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], UserId, Limit_Exec_AND) + !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], playerIndex, Limit_Exec_AND) + || !VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], playerIndex, Limit_Exec_AND) + || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], playerIndex, Limit_Exec_AND) ) { - ChatPrintLIf(!bSilent, UserId, "MSG_MENUITEM_NOT_PASSED_LIMIT"); + ChatPrintLIf(!bSilent, playerIndex, "MSG_MENUITEM_NOT_PASSED_LIMIT"); - Dbg_Log("_Cmd_Menu(%n, %s): Not passed item limits", UserId, bSilent ? "true" : "false"); + Dbg_Log("_Cmd_Menu(%n, %s): Not passed item limits", playerIndex, bSilent ? "true" : "false"); return; } if ( - IC_Item_GiveArray(UserId, MenuItem[MenuItem_Items]) + IC_Item_GiveArray(playerIndex, MenuItem[MenuItem_Items]) && MenuItem[MenuItem_UseCounter] ) { - gUserLeftItems[UserId]--; + gUserLeftItems[playerIndex]--; if (Menu[WeaponMenu_Count]) { - KeyValueCounter_Inc(g_tUserMenuItemsCounter[UserId], IntToStr(MenuId)); + KeyValueCounter_Inc(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId)); } } @@ -309,30 +310,30 @@ _Cmd_Menu(const UserId, const bool:bSilent = false) { || iItemsLeft != 0 ) ) { - client_cmd(UserId, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, MenuId); + client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, MenuId); } } -GetUserLeftItems(const UserId, const MenuId, const Menu[S_WeaponMenu]) { - new iUserItemsLeft = gUserLeftItems[UserId]; - new iMenuItemsLeft = Menu[WeaponMenu_Count] - KeyValueCounter_Get(g_tUserMenuItemsCounter[UserId], IntToStr(MenuId)); +GetUserLeftItems(const playerIndex, const MenuId, const Menu[S_WeaponMenu]) { + new iUserItemsLeft = gUserLeftItems[playerIndex]; + new iMenuItemsLeft = Menu[WeaponMenu_Count] - KeyValueCounter_Get(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId)); - Dbg_Log("GetUserLeftItems(%n, %d, %d): iUserItemsLeft = %d", UserId, MenuId, Menu[WeaponMenu_Name], iUserItemsLeft); - Dbg_Log("GetUserLeftItems(%n, %d, %d): iMenuItemsLeft = %d", UserId, MenuId, Menu[WeaponMenu_Name], iMenuItemsLeft); - Dbg_Log("GetUserLeftItems(%n, %d, %d): Menu[WeaponMenu_Count] = %d", UserId, MenuId, Menu[WeaponMenu_Name], Menu[WeaponMenu_Count]); - Dbg_Log("GetUserLeftItems(%n, %d, %d): g_tUserMenuItemsCounter[UserId] = %d", UserId, MenuId, Menu[WeaponMenu_Name], KeyValueCounter_Get(g_tUserMenuItemsCounter[UserId], IntToStr(MenuId))); + Dbg_Log("GetUserLeftItems(%n, %d, %d): iUserItemsLeft = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], iUserItemsLeft); + Dbg_Log("GetUserLeftItems(%n, %d, %d): iMenuItemsLeft = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], iMenuItemsLeft); + Dbg_Log("GetUserLeftItems(%n, %d, %d): Menu[WeaponMenu_Count] = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], Menu[WeaponMenu_Count]); + Dbg_Log("GetUserLeftItems(%n, %d, %d): g_tUserMenuItemsCounter[playerIndex] = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], KeyValueCounter_Get(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId))); if (iUserItemsLeft < 0) { - Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (no global limit)", UserId, MenuId, Menu[WeaponMenu_Name], iMenuItemsLeft); + Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (no global limit)", playerIndex, MenuId, Menu[WeaponMenu_Name], iMenuItemsLeft); return iMenuItemsLeft; } if (Menu[WeaponMenu_Count] < 0) { - Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (no menu limit)", UserId, MenuId, Menu[WeaponMenu_Name], iUserItemsLeft); + Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (no menu limit)", playerIndex, MenuId, Menu[WeaponMenu_Name], iUserItemsLeft); return iUserItemsLeft; } - Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (has both limits)", UserId, MenuId, Menu[WeaponMenu_Name], min(iUserItemsLeft, iMenuItemsLeft)); + Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (has both limits)", playerIndex, MenuId, Menu[WeaponMenu_Name], min(iUserItemsLeft, iMenuItemsLeft)); return min(iUserItemsLeft, iMenuItemsLeft); } diff --git a/readme/extensions/modules/weapon-menu.md b/readme/extensions/modules/weapon-menu.md index d91d87d..54b5394 100644 --- a/readme/extensions/modules/weapon-menu.md +++ b/readme/extensions/modules/weapon-menu.md @@ -11,12 +11,13 @@ _Данный модуль использует [контроллер предм | MainMenuTitle | Нет | Строка | Загловок главного меню. По умолчанию будет `MENU_MAIN_TITLE` из ланг-файла | | Menus | Да | [Массив обьектов меню](#поля-обьекта-меню) | Обьекты доступных меню. Поддерживает ссылки. | | Count | Нет | Ц.Число | Сколько предметов за раунд можно взять из всех меню. По умолчанию неограничено | +| ResetCountOnSpawn | Нет | `true`/`false` | Сбрасывать ли счётчик предметов при спавне, иначе в начале раунда. По умолчанию `false` | | Limits | Нет | Массив [лимитов](/readme/extensions/limits.md) | Условия, при которых меню будет доступно | | | | | | | AutoopenLimits | Нет | Массив [лимитов](/readme/extensions/limits.md) | Условия, при которых будет срабатывать автоматическое открытие меню | -| AutoopenDelay | Нет | Д.Число | Задержка перед автоматическим открытием меню в секундах. По умолчанию `0.0` | +| AutoopenDelay | Нет | Д.Число | Задержка перед автоматическим открытием меню в секундах. По умолчанию `0.0` | | AutoopenCloseDelay | Нет | Д.Число | Время перед автоматическим закрытием после автоматического открытия меню в секундах | -| AutoopenMenuNum | Нет | Ц.Число | Порядковый номер оружейного меню из параметра `Menus`, которое будет открыто при автоматическом открытии. Если | +| AutoopenMenuNum | Нет | Ц.Число | Порядковый номер оружейного меню из параметра `Menus`, которое будет открыто при автоматическом открытии. Если | | | | | | | StayOpen | Нет | `true`/`false` | Оставлять ли оружейное меню открытым после выбора пункта. По умолчанию `false` | | StayOpen_CheckCounter | Нет | `true`/`false` | Проверять ли остаток предметов при повторном открытии оружейного меню при `StayOpen: true`. По умолчанию `false` | From fd4cef2f77bb6ef2938d5f6706ccf42e1661839b Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 19 Oct 2025 14:47:46 +0300 Subject: [PATCH 073/108] Some refactor and update ci script --- .github/workflows/CI.yml | 60 ++++++++++++++-- amxmodx/scripting/VipM-M-SpawnHealth.sma | 30 ++++---- amxmodx/scripting/VipM-M-SpawnItems.sma | 29 +++----- amxmodx/scripting/VipM-M-Vampire.sma | 56 ++++++++------- amxmodx/scripting/VipM-M-VipInTab.sma | 24 +++---- amxmodx/scripting/VipM-M-WeaponMenu.sma | 54 +++------------ amxmodx/scripting/VipM-ModulesLimiter.sma | 69 +++++++++---------- amxmodx/scripting/VipM/ArrayTrieUtils.inc | 8 --- .../scripting/VipM/Core/Objects/VipUnit.inc | 2 +- amxmodx/scripting/VipM/Core/SrvCmds.inc | 49 +++++++------ .../VipM/DefaultObjects/Limit/GameTime.inc | 2 + amxmodx/scripting/VipM/Utils.inc | 14 ---- amxmodx/scripting/VipM/WeaponMenu/Menus.inc | 4 +- amxmodx/scripting/include/VipM/Limits.inc | 4 +- amxmodx/scripting/include/VipModular.inc | 2 +- readme/default-extensions.md | 64 +---------------- readme/extensions/items/command.md | 26 +------ readme/extensions/items/defuse-kit.md | 16 +---- readme/extensions/items/items-list.md | 32 +-------- readme/extensions/items/weapon.md | 29 +------- readme/thirdparty-extensions.md | 26 +------ 21 files changed, 194 insertions(+), 406 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9f00a17..63a527d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [master] + branches: [master, feature/**, fix/**] paths-ignore: - "**.md" @@ -14,8 +14,11 @@ on: env: PACKAGE_NAME: VipModular STORE_README: 0 - GENERATE_PLUGINS_INI: 1 + PLUGINS_INI_GENERATE: 1 PLUGINS_INI_POSTFIX: vipm + DEPS_LIST: | + AmxxModularEcosystem/ParamsController@1.2.0 + AmxxModularEcosystem/CommandAliases@1.0.1 jobs: build: @@ -52,6 +55,7 @@ jobs: - name: Setup latest ReAPI includes env: REPO: "rehlds/ReAPI" + OUTPUT_VAR_NAME: REAPI_INCLUDE_PATH run: | mkdir -p dep/reapi cd dep/reapi @@ -64,7 +68,49 @@ jobs: 7z x *.zip - echo "REAPI_INCLUDE_PATH=$(pwd)/addons/amxmodx/scripting/include" >> $GITHUB_ENV + echo "${OUTPUT_VAR_NAME}=$(pwd)/addons/amxmodx/scripting/include" >> $GITHUB_ENV + + - name: Setup deps includes + env: + DEPS_LIST: ${{ env.DEPS_LIST }} + OUTPUT_VAR_NAME: DEPS_COMPILER_ARGS + run: | + handleDep() { + REPO=`echo $1 | grep -Po '.+(?=@)'` + TAG=`echo $1 | grep -Po '(?<=@).+(?=:)'` + OVERRIDE_INCLUDE_PATH=`echo $1 | grep -Po '(?<=:).+'` + + if [ -z "$REPO" ]; then + echo "No repo provided" + exit 1 + fi + + INIT_PWD=$(pwd) + mkdir -p dep/${REPO} + cd dep/${REPO} + + if [ -z "$2" ]; then + TAG=`curl --silent https://api.github.com/repos/${REPO}/releases/latest | jq .tag_name -r` + else + TAG=$2 + fi + + wget https://github.com/${REPO}/archive/refs/tags/${TAG}.zip + 7z x ${TAG}.zip + + REPO_NAME=`echo "${REPO}" | grep -Po '(?<=\/).+'` + INCLUDE_PATH='$(pwd)/${REPO_NAME}-${TAG}/${OVERRIDE_INCLUDE_PATH:-amxmodx/scripting/include}' + + echo "${OUTPUT_VAR_NAME}=\"\${${OUTPUT_VAR_NAME}} -i\\\"${INCLUDE_PATH}\\\"\"" >> $GITHUB_ENV + + cd $INIT_PWD + } + + deps=$(echo ${DEPS_LIST} | tr ";" "\n") + for dep in $deps + do + handleDep $dep + done - name: Setup AMXXPawn Compiler uses: wopox1337/setup-amxxpawn@v1.1.0 @@ -75,8 +121,9 @@ jobs: working-directory: amxmodx/scripting/ env: REAPI_INCLUDE: ${{ env.REAPI_INCLUDE_PATH }} - GENERATE_PLUGINS_INI: ${{ env.GENERATE_PLUGINS_INI }} + PLUGINS_INI_GENERATE: ${{ env.PLUGINS_INI_GENERATE }} PLUGINS_INI_POSTFIX: ${{ env.PLUGINS_INI_POSTFIX }} + DEPS_COMPILER_ARGS: ${{ env.DEPS_COMPILER_ARGS }} run: | compile() { sourcefile=$1 @@ -89,9 +136,10 @@ jobs: amxxpc $sourcefile -o"$output_path" \ -i"include" \ -i"$REAPI_INCLUDE" \ - -i"$PARAMS_CONRTOLLER_INCLUDE" + ${DEPS_COMPILER_ARGS} \ + GITHUB_ACTIONS_USED=1 - if [ ! -z "${GENERATE_PLUGINS_INI}" ]; then + if [ ! -z "${PLUGINS_INI_GENERATE}" ]; then plugin_ini_path="../configs/plugins-${PLUGINS_INI_POSTFIX}.ini" touch $plugin_ini_path echo $amxxfile >> $plugin_ini_path diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index 3cabc1b..236b31b 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -1,12 +1,6 @@ #include #include #include -#include "VipM/Utils" -#include "VipM/DebugMode" -#include "VipM/ArrayTrieUtils" - -#pragma semicolon 1 -#pragma compress 1 public stock const PluginName[] = "[VipM-M] Spawn Health"; public stock const PluginVersion[] = _VIPM_VERSION; @@ -41,35 +35,39 @@ public VipM_Modules_OnInited() { RegisterHookChain(RG_CBasePlayer_Spawn, "@Event_PlayerSpawned", true); } -@Event_PlayerSpawned(const UserId) { - if (!is_user_alive(UserId)) { +@Event_PlayerSpawned(const playerIndex) { + if (!is_user_alive(playerIndex)) { return; } - if (!VipM_Modules_HasModule(MODULE_NAME, UserId)) { + if (!VipM_Modules_HasModule(MODULE_NAME, playerIndex)) { return; } - new Trie:p = VipM_Modules_GetParams(MODULE_NAME, UserId); + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); - if (!PCGet_VipmLimitsCheck(p, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND)) { return; } + new maxHealth = PCGet_Int(p, "MaxHealth", floatround(get_entvar(playerIndex, var_max_health))); + set_entvar(playerIndex, var_max_health, float(maxHealth)); + new health = PCGet_Int(p, "Health", 0); - new maxHealth = PCGet_Int(p, "MaxHealth", floatround(Float:get_entvar(UserId, var_max_health))); if (health > 0) { if (!PCGet_Bool(p, "SetHealth", true)) { - health = min(floatround(get_entvar(UserId, var_health)) + health, maxHealth); + health = min(floatround(get_entvar(playerIndex, var_health)) + health, maxHealth); } - set_entvar(UserId, var_health, float(health)); + + set_entvar(playerIndex, var_health, float(health)); } new armor = PCGet_Int(p, "Armor", 0); if (armor > 0) { if (!PCGet_Bool(p, "SetArmor", true)) { - armor = min(rg_get_user_armor(UserId) + armor, PCGet_Int(p, "MaxArmor", 100)); + armor = min(rg_get_user_armor(playerIndex) + armor, PCGet_Int(p, "MaxArmor", 100)); } - rg_set_user_armor(UserId, armor, PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); + + rg_set_user_armor(playerIndex, armor, PCGet_Bool(p, "Helmet", false) ? ARMOR_VESTHELM : ARMOR_KEVLAR); } } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index e44c5f6..dca64a1 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -3,11 +3,6 @@ #include #include #include -#include "VipM/Utils" -#include "VipM/DebugMode" - -#include "VipM/Utils" -#include "VipM/ArrayTrieUtils" public stock const PluginName[] = "[VipM-M] Spawn Items"; public stock const PluginVersion[] = _VIPM_VERSION; @@ -33,32 +28,24 @@ public VipM_Modules_OnInited() { RegisterHookChain(RG_CBasePlayer_Spawn, "@OnPlayerSpawned", true); } -@OnPlayerSpawned(const UserId) { - Dbg_Log("@OnPlayerSpawned(%n) Spawned, request frame", UserId); - RequestFrame("@GivePlayerItems", UserId); +@OnPlayerSpawned(const playerIndex) { + RequestFrame("@GivePlayerItems", playerIndex); } -@GivePlayerItems(const UserId) { - if (!is_user_alive(UserId)) { - Dbg_Log("@GivePlayerItems(%n) Dead", UserId); +@GivePlayerItems(const playerIndex) { + if (!is_user_alive(playerIndex)) { return; } - if (!VipM_Modules_HasModule(MODULE_NAME, UserId)) { - Dbg_Log("@GivePlayerItems(%n) Has not module", UserId); + if (!VipM_Modules_HasModule(MODULE_NAME, playerIndex)) { return; } - new Trie:p = VipM_Modules_GetParams(MODULE_NAME, UserId); + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); - if (!PCGet_VipmLimitsCheck(p, "Limits", UserId, Limit_Exec_AND)) { - Dbg_Log("@GivePlayerItems(%n) Limits not passed", UserId); + if (!PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND)) { return; } - if (PCGet_IcItemsGive(p, "Items", UserId)) { - Dbg_Log("@GivePlayerItems(%n) Items given", UserId); - } else { - Dbg_Log("@GivePlayerItems(%n) Items not given", UserId); - } + PCGet_IcItemsGive(p, "Items", playerIndex); } diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index 5f1ca3d..e52c847 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -1,10 +1,6 @@ #include #include #include -#include "VipM/Utils" - -#pragma semicolon 1 -#pragma compress 1 public stock const PluginName[] = "[VipM-M] Vampire"; public stock const PluginVersion[] = _VIPM_VERSION; @@ -36,52 +32,54 @@ public VipM_Modules_OnInited() { RegisterHookChain(RG_CBasePlayer_Killed, "@Event_PlayerKilled", true); } -@Event_PlayerKilled(const VictimId, UserId, InflictorId) { +@Event_PlayerKilled(const victimIndex, playerIndex, inflictorIndex) { if ( - UserId == VictimId - || !is_user_alive(UserId) - || !is_user_connected(VictimId) + playerIndex == victimIndex + || !is_user_alive(playerIndex) + || !is_user_connected(victimIndex) ) { return; } - new Trie:p = VipM_Modules_GetParams(MODULE_NAME, UserId); + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); if (p == Invalid_Trie) { return; } - if (!PCGet_VipmLimitsCheck(p, "Limits", UserId, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND)) { return; } - new MaxHealth = PCGet_Int(p, "MaxHealth", 100); - new Health = floatround(get_entvar(UserId, var_health)); - if (Health >= MaxHealth) { + new maxHealth = PCGet_Int(p, "MaxHealth", floatround(get_entvar(playerIndex, var_max_health))); + new currentHealth = floatround(get_entvar(playerIndex, var_health)); + if (currentHealth >= maxHealth) { return; } - new ByKill = PCGet_Int(p, "ByKill", 0); - new VampHealth = 0; - new ActiveItem; ActiveItem = get_member(UserId, m_pActiveItem); + new healthByKill = PCGet_Int(p, "ByKill", 0); + new addHealth = 0; + new activeItem = get_member(playerIndex, m_pActiveItem); + if ( - !(get_member(VictimId, m_bitsDamageType) & DMG_SLASH) - && is_entity(ActiveItem) - && rg_get_iteminfo(ActiveItem, ItemInfo_iId) == CSW_KNIFE + !(get_member(victimIndex, m_bitsDamageType) & DMG_SLASH) + && is_entity(activeItem) + && rg_get_iteminfo(activeItem, ItemInfo_iId) == CSW_KNIFE ) { - VampHealth = PCGet_Int(p, "ByKnife", ByKill); - } else if(get_member(VictimId, m_bHeadshotKilled)) { - VampHealth = PCGet_Int(p, "ByHead", ByKill); - } else if (get_member(VictimId, m_bKilledByGrenade)) { - VampHealth = PCGet_Int(p, "ByGrenade", ByKill); + addHealth = PCGet_Int(p, "ByKnife", healthByKill); + } else if(get_member(victimIndex, m_bHeadshotKilled)) { + addHealth = PCGet_Int(p, "ByHead", healthByKill); + } else if (get_member(victimIndex, m_bKilledByGrenade)) { + addHealth = PCGet_Int(p, "ByGrenade", healthByKill); } else { - VampHealth = ByKill; + addHealth = healthByKill; } - if (ByKill <= 0) { + if (addHealth <= 0) { return; } - client_print(UserId, print_center, "%L", UserId, "VAMPIRE_HEALTH_MESSAGE", VampHealth); - Health = clamp(Health + VampHealth, 1, MaxHealth < 1 ? cellmax : MaxHealth); - set_entvar(UserId, var_health, float(Health)); + new newHealth = clamp(currentHealth + addHealth, 1, maxHealth < 1 ? cellmax : maxHealth); + set_entvar(playerIndex, var_health, float(newHealth)); + + client_print(playerIndex, print_center, "%L", playerIndex, "VAMPIRE_HEALTH_MESSAGE", addHealth); } diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index b36176a..2b0e7bd 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -1,9 +1,5 @@ #include #include -#include "VipM/Utils" - -#pragma semicolon 1 -#pragma compress 1 enum E_ModuleParams { Param_Enabled = 0, @@ -14,11 +10,11 @@ public stock const PluginName[] = "[VipM-M] Vip in TAB"; public stock const PluginVersion[] = _VIPM_VERSION; public stock const PluginAuthor[] = "ArKaNeMaN"; public stock const PluginURL[] = _VIPM_PLUGIN_URL; -public stock const PluginDescription[] = "Vip modular`s module - VipInTab"; +public stock const PluginDescription[] = "[VipModular-Module] Show VIP status in TAB."; new const MODULE_NAME[] = "VipInTab"; -new bool:gHasTag[MAX_PLAYERS + 1][E_ModuleParams]; +new bool:PlayerSettings[MAX_PLAYERS + 1][E_ModuleParams]; public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); @@ -31,25 +27,25 @@ public VipM_Modules_OnInited() { VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } -public VipM_OnUserUpdated(const UserId) { - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, UserId); +public VipM_OnUserUpdated(const playerIndex) { + new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, playerIndex); - gHasTag[UserId][Param_Enabled] = PCGet_Bool(Params, "Enabled", false); - gHasTag[UserId][Param_Override] = PCGet_Bool(Params, "Override", false); + PlayerSettings[playerIndex][Param_Enabled] = PCGet_Bool(Params, "Enabled", false); + PlayerSettings[playerIndex][Param_Override] = PCGet_Bool(Params, "Override", false); } @OnModuleActivate() { register_message(get_user_msgid("ScoreAttrib"), "@OnMsgScoreAttrib"); } -@OnMsgScoreAttrib(const MsgId, const MsgType, const MsgDest) { - new UserId = get_msg_arg_int(1); - if (!gHasTag[UserId][Param_Enabled]) { +@OnMsgScoreAttrib(const messageIndex, const messageType, const messageDestination) { + new playerIndex = get_msg_arg_int(1); + if (!PlayerSettings[playerIndex][Param_Enabled]) { return; } if ( - !gHasTag[UserId][Param_Override] + !PlayerSettings[playerIndex][Param_Override] && get_msg_arg_int(2) != 0 ) { return; diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 10e1af8..6c132c5 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -3,7 +3,6 @@ #include #include #include "VipM/Utils" -#include "VipM/DebugMode" #include "VipM/WeaponMenu/Objects/WeaponMenu" #include "VipM/WeaponMenu/Objects/MenuItem" @@ -38,7 +37,7 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - // TODO Read "Menus" as param + // TODO: Read "Menus" as param "MainMenuTitle", DEFAULT_PARAMS_STR_NAME, false, "Count", DEFAULT_PARAMS_INT_NAME, false, "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false, @@ -89,8 +88,6 @@ ResetUserMenuCounters(const playerIndex) { g_tUserMenuItemsCounter[playerIndex] = KeyValueCounter_Reset(g_tUserMenuItemsCounter[playerIndex]); gUserShouldResetCounters[playerIndex] = false; - - Dbg_Log("ResetUserMenuCounters(%n): gUserLeftItems[playerIndex] = %d", playerIndex, gUserLeftItems[playerIndex]); } public client_putinserver(playerIndex) { @@ -106,12 +103,10 @@ public client_disconnected(playerIndex) { for (new playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++) { gUserShouldResetCounters[playerIndex] = true; } - Dbg_Log("@OnRestartRound(): Should reset all counters."); } @OnPlayerSpawn(const playerIndex) { - if (!IsPlayerAlive(playerIndex)) { - Dbg_Log("@OnPlayerSpawn(%n): Invalid (or dead) player", playerIndex); + if (!is_user_alive(playerIndex)) { return; } @@ -119,8 +114,6 @@ public client_disconnected(playerIndex) { if (gUserShouldResetCounters[playerIndex] || PCGet_Bool(p, "ResetCountOnSpawn", false)) { ResetUserMenuCounters(playerIndex); - } else { - Dbg_Log("@OnPlayerSpawn(%n): Shouldn't reset counter", playerIndex); } // TODO: Добавить квар для отключения авто-открытия @@ -153,15 +146,12 @@ public client_disconnected(playerIndex) { client_cmd(playerIndex, VIPM_M_WEAPONMENU_CMD_MENU_SILENT); } - Dbg_Log("@Task_AutoOpen(%d): fAutoCloseDelay = %.2f", playerIndex, fAutoCloseDelay); if (fAutoCloseDelay > 0.0) { - Dbg_Log("@Task_AutoOpen(%d): Start auto close task", playerIndex); set_task(fAutoCloseDelay, "@Task_AutoClose", TASK_OFFSET_AUTO_CLOSE + playerIndex); } } @Task_AutoClose(playerIndex) { - Dbg_Log("@Task_AutoClose(%d)", playerIndex); playerIndex -= TASK_OFFSET_AUTO_CLOSE; menu_cancel(playerIndex); show_menu(playerIndex, 0, ""); @@ -188,32 +178,25 @@ AbortAutoCloseMenu(const playerIndex) { } _Cmd_Menu(const playerIndex, const bool:bSilent = false) { - if (!IsPlayerValid(playerIndex)) { - Dbg_Log("_Cmd_Menu(%d, %s): Invalid player", playerIndex, bSilent ? "true" : "false"); + if (!is_user_connected(playerIndex)) { return; } if (!is_user_alive(playerIndex)) { ChatPrintLIf(!bSilent, playerIndex, "MSG_YOU_DEAD"); - - Dbg_Log("_Cmd_Menu(%n, %s): Player is dead", playerIndex, bSilent ? "true" : "false"); return; } - new Trie:Params = VipM_Modules_GetParams(MODULE_NAME, playerIndex); - new Array:aMenus = VipM_Params_GetArr(Params, "Menus"); + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); + new Array:aMenus = VipM_Params_GetArr(p, "Menus"); if (ArraySizeSafe(aMenus) < 1) { ChatPrintLIf(!bSilent, playerIndex, "MSG_NO_ACCESS"); - - Dbg_Log("_Cmd_Menu(%n, %s): No access", playerIndex, bSilent ? "true" : "false"); return; } - if (!PCGet_VipmLimitsCheck(Params, "Limits", playerIndex, Limit_Exec_AND)) { + if (!PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND)) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MAIN_NOT_PASSED_LIMIT"); - - Dbg_Log("_Cmd_Menu(%n, %s): Not passed main limits", playerIndex, bSilent ? "true" : "false"); return; } @@ -221,10 +204,9 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { if (ArraySizeSafe(aMenus) == 1) { client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, 0); } else { - static MainMenuTitle[128]; - PCGet_Str(Params, "MainMenuTitle", MainMenuTitle, charsmax(MainMenuTitle)); - Menu_MainMenu(playerIndex, MainMenuTitle, aMenus); + Menu_MainMenu(playerIndex, PCGet_iStr(p, "MainMenuTitle", uLang(playerIndex, "MENU_MAIN_TITLE")), aMenus); } + return; } @@ -233,7 +215,6 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { ArraySizeSafe(aMenus) <= MenuId || MenuId < 0 ) { - Dbg_Log("_Cmd_Menu(%n, %s): Invalid menu id (%d)", playerIndex, bSilent ? "true" : "false", MenuId); return; } @@ -242,13 +223,11 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { if (Menu[WeaponMenu_Limits] != Invalid_Array && !VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], playerIndex, Limit_Exec_AND)) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MENU_NOT_PASSED_LIMIT"); - Dbg_Log("_Cmd_Menu(%n, %s): Not passed menu limits", playerIndex, bSilent ? "true" : "false"); return; } if (Menu[WeaponMenu_FakeMessage][0]) { ChatPrint(playerIndex, Menu[WeaponMenu_FakeMessage]); - Dbg_Log("_Cmd_Menu(%n, %s): Fake menu (%s)", playerIndex, bSilent ? "true" : "false", Menu[WeaponMenu_FakeMessage]); return; } @@ -262,7 +241,6 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { ArraySizeSafe(Menu[WeaponMenu_Items]) <= ItemId || ItemId < 0 ) { - Dbg_Log("_Cmd_Menu(%n, %s): Invalid item id (%d)", playerIndex, bSilent ? "true" : "false", ItemId); return; } @@ -276,8 +254,6 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { && iItemsLeft == 0 ) { ChatPrintLIf(!bSilent, playerIndex, "MSG_NO_LEFT_ITEMS"); - - Dbg_Log("_Cmd_Menu(%n, %s): No left items", playerIndex, bSilent ? "true" : "false"); return; } @@ -287,8 +263,6 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], playerIndex, Limit_Exec_AND) ) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MENUITEM_NOT_PASSED_LIMIT"); - - Dbg_Log("_Cmd_Menu(%n, %s): Not passed item limits", playerIndex, bSilent ? "true" : "false"); return; } @@ -304,9 +278,9 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { } if ( - PCGet_Bool(Params, "StayOpen", false) + PCGet_Bool(p, "StayOpen", false) && ( - !PCGet_Bool(Params, "StayOpen_CheckCounter", true) + !PCGet_Bool(p, "StayOpen_CheckCounter", true) || iItemsLeft != 0 ) ) { @@ -318,22 +292,14 @@ GetUserLeftItems(const playerIndex, const MenuId, const Menu[S_WeaponMenu]) { new iUserItemsLeft = gUserLeftItems[playerIndex]; new iMenuItemsLeft = Menu[WeaponMenu_Count] - KeyValueCounter_Get(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId)); - Dbg_Log("GetUserLeftItems(%n, %d, %d): iUserItemsLeft = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], iUserItemsLeft); - Dbg_Log("GetUserLeftItems(%n, %d, %d): iMenuItemsLeft = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], iMenuItemsLeft); - Dbg_Log("GetUserLeftItems(%n, %d, %d): Menu[WeaponMenu_Count] = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], Menu[WeaponMenu_Count]); - Dbg_Log("GetUserLeftItems(%n, %d, %d): g_tUserMenuItemsCounter[playerIndex] = %d", playerIndex, MenuId, Menu[WeaponMenu_Name], KeyValueCounter_Get(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId))); - if (iUserItemsLeft < 0) { - Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (no global limit)", playerIndex, MenuId, Menu[WeaponMenu_Name], iMenuItemsLeft); return iMenuItemsLeft; } if (Menu[WeaponMenu_Count] < 0) { - Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (no menu limit)", playerIndex, MenuId, Menu[WeaponMenu_Name], iUserItemsLeft); return iUserItemsLeft; } - Dbg_Log("GetUserLeftItems(%n, %d, %d): return %d (has both limits)", playerIndex, MenuId, Menu[WeaponMenu_Name], min(iUserItemsLeft, iMenuItemsLeft)); return min(iUserItemsLeft, iMenuItemsLeft); } diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 51e4814..3044269 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -3,7 +3,6 @@ #include #include #include "VipM/Utils" -#include "VipM/DebugMode" #include "VipM/ArrayTrieUtils" public stock const PluginName[] = "[VipM] Modules Limiter"; @@ -14,32 +13,28 @@ public stock const PluginDescription[] = "Modules activation controller"; new const CONFIG_FILE_PATH[] = "Modules.json"; -new Trie:g_tModulesLimits = Invalid_Trie; +new Trie:ModulesLimits = Invalid_Trie; public VipM_OnLoaded() { register_plugin(PluginName, PluginVersion, PluginAuthor); - g_tModulesLimits = LoadModulesLimitsFromFile(PCPath_iMakePath(fmt("%s/%s", VIPM_CONFIGS_FOLDER_NAME, CONFIG_FILE_PATH))); + ModulesLimits = LoadModulesLimitsFromFile(PCPath_iMakePath(fmt("%s/%s", VIPM_CONFIGS_FOLDER_NAME, CONFIG_FILE_PATH))); } -public VipM_Modules_OnActivate(const sModuleName[]) { +public VipM_Modules_OnActivate(const moduleName[]) { if ( - g_tModulesLimits == Invalid_Trie - || !TrieKeyExists(g_tModulesLimits, sModuleName) + ModulesLimits == Invalid_Trie + || !TrieKeyExists(ModulesLimits, moduleName) ) { - Dbg_Log("Module `%s` activated. (!TrieKeyExists)", sModuleName); return VIPM_CONTINUE; } - new Array:aLimits; - TrieGetCell(g_tModulesLimits, sModuleName, aLimits); - if (!VipM_Limits_ExecuteList(aLimits)) { - Dbg_Log("Module `%s` not ativated.", sModuleName); + new Array:limits; + TrieGetCell(ModulesLimits, moduleName, limits); + if (!VipM_Limits_ExecuteList(limits)) { return VIPM_STOP; } - Dbg_Log("Module `%s` activated. (Limits passed)", sModuleName); - return VIPM_CONTINUE; } @@ -48,53 +43,51 @@ Trie:LoadModulesLimitsFromFile(const filePath[], &Trie:modules = Invalid_Trie) { modules = TrieCreate(); } - new JSON:jFile = PCJson_ParseFile(filePath); - if (jFile == Invalid_JSON) { + new JSON:fileJson = PCJson_ParseFile(filePath); + if (fileJson == Invalid_JSON) { log_error(0, "Invalid JSON syntax. File `%s`.", filePath); return modules; } - if (!json_is_array(jFile)) { - PCJson_LogForFile(jFile, "WARNING", "Root value must be an array."); - PCJson_Free(jFile); + if (!json_is_array(fileJson)) { + PCJson_LogForFile(fileJson, "WARNING", "Root value must be an array."); + PCJson_Free(fileJson); return modules; } - json_array_foreach_value (jFile: i => jItem) { - if (!json_is_object(jItem)) { - PCJson_LogForFile(jItem, "WARNING", "Array item #%d isn`t object.", i); - json_free(jItem); + json_array_foreach_value (fileJson: i => itemJson) { + if (!json_is_object(itemJson)) { + PCJson_LogForFile(itemJson, "WARNING", "Array item #%d isn`t object.", i); + json_free(itemJson); continue; } - new JSON:jLimits = json_object_get_value(jItem, "Limits"); - new Array:aLimits = VipM_Limits_ReadListFromJson(jLimits); - json_free(jLimits); - if (!ArraySizeSafe(aLimits)) { - PCJson_LogForFile(jItem, "WARNING", "Field `Limits` must have 1 or more items."); - json_free(jItem); + new Array:limits = PCSingle_ObjVipmLimits(itemJson, "Limits"); + if (!ArraySizeSafe(limits)) { + PCJson_LogForFile(itemJson, "WARNING", "Field `Limits` must have 1 or more items."); + json_free(itemJson); continue; } - new Array:aModuleNames = json_object_get_strings_list(jItem, "Modules", VIPM_MODULES_TYPE_NAME_MAX_LEN); - if (!ArraySizeSafe(aModuleNames)) { - PCJson_LogForFile(jItem, "WARNING", "Field `Modules` must have 1 or more items."); + new Array:moduleNames = json_object_get_strings_list(itemJson, "Modules", VIPM_MODULES_TYPE_NAME_MAX_LEN); + if (!ArraySizeSafe(moduleNames)) { + PCJson_LogForFile(itemJson, "WARNING", "Field `Modules` must have 1 or more items."); continue; } - ArrayForeachString (aModuleNames: j => sModuleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]) { - if (TrieKeyExists(modules, sModuleName)) { - PCJson_LogForFile(jItem, "WARNING", "Duplicate limits for module `%s`.", sModuleName); + ArrayForeachString (moduleNames: j => moduleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]) { + if (TrieKeyExists(modules, moduleName)) { + PCJson_LogForFile(itemJson, "WARNING", "Duplicate limits for module `%s`.", moduleName); continue; } - TrieSetCell(modules, sModuleName, aLimits); + TrieSetCell(modules, moduleName, limits); } - json_free(jItem); - ArrayDestroy(aModuleNames); + json_free(itemJson); + ArrayDestroy(moduleNames); } - PCJson_Free(jFile); + PCJson_Free(fileJson); return modules; } diff --git a/amxmodx/scripting/VipM/ArrayTrieUtils.inc b/amxmodx/scripting/VipM/ArrayTrieUtils.inc index 1f99e0b..be6bc53 100644 --- a/amxmodx/scripting/VipM/ArrayTrieUtils.inc +++ b/amxmodx/scripting/VipM/ArrayTrieUtils.inc @@ -9,14 +9,6 @@ stock ArraySizeSafe(const Array:h) { return h == Invalid_Array ? 0 : ArraySize(h); } -#define ArrayForeachArray(%1=>%2[%3]) \ - ArrayForeachArrayEx(%1 => %2[%3], __i__) - -#define ArrayForeachArrayEx(%1=>%2[%3],%4) \ - if (%1 != Invalid_Array)\ - for (new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++)\ - if (ArrayGetArray(%1, %4, %2)) - #define ArrayForeachArray2(%1:%4=>%2[%3]) \ if (%1 != Invalid_Array) \ for (new %2[%3], %4 = 0; %4 < ArraySizeSafe(%1); %4++) \ diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index 2c05e13..c1e2274 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -78,7 +78,7 @@ T_VipUnit:VipUnit_Read(const JSON:valueJson) { return cached; } - new Array:aAccess = PCSingle_VipmLimits(linked, "Access"); + new Array:aAccess = PCSingle_ObjVipmLimits(linked, "Access"); if (aAccess == Invalid_Array) { PCJson_ErrorForFile(linked, "Field 'Access' is required in vip object."); PCJson_FreeLinked(linked); diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 4aeebad..7f0053f 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -5,7 +5,6 @@ #include #include "VipM/ArrayTrieUtils" -#include "VipM/ArrayMap" #include "VipM/Core/Objects/Modules/Type" #include "VipM/Core/Objects/Modules/Unit" @@ -13,11 +12,10 @@ #include "VipM/Core/Objects/Limits/Unit" #include "VipM/Core/Objects/Param" -// TODO: Дописать в параметрах компиляции в экшонах -#if !defined VIPM_INFO_COMPILED_BY_GH_ACTIONS +#if !defined GITHUB_ACTIONS_USED new bool:__VIPM_INFO_COMPILED_BY_GH_ACTIONS = false; #else -new bool:__VIPM_INFO_COMPILED_BY_GH_ACTIONS = bool:(VIPM_INFO_COMPILED_BY_GH_ACTIONS); +new bool:__VIPM_INFO_COMPILED_BY_GH_ACTIONS = bool:(GITHUB_ACTIONS_USED); #endif SrvCmds_Init() { @@ -29,20 +27,20 @@ SrvCmds_Init() { } @SrvCmd_Info() { - new sAmxxVersion[32]; - get_amxx_verstring(sAmxxVersion, charsmax(sAmxxVersion)); + new amxxVersion[32]; + get_amxx_verstring(amxxVersion, charsmax(amxxVersion)); server_print("╓─────────"); server_print("║ %s v%s by %s:", PluginName, VIPM_VERSION, PluginAuthor); server_print("║ │"); server_print("║ ├─Contacts:"); - server_print("║ │ ├─GitHub: https://github.com/akraneman"); - server_print("║ │ ├─Dev-CS: https://dev-cs.ru/members/949/"); - server_print("║ │ ├─VK: https://vk.com/akraneman"); + server_print("║ │ ├─GitHub Acc: https://github.com/arkaneman"); + server_print("║ │ ├─GitHub Org: https://github.com/AmxxModularEcosystem"); + server_print("║ │ ├─hlds.run: https://hlds.run/members/26/"); server_print("║ │ └─TG: https://t.me/arkaneman"); server_print("║ ├─Support:"); - server_print("║ │ ├─GitHub Issues: https://github.com/ArKaNeMaN/amxx-VipModular-pub/issues"); - server_print("║ │ ├─Dev-CS Resource: https://dev-cs.ru/resources/1466/"); + server_print("║ │ ├─GitHub Issues: https://github.com/AmxxModularEcosystem/VipModular/issues"); + server_print("║ │ ├─hlds.run Resource: https://hlds.run/resources/2/"); server_print("║ │ └─TG Forum: https://t.me/arkanaplugins/5"); server_print("║ │"); server_print("║ ├─Stats:"); @@ -55,10 +53,10 @@ SrvCmds_Init() { server_print("║ │ ├─Vips:"); server_print("║ │ │ └─Vips count: %d", VipUnit_GetCount()); server_print("║ │ ├─Compiled by AmxModX v%s", AMXX_VERSION_STR); - server_print("║ │ ├─Runned by AmxModX v%s", sAmxxVersion); + server_print("║ │ ├─Runned by AmxModX v%s", amxxVersion); server_print("║ │ └─Builded by GitHub Actions?: %s", __VIPM_INFO_COMPILED_BY_GH_ACTIONS ? "Yes" : "No"); server_print("║ │"); - server_print("║ └─GitHub repo: https://github.com/ArKaNeMaN/amxx-VipModular-pub"); + server_print("║ └─GitHub repo: https://github.com/AmxxModularEcosystem/VipModular"); server_print("╙─────────"); } @@ -66,12 +64,13 @@ SrvCmds_Init() { server_print("╔═════╤══════════════════════════════════╤════════╗"); server_print("║ # │ Module name │ Status ║"); server_print("╟─────┼──────────────────────────────────┼────────╢"); - new Array:aModuleTypes = ModuleType_GetAll(); - ArrayForeachArray2 (aModuleTypes: i => ModuleType[S_ModuleType]) { - server_print("║ %03d │ %-32s │ %-6s ║", i + 1, ModuleType[ModuleType_Name], ModuleType[ModuleType_Active] ? "On" : "Off"); + new Array:types = ModuleType_GetAll(); + ArrayForeachArray2 (types: i => typeObject[S_ModuleType]) { + server_print("║ %03d │ %-32s │ %-6s ║", i + 1, typeObject[ModuleType_Name], typeObject[ModuleType_Active] ? "On" : "Off"); } + ArrayDestroy(types); server_print("╟─────┴──────────────────────────────────┴────────╢"); - server_print("║ Total: %-5d ║", ModuleType_GetCount()); + server_print("║ Total: %-4d ║", ModuleType_GetCount()); server_print("╚═════════════════════════════════════════════════╝"); return PLUGIN_HANDLED; @@ -82,19 +81,19 @@ SrvCmds_Init() { server_print("║ # │ Limit name │ Params │ Static │ For player ║"); server_print("╟─────┼──────────────────────────────────┼────────┼────────┼────────────╢"); - new Array:aLimitTypes = LimitType_GetAll(); - ArrayForeachArray2 (aLimitTypes: i => LimitType[S_LimitType]) { + new Array:types = LimitType_GetAll(); + ArrayForeachArray2 (types: i => typeObject[S_LimitType]) { server_print("║ %03d │ %-32s │ %-6d │ %-6s │ %-10s ║", - i + 1, LimitType[LimitType_Name], - ArraySizeSafe(LimitType[LimitType_Params]), - LimitType[LimitType_Static] ? "Yes" : "No", - LimitType[LimitType_ForPlayer] ? "Yes" : "No" + i + 1, typeObject[LimitType_Name], + ArraySizeSafe(typeObject[LimitType_Params]), + typeObject[LimitType_Static] ? "Yes" : "No", + typeObject[LimitType_ForPlayer] ? "Yes" : "No" ); } - ArrayDestroy(aLimitTypes); + ArrayDestroy(types); server_print("╟─────┴──────────────────────────────────┴────────┴────────┴────────────╢"); - server_print("║ Total: %-5d ║", LimitType_GetCount()); + server_print("║ Total: %-4d ║", LimitType_GetCount()); server_print("╚═══════════════════════════════════════════════════════════════════════╝"); return PLUGIN_HANDLED; diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc index ca89a18..4a881ef 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -13,6 +13,8 @@ DefaultObjects_Limit_GameTime_Register() { @DefaultObjects_Limit_GameTime_OnCheck(const Trie:p) { + new gameTime = floatround(get_gametime()); + return ( gameTime >= PCGet_Int(p, "Min", cellmin) && gameTime <= PCGet_Int(p, "Max", cellmax) diff --git a/amxmodx/scripting/VipM/Utils.inc b/amxmodx/scripting/VipM/Utils.inc index 6eadec7..ffc7a21 100644 --- a/amxmodx/scripting/VipM/Utils.inc +++ b/amxmodx/scripting/VipM/Utils.inc @@ -30,20 +30,6 @@ stock IsPlayerIndexValid(const playerIndex) { return playerIndex >= 1 && playerIndex <= 32; } -stock IsPlayerValid(const playerIndex) { - return ( - IsPlayerIndexValid(playerIndex) - && is_user_connected(playerIndex) - ); -} - -stock IsPlayerAlive(const playerIndex) { - return ( - IsPlayerIndexValid(playerIndex) - && is_user_alive(playerIndex) - ); -} - #define Lang(%1) \ fmt(__SLANG_TEMPLATE_STR, %1) diff --git a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc index 969c70a..86e0a38 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc @@ -13,7 +13,7 @@ Menu_GetUserMenusCount(const UserId) { Menu_MainMenu(const UserId, const MainMenuTitle[], const Array:aMenus) { new iMenu = menu_create(MainMenuTitle, "@MenuHandler_Command"); - ArrayForeachArray(aMenus => Menu[S_WeaponMenu]) { + ArrayForeachArray2 (aMenus: i => Menu[S_WeaponMenu]) { menu_additem(iMenu, Menu[WeaponMenu_Name], fmt("%s %d", VIPM_M_WEAPONMENU_CMD_MENU, __i__)); } @@ -72,7 +72,7 @@ Menu_WeaponsMenu(const UserId, const MenuId, const Menu[S_WeaponMenu]) { } new iItemIndex = 0; - ArrayForeachArray(Menu[WeaponMenu_Items] => MenuItem[S_MenuItem]) { + ArrayForeachArray2 (Menu[WeaponMenu_Items]: i => MenuItem[S_MenuItem]) { if ( MenuItem[MenuItem_ShowLimits] != Invalid_Array && !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId, Limit_Exec_AND) diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index 69dbce5..9b60d63 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -243,10 +243,10 @@ stock bool:PCGet_VipmLimitsCheck(const Trie:p, const key[], const playerIndex = return VipM_Limits_ExecuteList(limits, playerIndex, type); } -stock T_LimitUnit:PCSingle_VipmLimit(const JSON:objectJson, const key[], const T_LimitUnit:def = Invalid_LimitUnit, const bool:dotNot = false, const bool:orFail = false) { +stock T_LimitUnit:PCSingle_ObjVipmLimit(const JSON:objectJson, const key[], const T_LimitUnit:def = Invalid_LimitUnit, const bool:dotNot = false, const bool:orFail = false) { return PCSingle_ObjCell(objectJson, key, VIPM_PARAM_TYPE_LIMIT_NAME, def, dotNot, orFail); } -stock Array:PCSingle_VipmLimits(const JSON:objectJson, const key[], const Array:def = Invalid_Array, const bool:dotNot = false, const bool:orFail = false) { +stock Array:PCSingle_ObjVipmLimits(const JSON:objectJson, const key[], const Array:def = Invalid_Array, const bool:dotNot = false, const bool:orFail = false) { return PCSingle_ObjCell(objectJson, key, VIPM_PARAM_TYPE_LIMITS_NAME, def, dotNot, orFail); } diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index b0827fb..dcf694c 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -9,7 +9,7 @@ stock const VIPM_LIBRARY[] = "VipModular"; #define _VIPM_VERSION "5.0.0-b13" stock const VIPM_VERSION[] = _VIPM_VERSION; -#define _VIPM_PLUGIN_URL "https://github.com/ArKaNeMaN/amxx-VipModular-pub" +#define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" // deprecated stock const VIPM_CFG_PATH[] = "plugins/VipModular"; diff --git a/readme/default-extensions.md b/readme/default-extensions.md index 8726e77..f5a806a 100644 --- a/readme/default-extensions.md +++ b/readme/default-extensions.md @@ -10,68 +10,8 @@ ## Ограничения -Ограничения и их параметры (при наличии). - -- ForAll/Always - Условие всегда верно -- Never - Условие всегда ложно -- Steam - Условие верно для Steam-игроков -- Alive - Условие верно для живых игроков -- Bot - Условие верно для ботов -- Name - Условие верно для игроков с указанным ником - - `Name` - ник игрока -- Flags - Условие верно для игрков, имеющих указанные флаги - - `Flags` - требуемые флаги - - `Strict` - если `true`, будет срабатывать при наличии всех указанных флагов, иначе сработает при наличии хотя бы одного флага -- SteamId - Усовие верно для игроков с указанным SteamID - - `SteamId` - SteamID игрока -- Ip - Условие верно для игроков с указанным IP-адресом - - `Ip` - IP-адрес игрока -- Map - Условие верно на указанной карте - - `Map` - Название/префикс карты - - `Real` - если `true`, проверяться будет реальное название карты, а не установленное другими плагинами. - - `Prefix` - если `true`, будет проверяться наличие значения параметра `Map` в начале названия карты. -- HasPrimaryWeapon - Условие верно для игроков имеющих основное оружие - - `HasNot` - если `true`, условие сработает для игроков, НЕ имеющих основное оружие -- Round - Условие верно в указанные раунды - - `Min` - раунд, с которого начнёт срабатывать условие - - `Max` - раунд, с которого условие перестанет срабатывать -- WeekDay - Условие верно в указанный день недели - - `Day` - название дня недели (Пн, Вт, Ср, Чт, Пт, Сб, Вс) -- RoundTime - Условие верно в указанный интервал времени от начала раунда - - `Min` - секунда, с которой начнёт срабатывать условие - - `Max` - секунда, с которой условие перестанет срабатывать -- InFreezyTime - Условие верно во время freezy time - - `Reverse` - если `true`, результат проверки будет обращён в обратную сторону -- InBuyZone - Условие верно для игроков, находящихся в зоне закупки - - `Reverse` - если `true`, результат проверки будет обращён в обратную сторону - -- Logic-OR - Условие верно, когда верно хотя бы одно из указанных условий - - `Limits` - список условий -- Logic-XOR - Условие верно, когда верно только одно из указанных условий - - `Limits` - список условий -- Logic-AND - Условие верно, когда верно все указанные условия - - `Limits` - список условий -- Logic-NOT - Условие верно, когда указанное условие не верное - - `Limits` - список условий - -- OncePerMap - Условие верно только при первой проверке за карту - - _Рекомендуется ставить последним в списке условий, чтобы лишний раз не проверялось, хотя зависит от задачи_ - - Указанные в разных местах лимиты не пересекаются друг с другом - - ... но если лимит проброшен через ссылку, то он везде один и будет пересекаться - - Примечание относится ко всем лимитам типа `OncePer*` -- OncePerGame - Условие верно только при первой проверке за игру (сбрасывается при рестарте, например через sv_restart) -- OncePerRound - Условие верно только при первой проверке за раунд - -- Time - Условие верно в указанном интервале времени - - `Before` - Время ДО которого условие будет верно. Формат HH:MM - - `After` - Время ПОСЛЕ которого условие будет верно. Формат HH:MM -- GameTime - Условие верно в указанном интервале времени от начала карты - - `Min` - секунда, с которой начнёт срабатывать условие - - `Max` - секунда, с которой условие перестанет срабатывать -- Frags - Проверка на кол-во фрагов у игрока - - `Min` - минимальное кол-во для срабатывания - - `Max` - максимальное кол-во для срабатывания +Список переехал [сюда](/wiki/Встроенные-лимиты). ## Типы предметов -Список переехал [сюда](/wiki/Встроенные-типы-предметов). \ No newline at end of file +Список переехал [сюда](/wiki/Встроенные-типы-предметов). diff --git a/readme/extensions/items/command.md b/readme/extensions/items/command.md index 00a0d06..33c089f 100644 --- a/readme/extensions/items/command.md +++ b/readme/extensions/items/command.md @@ -1,25 +1 @@ -# Command - -Выполнение команды от имени игрока или сервера. - -## Параметры - -| Название | Тип | По умолчанию\* | Описание | -| :------- | :------------- | :------------- | :-------------------------------------------- | -| Command | Строка | - | Текст команды, которая будет вызываться | -| ByServer | `true`/`false` | `false` | Должна ли команда вызываться от имени сервера | - -_\* - если указано "-", то параметр является обязательным._ - -Параметр `Command` может содержать плейсхолдер `{UserId}`, который при вызове команды будет заменён на индекс игрока. - -## Пример - -```jsonc -{ - "Item": "Command", - - "Command": "HealthNade_Give {UserId}", - "ByServer": true -} -``` +Документация переехала в [раздел WIKI](/wiki/Встроенные-типы-предметов#command). diff --git a/readme/extensions/items/defuse-kit.md b/readme/extensions/items/defuse-kit.md index a992f2f..d7b9b39 100644 --- a/readme/extensions/items/defuse-kit.md +++ b/readme/extensions/items/defuse-kit.md @@ -1,15 +1 @@ -# DefuseKit - -Набор сапёра (Только для команды CT, для TT будет игнорироваться). - -## Пример - -```jsonc -{ - "Item": "DefuseKit" -} -``` - -## Параметры - -_Параметры отсутствуют._ +Документация переехала в [раздел WIKI](/wiki/Встроенные-типы-предметов#defusekit). diff --git a/readme/extensions/items/items-list.md b/readme/extensions/items/items-list.md index a316b0f..f21ff14 100644 --- a/readme/extensions/items/items-list.md +++ b/readme/extensions/items/items-list.md @@ -1,31 +1 @@ -# ItemsList - -Список любых предметов. - -## Пример - -```jsonc -{ - "Item": "ItemsList", - - "Items": [ - { - "Item": "Cwapi", - - "Name": "Vip_Ak47", - "GiveType": "Replace" - }, - { - "Item": "Cwapi", - - "Name": "Vip_Deagle", - "GiveType": "Replace" - } - ] -} -``` - -## Параметры - -- `Items` - - Массив обьектов предметов. +Документация переехала в [раздел WIKI](/wiki/Встроенные-типы-предметов#itemslist). diff --git a/readme/extensions/items/weapon.md b/readme/extensions/items/weapon.md index c42fff3..09753ab 100644 --- a/readme/extensions/items/weapon.md +++ b/readme/extensions/items/weapon.md @@ -1,28 +1 @@ -# Weapon - -Стандартное оружие из игры с префиксом `weapon_`. - -## Пример - -```jsonc -{ - "Item": "Weapon", - - "Name": "weapon_ak47", - "GiveType": "Replace", - "BpAmmo": 30 -} -``` - -## Параметры - -- `Name` - - Название оружия из CWAPI. -- `BpAmmo` - - Количество запасных патронов. -- `GiveType` - - Тип выдачи оружия. - - Доступные типы: - - `GT_APPEND` или `Append` или `Add` - Добавить к текущему в соответствующем слоте - - `GT_REPLACE` или `Replace` - Заменить оружие из соответствующего слота на новое - - `GT_DROP_AND_REPLACE` или `Drop` или `DropAndReplace` - Выбросить текущее в соответствующем слоте и выдать новое +Документация переехала в [раздел WIKI](/wiki/Встроенные-типы-предметов#weapon). diff --git a/readme/thirdparty-extensions.md b/readme/thirdparty-extensions.md index 761b042..24de0e3 100644 --- a/readme/thirdparty-extensions.md +++ b/readme/thirdparty-extensions.md @@ -12,30 +12,8 @@ ## Ограничения -- [VipTest](https://github.com/AmxxModularEcosystem/VipM-L-VipTest) - Позволяет игрокам временно получить доступ к привилегиям. -- [RWW-InProgress](https://github.com/AmxxModularEcosystem/VipM-L-RandomWeaponsWarmUP) - Добавляет условие, которое верно во время разминки из плагина [Random Weapons WarmUP](https://github.com/ArKaNeMaN/amxx-RandomWeaponsWarmUP). -- [SnipersRBS-CanTakeAwp](https://github.com/AmxxModularEcosystem/VipM-L-SnipersRBS) - Интеграция с [Snipers RBS](https://fungun.net/shop/?p=show&id=48) от SKAJIbnEJIb. Добавляет условие, которое верно только тогда, когда игрок может взять АВП. -- [GCMS-Service & GCMS-Member](https://github.com/AmxxModularEcosystem/VipM-L-GameCMS) - Интеграция с [GameCMS API](https://cs-games.club/index.php?resources/gamecms-api.4/) от [zhorzh78](https://dev-cs.ru/members/326/). -- [AWPLimiter-CanTakeAwp](https://gist.github.com/ArKaNeMaN/db60225785d7e5bac1a73bf7a8466ab2) - Интеграция с [AWP Limiter](https://github.com/Nord1cWarr1or/AWP-Limiter) от [Nordic Warrior](https://dev-cs.ru/members/3093/). -- [MMM-VoteStarted](https://gist.github.com/ArKaNeMaN/a5607b74e991646fb0754e7dd8ba3a0c) - Интеграция с [MapManager Modular](https://github.com/Mistrick/MapManagerModular) от [Mistrick](https://dev-cs.ru/members/76/). -- [AwpOFF-Restricted](https://gist.github.com/ArKaNeMaN/f3c53992b0f041a647068d74b63aeb54) - Интеграция с [Awp OFF](https://dev-cs.ru/resources/225/) от [paffgame](https://dev-cs.ru/members/124/). -- [Radius-AwpRestricted](https://gist.github.com/ArKaNeMaN/42c7201e1bb19e2d2e3a72782c695f7b) - Интеграция с [AWP Restrictions](https://goldsrc.ru/resources/137/) от Radius. +Список переехал в [раздел WIKI](/wiki/Доступные-лимиты#сторонние-лимиты) ## Типы предметов -- Системы кастомного оружия: - - [Cwapi](https://github.com/AmxxModularEcosystem/IC-I-Cwapi) - Кастомное оружие из плагина [Custom Weapons API](https://github.com/AmxxModularEcosystem/CustomWeaponsAPI). - - [AUW-Weapon](https://github.com/AmxxModularEcosystem/VipM-I-AdvancedUltimateWeapons) - Позволяет выдавать кастомное оружие из плагина [Advanced Ultimate Weapons](https://dev-cs.ru/resources/945/) от [steelzzz](https://dev-cs.ru/members/19/). - - [UW-Weapon](https://gist.github.com/ArKaNeMaN/8720ae20f87245c0fe00d28c387065e0) - Интеграция с [Ultimate Weapons](https://fungun.net/shop/?p=show&id=82) от SKAJIbnEJIb. -- Различные реализации коктейля молотова: - - [BlackSignature-Molotov](https://github.com/ArKaNeMaN/VipM-I-BlackSignature-Molotov) - Позволяет выдавать [коктейль молотова](https://shorturl.at/jtzGZ) от [BlackSignature](https://dev-cs.ru/members/1111/). - - [Medusa-Molotov](https://gist.github.com/ArKaNeMaN/13bdfa31b2262c61b3adce9845c9e893) - Интеграция с [[GRENADE] Molotov](https://dev-cs.ru/resources/1160/) От [medusa](https://dev-cs.ru/members/65/). - - [WellAsGood-Molotov](https://gist.github.com/ArKaNeMaN/970685239663cb1b7a7791c0d2c55c6e) - Интеграция с [[Reapi] Molotov](https://dev-cs.ru/resources/1166/) От [wellasgood](https://dev-cs.ru/members/1657/). -- Кастомное оружие от CHEL74 (плагины-расширения поставляются в архиве после покупки): - - [Artifact](https://dev-cs.ru/threads/43339/) - Артефакт из S.T.A.L.K.E.R. - - [GaussRifle](https://dev-cs.ru/threads/42873/) - Гаусс пушка из S.T.A.L.K.E.R. - - [BananaBomb](https://dev-cs.ru/threads/30559/) - Banana Bomb - - [DecoyGrenade](https://github.com/AmxxModularEcosystem/VipM-I-Chel74Nades) - Ложная граната - - [HolyGrenade](https://dev-cs.ru/threads/35089/) - Holy Grenade -- [HealthNade](https://github.com/AmxxModularEcosystem/VipM-I-HealthNade) - Позволяет выдавать лечащую гранату из плагина [[fork] Healthnade](https://dev-cs.ru/resources/1271/) от [BlackSignature](https://dev-cs.ru/members/1111/). -- [ACS-Injection](https://gist.github.com/ArKaNeMaN/14d46548bbdbc7dacec5425e20315abd) - Интеграция с [[ACS] INJECTION](https://dev-cs.ru/resources/1582/) от [Refresh](https://dev-cs.ru/members/10396/). +Список переехал в [раздел WIKI](/wiki/Доступные-типы-предметов#сторонние-типы) From 93d676ffa2ae5ce7f30ebefc367dbcce39948328 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 5 Jan 2026 01:08:12 +0300 Subject: [PATCH 074/108] Use counter limit api for weapon menu counters --- .../Objects/Items/Instance.inc | 2 + .../ItemsController/Objects/Items/Type.inc | 6 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 96 ++++++++----- .../VipM/Core/Objects/Limits/Type.inc | 5 + .../VipM/Core/Objects/Limits/Unit.inc | 2 + .../VipM/Core/Objects/Modules/Type.inc | 5 + .../VipM/Core/Objects/Modules/Unit.inc | 2 + .../scripting/VipM/Core/Objects/VipUnit.inc | 2 + amxmodx/scripting/VipM/Core/SrvCmds.inc | 2 - amxmodx/scripting/VipM/WeaponMenu/Menus.inc | 128 +++++++++--------- .../VipM/WeaponMenu/Objects/MenuItem.inc | 16 ++- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 34 +++-- .../include/VipM/ItemsController.inc | 4 +- amxmodx/scripting/include/VipM/L/Counter.inc | 40 +++++- .../scripting/include/VipM/M/WeaponMenu.inc | 3 + amxmodx/scripting/include/VipM/Modules.inc | 18 +-- amxmodx/scripting/include/VipM/Params.inc | 11 ++ 17 files changed, 244 insertions(+), 132 deletions(-) diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc index 584afee..b41641f 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc @@ -23,6 +23,7 @@ static ActiveItemInstancesCount = 0; ItemInstance_Init() { CallOnce(); + log_amx("Init item instances..."); ItemType_Init(); @@ -31,6 +32,7 @@ ItemInstance_Init() { ActiveItemInstancesCount = 0; Forwards_RegAndCall("IC_Item_OnInited", ET_IGNORE); + log_amx("Item instances inited."); } T_IC_Item:ItemInstance_Construct(const T_IC_ItemType:type, const Trie:params) { diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc index 1ed53f0..7465ce6 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Type.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Type.inc @@ -19,11 +19,13 @@ static Trie:ItemTypesMap = Invalid_Trie; ItemType_Init() { CallOnce(); + log_amx("Init item types..."); ItemTypes = ArrayCreate(S_ItemType, 1); ItemTypesMap = TrieCreate(); Forwards_RegAndCall("IC_ItemType_OnInited", ET_IGNORE); + log_amx("Item types inited."); } T_IC_ItemType:ItemType_Construct(const name[]) { @@ -40,10 +42,12 @@ T_IC_ItemType:ItemType_Construct(const name[]) { new typeObject[S_ItemType]; copy(typeObject[ItemType_Name], charsmax(typeObject[ItemType_Name]), name); arrayset(typeObject[ItemType_Events], INVALID_HANDLE, sizeof(typeObject[ItemType_Events])); - typeObject[ItemType_Params]= ArrayCreate(1, 1); + typeObject[ItemType_Params] = ArrayCreate(1, 1); new T_IC_ItemType:type = T_IC_ItemType:ArrayPushArray(ItemTypes, typeObject); TrieSetCell(ItemTypesMap, typeObject[ItemType_Name], type); + + log_amx("Item type '%s' registered.", typeObject[ItemType_Name]); return type; } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index 6c132c5..a8655dc 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -2,6 +2,8 @@ #include #include #include +#include + #include "VipM/Utils" #include "VipM/WeaponMenu/Objects/WeaponMenu" @@ -39,9 +41,13 @@ public VipM_Modules_OnInited() { VipM_Modules_AddParamsEx(MODULE_NAME, // TODO: Read "Menus" as param "MainMenuTitle", DEFAULT_PARAMS_STR_NAME, false, + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false + ); + VipM_Modules_AddParamsEx(MODULE_NAME, "Count", DEFAULT_PARAMS_INT_NAME, false, - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false, - "ResetCountOnSpawn", DEFAULT_PARAMS_BOOL_NAME, false + "CounterType", VIPM_L_COUNTER_PARAM_TYPE, false, + "CounterKey", DEFAULT_PARAMS_SHORT_STR_NAME, false, + "ResetCountOnSpawn", DEFAULT_PARAMS_BOOL_NAME, false // deprecated ); VipM_Modules_AddParamsEx(MODULE_NAME, "AutoopenLimits", VIPM_PARAM_TYPE_LIMITS_NAME, false, @@ -210,16 +216,16 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { return; } - new MenuId = read_argv_int(2); + new menuIndex = read_argv_int(2); if ( - ArraySizeSafe(aMenus) <= MenuId - || MenuId < 0 + ArraySizeSafe(aMenus) <= menuIndex + || menuIndex < 0 ) { return; } static Menu[S_WeaponMenu]; - ArrayGetArray(aMenus, MenuId, Menu); + ArrayGetArray(aMenus, menuIndex, Menu); if (Menu[WeaponMenu_Limits] != Invalid_Array && !VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], playerIndex, Limit_Exec_AND)) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MENU_NOT_PASSED_LIMIT"); @@ -232,25 +238,25 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { } if (read_argc() < 3) { - Menu_WeaponsMenu(playerIndex, MenuId, Menu); + Menu_WeaponsMenu(playerIndex, menuIndex, Menu); return; } - new ItemId = read_argv_int(3); + new itemIndex = read_argv_int(3); if ( - ArraySizeSafe(Menu[WeaponMenu_Items]) <= ItemId - || ItemId < 0 + ArraySizeSafe(Menu[WeaponMenu_Items]) <= itemIndex + || itemIndex < 0 ) { return; } - static MenuItem[S_MenuItem]; - ArrayGetArray(Menu[WeaponMenu_Items], ItemId, MenuItem); + static itemObject[S_MenuItem]; + ArrayGetArray(Menu[WeaponMenu_Items], itemIndex, itemObject); - new iItemsLeft = GetUserLeftItems(playerIndex, MenuId, Menu); + new iItemsLeft = GetUserLeftItems(playerIndex, Menu); if ( - MenuItem[MenuItem_UseCounter] + itemObject[MenuItem_UseCounter] && iItemsLeft == 0 ) { ChatPrintLIf(!bSilent, playerIndex, "MSG_NO_LEFT_ITEMS"); @@ -258,23 +264,19 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { } if ( - !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], playerIndex, Limit_Exec_AND) - || !VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], playerIndex, Limit_Exec_AND) - || !VipM_Limits_ExecuteList(MenuItem[MenuItem_Limits], playerIndex, Limit_Exec_AND) + !VipM_Limits_ExecuteList(itemObject[MenuItem_ShowLimits], playerIndex, Limit_Exec_AND) + || !VipM_Limits_ExecuteList(itemObject[MenuItem_ActiveLimits], playerIndex, Limit_Exec_AND) + || !VipM_Limits_ExecuteList(itemObject[MenuItem_Limits], playerIndex, Limit_Exec_AND) ) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MENUITEM_NOT_PASSED_LIMIT"); return; } if ( - IC_Item_GiveArray(playerIndex, MenuItem[MenuItem_Items]) - && MenuItem[MenuItem_UseCounter] + IC_Item_GiveArray(playerIndex, itemObject[MenuItem_Items]) + && itemObject[MenuItem_UseCounter] ) { - gUserLeftItems[playerIndex]--; - - if (Menu[WeaponMenu_Count]) { - KeyValueCounter_Inc(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId)); - } + IncUserMenuCounters(playerIndex, Menu); } if ( @@ -284,23 +286,45 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { || iItemsLeft != 0 ) ) { - client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, MenuId); + client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, menuIndex); } } -GetUserLeftItems(const playerIndex, const MenuId, const Menu[S_WeaponMenu]) { - new iUserItemsLeft = gUserLeftItems[playerIndex]; - new iMenuItemsLeft = Menu[WeaponMenu_Count] - KeyValueCounter_Get(g_tUserMenuItemsCounter[playerIndex], IntToStr(MenuId)); - - if (iUserItemsLeft < 0) { - return iMenuItemsLeft; - } +IncUserMenuCounters(const playerIndex, const menuObject[S_WeaponMenu]) { + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); - if (Menu[WeaponMenu_Count] < 0) { - return iUserItemsLeft; - } + VipM_L_Counter_Inc( + PCGet_VipmCounterType(p, "CounterType", VipM_L_Counter_PerLife), + PCGet_iStr(p, "CounterKey", VIPM_M_WEAPONMENU_PLAYER_COUNTER_KEY), + playerIndex + ); + + VipM_L_Counter_Inc( + menuObject[WeaponMenu_CounterType], + menuObject[WeaponMenu_CounterKey], + playerIndex + ); +} + +GetUserLeftItems(const playerIndex, const menuObject[S_WeaponMenu]) { + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); + + new usedPlayer = VipM_L_Counter_Get( + PCGet_VipmCounterType(p, "CounterType", VipM_L_Counter_PerLife), + PCGet_iStr(p, "CounterKey", VIPM_M_WEAPONMENU_PLAYER_COUNTER_KEY), + playerIndex + ); + + new usedMenu = VipM_L_Counter_Get( + menuObject[WeaponMenu_CounterType], + menuObject[WeaponMenu_CounterKey], + playerIndex + ); - return min(iUserItemsLeft, iMenuItemsLeft); + return min( + usedMenu, + usedPlayer + ); } #include "VipM/WeaponMenu/Natives" diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 15fdcb1..5000a1b 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -29,8 +29,11 @@ static ArrayMap(g_amLimitTypes); // S_LimitType LimitType_Init() { CallOnce(); + log_amx("Init limit types..."); ArrayMapCreate(g_amLimitTypes, S_LimitType); + + log_amx("Limit types inited."); } Array:LimitType_GetAll() { @@ -63,6 +66,8 @@ T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, co LimitType[LimitType_ForPlayer] = bForPlayer; arrayset(LimitType[LimitType_Events], -1, sizeof(LimitType[LimitType_Events])); + + log_amx("Limit type '%s' registered.", LimitType[LimitType_Name]); return T_LimitType:ArrayMapPushArray(g_amLimitTypes, LimitType, LimitType[LimitType_Name]); } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index c239543..99631b8 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -23,12 +23,14 @@ static Array:g_aLimitUnits = Invalid_Array; LimitUnit_Init() { CallOnce(); + log_amx("Init limit units..."); LimitType_Init(); g_aLimitUnits = ArrayCreate(S_LimitUnit, 1); Forwards_RegAndCall("VipM_Limits_OnInited", ET_IGNORE); + log_amx("Limit units inited."); } LimitUnit_GetCount() { diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index 35ce43c..6b8c92c 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -28,10 +28,13 @@ static ArrayMap(g_amModuleTypes); // S_ModuleType ModuleType_Init() { CallOnce(); + log_amx("Init module types..."); ArrayMapCreate(g_amModuleTypes, S_ModuleType); Forwards_Reg("VipM_Modules_OnActivate", ET_STOP, FP_STRING); + + log_amx("Module types inited."); } Array:ModuleType_GetAll() { @@ -62,6 +65,8 @@ T_ModuleType:ModuleType_Construct(const sName[]) { ModuleType[ModuleType_Active] = false; arrayset(ModuleType[ModuleType_Events], -1, sizeof(ModuleType[ModuleType_Events])); + + log_amx("Module type '%s' registered.", ModuleType[ModuleType_Name]); return T_ModuleType:ArrayMapPushArray(g_amModuleTypes, ModuleType, ModuleType[ModuleType_Name]); } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index b47ffea..d6ee44e 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -23,12 +23,14 @@ static Array:g_aModuleUnits = Invalid_Array; ModuleUnit_Init() { CallOnce(); + log_amx("Init module units..."); ModuleType_Init(); g_aModuleUnits = ArrayCreate(S_ModuleUnit, 1); Forwards_RegAndCall("VipM_Modules_OnInited", ET_IGNORE); + log_amx("Module units inited."); } ModuleUnit_GetCount() { diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index c1e2274..d54025a 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -22,6 +22,7 @@ new Array:g_aVipUnits = Invalid_Array; VipUnit_Init() { CallOnce(); + log_amx("Init vip units..."); // Пока что лимиты обязательно должны быть перед модулями // После поломки интерфейса будет отдельный форвард для лимитов, а пока только для модулей @@ -29,6 +30,7 @@ VipUnit_Init() { ModuleUnit_Init(); g_aVipUnits = ArrayCreate(S_VipUnit, 1); + log_amx("Vip units inited."); } VipUnit_GetCount() { diff --git a/amxmodx/scripting/VipM/Core/SrvCmds.inc b/amxmodx/scripting/VipM/Core/SrvCmds.inc index 7f0053f..4de945b 100644 --- a/amxmodx/scripting/VipM/Core/SrvCmds.inc +++ b/amxmodx/scripting/VipM/Core/SrvCmds.inc @@ -20,9 +20,7 @@ new bool:__VIPM_INFO_COMPILED_BY_GH_ACTIONS = bool:(GITHUB_ACTIONS_USED); SrvCmds_Init() { register_srvcmd("vipm_info", "@SrvCmd_Info"); - register_srvcmd("vipm_modules", "@SrvCmd_Modules"); - register_srvcmd("vipm_limits", "@SrvCmd_Limits"); } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc index 86e0a38..4fba87d 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc @@ -1,135 +1,139 @@ -#include amxmodx -#include VipModular +#include +#include +#include + #include "VipM/Utils" #include "VipM/ArrayTrieUtils" -#include "VipM/DebugMode" #include "VipM/WeaponMenu/Objects/WeaponMenu" -Menu_GetUserMenusCount(const UserId) { - return ArraySizeSafe(VipM_Params_GetArr(VipM_Modules_GetParams(MODULE_NAME, UserId), "Menus")); +Menu_GetUserMenusCount(const playerIndex) { + return ArraySizeSafe(VipM_Params_GetArr(VipM_Modules_GetParams(MODULE_NAME, playerIndex), "Menus")); } -Menu_MainMenu(const UserId, const MainMenuTitle[], const Array:aMenus) { - new iMenu = menu_create(MainMenuTitle, "@MenuHandler_Command"); +Menu_MainMenu(const playerIndex, const MainMenuTitle[], const Array:menus) { + new menuHandler = menu_create(MainMenuTitle, "@MenuHandler_Command"); - ArrayForeachArray2 (aMenus: i => Menu[S_WeaponMenu]) { - menu_additem(iMenu, Menu[WeaponMenu_Name], fmt("%s %d", VIPM_M_WEAPONMENU_CMD_MENU, __i__)); + ArrayForeachArray2 (menus: i => menuObject[S_WeaponMenu]) { + menu_additem(menuHandler, menuObject[WeaponMenu_Name], fmt("%s %d", VIPM_M_WEAPONMENU_CMD_MENU, i)); } - menu_setprop(iMenu, MPROP_BACKNAME, Lang("VIPM_M_WM_MENU_BACK")); - menu_setprop(iMenu, MPROP_NEXTNAME, Lang("VIPM_M_WM_MENU_NEXT")); - menu_setprop(iMenu, MPROP_EXITNAME, Lang("VIPM_M_WM_MENU_EXIT")); + menu_setprop(menuHandler, MPROP_BACKNAME, Lang("VIPM_M_WM_MENU_BACK")); + menu_setprop(menuHandler, MPROP_NEXTNAME, Lang("VIPM_M_WM_MENU_NEXT")); + menu_setprop(menuHandler, MPROP_EXITNAME, Lang("VIPM_M_WM_MENU_EXIT")); - menu_display(UserId, iMenu); + menu_display(playerIndex, menuHandler); } -Menu_WeaponsMenu(const UserId, const MenuId, const Menu[S_WeaponMenu]) { - new iItemsLeft = GetUserLeftItems(UserId, MenuId, Menu); - new iMenusCount = Menu_GetUserMenusCount(UserId); +Menu_WeaponsMenu(const playerIndex, const menuIndex, const menuObject[S_WeaponMenu]) { + new iItemsLeft = GetUserLeftItems(playerIndex, menuObject); + new iMenusCount = Menu_GetUserMenusCount(playerIndex); static sItemsLeft[128] = ""; if (iItemsLeft >= 0) { - formatex(sItemsLeft, charsmax(sItemsLeft), "\w%L^n", UserId, "VIPM_M_WM_MENU_MAIN_ITEMS_LEFT", iItemsLeft); + formatex(sItemsLeft, charsmax(sItemsLeft), "\w%L^n", playerIndex, "VIPM_M_WM_MENU_MAIN_ITEMS_LEFT", iItemsLeft); } else { sItemsLeft[0] = 0; } static sExpireStatus[128]; - if (gUserExpireStatus[UserId][0]) { - formatex(sExpireStatus, charsmax(sExpireStatus), "\w%L^n", UserId, "VIPM_M_WM_MENU_EXPIRE_STATUS", gUserExpireStatus[UserId]); + if (gUserExpireStatus[playerIndex][0]) { + formatex(sExpireStatus, charsmax(sExpireStatus), "\w%L^n", playerIndex, "VIPM_M_WM_MENU_EXPIRE_STATUS", gUserExpireStatus[playerIndex]); } else { sExpireStatus[0] = 0; } static sMenu[512]; - formatex(sMenu, charsmax(sMenu), "%s^n%s%s", Menu[WeaponMenu_Title], sExpireStatus, sItemsLeft); + formatex(sMenu, charsmax(sMenu), "%s^n%s%s", menuObject[WeaponMenu_Title], sExpireStatus, sItemsLeft); - new iMenu = menu_create( - sMenu, - Menu[WeaponMenu_BackOnExit] && iMenusCount > 1 - ? "@MenuHandler_Weapons" - : "@MenuHandler_Command" - ); + new menuHandler = menu_create(sMenu, "@MenuHandler_Command"); - if (Menu[WeaponMenu_BackOnExit] && iMenusCount > 1) { - menu_setprop(iMenu, MPROP_EXITNAME, uLang(UserId, "VIPM_M_WM_MENU_WEAPONS_BACK_TO_MAIN_TEXT")); + if (menuObject[WeaponMenu_BackOnExit] && iMenusCount > 1) { + menu_setprop(menuHandler, MPROP_EXITNAME, uLang(playerIndex, "VIPM_M_WM_MENU_WEAPONS_BACK_TO_MAIN_TEXT")); } - if (Menu[WeaponMenu_PerPage] >= 0) { - menu_setprop(iMenu, MPROP_PERPAGE, Menu[WeaponMenu_PerPage]); + if (menuObject[WeaponMenu_PerPage] >= 0) { + menu_setprop(menuHandler, MPROP_PERPAGE, menuObject[WeaponMenu_PerPage]); } - menu_setprop(iMenu, MPROP_SHOWPAGE, Menu[WeaponMenu_ShowPage]); + menu_setprop(menuHandler, MPROP_SHOWPAGE, menuObject[WeaponMenu_ShowPage]); - menu_setprop(iMenu, MPROP_BACKNAME, Lang("VIPM_M_WM_MENU_BACK")); - menu_setprop(iMenu, MPROP_NEXTNAME, Lang("VIPM_M_WM_MENU_NEXT")); - menu_setprop(iMenu, MPROP_EXITNAME, Lang("VIPM_M_WM_MENU_EXIT")); + menu_setprop(menuHandler, MPROP_BACKNAME, Lang("VIPM_M_WM_MENU_BACK")); + menu_setprop(menuHandler, MPROP_NEXTNAME, Lang("VIPM_M_WM_MENU_NEXT")); + menu_setprop(menuHandler, MPROP_EXITNAME, Lang("VIPM_M_WM_MENU_EXIT")); static iInactiveItemHandler; if (!iInactiveItemHandler) { iInactiveItemHandler = menu_makecallback("@MenuItemHandler_Inactive"); } - new iItemIndex = 0; - ArrayForeachArray2 (Menu[WeaponMenu_Items]: i => MenuItem[S_MenuItem]) { + new itemIndex = 0; + ArrayForeachArray2 (menuObject[WeaponMenu_Items]: i => itemObject[S_MenuItem]) { if ( - MenuItem[MenuItem_ShowLimits] != Invalid_Array - && !VipM_Limits_ExecuteList(MenuItem[MenuItem_ShowLimits], UserId, Limit_Exec_AND) + itemObject[MenuItem_ShowLimits] != Invalid_Array + && !VipM_Limits_ExecuteList(itemObject[MenuItem_ShowLimits], playerIndex, Limit_Exec_AND) ) { continue; } + + new bool:isItemActive = ( + itemObject[MenuItem_ShowLimits] == Invalid_Array + || VipM_Limits_ExecuteList(itemObject[MenuItem_ActiveLimits], playerIndex, Limit_Exec_AND) + ); + + static title[64]; + if (isItemActive) { + copy(title, charsmax(title), itemObject[MenuItem_Title]); + } else { + copy(title, charsmax(title), itemObject[MenuItem_InactiveTitle]); + } - switch (MenuItem[MenuItem_Type]) { + switch (itemObject[MenuItem_Type]) { case MenuItemType_Default: { - new bool:bIsActive = MenuItem[MenuItem_ShowLimits] == Invalid_Array - || VipM_Limits_ExecuteList(MenuItem[MenuItem_ActiveLimits], UserId, Limit_Exec_AND); + static cmd[128]; + formatex(cmd, charsmax(cmd), "%s %d %d", VIPM_M_WEAPONMENU_CMD_MENU, menuIndex, i); + if (menuObject[WeaponMenu_BackOnExit]) { + add(cmd, charsmax(cmd), fmt(";%s %d", VIPM_M_WEAPONMENU_CMD_MENU, menuIndex)); + } + + menu_additem(menuHandler, title, cmd); - menu_additem(iMenu, fmt("%s%s", bIsActive ? "" : "\d", MenuItem[MenuItem_Title]), fmt("%s %d %d", VIPM_M_WEAPONMENU_CMD_MENU, MenuId, __i__)); - if (!bIsActive && !MenuItem[MenuItem_FakeInactive]) { - menu_item_setcall(iMenu, iItemIndex, iInactiveItemHandler); + if (!isItemActive && !itemObject[MenuItem_FakeInactive]) { + menu_item_setcall(menuHandler, itemIndex, iInactiveItemHandler); } } case MenuItemType_Text: { - menu_addtext2(iMenu, MenuItem[MenuItem_Title]); + menu_addtext2(menuHandler, itemObject[MenuItem_Title]); } case MenuItemType_Blank: { - menu_addblank2(iMenu); + menu_addblank2(menuHandler); } } - iItemIndex++; + itemIndex++; } - menu_display(UserId, iMenu); + menu_display(playerIndex, menuHandler); } @MenuItemHandler_Inactive() { return ITEM_DISABLED; } -@MenuHandler_Weapons(const UserId, const MenuId, const ItemId) { - @MenuHandler_Command(UserId, MenuId, ItemId); - - if (ItemId == MENU_EXIT) { - client_cmd(UserId, "%s", VIPM_M_WEAPONMENU_CMD_MENU); - } -} - -@MenuHandler_Command(const UserId, const MenuId, const ItemId){ - AbortAutoCloseMenu(UserId); +@MenuHandler_Command(const playerIndex, const menuIndex, const ItemId){ + AbortAutoCloseMenu(playerIndex); if (ItemId == MENU_EXIT) { - menu_destroy(MenuId); + menu_destroy(menuIndex); return; } static sCmd[128]; - menu_item_getinfo(MenuId, ItemId, _, sCmd, charsmax(sCmd)); + menu_item_getinfo(menuIndex, ItemId, _, sCmd, charsmax(sCmd)); if (sCmd[0]) { - client_cmd(UserId, sCmd); + client_cmd(playerIndex, sCmd); } - menu_destroy(MenuId); + menu_destroy(menuIndex); } \ No newline at end of file diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index f671573..000203e 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -17,6 +17,7 @@ enum _:S_MenuItem { MenuItemType:MenuItem_Type, MenuItem_Title[64], + MenuItem_InactiveTitle[64], Array:MenuItem_Items, // T_IC_Item[] bool:MenuItem_UseCounter, bool:MenuItem_FakeInactive, @@ -32,23 +33,26 @@ bool:MenuItem_Read(const JSON:itemJson, item[S_MenuItem]) { return false; } - if (!json_object_get_string(itemJson, "Title", item[MenuItem_Title], charsmax(item[MenuItem_Title]))) { + if (!PCSingle_ObjShortString(itemJson, "Title", item[MenuItem_Title], charsmax(item[MenuItem_Title]))) { item[MenuItem_Type] = MenuItemType_Blank; return true; } + + item[MenuItem_ShowLimits] = PCSingle_ObjVipmLimits(itemJson, "ShowLimits"); + item[MenuItem_ActiveLimits] = PCSingle_ObjVipmLimits(itemJson, "ActiveLimits"); + + if (!PCSingle_ObjShortString(itemJson, "InactiveTitle", item[MenuItem_InactiveTitle], charsmax(item[MenuItem_InactiveTitle]))) { + formatex(item[MenuItem_InactiveTitle], charsmax(item[MenuItem_InactiveTitle]), "\d%s", item[MenuItem_Title]); + } item[MenuItem_Items] = PCSingle_ObjIcItems(itemJson, "Items"); - if (item[MenuItem_Items] == Invalid_Array) { item[MenuItem_Type] = MenuItemType_Text; return true; } item[MenuItem_Type] = MenuItemType_Default; - - item[MenuItem_ShowLimits] = Json_Object_GetLimits(itemJson, "ShowLimits"); - item[MenuItem_ActiveLimits] = Json_Object_GetLimits(itemJson, "ActiveLimits"); - item[MenuItem_Limits] = Json_Object_GetLimits(itemJson, "Limits"); + item[MenuItem_Limits] = PCSingle_ObjVipmLimits(itemJson, "Limits"); item[MenuItem_FakeInactive] = PCSingle_ObjBool(itemJson, "FakeInactive", false); item[MenuItem_UseCounter] = PCSingle_ObjBool(itemJson, "UseCounter", true); diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 216069e..1a768c0 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -7,6 +7,7 @@ #include #include #include +#include #include "VipM/WeaponMenu/Objects/MenuItem" @@ -16,6 +17,8 @@ enum _:S_WeaponMenu { Array:WeaponMenu_Items, // S_MenuItem[] WeaponMenu_Count, + VipM_L_Counter_Type:WeaponMenu_CounterType, + WeaponMenu_CounterKey[VIPM_L_COUNTER_KEY_MAX_LEN], Array:WeaponMenu_Limits, // T_LimitUnit[] @@ -26,29 +29,36 @@ enum _:S_WeaponMenu { WeaponMenu_FakeMessage[256], } -bool:WeaponMenu_Read(const JSON:menuJson, Menu[S_WeaponMenu]) { - PCSingle_ObjString(menuJson, "Name", Menu[WeaponMenu_Name], charsmax(Menu[WeaponMenu_Name])); +static WeaponMenuCounterKeysCount = 0; + +bool:WeaponMenu_Read(const JSON:menuJson, menuObject[S_WeaponMenu]) { + PCSingle_ObjString(menuJson, "Name", menuObject[WeaponMenu_Name], charsmax(menuObject[WeaponMenu_Name])); if (PCSingle_ObjChatMessage( menuJson, "FakeMessage", - Menu[WeaponMenu_FakeMessage], charsmax(Menu[WeaponMenu_FakeMessage]) + menuObject[WeaponMenu_FakeMessage], charsmax(menuObject[WeaponMenu_FakeMessage]) )) { return true; } - Menu[WeaponMenu_Items] = Json_Object_GetMenuItemsList(menuJson, "Items"); - if (Menu[WeaponMenu_Items] == Invalid_Array) { - PCJson_LogForFile(menuJson, "WARNING", "Menu items list are empty."); + menuObject[WeaponMenu_Items] = Json_Object_GetMenuItemsList(menuJson, "Items"); + if (menuObject[WeaponMenu_Items] == Invalid_Array) { + PCJson_LogForFile(menuJson, "WARNING", "menuObject items list are empty."); return false; } - PCSingle_ObjString(menuJson, "Title", Menu[WeaponMenu_Title], charsmax(Menu[WeaponMenu_Title]), Menu[WeaponMenu_Name]); + PCSingle_ObjString(menuJson, "Title", menuObject[WeaponMenu_Title], charsmax(menuObject[WeaponMenu_Title]), menuObject[WeaponMenu_Name]); + + menuObject[WeaponMenu_BackOnExit] = PCSingle_ObjBool(menuJson, "BackOnExit", false); + menuObject[WeaponMenu_PerPage] = PCSingle_ObjInt(menuJson, "PerPage", -1); + menuObject[WeaponMenu_ShowPage] = PCSingle_ObjBool(menuJson, "ShowPage", true); + menuObject[WeaponMenu_Limits] = PCSingle_ObjVipmLimits(menuJson, "Limits"); - Menu[WeaponMenu_Count] = PCSingle_ObjInt(menuJson, "Count", -1); - Menu[WeaponMenu_BackOnExit] = PCSingle_ObjBool(menuJson, "BackOnExit", false); - Menu[WeaponMenu_PerPage] = PCSingle_ObjInt(menuJson, "PerPage", -1); - Menu[WeaponMenu_ShowPage] = PCSingle_ObjBool(menuJson, "ShowPage", true); - Menu[WeaponMenu_Limits] = Json_Object_GetLimits(menuJson, "Limits"); + menuObject[WeaponMenu_Count] = PCSingle_ObjInt(menuJson, "Count", -1); + menuObject[WeaponMenu_CounterType] = PCSingle_ObjVipmCounterType(menuJson, "CounterType"); + if (!PCSingle_ObjShortString(menuJson, "CounterKey", menuObject[WeaponMenu_CounterKey], charsmax(menuObject[WeaponMenu_CounterKey]))) { + formatex(menuObject[WeaponMenu_CounterKey], charsmax(menuObject[WeaponMenu_CounterKey]), "%s-%d", VIPM_M_WEAPONMENU_MENU_COUNTER_KEY_PREFIX, ++WeaponMenuCounterKeysCount); + } return true; } diff --git a/amxmodx/scripting/include/VipM/ItemsController.inc b/amxmodx/scripting/include/VipM/ItemsController.inc index db06c8e..2f9cf38 100644 --- a/amxmodx/scripting/include/VipM/ItemsController.inc +++ b/amxmodx/scripting/include/VipM/ItemsController.inc @@ -1 +1,3 @@ -#include \ No newline at end of file +// for compat with old vipm versions + +#include diff --git a/amxmodx/scripting/include/VipM/L/Counter.inc b/amxmodx/scripting/include/VipM/L/Counter.inc index 2333dfc..5b65371 100644 --- a/amxmodx/scripting/include/VipM/L/Counter.inc +++ b/amxmodx/scripting/include/VipM/L/Counter.inc @@ -3,15 +3,36 @@ #endif #define _vipmodular_l_counter_included +#include + #define VIPM_L_COUNTER_KEY_MAX_LEN 64 new const VIPM_L_COUNTER_PARAM_TYPE[] = "VipM-L-CounterType"; enum VipM_L_Counter_Type { + /** + * Сбрасывается при спавне игрока + */ VipM_L_Counter_PerLife, + + /** + * Сбрасывается в начале раунда + */ VipM_L_Counter_PerRound, + + /** + * Сбрасывается при звходе игрока на сервер + */ VipM_L_Counter_PerSession, + + /** + * Сбрасывается в начале игры (начало карты или sv_restart) + */ VipM_L_Counter_PerGame, + + /** + * Сбрасывается в начале карты + */ VipM_L_Counter_PerMap, } @@ -39,14 +60,27 @@ native VipM_L_Counter_Get(const VipM_L_Counter_Type:type, const key[], const pla native VipM_L_Counter_Set(const VipM_L_Counter_Type:type, const key[], const playerIndex, const value); /** - * Перезапись текущего значения счётчика. + * Инкрементация значения счётчика. * * @param type Тип счётчика (см. VipM_L_Counter_Type). * @param key Ключ счётчика, уникальный для каждого типа. * @param playerIndex Индекс игрока. + * @param add Добавляемое значение. * * @return Новое значение счётчика. */ -stock VipM_Counter_Inc(const VipM_L_Counter_Type:type, const key[], const playerIndex) { - return VipM_L_Counter_Set(type, key, playerIndex, VipM_L_Counter_Get(type, key) + 1); +stock VipM_L_Counter_Inc(const VipM_L_Counter_Type:type, const key[], const playerIndex, const add = 1) { + return VipM_L_Counter_Set(type, key, playerIndex, VipM_L_Counter_Get(type, key, playerIndex) + add); +} + +stock VipM_L_Counter_Type:PCGet_VipmCounterType(const Trie:p, const key[], const VipM_L_Counter_Type:def = VipM_L_Counter_PerLife) { + return PCGet_Cell(p, key, def); +} + +stock VipM_L_Counter_Type:PCSingle_VipmCounterType(const JSON:valueJson, const key[], const VipM_L_Counter_Type:def = VipM_L_Counter_PerLife, const orFailKey[] = "") { + return PCSingle_Cell(valueJson, key, VIPM_L_COUNTER_PARAM_TYPE, def, orFailKey); +} + +stock VipM_L_Counter_Type:PCSingle_ObjVipmCounterType(const JSON:objectJson, const key[], const VipM_L_Counter_Type:def = VipM_L_Counter_PerLife, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, VIPM_L_COUNTER_PARAM_TYPE, def, dotNot, orFail); } diff --git a/amxmodx/scripting/include/VipM/M/WeaponMenu.inc b/amxmodx/scripting/include/VipM/M/WeaponMenu.inc index c99a0ae..e9a5067 100644 --- a/amxmodx/scripting/include/VipM/M/WeaponMenu.inc +++ b/amxmodx/scripting/include/VipM/M/WeaponMenu.inc @@ -9,6 +9,9 @@ stock const VIPM_M_WEAPONMENU_CMD_MENU[] = "vipm_m_weaponmenu_menu"; stock const VIPM_M_WEAPONMENU_CMD_MENU_SILENT[] = "vipm_m_weaponmenu_menu_silent"; stock const VIPM_M_WEAPONMENU_CMD_AUTOOPEN_TOGGLE[] = "vipm_m_weaponmenu_autoopen_toggle"; +stock const VIPM_M_WEAPONMENU_PLAYER_COUNTER_KEY[] = "VipM-M-WeaponMenu-Player"; +stock const VIPM_M_WEAPONMENU_MENU_COUNTER_KEY_PREFIX[] = "VipM-M-WeaponMenu-Menu"; + /** * Устанавливает статус окончания привилегий, выводимый игроку в оружейном меню. * diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index 829be41..b8141c1 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -26,9 +26,9 @@ enum E_ModuleEvent{ /* * Описание: Вызывается, когда читаются параметры модуля. * Возв. тип: VipM_FwdReturn - * Параметры: (const JSON:jCfg, Trie:Params): - * jCfg - JSON-обьект с параметрами. - * Params - Хэш-карта с прочитанными параметрами. Может быть изменена. + * Параметры: (const JSON:moduleJson, Trie:p): + * moduleJson - JSON-обьект с параметрами. + * p - Хэш-карта с прочитанными параметрами. Может быть изменена. * * Примечание: Вызывается в plugin_precache * Примечание: Если возвращено VIPM_STOP, элемент модуля будет пропущен. @@ -51,14 +51,14 @@ enum E_ModuleEvent{ /* * Описание: Вызывается при добавлении игроку второго и последующих модулей одного типа. * Возв. тип: Trie - * Параметры: (const Trie:tParams1, const Trie:tParams2): - * tParams1 - Первый набор параметров. - * tParams2 - Второй набор параметров. + * Параметры: (const Trie:p1, const Trie:p2): + * p1 - Первый набор параметров. + * p2 - Второй набор параметров. * * Примечание: Если обработчик для этого события не зарегистрирован, - * всегда будет выбираться tParams1 (модуль, добавленный первым) без изменений. + * всегда будет выбираться p1 (модуль, добавленный первым) без изменений. * - * Примечание: Очищение/изменение пришедших в параметрах Trie вызовет ошибки в работе модулей. + * Примечание: Очищение/изменение переданных в параметры Trie недопустимо. * * Примечание: Обработчик может вернуть один из полученных Trie или создать новый. * При содании нового Trie ядро само позаботится о его очищении в будущем. @@ -149,7 +149,7 @@ native bool:VipM_Modules_IsActive(const Module[]); * @param Module Название модуля. * @param UserId Индекс игрока. * - * @return Хэш-карту с параметрами. + * @return Trie с параметрами. */ native Trie:VipM_Modules_GetParams(const Module[], const UserId); diff --git a/amxmodx/scripting/include/VipM/Params.inc b/amxmodx/scripting/include/VipM/Params.inc index 7417136..ad3dbfd 100644 --- a/amxmodx/scripting/include/VipM/Params.inc +++ b/amxmodx/scripting/include/VipM/Params.inc @@ -12,57 +12,68 @@ * Vip Modular: Parameters */ +#pragma deprecated Use params controller instead enum E_ParamType { /* * Пользовательский тип параметра. Подразумевает использование события OnRead. * Обязательность таких параметров игнорируется. */ + #pragma deprecated Use params controller instead ptCustom = 0, /* * Целое число. */ + #pragma deprecated Use params controller instead ptInteger, /* * Дробное число. */ + #pragma deprecated Use params controller instead ptFloat, /* * true/false. */ + #pragma deprecated Use params controller instead ptBoolean, /* * Строка. */ + #pragma deprecated Use params controller instead ptString, /* * Цвет (Массив из трёх целых чисел). */ + #pragma deprecated Use params controller instead ptColor, /* * Двумерный вектор (Массив из двух дробных чисел). */ + #pragma deprecated Use params controller instead ptVector2, /* * Трёхмерный вектор (Массив из трёх дробных чисел). */ + #pragma deprecated Use params controller instead ptVector3, /* * Условный элемент. */ + #pragma deprecated Use params controller instead ptLimit, /* * Массив условных элементов. */ + #pragma deprecated Use params controller instead ptLimits, } stock const VIPM_PARAM_TYPE_NAMES[E_ParamType][] = {"Custom", "Integer", "Float", "Bool", "String", "Color", "Vector2", "Vector3", "Limit", "Limits"}; From 9c92c3ae57780d1f3e925eced12891931ad6292a Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Tue, 6 Jan 2026 12:11:38 +0300 Subject: [PATCH 075/108] Try to fix CI --- .github/workflows/CI.yml | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 63a527d..7b7b197 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,7 +17,7 @@ env: PLUGINS_INI_GENERATE: 1 PLUGINS_INI_POSTFIX: vipm DEPS_LIST: | - AmxxModularEcosystem/ParamsController@1.2.0 + AmxxModularEcosystem/ParamsController@1.3.0 AmxxModularEcosystem/CommandAliases@1.0.1 jobs: @@ -76,8 +76,9 @@ jobs: OUTPUT_VAR_NAME: DEPS_COMPILER_ARGS run: | handleDep() { - REPO=`echo $1 | grep -Po '.+(?=@)'` - TAG=`echo $1 | grep -Po '(?<=@).+(?=:)'` + REPO="${1%%@*}" + TAG="${1#*@}" + TAG="${TAG%%:*}" OVERRIDE_INCLUDE_PATH=`echo $1 | grep -Po '(?<=:).+'` if [ -z "$REPO" ]; then @@ -89,28 +90,39 @@ jobs: mkdir -p dep/${REPO} cd dep/${REPO} - if [ -z "$2" ]; then + if [ -z "$" ]; then TAG=`curl --silent https://api.github.com/repos/${REPO}/releases/latest | jq .tag_name -r` - else - TAG=$2 fi - wget https://github.com/${REPO}/archive/refs/tags/${TAG}.zip - 7z x ${TAG}.zip + wget https://github.com/${REPO}/archive/refs/tags/${TAG}.zip -q > /dev/null + 7z x ${TAG}.zip > /dev/null REPO_NAME=`echo "${REPO}" | grep -Po '(?<=\/).+'` - INCLUDE_PATH='$(pwd)/${REPO_NAME}-${TAG}/${OVERRIDE_INCLUDE_PATH:-amxmodx/scripting/include}' + INCLUDE_PATH="$(pwd)/${REPO_NAME}-${TAG}/${OVERRIDE_INCLUDE_PATH:-amxmodx/scripting/include}" - echo "${OUTPUT_VAR_NAME}=\"\${${OUTPUT_VAR_NAME}} -i\\\"${INCLUDE_PATH}\\\"\"" >> $GITHUB_ENV + echo "-i\"${INCLUDE_PATH}\"" cd $INIT_PWD } + # Собираем все аргументы в локальную переменную + DEPS_COMPILER_ARGS="" + deps=$(echo ${DEPS_LIST} | tr ";" "\n") + echo "deps: ${deps}" + echo "-" + echo "-" + for dep in $deps do - handleDep $dep + # Вызываем функцию, но перенаправляем её вывод в локальную переменную + path_arg=$(handleDep "$dep") + DEPS_COMPILER_ARGS="${DEPS_COMPILER_ARGS} ${path_arg}" done + + # Записываем финальную переменную + echo "Final ${OUTPUT_VAR_NAME}: ${DEPS_COMPILER_ARGS}" + echo "${OUTPUT_VAR_NAME}=${DEPS_COMPILER_ARGS}" >> $GITHUB_ENV - name: Setup AMXXPawn Compiler uses: wopox1337/setup-amxxpawn@v1.1.0 @@ -132,11 +144,12 @@ jobs: mkdir -p $(dirname $output_path) - echo -n "Compiling $sourcefile ... " + echo "Compiling $sourcefile ... " + echo "amxxpc $sourcefile -o\"$output_path\" -i\"include\" -i\"$REAPI_INCLUDE\" $DEPS_COMPILER_ARGS GITHUB_ACTIONS_USED=1" amxxpc $sourcefile -o"$output_path" \ -i"include" \ -i"$REAPI_INCLUDE" \ - ${DEPS_COMPILER_ARGS} \ + $DEPS_COMPILER_ARGS \ GITHUB_ACTIONS_USED=1 if [ ! -z "${PLUGINS_INI_GENERATE}" ]; then From 03a5ffbeecbf8de08285c9c315602dedf36818d1 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Tue, 6 Jan 2026 23:09:07 +0300 Subject: [PATCH 076/108] Some refactors --- amxmodx/scripting/VipM/Core/API/Modules.inc | 9 +- .../VipM/Core/Objects/Limits/Type.inc | 90 +++++++++---------- .../VipM/Core/Objects/Limits/Unit.inc | 1 - .../VipM/Core/Objects/Modules/Type.inc | 26 +++--- .../VipM/Core/Objects/Modules/Unit.inc | 1 - .../DefaultObjects/ParamType/LimitType.inc | 27 ++++++ .../VipM/DefaultObjects/Registrar.inc | 2 + amxmodx/scripting/include/VipM/Limits.inc | 1 + 8 files changed, 94 insertions(+), 63 deletions(-) create mode 100644 amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc diff --git a/amxmodx/scripting/VipM/Core/API/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc index f45feb3..e087f4c 100644 --- a/amxmodx/scripting/VipM/Core/API/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -42,12 +42,13 @@ T_ModuleType:@_Modules_Register(const PluginId) { return; } - new Array:aParams = CfgParam_GetFromNative(Arg_Params, iParamsNum); - if (aParams == Invalid_Array) { + new Array:params = CfgParam_GetFromNative(Arg_Params, iParamsNum); + if (params == Invalid_Array) { return; } - ModuleType_AddParams(iModuleType, aParams); + ModuleType_AddParams(iModuleType, params); + ArrayDestroy(params); } @VipM_Modules_AddParamsEx(const pluginIndex, const paramsCount) { @@ -65,6 +66,8 @@ T_ModuleType:@_Modules_Register(const PluginId) { new Array:params = ParamsController_Param_ListFromNativeParams(Arg_Params, paramsCount); ModuleType_AddParams(module, params); ArrayDestroy(params); + + set_error_filter() } bool:@_Modules_RegisterEvent(const PluginId) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 5000a1b..52be831 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -25,27 +25,27 @@ enum _:S_LimitType { enum T_LimitType { Invalid_LimitType = -1 } -static ArrayMap(g_amLimitTypes); // S_LimitType +static ArrayMap(LimitTypes); // S_LimitType LimitType_Init() { CallOnce(); log_amx("Init limit types..."); - ArrayMapCreate(g_amLimitTypes, S_LimitType); + ArrayMapCreate(LimitTypes, S_LimitType); log_amx("Limit types inited."); } Array:LimitType_GetAll() { - return ArrayClone(g_amLimitTypes[AM_Arr]); + return ArrayClone(LimitTypes[AM_Arr]); } LimitType_GetCount() { - return ArraySizeSafe(g_amLimitTypes[AM_Arr]); + return ArraySizeSafe(LimitTypes[AM_Arr]); } T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, const bool:bStatic = false) { - if (!ArrayMapCreated(g_amLimitTypes)) { + if (!ArrayMapCreated(LimitTypes)) { abort(AMX_ERR_GENERAL, "Attempt to create limit type before limits controller init."); return Invalid_LimitType; } @@ -55,37 +55,37 @@ T_LimitType:LimitType_Construct(const sName[], const bool:bForPlayer = false, co return Invalid_LimitType; } - new LimitType[S_LimitType]; + new typeObject[S_LimitType]; - copy(LimitType[LimitType_Name], charsmax(LimitType[LimitType_Name]), sName); - LimitType[LimitType_Params] = ArrayCreate(1, 1); + copy(typeObject[LimitType_Name], charsmax(typeObject[LimitType_Name]), sName); + typeObject[LimitType_Params] = ArrayCreate(1, 1); - LimitType[LimitType_Static] = bStatic; - LimitType[LimitType_StaticValue] = 0; + typeObject[LimitType_Static] = bStatic; + typeObject[LimitType_StaticValue] = 0; - LimitType[LimitType_ForPlayer] = bForPlayer; + typeObject[LimitType_ForPlayer] = bForPlayer; - arrayset(LimitType[LimitType_Events], -1, sizeof(LimitType[LimitType_Events])); + arrayset(typeObject[LimitType_Events], -1, sizeof(typeObject[LimitType_Events])); - log_amx("Limit type '%s' registered.", LimitType[LimitType_Name]); + log_amx("Limit type '%s' registered.", typeObject[LimitType_Name]); - return T_LimitType:ArrayMapPushArray(g_amLimitTypes, LimitType, LimitType[LimitType_Name]); + return T_LimitType:ArrayMapPushArray(LimitTypes, typeObject, typeObject[LimitType_Name]); } T_LimitType:LimitType_Find(const sName[]) { - if (ArrayMapKeyExists(g_amLimitTypes, sName)) { - return T_LimitType:ArrayMapGetIndex(g_amLimitTypes, sName); + if (ArrayMapKeyExists(LimitTypes, sName)) { + return T_LimitType:ArrayMapGetIndex(LimitTypes, sName); } else { return Invalid_LimitType; } } -static LimitType__Get(const T_LimitType:type, LimitType[S_LimitType]) { - ArrayMapGetArray(g_amLimitTypes, _:type, LimitType); +static LimitType__Get(const T_LimitType:type, typeObject[S_LimitType]) { + ArrayMapGetArray(LimitTypes, _:type, typeObject); } -static LimitType__Set(const LimitType[S_LimitType]) { - ArrayMapSetArrayByKey(g_amLimitTypes, LimitType[LimitType_Name], LimitType); +static LimitType__Set(const typeObject[S_LimitType]) { + ArrayMapSetArrayByKey(LimitTypes, typeObject[LimitType_Name], typeObject); } LimitType_AddParams(const T_LimitType:type, const Array:params) { @@ -152,20 +152,20 @@ LimitType_SetEventListener( const PluginId, const sFuncName[] ) { - new LimitType[S_LimitType]; - LimitType__Get(type, LimitType); + new typeObject[S_LimitType]; + LimitType__Get(type, typeObject); - if (LimitType[LimitType_Events][iEvent] >= 0) { - DestroyForward(LimitType[LimitType_Events][iEvent]); + if (typeObject[LimitType_Events][iEvent] >= 0) { + DestroyForward(typeObject[LimitType_Events][iEvent]); } - LimitType[LimitType_Events][iEvent] = LimitType__MakeEventForward(iEvent, PluginId, sFuncName); + typeObject[LimitType_Events][iEvent] = LimitType__MakeEventForward(iEvent, PluginId, sFuncName); - if (LimitType[LimitType_Events][iEvent] < 0) { + if (typeObject[LimitType_Events][iEvent] < 0) { abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); } - LimitType__Set(LimitType); + LimitType__Set(typeObject); } static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, const sFuncName[]) { @@ -182,47 +182,47 @@ static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, co } bool:LimitType_IsStatic(const T_LimitType:type) { - new LimitType[S_LimitType]; - LimitType__Get(type, LimitType); + new typeObject[S_LimitType]; + LimitType__Get(type, typeObject); - return LimitType[LimitType_Static]; + return typeObject[LimitType_Static]; } LimitType_SetStaticValue(const T_LimitType:type, const bool:bValue, const UserId = 0) { - new LimitType[S_LimitType]; - LimitType__Get(type, LimitType); + new typeObject[S_LimitType]; + LimitType__Get(type, typeObject); - if (!LimitType[LimitType_Static]) { + if (!typeObject[LimitType_Static]) { abort(AMX_ERR_PARAMS, "Trying to set static value for a non-static limit."); return; } if (UserId > 0) { - BitSetIf(LimitType[LimitType_StaticValue], UserId - 1, bValue); + BitSetIf(typeObject[LimitType_StaticValue], UserId - 1, bValue); } else { - LimitType[LimitType_StaticValue] = bValue; + typeObject[LimitType_StaticValue] = bValue; } - LimitType__Set(LimitType); + LimitType__Set(typeObject); } bool:LimitType_Execute(const T_LimitType:type, const Trie:tParams, const UserId = 0) { - new LimitType[S_LimitType]; - LimitType__Get(type, LimitType); + new typeObject[S_LimitType]; + LimitType__Get(type, typeObject); new bool:bRes = false; - if (LimitType[LimitType_Static]) { - if (LimitType[LimitType_ForPlayer]) { - bRes = BitIs(LimitType[LimitType_StaticValue], UserId - 1); + if (typeObject[LimitType_Static]) { + if (typeObject[LimitType_ForPlayer]) { + bRes = BitIs(typeObject[LimitType_StaticValue], UserId - 1); } else { - bRes = !!LimitType[LimitType_StaticValue]; + bRes = !!typeObject[LimitType_StaticValue]; } } else { - if (LimitType[LimitType_Events][Limit_OnCheck] < 0) { - abort(AMX_ERR_GENERAL, "'Limit_OnCheck' event listener for non-static limit type '%s' must be implemented.", LimitType[LimitType_Name]); + if (typeObject[LimitType_Events][Limit_OnCheck] < 0) { + abort(AMX_ERR_GENERAL, "'Limit_OnCheck' event listener for non-static limit type '%s' must be implemented.", typeObject[LimitType_Name]); bRes = false; } else { - ExecuteForward(LimitType[LimitType_Events][Limit_OnCheck], bRes, tParams, UserId); + ExecuteForward(typeObject[LimitType_Events][Limit_OnCheck], bRes, tParams, UserId); } } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 99631b8..b9b551f 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -7,7 +7,6 @@ #include #include #include "VipM/Utils" -#include "VipM/ArrayMap" #include "VipM/ArrayTrieUtils" #include "VipM/Core/Objects/Limits/Type" diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index 6b8c92c..2eabdb4 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -24,13 +24,13 @@ enum _:S_ModuleType { enum T_ModuleType { Invalid_ModuleType = -1 } -static ArrayMap(g_amModuleTypes); // S_ModuleType +static ArrayMap(ModuleTypes); // S_ModuleType ModuleType_Init() { CallOnce(); log_amx("Init module types..."); - ArrayMapCreate(g_amModuleTypes, S_ModuleType); + ArrayMapCreate(ModuleTypes, S_ModuleType); Forwards_Reg("VipM_Modules_OnActivate", ET_STOP, FP_STRING); @@ -38,15 +38,15 @@ ModuleType_Init() { } Array:ModuleType_GetAll() { - return ArrayClone(g_amModuleTypes[AM_Arr]); + return ArrayClone(ModuleTypes[AM_Arr]); } ModuleType_GetCount() { - return ArrayMapSize(g_amModuleTypes); + return ArrayMapSize(ModuleTypes); } T_ModuleType:ModuleType_Construct(const sName[]) { - if (!ArrayMapCreated(g_amModuleTypes)) { + if (!ArrayMapCreated(ModuleTypes)) { abort(AMX_ERR_GENERAL, "Attempt to create module type before modules init."); return Invalid_ModuleType; } @@ -68,31 +68,31 @@ T_ModuleType:ModuleType_Construct(const sName[]) { log_amx("Module type '%s' registered.", ModuleType[ModuleType_Name]); - return T_ModuleType:ArrayMapPushArray(g_amModuleTypes, ModuleType, ModuleType[ModuleType_Name]); + return T_ModuleType:ArrayMapPushArray(ModuleTypes, ModuleType, ModuleType[ModuleType_Name]); } T_ModuleType:ModuleType_Find(const sName[]) { - if (ArrayMapKeyExists(g_amModuleTypes, sName)) { - return T_ModuleType:ArrayMapGetIndex(g_amModuleTypes, sName); + if (ArrayMapKeyExists(ModuleTypes, sName)) { + return T_ModuleType:ArrayMapGetIndex(ModuleTypes, sName); } else { return Invalid_ModuleType; } } static ModuleType__Get(const T_ModuleType:iModuleType, ModuleType[S_ModuleType]) { - ArrayMapGetArray(g_amModuleTypes, _:iModuleType, ModuleType); + ArrayMapGetArray(ModuleTypes, _:iModuleType, ModuleType); } static ModuleType__Save(const ModuleType[S_ModuleType]) { - ArrayMapSetArrayByKey(g_amModuleTypes, ModuleType[ModuleType_Name], ModuleType); + ArrayMapSetArrayByKey(ModuleTypes, ModuleType[ModuleType_Name], ModuleType); } static ModuleType__SetValue(const T_ModuleType:iModuleType, const iCell, const any:iValue) { - return ArrayMapSetCell(g_amModuleTypes, iModuleType, iValue, iCell); + return ArrayMapSetCell(ModuleTypes, iModuleType, iValue, iCell); } static any:ModuleType__GetValue(const T_ModuleType:iModuleType, const iCell) { - return ArrayMapGetCell(g_amModuleTypes, iModuleType, iCell); + return ArrayMapGetCell(ModuleTypes, iModuleType, iCell); } ModuleType_GetName(const T_ModuleType:iModuleType, sOut[], const iOutLen) { @@ -235,7 +235,7 @@ bool:ModuleType_Activate(const T_ModuleType:type) { } ModuleType_ActivateUsed() { - ArrayMapForeachArray (g_amModuleTypes: type => ModuleType[S_ModuleType]) { + ArrayMapForeachArray (ModuleTypes: type => ModuleType[S_ModuleType]) { if (ModuleType[ModuleType_Used]) { ModuleType_Activate(type); } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index d6ee44e..a7105ff 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -7,7 +7,6 @@ #include "VipM/Utils" #include "VipM/Forwards" #include -#include "VipM/ArrayMap" #include "VipM/ArrayTrieUtils" #include "VipM/Core/Objects/Modules/Type" diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc new file mode 100644 index 0000000..5e631ad --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#include "VipM/Core/Objects/Limits/Type" + +DefaultObjects_ParamType_LimitType_Register() { + ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMIT_TYPE_NAME, "@DefaultObjects_ParamType_LimitType_OnRead"); +} + +bool:@DefaultObjects_ParamType_LimitType_OnRead(const JSON:valueJson) { + new typeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; + PCSingle_ShortString(valueJson, typeName, charsmax(typeName)); + trim(typeName); + + if (typeName[0] == EOS) { + return PCJson_LogForFile(valueJson, "WARNING", "Limit type name not specified."); + } + + new T_LimitType:type = LimitType_Find(typeName); + if (type == Invalid_LimitType) { + return PCJson_LogForFile(valueJson, "WARNING", "Limit type '%s' not found.", typeName); + } + + return ParamsController_SetCell(type); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc index a5d1c64..1da3a86 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc @@ -2,11 +2,13 @@ #include "VipM/DefaultObjects/ParamType/Limit" #include "VipM/DefaultObjects/ParamType/Limits" +#include "VipM/DefaultObjects/ParamType/LimitType" #include "VipM/DefaultObjects/ParamType/CounterType" public ParamsController_OnRegisterTypes() { DefaultObjects_ParamType_Limit_Register(); DefaultObjects_ParamType_Limits_Register(); + DefaultObjects_ParamType_LimitType_Register(); DefaultObjects_ParamType_CounterType_Register(); } diff --git a/amxmodx/scripting/include/VipM/Limits.inc b/amxmodx/scripting/include/VipM/Limits.inc index 9b60d63..245098b 100644 --- a/amxmodx/scripting/include/VipM/Limits.inc +++ b/amxmodx/scripting/include/VipM/Limits.inc @@ -12,6 +12,7 @@ #define VIPM_LIMITS_TYPE_NAME_MAX_LEN 64 +stock const VIPM_PARAM_TYPE_LIMIT_TYPE_NAME[] = "VipM-LimitType"; stock const VIPM_PARAM_TYPE_LIMIT_NAME[] = "VipM-Limit"; stock const VIPM_PARAM_TYPE_LIMITS_NAME[] = "VipM-Limits"; From 1f0b3c7a861aff8ff8b251371c3e8bc0e6d9c21c Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 7 Jan 2026 00:16:08 +0300 Subject: [PATCH 077/108] Fix --- amxmodx/scripting/VipM/Core/API/Modules.inc | 2 -- .../VipM/Core/Objects/Limits/Type.inc | 5 +++++ .../VipM/Core/Objects/Limits/Unit.inc | 22 +------------------ 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/amxmodx/scripting/VipM/Core/API/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc index e087f4c..33e2df7 100644 --- a/amxmodx/scripting/VipM/Core/API/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -66,8 +66,6 @@ T_ModuleType:@_Modules_Register(const PluginId) { new Array:params = ParamsController_Param_ListFromNativeParams(Arg_Params, paramsCount); ModuleType_AddParams(module, params); ArrayDestroy(params); - - set_error_filter() } bool:@_Modules_RegisterEvent(const PluginId) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index 52be831..ca139af 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -4,6 +4,7 @@ #define __vipm_core_objects_limits_type_included #include +#include #include #include #include "VipM/Utils" @@ -228,3 +229,7 @@ bool:LimitType_Execute(const T_LimitType:type, const Trie:tParams, const UserId return bRes; } + +T_LimitType:PCSingle_ObjVipmLimitType(const JSON:objectJson, const key[], const T_LimitType:def = Invalid_LimitType, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, VIPM_PARAM_TYPE_LIMIT_TYPE_NAME, def, dotNot, orFail); +} diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index b9b551f..f9fa191 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -63,26 +63,6 @@ static bool:LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit], return true; } -static T_LimitType:LimitUnit__ReadType(const JSON:limitJson) { - new typeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; - PCSingle_ObjString(limitJson, "Limit", typeName, charsmax(typeName)); - trim(typeName); - - if (!typeName[0]) { - PCJson_ErrorForFile(limitJson, "Limit type name not specified."); - return Invalid_LimitType; - } - - new T_LimitType:type = LimitType_Find(typeName); - - if (type == Invalid_LimitType) { - PCJson_ErrorForFile(limitJson, "Limit type '%s' not found.", typeName); - return Invalid_LimitType; - } - - return type; -} - T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { static Trie:cache = Invalid_Trie; TrieCreateIfNotCreated(cache); @@ -92,7 +72,7 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { return cached; } - new T_LimitType:type = LimitUnit__ReadType(linked); + new T_LimitType:type = PCSingle_ObjVipmLimitType(linked, "Limit", .orFail = true); if (type == Invalid_LimitType) { PCJson_FreeLinked(linked); return Invalid_LimitUnit; From c941e91ea189c67386f91b98e2d770984d6dc162 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 7 Jan 2026 00:16:36 +0300 Subject: [PATCH 078/108] Yet another try to fix CI)) --- .github/workflows/CI.yml | 44 +++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7b7b197..7562372 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -79,7 +79,7 @@ jobs: REPO="${1%%@*}" TAG="${1#*@}" TAG="${TAG%%:*}" - OVERRIDE_INCLUDE_PATH=`echo $1 | grep -Po '(?<=:).+'` + OVERRIDE_INCLUDE_PATH=$(echo "$1" | grep -Po '(?<=:).+' || true) if [ -z "$REPO" ]; then echo "No repo provided" @@ -87,40 +87,33 @@ jobs: fi INIT_PWD=$(pwd) - mkdir -p dep/${REPO} - cd dep/${REPO} + mkdir -p "dep/${REPO}" + cd "dep/${REPO}" - if [ -z "$" ]; then - TAG=`curl --silent https://api.github.com/repos/${REPO}/releases/latest | jq .tag_name -r` + if [ -z "$TAG" ]; then + TAG=$(curl --silent "https://api.github.com/repos/${REPO}/releases/latest" | jq -r .tag_name) fi - wget https://github.com/${REPO}/archive/refs/tags/${TAG}.zip -q > /dev/null - 7z x ${TAG}.zip > /dev/null + wget -q "https://github.com/${REPO}/archive/refs/tags/${TAG}.zip" + 7z x "${TAG}.zip" > /dev/null - REPO_NAME=`echo "${REPO}" | grep -Po '(?<=\/).+'` + REPO_NAME=$(echo "${REPO}" | grep -Po '(?<=\/).+') INCLUDE_PATH="$(pwd)/${REPO_NAME}-${TAG}/${OVERRIDE_INCLUDE_PATH:-amxmodx/scripting/include}" - echo "-i\"${INCLUDE_PATH}\"" + # ВАЖНО: без кавычек внутри аргумента + echo "-i${INCLUDE_PATH}" - cd $INIT_PWD + cd "$INIT_PWD" } - # Собираем все аргументы в локальную переменную DEPS_COMPILER_ARGS="" - - deps=$(echo ${DEPS_LIST} | tr ";" "\n") - echo "deps: ${deps}" - echo "-" - echo "-" - - for dep in $deps - do - # Вызываем функцию, но перенаправляем её вывод в локальную переменную + + while IFS= read -r dep; do + [ -z "$dep" ] && continue path_arg=$(handleDep "$dep") DEPS_COMPILER_ARGS="${DEPS_COMPILER_ARGS} ${path_arg}" - done - - # Записываем финальную переменную + done <<< "$DEPS_LIST" + echo "Final ${OUTPUT_VAR_NAME}: ${DEPS_COMPILER_ARGS}" echo "${OUTPUT_VAR_NAME}=${DEPS_COMPILER_ARGS}" >> $GITHUB_ENV @@ -146,6 +139,11 @@ jobs: echo "Compiling $sourcefile ... " echo "amxxpc $sourcefile -o\"$output_path\" -i\"include\" -i\"$REAPI_INCLUDE\" $DEPS_COMPILER_ARGS GITHUB_ACTIONS_USED=1" + + echo "DEPS_COMPILER_ARGS=[$DEPS_COMPILER_ARGS]" + echo "Listing dep tree:" + find ../.. -maxdepth 4 -type d -path "*ParamsController*" -o -path "*CommandAliases*" + amxxpc $sourcefile -o"$output_path" \ -i"include" \ -i"$REAPI_INCLUDE" \ From d440a106904116efe3bb28bf108e71600d6810cd Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 7 Jan 2026 00:22:17 +0300 Subject: [PATCH 079/108] Bump params controller version --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7562372..aabec6c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,7 +17,7 @@ env: PLUGINS_INI_GENERATE: 1 PLUGINS_INI_POSTFIX: vipm DEPS_LIST: | - AmxxModularEcosystem/ParamsController@1.3.0 + AmxxModularEcosystem/ParamsController@1.3.1 AmxxModularEcosystem/CommandAliases@1.0.1 jobs: From c7ab72e951dcb2fae90b541ff27bc283009e2ea4 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Thu, 8 Jan 2026 00:53:13 +0300 Subject: [PATCH 080/108] Some refactors --- .../VipM/Core/Objects/Limits/Type.inc | 52 ++++++++-------- .../VipM/Core/Objects/Limits/Unit.inc | 54 ++++++++--------- .../VipM/Core/Objects/Modules/Type.inc | 9 ++- .../VipM/Core/Objects/Modules/Unit.inc | 60 ++++++------------- .../DefaultObjects/ParamType/ModuleType.inc | 27 +++++++++ .../VipM/DefaultObjects/Registrar.inc | 4 +- amxmodx/scripting/include/VipM/Modules.inc | 35 ++++------- 7 files changed, 117 insertions(+), 124 deletions(-) create mode 100644 amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc index ca139af..17ffeae 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Type.inc @@ -149,36 +149,36 @@ Trie:LimitType_ReadParams(const T_LimitType:type, const JSON:paramsJson) { LimitType_SetEventListener( const T_LimitType:type, - const E_LimitEvent:iEvent, - const PluginId, - const sFuncName[] + const E_LimitEvent:event, + const pluginIndex, + const func[] ) { new typeObject[S_LimitType]; LimitType__Get(type, typeObject); - if (typeObject[LimitType_Events][iEvent] >= 0) { - DestroyForward(typeObject[LimitType_Events][iEvent]); + if (typeObject[LimitType_Events][event] >= 0) { + DestroyForward(typeObject[LimitType_Events][event]); } - typeObject[LimitType_Events][iEvent] = LimitType__MakeEventForward(iEvent, PluginId, sFuncName); + typeObject[LimitType_Events][event] = LimitType__MakeEventForward(event, pluginIndex, func); - if (typeObject[LimitType_Events][iEvent] < 0) { - abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", sFuncName, PluginId); + if (typeObject[LimitType_Events][event] < 0) { + abort(AMX_ERR_PARAMS, "[ERROR] Can't create forward for func '%s' in plugin #%d.", func, pluginIndex); } LimitType__Set(typeObject); } -static LimitType__MakeEventForward(const E_LimitEvent:iEvent, const PluginId, const sFuncName[]) { - switch (iEvent) { - case Limit_OnRead: // (const JSON:jCfg, Trie:tParams) - return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); +static LimitType__MakeEventForward(const E_LimitEvent:event, const pluginIndex, const func[]) { + switch (event) { + case Limit_OnRead: // (const JSON:jCfg, Trie:p) + return CreateOneForward(pluginIndex, func, FP_CELL, FP_CELL); - case Limit_OnCheck: // (const Trie:tParams, const UserId) - return CreateOneForward(PluginId, sFuncName, FP_CELL, FP_CELL); + case Limit_OnCheck: // (const Trie:p, const playerIndex) + return CreateOneForward(pluginIndex, func, FP_CELL, FP_CELL); } - abort(AMX_ERR_GENERAL, "[ERROR] Invalid event index (%d).", iEvent); + abort(AMX_ERR_GENERAL, "[ERROR] Invalid event index (%d).", event); return -1; } @@ -189,7 +189,7 @@ bool:LimitType_IsStatic(const T_LimitType:type) { return typeObject[LimitType_Static]; } -LimitType_SetStaticValue(const T_LimitType:type, const bool:bValue, const UserId = 0) { +LimitType_SetStaticValue(const T_LimitType:type, const bool:value, const playerIndex = 0) { new typeObject[S_LimitType]; LimitType__Get(type, typeObject); @@ -198,36 +198,36 @@ LimitType_SetStaticValue(const T_LimitType:type, const bool:bValue, const UserId return; } - if (UserId > 0) { - BitSetIf(typeObject[LimitType_StaticValue], UserId - 1, bValue); + if (playerIndex > 0) { + BitSetIf(typeObject[LimitType_StaticValue], playerIndex - 1, value); } else { - typeObject[LimitType_StaticValue] = bValue; + typeObject[LimitType_StaticValue] = value; } LimitType__Set(typeObject); } -bool:LimitType_Execute(const T_LimitType:type, const Trie:tParams, const UserId = 0) { +bool:LimitType_Execute(const T_LimitType:type, const Trie:p, const playerIndex = 0) { new typeObject[S_LimitType]; LimitType__Get(type, typeObject); - new bool:bRes = false; + new bool:res = false; if (typeObject[LimitType_Static]) { if (typeObject[LimitType_ForPlayer]) { - bRes = BitIs(typeObject[LimitType_StaticValue], UserId - 1); + res = BitIs(typeObject[LimitType_StaticValue], playerIndex - 1); } else { - bRes = !!typeObject[LimitType_StaticValue]; + res = !!typeObject[LimitType_StaticValue]; } } else { if (typeObject[LimitType_Events][Limit_OnCheck] < 0) { abort(AMX_ERR_GENERAL, "'Limit_OnCheck' event listener for non-static limit type '%s' must be implemented.", typeObject[LimitType_Name]); - bRes = false; + res = false; } else { - ExecuteForward(typeObject[LimitType_Events][Limit_OnCheck], bRes, tParams, UserId); + ExecuteForward(typeObject[LimitType_Events][Limit_OnCheck], res, p, playerIndex); } } - return bRes; + return res; } T_LimitType:PCSingle_ObjVipmLimitType(const JSON:objectJson, const key[], const T_LimitType:def = Invalid_LimitType, const bool:dotNot = false, const bool:orFail = false) { diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index f9fa191..063c175 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -18,7 +18,7 @@ enum _:S_LimitUnit { Trie:LimitUnit_Params, } -static Array:g_aLimitUnits = Invalid_Array; +static Array:LimitUnits = Invalid_Array; LimitUnit_Init() { CallOnce(); @@ -26,40 +26,40 @@ LimitUnit_Init() { LimitType_Init(); - g_aLimitUnits = ArrayCreate(S_LimitUnit, 1); + LimitUnits = ArrayCreate(S_LimitUnit, 1); Forwards_RegAndCall("VipM_Limits_OnInited", ET_IGNORE); log_amx("Limit units inited."); } LimitUnit_GetCount() { - return ArraySizeSafe(g_aLimitUnits); + return ArraySizeSafe(LimitUnits); } -static T_LimitUnit:LimitUnit__Construct(const T_LimitType:iLimitType, const Trie:params) { - if (g_aLimitUnits == Invalid_Array) { +static T_LimitUnit:LimitUnit__Construct(const T_LimitType:type, const Trie:p) { + if (LimitUnits == Invalid_Array) { abort(AMX_ERR_GENERAL, "Attempt to create limit unit before init."); return Invalid_LimitUnit; } - new LimitUnit[S_LimitUnit]; + new unitObject[S_LimitUnit]; - LimitUnit[LimitUnit_Type] = iLimitType; - LimitUnit[LimitUnit_Params] = params; + unitObject[LimitUnit_Type] = type; + unitObject[LimitUnit_Params] = p; - return T_LimitUnit:ArrayPushArray(g_aLimitUnits, LimitUnit); + return T_LimitUnit:ArrayPushArray(LimitUnits, unitObject); } -static bool:LimitUnit__Get(const T_LimitUnit:iLimitUnit, LimitUnit[S_LimitUnit], const bool:bOrFail = true) { - if (_:iLimitUnit < 0 || _:iLimitUnit >= LimitUnit_GetCount()) { - if (bOrFail) { - abort(AMX_ERR_NOTFOUND, "Invalid limit unit index (%d).", iLimitUnit); +static bool:LimitUnit__Get(const T_LimitUnit:limit, unitObject[S_LimitUnit], const bool:orFail = true) { + if (_:limit < 0 || _:limit >= LimitUnit_GetCount()) { + if (orFail) { + abort(AMX_ERR_NOTFOUND, "Invalid limit unit index (%d).", limit); } return false; } - ArrayGetArray(g_aLimitUnits, _:iLimitUnit, LimitUnit); + ArrayGetArray(LimitUnits, _:limit, unitObject); return true; } @@ -78,16 +78,16 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { return Invalid_LimitUnit; } - new Trie:params = Invalid_Trie; + new Trie:p = Invalid_Trie; if (!LimitType_IsStatic(type)) { - params = LimitType_ReadParams(type, linked); - if (params == Invalid_Trie) { + p = LimitType_ReadParams(type, linked); + if (p == Invalid_Trie) { PCJson_FreeLinked(linked); return Invalid_LimitUnit; } } - cached = LimitUnit__Construct(type, params); + cached = LimitUnit__Construct(type, p); if (linkPath[0] != EOS && cached != Invalid_LimitUnit) { TrieSetCell(cache, linkPath, cached); } @@ -96,31 +96,31 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { return cached; } -Array:LimitUnit_ReadList(const JSON:limitsJson, &Array:limits = Invalid_Array) { - if (limits == Invalid_Array) { - limits = ArrayCreate(1, 1); +Array:LimitUnit_ReadList(const JSON:limitsJson, &Array:append = Invalid_Array) { + if (append == Invalid_Array) { + append = ArrayCreate(1, 1); } if (!json_is_array(limitsJson)) { new T_LimitUnit:limit = LimitUnit_Read(limitsJson); if (limit != Invalid_LimitUnit) { - ArrayPushCell(limits, limit); + ArrayPushCell(append, limit); } } else { json_array_foreach_value (limitsJson: i => limitJson) { - limits = LimitUnit_ReadList(limitJson, limits); + append = LimitUnit_ReadList(limitJson, append); json_free(limitJson); } } - return limits; + return append; } bool:LimitUnit_Execute(const T_LimitUnit:limit, const UserId = 0) { - new LimitUnit[S_LimitUnit]; - LimitUnit__Get(limit, LimitUnit); + new unitObject[S_LimitUnit]; + LimitUnit__Get(limit, unitObject); - return LimitType_Execute(LimitUnit[LimitUnit_Type], LimitUnit[LimitUnit_Params], UserId); + return LimitType_Execute(unitObject[LimitUnit_Type], unitObject[LimitUnit_Params], UserId); } bool:LimitUnit_ExecuteList( diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc index 2eabdb4..04d2680 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Type.inc @@ -173,11 +173,6 @@ ModuleType_SetEventListener( new typeObject[S_ModuleType]; ModuleType__Get(type, typeObject); - if (event == Module_OnCompareParams) { - log_amx("[WARNING] Event 'Module_OnCompareParams' is deprecated and will not be fired."); - return; - } - if (typeObject[ModuleType_Events][event] >= 0) { DestroyForward(typeObject[ModuleType_Events][event]); } @@ -257,3 +252,7 @@ Trie:ModuleType_MergeParams(const T_ModuleType:type, const Trie:tParams1, const return tRes; } + +T_ModuleType:PCSingle_ObjVipmModuleType(const JSON:objectJson, const key[], const T_ModuleType:def = Invalid_ModuleType, const bool:dotNot = false, const bool:orFail = false) { + return PCSingle_ObjCell(objectJson, key, VIPM_PARAM_TYPE_MODULE_TYPE_NAME, def, dotNot, orFail); +} diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index a7105ff..622bf95 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -18,7 +18,7 @@ enum _:S_ModuleUnit { Trie:ModuleUnit_Params, } -static Array:g_aModuleUnits = Invalid_Array; +static Array:ModuleUnits = Invalid_Array; ModuleUnit_Init() { CallOnce(); @@ -26,58 +26,34 @@ ModuleUnit_Init() { ModuleType_Init(); - g_aModuleUnits = ArrayCreate(S_ModuleUnit, 1); + ModuleUnits = ArrayCreate(S_ModuleUnit, 1); Forwards_RegAndCall("VipM_Modules_OnInited", ET_IGNORE); log_amx("Module units inited."); } ModuleUnit_GetCount() { - return ArraySizeSafe(g_aModuleUnits); + return ArraySizeSafe(ModuleUnits); } -static T_ModuleUnit:ModuleUnit__Construct(const T_ModuleType:iModuleType, const Trie:tParams) { - if (g_aModuleUnits == Invalid_Array) { +static T_ModuleUnit:ModuleUnit__Construct(const T_ModuleType:type, const Trie:p) { + if (ModuleUnits == Invalid_Array) { abort(AMX_ERR_GENERAL, "Attempt to create module unit before init."); return Invalid_ModuleUnit; } - new ModuleUnit[S_ModuleUnit]; + new unitObject[S_ModuleUnit]; - ModuleUnit[ModuleUnit_Type] = iModuleType; - ModuleUnit[ModuleUnit_Params] = tParams; + unitObject[ModuleUnit_Type] = type; + unitObject[ModuleUnit_Params] = p; - ModuleType_MarkAsUsed(iModuleType); + ModuleType_MarkAsUsed(type); - return T_ModuleUnit:ArrayPushArray(g_aModuleUnits, ModuleUnit); + return T_ModuleUnit:ArrayPushArray(ModuleUnits, unitObject); } -// static ModuleUnit__Get(const T_ModuleUnit:iModuleUnit, ModuleUnit[S_ModuleUnit]) { -// ArrayGetArray(g_aModuleUnits, _:iModuleUnit, ModuleUnit); -// } - static any:ModuleUnit__GetValue(const T_ModuleUnit:iModuleUnit, const iCell) { - return ArrayGetCell(g_aModuleUnits, _:iModuleUnit, iCell); -} - -static T_ModuleType:ModuleUnit__ReadType(const JSON:jModuleUnit) { - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - PCSingle_ObjString(jModuleUnit, "Module", sModuleTypeName, charsmax(sModuleTypeName)); - trim(sModuleTypeName); - - if (!sModuleTypeName[0]) { - PCJson_ErrorForFile(jModuleUnit, "Module type name not specified."); - return Invalid_ModuleType; - } - - new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); - - if (iModuleType == Invalid_ModuleType) { - PCJson_ErrorForFile(jModuleUnit, "Module type '%s' not found.", sModuleTypeName); - return Invalid_ModuleType; - } - - return iModuleType; + return ArrayGetCell(ModuleUnits, _:iModuleUnit, iCell); } T_ModuleUnit:ModuleUnit_Read(const JSON:valueJson) { @@ -89,7 +65,7 @@ T_ModuleUnit:ModuleUnit_Read(const JSON:valueJson) { return cached; } - new T_ModuleType:type = ModuleUnit__ReadType(linked); + new T_ModuleType:type = PCSingle_ObjVipmModuleType(linked, "Module", .orFail = true); if (type == Invalid_ModuleType) { PCJson_FreeLinked(linked); return Invalid_ModuleUnit; @@ -154,16 +130,16 @@ ModuleUnit_GetTypeName(const T_ModuleUnit:iModuleUnit, sOut[], const iOutLen) { // return sName; // } -Trie:ModuleUnit_FreeParamsIfTemp(&Trie:tParams) { - if (tParams == Invalid_Trie) { - return tParams; +Trie:ModuleUnit_FreeParamsIfTemp(&Trie:p) { + if (p == Invalid_Trie) { + return p; } - if (TrieKeyExists(tParams, VIPM_MODULES_PARAMS_TEMP_MARK_KEY)) { - TrieDestroy(tParams); + if (TrieKeyExists(p, VIPM_MODULES_PARAMS_TEMP_MARK_KEY)) { + TrieDestroy(p); } - return tParams; + return p; } Trie:ModuleUnit_Merge(const T_ModuleUnit:iModuleUnit, const Trie:tParams1, const Trie:tParams2) { diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc new file mode 100644 index 0000000..fd08e45 --- /dev/null +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#include "VipM/Core/Objects/Modules/Type" + +DefaultObjects_ParamType_ModuleType_Register() { + ParamsController_RegSimpleType(VIPM_PARAM_TYPE_MODULE_TYPE_NAME, "@DefaultObjects_ParamType_ModuleType_OnRead"); +} + +bool:@DefaultObjects_ParamType_ModuleType_OnRead(const JSON:valueJson) { + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + PCSingle_ShortString(valueJson, typeName, charsmax(typeName)); + trim(typeName); + + if (typeName[0] == EOS) { + return PCJson_LogForFile(valueJson, "WARNING", "Module type name not specified."); + } + + new T_ModuleType:type = ModuleType_Find(typeName); + if (type == Invalid_ModuleType) { + return PCJson_LogForFile(valueJson, "WARNING", "Module type '%s' not found.", typeName); + } + + return ParamsController_SetCell(type); +} diff --git a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc index 1da3a86..1370160 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Registrar.inc @@ -1,14 +1,16 @@ -#include +#include #include "VipM/DefaultObjects/ParamType/Limit" #include "VipM/DefaultObjects/ParamType/Limits" #include "VipM/DefaultObjects/ParamType/LimitType" +#include "VipM/DefaultObjects/ParamType/ModuleType" #include "VipM/DefaultObjects/ParamType/CounterType" public ParamsController_OnRegisterTypes() { DefaultObjects_ParamType_Limit_Register(); DefaultObjects_ParamType_Limits_Register(); DefaultObjects_ParamType_LimitType_Register(); + DefaultObjects_ParamType_ModuleType_Register(); DefaultObjects_ParamType_CounterType_Register(); } diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index b8141c1..e780cc2 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -11,7 +11,9 @@ stock const VIPM_MODULES_PARAMS_TEMP_MARK_KEY[] = "___temp_module_params___"; -enum E_ModuleEvent{ +stock const VIPM_PARAM_TYPE_MODULE_TYPE_NAME[] = "VipM-ModuleType"; + +enum E_ModuleEvent { /* * Описание: Вызывается, когда модуль был активирован. @@ -35,19 +37,6 @@ enum E_ModuleEvent{ */ Module_OnRead, - /* - * Описание: Вызывается, когда надо обьединить два набора параметров модуля. Только для модулей с Once = false. - * Возв. тип: Trie - * Параметры: (const Trie:MainParams, const Trie:NewParams): - * MainParams - Основной набор параметров модуля. - * NewParams - Добавляемый набор параметров модуля. - * - * Примечание: Результат обьединения должен быть возвращён обработчиком события. - * - * УСТАРЕЛО! Используйте Module_OnMergeParams. - */ - Module_OnCompareParams, - /* * Описание: Вызывается при добавлении игроку второго и последующих модулей одного типа. * Возв. тип: Trie @@ -137,30 +126,30 @@ native VipM_Modules_AddParamsEx(const moduleName[], const any:...); /** * Активен ли указанный модуль. * - * @param Module Название модуля. + * @param moduleName Название модуля. * * @return true, если модуль активен, иначе false. */ -native bool:VipM_Modules_IsActive(const Module[]); +native bool:VipM_Modules_IsActive(const moduleName[]); /** * Получение набора параметров модуля для указанного игрока. * - * @param Module Название модуля. - * @param UserId Индекс игрока. + * @param moduleName Название модуля. + * @param playerIndex Индекс игрока. * * @return Trie с параметрами. */ -native Trie:VipM_Modules_GetParams(const Module[], const UserId); +native Trie:VipM_Modules_GetParams(const moduleName[], const playerIndex); /** * Проверка наличия у игрока доступа к указанному модулю. * - * @param sModuleName Название модуля. - * @param UserId Индекс игрока. + * @param moduleName Название модуля. + * @param playerIndex Индекс игрока. * * @return true, если у игрока имеется доступ к модулю, иначе false. */ -stock bool:VipM_Modules_HasModule(const sModuleName[], const UserId) { - return VipM_Modules_GetParams(sModuleName, UserId) != Invalid_Trie; +stock bool:VipM_Modules_HasModule(const moduleName[], const playerIndex) { + return VipM_Modules_GetParams(moduleName, playerIndex) != Invalid_Trie; } From ba83aaeb4ededec724f2b763ba2ea8d291625ea1 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Tue, 10 Feb 2026 13:05:35 +0300 Subject: [PATCH 081/108] Bump vipm and ic versions to rc --- amxmodx/scripting/include/ItemsController.inc | 2 +- amxmodx/scripting/include/VipModular.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index ff7c238..6af7677 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -7,7 +7,7 @@ #include #include -#define IC_VERSION "1.0.0" +#define IC_VERSION "1.0.0-rc1" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index dcf694c..25fc598 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-b13" +#define _VIPM_VERSION "5.0.0-rc1" stock const VIPM_VERSION[] = _VIPM_VERSION; #define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" From b0e35296ce18ba2c048c03cf8700095a815f0abb Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 02:21:25 +0300 Subject: [PATCH 082/108] Fix json refs usage; Fix `If` item type --- .github/workflows/CI.yml | 2 +- README.md | 2 +- amxmodx/scripting/ItemsController.sma | 5 +++-- .../ItemsController/DefaultObjects/ItemType/If.inc | 13 ++++++++----- .../DefaultObjects/ItemType/ItemsList.inc | 2 +- .../DefaultObjects/ItemType/Random.inc | 2 +- .../ItemsController/DefaultObjects/Registrar.inc | 10 +++++----- .../ItemsController/Objects/Items/Instance.inc | 2 +- amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc | 6 +++--- .../scripting/VipM/Core/Objects/Modules/Unit.inc | 6 +++--- amxmodx/scripting/VipM/Core/Objects/Param.inc | 4 ++++ amxmodx/scripting/VipM/Core/Objects/VipUnit.inc | 6 +++--- .../VipM/DefaultObjects/Limit/GameTime.inc | 2 +- .../scripting/VipM/DefaultObjects/Limit/Time.inc | 3 +-- .../scripting/VipM/DefaultObjects/Limit/WeekDay.inc | 3 +-- .../scripting/VipM/WeaponMenu/Objects/MenuItem.inc | 2 +- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 2 +- 17 files changed, 39 insertions(+), 33 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index aabec6c..f6fa9d6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,7 +17,7 @@ env: PLUGINS_INI_GENERATE: 1 PLUGINS_INI_POSTFIX: vipm DEPS_LIST: | - AmxxModularEcosystem/ParamsController@1.3.1 + AmxxModularEcosystem/ParamsController@1.3.2 AmxxModularEcosystem/CommandAliases@1.0.1 jobs: diff --git a/README.md b/README.md index b6de6b5..970ff9e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Требования -- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.2.0](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.2.0) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.3.2](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.3.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). - [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). - [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). diff --git a/amxmodx/scripting/ItemsController.sma b/amxmodx/scripting/ItemsController.sma index 7d17b2f..2852817 100644 --- a/amxmodx/scripting/ItemsController.sma +++ b/amxmodx/scripting/ItemsController.sma @@ -50,9 +50,10 @@ public plugin_natives() { } @NativeFilter(const name[], index, trap) { + new bool:handled = false; if (DefaultObjects_HandleNativeFilter(name, trap)) { - return PLUGIN_HANDLED; + handled = true; } - return PLUGIN_CONTINUE; + return handled ? PLUGIN_HANDLED : PLUGIN_CONTINUE; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc index 47f5c5f..845b56c 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/If.inc @@ -5,8 +5,10 @@ #include #include +static bool:IsVipModularInstalled = true; + DefaultObjects_ItemType_If_Register() { - if (!LibraryExists(VIPM_LIBRARY, LibType_Library)) { + if (!IsVipModularInstalled) { return; } @@ -15,9 +17,9 @@ DefaultObjects_ItemType_If_Register() { .onGive = "@OnIfGive" ); IC_ItemType_AddParams(type, - "Limits", "VipM-Limits", true, - "Items", "IC-Items", false, - "ElseItems", "IC-Items", false + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true, + "Items", IC_PARAM_TYPE_ITEMS_NAME, false, + "ElseItems", IC_PARAM_TYPE_ITEMS_NAME, false ); } @@ -29,8 +31,9 @@ DefaultObjects_ItemType_If_Register() { return PCGet_IcItemsGive(p, "Items", playerIndex) ? IC_RET_GIVE_SUCCESS : IC_RET_GIVE_FAIL; } -bool:DefaultObjects_ItemType_If_NativeFilter(const name[]) { +bool:DefaultObjects_ItemType_If_NativeFilter(const name[], const trap) { if (equal(name, "VipM_Limits_ExecuteList")) { + IsVipModularInstalled = !!trap; return true; } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc index df72b43..5ee1cd8 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/ItemsList.inc @@ -9,7 +9,7 @@ DefaultObjects_ItemType_ItemsList_Register() { .onGive = "@OnItemsListGive" ); IC_ItemType_AddParams(type, - "Items", "IC-Items", true + "Items", IC_PARAM_TYPE_ITEMS_NAME, true ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc index f5a3076..74e5f85 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Random.inc @@ -9,7 +9,7 @@ DefaultObjects_ItemType_Random_Register() { .onGive = "@OnRandomGive" ); IC_ItemType_AddParams(type, - "Items", "IC-Items", true + "Items", IC_PARAM_TYPE_ITEMS_NAME, true ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc index a6baa4b..dc4520b 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/Registrar.inc @@ -1,17 +1,17 @@ #include DefaultObjects_HandleNativeFilter(const name[], const trap) { - new ret = false; + new handled = false; if (DefaultObjects_ItemType_CustomWeapon_NativeFilter(name, trap)) { - ret = true; + handled = true; } - if (DefaultObjects_ItemType_If_NativeFilter(name)) { - ret = true; + if (DefaultObjects_ItemType_If_NativeFilter(name, trap)) { + handled = true; } - return ret; + return handled; } #include "ItemsController/DefaultObjects/ItemType/Armor" diff --git a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc index b41641f..483c47a 100644 --- a/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc +++ b/amxmodx/scripting/ItemsController/Objects/Items/Instance.inc @@ -161,7 +161,7 @@ Array:ItemInstance_ReadArrayFromJsonValue(const JSON:instancesJson, &Array:array PCJson_ErrorForFile(linkedJson, "Json value must be an array or an object."); } - PCJson_FreeLinked(linkedJson); + PCJson_FreeLinked(linkedJson, instancesJson); return array; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc index 063c175..2509916 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Limits/Unit.inc @@ -74,7 +74,7 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { new T_LimitType:type = PCSingle_ObjVipmLimitType(linked, "Limit", .orFail = true); if (type == Invalid_LimitType) { - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return Invalid_LimitUnit; } @@ -82,7 +82,7 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { if (!LimitType_IsStatic(type)) { p = LimitType_ReadParams(type, linked); if (p == Invalid_Trie) { - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return Invalid_LimitUnit; } } @@ -92,7 +92,7 @@ T_LimitUnit:LimitUnit_Read(const JSON:valueJson) { TrieSetCell(cache, linkPath, cached); } - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return cached; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc index 622bf95..00ab969 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Modules/Unit.inc @@ -67,13 +67,13 @@ T_ModuleUnit:ModuleUnit_Read(const JSON:valueJson) { new T_ModuleType:type = PCSingle_ObjVipmModuleType(linked, "Module", .orFail = true); if (type == Invalid_ModuleType) { - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return Invalid_ModuleUnit; } new Trie:p = ModuleType_ReadParams(type, linked); if (p == Invalid_Trie) { - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return Invalid_ModuleUnit; } @@ -82,7 +82,7 @@ T_ModuleUnit:ModuleUnit_Read(const JSON:valueJson) { TrieSetCell(cache, linkPath, cached); } - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return cached; } diff --git a/amxmodx/scripting/VipM/Core/Objects/Param.inc b/amxmodx/scripting/VipM/Core/Objects/Param.inc index c31d89b..dd1e45f 100644 --- a/amxmodx/scripting/VipM/Core/Objects/Param.inc +++ b/amxmodx/scripting/VipM/Core/Objects/Param.inc @@ -57,6 +57,10 @@ Array:CfgParam_GetFromNative(const iStartParam, const iNativeParamsCount, &Array case ptLimits: { paramType = VIPM_PARAM_TYPE_LIMITS_NAME; } + case ptCustom: { + // Чтоб не ругалось + continue; + } default: { log_amx("[WARNING] Invalid param type (%d).", get_param_byref(i + 1)); continue; diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index d54025a..a20a8eb 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -83,14 +83,14 @@ T_VipUnit:VipUnit_Read(const JSON:valueJson) { new Array:aAccess = PCSingle_ObjVipmLimits(linked, "Access"); if (aAccess == Invalid_Array) { PCJson_ErrorForFile(linked, "Field 'Access' is required in vip object."); - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return Invalid_VipUnit; } new Array:aModules = JsonObject_GetModuleUnits(linked, "Modules"); if (aModules == Invalid_Array) { PCJson_ErrorForFile(linked, "Field 'Modules' is required in vip object."); - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return Invalid_VipUnit; } @@ -99,7 +99,7 @@ T_VipUnit:VipUnit_Read(const JSON:valueJson) { TrieSetCell(cache, linkPath, cached); } - PCJson_FreeLinked(linked); + PCJson_FreeLinked(linked, valueJson); return cached; } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc index 4a881ef..cdec24f 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -4,7 +4,7 @@ DefaultObjects_Limit_GameTime_Register() { VipM_Limits_RegisterType("GameTime", false, false); - VipM_Limits_AddTypeParams("GameTime", + VipM_Limits_AddParamsEx("GameTime", "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false ); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc index 1394729..8e2d9d5 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc @@ -4,11 +4,10 @@ DefaultObjects_Limit_Time_Register() { VipM_Limits_RegisterType("Time", false, false); - VipM_Limits_AddTypeParams("Time", + VipM_Limits_AddParamsEx("Time", "Before", DEFAULT_PARAMS_TIME_NAME, false, "After", DEFAULT_PARAMS_TIME_NAME, false ); - VipM_Limits_RegisterTypeEvent("Time", Limit_OnRead, "@DefaultObjects_Limit_Time_OnRead"); VipM_Limits_RegisterTypeEvent("Time", Limit_OnCheck, "@DefaultObjects_Limit_Time_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc index cf292f2..9e64a10 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc @@ -5,10 +5,9 @@ DefaultObjects_Limit_WeekDay_Register() { VipM_Limits_RegisterType("WeekDay", false, false); - VipM_Limits_AddTypeParams("WeekDay", + VipM_Limits_AddParamsEx("WeekDay", "Day", DEFAULT_PARAMS_WEEK_DAY_NAME, true ); - VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnRead, "@DefaultObjects_Limit_WeekDay_OnRead"); VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnCheck, "@DefaultObjects_Limit_WeekDay_OnCheck"); } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc index 000203e..c60b90d 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/MenuItem.inc @@ -83,7 +83,7 @@ Array:MenuItem_ReadList(const JSON:itemsJson, &Array:items = Invalid_Array) { } } - PCJson_FreeLinked(linkedJson); + PCJson_FreeLinked(linkedJson, itemsJson); return items; } diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index 1a768c0..eb58935 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -87,7 +87,7 @@ Array:WeaponMenu_ReadList(const JSON:jWeaponMenus, &Array:aWeaponMenus = Invalid } } - PCJson_FreeLinked(linkedJson); + PCJson_FreeLinked(linkedJson, jWeaponMenus); return aWeaponMenus; } From b1dc14ab1e756a89b4a4ae0eed40b58441cd6518 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 02:21:59 +0300 Subject: [PATCH 083/108] Bump version --- amxmodx/scripting/include/ItemsController.inc | 2 +- amxmodx/scripting/include/VipModular.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 6af7677..9a6fdbc 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -7,7 +7,7 @@ #include #include -#define IC_VERSION "1.0.0-rc1" +#define IC_VERSION "1.0.0-rc2" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 25fc598..e2e8b5a 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-rc1" +#define _VIPM_VERSION "5.0.0-rc2" stock const VIPM_VERSION[] = _VIPM_VERSION; #define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" From 29adaea1c6e636bd580fb060f324e4f76a019b2e Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 02:38:35 +0300 Subject: [PATCH 084/108] Add `Inc` param to `Counter` limit --- amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc index bfb1d4c..6ce15eb 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -11,7 +11,8 @@ DefaultObjects_Limit_Counter_Register() { VipM_Limits_AddParamsEx("Counter", "Type", VIPM_L_COUNTER_PARAM_TYPE, true, "Key", DEFAULT_PARAMS_SHORT_STR_NAME, true, - "Max", DEFAULT_PARAMS_INT_NAME, false + "Max", DEFAULT_PARAMS_INT_NAME, false, + "Inc", DEFAULT_PARAMS_INT_NAME, false ); RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnPlayerSpawn", false); @@ -87,7 +88,9 @@ static DefaultObjects_Limit_Counter_GetPlayerKey(const playerIndex) { return false; } - TrieSetCell(counter, DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex), ++value); + value += PCGet_Int(p, "Inc", 1); + + TrieSetCell(counter, DefaultObjects_Limit_Counter_GetPlayerKey(playerIndex), value); return true; } From 944219b905b5b94713710ad7f4783694b63cbd7a Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 20:17:21 +0300 Subject: [PATCH 085/108] Fix weapon menus --- amxmodx/scripting/VipM-M-WeaponMenu.sma | 39 ++++++++++++------- .../VipM/WeaponMenu/Objects/WeaponMenu.inc | 2 +- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index a8655dc..c2e1246 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -216,11 +216,8 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { return; } - new menuIndex = read_argv_int(2); - if ( - ArraySizeSafe(aMenus) <= menuIndex - || menuIndex < 0 - ) { + new menuIndex = read_argv_int(1); + if (menuIndex >= ArraySizeSafe(aMenus) || menuIndex < 0) { return; } @@ -242,7 +239,7 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { return; } - new itemIndex = read_argv_int(3); + new itemIndex = read_argv_int(2); if ( ArraySizeSafe(Menu[WeaponMenu_Items]) <= itemIndex || itemIndex < 0 @@ -253,11 +250,11 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { static itemObject[S_MenuItem]; ArrayGetArray(Menu[WeaponMenu_Items], itemIndex, itemObject); - new iItemsLeft = GetUserLeftItems(playerIndex, Menu); + new leftItems = GetUserLeftItems(playerIndex, Menu); if ( itemObject[MenuItem_UseCounter] - && iItemsLeft == 0 + && leftItems == 0 ) { ChatPrintLIf(!bSilent, playerIndex, "MSG_NO_LEFT_ITEMS"); return; @@ -283,7 +280,7 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { PCGet_Bool(p, "StayOpen", false) && ( !PCGet_Bool(p, "StayOpen_CheckCounter", true) - || iItemsLeft != 0 + || leftItems != 0 ) ) { client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU, menuIndex); @@ -309,6 +306,13 @@ IncUserMenuCounters(const playerIndex, const menuObject[S_WeaponMenu]) { GetUserLeftItems(const playerIndex, const menuObject[S_WeaponMenu]) { new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); + new maxPlayer = PCGet_Int(p, "Count", -1); + new maxMenu = menuObject[WeaponMenu_Count]; + + if (maxPlayer < 0 && maxMenu < 0) { + return -1; + } + new usedPlayer = VipM_L_Counter_Get( PCGet_VipmCounterType(p, "CounterType", VipM_L_Counter_PerLife), PCGet_iStr(p, "CounterKey", VIPM_M_WEAPONMENU_PLAYER_COUNTER_KEY), @@ -320,11 +324,18 @@ GetUserLeftItems(const playerIndex, const menuObject[S_WeaponMenu]) { menuObject[WeaponMenu_CounterKey], playerIndex ); - - return min( - usedMenu, - usedPlayer - ); + + + if (maxPlayer < 0) { + return maxMenu - usedMenu; + } else if (maxMenu < 0) { + return maxPlayer - usedPlayer; + } else { + return min( + maxPlayer - usedPlayer, + maxMenu - usedMenu + ); + } } #include "VipM/WeaponMenu/Natives" diff --git a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc index eb58935..ab35c8e 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Objects/WeaponMenu.inc @@ -55,7 +55,7 @@ bool:WeaponMenu_Read(const JSON:menuJson, menuObject[S_WeaponMenu]) { menuObject[WeaponMenu_Limits] = PCSingle_ObjVipmLimits(menuJson, "Limits"); menuObject[WeaponMenu_Count] = PCSingle_ObjInt(menuJson, "Count", -1); - menuObject[WeaponMenu_CounterType] = PCSingle_ObjVipmCounterType(menuJson, "CounterType"); + menuObject[WeaponMenu_CounterType] = PCSingle_ObjVipmCounterType(menuJson, "CounterType", VipM_L_Counter_PerLife); if (!PCSingle_ObjShortString(menuJson, "CounterKey", menuObject[WeaponMenu_CounterKey], charsmax(menuObject[WeaponMenu_CounterKey]))) { formatex(menuObject[WeaponMenu_CounterKey], charsmax(menuObject[WeaponMenu_CounterKey]), "%s-%d", VIPM_M_WEAPONMENU_MENU_COUNTER_KEY_PREFIX, ++WeaponMenuCounterKeysCount); } From f4c4dc1660f6344618860f639e973935039983de Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 20:17:31 +0300 Subject: [PATCH 086/108] Fix `Counter` limit --- amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc index 6ce15eb..caed960 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -14,6 +14,7 @@ DefaultObjects_Limit_Counter_Register() { "Max", DEFAULT_PARAMS_INT_NAME, false, "Inc", DEFAULT_PARAMS_INT_NAME, false ); + VipM_Limits_RegisterTypeEvent("Counter", Limit_OnCheck, "@DefaultObjects_Limit_Counter_OnCheck"); RegisterHookChain(RG_CBasePlayer_Spawn, "@DefaultObjects_Limit_Counter_OnPlayerSpawn", false); RegisterHookChain(RG_CSGameRules_RestartRound, "@DefaultObjects_Limit_Counter_OnRestartRound", false); From c314f9fbee800849e0905fba4faa3dfd48120851 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 20:18:43 +0300 Subject: [PATCH 087/108] Bump version --- amxmodx/scripting/include/ItemsController.inc | 2 +- amxmodx/scripting/include/VipModular.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 9a6fdbc..63f7b95 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -7,7 +7,7 @@ #include #include -#define IC_VERSION "1.0.0-rc2" +#define IC_VERSION "1.0.0-rc3" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index e2e8b5a..c36b634 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-rc2" +#define _VIPM_VERSION "5.0.0-rc3" stock const VIPM_VERSION[] = _VIPM_VERSION; #define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" From f5016b227c7746aa6a10f012f89b3653254873fd Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 21 Feb 2026 20:57:02 +0300 Subject: [PATCH 088/108] Update pc dep --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f6fa9d6..b98e2d4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,7 +17,7 @@ env: PLUGINS_INI_GENERATE: 1 PLUGINS_INI_POSTFIX: vipm DEPS_LIST: | - AmxxModularEcosystem/ParamsController@1.3.2 + AmxxModularEcosystem/ParamsController@1.3.3 AmxxModularEcosystem/CommandAliases@1.0.1 jobs: From b2be45ab7ae2962a01fe6db538e9a8499d289e11 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Mon, 23 Feb 2026 11:39:46 +0300 Subject: [PATCH 089/108] Fix inactive menu item display --- amxmodx/scripting/VipM/WeaponMenu/Menus.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc index 4fba87d..b7a4c29 100644 --- a/amxmodx/scripting/VipM/WeaponMenu/Menus.inc +++ b/amxmodx/scripting/VipM/WeaponMenu/Menus.inc @@ -77,7 +77,7 @@ Menu_WeaponsMenu(const playerIndex, const menuIndex, const menuObject[S_WeaponMe } new bool:isItemActive = ( - itemObject[MenuItem_ShowLimits] == Invalid_Array + itemObject[MenuItem_ActiveLimits] == Invalid_Array || VipM_Limits_ExecuteList(itemObject[MenuItem_ActiveLimits], playerIndex, Limit_Exec_AND) ); From fb83de477552b78bc7fe1e5219559194dff7fbc5 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Tue, 24 Feb 2026 14:04:31 +0300 Subject: [PATCH 090/108] Fix `VipM_Modules_GetParams` for some cases --- amxmodx/scripting/VipM/Core/API/Modules.inc | 100 +++++++++--------- .../scripting/VipM/Core/Objects/VipUnit.inc | 10 +- amxmodx/scripting/VipM/Core/VipsManager.inc | 57 +++++----- 3 files changed, 86 insertions(+), 81 deletions(-) diff --git a/amxmodx/scripting/VipM/Core/API/Modules.inc b/amxmodx/scripting/VipM/Core/API/Modules.inc index 33e2df7..ae829f8 100644 --- a/amxmodx/scripting/VipM/Core/API/Modules.inc +++ b/amxmodx/scripting/VipM/Core/API/Modules.inc @@ -15,30 +15,30 @@ API_Modules_Init(){ } -T_ModuleType:@_Modules_Register(const PluginId) { - enum {Arg_sModuleTypeName = 1} +T_ModuleType:@_Modules_Register(const pluginIndex) { + enum {Arg_TypeName = 1} - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_TypeName, typeName, charsmax(typeName)); - new T_ModuleType:iModuleType = ModuleType_Construct(sModuleTypeName); - if (iModuleType == Invalid_ModuleType) { - log_error(0, "Can't create module type '%s'.", sModuleTypeName); + new T_ModuleType:type = ModuleType_Construct(typeName); + if (type == Invalid_ModuleType) { + log_error(0, "Can't create module type '%s'.", typeName); return Invalid_ModuleType; } - return iModuleType; + return type; } -@_Modules_AddParams(const PluginId, const iParamsNum) { - enum {Arg_sModuleTypeName = 1, Arg_Params} +@_Modules_AddParams(const pluginIndex, const iParamsNum) { + enum {Arg_TypeName = 1, Arg_Params} - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_TypeName, typeName, charsmax(typeName)); - new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); - if (iModuleType == Invalid_ModuleType) { - log_error(0, "Module type '%s' not found.", sModuleTypeName); + new T_ModuleType:type = ModuleType_Find(typeName); + if (type == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", typeName); return; } @@ -47,77 +47,77 @@ T_ModuleType:@_Modules_Register(const PluginId) { return; } - ModuleType_AddParams(iModuleType, params); + ModuleType_AddParams(type, params); ArrayDestroy(params); } @VipM_Modules_AddParamsEx(const pluginIndex, const paramsCount) { - enum {Arg_ModuleName = 1, Arg_Params} + enum {Arg_TypeName = 1, Arg_Params} - new modelName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - get_string(Arg_ModuleName, modelName, charsmax(modelName)); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_TypeName, typeName, charsmax(typeName)); - new T_ModuleType:module = ModuleType_Find(modelName); - if (module == Invalid_ModuleType) { - log_error(0, "Module type '%s' not found.", modelName); + new T_ModuleType:type = ModuleType_Find(typeName); + if (type == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", typeName); return; } new Array:params = ParamsController_Param_ListFromNativeParams(Arg_Params, paramsCount); - ModuleType_AddParams(module, params); + ModuleType_AddParams(type, params); ArrayDestroy(params); } -bool:@_Modules_RegisterEvent(const PluginId) { - enum {Arg_sModuleTypeName = 1, Arg_iEvent, Arg_sFuncName} +bool:@_Modules_RegisterEvent(const pluginIndex) { + enum {Arg_TypeName = 1, Arg_iEvent, Arg_sFuncName} - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_TypeName, typeName, charsmax(typeName)); - new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); - if (iModuleType == Invalid_ModuleType) { - log_error(0, "Module type '%s' not found.", sModuleTypeName); + new T_ModuleType:type = ModuleType_Find(typeName); + if (type == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", typeName); return false; } - new E_ModuleEvent:iEvent = E_ModuleEvent:get_param(Arg_iEvent); + new E_ModuleEvent:event = E_ModuleEvent:get_param(Arg_iEvent); - new sFuncName[64]; - get_string(Arg_sFuncName, sFuncName, charsmax(sFuncName)); + new funcName[64]; + get_string(Arg_sFuncName, funcName, charsmax(funcName)); - ModuleType_SetEventListener(iModuleType, iEvent, PluginId, sFuncName); + ModuleType_SetEventListener(type, event, pluginIndex, funcName); return true; } bool:@_Modules_IsActive() { - enum {Arg_sModuleTypeName = 1} + enum {Arg_TypeName = 1} - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_TypeName, typeName, charsmax(typeName)); - new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); - if (iModuleType == Invalid_ModuleType) { - log_error(0, "Module type '%s' not found.", sModuleTypeName); + new T_ModuleType:type = ModuleType_Find(typeName); + if (type == Invalid_ModuleType) { + log_error(0, "Module type '%s' not found.", typeName); return false; } - return ModuleType_IsActive(iModuleType); + return ModuleType_IsActive(type); } Trie:@_Modules_GetParams() { - enum {Arg_sModuleTypeName = 1, Arg_UserId} + enum {Arg_TypeName = 1, Arg_PlayerIndex} - new sModuleTypeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; - get_string(Arg_sModuleTypeName, sModuleTypeName, charsmax(sModuleTypeName)); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; + get_string(Arg_TypeName, typeName, charsmax(typeName)); - // TODO: Потом переделать сразу не хендлеры - new T_ModuleType:iModuleType = ModuleType_Find(sModuleTypeName); - if (iModuleType == Invalid_ModuleType) { - log_error(0, "Module type '%s' not found.", sModuleTypeName); + // TODO: Потом переделать сразу на хендлеры + new T_ModuleType:type = ModuleType_Find(typeName); + if (type == Invalid_ModuleType) { + log_error(AMX_ERR_PARAMS, "Module type '%s' not found.", typeName); return Invalid_Trie; } - new UserId = get_param(Arg_UserId); + new playerIndex = get_param(Arg_PlayerIndex); - return VipsManager_GetUserParams(UserId, iModuleType); + return VipsManager_GetUserParams(playerIndex, type); } diff --git a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc index a20a8eb..4708107 100644 --- a/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc +++ b/amxmodx/scripting/VipM/Core/Objects/VipUnit.inc @@ -80,21 +80,21 @@ T_VipUnit:VipUnit_Read(const JSON:valueJson) { return cached; } - new Array:aAccess = PCSingle_ObjVipmLimits(linked, "Access"); - if (aAccess == Invalid_Array) { + new Array:accessLimits = PCSingle_ObjVipmLimits(linked, "Access"); + if (accessLimits == Invalid_Array) { PCJson_ErrorForFile(linked, "Field 'Access' is required in vip object."); PCJson_FreeLinked(linked, valueJson); return Invalid_VipUnit; } - new Array:aModules = JsonObject_GetModuleUnits(linked, "Modules"); - if (aModules == Invalid_Array) { + new Array:modules = JsonObject_GetModuleUnits(linked, "Modules"); + if (modules == Invalid_Array) { PCJson_ErrorForFile(linked, "Field 'Modules' is required in vip object."); PCJson_FreeLinked(linked, valueJson); return Invalid_VipUnit; } - cached = VipUnit__Construct(aAccess, aModules); + cached = VipUnit__Construct(accessLimits, modules); if (linkPath[0] != EOS && cached != Invalid_VipUnit) { TrieSetCell(cache, linkPath, cached); } diff --git a/amxmodx/scripting/VipM/Core/VipsManager.inc b/amxmodx/scripting/VipM/Core/VipsManager.inc index 92730a0..a26900a 100644 --- a/amxmodx/scripting/VipM/Core/VipsManager.inc +++ b/amxmodx/scripting/VipM/Core/VipsManager.inc @@ -30,26 +30,26 @@ VipsManager_SetRootDir(const sRootDir[]) { copy(g_sRootDir, charsmax(g_sRootDir), sRootDir); } -bool:VipsManager_LoadFromFile(const sFilePath[]) { - if (!file_exists(sFilePath)) { +bool:VipsManager_LoadFromFile(const filePath[]) { + if (!file_exists(filePath)) { return false; } - new JSON:jVipUnits = PCJson_ParseFile(sFilePath, g_sRootDir); - g_aVips = VipUnit_ReadList(jVipUnits, g_aVips); - PCJson_Free(jVipUnits); + new JSON:unitsJson = PCJson_ParseFile(filePath, g_sRootDir); + g_aVips = VipUnit_ReadList(unitsJson, g_aVips); + PCJson_Free(unitsJson); return true; } -bool:VipsManager_LoadFromFolder(sFolderPath[]) { - if (!dir_exists(sFolderPath)) { +bool:VipsManager_LoadFromFolder(dirPath[]) { + if (!dir_exists(dirPath)) { return false; } - new sFile[PLATFORM_MAX_PATH], iDirHandler, FileType:iType; - iDirHandler = open_dir(sFolderPath, sFile, charsmax(sFile), iType); - if (!iDirHandler) { + new filePath[PLATFORM_MAX_PATH], dirHandler, FileType:fileType; + dirHandler = open_dir(dirPath, filePath, charsmax(filePath), fileType); + if (!dirHandler) { return false; } @@ -57,15 +57,15 @@ bool:VipsManager_LoadFromFolder(sFolderPath[]) { iRegEx_FileName = regex_compile("(.+).json$", ret, "", 0, "i"); do { - if (iType != FileType_File || regex_match_c(sFile, iRegEx_FileName) <= 0) { + if (fileType != FileType_File || regex_match_c(filePath, iRegEx_FileName) <= 0) { continue; } - VipsManager_LoadFromFile(fmt("%s/%s", sFolderPath, sFile)); - } while (next_file(iDirHandler, sFile, charsmax(sFile), iType)); + VipsManager_LoadFromFile(fmt("%s/%s", dirPath, filePath)); + } while (next_file(dirHandler, filePath, charsmax(filePath), fileType)); regex_free(iRegEx_FileName); - close_dir(iDirHandler); + close_dir(dirHandler); return true; } @@ -112,26 +112,31 @@ VipsManager_UserReload(const playerIndex) { Forwards_CallP("VipM_OnUserUpdated", playerIndex); } -VipsManager_UserReset(const UserId) { - if (g_tUserModules[UserId] == Invalid_Trie) { +VipsManager_UserReset(const playerIndex) { + if (g_tUserModules[playerIndex] == Invalid_Trie) { return; } - new TrieIter:Iter = TrieIterCreate(g_tUserModules[UserId]); - while (!TrieIterEnded(Iter)) { + new TrieIter:iter = TrieIterCreate(g_tUserModules[playerIndex]); + while (!TrieIterEnded(iter)) { new Trie:tParams = Invalid_Trie; - if (TrieIterGetCell(Iter, tParams)) { + if (TrieIterGetCell(iter, tParams)) { ModuleUnit_FreeParamsIfTemp(tParams); } - TrieIterNext(Iter); + TrieIterNext(iter); } - TrieIterDestroy(Iter); + TrieIterDestroy(iter); - TrieDestroy(g_tUserModules[UserId]); + TrieDestroy(g_tUserModules[playerIndex]); } -Trie:VipsManager_GetUserParams(const UserId, const T_ModuleType:iModuleType) { - new Trie:tParams = Invalid_Trie; - TrieGetCell(g_tUserModules[UserId], ModuleType_iGetName(iModuleType), tParams); - return tParams; +Trie:VipsManager_GetUserParams(const playerIndex, const T_ModuleType:type) { + if (g_tUserModules[playerIndex] == Invalid_Trie) { + return Invalid_Trie; + } + + new Trie:p = Invalid_Trie; + TrieGetCell(g_tUserModules[playerIndex], ModuleType_iGetName(type), p); + + return p; } From 78c1f395eba7b155f8ff5009ca3c6821997d33c9 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 27 Feb 2026 01:15:58 +0300 Subject: [PATCH 091/108] Add logs to modules limiter --- amxmodx/scripting/VipM-ModulesLimiter.sma | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 3044269..4d26e81 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -26,13 +26,17 @@ public VipM_Modules_OnActivate(const moduleName[]) { ModulesLimits == Invalid_Trie || !TrieKeyExists(ModulesLimits, moduleName) ) { + log_amx("Module `%s` is not limited.", moduleName); return VIPM_CONTINUE; } new Array:limits; TrieGetCell(ModulesLimits, moduleName, limits); if (!VipM_Limits_ExecuteList(limits)) { + log_amx("Module `%s` is disabled by limits.", moduleName); return VIPM_STOP; + } else { + log_amx("Module `%s` is enabled by limits.", moduleName); } return VIPM_CONTINUE; From 5b4278466497f30dbe0e9682fbc9ad0f5df58231 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 27 Feb 2026 01:19:09 +0300 Subject: [PATCH 092/108] Add `StayOpen_WhenRestricted` param to WeaponMenu module --- amxmodx/scripting/VipM-M-WeaponMenu.sma | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index c2e1246..a57429b 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -57,7 +57,8 @@ public VipM_Modules_OnInited() { ); VipM_Modules_AddParamsEx(MODULE_NAME, "StayOpen", DEFAULT_PARAMS_BOOL_NAME, false, - "StayOpen_CheckCounter", DEFAULT_PARAMS_BOOL_NAME, false + "StayOpen_CheckCounter", DEFAULT_PARAMS_BOOL_NAME, false, + "StayOpen_WhenRestricted", DEFAULT_PARAMS_BOOL_NAME, false ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnRead, "@OnReadConfig"); @@ -226,6 +227,11 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { if (Menu[WeaponMenu_Limits] != Invalid_Array && !VipM_Limits_ExecuteList(Menu[WeaponMenu_Limits], playerIndex, Limit_Exec_AND)) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MENU_NOT_PASSED_LIMIT"); + + if (PCGet_Bool(p, "StayOpen_WhenRestricted", false)) { + client_cmd(playerIndex, VIPM_M_WEAPONMENU_CMD_MENU_SILENT); + } + return; } @@ -266,6 +272,11 @@ _Cmd_Menu(const playerIndex, const bool:bSilent = false) { || !VipM_Limits_ExecuteList(itemObject[MenuItem_Limits], playerIndex, Limit_Exec_AND) ) { ChatPrintLIf(!bSilent, playerIndex, "MSG_MENUITEM_NOT_PASSED_LIMIT"); + + if (PCGet_Bool(p, "StayOpen_WhenRestricted", false)) { + client_cmd(playerIndex, "%s %d", VIPM_M_WEAPONMENU_CMD_MENU_SILENT, menuIndex); + } + return; } From ed8b51788502b74f2b9228d290f82a12e4e676e4 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 27 Feb 2026 01:24:33 +0300 Subject: [PATCH 093/108] Fix modules limiter --- amxmodx/scripting/VipM-ModulesLimiter.sma | 12 +----------- amxmodx/scripting/include/VipM/Modules.inc | 10 ++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/amxmodx/scripting/VipM-ModulesLimiter.sma b/amxmodx/scripting/VipM-ModulesLimiter.sma index 4d26e81..94d4537 100644 --- a/amxmodx/scripting/VipM-ModulesLimiter.sma +++ b/amxmodx/scripting/VipM-ModulesLimiter.sma @@ -15,7 +15,7 @@ new const CONFIG_FILE_PATH[] = "Modules.json"; new Trie:ModulesLimits = Invalid_Trie; -public VipM_OnLoaded() { +public VipM_Modules_OnInited() { register_plugin(PluginName, PluginVersion, PluginAuthor); ModulesLimits = LoadModulesLimitsFromFile(PCPath_iMakePath(fmt("%s/%s", VIPM_CONFIGS_FOLDER_NAME, CONFIG_FILE_PATH))); @@ -67,17 +67,7 @@ Trie:LoadModulesLimitsFromFile(const filePath[], &Trie:modules = Invalid_Trie) { } new Array:limits = PCSingle_ObjVipmLimits(itemJson, "Limits"); - if (!ArraySizeSafe(limits)) { - PCJson_LogForFile(itemJson, "WARNING", "Field `Limits` must have 1 or more items."); - json_free(itemJson); - continue; - } - new Array:moduleNames = json_object_get_strings_list(itemJson, "Modules", VIPM_MODULES_TYPE_NAME_MAX_LEN); - if (!ArraySizeSafe(moduleNames)) { - PCJson_LogForFile(itemJson, "WARNING", "Field `Modules` must have 1 or more items."); - continue; - } ArrayForeachString (moduleNames: j => moduleName[VIPM_MODULES_TYPE_NAME_MAX_LEN]) { if (TrieKeyExists(modules, moduleName)) { diff --git a/amxmodx/scripting/include/VipM/Modules.inc b/amxmodx/scripting/include/VipM/Modules.inc index e780cc2..4b41730 100644 --- a/amxmodx/scripting/include/VipM/Modules.inc +++ b/amxmodx/scripting/include/VipM/Modules.inc @@ -55,6 +55,16 @@ enum E_ModuleEvent { Module_OnMergeParams, } +/** + * Вызывается в момент, когда нужно регистрировать модули. + * Модули должны регистрироваться строго в рамках этого форварда. + * + * @note Вызывается в рамках plugin_precache. + * + * @noreturn + */ +forward VipM_Modules_OnInited(); + /** * Вызывается перед активацией модуля. * From ad57e27e4a3ba2f873f1aa45af57ed8a4d255104 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 27 Feb 2026 01:27:33 +0300 Subject: [PATCH 094/108] Try to use separated workflow stage for deps --- .github/workflows/CI.yml | 50 ++++------------------------------------ 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b98e2d4..4f3fe0f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -70,52 +70,10 @@ jobs: echo "${OUTPUT_VAR_NAME}=$(pwd)/addons/amxmodx/scripting/include" >> $GITHUB_ENV - - name: Setup deps includes - env: - DEPS_LIST: ${{ env.DEPS_LIST }} - OUTPUT_VAR_NAME: DEPS_COMPILER_ARGS - run: | - handleDep() { - REPO="${1%%@*}" - TAG="${1#*@}" - TAG="${TAG%%:*}" - OVERRIDE_INCLUDE_PATH=$(echo "$1" | grep -Po '(?<=:).+' || true) - - if [ -z "$REPO" ]; then - echo "No repo provided" - exit 1 - fi - - INIT_PWD=$(pwd) - mkdir -p "dep/${REPO}" - cd "dep/${REPO}" - - if [ -z "$TAG" ]; then - TAG=$(curl --silent "https://api.github.com/repos/${REPO}/releases/latest" | jq -r .tag_name) - fi - - wget -q "https://github.com/${REPO}/archive/refs/tags/${TAG}.zip" - 7z x "${TAG}.zip" > /dev/null - - REPO_NAME=$(echo "${REPO}" | grep -Po '(?<=\/).+') - INCLUDE_PATH="$(pwd)/${REPO_NAME}-${TAG}/${OVERRIDE_INCLUDE_PATH:-amxmodx/scripting/include}" - - # ВАЖНО: без кавычек внутри аргумента - echo "-i${INCLUDE_PATH}" - - cd "$INIT_PWD" - } - - DEPS_COMPILER_ARGS="" - - while IFS= read -r dep; do - [ -z "$dep" ] && continue - path_arg=$(handleDep "$dep") - DEPS_COMPILER_ARGS="${DEPS_COMPILER_ARGS} ${path_arg}" - done <<< "$DEPS_LIST" - - echo "Final ${OUTPUT_VAR_NAME}: ${DEPS_COMPILER_ARGS}" - echo "${OUTPUT_VAR_NAME}=${DEPS_COMPILER_ARGS}" >> $GITHUB_ENV + - uses: AmxxModularEcosystem/install-amxmodx-deps@master + with: + deps_list: ${{ env.DEPS_LIST }} + output_var_name: DEPS_COMPILER_ARGS - name: Setup AMXXPawn Compiler uses: wopox1337/setup-amxxpawn@v1.1.0 From 163c7a1b8c52cbad49453c4c2fd2715fedb18dde Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 27 Feb 2026 01:29:45 +0300 Subject: [PATCH 095/108] Bump version --- .github/workflows/CI.yml | 8 +------- amxmodx/scripting/include/ItemsController.inc | 2 +- amxmodx/scripting/include/VipModular.inc | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4f3fe0f..4d7671a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -95,13 +95,7 @@ jobs: mkdir -p $(dirname $output_path) - echo "Compiling $sourcefile ... " - echo "amxxpc $sourcefile -o\"$output_path\" -i\"include\" -i\"$REAPI_INCLUDE\" $DEPS_COMPILER_ARGS GITHUB_ACTIONS_USED=1" - - echo "DEPS_COMPILER_ARGS=[$DEPS_COMPILER_ARGS]" - echo "Listing dep tree:" - find ../.. -maxdepth 4 -type d -path "*ParamsController*" -o -path "*CommandAliases*" - + echo "Compiling $sourcefile... " amxxpc $sourcefile -o"$output_path" \ -i"include" \ -i"$REAPI_INCLUDE" \ diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 63f7b95..c14f5c9 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -7,7 +7,7 @@ #include #include -#define IC_VERSION "1.0.0-rc3" +#define IC_VERSION "1.0.0-rc4" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index c36b634..d72283d 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-rc3" +#define _VIPM_VERSION "5.0.0-rc4" stock const VIPM_VERSION[] = _VIPM_VERSION; #define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" From bb54b8630de9f8998857f0149f57644070a247c2 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 4 Mar 2026 23:08:23 +0300 Subject: [PATCH 096/108] Fix pc init order --- amxmodx/scripting/VipModular.sma | 1 + 1 file changed, 1 insertion(+) diff --git a/amxmodx/scripting/VipModular.sma b/amxmodx/scripting/VipModular.sma index 6bb98f7..a369051 100644 --- a/amxmodx/scripting/VipModular.sma +++ b/amxmodx/scripting/VipModular.sma @@ -22,6 +22,7 @@ public plugin_precache() { register_plugin(PluginName, PluginVersion, PluginAuthor); register_library(VIPM_LIBRARY); PCCvar_Const("vipm_version", PluginVersion); + ParamsController_Init(); Forwards_Init(); From f0e260e2d3fb65d1cea607b1f8d7ddac619ecdc4 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Wed, 4 Mar 2026 23:13:24 +0300 Subject: [PATCH 097/108] Bump version --- amxmodx/scripting/include/ItemsController.inc | 2 +- amxmodx/scripting/include/VipModular.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index c14f5c9..828f496 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -7,7 +7,7 @@ #include #include -#define IC_VERSION "1.0.0-rc4" +#define IC_VERSION "1.0.0-rc4f1" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index d72283d..16d9027 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-rc4" +#define _VIPM_VERSION "5.0.0-rc4f1" stock const VIPM_VERSION[] = _VIPM_VERSION; #define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" From eb7fd14ff1fe8df85b26e091fa158e36b4216ef5 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 10 Apr 2026 01:07:39 +0300 Subject: [PATCH 098/108] Add docs for claude code --- CLAUDE.md | 179 +++++++++++++++++++++++++++++++++++ docs/claude/config-format.md | 151 +++++++++++++++++++++++++++++ docs/claude/items-system.md | 107 +++++++++++++++++++++ docs/claude/limits-system.md | 140 +++++++++++++++++++++++++++ docs/claude/module-system.md | 115 ++++++++++++++++++++++ 5 files changed, 692 insertions(+) create mode 100644 CLAUDE.md create mode 100644 docs/claude/config-format.md create mode 100644 docs/claude/items-system.md create mode 100644 docs/claude/limits-system.md create mode 100644 docs/claude/module-system.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6e9a20e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,179 @@ +# VipModular — Project Context + +Modular VIP/privilege system for **Counter-Strike 1.6** built on **AMX Mod X** (AMXX), written in **Pawn**. +Version: `5.0.0-rc4f1` | Author: ArKaNeMaN + +> For deeper detail on each subsystem, see `docs/claude/`. + +--- + +## What it does + +Lets server admins define privilege tiers (VIPs) in JSON configs. Each privilege specifies: +- **Conditions** (`Access`) — which players qualify (Limits system) +- **Features** (`Modules`) — what those players get (Modules system) + +Modules and limits are fully extensible: third-party plugins register new types at runtime. + +--- + +## Plugin files + +| File | Role | +|------|------| +| `VipModular.sma` | Core — init, config loading, player update lifecycle | +| `ItemsController.sma` | Standalone item-effects framework (give weapon/health/etc.) | +| `VipM-Misc.sma` | Reload helper — triggers `VipM_UserUpdate` on spawn/round events | +| `VipM-ModulesLimiter.sma` | Enables/disables modules per-map via `Modules.json` | +| `VipM-M-WeaponMenu.sma` | Module: weapon selection menu | +| `VipM-M-SpawnItems.sma` | Module: give items on spawn | +| `VipM-M-SpawnHealth.sma` | Module: set health/armor on spawn | +| `VipM-M-Vampire.sma` | Module: heal on kill | +| `VipM-M-VipInTab.sma` | Module: VIP label in scoreboard | + +--- + +## Source layout + +``` +amxmodx/scripting/ +├── include/VipModular.inc — public API header (include this in plugins) +├── include/VipM/Modules.inc — module system API +├── include/VipM/Limits.inc — limits system API +├── include/ItemsController.inc — items system API +├── VipM/ +│ ├── Core/ +│ │ ├── VipsManager.inc — loads Vips.json, manages g_tUserModules[] +│ │ ├── Objects/Modules/Type.inc — module type registry (ArrayMap) +│ │ ├── Objects/Modules/Unit.inc — module instance (params per VIP entry) +│ │ ├── Objects/Limits/Type.inc — limit type registry +│ │ ├── Objects/Limits/Unit.inc — limit instance +│ │ ├── Objects/VipUnit.inc — deserializes one privilege from JSON +│ │ └── API/{Main,Modules,Limits}.inc — native implementations +│ ├── DefaultObjects/ +│ │ ├── Limit/*.inc — 24 built-in limit types +│ │ └── Registrar.inc — registers all defaults +│ ├── Forwards.inc — thin macro wrapper over CreateMultiForward +│ ├── ArrayMap.inc — string-keyed array map (used for type registries) +│ └── WeaponMenu/ — WeaponMenu module implementation +└── ItemsController/ + ├── Objects/Items/{Type,Instance}.inc + ├── API/{ItemType,Item,Compat}.inc + └── DefaultObjects/ItemType/ — 18 built-in item types +``` + +--- + +## Core data flow + +``` +plugin_precache + Forwards_RegAndCall("VipM_Modules_OnInited") ← modules register here + Forwards_RegAndCall("VipM_Limits_OnInited") ← limits register here + IC_ItemType_OnInited() ← item types register here + VipsManager_LoadFromFile("Vips.json") + VipsManager_LoadFromFolder("Vips/") + ModuleType_ActivateUsed() ← fires Module_OnActivated + Forwards_RegAndCall("VipM_OnLoaded") + +client_putinserver → RequestFrame → VipsManager_UserReload(playerIndex) + for each VipUnit: check Access limits → grant matching Modules + result stored in g_tUserModules[playerIndex]: Trie> + fires VipM_OnUserUpdated(playerIndex) + +client_disconnected → VipsManager_UserReset(playerIndex) ← frees all Tries +``` + +--- + +## Key patterns + +- **Type registries** use `ArrayMap` (string key → index cast to enum type, e.g. `T_ModuleType`, `T_LimitType`) +- **Params** stored in AMXX `Trie` (string key → value); parsed from JSON via ParamsController +- **Forwards** wrapped in `Forwards_Reg` / `Forwards_Call` macros (`VipM/Forwards.inc`) +- **Object handles** are array indices cast to enum type — `Invalid_*` sentinel = `-1` +- **Static limits** store a bitmask instead of calling a forward (faster, no params) + +--- + +## External dependencies + +| Library | Min version | Purpose | +|---------|-------------|---------| +| ParamsController | 1.3.2 | JSON parsing, param reading, path utils (`PCPath_*`, `PCJson_*`, `PCGet_*`) | +| CommandAliases | 1.0.1 | Server command aliasing | +| ReAPI | 5.24.0.300 | Game hooks: `RG_CBasePlayer_Spawn`, `RG_CSGameRules_RestartRound`, etc. | + +--- + +## Config files + +All under `amxmodx/configs/plugins/VipModular/`: + +| File | Purpose | +|------|---------| +| `Vips.json` | Privilege definitions (or `Vips/` folder for multiple files) | +| `Modules.json` | Module enable/disable rules (read by `VipM-ModulesLimiter`) | +| `Items/*.json` | Reusable item definitions | + +`"File:WeaponMenu/Premium"` in JSON → resolves to `configs/plugins/VipModular/WeaponMenu/Premium.json` + +--- + +## Sub-docs + +- [`docs/claude/module-system.md`](docs/claude/module-system.md) — registering & using modules +- [`docs/claude/limits-system.md`](docs/claude/limits-system.md) — registering & using limits +- [`docs/claude/items-system.md`](docs/claude/items-system.md) — ItemsController API +- [`docs/claude/config-format.md`](docs/claude/config-format.md) — Vips.json format reference + +--- + +## Working rules for Claude + +### Code style + +Match the existing style exactly. Key conventions: + +**Naming — identifiers** + +| Kind | Convention | Example | +|------|-----------|---------| +| Local variables | camelCase | `playerIndex`, `menuIndex`, `params` | +| Global variables | PascalCase (capital first letter) | `UserAutoOpen`, `UserLeftItems`, `Vips` | +| Public functions / API | `Namespace_PascalCase` | `VipsManager_Init`, `ModuleType_Find` | +| Static (private) functions | `Namespace_PascalCase` + `static` keyword | `static LimitType_Get(...)` | +| Internal helpers | `_PascalCase` | `_Cmd_Menu` | +| Native/forward callbacks | `@FullNativeName` | `@RG_CBasePlayer_Spawn`, `@Module_OnActivated` | +| Enum handle types | `T_Name` | `T_ModuleType`, `T_VipUnit` | +| Enum struct layouts | `S_Name` | `S_ModuleType`, `S_WeaponMenu` | +| Enum (actual enumerations) | `E_Name` | `E_ModuleEvent`, `E_LimitEvent` | +| Enum fields | `StructName_FieldName` | `ModuleType_Name`, `VipUnit_Access` | +| Constants / macros | `SCREAMING_SNAKE_CASE` | `MODULE_NAME`, `TASK_OFFSET_AUTO_OPEN` | + +**No Hungarian notation anywhere.** Don't add `i`, `s`, `f`, `b`, `g`, `g_` prefixes to variables — not on locals, not on globals. The existing codebase has legacy `g_aVips`, `gUserAutoOpen`, `iRet`, `sName` etc. — don't copy that pattern into new code. + +**Formatting** +- 4-space indentation +- Braces on same line for control flow: `if (...) {` +- Single blank line between logical blocks; two blank lines between top-level function definitions +- Long argument lists: one argument per line, aligned to opening paren +- Conditions spanning multiple lines: each sub-condition on its own line, operator at start + +**Other** +- Use `PCGet_*` / `PCSingle_*` helpers from ParamsController for reading params from Trie/JSON — don't read Tries directly where a helper exists +- Prefer `Invalid_*` sentinel checks over magic `-1` literals +- Don't add error handling for cases the framework already guards against + +--- + +### Documentation maintenance + +**After every code change, update the relevant `docs/claude/*.md` file** to reflect what changed: +- New module → update `docs/claude/module-system.md` +- New/changed limit type → update `docs/claude/limits-system.md` +- New/changed item type → update `docs/claude/items-system.md` +- Config format change → update `docs/claude/config-format.md` +- Structural change affecting multiple systems → update `CLAUDE.md` and the affected sub-docs + +If a change doesn't fit any existing sub-doc, create a new one in `docs/claude/` and add it to the sub-docs list above. diff --git a/docs/claude/config-format.md b/docs/claude/config-format.md new file mode 100644 index 0000000..2e3b591 --- /dev/null +++ b/docs/claude/config-format.md @@ -0,0 +1,151 @@ +# Config Format Reference + +All configs are JSON, located in `amxmodx/configs/plugins/VipModular/`. +Paths inside JSON are relative to that folder unless prefixed with `/` (then relative to `amxmodx/configs/`). + +--- + +## Vips.json + +Array of privilege objects, checked top-to-bottom. First match wins for each module. + +```json +[ + { + "Access": [ + { "Type": "Flags", "Flags": "t" } + ], + "Modules": [ + { + "Type": "SpawnItems", + "Items": [ + { "Type": "Weapon", "Name": "weapon_awp" }, + { "Type": "Health", "Value": 150 } + ] + }, + { + "Type": "WeaponMenu", + "File:Config": "WeaponMenu/Premium" + } + ] + } +] +``` + +- `Access` — array of Limit objects, evaluated with **OR** by default +- `Modules` — array of module config objects; `"Type"` is the module name +- `"File:Config": "Path/Name"` — loads `configs/plugins/VipModular/Path/Name.json` and merges it + +Alternatively, put individual privilege files in `Vips/` folder — all `.json` files there are loaded automatically. + +--- + +## Limit object + +```json +{ "Type": "LimitTypeName", ...params } +``` + +Examples: +```json +{ "Type": "Flags", "Flags": "ab" } +{ "Type": "Map", "Prefix": "de_" } +{ "Type": "Map", "Exact": "de_dust2" } +{ "Type": "Map", "Regex": "^de_.*2$" } +{ "Type": "Time", "From": "18:00", "To": "23:59" } +{ "Type": "Steam" } +{ "Type": "SteamId", "List": ["STEAM_0:1:12345"] } +{ "Type": "Round", "Min": 1, "Max": 5 } +{ "Type": "Frags", "Min": 10 } +{ "Type": "WeekDay", "Days": [1, 2, 3, 4, 5] } +{ "Type": "Always" } +{ "Type": "Never" } + +// Logical combinator +{ "Type": "Logic", "Mode": "AND", "Limits": [ + { "Type": "Alive" }, + { "Type": "InBuyZone" } +]} +``` + +--- + +## Item object (ItemsController) + +```json +{ "Type": "ItemTypeName", ...params } +``` + +Examples: +```json +{ "Type": "Weapon", "Name": "weapon_ak47" } +{ "Type": "Health", "Value": 100, "Add": true } +{ "Type": "Armor", "Value": 100 } +{ "Type": "Money", "Value": 1000, "Add": true } +{ "Type": "Speed", "Value": 1.2 } +{ "Type": "DefuseKit" } +{ "Type": "RefillBpAmmo" } +{ "Type": "Command", "Value": "say_team VIP spawned" } + +// Conditional: check limit, then give item +{ "Type": "If", "Limit": { "Type": "Alive" }, "Item": { "Type": "Health", "Value": 50 } } + +// Random pick +{ "Type": "Random", "Items": [ + { "Type": "Weapon", "Name": "weapon_awp" }, + { "Type": "Weapon", "Name": "weapon_ak47" } +]} + +// List +{ "Type": "ItemsList", "Items": [ + { "Type": "Weapon", "Name": "weapon_deagle" }, + { "Type": "Armor", "Value": 100 } +]} +``` + +--- + +## Modules.json (VipM-ModulesLimiter) + +Array of rules; each rule specifies conditions and which modules to enable/disable. +Checked by `VipM-ModulesLimiter.sma` in `VipM_Modules_OnActivate` forward. + +```json +[ + { + "Limits": [{ "Type": "Map", "Prefix": "cs_" }], + "Disable": ["WeaponMenu"] + }, + { + "Limits": [{ "Type": "Always" }], + "Enable": ["SpawnItems", "SpawnHealth"] + } +] +``` + +--- + +## File reference syntax + +In any JSON field value: +- `"File:Path/Name"` → loads `configs/plugins/VipModular/Path/Name.json` +- `"File:/configs/Path/Name"` → loads `amxmodx/configs/Path/Name.json` + +ParamsController resolves these transparently when calling `PCJson_ParseFile`. + +--- + +## Param type names (for `AddParamsEx`) + +| Name | Type | Usage | +|------|------|-------| +| `"Integer"` | `int` | | +| `"Float"` | `float` | | +| `"Bool"` | `bool` | | +| `"String"` | `string` | | +| `"VipM-Limit"` | `T_LimitUnit` | Single limit | +| `"VipM-Limits"` | `Array:T_LimitUnit` | List of limits | +| `"VipM-LimitType"` | `T_LimitType` | Limit type reference | +| `"VipM-ModuleType"` | `T_ModuleType` | Module type reference | +| `"IC-Item"` | `T_IC_Item` | Single item | +| `"IC-Items"` | `Array:T_IC_Item` | List of items | diff --git a/docs/claude/items-system.md b/docs/claude/items-system.md new file mode 100644 index 0000000..c7f6595 --- /dev/null +++ b/docs/claude/items-system.md @@ -0,0 +1,107 @@ +# Items System (ItemsController) + +`ItemsController.sma` is a standalone framework for applying effects ("items") to players. +It is independent from VipModular core but used by SpawnItems, Vampire, and WeaponMenu modules. + +Public header: `include/ItemsController.inc` + +--- + +## Concepts + +- **Item Type** (`T_IC_ItemType`) — named effect class, registered by a plugin +- **Item Instance** (`T_IC_Item`) — one concrete item with parsed params, created from JSON +- Give an item: `IC_Item_Give(playerIndex, item)` → fires `ItemType_OnGive` + +--- + +## Registration (in `IC_ItemType_OnInited`) + +```pawn +public IC_ItemType_OnInited() { + register_plugin(...); + IC_Init(); // must call this in the plugin that registers types + + new T_IC_ItemType:t = IC_ItemType_Register("MyEffect"); + IC_ItemType_SetEventListener(t, ItemType_OnRead, "@OnRead"); + IC_ItemType_SetEventListener(t, ItemType_OnGive, "@OnGive"); + // IC_ItemType_SetEventListener(t, ItemType_OnFree, "@OnFree"); // optional +} +``` + +--- + +## Events + +| Event | Signature | Return | +|-------|-----------|--------| +| `ItemType_OnRead` | `(JSON:jCfg, Trie:params)` | `IC_RET_READ_SUCCESS` or `IC_RET_READ_FAIL` | +| `ItemType_OnGive` | `(playerIndex, Trie:params)` | `IC_RET_GIVE_SUCCESS` or `IC_RET_GIVE_FAIL` | +| `ItemType_OnFree` | `(Trie:params)` | void — cleanup custom allocations | + +--- + +## Built-in item types (18) + +`ItemsController/DefaultObjects/ItemType/`: + +| Type | Effect | +|------|--------| +| `Weapon` | Give weapon (strips old if needed) | +| `Health` | Set / add health | +| `Armor` | Set / add armor | +| `DefuseKit` | Give defuse kit | +| `Money` | Give / set money | +| `Speed` | Modify movement speed | +| `DamageMult` | Damage multiplier | +| `InstantReload` | Reload current weapon instantly | +| `InstantReloadAllWeapons` | Reload all weapons | +| `RefillBpAmmo` | Refill backpack ammo | +| `Command` | Execute server command | +| `Function` | Call a plugin function | +| `If` | Conditional execution (check limit, then give item) | +| `ItemsList` | Ordered list of items | +| `Random` | Random item from a list | +| `CustomWeapon` | Spawn a custom weapon entity | + +--- + +## Using ItemsController in a module + +```pawn +// In VipM_Modules_OnInited: +VipM_Modules_AddParamsEx(MODULE_NAME, + "Items", IC_PARAM_TYPE_ITEMS_NAME, true +); + +// In game event handler: +new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); +PCGet_IcItemsGive(p, "Items", playerIndex); // give list +// or: +PCGet_IcItemGive(p, "Item", playerIndex); // give single +``` + +--- + +## Reading items from JSON manually + +```pawn +// Single item +new T_IC_Item:item = IC_Item_ReadFromJson(jsonObject); +IC_Item_Give(playerIndex, item); +IC_Item_Free(item); + +// List of items +new Array:items = IC_Items_ReadFromJson(jsonArray); +IC_Items_Give(playerIndex, items); +IC_Items_Free(items); +``` + +--- + +## Param type names (for `VipM_Modules_AddParamsEx`) + +```pawn +IC_PARAM_TYPE_ITEM_NAME // "IC-Item" — single item +IC_PARAM_TYPE_ITEMS_NAME // "IC-Items" — array of items +``` diff --git a/docs/claude/limits-system.md b/docs/claude/limits-system.md new file mode 100644 index 0000000..5794cd8 --- /dev/null +++ b/docs/claude/limits-system.md @@ -0,0 +1,140 @@ +# Limits System + +Limits are boolean conditions that gate access to privileges, modules, or items. +They are read from JSON configs and evaluated at runtime. + +--- + +## Two kinds of limits + +| Kind | How it works | Use case | +|------|-------------|---------| +| **Dynamic** | Has params + `Limit_OnRead` / `Limit_OnCheck` callbacks | Most conditions (Map, Flags, Time, Frags…) | +| **Static** | No params, value is set programmatically via `VipM_Limits_SetStaticValue` | Fast per-player flags (e.g. Steam validation status, alive check) | + +Static limit types store their result in a bitmask per player; no forward is called on check. + +--- + +## Registration (in `VipM_Limits_OnInited`) + +```pawn +public VipM_Limits_OnInited() { + register_plugin(...); + + // Dynamic limit + VipM_Limits_RegisterType("MyLimit", + .bForPlayer = true, // depends on a specific player + .bStatic = false // dynamic + ); + VipM_Limits_AddParamsEx("MyLimit", + "MinFrags", "Integer", true + ); + VipM_Limits_RegisterTypeEvent("MyLimit", Limit_OnCheck, "@OnCheck"); + + // Static limit (no params, no callback) + VipM_Limits_RegisterType("HasPremium", + .bForPlayer = true, + .bStatic = true + ); + VipM_Limits_SetStaticValue("HasPremium", false); // default for all +} +``` + +--- + +## Events + +| Event | Signature | Purpose | +|-------|-----------|---------| +| `Limit_OnRead` | `(JSON:jUnit, Trie:tParams)` | Post-parse hook — modify params or abort (`VIPM_STOP`) | +| `Limit_OnCheck` | `(Trie:tParams, playerIndex) → bool` | Evaluate the condition for a player | + +`Limit_OnCheck` is **not called** for static limits — the core reads the bitmask directly. + +--- + +## Built-in limit types (24) + +`VipM/DefaultObjects/Limit/`: + +| Type | File | Notes | +|------|------|-------| +| `Flags` | Flags.inc | Admin flags bitmask | +| `Steam` | Steam.inc | Steam validation status (static) | +| `SteamId` | SteamId.inc | Specific Steam IDs list | +| `Ip` | Ip.inc | IP address match | +| `Map` | Map.inc | Map name (prefix / exact / regex) | +| `Time` | Time.inc | Server clock range | +| `RoundTime` | RoundTime.inc | Time elapsed in current round | +| `Round` | Round.inc | Round number | +| `GameTime` | GameTime.inc | Total game time | +| `Alive` | Alive.inc | Player alive state (static) | +| `Frags` | Frags.inc | Kill count range | +| `WasKilled` | WasKilled.inc | Death state this round | +| `InBuyZone` | InBuyZone.inc | Buy zone presence | +| `InFreezyTime` | InFreezyTime.inc | Freeze time active | +| `HasPrimaryWeapon` | HasPrimaryWeapon.inc | Primary weapon in inventory | +| `LifeTime` | LifeTime.inc | Time connected | +| `WeekDay` | WeekDay.inc | Day of week | +| `Bot` | Bot.inc | Is bot | +| `Name` | Name.inc | Player name match | +| `Counter` | Counter.inc | Counter limit (max uses) | +| `OncePer` | OncePer.inc | One-time per period | +| `Logic` | Logic.inc | AND / OR / NOT over nested limits | +| `Always` | Always.inc | Always true (static) | +| `Never` | Never.inc | Always false (static) | + +--- + +## Executing limits + +```pawn +// Execute a single limit unit +bool:VipM_Limits_Execute(T_LimitUnit:iLimit, UserId = 0) + +// Execute a list with a logical operator (OR / AND / XOR) +bool:VipM_Limits_ExecuteList(Array:aLimits, UserId = 0, E_LimitsExecType:iType = Limit_Exec_OR) + +// Convenience: read a limit from a params Trie and check it +PCGet_VipmLimitCheck(Trie:p, "LimitKey", playerIndex, bool:def = true) +PCGet_VipmLimitsCheck(Trie:p, "LimitsKey", playerIndex, Limit_Exec_AND, bool:def = true) +``` + +`E_LimitsExecType`: `Limit_Exec_OR`, `Limit_Exec_AND`, `Limit_Exec_XOR` + +--- + +## Limit in JSON config + +```json +// Single limit object +{ "Type": "Flags", "Flags": "a" } + +// As access condition in Vips.json +"Access": [ + { "Type": "Flags", "Flags": "t" }, + { "Type": "Map", "Prefix": "de_" } +] +// default exec type is OR: either condition passes + +// Logic limit for AND +{ "Type": "Logic", "Mode": "AND", "Limits": [ + { "Type": "Alive" }, + { "Type": "InBuyZone" } +]} +``` + +--- + +## Setting static values + +Static limits must have their value pushed externally (e.g. on spawn or auth): + +```pawn +// Set for all players +VipM_Limits_SetStaticValue("MyStaticLimit", true); + +// Set for specific player +VipM_Limits_SetStaticValue("Steam", is_user_steam(playerIndex), playerIndex); +``` diff --git a/docs/claude/module-system.md b/docs/claude/module-system.md new file mode 100644 index 0000000..d66df1c --- /dev/null +++ b/docs/claude/module-system.md @@ -0,0 +1,115 @@ +# Module System + +Modules are named, pluggable game features. A module plugin registers a type during init, the core activates it if referenced in configs, and the module then hooks into game events. + +--- + +## Registration (in `VipM_Modules_OnInited`) + +```pawn +public VipM_Modules_OnInited() { + register_plugin(...); + + VipM_Modules_Register("SpawnItems"); + + // paramName, paramTypeName, required + VipM_Modules_AddParamsEx("SpawnItems", + "Items", IC_PARAM_TYPE_ITEMS_NAME, true, + "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false + ); + + VipM_Modules_RegisterEvent("SpawnItems", Module_OnActivated, "@OnModuleActivate"); + // Optional: Module_OnRead, Module_OnMergeParams +} +``` + +`VipM_Modules_Register(name, Once = true)` — `Once = false` means the system will call `Module_OnMergeParams` when the same module appears from multiple VIP tiers for one player. + +--- + +## Events + +| Event | Signature | When called | Notes | +|-------|-----------|-------------|-------| +| `Module_OnActivated` | `()` | After config load, in `plugin_precache` | Register game hooks here. Return `VIPM_STOP` to cancel activation. | +| `Module_OnRead` | `(JSON:jCfg, Trie:p)` | While reading config, `plugin_precache` | Extend/override parsed params. Return `VIPM_STOP` to skip this module unit. | +| `Module_OnMergeParams` | `(Trie:p1, Trie:p2) → Trie` | When same module appears from 2+ VIP levels | Return `p1`, `p2`, or a new Trie. New Trie is auto-freed by core. Do not modify `p1`/`p2`. | + +--- + +## Activation flow + +``` +VipsManager_LoadFromFile → reads all VipUnits + each VipUnit's module entries mark their type as "Used" +ModuleType_ActivateUsed() + for each used type: + fires "VipM_Modules_OnActivate" forward (any plugin can return VIPM_STOP to block) + if not blocked: Module_OnActivated event → module registers its ReAPI hooks, etc. +``` + +`VipM-ModulesLimiter` uses `VipM_Modules_OnActivate` to block modules based on map/conditions from `Modules.json`. + +--- + +## Checking module access in-game + +```pawn +// Simple check +if (!VipM_Modules_HasModule("SpawnItems", playerIndex)) + return; + +// Get params +new Trie:p = VipM_Modules_GetParams("SpawnItems", playerIndex); + +// Use ParamsController getters +PCGet_IcItemsGive(p, "Items", playerIndex); +PCGet_VipmLimitsCheck(p, "Limits", playerIndex, Limit_Exec_AND); +``` + +`VipM_Modules_GetParams` returns `Invalid_Trie` if player has no access → `HasModule` is just a null check. + +--- + +## Player module state + +`g_tUserModules[playerIndex]` in `VipM/Core/VipsManager.inc`: +- Created fresh on each `VipsManager_UserReload()` +- Key: module name string → Value: `Trie:params` +- Destroyed (with inner Tries) on `VipsManager_UserReset()` +- Updated via `VipM_UserUpdate(playerIndex)` native + +--- + +## Minimal module skeleton + +```pawn +#include +#include +#include + +new const MODULE_NAME[] = "MyModule"; + +public VipM_Modules_OnInited() { + register_plugin("VipM-M-MyModule", "1.0.0", "Author"); + + VipM_Modules_Register(MODULE_NAME); + VipM_Modules_AddParamsEx(MODULE_NAME, + "SomeValue", "Integer", true + ); + VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnActivate"); +} + +@OnActivate() { + RegisterHookChain(RG_CBasePlayer_Spawn, "@OnSpawn", true); +} + +@OnSpawn(const playerIndex) { + if (!VipM_Modules_HasModule(MODULE_NAME, playerIndex)) + return; + + new Trie:p = VipM_Modules_GetParams(MODULE_NAME, playerIndex); + new val = PCGet_Int(p, "SomeValue", 100); + // apply effect... +} +``` From 8a418eadadcc523e6d539fb6d767243c90402d85 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 10 Apr 2026 01:26:31 +0300 Subject: [PATCH 099/108] Use const param type names for all def objs --- .gitignore | 1 + CLAUDE.md | 7 +++++++ .../DefaultObjects/ItemType/Armor.inc | 8 ++++---- .../DefaultObjects/ItemType/Command.inc | 4 ++-- .../DefaultObjects/ItemType/DamageMult.inc | 4 ++-- .../DefaultObjects/ItemType/Function.inc | 12 ++++++------ .../DefaultObjects/ItemType/Health.inc | 6 +++--- .../DefaultObjects/ItemType/Money.inc | 4 ++-- .../DefaultObjects/ItemType/Speed.inc | 2 +- .../DefaultObjects/ItemType/Weapon.inc | 4 ++-- 10 files changed, 30 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 29c91b0..40b0a40 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.zip .build plugins-*.ini +.claude diff --git a/CLAUDE.md b/CLAUDE.md index 6e9a20e..f0d964f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -120,6 +120,13 @@ All under `amxmodx/configs/plugins/VipModular/`: --- +## Local-only docs + +Some context is intentionally kept out of the repository (e.g. local tool paths). +Check `.claude/` memory for a `local-env.md` file — if it exists, read it before working with the build system or dependency headers. + +--- + ## Sub-docs - [`docs/claude/module-system.md`](docs/claude/module-system.md) — registering & using modules diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc index f645986..cd32371 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc @@ -9,10 +9,10 @@ DefaultObjects_ItemType_Armor_Register() { .onGive = "@OnArmorGive" ); IC_ItemType_AddParams(type, - "Armor", "Integer", true, - "MaxArmor", "Integer", false, - "SetArmor", "Boolean", false, - "Helmet", "Boolean", false + "Armor", DEFAULT_PARAMS_INT_NAME, true, + "MaxArmor", DEFAULT_PARAMS_INT_NAME, false, + "SetArmor", DEFAULT_PARAMS_BOOL_NAME, false, + "Helmet", DEFAULT_PARAMS_BOOL_NAME, false ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc index 1766dfc..23d368f 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -8,8 +8,8 @@ DefaultObjects_ItemType_Command_Register() { .onGive = "@OnCommandGive" ); IC_ItemType_AddParams(type, - "Command", "String", true, - "ByServer", "Boolean", false + "Command", DEFAULT_PARAMS_STR_NAME, true, + "ByServer", DEFAULT_PARAMS_BOOL_NAME, false ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc index 4629635..b9d5169 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc @@ -12,8 +12,8 @@ DefaultObjects_ItemType_DamageMult_Register() { .onGive = "@ItemType_DamageMult_OnGive" ); IC_ItemType_AddParams(type, - "Given", "Float", false, - "Taken", "Float", false + "Given", DEFAULT_PARAMS_FLOAT_NAME, false, + "Taken", DEFAULT_PARAMS_FLOAT_NAME, false ); RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_DamageMult_OnPlayerSpawnPre", false); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc index 63198cf..6ce3447 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc @@ -9,15 +9,15 @@ DefaultObjects_ItemType_Function_Register() { .onGive = "@OnFunctionGive" ); IC_ItemType_AddParams(type, - "Plugin", "String", true, - "Function", "String", true + "Plugin", DEFAULT_PARAMS_STR_NAME, true, + "Function", DEFAULT_PARAMS_STR_NAME, true ); - + // For AES-Bonuses compat IC_ItemType_AddParams(type, - "Value", "Integer", false, - "Flags", "ShortString", false, - "Days", "Integer", false + "Value", DEFAULT_PARAMS_INT_NAME, false, + "Flags", DEFAULT_PARAMS_SHORT_STR_NAME, false, + "Days", DEFAULT_PARAMS_INT_NAME, false ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc index 3b31ee9..8737706 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -10,9 +10,9 @@ DefaultObjects_ItemType_Health_Register() { .onGive = "@OnHealthGive" ); IC_ItemType_AddParams(type, - "Health", "Float", true, - "MaxHealth", "Float", false, - "SetHealth", "Boolean", false + "Health", DEFAULT_PARAMS_FLOAT_NAME, true, + "MaxHealth", DEFAULT_PARAMS_FLOAT_NAME, false, + "SetHealth", DEFAULT_PARAMS_BOOL_NAME, false ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc index cab2243..e4ff6b4 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -10,8 +10,8 @@ DefaultObjects_ItemType_Money_Register() { .onGive = "@OnMoneyGive" ); IC_ItemType_AddParams(type, - "Amount", "Integer", true, - "TrackChange", "Boolean", false + "Amount", DEFAULT_PARAMS_INT_NAME, true, + "TrackChange", DEFAULT_PARAMS_BOOL_NAME, false ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc index 8747288..bcd6d76 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc @@ -12,7 +12,7 @@ DefaultObjects_ItemType_Speed_Register() { .onGive = "@ItemType_Speed_OnGive" ); IC_ItemType_AddParams(type, - "Multiplier", "Float", true + "Multiplier", DEFAULT_PARAMS_FLOAT_NAME, true ); RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@ItemType_Speed_OnPlayerResetSpeedPost", true); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc index 6ec4503..bb08556 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -10,8 +10,8 @@ DefaultObjects_ItemType_Weapon_Register() { .onGive = "@OnWeaponGive" ); IC_ItemType_AddParams(type, - "Name", "String", true, - "BpAmmo", "Integer", false + "Name", DEFAULT_PARAMS_STR_NAME, true, + "BpAmmo", DEFAULT_PARAMS_INT_NAME, false ); } From 0ed63a6d0ed249c6294975214721c0f13f533ce6 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 10 Apr 2026 12:26:15 +0300 Subject: [PATCH 100/108] Update map limit --- .../VipM/DefaultObjects/Limit/Map.inc | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc index 9402e85..e22ee67 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc @@ -1,15 +1,15 @@ #include +#include #include #include new RealCurrentMapName[32]; -// TODO: Указывание нескольких карт/префиксов. Возможно отдельным лимитом. - DefaultObjects_Limit_Map_Register() { VipM_Limits_RegisterType("Map", true, false); VipM_Limits_AddParamsEx("Map", - "Map", DEFAULT_PARAMS_SHORT_STR_NAME, true, + "Map", DEFAULT_PARAMS_SHORT_STR_NAME, false, + "Regexp", DEFAULT_PARAMS_REGEXP_NAME, false, "Real", DEFAULT_PARAMS_BOOL_NAME, false, "Prefix", DEFAULT_PARAMS_BOOL_NAME, false ); @@ -18,20 +18,46 @@ DefaultObjects_Limit_Map_Register() { rh_get_mapname(RealCurrentMapName, charsmax(RealCurrentMapName), MNT_TRUE); } +static DefaultObjects_Limit_Map_GetCurrentName(out[], const outLen, const bool:real) { + if (real) { + copy(out, outLen, RealCurrentMapName); + } else { + rh_get_mapname(out, outLen, MNT_SET); + } +} + @DefaultObjects_Limit_Map_OnCheck(const Trie:p, const playerIndex) { - static map[32]; - new len = PCGet_Str(p, "Map", map, charsmax(map)); + new bool:real = PCGet_Bool(p, "Real", false); - if (!PCGet_Bool(p, "Prefix", false)) { - len = 0; + if (real && TrieKeyExists(p, "$Result")) { + new cachedResult; + TrieGetCell(p, "$Result", cachedResult); + return cachedResult; } - if (PCGet_Bool(p, "Real", false)) { - return equali(map, RealCurrentMapName, len); + static currentMapName[32]; + DefaultObjects_Limit_Map_GetCurrentName(currentMapName, charsmax(currentMapName), real); + + new result; + if (PCGet_Regexp(p, "Regexp") != REGEX_PATTERN_FAIL) { + result = PCGet_RegexpMatch(p, "Regexp", currentMapName); } else { - static currentMapName[32]; - rh_get_mapname(currentMapName, charsmax(currentMapName), MNT_SET); + static map[32]; + new len = PCGet_Str(p, "Map", map, charsmax(map)); + + if (!len) { + result = false; + } else { + if (!PCGet_Bool(p, "Prefix", false)) { + len = 0; + } + result = equali(map, currentMapName, len); + } + } - return equali(map, currentMapName, len); + if (real) { + TrieSetCell(p, "$Result", result); } + + return result; } From 333670ced8e6c6d9261dbd4f1d6a9619a14aade3 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 10 Apr 2026 17:47:48 +0300 Subject: [PATCH 101/108] Use PCParam style for all params register --- .github/workflows/CI.yml | 2 +- .../configs/plugins/VipModular/Modules.json | 60 +------------------ .../DefaultObjects/ItemType/Armor.inc | 8 +-- .../DefaultObjects/ItemType/Command.inc | 4 +- .../DefaultObjects/ItemType/DamageMult.inc | 4 +- .../DefaultObjects/ItemType/Function.inc | 10 ++-- .../DefaultObjects/ItemType/Health.inc | 6 +- .../DefaultObjects/ItemType/Money.inc | 4 +- .../DefaultObjects/ItemType/Speed.inc | 2 +- .../DefaultObjects/ItemType/Weapon.inc | 4 +- amxmodx/scripting/VipM-M-SpawnHealth.sma | 16 ++--- amxmodx/scripting/VipM-M-SpawnItems.sma | 4 +- amxmodx/scripting/VipM-M-Vampire.sma | 12 ++-- amxmodx/scripting/VipM-M-VipInTab.sma | 4 +- amxmodx/scripting/VipM-M-WeaponMenu.sma | 32 ++++------ .../VipM/DefaultObjects/Limit/Counter.inc | 8 +-- .../VipM/DefaultObjects/Limit/Flags.inc | 4 +- .../VipM/DefaultObjects/Limit/Frags.inc | 4 +- .../VipM/DefaultObjects/Limit/GameTime.inc | 4 +- .../DefaultObjects/Limit/HasPrimaryWeapon.inc | 2 +- .../VipM/DefaultObjects/Limit/InBuyZone.inc | 2 +- .../DefaultObjects/Limit/InFreezyTime.inc | 2 +- .../VipM/DefaultObjects/Limit/Ip.inc | 2 +- .../VipM/DefaultObjects/Limit/LifeTime.inc | 4 +- .../VipM/DefaultObjects/Limit/Logic.inc | 8 +-- .../VipM/DefaultObjects/Limit/Map.inc | 8 +-- .../VipM/DefaultObjects/Limit/Name.inc | 2 +- .../VipM/DefaultObjects/Limit/Round.inc | 4 +- .../VipM/DefaultObjects/Limit/RoundTime.inc | 4 +- .../VipM/DefaultObjects/Limit/SteamId.inc | 2 +- .../VipM/DefaultObjects/Limit/Time.inc | 4 +- .../VipM/DefaultObjects/Limit/WeekDay.inc | 2 +- 32 files changed, 89 insertions(+), 149 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4d7671a..10baf5d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,7 +17,7 @@ env: PLUGINS_INI_GENERATE: 1 PLUGINS_INI_POSTFIX: vipm DEPS_LIST: | - AmxxModularEcosystem/ParamsController@1.3.3 + AmxxModularEcosystem/ParamsController@1.4.0 AmxxModularEcosystem/CommandAliases@1.0.1 jobs: diff --git a/amxmodx/configs/plugins/VipModular/Modules.json b/amxmodx/configs/plugins/VipModular/Modules.json index e996104..391cf02 100644 --- a/amxmodx/configs/plugins/VipModular/Modules.json +++ b/amxmodx/configs/plugins/VipModular/Modules.json @@ -19,63 +19,9 @@ "Limits": { "Limit": "Logic-NOT", "Limits": { - "Limit": "Logic-OR", - "Limits": [ - { - "Limit": "Map", - "Map": "$", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "aim_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "awp_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "fy_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "35hp_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "1hp_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "100hp_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "he_", - "Prefix": true, - "Real": true - }, - { - "Limit": "Map", - "Map": "ka_", - "Prefix": true, - "Real": true - } - ] + "Limit": "Map", + "Regexp": "^(\\$|aim_|awp_|fy_|35hp_|1hp_|100hp_|he_|ka_)", + "Real": true } } } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc index cd32371..e4d1051 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Armor.inc @@ -9,10 +9,10 @@ DefaultObjects_ItemType_Armor_Register() { .onGive = "@OnArmorGive" ); IC_ItemType_AddParams(type, - "Armor", DEFAULT_PARAMS_INT_NAME, true, - "MaxArmor", DEFAULT_PARAMS_INT_NAME, false, - "SetArmor", DEFAULT_PARAMS_BOOL_NAME, false, - "Helmet", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Armor", DEFAULT_PARAMS_INT_NAME, true), + PCParam("MaxArmor", DEFAULT_PARAMS_INT_NAME), + PCParam("SetArmor", DEFAULT_PARAMS_BOOL_NAME), + PCParam("Helmet", DEFAULT_PARAMS_BOOL_NAME) ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc index 23d368f..feac2da 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Command.inc @@ -8,8 +8,8 @@ DefaultObjects_ItemType_Command_Register() { .onGive = "@OnCommandGive" ); IC_ItemType_AddParams(type, - "Command", DEFAULT_PARAMS_STR_NAME, true, - "ByServer", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Command", DEFAULT_PARAMS_STR_NAME, true), + PCParam("ByServer", DEFAULT_PARAMS_BOOL_NAME) ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc index b9d5169..241c346 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/DamageMult.inc @@ -12,8 +12,8 @@ DefaultObjects_ItemType_DamageMult_Register() { .onGive = "@ItemType_DamageMult_OnGive" ); IC_ItemType_AddParams(type, - "Given", DEFAULT_PARAMS_FLOAT_NAME, false, - "Taken", DEFAULT_PARAMS_FLOAT_NAME, false + PCParam("Given", DEFAULT_PARAMS_FLOAT_NAME), + PCParam("Taken", DEFAULT_PARAMS_FLOAT_NAME) ); RegisterHookChain(RG_CBasePlayer_Spawn, "@ItemType_DamageMult_OnPlayerSpawnPre", false); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc index 6ce3447..4ffadec 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Function.inc @@ -9,15 +9,15 @@ DefaultObjects_ItemType_Function_Register() { .onGive = "@OnFunctionGive" ); IC_ItemType_AddParams(type, - "Plugin", DEFAULT_PARAMS_STR_NAME, true, - "Function", DEFAULT_PARAMS_STR_NAME, true + PCParam("Plugin", DEFAULT_PARAMS_STR_NAME, true), + PCParam("Function", DEFAULT_PARAMS_STR_NAME, true) ); // For AES-Bonuses compat IC_ItemType_AddParams(type, - "Value", DEFAULT_PARAMS_INT_NAME, false, - "Flags", DEFAULT_PARAMS_SHORT_STR_NAME, false, - "Days", DEFAULT_PARAMS_INT_NAME, false + PCParam("Value", DEFAULT_PARAMS_INT_NAME), + PCParam("Flags", DEFAULT_PARAMS_SHORT_STR_NAME), + PCParam("Days", DEFAULT_PARAMS_INT_NAME) ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc index 8737706..eb36c73 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Health.inc @@ -10,9 +10,9 @@ DefaultObjects_ItemType_Health_Register() { .onGive = "@OnHealthGive" ); IC_ItemType_AddParams(type, - "Health", DEFAULT_PARAMS_FLOAT_NAME, true, - "MaxHealth", DEFAULT_PARAMS_FLOAT_NAME, false, - "SetHealth", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Health", DEFAULT_PARAMS_FLOAT_NAME, true), + PCParam("MaxHealth", DEFAULT_PARAMS_FLOAT_NAME), + PCParam("SetHealth", DEFAULT_PARAMS_BOOL_NAME) ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc index e4ff6b4..5f4289c 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Money.inc @@ -10,8 +10,8 @@ DefaultObjects_ItemType_Money_Register() { .onGive = "@OnMoneyGive" ); IC_ItemType_AddParams(type, - "Amount", DEFAULT_PARAMS_INT_NAME, true, - "TrackChange", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Amount", DEFAULT_PARAMS_INT_NAME, true), + PCParam("TrackChange", DEFAULT_PARAMS_BOOL_NAME) ); } diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc index bcd6d76..682f753 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Speed.inc @@ -12,7 +12,7 @@ DefaultObjects_ItemType_Speed_Register() { .onGive = "@ItemType_Speed_OnGive" ); IC_ItemType_AddParams(type, - "Multiplier", DEFAULT_PARAMS_FLOAT_NAME, true + PCParam("Multiplier", DEFAULT_PARAMS_FLOAT_NAME, true) ); RegisterHookChain(RG_CBasePlayer_ResetMaxSpeed, "@ItemType_Speed_OnPlayerResetSpeedPost", true); diff --git a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc index bb08556..e07d52b 100644 --- a/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc +++ b/amxmodx/scripting/ItemsController/DefaultObjects/ItemType/Weapon.inc @@ -10,8 +10,8 @@ DefaultObjects_ItemType_Weapon_Register() { .onGive = "@OnWeaponGive" ); IC_ItemType_AddParams(type, - "Name", DEFAULT_PARAMS_STR_NAME, true, - "BpAmmo", DEFAULT_PARAMS_INT_NAME, false + PCParam("Name", DEFAULT_PARAMS_STR_NAME, true), + PCParam("BpAmmo", DEFAULT_PARAMS_INT_NAME) ); } diff --git a/amxmodx/scripting/VipM-M-SpawnHealth.sma b/amxmodx/scripting/VipM-M-SpawnHealth.sma index 236b31b..97de2a3 100644 --- a/amxmodx/scripting/VipM-M-SpawnHealth.sma +++ b/amxmodx/scripting/VipM-M-SpawnHealth.sma @@ -15,18 +15,18 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "Health", DEFAULT_PARAMS_INT_NAME, false, - "SetHealth", DEFAULT_PARAMS_BOOL_NAME, false, - "MaxHealth", DEFAULT_PARAMS_INT_NAME, false + PCParam("Health", DEFAULT_PARAMS_INT_NAME), + PCParam("SetHealth", DEFAULT_PARAMS_BOOL_NAME), + PCParam("MaxHealth", DEFAULT_PARAMS_INT_NAME) ); VipM_Modules_AddParamsEx(MODULE_NAME, - "Armor", DEFAULT_PARAMS_INT_NAME, false, - "SetArmor", DEFAULT_PARAMS_BOOL_NAME, false, - "MaxArmor", DEFAULT_PARAMS_INT_NAME, false + PCParam("Armor", DEFAULT_PARAMS_INT_NAME), + PCParam("SetArmor", DEFAULT_PARAMS_BOOL_NAME), + PCParam("MaxArmor", DEFAULT_PARAMS_INT_NAME) ); VipM_Modules_AddParamsEx(MODULE_NAME, - "Helmet", DEFAULT_PARAMS_BOOL_NAME, false, - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false + PCParam("Helmet", DEFAULT_PARAMS_BOOL_NAME), + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME) ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-SpawnItems.sma b/amxmodx/scripting/VipM-M-SpawnItems.sma index dca64a1..aa44797 100644 --- a/amxmodx/scripting/VipM-M-SpawnItems.sma +++ b/amxmodx/scripting/VipM-M-SpawnItems.sma @@ -18,8 +18,8 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "Items", IC_PARAM_TYPE_ITEMS_NAME, true, - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false + PCParam("Items", IC_PARAM_TYPE_ITEMS_NAME, true), + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME) ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-Vampire.sma b/amxmodx/scripting/VipM-M-Vampire.sma index e52c847..dc35206 100644 --- a/amxmodx/scripting/VipM-M-Vampire.sma +++ b/amxmodx/scripting/VipM-M-Vampire.sma @@ -16,14 +16,14 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "ByKill", DEFAULT_PARAMS_INT_NAME, false, - "ByHead", DEFAULT_PARAMS_INT_NAME, false, - "ByKnife", DEFAULT_PARAMS_INT_NAME, false, - "ByGrenade", DEFAULT_PARAMS_INT_NAME, false + PCParam("ByKill", DEFAULT_PARAMS_INT_NAME), + PCParam("ByHead", DEFAULT_PARAMS_INT_NAME), + PCParam("ByKnife", DEFAULT_PARAMS_INT_NAME), + PCParam("ByGrenade", DEFAULT_PARAMS_INT_NAME) ); VipM_Modules_AddParamsEx(MODULE_NAME, - "MaxHealth", DEFAULT_PARAMS_INT_NAME, false, - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false + PCParam("MaxHealth", DEFAULT_PARAMS_INT_NAME), + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME) ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@Event_ModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-VipInTab.sma b/amxmodx/scripting/VipM-M-VipInTab.sma index 2b0e7bd..c5ba8bd 100644 --- a/amxmodx/scripting/VipM-M-VipInTab.sma +++ b/amxmodx/scripting/VipM-M-VipInTab.sma @@ -21,8 +21,8 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, - "Enabled", DEFAULT_PARAMS_BOOL_NAME, true, - "Override", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Enabled", DEFAULT_PARAMS_BOOL_NAME, true), + PCParam("Override", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); } diff --git a/amxmodx/scripting/VipM-M-WeaponMenu.sma b/amxmodx/scripting/VipM-M-WeaponMenu.sma index a57429b..2cfe832 100644 --- a/amxmodx/scripting/VipM-M-WeaponMenu.sma +++ b/amxmodx/scripting/VipM-M-WeaponMenu.sma @@ -40,25 +40,19 @@ public VipM_Modules_OnInited() { VipM_Modules_Register(MODULE_NAME); VipM_Modules_AddParamsEx(MODULE_NAME, // TODO: Read "Menus" as param - "MainMenuTitle", DEFAULT_PARAMS_STR_NAME, false, - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, false - ); - VipM_Modules_AddParamsEx(MODULE_NAME, - "Count", DEFAULT_PARAMS_INT_NAME, false, - "CounterType", VIPM_L_COUNTER_PARAM_TYPE, false, - "CounterKey", DEFAULT_PARAMS_SHORT_STR_NAME, false, - "ResetCountOnSpawn", DEFAULT_PARAMS_BOOL_NAME, false // deprecated - ); - VipM_Modules_AddParamsEx(MODULE_NAME, - "AutoopenLimits", VIPM_PARAM_TYPE_LIMITS_NAME, false, - "AutoopenDelay", DEFAULT_PARAMS_FLOAT_NAME, false, - "AutoopenCloseDelay", DEFAULT_PARAMS_FLOAT_NAME, false, - "AutoopenMenuNum", DEFAULT_PARAMS_INT_NAME, false - ); - VipM_Modules_AddParamsEx(MODULE_NAME, - "StayOpen", DEFAULT_PARAMS_BOOL_NAME, false, - "StayOpen_CheckCounter", DEFAULT_PARAMS_BOOL_NAME, false, - "StayOpen_WhenRestricted", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("MainMenuTitle", DEFAULT_PARAMS_STR_NAME), + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME), + PCParam("Count", DEFAULT_PARAMS_INT_NAME), + PCParam("CounterType", VIPM_L_COUNTER_PARAM_TYPE), + PCParam("CounterKey", DEFAULT_PARAMS_SHORT_STR_NAME), + PCParam("ResetCountOnSpawn", DEFAULT_PARAMS_BOOL_NAME), // deprecated + PCParam("AutoopenLimits", VIPM_PARAM_TYPE_LIMITS_NAME), + PCParam("AutoopenDelay", DEFAULT_PARAMS_FLOAT_NAME), + PCParam("AutoopenCloseDelay", DEFAULT_PARAMS_FLOAT_NAME), + PCParam("AutoopenMenuNum", DEFAULT_PARAMS_INT_NAME), + PCParam("StayOpen", DEFAULT_PARAMS_BOOL_NAME), + PCParam("StayOpen_CheckCounter", DEFAULT_PARAMS_BOOL_NAME), + PCParam("StayOpen_WhenRestricted", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnActivated, "@OnModuleActivate"); VipM_Modules_RegisterEvent(MODULE_NAME, Module_OnRead, "@OnReadConfig"); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc index caed960..304e3c0 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Counter.inc @@ -9,10 +9,10 @@ static Trie:CounterTypes[VipM_L_Counter_Type]; DefaultObjects_Limit_Counter_Register() { VipM_Limits_RegisterType("Counter", true, false); VipM_Limits_AddParamsEx("Counter", - "Type", VIPM_L_COUNTER_PARAM_TYPE, true, - "Key", DEFAULT_PARAMS_SHORT_STR_NAME, true, - "Max", DEFAULT_PARAMS_INT_NAME, false, - "Inc", DEFAULT_PARAMS_INT_NAME, false + PCParam("Type", VIPM_L_COUNTER_PARAM_TYPE, true), + PCParam("Key", DEFAULT_PARAMS_SHORT_STR_NAME, true), + PCParam("Max", DEFAULT_PARAMS_INT_NAME), + PCParam("Inc", DEFAULT_PARAMS_INT_NAME) ); VipM_Limits_RegisterTypeEvent("Counter", Limit_OnCheck, "@DefaultObjects_Limit_Counter_OnCheck"); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc index 328465b..6a95a52 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Flags.inc @@ -5,8 +5,8 @@ DefaultObjects_Limit_Flags_Register() { VipM_Limits_RegisterType("Flags", true, false); VipM_Limits_AddParamsEx("Flags", - "Flags", DEFAULT_PARAMS_FLAGS_NAME, true, - "Strict", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Flags", DEFAULT_PARAMS_FLAGS_NAME, true), + PCParam("Strict", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Limits_RegisterTypeEvent("Flags", Limit_OnCheck, "@DefaultObjects_Limit_Flags_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc index 78d6700..a5ee8e3 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Frags.inc @@ -5,8 +5,8 @@ DefaultObjects_Limit_Frags_Register() { VipM_Limits_RegisterType("Frags", true, false); VipM_Limits_AddParamsEx("Frags", - "Min", DEFAULT_PARAMS_INT_NAME, false, - "Max", DEFAULT_PARAMS_INT_NAME, false + PCParam("Min", DEFAULT_PARAMS_INT_NAME), + PCParam("Max", DEFAULT_PARAMS_INT_NAME) ); VipM_Limits_RegisterTypeEvent("Frags", Limit_OnCheck, "@DefaultObjects_Limit_Frags_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc index cdec24f..f2a4170 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/GameTime.inc @@ -5,8 +5,8 @@ DefaultObjects_Limit_GameTime_Register() { VipM_Limits_RegisterType("GameTime", false, false); VipM_Limits_AddParamsEx("GameTime", - "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, - "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false + PCParam("Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME), + PCParam("Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME) ); VipM_Limits_RegisterTypeEvent("GameTime", Limit_OnCheck, "@DefaultObjects_Limit_GameTime_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc index bec98a6..64f9a06 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/HasPrimaryWeapon.inc @@ -5,7 +5,7 @@ DefaultObjects_Limit_HasPrimaryWeapon_Register() { VipM_Limits_RegisterType("HasPrimaryWeapon", true, false); VipM_Limits_AddParamsEx("HasPrimaryWeapon", - "HasNot", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("HasNot", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Limits_RegisterTypeEvent("HasPrimaryWeapon", Limit_OnCheck, "@DefaultObjects_Limit_HasPrimaryWeapon_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc index 6c52132..9825207 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/InBuyZone.inc @@ -7,7 +7,7 @@ DefaultObjects_Limit_InBuyZone_Register() { VipM_Limits_RegisterType("InBuyZone", true, false); VipM_Limits_AddParamsEx("InBuyZone", - "Reverse", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Reverse", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Limits_RegisterTypeEvent("InBuyZone", Limit_OnCheck, "@DefaultObjects_Limit_InBuyZone_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc index 7b56d24..c0f729b 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/InFreezyTime.inc @@ -5,7 +5,7 @@ DefaultObjects_Limit_InFreezyTime_Register() { VipM_Limits_RegisterType("InFreezyTime", false, false); VipM_Limits_AddParamsEx("InFreezyTime", - "Reverse", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Reverse", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Limits_RegisterTypeEvent("InFreezyTime", Limit_OnCheck, "@DefaultObjects_Limit_InFreezyTime_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc index 24f7363..e055bb8 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Ip.inc @@ -7,7 +7,7 @@ static PlayerIps[MAX_PLAYERS + 1][MAX_IP_LENGTH]; DefaultObjects_Limit_Ip_Register() { VipM_Limits_RegisterType("Ip", true, false); VipM_Limits_AddParamsEx("Ip", - "Ip", DEFAULT_PARAMS_SHORT_STR_NAME, true + PCParam("Ip", DEFAULT_PARAMS_SHORT_STR_NAME, true) ); VipM_Limits_RegisterTypeEvent("Ip", Limit_OnCheck, "@DefaultObjects_Limit_Ip_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc index 8271523..898b0ee 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/LifeTime.inc @@ -7,8 +7,8 @@ static Float:PlayerSpawnTime[MAX_PLAYERS + 1] = {0.0, ...}; DefaultObjects_Limit_LifeTime_Register() { VipM_Limits_RegisterType("LifeTime", true, false); VipM_Limits_AddParamsEx("LifeTime", - "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, - "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false + PCParam("Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME), + PCParam("Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME) ); VipM_Limits_RegisterTypeEvent("LifeTime", Limit_OnCheck, "@DefaultObjects_Limit_LifeTime_OnCheck"); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc index 866ed86..95ddab3 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Logic.inc @@ -4,25 +4,25 @@ DefaultObjects_Limit_Logic_Register() { VipM_Limits_RegisterType("Logic-OR", false, false); VipM_Limits_AddParamsEx("Logic-OR", - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true) ); VipM_Limits_RegisterTypeEvent("Logic-OR", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnOrCheck"); VipM_Limits_RegisterType("Logic-XOR", false, false); VipM_Limits_AddParamsEx("Logic-XOR", - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true) ); VipM_Limits_RegisterTypeEvent("Logic-XOR", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnXorCheck"); VipM_Limits_RegisterType("Logic-AND", false, false); VipM_Limits_AddParamsEx("Logic-AND", - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true) ); VipM_Limits_RegisterTypeEvent("Logic-AND", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnAndCheck"); VipM_Limits_RegisterType("Logic-NOT", false, false); VipM_Limits_AddParamsEx("Logic-NOT", - "Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true + PCParam("Limits", VIPM_PARAM_TYPE_LIMITS_NAME, true) ); VipM_Limits_RegisterTypeEvent("Logic-NOT", Limit_OnCheck, "@DefaultObjects_Limit_Logic_OnNotCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc index e22ee67..63f3402 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Map.inc @@ -8,10 +8,10 @@ new RealCurrentMapName[32]; DefaultObjects_Limit_Map_Register() { VipM_Limits_RegisterType("Map", true, false); VipM_Limits_AddParamsEx("Map", - "Map", DEFAULT_PARAMS_SHORT_STR_NAME, false, - "Regexp", DEFAULT_PARAMS_REGEXP_NAME, false, - "Real", DEFAULT_PARAMS_BOOL_NAME, false, - "Prefix", DEFAULT_PARAMS_BOOL_NAME, false + PCParam("Map", DEFAULT_PARAMS_SHORT_STR_NAME), + PCParam("Regexp", DEFAULT_PARAMS_REGEXP_NAME), + PCParam("Real", DEFAULT_PARAMS_BOOL_NAME), + PCParam("Prefix", DEFAULT_PARAMS_BOOL_NAME) ); VipM_Limits_RegisterTypeEvent("Map", Limit_OnCheck, "@DefaultObjects_Limit_Map_OnCheck"); diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc index a444a3a..45aa1c8 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Name.inc @@ -6,7 +6,7 @@ DefaultObjects_Limit_Name_Register() { VipM_Limits_RegisterType("Name", true, false); VipM_Limits_AddParamsEx("Name", - "Name", DEFAULT_PARAMS_SHORT_STR_NAME, true + PCParam("Name", DEFAULT_PARAMS_SHORT_STR_NAME, true) ); VipM_Limits_RegisterTypeEvent("Name", Limit_OnCheck, "@DefaultObjects_Limit_Name_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc index fc71201..202c479 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Round.inc @@ -6,8 +6,8 @@ DefaultObjects_Limit_Round_Register() { VipM_Limits_RegisterType("Round", false, false); VipM_Limits_AddParamsEx("Round", - "Min", DEFAULT_PARAMS_INT_NAME, false, - "Max", DEFAULT_PARAMS_INT_NAME, false + PCParam("Min", DEFAULT_PARAMS_INT_NAME), + PCParam("Max", DEFAULT_PARAMS_INT_NAME) ); VipM_Limits_RegisterTypeEvent("Round", Limit_OnCheck, "@DefaultObjects_Limit_Round_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc index 64c170e..e724634 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/RoundTime.inc @@ -5,8 +5,8 @@ DefaultObjects_Limit_RoundTime_Register() { VipM_Limits_RegisterType("RoundTime", false, false); VipM_Limits_AddParamsEx("RoundTime", - "Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false, - "Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME, false + PCParam("Min", DEFAULT_PARAMS_TIME_INTERVAL_NAME), + PCParam("Max", DEFAULT_PARAMS_TIME_INTERVAL_NAME) ); VipM_Limits_RegisterTypeEvent("RoundTime", Limit_OnCheck, "@DefaultObjects_Limit_RoundTime_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc index 12610d4..cef7c77 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/SteamId.inc @@ -7,7 +7,7 @@ static PlayerSteamIds[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH]; DefaultObjects_Limit_SteamId_Register() { VipM_Limits_RegisterType("SteamId", true, false); VipM_Limits_AddParamsEx("SteamId", - "SteamId", DEFAULT_PARAMS_SHORT_STR_NAME, true + PCParam("SteamId", DEFAULT_PARAMS_SHORT_STR_NAME, true) ); VipM_Limits_RegisterTypeEvent("SteamId", Limit_OnCheck, "@DefaultObjects_Limit_SteamId_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc index 8e2d9d5..799aba0 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/Time.inc @@ -5,8 +5,8 @@ DefaultObjects_Limit_Time_Register() { VipM_Limits_RegisterType("Time", false, false); VipM_Limits_AddParamsEx("Time", - "Before", DEFAULT_PARAMS_TIME_NAME, false, - "After", DEFAULT_PARAMS_TIME_NAME, false + PCParam("Before", DEFAULT_PARAMS_TIME_NAME), + PCParam("After", DEFAULT_PARAMS_TIME_NAME) ); VipM_Limits_RegisterTypeEvent("Time", Limit_OnCheck, "@DefaultObjects_Limit_Time_OnCheck"); } diff --git a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc index 9e64a10..94a1c7d 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/Limit/WeekDay.inc @@ -6,7 +6,7 @@ DefaultObjects_Limit_WeekDay_Register() { VipM_Limits_RegisterType("WeekDay", false, false); VipM_Limits_AddParamsEx("WeekDay", - "Day", DEFAULT_PARAMS_WEEK_DAY_NAME, true + PCParam("Day", DEFAULT_PARAMS_WEEK_DAY_NAME, true) ); VipM_Limits_RegisterTypeEvent("WeekDay", Limit_OnCheck, "@DefaultObjects_Limit_WeekDay_OnCheck"); } From f0b186ce3cbe705db890296f6f7bb75e5663c789 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Fri, 10 Apr 2026 17:56:35 +0300 Subject: [PATCH 102/108] Specify deps install action version (instead master) --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 10baf5d..0b918f4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -70,7 +70,7 @@ jobs: echo "${OUTPUT_VAR_NAME}=$(pwd)/addons/amxmodx/scripting/include" >> $GITHUB_ENV - - uses: AmxxModularEcosystem/install-amxmodx-deps@master + - uses: AmxxModularEcosystem/install-amxmodx-deps@v1 with: deps_list: ${{ env.DEPS_LIST }} output_var_name: DEPS_COMPILER_ARGS From cba5406bc09cee0a5d18dac222e25179dc364271 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN <42887370+ArKaNeMaN@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:59:53 +0300 Subject: [PATCH 103/108] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 970ff9e..ba46538 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Требования -- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.3.2](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.3.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.4.0](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.3.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). - [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). - [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). From 521e22eaa25e42c4dd0cb93cce862e09f784566a Mon Sep 17 00:00:00 2001 From: ArKaNeMaN <42887370+ArKaNeMaN@users.noreply.github.com> Date: Fri, 10 Apr 2026 18:00:04 +0300 Subject: [PATCH 104/108] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba46538..7a5cce4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Требования -- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.4.0](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.3.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.4.0](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.4.0) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). - [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). - [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). From 96bb84f988d34fd0cb577bea45cbe73cb15369f1 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Thu, 28 May 2026 17:43:52 +0300 Subject: [PATCH 105/108] Fix limits init for params --- amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc | 4 ++++ amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc | 2 ++ amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc | 4 ++++ .../scripting/VipM/DefaultObjects/ParamType/ModuleType.inc | 2 ++ 4 files changed, 12 insertions(+) diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc index b6d0f5b..6fb4a47 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limit.inc @@ -3,11 +3,15 @@ #include #include +#include "VipM/Core/Objects/Limits/Unit" + DefaultObjects_ParamType_Limit_Register() { ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMIT_NAME, "@DefaultObjects_ParamType_Limit_OnRead"); } bool:@DefaultObjects_ParamType_Limit_OnRead(const JSON:valueJson) { + LimitUnit_Init(); + new T_LimitUnit:limit = VipM_Limits_ReadFromJson(valueJson); if (limit == Invalid_LimitUnit) { diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc index 5e631ad..46d6892 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/LimitType.inc @@ -10,6 +10,8 @@ DefaultObjects_ParamType_LimitType_Register() { } bool:@DefaultObjects_ParamType_LimitType_OnRead(const JSON:valueJson) { + LimitType_Init(); + new typeName[VIPM_LIMITS_TYPE_NAME_MAX_LEN]; PCSingle_ShortString(valueJson, typeName, charsmax(typeName)); trim(typeName); diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc index 6eba2b7..3c6d69d 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/Limits.inc @@ -3,11 +3,15 @@ #include #include +#include "VipM/Core/Objects/Limits/Unit" + DefaultObjects_ParamType_Limits_Register() { ParamsController_RegSimpleType(VIPM_PARAM_TYPE_LIMITS_NAME, "@DefaultObjects_ParamType_Limits_OnRead"); } @DefaultObjects_ParamType_Limits_OnRead(const JSON:valueJson) { + LimitUnit_Init(); + if (json_is_array(valueJson) && json_array_get_count(valueJson) < 1) { PCJson_LogForFile(valueJson, "WARNING", "Limits array is empty."); return false; diff --git a/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc b/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc index fd08e45..7c6aaf6 100644 --- a/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc +++ b/amxmodx/scripting/VipM/DefaultObjects/ParamType/ModuleType.inc @@ -10,6 +10,8 @@ DefaultObjects_ParamType_ModuleType_Register() { } bool:@DefaultObjects_ParamType_ModuleType_OnRead(const JSON:valueJson) { + ModuleType_Init(); + new typeName[VIPM_MODULES_TYPE_NAME_MAX_LEN]; PCSingle_ShortString(valueJson, typeName, charsmax(typeName)); trim(typeName); From 024ceb0a43c8ff85b0a24563808e1d05dbd16f20 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Thu, 28 May 2026 17:44:13 +0300 Subject: [PATCH 106/108] Bump version --- amxmodx/scripting/include/ItemsController.inc | 2 +- amxmodx/scripting/include/VipModular.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/amxmodx/scripting/include/ItemsController.inc b/amxmodx/scripting/include/ItemsController.inc index 828f496..8c61183 100644 --- a/amxmodx/scripting/include/ItemsController.inc +++ b/amxmodx/scripting/include/ItemsController.inc @@ -7,7 +7,7 @@ #include #include -#define IC_VERSION "1.0.0-rc4f1" +#define IC_VERSION "1.0.0-rc4f2" stock const IC_LIBRARY[] = "items-controller"; stock const IC_VERSION_CVAR[] = "ic_version"; diff --git a/amxmodx/scripting/include/VipModular.inc b/amxmodx/scripting/include/VipModular.inc index 16d9027..65003a4 100644 --- a/amxmodx/scripting/include/VipModular.inc +++ b/amxmodx/scripting/include/VipModular.inc @@ -7,7 +7,7 @@ #include json stock const VIPM_LIBRARY[] = "VipModular"; -#define _VIPM_VERSION "5.0.0-rc4f1" +#define _VIPM_VERSION "5.0.0-rc4f2" stock const VIPM_VERSION[] = _VIPM_VERSION; #define _VIPM_PLUGIN_URL "https://github.com/AmxxModularEcosystem/VipModular" From b4638f11b83d5efac401b254bf0cd9e5b53131a5 Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sat, 30 May 2026 19:13:27 +0300 Subject: [PATCH 107/108] Use amxx-builder --- .build-config | 11 --- .github/workflows/CI.yml | 147 +++++++-------------------------------- .gitignore | 6 +- README.md | 2 +- amxbuild.yml | 27 +++++++ build-debug.bat | 4 -- build-release.bat | 4 -- build.bat | 96 +------------------------ config.bat | 84 ---------------------- 9 files changed, 57 insertions(+), 324 deletions(-) delete mode 100644 .build-config create mode 100644 amxbuild.yml delete mode 100644 build-debug.bat delete mode 100644 build-release.bat delete mode 100644 config.bat diff --git a/.build-config b/.build-config deleted file mode 100644 index 4a73098..0000000 --- a/.build-config +++ /dev/null @@ -1,11 +0,0 @@ -PACKAGE_NAME=VipModular -PACKAGE_README_USE=0 - -PACKAGE_COMPILED_PLUGINS_USE=1 -PACKAGE_COMPILED_PLUGINS_SAVE=0 - -PACKAGE_PLUINGS_LIST_USE=1 -PACKAGE_PLUINGS_LIST_POSTFIX=vipm -PACKAGE_PLUINGS_LIST_SAVE=0 - -PACKAGE_ASSETS_USE=0 diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0b918f4..d8cedf3 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -5,132 +5,38 @@ on: branches: [master, feature/**, fix/**] paths-ignore: - "**.md" - pull_request: types: [opened, reopened, synchronize] release: types: [published] -env: - PACKAGE_NAME: VipModular - STORE_README: 0 - PLUGINS_INI_GENERATE: 1 - PLUGINS_INI_POSTFIX: vipm - DEPS_LIST: | - AmxxModularEcosystem/ParamsController@1.4.0 - AmxxModularEcosystem/CommandAliases@1.0.1 - jobs: build: - name: "Build" + name: Build runs-on: ubuntu-latest outputs: - COMMIT_SHA: ${{ steps.declare_sha.outputs.COMMIT_SHA }} - SEMVER: ${{ steps.declare_sha.outputs.SEMVER }} + sha: ${{ steps.sha.outputs.SHORT }} + name: ${{ steps.build.outputs.name }} steps: - - name: Checkout - uses: actions/checkout@v4.1.1 - with: - fetch-depth: 0 - - - name: Parse SemVer string (release) - id: semver_parser - if: | - github.event_name == 'release' && - github.event.action == 'published' && - startsWith(github.ref, 'refs/tags/') - uses: booxmedialtd/ws-action-parse-semver@v1.4.7 - with: - input_string: ${{ github.ref }} - version_extractor_regex: 'refs\/tags\/(.*)$' - - - name: Declare SHA & package name - id: declare_sha - shell: bash - run: | - SHA=$(git rev-parse --short HEAD) - echo "COMMIT_SHA=$SHA" >> $GITHUB_OUTPUT - echo "SEMVER=${{ steps.semver_parser.outputs.fullversion }}" >> $GITHUB_OUTPUT - - - name: Setup latest ReAPI includes - env: - REPO: "rehlds/ReAPI" - OUTPUT_VAR_NAME: REAPI_INCLUDE_PATH - run: | - mkdir -p dep/reapi - cd dep/reapi - - curl \ - --silent \ - https://api.github.com/repos/$REPO/releases/latest | \ - jq .assets[0].browser_download_url -r | \ - xargs wget - - 7z x *.zip + - uses: actions/checkout@v4 - echo "${OUTPUT_VAR_NAME}=$(pwd)/addons/amxmodx/scripting/include" >> $GITHUB_ENV + - id: sha + run: echo "SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - uses: AmxxModularEcosystem/install-amxmodx-deps@v1 + - id: build + uses: AmxxModularEcosystem/amxx-builder@v1 with: - deps_list: ${{ env.DEPS_LIST }} - output_var_name: DEPS_COMPILER_ARGS + set: | + output.pack=false + output.dir=./artifact - - name: Setup AMXXPawn Compiler - uses: wopox1337/setup-amxxpawn@v1.1.0 + - uses: actions/upload-artifact@v4 with: - version: "1.10.5428" - - - name: Compile plugins - working-directory: amxmodx/scripting/ - env: - REAPI_INCLUDE: ${{ env.REAPI_INCLUDE_PATH }} - PLUGINS_INI_GENERATE: ${{ env.PLUGINS_INI_GENERATE }} - PLUGINS_INI_POSTFIX: ${{ env.PLUGINS_INI_POSTFIX }} - DEPS_COMPILER_ARGS: ${{ env.DEPS_COMPILER_ARGS }} - run: | - compile() { - sourcefile=$1 - amxxfile="$(echo $sourcefile | sed -e 's/\.sma$/.amxx/')" - output_path="../plugins/$amxxfile" - - mkdir -p $(dirname $output_path) - - echo "Compiling $sourcefile... " - amxxpc $sourcefile -o"$output_path" \ - -i"include" \ - -i"$REAPI_INCLUDE" \ - $DEPS_COMPILER_ARGS \ - GITHUB_ACTIONS_USED=1 - - if [ ! -z "${PLUGINS_INI_GENERATE}" ]; then - plugin_ini_path="../configs/plugins-${PLUGINS_INI_POSTFIX}.ini" - touch $plugin_ini_path - echo $amxxfile >> $plugin_ini_path - fi - } - export -f compile - - find . -type f -name "*.sma" -exec bash -c 'compile "$0"' {} \; - - - name: Move files - env: - STORE_README: ${{ env.STORE_README }} - run: | - mkdir -p publish/${{ env.PACKAGE_NAME }}/addons - mv amxmodx/ publish/${{ env.PACKAGE_NAME }}/addons - - if [ ! -z "${STORE_README}" ]; then - mv README.md publish/ - fi - - - name: Deploy artifact - uses: actions/upload-artifact@v4.3.1 - with: - name: ${{ env.PACKAGE_NAME }}-${{ steps.declare_sha.outputs.COMMIT_SHA }}-dev - path: publish/* + name: ${{ steps.build.outputs.name }}-${{ steps.sha.outputs.SHORT }}-dev + path: artifact/ publish: - name: "Publish release" + name: Publish release runs-on: ubuntu-latest needs: [build] if: | @@ -138,21 +44,16 @@ jobs: github.event.action == 'published' && startsWith(github.ref, 'refs/tags/') steps: - - name: Download artifact - uses: actions/download-artifact@v4.1.4 + - uses: actions/download-artifact@v4 with: - name: ${{ env.PACKAGE_NAME }}-${{ needs.build.outputs.COMMIT_SHA }}-dev + name: ${{ needs.build.outputs.name }}-${{ needs.build.outputs.sha }}-dev + path: artifact/ - - name: Packaging binaries - id: packaging - run: 7z a -mm=Deflate -mfb=258 -mpass=15 -r ${{ env.PACKAGE_NAME }}-${{ needs.build.outputs.SEMVER }}.zip + - name: Package for release + run: | + cd artifact + zip -r "../${{ needs.build.outputs.name }}-${{ github.ref_name }}.zip" . - - name: Publish artifacts - uses: softprops/action-gh-release@v2.0.4 - id: publish-job - if: | - startsWith(github.ref, 'refs/tags/') && - steps.packaging.outcome == 'success' + - uses: softprops/action-gh-release@v2 with: - files: | - *.zip + files: "${{ needs.build.outputs.name }}-*.zip" diff --git a/.gitignore b/.gitignore index 40b0a40..3ac5806 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ *.amxx *.zip -.build -plugins-*.ini +.env +.amxb-cache .claude +build +dist diff --git a/README.md b/README.md index 7a5cce4..4e3834a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Требования -- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.4.0](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.4.0) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). +- [ParamsController](https://github.com/AmxxModularEcosystem/ParamsController) версии [1.4.2](https://github.com/AmxxModularEcosystem/ParamsController/releases/tag/1.4.2) или [выше](https://github.com/AmxxModularEcosystem/ParamsController/releases/latest). - [CommandAliases](https://github.com/AmxxModularEcosystem/CommandAliases) версии [1.0.1](https://github.com/AmxxModularEcosystem/CommandAliases/releases/tag/1.0.1-fix1) или [выше](https://github.com/AmxxModularEcosystem/CommandAliases/releases/latest). - [ReAPI](https://github.com/rehlds/ReAPI) версии [5.24.0.300](https://github.com/rehlds/ReAPI/releases/tag/5.24.0.300) или [выше](https://github.com/rehlds/ReAPI/releases/latest). diff --git a/amxbuild.yml b/amxbuild.yml new file mode 100644 index 0000000..13f1cb8 --- /dev/null +++ b/amxbuild.yml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/AmxxModularEcosystem/amxx-builder/master/schema/amxbuild.schema.json + +name: VipModular + +amxmodx: + version: "1.10.5428" + +deps: + - AmxxModularEcosystem/ParamsController@1.4.2 + - AmxxModularEcosystem/CommandAliases@1.0.1 + - repo: rehlds/ReAPI + ref: 5.29.0.358 + source: release + include_path: addons/amxmodx/scripting/include + +plugins_ini_postfix: vipm + +output: + dir: ./ + archive_name: "{name}.zip" + amxmodx_path: "{name}/addons/amxmodx" + readme: true + generate_ini: true + +deploy: + exclude: + - addons/amxmodx/configs/ \ No newline at end of file diff --git a/build-debug.bat b/build-debug.bat deleted file mode 100644 index c7e2ab3..0000000 --- a/build-debug.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off - -set PACKAGE_DEBUG=1 -call build diff --git a/build-release.bat b/build-release.bat deleted file mode 100644 index c310a15..0000000 --- a/build-release.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off - -set PACKAGE_RELEASE=1 -call build diff --git a/build.bat b/build.bat index 3b105ce..41dfc7b 100644 --- a/build.bat +++ b/build.bat @@ -1,97 +1,3 @@ @echo off -call config - -echo Copy includes to compiler... -if exist "%INCLUDES_PATH%" ( - call :copy %INCLUDES_PATH%\*, %AMXX_COMPILER_INCLUDES_PATH% -) - -echo Cleanup old compiled plugins... -call :deldir %COMPILER_OUTPUT_PATH% -call :deldir %AMXMODX_PATH%\plugins - -if not "%PACKAGE_COMPILED_PLUGINS_USE%" == "1" goto after-compile - -echo Prepare for compiling plugins... - -call :del %PLUGINS_LIST% -if "%PACKAGE_PLUINGS_LIST_USE%" == "1" ( - call :makedir %PLUGINS_LIST_PATH% - echo. 2>%PLUGINS_LIST% -) - -echo Compile plugins... - -call :makedir %COMPILER_OUTPUT_PATH% -cd %COMPILER_OUTPUT_PATH% -for /R %AMXMODX_PATH%\scripting %%F in (*.sma) do ( - echo. - echo Compile %%~nF: - - if "%PACKAGE_DEBUG%" == "1" ( - %AMXX_COMPILER_EXECUTABLE_PATH% DEBUG=1 %%F - ) else ( - %AMXX_COMPILER_EXECUTABLE_PATH% %%F - ) - - if errorlevel 1 ( - echo. - echo Plugin %%~nF compiled with error. - set /p q= - exit /b %errorlevel% - ) - - if "%PACKAGE_PLUINGS_LIST_USE%" == "1" ( - echo %%~nF.amxx>>%PLUGINS_LIST% - ) -) -cd %ROOT_PATH% -:after-compile - -echo Prepare files... -call :makedir %BUILD_AMXMODX_PATH% -call :copy "%AMXMODX_PATH%\*", "%BUILD_AMXMODX_PATH%" - -if "%PACKAGE_README_USE%" == "1" ( - call :copy "%README_FILE%", "%BUILD_ROOT_PATH%" -) - -if "%PACKAGE_ASSETS_USE%" == "1" ( - call :makedir %BUILD_ASSETS_PATH% - call :copy %ASSETS_PATH%\* %BUILD_ASSETS_PATH% -) - -echo Compress files to ZIP archive... -call :del %ZIP_FILE% -cd %BUILD_ROOT_PATH% -call :zip ./* %ZIP_FILE% -cd %ROOT_PATH% - -echo Cleanup temp files... -call :deldir %BUILD_ROOT_PATH% - -echo Build finished. - -exit 0 - -:makedir - if not exist %~1 mkdir %~1 -exit /b - -:deldir - if exist %~1 rd /S /q %~1 -exit /b - -:del - if exist %~1 del %~1 -exit /b - -:copy - powershell Copy-Item -Path %~1 -Destination %~2 -Recurse -Force -exit /b - -:zip - rem powershell Compress-Archive %~1 %~2 -Force - zip -r9 %~2 ./%~1 -exit /b \ No newline at end of file +amxb build \ No newline at end of file diff --git a/config.bat b/config.bat deleted file mode 100644 index 36b19b9..0000000 --- a/config.bat +++ /dev/null @@ -1,84 +0,0 @@ -@echo off - -echo Read build config: -set PACKAGE_NAME=Unnamed -set PACKAGE_AMXMODX_FOLDER=amxmodx -set PACKAGE_README_USE=0 - -set PACKAGE_ASSETS_USE=0 -set PACKAGE_ASSETS_FOLDER=assets - -set PACKAGE_COMPILED_PLUGINS_USE=1 -set PACKAGE_COMPILED_PLUGINS_SAVE=1 - -set PACKAGE_PLUINGS_LIST_USE=0 -set PACKAGE_PLUINGS_LIST_POSTFIX=unnamed -set PACKAGE_PLUINGS_LIST_SAVE=0 - -if not defined AMXX_COMPILER_DIR ( - set AMXX_COMPILER_DIR=C:\AmxModX\1.9.0 -) -if not defined AMXX_COMPILER_EXECUTABLE ( - set AMXX_COMPILER_EXECUTABLE=amxx190 -) -if not defined PACKAGE_DEBUG ( - set PACKAGE_DEBUG=0 -) - -for /f "delims== tokens=1,2" %%G in (.build-config) do set %%G=%%H -if exist (local.build-config) ( - for /f "delims== tokens=1,2" %%G in (local.build-config) do set %%G=%%H -) - -if "%PACKAGE_RELEASE%" == "1" ( - set PACKAGE_DEBUG=0 - set PACKAGE_COMPILED_PLUGINS_USE=0 - set PACKAGE_NAME=%PACKAGE_NAME%-release -) else if "%PACKAGE_DEBUG%" == "1" ( - set PACKAGE_NAME=%PACKAGE_NAME%-debug -) - -set AMXX_COMPILER_EXECUTABLE_PATH=%AMXX_COMPILER_DIR%\%AMXX_COMPILER_EXECUTABLE% - -set ROOT_PATH=%CD% -set AMXMODX_PATH=%ROOT_PATH%\%PACKAGE_AMXMODX_FOLDER% -set INCLUDES_PATH=%AMXMODX_PATH%\scripting\include -set README_FILE=%ROOT_PATH%\README.md -set ASSETS_PATH=%ROOT_PATH%\%PACKAGE_ASSETS_FOLDER% - -set BUILD_ROOT_PATH=%ROOT_PATH%\.build -set BUILD_PACKAGE_PATH=%BUILD_ROOT_PATH%\%PACKAGE_NAME% -set BUILD_AMXMODX_PATH=%BUILD_PACKAGE_PATH%\addons\amxmodx -set BUILD_ASSETS_PATH=%BUILD_PACKAGE_PATH% - -set AMXX_COMPILER_INCLUDES_PATH=%AMXX_COMPILER_DIR%\include - -set PLUGINS_LIST_PATH=%BUILD_AMXMODX_PATH%\configs -if "%PACKAGE_PLUINGS_LIST_SAVE%" == "1" ( - set PLUGINS_LIST_PATH=%AMXMODX_PATH%\configs -) -set PLUGINS_LIST=%PLUGINS_LIST_PATH%\plugins-%PACKAGE_PLUINGS_LIST_POSTFIX%.ini - -set COMPILER_OUTPUT_PATH=%BUILD_AMXMODX_PATH%\plugins -if "%PACKAGE_COMPILED_PLUGINS_SAVE%" == "1" ( - set COMPILER_OUTPUT_PATH=%AMXMODX_PATH%\plugins -) - -set ZIP_FILE=%ROOT_PATH%\%PACKAGE_NAME%.zip - - -echo - PACKAGE_NAME = %PACKAGE_NAME% -echo - PACKAGE_README_USE = %PACKAGE_PLUINGS_LIST_USE% - -echo - PACKAGE_COMPILED_PLUGINS_USE = %PACKAGE_COMPILED_PLUGINS_USE% -echo - PACKAGE_COMPILED_PLUGINS_SAVE = %PACKAGE_COMPILED_PLUGINS_SAVE% - -echo - PACKAGE_PLUINGS_LIST_USE = %PACKAGE_PLUINGS_LIST_USE% -echo - PACKAGE_PLUINGS_LIST_POSTFIX = %PACKAGE_PLUINGS_LIST_POSTFIX% -echo - PACKAGE_PLUINGS_LIST_SAVE = %PACKAGE_PLUINGS_LIST_SAVE% - -echo - AMXX_COMPILER_DIR = %AMXX_COMPILER_DIR% -echo - AMXX_COMPILER_EXECUTABLE = %AMXX_COMPILER_EXECUTABLE% -echo. -echo - PACKAGE_DEBUG = %PACKAGE_DEBUG% -echo. From 8c15ede6e11ba120633292a88ee0326ec665200c Mon Sep 17 00:00:00 2001 From: ArKaNeMaN Date: Sun, 31 May 2026 10:46:43 +0300 Subject: [PATCH 108/108] Update manifest for builder v1.3 --- amxbuild.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/amxbuild.yml b/amxbuild.yml index 13f1cb8..d654c98 100644 --- a/amxbuild.yml +++ b/amxbuild.yml @@ -16,12 +16,8 @@ deps: plugins_ini_postfix: vipm output: - dir: ./ - archive_name: "{name}.zip" - amxmodx_path: "{name}/addons/amxmodx" - readme: true generate_ini: true deploy: exclude: - - addons/amxmodx/configs/ \ No newline at end of file + - addons/amxmodx/configs/