[SCRIPT] Anti-Hack script by Yourself

Intended for use on live public servers.
6 posts Page 1 of 1 First unread post
Lincent
Veterans
Veterans
Posts: 693
Joined: Wed Mar 27, 2013 9:47 pm


From wayback in January 2012, this script should still work, Download and Instructions below.

New Experimental Version: http://pastebin.com/5J4REyhz
First Version: https://raw.github.com/matpow2/pyspades ... aimbot2.py

PLEASE READ THE CONFIGURATION CAREFULLY BEFORE YOU RUN THIS SCRIPT

The anti-aimbot script statistically analyzes player behavior to kick or ban aimbots. The description of all the configuration options are all commented in the script.

Here is a brief overview of the different detection methods using the default values. The values are of course completely configurable.
  • Headshot snap detection: Kick/ban if the player's orientation changes more than 90 degrees to align with the head of an enemy 6 or more times in 20 seconds
  • Hit percent: Kick/ban if hit accuracy exceeds 90% (rifle), 80% (smg), or 90% (shotgun) and the minimum number of shots is met (45 rifle, 90 smg, 45 shotgun)
  • Detect damage hack: Invalid damage values are ignored. The current aimbot doesn't actually modify the damage values, but keep this on just in case.
  • Detect kills in time: Kick/ban the player if they kill 15 enemies in 20 seconds (grenade and airstrike kills don't count)
  • Detect multiple bullets: Kick/ban the player if the server receives 8 or more hit packets in 0.25 seconds (rifle) or 0.05 seconds (smg). Note that this method should kick aimbotters with 100% accuracy with an extremely small chance of false positives.
This script also contains a command available to all players to check on how accurate someone's shots are. The name parameter is optional.
Code: Select all
/accuracy name

What should I do if I'm worried about false positives?
Feel free to change the configuration of the script to your liking. For the person extremely paranoid about false positives, I recommend this setting:
Code: Select all
DETECT_SNAP_HEADSHOT = True
DETECT_HIT_PERCENT = False
DETECT_DAMAGE_HACK = True
DETECT_KILLS_IN_TIME = False
DETECT_MULTIPLE_BULLETS = True
vvV#NEW#Vvv
LONG_RANGE = True
Updated version of this script with Foglinedetection.
Code: Select all
from twisted.internet.task import LoopingCall
from pyspades.constants import *
from math import sqrt, cos, acos, pi, tan
from commands import add, admin, get_player
from twisted.internet import reactor
from pyspades.collision import distance_3d_vector
from pyspades.server import position_data
from commands import name, get_player, add, admin, alias
import commands
import re

DISABLED, KICK, BAN, WARN_ADMIN = xrange(4)

# This is an option for data collection. Data is outputted to aimbot2log.txt
DATA_COLLECTION = True

# This controls which detection methods are enabled. If a player is detected
# using one of these methods, the player is kicked.
HEADSHOT_SNAP = KICK
HIT_PERCENT = WARN_ADMIN
KILLS_IN_TIME = WARN_ADMIN
MULTIPLE_BULLETS = BAN
LONG_RANGE = BAN

DETECT_DAMAGE_HACK = True

# Minimum amount of time that must pass between admin warnings that are
# triggered by the same detection method. Time is in seconds.
WARN_INTERVAL_MINIMUM = 100

# These controls are only used if banning is enabled
# Time is given in minutes. Set to 0 for a permaban
HEADSHOT_SNAP_BAN_DURATION = 0
HIT_PERCENT_BAN_DURATION = 5
KILLS_IN_TIME_BAN_DURATION = 5
MULTIPLE_BULLETS_BAN_DURATION = 0
LONG_RANGE_BAN_DURATION = 0

# If more than or equal to this number of weapon hit packets are recieved
# from the client in half the weapon delay time, then an aimbot is detected.
# This method of detection should have 100% detection and no false positives
# with the current aimbot.
# Note that the current aimbot does not modify the number of bullets
# of the shotgun, so this method will not work if the player uses a shotgun.
# These values may need to be changed if an update to the aimbot is released.
RIFLE_MULTIPLE_BULLETS_MAX = 8
SMG_MULTIPLE_BULLETS_MAX = 12

# The minimum number of near misses + hits that are fired before kicking, 
# banning, or warning an admin about someone using the hit percentage check
RIFLE_KICK_MINIMUM = 45
SMG_KICK_MINIMUM = 90
SHOTGUN_KICK_MINIMUM = 45

# Kick, ban, or warn when the above minimum is met and the
# bullet hit percentage is greater than or equal to this amount
RIFLE_KICK_PERC = 0.90
SMG_KICK_PERC = 0.80
SHOTGUN_KICK_PERC = 0.90

# If a player gets more kills than the KILL_THRESHOLD in the given
# KILL_TIME, kick, ban, or warn. This check is performed every
# time somebody kills someone with a gun
KILL_TIME = 20.0
KILL_THRESHOLD = 15

# If the number of headshot snaps exceeds the HEADSHOT_SNAP_THRESHOLD in the
# given HEADSHOT_SNAP_TIME, kick, ban, or warn. This check is performed every
# time somebody performs a headshot snap
HEADSHOT_SNAP_TIME = 20.0
HEADSHOT_SNAP_THRESHOLD = 6

# When the user's orientation angle (degrees) changes more than this amount,
# check if the user snapped to an enemy's head. If it is aligned with a head,
# record this as a headshot snap
HEADSHOT_SNAP_ANGLE = 90.0

# A near miss occurs when the player is NEAR_MISS_ANGLE degrees or less off
# of an enemy
NEAR_MISS_ANGLE = 10.0

# Valid damage values for each gun
RIFLE_DAMAGE = (33, 49, 100)
SMG_DAMAGE = (18, 29, 75)
SHOTGUN_DAMAGE = (16, 27, 37)

# Approximate size of player's heads in blocks
HEAD_RADIUS = 0.7

# 128 is the approximate fog distance, but bump it up a little
# just in case
FOG_DISTANCE = 135.0

# Don't touch any of this stuff
FOG_DISTANCE2 = FOG_DISTANCE**2
NEAR_MISS_COS = cos(NEAR_MISS_ANGLE * (pi/180.0))
HEADSHOT_SNAP_ANGLE_COS = cos(HEADSHOT_SNAP_ANGLE * (pi/180.0))

aimbot_pattern = re.compile(".*(aim|bot|ha(ck|x)|cheat).*", re.IGNORECASE)

def aimbot_match(msg):
    return (not aimbot_pattern.match(msg) is None)

def point_distance2(c1, c2):
    if c1.world_object is not None and c2.world_object is not None:
        p1 = c1.world_object.position
        p2 = c2.world_object.position
        return (p1.x - p2.x)**2 + (p1.y - p2.y)**2 + (p1.z - p2.z)**2

def dot3d(v1, v2):
    return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]

