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:
Arkshine 2014-07-04 00:17:55 +02:00
parent 884c5e9643
commit 0728fee706
2 changed files with 66 additions and 30 deletions

View File

@ -163,14 +163,17 @@
* CS_OnBuy forward * CS_OnBuy forward
*/ */
#if defined(__linux__) #if defined(__linux__)
#define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb"
#define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc"
#define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib"
#define CS_IDENT_HIDDEN_STATE false #define CS_IDENT_HIDDEN_STATE false
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb"
#define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc"
#define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib"
#define CS_IDENT_HIDDEN_STATE true #define CS_IDENT_HIDDEN_STATE true
#elif defined(WIN32) #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_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_ADDACCOUNT "\\x8B\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x03"
#define CS_IDENT_HIDDEN_STATE false #define CS_IDENT_HIDDEN_STATE false

View File

@ -47,9 +47,7 @@ int *g_UseBotArgs = NULL;
const char **g_BotArgs = NULL; const char **g_BotArgs = NULL;
CDetour *g_ClientCommandDetour = NULL; CDetour *g_ClientCommandDetour = NULL;
CDetour *g_CanBuyThisDetour = NULL; CDetour *g_GiveShieldDetour = NULL;
CDetour *g_BuyItemDetour = NULL;
CDetour *g_BuyGunAmmoDetour = NULL;
CDetour *g_GiveNamedItemDetour = NULL; CDetour *g_GiveNamedItemDetour = NULL;
CDetour *g_AddAccountDetour = NULL; CDetour *g_AddAccountDetour = NULL;
@ -93,7 +91,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
{ {
const char *command = CMD_ARGV(0); 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; g_CurrentItemId = 0;
// Purpose is to retrieve an item id based on alias name or selected item from menu, // 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; int itemId = 0;
// Handling via menu. // Handling buy via menu.
if (!strcmp(command, "menuselect")) if (!strcmp(command, "menuselect"))
{ {
int slot = atoi(CMD_ARGV(1)); 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 // Handling buy via alias
else
{ {
if (g_ItemAliasList.retrieve(command, &itemId)) 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) 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) if (g_CurrentItemId && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(PrivateToIndex(this)), static_cast<cell>(g_CurrentItemId)) > 0)
{ {
return; return;
} }
// From here, forward is not blocked, resetting this
// to ignore code in AddAccount which is called right after.
g_CurrentItemId = 0; g_CurrentItemId = 0;
// Give me my item!
DETOUR_MEMBER_CALL(GiveNamedItem)(pszName); DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
} }
DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire)
DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
{ {
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; 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 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); 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) 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 *giveNamedItemAddress = UTIL_FindAddressFromEntry(CS_IDENT_GIVENAMEDITEM, CS_IDENT_HIDDEN_STATE);
void *addAccountAddress = UTIL_FindAddressFromEntry(CS_IDENT_ADDACCOUNT , 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_GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, giveNamedItemAddress);
g_AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, addAccountAddress); 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."); 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. // 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 typedef struct
{ {
char *alias; char *alias;
@ -298,21 +346,6 @@ void CtrlDetours_BuyCommands(bool set)
} }
else else
{ {
if (g_GiveNamedItemDetour)
g_GiveNamedItemDetour->Destroy();
if (g_AddAccountDetour)
g_AddAccountDetour->Destroy();
g_ItemAliasList.clear(); 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();
}