Scripts:Enhanced TK Script in ModManager format

From BF2 Technical Information Wiki
Jump to: navigation, search

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 ) 
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox