diff --git a/mods/ra/languages/lua/en.ftl b/mods/ra/languages/lua/en.ftl index 050b1d979b..ea52d3ae27 100644 --- a/mods/ra/languages/lua/en.ftl +++ b/mods/ra/languages/lua/en.ftl @@ -65,6 +65,8 @@ destroy-soviet-buildings-units = Destroy all Soviet buildings and units in the a dont-capture-tech-centers = Do not capture the tech centers! Infiltrate one with a spy. infiltrate-tech-center-spy = Infiltrate one of the Soviet tech centers with a spy. capture-radar-shore = Capture the Radar Dome at the shore. +build-naval-yard-redeploy-mcv = Secure a foothold and build a Naval Yard. + If needed, the MCV can be redeployed. # allies-07 enemy-approaching = Enemy approaching. diff --git a/mods/ra/maps/allies-06a/allies06a-AI.lua b/mods/ra/maps/allies-06a/allies06a-AI.lua index a6dcd38e99..8067eae734 100644 --- a/mods/ra/maps/allies-06a/allies06a-AI.lua +++ b/mods/ra/maps/allies-06a/allies06a-AI.lua @@ -7,6 +7,8 @@ information, see COPYING. ]] +SovietsActivated = false + WTransWays = { { WaterUnloadEntry1.Location, WaterUnload1.Location }, @@ -20,23 +22,23 @@ WTransUnits = } WTransDelays = { - easy = 4, - normal = 3, - hard = 1 + easy = DateTime.Seconds(240), + normal = DateTime.Seconds(180), + hard = DateTime.Seconds(140) } BuildDelays = { - easy = 90, - normal = 60, - hard = 30 + easy = DateTime.Seconds(90), + normal = DateTime.Seconds(60), + hard = DateTime.Seconds(30) } -WaterAttacks = +FirstAirDelays = { - easy = 1, - normal = 2, - hard = 3 + easy = DateTime.Seconds(180), + normal = DateTime.Seconds(120), + hard = DateTime.Seconds(90) } WaterAttackTypes = @@ -52,6 +54,7 @@ InfTypes = { { "e1", "e1", "e1"}, { "e2", "e1", "e1"}, + { "e2", "e2", "e1"}, { "e4", "e4", "e1"} } @@ -62,14 +65,12 @@ AttackRallyPoints = { SovietOreAttack2.Location } } -ImportantBuildings = { WeaponsFactory, Airfield, dome2, SovietConyard } +ImportantBuildings = { WeaponsFactory, Airfield, EastRadarDome, SovietConyard } SovietAircraftType = { "yak" } -Yaks = { } -IdlingUnits = { } IdlingTanks = { tank1, tank2, tank3, tank4, tank5, tank6, tank7, tank8 } IdlingNavalUnits = { } -InitialiseAttack = function() +PrepareTankDefenders = function() Utils.Do(ImportantBuildings, function(a) Trigger.OnDamaged(a, function() Utils.Do(IdlingTanks, function(unit) @@ -81,23 +82,23 @@ InitialiseAttack = function() end) end -Attack = 0 +InfantryWave = 0 ProduceInfantry = function() if SovietBarracks.IsDead or SovietBarracks.Owner ~= USSR then return end - Attack = Attack + 1 + InfantryWave = InfantryWave + 1 local toBuild = Utils.Random(InfTypes) USSR.Build(toBuild, function(units) - if Attack == 2 and not AttackTnk1.IsDead then + if InfantryWave == 2 and not AttackTnk1.IsDead then units[#units + 1] = AttackTnk1 - elseif Attack == 4 and not AttackTnk2.IsDead then + elseif InfantryWave == 4 and not AttackTnk2.IsDead then units[#units + 1] = AttackTnk2 end SendAttack(units, Utils.Random(AttackRallyPoints)) - Trigger.AfterDelay(DateTime.Seconds(BuildDelays), ProduceInfantry) + Trigger.AfterDelay(BuildDelays[Difficulty], ProduceInfantry) end) end @@ -115,24 +116,22 @@ ProduceVehicles = function() end ProduceNaval = function() - if not ShouldProduce and #Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == Greece and self.Type == "syrd" end) < 1 then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceNaval) + if not Greece.HasPrerequisites({ "syrd" }) then + Trigger.AfterDelay(DateTime.Seconds(60), ProduceNaval) return end - ShouldProduce = true - if SubPen.IsDead or SubPen.Owner ~= USSR then return end - USSR.Build(WaterAttackTypes, function(units) + USSR.Build(WaterAttackTypes[Difficulty], function(units) Utils.Do(units, function(unit) IdlingNavalUnits[#IdlingNavalUnits + 1] = unit end) Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(40), ProduceNaval) - if #IdlingNavalUnits >= WaterAttacks then + if #IdlingNavalUnits >= #WaterAttackTypes[Difficulty] then Trigger.AfterDelay(DateTime.Seconds(20), function() SendAttack(SetupNavalAttackGroup(), { Harbor.Location }) end) @@ -146,15 +145,12 @@ ProduceAircraft = function() end USSR.Build(SovietAircraftType, function(units) - local yak = units[1] - Yaks[#Yaks + 1] = yak - - Trigger.OnKilled(yak, ProduceAircraft) - if #Yaks == 1 then - Trigger.AfterDelay(DateTime.Seconds(BuildDelays), ProduceAircraft) - end - - InitializeAttackAircraft(yak, Greece) + Utils.Do(units, function(yak) + InitializeAttackAircraft(yak, Greece) + Trigger.OnKilled(yak, function() + Trigger.AfterDelay(BuildDelays[Difficulty], ProduceAircraft) + end) + end) end) end @@ -167,7 +163,7 @@ end SetupNavalAttackGroup = function() local units = { } - for i = 0, 3 do + for i = 1, 3 do if #IdlingNavalUnits == 0 then return units end @@ -184,7 +180,7 @@ end WTransWaves = function() local way = Utils.Random(WTransWays) - local units = Utils.Random(WTransUnits) + local units = Utils.Random(WTransUnits[Difficulty]) local attackUnits = Reinforcements.ReinforceWithTransport(USSR, "lst", units , way, { way[2], way[1] })[2] Utils.Do(attackUnits, function(a) Trigger.OnAddedToWorld(a, function() @@ -193,25 +189,31 @@ WTransWaves = function() end) end) - Trigger.AfterDelay(DateTime.Minutes(WTransDelays), WTransWaves) + Trigger.AfterDelay(WTransDelays[Difficulty], WTransWaves) end ActivateAI = function() - WaterAttackTypes = WaterAttackTypes[Difficulty] - WaterAttacks = WaterAttacks[Difficulty] - WTransUnits = WTransUnits[Difficulty] - WTransDelays = WTransDelays[Difficulty] - BuildDelays = BuildDelays[Difficulty] - - InitialiseAttack() - Trigger.AfterDelay(DateTime.Seconds(10), ProduceInfantry) - Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(10), function() - ProduceAircraft() - ProduceVehicles() - end) + if SovietsActivated then + return + end + SovietsActivated = true WeaponsFactory.RallyPoint = WeaponMeetPoint.Location SubPen.RallyPoint = SubMeetPoint.Location - Trigger.AfterDelay(DateTime.Minutes(5) + DateTime.Seconds(10), ProduceNaval) - Trigger.AfterDelay(DateTime.Minutes(WTransDelays), WTransWaves) + PrepareTankDefenders() + ProduceInfantry() + Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) + + Trigger.AfterDelay(FirstAirDelays[Difficulty], ProduceAircraft) + Trigger.OnProduction(Airfield, function() + if not YakCamera.IsInWorld then + return + end + + -- This begins neutral to lessen its effect on ground attacks. + YakCamera.Owner = USSR + end) + + Trigger.OnAnyKilled(USSR.GetActorsByType("ss"), ProduceNaval) + Trigger.AfterDelay(WTransDelays[Difficulty], WTransWaves) end diff --git a/mods/ra/maps/allies-06a/allies06a.lua b/mods/ra/maps/allies-06a/allies06a.lua index 147a8c5c0a..25d1ca7a49 100644 --- a/mods/ra/maps/allies-06a/allies06a.lua +++ b/mods/ra/maps/allies-06a/allies06a.lua @@ -56,7 +56,7 @@ GroupPatrol = function(units, waypoints, delay) return end if unit.Location == waypoints[i] then - local bool = Utils.All(units, function(actor) return actor.IsIdle end) + local bool = Utils.All(units, function(actor) return actor.IsIdle or actor.IsDead end) if bool then stop = true i = i + 1 @@ -90,8 +90,7 @@ InitialSovietPatrols = function() -- Sub Patrols Patrol1Sub.Patrol({ SubPatrol1_1.Location, SubPatrol1_2.Location }) Patrol2Sub.Patrol({ SubPatrol2_1.Location, SubPatrol2_2.Location }) - Patrol3Sub1.Patrol(SovietSubPath) - Patrol3Sub2.Patrol(SovietSubPath) + Patrol3Sub.Patrol(SovietSubPath) end InitialAlliedReinforcements = function() @@ -103,12 +102,16 @@ InitialAlliedReinforcements = function() Reinforcements.Reinforce(Greece, AlliedReinforcementsB, { AlliedEntry2.Location, UnitAStopLocation.Location }, 2) end) Trigger.AfterDelay(DateTime.Seconds(5), function() - Reinforcements.Reinforce(Greece, { "mcv" }, { AlliedEntry3.Location, MCVStopLocation.Location }) + local mcv = Reinforcements.Reinforce(Greece, { "mcv" }, { AlliedEntry3.Location, MCVStopLocation.Location })[1] + Trigger.OnRemovedFromWorld(mcv, ActivateAI) end) end CaptureRadarDome = function() Trigger.OnKilled(RadarDome, function() + if Greece.IsObjectiveCompleted(CaptureRadarDomeObj) then + return + end Greece.MarkFailedObjective(CaptureRadarDomeObj) end) @@ -135,44 +138,131 @@ CaptureRadarDome = function() end InfiltrateTechCenter = function() + local infiltrated = false + local allKilled = false + Utils.Do(SovietTechLabs, function(a) Trigger.OnInfiltrated(a, function() - if Infiltrated then + if infiltrated then return end - Infiltrated = true - DestroySovietsObj = AddPrimaryObjective(Greece, "destroy-soviet-buildings-units") - Greece.MarkCompletedObjective(InfiltrateTechCenterObj) + infiltrated = true + InfiltrateTechCenterObj = InfiltrateTechCenterObj or AddPrimaryObjective(Greece, "infiltrate-tech-center-spy") - local Proxy = Actor.Create("powerproxy.paratroopers", false, { Owner = USSR }) - Utils.Do(ParadropWaypoints[Difficulty], function(waypoint) - Proxy.TargetParatroopers(waypoint.CenterPosition, Angle.South) + -- Let the infiltration speech play first. + Trigger.AfterDelay(38, function() + Media.PlaySpeechNotification(Greece, "SecondObjectiveMet") + DestroySovietsObj = AddPrimaryObjective(Greece, "destroy-soviet-buildings-units") + Greece.MarkCompletedObjective(InfiltrateTechCenterObj) + + local proxy = Actor.Create("powerproxy.paratroopers", false, { Owner = USSR }) + Utils.Do(ParadropWaypoints[Difficulty], function(waypoint) + local plane = proxy.TargetParatroopers(waypoint.CenterPosition, Angle.South)[1] + Trigger.OnPassengerExited(plane, function(_, passenger) + IdleHunt(passenger) + end) + end) + proxy.Destroy() end) - Proxy.Destroy() end) Trigger.OnCapture(a, function() - if not Infiltrated then + if not infiltrated then + Media.PlaySoundNotification(Greece, "AlertBleep") Media.DisplayMessage(UserInterface.Translate("dont-capture-tech-centers")) end end) end) + Trigger.OnAllKilled(SovietTechLabs, function() + allKilled = true + end) + Trigger.OnAllKilledOrCaptured(SovietTechLabs, function() - if not Greece.IsObjectiveCompleted(InfiltrateTechCenterObj) then - Greece.MarkFailedObjective(InfiltrateTechCenterObj) + if infiltrated then + return end + + Trigger.AfterDelay(1, function() + FailTechCenter(allKilled) + end) + end) +end + +FailTechCenter = function(killed) + local speechDelay = 0 + + if not killed then + -- Let the capture speech play first. + speechDelay = 36 + end + + Trigger.AfterDelay(speechDelay, function() + Media.PlaySpeechNotification(Greece, "ObjectiveNotMet") + end) + + Trigger.AfterDelay(speechDelay + DateTime.Seconds(1), function() + InfiltrateTechCenterObj = InfiltrateTechCenterObj or AddPrimaryObjective(Greece, "infiltrate-tech-center-spy") + Greece.MarkFailedObjective(InfiltrateTechCenterObj) + end) +end + +-- Check progress on the Naval Yard and smaller Soviet base. +-- If a Naval Yard is built, send a sub to investigate the coast. +-- Its death will trigger production of more subs, if that's not yet started. +CheckNavalObjective = function() + if not Greece.HasPrerequisites({ "syrd" } ) then + Trigger.AfterDelay(DateTime.Seconds(3), CheckNavalObjective) + return + end + + local intact = IntactMiniBaseStructures() + if #intact == 0 then + MarkNavalObjective() + else + Trigger.OnAllKilledOrCaptured(intact, MarkNavalObjective) + end + + if ScoutSub.IsDead then + return + end + + local path = { SubPatrol1_1.Location, SubMeetPoint.Location, Harbor.Location } + ScoutSub.Patrol(path, false) + IdleHunt(ScoutSub) +end + +MarkNavalObjective = function() + Trigger.AfterDelay(DateTime.Seconds(2), function() + InfiltrateTechCenterObj = InfiltrateTechCenterObj or AddPrimaryObjective(Greece, "infiltrate-tech-center-spy") + Greece.MarkCompletedObjective(NavalYardObj) + Media.PlaySpeechNotification(Greece, "FirstObjectiveMet") + end) +end + +IntactMiniBaseStructures = function() + local base = { MiniBaseTower1, MiniBaseTower2, SovietBarracks } + return Utils.Where(base, function(structure) + return not structure.IsDead and structure.Owner == USSR end) end Tick = function() - if DateTime.GameTime > DateTime.Seconds(10) and Greece.HasNoRequiredUnits() then - Greece.MarkFailedObjective(InfiltrateTechCenterObj) - end - if DestroySovietsObj and USSR.HasNoRequiredUnits() then Greece.MarkCompletedObjective(DestroySovietsObj) end + + if not Greece.HasNoRequiredUnits() then + return + end + + Utils.Do({ NavalYardObj, InfiltrateTechCenterObj, DestroySovietsObj }, function(objective) + if Greece.IsObjectiveCompleted(objective) then + return + end + + Greece.MarkFailedObjective(objective) + end) end WorldLoaded = function() @@ -181,7 +271,7 @@ WorldLoaded = function() InitObjectives(Greece) - InfiltrateTechCenterObj = AddPrimaryObjective(Greece, "infiltrate-tech-center-spy") + NavalYardObj = AddPrimaryObjective(Greece, "build-naval-yard-redeploy-mcv") CaptureRadarDomeObj = AddSecondaryObjective(Greece, "capture-radar-shore") Camera.Position = DefaultCameraPosition.CenterPosition @@ -205,5 +295,7 @@ WorldLoaded = function() CaptureRadarDome() InfiltrateTechCenter() - Trigger.AfterDelay(0, ActivateAI) + Trigger.AfterDelay(DateTime.Minutes(2), CheckNavalObjective) + -- Prepare Soviet attacks if Greece still has an undeployed MCV. + Trigger.AfterDelay(DateTime.Seconds(30), ActivateAI) end diff --git a/mods/ra/maps/allies-06a/map.yaml b/mods/ra/maps/allies-06a/map.yaml index 1417469742..f1558d27b8 100644 --- a/mods/ra/maps/allies-06a/map.yaml +++ b/mods/ra/maps/allies-06a/map.yaml @@ -38,14 +38,14 @@ Players: LockFaction: True Faction: allies LockColor: True - Color: E2E6F6 + Color: ABB7E4 LockSpawn: True LockTeam: True Enemies: USSR Actors: - Actor176: camera - Owner: USSR + YakCamera: camera + Owner: Neutral Location: 19,66 Actor0: sbag Location: 22,81 @@ -242,10 +242,10 @@ Actors: Actor74: kenn Location: 77,101 Owner: USSR - Actor75: ftur + MiniBaseTower1: ftur Location: 16,82 Owner: USSR - Actor76: ftur + MiniBaseTower2: ftur Location: 19,82 Owner: USSR Actor77: tsla @@ -300,7 +300,7 @@ Actors: Location: 23,82 Owner: USSR Facing: 124 - SubCell: 3 + SubCell: 4 Actor111: e1 Location: 20,64 Owner: Greece @@ -324,7 +324,7 @@ Actors: Location: 13,85 Owner: USSR Facing: 252 - SubCell: 3 + SubCell: 4 Actor117: dog Location: 79,100 Owner: USSR @@ -333,11 +333,11 @@ Actors: Actor126: ss Location: 59,102 Owner: USSR - Facing: 380 + Facing: 384 Actor130: ss Location: 74,113 Owner: USSR - Facing: 252 + Facing: 256 Actor177: mine Owner: Neutral Location: 56,94 @@ -350,7 +350,7 @@ Actors: SovietConyard: fact Location: 69,96 Owner: USSR - dome2: dome + EastRadarDome: dome Location: 90,109 Owner: USSR harv: harv @@ -397,22 +397,22 @@ Actors: SubPatrol3_3: waypoint Location: 79,71 Owner: Neutral - Patrol3Sub1: ss + Patrol3Sub: ss Location: 46,105 Owner: USSR - Facing: 252 - Patrol3Sub2: ss + Facing: 256 + ScoutSub: ss Location: 77,71 Owner: USSR - Facing: 252 + Facing: 256 Patrol1Sub: ss Location: 46,71 Owner: USSR - Facing: 508 + Facing: 512 Patrol2Sub: ss Location: 52,85 Owner: USSR - Facing: 252 + Facing: 256 SubPatrol1_1: waypoint Location: 42,71 Owner: Neutral @@ -502,7 +502,7 @@ Actors: BadGuy1: e1 Location: 20,69 Owner: USSR - SubCell: 3 + SubCell: 4 BadGuy2: e1 Location: 19,70 Owner: USSR @@ -511,11 +511,11 @@ Actors: Location: 24,67 Owner: USSR Facing: 252 - SubCell: 3 + SubCell: 4 Patrol_1_e1: e1 Location: 71,84 Owner: USSR - SubCell: 4 + SubCell: 5 Patrol_1_dog: dog Location: 72,84 Owner: USSR @@ -529,7 +529,7 @@ Actors: Location: 89,93 Owner: USSR Facing: 380 - SubCell: 4 + SubCell: 5 Patrol_3_e1: e1 Location: 92,108 Owner: USSR @@ -537,16 +537,16 @@ Actors: Patrol_3_dog: dog Location: 92,108 Owner: USSR - SubCell: 3 + SubCell: 4 Patrol_4_e1: e1 Location: 76,102 Owner: USSR - SubCell: 4 + SubCell: 5 Patrol_4_dog: dog Location: 77,102 Owner: USSR Facing: 380 - SubCell: 4 + SubCell: 5 WaterUnloadEntry1: waypoint Location: 22,114 Owner: Neutral @@ -628,6 +628,201 @@ Actors: WeaponMeetPoint: waypoint Owner: Neutral Location: 73,90 + Actor179: fenc + Location: 14,81 + Owner: USSR + Actor181: fenc + Location: 16,81 + Owner: USSR + Actor182: fenc + Location: 19,81 + Owner: USSR + Actor183: fenc + Location: 20,81 + Owner: USSR + Actor184: fenc + Location: 21,81 + Owner: USSR + Actor185: fenc + Location: 79,81 + Owner: USSR + Actor186: fenc + Location: 80,81 + Owner: USSR + Actor187: fenc + Location: 14,82 + Owner: USSR + Actor188: fenc + Location: 67,82 + Owner: USSR + Actor189: fenc + Location: 73,82 + Owner: USSR + Actor190: fenc + Location: 14,83 + Owner: USSR + Actor191: fenc + Location: 73,83 + Owner: USSR + Actor192: fenc + Location: 22,84 + Owner: USSR + Actor193: fenc + Location: 22,85 + Owner: USSR + Actor194: fenc + Location: 73,85 + Owner: USSR + Actor195: fenc + Location: 74,85 + Owner: USSR + Actor196: fenc + Location: 75,85 + Owner: USSR + Actor197: fenc + Location: 76,85 + Owner: USSR + Actor198: fenc + Location: 73,86 + Owner: USSR + Actor199: fenc + Location: 77,86 + Owner: USSR + Actor200: fenc + Location: 14,87 + Owner: USSR + Actor201: fenc + Location: 77,87 + Owner: USSR + Actor202: fenc + Location: 14,88 + Owner: USSR + Actor203: fenc + Location: 77,88 + Owner: USSR + Actor204: fenc + Location: 80,89 + Owner: USSR + Actor205: fenc + Location: 81,89 + Owner: USSR + Actor206: fenc + Location: 82,89 + Owner: USSR + Actor207: fenc + Location: 83,89 + Owner: USSR + Actor208: fenc + Location: 84,89 + Owner: USSR + Actor209: fenc + Location: 84,90 + Owner: USSR + Actor210: fenc + Location: 84,91 + Owner: USSR + Actor211: fenc + Location: 85,91 + Owner: USSR + Actor212: fenc + Location: 62,95 + Owner: USSR + Actor213: fenc + Location: 63,95 + Owner: USSR + Actor214: fenc + Location: 64,95 + Owner: USSR + Actor215: fenc + Location: 65,95 + Owner: USSR + Actor216: fenc + Location: 66,95 + Owner: USSR + Actor217: fenc + Location: 67,95 + Owner: USSR + Actor218: fenc + Location: 62,96 + Owner: USSR + Actor219: fenc + Location: 67,96 + Owner: USSR + Actor220: fenc + Location: 68,96 + Owner: USSR + Actor221: fenc + Location: 85,98 + Owner: USSR + Actor222: fenc + Location: 86,98 + Owner: USSR + Actor223: fenc + Location: 87,98 + Owner: USSR + Actor224: fenc + Location: 88,98 + Owner: USSR + Actor225: fenc + Location: 89,98 + Owner: USSR + Actor226: fenc + Location: 90,98 + Owner: USSR + Actor227: fenc + Location: 93,98 + Owner: USSR + Actor228: fenc + Location: 84,99 + Owner: USSR + Actor229: fenc + Location: 85,99 + Owner: USSR + Actor230: fenc + Location: 77,100 + Owner: USSR + Actor231: fenc + Location: 78,100 + Owner: USSR + Actor232: fenc + Location: 80,100 + Owner: USSR + Actor233: fenc + Location: 81,100 + Owner: USSR + Actor234: fenc + Location: 78,101 + Owner: USSR + Actor235: fenc + Location: 79,101 + Owner: USSR + Actor236: fenc + Location: 80,101 + Owner: USSR + Actor237: fenc + Location: 92,103 + Owner: USSR + Actor238: fenc + Location: 93,103 + Owner: USSR + Actor239: fenc + Location: 94,103 + Owner: USSR + Actor240: fenc + Location: 95,103 + Owner: USSR + Actor241: fenc + Location: 96,103 + Owner: USSR + Actor242: fenc + Location: 96,104 + Owner: USSR + Actor243: fenc + Location: 96,105 + Owner: USSR + Actor244: fenc + Location: 15,81 + Owner: USSR Rules: ra|rules/campaign-rules.yaml, ra|rules/campaign-tooltips.yaml, ra|rules/campaign-palettes.yaml, rules.yaml diff --git a/mods/ra/maps/allies-06a/rules.yaml b/mods/ra/maps/allies-06a/rules.yaml index 4ea5d56c80..d3a4102a4f 100644 --- a/mods/ra/maps/allies-06a/rules.yaml +++ b/mods/ra/maps/allies-06a/rules.yaml @@ -1,6 +1,6 @@ Player: PlayerResources: - DefaultCash: 5000 + DefaultCash: 8500 World: LuaScript: