# target
import host
import bf2
import math
import tokenize
from game.scoringCommon import addScore, RPL, SKILL, NORMAL
from bf2 import g_debug
from bf2.stats.constants import *

TAKEOVERTYPE_CAPTURE = 1
TAKEOVERTYPE_NEUTRALIZE = 2

SCORE_CAPTURE = 2
SCORE_NEUTRALIZE = 2
SCORE_CAPTUREASSIST = 1
SCORE_NEUTRALIZEASSIST = 1
SCORE_DEFEND = 1

Top = 0
Middle = 1
Bottom = 2

g_controlPoints = [] # cache, as this map won't change

class Porte:
	def __init__(self):
		self.porte_PCO = None
		self.porte_initialized = 0
		self.porte_trigger_id = 0

Entree = Porte()
Sortie = Porte()


class Pakebotte:
	def __init__(self):
		self.pb_PCO = None
		self.pb_initialized = 0
		self.pb_trigger_id = 0
		self.pb_SON_DESTRUCTION = None

PaquebotteB = Pakebotte()
PaquebotteT = Pakebotte()

KILL_CAMPERS = None

vehiclesbisouporte = ["paquebotte", "paquebotte_teubes"]

devmembers = ["-=ReS=-Badger_man","-=ReS=-The_Lud","-=ReS=-T2Fighter", "[BAT]GrosRobert", "Guybrush_3pwood"]#dev team
SCORE_KILL_DEV = 2;
SCORE_KILL_SL = 1;
SCORE_KILL_NO_SQUAD = -1;
TEMPS_PENALITE_CAMPER = 10;
TEMPS_SPAWN_DEV_TEAM = 5;

def handle_token(type, token, (srow, scol), (erow, ecol), line):
	global KILL_CAMPERS
	if srow % 2 == 1:
		pass
	else:
		if KILL_CAMPERS is None:	
			try: KILL_CAMPERS = int(token)
			except: pass

def setBPaintOptions():
	global KILL_CAMPERS

	try:
		bPaintSettings = open("mods/bpaint/settings/bpaint.con", "r")
		tokenize.tokenize(bPaintSettings.readline, handle_token)
		bPaintSettings.close()
			
	except IOError:
		host.rcon_invoke('echo "WARNING! bpaint.con not found!"')
		KILL_CAMPERS = 0


setBPaintOptions()
print KILL_CAMPERS

def init():
	# events hook
	host.registerGameStatusHandler(onGameStatusChanged)
	if host.sgl_getIsAIGame() == 1:
		host.sh_setEnableCommander(0)
	else:
		host.sh_setEnableCommander(0)
		
	host.registerHandler('TimeLimitReached', onTimeLimitReached, 1)	

	if g_debug: print "gpm_cq.py modifie BPaint initialized"

		
		
def deinit():
	bf2.triggerManager.destroyAllTriggers()
	global g_controlPoints
	g_controlPoints = []
	host.unregisterGameStatusHandler(onGameStatusChanged)
	if g_debug: print "gpm_cq.py uninitialized"



def onGameStatusChanged(status):
	global g_controlPoints
	if status == bf2.GameStatus.Playing:

		# add control point triggers
		g_controlPoints = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.ControlPoint')
		for obj in g_controlPoints:
			if obj.cp_getParam('unableToChangeTeam') == 1 and KILL_CAMPERS:
				radius = float(obj.getTemplateProperty('radius'))
				#radius = 15
				isHemi = int(obj.cp_getParam('isHemisphere'))
				if isHemi != 0:
					id = bf2.triggerManager.createHemiSphericalTrigger(obj, onNonCapTrigger, '<<PCO>>', radius, (1, 2, 3))
				else:
					id = bf2.triggerManager.createRadiusTrigger(obj, onNonCapTrigger, '<<PCO>>', radius, (1, 2, 3))
					
				obj.triggerId = id
				obj.lastAttackingTeam = 0
				if obj.cp_getParam('team') > 0:
					obj.flagPosition = Top
				else:
					obj.flagPosition = Bottom					

			else:
				radius = float(obj.getTemplateProperty('radius'))
				isHemi = int(obj.cp_getParam('isHemisphere'))
				if isHemi != 0:
					id = bf2.triggerManager.createHemiSphericalTrigger(obj, onCPTrigger, '<<PCO>>', radius, (1, 2, 3))
				else:
					id = bf2.triggerManager.createRadiusTrigger(obj, onCPTrigger, '<<PCO>>', radius, (1, 2, 3))			
				obj.triggerId = id
				obj.lastAttackingTeam = 0
				if obj.cp_getParam('team') > 0:
					obj.flagPosition = Top
				else:
					obj.flagPosition = Bottom

		host.registerHandler('ControlPointChangedOwner', onCPStatusChange)

		# setup ticket system
		ticketsTeam1 = calcStartTickets(bf2.gameLogic.getDefaultTickets(1))
		ticketsTeam2 = calcStartTickets(bf2.gameLogic.getDefaultTickets(2))
		
		bf2.gameLogic.setTickets(1, ticketsTeam1)
		bf2.gameLogic.setTickets(2, ticketsTeam2)

		bf2.gameLogic.setTicketState(1, 0)
		bf2.gameLogic.setTicketState(2, 0)

		bf2.gameLogic.setTicketLimit(1, 1, 0)
		bf2.gameLogic.setTicketLimit(2, 1, 0)
		bf2.gameLogic.setTicketLimit(1, 2, 10)
		bf2.gameLogic.setTicketLimit(2, 2, 10)
		bf2.gameLogic.setTicketLimit(1, 3, int(ticketsTeam1*0.1))
		bf2.gameLogic.setTicketLimit(2, 3, int(ticketsTeam2*0.1))
		bf2.gameLogic.setTicketLimit(1, 4, int(ticketsTeam1*0.2))
		bf2.gameLogic.setTicketLimit(2, 4, int(ticketsTeam1*0.2))
		
		host.registerHandler('TicketLimitReached', onTicketLimitReached)
		updateTicketLoss()

		# player events
		host.registerHandler('PlayerDeath', onPlayerDeathCQ)
		host.registerHandler('PlayerKilled', onPlayerKilledCQ)
		host.registerHandler('PlayerRevived', onPlayerRevived)
		host.registerHandler('PlayerSpawn', onPlayerSpawn)
		host.registerHandler('EnterVehicle', onEnterVehicle)
		host.registerHandler('ExitVehicle', onExitVehicle)
		host.registerHandler('VehicleDestroyed', onVehicleDestroyed)	

		if g_debug: print "Conquest gamemode initialized."
	else:
		bf2.triggerManager.destroyAllTriggers()
		g_controlPoints = []
		iniPaquebotte()
		iniPorte()

