Scripts:TK punish announcer
Contents |
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
# 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)