def magnitude(v):
    return sqrt(v[0]**2 + v[1]**2 + v[2]**2)

def scale(v, scale):
    return (v[0]*scale, v[1]*scale, v[2]*scale)

def subtract(v1, v2):
    return (v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2])

def accuracy(connection, name = None):
    if name is None:
        player = connection
    else:
        player = get_player(connection.protocol, name)
    return accuracy_player(player)

def accuracy_player(player, name_info = True):
    if player.rifle_count != 0:
        rifle_percent = str(int(100.0 * (float(player.rifle_hits)/float(player.rifle_count)))) + '%'
    else:
        rifle_percent = 'None'
    if player.smg_count != 0:
        smg_percent = str(int(100.0 * (float(player.smg_hits)/float(player.smg_count)))) + '%'
    else:
        smg_percent = 'None'
    if player.shotgun_count != 0:
        shotgun_percent = str(int(100.0 * (float(player.shotgun_hits)/float(player.shotgun_count)))) + '%'
    else:
        shotgun_percent = 'None'
    s = ''
    if name_info:
        s += player.name + ' has an accuracy of: '
    s += 'Rifle: %s SMG: %s Shotgun: %s.' % (rifle_percent, smg_percent, shotgun_percent)
    return s

add(accuracy)

@admin
def hackinfo(connection, name):
    player = get_player(connection.protocol, name)
    return hackinfo_player(player)

def hackinfo_player(player):
    info = "%s #%s (%s) has an accuracy of: " % (player.name, player.player_id, player.address[0])
    info += accuracy_player(player, False)
    ratio = player.ratio_kills/float(max(1,player.ratio_deaths))
    info += " Kill-death ratio of %.2f (%s kills, %s deaths)." % (ratio, player.ratio_kills, player.ratio_deaths)
    info += " %i kills in the last %i seconds." % (player.get_kill_count(), KILL_TIME)
    info += " %i headshot snaps in the last %i seconds." % (player.get_headshot_snap_count(), HEADSHOT_SNAP_TIME)
    return info

add(hackinfo)

def apply_script(protocol, connection, config):
    class Aimbot2Protocol(protocol):
        def start_votekick(self, payload):
            if aimbot_match(payload.reason):
                payload.target.warn_admin('Hack related votekick.')
            return protocol.start_votekick(self, payload)

    class Aimbot2Connection(connection):
        def __init__(self, *arg, **kw):
            connection.__init__(self, *arg, **kw)
            self.rifle_hits = self.smg_hits = self.shotgun_hits = 0
            self.rifle_count = self.smg_count = self.shotgun_count = 0
            self.last_target = None
            self.first_orientation = True
            self.kill_times = []
            self.headshot_snap_times = []
            self.bullet_loop = LoopingCall(self.on_bullet_fire)
            self.shot_time = 0.0
            self.multiple_bullets_count = 0
            self.headshot_snap_warn_time = self.hit_percent_warn_time = 0.0
            self.kills_in_time_warn_time = self.multiple_bullets_warn_time = 0.0

        def warn_admin(self, prefix = 'Possible aimbot detected.'):
            prefix += ' '
            message = hackinfo_player(self)
            for player in self.protocol.players.values():
                if player.admin:
                    player.send_chat(prefix + message)
            irc_relay = self.protocol.irc_relay
            if irc_relay:
                if irc_relay.factory.bot and irc_relay.factory.bot.colors:
                    prefix = '\x0304' + prefix + '\x0f'
                irc_relay.send(prefix + message)
        
        def on_spawn(self, pos):
            self.first_orientation = True
            return connection.on_spawn(self, pos)

        def bullet_loop_start(self, interval):
            if not self.bullet_loop.running:
                self.bullet_loop.start(interval)
        
        def bullet_loop_stop(self):
            if self.bullet_loop.running:
                self.bullet_loop.stop()
        
        def get_headshot_snap_count(self):
            pop_count = 0
            headshot_snap_count = 0
            current_time = reactor.seconds()
            for old_time in self.headshot_snap_times:
                if current_time - old_time <= HEADSHOT_SNAP_TIME:
                    headshot_snap_count += 1
                else:
                    pop_count += 1
            for i in xrange(0, pop_count):
                self.headshot_snap_times.pop(0)
            return headshot_snap_count

        def on_orientation_update(self, x, y, z):
            if not self.first_orientation and self.world_object is not None:
                orient = self.world_object.orientation
                old_orient_v = (orient.x, orient.y, orient.z)
                new_orient_v = (x, y, z)
                theta = dot3d(old_orient_v, new_orient_v)
                if theta <= HEADSHOT_SNAP_ANGLE_COS:
                    self_pos = self.world_object.position
                    for enemy in self.team.other.get_players():
                        enemy_pos = enemy.world_object.position
                        position_v = (enemy_pos.x - self_pos.x, enemy_pos.y - self_pos.y, enemy_pos.z - self_pos.z)
                        c = scale(new_orient_v, dot3d(new_orient_v, position_v))
                        h = magnitude(subtract(position_v, c))
                        if h <= HEAD_RADIUS:
                            current_time = reactor.seconds()
                            self.headshot_snap_times.append(current_time)
                            if self.get_headshot_snap_count() >= HEADSHOT_SNAP_THRESHOLD:
                                if HEADSHOT_SNAP == BAN:
                                    self.ban('Aimbot detected - headshot snap', HEADSHOT_SNAP_BAN_DURATION)
                                    return
                                elif HEADSHOT_SNAP == KICK:
                                    self.kick('Aimbot detected - headshot snap')
                                    return
                                elif HEADSHOT_SNAP == WARN_ADMIN:
                                    if (current_time - self.headshot_snap_warn_time) > WARN_INTERVAL_MINIMUM:
                                        self.headshot_snap_warn_time = current_time
                                        self.warn_admin()
            else:
                self.first_orientation = False
            return connection.on_orientation_update(self, x, y, z)
        
        def on_shoot_set(self, shoot):
            if self.tool == WEAPON_TOOL:
                if shoot and not self.bullet_loop.running:
                    self.possible_targets = []
                    for enemy in self.team.other.get_players():
                        if point_distance2(self, enemy) <= FOG_DISTANCE2:
                            self.possible_targets.append(enemy)
                    self.bullet_loop_start(self.weapon_object.delay)
                elif not shoot:
                    self.bullet_loop_stop()
            return connection.on_shoot_set(self, shoot)
        
        def get_kill_count(self):
            current_time = reactor.seconds()
            kill_count = 0
            pop_count = 0
            for old_time in self.kill_times:
                if current_time - old_time <= KILL_TIME:
                    kill_count += 1
                else:
                    pop_count += 1
            for i in xrange(0, pop_count):
                self.kill_times.pop(0)
            return kill_count

        def on_kill(self, by, type, grenade):
            if by is not None and by is not self:
                if type == WEAPON_KILL or type == HEADSHOT_KILL:
                    by.kill_times.append(reactor.seconds())
                    if by.get_kill_count() >= KILL_THRESHOLD:
                        if KILLS_IN_TIME == BAN:
                            by.ban('Aimbot detected - kills in time window', KILLS_IN_TIME_BAN_DURATION)
                            return
                        elif KILLS_IN_TIME == KICK:
                            by.kick('Aimbot detected - kills in time window')
                            return
                        elif KILLS_IN_TIME == WARN_ADMIN:
                            current_time = reactor.seconds()
                            if (current_time - by.kills_in_time_warn_time) > WARN_INTERVAL_MINIMUM:
                                by.kills_in_time_warn_time = current_time
                                by.warn_admin()
            return connection.on_kill(self, by, type, grenade)

        def multiple_bullets_eject(self):
            if MULTIPLE_BULLETS == BAN:
                self.ban('Aimbot detected - multiple bullets', MULTIPLE_BULLETS_BAN_DURATION)
            elif MULTIPLE_BULLETS == KICK:
                self.kick('Aimbot detected - multiple bullets')
            elif MULTIPLE_BULLETS == WARN_ADMIN:
                current_time = reactor.seconds()
                if (current_time - self.multiple_bullets_warn_time) > WARN_INTERVAL_MINIMUM:
                    self.multiple_bullets_warn_time = current_time
                    self.warn_admin()

        def long_range_eject(self, accuracy):
            message = 'Aimbot detected - %i%% %s hit accuracy from 100 blocks or more' %\
                      (100.0 * accuracy, self.weapon_object.name)
            if LONG_RANGE == BAN:
                self.ban('Aimbot detected - message', LONG_RANGE_BAN_DURATION)
            elif LONG_RANGE == KICK:
                self.kick('Aimbot detected - message')
            elif LONG_RANGE == WARN_ADMIN:
                current_time = reactor.seconds()
                if (current_time - self.meow) > WARN_INTERVAL_MINIMUM:
                    self.meow = current_time
                    self.warn_admin()
               
        def apply_script(protocol, connection):

            class fogprotocol(protocol):

                distancealert = 127 # default distance for showing alerts, i prefer setting it to about 123, 126 is about the max range you can see (+10 if you include height)
