difficulty = Map.LobbyOption("difficulty")
tanktypes = Map.LobbyOption("tanktypes")
rules2 = function()
    Trigger.AfterDelay(DateTime.Seconds(1320), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1500), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1600), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1700), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(702), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1800), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1803), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1805), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(1905), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(2005), function()
        Media.PlaySound("laugh.aud")
    end)
    Trigger.AfterDelay(DateTime.Seconds(400), function()
        Media.PlaySound("CyberWar.aud")
	    Trigger.AfterDelay(DateTime.Seconds(110), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(800), function()
        Media.PlaySound("CyberWar2.aud")
	    Trigger.AfterDelay(DateTime.Seconds(315), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(1200), function()
        Media.PlaySound("CyberWar.aud")
	    Trigger.AfterDelay(DateTime.Seconds(110), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(1600), function()
        Media.PlaySound("CyberWar2.aud")
	    Trigger.AfterDelay(DateTime.Seconds(315), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(2000), function()
        Media.PlaySound("CyberWar.aud")
	    Trigger.AfterDelay(DateTime.Seconds(110), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(2400), function()
        Media.PlaySound("CyberWar2.aud")
	    Trigger.AfterDelay(DateTime.Seconds(315), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(2800), function()
        Media.PlaySound("CyberWar.aud")
	    Trigger.AfterDelay(DateTime.Seconds(110), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(3200), function()
        Media.PlaySound("CyberWar2.aud")
	    Trigger.AfterDelay(DateTime.Seconds(315), function()
	        Media.PlaySound("war.aud")
	    end)
    end)
    Trigger.AfterDelay(DateTime.Seconds(30), function()
        Media.DisplayMessage ("Loading background noise, hang on...", "PMG", HSLColor.Red)
        Trigger.AfterDelay(DateTime.Seconds(3), function()
            Media.PlaySound("war.aud")
		    --Media.DisplayMessage ("Playing war.aud","PMG", HSLColor.Yellow)
            Trigger.AfterDelay(DateTime.Seconds(3), function()
                Media.DisplayMessage ("Welcome to the Ultimate AI mod.\nCopyright Melons 2022, ask permission before use. ","Melons", HSLColor.Red)
                Trigger.AfterDelay(DateTime.Seconds(1), function()
                    Media.DisplayMessage ("I'm asking permission to use this.", "PMG", HSLColor.Yellow)
				    Trigger.AfterDelay(DateTime.Seconds(1), function()
		                Media.DisplayMessage ("So i asked permission...","PMG", HSLColor.Yellow)
				    end)
                    Trigger.AfterDelay(DateTime.Seconds(2), function()
                        Media.PlaySound("laugh.aud")
                        Trigger.AfterDelay(DateTime.Seconds(16), function()
                            Media.DisplayMessage ("Special thanks to OpenRA team, the map & mod creators, and all the players around the world. GLHF!\n", "Waggy", HSLColor.Green)
                            Trigger.AfterDelay(DateTime.Seconds(130), function()
                                Media.PlaySound("output.aud")
                                Trigger.AfterDelay(DateTime.Seconds(5), function()
                                    --Media.PlaySound("war.aud")
									--Media.DisplayMessage ("Playing war.aud","PMG", HSLColor.Yellow)
                                    Trigger.AfterDelay(DateTime.Seconds(130), function()
                                        Media.PlaySound("output.aud")
                                        Trigger.AfterDelay(DateTime.Seconds(5), function()
                                            --Media.PlaySound("war.aud")
											--Media.DisplayMessage ("Playing war.aud","PMG", HSLColor.Yellow)
                                            Trigger.AfterDelay(DateTime.Seconds(130), function()
                                                Media.PlaySound("laugh.aud")
                                                Trigger.AfterDelay(DateTime.Seconds(5), function()
                                                    Media.PlaySound("kill.aud")
                                                    Trigger.AfterDelay(DateTime.Seconds(130), function()
	                                                    Media.PlaySound("kill.aud")
                                                    end)
                                                end)
                                            end)
                                        end)
                                    end)
                                end)
                            end)
                        end)
                    end)
                end)
            end)
        end)
    end)
end

function setDifficulty() 

	toxicAdjustment =1

	if toxic_enabled == 1
	then 
		toxicAdjustment = 3
	end


	if difficulty == "noob" then
		difficultyHandicap = 0.6
		maxLimit = (6*HandicapAdjustment)*toxicAdjustment
		mcvLimit = (12*HandicapAdjustment)*toxicAdjustment
	elseif difficulty == "easy" then
		difficultyHandicap = 0.8
		maxLimit = (10*HandicapAdjustment)*toxicAdjustment
		mcvLimit = (14*HandicapAdjustment)*toxicAdjustment
	elseif difficulty == "normal" then
		difficultyHandicap = 1
		maxLimit = (14*HandicapAdjustment)*toxicAdjustment
		mcvLimit = (18*HandicapAdjustment)*toxicAdjustment
	elseif difficulty == "extreme" then
		difficultyHandicap = 1.2
		maxLimit = (20*HandicapAdjustment)*toxicAdjustment
		mcvLimit = (30*HandicapAdjustment)*toxicAdjustment
	else
		difficultyHandicap = 1.5
		maxLimit = 99
		mcvLimit = 99
	end
end


function theBots()
    return Player.GetPlayers(function(player)
        return player.IsBot == true;
    end);
end

function theUltimateBots()
    return Player.GetPlayers(function(player)
        return player.IsBot == true and player.HasPrerequisites({"ultimateaienabled"});
    end);
end

function theHumans()
    return Player.GetPlayers(function(player)
        return player.IsBot == false and player.IsNonCombatant == false;
    end);
end

function thePlayers()
    return Player.GetPlayers(function(player)
        return player.IsNonCombatant == false;
    end);
end

function thePlayersAndCreeps()
    return Player.GetPlayers(function(player)
        return true
    end);
end


--Random Testing
function getActorsAround(actorselected,actorsToFind, distance)
	actorList = Map.ActorsInCircle(actorselected.CenterPosition, WDist.FromCells(distance), function(a)
		return a.Type == actorsToFind
	end)

	return actorList
end


--messaging system
function readmessages() 
					
	messagescount = tablelength(messages)
	
	resetmessagestimer = messagescount*3+1

	if messagescount > 0 then
		for i = tablelength(messages),1,-1 
		do 
			Trigger.AfterDelay(DateTime.Seconds(i*3), function()
				Media.DisplayMessage (messages[i], "Mission", HSLColor.Red)
			end)
		end
	else
		Media.DisplayMessage ("No Messages to Display", "Mission", HSLColor.Red)
	end

	Trigger.AfterDelay(DateTime.Seconds(resetmessagestimer), function()
		messages = {}
	end)

end



--message loop
function readmessagesloop() 
					
	if loopcounter < 6 then
			
		messagescount = tablelength(messagesloop)
		
		resetmessagestimer = messagescount*3+1

		if messagescount > 0 then
			for i = tablelength(messagesloop),1,-1 
			do 
				Trigger.AfterDelay(DateTime.Seconds(i*3), function()
					Media.DisplayMessage (messagesloop[i], "Mission", HSLColor.Red)
				end)
			end
		else
			--Media.DisplayMessage ("No Loop Messages to Display", "Mission", HSLColor.Red)
		end


		Trigger.AfterDelay(5000, readmessagesloop)
		loopcounter = loopcounter +1
	end

end

--Ref Setup
function setupRefs()

	facts = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor)
		return actor.Type == "fact" or actor.Type == "mcv"
	end)


	Utils.Do(facts, function(a)
		
			-- Media.DisplayMessage (""..a.Owner.Name, "Mission", HSLColor.Red)
		if a.Owner ~= castlePlayer then
			actorOwner = a.Owner
			--Media.DisplayMessage (""..actorOwner.Name, "Mission", HSLColor.Red)

			toCapture = {}
			toCapture = { "silo","powr"}

			Utils.Do(toCapture, function(z)
				actorsToCapture = getActorsAround(a,z,20)
					
				Utils.Do(actorsToCapture, function(b)
					b.Owner = actorOwner
				end)
			end)
		end
	end)

	--Create Refs
	Trigger.AfterDelay(DateTime.Seconds(1), function()
		powrs = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor)
			return 
			actor.Type == "silo"
		end)

		Utils.Do(powrs, function(a)

			actorOwner = a.Owner
			originalLocation = a.Location
			newLocation = originalLocation + CVec.New(0,1)

			if actorOwner.InternalName ~= "Creeps" then
				Actor.Create("proc", true, { Owner = actorOwner, Location = newLocation})
			end

			
			 --Media.DisplayMessage (""..actorOwner.InternalName, "Mission", HSLColor.Red)
			-- Media.DisplayMessage(""..newLocation, "Mission", HSLColor.Red)
		end)

	end)


	Trigger.AfterDelay(DateTime.Seconds(2), function()
		creepActors = getAllCreeps()
		removeactors(creepActors)
		--Media.DisplayMessage(""..#creepActors, "Mission", HSLColor.Red)

	end)

end

--Remove Boxes in Table
function removeactors(a)
	Utils.Do(a, function(unit)
		unit.Destroy()
	end)
	return 
end


function getClosetActor(actorselected,actorsToFind)
	actorList = Map.ActorsInCircle(actorselected.CenterPosition, WDist.FromCells(50), function(a)
		return a.Type == actorsToFind
	end)

	return actorList[1]
end

function getAllActors(a)

	theActors = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor)
		return actor.Type == a
	end)

	return theActors

end

function getAllCreeps()

	targets = Utils.Where(Creeps.GetActors(), function(actor)
		return
			actor.Type == "powr" or actor.Type == "silo"
	end)
	return targets

end

----START OF AI REINFORCEMENTS ---

function createNewMcv(quantity)
	if quantity == nil then
		quantity = 1
	end
	Trigger.AfterDelay(DateTime.Seconds(10), function()
		for z, thePlayer in ipairs(AIPlayers) do
			Actor.Create("mcv", true, { Owner = thePlayer, Location = thePlayer.HomeLocation + CVec.New(0, 3) });
		end
		quantity = quantity -1
		if quantity > 0 then
			createNewMcv(quantity)
		end
	end)
end



function createRandomInfantryPerBuilding(quantity)
	if quantity == nil then
		quantity = 1
	end
	
	countLimit = 0

			for z, thePlayer in ipairs(AIPlayers) do
				theProducers = thePlayer.GetActorsByTypes({ "barr", "tent" });
				
				Utils.Do(theProducers, function(theUnits)
					if countLimit < maxLimit then
						if (difficulty == "easy" or difficulty == "noob") then
							toProduceTanks = { "e1", "e1", "e1",  "e1", "e1", "e1", "e3"  }
						else
							toProduceTanks = { "e1", "e1", "e1", "e3", "e3" }
						end
						randomUnit = Utils.RandomInteger(1,#toProduceTanks+1)
						randomTank =  toProduceTanks[randomUnit];
						-- Media.DisplayMessage("hello1", "Mission", HSLColor.Red)
						theTank = Actor.Create(randomTank, true, { Owner = thePlayer, Location = theUnits.Location + CVec.New(0, 2) });
						theTank.Move(theUnits.RallyPoint)
						countLimit = countLimit+1
					end
				end)
			end
			quantity = quantity -1
			if quantity > 0 then
				--Media.DisplayMessage("hello2", "Mission", HSLColor.Red)
				createRandomInfantryPerBuilding(quantity)
			end
end

function createRandomTankPerBuilding(quantity)
	if quantity == nil then
		quantity = 1
	end

	countLimit = 0

			for z, thePlayer in ipairs(AIPlayers) do
				theProducers = thePlayer.GetActorsByTypes({ "weap" });

				Utils.Do(theProducers, function(theUnits)
					if countLimit < maxLimit then
						
						if (tanktypes == "demolition") then 
							toProduceTanks = { "dtrk" }
						elseif (doomsdayenabled == 1) then
							toProduceTanks = { "4tnk", "4tnk","4tnk", "4tnk", "3tnk", "3tnk", "3tnk", "ctnk", "ctnk", "v2rl", "mrj", "arty", "mgg", "v2rl", "arty"}
						else	
							if (difficulty == "easy" or difficulty == "noob") then
								toProduceTanks = { "jeep", "apc", "1tnk", "ftrk", "jeep", "apc", "1tnk", "ftrk", "jeep", "apc", "1tnk", "ftrk", "4tnk", "ctnk", "v2rl", "2tnk", "2tnk", "1tnk", "3tnk", "mrj", "2tnk", "arty", "mgg", "mrj", "v2rl", "2tnk", "arty", "3tnk", "2tnk", "stnk", "dtrk" }
							elseif (difficulty == "normal") then
								toProduceTanks = { "apc", "apc", "1tnk", "1tnk", "ftrk", "4tnk", "3tnk", "3tnk", "ctnk", "v2rl", "2tnk", "2tnk", "2tnk", "1tnk", "3tnk", "2tnk", "arty", "mgg", "mrj", "v2rl", "2tnk", "arty", "3tnk", "mrj", "stnk", "dtrk"}
							else
								toProduceTanks = { "apc", "1tnk", "ftrk", "4tnk", "4tnk", "ctnk", "v2rl", "2tnk", "2tnk", "1tnk", "3tnk", "mrj", "2tnk", "arty", "mgg", "mrj", "v2rl", "2tnk", "arty", "3tnk", "mrj", "stnk", "dtrk"}
							end
						end		
						randomUnit = Utils.RandomInteger(1,#toProduceTanks+1)
						randomTank =  toProduceTanks[randomUnit];
						-- Media.DisplayMessage("hello1", "Mission", HSLColor.Red)
						theTank = Actor.Create(randomTank, true, { Owner = thePlayer, Location = theUnits.Location + CVec.New(0, 2) });
						theTank.Move(theUnits.RallyPoint)
						countLimit = countLimit+1
					end
				end)

			end
			quantity = quantity -1
			if quantity > 0 then
				--Media.DisplayMessage("hello2", "Mission", HSLColor.Red)
				createRandomTankPerBuilding(quantity)
			end
end




function spawnUnits(spawnUnitType, spawnUnitOwner, spawnUnitLocation)
	theActor = Actor.Create(spawnUnitType, true, { Owner = spawnUnitOwner, Location =  spawnUnitLocation});

	if spawnUnitType ~= "mcv" then
		if spawnUnitType == "qtnk" or spawnUnitType == "mgg" or spawnUnitType == "mrj" or spawnUnitType == "thf" then
			--theActor.Move(CaptureMiddle.Location)
		else
			--theActor.AttackMove(CaptureMiddle.Location)
		end
	end
	
end

function sendRepeatWave(unitsTier,quantity,repeatTime)
	
	if repeatTime == nil then
		repeatTime = 120
	end

	sendAttackWave(unitsTier,quantity)

			--Set Next Wave
			Trigger.AfterDelay(DateTime.Seconds(repeatTime), function()
				sendRepeatWave(unitsTier,quantity,repeatTime)
			end)
end


function sendAttackWave(unitsTier, quantity)

	if repeatWave == nil then
		local repeatWave = 0
	end
	if unitsTier == nil then
		unitsTier = tier1Tanks
	end

	--bug for ai production
		for z, thePlayer in ipairs(AIPlayers) do

			if #thePlayer.GetActors() > 1 then

				if (unitsTier == tierMcv) then
					if (countMcvs(thePlayer) >= mcvLimit) then
						return
					end
				end

				if quantity == nil or quantity == 0 then
					quantityToProduce = 7
				else
					quantityToProduce = quantity
				end

				--currentSpawn = thePlayer.HomeLocation + CVec.New(-5,-5)
				currentSpawn = thePlayer.HomeLocation + CVec.New(-1,-1)

				while quantityToProduce > 0 do
					randomUnit = Utils.RandomInteger(1,#unitsTier+1)
					--Media.DisplayMessage("".. randomUnit, "Mission", HSLColor.Red)

					spawnUnits(unitsTier[randomUnit],thePlayer, currentSpawn)

					quantityToProduce = quantityToProduce -1

					if currentSpawn == spawnPoint1 then
						currentSpawn = spawnPoint2
					elseif  currentSpawn == spawnPoint2 then
						currentSpawn = spawnPoint3
					elseif  currentSpawn == spawnPoint3 then
						currentSpawn = spawnPoint4
					elseif  currentSpawn == spawnPoint4 then
						currentSpawn = spawnPoint1
					end
				end
			end
		end

end


function createHarv()
	if quantity == nil then
		quantity = 1
	end
	if toxic_enabled then
		Trigger.AfterDelay(DateTime.Seconds(10), function()
			for z, thePlayer in ipairs(AIPlayers) do
				if thePlayer.Cash < 2500 then
					Actor.Create("harv", true, { Owner = thePlayer, Location = thePlayer.HomeLocation + CVec.New(0, 2) });
				end
			end
			createHarv()
		end)
	else
		Trigger.AfterDelay(DateTime.Seconds(25), function()
			for z, thePlayer in ipairs(AIPlayers) do
				if thePlayer.Cash < 1500 then
					Actor.Create("harv", true, { Owner = thePlayer, Location = thePlayer.HomeLocation + CVec.New(0, 2) });
				end
			end
			createHarv()
		end)

	end
end

function createEngineers(quantity)--
	if quantity == nil then
		quantity = 1
	end

				sendAttackWave(tierEngineers,#theHumans())
				sendAttackWave(tierThief,#theHumans())
				
				if (difficulty ~= "easy" and difficulty ~= "noob" and difficulty ~= "normal") then
					sendAttackWave(tierSpy,#theHumans())
				end

			Trigger.AfterDelay(DateTime.Seconds(5), function()
				sendEngineers()
				if (difficulty ~= "easy" and difficulty ~= "noob") then
				end
			end)
			if quantity > 0 then
				Trigger.AfterDelay(DateTime.Seconds(60), function()
					--Media.DisplayMessage("hello2", "Mission", HSLColor.Red)
					createEngineers(quantity)
					sendThief()
					sendSpy()
				end)
			end
end

--send engineers to cap middle
function sendThief()
	
	for z, thePlayer in ipairs(AIPlayers) do
        local theUnits = thePlayer.GetActorsByType("thf");

		--Media.DisplayMessage("sendThief", "Mission", HSLColor.Red)

		if #theUnits > 0 then
			Utils.Do(theUnits, function(unit)

				--actorToTarget = { "ectnk", "dtrk" }
--				actorToTarget = { "1tnk", "2tnk", "3tnk", "4tnk", "apc", "apoc", "arty", "batf", "ctnk", "ctrk", "dtrk", "ectnk", "ftnk", "ftrk", "hftk", "isu", "jeep", "katy", "mgg", "mrj", "msam", "panzer", "ptnk", "rtnk", "sherman", "stnk", "tnkd", "ttnk2", "v2rl", "v3rl" }
				actorToTarget = { "jeep", "apc", "1tnk", "ftrk", "v2rl", "2tnk", "arty", "mgg", "mrj", "ttnk", "3tnk", "mrj", "ctnk", "stnk", "4tnk", "3tnk", "mrj", "dtrk", "ctnk", "stnk" }

				unitToTarget = findClosestTargetAiNeutral(unit,actorToTarget)

				if unitToTarget ~= nil then
					--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					unit.Stop()
					unit.Move(unitToTarget.Location)
					unit.Capture(unitToTarget)
				else
					--Media.DisplayMessage("sendThief: no ectnk", "Mission", HSLColor.Red)
					actorToTarget = { "proc" }

					unitToTarget = findClosestTargetAi(unit,actorToTarget)

					if unitToTarget ~= nil then
						--Media.DisplayMessage("INFILTRATE: Type: "..unitToTarget.Type, "Mission", HSLColor.Red);
						unit.Stop()
						unit.Move(unitToTarget.Location)
						unit.Infiltrate(unitToTarget)
					end
				end
			end)
		end
	end
end


--send engineers to cap middle
function sendSpy()
	
	for z, thePlayer in ipairs(AIPlayers) do
        local theUnits = thePlayer.GetActorsByType("spy");

		actorToTarget = { "powr", "apwr", "dome" }

		if #theUnits > 0 then
			Utils.Do(theUnits, function(unit)
				unitToTarget = findClosestTargetAi(unit,actorToTarget)
	
				if unitToTarget ~= nil then
					--Media.DisplayMessage("hello5", "Mission", HSLColor.Red)
					unit.Stop()
					unit.DisguiseAsType("e1",unitToTarget.EffectiveOwner)
					unit.Move(unitToTarget.Location)
					unit.Infiltrate(unitToTarget)
				end
			end)
		end
	end
end

function findClosestTargetAi(searchActor, actorTypes)
    closestActor = nil
    distnceCloset = 250000;
   
	if Utils.RandomInteger(1,3) == 1 then
	    for rr, enemyPlayer in ipairs(HumanPlayers) do
	        if enemyPlayer ~= searchActor.EffectiveOwner then
	            if enemyPlayer.Team ~= searchActor.EffectiveOwner.Team or enemyPlayer.Team == 0 or searchActor.EffectiveOwner.Team == 0 then
	                local actors = enemyPlayer.GetActorsByTypes(actorTypes);
	                for rr, actor in ipairs(actors) do
	                     theDistance = actor.Location - searchActor.Location;
	                     distanceMath = math.sqrt((theDistance.X * theDistance.X) + (theDistance.Y * theDistance.Y));
	                    if distanceMath <= distnceCloset then
	                        distnceCloset = distanceMath;
	                        closestActor = actor;
	                    end
	                end
	            end
	        end
	    end
	    if (closestActor == nil) then 
		    for rr, enemyPlayer in ipairs(AllBots) do
		        if enemyPlayer ~= searchActor.Owner then
		            if enemyPlayer.Team ~= searchActor.Owner.Team or enemyPlayer.Team == 0 or searchActor.Owner.Team == 0 then
		                local actors = enemyPlayer.GetActorsByTypes(actorTypes);
		                for rr, actor in ipairs(actors) do
		                    theDistance = actor.Location - searchActor.Location;
		                    distanceMath = math.sqrt((theDistance.X * theDistance.X) + (theDistance.Y * theDistance.Y));
		                    if distanceMath <= distnceCloset then
		                        distnceCloset = distanceMath;
		                        closestActor = actor;
		                    end
		                end
		            end
		        end
		    end
	    end
	else
	    for rr, enemyPlayer in ipairs(AllBots) do
	        if enemyPlayer ~= searchActor.Owner then
	            if enemyPlayer.Team ~= searchActor.Owner.Team or enemyPlayer.Team == 0 or searchActor.Owner.Team == 0 then
	                local actors = enemyPlayer.GetActorsByTypes(actorTypes);
	                for rr, actor in ipairs(actors) do
	                    theDistance = actor.Location - searchActor.Location;
	                    distanceMath = math.sqrt((theDistance.X * theDistance.X) + (theDistance.Y * theDistance.Y));
	                    if distanceMath <= distnceCloset then
	                        distnceCloset = distanceMath;
	                        closestActor = actor;
	                    end
	                end
	            end
	        end
	    end
	    if (closestActor == nil) then 
		    for rr, enemyPlayer in ipairs(HumanPlayers) do
		        if enemyPlayer ~= searchActor.EffectiveOwner then
		            if enemyPlayer.Team ~= searchActor.EffectiveOwner.Team or enemyPlayer.Team == 0 or searchActor.EffectiveOwner.Team == 0 then
		                local actors = enemyPlayer.GetActorsByTypes(actorTypes);
		                for rr, actor in ipairs(actors) do
		                     theDistance = actor.Location - searchActor.Location;
		                     distanceMath = math.sqrt((theDistance.X * theDistance.X) + (theDistance.Y * theDistance.Y));
		                    if distanceMath <= distnceCloset then
		                        distnceCloset = distanceMath;
		                        closestActor = actor;
		                    end
		                end
		            end
		        end
		    end
    	end
	end
    return closestActor;
end

function findClosestTargetAiNeutral(searchActor, actorTypes)
    closestActor = nil
    distnceCloset = 250000;
    
    local actors = Neutral.GetActorsByTypes(actorTypes);
    for rr, actor in ipairs(actors) do
        theDistance = actor.Location - searchActor.Location;
        distanceMath = math.sqrt((theDistance.X * theDistance.X) + (theDistance.Y * theDistance.Y));
        if distanceMath <= distnceCloset then
            distnceCloset = distanceMath;
            closestActor = actor;
        end
    end
    return closestActor;
end

actorToTargetAi 		= {                       "agun",                 "silo", "hpad", "weap", "oilb","fcom","hosp","miss","bio","afld.ukraine","afld","powr","apwr","stek","barr","kenn","proc","tent","fix","dome","mslo","gap","iron","sam","atek","fact" }
actorToTargetNeutral 	= {"ftur", "gun", "tsla", "agun", "pbox", "hbox", "silo", "hpad", "weap", "oilb","fcom","hosp","miss","bio","afld.ukraine","afld","powr","apwr","stek","barr","kenn","proc","tent","fix","dome","mslo","gap","iron","sam","atek","fact" }

function sendEngineerNextTarget(u) 
	local unit = u
	Trigger.AfterDelay(DateTime.Seconds(1), function()
		if not unit.IsDead then
			--actorToTarget = {"embsy","adept","mtsla","pris","pbox","ioncan", "silo", "afld.ukraine", "hpad", "weap", "htur", "oilb","fcom","hosp","miss","bio","fact","afld","powr","apwr","stek","barr","kenn","proc","tent","fix","dome","mslo","gap","spen","syrd","iron","pdox","agun","sam","atek","fact" }

			--local unitToTarget = findClosestTargetAiNeutral(unit,actorToTarget)
			local unitToTarget
			if Utils.RandomInteger(1,3) == 1 then
				unitToTarget = findClosestTargetAi(unit,actorToTargetAi)
				if unitToTarget ~= nil then
					--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					unit.Stop()
					unit.Move(unitToTarget.Location)
					unit.Capture(unitToTarget)
				else
					unitToTarget = findClosestTargetAiNeutral(unit,actorToTargetNeutral)
					if unitToTarget ~= nil then
						--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						unit.Stop()
						unit.Move(unitToTarget.Location)
						unit.Capture(unitToTarget)
					end
				end
			else

				unitToTarget = findClosestTargetAiNeutral(unit,actorToTargetNeutral)
				if unitToTarget ~= nil then
					--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					unit.Stop()
					unit.Move(unitToTarget.Location)
					unit.Capture(unitToTarget)
				else
					unitToTarget = findClosestTargetAi(unit,actorToTargetAi)
					if unitToTarget ~= nil then
						--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						unit.Stop()
						unit.Move(unitToTarget.Location)
						unit.Capture(unitToTarget)
					end
				end
			end
		end
	end)
end

--send engineers to cap middle
function sendEngineers()
--			actorToTarget = {"embsy","adept","mtsla","pris","pbox","ioncan", "silo", "afld.ukraine", "hpad", "weap", "htur", "oilb","fcom","hosp","miss","bio","fact","afld","powr","apwr","stek","barr","kenn","proc","tent","fix","dome","mslo","gap","spen","syrd","iron","pdox","agun","sam","atek","fact" }
	for z, thePlayer in ipairs(AIPlayers) do
        local engineers = thePlayer.GetActorsByType("e6");
		Utils.Do(engineers, function(unit)


			local unitToTarget
			if Utils.RandomInteger(1,3) == 1 then
				unitToTarget = findClosestTargetAi(unit,actorToTargetAi)
				if unitToTarget ~= nil then
					--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					--Media.DisplayMessage("RandomInteger: 1 "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					unit.Stop()
					unit.Move(unitToTarget.Location)
					unit.Capture(unitToTarget)
					trigger(unit, unitToTarget)
				else
					unitToTarget = findClosestTargetAiNeutral(unit,actorToTargetNeutral)
					if unitToTarget ~= nil then
						--Media.DisplayMessage("RandomInteger: 1 "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						unit.Stop()
						unit.Move(unitToTarget.Location)
						unit.Capture(unitToTarget)
						trigger(unit, unitToTarget)
					end
				end
			else
				unitToTarget = findClosestTargetAiNeutral(unit,actorToTargetNeutral)
				if unitToTarget ~= nil then
					--Media.DisplayMessage("RandomInteger: 2 "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
					unit.Stop()
					unit.Move(unitToTarget.Location)
					unit.Capture(unitToTarget)
					trigger(unit, unitToTarget)
				else
					unitToTarget = findClosestTargetAi(unit,actorToTargetAi)
					if unitToTarget ~= nil then
						--Media.DisplayMessage("RandomInteger: 2 "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						--Media.DisplayMessage("CAPTURE: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						unit.Stop()
						unit.Move(unitToTarget.Location)
						unit.Capture(unitToTarget)
						trigger(unit, unitToTarget)
					end
				end
			end

		end)
	end
end

function trigger(u, uT)
	local unit = u
	local unitToTarget = uT
	--Trigger.OnObjectiveCompleted(unit, function(p, id)
	--	if not p.IsDead then
	--		Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed")
	--	end
	--end)				
	Trigger.OnCapture(unitToTarget, function()
		if not unit.IsDead then
			--Media.DisplayMessage("CAPTURED: Type: "..unit.Type.." Loc: "..unit.Location.X..","..unit.Location.Y , "Mission", HSLColor.Red);
			--Media.DisplayMessage("CAPTURED: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
			sendEngineerNextTarget(unit)
		end
	end)
end					

function aiCash()

	if toxic_enabled then
		Trigger.AfterDelay(DateTime.Seconds(10), function()
			for z, thePlayer in ipairs(AIPlayers) do
				if thePlayer.Cash < 4000 then
					thePlayer.Cash =  thePlayer.Cash +2000
				end
			end
			aiCash()
		end)
	else
		Trigger.AfterDelay(DateTime.Seconds(20), function()
			for z, thePlayer in ipairs(AIPlayers) do
				if thePlayer.Cash < 4000 then
					thePlayer.Cash =  thePlayer.Cash +500
				end
			end
			aiCash()
		end)
	end
	
end



--Tanks every 60s
function continuousProductionTanks()

	if (difficulty == "noob") then
		continuousDelay = 90/ToxicHandicap
	elseif (difficulty == "easy") then
		continuousDelay = 74/ToxicHandicap
	elseif (difficulty == "normal") then
		continuousDelay = 65/ToxicHandicap
	else
		continuousDelay = 45/ToxicHandicap
	end

	createRandomTankPerBuilding((4*HandicapAdjustment))
	Trigger.AfterDelay(DateTime.Seconds(continuousDelay), continuousProductionTanks)
end

--Infantry every 15s
function continuousProductionInfantry()

	if (difficulty == "noob" ) then
		continuousDelay = 30/ToxicHandicap
	elseif (difficulty == "easy") then
		continuousDelay = 25/ToxicHandicap
	elseif (difficulty == "normal") then
		continuousDelay = 20/ToxicHandicap
	else
		continuousDelay = 15/ToxicHandicap
	end

	createRandomInfantryPerBuilding((4*HandicapAdjustment))
	Trigger.AfterDelay(DateTime.Seconds(continuousDelay), continuousProductionInfantry)
end

function continuousProduction()
	continuousProductionTanks()
	continuousProductionInfantry()
end

function countMcvs(isPlayer)
	mcvCount = countbuildings("mcv", isPlayer)
	factCount = countbuildings("fact", isPlayer)
	totalMcvs = mcvCount + factCount
	return totalMcvs
end


-- Ultimate AI Functions (Before WorldLoaded) End

a = 500 --nuke timer

NuclearStrikes = Map.LobbyOption("NuclearStrikes")

--check option selected
if (NuclearStrikes ~= "entry_1") then
	if (NuclearStrikes == "entry_2") then
		a = 5
	else
		if (NuclearStrikes == "entry_3") then
			a = 8
		else
			if (NuclearStrikes == "entry_4") then
				a = 12
			else
				a = 15
			end
		end
	end
end

rules = function()
		if (Cappoints ~= "entry_off") then
			if (Cappoints == "entry_1") then
				table.insert(messages, "OBJECTIVE: Capture the Communications Centre with an engineer and hold for timer amount")
				-- Media.DisplayMessage ("OBJECTIVE: Capture the Communications Centre with an engineer and hold for timer amount  ", "Mission", HSLColor.Red)
			else
				table.insert(messages, "OBJECTIVE: Capture all the Communications Centres with an engineer and hold for timer amount")
				-- Media.DisplayMessage ("OBJECTIVE: Capture all the Communications Centres with an engineer and hold for timer amount  ", "Mission", HSLColor.Red)
			end
		end
		if (NuclearStrikes ~= "entry_1") then
			Beaconmiddle()
			if (Cappoints ~= "entry_off") then
					table.insert(messages, "WARNING: Nuclear strike mode enabled, middle area will be nuked every 5-15 minutes")
					-- Media.DisplayMessage ("WARNING: Nuclear strike mode enabled, middle area will be nuked every 5-15 minutes", "Mission", HSLColor.Red)
				
			else
				table.insert(messages, "WARNING: Nuclear strike mode enabled, middle area will be nuked every 5-15 minutes")
				-- Media.DisplayMessage ("WARNING: Nuclear strike mode enabled, middle area will be nuked every 5-15 minutes", "Mission", HSLColor.Red)
			end
			Trigger.AfterDelay(DateTime.Seconds(5), function()
				nukemid() 
      	 	 end)
		end
end


prepandfire = function()
	if (Nuker.HasProperty("ActivateNukePower")) then
		Media.DisplayMessage ("WARNING: Abomb preparing to launch in the middle", "Mission", HSLColor.Red)
		Media.PlaySpeechNotification(USSR, "AbombPrepping")
		Trigger.AfterDelay(DateTime.Seconds(30), function()
			nukemid()
		end)
	end
end

delayedlaunch = function()
	Trigger.AfterDelay(DateTime.Minutes(a), function()
		prepandfire()
	end)
end

nukemid = function()
			Media.PlaySpeechNotification(USSR, "AbombLaunchDetected")

--Middle Area
			Nuker.ActivateNukePower(CPos.New(57,55))
			Nuker.ActivateNukePower(CPos.New(65,55))
			Nuker.ActivateNukePower(CPos.New(73,55))

			Nuker.ActivateNukePower(CPos.New(57,73))
			Nuker.ActivateNukePower(CPos.New(65,73))
			Nuker.ActivateNukePower(CPos.New(73,73))

			Nuker.ActivateNukePower(CPos.New(48,60))
			Nuker.ActivateNukePower(CPos.New(48,68))
			
			Nuker.ActivateNukePower(CPos.New(80,60))
			Nuker.ActivateNukePower(CPos.New(80,68))
--[[ Left Side ]]
			Nuker.ActivateNukePower(CPos.New(7,64))
--[[ Right Side ]]
			Nuker.ActivateNukePower(CPos.New(123,64))
			--delayedparabombs()
			delayedlaunch()
end

delayedtroopers = function()
	Trigger.AfterDelay(DateTime.Seconds(15), function()
			
		
	--	Media.DisplayMessage ("Troops incoming", "Mission", HSLColor.Red)

	ShockDrop.TargetParatroopers(SHOCKER1.CenterPosition, Angle.New(300))
	ShockDrop2.TargetParatroopers(SHOCKER2.CenterPosition, Angle.New(300))
	ShockDrop3.TargetParatroopers(SHOCKER3.CenterPosition, Angle.New(800))
	ShockDrop4.TargetParatroopers(SHOCKER4.CenterPosition, Angle.New(800))
		

	end)
end


function tablelength(T)
	local count = 0
	for _ in pairs(T) do count = count + 1 end
	return count
  end

function toxicPlayersCheck()
    return Player.GetPlayers(function(player)
        return true
    end);
end

function setToxic()
	toxiccheck = 1
	Utils.Do(toxicPlayersCheck(), function(thesePlayers)
		if toxiccheck == 1 then
			if thesePlayers.HasPrerequisites({"toxic_enabled"}) 
			then
				toxic_enabled = 1
				-- Media.DisplayMessage ("Toxic Enabled", "Mission", HSLColor.Red)
				toxiccheck = 2
			end
		end
	end)
end

WorldLoaded = function()
	

doomsdayenabled = 0	
Neutral = Player.GetPlayer("Neutral") 
Creeps = Player.GetPlayer("Creeps") 
Cappoints = Map.LobbyOption("Cappoints")
NuclearStrikes = Map.LobbyOption("NuclearStrikes")
toxic_enabled = 0
enablechecking = 0
playersingame = {"Multi0","Multi1","Multi2","Multi3","Multi4","Multi5","Multi6","Multi7","Multi8","Multi9","Multi10","Multi11","Multi12","Multi13","Multi14","Multi15"} -- Table of Potential Players
actorstoupdate = {"fact","weap","tent","barr","hpad","afld","afld.ukraine","kenn","spen","syrd"}
messages = {}
messagesloop = {}

setToxic()

	----START OF AI SETUP CODE After setToxic() ---
		
	AllPlayersIncludingCreeps = thePlayersAndCreeps();
	AllPlayers = thePlayers();
	AIPlayers = theUltimateBots();
	UltimateBotsCount = #theUltimateBots();
	AllBots = theBots();
	HumanPlayers = theHumans();
	HandicapAdjustment = #theHumans()/4
	HumansCount = #theHumans()
	ToxicHandicap = 1
			
--	createwarriorant = "warriorant"
--	createfireant = "fireant"
--	creategiantant = "ant"

	tierEngineers = { "e6", "e6", "e6", "e6"}
	tierThief = { "thf", "thf", "thf", "thf"}
	tierSpy = { "spy", "spy", "spy", "spy"}
	tier1Tanks = { "jeep", "apc", "1tnk", "ftrk"}
	tier2Tanks = { "v2rl", "2tnk", "arty", "mgg", "mrj", "ttnk"}
	tier3Tanks = { "3tnk", "mrj", "ctnk", "stnk" }
	tier4Tanks = { "4tnk", "3tnk", "mrj", "dtrk", "ctnk", "stnk" }
	tier0infantry = {"e1"}
	tier1infantry = { "e1", "medi", "dog", "e1", "e2", "e3", "e3r1", "e4", "mech", "gnrl", "shok", "ant" }
	tier2infantry = { "spy", "thf", "fireant" }
	tier3infantry = { "e7", "sniper", "warriorant"}
	tierMcv = { "mcv"}

	if HandicapAdjustment == 0 then 
		HandicapAdjustment = 1
	end

	if toxic_enabled == 1 	then 
		ToxicHandicap = HandicapAdjustment*2
	end
	----END OF AI SETUP CODE After setToxic() ---


  playersingamecount = tablelength(playersingame) 
  actorstoupdatecount = tablelength(actorstoupdate) 

--Media.DisplayMessage ("Total Players is " .. playersingame2, "Mission", HSLColor.Red)

activeplayers = {}    -- Table for Active Players
activeplayername = {}    -- Table for Active Players
z = 1
for i = playersingamecount,1,-1 
do 

	playername = playersingame[i]
	
	if (Player.GetPlayer(playername) ~= nil) then
		playerinfo = Player.GetPlayer(playername)
		activeplayers[z] = Player.GetPlayer(playername)
		--Media.DisplayMessage (playerinfo.InternalName, "Mission", HSLColor.Red)
		--activeplayername[i] = playername
		z = z + 1
		if playerinfo.HasPrerequisites({"toxic_enabled"}) 
		then
			toxic_enabled = 1
		end
		i = i + 1
		--message = playername .. " is here"
	end
	
	--Media.DisplayMessage ("Player  " .. message, "Mission", HSLColor.Red)
end


--activeplayerscount = tablelength(activeplayers) --Table of players currently in the game


activeplayerscount = function()
	return tablelength(activeplayers)
end

--Media.DisplayMessage ("Active Players  " .. activeplayerscount(), "Mission", HSLColor.Red) --display total of players





----

Beaconmiddle = function()

	Trigger.AfterDelay(DateTime.Seconds(5), function()
		Media.PlaySoundNotification(USSR, "Beacon")
			for i = activeplayerscount(),1,-1 
			do 
				playeractive = activeplayers[i]
				playername = playeractive.InternalName
				Beacon.New(playeractive, MIDFOREST.CenterPosition, 500)
				Radar.Ping(playeractive, MIDFOREST.CenterPosition, HSLColor.Aqua, 500)
			end
	end)
end
	

Spawnspyplanemiddle = function()
	for i = activeplayerscount(),1,-1 
	do 
		playeractive = activeplayers[i]
		playername = playeractive.InternalName
		spyplanemiddle1 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = spymiddle.Location})
		spyplanemiddle1.Destroy()
	end
end

Spawnspyplanetemp = function()
			for i = activeplayerscount(),1,-1 
			do 
				playeractive = activeplayers[i]
				playername = playeractive.InternalName
				spyplanemiddle2 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = spymiddle.Location})
				tempspyplane1 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = COMMLEFT.Location})
				tempspyplane2 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = COMMRIGHT.Location})
				tempspyplane3 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = BioUp1.Location})
				tempspyplane4 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = BioUp2.Location})
				tempspyplane5 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = BioDown1.Location})
				tempspyplane6 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = BioDown2.Location})
				spyplanemiddle2.Destroy()
				tempspyplane1.Destroy()
				tempspyplane2.Destroy()
				tempspyplane3.Destroy()
				tempspyplane4.Destroy()
				tempspyplane5.Destroy()
				tempspyplane6.Destroy()
			end
