
-- Time, Actor, Text, Duration, Color
InitialSpeechTexts =
{
	{ DateTime.Seconds(5), General, "OK everyone! Come here", DateTime.Seconds(2), HSLColor.Aqua },
	{ DateTime.Seconds(8), General, "We are *here* on the map", DateTime.Seconds(2), HSLColor.Aqua },
	{ DateTime.Seconds(12), General, "and the Research Center is Northea-", DateTime.Seconds(2), HSLColor.Aqua },
	{ DateTime.Seconds(14), Civ8, "I can't see it, the map is too small...", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(16), Civ3, "Don't you have a bigger map?", DateTime.Seconds(2), HSLColor.Fuchsia },
	{ DateTime.Seconds(18), Civ7, "YEAH BIGGER MAP!!1!", DateTime.Seconds(2), HSLColor.DarkOrange },
	{ DateTime.Seconds(19), Civ2, "Yeah!", DateTime.Seconds(2), HSLColor.LawnGreen },
	{ DateTime.Seconds(20), General, "SHUT UP!", DateTime.Seconds(2), HSLColor.Aqua },
	{ DateTime.Seconds(22), General, "Follow me Northeast!", DateTime.Seconds(2), HSLColor.Aqua }
}

MovedTenCellsTexts =
{
	{ DateTime.Seconds(2), Civ4, "How are your RAGL games going?", DateTime.Seconds(2), HSLColor.LawnGreen },
	{ DateTime.Seconds(5), Civ5, "Lost everything...", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(8), Civ4, "Bummer...", DateTime.Seconds(2), HSLColor.LawnGreen },
}

HalfWayMovedSound = "mentalward.wav"
HalfWayMovedTexts =
{
	{ DateTime.Seconds(3), Civ6, "W-w-what is that?", DateTime.Seconds(2), HSLColor.Fuchsia },
	{ DateTime.Seconds(11), Civ7, "I'm scared!", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(15), Civ2, "I'm SoScared!", DateTime.Seconds(2), HSLColor.LightCyan },
}

MoreThanHalfMovedTexts =
{
	{ DateTime.Seconds(1), Civ6, "NAZGÛÛÛÛÛLLL!!", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(3), Civ3, "What!? Where??", DateTime.Seconds(2), HSLColor.Fuchsia },
	{ DateTime.Seconds(5), Civ6, "jk lulz", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(7), Civ3, "dickhead...", DateTime.Seconds(2), HSLColor.Fuchsia },
}

ThreefourhtsMovedTexts =
{
	{ DateTime.Seconds(4), Civ2, "I feel like something is watching us...", DateTime.Seconds(2), HSLColor.LawnGreen },
	{ DateTime.Seconds(8), Civ4, "I think... I hear someone calling my name!", DateTime.Seconds(2), HSLColor.DarkOrange },
	{ DateTime.Seconds(11), General, "Keep moving, guys!", DateTime.Seconds(2), HSLColor.Aqua }
}

TechCenterReachedTexts =
{
	{ DateTime.Seconds(1), Civ8, "*GASP* The Research Center!", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(4), Civ8, "Everything is destroyed!", DateTime.Seconds(2), HSLColor.Salmon },
	{ DateTime.Seconds(8), General, "Let's go look for survivors!", DateTime.Seconds(2), HSLColor.Aqua }
}

TechCenterEnteredSound = "immortality2.wav"

ShroudRegrowDelay = DateTime.Seconds(42)

Civilians = { Civ1, Civ2, Civ3, Civ4, Civ5, Civ6, Civ7, Civ8, Civ9, General }

DisplayTextMessages = function(texts, delay, after)
	Utils.Do(texts, function(speech)
		lastDelay = speech[1]
		Trigger.AfterDelay(speech[1], function()
			for i = 0, speech[4] do
				Trigger.AfterDelay(i, function()
					Media.FloatingText(speech[3], speech[2].CenterPosition + WVec.New(0, 0, 1024), 1, speech[5])
				end)
			end
		end)
	end)

	if after then
		Trigger.AfterDelay(lastDelay + delay, after)
	end
end

PlayRainSound = function()
	Media.PlaySound("rain.aud")
	Trigger.AfterDelay(DateTime.Seconds(12) + 10, PlayRainSound)
end

HorizontalLength = function(pos)
	local sum = pos.X * pos.X + pos.Y * pos.Y
	return math.sqrt(sum)
end

