if Map.LobbyOption("difficulty") == "easy" then
	Rambo = "rmbo.easy"
elseif Map.LobbyOption("difficulty") == "hard" then
	Rambo = "rmbo.hard"
else
	Rambo = "rmbo"
end

WaypointGroup1 = { waypoint0, waypoint3, waypoint2, waypoint4, waypoint5, waypoint7 }
WaypointGroup2 = { waypoint0, waypoint3, waypoint2, waypoint4, waypoint5, waypoint6 }
WaypointGroup3 = { waypoint0, waypoint8, waypoint9, waypoint10, waypoint11, waypoint12, waypoint6, waypoint13 }
Patrol1Waypoints = { waypoint0.Location, waypoint8.Location, waypoint9.Location, waypoint10.Location }
Patrol2Waypoints = { waypoint0.Location, waypoint3.Location, waypoint2.Location, waypoint4.Location }

GDI1 = { units = { ['e2'] = 3, ['e3'] = 2 }, waypoints = WaypointGroup1, delay = 40 }
GDI2 = { units = { ['e1'] = 2, ['e2'] = 4 }, waypoints = WaypointGroup2, delay = 50 }
GDI4 = { units = { ['jeep'] = 2 }, waypoints = WaypointGroup1, delay = 50 }
GDI5 = { units = { ['mtnk'] = 1 }, waypoints = WaypointGroup1, delay = 40 }
Auto1 = { units = { ['e1'] = 2, ['e3'] = 3 }, waypoints = WaypointGroup3, delay = 40 }
Auto2 = { units = { ['e2'] = 2, ['e3'] = 2 }, waypoints = WaypointGroup3, delay = 50 }
Auto3 = { units = { ['e1'] = 3, ['e2'] = 2 }, waypoints = WaypointGroup2, delay = 60 }
Auto4 = { units = { ['mtnk'] = 1 }, waypoints = WaypointGroup1, delay = 50 }
Auto5 = { units = { ['mtnk'] = 1 }, waypoints = WaypointGroup3, delay = 50 }
Auto6 = { units = { ['e1'] = 2, ['e3'] = 2 }, waypoints = WaypointGroup3, delay = 50 }
Auto7 = { units = { ['msam'] = 1 }, waypoints = WaypointGroup1, delay = 40 }
Auto8 = { units = { ['msam'] = 1 }, waypoints = WaypointGroup3, delay = 50 }

RmboReinforcements = { Rambo }
EngineerReinforcements = { "e6", "e6" }
RocketReinforcements = { "e3", "e3", "e3", "e3" }

AutoAttackWaves = { GDI1, GDI2, GDI4, GDI5, Auto1, Auto2, Auto3, Auto4, Auto5, Auto6, Auto7, Auto8 }

NodBaseTrigger = { CPos.New(9, 52), CPos.New(9, 51), CPos.New(9, 50), CPos.New(9, 49), CPos.New(9, 48), CPos.New(9, 47), CPos.New(9, 46), CPos.New(10, 46), CPos.New(11, 46), CPos.New(12, 46), CPos.New(13, 46), CPos.New(14, 46), CPos.New(15, 46), CPos.New(16, 46), CPos.New(17, 46), CPos.New(18, 46), CPos.New(19, 46), CPos.New(20, 46), CPos.New(21, 46), CPos.New(22, 46), CPos.New(23, 46), CPos.New(24, 46), CPos.New(25, 46), CPos.New(25, 47), CPos.New(25, 48), CPos.New(25, 49), CPos.New(25, 50), CPos.New(25, 51), CPos.New(25, 52) }
EngineerTrigger = { CPos.New(5, 13), CPos.New(6, 13), CPos.New(7, 13), CPos.New(8, 13), CPos.New(9, 13), CPos.New(10, 13), CPos.New(16, 7), CPos.New(16, 6), CPos.New(16, 5), CPos.New(16, 4), CPos.New(16, 3)}
RocketTrigger = { CPos.New(20, 15), CPos.New(21, 15), CPos.New(22, 15), CPos.New(23, 15), CPos.New(24, 15), CPos.New(25, 15), CPos.New(26, 15), CPos.New(32, 15), CPos.New(32, 14), CPos.New(32, 13), CPos.New(32, 12), CPos.New(32, 11)}

GunboatPatrolPath = { GunboatLeft.Location, GunboatRight.Location }