end

	Nuker = Actor.Create("nuker", false, { Owner = Creeps })
	ShockDrop = Actor.Create("shockdrop", false, { Owner = Creeps })
	ShockDrop2 = Actor.Create("shockdrop", false, { Owner = Creeps })
	ShockDrop3 = Actor.Create("shockdrop", false, { Owner = Creeps })
	ShockDrop4 = Actor.Create("shockdrop", false, { Owner = Creeps })



unittocreate = "miss"
unittocreate2 = "gmine"
unittocreate3 = "POWR"
unittocreatebio = "bio"
unittocreatetree1 = "tc05"
unittocreatetree2 = "tc02"
unittocreatespyplane1 = "camera.spyplane"
createwarriorant = "warriorant"
createfireant = "fireant"
creategiantant = "ant"


--[[
Spawnspyplanemiddle = function()
	for i = activeplayerscount,1,-1 
	do 
		--playeractive = activeplayers[i]
		--playername = activeplayername[i]
		--spy0 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = spymiddle.Location})
	
	end
end

]]


-- Middle Only
Spawncom1 = function()
	comcentre1 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = COMMCENTER.Location})
end

-- 2 x Middle 
Spawncom2 = function()
	comtopmid = Actor.Create(unittocreate, true, { Owner = Neutral, Location = comtopmid.Location})
	combotmid = Actor.Create(unittocreate, true, { Owner = Neutral, Location = combotmid.Location})
