diff --git a/OpenRA.sln b/OpenRA.sln index 118fe03616..8b54060969 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -34,6 +34,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Dawn Lua scripts", mods\cnc\maps\gdi05a\gdi05a.lua = mods\cnc\maps\gdi05a\gdi05a.lua mods\cnc\maps\nod01\nod01.lua = mods\cnc\maps\nod01\nod01.lua mods\cnc\maps\nod02a\nod02a.lua = mods\cnc\maps\nod02a\nod02a.lua + mods\cnc\maps\nod02b\nod02b.lua = mods\cnc\maps\nod02b\nod02b.lua mods\cnc\maps\nod03a\nod03a.lua = mods\cnc\maps\nod03a\nod03a.lua mods\cnc\maps\nod03b\nod03b.lua = mods\cnc\maps\nod03b\nod03b.lua mods\cnc\maps\shellmap\shellmap.lua = mods\cnc\maps\shellmap\shellmap.lua diff --git a/mods/cnc/maps/nod02a/nod02a.lua b/mods/cnc/maps/nod02a/nod02a.lua index 101fb7f6e2..eff80110e6 100644 --- a/mods/cnc/maps/nod02a/nod02a.lua +++ b/mods/cnc/maps/nod02a/nod02a.lua @@ -74,7 +74,7 @@ end DfndTriggerFunction = function() local list = GDI.GetGroundAttackers() Utils.Do(list, function(unit) - unit.Hunt() + IdleHunt(unit) end) end @@ -127,30 +127,35 @@ Atk1Movement = function(unit) Utils.Do(Atk1Waypoints, function(waypoint) unit.AttackMove(waypoint.Location) end) + IdleHunt(unit) end Atk2Movement = function(unit) Utils.Do(Atk2Waypoints, function(waypoint) unit.AttackMove(waypoint.Location) end) + IdleHunt(unit) end Atk3Movement = function(unit) Utils.Do(Atk3Waypoints, function(waypoint) unit.AttackMove(waypoint.Location) end) + IdleHunt(unit) end Atk4Movement = function(unit) Utils.Do(Atk4Waypoints, function(waypoint) unit.AttackMove(waypoint.Location) end) + IdleHunt(unit) end Pat1Movement = function(unit) Utils.Do(Pat1Waypoints, function(waypoint) unit.Move(waypoint.Location) end) + IdleHunt(unit) end WorldLoaded = function() @@ -246,7 +251,6 @@ checkProduction = function(player) for i = 1, unitsToProduce, 1 do UnitsType[i] = UnitToRebuild end - Barracks.Build(UnitsType) end end @@ -262,3 +266,9 @@ getStartUnits = function() end end) end + +IdleHunt = function(unit) + if not unit.IsDead then + Trigger.OnIdle(unit, unit.Hunt) + end +end \ No newline at end of file diff --git a/mods/cnc/maps/nod02b/map.bin b/mods/cnc/maps/nod02b/map.bin new file mode 100644 index 0000000000..d0c57bbf75 Binary files /dev/null and b/mods/cnc/maps/nod02b/map.bin differ diff --git a/mods/cnc/maps/nod02b/map.png b/mods/cnc/maps/nod02b/map.png new file mode 100644 index 0000000000..59bd2437fd Binary files /dev/null and b/mods/cnc/maps/nod02b/map.png differ diff --git a/mods/cnc/maps/nod02b/map.yaml b/mods/cnc/maps/nod02b/map.yaml new file mode 100644 index 0000000000..0dcd4e99a3 --- /dev/null +++ b/mods/cnc/maps/nod02b/map.yaml @@ -0,0 +1,402 @@ +MapFormat: 7 + +RequiresMod: cnc + +Title: Invasion of Egypt (b) + +Description: GDI has kept a stranglehold on Egypt for many years. Set up a forward attack base in your area. To do this you must select your Mobile Construction Vehicle (MCV) and right click on it. From here you can begin to build a base. This area contains plenty of Tiberium, so establishing the base should be easy. + +Author: Westwood Studios + +Tileset: DESERT + +MapSize: 64,64 + +Bounds: 3,23,36,26 + +Visibility: MissionSelector + +Type: Campaign + +Videos: + Briefing: nod2.vqa + GameLost: deskill.vqa + GameWon: airstrk.vqa + GameStart: seige.vqa + +Options: + Crates: False + Creeps: False + Fog: True + Shroud: True + AllyBuildRadius: False + FragileAlliances: False + StartingCash: 4000 + ConfigurableStartingUnits: False + ShortGame: False + +Players: + PlayerReference@GDI: + Name: GDI + Race: gdi + ColorRamp: 31,222,183 + Allies: GDI + Enemies: Nod + PlayerReference@Nod: + Name: Nod + Playable: True + AllowBots: False + Required: True + LockRace: True + Race: nod + LockColor: True + ColorRamp: 3,255,127 + LockSpawn: True + LockTeam: True + Enemies: GDI + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Race: gdi + +Actors: + Actor0: t08 + Location: 34,38 + Owner: Neutral + Actor1: t18 + Location: 34,36 + Owner: Neutral + Actor2: t08 + Location: 25,31 + Owner: Neutral + Actor3: t08 + Location: 26,31 + Owner: Neutral + Actor4: t08 + Location: 21,40 + Owner: Neutral + Actor5: t08 + Location: 3,24 + Owner: Neutral + Actor6: t08 + Location: 3,42 + Owner: Neutral + Actor7: t08 + Location: 4,42 + Owner: Neutral + Actor8: t08 + Location: 6,48 + Owner: Neutral + Actor9: t08 + Location: 16,43 + Owner: Neutral + Actor10: t08 + Location: 26,48 + Owner: Neutral + Actor11: t08 + Location: 13,27 + Owner: Neutral + Actor12: t08 + Location: 6,40 + Owner: Neutral + Actor13: rock1 + Location: 22,32 + Owner: Neutral + Actor20: jeep + Location: 5,24 + Owner: GDI + Facing: 96 + Actor21: jeep + Location: 6,32 + Owner: GDI + Facing: 160 + Actor22: jeep + Location: 12,27 + Owner: GDI + Facing: 32 + Actor28: e1 + Location: 10,24 + Owner: GDI + Facing: 96 + SubCell: 3 + Actor29: e1 + Location: 10,24 + Owner: GDI + Facing: 96 + SubCell: 1 + Actor30: e1 + Location: 9,24 + Owner: GDI + Facing: 96 + SubCell: 4 + Actor31: e1 + Location: 5,34 + Owner: GDI + SubCell: 3 + Actor32: e1 + Location: 5,35 + Owner: GDI + SubCell: 2 + Actor33: e1 + Location: 10,27 + Owner: GDI + SubCell: 2 + Actor34: e1 + Location: 11,27 + Owner: GDI + SubCell: 1 + Actor35: e1 + Location: 10,24 + Owner: GDI + Facing: 96 + SubCell: 2 + Actor37: e1 + Location: 7,40 + Owner: GDI + SubCell: 2 + waypoint27: waypoint + Location: 60,61 + Owner: Neutral + waypoint26: waypoint + Location: 26,41 + Owner: Neutral + waypoint23: waypoint + Location: 33,45 + Owner: Neutral + waypoint21: waypoint + Location: 32,42 + Owner: Neutral + waypoint17: waypoint + Location: 32,26 + Owner: Neutral + waypoint9: waypoint + Location: 29,47 + Owner: Neutral + waypoint8: waypoint + Location: 16,28 + Owner: Neutral + waypoint7: waypoint + Location: 23,40 + Owner: Neutral + waypoint6: waypoint + Location: 20,47 + Owner: Neutral + waypoint5: waypoint + Location: 10,44 + Owner: Neutral + waypoint4: waypoint + Location: 13,36 + Owner: Neutral + waypoint3: waypoint + Location: 36,41 + Owner: Neutral + waypoint2: waypoint + Location: 31,28 + Owner: Neutral + waypoint1: waypoint + Location: 18,25 + Owner: Neutral + waypoint0: waypoint + Location: 4,26 + Owner: Neutral + Refinery: proc + Location: 7,27 + Owner: GDI + FreeActor: false + Yard: fact + Location: 10,28 + Owner: GDI + Barracks: pyle + Location: 7,32 + Owner: GDI + Plant: nuke + Location: 11,31 + Owner: GDI + Silo1: silo + Location: 9,31 + Owner: GDI + Silo2: silo + Location: 9,33 + Owner: GDI + Guard1: e1 + Location: 8,40 + Owner: GDI + SubCell: 1 + Guard2: e1 + Location: 37,24 + Owner: GDI + SubCell: 3 + Guard3: e1 + Location: 36,24 + Owner: GDI + SubCell: 2 + Guard4: e1 + Location: 27,31 + Owner: GDI + SubCell: 1 + Harvester: harv + Location: 5,29 + Owner: GDI + Health: 0.3945313 + Facing: 224 + McvEntry: waypoint + Location: 33,48 + Owner: Neutral + McvRally: waypoint + Location: 33,46 + Owner: Neutral + UnitsEntry: waypoint + Location: 30,48 + Owner: Neutral + UnitsRally: waypoint + Location: 30,44 + Owner: Neutral + +Smudges: + +Rules: + Player: + -ConquestVictoryConditions: + MissionObjectives: + EarlyGameOver: true + World: + -CrateSpawner: + -SpawnMPUnits: + -MPStartLocations: + ObjectivesPanel: + PanelName: MISSION_OBJECTIVES + LuaScript: + Scripts: nod02b.lua + ^Vehicle: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Tank: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Helicopter: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Infantry: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Plane: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Ship: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Building: + Tooltip: + GenericVisibility: Enemy + ShowOwnerRow: false + ^Wall: + Tooltip: + ShowOwnerRow: false + ^Husk: + Tooltip: + GenericVisibility: Enemy, Ally, Neutral + GenericStancePrefix: false + ShowOwnerRow: false + NUK2: + Buildable: + Prerequisites: ~disabled + GUN: + Buildable: + Prerequisites: ~disabled + CYCL: + Buildable: + Prerequisites: ~disabled + FIX: + Buildable: + Prerequisites: ~disabled + HPAD: + Buildable: + Prerequisites: ~disabled + OBLI: + Buildable: + Prerequisites: ~disabled + BRIK: + Buildable: + Prerequisites: ~disabled + TMPL: + Buildable: + Prerequisites: ~disabled + FTNK: + Buildable: + Prerequisites: ~disabled + STNK: + Buildable: + Prerequisites: ~disabled + ARTY: + Buildable: + Prerequisites: ~disabled + E5: + Buildable: + Prerequisites: ~disabled + RMBO: + Buildable: + Prerequisites: ~disabled + MLRS: + Buildable: + Prerequisites: ~disabled + MCV: + Buildable: + Prerequisites: ~disabled + LST: + Buildable: + Prerequisites: ~disabled + C17: + Buildable: + Prerequisites: ~disabled + SAM: + Buildable: + Prerequisites: ~disabled + HQ: + Buildable: + Prerequisites: ~disabled + AFLD: + Buildable: + Prerequisites: ~disabled + E4: + Buildable: + Prerequisites: ~disabled + E3: + Buildable: + Prerequisites: ~disabled + E2: + Buildable: + Prerequisites: ~disabled + SBAG: + Buildable: + Prerequisites: ~disabled + GTWR: + Buildable: + Prerequisites: ~disabled + WEAP: + Buildable: + Prerequisites: ~disabled + EYE: + Buildable: + Prerequisites: ~disabled + ATWR: + Buildable: + Prerequisites: ~disabled + +Sequences: + +VoxelSequences: + +Weapons: + +Voices: + +Notifications: + +Translations: diff --git a/mods/cnc/maps/nod02b/nod02b.lua b/mods/cnc/maps/nod02b/nod02b.lua new file mode 100644 index 0000000000..a1083b0846 --- /dev/null +++ b/mods/cnc/maps/nod02b/nod02b.lua @@ -0,0 +1,241 @@ +NodUnits = { "bggy", "e1", "e1", "e1", "e1", "e1", "bggy", "e1", "e1", "e1", "bggy" } +NodBaseBuildings = { "hand", "fact", "nuke" } + +Grd2ActorTriggerActivator = { Refinery, Yard } +Atk4ActorTriggerActivator = { Guard1 } +Atk3ActorTriggerActivator = { Guard4 } +Atk6ActorTriggerActivator = { Guard2, Guard3 } +HuntActorTriggerActivator = { Refinery, Yard, Barracks, Plant, Silo1, Silo2 } + +Atk8TriggerFunctionTime = DateTime.Minutes(1) + DateTime.Seconds(25) +Atk7TriggerFunctionTime = DateTime.Minutes(1) + DateTime.Seconds(20) + +Gdi1Waypoints = { waypoint0, waypoint1, waypoint2, waypoint3 } +Gdi3Waypoints = { waypoint0, waypoint1, waypoint4, waypoint5, waypoint6, waypoint7, waypoint9 } + +UnitToRebuild = 'e1' +GDIStartUnits = 0 + +Grd2TriggerFunction = function() + if not Grd2TriggerSwitch then + Grd2TriggerSwitch = true + MyActors = getActors(GDI, { ['e1'] = 5 }) + Utils.Do(MyActors, function(actor) + Gdi5Movement(actor) + end) + end +end + +Atk8TriggerFunction = function() + MyActors = getActors(GDI, { ['e1'] = 2 }) + Utils.Do(MyActors, function(actor) + Gdi1Movement(actor) + end) +end + +Atk7TriggerFunction = function() + MyActors = getActors(GDI, { ['e1'] = 3 }) + Utils.Do(MyActors, function(actor) + Gdi3Movement(actor) + end) +end + +Atk4TriggerFunction = function() + MyActors = getActors(GDI, { ['e1'] = 3 }) + Utils.Do(MyActors, function(actor) + Gdi3Movement(actor) + end) +end + +Atk3TriggerFunction = function() + MyActors = getActors(GDI, { ['e1'] = 2 }) + Utils.Do(MyActors, function(actor) + Gdi1Movement(actor) + end) +end + +Atk6TriggerFunction = function() + MyActors = getActors(GDI, { ['e1'] = 2 }) + Utils.Do(MyActors, function(actor) + Gdi1Movement(actor) + end) +end + +Atk5TriggerFunction = function() + if not Atk5TriggerSwitch then + Atk5TriggerSwitch = true + MyActors = getActors(GDI, { ['e1'] = 3 }) + Utils.Do(MyActors, function(actor) + Gdi3Movement(actor) + end) + end +end + +HuntTriggerFunction = function() + local list = GDI.GetGroundAttackers() + Utils.Do(list, function(unit) + IdleHunt(unit) + end) +end + +Gdi5Movement = function(unit) + IdleHunt(unit) +end + +Gdi1Movement = function(unit) + Utils.Do(Gdi1Waypoints, function(waypoint) + unit.AttackMove(waypoint.Location) + end) + IdleHunt(unit) +end + +Gdi3Movement = function(unit) + Utils.Do(Gdi3Waypoints, function(waypoint) + unit.AttackMove(waypoint.Location) + end) + IdleHunt(unit) +end + +WorldLoaded = function() + GDI = Player.GetPlayer("GDI") + Nod = Player.GetPlayer("Nod") + + Trigger.OnObjectiveAdded(Nod, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") + end) + + Trigger.OnObjectiveCompleted(Nod, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") + end) + + Trigger.OnObjectiveFailed(Nod, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") + end) + + Trigger.OnPlayerWon(Nod, function() + Media.PlaySpeechNotification(Nod, "Win") + end) + + Trigger.OnPlayerLost(Nod, function() + Media.PlaySpeechNotification(Nod, "Lose") + end) + + GDIObjective = GDI.AddPrimaryObjective("Kill all enemies!") + NodObjective1 = Nod.AddPrimaryObjective("Build a base!") + NodObjective2 = Nod.AddPrimaryObjective("Destroy all GDI units!") + + OnAnyDamaged(Grd2ActorTriggerActivator, Grd2TriggerFunction) + Trigger.AfterDelay(Atk8TriggerFunctionTime, Atk8TriggerFunction) + Trigger.AfterDelay(Atk7TriggerFunctionTime, Atk7TriggerFunction) + Trigger.OnAllRemovedFromWorld(Atk4ActorTriggerActivator, Atk4TriggerFunction) + Trigger.OnAllRemovedFromWorld(Atk3ActorTriggerActivator, Atk3TriggerFunction) + Trigger.OnDamaged(Harvester, Atk5TriggerFunction) + Trigger.OnAllRemovedFromWorld(HuntActorTriggerActivator, HuntTriggerFunction) + + Trigger.AfterDelay(0, getStartUnits) + Harvester.FindResources() + InsertNodUnits() +end + +Tick = function() + if Nod.HasNoRequiredUnits() then + if DateTime.GameTime > 2 then + GDI.MarkCompletedObjective(GDIObjective) + end + end + + if GDI.HasNoRequiredUnits() then + Nod.MarkCompletedObjective(NodObjective2) + end + + if DateTime.GameTime % DateTime.Seconds(1) == 0 and not Nod.IsObjectiveCompleted(NodObjective1) and CheckForBase(Nod, NodBaseBuildings) then + Nod.MarkCompletedObjective(NodObjective1) + end + + if DateTime.GameTime % DateTime.Seconds(3) == 0 and Barracks.IsInWorld then + checkProduction(GDI) + end +end + +CheckForBase = function(player, buildings) + local checked = { } + local baseBuildings = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor) + if actor.Owner ~= Nod or Utils.Any(checked, function(bldng) return bldng.Type == actor.Type end) then + return false + end + + local found = false + for i = 1, #buildings, 1 do + if actor.Type == buildings[i] then + found = true + checked[#checked + 1] = actor + end + end + return found + end) + return #baseBuildings >= 3 +end + +OnAnyDamaged = function(actors, func) + Utils.Do(actors, function(actor) + Trigger.OnDamaged(actor, func) + end) +end + +getActors = function(owner, units) + local maxUnits = 0 + local actors = { } + for type, count in pairs(units) do + local globalActors = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor) + return actor.Owner == owner and actor.Type == type and not actor.IsDead + end) + if #globalActors < count then + maxUnits = #globalActors + else + maxUnits = count + end + for i = 1, maxUnits, 1 do + actors[#actors + 1] = globalActors[i] + end + end + return actors +end + +checkProduction = function(player) + local Units = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor) + return actor.Owner == player and actor.Type == UnitToRebuild + end) + + if #Units < GDIStartUnits then + local unitsToProduce = GDIStartUnits - #Units + if Barracks.IsInWorld and unitsToProduce > 0 then + local UnitsType = { } + for i = 1, unitsToProduce, 1 do + UnitsType[i] = UnitToRebuild + end + Barracks.Build(UnitsType) + end + end +end + +getStartUnits = function() + local Units = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(actor) + return actor.Owner == GDI + end) + Utils.Do(Units, function(unit) + if unit.Type == UnitToRebuild then + GDIStartUnits = GDIStartUnits + 1 + end + end) +end + +InsertNodUnits = function() + Reinforcements.Reinforce(Nod, NodUnits, { UnitsEntry.Location, UnitsRally.Location }, 15) + Reinforcements.Reinforce(Nod, { "mcv" }, { McvEntry.Location, McvRally.Location }) +end + +IdleHunt = function(unit) + if not unit.IsDead then + Trigger.OnIdle(unit, unit.Hunt) + end +end \ No newline at end of file diff --git a/mods/cnc/missions.yaml b/mods/cnc/missions.yaml index 13b311812b..3cec5f8b64 100644 --- a/mods/cnc/missions.yaml +++ b/mods/cnc/missions.yaml @@ -10,5 +10,6 @@ GDI Campaign: Nod Campaign: ./mods/cnc/maps/nod01 ./mods/cnc/maps/nod02a + ./mods/cnc/maps/nod02b ./mods/cnc/maps/nod03a ./mods/cnc/maps/nod03b