# frontline

TAKEOVERTYPE_CAPTURE = 1
TAKEOVERTYPE_NEUTRALIZE = 2

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

Top = 0
Middle = 1
Bottom = 2

import host
import bf2
import math
import tokenize
from game.scoringCommon import addScore, RPL
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.txt 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)	

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

def onGameStatusChanged(status):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
	global g_controlPoints
	if g_debug: print 'frontlines gamemode playing'
	if status == bf2.GameStatus.Playing:

		# add control point triggers
		cpNumber = 0 # flag for setting capture status on cp
		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
			obj.cpNumber = cpNumber
			cpNumber += 1

		host.registerHandler('ControlPointChangedOwner', onCPStatusChange)

		# setup ticket system
		ticketsTeam1 = calcStartTickets(bf2.gameLogic.getDefaultTickets(1)) * 2
		ticketsTeam2 = calcStartTickets(bf2.gameLogic.getDefaultTickets(2)) * 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', onPlayerDeathFL)
		host.registerHandler('PlayerKilled', onPlayerKilledFL)
		host.registerHandler('PlayerRevived', onPlayerRevived)
		host.registerHandler('PlayerSpawn', onPlayerSpawn)
		host.registerHandler('EnterVehicle', onEnterVehicle)
		host.registerHandler('ExitVehicle', onExitVehicle)
		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() / 100.0))
	