end

--middle + sides
Spawncom3 = function() 
	comcentre1 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = COMMLEFT.Location})
	comcentre2 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = COMMRIGHT.Location})
	comcentre3 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = comtopmid.Location})
	comcentre4 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = combotmid.Location})
end

-- Sides
Spawncom4 = function() 
	comcentre1 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = COMMLEFT.Location})
	comcentre2 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = COMMRIGHT.Location})
end

--trees for middle
Spawntrees = function()
	tree1 = Actor.Create(unittocreatetree1, true, { Owner = Neutral, Location = tc05left.Location})
	tree2 = Actor.Create(unittocreatetree1, true, { Owner = Neutral, Location = tc05right.Location})
	tree3 = Actor.Create(unittocreatetree2, true, { Owner = Neutral, Location = tc02middle.Location})
end

--trees for middle
Biolabs = function()
	biolab1 = Actor.Create(unittocreatebio, true, { Owner = Neutral, Location = BioUp1.Location})
	biolab2 = Actor.Create(unittocreatebio, true, { Owner = Neutral, Location = BioUp2.Location})
	biolab3 = Actor.Create(unittocreatebio, true, { Owner = Neutral, Location = BioDown1.Location})
	biolab4 = Actor.Create(unittocreatebio, true, { Owner = Neutral, Location = BioDown2.Location})

		table.insert(messages, "WARNING: Bio Labs Enabled")
		-- Media.DisplayMessage ("WARNING: Bio Labs Enabled", "Mission", HSLColor.Red)