def calcStartTickets(mapDefaultTickets):
	return int(mapDefaultTickets * (bf2.serverSettings.getTicketRatio() / 100.0))
		
def onTimeLimitReached(value):
	team1tickets = bf2.gameLogic.getTickets(1)
	team2tickets = bf2.gameLogic.getTickets(2)
	
	winner = 0
	victoryType = 0
	if team1tickets > team2tickets:
		winner = 1
		victoryType = 3
	elif team2tickets > team1tickets:
		winner = 2
		victoryType = 3
	
	host.sgl_endGame(winner, victoryType)
	iniPaquebotte()
	iniPorte()

# update ticket system
def updateTicketLoss():
	areaValueTeam1 = 0
	areaValueTeam2 = 0
	totalAreaValue = 0
	numCpsTeam0 = 0
	numCpsTeam1 = 0
	numCpsTeam2 = 0
	
	# calculate control point area value for each team
	for obj in g_controlPoints:
		team = obj.cp_getParam('team')
		if team == 1:
			areaValueTeam1 += obj.cp_getParam('areaValue', team)
			totalAreaValue += areaValueTeam1
			numCpsTeam1 += 1
		elif team == 2:
			areaValueTeam2 += obj.cp_getParam('areaValue', team)
			totalAreaValue += areaValueTeam2
			numCpsTeam2 += 1
		else:
			numCpsTeam0 += 1
			totalAreaValue += 0
		
	# check if a team has no control points
	if numCpsTeam1 == 0 or numCpsTeam2 == 0:
		if numCpsTeam1 == 0:
			losingTeam = 1
			winningTeam = 2
		else:
			losingTeam = 2
			winningTeam = 1
		
		# check if there is anyone alive
		foundLivingPlayer = False
		for p in bf2.playerManager.getPlayers():
			if p.getTeam() == losingTeam and p.isAlive():
				foundLivingPlayer = True
				break
				
		if not foundLivingPlayer:

			# drop tickets
			ticketLossPerSecond = bf2.gameLogic.getDefaultTicketLossAtEndPerMin()
			bf2.gameLogic.setTicketChangePerSecond(losingTeam, -ticketLossPerSecond)
			bf2.gameLogic.setTicketChangePerSecond(winningTeam, 0)
			
			return

	
	# update ticket loss
	team1AreaOverweight = areaValueTeam1 - areaValueTeam2
	percentualOverweight = 1.0
	if totalAreaValue != 0:
		percentualOverweight = abs(team1AreaOverweight / totalAreaValue)
	
	ticketLossPerSecTeam1 = calcTicketLossForTeam(1, areaValueTeam2, -team1AreaOverweight)
	ticketLossPerSecTeam2 = calcTicketLossForTeam(2, areaValueTeam1, team1AreaOverweight)
	bf2.gameLogic.setTicketChangePerSecond(1, -ticketLossPerSecTeam1)
	bf2.gameLogic.setTicketChangePerSecond(2, -ticketLossPerSecTeam2)


	
# actual ticket loss calculation function
def calcTicketLossForTeam(team, otherTeamAreaValue, otherTeamAreaOverweight):
	if otherTeamAreaValue >= 100 and otherTeamAreaOverweight > 0:
		ticketLossPerSecond = (bf2.gameLogic.getDefaultTicketLossPerMin(team) / 60.0) * (otherTeamAreaOverweight / 100.0)
		return ticketLossPerSecond
	else:
		return 0

	
DOWNWARDS = -1
UPWARDS = 1	

