Cstrike: Make CS_OnBuy forward more reliable - part 2
Purpose is to have the forward be called only on actual buying. This has been requested on the forum.
This commit is contained in:
		@@ -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',
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -353,4 +354,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
 | 
			
		||||
@@ -33,6 +33,9 @@
 | 
			
		||||
#include "CstrikeDatas.h"
 | 
			
		||||
#include "CstrikeUtils.h"
 | 
			
		||||
#include "CDetour/detours.h"
 | 
			
		||||
#include <sm_stringhashmap.h>
 | 
			
		||||
 | 
			
		||||
using namespace SourceMod; // hashmap 
 | 
			
		||||
 | 
			
		||||
void CtrlDetours_ClientCommand(bool set);
 | 
			
		||||
void CtrlDetours_BuyCommands(bool set);
 | 
			
		||||
@@ -50,6 +53,9 @@ CDetour *g_BuyGunAmmoDetour = NULL;
 | 
			
		||||
CDetour *g_GiveNamedItemDetour = NULL;
 | 
			
		||||
CDetour *g_AddAccountDetour = NULL;
 | 
			
		||||
 | 
			
		||||
int g_CurrentItemId = 0;
 | 
			
		||||
StringHashMap<int> g_ItemAliasList;
 | 
			
		||||
 | 
			
		||||
void InitializeHacks()
 | 
			
		||||
{
 | 
			
		||||
#if defined AMD64
 | 
			
		||||
@@ -66,9 +72,92 @@ void ShutdownHacks()
 | 
			
		||||
	CtrlDetours_BuyCommands(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef CMD_ARGV
 | 
			
		||||
 | 
			
		||||
const char *CMD_ARGV(int i)
 | 
			
		||||
{
 | 
			
		||||
	if (*g_UseBotArgs)
 | 
			
		||||
	{
 | 
			
		||||
		if (i < 4)
 | 
			
		||||
		{
 | 
			
		||||
			return g_BotArgs[i];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return g_engfuncs.pfnCmd_Argv(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
 | 
			
		||||
{
 | 
			
		||||
	const char *command = CMD_ARGV(0);
 | 
			
		||||
	
 | 
			
		||||
	// A new command is triggered, reset current item.
 | 
			
		||||
	g_CurrentItemId = 0;
 | 
			
		||||
 | 
			
		||||
	// Purpose is to retrieve an item id based on alias name or selected item from menu,
 | 
			
		||||
	// to be used in OnBuy* forwards.
 | 
			
		||||
	if (command && *command)
 | 
			
		||||
	{
 | 
			
		||||
		int itemId = 0;
 | 
			
		||||
		
 | 
			
		||||
		// Handling 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)
 | 
			
		||||
					{
 | 
			
		||||
						g_CurrentItemId = itemId;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// Handling via alias
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if (g_ItemAliasList.retrieve(command, &itemId))
 | 
			
		||||
			{
 | 
			
		||||
				g_CurrentItemId = itemId;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (*g_UseBotArgs)
 | 
			
		||||
	{
 | 
			
		||||
		int client = ENTINDEX(pEdict);
 | 
			
		||||
@@ -89,9 +178,9 @@ DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool Ca
 | 
			
		||||
	{
 | 
			
		||||
		int player = PrivateToIndex(pvPlayer);
 | 
			
		||||
 | 
			
		||||
		if (MF_IsPlayerAlive(player) && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(player), static_cast<cell>(weaponId)) > 0)
 | 
			
		||||
		if (MF_IsPlayerAlive(player))
 | 
			
		||||
		{
 | 
			
		||||
			return false;
 | 
			
		||||
			g_CurrentItemId = weaponId;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
@@ -106,9 +195,9 @@ DETOUR_DECL_STATIC2(BuyItem, void, void*, pvPlayer, int, iSlot) // void BuyItem(
 | 
			
		||||
	{
 | 
			
		||||
		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<cell>(player), static_cast<cell>(itemSlotToWeaponId[iSlot])) > 0)
 | 
			
		||||
		if (iSlot >= 1 && iSlot <= 8)
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
			g_CurrentItemId = itemSlotToWeaponId[iSlot];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -128,10 +217,7 @@ DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bB
 | 
			
		||||
			int weaponId = *((int *)pWeapon->pvPrivateData + OFFSET_WEAPONTYPE);
 | 
			
		||||
			int ammoId = (1<<weaponId & BITS_PISTOLS) ? CSI_SECAMMO : CSI_PRIMAMMO;
 | 
			
		||||
 | 
			
		||||
			if (MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(player), static_cast<cell>(ammoId)) > 0)
 | 
			
		||||
			{
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			g_CurrentItemId = ammoId;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -140,12 +226,25 @@ DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bB
 | 
			
		||||
 | 
			
		||||
DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName)
 | 
			
		||||
{
 | 
			
		||||
	if (g_CurrentItemId && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(PrivateToIndex(this)), static_cast<cell>(g_CurrentItemId)) > 0)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_CurrentItemId = 0;
 | 
			
		||||
 | 
			
		||||
	DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
 | 
			
		||||
{
 | 
			
		||||
	if (g_CurrentItemId)
 | 
			
		||||
	{
 | 
			
		||||
		g_CurrentItemId = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -212,6 +311,52 @@ void CtrlDetours_BuyCommands(bool set)
 | 
			
		||||
		{
 | 
			
		||||
			MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward.");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Build the item alias list.
 | 
			
		||||
		// Used in ClientCommand to check and get fastly item id from aiias name.
 | 
			
		||||
		typedef struct
 | 
			
		||||
		{
 | 
			
		||||
			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)
 | 
			
		||||
		{
 | 
			
		||||
			g_ItemAliasList.insert(aliasToId[i].alias, aliasToId[i].id);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
@@ -229,6 +374,8 @@ void CtrlDetours_BuyCommands(bool set)
 | 
			
		||||
 | 
			
		||||
		if (g_AddAccountDetour)
 | 
			
		||||
			g_AddAccountDetour->Destroy();
 | 
			
		||||
 | 
			
		||||
		g_ItemAliasList.clear();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <string.h> // strcpy()
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@
 | 
			
		||||
    <ClCompile>
 | 
			
		||||
      <Optimization>Disabled</Optimization>
 | 
			
		||||
      <AdditionalIncludeDirectories>..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
 | 
			
		||||
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 | 
			
		||||
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HAVE_STDINT_H;_CRT_SECURE_NO_DEPRECATE;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 | 
			
		||||
      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
 | 
			
		||||
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
 | 
			
		||||
      <RuntimeTypeInfo>false</RuntimeTypeInfo>
 | 
			
		||||
@@ -106,7 +106,7 @@
 | 
			
		||||
      <Optimization>MaxSpeed</Optimization>
 | 
			
		||||
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
 | 
			
		||||
      <AdditionalIncludeDirectories>..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
 | 
			
		||||
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 | 
			
		||||
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HAVE_STDINT_H;_CRT_SECURE_NO_DEPRECATE;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 | 
			
		||||
      <StringPooling>true</StringPooling>
 | 
			
		||||
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
 | 
			
		||||
      <FunctionLevelLinking>true</FunctionLevelLinking>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user