end

Spawnmines = function()
	extramine = {}
	actornames = {}    -- Table for Active Players
	zerocount = 0

	for i = 311,273,-1 
	do 

		minename = "Tmine" .. i
		actornames[zerocount] = "Tmine" .. i
		zerocount = zerocount+1
		-- Media.DisplayMessage (minename, "Mission", HSLColor.Red)
	end
	
	actornamescount = tablelength(actornames) 
	-- actornamescount = "test"
	-- Media.DisplayMessage (actornamescount .. "", "Mission", HSLColor.Red)
	

	for i = actornamescount,1,-1 
	do 

		actorname = actornames[i]
		if (actorname ~= nil) then

			minename2 = Map.NamedActor(actorname)
			-- Media.DisplayMessage (actorname .. "", "Mission", HSLColor.Red)
			extramine[i] = Actor.Create(unittocreate2, true, { Owner = Neutral, Location = minename2.Location})
			
		end
		i = i + 1
		
	end


end


Spawnants = function()
	extramine = {}
	for i = 26,1,-1 
	do 
		antname = "Ant" .. i
		antactor = Map.NamedActor(antname)


		if i < 18 then
			if i < 6 then
				extramine[i] = Actor.Create(createwarriorant, true, { Owner = Creeps, Stance = AttackAnything, Location = antactor.Location})
			else
				extramine[i] = Actor.Create(creategiantant, true, { Owner = Creeps, Stance = AttackAnything, Location = antactor.Location})
			end
		else
			extramine[i] = Actor.Create(createfireant, true, { Owner = Creeps, Stance = AttackAnything, Location = antactor.Location})
		end
		--Media.DisplayMessage (minename, "Mission", HSLColor.Red)
	end

		table.insert(messages, "Ants have escaped from the Bio Labs!")
		-- Media.DisplayMessage ("Ants have escaped from the Bio Labs!", "Mission", HSLColor.Red)
end

bioenabled = 0
if activeplayers[1].HasPrerequisites({"bio_enabled"}) 
then
	bioenabled = 1
	Biolabs()
	Spawnspyplanetemp()

	if (NuclearStrikes == "entry_1") then
		Spawnants() -- Not working right now
	end
end





--	if (Cappoints == "entry_off") then
--		Spawntrees()
--	else
--	
--		
--		if (Cappoints == "entry_1") then -- 1 x middle
--			Spawncom1()
--			--Spawnspyplanemiddle()
--		end
--		
--		if (Cappoints == "entry_1a") then -- 2 x middle
--			Spawncom2()
--			Spawntrees()
--			Spawnspyplanetemp()
--			--Spawnspyplanemiddle()
--		end
--		
--		if (Cappoints == "entry_2") then --middle + sides
--			Spawncom3()
--			--Spawnspyplanemiddle()
--			Spawnspyplanetemp()
--		end
--		
--		if (Cappoints == "entry_3") then --sides
--			Spawncom4()
--			Spawntrees()
--			Spawnspyplanetemp()
--		end
--	end


--count buildings

countbuildings = function(buildingtype, theplayer)
	local sams = theplayer.GetActorsByType(buildingtype)
	return #sams
end


debugactive = function()
	for i = activeplayerscount(),1,-1 
	do 
		playeractive = activeplayers[i]
		playername = playeractive.InternalName
		--Media.DisplayMessage (playername, "Mission", HSLColor.Red)
	end