#--------------------------------------------------------------------------------------------------------------------------------------------------------------            
# Foglinehitdetector.py by Dr.Morphman         
#--------------------------------------------------------------------------------------------------------------------------------------------------------------            
            class fogconnection(connection): # just some random note

                class helppoint(): # hmm too lazy
                    x = 0          # to check if
                    y = 0          # its better to
                    z = 0          # store it here, nah whatever

                def on_lrhit(self, lrhit_amount, lrhit_player, type, grenade):

                    lrhit_player.helppoint.x = lrhit_player.world_object.position.x
                    lrhit_player.helppoint.y = lrhit_player.world_object.position.y
                    lrhit_player.helppoint.z = self.world_object.position.z

                    distance = int(distance_3d_vector(self.world_object.position, lrhit_player.helppoint))               # phew and there i thought i had to calculate it manualy
                    meow = "Accurate long range hit detected: %s horizontal distance: %d blocks " % (self.name, distance)

                    if distance >= self.protocol.distancealert and distance <= 139 and grenade is None:           # i wonder if i should 
                        for players in self.protocol.players.values(long_range_eject):    # add something to make

            return connection.on_lrhit(self, lrhit_amount, lrhit_player, type, grenade) 

            return fogprotocol, fogconnection
   
#--------------------------------------------------------------------------------------------------------------------------------------------------------------                        
               
        def on_hit(self, hit_amount, hit_player, type, grenade):
            if self.team is not hit_player.team:
                if type == WEAPON_KILL or type == HEADSHOT_KILL:
                    current_time = reactor.seconds()
                    shotgun_use = False
                    if current_time - self.shot_time > (0.5 * hit_player.weapon_object.delay):
                        shotgun_use = True
                        self.multiple_bullets_count = 0
                        self.shot_time = current_time
                    if type == HEADSHOT_KILL:
                        self.multiple_bullets_count += 1
                    if self.weapon == RIFLE_WEAPON:
                        if (not (hit_amount in RIFLE_DAMAGE)) and DETECT_DAMAGE_HACK:
                            return False
                        else:
                            self.rifle_hits += 1
                            if self.multiple_bullets_count >= RIFLE_MULTIPLE_BULLETS_MAX:
                                self.multiple_bullets_eject()
                                return False
                    elif self.weapon == SMG_WEAPON:
                        if (not (hit_amount in SMG_DAMAGE)) and DETECT_DAMAGE_HACK:
                            return False
                        else:
                            self.smg_hits += 1
                            if self.multiple_bullets_count >= SMG_MULTIPLE_BULLETS_MAX:
                                self.multiple_bullets_eject()
                                return False
                    elif self.weapon == SHOTGUN_WEAPON:
                        if (not (hit_amount in SHOTGUN_DAMAGE)) and DETECT_DAMAGE_HACK:
                            return False
                        elif shotgun_use:
                            self.shotgun_hits += 1
            return connection.on_hit(self, hit_amount, hit_player, type, grenade)
        
        def hit_percent_eject(self, accuracy):
            message = 'Aimbot detected - %i%% %s hit accuracy' %\
                      (100.0 * accuracy, self.weapon_object.name)
            if HIT_PERCENT == BAN:
                self.ban(message, HIT_PERCENT_BAN_DURATION)
            elif HIT_PERCENT == KICK:
                self.kick(message)
            elif HIT_PERCENT == WARN_ADMIN:
                current_time = reactor.seconds()
                if (current_time - self.hit_percent_warn_time) > WARN_INTERVAL_MINIMUM:
                    self.hit_percent_warn_time = current_time
                    self.warn_admin()

        def check_percent(self):
            if self.weapon == RIFLE_WEAPON:
                rifle_perc = float(self.rifle_hits)/float(self.rifle_count)
                if self.rifle_count >= RIFLE_KICK_MINIMUM:
                    if rifle_perc >= RIFLE_KICK_PERC:
                        self.hit_percent_eject(rifle_perc)
            elif self.weapon == SMG_WEAPON:
                smg_perc = float(self.smg_hits)/float(self.smg_count)
                if self.smg_count >= SMG_KICK_MINIMUM:
                    if smg_perc >= SMG_KICK_PERC:
                        self.hit_percent_eject(smg_perc)
            elif self.weapon == SHOTGUN_WEAPON:
                shotgun_perc = float(self.shotgun_hits)/float(self.shotgun_count)
                if self.shotgun_count >= SHOTGUN_KICK_MINIMUM:
                    if shotgun_perc >= SHOTGUN_KICK_PERC:
                        self.hit_percent_eject(shotgun_perc)

        def on_bullet_fire(self):
            # Remembering the past offers a performance boost, particularly with the SMG
            if self.last_target is not None:
                if self.last_target.hp is not None:
                    if self.check_near_miss(self.last_target):
                        self.check_percent()
                        return
            for enemy in self.possible_targets:
                if enemy.hp is not None and enemy is not self.last_target:
                    if self.check_near_miss(enemy):
                        self.last_target = enemy
                        self.check_percent()
                        return

        def check_near_miss(self, target):
            if self.world_object is not None and target.world_object is not None:
                p_self = self.world_object.position
                p_targ = target.world_object.position
                position_v = (p_targ.x - p_self.x, p_targ.y - p_self.y, p_targ.z - p_self.z)
                orient = self.world_object.orientation
                orient_v = (orient.x, orient.y, orient.z)
                position_v_mag = magnitude(position_v)
                if position_v_mag != 0 and (dot3d(orient_v, position_v)/position_v_mag) >= NEAR_MISS_COS:
                    if self.weapon == RIFLE_WEAPON:
                        self.rifle_count += 1
                    elif self.weapon == SMG_WEAPON:
                        self.smg_count += 1
                    elif self.weapon == SHOTGUN_WEAPON:
                        self.shotgun_count += 1
                    return True
            return False
        
        # Data collection stuff
        def on_disconnect(self):
            self.bullet_loop_stop()
            if DATA_COLLECTION:
                if self.name != None:
                    with open('aimbot2log.txt','a') as myfile:
                        output = self.name.encode('ascii','ignore').replace(',','') + ','
                        output += str(self.rifle_hits) + ',' + str(self.rifle_count) + ','
                        output += str(self.smg_hits) + ',' + str(self.smg_count) + ','
                        output += str(self.shotgun_hits) + ',' + str(self.shotgun_count) + '\n'
                        myfile.write(output)
                        myfile.close()
            return connection.on_disconnect(self)
    
    return Aimbot2Protocol, Aimbot2Connection