# called when tickets reach a predetermined limit (negativ value means that the tickets have become less than the limit)
def onTicketLimitReached(team, limitId):
	if (limitId == -1):
		if (team == 1):
			winner = 2
		
		elif (team == 2):
			winner = 1
		
		iniPaquebotte()
		iniPorte()
		bf2.gameLogic.setTicketState(1, 0)
		bf2.gameLogic.setTicketState(2, 0)
	
		host.sgl_endGame(winner, 3)		

	# update ticket state
	else:
		updateTicketWarning(team, limitId)
	
	

# called when the ticket state should be updated (for triggering messages and sounds based on tickets left)
def updateTicketWarning(team, limitId):
	oldTicketState = bf2.gameLogic.getTicketState(team)
	newTicketState = 0
	
	if (oldTicketState >= 10):
		newTicketState = 10		

	if (limitId == -2):
		newTicketState = 10
	
	elif (limitId == 2):
		newTicketState = 0		

	elif (limitId == -3):
		newTicketState += 2

	elif (limitId == -4):
		newTicketState += 1

	if (oldTicketState != newTicketState):
		bf2.gameLogic.setTicketState(team, newTicketState)




def onNonCapTrigger(triggerId, cp, vehicle, enter, userData):
	if not cp.isValid() and cp.cp_getParam('unableToChangeTeam') != 1: return
	
	cpTeam = cp.cp_getParam('team')
	
	playersInVehicle = None	
						
	if vehicle:
		playersInVehicle = vehicle.getOccupyingPlayers()			
		for p in playersInVehicle:
			pTeam = p.getTeam()
			
			
			if cpTeam != pTeam and isPlayerInRadius(p, triggerId):
				#cp == getOccupyingCP(p):
				try:
					p.camperPentaltyTimer.destroy()
					p.camperPentaltyTimer = None
					
				except: pass
				host.rcon_invoke("game.sayAll \"" + p.getName() + " inside an enemy main base and is being penalized!"  + "\"")
				bf2.gameLogic.sendMedalEvent(p, 1031406, 1) 	
				p.CPId = int(cp.getTemplateProperty('ControlPointID'))
				p.camperPenaltyTimer = bf2.Timer(penalizePlayer, 1, 1, p)
				p.camperPenaltyTimer.setRecurring(1.0)					
	
	
# called when someone enters or exits cp radius
def onCPTrigger(triggerId, cp, vehicle, enter, userData):

	if not cp.isValid(): return
	
	if vehicle and vehicle.getParent(): return
	
	# can this cp be captured at all?
	if cp.cp_getParam('unableToChangeTeam') != 0:
		return					
		
	playersInVehicle = None	
	if vehicle:
		playersInVehicle = vehicle.getOccupyingPlayers()
	
	if enter:
		for p in playersInVehicle:
			cp = getOccupyingCP(p)
			if cp != None:
				if not p.getIsInsideCP():
					if g_debug: print "Resetting enterPctAt for player ", p.getName()
					p.enterCpAt = host.timer_getWallTime()
	
	if vehicle:	
		for p in playersInVehicle:
			# only count first player in a vehicle
			if p == playersInVehicle[0]:  
				print p.index, " is in radius. v=", vehicle.templateName
				p.setIsInsideCP(enter)	
			else:
				p.setIsInsideCP(0)
				if enter == 1:
					bf2.gameLogic.sendHudEvent(p, 66, 49) #66 = HEEnableHelpMessage, 49 = VHMExitToCaptureFlag;			

	# count people in radius
	team1Occupants = 0
	team2Occupants = 0

	pcos = bf2.triggerManager.getObjects(cp.triggerId)
	for o in pcos:
		if not o: continue # you can get None in the result tuple when the host can't figure out what object left the trigger
		if o.getParent(): continue # getOccupyingPlayers returns all players downwards in the hierarchy, so dont count them twice
		occupyingPlayers = o.getOccupyingPlayers()
		for p in occupyingPlayers:
			
			# only count first player in a vehicle
			if p != occupyingPlayers[0]: 
				continue
				
			if p.isAlive() and not p.isManDown():
				
				if not p.killed:
					if p.getTeam() == 1:
						team1Occupants += 1
					elif p.getTeam() == 2:
						team2Occupants += 1


	# determine who is taking control
	team1OverWeight = team1Occupants - team2Occupants
	attackOverWeight = 0

	if team1OverWeight > 0:
		attackingTeam = 1
	elif team1OverWeight < 0:
		attackingTeam = 2
	else:
		attackingTeam = 0

	
	if team1Occupants == 0 and team2Occupants == 0:

		# nobody here, slowly go back to owning team
		if cp.cp_getParam('team') == 0:
			attackOverWeight = -0.5
		else:
			attackOverWeight = 0.5
			
		timeToChangeControl = cp.cp_getParam('timeToLoseControl')

	else:

		# raise flag if already ours, or at bottom and neutral. Otherwise lower first.
		if cp.cp_getParam('flag') == attackingTeam or (cp.flagPosition == Bottom and cp.cp_getParam('team') == 0):

			# our flag, raise
			attackOverWeight = abs(team1OverWeight)
			timeToChangeControl = cp.cp_getParam('timeToGetControl')
		else:

			# other team raised flag, lower first
			attackOverWeight = - abs(team1OverWeight)
			timeToChangeControl = cp.cp_getParam('timeToLoseControl')


	if cp.cp_getParam('onlyTakeableByTeam') != 0 and cp.cp_getParam('onlyTakeableByTeam') != attackingTeam:
		return


	# flag can only be changed when at bottom
	if cp.flagPosition == Bottom:
		cp.cp_setParam('flag', attackingTeam)


	# calculate flag raising/lowering speed
	if timeToChangeControl > 0:
		takeOverChangePerSecond = 1.0 * attackOverWeight / timeToChangeControl
	else:
		takeOverChangePerSecond = 0.0

	if (cp.flagPosition == Top and takeOverChangePerSecond > 0) or (cp.flagPosition == Bottom and takeOverChangePerSecond < 0):
		takeOverChangePerSecond = 0.0

	if abs(takeOverChangePerSecond) > 0:
		cp.flagPosition = Middle
				
	cp.cp_setParam('takeOverChangePerSecond', takeOverChangePerSecond)

			
	
