103 lines
3.0 KiB
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;
|
|
}
|