After studying the cod4x source for a few hours i found a way to get a client's real fps in cod2.
Basically, this hooks every call the code makes when a client issues a SV_ClientThink() command serverside (this happens for each client frame).
This way, you can not only get a client's real fps (which is unspoofable), but also detect if a client has major fps drops (and maybe adjust his settings on the fly to counter this?)
patch:
libcod.cpp:
(cod2 1.3 only)Code:cHook *hook_clientmovethink; void clientmovethink(int a1, int a2, int a3) { extern int playerinfo_size; int clid = (a1 - *(int*)0x842308C) / playerinfo_size; //is svs.clients clfpstemp[clid]++; hook_clientmovethink->unhook(); int (*sig)(int a1, int a2, int a3); *(int *)&sig = hook_clientmovethink->from; int ret = sig(a1, a2, a3); hook_clientmovethink->hook(); } ... hook_clientmovethink = new cHook(0x8090DAC, (int) clientmovethink); hook_clientmovethink->hook();
player.cpp:
with appropriate changes to player.hpp and gsc.cpp to support this.Code:int clfps[64][20]; int clfpstemp[64]; int clfpsindex = 0; void gsc_player_resetfps(int id) { for(int i = 0; i < sizeof(clfps[0]) / sizeof(int); i++) clfps[id][i] = -1; clfpstemp[id] = 0; stackPushInt(0); } void gsc_player_getfps(int id) { int total = 0; for(int i = 0; i < sizeof(clfps[0]) / sizeof(int); i++) { if(clfps[id][i] == -1) { stackPushInt(-1); return; } total += clfps[id][i]; } stackPushInt(total); } void gsc_player_fpsnextframe() { for(int i = 0; i < sizeof(clfpstemp) / sizeof(int); i++) { clfps[i][clfpsindex] = clfpstemp[i]; clfpstemp[i] = 0; } clfpsindex++; if(clfpsindex >= sizeof(clfps[0]) / sizeof(int)) clfpsindex = 0; stackPushInt(0); }
gsc code: call resetfps() when a client joins, call fpsnextframe() on each new frame and use getfps() to obtain a client's current fps.
The fps returned is filtered through a 20-frame moving-average filter and is pretty darn accurate.

Reply With Quote