local ScenarioUtils = import('/lua/sim/ScenarioUtilities.lua')
local ScenarioFramework = import('/lua/ScenarioFramework.lua')
local Utilities = import('/lua/utilities.lua')
local AIUtils = import('/lua/AI/aiutilities.lua')

##This works fairly simply and is easy to make work with any map.
##Create a series of markers on the map, named WAYPOINT_# from 0 to however many you want
##The defence object will spawn at WAYPOINT_0
##To make any waypoint the final waypoint, place a second marker on top of it named it GOAL

###For every waypoint, make a marker named GROUNDSPAWN.  The script keeps track of which
### waypoint the defense object is closest to and spawns ground units from this marker.
##For WAYPOINT_1 there must be a GROUNDSPAWN_1 and so forth for every waypoint.

###For every waypoint, make a marker named AIRSPAWN.  The script keeps track of which
### waypoint the defense object is closest to and spawns air units from this marker.
##For WAYPOINT_1 there must be a AIRSPAWN_1 and so forth for every waypoint.

##T1 units will spawn for Waypoints 0 to 5.  T2 for 5 to 9.  T3 for 10 and up.

#Boss Battles are battles with experimental enemies, specifically Ythothas.  Map maker must specify how many boss #battles he ##has in his map (0 or 50, however many.)  Each ##Boss encounter requires 2 makers, BOSS_BATTLE_1 is the 
#marker that the defense object will cross.  When the defense object is within 50 units, a warning will be given to 
#the team.  When the defense 
##object is within 10 units the Ythothas will spawn at the marker BOSSSPAWN_1 and the 
#players will be given another warning.  
##The script #will then monitor the distance until the next boss battle marker (BOSS_BATTLE_2). Thus boss battles must occur 
##in order, 1 before 2 before 3 before 4, etc etc.
##Note that the number of XPs that #spawn is dependent on the marker number.  1 will spawn for BOSS_BATTLE_1, 2 for 
##BOSS_BATTLE_2, etc etc.  

#Naval Battles can be created.  Place a 'WATERSPAWN' marker where naval units are to spawn.  The script will check 
##the current status of the Defense Object.  If it is under water (and AttackViaWater = 'true') then naval units will ##periodically spawn at the naval waypoint and attack,  ##'Periodically' being defined as the user-inputted WaveDelay * 5.
##Naval unit spawns will cease when the Defense Object leaves the water.  (Ground/air spawns will continue the whole time, 
## fyi)

###Lastly, playable areas are supported.  This allows certain parts of the map to be 'unlocked', like in campaign.
##The script assumes (and requires) that you specified an AREA_1.  If you want no expansion, make AREA_1 the whole map.
##The script also assumes that MAP_EXPANSION_1 will open up area 2 (because AREA_1 starts open) and 2 opens 3, 3 opens 4, etc etc.
##I recommend placing a map expansion point on top of a waypoint so you're 100% sure that it will be triggered.


local AttackViaWater = 'true' #Map maker needs to specify if he wants the defense object attacked while under water. 
#This is the only value that still needs to be input by the map maker


local TargetWaypoint = 0  #Do not touch plx
local TotalWaypoints = nil  #Map maker needs not fuck with this any longer
local TotalBossBattles = nil #Map maker needs not input this value either
local TotalExpansionPoints = nil  #The number of playable areas - 1.  Don't bother adjusting this.
local CurrentArea = 1


local oldOnPopulate = OnPopulate

   function OnPopulate()
        #oldOnPopulate()
        ScenarioUtils.InitializeArmies()
	Survival_InitGame()
 	ScenarioFramework.SetPlayableArea('AREA_1', false)
   end

   local oldOnStart = OnStart
   function OnStart(self)
      oldOnStart(self)
   end

   
   
   
-- econ adjust based on who is playing
-- taken from original survival/Jotto
--------------------------------------------------------------------------
function ScenarioUtils.CreateResources()
	local Markers = ScenarioUtils.GetMarkers();

	for i, tblData in pairs(Markers) do -- loop marker list
		local SpawnThisResource = false; -- default to no
		if (tblData.resource and not tblData.SpawnWithArmy) then -- if this is a regular resource
			SpawnThisResource = true;
		elseif (tblData.resource and tblData.SpawnWithArmy) then -- if this is an army-specific resource
			if (tblData.SpawnWithArmy == "ARMY_0") then
				SpawnThisResource = true;
			else
				for x, army in ListArmies() do -- loop through army list

					if (tblData.SpawnWithArmy == army) then -- if this army is present
						SpawnThisResource = true; -- spawn this resource
						break;
					end
				end
			end
		end

		if (SpawnThisResource) then -- if we can spawn the resource do it
			local bp, albedo, sx, sz, lod;
			if (tblData.type == "Mass") then
				albedo = "/env/common/splats/mass_marker.dds";
				bp = "/env/common/props/massDeposit01_prop.bp";
				sx = 2;
				sz = 2;
				lod = 100;
			else
				albedo = "/env/common/splats/hydrocarbon_marker.dds";
				bp = "/env/common/props/hydrocarbonDeposit01_prop.bp";
				sx = 6;
				sz = 6;
				lod = 200;
			end
			-- create the resource
			CreateResourceDeposit(tblData.type,	tblData.position[1], tblData.position[2], tblData.position[3], tblData.size);

			-- create the resource graphic on the map
			CreatePropHPR(bp, tblData.position[1], tblData.position[2], tblData.position[3], Random(0,360), 0, 0);

			-- create the resource icon on the map
			CreateSplat(
				tblData.position,           # Position
				0,                          # Heading (rotation)
				albedo,                     # Texture name for albedo
				sx, sz,                     # SizeX/Z
				lod,                        # LOD
				0,                          # Duration (0 == does not expire)
				-1,                         # army (-1 == not owned by any single army)
				0							# ???
			);
		end
	end
end

## broadcast a text message to players
----------------------------------------------------------------------------
BroadcastMSG = function(MSG, Fade, TextColor)
	PrintText(MSG, 20, TextColor, Fade, 'center')	
end