Last edited by Lincent on Thu Sep 08, 2016 4:05 am, edited 6 times in total.
Zyc
Deuced Up
Posts: 83
Joined: Sun Dec 29, 2013 10:28 pm


Sounds great, but the "Detect kills in time" should be up to 20, cause anyways hackers will be banned by the other features of the script. Great job.
Lincent
Veterans
Veterans
Posts: 693
Joined: Wed Mar 27, 2013 9:47 pm


Turns out several servers use this but somehow hacks have found a way around this.
Zyc
Deuced Up
Posts: 83
Joined: Sun Dec 29, 2013 10:28 pm


That's why the community really needs to update the game to something like .80
The community has been playing for far too long on .75
Lincent
Veterans
Veterans
Posts: 693
Joined: Wed Mar 27, 2013 9:47 pm


I bet they just set the settings to warn instead of kick or ban.
As if they actually would do something, it worked on my server, however I recommend turning the warning limit down to about 50.
Lincent
Veterans
Veterans
Posts: 693
Joined: Wed Mar 27, 2013 9:47 pm


Quick update, added this script FoglineHitDetector to the script.
Spoiler:
Code: Select all
from twisted.internet.task import LoopingCall
from pyspades.constants import *
from math import sqrt, cos, acos, pi, tan
from commands import add, admin, get_player
from twisted.internet import reactor
from pyspades.collision import distance_3d_vector
from pyspades.server import position_data
from commands import name, get_player, add, admin, alias
import commands
import re

DISABLED, KICK, BAN, WARN_ADMIN = xrange(4)

# This is an option for data collection. Data is outputted to aimbot2log.txt
DATA_COLLECTION = True

# This controls which detection methods are enabled. If a player is detected
# using one of these methods, the player is kicked.
HEADSHOT_SNAP = KICK
HIT_PERCENT = WARN_ADMIN
KILLS_IN_TIME = WARN_ADMIN
MULTIPLE_BULLETS = BAN
LONG_RANGE = BAN

DETECT_DAMAGE_HACK = True

# Minimum amount of time that must pass between admin warnings that are
# triggered by the same detection method. Time is in seconds.
WARN_INTERVAL_MINIMUM = 100

# These controls are only used if banning is enabled
# Time is given in minutes. Set to 0 for a permaban
HEADSHOT_SNAP_BAN_DURATION = 0
HIT_PERCENT_BAN_DURATION = 5
KILLS_IN_TIME_BAN_DURATION = 5
MULTIPLE_BULLETS_BAN_DURATION = 0
LONG_RANGE_BAN_DURATION = 0

# If more than or equal to this number of weapon hit packets are recieved
# from the client in half the weapon delay time, then an aimbot is detected.
# This method of detection should have 100% detection and no false positives
# with the current aimbot.
# Note that the current aimbot does not modify the number of bullets
# of the shotgun, so this method will not work if the player uses a shotgun.
# These values may need to be changed if an update to the aimbot is released.
RIFLE_MULTIPLE_BULLETS_MAX = 8
SMG_MULTIPLE_BULLETS_MAX = 12

# The minimum number of near misses + hits that are fired before kicking, 
# banning, or warning an admin about someone using the hit percentage check
RIFLE_KICK_MINIMUM = 45
SMG_KICK_MINIMUM = 90
SHOTGUN_KICK_MINIMUM = 45

# Kick, ban, or warn when the above minimum is met and the
# bullet hit percentage is greater than or equal to this amount
RIFLE_KICK_PERC = 0.90
SMG_KICK_PERC = 0.80
SHOTGUN_KICK_PERC = 0.90

# If a player gets more kills than the KILL_THRESHOLD in the given
# KILL_TIME, kick, ban, or warn. This check is performed every
# time somebody kills someone with a gun
KILL_TIME = 20.0
KILL_THRESHOLD = 15

# If the number of headshot snaps exceeds the HEADSHOT_SNAP_THRESHOLD in the
# given HEADSHOT_SNAP_TIME, kick, ban, or warn. This check is performed every
# time somebody performs a headshot snap
HEADSHOT_SNAP_TIME = 20.0
HEADSHOT_SNAP_THRESHOLD = 6

# When the user's orientation angle (degrees) changes more than this amount,
# check if the user snapped to an enemy's head. If it is aligned with a head,
# record this as a headshot snap
HEADSHOT_SNAP_ANGLE = 90.0

# A near miss occurs when the player is NEAR_MISS_ANGLE degrees or less off
# of an enemy
NEAR_MISS_ANGLE = 10.0

# Valid damage values for each gun
RIFLE_DAMAGE = (33, 49, 100)
SMG_DAMAGE = (18, 29, 75)
SHOTGUN_DAMAGE = (16, 27, 37)

# Approximate size of player's heads in blocks
HEAD_RADIUS = 0.7

# 128 is the approximate fog distance, but bump it up a little
# just in case
FOG_DISTANCE = 135.0

