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:
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 :/
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++):
mov ecx, thisptr;
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:
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:
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:
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:
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:
void S_SwitchTeam(CBaseEntity* thisptr, int iTeamIndex)
g_pGlobals->m_engine->Con_NPrintf(0, "m_SwitchTeam failed!");
void* func = (void*)m_SwitchTeam;
mov ecx, thisptr;
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:
I hope this helped!