Skip to content

Instantly share code, notes, and snippets.

@iamgreaser
Created October 18, 2011 09:27
Show Gist options
  • Save iamgreaser/1295043 to your computer and use it in GitHub Desktop.
Save iamgreaser/1295043 to your computer and use it in GitHub Desktop.
aimblock for pyspades - an aimbot detector
# AImBlock - aimbot detection script
#
# The point of this script is to detect aimbots
# WITHOUT resorting to a hit-to-miss ratio.
#
# Current detection methods:
# - if one changes target, determine how accurate the gun is with respect to the head
# - if one gets a lot of kills quickly it will warn the admins over IRC
#
# There are more possible methods that can be used, but for now, this should work.
# I'm a bit worried about false positives though.
#
# - Ben "GreaseMonkey" Russell
from twisted.internet import reactor
import commands
# disable if you don't want to see all the jerk information
AIMBLOCK_SPAM = True
# disable if you don't want to kick people who jerk conviniently onto their targets
AIMBLOCK_KICK_JERK = True
def aimbotcheck(connection, user, minutes):
connection = commands.get_player(connection.protocol, user)
if connection not in connection.protocol.players:
raise KeyError()
kills = connection.tally_kill_log(reactor.seconds() - int(minutes)*60)
return ('Player %s did %s kills in the last %s minutes.' %
(connection.name, kills, minutes))
commands.add(aimbotcheck)
def apply_script(protocol, connection, config):
def aimblock(f):
def _f1(self, *args, **kwargs):
if self.aimbot_detect:
return f(self, *args, **kwargs)
return _f1
class AImBlockConnection(connection):
aimbot_detect = True
aimbot_heur_max = 0.8
aimbot_heur_jerk = 0.45
aimbot_heur_leeway = 0.9
aimbot_heuristic = 0.0
aimbot_target = None
aimbot_orient_uv = (1.0, 0.0, 0.0)
aimbot_kill_time = 30.0
aimbot_kill_count = 10.0
aimbot_kill_log = None
aimbot_kill_warn_last = -3000.0
aimbot_kill_warn_pause = 30.0
def aimbot_record_kill(self):
curkill = reactor.seconds()
if self.aimbot_kill_log == None:
self.aimbot_kill_log = []
self.aimbot_kill_log.append(curkill)
if self.tally_kill_log(self.aimbot_kill_time) >= self.aimbot_kill_count:
self.aimbot_trywarn()
def tally_kill_log(self, seconds):
if self.aimbot_kill_log == None:
return 0
i = -1
while i >= -len(self.aimbot_kill_log):
t = self.aimbot_kill_log[i]
if t < seconds:
break
i -= 1
return -1-i
def aimbot_trywarn(self):
curtime = reactor.seconds()
if curtime < self.aimbot_kill_warn_last+self.aimbot_kill_warn_pause:
return
self.aimbot_kill_warn_last = curtime
aimwarn = "AIMBOT WARNING: Player \"%s\" got %d kills in the last %d seconds!" % (
self.name, self.tally_kill_log(self.aimbot_kill_time), self.aimbot_kill_time
)
self.protocol.irc_say(aimwarn)
def on_kill(self, killer):
if killer != None and killer != self:
killer.aimbot_record_kill()
def loader_received(self, loader):
ret = connection.loader_received(self, loader)
if not self.aimbot_detect:
return ret
chtarg = False
if self.hp:
if self.player_id is not None:
chtarg = True
self.recalc_orient_uv()
if chtarg:
self.get_aimbot_target()
return ret
def sub_vec(self, (x1, y1, z1), (x2, y2, z2)):
return ((x1-x2),(y1-y2),(z1-z2))
def calc_uv(self, (x, y, z)):
d = (x*x + y*y + z*z)**0.5
if d <= 0.001:
d = 0.001
x /= d
y /= d
z /= d
return (x,y,z)
def recalc_orient_uv(self):
ox, oy, oz = self.world_object.orientation.get()
self.aimbot_orient_uv = self.calc_uv((ox, oy, oz))
def dot_product(self, v1, v2):
x1, y1, z1 = v1
x2, y2, z2 = v2
return x1*x2 + y1*y2 + z1*z2
@aimblock
def get_aimbot_target(self):
oldtarget = self.aimbot_target
# find best target
ftarg = None
fdist = 0.0
locpos = self.world_object.position.get()
for pid in xrange(32):
if pid not in self.protocol.players:
continue
p = self.protocol.players[pid]
if pid == self.player_id:
continue
if p.team == self.team:
continue
xpos = p.world_object.position.get()
xdist = self.dot_product(
self.calc_uv(self.sub_vec(xpos,locpos)),
self.aimbot_orient_uv
)
if xdist > fdist:
ftarg = p
fdist = xdist
# if we haven't found one, return
if ftarg == None:
return
# do a quick unit vector check
# TODO: proper triangulation check
odist = 0.0
if oldtarget != None:
opos = oldtarget.world_object.position.get()
odist = self.dot_product(
self.calc_uv(self.sub_vec(opos,locpos)),
self.aimbot_orient_uv
)
if (oldtarget != None and oldtarget != ftarg
and odist < self.aimbot_heur_leeway):
self.aimbot_heuristic += (
(fdist-self.aimbot_heuristic)
* self.aimbot_heur_jerk
)
if AIMBLOCK_SPAM:
print "Jerk test: %.5f -> %.5f" % (
fdist, self.aimbot_heuristic)
self.aimbot_target = ftarg
self.aimblock_try_complain()
@aimblock
def aimblock_try_complain(self):
if self.aimbot_heuristic >= self.aimbot_heur_max:
if AIMBLOCK_KICK_JERK:
self.on_hack_attempt('Aimbot detected')
else:
self.aimbot_trywarn()
return protocol, AImBlockConnection
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment