old version code:
PHP Code:
CreteSurvivorBot()
{
int bot = CreateFakeClient("fake");
ChangeClientTeam(bot, 2);
KickClient(bot);
//the bot index is invalid. because bot was disconnected.
//we can't write code, like that:
if(!IsPlayerAlive(bot))
{
//this is mistake, can't exec here
//ba la ba la ...
}
}
public Action:OnClientPutInServer(int _iClientIndex)
{
//We need judgment this bot was created by we are
//write code
// ba la ba la ...
}
now. using my extensions.
PHP Code:
#include <CreateSurvivorBot>
int Test()
{
int index = CreateSurvivorBot();
if(IsValidEntity(index))
{
PrintToServer("Created SurvivorBot:%d", index);
//ba la ba la ... write code
return index;
}
return -1;
}
inc file:
PHP Code:
#if defined _CreateSurvivorBot_included
#endinput
#endif
#define _CreateSurvivorBot_included
enum TEAMNUMBER
{
TEAM_SPECTATOR = 1,
TEAM_SURVIVORS,
TEAM_INFECTED
};
native int NextBotCreatePlayerBotSurvivorBot(const char[] _szName);
native bool HandleCommand_JoinTeam(int _iClientIndex, TEAMNUMBER _iTeam,int _iSurvivorCharacter, bool _bForcedJoinSurvivor);
native bool CTerrorPlayerRoundRespawn(int _iClientIndex);
stock int CreateSurvivorBot(bool _bForcedJoinSurvivor = true)
{
int bot = NextBotCreatePlayerBotSurvivorBot("");
if(IsValidEntity(bot))
{
if( HandleCommand_JoinTeam(bot, TEAM_SURVIVORS, 0, _bForcedJoinSurvivor) )
{
if(!IsPlayerAlive(bot))
{
CTerrorPlayerRoundRespawn(bot);
}
return bot;
}
}
return -1;
}
#if !defined REQUIRE_EXTENSIONS
public __ext_rare_SetNTVOptional()
{
MarkNativeAsOptional("HandleCommand_JoinTeam");
MarkNativeAsOptional("NextBotCreatePlayerBotSurvivorBot");
MarkNativeAsOptional("CTerrorPlayerRoundRespawn");
}
#endif
/**
* Do not edit below this line!
*/
public Extension __ext_CreateSurvivorBot =
{
name = "CreateSurvivorBot",
file = "CreateSurvivorBot.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};
Game Signatures:
PHP Code:
"Games"
{
"left4dead2"
{
"Signatures"
{
/* IDA Tag: */
/* IDA Code: */
/* C++ Function: */
/* Search string: */
/* Windows signature: */
/* Finally: */
/* Version: */
/*
* Where call this function:
*
*/
"template"
{
"library" ""
"windows" ""
"linux" "@"
}
/* IDA Tag: CTerrorPlayer::HandleCommand_JoinTeam(int, SurvivorCharacterType, bool) */
/* IDA Code: int __cdecl CTerrorPlayer::HandleCommand_JoinTeam(CBaseEntity *a1, int a2, int a3, char a4) */
/* C++ Function: bool __thiscall CTerrorPlayer::HandleCommand_JoinTeam(CBaseEntity *_pEntity, int _iTeam, int _iSurvivorCharacter, bool _bForcedJoinSurvivorTeam) */
/* Search string: (SKIN) Survivor %s changed model from %s to %s via HandleCommand_JoinTeam */
/* Windows signature: 55 8B EC 56 57 8B F1 E8 ?? ?? ?? ?? 8B 7D 08 3B C7 75 08 5F B0 01 5E 5D C2 0C 00 */
/* Finally: 55 8B EC 56 57 8B F1 E8 ?? ?? ?? ?? 8B 7D 08 3B */
/* Version: 2209 */
/*
* Where call this function:
* CDirector::AddSurvivorBot(SurvivorCharacterType)
* It's not explicit, virtual function: offset(2252) (*(_DWORD *)v4 + 2252))(v4,2 * (v2 > 3) + 2,v2,0)
*/
"HandleCommand_JoinTeam"
{
"library" "server"
"windows" "\x55\x8B\xEC\x56\x57\x8B\xF1\xE8****\x8B\x7D\x08\x3B"
"linux" "@_ZN13CTerrorPlayer22HandleCommand_JoinTeamEi21SurvivorCharacterTypeb"
}
/* IDA Tag: NextBotCreatePlayerBot<SurvivorBot>(char const*) */
/* IDA Code: CBaseEntity* __cdecl NextBotCreatePlayerBot<SurvivorBot>(char *src) */
/* C++ Function: CBaseEntity* __cdecl NextBotCreatePlayerBotSurvivorBot(const char *src) */
/* Search string: CreatePlayerBot: Could not Instance() from the bot edict */
/* Windows signature: (so crazy->to long)55 8B EC 83 EC 28 A1 ?? ?? ?? ?? 33 C5 89 45 FC 56 57 8B 7D 08 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 8B 01 8B 90 DC 00 00 00 83 C4 04 57 FF D2 6A 00 8B F0 E8 ?? ?? ?? ?? 83 C4 04 85 F6 75 21 57 */
/* Windows signature2: 33 C0 6A 00 68 FC ?? ?? ?? 68 ?? ?? ?? ?? 6A 00 50 E8 ?? ?? ?? ?? 8B F0 83 C4 14 85 F6 75 20 68 ?? ?? ?? ?? FF 15 */
/* Windows signature3: E8 ?? ?? ?? ?? 83 C4 08 85 C0 74 1C 8B 10 8B 92 this signature into <CDirector::AddSurvivorBot> */
/* Finally: 33 C0 6A 00 68 FC (warning:0xFC may be change when next game version) */
/* Version: 2209 */
/*
* Where call this function:
* RestoreTransitionedSurvivorBots(void); CDirector::AddSurvivorBot(SurvivorCharacterType)
*/
"NextBotCreatePlayerBot<SurvivorBot>"
{
"library" "server"
"windows" "\xE8****\x83\xC4\x08\x85\xC0\x74\x1C"// (addr+5) + *(addr+1) = call function addr -> this signature into <CDirector::AddSurvivorBot>
"linux" "@_Z22NextBotCreatePlayerBotI11SurvivorBotEPT_PKc"
}
/* IDA Tag: CTerrorPlayer::RoundRespawn(void) */
/* IDA Code: int __usercall CTerrorPlayer::RoundRespawn@<eax>(long double a1@<st0>, CTerrorPlayer *this) */
/* C++ Function: void* __thiscall CTerrorPlayer::RoundRespawn(CBaseEntity*) */
/*
* Search string: Through "playercontrolledzombies" to find function < CTerrorGameRules::HasPlayerControlledZombies >
* function < CTerrorPlayer::RoundRespawn(void) > on the inside call the function < CTerrorGameRules::HasPlayerControlledZombies >
* you need search this function < CTerrorGameRules::HasPlayerControlledZombies > , one by one for match linux's function < CTerrorPlayer::RoundRespawn(void) >
*/
/* Windows signature: 56 8B F1 E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 75 07 8B CE E8 ?? ?? ?? ?? C6 86 75 3E 00 00 00 */
/* Finally: 56 8B F1 E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 75 */
/* Version: 2209 */
/*
* Where call this function:
* windows: 8B 06 8B 90 08 08 00 00 8B CE FF D2 B0 01 5E 5D C2 04 00 CC < call edx > < edx = (*pEntity)+0x808 > OllyDebug breakpoint
*/
"CTerrorPlayer::RoundRespawn"
{
"library" "server"
"windows" "\x56\x8B\xF1\xE8****\xE8****\x84\xC0\x75"
"linux" "@_ZN13CTerrorPlayer12RoundRespawnEv"
}
}
}
}
Update 12/18/2020
For Windows:
Signature of NextBotCreatePlayerBot<SurvivorBot> changed.
The CreateSurvivorBot.ext.2.l4d2.dll changed.
The signature in the next version should not change. The premise is CDirector::AddSurvivorBot() function will not be modified by valve.
Game Version: 2209
build:
Visual Studio 2013
sdk:
amtl
sourcepawn-1.10-dev
metamod-source-1.11-dev
sourcemod-1.10-dev
hl2sdk-l4d2
if you need other version. you have to compile by yourself