-- initializes the game settings
--------------------------------------------------------------------------
Survival_InitGame = function()
	LOG("-------Finding important Markers------")
	local WaypointMarkers = {}
	local BossMarkers = {}
	local BossSpawnMarkers = {}
	local MapExpansionMarkers = {}
    local Markers = ScenarioUtils.GetMarkers()
	for i,name in Markers do
		if string.sub(i,1,9) == "WAYPOINT_" then
			table.insert(WaypointMarkers, i)
		elseif string.sub(i,1,12) == "BOSS_BATTLE_" then
			table.insert(BossMarkers, i)
		elseif string.sub(i,1,14) == "MAP_EXPANSION_"  then
			table.insert(MapExpansionMarkers, i)
		elseif string.sub(i,1,10) == "BOSSSPAWN_" then
			table.insert(BossSpawnMarkers, i)
		end
	end
	TotalWaypoints = table.getn(WaypointMarkers)
	TotalWaypoints = TotalWaypoints - 1 #adjusting for Waypoint 0
	LOG("There are a total of " .. TotalWaypoints - 1 .. " waypoints")
	TotalBossBattles = table.getn(BossMarkers)
	LOG("There are a total of " .. TotalBossBattles .. " Boss Battles")
	TotalMapExpansions = table.getn(MapExpansionMarkers)
	LOG("There are a total of " .. TotalMapExpansions .. " map expansions")
	LOG("----- Survival MOD: Configuring match settings...")
	-- check game configuration
	
	
	SetArmyColor('ARMY_SURVIVAL_ENEMY',150,150,0) 
	SetArmyColor('ARMY_SURVIVAL_ALLY',0,180,255)
	
	#####Checking difficulty options
	local Difficulty = ScenarioInfo.Options.Difficulty

	if Difficulty == nil then
	Difficulty = 4
	end

		LOG("Difficulty is " .. Difficulty)
		
	ScenarioInfo.Options.Victory = 'sandbox' -- force sandbox in order to implement our own rules
	local ArmiesPresent = {}
	local Armies = ListArmies()
	Survival_PlayerCount = table.getn(Armies) - 2 -- save player count, subtracting the 2 AI "players"

	-- loop through armies
	for i, Army in ListArmies() do
	
		if (Army == "ARMY_1") then
			ArmiesPresent[1] = true
		elseif (Army == "ARMY_2") then
			ArmiesPresent[2] = true
		elseif (Army == "ARMY_3") then
			ArmiesPresent[3] = true
		elseif	(Army == "ARMY_4") then
			ArmiesPresent[4] = true
		end
		-- check if it's a human army
		if (Army == "ARMY_1" or Army == "ARMY_2" or Army == "ARMY_3" or Army == "ARMY_4" or Army == "ARMY_5" or Army == "ARMY_6" or Army == "ARMY_7" or Army == "ARMY_8") then 

			ScenarioFramework.AddRestriction(Army, categories.WALL) -- don't allow them to build walls
			#ScenarioFramework.AddRestriction(Army, categories.AIR) -- don't allow them to build air stuff

			-- loop through other armies to ally with other human armies
			for x, ArmyX in ListArmies() do
				-- if human army
				if (ArmyX == "ARMY_1" or ArmyX == "ARMY_2" or ArmyX == "ARMY_3" or ArmyX == "ARMY_4" or ArmyX == "ARMY_5" or ArmyX == "ARMY_6" or ArmyX == "ARMY_7" or ArmyX == "ARMY_8") then 
					SetAlliance(Army, ArmyX, 'Ally') 
				end
			end			

			SetAlliance(Army, "ARMY_SURVIVAL_ALLY", 'Ally') -- friendly AI team
			SetAlliance(Army, "ARMY_SURVIVAL_ENEMY", 'Enemy')  -- enemy AI team

			SetAlliedVictory(Army, true) -- can win together of course :)
		end
	end

	SetAlliance("ARMY_SURVIVAL_ALLY", "ARMY_SURVIVAL_ENEMY", 'Enemy') -- the friendly and enemy AI teams should be enemies

	#SetIgnoreArmyUnitCap('ARMY_SURVIVAL_ENEMY', true) -- remove unit cap from enemy AI team
	SetArmyUnitCap("ARMY_SURVIVAL_ENEMY", 10000)
	SetArmyUnitCap("ARMY_SURVIVAL_ALLY", 10000)

		local Difficulty = ScenarioInfo.Options.Difficulty
	
		if Difficulty == nil then
			Difficulty = 4
		end
	
		SpawnDefenses(CurrentArea)
		ForkThread(Survival_SpawnDef)
		#Immunize_ACU() #Appears to freeze the game randomly

		ForkThread(SpawnEnemies, Difficulty)
		ForkThread(EmergencyShield, Difficulty) 
		ForkThread(Immunize_StartUnits)

		if TotalBossBattles > 0 and Difficulty > 3 then
			ForkThread(BossBattles, BossSpawnMarkers)
		end
		if AttackViaWater == 'true' then
			ForkThread(WaterCheck, Difficulty)
		#	WaterCheck(Difficulty)
		end
		if TotalMapExpansions > 0 then
			ForkThread(ExpansionCheck)
		end	
		
		local ArmyTechUnit = {
		[1] = {
			[1] = 'uel0103',
			[2] = 'uel0111',
			[3] = 'uel0304',
			[0] = 'ueb0304',
			},
		[2] = {
			[1] = 'uel0201',
			[2] = 'uel0202',
			[3] = 'uel0303',
			[0] = 'ueb0304',
			},
		[3] = {
			[1] = 'uaa0102',
			[2] = 'xaa0202',
			[3] = 'uaa0303',
			[0] = 'uab0304',
			},
		[4] = {
			[1] = 'xra0105',
			[2] = 'ura0203',
			[3] = 'xra0305',
			[0] = 'urb0304',
			},		
		}
		for n=1, 4 do
			if not ArmiesPresent[n] == true then
					ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ALLY','GROUP_' .. repr(n))
					ForkThread(ArmiesMissingSupport,n,ArmyTechUnit[n], Difficulty)
			end
		end

		
end


ArmiesMissingSupport = function(ArmyNumber, ArmyUnit, Difficulty)

	local PlatoonList = {}
	local aiBrain = GetArmyBrain("ARMY_SURVIVAL_ALLY");
	local aiPlatoon = aiBrain:MakePlatoon('','')
	local POS =  ScenarioUtils.MarkerToPosition("ARMY_" .. ArmyNumber)
	local UnitID = nil
	local LocalCurrentArea = nil
	local Gate = CreateUnitHPR(ArmyUnit[0], "ARMY_SURVIVAL_ALLY", POS[1], POS[2], POS[3], 0, 0,0)
	table.insert(PlatoonList, Gate)
	aiBrain:AssignUnitsToPlatoon(aiPlatoon, PlatoonList, 'Attack', 'None')		
	#The gate being in the platoon is to prevent the platoon from killing itself when all the members within die.
	#Yes, the gate can die, but if it does no more units will spawn from it, so who cares anyways
			
	while not Survival_DefUnit:IsDead() and not Gate:IsDead() do
		LocalCurrentArea = CurrentArea
		if LocalCurrentArea > 3 then
			LocalCurrentArea = 3
		end
		#for n=1,2 do
		PlatoonList = {}
		#if not aiPlatoon then
		#	aiPlatoon = aiBrain:MakePlatoon('','')
		#end
		NewUnit = CreateUnitHPR(ArmyUnit[LocalCurrentArea], "ARMY_SURVIVAL_ALLY", POS[1], POS[2], POS[3], 0, 0,0)
		table.insert(PlatoonList, NewUnit)
		aiBrain:AssignUnitsToPlatoon(aiPlatoon, PlatoonList, 'Attack', 'None')
		#end
		Gate:PlayUnitSound('CommanderArrival')
		Gate:CreateProjectile( '/effects/entities/UnitTeleport01/UnitTeleport01_proj.bp', 0, 1.35, 0, nil, nil, nil):SetCollision(false)
		if TargetWaypoint < 4 then
			aiPlatoon:AggressiveMoveToLocation(ScenarioUtils.MarkerToPosition("WAYPOINT_2"))
		else
			aiPlatoon:AggressiveMoveToLocation(ScenarioUtils.MarkerToPosition("WAYPOINT_" .. TargetWaypoint))
		end
		aiPlatoon:GuardTarget(Survival_DefUnit)
		WaitSeconds((40/Difficulty) + (Random(1,5)))
	end




