# Name: CQTF

TAKEOVERTYPE_CAPTURE = 1
TAKEOVERTYPE_NEUTRALIZE = 2

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

SCORE_CQTF_KILLCARRIER = "return"
SCORE_CQTF_TKCARRIER = "tk"

CQTF_INITIALIZED = False

PAC_TEAM_CARRIERS = []
EU_TEAM_CARRIERS = []

PAC_DROP_FLAGS = []
EU_DROP_FLAGS = []

PAC_FLAG_TEMPLATE = "pac_flag_l2"
EU_FLAG_TEMPLATE = "eu_flag_l2"

PAC_DF_TEMPLATE = "pac_dropflag_l2"
EU_DF_TEMPLATE = "eu_dropflag_l2"

Top = 0
Middle = 1
Bottom = 2

import host
import bf2
import math
from game.scoringCommon import addScore, RPL
from bf2 import g_debug
from game.gamemodes.gpm_cq import getVectorDistance
from game.ctfsupports import addFlag, removeFlag, resetCQTFFlag, addCTFScore, killAllTimers, onCQTFDropTrigger, initCQTFSupport
from game.ctfsupports import setInPlay, getInPlay, checkHolder, findCarrier, dropFlag, findAvailableDF

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



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

	if g_debug: print "gpm_cqtf.py initialized"
		

def deinit():
	bf2.triggerManager.destroyAllTriggers()
	global g_controlPoints
	g_controlPoints = []
	host.unregisterGameStatusHandler(onGameStatusChanged)
	host.unregisterHandler('TimeLimitReached', onTimeLimitReachedCQTF)	
	host.unregisterHandler('ControlPointChangedOwner', onCPStatusChangeCQTF)
	host.unregisterHandler('TicketLimitReached', onTicketLimitReachedCQTF)
	host.unregisterHandler('PlayerDeath', onPlayerDeathCQTF)
	host.unregisterHandler('PlayerKilled', onPlayerKilledCQTF)
	host.unregisterHandler('PlayerRevived', onPlayerRevivedCQTF)
	host.unregisterHandler('PlayerSpawn', onPlayerSpawnCQTF)
	host.unregisterHandler('EnterVehicle', onEnterVehicleCQTF)
	host.unregisterHandler('ExitVehicle', onExitVehicleCQTF)
	host.unregisterHandler('PlayerDisconnect', onPlayerDisconnectCQTF)
	host.unregisterHandler('PlayerChangeTeams', onPlayerChangeTeamsCQTF)
	host.unregisterHandler('VehicleDestroyed', onVehicleDestroyedCQTF)
	host.unregisterHandler('VehicleSpawn', onVehicleSpawnCQTF)
	if g_debug: print "gpm_cqtf.py uninitialized"


def onGameStatusChanged(status):
	global g_controlPoints, CQTF_INITIALIZED
	killAllTimers()
	EU_TOTAL_FLAGS = 0
	PAC_TOTAL_FLAGS = 0
	CQTF_INITIALIZED = False
	
	if status == bf2.GameStatus.Playing:

		# add control point triggers
		g_controlPoints = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.ControlPoint')
		for obj in g_controlPoints:
			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', onCPStatusChangeCQTF)

		# 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', onTicketLimitReachedCQTF)
		updateTicketLoss()

		# player events
		host.registerHandler('PlayerDeath', onPlayerDeathCQTF)
		host.registerHandler('PlayerKilled', onPlayerKilledCQTF)
		host.registerHandler('PlayerRevived', onPlayerRevivedCQTF)
		host.registerHandler('PlayerSpawn', onPlayerSpawnCQTF)
		host.registerHandler('EnterVehicle', onEnterVehicleCQTF)
		host.registerHandler('ExitVehicle', onExitVehicleCQTF)
		host.registerHandler('PlayerDisconnect', onPlayerDisconnectCQTF)
		host.registerHandler('PlayerChangeTeams', onPlayerChangeTeamsCQTF)
		host.registerHandler('VehicleDestroyed', onVehicleDestroyedCQTF)
		host.registerHandler('VehicleSpawn', onVehicleSpawnCQTF)

		if g_debug: print "CQTF gamemode initialized."
	else:
		bf2.triggerManager.destroyAllTriggers()
		g_controlPoints = []
	
	
	
def calcStartTickets(mapDefaultTickets):
	return int(mapDefaultTickets * (bf2.serverSettings.getTicketRatio() / 100.0))

# 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() and not p.isAutoController():
				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)


def onPlayerDisconnectCQTF(player):
	if searchCarrier(player):
		try:
			player.flag.setDamage(-1)
		except: pass
		
		dropFlag = player.dropFlag
		resetCQTFFlag(dropFlag)
		removeCarrier(victim)
		player.flag = None
		player.dropFlag = None	
	
	
def onPlayerChangeTeamsCQTF(player, humanHasSpawed):
	player.changedTeam = True
		
	
def onTimeLimitReachedCQTF(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, 0)
	
# 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 onTicketLimitReachedCQTF(team, limitId):
	if (limitId == -1):
		if (team == 1):
			winner = 2
		
		elif (team == 2):
			winner = 1
		
		bf2.gameLogic.setTicketState(1, 0)
		bf2.gameLogic.setTicketState(2, 0)
	
		host.sgl_endGame(winner, 3, 0)		
	
	
# called when someone enters or exits cp radius
def onCPTrigger(triggerId, cp, vehicle, enter, userData):
	# can this cp be captured at all?
	if cp.cp_getParam('unableToChangeTeam') != 0:
		return
	
	playersInVehicle = None
	
	if vehicle:
		playersInVehicle = vehicle.getOccupyingPlayers()

	#if a player is alive, on foot and a flag carrier, set him inside
	if enter:
		for p in playersInVehicle:
			if p.isAlive() and not p.isManDown() and not p.killed:
				team = p.getTeam()
				if p.getDefaultVehicle() == p.getVehicle() and p.dropFlag:
					p.enterCpAt = host.timer_getWallTime()
					p.setIsInsideCP(1)
			
			else:
				p.setIsInsideCP(0)
	
	#only count players on foot
	if vehicle:
		for p in playersInVehicle:
			if vehicle != p.getDefaultVehicle():
					p.setIsInsideCP(0)
					if enter == 1:
						bf2.gameLogic.sendHudEvent(p, 71, 49) #71 = 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 players on foot that are flag carriers			
			if p.isAlive() and not p.isManDown() and p.getVehicle() == p.getDefaultVehicle() and p.dropFlag:
				if not p.killed:
					if g_debug: print "Player ", p.getName(), " is inside radius"

					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)
	
	updateTicketLoss()
	