StartMovingToMCVs = function()
	Mcv0 = Player0.GetActorsByType("fakemcv")[1]
	Mcv1 = Player1.GetActorsByType("fakemcv")[1]
	local vec = TechnologyCenter.CenterPosition - Mcv0.CenterPosition
	local vec1 = TechnologyCenter.CenterPosition - Mcv1.CenterPosition
	local steps = math.ceil(HorizontalLength(vec) / 256)
	local steps1 = math.ceil(HorizontalLength(vec1) / 256)

	local totalSteps = steps
	if steps < steps1 then
		totalSteps = steps1
	end

	if Player0.IsLocalPlayer then
		PerStep = WVec.New(vec.X / totalSteps, vec.Y / totalSteps, 0)
	else
		PerStep = WVec.New(vec1.X / totalSteps, vec1.Y / totalSteps, 0)
	end
end

MoveToMCVs = function()
	local p = Player1
	local a = Mcv1
	if Player0.IsLocalPlayer then
		p = Player0
		a = Mcv0
	end

	local pos = a.CenterPosition
	local dist = LockCamera - pos

	if HorizontalLength(dist) < HorizontalLength(PerStep) then
		MoveCam = false
		Media.PlaySpeechNotification(p, "StartGame")
		StartWaves()

		-- Avoid a desync
		local mcvs = Utils.Where(Map.ActorsInWorld, function(a) return a.Type == "fakemcv" end)
		Utils.Do(mcvs, function(m)
			Actor.Create("mcv", true, { Owner = m.Owner, Location = m.Location })
			m.Destroy()
		end)

		return false
	end

	return LockCamera - PerStep
end

MoveCivilians = function()
	local toWait = { }
	local notInRange = { }
	local allWaiting = false
	Utils.Do(Civilians, function(civ)
		local vec = civ.Location - General.Location
		if civ ~= General and HorizontalLength(vec) > 1.5 then
			notInRange[civ] = true
			if vec.X >= 0 and vec.Y <= 0 then
				toWait[civ] = math.ceil(HorizontalLength(vec))
				notInRange[civ] = false
			else
				allWaiting = true
			end
		end
	end)

	Utils.Do(Civilians, function(civ)
		if notInRange[civ] then
			civ.Move(TechnologyCenter.Location)
			return
		end

		local t = 0
		if allWaiting then
			t = 15
		end

		if toWait[civ] then
			t = t + 15 * toWait[civ]
		end

		if t > 0 then
			civ.Wait(t)
		end

		civ.Move(TechnologyCenter.Location)
	end)
end

Tick = function()
	if Utils.RandomInteger(1, 200) == 10 then
		local delay = Utils.RandomInteger(1, 10)
		Lighting.Flash("LightningStrike", delay)
		Trigger.AfterDelay(delay, function()
			Media.PlaySound("thunder" .. Utils.RandomInteger(1,6) .. ".aud")
		end)
	end

	if Utils.RandomInteger(1, 200) == 10 then
		Media.PlaySound("thunder-ambient.aud")
	end

	if LockCamera then
		Camera.Position = LockCamera

		if General.IsInWorld then
			LockCamera = General.CenterPosition
		end

		if MoveCam then
			LockCamera = MoveToMCVs()
		end
	end
end