#quand un joueur s'approche de l'entree			
def onPorteEntreeTrigger(triggerId, cp, vehicle, enter, userData):					
	if not cp.isValid(): return
					
	playersInVehicle = None	
	authorise = 1
	
	if vehicle:	
		for v in vehiclesbisouporte:
			if vehicle.templateName == v:			
				authorise = 0
		
		if authorise == 1:						
			sPos = Sortie.porte_PCO.getPosition()						
			playersInVehicle = vehicle.getOccupyingPlayers()	

			#1 seul mec à la fois			
			nb = len(playersInVehicle)
			#host.rcon_invoke("game.sayAll \"" + str(nb) + " utilisateurs !"  + "\"")
			if(nb > 1):
				return
			
			for p in playersInVehicle:
				if isPlayerInRadius(p, triggerId) and p.isAlive():
					traverserPorte = 1
			
			if traverserPorte == 1:				
									
				for p in playersInVehicle:
					if p.isAlive():
						#host.rcon_invoke("game.sayAll \"" + p.getName() + " a utilisé la porte !"  + "\"")		
						bf2.gameLogic.sendGameEvent(p, 13, 1) #trouble	
						
				vehicle.setPosition((sPos[0]+5, sPos[1]-0.2, sPos[2]+10))	

				#if isPlayerInRadius(p, triggerId) and p.isAlive():
					#host.rcon_invoke("game.sayAll \"" + p.getName() + " a utilisé la porte !"  + "\"")							
					#sPos = Sortie.porte_PCO.getPosition()	
					#bf2.gameLogic.sendGameEvent(p, 13, 1) #trouble					
					#vehicle.setPosition((sPos[0]+5, sPos[1]-0.2, sPos[2]+10))		


#quand un joueur s'approche de la sortie			
def onPorteSortieTrigger(triggerId, cp, vehicle, enter, userData):
	if not cp.isValid(): return
	
	playersInVehicle = None	
	authorise = 1
	traverserPorte = 0
	
	if vehicle:					
		for v in vehiclesbisouporte:
			if vehicle.templateName == v: 			
				authorise = 0
	
		if authorise == 1:									
			sPos = Entree.porte_PCO.getPosition()	
				
			#vehicleV = vehicle.getVehicle()
			#rootVehicle = getRootParent(vehicleV)
			#if getVehicleType(rootVehicle.templateName) == VEHICLE_TYPE_SOLDIER:
				#host.rcon_invoke("game.sayAll \"" + "SOLDIER" + rootVehicle.templateName + " a utilisé la porte !"  + "\"")	
			#else:
				#host.rcon_invoke("game.sayAll \"" + "VEHICLE" + rootVehicle.templateName + " a utilisé la porte !"  + "\"")	
				#playersInVehicle = vehicle.getOccupyingPlayers()	
				#for p in playersInVehicle:
					#host.rcon_invoke("game.sayAll \"" + p.getName() + "\"")		

			playersInVehicle = vehicle.getOccupyingPlayers()
			
			#1 seul mec à la fois
			nb = len(playersInVehicle)
			#host.rcon_invoke("game.sayAll \"" + str(nb) + " utilisateurs !"  + "\"")
			if(nb > 1):
				return
				
			for p in playersInVehicle:
				if isPlayerInRadius(p, triggerId) and p.isAlive():
					traverserPorte = 1
			
			if traverserPorte == 1:				
						
				for p in playersInVehicle:		
					if p.isAlive():
						#host.rcon_invoke("game.sayAll \"" + p.getName() + " a utilisé la porte !"  + "\"")	
						bf2.gameLogic.sendGameEvent(p, 13, 1) #trouble	
						
				vehicle.setPosition((sPos[0]+5, sPos[1]-0.2, sPos[2]+10))	
					
				#if isPlayerInRadius(p, triggerId) and p.isAlive():
					#host.rcon_invoke("game.sayAll \"" + p.getName() + " a utilisé la porte !"  + "\"")	
					#sPos = Entree.porte_PCO.getPosition()		
					#bf2.gameLogic.sendGameEvent(p, 13, 1) #trouble
					


# renvoit 1 si le joueur se trouve dans le radius donné
def isPlayerInRadius(player, triggerId):
	# is the player in radius?
	pcos = bf2.triggerManager.getObjects(triggerId)
	for o in pcos:
		if o == player.getDefaultVehicle():
			# Player is DEFAULT vehicle - this is needed when called from onEnterVehicle
			return 1
		else:
			for p in o.getOccupyingPlayers():
				if p == player:
					return 1
	
	return 0


			
# called when a control point flag reached top or bottom
def onCPStatusChange(cp, top):
	playerId = -1
	takeoverType = -1
	newTeam = -1
	scoringTeam = -1
	
	if top:	cp.flagPosition = Top
	else:   cp.flagPosition = Bottom
	
	# determine capture / neutralize / defend
	if cp.cp_getParam('team') != 0:

		if top:
			# regained flag, do nothing
			pass
			
		else:
			# neutralize
			newTeam = 0
			if cp.cp_getParam('team') == 1:
				scoringTeam = 2
			else:
				scoringTeam = 1
				
			takeoverType = TAKEOVERTYPE_NEUTRALIZE

	else:

		if top:
			# capture
			newTeam = cp.cp_getParam('flag')
			scoringTeam = newTeam
			takeoverType = TAKEOVERTYPE_CAPTURE

		else:
			# hit bottom, but still neutral
			pass

	
	# scoring
	if takeoverType > 0:
		pcos = bf2.triggerManager.getObjects(cp.triggerId)
	
		# count number of players
		scoringPlayers = []
		firstPlayers = []
		for o in pcos:
			if o.getParent(): continue

			occupyingPlayers = o.getOccupyingPlayers()
			for p in occupyingPlayers:
			
				# only count first player in a vehicle
				if p != occupyingPlayers[0]: 
					continue
					
				if p.isAlive() and not p.isManDown() and p.getTeam() == scoringTeam:
					if len(firstPlayers) == 0 or p.enterCpAt < firstPlayers[0].enterCpAt:
						firstPlayers = [p]
					elif p.enterCpAt == firstPlayers[0].enterCpAt:
						firstPlayers += [p]
					
					if not p in scoringPlayers:
						scoringPlayers += [p]
	
		# deal score
		for p in scoringPlayers:
			oldScore = p.score.score;
			if takeoverType == TAKEOVERTYPE_CAPTURE:
				if p in firstPlayers:
					p.score.cpCaptures += 1
					addScore(p, SCORE_CAPTURE, RPL)
					bf2.gameLogic.sendGameEvent(p, 12, 0) #12 = Conquest, 0 = Capture
					playerId = p.index
				else:
					p.score.cpAssists += 1
					addScore(p, SCORE_CAPTUREASSIST, RPL)
					bf2.gameLogic.sendGameEvent(p, 12, 2) #12 = Conquest, 2 = Assist


			elif takeoverType == TAKEOVERTYPE_NEUTRALIZE:
				if p in firstPlayers:
					p.score.cpNeutralizes += 1
					addScore(p, SCORE_NEUTRALIZE, RPL)
					bf2.gameLogic.sendGameEvent(p, 12, 3) #12 = Conquest, 3 = Neutralize
				else:
					p.score.cpNeutralizeAssists += 1
					addScore(p, SCORE_NEUTRALIZEASSIST, RPL)
					bf2.gameLogic.sendGameEvent(p, 12, 4) #12 = Conquest, 4 = Neutralize assist
					
				

	# immediate ticket loss for opposite team
	enemyTicketLossInstant = cp.cp_getParam('enemyTicketLossWhenCaptured')
	if enemyTicketLossInstant > 0 and newTeam > 0:
		
		if newTeam == 1:
			punishedTeam = 2
		elif newTeam == 2:
			punishedTeam = 1
		
		tickets = bf2.gameLogic.getTickets(punishedTeam)
		tickets -= enemyTicketLossInstant
		bf2.gameLogic.setTickets(punishedTeam, tickets)
	
	
	# update control point	
	cp.cp_setParam('playerId', playerId) #always set player first
	if newTeam != -1 and cp.cp_getParam('team') != newTeam:
		cp.cp_setParam('team', newTeam)
	onCPTrigger(cp.triggerId, cp, 0, 0, 0)
	updateTicketLoss()

				
				
def onPlayerDeathCQ(victim, vehicle):	
	
	if victim != None:
		if victim.deadforcamp == 1:
			try:
				victim.setTimeToSpawn(victim.getTimeToSpawn() + TEMPS_PENALITE_CAMPER)   #temps de pénalité pour base camp
				bf2.gameLogic.sendMedalEvent(victim, 1031406, 2) 	
				victim.deadforcamp = 0
			except: pass		
		
		else:
			try:
				victimName = victim.getName()      			
				for name in devmembers:
					if name == victimName and victim.getTimeToSpawn() > TEMPS_SPAWN_DEV_TEAM: 
						victim.setTimeToSpawn(TEMPS_SPAWN_DEV_TEAM)   #un peu de triche :)								
						break					
			except: pass		
	
	if victim != None and victim.camperPenaltyTimer != None:
		victim.camperPenaltyTimer.destroy()
		victim.camperPenaltyTimer = None
		victim.CPId = None
		
	# punish team with one ticket
	if victim != None:
		team = victim.getTeam()
		teamTickets = bf2.gameLogic.getTickets(team)
		teamTickets -= 1
		bf2.gameLogic.setTickets(team, teamTickets)

	#on n'appelle pas updateTicketLoss si on est en mode bataille naval
	if PaquebotteB.pb_initialized and PaquebotteT.pb_initialized: 
		return
		
	# check if it was the last player
	foundLivingPlayer = False
	for p in bf2.playerManager.getPlayers():
		if p != victim and p.getTeam() == victim.getTeam() and p.isAlive():
			foundLivingPlayer = True
	
	if not foundLivingPlayer:
		updateTicketLoss()
		