def onTimeLimitReached(value):
	if bf2.serverSettings.getGameMode() != "gpm_fl": 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
		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 > 0 and otherTeamAreaOverweight > 0:
		ticketLossPerSecond = (bf2.gameLogic.getDefaultTicketLossPerMin(team) / 60.0) * (otherTeamAreaOverweight / 100.0) * (otherTeamAreaValue / 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_fl": 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)		

	# 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 checkFirstCP(cp):
	first = 0
	if cp.cpNumber == 0:
		first = 1	
	return first
	
def checkLastCP(cp):
	last = 0
	if cp.cpNumber == (len(g_controlPoints) - 1):
		last = 1
	return last

def getTeam1CPs():
	found = 0
	for obj in g_controlPoints:
		if obj.cp_getParam('team') == 1:
			found = 1
	
	#Didn't find any cp for team
	return found

def getTeam2CPs():
	found = 0
	for obj in g_controlPoints:
		if obj.cp_getParam('team') == 2:
			found = 1
	
	#Didn't find any cp for team
	return found
	
def bootPlayers(cpoint):
	#cappingPlayers = []
	bootedPlayers = []

	for obj in g_controlPoints:
		pcos = bf2.triggerManager.getObjects(obj.triggerId)
		for o in pcos:
			occupyingPlayers = o.getOccupyingPlayers()
			if not occupyingPlayers: pass
			for p in occupyingPlayers:
				cp = getOccupyingCP(p)
				if cp.cpNumber == cpoint.cpNumber:# and p.getIsInsideCP() == 1:
					pass
				else:
					bootedPlayers.append(p)

	for p in bootedPlayers:
		print 'booted ', p.getName()
		cp = getOccupyingCP(p)
		p.isBooted = 1
		if cp != None:
			try:
				onCPTrigger(-1, cp, p.getVehicle(), False, None)
			except: pass
		else: pass
		p.isBooted = 0
		
def checkFlagTeam():
	for cp in g_controlPoints:
		team = cp.cp_getParam('team')
		if team is 1 and cp.flagPosition is not Top:
			cp.cp_setParam('team', 0)
			cp.cp_setParam('flag', 0)
			cp.cp_setParam('team', 1)
			cp.cp_setParam('flag', 1)
			onCPTrigger(-1, cp, None, False, None)
			
		elif team is 2 and cp.flagPosition is not Top:
			cp.cp_setParam('team', 0)
			cp.cp_setParam('flag', 0)
			cp.cp_setParam('team', 2)
			cp.cp_setParam('flag', 2)
			onCPTrigger(-1, cp, None, False, None)
	
# 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:
			if p.getTeam() == 1 and cp.cp_getParam('team') != 1:
				if checkFirstCP(cp):
					if getTeam1CPs() == 0:
						p.setIsInsideCP(1)
					else:
						p.setIsInsideCP(0)
						
				elif checkLastCP(cp):
					if g_controlPoints[cp.cpNumber - 1].cp_getParam('team') == 1:
						p.setIsInsideCP(1)
					else:
						p.setIsInsideCP(0)
				else:
					if g_controlPoints[cp.cpNumber + 1].cp_getParam('team') != 1 and g_controlPoints[cp.cpNumber - 1].cp_getParam('team') == 1:
						p.setIsInsideCP(1)
					else:
						p.setIsInsideCP(0)
							
			elif p.getTeam() == 2 and cp.cp_getParam('team') != 2:
				if checkLastCP(cp):
					if getTeam2CPs() == 0:
						p.setIsInsideCP(1)
					else:
						p.setIsInsideCP(0)
						
				elif checkFirstCP(cp):
					if g_controlPoints[cp.cpNumber + 1].cp_getParam('team') == 2:
						p.setIsInsideCP(1)
					else:
						p.setIsInsideCP(0)
				else:
					if g_controlPoints[cp.cpNumber + 1].cp_getParam('team') == 2 and g_controlPoints[cp.cpNumber - 1].cp_getParam('team') != 2:
						p.setIsInsideCP(1)
					else:
						p.setIsInsideCP(0)

	# 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:	
			if p.isAlive() and not p.isManDown():
				if not p.killed:
					try:
						temp = p.isBooted
					except:
						p.isBooted = 0
					
					if p.isBooted:
						p.setIsInsideCP(0)
						p.enterCpAt = host.timer_getWallTime()
						p.isBooted = 0
					
					else:
						if p.getTeam() == 1:
							if getTeam1CPs() == 0 and checkFirstCP(cp):# and cPoint.triggerId == triggerId: #if team1 has no CPs and this is the first cp
								team1Occupants += 1
							else:
								if cp.cp_getParam('team') == p.getTeam():
									team1Occupants += 1
								elif g_controlPoints[cp.cpNumber -1].cp_getParam('team') == 1:
									if team1Occupants < 3:
										team1Occupants += 1

						elif p.getTeam() == 2:
							if getTeam2CPs() == 0 and checkLastCP(cp):# and cPoint.triggerId == triggerId:
								team2Occupants += 1
							else:
								if cp.cp_getParam('team') == p.getTeam():
									team2Occupants += 1
								elif g_controlPoints[cp.cpNumber +1].cp_getParam('team') == 2:
									if team2Occupants < 3:
										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:
		if cp.cp_getParam('team') == 0:
			attackOverWeight = -0.5
		else:
			if cp.cp_getParam('team') == 1:
				if checkFirstCP(cp):
					attackOverWeight = 1.0
				elif checkLastCP(cp):
					attackOverWeight = 0.5
				else:
					attackOverWeight = 0.5

			elif cp.cp_getParam('team') == 2:
				if checkFirstCP(cp):
					attackOverWeight = 0.5
				elif checkLastCP(cp):
					attackOverWeight = 1.0
				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 and attackOverWeight != 100:
		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)
		
