AC Sourcecode tells us:
Code:
playerent *ge***ient(int cn) // ensure valid entity
{
return players.inrange(cn) ? players[cn] : NULL;
}
void ini***ient()
{
clientmap[0] = 0;
newname("unarmed");
changeteam(rnd(2), false);
}
We wan't ge***ient, but that has nothing easy to search for...
Lets take ini***ient, which has "unarmed"!
Rough estimation of what we will encounter:
1. the string "unarmed" will be somewhere near the top of the function
2. near the bottom we should find something to do with teams.
RVSF and CLA are the team names in AC, so we'll encounter one of those probably.
First unarmed I encountered with olly contined stuff with 'your current name is', so, its not the one we want.
But the second unarmed I find is a whole lot more interesting!
It contains both unarmed and team related stuff
Now if you scroll up a bit from there, you'll see this function:
Code:
004205C0 /$ 85C0 TEST EAX,EAX
004205C2 |. 7C 12 JL SHORT ac_clien.004205D6
004205C4 |. 3B05 983C4D00 CMP EAX,DWORD PTR DS:[4D3C98]
004205CA |. 7D 0A JGE SHORT ac_clien.004205D6
004205CC |. 8B0D 903C4D00 MOV ECX,DWORD PTR DS:[4D3C90]
004205D2 |. 8B0481 MOV EAX,DWORD PTR DS:[ECX+EAX*4]
004205D5 |. C3 RETN
004205D6 |> 33C0 XOR EAX,EAX
004205D8 \. C3 RETN
now compare that to this:
Code:
playerent *ge***ient(int cn) // ensure valid entity
{
return players.inrange(cn) ? players[cn] : NULL;
}
Did we just find ourselves the function???
YES!
First off eax is tested against itself, and its followed JL(jump if lower), thts probably because there are no players for negative indexes.
next off its compared to the value at DWORD pointer 0x4D3C98, and then tested with JGE(jump if greater/equal)
Which is because there are no players after playercount-1, so if the index specified is equal to the playercount or bigger, we return 0.
Now
0x4D3C90 is moved into ECX, thats the base address for the player list.
Now take a look at this:
Code:
MOV EAX,DWORD PTR DS:[ECX+EAX*4]
What do you think that does?
if you didnt think 'oh, they add the index we specified * 4 because a pointer is 4 bytes on my 32 bit OS to the base address we just saw', then you're either a retard or you suck at assembly.
Anyway, its exactly what I just written above. They take the base pointer 0x4D3C90, add 4*index to it to get the pointer of the player we want.
Now finally some C++ code:
Code:
int playercount = *(DWORD*)0x004D3C98;
for(int i = 0; i < playercount-1; i++)
{
DWORD pTable = *(DWORD*)0x004D3C90;
playerent *pPlayer = (playerent*)(pTable+(0x4*playercount));
pPlayer->health = 0;
}
Feel free to add this to the AssaultCube tutorials posted by Hell_Demon(kinda weird to talk about yourself in third person o__O)
edit: the *** is t-c-l, no idea why they block it...