1--[[ 2 Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 3 This file is part of OpenRA, which is free software. It is made 4 available to you under the terms of the GNU General Public License 5 as published by the Free Software Foundation, either version 3 of 6 the License, or (at your option) any later version. For more 7 information, see COPYING. 8]] 9 10RepairThreshold = { easy = 0.3, normal = 0.6, hard = 0.9 } 11 12ActorRemovals = 13{ 14 easy = { Actor167, Actor168, Actor190, Actor191, Actor193, Actor194, Actor196, Actor198, Actor200 }, 15 normal = { Actor167, Actor194, Actor196, Actor197 }, 16 hard = { }, 17} 18 19GdiTanks = { "mtnk", "mtnk" } 20GdiApc = { "apc" } 21GdiInfantry = { "e1", "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e2", "e2" } 22GDIBase = { GdiNuke1, GdiNuke2, GdiProc, GdiSilo1, GdiSilo2, GdiPyle, GdiWeap, GdiHarv } 23NodSams = { Sam1, Sam2, Sam3, Sam4 } 24CoreNodBase = { NodConYard, NodRefinery, HandOfNod, Airfield } 25 26Guard1UnitTypes = { "bggy" } 27Guard1Path = { waypoint4.Location, waypoint5.Location, waypoint10.Location } 28Guard1Delay = { easy = DateTime.Minutes(2), normal = DateTime.Minutes(1), hard = DateTime.Seconds(30) } 29Guard2UnitTypes = { "bggy" } 30Guard2Path = { waypoint0.Location, waypoint1.Location, waypoint2.Location } 31Guard3Path = { waypoint4.Location, waypoint5.Location, waypoint9.Location } 32 33AttackDelayMin = { easy = DateTime.Minutes(1), normal = DateTime.Seconds(45), hard = DateTime.Seconds(30) } 34AttackDelayMax = { easy = DateTime.Minutes(2), normal = DateTime.Seconds(90), hard = DateTime.Minutes(1) } 35AttackUnitTypes = 36{ 37 easy = 38 { 39 { factory = HandOfNod, types = { "e1", "e1" } }, 40 { factory = HandOfNod, types = { "e1", "e3" } }, 41 { factory = HandOfNod, types = { "e1", "e1", "e3" } }, 42 { factory = HandOfNod, types = { "e1", "e3", "e3" } }, 43 }, 44 normal = 45 { 46 { factory = HandOfNod, types = { "e1", "e1", "e3" } }, 47 { factory = HandOfNod, types = { "e1", "e3", "e3" } }, 48 { factory = HandOfNod, types = { "e1", "e1", "e3", "e3" } }, 49 { factory = Airfield, types = { "bggy" } }, 50 }, 51 hard = 52 { 53 { factory = HandOfNod, types = { "e1", "e1", "e3", "e3" } }, 54 { factory = HandOfNod, types = { "e1", "e1", "e1", "e3", "e3" } }, 55 { factory = HandOfNod, types = { "e1", "e1", "e3", "e3", "e3" } }, 56 { factory = Airfield, types = { "bggy" } }, 57 { factory = Airfield, types = { "ltnk" } }, 58 } 59} 60 61AttackPaths = 62{ 63 { waypoint0.Location, waypoint1.Location, waypoint2.Location, waypoint3.Location }, 64 { waypoint4.Location, waypoint9.Location, waypoint7.Location, waypoint8.Location }, 65} 66 67Attack = function() 68 local production = Utils.Random(AttackUnitTypes[Difficulty]) 69 local path = Utils.Random(AttackPaths) 70 local toBuild = function() return production.types end 71 ProduceUnits(Nod, production.factory, nil, toBuild, function(units) 72 Utils.Do(units, function(unit) 73 unit.Patrol(path, false) 74 IdleHunt(unit) 75 end) 76 end) 77 78 Trigger.AfterDelay(Utils.RandomInteger(AttackDelayMin[Difficulty], AttackDelayMax[Difficulty]), Attack) 79end 80 81Guard1Action = function() 82 ProduceUnits(Nod, Airfield, nil, function() return Guard1UnitTypes end, function(units) 83 Trigger.OnAllKilled(units, function() 84 Trigger.AfterDelay(Guard1Delay[Difficulty], Guard1Action) 85 end) 86 87 Utils.Do(units, function(unit) 88 unit.Patrol(Guard1Path, true, DateTime.Seconds(7)) 89 end) 90 end) 91end 92 93Guard2Action = function() 94 ProduceUnits(Nod, Airfield, nil, function() return Guard2UnitTypes end, function(units) 95 Utils.Do(units, function(unit) 96 unit.Patrol(Guard2Path, true, DateTime.Seconds(5)) 97 end) 98 end) 99end 100 101DiscoverGDIBase = function(actor, discoverer) 102 if BaseDiscovered or not discoverer == GDI then 103 return 104 end 105 106 Utils.Do(GDIBase, function(actor) 107 actor.Owner = GDI 108 end) 109 110 BaseDiscovered = true 111 112 EliminateNod = GDI.AddObjective("Eliminate all Nod forces in the area.") 113 GDI.MarkCompletedObjective(FindBase) 114 115 Attack() 116end 117 118SetupWorld = function() 119 Utils.Do(ActorRemovals[Difficulty], function(unit) 120 unit.Destroy() 121 end) 122 123 Media.PlaySpeechNotification(GDI, "Reinforce") 124 Reinforcements.Reinforce(GDI, GdiTanks, { GdiTankEntry.Location, GdiTankRallyPoint.Location }, DateTime.Seconds(1), function(actor) actor.Stance = "Defend" end) 125 Reinforcements.Reinforce(GDI, GdiApc, { GdiApcEntry.Location, GdiApcRallyPoint.Location }, DateTime.Seconds(1), function(actor) actor.Stance = "Defend" end) 126 Reinforcements.Reinforce(GDI, GdiInfantry, { GdiInfantryEntry.Location, GdiInfantryRallyPoint.Location }, 15, function(actor) actor.Stance = "Defend" end) 127 128 Trigger.OnPlayerDiscovered(AbandonedBase, DiscoverGDIBase) 129 130 RepairNamedActors(Nod, RepairThreshold[Difficulty]) 131 132 Trigger.OnAllKilled(NodSams, function() 133 GDI.MarkCompletedObjective(DestroySAMs) 134 Actor.Create("airstrike.proxy", true, { Owner = GDI }) 135 end) 136 137 Trigger.AfterDelay(0, function() 138 GdiHarv.Stop() 139 end) 140 141 if Difficulty ~= "easy" then 142 Trigger.OnDamaged(NodHarv, function() 143 Utils.Do(Nod.GetGroundAttackers(), function(unit) 144 unit.AttackMove(NodHarv.Location) 145 if Difficulty == "hard" then 146 IdleHunt(unit) 147 end 148 end) 149 end) 150 end 151 152 Trigger.AfterDelay(DateTime.Seconds(45), Guard1Action) 153 Trigger.AfterDelay(DateTime.Minutes(3), Guard2Action) 154 155 Trigger.OnKilled(GuardTank1, function() 156 if not GuardTank2.IsDead then 157 GuardTank2.Patrol(Guard3Path, true, DateTime.Seconds(11)) 158 end 159 end) 160 161 GuardTank1.Patrol(Guard3Path, true, DateTime.Seconds(11)) 162end 163 164WorldLoaded = function() 165 AbandonedBase = Player.GetPlayer("AbandonedBase") 166 GDI = Player.GetPlayer("GDI") 167 Nod = Player.GetPlayer("Nod") 168 169 InitObjectives(GDI) 170 171 NodObjective = Nod.AddObjective("Destroy all GDI troops.") 172 FindBase = GDI.AddObjective("Find the GDI base.") 173 DestroySAMs = GDI.AddObjective("Destroy all SAM sites to receive air support.", "Secondary", false) 174 175 SetupWorld() 176 177 Camera.Position = GdiTankRallyPoint.CenterPosition 178end 179 180Tick = function() 181 if DateTime.GameTime > 2 and GDI.HasNoRequiredUnits() then 182 Nod.MarkCompletedObjective(NodObjective) 183 end 184 185 if BaseDiscovered and Nod.HasNoRequiredUnits() then 186 GDI.MarkCompletedObjective(EliminateNod) 187 end 188end 189