end

checkbuildings = function()

	for i = activeplayerscount(),1,-1 
	do 
		mcvscount =0
		playeractive = activeplayers[i]
		playername = playeractive.InternalName
		
		for y = actorstoupdatecount,1,-1 
		do 
			buildingtype = actorstoupdate[y]


			--Media.DisplayMessage (playername, "Mission", HSLColor.Red)
			
			factorycount = countbuildings(buildingtype, playeractive)
			--factorycount = 11
			conditonname = buildingtype .. factorycount

			if (factorycount > 1) then
				if (factorycount < 8) then
					playeractive.GrantCondition(conditonname,1)
				else
					if (factorycount <= 9) then
						conditonname = buildingtype .. "8"
						playeractive.GrantCondition(conditonname,1)
					else
						if (factorycount <= 12) then
							conditonname = buildingtype .. "10"
							playeractive.GrantCondition(conditonname,1)
						else
							if (factorycount <= 15) then
								conditonname = buildingtype .. "13"
								playeractive.GrantCondition(conditonname,1)
							else
								if (factorycount <= 16) then
									conditonname = buildingtype .. "17"
									playeractive.GrantCondition(conditonname,1)
								else
									if (factorycount <= 24) then
										conditonname = buildingtype .. "21"
										playeractive.GrantCondition(conditonname,1)
									else
										conditonname = buildingtype .. "25"
										playeractive.GrantCondition(conditonname,1)
									end
								end
							end
						end
					end
				end
			end
			--Media.DisplayMessage ("Granted!" .. playername, "Mission", HSLColor.Red)

		--	Media.DisplayMessage (" Condition Name2 :  " .. conditonname, "Mission", HSLColor.Red)
		end
		--Media.DisplayMessage (playername .." Factories  " .. mcvscount, "Mission", HSLColor.Red)
	end

