diff --git a/gamedata/modules.games/game.cstrike.txt b/gamedata/modules.games/game.cstrike.txt index d1a0f7c0..fb44cd70 100644 --- a/gamedata/modules.games/game.cstrike.txt +++ b/gamedata/modules.games/game.cstrike.txt @@ -99,5 +99,338 @@ } } } + + "#default" + { + "CommandsAliases" + { + "Common" + { + "p228" + { + "itemid" "1" // CSW/I_P228 + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "scout" + { + "itemid" "3" // CSW/I_SCOUT + "classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE + } + "xm1014" + { + "itemid" "5" // CSW/I_XM1014 + "classid" "5" // CS_WEAPONCLASS_SHOTGUN + } + "mac10" + { + "itemid" "7" // CSW/I_MAC10 + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "aug" + { + "itemid" "8" // CSW/I_AUG + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "elites" + { + "itemid" "10" // CSW/I_ELITE + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "fn57" + { + "itemid" "11" // CSW/I_FIVESEVEN + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "ump45" + { + "itemid" "12" // CSW/I_UMP45 + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "sg550" + { + "itemid" "13" // CSW/I_SG550 + "classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE + } + "galil" + { + "itemid" "14" // CSW/I_GALIL + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "famas" + { + "itemid" "15" // CSW/I_FAMAS + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "usp" + { + "itemid" "16" // CSW/I_USP + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "glock" + { + "itemid" "17" // CSW/I_GLOCK18 + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "awp" + { + "itemid" "18" // CSW/I_AWP + "classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE + } + "mp5" + { + "itemid" "19" // CSW/I_MP5NAVY + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "m249" + { + "itemid" "20" // CSW/I_M249 + "classid" "6" // CS_WEAPONCLASS_MACHINEGUN + } + "m3" + { + "itemid" "21" // CSW/I_M3 + "classid" "5" // CS_WEAPONCLASS_SHOTGUN + } + "m4a1" + { + "itemid" "22" // CSW/I_M4A1 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "tmp" + { + "itemid" "23" // CSW/I_TMP + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "g3sg1" + { + "itemid" "24" // CSW/I_G3SG1 + "classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE + } + "deagle" + { + "itemid" "26" // CSW/I_DEAGLE + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "sg552" + { + "itemid" "27" // CSW/I_SG552 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "ak47" + { + "itemid" "28" // CSW/I_AK47 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "p90" + { + "itemid" "30" // CSW/I_P90 + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "fiveseven" + { + "itemid" "11" // CSW/I_FIVESEVEN + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + } + + "Weapon" + { + "grenade" + { + "itemid" "4" // CSW/I_HEGRENADE + "classid" "3" // CS_WEAPONCLASS_GRENADE + } + "hegrenade" + { + "itemid" "4" // CSW/I_HEGRENADE + "classid" "3" // CS_WEAPONCLASS_GRENADE + } + "c4" + { + "itemid" "6" // CSW/I_C4 + "classid" "3" // CS_WEAPONCLASS_GRENADE + } + "elite" + { + "itemid" "10" // CSW/I_ELITE + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "glock18" + { + "itemid" "17" // CSW/I_GLOCK18 + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "mp5navy" + { + "itemid" "19" // CSW/I_MP5NAVY + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "knife" + { + "itemid" "29" // CSW/I_KNIFE + "classid" "1" // CS_WEAPONCLASS_KNIFE + } + } + + "Buy" + { + "228compact" + { + "itemid" "1" // CSW/I_P228 + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "autoshotgun" + { + "itemid" "5" // CSW/I_XM1014 + "classid" "5" // CS_WEAPONCLASS_SHOTGUN + } + "bullpup" + { + "itemid" "8" // CSW/I_AUG + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "sg550" + { + "itemid" "13" // CSW/I_SG550 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "krieg550" + { + "itemid" "13" // CSW/I_SG550 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "defender" + { + "itemid" "14" // CSW/I_GALIL + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "clarion" + { + "itemid" "15" // CSW/I_FAMAS + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "km45" + { + "itemid" "16" // CSW/I_USP + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "9x19mm" + { + "itemid" "17" // CSW/I_GLOCK18 + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "magnum" + { + "itemid" "18" // CSW/I_AWP + "classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE + } + "smg" + { + "itemid" "19" // CSW/I_MP5NAVY + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "12gauge" + { + "itemid" "21" // CSW/I_M3 + "classid" "5" // CS_WEAPONCLASS_SHOTGUN + } + "mp" + { + "itemid" "23" // CSW/I_TMP + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + "d3au1" + { + "itemid" "24" // CSW/I_G3SG1 + "classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE + } + "nighthawk" + { + "itemid" "26" // CSW/I_DEAGLE + "classid" "2" // CS_WEAPONCLASS_PISTOL + } + "krieg552" + { + "itemid" "27" // CSW/I_SG552 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "cv47" + { + "itemid" "28" // CSW/I_AK47 + "classid" "7" // CS_WEAPONCLASS_RIFLE + } + "c90" + { + "itemid" "30" // CSW/I_P90 + "classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN + } + } + + "BuyEquip" + { + "hegren" + { + "itemid" "4" // CSW/I_HEGRENADE + "classid" "3" // CS_WEAPONCLASS_GRENADE + } + "sgren" + { + "itemid" "9" // CSW/I_SMOKEGRENADE + "classid" "3" // CS_WEAPONCLASS_GRENADE + } + "flash" + { + "itemid" "25" // CSW/I_FLASHBANG + "classid" "3" // CS_WEAPONCLASS_GRENADE + } + "vest" + { + "itemid" "31" // CSW/I_VEST + "classname" "item_kevlar" + } + "vesthelm" + { + "itemid" "32" // CSW/I_VESTHELM + "classname" "item_assaultsuit" + } + "defuser" + { + "itemid" "33" // CSI_DEFUSER + "classname" "item_thighpack" + } + "nvgs" + { + "itemid" "34" // CSI_NVGS + + } + "shield" + { + "itemid" "35" // CSI_SHIELD + "classid" "2" // CS_WEAPONCLASS_PISTOL + "classname" "weapon_shield" + } + } + + "BuyAmmo" + { + "primammo" + { + "itemid" "36" // CSI_PRIAMMO + } + "secammo" + { + "itemid" "37" // CSI_SECAMMO + } + "buyammo1" + { + "itemid" "36" // CSI_PRIAMMO + } + "buyammo2" + { + "itemid" "37" // CSI_SECAMMO + } + } + } + } } diff --git a/modules/cstrike/cstrike/AMBuilder b/modules/cstrike/cstrike/AMBuilder index 0db59424..17ede82c 100644 --- a/modules/cstrike/cstrike/AMBuilder +++ b/modules/cstrike/cstrike/AMBuilder @@ -15,6 +15,7 @@ binary.sources = [ 'CstrikeHacks.cpp', 'CstrikeUtils.cpp', 'CstrikeUserMessages.cpp', + 'CstrikeitemsInfos.cpp', '../../../public/memtools/MemoryUtils.cpp', '../../../public/memtools/CDetour/detours.cpp', '../../../public/memtools/CDetour/asm/asm.c', diff --git a/modules/cstrike/cstrike/CstrikeDatas.h b/modules/cstrike/cstrike/CstrikeDatas.h index 6167f7f3..40b823ba 100644 --- a/modules/cstrike/cstrike/CstrikeDatas.h +++ b/modules/cstrike/cstrike/CstrikeDatas.h @@ -17,6 +17,7 @@ /** * Weapon Ids for use with CS_OnBuyAttempt(), CS_OnBuy(). */ +#define CSI_NONE CSW_NONE #define CSI_P228 CSW_P228 #define CSI_SCOUT CSW_SCOUT #define CSI_HEGRENADE CSW_HEGRENADE @@ -50,15 +51,17 @@ #define CSI_VESTHELM CSW_VESTHELM // Custom #define CSI_DEFUSER 33 // Custom #define CSI_NVGS 34 // Custom +#define CSI_SHIELD 35 // Custom - The value passed by the forward, more convenient for plugins. #define CSI_PRIAMMO 36 // Custom #define CSI_SECAMMO 37 // Custom -#define CSI_SHIELD 38 // Custom - The value passed by the forward, more convenient for plugins. +#define CSI_MAX_COUNT 38 #define BITS_PISTOLS (1< ItemAliasList; TypeDescription TeamDesc; TypeDescription MenuDesc; @@ -148,9 +149,11 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma } else // Handling buy via alias { - if (ItemAliasList.retrieve(command, &itemId)) + AliasInfo info; + + if (ItemsManager.GetAliasInfosFromBuy(command, &info)) { - CurrentItemId = itemId; + CurrentItemId = info.itemid; } } } @@ -319,8 +322,6 @@ void CtrlDetours_ClientCommand(bool set) { ClientCommandDetour->Destroy(); } - - ItemAliasList.clear(); } } @@ -330,59 +331,6 @@ void ToggleDetour_ClientCommands(bool enable) { (enable) ? ClientCommandDetour->EnableDetour() : ClientCommandDetour->DisableDetour(); } - - if (enable) - { - // Build the item alias list. - // Used in ClientCommand to check and get fastly item id from alias name. - typedef struct - { - const char *alias; - int id; - - } itemBuyAliasInfo; - - itemBuyAliasInfo aliasToId[] = - { - { "p228" , CSI_P228 }, { "228compact" , CSI_P228 }, - { "scout" , CSI_SCOUT }, { "hegren" , CSI_HEGRENADE }, - { "xm1014" , CSI_XM1014 }, { "autoshotgun", CSI_XM1014 }, - { "mac10" , CSI_MAC10 }, { "aug" , CSI_AUG }, - { "bullpup" , CSI_AUG }, { "sgren" , CSI_SMOKEGRENADE }, - { "elites" , CSI_ELITE }, { "fn57" , CSI_FIVESEVEN }, - { "fiveseven" , CSI_FIVESEVEN }, { "ump45" , CSI_UMP45 }, - { "sg550" , CSI_SG550 }, { "krieg550" , CSI_SG550 }, - { "galil" , CSI_GALIL }, { "defender" , CSI_GALIL }, - { "famas" , CSI_FAMAS }, { "clarion" , CSI_FAMAS }, - { "usp" , CSI_USP }, { "km45" , CSI_USP }, - { "glock" , CSI_GLOCK18 }, { "9x19mm" , CSI_GLOCK18 }, - { "awp" , CSI_AWP }, { "magnum" , CSI_AWP }, - { "mp5" , CSI_MP5NAVY }, { "smg" , CSI_MP5NAVY }, - { "m249" , CSI_M249 }, { "m3" , CSI_M3 }, - { "12gauge" , CSI_M3 }, { "m4a1" , CSI_M4A1 }, - { "tmp" , CSI_TMP }, { "mp" , CSI_TMP }, - { "g3sg1" , CSI_G3SG1 }, { "d3au1" , CSI_G3SG1 }, - { "flash" , CSI_FLASHBANG }, { "deagle" , CSI_DEAGLE }, - { "nighthawk" , CSI_DEAGLE }, { "sg552" , CSI_SG552 }, - { "krieg552" , CSI_SG552 }, { "ak47" , CSI_AK47 }, - { "cv47" , CSI_AK47 }, { "p90" , CSI_P90 }, - { "c90" , CSI_P90 }, { "vest" , CSI_VEST }, - { "vesthelm" , CSI_VESTHELM }, { "defuser" , CSI_DEFUSER }, - { "nvgs" , CSI_NVGS }, { "shield" , CSI_SHIELDGUN }, - { "buyammo1" , CSI_PRIAMMO }, { "primammo" , CSI_PRIAMMO }, - { "buyammo2" , CSI_SECAMMO }, { "secammo" , CSI_SECAMMO }, - { nullptr , 0 } - }; - - for (size_t i = 0; aliasToId[i].alias != nullptr; ++i) - { - ItemAliasList.insert(aliasToId[i].alias, aliasToId[i].id); - } - } - else - { - ItemAliasList.clear(); - } } @@ -443,8 +391,6 @@ void CtrlDetours_BuyCommands(bool set) { AddAccountDetour->Destroy(); } - - ItemAliasList.clear(); } } @@ -550,4 +496,4 @@ void InitGlobalVars() { MF_Log("sv global variable is not available"); } -} \ No newline at end of file +} diff --git a/modules/cstrike/cstrike/CstrikeHacks.h b/modules/cstrike/cstrike/CstrikeHacks.h index c7d91474..13404784 100644 --- a/modules/cstrike/cstrike/CstrikeHacks.h +++ b/modules/cstrike/cstrike/CstrikeHacks.h @@ -18,6 +18,7 @@ #include #include #include +#include "CstrikeDatas.h" void InitializeHacks(); void InitGlobalVars(); diff --git a/modules/cstrike/cstrike/CstrikeItemsInfos.cpp b/modules/cstrike/cstrike/CstrikeItemsInfos.cpp new file mode 100644 index 00000000..ad8c5532 --- /dev/null +++ b/modules/cstrike/cstrike/CstrikeItemsInfos.cpp @@ -0,0 +1,241 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +// +// Counter-Strike Module +// + +#include "CstrikeitemsInfos.h" + +CsItemInfo ItemsManager; + +#define PSTATE_NONE +#define PSTATE_ALIASES_TYPE 0 +#define PSTATE_ALIASES_ALIAS 1 +#define PSTATE_ALIASES_ALIAS_DEFS 2 + +CsItemInfo::CsItemInfo() + : + m_ParseState(0), + m_List(nullptr), + m_ListsRetrievedFromConfig(false) +{ +} + +CsItemInfo::~CsItemInfo() +{ + Clear(); +} + +void CsItemInfo::Clear() +{ + m_CommonAliasesList.clear(); + m_WeaponAliasesList.clear(); + m_BuyAliasesList.clear(); +} + +bool CsItemInfo::HasConfigError() +{ + return !m_ListsRetrievedFromConfig; +} + +SMCResult CsItemInfo::ReadSMC_NewSection(const SMCStates *states, const char *name) +{ + switch (m_ParseState) + { + case PSTATE_ALIASES_TYPE: + { + m_List = nullptr; + + if (!strcmp(name, "Common")) + { + m_List = &m_CommonAliasesList; + } + else if (!strcmp(name, "Weapon")) + { + m_List = &m_WeaponAliasesList; + } + else if (strstr(name, "Buy")) + { + m_List = &m_BuyAliasesList; + } + else + { + return SMCResult_HaltFail; + } + + m_ParseState = PSTATE_ALIASES_ALIAS; + break; + } + case PSTATE_ALIASES_ALIAS: + { + m_AliasInfo.clear(); + m_Alias = name; + + m_ParseState = PSTATE_ALIASES_ALIAS_DEFS; + break; + } + } + + return SMCResult_Continue; +} + +SMCResult CsItemInfo::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) +{ + switch (m_ParseState) + { + case PSTATE_ALIASES_ALIAS_DEFS: + { + if (!strcmp(key, "itemid")) + { + m_AliasInfo.itemid = atoi(value); + + if (m_AliasInfo.itemid < CSI_NONE || m_AliasInfo.itemid >= CSI_MAX_COUNT) + { + m_AliasInfo.itemid = CSI_NONE; + } + } + else if (!strcmp(key, "classid")) + { + m_AliasInfo.classid = atoi(value); + + if (m_AliasInfo.classid < CS_WEAPONCLASS_NONE || m_AliasInfo.classid >= CS_WEAPONCLASS_MAX_COUNT) + { + m_AliasInfo.classid = CS_WEAPONCLASS_NONE; + } + } + else if (!strcmp(key, "classname")) + { + m_AliasInfo.classname = value; + } + else + { + return SMCResult_HaltFail; + } + break; + } + } + + return SMCResult_Continue; +} + +SMCResult CsItemInfo::ReadSMC_LeavingSection(const SMCStates *states) +{ + switch (m_ParseState) + { + case PSTATE_ALIASES_ALIAS: + { + m_ParseState = PSTATE_ALIASES_TYPE; + break; + } + case PSTATE_ALIASES_ALIAS_DEFS: + { + m_List->replace(m_Alias.chars(), m_AliasInfo); + m_WeaponIdToClass[m_AliasInfo.itemid] = static_cast(m_AliasInfo.classid); + + m_AliasInfo.clear(); + + m_ParseState = PSTATE_ALIASES_ALIAS; + break; + } + } + + return SMCResult_Continue; +} + +void CsItemInfo::ReadSMC_ParseEnd(bool halted, bool failed) +{ + if (halted) + { + MF_Log("Invalid or missing key in \"%s\" section. Please check your gamedata files.", m_Alias.chars()); + return; + } + + m_ListsRetrievedFromConfig = true; +} + +bool CsItemInfo::GetAliasInfos(const char *alias, AliasInfo *info) +{ + if (GetAliasInfosFromBuy(alias, info) || m_WeaponAliasesList.retrieve(alias, info)) + { + return true; + } + + return false; +} + +bool CsItemInfo::GetAliasInfosFromBuy(const char *alias, AliasInfo *info) +{ + if (m_CommonAliasesList.retrieve(alias, info) || m_BuyAliasesList.retrieve(alias, info)) + { + return true; + } + + return false; +} + +bool CsItemInfo::GetAliasInfosFromName(const char *name, AliasInfo *info) +{ + static const char prefix_weapon[] = "weapon_"; + static const char prefix_item[] = "item_"; + + const char *alias = name; + + if (strstr(name, prefix_weapon) && strcmp(name + sizeof(prefix_weapon) - 1, "shield")) + { + for (size_t id = 0; id < ARRAYSIZE(WeaponNameList); ++id) + { + if (!strcmp(name, WeaponNameList[id])) + { + info->classname = name; + info->itemid = id; + info->classid = WeaponIdToClass(id); + + return true; + } + } + + alias = name + sizeof(prefix_weapon) - 1; + } + else if (strstr(name, prefix_item)) + { + for (auto iter = m_BuyAliasesList.iter(); !iter.empty(); iter.next()) + { + if (iter->value.classname.length() && !iter->value.classname.compare(name)) + { + *info = iter->value; + return true; + } + } + + alias = name + sizeof(prefix_item) - 1; + } + + if (GetAliasInfos(alias, info)) + { + return true; + } + + return false; +} + +CsWeaponClassType CsItemInfo::WeaponIdToClass(int id) +{ + if ((id > CSI_NONE && id <= CSI_P90) || id == CSI_SHIELD || id == CSI_SHIELDGUN) + { + if (id == CSI_SHIELDGUN) + { + id = CSI_SHIELD; + } + + return m_WeaponIdToClass[id]; + } + + return CS_WEAPONCLASS_NONE; +} \ No newline at end of file diff --git a/modules/cstrike/cstrike/CstrikeItemsInfos.h b/modules/cstrike/cstrike/CstrikeItemsInfos.h new file mode 100644 index 00000000..6df10eb1 --- /dev/null +++ b/modules/cstrike/cstrike/CstrikeItemsInfos.h @@ -0,0 +1,87 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +// +// Counter-Strike Module +// + +#ifndef _CSTRIKE_WEAPONS_INFOS_H_ +#define _CSTRIKE_WEAPONS_INFOS_H_ + +#include "CstrikeDatas.h" +#include +#include + +struct AliasInfo +{ + AliasInfo() + { + clear(); + } + + void clear() + { + itemid = CSI_NONE; + classid = CS_WEAPONCLASS_NONE; + } + + int itemid; + int classid; + ke::AString classname; +}; + +class CsItemInfo : public ITextListener_SMC +{ + public: + + CsItemInfo(); + ~CsItemInfo(); + + public: + + void Clear(); + bool HasConfigError(); + + public: + + SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); + SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); + SMCResult ReadSMC_LeavingSection(const SMCStates *states); + void ReadSMC_ParseEnd(bool halted, bool failed); + + public: + + bool GetAliasInfos(const char *alias, AliasInfo *info); + bool GetAliasInfosFromBuy(const char *alias, AliasInfo *info); + bool GetAliasInfosFromName(const char *classname, AliasInfo *info); + + CsWeaponClassType WeaponIdToClass(int id); + + private: // Retrieved datas + + typedef StringHashMap AliasMap; + + AliasMap m_CommonAliasesList; + AliasMap m_WeaponAliasesList; + AliasMap m_BuyAliasesList; + + CsWeaponClassType m_WeaponIdToClass[CSI_MAX_COUNT]; + + private: // Config parsing + + int m_ParseState; + AliasMap* m_List; + ke::AString m_Alias; + AliasInfo m_AliasInfo; + bool m_ListsRetrievedFromConfig; +}; + +extern CsItemInfo ItemsManager; + +#endif // _CSTRIKE_WEAPONS_INFOS_H_ diff --git a/modules/cstrike/cstrike/CstrikeMain.cpp b/modules/cstrike/cstrike/CstrikeMain.cpp index 1313bc36..8339f60b 100644 --- a/modules/cstrike/cstrike/CstrikeMain.cpp +++ b/modules/cstrike/cstrike/CstrikeMain.cpp @@ -41,6 +41,8 @@ void OnAmxxAttach() char error[256]; error[0] = '\0'; + ConfigManager->AddUserConfigHook("CommandsAliases", &ItemsManager); + if (!ConfigManager->LoadGameConfigFile("modules.games", &MainConfig, error, sizeof(error)) && error[0] != '\0') { MF_Log("Could not read module.games gamedata: %s", error); @@ -83,8 +85,21 @@ void OnPluginsLoaded() g_pFunctionTable->pfnStartFrame = nullptr; } +void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax) +{ + // Used to catch WeaponList message at map change. + EnableMessageHooks(); +} + +void OnServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax) +{ + DisableMessageHooks(); +} + void OnAmxxDetach() { + ConfigManager->RemoveUserConfigHook("CommandsAliases", &ItemsManager); + ConfigManager->CloseGameConfigFile(MainConfig); ConfigManager->CloseGameConfigFile(CommonConfig); diff --git a/modules/cstrike/cstrike/CstrikeNatives.cpp b/modules/cstrike/cstrike/CstrikeNatives.cpp index e1419a98..62015acb 100644 --- a/modules/cstrike/cstrike/CstrikeNatives.cpp +++ b/modules/cstrike/cstrike/CstrikeNatives.cpp @@ -20,6 +20,7 @@ #include bool NoKifesMode = false; +char WeaponNameList[MAX_WEAPONS][64]; // native cs_set_user_money(index, money, flash = 1); static cell AMX_NATIVE_CALL cs_set_user_money(AMX *amx, cell *params) @@ -1739,6 +1740,77 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params) return 0; } +// native any:cs_get_item_id(const name[], &CsWeaponClassType:classid = CS_WEAPONCLASS_NONE); +static cell AMX_NATIVE_CALL cs_get_item_id(AMX* amx, cell* params) +{ + if (ItemsManager.HasConfigError()) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_item_id() is disabled"); + return 0; + } + + int length; + char *name = MF_GetAmxString(amx, params[1], 0, &length); + cell *classid = MF_GetAmxAddr(amx, params[2]); + + if (length) + { + AliasInfo info; + + if (ItemsManager.GetAliasInfosFromName(name, &info)) + { + *classid = info.classid; + return info.itemid; + } + } + + return CSI_NONE; +} + +// native bool:cs_get_translated_item_alias(const alias[], itemname[], maxlength); +static cell AMX_NATIVE_CALL cs_get_translated_item_alias(AMX* amx, cell* params) +{ + if (ItemsManager.HasConfigError()) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_translated_item_alias() is disabled"); + return 0; + } + + int length; + const char *alias = MF_GetAmxString(amx, params[1], 0, &length); + const char *name = alias; + AliasInfo info; + + if (length && ItemsManager.GetAliasInfos(alias, &info) && info.itemid != CSI_NONE) + { + switch (info.itemid) + { + case CSI_VEST: + case CSI_VESTHELM: + case CSI_DEFUSER: + case CSI_SHIELD: + { + // Special item_* defined in gamdata file as game + // doesn't give us really a way to know about their classname + // and I don't want to hard code them in module. + name = info.classname.chars(); + break; + } + default: + { + // weapon_* retrieved from WeaponList messages at map change. + name = WeaponNameList[info.itemid]; + break; + } + } + } + + MF_SetAmxString(amx, params[2], alias, params[3]); + + return info.itemid != CSI_NONE; +} + + AMX_NATIVE_INFO CstrikeNatives[] = { {"cs_set_user_money", cs_set_user_money}, @@ -1802,7 +1874,9 @@ AMX_NATIVE_INFO CstrikeNatives[] = {"cs_get_c4_defusing", cs_get_c4_defusing}, {"cs_set_c4_defusing", cs_set_c4_defusing}, {"cs_create_entity", cs_create_entity }, - {"cs_find_ent_by_class", cs_find_ent_by_class}, - + {"cs_find_ent_by_class", cs_find_ent_by_class}, + {"cs_get_item_id", cs_get_item_id}, + {"cs_get_translated_item_alias",cs_get_translated_item_alias}, + {"cs_get_weapon_info", cs_get_weapon_info}, {nullptr, nullptr} }; diff --git a/modules/cstrike/cstrike/CstrikeUserMessages.cpp b/modules/cstrike/cstrike/CstrikeUserMessages.cpp index 00c368f6..b290713e 100644 --- a/modules/cstrike/cstrike/CstrikeUserMessages.cpp +++ b/modules/cstrike/cstrike/CstrikeUserMessages.cpp @@ -16,9 +16,14 @@ #include "CstrikeUtils.h" #include "CstrikeHacks.h" #include "CstrikePlayer.h" +#include "CstrikeDatas.h" +#include bool ShouldBlock; bool ShouldBlockHLTV; +bool RetrieveWeaponName; +ke::AString CurrentWeaponName; +int ArgPosition; int MessageIdArmorType; int MessageIdHLTV; @@ -30,6 +35,7 @@ int MessageIdSetFOV; int MessageIdStatusIcon; int MessageIdTeamInfo; int MessageIdTextMsg; +int MessageIdWeaponList; struct UserMsg { @@ -49,6 +55,7 @@ UserMsg MessagesList[] = { "StatusIcon" , &MessageIdStatusIcon }, { "TeamInfo" , &MessageIdTeamInfo }, { "TextMsg" , &MessageIdTextMsg }, + { "WeaponList" , &MessageIdWeaponList }, { nullptr , nullptr } }; @@ -113,6 +120,13 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p } break; } + case MSG_INIT: + { + if (msg_type == MessageIdWeaponList) + { + RetrieveWeaponName = true; + } + } } if (ShouldBlockHLTV) @@ -123,12 +137,26 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p RETURN_META(MRES_IGNORED); } -void OnWriteByte(int iValue) +void OnWriteByte(int value) { if (ShouldBlock) { RETURN_META(MRES_SUPERCEDE); } + else if (RetrieveWeaponName && ++ArgPosition == 7 && value >= 0 && value < MAX_WEAPONS) + { + strncopy(WeaponNameList[value], CurrentWeaponName.chars(), sizeof(WeaponNameList[value])); + } + + RETURN_META(MRES_IGNORED); +} + +void OnWriteString(const char *value) +{ + if (RetrieveWeaponName) + { + CurrentWeaponName = value; + } RETURN_META(MRES_IGNORED); } @@ -140,6 +168,11 @@ void OnMessageEnd(void) ShouldBlock = false; RETURN_META(MRES_SUPERCEDE); } + else if (RetrieveWeaponName) + { + RetrieveWeaponName = false; + ArgPosition = 0; + } RETURN_META(MRES_IGNORED); } @@ -150,6 +183,15 @@ void EnableMessageHooks() { g_pengfuncsTable->pfnMessageBegin = OnMessageBegin; g_pengfuncsTable->pfnWriteByte = OnWriteByte; + g_pengfuncsTable->pfnWriteString = OnWriteString; g_pengfuncsTable->pfnMessageEnd = OnMessageEnd; } } + +void DisableMessageHooks() +{ + g_pengfuncsTable->pfnMessageBegin = nullptr; + g_pengfuncsTable->pfnWriteByte = nullptr; + g_pengfuncsTable->pfnWriteString = nullptr; + g_pengfuncsTable->pfnMessageEnd = nullptr; +} diff --git a/modules/cstrike/cstrike/CstrikeUserMessages.h b/modules/cstrike/cstrike/CstrikeUserMessages.h index 7c1a66ac..7541ad1a 100644 --- a/modules/cstrike/cstrike/CstrikeUserMessages.h +++ b/modules/cstrike/cstrike/CstrikeUserMessages.h @@ -26,5 +26,6 @@ extern int MessageIdTeamInfo; extern int MessageIdTextMsg; void EnableMessageHooks(); +void DisableMessageHooks(); #endif // CSTRIKE_USER_MESSAGES_H diff --git a/modules/cstrike/cstrike/moduleconfig.h b/modules/cstrike/cstrike/moduleconfig.h index 79b9eccd..6438f750 100644 --- a/modules/cstrike/cstrike/moduleconfig.h +++ b/modules/cstrike/cstrike/moduleconfig.h @@ -123,7 +123,7 @@ // #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */ // #define FN_ClientCommand ClientCommand /* pfnClientCommand() (wd) Player has sent a command (typed or from a bind) */ // #define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */ -// #define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */ +#define FN_ServerActivate OnServerActivate /* pfnServerActivate() (wd) Server is starting a new map */ // #define FN_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */ // #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */ // #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */ @@ -175,7 +175,7 @@ // #define FN_ClientPutInServer_Post ClientPutInServer_Post // #define FN_ClientCommand_Post ClientCommand_Post // #define FN_ClientUserInfoChanged_Post ClientUserInfoChanged_Post -// #define FN_ServerActivate_Post ServerActivate_Post +#define FN_ServerActivate_Post OnServerActivate_Post // #define FN_ServerDeactivate_Post ServerDeactivate_Post // #define FN_PlayerPreThink_Post PlayerPreThink_Post // #define FN_PlayerPostThink_Post PlayerPostThink_Post diff --git a/modules/cstrike/cstrike/msvc12/cstrike.vcxproj b/modules/cstrike/cstrike/msvc12/cstrike.vcxproj index f4fb687b..e15df551 100644 --- a/modules/cstrike/cstrike/msvc12/cstrike.vcxproj +++ b/modules/cstrike/cstrike/msvc12/cstrike.vcxproj @@ -151,12 +151,14 @@ + + diff --git a/modules/cstrike/cstrike/msvc12/cstrike.vcxproj.filters b/modules/cstrike/cstrike/msvc12/cstrike.vcxproj.filters index d7d54327..89db5505 100644 --- a/modules/cstrike/cstrike/msvc12/cstrike.vcxproj.filters +++ b/modules/cstrike/cstrike/msvc12/cstrike.vcxproj.filters @@ -59,6 +59,9 @@ Source Files + + Source Files + @@ -94,6 +97,9 @@ Header Files + + Header Files + diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 3649bd4a..8c769f6f 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -1025,6 +1025,43 @@ native cs_create_entity(const classname[]); */ native cs_find_ent_by_class(start_index, const classname[]); +/** + * Returns the item id associated with an item name and its aliases. + * + * @note The item name is case sensitive an can be with or without + * weapon_ and item_ prefixes. This can be a command alias as well. + * Values examples: ak47, weapon_ak47, kevlar, item_kevlar, vest, bullpup, ... + * + * @param name Alias or classname + * @param classid If item is a weapon, variable to store the associated + * weapon class id in (CS_WEAPONCLASS_* constants) + * + * @return Item id (CSI_* constants) + */ +native any:cs_get_item_id(const name[], &CsWeaponClassType:classid = CS_WEAPONCLASS_NONE); + +/** + * Returns an item name associated with a command alias. + * + * @note The alias is case sensitive. + * @note If not an alias to a weapon, buffer will be set with the original alias. + * + * @param alias Alias name + * @param itemname Buffer to store item name to + * @param maxlength Maximum buffer size + * + * @return True if alias is translated, false otherwise + */ +native bool:cs_get_translated_item_alias(const alias[], itemname[], maxlength); + +/** + * + */ +stock cs_get_weapon_class(weapon_id) +{ + +} + /** * Called when CS internally fires a command to a player. * diff --git a/plugins/include/cstrike_const.inc b/plugins/include/cstrike_const.inc index 8f2f46e6..6462997c 100644 --- a/plugins/include/cstrike_const.inc +++ b/plugins/include/cstrike_const.inc @@ -129,9 +129,10 @@ enum #define CSI_VESTHELM CSW_VESTHELM // Custom #define CSI_DEFUSER 33 // Custom #define CSI_NVGS 34 // Custom +#define CSI_SHIELD 35 // Custom - The value passed by the forward, more convenient for plugins. #define CSI_PRIAMMO 36 // Custom #define CSI_SECAMMO 37 // Custom -#define CSI_SHIELD 38 // Custom - The value passed by the forward, more convenient for plugins. +#define CSI_MAX_COUNT 38 /** * Player's movements constants.