# Don't touch any of this stuff
FOG_DISTANCE2 = FOG_DISTANCE**2
NEAR_MISS_COS = cos(NEAR_MISS_ANGLE * (pi/180.0))
HEADSHOT_SNAP_ANGLE_COS = cos(HEADSHOT_SNAP_ANGLE * (pi/180.0))

aimbot_pattern = re.compile(".*(aim|bot|ha(ck|x)|cheat).*", re.IGNORECASE)

def aimbot_match(msg):
    return (not aimbot_pattern.match(msg) is None)

def point_distance2(c1, c2):
    if c1.world_object is not None and c2.world_object is not None:
        p1 = c1.world_object.position
        p2 = c2.world_object.position
        return (p1.x - p2.x)**2 + (p1.y - p2.y)**2 + (p1.z - p2.z)**2

def dot3d(v1, v2):
    return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]

def magnitude(v):
    return sqrt(v[0]**2 + v[1]**2 + v[2]**2)

def scale(v, scale):
    return (v[0]*scale, v[1]*scale, v[2]*scale)

def subtract(v1, v2):
    return (v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2])

def accuracy(connection, name = None):
    if name is None:
        player = connection
    else:
        player = get_player(connection.protocol, name)
    return accuracy_player(player)

def accuracy_player(player, name_info = True):
    if player.rifle_count != 0:
        rifle_percent = str(int(100.0 * (float(player.rifle_hits)/float(player.rifle_count)))) + '%'
    else:
        rifle_percent = 'None'
    if player.smg_count != 0:
        smg_percent = str(int(100.0 * (float(player.smg_hits)/float(player.smg_count)))) + '%'
    else:
        smg_percent = 'None'
    if player.shotgun_count != 0:
        shotgun_percent = str(int(100.0 * (float(player.shotgun_hits)/float(player.shotgun_count)))) + '%'
    else:
        shotgun_percent = 'None'
    s = ''
    if name_info:
        s += player.name + ' has an accuracy of: '
    s += 'Rifle: %s SMG: %s Shotgun: %s.' % (rifle_percent, smg_percent, shotgun_percent)
    return s

add(accuracy)

@admin
def hackinfo(connection, name):
    player = get_player(connection.protocol, name)
    return hackinfo_player(player)

def hackinfo_player(player):
    info = "%s #%s (%s) has an accuracy of: " % (player.name, player.player_id, player.address[0])
    info += accuracy_player(player, False)
    ratio = player.ratio_kills/float(max(1,player.ratio_deaths))
    info += " Kill-death ratio of %.2f (%s kills, %s deaths)." % (ratio, player.ratio_kills, player.ratio_deaths)
    info += " %i kills in the last %i seconds." % (player.get_kill_count(), KILL_TIME)
    info += " %i headshot snaps in the last %i seconds." % (player.get_headshot_snap_count(), HEADSHOT_SNAP_TIME)
    return info

add(hackinfo)

