q2wf-portable/zbotcheck.c

103 lines
3.0 KiB
C

/*============================================================================
ZbotCheck v1.01 for Quake 2 by Matt "WhiteFang" Ayres (matt@lithium.com)
This is provided for mod authors to implement Zbot detection, nothing more.
The code has so far proven to be reliable at detecting Zbot auto-aim clients
(cheaters). However, no guarantees of any kind are made. This is provided
as-is. You must be familiar with Quake 2 mod coding to make use of this.
In g_local.h, add to struct client_respawn_t:
short angles[2][2];
int tog;
int jitter;
float jitter_time;
float jitter_last;
Next, in p_client.c, add a simple forward declaration:
qboolean ZbotCheck(edict_t *ent, usercmd_t *ucmd);
Then in p_client.c, anywhere in the ClientThink function, call the
ZbotCheck function. Pass it the same parameters you get from ClientThink.
It will return true if the client is using a Zbot. Simple example:
if(ZbotCheck(ent, ucmd))
gi.bprintf(PRINT_HIGH, ">>> Zbot detected: %s\n",
ent->client->pers.netname);
From here you can do as you please with the cheater. ZbotCheck will only
return true once, following returns will be false.
============================================================================*/
#include "g_local.h"
#define ZBOT_JITTERMAX 4
#define ZBOT_JITTERTIME 10
#define ZBOT_JITTERMOVE 500
//Set this player as a zbot, and mess with them
//This is to help solve problem where you can't actually kick them off server
void I_AM_A_ZBOT(edict_t *ent)
{
//stuffcmd(ent, "disconnect\n"); // kick out zbots.
//Really mess them up
ent->movetype = MOVETYPE_NOCLIP;
ent->client->pers.feign = 1;
ent->client->pers.i_am_a_bot = 1;
VectorClear (ent->avelocity);
ent->takedamage = DAMAGE_YES;
ent->s.modelindex2 = 0; // remove linked weapon model
ent->s.angles[0] = 0;
ent->s.angles[2] = 0;
ent->s.sound = 0;
ent->client->weapon_sound = 0;
ent->maxs[2] = -8;
ent->viewheight = 0;
ent->flags |= FL_NO_KNOCKBACK;
// stop running/footsteps
VectorClear (ent->velocity);
//dont keep firing/no model to fire/model removed from player view
ent->client->pers.lastweapon = ent->client->pers.weapon;
ent->client->pers.weapon = NULL;// needed?
ent->client->ps.gunindex = 0;
}
qboolean ZbotCheck(edict_t *ent, usercmd_t *ucmd) {
int tog0, tog1;
client_respawn_t *resp = &ent->client->resp;
tog0 = resp->tog;
resp->tog ^= 1;
tog1 = resp->tog;
if(ucmd->angles[0] == resp->angles[tog1][0] &&
ucmd->angles[1] == resp->angles[tog1][1] &&
ucmd->angles[0] != resp->angles[tog0][0] &&
ucmd->angles[1] != resp->angles[tog0][1] &&
abs(ucmd->angles[0] - resp->angles[tog0][0]) +
abs(ucmd->angles[1] - resp->angles[tog0][1]) >= ZBOT_JITTERMOVE) {
if(level.time <= resp->jitter_last + 0.1) {
if(!resp->jitter)
resp->jitter_time = level.time;
if(++resp->jitter == ZBOT_JITTERMAX)
return true;
}
resp->jitter_last = level.time;
}
resp->angles[tog1][0] = ucmd->angles[0];
resp->angles[tog1][1] = ucmd->angles[1];
if(level.time > resp->jitter_time + ZBOT_JITTERTIME)
resp->jitter = 0;
return false;
}