--Copyright Melons 2022, ask permission before use. (Fuck you!)


-- Ultimate AI Functions Start
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(1), function()
        Media.DisplayMessage ("Loading background noise, hang on...", "Pacman", HSLColor.Red)
        Trigger.AfterDelay(DateTime.Seconds(3), function()
            Media.PlaySound("war.aud")
            Trigger.AfterDelay(DateTime.Seconds(3), function()
                Media.DisplayMessage ("Welcome to the WW3 mod v2.0.6", "Waggy", HSLColor.Red)
                Trigger.AfterDelay(DateTime.Seconds(8), function()
                    Media.DisplayMessage ("Make Pacman President!", "Clyde", HSLColor.Brown)
                    Trigger.AfterDelay(DateTime.Seconds(1), function()
                        Media.PlaySound("laugh.aud")
                        Trigger.AfterDelay(DateTime.Seconds(16), function()
                            Media.DisplayMessage ("Special thanks to the map creator & ERCC creators. GLHF!", "Waggy", HSLColor.Green)
                            Trigger.AfterDelay(DateTime.Seconds(130), function()
                                Media.PlaySound("output.aud")
                                Trigger.AfterDelay(DateTime.Seconds(5), function()
                                    Media.PlaySound("war.aud")
                                    Trigger.AfterDelay(DateTime.Seconds(130), function()
                                        Media.PlaySound("output.aud")
                                        Trigger.AfterDelay(DateTime.Seconds(5), function()
                                            Media.PlaySound("war.aud")
                                            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("war.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

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", "e6", "thf" }
						else
							toProduceTanks = { "e1", "e1", "e1", "e3", "e1", "e1", "e1", "e3", "e6", "thf"  }
						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)
						if (randomTank == "e6") then 
							--Trigger.AfterDelay(DateTime.Seconds(3), function()
								sendEngineerNextTarget(theTank)
							--end)
						end
						countLimit = countLimit+1
					end
				end)
				quantity = quantity -1
			end
			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" }
						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"}
								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", "v3rl", "ectnk", "apoc", "isu", "ttnk2", "msam", "hftk","ftnk", "ctrk", "katy", "batf", "tnkd", "ptnk", "sherman", "panzer", "rtnk"}
								--toProduceTanks = { "v3rl", "ectnk", "apoc", "isu", "ttnk2", "msam", "hftk","ftnk", "ctrk", "katy", "batf", "tnkd", "ptnk", "sherman", "panzer", "rtnk"}
							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", "v3rl", "ectnk", "apoc", "isu", "ttnk2", "msam", "hftk","ftnk", "ctrk", "katy", "batf", "tnkd", "ptnk", "sherman", "panzer", "rtnk"}
							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)

						--if (randomTank == "ant40") 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" }
						--	--actorToTarget = {"1tnk","2tnk","3tnk","4tnk","ant40","apache","apc","apoc","arty","batf","ca","ctrk","dd","dog","douglas","e1","e2","e3","e4","ectnk","ftnk","ftrk","harr","harv","heli","hftk","hind","isu","jeep","katy","kirov","mcv","mh60","mig","msam","msub","panzer","pt","ptnk","rtnk","sherman","shok","ss","stnk","suk","tnkd","ttnk","ttnk2","v2rl","v3rl","yak" }
						--	unitToTarget = findClosestTargetAi(theTank, actorToTarget)
						--	if unitToTarget ~= nil then
						--		--unit.stop()
						--		--Media.DisplayMessage("Per building: Type: "..theTank.Type.." Loc: "..theTank.Location.X..","..theTank.Location.Y , "Mission", HSLColor.Red);
						--		--Media.DisplayMessage("Goto: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
						--		--theTank.AttackMove(unitToTarget.Location,10)
						--		theTank.AttackMove(unitToTarget.Location)
						--		--theTank.Attack(unitToTarget.Location)
						--		IdleHunt(theTank)
						--	end
						--end
						countLimit = countLimit+1
					end
				end)
				quantity = quantity -1

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

function spawnUnits(spawnUnitType, spawnUnitOwner, spawnUnitLocation, spawnTime)
	--Message = "Spawning Unit:"..spawnUnitType.." After: "..spawnTime
	--Media.DisplayMessage(""..Message, "Mission", HSLColor.Red)
	theActor = Actor.Create(spawnUnitType, true, { Owner = spawnUnitOwner, Location =  spawnUnitLocation});

	--if (spawnUnitType == "ant40") then 
	--	--actorToTarget = {"1tnk","2tnk","3tnk","4tnk","ant40","apache","apc","apoc","arty","batf","ca","ctrk","dd","dog","douglas","e1","e2","e3","e4","ectnk","ftnk","ftrk","harr","harv","heli","hftk","hind","isu","jeep","katy","kirov","mcv","mh60","mig","msam","msub","panzer","pt","ptnk","rtnk","sherman","shok","ss","stnk","suk","tnkd","ttnk","ttnk2","v2rl","v3rl","yak" }
	--	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" }
	--	unitToTarget = findClosestTargetAi(theActor,actorToTarget)
	--	if unitToTarget ~= nil then
	--		--theActor.stop()
	--		--Media.DisplayMessage("SpawnUnits: Type: "..theActor.Type.." Loc: "..theActor.Location.X..","..theActor.Location.Y , "Mission", HSLColor.Red);
	--		--Media.DisplayMessage("Move: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
	--		theActor.AttackMove(unitToTarget.Location)
	--		--IdleHunt(theActor)
	--		--theActor.Attack(unitToTarget.Location)
	--		--theActor.Move(unitToTarget.Location,10)
	--	end
	--end
	if (spawnUnitType == "e6") then 
		--Trigger.AfterDelay(DateTime.Seconds(3), function()
			sendEngineerNextTarget(theActor)
		--end)
	end

	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 spawnUnits2(spawnUnitType, spawnUnitOwner, spawnUnitLocation, spawnTime)
	--Message = "Unit:"..spawnUnitType.." After: "..spawnTime
	--Media.DisplayMessage(""..Message, "Mission", HSLColor.Red)
	if (spawnUnitType == "dtrk") then
		spawnTime=spawnTime*4
	end
	Trigger.AfterDelay(DateTime.Seconds(spawnTime), function()
		spawnUnits(spawnUnitType, spawnUnitOwner, spawnUnitLocation, spawnTime)
	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(-1,-1)

				while quantityToProduce > 0 do
					randomUnit = Utils.RandomInteger(1,#unitsTier+1)
					pTime = quantityToProduce*2 + z/50
					--Message = "TIMING: Nr. "..z.." Player: "..playersingame[z].." #"..quantityToProduce.." Unit:"..unitsTier[randomUnit].." After: "..pTime
					--Media.DisplayMessage(""..Message, "Mission", HSLColor.Red)

					spawnUnits2(unitsTier[randomUnit],thePlayer, currentSpawn, pTime)

					--Trigger.AfterDelay(DateTime.Seconds(quantityToProduce*3 + z/50), function()
						--Message = "ACTIVATING: Nr. "..z.." Player: "..playersingame[z].." #"..quantityToProduce.." Unit:"..unitsTier[randomUnit].." After: "..pTime
						--Media.DisplayMessage(""..Message, "Mission", HSLColor.Red)
						--spawnUnits(unitsTier[randomUnit],thePlayer, currentSpawn)
					--end)


					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

			num = #thePlayers()
--			Media.DisplayMessage(""..num, "thePlayers()", HSLColor.Red)
--
			if (num == 0) then
				num = 7
			end
			for i = num,1,-1
			do
				Trigger.AfterDelay(DateTime.Seconds(1+10*i), function()
--					Media.DisplayMessage(""..i, "Engineer", HSLColor.Red)
					--if (tanktypes == "demolition") then 
					--	sendAttackWave(tierDemolition,10)
					--end
					sendAttackWave(tierEngineers,1)
					sendAttackWave(tierThief,1)
					sendAttackWave(tierSpy,1)
--					sendAttackWave(tierEngineers,num)
				end)
			end

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

			Trigger.AfterDelay(DateTime.Seconds(5), function()
				--if (tanktypes == "demolition") then 
				--	sendDemolition()
				--end
				sendEngineers()
				sendThief()
				sendSpy()
				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" }

				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)
--					sendThief()
--					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)
--					end


				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


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)
			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,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)
				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 showNeutral()
	local actorTypes = { "proc", "ectnk" }
    local actors = Neutral.GetActorsByTypes(actorTypes);
    --local actors = Neutral.GetActors();
    for rr, actor in ipairs(actors) do
		Media.DisplayMessage(actor.Type, "Mission", HSLColor.Red)
    end
end


function findRandomTargetAi(searchActor, actorTypes)
     closestActor = nil
     distnceCloset = 250000;
	        
    --for rr, enemyPlayer in ipairs(AllPlayers) do
    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);
               if (actors ~= nil) then 
                  closestActor=Utils.Random(actors)
               end
            end
        end
    end
    --DUH
    if (closestActor == nil) then 
       for rr, enemyPlayer in ipairs(AllBots) do
	        if enemyPlayer ~= searchActor.Owner then
	            if enemyPlayer.Team ~= searchActor.EffectiveOwner.Team or enemyPlayer.Team == 0 or searchActor.EffectiveOwner.Team == 0 then
	               local actors = enemyPlayer.GetActorsByTypes(actorTypes);
	               if (actors ~= nil) then 
	                  closestActor=Utils.Random(actors)
	               end
	            end
	        end
       end
    end
    if (closestActor == nil) then 
		Media.DisplayMessage("No target: Type: "..searchActor.Type.." Loc: "..searchActor.Location.X..","..searchActor.Location.Y , "Mission", HSLColor.Red);
	else 
		Media.DisplayMessage("Random Target: Type: "..closestActor.Type.." Loc: "..closestActor.Location.X..","..closestActor.Location.Y , "Mission", HSLColor.Red);
		Media.DisplayMessage("Found: Type: "..searchActor.Type.." Loc: "..searchActor.Location.X..","..searchActor.Location.Y , "Mission", HSLColor.Red);
    end
    return closestActor;
end

function findClosestTargetAi(searchActor, actorTypes)
     closestActor = nil
     distnceCloset = 250000;
    
    --for rr, enemyPlayer in ipairs(AllPlayers) do
    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
    --DUH
    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
    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


function destroyNeutral(actorTypes)
    local actors = Neutral.GetActorsByTypes(actorTypes);
    closestActor = nil
    distnceCloset = 250000;
	mid = CVec.New(112,112)

    for rr, actor in ipairs(actors) do
        theDistance = actor.Location - mid;
        distanceMath = math.sqrt((theDistance.X * theDistance.X) + (theDistance.Y * theDistance.Y));
        if distanceMath <= distnceCloset then
            distnceCloset = distanceMath;
            closestActor = actor;
        end
	end


	if (closestActor ~= nil) then
	    Location = closestActor.Location
	    Type = closestActor.Type
		--Media.DisplayMessage("Destroy: "..Type.." At: ("..Location.X..","..Location.Y..")", "Sweapteam", HSLColor.Red)
	    closestActor.Destroy()
	    --spawnLater(closestActor)
		Trigger.AfterDelay(DateTime.Seconds(0.5), function()
		    destroyNeutral(actorTypes)
		end)
	end
end

function spawnLater(actor)
	local Type = actor.Type
	local Location = actor.Location
	local initial = {Owner = Creeps, Location = Location}

	Trigger.AfterDelay(DateTime.Seconds(5.0), function()
		--Media.DisplayMessage("CREATE: "..Type, "Sweapteam", HSLColor.Red)
		--Media.DisplayMessage("CREATE: "..Type.." At: ("..initial.Location.X..","..initial.Location.Y..")", "Sweapteam", HSLColor.Red)
		ShockDrop = Actor.Create(Type, true, initial)
--		if (Type == "htur") then
--			mid = CVec.New(112,112)
--	    	dir = (Location - mid)
--			ShockDrop.TargetParatroopers(mid, dir.facing)
--		end
	end)
end

--send engineers to cap middle
function sendEngineers()
	for z, thePlayer in ipairs(AIPlayers) do
        local engineers = thePlayer.GetActorsByType("e6");
		--Media.DisplayMessage("sendEngineers", "Sweapteam", HSLColor.Red)
		Utils.Do(engineers, function(unit)
			--if (unit.IsIdle) 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" }
				unitToTarget = findClosestTargetAiNeutral(unit,actorToTarget)

				if unitToTarget ~= nil then
					--Media.DisplayMessage("INFILTRATE: Type: "..unitToTarget.Type, "Mission", HSLColor.Red);
					--sendEngineerNextTarget(unit)
					--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)
					--Trigger.OnObjectiveCompleted(player, function(p, id)
					--	Media.DisplayMessage(p.GetObjectiveDescription(id), UserInterface.Translate("objective-completed"))
					--end)	
					--Trigger.OnObjectiveCompleted(unit, function(p, id)
					--	Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed")
					--end)				
					--trigger.OnObjectiveCompleted(unit, function(p, id)
					--	Media.DisplayMessage("ObjectiveCompleted", p.GetObjectiveDescription(id), "Mission", HSLColor.Red)
					--	if not p.IsDead then
					--		--Media.DisplayMessage("CAPTURED: Type: "..unit.Type.." Loc: "..unit.Location.X..","..unit.Location.Y , "Mission", HSLColor.Red);
					--		sendEngineerNextTarget(p)
					--	end
					--end)
					--Trigger.OnCapture(unitToTarget, function()
					----	Media.DisplayMessage ("CAPTURED", "Mission", HSLColor.Red)
					--	if not unit.IsDead then
					--		--Media.DisplayMessage("CAPTURED: Type: "..unit.Type.." Loc: "..unit.Location.X..","..unit.Location.Y , "Mission", HSLColor.Red);
					--		sendEngineerNextTarget(unit)
					--	end
					--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 sendDemolition()
--	for z, thePlayer in ipairs(AIPlayers) do
--        local dtrk = thePlayer.GetActorsByType("dtrk");
--		Media.DisplayMessage("sendDemolition", "Sweapteam", HSLColor.Red)
--		Utils.Do(dtrk, function(unit)
--			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" }
--			--actorToTarget = {"1tnk","2tnk","3tnk","4tnk","ant40","apache","apc","apoc","arty","batf","ca","ctrk","dd","dog","douglas","e1","e2","e3","e4","ectnk","ftnk","ftrk","harr","harv","heli","hftk","hind","isu","jeep","katy","kirov","mcv","mh60","mig","msam","msub","panzer","pt","ptnk","rtnk","sherman","shok","ss","stnk","suk","tnkd","ttnk","ttnk2","v2rl","v3rl","yak" }
--
--			unitToTarget = findRandomTargetAi(unit,actorToTarget)
--
--			if unitToTarget ~= nil then
--				Media.DisplayMessage("Demolition: Type: "..unit.Type.." Loc: "..unit.Location.X..","..unit.Location.Y , "Mission", HSLColor.Red);
--				Media.DisplayMessage("Goto: Type: "..unitToTarget.Type.." Loc: "..unitToTarget.Location.X..","..unitToTarget.Location.Y , "Mission", HSLColor.Red);
--				unit.Move(unitToTarget.Location,10)
--				--unit.AttackMove(unitToTarget.Location,10)
--				--IdleHunt(unit)
--			end
--		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

function attackAll()
	Media.DisplayMessage ("Attack? ", "Mission", HSLColor.Red)
	for z, thePlayer in ipairs(AIPlayers) do
		--if (Utils.RandomInteger(1,10) == 0) then
	        local theUnits = thePlayer.GetActors();
			Media.DisplayMessage ("YES: "..z, "Mission", HSLColor.Red)

			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)
						theActor.AttackMove(unitToTarget,10)
					end
				end)
			end
		--end
	end
end	

--Tanks every 60s
function continuousProductionTanks()
	--attackAll()
	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 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


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

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,15)
					
				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


	function getAllCreeps()

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

	end

	--Remove Boxes in Table
	function removeactors(a)
		Utils.Do(a, function(unit)
			unit.Destroy()
		end)
		return 
	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(42,64))
Nuker.ActivateNukePower(CPos.New(58,64))
Nuker.ActivateNukePower(CPos.New(50,64)) 
Nuker.ActivateNukePower(CPos.New(50,70))
Nuker.ActivateNukePower(CPos.New(50,57))
Nuker.ActivateNukePower(CPos.New(14,64)) -- Left
Nuker.ActivateNukePower(CPos.New(83,64)) -- Right 

--[[]
			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))
			Nuker.ActivateNukePower(CPos.New(12,64)) -- Left
			Nuker.ActivateNukePower(CPos.New(115,64)) -- Right 
			]]
			--delayedparabombs()
			delayedlaunch()
end

delayedtroopers = function()
	Trigger.AfterDelay(DateTime.Seconds(25), 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
				UserInterface.SetMissionText("TOXIC MODE ENABLED", HSLColor.Red)
			end
		end
	end)
end


WorldLoaded = function()
	
Neutral = Player.GetPlayer("Neutral")
--showNeutral()

Creeps = Player.GetPlayer("Creeps") 
Cappoints = Map.LobbyOption("Cappoints")
NuclearStrikes = Map.LobbyOption("NuclearStrikes")
toxic_enabled = 0
enablechecking = 0
bioenabled = 0
playersingame = {"Multi0","Multi1","Multi2","Multi3","Multi4","Multi5","Multi6","Multi7","Multi8","Multi9","Multi10","Multi11"} -- Table of Potential Players
actorstoupdate = {"fact","weap","tent","barr","hpad","afld","afld.ukraine","kenn","spen","syrd"}
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

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

HandicapAdjustment = #thePlayers()/4
--HandicapAdjustment = (#thePlayers()-UltimateBotsCount)/(4)

HumansCount = #theHumans()
ToxicHandicap = 1
		
tierEngineers = { "e6", "e6", "e6", "e6"}
tierDemolition = { "dtrk", "dtrk", "dtrk", "dtrk"}
tierThief = { "thf", "thf", "thf", "thf"}
tierSpy = { "spy", "spy", "spy", "spy"}
--tier1Tanks = { "jeep", "apc", "1tnk", "ftrk"}
tier1Tanks = { "jeep", "apc", "1tnk", "ftrk", "mig", "yak", "heli", "hind"}
--tier1Tanks = { "ant40", "ant40", "ant40", "ant40" }
tier2Tanks = { "v2rl", "2tnk", "arty", "mgg", "mrj", "ttnk", "mh60", "suk", "harr", "apache", "kirov", "ant40"} --, "douglas"
tier3Tanks = { "3tnk", "mrj", "ctnk", "stnk", "v3rl", "ectnk", "apoc", "isu", "ttnk2", "msam", "hftk", "ftnk", "ctrk", "katy", "batf", "tnkd", "ptnk", "sherman", "panzer", "rtnk", "kirov", "ant40", "kirov", "ant40" }
tier4Tanks = { "4tnk", "3tnk", "mrj", "dtrk", "ctnk", "stnk", "ftrk", "kirov", "ant40"}
tier0infantry = {"e1"}
tier1infantry = { "e1", "medi", "dog", "e1", "e2", "e3", "e3r1", "e4", "mech", "gnrl", "shok" }
tier2infantry = { "spy", "thf" }
tier3infantry = { "e7", "sniper"}
tierMcv = { "mcv"}

if (tanktypes == "demolition") then 
	tier1Tanks = { "dtrk" }
	tier2Tanks = { "dtrk" }
	tier3Tanks = { "dtrk" }
	tier4Tanks = { "dtrk" }
end

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




for i = playersingamecount,1,-1 
do 
	playername = playersingame[i]
	if (Player.GetPlayer(playername) ~= nil) then
		playerinfo = Player.GetPlayer(playername)
		activeplayers[z] = Player.GetPlayer(playername)
		z = z + 1
		i = i + 1
	end
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, spymiddle.CenterPosition, 500)
				Radar.Ping(playeractive, spymiddle.CenterPosition, HSLColor.Aqua, 500)
			end
	end)
