2023 Offsets
#define CS_BOTS 0xE8, '*', '*', '*', '*'
#ifdef WIN32
#define CS_BOTS_W CS_BOTS, 0x83, 0xC4, 0x04, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'
unsigned char CS_BOTS_RADIO[]{ CS_BOTS_W, '*', '*', 0xE8, '*', '*', '*', '*', 0x83, }; // phraseMan
unsigned char CS_BOTS_PROFILES[]{ CS_BOTS_W, 0x57, 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, };
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_W, 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, };
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_W, 0x8B, '*', 0x8B, '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', 0x8B, '*', 0x8B, '*', 0x68, };
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_W, 0x56, 0x8B, '*', '*', 0xB9, '*', '*', '*', '*', 0x8B, '*', 0x0F, };
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_W, 0xC6, '*', '*', '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x74, '*', 0x68, };
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_W, '*', '*', 0x83, '*', '*', 0x75, '*', 0x8B, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, }; // addBot
unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x83, '*', '*', 0x80, '*', '*', '*', 0x74, '*', 0x8B, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0x6A, '*', 0x6A, '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0xFF, }; // clientPrint #Game_radio_loc...
#else
#define CS_BOTS_L CS_BOTS, 0x83, 0xC4, 0x10, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'
unsigned char CS_BOTS_RADIO[]{ CS_BOTS_L, 0x83, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x83, '*', '*', 0x31, '*', 0xE9, }; // phraseMan
unsigned char CS_BOTS_PROFILES[]{ CS_BOTS, 0x84, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, };
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_L, 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0xFF, };
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_L, '*', 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x58, 0x8B, '*', 0x5A, 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x59, 0x58, 0x8B, };
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_L, '*', '*', 0xBF, '*', '*', '*', '*', 0xB9, '*', '*', '*', '*', 0xF3, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0xBF, };
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_L, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xA1, };
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_L, 0x83, '*', '*', 0x89, '*', 0x8B, '*', '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x0F, }; // addBot
unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x80, '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', 0x31, '*', 0xBB, '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0x89, }; // clientPrint #Game_radio_loc...
#endif
Use Orpheu to patch void CHostage::IdleThink(void).
The \steamapps\common\Half-Life\cstrike\addons\amxmodx\configs\orpheu\functions\CHostage\IdleThink file.
{
"name" : "IdleThink",
"class" : "CHostage",
"library" : "mod",
"identifiers" :
[
{
"os" : "windows",
"mod" : "cstrike",
"value" : "?IdleThink@CHostage@@QAEXXZ"
},
{
"os" : "linux",
"mod" : "cstrike",
"value" : "_ZN8CHostage9IdleThinkEv"
}
]
}
#pragma tabsize 0
#pragma semicolon 0
#pragma ctrlchar '\'
#pragma dynamic 4194304
#include <amxmodx>
#tryinclude <amxmisc>
/// #include <fun>
/// #include <csx>
/// #include <json>
/// #include <sqlx>
/// #include <geoip>
/// #include <regex>
/// #include <engine>
/// #include <nvault>
/// #include <cstrike>
/// #include <sockets>
/// #include <fakemeta>
/// #include <hamsandwich>
#include <orpheu>
#tryinclude <orpheu_memory>
public plugin_init()
{
register_plugin("CS Block Hostage Think", __DATE__, "Hattrick HKS (Caramel)");
return PLUGIN_CONTINUE;
}
public plugin_precache()
{
new OrpheuFunction: eOnHostageIdleThink = OrpheuGetFunction("IdleThink", "CHostage");
if (OrpheuInvalidFunction != eOnHostageIdleThink)
{
OrpheuRegisterHook(eOnHostageIdleThink, "OnHostageIdleThink_PRE", OrpheuHookPre);
}
return PLUGIN_CONTINUE;
}
public OrpheuHookReturn: OnHostageIdleThink_PRE(nHostage)
{
return OrpheuSupercede;
}
Wasn't able to test the Linux signatures. EDIT: Tested, working.
void CHostage::IdleThink(void) L/ W Signatures (To Block This Function)
L/ 57 56 53 83 ?? ?? 81 ?? ?? ?? ?? ?? ?? ?? ?? ?? 8B ?? ?? ?? 0F ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 85 ?? 0F
W/ 55 8B ?? 6A ?? 68 ?? ?? ?? ?? 64 ?? ?? ?? ?? ?? 50 83 ?? ?? 53 56 57 A1 ?? ?? ?? ?? 33 ?? 50 8D ?? ?? 64 ?? ?? ?? ?? ?? 8B ?? 83 ?? ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 75 ?? 85 ?? 74 ?? 8B ?? 6A ?? FF
[Update on Dec. 17, 2013] Patching void CHostage::IdleThink(void)/ blocking its execution will cause hostages to not work anymore. So:
#define CS_BOTS 0xE8, '*', '*', '*', '*'
#ifdef WIN32
#define CS_BOTS_W CS_BOTS, 0x83, 0xC4, 0x04, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'
unsigned char CS_BOTS_RADIO[]{ CS_BOTS_W, '*', '*', 0xE8, '*', '*', '*', '*', 0x83, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __cdecl BotPhraseManager::Initialize (BotPhraseManager * this, char * a2, int a3)` ( LINUX )
unsigned char CS_BOTS_PROFILES[]{ CS_BOTS_W, 0x57, 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl BotProfileManager::Init (BotProfileManager * const this, char * filename, unsigned int * checksum)` ( LINUX )
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_W, 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void Bot_RegisterCvars (void)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_W, 0x8B, '*', 0x8B, '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', 0x8B, '*', 0x8B, '*', 0x68, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::AddServerCommands (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_W, 0x56, 0x8B, '*', '*', 0xB9, '*', '*', '*', '*', 0x8B, '*', 0x0F, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `unsigned int __cdecl CCSBotManager::ServerCommand (CCSBotManager * this, const char * a2)` ( LINUX )
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_W, 0xC6, '*', '*', '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x74, '*', 0x68, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::ValidateMapData (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_W, '*', '*', 0x83, '*', '*', 0x75, '*', 0x8B, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __usercall CCSBotManager::AddBot @ <eax> (int a1 @ <edi>, BotProfile * this, const BotProfile * a3)` ( LINUX )
unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x83, '*', '*', 0x80, '*', '*', '*', 0x74, '*', 0x8B, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0x6A, '*', 0x6A, '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0xFF, }; /// `void __cdecl ClientPrint (entvars_t * client, int msg_dest, const char * msg_name, const char * param1, const char * param2, const char * param3, const char * param4)` CALL WITH "#Game_radio_location" PARAMETER INSIDE FUNCTION `void __cdecl CBasePlayer::Radio (CBasePlayer * const this, const char * msg_id, const char * msg_verbose, __int16 pitch, bool showIcon)` ( LINUX )
unsigned char CS_BOTS_HOSTAGE[]{ 0x55, 0x8B, '*', 0x6A, '*', 0x68, '*', '*', '*', '*', 0x64, '*', '*', '*', '*', '*', 0x50, 0x83, '*', '*', 0x53, 0x56, 0x57, 0xA1, '*', '*', '*', '*', 0x33, '*', 0x50, 0x8D, '*', '*', /// `void __thiscall CHostage::IdleThink (CHostage * this)` FUNCTION ( WINDOWS )
0x64, '*', '*', '*', '*', '*', 0x8B, '*', 0x83, '*', '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x75, '*', 0x85, '*', 0x74, '*', 0x8B, '*', 0x6A, '*', 0xFF, }; /// `void __cdecl CHostage::IdleThink (CHostage * const this)` FUNCTION ( LINUX )
unsigned char CS_BOTS_IMPROV[]{ 0x53, 0x8B, '*', 0x83, '*', '*', 0x83, '*', '*', 0x83, '*', '*', 0x55, 0x8B, '*', '*', 0x89, '*', '*', '*', 0x8B, '*', 0x6A, '*', 0x68, '*', '*', '*', '*', 0x64, '*', '*', '*', '*', '*', /// `int * __userpurge sub_1004DBB0 @ <eax> (int * a1 @ <ecx>, int a2 @ <edi>, int a3 @ <esi>, int a4)` FUNCTION ( WINDOWS )
0x50, 0x53, 0x83, '*', '*', 0x56, 0x57, 0xA1, '*', '*', '*', '*', 0x33, '*', 0x50, 0x8D, '*', '*', 0x64, '*', '*', '*', '*', '*', 0x8B, '*', 0x89, '*', '*', 0xC7, }; /// `void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity)` FUNCTION ( LINUX )
unsigned char CS_BOTS_NEW[]{ CS_BOTS, 0x83, '*', '*', 0x89, '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0x85, '*', 0x74, '*', 0x57, 0x8B, '*', 0xE8, '*', '*', '*', '*', 0xEB, }; /// `void * __cdecl operator new (unsigned size)` CALL INSIDE FUNCTION `void __cdecl CHostage::IdleThink (CHostage * const this)` ( LINUX )
#else
#define CS_BOTS_L CS_BOTS, 0x83, 0xC4, 0x10, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'
unsigned char CS_BOTS_RADIO[]{ CS_BOTS_L, 0x83, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x83, '*', '*', 0x31, '*', 0xE9, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __cdecl BotPhraseManager::Initialize (BotPhraseManager * this, char * a2, int a3)` ( LINUX )
unsigned char CS_BOTS_PROFILES[]{ CS_BOTS, 0x84, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl BotProfileManager::Init (BotProfileManager * const this, char * filename, unsigned int * checksum)` ( LINUX )
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_L, 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0xFF, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void Bot_RegisterCvars (void)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_L, '*', 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x58, 0x8B, '*', 0x5A, 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x59, 0x58, 0x8B, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::AddServerCommands (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_L, '*', '*', 0xBF, '*', '*', '*', '*', 0xB9, '*', '*', '*', '*', 0xF3, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0xBF, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `unsigned int __cdecl CCSBotManager::ServerCommand (CCSBotManager * this, const char * a2)` ( LINUX )
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_L, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xA1, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::ValidateMapData (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_L, 0x83, '*', '*', 0x89, '*', 0x8B, '*', '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x0F, }; /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __usercall CCSBotManager::AddBot @ <eax> (int a1 @ <edi>, BotProfile * this, const BotProfile * a3)` ( LINUX )
unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x80, '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', 0x31, '*', 0xBB, '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0x89, }; /// `void __cdecl ClientPrint (entvars_t * client, int msg_dest, const char * msg_name, const char * param1, const char * param2, const char * param3, const char * param4)` CALL WITH "#Game_radio_location" PARAMETER INSIDE FUNCTION `void __cdecl CBasePlayer::Radio (CBasePlayer * const this, const char * msg_id, const char * msg_verbose, __int16 pitch, bool showIcon)` ( LINUX )
unsigned char CS_BOTS_HOSTAGE[]{ 0x57, 0x56, 0x53, 0x83, '*', '*', 0x81, '*', '*', '*', '*', '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x85, '*', 0x0F, }; /// `void __cdecl CHostage::IdleThink (CHostage * const this)` FUNCTION ( LINUX )
unsigned char CS_BOTS_IMPROV[]{ 0x57, 0x31, '*', 0x66, '*', '*', '*', 0x56, 0xBA, '*', '*', '*', '*', 0x53, 0xB9, '*', '*', '*', '*', 0x83, '*', '*', 0xBF, '*', '*', '*', '*', 0x8B, '*', '*', '*', 0x0F, '*', '*', '*', '*', /// `int * __userpurge sub_1004DBB0 @ <eax> (int * a1 @ <ecx>, int a2 @ <edi>, int a3 @ <esi>, int a4)` FUNCTION ( WINDOWS )
'*', '*', 0x8B, '*', '*', '*', 0x0F, '*', '*', '*', 0x0F, '*', '*', '*', 0xF3, '*', '*', '*', '*', '*', '*', '*', 0x89, '*', '*', '*', '*', '*', 0xB8, }; /// `void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity)` FUNCTION ( LINUX )
unsigned char CS_BOTS_NEW[]{ CS_BOTS, 0x89, '*', '*', '*', 0x89, '*', '*', 0x89, '*', 0xE8, '*', '*', '*', '*', 0x89, '*', '*', '*', '*', '*', 0xE9, }; /// `void * __cdecl operator new (unsigned size)` CALL INSIDE FUNCTION `void __cdecl CHostage::IdleThink (CHostage * const this)` ( LINUX )
#endif
-
Should block
void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity)function. On Windows, it's aint *function. Notvoid. So in Windows,return nullptr;is needed. -
Should block
void * __cdecl operator new (unsigned size)call inside functionvoid __cdecl CHostage::IdleThink (CHostage * const this). On Windows and Linux,return nullptr;is needed. Thevoid * __cdecl operator new (unsigned size)function is avoid *function. -
Warning,
void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity)is a main function, not a sub-function which resides inside a main function (like the others are). Perhaps this needs a different hook method. -
No need to hook/ block
void __cdecl CHostage::IdleThink (CHostage * const this)anymore. Can still be hooked but call the original function into the hook.
unsigned char* Hook_LoadFileForMe(const char* pcszFileName, int* pnLength) noexcept
{
static bool bShouldBlock{ };
if (!::g_strGameDir.empty())
{
if (!::g_strGameDir.compare("cstrike"))
{
if (pcszFileName)
{
if (*pcszFileName)
{
if (::std::strcmp("tutordata.txt", pcszFileName))
{
if (::std::strcmp("BotChatter.db", pcszFileName))
{
if (!::std::strstr(pcszFileName, "sound\\radio\\bot\\"))
{
if (!::std::strstr(pcszFileName, "sound/radio/bot/"))
{
bShouldBlock = { };
}
else
{
bShouldBlock = true;
}
}
else
{
bShouldBlock = true;
}
}
else
{
bShouldBlock = true;
}
}
else
{
bShouldBlock = true;
}
}
else
{
bShouldBlock = { };
}
}
else
{
bShouldBlock = { };
}
}
else
{
bShouldBlock = { };
}
}
else
{
bShouldBlock = { };
}
if (!::g_bNoReturn)
{
do
{
::gpMetaGlobals->mres = ((bShouldBlock) ? (::MRES_SUPERCEDE) : (::MRES_IGNORED));
if (((::gpMetaGlobals)->orig_ret))
{
if (bShouldBlock)
{
return { };
}
return (*(unsigned char**) ::gpMetaGlobals->orig_ret);
}
else
{
return { };
}
return { };
}
while (false);
}
else
{
return { };
}
return { };
}
I use bot_chatter off setting and I don't need talkable bots. I use this Meta Mod hook above as is. And return false; into the custom hook for: int __cdecl UTIL_IsGame(const char * gameName) call inside function int __cdecl BotPhraseManager::Initialize (BotPhraseManager * this, char * a2, int a3).
To hook functions (not sub-functions) on Windows/ Linux you can use https://github.com/Zeex/subhook To hook functions (not sub-functions) on Windows you can use https://github.com/microsoft/Detours
This should really be a pull request