Quote:
Originally Posted by robot
Thanks for the fast response there! Unfortunately, for whatever reason - that sig is not working for me.
The plugin certainly finds it, but after loading, the server dies and goes into loop (although I probably need to debug a bit more to confirm exactly what is happening). I will try to debug it further on my end - but was wondering if you have confirmed that this is indeed the correct function and it is callable...?
Basically to explain a bit more, the last Valve update killed my plugin. The sig I was using was:
Code:
\x83\xEC\x10\x56\x57\x8B\x7C\x24\x1C\x57\x8B\xF1\xE8\xDF\x4D\xF9
However now I cannot find the correct one. I should also mention my code is quite old ( http://zombiehorde.svn.sourceforge.n...nk/zhplug-1.1/) and may have other issues - although it did was working up until last update :/
robot
|
EDIT:
This is a windows signature, not a Linux one
Yes. I test every single signature I create. That signature worked for me when I used it (which was right before submitting my post), so I'm sure it's the way you are using the signature. Remember that this signature is a __thiscall, which means you need to pass in a this-pointer as the first parameter in the function. Then, inside the function, you need to do the following with the __asm keyword if you are using windows (if you are using c++):
Code:
__asm {
push ecx;
mov ecx, thisptr;
push iTeamIndex;
call thesignaturefunction;
pop ecx;
};
To use signatures, I use something LDuke taught me, which he was shown by Cybermind.
Essentially, take a look at the declaration of the function. In this case, it has one parameter, int iTeamIndex. It's also a __thiscall which means that you need a pointer to an instance of CCSPlayer. If you take a look at the class heirarchy, CCSPlayer is also an instance of CBaseEntity. So from an edict_t* you do ->GetUnknown()->GetBaseEntity(); Use that as your this-pointer.
Now, create a typedef for the function, inside your code. The syntax works like this:
Code:
typedef <return-type> (<callingconvention> *<SomeName>) (<param1 type>, <param2 type>, ..etc..)
With the above, if your calling convention is anything other than a __fastcall, you do not need to put a calling convention there
.
So with CCSPlayer::SwitchTeam:
Code:
typedef void (*SwitchTeam)(CBaseEntity*, int);
Next, what I do in my code is I have a class which manages my signatures. Inside it, I create an instance of the typedef in my class's private member variables section:
Code:
private:
SwitchTeam m_SwitchTeam;
.
Finally, I have a global instance of the signature scanner (I use BAILOPAN's). I have a function called Initialize() in my manager class, which I call when metamod loads. I then do the following for each "function type members" that I showed you above:
Code:
m_SwitchTeam = (SwitchTeam)g_SigMngr.ResolveSig(laddr, Signature, Signature_Length);
Finally, you need to call your newfound function! In my manager class, I have callable functions for each signature. In this case, since we have a __thiscall, you need to move the this pointer into the ecx register, and push all the parameters into the stack left to right. This is why I put the thispointer (the CBaseEntity* instance) first
. So the code:
Code:
void S_SwitchTeam(CBaseEntity* thisptr, int iTeamIndex)
{
if(!m_SwitchTeam)
{
g_pGlobals->m_engine->Con_NPrintf(0, "m_SwitchTeam failed!");
return;
}
void* func = (void*)m_SwitchTeam;
#ifdef _WIN32
__asm {
push ecx;
mov ecx, thisptr;
push iTeamIndex;
call func;
pop ecx;
};
#else
(m_SwitchTeam)(thisptr, iTeamIndex);
#endif
}
And that's it! You can apply the same principles for pretty much any other thiscall (I haven't run into any exceptions. Also, on a side note, I am signature scanning for classes in CS:S. I have written up a page on CCSPlayer if you want to take a look:
http://wiki.alliedmods.net/CCSPlayer
I hope this helped!