end
	

Spawnspyplanemiddle = function()
			for i = activeplayerscount(),1,-1 
			do 
				playeractive = activeplayers[i]
				playername = playeractive.InternalName
				spyplanemiddle1 = Actor.Create(unittocreatespyplane2, 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 = ComLeft.Location})
				tempspyplane2 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = ComRight.Location})
				tempspyplane3 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = BioDown.Location})
				tempspyplane4 = Actor.Create(unittocreatespyplane1, true, { Owner = playeractive, Location = BioUp.Location})
				spyplanemiddle2.Destroy()
				tempspyplane1.Destroy()
				tempspyplane2.Destroy()
				tempspyplane3.Destroy()
				tempspyplane4.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 })

--Spawn Units

unittocreate = "miss"
unittocreate2 = "gmine"
unittocreate3 = "POWR"
unittocreatebio = "bio"
unittocreatetree1 = "tc05"
unittocreatetree2 = "t05"
unittocreatespyplane1 = "camera.spyplane"
unittocreatespyplane2 = "camera.spyplane2"
createwarriorant = "warriorant"
createfireant = "fireant"
creategiantant = "ant"
Createtreehusk1 = "tc01.husk"
Createtreehusk2 = "t08.husk"


-- 1 x Middle 
Spawncom1 = function()
	comcentre1 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComMiddle.Location})
	--combotmid = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComMiddleBottom.Location})
end

-- Sides
Spawncom2 = function() 
	comcentre1 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComLeft.Location})
	comcentre2 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComRight.Location})
end

-- 1 x Middle + Sides
Spawncom3 = function() 
	comcentre1 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComLeft.Location})
	comcentre2 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComMiddle.Location})
	comcentre3 = Actor.Create(unittocreate, true, { Owner = Neutral, Location = ComRight.Location})
end

----trees for middle
--Spawntrees = function()
--	--tree1 = Actor.Create(Createtreehusk1, true, { Owner = Neutral, Location = tc05left.Location})
--	--tree2 = Actor.Create(Createtreehusk2, true, { Owner = Neutral, Location = tc05right.Location})
--	--tree3 = Actor.Create(unittocreatetree2, true, { Owner = Neutral, Location = tc02middle.Location})
--
--	trees = {}
--	for i = 4,1,-1 
--	do 
--		treename = "Tree" .. i
--			if i < 3 then
--				trees[i] = Actor.Create(unittocreatetree1, true, { Owner = Neutral, Location = _G[treename].Location})
--			else
--				trees[i] = Actor.Create(unittocreatetree2, true, { Owner = Neutral, Location = _G[treename].Location})
--			end
--		--Media.DisplayMessage (minename, "Mission", HSLColor.Red)
--	end
--
--
--end