def onPlayerKilledCQ(victim, attacker, weapon, assists, object):

	if not victim: 
		return
	
	if victim != None and victim.deadforcamp != 1:
		try:
			victimName = victim.getName()      			
			for name in devmembers:
				if name == victimName and victim.getTimeToSpawn() > TEMPS_SPAWN_DEV_TEAM: 
					victim.setTimeToSpawn(TEMPS_SPAWN_DEV_TEAM)   #un peu de triche :)								
					break					
		except: pass		
	
	victim.killed = True
	
	# update flag takeover status if victim was in a CP radius
	cp = getOccupyingCP(victim)
	if cp != None:
		onCPTrigger(-1, cp, victim.getVehicle(), False, None)

		# give defend score if killing enemy within cp radius
		if attacker != None and attacker.getTeam() != victim.getTeam()\
			and cp.cp_getParam('unableToChangeTeam') == 0 and cp.cp_getParam('onlyTakeableByTeam') == 0:
			
			if cp != None and cp.cp_getParam('team') == attacker.getTeam():
				attacker.score.cpDefends += 1
				addScore(attacker, SCORE_DEFEND, RPL)
				bf2.gameLogic.sendGameEvent(attacker, 12, 1) #12 = Conquest, 1 = Defend	
	
	#bonus pour avoir tué un membre de la dev team
	if attacker != None and victim != attacker and victim.getTeam() != attacker.getTeam(): 
		victimName = victim.getName()        
		attackerName = attacker.getName() 
		for name in devmembers:
			if name == victimName: 
				addScore(attacker, SCORE_KILL_DEV, SKILL)				
				host.rcon_invoke("game.sayAll \"" + "Bonus pour " + attackerName +" qui a tué un membre de la dev team de BPaint: "+ victimName  + "\"")	
				if victimName == "-=ReS=-The_Lud": 
					host.rcon_invoke("game.sayAll \"" + "Lud s'est fait tué, le nooooooooooooooob :)"+"\"")								
				break
				
	# 1 point de kill en moins si on n'est pas dans une squad
	if attacker and victim != attacker != None and (attacker.getSquadId() == 0) and not attacker.isCommander() and victim.getTeam() != attacker.getTeam():
		addScore(attacker, SCORE_KILL_NO_SQUAD, NORMAL)
	
	# 1 point de kill en plus si on tue un chef de squad
	if attacker and victim != attacker != None and victim != None and not attacker.isCommander() and victim.isSquadLeader() and victim.getTeam() != attacker.getTeam():
		addScore(attacker, SCORE_KILL_SL, SKILL)					
		host.rcon_invoke("game.sayAll \"" + attacker.getName() + ": bonus pour avoir tué un chef de squad"+"\"")		
	
	
	
	# check to remove any lingering penalty timers
	try:			
		player.camperPenaltyTimer.destroy()
		player.camperPenaltyTimer = None
		p.nonCap = None
	
	except: pass
			
def onPlayerRevived(victim, attacker):
	# update flag takeover status if victim was in a CP radius
	victim.killed = False
	
	cp = getOccupyingCP(victim)
	if cp != None:
		onCPTrigger(-1, cp, victim.getVehicle(), True, None)
			
def onPlayerSpawn(player, soldier):
	player.killed = False
	#host.rcon_invoke("player.moveTo -84/60/-180")
					
	if not PaquebotteB.pb_initialized or not PaquebotteT.pb_initialized:	
		try:
			#on recherche les paquebottes
			getPaquebotte()			
		except:
			pass	
			
	if not Entree.porte_initialized or not Sortie.porte_initialized:
		try:
			#on recherche la porte
			trouverPorte()			
		except:
			pass	
	if Entree.porte_initialized and Sortie.porte_initialized:	
		Entree.porte_trigger_id = bf2.triggerManager.createRadiusTrigger(Entree.porte_PCO, onPorteEntreeTrigger, '<<PCO>>', 1, 1)		
		Sortie.porte_trigger_id = bf2.triggerManager.createRadiusTrigger(Sortie.porte_PCO, onPorteSortieTrigger, '<<PCO>>', 1, 2)	

	player.deadforcamp = 0
	player.camperPenaltyTimer = None
	
	
def onEnterVehicle(player, vehicle, freeSoldier = False):
	player.setIsInsideCP(False)
	cp = getOccupyingCP(player)
	if cp != None:
		onCPTrigger(-1, cp, vehicle, False, None)
		updateCaptureStatus(vehicle) 


def onExitVehicle(player, vehicle):
	# update flag takeover status if player in a CP radius
	
	print "Player exiting ", player.getName()
	cp = getOccupyingCP(player)

	# can this cp be captured at all?
	player.setIsInsideCP(cp != None and cp.cp_getParam('unableToChangeTeam') == 0)

	updateCaptureStatus(vehicle)
		