end


--toxicrules = Player.HasPrerequisites("toxic_enabled")
--toxicrules = Map.LobbyOption("toxicrules")


if toxic_enabled == 1
then 
	UserInterface.SetMissionText("TOXIC MODE ENABLED", HSLColor.Red)
	table.insert(messages, "WARNING: Original Toxic Rules, More Buildings = Faster Build Speed (25 for Maximum Speed)")
	table.insert(messagesloop, "REMINDER: Toxic Rules (25 of each building for Maximum Speed)")
		-- Media.DisplayMessage ("Toxic Rules Enabled. 25 buildings of each for max speed", "Mission", HSLColor.Red)
	enablechecking = 1
	--Spawnmines()
else
		table.insert(messages, "Poops BuildTimeSpeedReduction: 100, 70, 50, 40, 20, 10, 10, 5")
		-- Media.DisplayMessage ("Standard Rules apply for maximum build speed (4 War/7 other buildings)", "Mission", HSLColor.Red)
end



if (NuclearStrikes ~= "entry_1") then
	delayedtroopers()
	if bioenabled == 1 then
		Trigger.AfterDelay(DateTime.Seconds(30), function()
			Spawnants()
		end)
	end
else
	if (Cappoints ~= "entry_off") then
		delayedtroopers()
	end
end



--end war fact check
	
	----START OF AI REFINFORCEMENT CODE ---
	if UltimateBotsCount > 0 then
		

		-- MCVs on repeat
	Trigger.AfterDelay(DateTime.Seconds(30), function()

		if (difficulty == "noob" ) then
			timerDelay = 70
		elseif (difficulty == "easy") then
			timerDelay = 50
		elseif (difficulty == "normal") then
			timerDelay = 40
		else
			timerDelay = 30
		end

		sendRepeatWave(tierMcv,1,timerDelay/HandicapAdjustment)
	end) 

	--One off attacks
	Trigger.AfterDelay(DateTime.Seconds(110), function()
		Media.DisplayMessage( "Enemy Troops Inbound", "Mission", HSLColor.Red)
		if (difficulty == "noob") then
			sendAttackWave(tier0infantry,(15*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "easy") then
			sendAttackWave(tier0infantry,(20*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "normal") then
			sendAttackWave(tier0infantry,(30*HandicapAdjustment)*difficultyHandicap)
		else
			sendAttackWave(tier0infantry,(50*HandicapAdjustment)*difficultyHandicap)
		end
	end)


	Trigger.AfterDelay(DateTime.Seconds(220), function()
		Media.DisplayMessage( "Enemy Troops Inbound", "Mission", HSLColor.Red)
		if (difficulty == "noob") then
			sendAttackWave(tier0infantry,(10*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "easy") then
			sendAttackWave(tier0infantry,(15*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "normal") then
			sendAttackWave(tier0infantry,(20*HandicapAdjustment)*difficultyHandicap)
		else
			sendAttackWave(tier0infantry,(25*HandicapAdjustment)*difficultyHandicap)
		end
	end)

	Trigger.AfterDelay(DateTime.Seconds(330), function()
		Media.DisplayMessage( "Enemy Troops Inbound", "Mission", HSLColor.Red)
		if (difficulty == "easy" or difficulty == "noob") then
			sendAttackWave(tier0infantry,(60*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier1Tanks,(8*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "normal") then
			sendAttackWave(tier0infantry,(60*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier1Tanks,(8*HandicapAdjustment)*difficultyHandicap)
		else
			sendAttackWave(tier1infantry,(60*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(8*HandicapAdjustment)*difficultyHandicap)
		end
	end)

	Trigger.AfterDelay(DateTime.Seconds(420), function()
		--Start of Tank Waves
		Media.DisplayMessage( "Enemy Tanks Inbound", "Mission", HSLColor.Red)

		if (difficulty == "easy" or difficulty == "noob") then
			--Infantry
			sendAttackWave(tier1infantry,(80*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier1Tanks,(8*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(8*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "normal") then
			--Infantry
			sendAttackWave(tier1infantry,(90*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier1Tanks,(8*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(8*HandicapAdjustment)*difficultyHandicap)
		else
			--Infantry
			sendAttackWave(tier1infantry,(100*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(10*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier3Tanks,(10*HandicapAdjustment)*difficultyHandicap)
		end
		-- sendAttackWave(tier4Tanks,2*HandicapAdjustment)*difficultyHandicap)
	end)

	Trigger.AfterDelay(DateTime.Seconds(540), function()

		Media.DisplayMessage( "Enemy Tanks Inbound", "Mission", HSLColor.Red)

		if (difficulty == "easy" or difficulty == "noob") then
			--Infantry
			sendAttackWave(tier1infantry,(100*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2infantry,(4*HandicapAdjustment)*difficultyHandicap)
			--Tanks
			sendAttackWave(tier1Tanks,(6*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(6*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier3Tanks,(4*HandicapAdjustment)*difficultyHandicap)
			--sendAttackWave(tier4Tanks,(2*HandicapAdjustment)*difficultyHandicap)
		elseif (difficulty == "normal") then
			--Infantry
			sendAttackWave(tier1infantry,(100*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2infantry,(4*HandicapAdjustment)*difficultyHandicap)
			--Tanks
			sendAttackWave(tier1Tanks,(8*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(8*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier3Tanks,(6*HandicapAdjustment)*difficultyHandicap)
			--sendAttackWave(tier4Tanks,(2*HandicapAdjustment)*difficultyHandicap)
		else
			--Infantry
			sendAttackWave(tier1infantry,(120*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2infantry,(8*HandicapAdjustment)*difficultyHandicap)
			--Tanks
			sendAttackWave(tier1Tanks,(10*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier2Tanks,(8*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier3Tanks,(6*HandicapAdjustment)*difficultyHandicap)
			sendAttackWave(tier4Tanks,(4*HandicapAdjustment)*difficultyHandicap)
		end
		
	end)

	Trigger.AfterDelay(DateTime.Seconds(2), function()
		aiCash() -- Stream of cash for AI
		createHarv() -- If ran out of money then create Harvester
		createEngineers()
	end)



	doomsdayCountdown = 600

	if (difficulty == "noob") then
		continuousCountdown = 720
	elseif (difficulty == "easy" ) then
		continuousCountdown = 600
	elseif (difficulty == "normal") then
		continuousCountdown = 600
	elseif (difficulty == "extreme") then
		continuousCountdown = 480
		doomsdayCountdown = 480
	else
		doomsdayCountdown = 480
		continuousCountdown = 480
	end

	if toxic_enabled == 1 	then 
		continuousCountdown = continuousCountdown*0.6
		doomsdayCountdown = doomsdayCountdown*0.6
	end


	Trigger.AfterDelay(DateTime.Seconds(continuousCountdown), function()
		Media.DisplayMessage( "WARNING: Ultimate AI has ramped up production!", "Mission", HSLColor.Red)
		continuousProduction()
		Trigger.AfterDelay(DateTime.Seconds(doomsdayCountdown), function()
			UserInterface.SetMissionText("TOXIC MODE ENABLED - DOOMSDAY ACTIVATED", HSLColor.Red)
			Media.DisplayMessage( "WARNING: Doomsday Mode Has Been Activated, AI has MAXED production, you will not survive!", "Mission", HSLColor.Red)
			doomsdayenabled = 1
			HandicapAdjustment = HandicapAdjustment*1.25
		end)
	end)

setDifficulty()

end
----END OF AI REFINFORCEMENT CODE ---
		
rules()
rules2()

		Trigger.AfterDelay(DateTime.Seconds(2), function()
			setupRefs()
			-- Media.DisplayMessage( "Setup Refs", "Mission", HSLColor.Red)

			if (difficulty == "noob") then
				removeactors(getAllActors("gap.defend"))
			end
		end)

		--read the messages
		readmessages()
		
		loopcounter = 1
		Trigger.AfterDelay(5000, readmessagesloop)

		if UltimateBotsCount > 0 then
			Trigger.AfterDelay(DateTime.Seconds(2), function()
				AdjustmentLevel = difficultyHandicap*HandicapAdjustment*toxicAdjustment
				Media.DisplayMessage( "AI Difficulty Level "..AdjustmentLevel.." (Adjusted For Players/Difficulty)", "Mission", HSLColor.Red)
			end)
		end
--		if UltimateBotsCount > 0 then
--			Trigger.AfterDelay(DateTime.Seconds(2), function()
--				AdjustmentLevel = difficultyHandicap*HandicapAdjustment*toxicAdjustment
--				table.insert(messages, "AI Difficulty Level "..AdjustmentLevel.." (Adjusted For Players/Difficulty)")
--			end)
--		end



end


-- Ticks for checkbulidings

Tick = function()

	if (enablechecking > 0) then
		checkbuildings()
	end

end