--Bio Labs for middle
Biolabs = function()
	biolab1 = Actor.Create(unittocreatebio, true, { Owner = Neutral, Location = BioUp.Location})
	biolab2 = Actor.Create(unittocreatebio, true, { Owner = Neutral, Location = BioDown.Location})
	table.insert(messages, "WARNING: Bio Labs Enabled")
		-- Media.DisplayMessage ("WARNING: Bio Labs Enabled", "Mission", HSLColor.Red)
end

Spawnmines = function()
	extramine = {}
	for i = 143,116,-1 
	do 
		minename = "Tmine" .. i
		if _G[minename] then
		extramine[i] = Actor.Create(unittocreate2, true, { Owner = Neutral, Location = _G[minename].Location})
		--Media.DisplayMessage (minename, "Mission", HSLColor.Red)
		end
	end
end

Spawnants = function()
	extramine = {}
	for i = 56,20,-1 
	do 
		antname = "Ant1" .. i
		--Media.DisplayMessage (antname, "Mission", HSLColor.Red)
		if i < 35 then
			if i < 30 then
				extramine[i] = Actor.Create(createwarriorant, true, { Owner = Creeps, Stance = AttackAnything, Location = _G[antname].Location})
			else
				extramine[i] = Actor.Create(creategiantant, true, { Owner = Creeps, Stance = AttackAnything, Location = _G[antname].Location})
			end
		else
			extramine[i] = Actor.Create(createfireant, true, { Owner = Creeps, Stance = AttackAnything, Location = _G[antname].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

if activeplayers[1].HasPrerequisites({"bio_enabled"}) 
then
	bioenabled = 1
	Biolabs()
	Spawnspyplanetemp()
	if (NuclearStrikes == "entry_1") then
		Spawnants()
	end
end


--if (Cappoints == "entry_off") then
--	Spawntrees()
--	Spawnspyplanetemp()
--else
--	if (Cappoints == "entry_1") then -- Middle
--		Spawncom1()
--		Spawnspyplanemiddle()
--		Spawnspyplanetemp()
--	end
--	
--	if (Cappoints == "entry_2") then --  Sides
--		Spawncom2()
--		Spawntrees()
--		Spawnspyplanetemp()
--	end
--	
--	if (Cappoints == "entry_3") then --  Middle + Sides
--		Spawncom3()
--		Spawnspyplanemiddle()
--		Spawnspyplanetemp()
--		--Spawntrees()
--	end
--end


--count buildings

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


checkbuildings = function()

	for i = activeplayerscount(),1,-1 
	do 
		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
	end
end

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

if toxic_enabled == 1
then 
		table.insert(messages, "Toxic Rules Enabled. 25 buildings of each for max speed")
		-- Media.DisplayMessage ("Toxic Rules Enabled. 25 buildings of each for max speed", "Mission", HSLColor.Red)
	enablechecking = 1
	--Spawnmines()
else
		--table.insert(messages, "BuildTimeSpeedReduction: 100, 80, 67, 55, 45, 37, 30, 25, 21, 18, 16, 14, 12, 10")
		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

	Tick = function()
		if enablechecking > 0 then
			checkbuildings()
		end
	end

--end war fact check
rules()
rules2()

	----START OF AI REFINFORCEMENT CODE ---
-- Media.DisplayMessage ("Ultimate Bots  " .. UltimateBotsCount, "Mission", HSLColor.Red) --display total of players
	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)
					sendAttackWave(tier3infantry,(1*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
			end)
			Trigger.AfterDelay(DateTime.Seconds(5), function()
				createEngineers()
			end)
		
		
		
			if (difficulty == "noob") then
				continuousCountdown = 720
			elseif (difficulty == "easy" ) then
				continuousCountdown = 600
			elseif (difficulty == "normal") then
				continuousCountdown = 600
			else
				continuousCountdown = 480
			end
		
				Trigger.AfterDelay(DateTime.Seconds(continuousCountdown), function()
					Media.DisplayMessage( "WARNING: Ultimate AI has ramped up production!", "Mission", HSLColor.Red)
					continuousProduction()
				end)
		
			setDifficulty()
	end
		----END OF AI REFINFORCEMENT CODE ---
		
		Trigger.AfterDelay(DateTime.Seconds(2), function()
			setupRefs()


		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

Trigger.AfterDelay(2, function()
	Media.DisplayMessage("Destroying Neutral", "Sweapteam", HSLColor.Red)
	destroyNeutral({ "embsy","adept","hosp","miss" })

--	destroyNeutral({ "powr", "apwr", "htur" })
end)

end