def apply_script(protocol, connection, config):
    class Aimbot2Protocol(protocol):
        def start_votekick(self, payload):
            if aimbot_match(payload.reason):
                payload.target.warn_admin('Hack related votekick.')
            return protocol.start_votekick(self, payload)

    class Aimbot2Connection(connection):
        def __init__(self, *arg, **kw):
            connection.__init__(self, *arg, **kw)
            self.rifle_hits = self.smg_hits = self.shotgun_hits = 0
            self.rifle_count = self.smg_count = self.shotgun_count = 0
            self.last_target = None
            self.first_orientation = True
            self.kill_times = []
            self.headshot_snap_times = []
            self.bullet_loop = LoopingCall(self.on_bullet_fire)
            self.shot_time = 0.0
            self.multiple_bullets_count = 0
            self.headshot_snap_warn_time = self.hit_percent_warn_time = 0.0
            self.kills_in_time_warn_time = self.multiple_bullets_warn_time = 0.0

        def warn_admin(self, prefix = 'Possible aimbot detected.'):
            prefix += ' '
            message = hackinfo_player(self)
            for player in self.protocol.players.values():
                if player.admin:
                    player.send_chat(prefix + message)
            irc_relay = self.protocol.irc_relay
            if irc_relay:
                if irc_relay.factory.bot and irc_relay.factory.bot.colors:
                    prefix = '\x0304' + prefix + '\x0f'
                irc_relay.send(prefix + message)
        
        def on_spawn(self, pos):
            self.first_orientation = True
            return connection.on_spawn(self, pos)

        def bullet_loop_start(self, interval):
            if not self.bullet_loop.running:
                self.bullet_loop.start(interval)
        
        def bullet_loop_stop(self):
            if self.bullet_loop.running:
                self.bullet_loop.stop()
        
        def get_headshot_snap_count(self):
            pop_count = 0
            headshot_snap_count = 0
            current_time = reactor.seconds()
            for old_time in self.headshot_snap_times:
                if current_time - old_time <= HEADSHOT_SNAP_TIME:
                    headshot_snap_count += 1
                else:
                    pop_count += 1
            for i in xrange(0, pop_count):
                self.headshot_snap_times.pop(0)
            return headshot_snap_count

        def on_orientation_update(self, x, y, z):
            if not self.first_orientation and self.world_object is not None:
                orient = self.world_object.orientation
                old_orient_v = (orient.x, orient.y, orient.z)
                new_orient_v = (x, y, z)
                theta = dot3d(old_orient_v, new_orient_v)
                if theta <= HEADSHOT_SNAP_ANGLE_COS:
                    self_pos = self.world_object.position
                    for enemy in self.team.other.get_players():
                        enemy_pos = enemy.world_object.position
                        position_v = (enemy_pos.x - self_pos.x, enemy_pos.y - self_pos.y, enemy_pos.z - self_pos.z)
                        c = scale(new_orient_v, dot3d(new_orient_v, position_v))
                        h = magnitude(subtract(position_v, c))
                        if h <= HEAD_RADIUS:
                            current_time = reactor.seconds()
                            self.headshot_snap_times.append(current_time)
                            if self.get_headshot_snap_count() >= HEADSHOT_SNAP_THRESHOLD:
                                if HEADSHOT_SNAP == BAN:
                                    self.ban('Aimbot detected - headshot snap', HEADSHOT_SNAP_BAN_DURATION)
                                    return
                                elif HEADSHOT_SNAP == KICK:
                                    self.kick('Aimbot detected - headshot snap')
                                    return
                                elif HEADSHOT_SNAP == WARN_ADMIN:
                                    if (current_time - self.headshot_snap_warn_time) > WARN_INTERVAL_MINIMUM:
                                        self.headshot_snap_warn_time = current_time
                                        self.warn_admin()
            else:
                self.first_orientation = False
            return connection.on_orientation_update(self, x, y, z)
        
        def on_shoot_set(self, shoot):
            if self.tool == WEAPON_TOOL:
                if shoot and not self.bullet_loop.running:
                    self.possible_targets = []
                    for enemy in self.team.other.get_players():
                        if point_distance2(self, enemy) <= FOG_DISTANCE2:
                            self.possible_targets.append(enemy)
                    self.bullet_loop_start(self.weapon_object.delay)
                elif not shoot:
                    self.bullet_loop_stop()
            return connection.on_shoot_set(self, shoot)
        
        def get_kill_count(self):
            current_time = reactor.seconds()
            kill_count = 0
            pop_count = 0
            for old_time in self.kill_times:
                if current_time - old_time <= KILL_TIME:
                    kill_count += 1
                else:
                    pop_count += 1
            for i in xrange(0, pop_count):
                self.kill_times.pop(0)
            return kill_count

        def on_kill(self, by, type, grenade):
            if by is not None and by is not self:
                if type == WEAPON_KILL or type == HEADSHOT_KILL:
                    by.kill_times.append(reactor.seconds())
                    if by.get_kill_count() >= KILL_THRESHOLD:
                        if KILLS_IN_TIME == BAN:
                            by.ban('Aimbot detected - kills in time window', KILLS_IN_TIME_BAN_DURATION)
                            return
                        elif KILLS_IN_TIME == KICK:
                            by.kick('Aimbot detected - kills in time window')
                            return
                        elif KILLS_IN_TIME == WARN_ADMIN:
                            current_time = reactor.seconds()
                            if (current_time - by.kills_in_time_warn_time) > WARN_INTERVAL_MINIMUM:
                                by.kills_in_time_warn_time = current_time
                                by.warn_admin()
            return connection.on_kill(self, by, type, grenade)

        def multiple_bullets_eject(self):
            if MULTIPLE_BULLETS == BAN:
                self.ban('Aimbot detected - multiple bullets', MULTIPLE_BULLETS_BAN_DURATION)
            elif MULTIPLE_BULLETS == KICK:
                self.kick('Aimbot detected - multiple bullets')
            elif MULTIPLE_BULLETS == WARN_ADMIN:
                current_time = reactor.seconds()
                if (current_time - self.multiple_bullets_warn_time) > WARN_INTERVAL_MINIMUM:
                    self.multiple_bullets_warn_time = current_time
                    self.warn_admin()

        def long_range_eject(self, accuracy):
            message = 'Aimbot detected - %i%% %s hit accuracy from 100 blocks or more' %\
                      (100.0 * accuracy, self.weapon_object.name)
            if LONG_RANGE == BAN:
                self.ban('Aimbot detected - message', LONG_RANGE_BAN_DURATION)
            elif LONG_RANGE == KICK:
                self.kick('Aimbot detected - message')
            elif LONG_RANGE == WARN_ADMIN:
                current_time = reactor.seconds()
                if (current_time - self.meow) > WARN_INTERVAL_MINIMUM:
                    self.meow = current_time
                    self.warn_admin()
					
        def apply_script(protocol, connection):

            class fogprotocol(protocol):

                distancealert = 127 # default distance for showing alerts, i prefer setting it to about 123, 126 is about the max range you can see (+10 if you include height)
#--------------------------------------------------------------------------------------------------------------------------------------------------------------				
# Foglinehitdetector.py by Dr.Morphman			
#--------------------------------------------------------------------------------------------------------------------------------------------------------------				
            class fogconnection(connection): # just some random note

                class helppoint(): # hmm too lazy
                    x = 0          # to check if
                    y = 0          # its better to
                    z = 0          # store it here, nah whatever

                def on_lrhit(self, lrhit_amount, lrhit_player, type, grenade):

                    lrhit_player.helppoint.x = lrhit_player.world_object.position.x
                    lrhit_player.helppoint.y = lrhit_player.world_object.position.y
                    lrhit_player.helppoint.z = self.world_object.position.z

                    distance = int(distance_3d_vector(self.world_object.position, lrhit_player.helppoint))               # phew and there i thought i had to calculate it manualy
                    meow = "Accurate long range hit detected: %s horizontal distance: %d blocks " % (self.name, distance)

                    if distance >= self.protocol.distancealert and distance <= 139 and grenade is None:           # i wonder if i should 
                        for players in self.protocol.players.values(long_range_eject):    # add something to make

				return connection.on_lrhit(self, lrhit_amount, lrhit_player, type, grenade) 

            return fogprotocol, fogconnection
   
