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 )