Cstrike: Make CS_OnBuy forward more reliable - part 4
Added support for shield , which is a special case. Moved hashmap creation to OnPluginsLoaded.
This commit is contained in:
		@@ -163,14 +163,17 @@
 | 
			
		||||
 * CS_OnBuy forward 
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
	#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_GIVENSHIELD        "_ZN11CBasePlayer10GiveShieldEb"
 | 
			
		||||
	#define CS_IDENT_GIVENAMEDITEM		"_ZN11CBasePlayer13GiveNamedItemEPKc"
 | 
			
		||||
	#define CS_IDENT_ADDACCOUNT			"_ZN11CBasePlayer10AddAccountEib"
 | 
			
		||||
	#define CS_IDENT_HIDDEN_STATE		true
 | 
			
		||||
#elif defined(WIN32)
 | 
			
		||||
	#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
 | 
			
		||||
 
 | 
			
		||||
@@ -43,15 +43,13 @@ void CtrlDetours_BuyCommands(bool set);
 | 
			
		||||
int g_CSCliCmdFwd = -1;
 | 
			
		||||
int g_CSBuyCmdFwd = -1;
 | 
			
		||||
 | 
			
		||||
int *g_UseBotArgs = NULL;
 | 
			
		||||
int *g_UseBotArgs      = NULL;
 | 
			
		||||
const char **g_BotArgs = NULL;
 | 
			
		||||
 | 
			
		||||
CDetour *g_ClientCommandDetour = NULL;
 | 
			
		||||
CDetour *g_CanBuyThisDetour = NULL;
 | 
			
		||||
CDetour *g_BuyItemDetour = NULL;
 | 
			
		||||
CDetour *g_BuyGunAmmoDetour = NULL;
 | 
			
		||||
CDetour *g_GiveShieldDetour    = NULL;
 | 
			
		||||
CDetour *g_GiveNamedItemDetour = NULL;
 | 
			
		||||
CDetour *g_AddAccountDetour = NULL;
 | 
			
		||||
CDetour *g_AddAccountDetour    = NULL;
 | 
			
		||||
 | 
			
		||||
int g_CurrentItemId = 0;
 | 
			
		||||
StringHashMap<int> g_ItemAliasList;
 | 
			
		||||