#--------------------------------------------------------------------------------------------------------------------------------------------------------------								
					
        def on_hit(self, hit_amount, hit_player, type, grenade):
            if self.team is not hit_player.team:
                if type == WEAPON_KILL or type == HEADSHOT_KILL:
                    current_time = reactor.seconds()
                    shotgun_use = False
                    if current_time - self.shot_time > (0.5 * hit_player.weapon_object.delay):
                        shotgun_use = True
                        self.multiple_bullets_count = 0
                        self.shot_time = current_time
                    if type == HEADSHOT_KILL:
                        self.multiple_bullets_count += 1
                    if self.weapon == RIFLE_WEAPON:
                        if (not (hit_amount in RIFLE_DAMAGE)) and DETECT_DAMAGE_HACK:
                            return False
                        else:
                            self.rifle_hits += 1
                            if self.multiple_bullets_count >= RIFLE_MULTIPLE_BULLETS_MAX:
                                self.multiple_bullets_eject()
                                return False
                    elif self.weapon == SMG_WEAPON:
                        if (not (hit_amount in SMG_DAMAGE)) and DETECT_DAMAGE_HACK:
                            return False
                        else:
                            self.smg_hits += 1
                            if self.multiple_bullets_count >= SMG_MULTIPLE_BULLETS_MAX:
                                self.multiple_bullets_eject()
                                return False
                    elif self.weapon == SHOTGUN_WEAPON:
                        if (not (hit_amount in SHOTGUN_DAMAGE)) and DETECT_DAMAGE_HACK:
                            return False
                        elif shotgun_use:
                            self.shotgun_hits += 1
            return connection.on_hit(self, hit_amount, hit_player, type, grenade)
        
        def hit_percent_eject(self, accuracy):
            message = 'Aimbot detected - %i%% %s hit accuracy' %\
                      (100.0 * accuracy, self.weapon_object.name)
            if HIT_PERCENT == BAN:
                self.ban(message, HIT_PERCENT_BAN_DURATION)
            elif HIT_PERCENT == KICK:
                self.kick(message)
            elif HIT_PERCENT == WARN_ADMIN:
                current_time = reactor.seconds()
                if (current_time - self.hit_percent_warn_time) > WARN_INTERVAL_MINIMUM:
                    self.hit_percent_warn_time = current_time
                    self.warn_admin()

        def check_percent(self):
            if self.weapon == RIFLE_WEAPON:
                rifle_perc = float(self.rifle_hits)/float(self.rifle_count)
                if self.rifle_count >= RIFLE_KICK_MINIMUM:
                    if rifle_perc >= RIFLE_KICK_PERC:
                        self.hit_percent_eject(rifle_perc)
            elif self.weapon == SMG_WEAPON:
                smg_perc = float(self.smg_hits)/float(self.smg_count)
                if self.smg_count >= SMG_KICK_MINIMUM:
                    if smg_perc >= SMG_KICK_PERC:
                        self.hit_percent_eject(smg_perc)
            elif self.weapon == SHOTGUN_WEAPON:
                shotgun_perc = float(self.shotgun_hits)/float(self.shotgun_count)
                if self.shotgun_count >= SHOTGUN_KICK_MINIMUM:
                    if shotgun_perc >= SHOTGUN_KICK_PERC:
                        self.hit_percent_eject(shotgun_perc)

        def on_bullet_fire(self):
            # Remembering the past offers a performance boost, particularly with the SMG
            if self.last_target is not None:
                if self.last_target.hp is not None:
                    if self.check_near_miss(self.last_target):
                        self.check_percent()
                        return
            for enemy in self.possible_targets:
                if enemy.hp is not None and enemy is not self.last_target:
                    if self.check_near_miss(enemy):
                        self.last_target = enemy
                        self.check_percent()
                        return

        def check_near_miss(self, target):
            if self.world_object is not None and target.world_object is not None:
                p_self = self.world_object.position
                p_targ = target.world_object.position
                position_v = (p_targ.x - p_self.x, p_targ.y - p_self.y, p_targ.z - p_self.z)
                orient = self.world_object.orientation
                orient_v = (orient.x, orient.y, orient.z)
                position_v_mag = magnitude(position_v)
                if position_v_mag != 0 and (dot3d(orient_v, position_v)/position_v_mag) >= NEAR_MISS_COS:
                    if self.weapon == RIFLE_WEAPON:
                        self.rifle_count += 1
                    elif self.weapon == SMG_WEAPON:
                        self.smg_count += 1
                    elif self.weapon == SHOTGUN_WEAPON:
                        self.shotgun_count += 1
                    return True
            return False
        
        # Data collection stuff
        def on_disconnect(self):
            self.bullet_loop_stop()
            if DATA_COLLECTION:
                if self.name != None:
                    with open('aimbot2log.txt','a') as myfile:
                        output = self.name.encode('ascii','ignore').replace(',','') + ','
                        output += str(self.rifle_hits) + ',' + str(self.rifle_count) + ','
                        output += str(self.smg_hits) + ',' + str(self.smg_count) + ','
                        output += str(self.shotgun_hits) + ',' + str(self.shotgun_count) + '\n'
                        myfile.write(output)
                        myfile.close()
            return connection.on_disconnect(self)
    
    return Aimbot2Protocol, Aimbot2Connection
6 posts Page 1 of 1 First unread post
Return to “Completed Releases”

Who is online

Users browsing this forum: No registered users and 5 guests