end







#spawns enemy defenses in relation to difficulty
---------------
SpawnDefenses = function(CurrentArea)
	local Difficulty = ScenarioInfo.Options.Difficulty
	
	if Difficulty == nil then
		Difficulty = 4
	end
	LOG("Difficulty is " .. Difficulty)

	if Difficulty > 1 then
		ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ENEMY','GROUP_' .. (7+CurrentArea))
	end
	if Difficulty > 3 then
		ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ENEMY','GROUP_' .. (11+CurrentArea))
	end
	if Difficulty > 5 then
		ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ENEMY','GROUP_' .. (24+CurrentArea))
	end
					
	if Difficulty > 2 then
		ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ENEMY','GROUP_' .. (3+CurrentArea))
	end

	if Difficulty > 4 then
		ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ENEMY','GROUP_' .. (15+CurrentArea))
	end
	if Difficulty > 6 then
		ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ENEMY','GROUP_' .. (20+CurrentArea))
	end

	
	
end


#handles allied reinforcements
------------------
Reinforcements = function (ReinforcementStrength)

	local AllyID1 = 'uel0201';
	local AllyID2 = 'uel0103';
	local AllyID3 = 'uel0104';

	LOG("reinforcementstrength is" .. ReinforcementStrength);
	local Quantity1 = 3 * ReinforcementStrength;
	local ArmyID = "ARMY_SURVIVAL_ALLY";
	local POS = ScenarioUtils.MarkerToPosition("WAYPOINT_0");
	
	local OrderID = 2;
	local PlatoonList = {};
		
	while not Survival_DefUnit:IsDead() do
		#LOG("starting spawning of allies");

		local PlatoonList = {};
		local Counter = 0;
		while Counter < Quantity1 do
			local NewUnit1 = CreateUnitHPR(AllyID1, ArmyID, POS[1], POS[2], POS[3] + Random(1,10), 0, Random(0,360),0);
			table.insert(PlatoonList, NewUnit1); -- add unit to a platoon
			Counter = Counter + 1;
			ImmunizeUnit(NewUnit1)
		end
		Counter = 0;
		while Counter < Quantity1/2 do
			local NewUnit1 = CreateUnitHPR(AllyID2, ArmyID, POS[1], POS[2], POS[3]  + Random(1,10), 0, Random(0,360),0);
			local NewUnit2 = CreateUnitHPR(AllyID3, ArmyID, POS[1], POS[2], POS[3] + Random(1,10), 0, Random(0,360),0);
			table.insert(PlatoonList, NewUnit1); -- add unit to a platoon
			table.insert(PlatoonList, NewUnit2); -- add unit to a platoon
			Counter = Counter + 1;
			#ImmunizeUnit(NewUnit1)
			ImmunizeUnit(NewUnit2)
		end
		local aiBrain = GetArmyBrain("ARMY_SURVIVAL_ALLY");
		local aiPlatoon = aiBrain:MakePlatoon('','');
		aiBrain:AssignUnitsToPlatoon(aiPlatoon, PlatoonList, 'Attack', 'None')
		#LOG("allies spawned");
		for n=1, TotalWaypoints do
			local TargetWaypoint = ScenarioUtils.MarkerToPosition("WAYPOINT_" .. n)
			aiPlatoon:AggressiveMoveToLocation(TargetWaypoint);
		end
		LOG("ally orders issued");
		WaitSeconds(30);
		aiPlatoon = aiBrain:MakePlatoon('','');
		PlatoonList = {}
		local IdleUnits = GetArmyBrain("ARMY_SURVIVAL_ALLY"):GetListOfUnits(categories.MOBILE - categories.xss0302, true, false) 
		for _,unit in IdleUnits do
			if unit:IsIdleState() then
				table.insert(PlatoonList, unit)
      	#     ChangeUnitArmy(unit,"ARMY_" .. Random(1,Survival_PlayerCount))
			 end
		end
		aiBrain:AssignUnitsToPlatoon(aiPlatoon, PlatoonList, 'Attack', 'None')
		aiPlatoon:GuardTarget(Survival_DefUnit);
				
	end


end

#makes the survival unit go faster if it has full hp
-----------------------
SpeedBoost = function()
	local CurrentSpeed = .5
	while not Survival_DefUnit:IsDead() do
		local MaxHealth = Survival_DefUnit:GetMaxHealth()
		local Health1 = Survival_DefUnit:GetHealth()
		if Health1 < (MaxHealth * .8) and CurrentSpeed > .5 then
			Survival_DefUnit:SetSpeedMult(.4)
			CurrentSpeed = .5
			BroadcastMSG("The HQ is taking damage.  Reverting power back to shields.", 4)
		elseif Health1 >= (MaxHealth * .9) and CurrentSpeed == .5 then
			WaitSeconds(10)
			Health1 = Survival_DefUnit:GetHealth()
			if Health1 >= (MaxHealth * .9) and CurrentSpeed > .5 then
				Survival_DefUnit:SetSpeedMult(.5)
				CurrentSpeed = .5
				BroadcastMSG("The HQ is taking damage. Reverting power back to shields.", 4)
			elseif Health1 == MaxHealth then
			WaitSeconds(10)
			Health1 = Survival_DefUnit:GetHealth()
				if Health1 >= (MaxHealth * .9)  and CurrentSpeed > .5  then
					Survival_DefUnit:SetSpeedMult(.5)
					BroadcastMSG("The HQ is taking damage. Reverting power back to shields.", 4)
				elseif Health1 == MaxHealth then
					Survival_DefUnit:SetSpeedMult(1)
					CurrentSpeed = 1
					BroadcastMSG("The HQ is in good shape.  Hitting the gas.", 4)
				end
			end
		end
		WaitSeconds(10)
	end