#Update cp capture status on players in vehicle
def updateCaptureStatus(vehicle):
	rootVehicle = bf2.objectManager.getRootParent(vehicle)
	playersInVehicle = rootVehicle.getOccupyingPlayers()
	
	# set the player in the topmost pco as inside - others outside
	for p in playersInVehicle:
		print "Players in vehicle ", p.getName()
		cp = getOccupyingCP(p)
		p.setIsInsideCP(cp != None and cp.cp_getParam('unableToChangeTeam') == 0 and p == playersInVehicle[0])
		
		
# find cp that player is occupying, if any		
def getOccupyingCP(player):
	vehicle = player.getVehicle()
	playerPos = vehicle.getPosition()
	
	# find closest CP
	closestCP = None
	if len(g_controlPoints) == 0: return None
	for obj in g_controlPoints:
		distanceTo = getVectorDistance(playerPos, obj.getPosition())
		if closestCP == None or distanceTo < closestCPdist:
			closestCP = obj
			closestCPdist = distanceTo
	
	# is the player in radius?
	pcos = bf2.triggerManager.getObjects(closestCP.triggerId)
	for o in pcos:
		if o == player.getDefaultVehicle():
			# Player is DEFAULT vehicle - this is needed when called from onEnterVehicle
			return closestCP
		else:
			for p in o.getOccupyingPlayers():
				if p == player:
					return closestCP
	
	return None



	
# get distance between two positions
def getVectorDistance(pos1, pos2):
	diffVec = [0.0, 0.0, 0.0]
	diffVec[0] = math.fabs(pos1[0] - pos2[0])
	diffVec[1] = math.fabs(pos1[1] - pos2[1])
	diffVec[2] = math.fabs(pos1[2] - pos2[2])
	 
	return math.sqrt(diffVec[0] * diffVec[0] + diffVec[1] * diffVec[1] + diffVec[2] * diffVec[2])
		
# system for penalizing a player in the enemy main base every second until he leaves or is killed
def penalizePlayer(player):
	#cp = getOccupyingCP(player)
	#cp = int(cp.getTemplateProperty('ControlPointID'))
	# player in the radius of the non-cap, begin or continue the penalty
	#if cp == player.CPId:
	cp = getCPbyId(player.CPId)
	if cp != None and isPlayerInRadius(player, cp.triggerId):
		vehicle = player.getDefaultVehicle()
		
		playerDefaultVehicle = player.getDefaultVehicle()
		playerVehicle = player.getVehicle()		
		parent = playerVehicle.getParent()
		parentDefault = playerDefaultVehicle.getParent()		
		
		if playerVehicle == playerDefaultVehicle: # player not in vehicle
			if parentDefault: # player in parachute					
					player.camperPenaltyTimer.destroy()
					player.camperPenaltyTimer = None
					player.CPId = None
					player.deadforcamp = 1
					playerDefaultVehicle.setDamage(1.0)
					return
		
		if playerDefaultVehicle.getDamage() <= 5:			
			player.camperPenaltyTimer.destroy()
			player.camperPenaltyTimer = None
			player.CPId = None
			player.deadforcamp = 1
			playerDefaultVehicle.setDamage(1)  #associé au criticaldamage sur armur soldat
		
		else:
			playerDefaultVehicle.setDamage(playerDefaultVehicle.getDamage() - 5)
	
	else: # player has left the non-cap, stop the penalty
		player.camperPenaltyTimer.destroy()
		player.camperPenaltyTimer = None
		player.CPId = None

# find cp with that id, if any		
def getCPbyId(CPId):

	if len(g_controlPoints) == 0: return None
	for obj in g_controlPoints:
		if int(obj.getTemplateProperty('ControlPointID')) == CPId:
			return obj
	
	return None
		
		
		
