# conquest

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

import host
import bf2
import math
import tokenize
from game.imports.artillery import onPlayerChangeWeaponPOE, onEnterArtyVehicle, ArtyInit, onPlayerKilledArty,  cleanUpArty
from game.scoringCommon import addScore, RPL
from game.content import getVehicleType, getArmyName, getKitType, getPassenger
from game.imports.demoRecording import demoChat
from game.poeSettings import GetSetting
from bf2 import g_debug

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


usingLauncher = None
try:
	usingLauncher = GetSetting("poe2Launcher")
	usingLauncher = int(usingLauncher[0])
except:
	pass


DOME_OF_DEATH = None
NUKE_TIME_LIMIT = None
DEMO_RECORDING = None

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

def initSettings():
	global DOME_OF_DEATH
	global NUKE_TIME_LIMIT
	global DEMO_RECORDING
	if usingLauncher:
		try:
			DOME_OF_DEATH = GetSetting("domeOfDeath")
			DOME_OF_DEATH = int(DOME_OF_DEATH[0])
		
			DEMO_RECORDING = GetSetting("demoRecording")
			DEMO_RECORDING = int(DEMO_RECORDING[0])
		except:
			if g_debug: print 'Error in returning game mode settings'
	else:
		if g_debug: print 'not using laucher'
		try:
			settingsList = open("mods/poe2/settings/POE2Settings.con".replace('/', '\\'), "r")
			tokenize.tokenize(settingsList.readline, handle_token)
			settingsList.close()
			
		except IOError:
			host.rcon_invoke('echo "WARNING! POE2Settings.con not found!"')
			DOME_OF_DEATH = 0
			NUKE_TIME_LIMIT = 0
			DEMO_RECORDING = 0

initSettings()

def init():
	# events hook
	host.registerGameStatusHandler(onGameStatusChanged)
	if host.sgl_getIsAIGame() == 1:
		host.sh_setEnableCommander(1)
	else:
		host.sh_setEnableCommander(1)
		
	host.registerHandler('TimeLimitReached', onTimeLimitReached, 1)	
		
def deinit():
	bf2.triggerManager.destroyAllTriggers()
	global g_controlPoints
	g_controlPoints = []
	host.unregisterGameStatusHandler(onGameStatusChanged)

def onGameStatusChanged(status):
	if bf2.serverSettings.getGameMode() != "gpm_cq": return
	global g_controlPoints
	global team1Name
	global team2Name
	if g_debug: print 'conquest game mode playing'
	if status == bf2.GameStatus.Playing:
		cleanUpArty()
		# add control point triggers
		g_controlPoints = bf2.objectManager.getObjectsOfType('dice.hfe.world.ObjectTemplate.ControlPoint')
		for obj in g_controlPoints:
			if DOME_OF_DEATH:
				if obj.cp_getParam('unableToChangeTeam') != 0:
					radius = float(obj.getTemplateProperty('radius'))
					id = bf2.triggerManager.createRadiusTrigger(obj, onCPMainTrigger, '<<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
			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)

		team1Name = getArmyName(bf2.gameLogic.getTeamName(1))
		team2Name = getArmyName(bf2.gameLogic.getTeamName(2))

		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('PlayerChangeWeapon', onPlayerChangeWeaponPOE)
		if DEMO_RECORDING: host.registerHandler('ChatMessage', onChatMessage)

	else:
		bf2.triggerManager.destroyAllTriggers()
		g_controlPoints = []
		
def onChatMessage(playerId, text, channel, flags):
	player = bf2.playerManager.getPlayerByIndex(playerId)
	demoChat(player, text)

def calcStartTickets(mapDefaultTickets):
	return int(mapDefaultTickets * (bf2.serverSettings.getTicketRatio() / 50.0))
	
def onTimeLimitReached(value):
	if bf2.serverSettings.getGameMode() != "gpm_cq": return
	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)

# 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
		players = bf2.playerManager.getPlayers()
		for p in players:
			if p.getTeam() == losingTeam and p.isAlive():
				foundLivingPlayer = True
				break
				
		if not foundLivingPlayer:
			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 bf2.serverSettings.getGameMode() != "gpm_cq": return
	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)		
	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)
		
	
# called when someone enters or exits cp radius
def onCPTrigger(triggerId, cp, vehicle, enter, userData):
	if not cp.isValid(): 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():
					p.enterCpAt = host.timer_getWallTime()
	
	if vehicle:	
		for p in playersInVehicle:
			playerVehicle = p.getVehicle()
			parent = playerVehicle.getParent()
			if not parent:
				if getVehicleType(playerVehicle.templateName) != 3: # check if player is in helicopter
					p.setIsInsideCP(enter)
				else:
					p.setIsInsideCP(0)
					if enter == 1:
						bf2.gameLogic.sendHudEvent(p, 66, 49) #66 = HEEnableHelpMessage, 49 = VHMExitToCaptureFlag;
			else:
				if getVehicleType(parent.templateName) != 3: # check if player is in helicopter
					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 # dep: you can get None in the result tuple when the host can't figure out what object left the trigger
		if o.getParent(): continue # jlo: getOccupyingPlayers returns all players downwards in the hierarchy, so dont count them twice
		occupyingPlayers = o.getOccupyingPlayers()
		for p in occupyingPlayers:
			playerVehicle = p.getVehicle()
			parent = playerVehicle.getParent()
			# do not count player in helicopter
			if not parent:
				if getVehicleType(playerVehicle.templateName) == 3:
					continue
			else:
				if getVehicleType(parent.templateName) == 3:
					continue

			if p.isAlive() and not p.isManDown() and not p.killed:
				pTeam = p.getTeam()
				if pTeam == 1:
					team1Occupants += 1
				else:
					team2Occupants += 1


	# determine who is actually getting it
	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)

		

	