end




##prev
-- keeps the truck moving
--------------------------------------------------------------------------

Waypoint_Tracker = function()
	#local TargetWaypoint = GetClosestWaypoint()  ##Should be 0 at the start of the game
	local OldDistance = nil
	local PlatoonList = {}
	table.insert(PlatoonList, Survival_DefUnit) -- add unit to a platoon
	
	local aiBrain = GetArmyBrain("ARMY_SURVIVAL_ALLY") #GetArmyBrain(ArmyID)	--"ARMY_SURVIVAL_ENEMY")
	local aiPlatoon = aiBrain:MakePlatoon('','')
	aiBrain:AssignUnitsToPlatoon(aiPlatoon, PlatoonList, 'Attack', 'None') -- platoon, unit list, "mission" and 


	BroadcastMSG("The defense object is on the move!",5)

	while TargetWaypoint < TotalWaypoints + 1 do
		local Distance = VDist3(Survival_DefUnit:GetPosition(),ScenarioUtils.MarkerToPosition("WAYPOINT_" .. TargetWaypoint))	

		if Distance < 10 then
			TargetWaypoint = TargetWaypoint + 1
			aiPlatoon:MoveToLocation(ScenarioUtils.MarkerToPosition("WAYPOINT_" .. (TargetWaypoint)), false)
			LOG("Truck has qued a move order to waypoint number " .. TargetWaypoint)			
		elseif Distance == OldDistance then
			#TargetWaypoint = GetClosestWaypoint() + 1
			aiPlatoon:MoveToLocation(ScenarioUtils.MarkerToPosition("WAYPOINT_" .. TargetWaypoint), false)	
			LOG("Truck was stuck. Re-queing a move order to waypoint number " .. TargetWaypoint)
		end
		LOG("Target waypoint is waypoint " .. TargetWaypoint .. " at distance " .. Distance)
		OldDistance = Distance
		WaitSeconds(10)	
	end	
end


------------------------------------------
GetGatesRemaining = function(WaypointNumber, Type)
      local units = AIUtils.GetOwnUnitsAroundPoint(GetArmyBrain("ARMY_SURVIVAL_ENEMY"), categories.xsb0304, ScenarioUtils.MarkerToPosition(Type .. "SPAWN_" .. WaypointNumber), 30 )
      return table.getn(units) 
end


#handles the emergency
---------------------------------------
EmergencyShield = function(Difficulty)

	local	EmergencyShieldCount = nil
	if Difficulty == 1 then
		EmergencyShieldCount = 5
	elseif Difficulty == 2 then 
		EmergencyShieldCount = 5
	elseif Difficulty == 3 then 
		EmergencyShieldCount = 4
	elseif Difficulty == 4 then 
		EmergencyShieldCount = 3
	elseif Difficulty == 5 then 
		EmergencyShieldCount = 3
	elseif Difficulty == 6 then 
		EmergencyShieldCount = 2
	elseif Difficulty == 7 then 
		EmergencyShieldCount = 2
	elseif Difficulty == 8 then 
		EmergencyShieldCount = 2
	else 
		EmergencyShieldCount = 1
	end

	LOG("Emergency Shield thread running with " .. EmergencyShieldCount .. " starting shields.")

        #local bp = Survival_DefUnit:GetBlueprint().Defense.Shield
	local bp ={
            ImpactEffects = 'UEFShieldHit01',
            ImpactMesh = '/effects/entities/ShieldSection01/ShieldSection01_mesh',
            Mesh = '/effects/entities/Shield01/Shield01_mesh',
            MeshZ = '/effects/entities/Shield01/Shield01z_mesh',
            RegenAssistMult = 60,
            ShieldEnergyDrainRechargeTime = 5,
            ShieldMaxHealth = 500000,
            ShieldRechargeTime = 160,
            ShieldRegenRate = 64,
            ShieldRegenStartTime = 1,
            ShieldSize = 25,
            ShieldVerticalOffset = -7,
	   }


	while not Survival_DefUnit:IsDead() do

		if Survival_DefUnit:GetHealth() < (Survival_DefUnit:GetMaxHealth() * .2) then
			BroadcastMSG("Coalition HQ hull integrity CRITICAL!", 4)
			if EmergencyShieldCount > 0 then
				EmergencyShieldCount = EmergencyShieldCount - 1
				BroadcastMSG("Emergency Shield activated.  HQ out.", 4)	
				ForkThread(function() WaitTicks(1) Survival_DefUnit:CreateShield(bp)   end)
				Survival_DefUnit:SetSpeedMult(0.01)
				local RegenAmount = (((Survival_DefUnit:GetMaxHealth() * .2) - Survival_DefUnit:GetHealth())/15)
				local Buff = import('/lua/sim/Buff.lua')
				if not Buffs['EmergencyRegen'] then
				BuffBlueprint {
                    Name = 'EmergencyRegen',
                    DisplayName = 'EmergencyRegen',
                    BuffType = 'ACUUPGRADEDMG',
                    Stacks = 'ALWAYS',
                    Duration = 30,
                    Affects = {
                        MaxHealth = {
                            Add = 000,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = RegenAmount,
                            Mult = 1.0,
                        },
                         },
                } 	
				end
				Buff.ApplyBuff(Survival_DefUnit, 'EmergencyRegen')   
				LOG("Regen amount for emer shield is " .. RegenAmount)
				WaitSeconds(30)
				BroadcastMSG("Emergency Shield dissipated.  Remaining Shield count:" .. EmergencyShieldCount, 4)
	   	        Survival_DefUnit:DestroyShield()
				Survival_DefUnit:SetSpeedMult(0.5)
			end
	
			if EmergencyShieldCount == 0 then
				WaitSeconds(10)
			end
		end
		WaitSeconds(1)
	end

end






#Controls the spawn of enemy XP units 
---------------------------------------------------------------------
function BossBattles(BossSpawnMarkers)
	
	local NextBossBattle = 1
	local WarningIssued = 'false'	
	local CurrentBattleSpawns = {}
	local SpawnNumber = 0

	while not Survival_DefUnit:IsDead() and NextBossBattle <= TotalBossBattles do


		
		local Distance = VDist3(Survival_DefUnit:GetPosition(),ScenarioUtils.MarkerToPosition("BOSS_BATTLE_" .. NextBossBattle))	

			if (Distance < 70) and (WarningIssued == 'false') then
				
			for i,mark in BossSpawnMarkers do
				if string.sub(mark,1,11) == ("BOSSSPAWN_" .. NextBossBattle) then
					table.insert(CurrentBattleSpawns, i)
				end
				SpawnNumber = table.getn(CurrentBattleSpawns)
				LOG("There are a total of " .. SpawnNumber .. " spawns for boss battle " .. NextBossBattle)
			end
				BroadcastMSG("Intel suggests an Enemy Experimental is approaching.  HQ out.", 5)
				WarningIssued = 'true'
			elseif (Distance < 10) then
				SpawnBoss(NextBossBattle, SpawnNumber)
				BroadcastMSG(" Enemy Experimental sighted in the operational area.  Destroy it.", 5)
				NextBossBattle = NextBossBattle + 1
				WarningIssued = 'false'
				CurrentBattleSpawns = {}
			end
		WaitSeconds(10)
	end
end

function SpawnBoss(NextBossBattle, SpawnNumber)
	
	local aiBrain = GetArmyBrain("ARMY_SURVIVAL_ENEMY") --"ARMY_SURVIVAL_ENEMY")
	local aiPlatoon = aiBrain:MakePlatoon('','')
	local PlatoonList = {}
	
	for n=1, NextBossBattle do
		local POS =ScenarioUtils.MarkerToPosition("BOSSSPAWN_" .. NextBossBattle .. "_" .. Random(1,SpawnNumber))
		local NewBoss = CreateUnitHPR('xsl0401', "ARMY_SURVIVAL_ENEMY", POS[1], POS[2], POS[3], 0, Random(0,360),0)	
		table.insert(PlatoonList, NewBoss) -- add unit to a platoon
		aiBrain:AssignUnitsToPlatoon(aiPlatoon, PlatoonList, 'Attack', 'None') 
		aiPlatoon:AggressiveMoveToLocation(Survival_DefUnit:GetPosition())
		aiPlatoon:AggressiveMovetoLocation(ScenarioUtils.MarkerToPosition("WAYPOINT_" .. TargetWaypoint ))
	end


end

#Controls map expansion
---------------------------------------------------------------------
function ExpansionCheck()

	#local NextMapExpansion = 1	

	while not Survival_DefUnit:IsDead() and CurrentArea <= TotalMapExpansions do

		local Distance = VDist3(Survival_DefUnit:GetPosition(),ScenarioUtils.MarkerToPosition("MAP_EXPANSION_" .. CurrentArea))	
	
			if (Distance < 10) then
				if CurrentArea == 1 then
					ForkThread(SpeedBoost)
				end
				CurrentArea = CurrentArea + 1
				BroadcastMSG("Waypoint reached.  Expanding the operational area.  HQ out.", 5)
				SpawnDefenses(CurrentArea)
				ScenarioFramework.SetPlayableArea('AREA_' .. (CurrentArea), false)
			end
	LOG("Next map expansion " .. CurrentArea .. " at distance " .. Distance)
	WaitSeconds(10)

	end
end



#See if the defense object is under water.  Attacks it with naval units if it is
---------------------------------------------------------------------
function WaterCheck(Difficulty)

	local	WaveDelay = nil
	local	SpawnMultiplier = nil

	if Difficulty == 1 then
		WaveDelay = 300
		SpawnMultiplier = .5
	elseif Difficulty == 2 then 
		WaveDelay = 250
		SpawnMultiplier = .8
	elseif Difficulty == 3 then 
		WaveDelay = 225
		SpawnMultiplier = 1.5
	elseif Difficulty == 4 then 
		WaveDelay = 200
		SpawnMultiplier = 2
	elseif Difficulty == 5 then 
		WaveDelay = 150
		SpawnMultiplier = 1.3
	elseif Difficulty == 6 then 
		WaveDelay = 125
		SpawnMultiplier = 1.5
	elseif Difficulty == 7 then 
		WaveDelay = 100
		SpawnMultiplier = 4
	elseif Difficulty == 8 then 
		WaveDelay = 75
		SpawnMultiplier = 5
	else 
		WaveDelay = 50
		SpawnMultiplier = 7
	end

	LOG("Running watercheck thread every " .. WaveDelay .. " seconds.")
	
	while not Survival_DefUnit:IsDead() do

			if (Survival_DefUnit:GetCurrentLayer() == 'Seabed') then
				BroadcastMSG("Enemy fleet sighted.  Defend the HQ.", 5)
				Survival_SpawnUnit('xss0203', 'ARMY_SURVIVAL_ENEMY', ScenarioUtils.MarkerToPosition("WATERSPAWN"), 1, (4 * SpawnMultiplier), 'xsl0203')
				Survival_SpawnUnit('xss0201', 'ARMY_SURVIVAL_ENEMY', ScenarioUtils.MarkerToPosition("WATERSPAWN"), 1, (2 * SpawnMultiplier), 'xss0103')
				Survival_SpawnUnit('xss0302', 'ARMY_SURVIVAL_ENEMY', ScenarioUtils.MarkerToPosition("WATERSPAWN"), 1, (.5 * SpawnMultiplier), 'xss0304')
				

			end

			
	WaitSeconds(WaveDelay)

	end
end



------------
function GetMarker(MarkerName)
	return Scenario.MasterChain._MASTERCHAIN_.Markers[MarkerName]
end

---------------------------------------------------------------------
function VictoryCheck()
	
	while not Survival_DefUnit:IsDead() do

		local Distance = VDist3(Survival_DefUnit:GetPosition(),ScenarioUtils.MarkerToPosition("GOAL"))	
	
			if (Distance <= 10) then
			BroadcastMSG("Coalition HQ has reached it's destination.  We live to fight another day.  HQ out.", 4)
			Survival_GameState = 2
				for i, army in ListArmies() do
					if (army == "ARMY_1" or army == "ARMY_2" or army == "ARMY_3" or army == "ARMY_4" or army == "ARMY_5" or army == "ARMY_6" or army == "ARMY_7" or army == "ARMY_8") then
					GetArmyBrain(army):OnVictory()
					end
				end
			GetArmyBrain("ARMY_SURVIVAL_ENEMY"):OnDefeat()
			end

	WaitSeconds(10)

	end
end

function GetMarker(MarkerName)
	return Scenario.MasterChain._MASTERCHAIN_.Markers[MarkerName]
end


---------------------------------------------------------------------
function SpawnEnemies(Difficulty)

	local StartTime = ScenarioInfo.Options.StartTime

	if StartTime == nil then
	StartTime = 0
	end

	BroadcastMSG("The HQ is arriving in " .. (StartTime) .. " seconds.", 5)	

	Survival_DefUnit:SetSpeedMult(0.01)
	WaitSeconds(StartTime + 5)
	Survival_DefUnit:SetSpeedMult(0.5)

	BroadcastMSG("Coalition HQ is on the move.  Defend it.  HQ out.", 5)
	WaitSeconds(15)
	
	local ReinforcementStrength = ScenarioInfo.Options.Reinforcements
	if ReinforcementStrength == nil then
		ReinforcementStrength = 1
	end
	if ReinforcementStrength > 0 then
		#ScenarioUtils.CreateArmyGroup('ARMY_SURVIVAL_ALLY','GROUP_16')
		#LOG("created group 16")
		ForkThread(Reinforcements, ReinforcementStrength)
	end



	
	
	local SpawnMultiplier = nil
	local WaveDelay = nil

	if Difficulty == 1 then
		WaveDelay = 45
		SpawnMultiplier = .5
	elseif Difficulty == 2 then 
		WaveDelay = 40
		SpawnMultiplier = .8
	elseif Difficulty == 3 then 
		WaveDelay = 35
		SpawnMultiplier = 1
	elseif Difficulty == 4 then 
		WaveDelay = 30
		SpawnMultiplier = 1
	elseif Difficulty == 5 then 
		WaveDelay = 25
		SpawnMultiplier = 1.5
	elseif Difficulty == 6 then 
		WaveDelay = 20
		SpawnMultiplier = 1.5
	elseif Difficulty == 7 then 
		WaveDelay = 15
		SpawnMultiplier = 2
	elseif Difficulty == 8 then 
		WaveDelay = 10
		SpawnMultiplier = 2.5
	else 
		WaveDelay = 5
		SpawnMultiplier = 3
	end

	BroadcastMSG("The Seraphim are attacking us.  Destroy them.  HQ Out.", 5)
	

	local WaypointNumber = 0
	local StartingGates = {}

	for n=0, TotalWaypoints do
		local units =  AIUtils.GetOwnUnitsAroundPoint(GetArmyBrain("ARMY_SURVIVAL_ENEMY"), categories.xsb0304, ScenarioUtils.MarkerToPosition("GROUNDSPAWN_" .. repr(n)), 30 )
		StartingGates[ n ] = 0
		for _,unit in units do
       	         StartingGates[ n ] = StartingGates[ n ] + 1
		end
		local units =  AIUtils.GetOwnUnitsAroundPoint(GetArmyBrain("ARMY_SURVIVAL_ENEMY"), categories.xsb0304, ScenarioUtils.MarkerToPosition("AIRSPAWN_" .. repr(n)), 30 )
			StartingGates[ n+100 ] = 0
		for _,unit in units do
       	    StartingGates[ n+100 ] = StartingGates[ n+100 ] + 1
		end
		LOG("Total gates around groundspawn "..repr(n).." is "..repr(StartingGates[ n ]))
		LOG("Total gates around airspawn "..repr(n).." is "..repr(StartingGates[ n+100 ]))
	end
	
	
	while not Survival_DefUnit:IsDead() do

		#local Distance = VDist3(Survival_DefUnit:GetPosition(),ScenarioUtils.MarkerToPosition("GOAL"))	
		#local ClosestWaypoint = GetClosestWaypoint()
		#OG("target waypoint is waypoint " .. TargetWaypoint)
		SpawnGroundWave(TargetWaypoint,SpawnMultiplier, StartingGates[TargetWaypoint])
		SpawnAirWave(TargetWaypoint, SpawnMultiplier, StartingGates[TargetWaypoint + 100])
		#SpawnAirDrop(TargetWaypoint, SpawnMultiplier, StartingGates[ TargetWaypoint ])
		#SpawnArtilleryWave(TargetWaypoint, SpawnMultiplier)		

		if TargetWaypoint > 1 then
			SpawnGroundWave((TargetWaypoint - 1), SpawnMultiplier, StartingGates[ TargetWaypoint - 1])	
			SpawnAirWave((TargetWaypoint - 1), SpawnMultiplier, StartingGates[TargetWaypoint + 99])	
		end	
		
		if TargetWaypoint > 2 then
			SpawnGroundWave((TargetWaypoint - 2), SpawnMultiplier, StartingGates[ TargetWaypoint - 2 ])	
			SpawnAirWave((TargetWaypoint - 2), SpawnMultiplier,StartingGates[ TargetWaypoint + 98 ])	
		end
		
		if TargetWaypoint > 3 then
			SpawnGroundWave((TargetWaypoint - 3), SpawnMultiplier, StartingGates[ TargetWaypoint - 3 ])	
			SpawnAirWave((TargetWaypoint - 3), SpawnMultiplier, StartingGates[ TargetWaypoint +97 ])	
		end

		WaitSeconds(WaveDelay)

	end


end



---------------------------------------------------------------------------------------------
SpawnGroundWave = function(ClosestWaypoint, SpawnMultiplier, StartingGates) -- This generates the units that will be in the wave then spawns them

	local UnitID = '0'
	local UnitID2 = '0'
	local Quantity = 0

	if ClosestWaypoint < 5 then
	UnitID = 'xsl0201'
	Quantity = (((ClosestWaypoint + 1) * 2) * SpawnMultiplier)
	elseif ClosestWaypoint <10 then
	UnitID = 'xsl0202'
	Quantity = ((ClosestWaypoint) * SpawnMultiplier)
	elseif ClosestWaypoint >= 10 then
	UnitID = 'xsl0303'
	Quantity = (((ClosestWaypoint)/2) * SpawnMultiplier)
	end

	if ClosestWaypoint < 5 then
	UnitID2 = 'xsl0103'
	#Quantity = (((ClosestWaypoint * 2) + 1) * SpawnMultiplier)
	elseif ClosestWaypoint <10 then
	UnitID2 = 'xsl0111'
	#Quantity = ((ClosestWaypoint) * SpawnMultiplier)
	elseif ClosestWaypoint >= 10 then
	UnitID2 = 'xsl0304'
	#Quantity = (((ClosestWaypoint)/2) * SpawnMultiplier)
	end

	local ArmyID = "ARMY_SURVIVAL_ENEMY"
	local POS = ScenarioUtils.MarkerToPosition("GROUNDSPAWN_" .. ClosestWaypoint)
	local OrderID = 2

	
	local GatesRemaining = GetGatesRemaining(ClosestWaypoint, 'GROUND')
	if GatesRemaining < StartingGates and StartingGates > 0 then
		Quantity = Quantity * (GatesRemaining/StartingGates)
	end
	
	Survival_SpawnUnit(UnitID, ArmyID, POS, OrderID, Quantity, UnitID2, 'GROUND')


end


---------------------------------------------------------------------------------------------
SpawnAirWave = function(ClosestWaypoint, SpawnMultiplier, StartingGates) -- This generates the units that will be in the wave then spawns them

	local UnitID = '0'
	local UnitID2 = '0'
	local Quantity = 0

	if ClosestWaypoint < 5 then
	UnitID = 'xsa0103'
	#Quantity = ((ClosestWaypoint + 2) * SpawnMultiplier)
	elseif ClosestWaypoint <10 then
	UnitID = 'xsa0202'
	#Quantity = (ClosestWaypoint * SpawnMultiplier)
	elseif ClosestWaypoint >= 10 then
	UnitID = 'xsa0303'
	#Quantity = ((ClosestWaypoint)/2 * SpawnMultiplier)
	end


	if ClosestWaypoint < 5 then
	UnitID2 = 'xsa0102'
	Quantity = (((ClosestWaypoint + 1) * 2) * SpawnMultiplier)
	elseif ClosestWaypoint <10 then
	UnitID2 = 'xsa0203'
	Quantity = ((ClosestWaypoint + 1) * SpawnMultiplier)
	elseif ClosestWaypoint >= 10 then
	UnitID2 = 'xsa0304'
	Quantity = (((ClosestWaypoint + 1)/2) * SpawnMultiplier)
	end

	local ArmyID = "ARMY_SURVIVAL_ENEMY"
	local POS = ScenarioUtils.MarkerToPosition("AIRSPAWN_" .. ClosestWaypoint)
	local OrderID = 2
	
	local GatesRemaining = GetGatesRemaining(ClosestWaypoint, 'AIR')
	if GatesRemaining < StartingGates and StartingGates > 0 then
		Quantity = Quantity * (GatesRemaining/StartingGates)
	end
	

	Survival_SpawnUnit(UnitID, ArmyID, POS, OrderID, Quantity, UnitID2, 'AIR')


end

---------------------------------------------------------------------------------------------
Survival_SpawnUnit = function(UnitID, ArmyID, POS, OrderID, Quantity, UnitID2, Type) -- blueprint, army, position, order

--	LOG("----- Survival MOD: SPAWNUNIT: Start function...")
	local PlatoonList = {}
	local Counter = 0

	while Counter < Quantity do
		local NewUnit = CreateUnitHPR(UnitID, ArmyID, POS[1], POS[2], POS[3], 0, Random(0,360),0)
		local NewUnit2 = CreateUnitHPR(UnitID2, ArmyID, POS[1], POS[2], POS[3], 0, Random(0,360),0)
		table.insert(PlatoonList, NewUnit) -- add unit to a platoon
		table.insert(PlatoonList, NewUnit2) -- add unit to a platoon
		Survival_PlatoonOrder(ArmyID, PlatoonList, OrderID, Type) -- give the unit orders
		Counter = Counter + 1
	end
end



--------------------------------------------------------------------------
Survival_PlatoonOrder = function(ArmyID, UnitList, OrderID, Type)	

--	LOG("----- Survival MOD: PLATOON: Start function...")

	if (UnitList == nil) then
		return
	end

	local aiBrain = GetArmyBrain(ArmyID) --"ARMY_SURVIVAL_ENEMY")
	local aiPlatoon = aiBrain:MakePlatoon('','')
	aiBrain:AssignUnitsToPlatoon(aiPlatoon, UnitList, 'Attack', 'None') -- platoon, unit list, "mission" and formation

 	-- 1 center / 2 waypoint / 3 spawn
 	if (OrderID == 2) then -- attack move
		-- attack move to random path
		POS = Survival_DefUnit:GetPosition()
		aiPlatoon:AggressiveMoveToLocation(POS)
	elseif (OrderID == 1) then
		POS = Survival_DefUnit:GetPosition()	
		aiPlatoon:MoveToLocation(POS, false)
 	#elseif (OrderID == 3) then -- patrol paths
	#	-- patrol to random path
	#	POS = Survival_GetPOS(2, 25)
	#	aiPlatoon:Patrol(POS)
	end
	if Type == 'AIR' then
		aiPlatoon:Patrol(Survival_DefUnit:GetPosition())
		aiPlatoon:Patrol(ScenarioUtils.MarkerToPosition("WAYPOINT_" .. TargetWaypoint))
	end
end




#Determine which waypoint is closest to... something
----------------------------
function GetClosestWaypoint(POS)
	if POS == nil then
	POS = Survival_DefUnit:GetPosition()
	end

	local WaypointCounter = 0
	local ShortestDistance = 20000
	local ShortestDistanceWaypoint = 100
	local WaypointDistance = 1000

	while (WaypointCounter < (TotalWaypoints + 1)) do
		WaypointDistance = VDist3(POS,ScenarioUtils.MarkerToPosition("WAYPOINT_" .. WaypointCounter))
		if WaypointDistance < ShortestDistance then
			ShortestDistance = WaypointDistance
			ShortestDistanceWaypoint = WaypointCounter
		end
	WaypointCounter = WaypointCounter + 1
	end
	#LOG("returned GetClosestWaypoint")
	return ShortestDistanceWaypoint
end









-- spawns a defense object
--------------------------------------------------------------------------
Survival_SpawnDef = function()

	#WaitSeconds(2)

	LOG("----- Survival MOD: Initializing defense object...")

	local POS = ScenarioUtils.MarkerToPosition("WAYPOINT_0")

	Survival_DefUnit = CreateUnitHPR('UEL0401', "ARMY_SURVIVAL_ALLY", POS[1], POS[2], POS[3], 0,0,0)  
	ForkThread(Waypoint_Tracker)
	ForkThread(VictoryCheck)

	Survival_DefUnit:SetReclaimable(false)
	Survival_DefUnit:SetCapturable(false)

	Survival_DefUnit:SetSpeedMult(0.5)
	Survival_DefUnit:SetTurnMult(0.5)

	Survival_DefUnit:HideBone('Turret_Right01', true)
	Survival_DefUnit:HideBone('Turret_Right01_Barrel01', true)
	Survival_DefUnit:HideBone('Turret_Right01_Barrel02', true)
	Survival_DefUnit:HideBone('Turret_Right01_Barrel03', true)
	Survival_DefUnit:HideBone('Turret_Right01_Muzzle01', true)
	Survival_DefUnit:HideBone('Turret_Right01_Muzzle02', true)
	Survival_DefUnit:HideBone('Turret_Right01_Muzzle03', true)

	Survival_DefUnit:HideBone('Turret_Right02', true)
	Survival_DefUnit:HideBone('Turret_Right02_Barrel01', true)
	Survival_DefUnit:HideBone('Turret_Right02_Barrel02', true)
	Survival_DefUnit:HideBone('Turret_Right02_Barrel03', true)
	Survival_DefUnit:HideBone('Turret_Right02_Muzzle01', true)
	Survival_DefUnit:HideBone('Turret_Right02_Muzzle02', true)
	Survival_DefUnit:HideBone('Turret_Right02_Muzzle03', true)

	Survival_DefUnit:HideBone('Turret_Left01', true)
	Survival_DefUnit:HideBone('Turret_Left01_Barrel01', true)
	Survival_DefUnit:HideBone('Turret_Left01_Barrel02', true)
	Survival_DefUnit:HideBone('Turret_Left01_Barrel03', true)
	Survival_DefUnit:HideBone('Turret_Left01_Muzzle01', true)
	Survival_DefUnit:HideBone('Turret_Left01_Muzzle02', true)
	Survival_DefUnit:HideBone('Turret_Left01_Muzzle03', true)

	Survival_DefUnit:HideBone('Turret_Left02', true)
	Survival_DefUnit:HideBone('Turret_Left02_Barrel01', true)
	Survival_DefUnit:HideBone('Turret_Left02_Barrel02', true)
	Survival_DefUnit:HideBone('Turret_Left02_Barrel03', true)
	Survival_DefUnit:HideBone('Turret_Left02_Muzzle01', true)
	Survival_DefUnit:HideBone('Turret_Left02_Muzzle02', true)
	Survival_DefUnit:HideBone('Turret_Left02_Muzzle03', true)

	Survival_DefUnit:SetWeaponEnabledByLabel('LeftTurret01', false)
	Survival_DefUnit:SetWeaponEnabledByLabel('LeftTurret02', false)
	Survival_DefUnit:SetWeaponEnabledByLabel('RightTurret01', false)
	Survival_DefUnit:SetWeaponEnabledByLabel('RightTurret02', false)

	Survival_DefUnit:DestroyShield()
	Survival_DefUnit:SetCustomName("Coalition HQ")

	#Survival_DefUnit:SetRegenRate(45 - (Survival_PlayerCount * 5))
	#Survival_DefUnit:SetMaxHealth(25000)
	#Survival_DefUnit:SetHealth(nil, 25000)

  for i = 1, Survival_DefUnit:GetWeaponCount() do
     local weapon = Survival_DefUnit:GetWeapon(i)
     weapon.oldCreateProjectileForWeapon = weapon.CreateProjectileForWeapon
     local p = weapon:CreateProjectileForWeapon()
     p:GetBlueprint().hq = 1
     p:Destroy()
   end 

	local Buff = import('/lua/sim/Buff.lua')
	        if not Buffs['FattyBuff'] then
               BuffBlueprint {
                    Name = 'FattyBuff',
                    DisplayName = 'FattyBuff',
                    BuffType = 'ACUUPGRADEDMG',
                    Stacks = 'ALWAYS',
                    Duration = -1,
                    Affects = {
                        MaxHealth = {
                            Add = 7500,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = 40,
                            Mult = 1.0,
                        },
                         },
                } 	
	end
        Buff.ApplyBuff(Survival_DefUnit, 'FattyBuff')    
	
	Survival_DefUnit:SetIntelRadius('Vision', 50)

	-- when the def object dies
	Survival_DefUnit.OldOnKilled = Survival_DefUnit.OnKilled
	 

	#Survival_DefUnit.OldOnDamage = Survival_DefUnit.OnDamage

	#Survival_DefUnit.OnDamage = function(self, instigator)
	#	self.OldOnDamage
	
	#end

	Survival_DefUnit.OnKilled = function(self, instigator, type, overkillRatio)

		BroadcastMSG("Coalition HQ has been lost.  The war is over.", 8)
		self.OldOnKilled(self, instigator, type, overkillRatio)

		Survival_GameState = 3

		for i, army in ListArmies() do

			if (army == "ARMY_1" or army == "ARMY_2" or army == "ARMY_3" or army == "ARMY_4" or army == "ARMY_5" or army == "ARMY_6" or army == "ARMY_7" or army == "ARMY_8") then
				--killAllCommanders(army)
				GetArmyBrain(army):OnDefeat()
			end
		end
	end
	#ImmunizeUnit(Survival_DefUnit, false)


end



##prevents units from hitting friendly units
------------------------------------------------------------------------
Immunize_StartUnits = function()
   WaitSeconds(5)
   for i, army in ListArmies() do
      if (army == "ARMY_1" or army == "ARMY_2" or army == "ARMY_3" or army == "ARMY_4" or army == "ARMY_SURVIVAL_ALLY") then
         local unitList = GetArmyBrain(army):GetListOfUnits( categories.ALLUNITS , false, false)
         for j, unit in unitList do
            ImmunizeUnit(unit)
         end
      end   
   end
end

## Makes a unit immune to friendly fire and neutralizes its weapons to not harm allies
ImmunizeUnit = function(unit)
   if unit.immune == nil then
      unit.immune = 1
      -- Makes friendly unit's projectiles pass through this unit
      unit.OldOnCollisionCheck = unit.OnCollisionCheck
      unit.OnCollisionCheck = newOnCollisionCheck
      unit.OldOnCollisionCheckWeapon = unit.OnCollisionCheckWeapon
      unit.OnCollisionCheckWeapon = newOnCollisionCheckWeapon
      
      -- Marks this unit's weapons as friendly
      neutralizeWeapons(unit)
      
      -- Modify unit's build function to pass immunity on to other units
      if unit.OnStartBuild and unit.OldOnStartBuild == nil then
         unit.OldOnStartBuild = unit.OnStartBuild
         unit.OnStartBuild = newOnStartBuild
      end
   end
end

## Immunize units built by this unit
newOnStartBuild = function(self, unitBeingBuilt, order)
   self:OldOnStartBuild(unitBeingBuilt, order )
   
   ImmunizeUnit(unitBeingBuilt)
end

## Replacement Collision Check function
newOnCollisionCheck = function(self, other, firingWeapon)
   if other.friendly == 1 then
      return false
   else
      return self.OldOnCollisionCheck(self, other, firingWeapon)   
   end
end

## Replacement function for Projectile Creation
newCreateProjectileForWeapon = function(self, muzzle)
   local proj = self.OldCreateProjectileForWeapon(self, muzzle)
   proj.friendly = 1
   return proj
end

## Replacement function for Child Projectile Creation
newCreateChildProjectile = function(self, bp)
   local proj = self.OldCreateChildProjectile(bp)
   proj.friendly = 1
   return proj
end

## Replacement Collision Check function used by Beam Weapons
newOnCollisionCheckWeapon = function(self, firingWeapon)
   if firingWeapon.friendly == 1 then
      return false
   else
      return self.OldOnCollisionCheckWeapon(self, firingWeapon)   
   end
end

## Mark weapons as friendly
neutralizeWeapons = function(unit)
   for i = 1, unit:GetWeaponCount() do
      local weapon = unit:GetWeapon(i)
      local bp = unit:GetBlueprint().Weapon[i]
      if bp.ProjectileId != "" then
         weapon.OldCreateProjectileForWeapon = weapon.CreateProjectileForWeapon
         weapon.CreateProjectileForWeapon = newCreateProjectileForWeapon
         
         weapon.OldCreateChildProjectile = weapon.CreateChildProjectile
         weapon.CreateChildProjectile = newCreateChildProjectile
      else
         weapon.friendly = 1
      end
   end
end