WorldLoaded = function()
	local civPlayer = Player.GetPlayer("Civilians")
	Creeps = Player.GetPlayer("Creeps")
	Player0 = Player.GetPlayer("Multi0")
	Player1 = Player.GetPlayer("Multi1")

	local startPosition = General.CenterPosition
	Camera.Position = startPosition
	LockCamera = Camera.Position

	-- Debug:
	--Actor.Create("fact", true, { Owner = Player0, Location = CPos.New(5, 5) })
	--Actor.Create("fact", true, { Owner = Player1, Location = CPos.New(85, 85) })
	--StartWaves()

	PlayRainSound()

	DisplayTextMessages(InitialSpeechTexts, DateTime.Seconds(2), function()
		Utils.Do(Civilians, function(civ)
			civ.Move(TechnologyCenter.Location)
		end)
	end)

	Trigger.OnExitedProximityTrigger(startPosition, WDist.FromCells(10), function(a, id)
		if a.Owner ~= civPlayer or tenCellsTriggered then
			return
		end

		tenCellsTriggered = true
		Trigger.RemoveProximityTrigger(id)

		DisplayTextMessages(MovedTenCellsTexts, DateTime.Seconds(2))
	end)

	Trigger.OnEnteredProximityTrigger(HalfWay.CenterPosition, WDist.FromCells(4), function(a, id)
		if a.Owner ~= civPlayer or halfWayTriggered then
			return
		end

		halfWayTriggered = true
		Trigger.RemoveProximityTrigger(id)
		Media.PlaySound(HalfWayMovedSound)

		Trigger.AfterDelay(DateTime.Seconds(2), function()
			Utils.Do(Civilians, function(civ)
				civ.Stop()
				civ.Scatter()
			end)

			DisplayTextMessages(HalfWayMovedTexts, DateTime.Seconds(2), MoveCivilians)
		end)
	end)

	Trigger.OnEnteredProximityTrigger(MoreThanHalf.CenterPosition, WDist.FromCells(4), function(a, id)
		if a.Owner ~= civPlayer or moreThanHalfTriggered then
			return
		end

		moreThanHalfTriggered = true
		Trigger.RemoveProximityTrigger(id)

		DisplayTextMessages(MoreThanHalfMovedTexts, DateTime.Seconds(2))
	end)

	Trigger.OnEnteredProximityTrigger(ThreeFourthsWay.CenterPosition, WDist.FromCells(4), function(a, id)
		if a.Owner ~= civPlayer or threefourhtsWayTriggered then
			return
		end

		threefourhtsWayTriggered = true
		Trigger.RemoveProximityTrigger(id)

		DisplayTextMessages(ThreefourhtsMovedTexts, DateTime.Seconds(2))
	end)

	Trigger.OnEnteredProximityTrigger(TechnologyCenter.CenterPosition, WDist.FromCells(3), function(a, id)
		if a.Owner ~= civPlayer or not a.HasProperty("Scatter") then
			return
		end

		a.Scatter()
		if techCenterReached then
			techCenterReached[#techCenterReached + 1] = a

			if #techCenterReached == #Civilians - 4 then
				Trigger.RemoveProximityTrigger(id)

				Utils.Do(Civilians, function(civ)
					if Utils.All(techCenterReached, function(t) return t ~= civ end) then
						civ.Scatter()
					end
				end)
			end

			return
		end

		techCenterReached = { a }
		RCcam = Actor.Create("camera.medium", true, { Owner = civPlayer, Location = TechnologyCenter.Location + CVec.New(1, 1) })

		DisplayTextMessages(TechCenterReachedTexts, DateTime.Seconds(2), function()
			Utils.Do(Civilians, function(civ)
				civ.EnterTransport(TechnologyCenter)
			end)
		end)
	end)

	Trigger.OnAllRemovedFromWorld(Civilians, function()
		LockCamera = TechnologyCenter.CenterPosition

		RCcam.Destroy()
		local cam = Actor.Create("camera.small", true, { Owner = civPlayer, Location = TechnologyCenter.Location + CVec.New(1, 1) })
		Media.PlaySound(TechCenterEnteredSound)

		Trigger.AfterDelay(ShroudRegrowDelay, function()
			cam.Destroy()

			-- HACK: No other way to create permanent shroud other than collecting a crate
			Trigger.AfterDelay(2, function()
				local crate1 = Actor.Create("HideMapCrate", true, { Owner = Creeps, Location = CPos.New(4, 114) })
				local engi1 = Actor.Create("fakee6", true, { Owner = Player0, Location = CPos.New(4, 115) })
				local crate2 = Actor.Create("HideMapCrate", true, { Owner = Creeps, Location = CPos.New(5, 114) })
				local engi2 = Actor.Create("fakee6", true, { Owner = Player1, Location = CPos.New(5, 115) })

				Trigger.AfterDelay(2, function()
					engi1.Move(crate1.Location)
					Trigger.OnIdle(engi1, engi1.Destroy)
					engi2.Move(crate2.Location)
					Trigger.OnIdle(engi2, engi2.Destroy)
				end)

				local civ = Actor.Create("dciv1", true, { Owner = Player.GetPlayer("Neutral"), Location = TechnologyCenter.Location + CVec.New(0, 1) })
				local einTanya = Actor.Create("eintanya", true, { Owner = Creeps, Location = TechnologyCenter.Location + CVec.New(0, 1) })
				civ.Move(civ.Location + CVec.New(1, 1))
				einTanya.Move(civ.Location + CVec.New(-1, 1))
			end)

			StartMovingToMCVs()
			MoveCam = true
		end)
	end)
end
