# common scoring 

import host
import bf2
import math

from bf2.stats.constants import *
from bf2 import g_debug

SCORE_KILL = 1
SCORE_TEAMKILL = -3
SCORE_SUICIDE = -2
SCORE_REVIVE = 1
SCORE_HEAL = 1
SCORE_RESUPPLY = 1
SCORE_REPAIR = 1
SCORE_STRATEGIC = 1
SCORE_STRATEGICREPAIR = 1
SCORE_EMP = 0.5
SCORE_DAMAGETITAN = 1
SCORE_DESTROYTITANWEAPON = 2
SCORE_REPAIRTITANWEAPON = 2
SCORE_DESTROYTITANPART = 2
SCORE_REPAIRTITANPART = 2
SCORE_DESTROYTITANCORE = 2
SCORE_REPAIRTITANCORE = 2
SCORE_DESTROYGROUNDCANNON = 2
SCORE_REPAIRGROUNDCANNON = 2
SCORE_DESTROYMISSILE = 2
SCORE_TEAMDAMAGE = -1
SCORE_TEAMVEHICLEDAMAGE = -1
SCORE_DESTROYREMOTECONTROLLED = 1
SCORE_DESTROYVEHICLESHIELD = 1
SCORE_DESTROYIFVVEHICLE = 1
SCORE_DROP = 1

SCORE_TITANATTACKBONUS = 1
SCORE_TITANDEFENDBONUS = 1
SCORE_MAX_SQUADORDER = 10 # to make this tweakable
SCORE_SO_REVIVE = 1
SCORE_SO_HEAL = 1
SCORE_SO_REPAIR = 1
SCORE_SO_REAMMO = 1
SCORE_SO_KILL = 0.5
SCORE_SO_PICKUP = 0
SCORE_SO_DROP = 0

SCORE_SM_REVIVE = 0
SCORE_SM_HEAL = 0
SCORE_SM_REPAIR = 0
SCORE_SM_REAMMO = 0
SCORE_SM_DROP = 0

SCORE_SM_KILLASSIST_DRIVER = 0.5
SCORE_SM_KILLASSIST_PASSENGER = 0
SCORE_SM_KILLASSIST_TARGETER = 0
SCORE_SM_KILLASSIST_DAMAGE = 0.5

SCORE_KILLASSIST_DRIVER = 0.5
SCORE_KILLASSIST_PASSENGER = 0
SCORE_KILLASSIST_TARGETER = 0.5
SCORE_KILLASSIST_DAMAGE = 0.5

TITAN_BONUSSCOREDIST = 100
TITAN_HORISONTAL_DROPDIST = 100
TITAN_VERTICAL_DROPDIST = 200
TITAN_HORISONTAL_SPAWNDIST = 3000
TITAN_VERTICAL_SPAWNDIST = 1500
TITAN_ENTER_DISTANCE = 300

REPAIR_POINT_LIMIT = 50
HEAL_POINT_LIMIT = 50
GIVEAMMO_POINT_LIMIT = 100
TEAMDAMAGE_POINT_LIMIT = 50
TEAMVEHICLEDAMAGE_POINT_LIMIT = 50

REPLENISH_POINT_MIN_INTERVAL = 30	# seconds
SQUADLEADER_BONUS_MOD = 1
COMMANDER_BONUS_MOD = 1
AWAY_BONUS_MOD = 2

TITAN_WEAPONS_DESTROY_LIMIT = 8
TITAN_WEAPONS_REPAIR_LIMIT = 8
TITAN_WEAPONS_TIME_LIMIT = 10

MAX_EMP_TIME = 5

# sub score
NORMAL = 0
SKILL = 1
RPL = 2
CMND = 3
SQUAD = 4
SQUADMEMBER = 5

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

def init():

	# set limits for how many repair HPs etc are needed to get a callback
	bf2.gameLogic.setHealPointLimit(HEAL_POINT_LIMIT)
	bf2.gameLogic.setRepairPointLimit(REPAIR_POINT_LIMIT)
	bf2.gameLogic.setGiveAmmoPointLimit(GIVEAMMO_POINT_LIMIT)
	bf2.gameLogic.setTeamDamagePointLimit(TEAMDAMAGE_POINT_LIMIT)
	bf2.gameLogic.setTeamVehicleDamagePointLimit(TEAMVEHICLEDAMAGE_POINT_LIMIT)
	
	host.registerGameStatusHandler(onGameStatusChanged)
	
	if g_debug: print "scoring common init"



def onGameStatusChanged(status):
	global g_titansMap

	if status == bf2.GameStatus.Playing:
		g_titansMap = []
			
		host.registerHandler('PlayerKilled', onPlayerKilled)
		host.registerHandler('PlayerDeath', onPlayerDeath)
		host.registerHandler('PlayerRevived', onPlayerRevived)
		host.registerHandler('PlayerHealPoint', onPlayerHealPoint)
		host.registerHandler('PlayerRepairPoint', onPlayerRepairPoint)
		host.registerHandler('PlayerGiveAmmoPoint', onPlayerGiveAmmoPoint)
		host.registerHandler('PlayerTeamDamagePoint', onPlayerTeamDamagePoint)
		host.registerHandler('PlayerScore', onPlayerScore)
		host.registerHandler('Emp', onEmp)
		#host.registerHandler('VehicleDamage', onVehicleDamage)
		host.registerHandler('VehicleDestroyed', onVehicleDestroyed)
		host.registerHandler('TitanPartDestroyed', onTitanPartDestroyed)
		host.registerHandler('TitanPartRepaired', onTitanPartRepaired)
		host.registerHandler('TitanCoreDestroyed', onTitanCoreDestroyed)
		host.registerHandler('TitanCoreRepaired', onTitanCoreRepaired)
		host.registerHandler('TitanWeaponDestroyed', onTitanWeaponDestroyed)
		host.registerHandler('TitanWeaponRepaired', onTitanWeaponRepaired)
		host.registerHandler('GroundCannonDestroyed', onGroundCannonDestroyed)
		host.registerHandler('GroundCannonRepaired', onGroundCannonRepaired)
		host.registerHandler('MissileDestroyed', onMissileDestroyed)
		host.registerHandler('VehicleSpawn', onVehicleSpawn, 1)
		host.registerHandler('ExitVehicle', onExitVehicle)
		host.registerHandler('EnterVehicle', onEnterVehicle)
		host.registerHandler('AutoControllerDestroyed', onAutoControllerDestroyed)
		host.registerHandler('CommanderAssetRepaired', onCommanderAssetRepaired)
		host.registerHandler('VehicleShieldDestroyed', onVehicleShieldDestroyed)
		
	
	elif status == bf2.GameStatus.EndGame:

		giveCommanderEndScore(bf2.playerManager.getCommander(1), bf2.gameLogic.getWinner())
		giveCommanderEndScore(bf2.playerManager.getCommander(2), bf2.gameLogic.getWinner())
		
		
#Object has spawned
def onVehicleSpawn(object):
	if checkTitan(object, 0):
		if g_debug: print "Titan: ", object.templateName," of team: ", object.getTeam(), " added to titan map"
		g_titansMap.append(object)
			
# give commander score for every player score
def addScore(player, points, subScore = NORMAL, subPoints = -1):

	# commander doesnt get score for regular actions, only for pure commander tasks. he also gets punishing points.
	if not player.isCommander() or subScore == CMND or points < 0:
	
		if subPoints == -1:
			subPoints = points

		# sub score
		if subScore == RPL:
			player.score.rplPyScore += subPoints			
			player.score.rplScore = int(player.score.rplPyScore)
		elif subScore == SKILL:
			player.score.skillScore += subPoints
		elif subScore == CMND:
			player.score.cmdPyScore += subPoints
			if bf2.serverSettings.getGameMode() == "gpm_ti":
					player.score.cmdTitanScore += subPoints
		elif subScore == SQUAD:			
			#Give the squadleader of the player a bonus score for every squad point
			giveSquadMemberBonusScore(player, points)
			giveSquadLeaderBonusScore(player, points)				
		elif subScore == SQUADMEMBER:	
			giveSquadMemberBonusScore(player, points)
		
		giveAwayBonysScore(player, points)	
		
		if subScore != SQUAD and subScore != SQUADMEMBER:
			player.score.score += points

	# commander score
	commander = bf2.playerManager.getCommander(player.getTeam())
	if commander != None and commander.isValid() and subScore != CMND and player != commander and points > 0:
		numPlayers = bf2.playerManager.getNumberOfAlivePlayersInTeam(commander.getTeam())
		if numPlayers > 0:
			scoreGotten = float(points) / numPlayers
			commander.score.score += scoreGotten 
			if scoreGotten > 0:
				commander.score.cmdPyScore += scoreGotten
				if bf2.serverSettings.getGameMode() == "gpm_ti":
					commander.score.cmdTitanScore += scoreGotten

def giveAwayBonysScore(player, points):
	if player == None: return
	
	#Add away bonus points if the played time is less then the remaining away bonus time
	if player.stats.timePlayed < player.stats.awayBonusTimeLeft:
		player.score.awayBonusScore += float(points)/float(AWAY_BONUS_MOD)
		if g_debug: print player.getName(), " has ", int(player.score.awayBonusScore), " away bonus score"

def giveCommanderEndScore(player, winningTeam):
	if player == None: return

	multiplier = 1

	if player.getTeam() == winningTeam: 
		multiplier = 2
	
	# double the commander score and add to regular score
	player.score.score = (player.score.score + player.score.fracScore - player.score.cmdPyScore) + player.score.cmdPyScore * multiplier
	player.score.cmdScore = int(player.score.cmdPyScore * multiplier)

	if bf2.serverSettings.getGameMode() == "gpm_ti":
		player.score.cmdTitanScore = player.score.cmdPyScore
	
def giveSquadMemberBonusScore(player, points):
	if player and points != 0 and player.getSquadId() > 0 and not player.isSquadLeader():
		player.score.experienceScore += points
		player.score.squadMemberBonusScore += points
		if g_debug: print player.getName(), " has ", player.score.squadMemberBonusScore, " SM score"

def giveSquadLeaderBonusScore(player, points):
	if player and points != 0 and player.getSquadId() > 0 and not player.isSquadLeader():
		squadLeader = bf2.playerManager.getSquadLeader(player.getTeam(), player.getSquadId())
		
		if squadLeader != None:
			oldScore = squadLeader.score.squadLeaderBonusScore
			squadLeader.score.experienceScore += float(points)/float(SQUADLEADER_BONUS_MOD)
			squadLeader.score.squadLeaderBonusScore += float(points)/float(SQUADLEADER_BONUS_MOD)
			giveCommanderBonusScore(player, points)

			#Only send when player actually will recieve a score in EOR
			if int(squadLeader.score.squadLeaderBonusScore) > int(oldScore):
				bf2.gameLogic.sendGameEvent(squadLeader, 21, 1) #21 = Bonus, 1 = SquadLeader

			if g_debug: print squadLeader.getName(), " has ", squadLeader.score.squadLeaderBonusScore, " SL score"
			
			

def giveCommanderBonusScore(player, points):
	if player and points != 0:
		commander = bf2.playerManager.getCommander(player.getTeam())
		if commander != None and commander.isValid() and player != commander:
			oldScore = commander.score.commanderBonusScore			
			commander.score.experienceScore += float(points)/float(COMMANDER_BONUS_MOD)
			commander.score.commanderBonusScore += float(points)/float(COMMANDER_BONUS_MOD)

			#Only send when player actually will recieve a score in EOR
			if int(commander.score.commanderBonusScore) > int(oldScore):
				bf2.gameLogic.sendGameEvent(commander, 21, 2) #21 = Bonus, 2 = Commander

			if g_debug: print commander.getName(), " has ", commander.score.commanderBonusScore, " commander score"

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

	killedByEmptyVehicle = False
	countAssists = False
	
	# killed by unknown, no score
	if attacker == None:
		
		# check if killed by vehicle in motion
		if weapon == None and object != None:
			if hasattr(object, 'lastDrivingPlayerIndex'):
				attacker = bf2.playerManager.getPlayerByIndex(object.lastDrivingPlayerIndex)
				killedByEmptyVehicle = True
			elif hasattr(object, 'lastEMPedTime') and object.lastEMPedTime + MAX_EMP_TIME > host.timer_getWallTime():
				attacker = object.lastEMPedBy

		if attacker == None:
			#Could have been jumping off a cliff and someone could have done him some damage before...
			countAssists = True				
			if g_debug: print "No attacker found"

	#bail out if we have no victim (happens when killing auto controllers)
	if victim == None:
		return
	
	victimVehicle = victim.getVehicle()


	# killed by remote controlled vehicle, no score awarded in this game
	if victimVehicle and victimVehicle.isPlayerControlObject and victimVehicle.getIsRemoteControlled():
		pass
		
	# no attacker, killed by object
	elif attacker == None:
		#Could have been jumping off a cliff and someone could have done him some damage before...
		countAssists = True
		
	# killed by self
	elif attacker == victim:

		# no suicides from own wreck
		if killedByEmptyVehicle and object.getIsWreck():
			return

		attacker.score.suicides += 1
		addScore(attacker, SCORE_SUICIDE, RPL)
			
	# killed by own team	
	elif attacker.getTeam() == victim.getTeam():

		# no teamkills from wrecks
		if object != None and object.getIsWreck():
			return
			
		# no teamkills from artillery
		if weapon:
			attackerVehicle = bf2.objectManager.getRootParent(weapon)
			if attackerVehicle and attackerVehicle.isPlayerControlObject and attackerVehicle.getIsRemoteControlled():
				return

		attacker.score.TKs += 1
		addScore(attacker, SCORE_TEAMKILL, RPL)
				
		countAssists = True


	# killed by enemy
	else:
		attacker.score.kills += 1		
		addScore(attacker, SCORE_KILL, SKILL)
		
		countAssists = True

		if (victim) :
			victimVehicle = victim.getVehicle()
			if (victimVehicle) :
				giveExtraOrderPoint(attacker, victimVehicle, SCORE_SO_KILL)
				giveExtraTitanPoint(attacker, victimVehicle)

		# give field upgrade every 4th killpoint
		# if attacker.score.kills % 4 == 0:
		#	host.pers_plrGiveFieldUnlock(attacker.index)				

	# kill assist
	if countAssists and victim:
			
		for a in assists:
			assister = a[0]
			assistType = a[1]
			
			if assister and assister.getTeam() != victim.getTeam():
			
				# passenger
				if assistType == 0:
					assister.score.passengerAssists += 1
					addScore(assister, SCORE_KILLASSIST_PASSENGER, RPL)			
					giveExtraSquadAssistPoint(attacker, assister, SCORE_SM_KILLASSIST_PASSENGER)
				# targeter
				elif assistType == 1:
					# Not used anymore
					# assister.score.targetAssists += 1
					# addScore(assister, SCORE_KILLASSIST_TARGETER, RPL)
					# giveExtraSquadAssistPoint(attacker, assister, SCORE_SM_KILLASSIST_TARGETER)
					pass
				# damage
				elif assistType == 2:
					assister.score.damageAssists += 1
					addScore(assister, SCORE_KILLASSIST_DAMAGE, RPL)
					giveExtraSquadAssistPoint(attacker, assister, SCORE_SM_KILLASSIST_DAMAGE)
				# driver passenger
				elif assistType == 3:
					assister.score.driverAssists += 1
					addScore(assister, SCORE_KILLASSIST_DRIVER, RPL)	
					giveExtraSquadAssistPoint(attacker, assister, SCORE_SM_KILLASSIST_DRIVER)			
				else:
					# unknown kill type
					pass
			

def onExitVehicle(player, vehicle):
	rootVehicle = bf2.objectManager.getRootParent(vehicle)

	if rootVehicle.isPlayerControlObject:
		playersInVehicle = rootVehicle.getOccupyingPlayers()
	
		for p in playersInVehicle:
			if p == playersInVehicle[0]:
				giveTitanDropPoint(p, player, vehicle)
				return

def onEnterVehicle(player, vehicle, freeSoldier = False):
	if player == None:
		return

	closestTitan = getClosestTitan(vehicle, TITAN_ENTER_DISTANCE, player.getTeam())

	if closestTitan and player:
		player.stats.enteredCloseToTitan = True
		return
	
	player.stats.enteredCloseToTitan = False
	
def onPlayerDeath(victim, vehicle):
	if victim == None:
		return

	victim.score.deaths += 1

	
	
def onPlayerRevived(victim, attacker):
	if checkGrindBlock(attacker, bf2.objectManager.getRootParent(victim.getVehicle())):
		return
	
	if attacker == None or victim == None or attacker.getTeam() != victim.getTeam():
		return
			
	attacker.score.revives += 1
	addScore(attacker, SCORE_REVIVE, RPL)
	
	bf2.gameLogic.sendGameEvent(attacker, 10, 4) #10 = Replenish, 4 = Revive

	if (victim) :
		victimVehicle = victim.getVehicle()
		if (victimVehicle) :
			giveExtraSquadPoint(attacker, victimVehicle, SCORE_SM_REVIVE)
			giveExtraOrderPoint(attacker, victimVehicle, SCORE_SO_REVIVE, True)
	


# prevent point-exploiting by replenishing same player again
def checkGrindBlock(player, object):

	if object.isPlayerControlObject:
		defPlayers = object.getOccupyingPlayers()
		if len(defPlayers) > 0:
			defPlayer = defPlayers[0]
			
			if not hasattr(player, 'lastReplenishPointMap'):
				player.lastReplenishPointMap = {}
			else:	
				if defPlayer.index in player.lastReplenishPointMap:
					if player.lastReplenishPointMap[defPlayer.index] + REPLENISH_POINT_MIN_INTERVAL > host.timer_getWallTime():
						return True
					
			player.lastReplenishPointMap[defPlayer.index] = host.timer_getWallTime()

	return False


def onPlayerHealPoint(player, object):
	if checkGrindBlock(player, object):
		return

	player.score.heals += 1
	addScore(player, SCORE_HEAL, RPL)
	bf2.gameLogic.sendGameEvent(player, 10, 0) 	# 10 = Replenish, 0 = Heal
	
	giveDriverSpecialPoint(player)
	giveExtraSquadPoint(player, object, SCORE_SM_HEAL)
	giveExtraOrderPoint(player, object, SCORE_SO_HEAL, True)
	
	