def onVehicleDestroyed(vehicle, attacker):	
	if not PaquebotteB.pb_initialized or not PaquebotteT.pb_initialized: return
	#host.rcon_invoke("game.sayAll \"" + "VEHICULE DETRUIT: "+vehicle.templateName+"\"")
	#paquebotte bisou detruit
	if vehicle.templateName == PaquebotteB.pb_PCO.templateName:
		host.rcon_invoke("game.sayAll \"" + "---------------PAQUEBOTTE BISOUNOURS DETRUIT---------------"  + "\"")					
		#detruit par un bisou
		if attacker!= None and attacker.getTeam() == 1:				
			addScore(attacker, -20, RPL)
						
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + "Punition de " + attacker.getName() + " pour avoir detruit son  paquebotte!"  + "\"")
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + "-------------------------------------"  + "\"")
			
			bf2.gameLogic.sendMedalEvent(attacker, 1031113, 1) # punished for tk		
			
		#detruit par un teube
		elif attacker!= None and attacker.getTeam() == 2:			
			addScore(attacker, 20, RPL)
					
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + attacker.getName() + " a detruit le paquebotte !"  + "\"")
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + "-------------------------------------"  + "\"")
				
			bf2.gameLogic.sendMedalEvent(attacker, 1031113, 2) # rewarded for destroying			
					
		#jouerSon(PaquebotteB.pb_SON_DESTRUCTION)	
		sendAllMessage(1032415, 1) # paquebotte bisou detruit
		bf2.gameLogic.setTicketChangePerSecond(1, -15.0) 
		bf2.gameLogic.setTicketChangePerSecond(2, 0)
		#bf2.gameLogic.setTickets(1, 1)
	
	#paquebotte teube detruit
	elif vehicle.templateName == PaquebotteT.pb_PCO.templateName:
		host.rcon_invoke("game.sayAll \"" + "---------------PAQUEBOTTE TEUBE DETRUIT---------------"  + "\"")					
		#detruit par un teube
		if attacker!= None and attacker.getTeam() == 2:				
			addScore(attacker, -20, RPL)
						
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + "Punition de " + attacker.getName() + "  pour avoir detruit son  paquebotte!"  + "\"")
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + "-------------------------------------"  + "\"")
			
			bf2.gameLogic.sendMedalEvent(attacker, 1031113, 1) # punished for tk		
			
		#detruit par un bisou
		elif attacker!= None and attacker.getTeam() == 1:			
			addScore(attacker, 20, RPL)
			
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + attacker.getName() + " a detruit le paquebotte !"  + "\"")
			host.rcon_invoke("game.sayAll \"" + "."  + "\"")
			host.rcon_invoke("game.sayAll \"" + "-------------------------------------"  + "\"")
			
			bf2.gameLogic.sendMedalEvent(attacker, 1031113, 2) # rewarded for destroying		
				
		#jouerSon(PaquebotteT.pb_SON_DESTRUCTION)
		sendAllMessage(1031113, 3) # paquebotte teubes detruit
		bf2.gameLogic.setTicketChangePerSecond(2, -15.0) 
		bf2.gameLogic.setTicketChangePerSecond(1, 0)
		#bf2.gameLogic.setTickets(2, -1)

#detruit le l'objet son pour qu'il joue son son
def jouerSon(obj):
	try:
		obj.setDamage(-1)
		obj.timer = bf2.Timer(ReparerSon, 0.2, 1,obj)
	except:
		pass

#reparer le son apres l'avoir detruit
def reparerSon(obj):
	try:
		obj.setDamage(1)
		obj.timer.destroy()
		obj.timer = None
	except:
		pass		
		
def sendAllMessage(id, data):
	players = bf2.playerManager.getPlayers()
	for p in players:
		if p.isAlive():
			bf2.gameLogic.sendMedalEvent(p, id, data)

#recherche la porte (entree et sortie) sur la carte
def trouverPorte():
	objects = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.PlayerControlObject')
	for obj in objects:
		if obj.templateName == 'bisouporte' and Entree.porte_initialized == 0:
			Entree.porte_PCO = obj
			Entree.porte_initialized = 1			
			host.rcon_invoke("game.sayAll \"" + "Entree initialisee: " + Entree.porte_PCO.templateName +"\"")
		elif obj.templateName == 'bisouporte' and Sortie.porte_initialized == 0:
			Sortie.porte_PCO = obj
			Sortie.porte_initialized = 1			
			host.rcon_invoke("game.sayAll \"" + "Sortie initialisee: " + Sortie.porte_PCO.templateName  +"\"")	


#pour trouver la cible
def getPaquebotte():
	objects = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.PlayerControlObject')
	for obj in objects:
		if obj.templateName == 'paquebotte' and not PaquebotteB.pb_initialized:			
			PaquebotteB.pb_PCO = obj
			PaquebotteB.pb_initialized = 1
			#host.rcon_invoke("game.sayAll \"" + "PaquebotteB "+ PaquebotteB.pb_PCO.templateName + "\"")
		if obj.templateName == 'paquebotte_teubes' and not PaquebotteT.pb_initialized:			
			PaquebotteT.pb_PCO = obj			
			PaquebotteT.pb_initialized = 1
			#host.rcon_invoke("game.sayAll \"" + "PaquebotteT "+ PaquebotteT.pb_PCO.templateName + "\"")
		if obj.templateName == 'paquebotteB_detruit_sound':
			PaquebotteB.pb_SON_DESTRUCTION = obj
			#host.rcon_invoke("game.sayAll \"" + PaquebotteB.pb_SON_DESTRUCTION.templateName + "\"")
		if obj.templateName == 'paquebotteT_detruit_sound':
			PaquebotteT.pb_SON_DESTRUCTION = obj
			#host.rcon_invoke("game.sayAll \"" + PaquebotteT.pb_SON_DESTRUCTION.templateName + "\"")
		
	if PaquebotteB.pb_initialized and PaquebotteT.pb_initialized:	 
		host.rcon_invoke("game.sayAll \"" + "MODE bataille navale" + "\"")
		
def iniPaquebotte():
	PaquebotteB.pb_PCO = None
	PaquebotteB.pb_initialized = 0
	PaquebotteB.pb_SON_DESTRUCTION = None
	
	PaquebotteT.pb_PCO = None
	PaquebotteT.pb_initialized = 0
	PaquebotteT.pb_SON_DESTRUCTION = None


def iniPorte():		
	Entree.porte_PCO = None
	Entree.porte_initialized = 0
	Entree.porte_trigger_id = 0
	
	Sortie.porte_PCO = None
	Sortie.porte_initialized = 0
	Sortie.porte_trigger_id = 0

