diff --git a/dlls/cstrike/cstrike/AMBuilder b/dlls/cstrike/cstrike/AMBuilder index fc243e71..ec1ac464 100644 --- a/dlls/cstrike/cstrike/AMBuilder +++ b/dlls/cstrike/cstrike/AMBuilder @@ -3,6 +3,10 @@ import os.path binary = AMXX.MetaModule(builder, 'cstrike') +binary.compiler.defines += [ + 'HAVE_STDINT_H', +] + binary.sources = [ 'sdk/amxxmodule.cpp', 'amxx_api.cpp', diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index d64c773e..c1d138f1 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -64,6 +64,7 @@ #define OFFSET_INTERNALMODEL 126 + EXTRAOFFSET #define OFFSET_NVGOGGLES 129 + EXTRAOFFSET #define OFFSET_DEFUSE_PLANT 193 + EXTRAOFFSET + #define OFFSET_MENU 205 + EXTRAOFFSET #define OFFSET_VIP 209 + EXTRAOFFSET #define OFFSET_TK 216 + EXTRAOFFSET // 040926 #define OFFSET_HOSTAGEKILLS 217 + EXTRAOFFSET @@ -162,19 +163,19 @@ * CS_OnBuy forward */ #if defined(__linux__) - #define CS_IDENT_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri" - #define CS_IDENT_BUYITEM "_Z7BuyItemP11CBasePlayeri" - #define CS_IDENT_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" + #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" + #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" + #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" #define CS_IDENT_HIDDEN_STATE false #elif defined(__APPLE__) - #define CS_IDENT_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri" - #define CS_IDENT_BUYITEM "_Z7BuyItemP11CBasePlayeri" - #define CS_IDENT_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" + #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" + #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" + #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" #define CS_IDENT_HIDDEN_STATE true #elif defined(WIN32) - #define CS_IDENT_CANBUYTHIS "\\x53\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x2A\\x2A\\x57" - #define CS_IDENT_BUYITEM "\\x53\\x56\\x8B\\x2A\\x2A\\x2A\\xBB\\x2A\\x2A\\x2A\\x2A\\x57\\x53" - #define CS_IDENT_BUYGUNAMMO "\\x56\\x57\\x8B\\x2A\\x2A\\x2A\\x6A\\x2A\\x8B\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x84\\x2A\\x0F" + #define CS_IDENT_GIVENSHIELD "\\x56\\x8B\\x2A\\x57\\x33\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\xB0" + #define CS_IDENT_GIVENAMEDITEM "\\x8B\\x2A\\x2A\\x2A\\x56\\x57\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x2B" + #define CS_IDENT_ADDACCOUNT "\\x8B\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x03" #define CS_IDENT_HIDDEN_STATE false #endif @@ -347,4 +348,24 @@ enum CS_SET_AUGSG552_ZOOM, }; +typedef enum +{ + Menu_OFF, + Menu_ChooseTeam, + Menu_IGChooseTeam, + Menu_ChooseAppearance, + Menu_Buy, + Menu_BuyPistol, + Menu_BuyRifle, + Menu_BuyMachineGun, + Menu_BuyShotgun, + Menu_BuySubMachineGun, + Menu_BuyItem, + Menu_Radio1, + Menu_Radio2, + Menu_Radio3, + Menu_ClientBuy + +} Menu; + #endif // CSTRIKE_DATA_H \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index e7703597..d20a9d59 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -33,21 +33,27 @@ #include "CstrikeDatas.h" #include "CstrikeUtils.h" #include "CDetour/detours.h" +#include + +using namespace SourceMod; // hashmap void CtrlDetours_ClientCommand(bool set); void CtrlDetours_BuyCommands(bool set); -int g_CSCliCmdFwd = -1; -int g_CSBuyCmdFwd = -1; +int ForwardInternalCommand = -1; +int ForwardOnBuy = -1; +int ForwardOnBuyAttempt = -1; -int *g_UseBotArgs = NULL; -const char **g_BotArgs = NULL; +int *UseBotArgs = NULL; +const char **BotArgs = NULL; -CDetour *g_ClientCommandDetour = NULL; -CDetour *g_CanBuyThisDetour = NULL; -CDetour *g_BuyItemDetour = NULL; -CDetour *g_BuyGunAmmoDetour = NULL; +CDetour *ClientCommandDetour = NULL; +CDetour *GiveShieldDetour = NULL; +CDetour *GiveNamedItemDetour = NULL; +CDetour *AddAccountDetour = NULL; +int CurrentItemId = 0; +StringHashMap ItemAliasList; void InitializeHacks() { @@ -65,76 +71,170 @@ void ShutdownHacks() CtrlDetours_BuyCommands(false); } +#undef CMD_ARGV + +const char *CMD_ARGV(int i) +{ + if (*UseBotArgs) + { + if (i < 4) + { + return BotArgs[i]; + } + + return NULL; + } + + return g_engfuncs.pfnCmd_Argv(i); +} DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity) { - if (*g_UseBotArgs) - { - int client = ENTINDEX(pEdict); - const char *args = *g_BotArgs; + const char *command = CMD_ARGV(0); + + // A new command is triggered, reset variable, always. + CurrentItemId = 0; - if (MF_ExecuteForward(g_CSCliCmdFwd, static_cast(client), args) > 0) + // Purpose is to retrieve an item id based on alias name or selected item from menu, + // to be used in OnBuy* forwards. + if ((ForwardOnBuyAttempt != -1 || ForwardOnBuy != -1) && command && *command) + { + // Just for safety. + command = UTIL_StringToLower((char *)command); + + int itemId = 0; + + // Handling buy via menu. + if (!strcmp(command, "menuselect")) + { + int slot = atoi(CMD_ARGV(1)); + + if (slot > 0 && slot < 9) + { + static const int menuItemsTe[][9] = + { + /* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIMAMMO, CSI_SECAMMO, 0 }, + /* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_ELITE, 0, 0, 0 }, + /* Menu_BuyRifle */ { 0, CSI_GALI, CSI_AK47, CSI_SCOUT, CSI_SG552, CSI_AWP, CSI_G3SG1, 0, 0 }, + /* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 }, + /* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 }, + /* Menu_BuySubMachineGun */ { 0, CSI_MAC10, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 }, + /* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, 0, 0 } + }; + + static const int menuItemsCt[][9] = + { + /* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIMAMMO, CSI_SECAMMO, 0 }, + /* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_FIVESEVEN, 0, 0, 0 }, + /* Menu_BuyRifle */ { 0, CSI_FAMAS, CSI_SCOUT, CSI_M4A1, CSI_AUG, CSI_SG550, CSI_AWP, 0, 0 }, + /* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 }, + /* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 }, + /* Menu_BuySubMachineGun */ { 0, CSI_TMP, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 }, + /* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN } + }; + + int menuId = *((int *)pEdict->pvPrivateData + OFFSET_MENU); + if (menuId >= Menu_Buy && menuId <= Menu_BuyItem) + { + int team = *((int *)pEdict->pvPrivateData + OFFSET_TEAM); + switch (team) + { + case TEAM_T: itemId = menuItemsTe[menuId - 4][slot]; break; // -4 because array is zero-based and Menu_Buy* constants starts from 4. + case TEAM_CT:itemId = menuItemsCt[menuId - 4][slot]; break; + } + + if (itemId) + { + CurrentItemId = itemId; + } + } + } + } + else // Handling buy via alias + { + if (ItemAliasList.retrieve(command, &itemId)) + { + CurrentItemId = itemId; + } + } + } + + int client = ENTINDEX(pEdict); + + if (ForwardInternalCommand != -1 && *UseBotArgs) + { + const char *args = *BotArgs; + + if (MF_ExecuteForward(ForwardInternalCommand, static_cast(client), args) > 0) { return; } } + if (ForwardOnBuyAttempt != -1 && + CurrentItemId && + MF_IsPlayerAlive(client) && + MF_ExecuteForward(ForwardOnBuyAttempt, static_cast(client), static_cast(CurrentItemId)) > 0) + { + return; + } + DETOUR_STATIC_CALL(C_ClientCommand)(pEdict); } -DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool CanBuyThis(CBasePlayer *pPlayer, int weaponId) +DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName) { - if (weaponId != CSI_SHIELDGUN) // This will be handled before with BuyItem. Avoiding duplicated call. + // If the current item id is not null, this means player has triggers a buy command. + if (CurrentItemId) { - int player = PrivateToIndex(pvPlayer); + int client = PrivateToIndex(this); - if (MF_IsPlayerAlive(player) && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast(player), static_cast(weaponId)) > 0) - { - return false; - } - } - - return DETOUR_STATIC_CALL(CanBuyThis)(pvPlayer, weaponId); -} - -DETOUR_DECL_STATIC2(BuyItem, void, void*, pvPlayer, int, iSlot) // void BuyItem(CBasePlayer *pPlayer, int iSlot) -{ - int player = PrivateToIndex(pvPlayer); - - if (MF_IsPlayerAlive(player)) - { - static const int itemSlotToWeaponId[] = {-1, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN}; - - if (iSlot >= 1 && iSlot <= 8 && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast(player), static_cast(itemSlotToWeaponId[iSlot])) > 0) + if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast(client), static_cast(CurrentItemId)) > 0) { return; } } - DETOUR_STATIC_CALL(BuyItem)(pvPlayer, iSlot); + // From here, forward is not blocked, resetting this + // to ignore code in AddAccount which is called right after. + CurrentItemId = 0; + + // Give me my item! + DETOUR_MEMBER_CALL(GiveNamedItem)(pszName); } -DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bBlinkMoney) // bool BuyGunAmmo(CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney) +DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire) { - int player = PrivateToIndex(pvPlayer); - - if (MF_IsPlayerAlive(player)) + // Special case for shield. Game doesn't use GiveNamedItem() to give a shield. + if (CurrentItemId == CSI_SHIELDGUN) { - edict_t *pWeapon = PrivateToEdict(pvWeapon); + int client = PrivateToIndex(this); - if (pWeapon) + if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast(client), CSI_SHIELDGUN) > 0) { - int weaponId = *((int *)pWeapon->pvPrivateData + OFFSET_WEAPONTYPE); - int ammoId = (1<(player), static_cast(ammoId)) > 0) - { - return false; - } + return; } } - return DETOUR_STATIC_CALL(BuyGunAmmo)(pvPlayer, pvWeapon, bBlinkMoney); + // From here, forward is not blocked, resetting this + // to ignore code in AddAccount which is called right after. + CurrentItemId = 0; + + // Give me my shield! + DETOUR_MEMBER_CALL(GiveShield)(bRetire); +} + +DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange) +{ + // No buy command or forward not blocked. + // Resuming game flow. + if (!CurrentItemId) + { + DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange); + } + + // Let's reset this right away to avoid issues. + CurrentItemId = 0; } @@ -146,33 +246,88 @@ void CtrlDetours_ClientCommand(bool set) #if defined(WIN32) - g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); - g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); + UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); + BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); #elif defined(__linux__) || defined(__APPLE__) - g_UseBotArgs = (int *)UTIL_FindAddressFromEntry(CS_IDENT_USEBOTARGS, CS_IDENT_HIDDEN_STATE); - g_BotArgs = (const char **)UTIL_FindAddressFromEntry(CS_IDENT_BOTARGS, CS_IDENT_HIDDEN_STATE); + UseBotArgs = (int *)UTIL_FindAddressFromEntry(CS_IDENT_USEBOTARGS, CS_IDENT_HIDDEN_STATE); + BotArgs = (const char **)UTIL_FindAddressFromEntry(CS_IDENT_BOTARGS, CS_IDENT_HIDDEN_STATE); #endif - g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); + ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); - if (g_ClientCommandDetour == NULL) + if (ClientCommandDetour == NULL) { MF_Log("No Client Commands detour could be initialized - Disabled Client Command forward."); } } else { - if (g_ClientCommandDetour) - g_ClientCommandDetour->Destroy(); + if (ClientCommandDetour) + ClientCommandDetour->Destroy(); + + ItemAliasList.clear(); } } void ToggleDetour_ClientCommands(bool enable) { - if (g_ClientCommandDetour) - (enable) ? g_ClientCommandDetour->EnableDetour() : g_ClientCommandDetour->DisableDetour(); + if (ClientCommandDetour) + (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_GALI }, { "defender" , CSI_GALI }, + { "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_PRIMAMMO }, { "primammo" , CSI_PRIMAMMO }, + { "buyammo2" , CSI_SECAMMO }, { "secammo" , CSI_SECAMMO }, + { NULL , 0 } + }; + + for (size_t i = 0; aliasToId[i].alias != NULL; ++i) + { + ItemAliasList.insert(aliasToId[i].alias, aliasToId[i].id); + } + } + else + { + ItemAliasList.clear(); + } } @@ -180,40 +335,42 @@ void CtrlDetours_BuyCommands(bool set) { if (set) { - void *canBuyThisAddress = UTIL_FindAddressFromEntry(CS_IDENT_CANBUYTHIS, CS_IDENT_HIDDEN_STATE); - void *buyItemAddress = UTIL_FindAddressFromEntry(CS_IDENT_BUYITEM, CS_IDENT_HIDDEN_STATE); - void *buyGunAmmoAddress = UTIL_FindAddressFromEntry(CS_IDENT_BUYGUNAMMO, CS_IDENT_HIDDEN_STATE); + void *giveShieldAddress = UTIL_FindAddressFromEntry(CS_IDENT_GIVENSHIELD , CS_IDENT_HIDDEN_STATE); + void *giveNamedItemAddress = UTIL_FindAddressFromEntry(CS_IDENT_GIVENAMEDITEM, CS_IDENT_HIDDEN_STATE); + void *addAccountAddress = UTIL_FindAddressFromEntry(CS_IDENT_ADDACCOUNT , CS_IDENT_HIDDEN_STATE); - g_CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, canBuyThisAddress); - g_BuyItemDetour = DETOUR_CREATE_STATIC_FIXED(BuyItem, buyItemAddress); - g_BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, buyGunAmmoAddress); + GiveShieldDetour = DETOUR_CREATE_MEMBER_FIXED(GiveShield, giveShieldAddress); + GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, giveNamedItemAddress); + AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, addAccountAddress); - if (g_CanBuyThisDetour == NULL || g_BuyItemDetour == NULL || g_BuyGunAmmoDetour == NULL) + if (GiveNamedItemDetour == NULL || AddAccountDetour == NULL) { MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward."); } } else { - if (g_CanBuyThisDetour) - g_CanBuyThisDetour->Destroy(); + if (GiveShieldDetour) + GiveShieldDetour->Destroy(); - if (g_BuyItemDetour) - g_BuyItemDetour->Destroy(); + if (GiveNamedItemDetour) + GiveNamedItemDetour->Destroy(); - if (g_BuyGunAmmoDetour) - g_BuyGunAmmoDetour->Destroy(); + if (AddAccountDetour) + AddAccountDetour->Destroy(); + + ItemAliasList.clear(); } } void ToggleDetour_BuyCommands(bool enable) { - if (g_CanBuyThisDetour) - (enable) ? g_CanBuyThisDetour->EnableDetour() : g_CanBuyThisDetour->DisableDetour(); + if (GiveShieldDetour) + (enable) ? GiveShieldDetour->EnableDetour() : GiveShieldDetour->DisableDetour(); - if (g_BuyItemDetour) - (enable) ? g_BuyItemDetour->EnableDetour() : g_BuyItemDetour->DisableDetour(); + if (GiveNamedItemDetour) + (enable) ? GiveNamedItemDetour->EnableDetour() : GiveNamedItemDetour->DisableDetour(); - if (g_BuyGunAmmoDetour) - (enable) ? g_BuyGunAmmoDetour->EnableDetour() : g_BuyGunAmmoDetour->DisableDetour(); + if (AddAccountDetour) + (enable) ? AddAccountDetour->EnableDetour() : AddAccountDetour->DisableDetour(); } \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeNatives.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp index 980f2cc1..756998b6 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -1749,7 +1749,7 @@ static cell AMX_NATIVE_CALL not_on_64(AMX* amx, cell* params) #endif -AMX_NATIVE_INFO cstrikeNatives[] = { +AMX_NATIVE_INFO CstrikeNatives[] = { {"cs_set_user_money", cs_set_user_money}, {"cs_get_user_money", cs_get_user_money}, {"cs_get_user_deaths", cs_get_user_deaths}, diff --git a/dlls/cstrike/cstrike/CstrikePlayer.cpp b/dlls/cstrike/cstrike/CstrikePlayer.cpp index 72cee51e..cd72d55f 100755 --- a/dlls/cstrike/cstrike/CstrikePlayer.cpp +++ b/dlls/cstrike/cstrike/CstrikePlayer.cpp @@ -3,14 +3,6 @@ ////////////////////////////////////////////////////////////////////// #include "CstrikePlayer.h" - -#if defined _MSC_VER - #if _MSC_VER >= 1400 - // MSVC8 - disable deprecation warnings for "unsafe" CRT functions - #define _CRT_SECURE_NO_DEPRECATE - #endif -#endif - #include // strcpy() ////////////////////////////////////////////////////////////////////// diff --git a/dlls/cstrike/cstrike/CstrikeUtils.cpp b/dlls/cstrike/cstrike/CstrikeUtils.cpp index 2c4fe6a3..76783b45 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.cpp +++ b/dlls/cstrike/cstrike/CstrikeUtils.cpp @@ -139,4 +139,15 @@ bool UTIL_CheckForPublic(const char *publicname) } return false; +} + +char *UTIL_StringToLower(char *str) +{ + char *p; + for (p = str; *p != '\0'; ++p) + { + *p = tolower(*p); + } + + return str; } \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeUtils.h b/dlls/cstrike/cstrike/CstrikeUtils.h index ec2c7bc4..4a58d5df 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.h +++ b/dlls/cstrike/cstrike/CstrikeUtils.h @@ -37,6 +37,7 @@ bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer); void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message); void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden = false, const char *library = "mod"); bool UTIL_CheckForPublic(const char *publicname); +char *UTIL_StringToLower(char *str); #define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) #define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue) diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index 67088517..bd1c9c3a 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -33,10 +33,11 @@ #include "amxxmodule.h" #include "CstrikeUtils.h" -extern AMX_NATIVE_INFO cstrikeNatives[]; +extern AMX_NATIVE_INFO CstrikeNatives[]; -extern int g_CSCliCmdFwd; -extern int g_CSBuyCmdFwd; +extern int ForwardInternalCommand; +extern int ForwardOnBuy; +extern int ForwardOnBuyAttempt; void InitializeHacks(); void ShutdownHacks(); @@ -56,17 +57,25 @@ int AmxxCheckGame(const char *game) void OnAmxxAttach() { - MF_AddNatives(cstrikeNatives); + MF_AddNatives(CstrikeNatives); InitializeHacks(); } void OnPluginsLoaded() { - g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); - g_CSBuyCmdFwd = MF_RegisterForward("CS_OnBuy", ET_STOP, FP_CELL, FP_CELL, FP_DONE); + ForwardInternalCommand = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); + ForwardOnBuy = MF_RegisterForward("CS_OnBuy" , ET_STOP, FP_CELL, FP_CELL, FP_DONE); + ForwardOnBuyAttempt = MF_RegisterForward("CS_OnBuyAttempt" , ET_STOP, FP_CELL, FP_CELL, FP_DONE); - ToggleDetour_ClientCommands(UTIL_CheckForPublic("CS_InternalCommand")); - ToggleDetour_BuyCommands(UTIL_CheckForPublic("CS_OnBuy")); + // Checking whether such public forwards are used in plugins. + // Resetting variable to -1 to avoid running unnecessary code in ClientCommand. + if (!UTIL_CheckForPublic("CS_InternalCommand")) { ForwardInternalCommand = -1; } + if (!UTIL_CheckForPublic("CS_OnBuy")) { ForwardOnBuy = -1; } + if (!UTIL_CheckForPublic("CS_OnBuyAttempt")) { ForwardOnBuyAttempt = -1; } + + // And enable/disable detours when necessary. + ToggleDetour_ClientCommands(ForwardInternalCommand != -1 || ForwardOnBuy != -1 || ForwardOnBuy != -1); + ToggleDetour_BuyCommands(ForwardOnBuy != -1); } void OnAmxxDetach() diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj index c19e1bda..2e39589c 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj @@ -63,7 +63,7 @@ Disabled ..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;HAVE_STDINT_H;_CRT_SECURE_NO_DEPRECATE;CSTRIKE_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false @@ -106,7 +106,7 @@ MaxSpeed OnlyExplicitInline ..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;HAVE_STDINT_H;_CRT_SECURE_NO_DEPRECATE;CSTRIKE_EXPORTS;%(PreprocessorDefinitions) true MultiThreaded true diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 21001ec1..294eb31e 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -357,7 +357,7 @@ forward CS_InternalCommand(id, const cmd[]); /** - * The following constants are used with CS_OnBuy forward. + * The following constants are used with CS_OnBuy[Attempt] forwards. */ #define CSI_P228 CSW_P228 #define CSI_SCOUT CSW_SCOUT @@ -397,9 +397,22 @@ forward CS_InternalCommand(id, const cmd[]); /** * Called when a player attempts to purchase an item. - * Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny. + * This is ususally called right away on buy commands issued by a player. + * + * @note Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny. * * @param index Player index. * @param item Item index, see CSI_* constants. */ -forward CS_OnBuy(index, item); +forward CS_OnBuyAttempt(index, item); + +/** + * Called when a player purchases an item. + * This usually called right before a player gets the purchased item. + * + * @note Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny. + * + * @param index Player index. + * @param item Item index, see CSI_* constants. + */ +forward CS_OnBuy(index, item); \ No newline at end of file diff --git a/public/memtools/CDetour/detours.h b/public/memtools/CDetour/detours.h index dea92c42..89c2b238 100644 --- a/public/memtools/CDetour/detours.h +++ b/public/memtools/CDetour/detours.h @@ -136,6 +136,7 @@ ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name #define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual #define DETOUR_CREATE_MEMBER(name, gamedata, target) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata, target); +#define DETOUR_CREATE_MEMBER_FIXED(name, address) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), address); #define DETOUR_CREATE_STATIC(name, gamedata, target) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata, target); #define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address);