@@ -93,7 +91,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
 | 
			
		||||
{
 | 
			
		||||
	const char *command = CMD_ARGV(0);
 | 
			
		||||
	
 | 
			
		||||
	// A new command is triggered, reset current item.
 | 
			
		||||
	// A new command is triggered, reset variable, always.
 | 
			
		||||
	g_CurrentItemId = 0;
 | 
			
		||||
 | 
			
		||||
	// Purpose is to retrieve an item id based on alias name or selected item from menu,
 | 
			
		||||
@@ -102,7 +100,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
 | 
			
		||||
	{
 | 
			
		||||
		int itemId = 0;
 | 
			
		||||
		
 | 
			
		||||
		// Handling via menu.
 | 
			
		||||
		// Handling buy via menu.
 | 
			
		||||
		if (!strcmp(command, "menuselect")) 
 | 
			
		||||
		{
 | 
			
		||||
			int slot = atoi(CMD_ARGV(1));
 | 
			
		||||
@@ -148,8 +146,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// Handling via alias
 | 
			
		||||
		else
 | 
			
		||||
		else // Handling buy via alias
 | 
			
		||||
		{
 | 
			
		||||
			if (g_ItemAliasList.retrieve(command, &itemId))
 | 
			
		||||
			{
 | 
			
		||||
@@ -174,26 +171,47 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
 | 
			
		||||
 | 
			
		||||
DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName)
 | 
			
		||||
{
 | 
			
		||||
	// If the current item id is not null, this means player has triggers a buy command.
 | 
			
		||||
	if (g_CurrentItemId && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(PrivateToIndex(this)), static_cast<cell>(g_CurrentItemId)) > 0)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// From here, forward is not blocked, resetting this
 | 
			
		||||
	// to ignore code in AddAccount which is called right after.
 | 
			
		||||
	g_CurrentItemId = 0;
 | 
			
		||||
 | 
			
		||||
	// Give me my item!
 | 
			
		||||
	DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
 | 
			
		||||
DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire)
 | 
			
		||||
{
 | 
			
		||||
	if (g_CurrentItemId)
 | 
			
		||||
	// Special case for shield. Game doesn't use GiveNamedItem() to give a shield.
 | 
			
		||||
	if (g_CurrentItemId == CSI_SHIELDGUN && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(PrivateToIndex(this)), CSI_SHIELDGUN) > 0)
 | 
			
		||||
	{
 | 
			
		||||
		g_CurrentItemId = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
 | 
			
		||||
	// From here, forward is not blocked, resetting this
 | 
			
		||||
	// to ignore code in AddAccount which is called right after.
 | 
			
		||||
	g_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 (!g_CurrentItemId)
 | 
			
		||||
	{
 | 
			
		||||
		DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Let's reset this right away to avoid issues.
 | 
			
		||||
	g_CurrentItemId = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -239,9 +257,11 @@ void CtrlDetours_BuyCommands(bool set)
 | 
			
		||||
{
 | 
			
		||||
	if (set)
 | 
			
		||||
	{
 | 
			
		||||
		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_GiveShieldDetour    = DETOUR_CREATE_MEMBER_FIXED(GiveShield, giveShieldAddress);
 | 
			
		||||
		g_GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, giveNamedItemAddress);
 | 
			
		||||
		g_AddAccountDetour    = DETOUR_CREATE_MEMBER_FIXED(AddAccount, addAccountAddress);
 | 
			
		||||
 | 
			
		||||
@@ -249,9 +269,37 @@ void CtrlDetours_BuyCommands(bool set)
 | 
			
		||||
		{
 | 
			
		||||
			MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward.");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (g_GiveShieldDetour)
 | 
			
		||||
			g_GiveShieldDetour->Destroy();
 | 
			
		||||
 | 
			
		||||
		if (g_GiveNamedItemDetour)
 | 
			
		||||
			g_GiveNamedItemDetour->Destroy();
 | 
			
		||||
 | 
			
		||||
		if (g_AddAccountDetour)
 | 
			
		||||
			g_AddAccountDetour->Destroy();
 | 
			
		||||
 | 
			
		||||
		g_ItemAliasList.clear();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToggleDetour_BuyCommands(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	if (g_GiveShieldDetour)
 | 
			
		||||
		(enable) ? g_GiveShieldDetour->EnableDetour() : g_GiveShieldDetour->DisableDetour();
 | 
			
		||||
 | 
			
		||||
	if (g_GiveNamedItemDetour)
 | 
			
		||||
		(enable) ? g_GiveNamedItemDetour->EnableDetour() : g_GiveNamedItemDetour->DisableDetour();
 | 
			
		||||
 | 
			
		||||
	if (g_AddAccountDetour)
 | 
			
		||||
		(enable) ? g_AddAccountDetour->EnableDetour() : g_AddAccountDetour->DisableDetour();
 | 
			
		||||
 | 
			
		||||
	if (enable)
 | 
			
		||||
	{
 | 
			
		||||
		// Build the item alias list.
 | 
			
		||||
		// Used in ClientCommand to check and get fastly item id from aiias name.
 | 
			
		||||
		// Used in ClientCommand to check and get fastly item id from alias name.
 | 
			
		||||
		typedef struct
 | 
			
		||||
		{
 | 
			
		||||
			char *alias;
 | 
			
		||||
@@ -298,21 +346,6 @@ void CtrlDetours_BuyCommands(bool set)
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (g_GiveNamedItemDetour)
 | 
			
		||||
			g_GiveNamedItemDetour->Destroy();
 | 
			
		||||
 | 
			
		||||
		if (g_AddAccountDetour)
 | 
			
		||||
			g_AddAccountDetour->Destroy();
 | 
			
		||||
 | 
			
		||||
		g_ItemAliasList.clear();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToggleDetour_BuyCommands(bool enable)
 | 
			
		||||
{
 | 
			
		||||
	if (g_GiveNamedItemDetour)
 | 
			
		||||
		(enable) ? g_GiveNamedItemDetour->EnableDetour() : g_GiveNamedItemDetour->DisableDetour();
 | 
			
		||||
 | 
			
		||||
	if (g_AddAccountDetour)
 | 
			
		||||
		(enable) ? g_AddAccountDetour->EnableDetour() : g_AddAccountDetour->DisableDetour();
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user