#trigger for Dome of Death
def onCPMainTrigger(triggerId, cp, vehicle, enter, userData):
	
	if not cp.isValid(): return
	playersInVehicle = None
	
	if vehicle:
		playersInVehicle = vehicle.getOccupyingPlayers()
		
		#Get all players and check for team vs controlpoint team
		for p in playersInVehicle:
			airVehicle = False
			
			#Check if it's an air vehicle, and if so set flag to true
			playerDefaultVehicle = p.getDefaultVehicle()
			playerVehicle = p.getVehicle()
			parent = playerVehicle.getParent()
			
			if not parent and (playerVehicle != playerDefaultVehicle) and (getVehicleType(playerVehicle.templateName) == 1):
				airVehicle = True
					
			elif parent and (playerVehicle != playerDefaultVehicle) and (getVehicleType(parent.templateName) == 1):
				airVehicle = True
						
			if (cp.cp_getParam('team') == 1) and (p.getTeam() == 2):
				cpOcc = getOccupyingCP(p)
				if cpOcc == cp:
					#DAMAGING PLAYER
					if p.damagePlayerTimer == None:
						if airVehicle:
							#get distance in height between plane and controlpoint
							distance = getHeightDistance(playerVehicle.getPosition(), cp.getPosition())
							if distance <= 5:
								startDamagePlayerTimer(p, team1Name)
						else:
							startDamagePlayerTimer(p, team1Name)
				else:
					#DESTROY TIMER
					if p.damagePlayerTimer != None:
						stopDamagePlayerTimer(p, team1Name)
						return

			elif (cp.cp_getParam('team') == 2) and (p.getTeam() == 1):
				cpOcc = getOccupyingCP(p)
				if cpOcc == cp:
					#DAMAGING PLAYER
					if p.damagePlayerTimer == None:
						if airVehicle:
							#get distance in height between plane and controlpoint
							distance = getHeightDistance(playerVehicle.getPosition(), cp.getPosition())
							if distance <= 5:
								startDamagePlayerTimer(p, team2Name)
						else:
							startDamagePlayerTimer(p, team2Name)
				else:
					#DESTROY TIMER
					if p.damagePlayerTimer != None:
						stopDamagePlayerTimer(p, team2Name)
						return

def startDamagePlayerTimer(player, teamName):
	host.rcon_invoke('game.sayAll "' + player.getName() + " is inside " + teamName + " main base and is being punished."'"')
	player.damagePlayerTimer = bf2.Timer(setDamagePlayer, 1, 1, player)
	player.damagePlayerTimer.setRecurring(1)

def stopDamagePlayerTimer(player, teamName):
	host.rcon_invoke('game.sayAll "' + player.getName() + " has left " + teamName + " main base."'"')
	player.damagePlayerTimer.destroy()
	player.damagePlayerTimer = None

def setDamagePlayer(player):
	playerVehicle = player.getVehicle()
	playerDefaultVehicle = player.getDefaultVehicle()
	parent = playerVehicle.getParent()
	parentDefault = playerDefaultVehicle.getParent()
	
	if playerVehicle != playerDefaultVehicle: # player in vehicle
		if getKitType(player.getKit().templateName) == 3:
			if playerDefaultVehicle.getDamage() > 30:
				playerDefaultVehicle.setDamage((playerDefaultVehicle.getDamage() - 30))
			else: #kill player
				playerDefaultVehicle.setDamage(1.0)
				playerVehicle.setDamage(1.0)
		else: #not a medic
			if playerDefaultVehicle.getDamage() > 10:
				playerDefaultVehicle.setDamage((playerDefaultVehicle.getDamage() - 10))
			else: #kill player
				playerDefaultVehicle.setDamage(1.0)

	else: # player not in vehicle
		#print 'not in vehicle'
		if player.getPrimaryWeapon().templateName == 'medikit': # check if player has medikit out
			if playerDefaultVehicle.getDamage() > 20:
				#Draw 20 health points from player with medikit
				playerDefaultVehicle.setDamage((playerDefaultVehicle.getDamage() - 20))
			else:
				# kill player
				if parentDefault: # player in parachute
					playerDefaultVehicle.setDamage(1.0)
				else:
					playerDefaultVehicle.setDamage(0.0)
		else:
			if playerDefaultVehicle.getDamage() > 10:
				playerDefaultVehicle.setDamage((playerDefaultVehicle.getDamage() - 10))
			else:
				if parentDefault: # player in parachute
					playerDefaultVehicle.setDamage(1.0)
				else:
					playerDefaultVehicle.setDamage(0.0)


