This snippet friendly fire on the pyro's flamethrower, if mp_friendlyfire is set to 1. This is because Valve are doing a check further down and line and I'm not going to break half the game to give friendlyfire to one weapon. (Okay, I might, but not now.)
As a disclaimer, I'm putting this here for others who are looking for it. I am working on something with it in it, whether I finish it or get bored by something else shiny, I don't know ...
I didn't even find
this request until I'd been hacking away on something totally unrelated (duel related), but I'm set
Game Data ... works as of ... well, now.
PHP Code:
// CTFFlameEntity::OnCollide(CBaseEntity *)
"CTFFlameEntity_OnCollide"
{
"library" "server"
"windows" "\x81\xEC\xA8\x00\x00\x00\x56\x8B\xF1\x8B\x86\xFC\x00\x00\x00\xC1\xE8\x0B\xA8\x01\x57"
"linux" "@_ZN14CTFFlameEntity9OnCollideEP11CBaseEntity"
}
// CTFFlameEntity::OnCollideWithTeammate(CTFPlayer *)
"CTFFlameEntity_OnCollideWithTeammate"
{
"library" "server"
"windows" "\x56\x8B\x74\x24\x08\x57\x8B\xF9\x6A\x2A\x8B\xCE\x2A\x2A\x2A\x2A\x2A\x84\xC0\x2A\x2A\x2A\x2A\x2A\x2A\x85\xF6\x2A\x2A\x8B\x06\x8B\x50\x08\x8B\xCE\xFF\xD2\x8B\x00\x89\x44\x24\x0C\x2A\x2A"
"linux" "@_ZN14CTFFlameEntity21OnCollideWithTeammateEP9CTFPlayer"
}
The detour...
PHP Code:
DETOUR_DECL_MEMBER1(CTFFlameEntity_OnCollideWithTeammate, int, CBaseEntity*, pPlayer)
{
/* Get the original result */
int TeamCollision = DETOUR_MEMBER_CALL(CTFFlameEntity_OnCollideWithTeammate)(pPlayer);
char *addr;
if(!g_pGameConf->GetMemSig("CTFFlameEntity_OnCollide", (void **)&addr) || !addr)
{
// If it goes pear-shaped, bail by performing the default function
META_CONPRINTF("Could not find signature for 'CTFFlameEntity_OnCollide'.\n");
return TeamCollision;
}
/* predcrab to the rescue -- this calls CTFFlameEntity::OnCollide using |this|, with platform specific code. */
union
{
int (VEmptyClass::*mfpOnCollide)(CBaseEntity *pPlayer);
#ifndef PLATFORM_POSIX
void *addr;
} u;
u.addr = addr;
#else
struct
{
void *addr;
intptr_t adjustor;
} s;
} u;
u.s.addr = addr;
u.s.adjustor = 0;
#endif
return (reinterpret_cast<VEmptyClass *>(this)->*u.mfpOnCollide)(pPlayer);
/* end predcrab to the rescue */
}
If you want to do what I'm doing in my extension then you need a cvar (enable/disable) or two (enable/disable flamethrower "modes"). You can then check for the cvar values and do whatever you want based on that.
If my extension is disabled it kills all cvars (atm), though I'm thinking of working out a mode of individual functions (based on mode cvars and callbacks).
You can additionally detour OnCollide, if you wish to disable all damage, and just return 0 on both.
While I did find the sigs on my own, there are some people who deserve thanks...
- predcrab - for providing a large chunk of the code and helping me get the detour working;
- asherkin - for basically re-teaching me more than I've forgotten about C++, and helping me debug various parts of this, and teaching me to find sigs;
- psychonic, and Wazz - for explaining things to me and teaching me to find sigs in a sensible way.