Scripts:Enhanced TK Script in ModManager format
From BF2 Technical Information Wiki
Contents |
What It Is
BF2CC/ModManager port of Enhanced TK Script by FBX, McAfee
Installation
Copy the script from below and replace your current mm_tk_punish.py file. Remember to make a backup of the original script first!
Code
Readable
# tk punish system
# Modifed by McAfee (JoseStefan@hotmail.com)
# Also modified by [FBX] Rubber Bullets
# original version 2005.06.28
# current version: 0.9
# converted into ModManager format by graag42 (2005.12.20 v2)
import bf2
import host
from bf2 import g_debug
__version__ = 0.9
__required_modules__ = {
'modmanager': 1.0
}
__supports_reload__ = True
__description__ = "ModManager Team kill punish system v%s" % __version__
TK_PUNISH_TIME = 20
TK_PUNISH_COMMANDID = 100
TK_FORGIVE_COMMANDID = 101
# This Determines which system of TK management you want to use:
TK_ZTMOD_USERATIO = 0 # 0 uses pardon system, 1 uses ratio system
# The following pertains to both methods of TK management
TK_ZTMOD_FILTERWEAPONS = True # Ignores some TKs depending on type of TK.
TK_ZTMOD_PASSIVEWEAPONS = 2 # Max number of TKs your allowed to deal out in a round from kills by a passive weapon
# F35B MEC mig SU34 F18 J10
forgivenWeapons = ('AIR_F35B_SidewinderLauncher', 'ruair_archerlauncher', 'ruair_su34_archerlauncher', 'F18_SidewinderLauncher', 'AIR_J10_ArcherLauncher', 'AIR_SU30MKK_ArcherLauncher', 'AAV_Type95_QW2Launcher', 'USAIR_F15_SidewinderLauncher', 'USAAV_M6_Stinger_Launcher', 'USAAS_Stinger_Launcher', 'aav_tunguska_SA19Lanucher', 'aas_seasparrow', 'igla_djigit_Launcher')
passiveWeapons = ('at_mine', 'usmin_claymore', 'USART_LS155_Barrel', 'ARS_D30_Barrel')
# The following pertains only if pardon system is used.
TK_KILLS_UNTIL_PARDON = 5
# The following pertains only if the ratio system is used.
# TK Ratio is set with: sv.tkNumPunishToKick
# Sets how many Enemy Kills are required per TK.
# 1 being more forgiving, and 10 being less tolerant.
TK_ZTMOD_SCOREKICK = -30 # Similar to the PunkBuster Feature.
TK_ZTMOD_WAIT = 5 # How many TKs to wait before considering the TK Ratio.
TK_ZTMOD_PUNISHBONUS = 3 # Punish Votes available at beginning of round.
TK_ZTMOD_PUNISHPERCENT = 25 # Percent of Score awarded as more Punish Votes.
# The following pertain to debug only and shouldn't be changed
# ... actually changing this doesnt really do anything
TK_ZTMOD_DEBUG = 0
hasPendingTks = {}
updateTimer = None
class TkData:
def __init__(self):
self.punisher = 0
self.punished = 0
self.pending = []
self.lastTKedBy = None
self.tkpardon = TK_KILLS_UNTIL_PARDON
self.tkpassive = 0
self.lastweapon = None
class Punisher ( object ):
def __init__( self, modManager ):
"""Create a new instance."""
self.mm = modManager
self.__state = 0
def init( self ):
if g_debug: print "initializing tk-punish script"
"""Provides default initialisation."""
#self.__config = self.mm.getModuleConfig( configDefaults )
#self.punishTime = self.__config['punishTime']
self.hasPendingTks = {}
self.updateTimer = None
if 0 == self.__state:
host.registerHandler('PlayerConnect', self.onPlayerConnect, 1)
host.registerHandler('PlayerKilled', self.onPlayerKilled)
host.registerHandler('ClientCommand', self.onClientCommand)
host.registerHandler('PlayerTeamDamagePoint', self.onPlayerTeamDamagePoint)
host.registerGameStatusHandler(self.onGameStatusChanged)
# Connect already connected players if reinitializing
for p in bf2.playerManager.getPlayers():
self.onPlayerConnect(p)
self.checkEnable()
self.__state = 1
def shutdown( self ):
"""Shutdown and stop processing."""
if self.updateTimer:
self.updateTimer.destroy()
self.updateTimer = None
# Flag as shutdown as there is currently way to do this
self.__state = 2
def checkEnable( self ):
"""Check to see if team kill punish is enabled."""
if not bf2.serverSettings.getTKPunishEnabled():
if self.updateTimer:
self.updateTimer.destroy()
self.updateTimer = None
return False
else:
if not self.updateTimer:
self.updateTimer = bf2.Timer(self.onUpdate, 10, 1)
self.updateTimer.setRecurring(10)
return True
def onUpdate( self, data):
#if TK_ZTMOD_DEBUG >= 1:
# pmanage = PlayerManager()
# pmanage.getPlayers()
# testplayer = pmanage.getNextPlayer(0)
# host.rcon_invoke('game.sayall "' + str(host.pmgr_p_get("weapon",testplayer, 0)) + '"')
# host.rcon_invoke('game.sayall "' + str(host.pmgr_p_get("weapon",testplayer, 1)) + '"')
# host.rcon_invoke('game.sayall "' + str(host.pmgr_p_get("weapon",testplayer, 2)) + '"')
if TK_ZTMOD_USERATIO == 1:
if not self.checkEnable():
return
currentTime = host.timer_getWallTime()
newPending = {}
for attacker in self.hasPendingTks.iterkeys():
newList = []
for tk in attacker.tkData.pending:
tkDate = tk[0]
tkVictim = tk[1]
# check if there is a pending TK with time expired
if tkDate + TK_PUNISH_TIME < currentTime:
if bf2.serverSettings.getTKPunishByDefault():
punishAvailable = (tkVictim.score.score * TK_ZTMOD_PUNISHPERCENT / 100) + TK_ZTMOD_PUNISHBONUS
if tkVictim.tkData.punisher < punishAvailable:
attacker.tkData.punished += 1
if TkVictim.tkData.lastweapon in passiveWeapons: TkVictim.tkData.tkpassive += 1
if TK_ZTMOD_USERATIO == 1:
tkVictim.tkData.punisher += 1
bf2.gameLogic.sendClientCommand(-1, 100, (0, tkVictim.index, attacker.index))
self.checkPunishLimit(attacker)
# 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
self.hasPendingTks = newPending
else:
if not self.checkEnable(): return
currentTime = host.timer_getWallTime()
newPending = {}
for attacker in self.hasPendingTks.iterkeys():
newList = []
for tk in attacker.tkData.pending:
tkDate = tk[0]
tkVictim = tk[1]
# check if there is a pending TK with time expired
if tkDate + TK_PUNISH_TIME < currentTime:
if bf2.serverSettings.getTKPunishByDefault():
attacker.tkData.punished += 1
if TkVictim.tkData.lastweapon in passiveWeapons: tkVictim.tkData.tkpassive += 1
self.checkPunishLimit(attacker)
# 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
self.hasPendingTks = newPending
def checkPunishLimit(self, player):
if TK_ZTMOD_USERATIO == 1:
if player.tkData.punished == 0:
tkRatio = 100
else:
tkRatio = player.score.kills / player.tkData.punished
if player.tkData.punished >= TK_ZTMOD_WAIT:
if tkRatio < bf2.serverSettings.getTKNumPunishToKick():
host.rcon_invoke('game.sayall "ZTMOD-KICKED ' + str(player.getName()) + ' (' + str(player.score.kills) + '/' + str(player.tkData.punished) + '=' + str(tkRatio) + ')"')
host.rcon_invoke('echo "ZTMOD-KICKED ' + str(player.getName()) + ' (' + str(player.score.kills) + '/' + str(player.tkData.punished) + '=' + str(tkRatio) + ') [' + str(bf2.serverSettings.getTKNumPunishToKick()) + ']"')
result = host.rcon_invoke("admin.banPlayer " + str(player.index) + " Round")
else:
if player.tkData.punished >= bf2.serverSettings.getTKNumPunishToKick():
result = host.rcon_invoke("admin.banPlayer " + str(player.index) + " Round")
# event actions
def onPlayerConnect(self, player):
"""Add team kill data to the player."""
if 1 != self.__state:
return 0
player.tkData = TkData()
def onClientCommand(self, command, issuer, args):
"""Envoke punishment if required."""
if 1 != self.__state:
return 0
if not self.checkEnable(): return
if command == TK_PUNISH_COMMANDID:
self.executePunishAction(issuer, True)
elif command == TK_FORGIVE_COMMANDID:
self.executePunishAction(issuer, False)
def onPlayerKilled(self, victim, attacker, weapon, assists, object):
"""Check to team kills."""
if 1 != self.__state:
return 0
if not self.checkEnable():
return
if TK_ZTMOD_USERATIO == 1:
if not victim or not attacker or victim == attacker or victim.getTeam() != attacker.getTeam(): return
if TK_ZTMOD_SCOREKICK < 0 and attacker.score.score <= TK_ZTMOD_SCOREKICK:
if attacker.tkData.punisher < 0: return
attacker.tkData.punisher = -10
host.rcon_invoke('game.sayall "ZTMOD-KICKED ' + str(attacker.getName()) + ' (' + str(attacker.score.score) + ')"')
host.rcon_invoke('echo "ZTMOD-KICKED ' + str(attacker.getName()) + ' (' + str(attacker.score.score) + ') [' + str(TK_ZTMOD_SCOREKICK) + ']"')
host.rcon_invoke("admin.banPlayer " + str(attacker.index) + " Round")
return
if TK_ZTMOD_FILTERWEAPONS and weapon.templateName in forgivenWeapons: return
if TK_ZTMOD_PASSIVEWEAPONS == victim.tkData.tkpassive and weapon.templateName in passiveWeapons: return
victim.tkData.lastweapon = weapon.templateName
punishAvailable = (victim.score.score * TK_ZTMOD_PUNISHPERCENT / 100) + TK_ZTMOD_PUNISHBONUS
if victim.tkData.punisher >= punishAvailable: return
# ok, we have a teamkill
currentTime = host.timer_getWallTime()
attacker.tkData.pending += [(currentTime, victim)]
self.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))
else:
if TK_ZTMOD_FILTERWEAPONS and weapon.templateName in forgivenWeapons: return
if not victim or not attacker or victim == attacker:return #or victim.getTeam() != attacker.getTeam(): #used to say "return"
#uncomment the following line to determine weapon names:
#host.rcon_invoke('game.sayall "' + str(weapon.templateName) + '"')
#host.rcon_invoke('game.sayall "' + str(host.pmgr_p_get("weapon",victim, 0)) + '"')
#host.rcon_invoke('game.sayall "' + str(host.pmgr_p_get("weapon",victim, 1)) + '"')
#host.rcon_invoke('game.sayall "' + str(host.pmgr_p_get("weapon",victim, 2)) + '"')
if TK_ZTMOD_PASSIVEWEAPONS == victim.tkData.tkpassive and weapon.templateName in passiveWeapons: return
victim.tkData.lastweapon = weapon.templateName
if victim.getTeam() != attacker.getTeam(): # added by [FBX] Rubber Bullets. This checks to make sure it wasn't a suicide
if attacker.tkData.punished > 0:
attacker.tkData.tkpardon -= 1 # subtract from the count needed to earn a pardon
if attacker.tkData.tkpardon == 0: # you earned a pardon!!!
attacker.tkData.punished -= 1 # subtract a teamkill on your record
attacker.tkData.tkpardon = TK_KILLS_UNTIL_PARDON # reset count needed to earn another pardon
return
else:
#debuggging begin
currentTime = host.timer_getWallTime()
attacker.tkData.pending += [(currentTime, victim)]
self.hasPendingTks[attacker] = 1
victim.tkData.lastTKedBy = attacker # can only punish / forgive the last TK'er
bf2.gameLogic.sendClientCommand(attacker.index, 100, (2, victim.index, attacker.index, TK_PUNISH_TIME))
return
#debugging end
# 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(self, victim, punish):
"""Punish a player."""
if not self.checkEnable() or not victim or not victim.isValid():
return
attacker = victim.tkData.lastTKedBy
if attacker == None or not attacker.isValid(): return
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:
victim.tkData.punisher += 1
if victim.tkData.lastweapon in passiveWeapons: victim.tkData.tkpassive += 1
attacker.tkData.punished += 1
bf2.gameLogic.sendClientCommand(-1, 100, (0, victim.index, attacker.index)) # 100 = tkpunish event, 0 = punish
#attacker.score.score = attacker.tkData.punished #also debugging
else:
bf2.gameLogic.sendClientCommand(-1, 100, (1, victim.index, attacker.index)) # 100 = tkpunish event, 1 = forgive
#debuggging begin
#if attacker.tkData.punished > 0:
# attacker.tkData.tkpardon -= 1 # subtract from the count needed to earn a pardon
# if attacker.tkData.tkpardon == 0: # you earned a pardon!!!
# attacker.tkData.punished -= 1 # subtract a teamkill on your record
# attacker.tkData.tkpardon = TK_KILLS_UNTIL_PARDON # reset count needed to earn another pardon
#attacker.score.score = attacker.tkData.punished
#debugging end
else:
newList += [tk]
attacker.tkData.pending = newList
if len(attacker.tkData.pending) == 0:
del self.hasPendingTks[attacker]
self.checkPunishLimit(attacker)
def onPlayerTeamDamagePoint(self, player, object):
if not self.checkEnable(): return
if TK_ZTMOD_SCOREKICK < 0 and player.score.score <= TK_ZTMOD_SCOREKICK:
if player.tkData.punisher < 0: return
player.tkData.punisher = -10
host.rcon_invoke('game.sayall "ZTMOD-KICKED ' + str(player.getName()) + ' (' + str(player.score.score) + ')"')
host.rcon_invoke('echo "ZTMOD-KICKED ' + str(player.getName()) + ' (' + str(player.score.score) + ') [' + str(TK_ZTMOD_SCOREKICK) + ']"')
host.rcon_invoke("admin.banPlayer " + str(player.index) + " Round")
return
def onGameStatusChanged(self, status):
if dUmMy== bf2.GameStatus.EndGame:
for p in bf2.playerManager.getPlayers():
p.tkData = TkData()
def mm_load( modManager ):
"""Creates the team kill punisher object."""
return Punisher( modManager )