# called when a control point flag reached top or bottom
def onCPStatusChange(cp, top):
	if bf2.serverSettings.getGameMode() != "gpm_cq": return
	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:
			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:
			pass
			# hit bottom, but still neutral

	# scoring
	if takeoverType > 0:
		pcos = bf2.triggerManager.getObjects(cp.triggerId)
	
		# count number of players
		scoringPlayers = []
		firstPlayers = []
		for o in pcos:
			occupyingPlayers = o.getOccupyingPlayers()
			if not occupyingPlayers:
				pass 
			
			for p in occupyingPlayers:
				playerVehicle = p.getVehicle()
				parent = playerVehicle.getParent()
				# do not count player in helicopter
				if not parent:
					if getVehicleType(playerVehicle.templateName) == 3:
						continue
				else:
					if getVehicleType(parent.templateName) == 3:
						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 bf2.serverSettings.getGameMode() != "gpm_cq": return	
	#remove DoD timer and print msg if killed by DoD
	if victim != None and victim.damagePlayerTimer != None:
		victim.damagePlayerTimer.destroy()
		victim.damagePlayerTimer = None
		if not victim.killedByEnemy: # check that player wasn't killed by enemy in DoD
			host.rcon_invoke('game.sayAll "' + victim.getName() + " has been killed for basecamping."'"')

	# punish team with one ticket
	if victim != None:
		team = victim.getTeam()
		teamTickets = bf2.gameLogic.getTickets(team)
		teamTickets -= 1
		bf2.gameLogic.setTickets(team, teamTickets)
		

	# check if it was the last player
	foundLivingPlayer = False
	players = bf2.playerManager.getPlayers()
	for p in players:
		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 bf2.serverSettings.getGameMode() != "gpm_cq": return
	if not victim: 
		return
	
	#send to arty method for testing of assist
	onPlayerKilledArty(victim, attacker, weapon)
	
	if attacker != None:
		victim.killedByEnemy = True #set flag to disable messaging of people dying in DoD

	victim.killed = True # Remove this flag to enabled players in "man down"-state to captuer flags
	
	# 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 g_debug: print "CP found:", cp.templateName
			if cp != None and cp.cp_getParam('team') == attacker.getTeam():
				#if g_debug: print "Player %d defended %s" % (attacker.index, cp.templateName)
				attacker.score.cpDefends += 1
				addScore(attacker, SCORE_DEFEND, RPL)
				bf2.gameLogic.sendGameEvent(attacker, 12, 1) #12 = Conquest, 1 = Defend
				
	
			
			
def onPlayerRevived(victim, attacker):
	if bf2.serverSettings.getGameMode() != "gpm_cq": return
	# update flag takeover status if victim was in a CP radius
	victim.killed = False
	
	cp = getOccupyingCP(victim)
	if cp != None:
		if cp.cp_getParam('unableToChangeTeam') != 0:
			onCPMainTrigger(-1, cp, victim.getVehicle(), True, None)
		else:
			onCPTrigger(-1, cp, victim.getVehicle(), True, None)
	
def onPlayerSpawn(player, soldier):
	if bf2.serverSettings.getGameMode() != 'gpm_cq': return
	player.killed = False
	
	#add in DoD timer for player
	player.damagePlayerTimer = None
	player.killedByEnemy = False
	
	# Set up artillery system
	ArtyInit()

	
def onEnterVehicle(player, vehicle, freeSoldier = False):
	if bf2.serverSettings.getGameMode() != "gpm_cq": return
	onEnterArtyVehicle(player, vehicle)
	
	# update flag takeover status if player in a CP radius
	cp = getOccupyingCP(player)
	if cp != None and cp.cp_getParam('unableToChangeTeam') != 1:
		player.setIsInsideCP(True)
	else:		
		player.setIsInsideCP(False)

def onExitVehicle(player, vehicle):
	if bf2.serverSettings.getGameMode() != "gpm_cq": return
	#onExitArtyVehcile(player, vehicle)
			
	# update flag takeover status if player in a CP radius
	cp = getOccupyingCP(player)
	if cp != None and cp.cp_getParam('unableToChangeTeam') != 1:
		player.setIsInsideCP(True)
	else:		
		player.setIsInsideCP(False)

#Update cp capture status on players in vehicle
def updateCaptureStatus(vehicle):	
	rootVehicle = bf2.objectManager.getRootParent(vehicle)
	playersInVehicle = rootVehicle.getOccupyingPlayers()
	vehicleType = getVehicleType(rootVehicle.templateName)
	
	# set players in helicopters as outside, others inside
	for p in playersInVehicle:
		if vehicleType != 3:
			p.setIsInsideCP(true)
		else:
			p.setIsInsideCP(false)
		
# 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:
			occupyingPlayers = o.getOccupyingPlayers()
			for p in occupyingPlayers:
				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])


# get height distance between two positions
def getHeightDistance(pos1, pos2):
	diffHeight = pos1[1] - pos2[1]
	 
	return diffHeight