# called when a control point flag reached top or bottom
def onCPStatusChangeCQTF(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 players on foot, and flag carriers for full points no matter the enter time
				if p.getVehicle() == p.getDefaultVehicle() and p.dropFlag:
					if p.isAlive() and not p.isManDown() and p.getTeam() == scoringTeam:
						if len(firstPlayers) == 0:
							firstPlayers = [p]
						else:
							firstPlayers += [p]
						
						if not p in scoringPlayers:
							scoringPlayers += [p]
				
				#all other players on foot and no a flag carrier get assist points
				elif p.getVehicle() == p.getDefaultVehicle() and not p.dropFlag:
					if p.isAlive() and not p.isManDown() and p.getTeam() == scoringTeam:
						if len(scoringPlayers) == 0:
							scoringPlayers = [p]
						else:
							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
					playerId = p.index
				else:
					p.score.cpNeutralizeAssists += 1
					addScore(p, SCORE_NEUTRALIZEASSIST, RPL)
					bf2.gameLogic.sendGameEvent(p, 12, 4) #12 = Conquest, 4 = Neutralize assist
					
		if takeoverType == TAKEOVERTYPE_CAPTURE:
			for p in firstPlayers:
				team = p.getTeam()		
				dropFlag = p.dropFlag
				resetCQTFFlag(dropFlag)
				removeCarrier(p)
				try:
					p.flag.setDamage(-1)
				except: pass
				
				flagHolderDestroyed(p, p.dropFlag)
				p.dropFlag = None
				p.flag = None
				p.setIsInsideCP(0)
	
	# 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)

def onPlayerDeathCQTF(victim, vehicle):		
	if victim == None:
		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() and not p.isAutoController():
			foundLivingPlayer = True
			
def onPlayerKilledCQTF(victim, attacker, weapon, assists, object):
	if not victim: return
	
	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
	
	if not victim.dropFlag:
		return
	
	if not attacker:
		dropFlag = victim.dropFlag
		resetCQTFFlag(dropFlag)
		removeCarrier(victim)
		victim.flag = None
		victim.dropFlag = None
		return
			
	if attacker.getTeam() == victim.getTeam(): #no points for tk'ing
		dropFlag = victim.dropFlag
		resetCQTFFlag(dropFlag)
		removeCarrier(victim)
		victim.flag = None
		victim.dropFlag = None
		if not attacker.index == victim.index: 
			host.rcon_invoke("game.sayall \"" + victim.getName() + " team killed a flag carrier!" + "\"")
			addCTFScore(attacker, SCORE_CQTF_TKCARRIER)
	
	#reward points for killing enemy flag carrier
	elif attacker.getTeam() != victim.getTeam():
		dropFlag = victim.dropFlag
		resetCQTFFlag(dropFlag)
		removeCarrier(victim)
		victim.flag = None
		victim.dropFlag = None
		host.rcon_invoke("game.sayall \"" + attacker.getName() + " killed an enemy flag carrier!" + "\"")
		addCTFScore(attacker, SCORE_CQTF_KILLCARRIER)

def onPlayerRevivedCQTF(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 onPlayerSpawnCQTF(player, soldier):
	global CQTF_INITIALIZED
	player.killed = False
	player.changedTeam = False
	player.dropFlag = None

	if not CQTF_INITIALIZED:
		CQTF_INITIALIZED = True		
		getSetCQTF()
		initCQTFSupport()

def getSetCQTF():
	global EU_DROP_FLAGS, PAC_DROP_FLAGS, EU_TEAM_CARRIERS, PAC_TEAM_CARRIERS
	EU_DROP_FLAGS = []
	PAC_DROP_FLAGS = []
	EU_TEAM_CARRIERS = []
	PAC_TEAM_CARRIERS = []
	
	objects = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.PlayerControlObject')
	for obj in objects:
		if obj.templateName == "eu_dropflag_l1":
			setInPlay(obj, 1)
			obj.team = 2
			if len(EU_DROP_FLAGS) == 0:
				EU_DROP_FLAGS = [obj]
			else:
				EU_DROP_FLAGS.append(obj)
					
			id = bf2.triggerManager.createHemiSphericalTrigger(obj, onCQTFDropTrigger, '<<PCO>>', 0.5, (1, 2, 3))
			obj.triggerId = id
			
		elif obj.templateName == "pac_dropflag_l1":
			setInPlay(obj, 1)
			obj.team = 1
			if len(PAC_DROP_FLAGS) == 0:
				PAC_DROP_FLAGS = [obj]
			else:
				PAC_DROP_FLAGS.append(obj)
			
			id = bf2.triggerManager.createHemiSphericalTrigger(obj, onCQTFDropTrigger, '<<PCO>>', 0.5, (1, 2, 3))
			obj.triggerId = id

	
def onEnterVehicleCQTF(player, vehicle, freeSoldier = False):
	rootVehicle = bf2.objectManager.getRootParent(vehicle)
	# update flag takeover status if player in a CP radius
	if player == None:
		return
	
	cp = getOccupyingCP(player)
	playersInVehicle = rootVehicle.getOccupyingPlayers()
	if cp != None and player == playersInVehicle[0]:
		occupyingPlayers = rootVehicle.getOccupyingPlayers()
		for p in occupyingPlayers:
			p.setIsInsideCP(False)
		if cp.cp_getParam('unableToChangeTeam') == 0:
			player.setIsInsideCP(True)
	else:		
		player.setIsInsideCP(False)

def onExitVehicleCQTF(player, vehicle):
	# Player remaining in vehicle might capture CP
	playersInVehicle = vehicle.getOccupyingPlayers()
	if len(playersInVehicle) != 0:
		remainingPlayer = playersInVehicle[0]
		if remainingPlayer != None:
			cpRm = getOccupyingCP(remainingPlayer)
			if cpRm != None and cpRm.cp_getParam('unableToChangeTeam') == 0:
				remainingPlayer.setIsInsideCP(True)

	# update flag takeover status if player in a CP radius
	cp = getOccupyingCP(player)
	if cp != None and cp.cp_getParam('unableToChangeTeam') == 0:
		player.setIsInsideCP(True)
	else:		
		player.setIsInsideCP(False)
		
# find cp that player is occupying, if any		
def getOccupyingCP(player):	
	if player == None: return

	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
	
#Object has spawned
def onVehicleSpawnCQTF(spawnedObject):
	global EU_TEAM_CARRIERS, PAC_TEAM_CARRIERS
	if checkHolder(spawnedObject):
		root = bf2.objectManager.getRootParent(spawnedObject)
		carrier = findCarrier(spawnedObject)
		carrierTeam = carrier.getTeam()
		carrierDropFlag = None
		try:
			carrierDropFlag = carrier.dropFlag
		except: pass
		
		if carrierDropFlag: #he was a carrier and clicked the button again
			spawnedObject.setDamage(-1)
			flagHolderDestroyed(carrier, carrierDropFlag)
			removeCarrier(carrier)
			
		else:
			df = getOccupyingDF(carrier)
			if df != None and getInPlay(df):
				if carrierTeam == 1 and len(PAC_TEAM_CARRIERS) == 0 or \
				carrierTeam == 1 and len(PAC_TEAM_CARRIERS) < len(PAC_DROP_FLAGS):
					linkedDropFlag = df
						
					if len(PAC_TEAM_CARRIERS) == 0:
						PAC_TEAM_CARRIERS = [carrier]
					else:
						PAC_TEAM_CARRIERS.append(carrier)
					
					spawnedObject.dropFlag = linkedDropFlag
					spawnedObject.carrier = carrier
					setInPlay(linkedDropFlag, 0)
					carrier.dropFlag = linkedDropFlag	
					carrier.flag = spawnedObject
					removeFlag(spawnedObject, EU_FLAG_TEMPLATE, None) 
					removeFlag(linkedDropFlag, PAC_DF_TEMPLATE, None)
				
				elif carrierTeam == 2 and len(EU_TEAM_CARRIERS) == 0 or \
				carrierTeam == 2 and len(EU_TEAM_CARRIERS) < len(EU_DROP_FLAGS):
					linkedDropFlag = df
					
					if len(EU_TEAM_CARRIERS) == 0:
						EU_TEAM_CARRIERS = [carrier]
					else:
						EU_TEAM_CARRIERS.append(carrier)
						
					spawnedObject.dropFlag = linkedDropFlag
					spawnedObject.carrier = carrier
					setInPlay(linkedDropFlag, 0)
					carrier.dropFlag = linkedDropFlag
					carrier.flag = spawnedObject
					removeFlag(spawnedObject, PAC_FLAG_TEMPLATE, None)
					removeFlag(linkedDropFlag, EU_DF_TEMPLATE, None)
				
				else:
					spawnedObject.dropFlag = None
					spawnedObject.setDamage(-1)
					onVehicleDestroyedCQTF(spawnedObject, carrier)
		
			else:
				spawnedObject.dropFlag = None
				spawnedObject.setDamage(-1)
				onVehicleDestroyedCQTF(spawnedObject, carrier)


def onVehicleDestroyedCQTF(vehicle, attacker):
	if not checkHolder(vehicle):
		return
	
	if attacker.dropFlag:
		carrier = vehicle.carrier
		dropFlag = vehicle.dropFlag
		resetCQTFFlag(dropFlag)
		carrier.flag = None
		carrier.dropFlag = None

	
def flagHolderDestroyed(player, dropFlag):
	resetCQTFFlag(dropFlag)
	player.flag = None
	player.dropFlag = None
	cp = getOccupyingCP(player)
	if cp != None:
		player.setIsInsideCP(False)
		onCPTrigger(-1, cp, player.getVehicle(), True, None)
		

def removeCarrier(player):
	global EU_TEAM_CARRIERS, PAC_TEAM_CARRIERS
	
	index = 0
	for carrier in EU_TEAM_CARRIERS:
		if carrier.index == player.index:
			del EU_TEAM_CARRIERS[index]
		else:
			index += 1
			
	index = 0
	
	for carrier in PAC_TEAM_CARRIERS:
		if carrier.index == player.index:
			del PAC_TEAM_CARRIERS[index]
		else:
			index += 1
			
def searchCarrier(player):
	foundCarrier = False
	for carrier in EU_TEAM_CARRIERS:
		if carrier.index == player.index:
			foundCarrier = True
	
	for carrier in PAC_TEAM_CARRIERS:
		if carrier.index == player.index:
			foundCarrier = True
			
	return foundCarrier
			
def getOccupyingDF(player):
	if player == None: return

	vehicle = player.getVehicle()
	playerPos = vehicle.getPosition()
	team  = player.getTeam()
	if team == 1:
		dropFlags = PAC_DROP_FLAGS
		
	elif team == 2:
		dropFlags = EU_DROP_FLAGS
	
	# find closest DF
	closestDF = None
	if len(dropFlags) == 0: return None
	for obj in dropFlags:
		distanceTo = getVectorDistance(playerPos, obj.getPosition())
		if closestDF == None or distanceTo < closestDFdist:
			closestDF = obj
			closestDFdist = distanceTo
	
	# is the player in radius?
	pcos = bf2.triggerManager.getObjects(closestDF.triggerId)
	for o in pcos:
		if o == player.getDefaultVehicle():
			return closestDF

	return None