AirstrikeDelay = DateTime.Minutes(2) + DateTime.Seconds(30)

CheckForSams = function(player)
	local sams = player.GetActorsByType("sam")
	return #sams >= 3
end

searches = 0
getAirstrikeTarget = function()
	local list = player.GetGroundAttackers()

	if #list == 0 then
		return
	end

	local target = list[DateTime.GameTime % #list + 1].CenterPosition

	local sams = Map.ActorsInCircle(target, WDist.New(8 * 1024), function(actor)
		return actor.Type == "sam" end)

	if #sams == 0 then
		searches = 0
		return target
	elseif searches < 6 then
		searches = searches + 1
		return getAirstrikeTarget()
	else
		searches = 0
		return nil
	end
end

SendAttackWave = function(team)
	for type, amount in pairs(team.units) do
		count = 0
		local actors = enemy.GetActorsByType(type)
		Utils.Do(actors, function(actor)
			if actor.IsIdle and count < amount then
				SetAttackWaypoints(actor, team.waypoints)
				IdleHunt(actor)
				count = count + 1
			end
		end)
	end
end

SetAttackWaypoints = function(actor, waypoints)
	if not actor.IsDead then
		Utils.Do(waypoints, function(waypoint)
			actor.AttackMove(waypoint.Location)
		end)
	end
end

SendGDIAirstrike = function(hq, delay)
	if not hq.IsDead and hq.Owner == enemy then
		local target = getAirstrikeTarget()

		if target then
			hq.SendAirstrike(target, false, Facing.NorthEast + 4)
			Trigger.AfterDelay(delay, function() SendGDIAirstrike(hq, delay) end)
		else
			Trigger.AfterDelay(delay/4, function() SendGDIAirstrike(hq, delay) end)
		end
	end
end

SendWaves = function(counter, Waves)
	if counter <= #Waves then
		local team = Waves[counter]
		SendAttackWave(team)
		Trigger.AfterDelay(DateTime.Seconds(team.delay), function() SendWaves(counter + 1, Waves) end)
	end
end

StartPatrols = function()
	local mtnks = enemy.GetActorsByType("mtnk")
	local msams = enemy.GetActorsByType("msam")

	if #mtnks >= 1 then
		mtnks[1].Patrol(Patrol1Waypoints, true, 20)
	end

	if #msams >= 1 then
		msams[1].Patrol(Patrol2Waypoints, true, 20)
	end
end

StartWaves = function()
	SendWaves(1, AutoAttackWaves)
end

Trigger.OnEnteredFootprint(NodBaseTrigger, function(a, id)
	if not nodBaseTrigger and a.Owner == player then
		nodBaseTrigger = true
		player.MarkCompletedObjective(NodObjective3)
		NodCYard.Owner = player

		local walls = nodBase.GetActorsByType("brik")
		Utils.Do(walls, function(actor)
			actor.Owner = player
		end)

		Trigger.AfterDelay(DateTime.Seconds(2), function()
			Media.PlaySpeechNotification(player, "NewOptions")
		end)
	end
end)

Trigger.OnEnteredFootprint(RocketTrigger, function(a, id)
	if not rocketTrigger and a.Owner == player then
		rocketTrigger = true
		player.MarkCompletedObjective(NodObjective1)

		Trigger.AfterDelay(DateTime.Seconds(5), function()
			Media.PlaySpeechNotification(player, "Reinforce")
			Reinforcements.ReinforceWithTransport(player, 'tran.in', RocketReinforcements, { HelicopterEntryRocket.Location, HelicopterGoalRocket.Location }, { HelicopterEntryRocket.Location }, nil, nil)
		end)

		Trigger.AfterDelay(DateTime.Seconds(10), function()
			FlareEngineerCamera1 = Actor.Create("camera", true, { Owner = player, Location = FlareEngineer.Location })
			FlareEngineerCamera2 = Actor.Create("camera", true, { Owner = player, Location = CameraEngineerPath.Location })
			FlareEngineer = Actor.Create("flare", true, { Owner = player, Location = FlareEngineer.Location })
		end)

		Trigger.AfterDelay(DateTime.Minutes(1), function()
			FlareRocketCamera.Destroy()
			FlareRocket.Destroy()
		end)
	end
end)

Trigger.OnEnteredFootprint(EngineerTrigger, function(a, id)
	if not engineerTrigger and a.Owner == player then
		engineerTrigger = true
		player.MarkCompletedObjective(NodObjective2)

		Trigger.AfterDelay(DateTime.Seconds(5), function()
			Media.PlaySpeechNotification(player, "Reinforce")
			Reinforcements.ReinforceWithTransport(player, 'tran.in', EngineerReinforcements, { HelicopterEntryEngineer.Location, HelicopterGoalEngineer.Location }, { HelicopterEntryEngineer.Location }, nil, nil)
		end)

		Trigger.AfterDelay(DateTime.Minutes(1), function()
			FlareEngineerCamera1.Destroy()
			FlareEngineerCamera2.Destroy()
			FlareEngineer.Destroy()
		end)
	end
end)

Trigger.OnKilledOrCaptured(OutpostProc, function()
	if not outpostCaptured then
		outpostCaptured = true

		if OutpostProc.IsDead then
			player.MarkFailedObjective(NodObjective4)
		else
			player.MarkCompletedObjective(NodObjective4)
			player.Cash = 1000
		end

		StartPatrols()

		Trigger.AfterDelay(DateTime.Minutes(1), function() StartWaves() end)
		Trigger.AfterDelay(AirstrikeDelay, function() SendGDIAirstrike(GDIHQ, AirstrikeDelay) end)
		Trigger.AfterDelay(DateTime.Minutes(3), function() ProduceInfantry(GDIPyle) end)
		Trigger.AfterDelay(DateTime.Minutes(3), function() ProduceVehicle(GDIWeap) end)
	end
end)

Trigger.OnKilled(Gunboat, function()
	GunboatCamera.Destroy()
end)

WorldLoaded = function()
	player = Player.GetPlayer("Nod")
	enemy = Player.GetPlayer("GDI")
	nodBase = Player.GetPlayer("NodBase")

	Camera.Position = CameraIntro.CenterPosition
	Media.PlaySpeechNotification(player, "Reinforce")
	Reinforcements.ReinforceWithTransport(player, 'tran.in', RmboReinforcements, { HelicopterEntryRmbo.Location, HelicopterGoalRmbo.Location }, { HelicopterEntryRmbo.Location }, nil, nil)
	FlareRocketCamera = Actor.Create("camera", true, { Owner = player, Location = FlareRocket.Location })
	FlareRocket = Actor.Create("flare", true, { Owner = player, Location = FlareRocket.Location })

	StartAI(GDICYard)
	AutoGuard(enemy.GetGroundAttackers())

	GunboatCamera = Actor.Create("camera.boat", true, { Owner = player, Location = Gunboat.Location })
	Trigger.OnIdle(Gunboat, function() Gunboat.Patrol(GunboatPatrolPath) end)

	Trigger.OnObjectiveAdded(player, function(p, id)
		Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective")
	end)

	Trigger.OnObjectiveCompleted(player, function(p, id)
		Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed")
	end)

	Trigger.OnObjectiveFailed(player, function(p, id)
		Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed")
	end)

	Trigger.OnPlayerWon(player, function()
		Media.PlaySpeechNotification(player, "Win")
	end)

	Trigger.OnPlayerLost(player, function()
		Media.PlaySpeechNotification(player, "Lose")
	end)

	NodObjective1 = player.AddPrimaryObjective("Secure the first landing zone.")
	NodObjective2 = player.AddPrimaryObjective("Secure the second landing zone.")
	NodObjective3 = player.AddPrimaryObjective("Locate the Nod base.")
	NodObjective4 = player.AddPrimaryObjective("Capture the refinery.")
	NodObjective5 = player.AddPrimaryObjective("Eliminate all GDI forces in the area.")
	NodObjective6 = player.AddSecondaryObjective("Build 3 SAMs to fend off the GDI bombers.")
	GDIObjective = enemy.AddPrimaryObjective("Eliminate all Nod forces in the area.")
end

Tick = function()
	if not Gunboat.IsDead then
		GunboatCamera.Teleport(Gunboat.Location)
	end

	if DateTime.GameTime > 2 and player.HasNoRequiredUnits() then
		enemy.MarkCompletedObjective(GDIObjective)
	end

	if DateTime.GameTime > 2 and enemy.HasNoRequiredUnits() then
		player.MarkCompletedObjective(NodObjective5)
	end

	if not player.IsObjectiveCompleted(NodObjective6) and CheckForSams(player) then
		player.MarkCompletedObjective(NodObjective6)
	end
end
