Zeex/sampgdk — Issue #7: Custom hooked native gets called every second?
Author: grasmanek94
Created: 2012-03-01 00:10:00+00:00
State: open

I have a weird problem,
I cut out the code from sscanf that hooks SetPlayerName, I edited it to hook 2 functions: GetPlayerMoney and SetPlayerMoney.

After a player joins the GetPlayerMoney functions is ran every second with the joined players id (didn't test on 1+ players).

the code I use is:

// From "amx.c", part of the PAWN language runtime:
// http://code.google.com/p/pawnscript/source/browse/trunk/amx/amx.c

#define USENAMETABLE(hdr) \
((hdr)->defsize==sizeof(AMX_FUNCSTUBNT))

#define NUMENTRIES(hdr,field,nextfield) \
(unsigned)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize)

#define GETENTRY(hdr,table,index) \
(AMX_FUNCSTUB *)((unsigned char*)(hdr) + (unsigned)(hdr)->table + (unsigned)index*(hdr)->defsize)

#define GETENTRYNAME(hdr,entry) \
(USENAMETABLE(hdr) ? \
(char *)((unsigned char*)(hdr) + (unsigned)((AMX_FUNCSTUBNT*)(entry))->nameofs) : \
((AMX_FUNCSTUB*)(entry))->name)

//AMX_NATIVE
//	x_GivePlayerMoney;
//AMX_NATIVE
//	x_GetPlayerMoney;

static cell AMX_NATIVE_CALL
n_GivePlayerMoney(AMX * amx, cell * params)
{
if(params[1] < 0 || params[1] >= MAX_PLAYERS)return 0;
PlayerMoney[params[1]] += params[2];
//cout << "vcalled!\n";
return GivePlayerMoney(params[1],PlayerMoney[params[1]]-GetPlayerMoney(params[1]));
}

static cell AMX_NATIVE_CALL
n_GetPlayerMoney(AMX * amx, cell * params)
{
cout << "gcalled id: " << params[1] << " params0: " << params[0] << " AMX script: " << amx << "\n";
if(params[1] < 0 || params[1] >= MAX_PLAYERS)return 0;
//cout << "gcalled!\n";
return PlayerMoney[params[1]];
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx )
{
//Code from sscanf2.5, [PAWN]SSCANF Author: Y_Less
int
num,
idx;
// Operate on the raw AMX file, don't use the amx_ functions to avoid issues
// with the fact that we've not actually finished initialisation yet. Based
// VERY heavilly on code from "amx.c" in the PAWN runtime library.
AMX_HEADER *
hdr = (AMX_HEADER *)amx->base;
AMX_FUNCSTUB *
func;
num = NUMENTRIES(hdr, natives, libraries);
bool found[2] = {false,false};
for (idx = 0; idx != num; ++idx)
{
func = GETENTRY(hdr, natives, idx);
if (!strcmp("GetPlayerMoney", GETENTRYNAME(hdr, func)))
{
// Intercept the call!
//x_GetPlayerMoney = (AMX_NATIVE)func->address;
func->address = (ucell)n_GetPlayerMoney;
found[0] = true;
}
if (!strcmp("GivePlayerMoney", GETENTRYNAME(hdr, func)))
{
// Intercept the call!
//x_GivePlayerMoney = (AMX_NATIVE)func->address;
func->address = (ucell)n_GivePlayerMoney;
found[1] = true;
}
if(found[0] == true && found[1] == true)break;
}
//End of sscanf cut
amx_list.push_back(amx);
return amx_Register( amx, AMXNatives, -1 );
}

I cannot reproduce the problem with normal sscanf 2.5 with the setplayername function, it's not getting called every second but just when really called.
If you need to inspect the whole plugin please download AntiCheat_22.zip from gpb.googlecode.com.
Thanks :)