def onPlayerRepairPoint(player, object):
	if checkGrindBlock(player, object):
		return
	
	player.score.repairs += 1
	addScore(player, SCORE_REPAIR, RPL)
	bf2.gameLogic.sendGameEvent(player, 10, 1) 	# 10 = Replenish, 1 = Repair
	
	giveDriverSpecialPoint(player)
	giveExtraOrderPoint(player, object, SCORE_SO_REPAIR, True)
	giveExtraSquadPoint(player, object, SCORE_SM_REPAIR)


def onPlayerGiveAmmoPoint(player, object):
	if checkGrindBlock(player, object):
		return
	
	player.score.ammos += 1
	addScore(player, SCORE_RESUPPLY, RPL)
	bf2.gameLogic.sendGameEvent(player, 10, 2) 	# 10 = Replenish, 2 = Ammo

	giveDriverSpecialPoint(player)
	giveExtraOrderPoint(player, object, SCORE_SO_REAMMO, True)
	giveExtraSquadPoint(player, object, SCORE_SM_REAMMO)

def giveDriverSpecialPoint(player):

	# special point given to driver, if someone in vehicle gets an abilitypoint
	vehicle = player.getVehicle()
	if vehicle and vehicle.isPlayerControlObject:
		rootVehicle = bf2.objectManager.getRootParent(vehicle)
		occPlayers = rootVehicle.getOccupyingPlayers()

		if len(occPlayers) > 0:
			driver = occPlayers[0]
	
			if driver != None and driver != player and driver.getVehicle() == rootVehicle:
				driver.score.driverSpecials += 1
				addScore(driver, 1, RPL)
				bf2.gameLogic.sendGameEvent(driver, 10, 3) #10 = Replenish, 3 = DriverAbility	
	
def onPlayerTeamDamagePoint(player, object):
	vehicleType = getVehicleType(object.templateName)
	
	if player.isCommander():
		return
	
	if vehicleType == VEHICLE_TYPE_SOLDIER:
		if player.isAlive() and not player.isManDown(): #Don't give point if victim died - teamkill handles this
			player.score.teamDamages += 1
			addScore(player, SCORE_TEAMDAMAGE, RPL)
	else:
		player.score.teamVehicleDamages += 1
		addScore(player, SCORE_TEAMVEHICLEDAMAGE, RPL)

def onPlayerScore(player, score):
	if g_debug: print player.getName(), "recieved ", score, " points"


def onVehicleDestroyed(vehicle, attacker):
	if attacker != None and checkIfOtherTeam(vehicle, attacker):
		if vehicle.getIsRemoteControlled() and not checkTitan(vehicle):
			addScore(attacker, SCORE_DESTROYREMOTECONTROLLED, RPL)
			bf2.gameLogic.sendGameEvent(attacker, 10, 5) #10 = Replenish, 5 = DestroyStrategic
		elif string.lower(vehicle.templateName) == "eu_ifv" or string.lower(vehicle.templateName) == "as_ifv":
			addScore(attacker, SCORE_DESTROYIFVVEHICLE, RPL)
			bf2.gameLogic.sendGameEvent(attacker, 10, 5) #10 = Replenish, 5 = DestroyStrategic
			
#Object is damaged
def onVehicleDamage(attacker, object, hitPoints):
	if attacker and checkTitan(object) and checkIfOtherTeam(object, attacker):
		if g_debug: print "Titan: ", object.templateName, " of team: ", object.getTeam()," lost: ", hitPoints, " hitpoints!"
		addScore(attacker, SCORE_DAMAGETITAN, RPL)
		bf2.gameLogic.sendGameEvent(attacker, 10, 8) #10 = Replenish, 5 = DamageTitan

def onVehicleShieldDestroyed(object, attacker):
	if attacker and checkIfOtherTeam(object, attacker):
		if g_debug: print "Shield: ", object.templateName, " destroyed by ", attacker.getName()
		addScore(attacker, SCORE_DESTROYVEHICLESHIELD, RPL)
		bf2.gameLogic.sendGameEvent(attacker, 10, 5) #10 = Replenish, 5 = DestroyStrategic

def onTitanCoreDestroyed(object, attacker):
	if attacker and checkTitan(object, 1) and checkIfOtherTeam(object, attacker):
		if g_debug: print "Titan core: ", object.templateName, " destroyed by ", attacker.getName()
		attacker.score.titanCoreDestroyed += 1	
		addScore(attacker, SCORE_DESTROYTITANCORE, RPL)
		bf2.gameLogic.sendGameEvent(attacker, 10, 14) #10 = Replenish, 14 = DestroyTitanCore

def onTitanCoreRepaired(object, attacker):
	if attacker and checkTitan(object, 1) and checkIfSameTeam(object, attacker):
		if g_debug: print "Titan core: ", object.templateName, " repaired by ", attacker.getName()
		attacker.score.titanCoreRepaired += 1	
		attacker.score.repairs += 1
		addScore(attacker, SCORE_REPAIRTITANCORE, RPL)
		#bf2.gameLogic.sendGameEvent(attacker, 10, 15) #10 = Replenish, 15 = RepairTitanPart

def onTitanPartDestroyed(object, attacker):
	if attacker and checkTitan(object, 1) and checkIfOtherTeam(object, attacker):
		if g_debug: print "Titan part: ", object.templateName, " destroyed by ", attacker.getName()
		attacker.score.titanPartsDestroyed += 1	
		addScore(attacker, SCORE_DESTROYTITANPART, RPL)
		bf2.gameLogic.sendGameEvent(attacker, 10, 6) #10 = Replenish, 5 = DestroyTitanPart

def onTitanPartRepaired(object, attacker):
	if attacker and checkTitan(object, 1) and checkIfSameTeam(object, attacker):
		if g_debug: print "Titan part: ", object.templateName, " repaired by ", attacker.getName()
		attacker.score.titanPartsRepaired += 1
		attacker.score.repairs += 1	
		addScore(attacker, SCORE_REPAIRTITANPART, RPL)
		#bf2.gameLogic.sendGameEvent(attacker, 10, 13) #10 = Replenish, 13 = RepairTitanPart
		
def onTitanWeaponDestroyed(object, attacker):
	if attacker and checkTitan(object, 1) and checkIfOtherTeam(object, attacker):
		if attacker.score.titanWeaponsDestroyed < TITAN_WEAPONS_DESTROY_LIMIT and (attacker.stats.lastTitanGunEventAt + TITAN_WEAPONS_TIME_LIMIT) < date():
			if g_debug: print "Titan weapon: ", object.templateName, " destroyed by ", attacker.getName()
			attacker.score.titanWeaponsDestroyed += 1	
			addScore(attacker, SCORE_DESTROYTITANWEAPON, RPL)
			attacker.stats.lastTitanGunEventAt = date()
			bf2.gameLogic.sendGameEvent(attacker, 10, 7) #10 = Replenish, 5 = DestroyTitanWeapon

def onTitanWeaponRepaired(object, attacker):
	if attacker and checkTitan(object, 1) and checkIfSameTeam(object, attacker):
		if attacker.score.titanWeaponsRepaired < TITAN_WEAPONS_REPAIR_LIMIT and (attacker.stats.lastTitanGunEventAt + TITAN_WEAPONS_TIME_LIMIT) < date():
			if g_debug: print "Titan weapon: ", object.templateName, " repaired by ", attacker.getName()
			attacker.score.titanWeaponsRepaired += 1	
			addScore(attacker, SCORE_REPAIRTITANWEAPON, RPL)
			attacker.stats.lastTitanGunEventAt = date()
			attacker.score.repairs += 1
			#bf2.gameLogic.sendGameEvent(attacker, 10, 10) #10 = Replenish, 10 = RepairTitanWeapon

def onGroundCannonDestroyed(object, attacker):
	if attacker and checkIfOtherTeam(object, attacker):
		if g_debug: print "Ground cannon: ", object.templateName, " destroyed by ", attacker.getName()
		attacker.score.groundCannonsDestroyed += 1
		addScore(attacker, SCORE_DESTROYGROUNDCANNON, RPL)
		bf2.gameLogic.sendGameEvent(attacker, 10, 9) #10 = Replenish, 9 = DestroyGroundCannon

def onGroundCannonRepaired(object, attacker):
	if attacker and checkIfSameTeam(object, attacker):
		if g_debug: print "Ground cannon: ", object.templateName, " repaired by ", attacker.getName()
		attacker.score.groundCannonsRepaired += 1
		attacker.score.repairs += 1
		addScore(attacker, SCORE_REPAIRGROUNDCANNON, RPL)
		#bf2.gameLogic.sendGameEvent(attacker, 10, 11) #10 = Replenish, 11 = RepairGroundCannon

def onMissileDestroyed(object, attacker):
		if g_debug: print "Missile: ", object.templateName, " destroyed by ", attacker.getName()
		attacker.score.missilesDestroyed += 1
		addScore(attacker, SCORE_DESTROYMISSILE, RPL)
		#bf2.gameLogic.sendGameEvent(attacker, 10, 12) #10 = Replenish, 12 = DestroyMissile

def onCommanderAssetRepaired(object, attacker):
	if checkIfSameTeam(object, attacker):
		addScore(attacker, SCORE_STRATEGICREPAIR, RPL)
		attacker.score.repairs += 1
		bf2.gameLogic.sendGameEvent(attacker, 10, 1) #10 = Replenish, 13 = RepairTitanPart



def onEmp(attacker, weapon, vehicle, level):
	if not vehicle.isValid(): return
	if g_debug: print "EMP ", attacker.getName(), level
	if level >= 1 and checkIfOtherTeam(vehicle, attacker) and vehicle.isPlayerControlObject:
		attacker.score.disabledVehicles += 1
		addScore(attacker, SCORE_EMP , RPL)
		
		victims = vehicle.getOccupyingPlayers()

		for player in victims:
			if weapon:
				weaponType = getWeaponType(weapon.templateName)
				player.stats.weapons[weaponType].disabledBy += 1	

#Check if the object is a titan and if it's valid
def checkTitan(object, checkRoot = 0):
	root = object
	
	if checkRoot == 1:
		root = bf2.objectManager.getRootParent(object)

	if object.isValid()and root.isTitan():
		if root.getTeam() != 0:
			return 1
	
	if object.isValid() and object.isTitan():
		if g_debug: print "Illegal team (", root.getTeam(), ") on titan: ", object.templateName
	elif object.isValid() and not object.isTitan():
		if g_debug: print "Titan is not valid!"
		return 0
	return 0

def checkIfSameTeam(object, player):
	root = bf2.objectManager.getRootParent(object)

	if root.isValid() and player:
		if root.getTeam() == player.getTeam():
			return 1
	return 0

def checkIfOtherTeam(object, player):
	root = bf2.objectManager.getRootParent(object)

	if root.isValid() and player:
		if root.isPlayerControlObject:
			if root.getTeam() != player.getTeam() and root.getTeam() != 0:
				return 1
	return 0

# if accepted an order from squad leader/commander and is inside radius of order marker, 
# you get extra point for killing enemy/healing/repairing/give ammo to team mate
def giveExtraOrderPoint(player, object, points, onlySquadMember = 0):
	if player and object and player.getIfAcceptedAttackDefendOrder() and points > 0 and object.isPlayerControlObject:
		isSquadLeader = onlySquadMember
		givePoint = False

		playersInVehicle = object.getOccupyingPlayers()

		for reciever in playersInVehicle:
			if reciever and reciever.getSquadId() == player.getSquadId() and reciever.getTeam() == player.getTeam():
				givePoint = True
				if not reciever.isSquadLeader():
					isSquadLeader = False
					
		if not givePoint and onlySquadMember:
			return

		distanceTo = getVectorDistance(player.getOrderPosition(), object.getPosition())
	
		if distanceTo < player.getOrderRadius():
			if not player.isSquadLeader():
				oldScore = player.score.squadMemberBonusScore

				if isSquadLeader:
					addScore(player, points, SQUADMEMBER)
				else:
					addScore(player, points, SQUAD)
				
				#Only send when player actually will recieve a score in EOR
				if int(player.score.squadMemberBonusScore) > int(oldScore):
					bf2.gameLogic.sendGameEvent(player, 21, 3) #21 = Bonus, 3 = SquadOrder

			player.setMaxOrderPoint(SCORE_MAX_SQUADORDER)
			player.setOrderPoint(points)

# if the subject is a member of the attackers squad you get extra point for healing/repairing/give ammo to squad mate
def giveExtraSquadPoint(giver, object, points):
		if object and giver and giver.getSquadId() > 0 and object.isPlayerControlObject:
			playersInVehicle = object.getOccupyingPlayers()
			for reciever in playersInVehicle:
				if reciever and points > 0 and reciever.getSquadId() == giver.getSquadId() and reciever.getTeam() == giver.getTeam():
					if not giver.isSquadLeader():
						oldScore = giver.score.squadMemberBonusScore

						if not reciever.isSquadLeader():
							addScore(giver, points, SQUAD)
						else:
							addScore(giver, points, SQUADMEMBER)
		
						#Only send when player actually will recieve a score in EOR
						if int(giver.score.squadMemberBonusScore) > int(oldScore):
							bf2.gameLogic.sendGameEvent(giver, 21, 0) #21 = Bonus, 3 = SquadMember

					giver.setMaxOrderPoint(SCORE_MAX_SQUADORDER)
					giver.setOrderPoint(points)
					return

# if the subject is a member of the attackers squad you get extra point for healing/repairing/give ammo to squad mate
def giveExtraSquadAssistPoint(attacker, assister, points):
	if assister and attacker and points > 0 and assister.getSquadId() > 0 and assister.getSquadId() == attacker.getSquadId() and assister.getTeam() == attacker.getTeam():
		if not assister.isSquadLeader():
			oldScore = assister.score.squadMemberBonusScore

			if not attacker.isSquadLeader():
				addScore(assister, points, SQUAD)
			else:
				addScore(assister, points, SQUADMEMBER)
			
			#Only send when player actually will recieve a score in EOR
			if int(assister.score.squadMemberBonusScore) > int(oldScore):
				bf2.gameLogic.sendGameEvent(assister, 21, 4) #21 = Bonus, 3 = SquadAssist
			
		assister.setMaxOrderPoint(SCORE_MAX_SQUADORDER)
		assister.setOrderPoint(points)	

# if the enemy is close to titan when killed you get extra point for killing him
def giveExtraTitanPoint(player, object):
	if player == None:
		return

	#Titan is now closer to gound and this needs to be restricted
	#closestTitan = getClosestTitan(object, TITAN_BONUSSCOREDIST)

	closestTitan = getTitanBelow(player, TITAN_BONUSSCOREDIST, TITAN_BONUSSCOREDIST, -1, 20)
	
	if closestTitan:
			if closestTitan.getTeam() == player.getTeam():
				if g_debug: print player.getName(), " defended his titan"
				player.score.titanDefendKills += 1

				if SCORE_TITANDEFENDBONUS > 0:
					bf2.gameLogic.sendGameEvent(player, 21, 5) #21 = Bonus, 5 = TitanDefend

				addScore(player, SCORE_TITANDEFENDBONUS, RPL)				
			else:
				if g_debug: print player.getName(), " attacked enemy titan"
				player.score.titanAttackKills += 1

				if SCORE_TITANATTACKBONUS > 0:
					bf2.gameLogic.sendGameEvent(player, 21, 6) #21 = Bonus, 6 = TitanAttack

				addScore(player, SCORE_TITANATTACKBONUS, RPL)

# if the enemy is close to titan when killed you get extra point for killing him
def giveTitanDropPoint(driver, player, object):
	if driver == None or player == None:
		return
	
	closestTitan = getTitanBelow(player, TITAN_HORISONTAL_DROPDIST, TITAN_VERTICAL_DROPDIST, player.getTeam())
	
	if closestTitan:
			if driver != player:
				if not player.stats.enteredCloseToTitan:
					if g_debug: print player.getName(), " dropped on enemy titan"
					addScore(driver, SCORE_DROP, RPL)
					driver.score.titanAirDrops += 1
					bf2.gameLogic.sendGameEvent(driver, 10, 3) #10 = Replenish, 3 = DriverAbility
				
					playerVehicle = player.getVehicle()

					if playerVehicle.isValid():
						giveExtraSquadPoint(driver, playerVehicle, SCORE_SM_DROP)
						giveExtraOrderPoint(driver, playerVehicle, SCORE_SO_DROP, True)				

#Get the titan below the player
def getTitanBelow(player, horisontalMaxDist, verticalMaxDist, team=-1, verticalOffset=0):
	if player == None:
		return 0

	vehicle = player.getVehicle()

	if vehicle.isValid():
		for titan in g_titansMap:
			titanPos = titan.getPosition()
			vehiclePos = vehicle.getPosition()
			horisontalDist = getVectorDistance([titanPos[0], 0.0, titanPos[2]], [vehiclePos[0], 0, vehiclePos[2]])
			verticalDist = getVectorDistance([0.0, titanPos[1], 0.0], [0.0, vehiclePos[1], 0.0])

			if horisontalDist <= horisontalMaxDist and verticalDist <= verticalMaxDist and (titanPos[1] - verticalOffset) < vehiclePos[1]:
				if titan.getTeam() != team:
					if g_debug: print player.getName(), " ", horisontalDist, "m, ", verticalDist, "m, ", "from titan"
					return titan		
	return 0	


def getClosestTitan(object, distance, team=-1):
	if object.isValid():
		for titan in g_titansMap:
			distanceTo = getVectorDistance(titan.getPosition(), object.getPosition())
			if distanceTo < distance:
				if titan.getTeam() != team:
					if g_debug: print distanceTo, "m from titan" 
					return titan
	
	return 0


# 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])		

# called when an auto controller is destroyed
def onAutoControllerDestroyed(object, attacker):
	if object == None or attacker == None:
		return

	if g_debug: print "AutoController Destroyed by: " + attacker.getName()	
	if object.getTeam() != attacker.getTeam():
		addScore(attacker, SCORE_KILL, RPL)

def date():
	return host.timer_getWallTime()
