Files
OpenRA/mods/cnc/maps/twist-of-fate/twist-of-fate.lua

353 lines
10 KiB
Lua

--[[
Copyright (c) The OpenRA Developers and Contributors
This file is part of OpenRA, which is free software. It is made
available to you under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. For more
information, see COPYING.
]]
CapturableStructures = { "weap", "pyle", "hq", "nuke", "nuk2", "silo", "proc" , "fact" }
ClearPathCameras = { Cam1, Cam2, Cam3, Cam4, Cam5 }
NodSams = { NodSam1, NodSam2, NodSam3, NodSam4, NodSam5, NodSam6, NodSam7 }
NodGuns = { Actor68, Actor69, NodGun4, Actor66 }
OldGDIBase = { OldGDIProc, OldGDIWeap, OldGDIPyle, OldGDIGtwr1, OldGDIGtwr2, OldGDIGtwr3 }
HeliTransEngineers = { "e6", "e6", "e6", "e6", "e6" }
CenterNodBaseEntrance = { CPos.New(35,22), CPos.New(33,23), CPos.New(34,23), CPos.New(35,23), CPos.New(36,23), CPos.New(33,24), CPos.New(34,24), CPos.New(35,24), CPos.New(33,25), CPos.New(34,25), CPos.New(32,27), CPos.New(33,27), CPos.New(32,28), CPos.New(33,28), CPos.New(31,29), CPos.New(32,29), CPos.New(33,29), CPos.New(31,30), CPos.New(32,30), CPos.New(33,30) }
GoDemolitionMan = function(rmbo)
if rmbo.IsDead then
return
end
local structures = Utils.Where(Map.ActorsInCircle(rmbo.CenterPosition , WDist.FromCells(6)), function(u) return u.HasProperty("StartBuildingRepairs") and u.Owner == GDI end)
if #structures > 0 then
rmbo.Stop()
rmbo.Demolish(Utils.Random(structures))
rmbo.Hunt()
Trigger.AfterDelay(DateTime.Seconds(10), function() GoDemolitionMan(rmbo) end)
end
end
EngineersSent = false
SendEngTeam = function()
if not EngineersSent then
EngineersSent = true
local cargo = Reinforcements.ReinforceWithTransport(Nod, "tran", HeliTransEngineers, { CPos.New(0,32), waypoint11.Location }, { CPos.New(0,32) })[2]
Utils.Do(cargo, function(engs)
engs.Move(CPos.New(39,52))
Trigger.OnIdle(engs, CaptureStructures)
end)
end
end
CaptureStructures = function(actor)
local structures = GDI.GetActorsByTypes(CapturableStructures)
local distance = 500
local captst = nil
Utils.Do(structures, function(st)
if not actor.IsDead and not st.IsDead and distance > (math.abs((actor.Location - st.Location).X) + math.abs((actor.Location - st.Location).Y)) then
distance = math.abs((actor.Location - st.Location).X) + math.abs((actor.Location - st.Location).Y)
captst = st
end
end)
if captst then
actor.Capture(captst)
end
end
LaunchNuke = function(loop)
if NukeDelay == 0 then
return
end
local targets = GDI.GetActorsByTypes({ "nuk2", "atwr", "weap", "proc" })
if #targets < 1 then
targets = GDI.GetGroundAttackers()
end
if not NodTmpl.IsDead then
Media.PlaySpeechNotification(GDI, "NuclearWarheadApproaching")
NodTmpl.ActivateNukePower(Utils.Random(targets).Location)
end
if loop then
Trigger.AfterDelay(DateTime.Seconds(NukeDelay), function() LaunchNuke(true) end)
end
end
SendNodAirstrike = function(loop)
if AstkDelay == 0 then
return
end
local target = GetAirstrikeTarget(GDI)
if target then
NodAirSupport.TargetAirstrike(target, Angle.SouthEast)
if loop then
Trigger.AfterDelay(DateTime.Seconds(AstkDelay), function() SendNodAirstrike(true) end)
end
else
Trigger.AfterDelay(DateTime.Seconds(20), function() SendNodAirstrike(loop) end)
end
end
SendEasyReinforcements = function(i)
local team = { }
if i < 4 then
team = ReinforceTeams[i]
else
team = ReinforceTeams[Utils.RandomInteger(1, 4)]
end
Media.PlaySpeechNotification(GDI, "Reinforce")
Reinforcements.Reinforce(GDI, team, { CPos.New(56,2), waypoint0.Location }, 25, function(a)
a.Move(waypoint1.Location, 2)
a.Move(waypoint2.Location, 2)
a.Move(CPos.New(49,44), 2)
end)
Trigger.AfterDelay(DateTime.Seconds(ReinforceDelay), function()
SendEasyReinforcements(i + 1)
end)
end
CheckObjectives = function()
if Nod.HasNoRequiredUnits() then GDI.MarkCompletedObjective(EliminateAllNod) end
if GDI.HasNoRequiredUnits() then GDI.MarkFailedObjective(EliminateAllNod) end
Trigger.AfterDelay(50, CheckObjectives)
end
CompleteCaptureCommCenterObjective = function()
GDI.MarkCompletedObjective(CaptureCommCenter)
if not NodCYard.IsDead and NodCYard.Owner == Nod then
Trigger.Clear(NodCYard, "OnDamaged")
Trigger.AfterDelay(1, function()
RepairBuilding(Nod, NodCYard, 0.75)
NodCYard.StartBuildingRepairs()
end)
end
Media.DisplayMessage(UserInterface.Translate("communications-center-captured-sams-located"))
local activeSams = Nod.GetActorsByType("sam")
local miniCams = { }
if #activeSams > 0 then
Utils.Do(activeSams, function(s)
table.insert(miniCams, Actor.Create("camera.mini", true, { Owner = GDI, Location = s.Location }))
table.insert(miniCams, Actor.Create("camera.mini", true, { Owner = GDI, Location = CPos.New(s.Location.X + 1, s.Location.Y) }))
end)
Trigger.AfterDelay(1, function()
Utils.Do(miniCams, function(c)
c.Destroy()
end)
end)
end
end
WorldLoaded = function()
Camera.Position = DefaultCameraPosition.CenterPosition
GDI = Player.GetPlayer("GDI")
Nod = Player.GetPlayer("Nod")
if Difficulty == "hard" then
ProduceBuildingsDelay = 50
ProduceUnitsDelay = 10
ProductionCooldownSeconds = 30
MinHarvs = 3
AstkDelay = 180
NukeDelay = 900
ProcUpgrade = "AIHProcUpgrade"
Nod.Resources = 3000
GDI.Cash = 3000
MCVReinf = { "mcv" }
end
if Difficulty == "normal" then
ProduceBuildingsDelay = 70
ProduceUnitsDelay = 15
ProductionCooldownSeconds = 55
MinHarvs = 3
AstkDelay = 220
NukeDelay = 1200
Nod.Resources = 3000
GDI.Cash = 4000
ProcUpgrade = "AINProcUpgrade"
MCVReinf = { "mtnk", "mcv" }
end
if Difficulty == "easy" then
ProduceBuildingsDelay = 100
ProduceUnitsDelay = 35
ProductionCooldownSeconds = 85
MinHarvs = 2
AstkDelay = 250
NukeDelay = 1500
Nod.Resources = 2000
GDI.Cash = 5000
MCVReinf = { "mtnk", "mtnk", "mcv", "mtnk" }
RT1 = { "jeep", "jeep", "apc" }
RT2 = { "mtnk", "msam" }
RT3 = { "htnk" }
ReinforceTeams = { RT1, RT2, RT3 }
ReinforceDelay = 240
Actor137.Teleport(CPos.New(57,6))
Actor203.Destroy()
end
GDI.PlayLowPowerNotification = false
InitObjectives(GDI)
ClearPath = AddPrimaryObjective(GDI, "clear-path")
Trigger.AfterDelay(DateTime.Seconds(5), function()
EliminateAllNod = AddPrimaryObjective(GDI, "eliminate-nod")
end)
InitAI()
CheckObjectives()
Flare = Actor.Create("flare", true, { Owner = GDI, Location = DefaultFlareLocation.Location })
Trigger.AfterDelay(1, function()
AmbushTeam = Map.ActorsInBox(Map.CenterOfCell(CPos.New(46,5)), Map.CenterOfCell(CPos.New(60,53)), function(a) return a.Owner == Nod and a.Type ~= "stnk" end)
Trigger.OnAllKilled(AmbushTeam, function()
GDI.MarkCompletedObjective(ClearPath)
Trigger.AfterDelay(DateTime.Seconds(2), function()
Trigger.AfterDelay(DateTime.Seconds(30), function()
Flare.Destroy()
end)
Media.PlaySpeechNotification(GDI, "Reinforce")
Reinforcements.Reinforce(GDI, MCVReinf, { CPos.New(56,2), waypoint0.Location }, 25, function(a)
a.Move(waypoint1.Location, 2)
a.Move(waypoint2.Location, 2)
a.Move(CPos.New(49,44), 2)
if a.HasProperty("Deploy") then
a.Move(CPos.New(48,51))
a.Deploy()
Trigger.OnRemovedFromWorld(a, function()
if not a.IsDead then
GDI.PlayLowPowerNotification = true
end
end)
end
end)
Utils.Do(ClearPathCameras, function(c)
c.Destroy()
end)
if Difficulty == "easy" then
Trigger.AfterDelay(DateTime.Seconds(ReinforceDelay), function()
SendEasyReinforcements(1)
end)
end
end)
Trigger.AfterDelay(DateTime.Seconds(8), function()
RecoverOldBase = AddSecondaryObjective(GDI, "recover-old-base")
end)
end)
end)
NodAirSupport = Actor.Create("Astk.proxy", true, { Owner = Nod })
Trigger.AfterDelay(DateTime.Seconds(AstkDelay), function()
if AstkDelay > 0 then
SendNodAirstrike(true)
Trigger.AfterDelay(DateTime.Seconds(15), function()
Media.DisplayMessage(UserInterface.Translate("air-strikes-intel-report"))
Trigger.AfterDelay(DateTime.Seconds(8), function()
CaptureCommCenter = AddSecondaryObjective(GDI, "capture-nod-communications-center")
if NodAstkHq.IsDead then
GDI.MarkFailedObjective(CaptureCommCenter)
return
end
if NodAstkHq.Owner == GDI then
Trigger.AfterDelay(DateTime.Seconds(4), CompleteCaptureCommCenterObjective)
end
end)
end)
end
end)
Trigger.OnKilled(NodOutPostCYard, function()
SendNodAirstrike(false)
if not RecoverOldBase then
RecoverOldBase = AddSecondaryObjective(GDI, "recover-old-base")
end
GDI.MarkFailedObjective(RecoverOldBase)
end)
Trigger.OnCapture(NodOutPostCYard, function()
Trigger.ClearAll(NodOutPostCYard)
Utils.Do(OldGDIBase, function(building)
if not building.IsDead then
building.Owner = GDI
end
end)
GDI.MarkCompletedObjective(RecoverOldBase)
table.insert(SneakPaths, SP2)
table.insert(SneakPaths, SP1)
table.insert(SneakPaths, SP2)
end)
Utils.Do(NodGuns, function(g)
Trigger.OnKilled(g, function()
SendEngTeam()
Utils.Do(NodGuns, function(gun) if not gun.IsDead then Trigger.Clear(gun, "OnKilled") end end)
end)
end)
RamboSent = false
Trigger.OnEnteredFootprint(CenterNodBaseEntrance, function(a, id)
if a.Owner == GDI and not RamboSent then
RamboSent = true
local cargo = Reinforcements.ReinforceWithTransport(Nod, "tran", { "rmbo" }, { CPos.New(0,32), waypoint12.Location }, { CPos.New(0,32) })[2]
Trigger.OnIdle(cargo[1], function()
Trigger.Clear(cargo[1], "OnIdle")
Media.PlaySpeechNotification(GDI, "BaseAttack")
Trigger.AfterDelay(5, function() GoDemolitionMan(cargo[1]) end)
end)
Trigger.RemoveFootprintTrigger(id)
end
end)
Trigger.OnDamaged(NodCYard, function(_, atk, _)
if atk.Owner == GDI and not NukeLaunched then
NukeLaunched = true
LaunchNuke(false)
Trigger.Clear(NodCYard, "OnDamaged")
Trigger.AfterDelay(1, function()
RepairBuilding(Nod, NodCYard, 0.75)
NodCYard.StartBuildingRepairs()
end)
end
end)
Trigger.OnKilledOrCaptured(NodTmpl, function()
NukeDelay = 0
end)
Trigger.OnCapture(NodAstkHq, function()
AstkDelay = 0
Trigger.ClearAll(NodAstkHq)
if CaptureCommCenter then
CompleteCaptureCommCenterObjective()
end
end)
Trigger.OnKilled(NodAstkHq, function()
if CaptureCommCenter then
GDI.MarkFailedObjective(CaptureCommCenter)
end
AstkDelay = 0
end)
end