# supplylines

import host
import bf2
import gpm_cq
from bf2 import g_debug

g_controlPoints = []

def init():
	# events hook
	host.registerGameStatusHandler(onGameStatusChanged)
	if host.sgl_getIsAIGame() == 1:
		host.sh_setEnableCommander(0)
	else:
		host.sh_setEnableCommander(1)

	host.registerHandler('TimeLimitReached', onTimeLimitReached, 1)	

	if g_debug: print "gpm_sl.py initialized"
		
def deinit():
	bf2.triggerManager.destroyAllTriggers()
	global g_controlPoints
	g_controlPoints = []
	
	host.unregisterGameStatusHandler(onGameStatusChanged)
	
	host.unregisterHandler('TimeLimitReached', onTimeLimitReached)	
	host.unregisterHandler('ControlPointChangedOwner', onCPStatusChange)
	host.unregisterHandler('TicketLimitReached', onTicketLimitReached)
	host.unregisterHandler('PlayerDeath', onPlayerDeath)
	host.unregisterHandler('PlayerKilled', onPlayerKilled)
	host.unregisterHandler('PlayerRevived', onPlayerRevived)
	host.unregisterHandler('PlayerSpawn', onPlayerSpawn)
	host.unregisterHandler('EnterVehicle', onEnterVehicle)
	host.unregisterHandler('ExitVehicle', onExitVehicle)
	
	if g_debug: print "gpm_sl.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')
		gpm_cq.g_controlPoints = g_controlPoints
		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 = gpm_cq.Top
			else:
				obj.flagPosition = gpm_cq.Bottom

		host.registerHandler('ControlPointChangedOwner', onCPStatusChange)

		# setup ticket system
		ticketsTeam1 = gpm_cq.calcStartTickets(bf2.gameLogic.getDefaultTickets(1))
		ticketsTeam2 = gpm_cq.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', onPlayerDeath)
		host.registerHandler('PlayerKilled', onPlayerKilled)
		host.registerHandler('PlayerRevived', onPlayerRevived)
		host.registerHandler('PlayerSpawn', onPlayerSpawn)
		host.registerHandler('EnterVehicle', onEnterVehicle)
		host.registerHandler('ExitVehicle', onExitVehicle)

		updateSupplyLines(1)	

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


def showControlGroups(): # temporary help function
	for obj in g_controlPoints:
		# check this CP's required groups
		if g_debug: print "Checking cp %s: team=%d group=%d supplyteam1=%d supplyteam2=%d" % \
			(obj.templateName, cp.cp_getParam('team'), obj.getSupplyGroupId(), hasSupply(obj, 1), hasSupply(obj, 2))



def hasSupply(cp, team):
	print "Checking supply for cp", cp.templateName, "team", team, "..."
	if cp.cp_getParam('onlyTakeableByTeam') != 0 and cp.cp_getParam('onlyTakeableByTeam') != team:
		return False

	groupsNeeded = cp.cp_getParam('supplyGroupsNeeded', team)
	optionalSupply = 0
	for grp in groupsNeeded:
		if g_debug: print "cp %s team %d needs supply from group %d" % (cp.templateName, team, grp[0])
		groupId = grp[0]
		optional = grp[1]
		print "group needed:", groupId, "optional:", optional
		if optional == True:
			if hasGroupUnderControl(team, groupId):
				optionalSupply += getSupplyValue(team, groupId)
		else:
			if hasGroupUnderControl(team, groupId) != True:
				if g_debug: print "=> required group %d not under control." % (groupId)
				return False
			else:
				optionalSupply += getSupplyValue(team, groupId)

	supplyNeeded = cp.cp_getParam('supplyValueNeeded', team)
		
	print "Needed: ", supplyNeeded, " received:", optionalSupply		
	if optionalSupply < supplyNeeded:
		if g_debug: print "%s team %d: Not enough supply value (%d < %d)" % (cp.templateName, team, optionalSupply, supplyNeeded)
		return False
	
	
	return True
	
	
def getSupplyValue(team, grp):
		
	cpsInGroup = host.sgl_getControlPointsInGroup(grp)
	
	supplyValue = 0
	for cp in cpsInGroup:
		value = cp.cp_getParam('supplyValue', team)
		if value != -1:
			supplyValue += value
		
	return supplyValue
	
	
def hasGroupUnderControl (team, grp):
	
	# check this groups supply status
	cpsInGroup = host.sgl_getControlPointsInGroup(grp)
	
	for cp in cpsInGroup:
		if cp.cp_getParam('team') != team:
			return False
	
	return True


def updateSupplyLines(gameStatusChanged):

	if g_debug: print "Updating supplylines"

	cps = g_controlPoints
	dirty = True
	while (dirty):
		dirty = False

		for obj in cps:
			#check this CP's required groups
			if obj.cp_getParam('unableToChangeTeam'):
				if g_debug: print "CP ", obj.templateName ," is not allowed to change team"
			else:
				if hasSupply(obj, 1) == True:
					if not obj.cp_getParam('allowCaptureByTeam', 1):
						obj.cp_setParam('allowCaptureByTeam', 1, True)	

						if obj.cp_getParam('team') != 1:
							if g_debug: print "Team 1 is now allowed to capture ", obj.templateName
							if  not gameStatusChanged and obj.cp_getParam('supplyGroupId') == 5:
								updateTicketWarning(1, -6)						
				else:
					if obj.cp_getParam('allowCaptureByTeam', 1):
						if obj.cp_getParam('team') == 1:
							if g_debug: print "Team 1 is no longer allowed to capture ", obj.templateName
							#obj.cp_setParam('team', 0)
							#dirty = True

						if not gameStatusChanged and obj.cp_getParam('supplyGroupId') == 5:
							updateTicketWarning(1, -5)
										
						obj.cp_setParam('allowCaptureByTeam', 1, False)

	
				if hasSupply(obj, 2) == True:
					if not obj.cp_getParam('allowCaptureByTeam', 2):
						obj.cp_setParam('allowCaptureByTeam', 2, True)	

						if obj.cp_getParam('team') != 2:
							if g_debug: print "Team 2 is now allowed to capture ", obj.templateName
							if  not gameStatusChanged and obj.cp_getParam('supplyGroupId') == 2:
								updateTicketWarning(2, -6)
				else:
					if obj.cp_getParam('allowCaptureByTeam', 2):	
						if obj.cp_getParam('team') == 2:
							if g_debug: print "Team 2 is no longer allowed to capture ", obj.templateName
							#obj.cp_setParam('team', 0)
							#dirty = True

						if  not gameStatusChanged and obj.cp_getParam('supplyGroupId') == 2:
							updateTicketWarning(2, -5)
						
						obj.cp_setParam('allowCaptureByTeam', 2, False)
					
						
def supplyLinesAllowTakeover(cp, team):
	if not cp.cp_getParam('allowCaptureByTeam', team):
		if g_debug: print "No supply to cp %s from team %d" % (cp.templateName, team)
		return False
				
	return True		

# called when the ticket state should be updated (for triggering messages and sounds based on tickets left)
def updateTicketWarning(team, limitId):
	gpm_cq.updateTicketWarning(team, limitId)

# wrap gpm_cq as most logic is identical
	
def onTimeLimitReached(value):
	gpm_cq.onTimeLimitReached(value)

def updateTicketLoss():
	gpm_cq.updateTicketLoss()
	
def onTicketLimitReached(team, limitId):
	gpm_cq.onTicketLimitReached(team, limitId)
	pass
	
def onPlayerDeath(victim, vehicle):
	gpm_cq.onPlayerDeathCQ(victim, vehicle)
	
def onPlayerKilled(victim, attacker, weapon, assists, object):
	gpm_cq.onPlayerKilledCQ(victim, attacker, weapon, assists, object)
	
def onPlayerRevived(victim, attacker):
	gpm_cq.onPlayerRevived(victim, attacker)
	
def onPlayerSpawn(player, soldier):
	gpm_cq.onPlayerSpawn(player, soldier)
	
def onEnterVehicle(player, vehicle, freeSoldier = False):
	gpm_cq.onEnterVehicle(player, vehicle, freeSoldier = False)
	
def onExitVehicle(player, vehicle):	
	gpm_cq.onExitVehicle(player, vehicle)

def onCPTrigger(triggerId, cp, vehicle, enter, userData):
	if not cp.isValid(): return

	team1Occupants = 0
	team2Occupants = 0

	pcos = bf2.triggerManager.getObjects(cp.triggerId)
	for o in pcos:
		for p in o.getOccupyingPlayers():
			if p.getTeam() == 1:
				team1Occupants += 1
			elif p.getTeam() == 2:
				team2Occupants += 1

	attackingTeam = 0
	team1OverWeight = team1Occupants - team2Occupants
	
	if team1OverWeight > 0 and cp.cp_getParam('team') != 1:
		attackingTeam = 1
	elif team1OverWeight < 0 and cp.cp_getParam('team') != 2:
		attackingTeam = 2
	
	if attackingTeam > 0:
		if not supplyLinesAllowTakeover(cp, attackingTeam):		
			if vehicle:	
				playersInVehicle = vehicle.getOccupyingPlayers()
				for p in playersInVehicle:
					p.setIsInsideCP(0)				
			return
	
	if g_debug: print "Ok cp %s had supply. Attacking team=%d, cpteam=%d" % (cp.templateName, attackingTeam, cp.cp_getParam('team'))

	gpm_cq.onCPTrigger(triggerId, cp, vehicle, enter, userData)		


	
		
def onCPStatusChange(cp, top):
	updateSupplyLines(0)

	scoringTeam = -1
	
	if cp.cp_getParam('team') != 0:
		if not top:
			# neutralize
			if cp.cp_getParam('team') == 1:
				scoringTeam = 2
			else:
				scoringTeam = 1

			if not cp.cp_getParam('allowCaptureByTeam', scoringTeam):
				onCPTrigger(cp.triggerId, cp, 0, 0, 0)
				updateTicketLoss()
				return
	else:

		if top:
			# capture
			if not cp.cp_getParam('allowCaptureByTeam', cp.cp_getParam('flag')):
				onCPTrigger(cp.triggerId, cp, 0, 0, 0)
				updateTicketLoss()
				return		


	gpm_cq.onCPStatusChange(cp, top)
	updateSupplyLines(0)
				
		