# called when a control point flag reached top or bottom
def onCPStatusChange(cp, top):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
	checkFlagTeam()
	playerId = -1
	takeoverType = -1
	newTeam = -1
	scoringTeam = -1
	
	if top:	cp.flagPosition = Top
	else:   cp.flagPosition = Bottom
	
	#chaning status of a flag that is not neutral
	if cp.cp_getParam('team') != 0:
		if top:
			pass
		else: #neutralize
			newTeam = 0
			if cp.cp_getParam('team') == 1:
				if checkFirstCP(cp):
					scoringTeam = 2
					takeoverType = TAKEOVERTYPE_NEUTRALIZE
					pass
						
				elif checkLastCP(cp):
					scoringTeam = 2
					takeoverType = TAKEOVERTYPE_NEUTRALIZE
					try:
						g_controlPoints[cp.cpNumber - 1].cp_setParam('team', 0)
						g_controlPoints[cp.cpNumber - 1].cp_setParam('flag', 0)
						g_controlPoints[cp.cpNumber - 1].cp_setParam('team', 1)
						g_controlPoints[cp.cpNumber - 1].cp_setParam('flag', 1)

					except:
						pass

				else: #middle flags
					scoringTeam = 2
					takeoverType = TAKEOVERTYPE_NEUTRALIZE
					bootPlayers(cp)
					g_controlPoints[cp.cpNumber - 1].cp_setParam('team', 0)
					g_controlPoints[cp.cpNumber - 1].cp_setParam('flag', 0)
					g_controlPoints[cp.cpNumber - 1].cp_setParam('team', 1)
					g_controlPoints[cp.cpNumber - 1].cp_setParam('flag', 1)

			if cp.cp_getParam('team') == 2:
				if checkFirstCP(cp):
					scoringTeam = 1
					takeoverType = TAKEOVERTYPE_NEUTRALIZE
					g_controlPoints[cp.cpNumber + 1].cp_setParam('team', 0)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('flag', 0)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('team', 2)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('flag', 2)

				elif checkLastCP(cp):
					scoringTeam = 1
					takeoverType = TAKEOVERTYPE_NEUTRALIZE
					pass

				else: #middle flags
					scoringTeam = 1
					takeoverType = TAKEOVERTYPE_NEUTRALIZE
					bootPlayers(cp)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('team', 0)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('flag', 0)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('team', 2)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('flag', 2)


	else: #cp.cp_getParam = 0
		if top:
			newTeam = cp.cp_getParam('flag')
			scoringTeam = newTeam
			if newTeam == 1:
				if checkFirstCP(cp):
					pass
				else:
					g_controlPoints[cp.cpNumber - 1].cp_setParam('team', 0)
					g_controlPoints[cp.cpNumber - 1].cp_setParam('flag', 0)

			else:
				if checkLastCP(cp):
					pass
				else:
					g_controlPoints[cp.cpNumber + 1].cp_setParam('team', 0)
					g_controlPoints[cp.cpNumber + 1].cp_setParam('flag', 0)

			takeoverType = TAKEOVERTYPE_CAPTURE
		else:
			if g_debug: print '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()
			for p in occupyingPlayers:
				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)
	
	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 onPlayerDeathFL(victim, vehicle):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
	# 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 onPlayerKilledFL(victim, attacker, weapon, assists, object):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
	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

def onPlayerRevived(victim, attacker):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
	# 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):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
		
	player.killed = False
	
def onEnterVehicle(player, vehicle, freeSoldier = False):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return

	player.setIsInsideCP(False)
	cp = getOccupyingCP(player)
	if cp != None:
		onCPTrigger(-1, cp, vehicle, False, None)
		updateCaptureStatus(vehicle) 

def onExitVehicle(player, vehicle):
	if bf2.serverSettings.getGameMode() != "gpm_fl": return
	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:
		cp = getOccupyingCP(p)
		if p.getTeam() == 1:
			if cp.cp_getParam('team') != 2: 
					if checkLastCP(cp) == 1:
						if g_controlPoints[cp.cpNumber - 1].cp_getParam('team') != 1:
							player.setIsInsideCP(false)
					elif g_controlPoints[cp.cpNumber - 1].cp_getParam('team') != 1 or g_controlPoints[cp.cpNumber - 1].cp_getParam('team') == 1:
						player.setIsInsideCP(false)
					else:
						player.setIsInsideCP(true)

		elif p.getTeam() == 2:
			if cp.cp_getParam('team') != 2: 
					if checkFirstCP(cp) == 1:
						if g_controlPoints[cp.cpNumber + 1].cp_getParam('team') != 2:
							player.setIsInsideCP(false)
					elif g_controlPoints[cp.cpNumber + 1].cp_getParam('team') != 2 or g_controlPoints[cp.cpNumber - 1].cp_getParam('team') == 2:
						player.setIsInsideCP(false)
					else:
						player.setIsInsideCP(true)
						
# 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])
