Scripts:TK punish announcer
Introduction
One of the major frustrations in BF2 is the often observed abuse of the PTK function. Since it is so easily available, many people punish others for TKs even when it's their own fault. At Battlefield.no we do not accept this behaviour, but it can be very hard for admins to take notice of people doing this. We have therefore made a modification to the tk_punish.py-script which is included with BF2.
Features
For each player a running tally of the number of forgives and punishes is kept. Whenever someone punishes a TK, a global announcement is made on the server indicating how many punishes and forgives this person has made. This makes it easy to spot people abusing the PTK-system.
This script is a drop-in replacement for the original tk_punish.py which comes with BF2. It is based on the script from the 1.12 release (build 1.1.2554-356). No functionality of the original script has been removed, so this script should be allowed on ranked servers.
Getting started
Copy the script from below and replace your current tk_punish.py which you can find under bf2/admin/standard_admin. Remember to make a backup of the original script first!
The code
The code # tk punish system import bf2 import host from bf2 import g_debug TK_PUNISH_TIME = 20 TK_PUNISH_COMMANDID = 100 TK_FORGIVE_COMMANDID = 101 hasPendingTks = {} updateTimer = None class TkData: def __init__(self): self.punished = 0 self.pending = [] self.lastTKedBy = None self.givenPunish = 0 # bf.no modification self.givenForgive = 0 # bf.no modification def init(): if g_debug: print "initializing tk-punish script" host.registerHandler('PlayerConnect', onPlayerConnect, 1) host.registerHandler('PlayerKilled', onPlayerKilled) host.registerHandler('ClientCommand', onClientCommand) # Connect already connected players if reinitializing for p in bf2.playerManager.getPlayers(): onPlayerConnect(p) checkEnable() def checkEnable(): global updateTimer if not bf2.serverSettings.getTKPunishEnabled(): if updateTimer: updateTimer.destroy() updateTimer = None return False else: if not updateTimer: #if g_debug: print "Started timer" updateTimer = bf2.Timer(onUpdate, 10, 1) updateTimer.setRecurring(10) return True def onUpdate(data): if not checkEnable(): return global hasPendingTks #if len(hasPendingTks) > 0: # if g_debug: print "update: Has pending tks!" #else: # if g_debug: print "update:No pending tks." currentTime = host.timer_getWallTime() newPending = {} for attacker in hasPendingTks.iterkeys(): newList = [] #if g_debug: print "attacker pending list:", len(attacker.tkData.pending) for tk in attacker.tkData.pending: tkDate = tk[0] tkVictim = tk[1] #if g_debug: print "check %d %s" % (tkDate, tkVictim.getName()) # if there is a pending TK with time expired if tkDate + TK_PUNISH_TIME < currentTime: if bf2.serverSettings.getTKPunishByDefault(): attacker.tkData.punished += 1 checkPunishLimit(attacker) # bf.no addons: tkVictim.tkData.givenPunish += 1 result = host.rcon_invoke('game.sayAll "TKPUNISH: %s punishes %s for teamkill (%s has %d punishes and %d forgives)"' % (tkVictim.getName(), attacker.getName(), tkVictim.getName(), tkVictim.tkData.givenPunish, tkVictim.tkData.givenForgive)) # ************* # if g_debug: print "Default punished ", attacker.getName() else: # bf.no addons: tkVictim.tkData.givenForgive += 1 # if g_debug: print "Timeouted pending tk for ", attacker.getName() # pass # remove player from global list, if it was the last tk if len(attacker.tkData.pending) == 1: pass else: newPending[attacker] = 1 else: newList += [tk] newPending[attacker] = 1 attacker.tkData.pending = newList hasPendingTks = newPending def checkPunishLimit(player): #if g_debug: print "player %s has %d punishes" % (player.getName(), player.tkData.punished) if player.tkData.punished >= bf2.serverSettings.getTKNumPunishToKick(): if g_debug: print "%s reached punish limit" % player.getName() if g_debug: print "Banning player!" result = host.rcon_invoke("admin.banPlayerKey " + str(player.index) + " Round") # event actions def onPlayerConnect(player): player.tkData = TkData() def onClientCommand(command, issuer, args): if not checkEnable(): return #if g_debug: print "received client command" if command == TK_PUNISH_COMMANDID: executePunishAction(issuer, True) elif command == TK_FORGIVE_COMMANDID: executePunishAction(issuer, False) def onPlayerKilled(victim, attacker, weapon, assists, object): if not checkEnable(): return if not victim or not attacker or victim == attacker or victim.getTeam() != attacker.getTeam(): return # verify that TK was really given # no teamkills from wrecks if object != None and object.getIsWreck(): return # no teamkills from artillery if weapon: attackerVehicle = bf2.objectManager.getRootParent(weapon) if attackerVehicle.isPlayerControlObject and attackerVehicle.getIsRemoteControlled(): return # ok, we have a teamkill currentTime = host.timer_getWallTime() attacker.tkData.pending += [(currentTime, victim)] hasPendingTks[attacker] = 1 victim.tkData.lastTKedBy = attacker # can only punish / forgive the last TK'er bf2.gameLogic.sendClientCommand(victim.index, 100, (2, victim.index, attacker.index, TK_PUNISH_TIME)) def executePunishAction(victim, punish): if not checkEnable() or not victim or not victim.isValid(): return attacker = victim.tkData.lastTKedBy if attacker == None or not attacker.isValid(): return global hasPendingTks if punish: if g_debug: print "%s tkPunished %s" % (victim.getName(), attacker.getName()) else: if g_debug: print "%s tkForgive %s" % (victim.getName(), attacker.getName()) currentTime = host.timer_getWallTime() newList = [] for tk in attacker.tkData.pending: tkDate = tk[0] tkVictim = tk[1] # if the attacker had a pending tk, and time has not run out if tkVictim == victim and tkDate + TK_PUNISH_TIME > currentTime: if punish: attacker.tkData.punished += 1 bf2.gameLogic.sendClientCommand(-1, 100, (0, victim.index, attacker.index)) # 100 = tkpunish event, 0 = punish if g_debug: print "%s punished %s, now has %d punishes" % (victim.getName(), attacker.getName(), attacker.tkData.punished) # bf.no addons: victim.tkData.givenPunish += 1 result = host.rcon_invoke('game.sayAll "TKPUNISH: %s punishes %s for teamkill (%s has %d punishes and %d forgives)"' % (victim.getName(), attacker.getName(), victim.getName(), victim.tkData.givenPunish, victim.tkData.givenForgive)) # ************* else: bf2.gameLogic.sendClientCommand(-1, 100, (1, victim.index, attacker.index)) # 100 = tkpunish event, 1 = forgive if g_debug: print "%s forgave %s" % (victim.getName(), attacker.getName()) # bf.no addons: victim.tkData.givenForgive += 1 else: newList += [tk] attacker.tkData.pending = newList if len(attacker.tkData.pending) == 0: del hasPendingTks[attacker] checkPunishLimit(attacker)