diff --git a/mods/ra/bits/scripts/campaign-global.lua b/mods/ra/bits/scripts/campaign-global.lua new file mode 100644 index 0000000000..b06e5574ce --- /dev/null +++ b/mods/ra/bits/scripts/campaign-global.lua @@ -0,0 +1,39 @@ +--[[ + Copyright 2007-2020 The OpenRA Developers (see AUTHORS) + 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. +]] + +AttackAircraftTargets = { } +InitializeAttackAircraft = function(aircraft, enemyPlayer) + Trigger.OnIdle(aircraft, function() + local actorId = tostring(aircraft) + local target = AttackAircraftTargets[actorId] + + if not target or not target.IsInWorld then + target = ChooseRandomTarget(aircraft, enemyPlayer) + end + + if target then + AttackAircraftTargets[actorId] = target + aircraft.Attack(target) + else + AttackAircraftTargets[actorId] = nil + aircraft.ReturnToBase() + end + end) +end + +ChooseRandomTarget = function(unit, enemyPlayer) + local target = nil + local enemies = Utils.Where(enemyPlayer.GetActors(), function(self) + return self.HasProperty("Health") and unit.CanTarget(self) and not Utils.Any({ "sbag", "fenc", "brik", "cycl", "barb" }, function(type) return self.Type == type end) + end) + if #enemies > 0 then + target = Utils.Random(enemies) + end + return target +end diff --git a/mods/ra/maps/allies-04/allies04-AI.lua b/mods/ra/maps/allies-04/allies04-AI.lua index 45710d917c..a71684209b 100644 --- a/mods/ra/maps/allies-04/allies04-AI.lua +++ b/mods/ra/maps/allies-04/allies04-AI.lua @@ -240,35 +240,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Minutes(1), ProduceAircraft) end - TargetAndAttack(yak) - end) -end - -TargetAndAttack = function(yak, target) - if yak.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == player and self.HasProperty("Health") and yak.CanTarget(self) end) - - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and yak.AmmoCount() > 0 and yak.CanTarget(target) then - yak.Attack(target) - else - yak.ReturnToBase() - end - - yak.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(yak, target) - end) + InitializeAttackAircraft(yak, player) end) end diff --git a/mods/ra/maps/allies-04/rules.yaml b/mods/ra/maps/allies-04/rules.yaml index 4e0dd490ca..1e38ca5c17 100644 --- a/mods/ra/maps/allies-04/rules.yaml +++ b/mods/ra/maps/allies-04/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: allies04.lua, allies04-AI.lua + Scripts: campaign-global.lua, allies04.lua, allies04-AI.lua MissionData: Briefing: Soviet forces are trying to retake the pass you cleared for our convoys.\n\nDon't let this happen. Hold the pass and prevent the Soviets from taking this vital area.\n\nDestroy all Soviet units and buildings in this region. BriefingVideo: ally4.vqa diff --git a/mods/ra/maps/allies-05a/allies05a-AI.lua b/mods/ra/maps/allies-05a/allies05a-AI.lua index 0d41972f90..dcf038c201 100644 --- a/mods/ra/maps/allies-05a/allies05a-AI.lua +++ b/mods/ra/maps/allies-05a/allies05a-AI.lua @@ -259,34 +259,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Minutes(1), ProduceAircraft) end - TargetAndAttack(yak) - end) -end - -TargetAndAttack = function(yak, target) - if yak.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == greece and self.HasProperty("Health") and yak.CanTarget(self) end) - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and yak.AmmoCount() > 0 and yak.CanTarget(target) then - yak.Attack(target) - else - yak.ReturnToBase() - end - - yak.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(yak, target) - end) + InitializeAttackAircraft(yak, greece) end) end diff --git a/mods/ra/maps/allies-05a/rules.yaml b/mods/ra/maps/allies-05a/rules.yaml index 1ba5740300..225c455df4 100644 --- a/mods/ra/maps/allies-05a/rules.yaml +++ b/mods/ra/maps/allies-05a/rules.yaml @@ -1,6 +1,6 @@ World: LuaScript: - Scripts: allies05a.lua, allies05a-AI.lua + Scripts: campaign-global.lua, allies05a.lua, allies05a-AI.lua MissionData: Briefing: Rescue Tanya.\n\nOnce disguised, your spy can move past any enemy unit, except dogs, without being detected. Direct him into the weapons factory located at a nearby Soviet Base where he will hijack a truck and free Tanya.\n\nWith Tanya's help, take out the air defenses on the island and a Chinook will arrive to rescue her.\n\nThen destroy all remaining Soviet buildings and units. BriefingVideo: ally5.vqa diff --git a/mods/ra/maps/allies-06a/allies06a-AI.lua b/mods/ra/maps/allies-06a/allies06a-AI.lua index a8fc3ede20..4eb593ae2c 100644 --- a/mods/ra/maps/allies-06a/allies06a-AI.lua +++ b/mods/ra/maps/allies-06a/allies06a-AI.lua @@ -154,34 +154,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Seconds(BuildDelays), ProduceAircraft) end - TargetAndAttack(yak) - end) -end - -TargetAndAttack = function(yak, target) - if yak.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == player and self.HasProperty("Health") and yak.CanTarget(self) end) - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and yak.AmmoCount() > 0 and yak.CanTarget(target) then - yak.Attack(target) - else - yak.ReturnToBase() - end - - yak.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(yak, target) - end) + InitializeAttackAircraft(yak, player) end) end diff --git a/mods/ra/maps/allies-06a/rules.yaml b/mods/ra/maps/allies-06a/rules.yaml index 02e29c0e08..6f2aa4371b 100644 --- a/mods/ra/maps/allies-06a/rules.yaml +++ b/mods/ra/maps/allies-06a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: allies06a.lua, allies06a-AI.lua + Scripts: campaign-global.lua, allies06a.lua, allies06a-AI.lua MissionData: Briefing: Priority one is to establish a base and get your spy into one of the Soviet Tech Centers in the base across the gulf.\nData on the Iron Curtain is in there and we need it.\n\nOnce you get the data complete your mission...\nWipe out everything. BriefingVideo: ally6.vqa diff --git a/mods/ra/maps/allies-06b/allies06b-AI.lua b/mods/ra/maps/allies-06b/allies06b-AI.lua index 6b238fb4a1..772fe2fc3c 100644 --- a/mods/ra/maps/allies-06b/allies06b-AI.lua +++ b/mods/ra/maps/allies-06b/allies06b-AI.lua @@ -166,34 +166,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Seconds(BuildDelays / 2), ProduceAircraft) end - TargetAndAttack(yak) - end) -end - -TargetAndAttack = function(yak, target) - if yak.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == player and self.HasProperty("Health") and yak.CanTarget(self) end) - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and yak.AmmoCount() > 0 and yak.CanTarget(target) then - yak.Attack(target) - else - yak.ReturnToBase() - end - - yak.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(yak, target) - end) + InitializeAttackAircraft(yak, player) end) end diff --git a/mods/ra/maps/allies-06b/rules.yaml b/mods/ra/maps/allies-06b/rules.yaml index 606a638591..8978a4edf1 100644 --- a/mods/ra/maps/allies-06b/rules.yaml +++ b/mods/ra/maps/allies-06b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: allies06b.lua, allies06b-AI.lua + Scripts: campaign-global.lua, allies06b.lua, allies06b-AI.lua MissionData: BriefingVideo: ally6.vqa WinVideo: allymorf.vqa diff --git a/mods/ra/maps/allies-07/allies07-AI.lua b/mods/ra/maps/allies-07/allies07-AI.lua index a247ec3946..c2d854f1a2 100644 --- a/mods/ra/maps/allies-07/allies07-AI.lua +++ b/mods/ra/maps/allies-07/allies07-AI.lua @@ -131,34 +131,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Seconds(ProductionInterval[Map.LobbyOption("difficulty")] / 2), ProduceAircraft) end - TargetAndAttack(yak) - end) -end - -TargetAndAttack = function(yak, target) - if yak.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == greece and self.HasProperty("Health") and yak.CanTarget(self) end) - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and yak.AmmoCount() > 0 and yak.CanTarget(target) then - yak.Attack(target) - else - yak.ReturnToBase() - end - - yak.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(yak, target) - end) + InitializeAttackAircraft(yak, greece) end) end diff --git a/mods/ra/maps/allies-07/rules.yaml b/mods/ra/maps/allies-07/rules.yaml index 7304741e34..816ae16fa9 100644 --- a/mods/ra/maps/allies-07/rules.yaml +++ b/mods/ra/maps/allies-07/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: allies07.lua, allies07-AI.lua + Scripts: campaign-global.lua, allies07.lua, allies07-AI.lua MissionData: Briefing: LANDCOM 16 HQS.\nTOP SECRET.\nTO: FIELD COMMANDER A9\n\nINTERCEPTION OF SOVIET COMMUNIQUE INDICATES THEIR IRON CURTAIN RESEARCH WAS SET BACK BY ESPIONAGE. EXCELLENT WORK, COMMANDER!\n\nCOMMUNIQUE WAS TRACED BACK TO SECRET SOVIET BASE IN BORNHOLM. INVESTIGATE POSSIBLE CONNECTION WITH IRON CURTAIN RESEARCH. CAPTURE RADAR CENTER AND DESTROY SUB PRODUCTION CAPABILITY.\n\nCONFIRMATION CODE 1138.\n\nTRANSMISSION ENDS.\n StartVideo: shorbom1.vqa diff --git a/mods/ra/maps/allies-08a/allies08a-AI.lua b/mods/ra/maps/allies-08a/allies08a-AI.lua index 74f61f0c29..6ea4ccd15a 100644 --- a/mods/ra/maps/allies-08a/allies08a-AI.lua +++ b/mods/ra/maps/allies-08a/allies08a-AI.lua @@ -125,36 +125,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Seconds(ProductionInterval[Map.LobbyOption("difficulty")] / 2), ProduceAircraft) end - TargetAndAttack(mig) - end) -end - -TargetAndAttack = function(mig, target) - if mig.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(greece.GetActors(), function(actor) - return actor.HasProperty("Health") and actor.Type ~= "brik" and mig.CanTarget(target) - end) - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and mig.AmmoCount() > 0 and mig.CanTarget(target) then - mig.Attack(target) - else - mig.ReturnToBase() - end - - mig.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(mig, target) - end) + InitializeAttackAircraft(mig, greece) end) end diff --git a/mods/ra/maps/allies-08a/rules.yaml b/mods/ra/maps/allies-08a/rules.yaml index be2afae172..b9a3aa68a9 100644 --- a/mods/ra/maps/allies-08a/rules.yaml +++ b/mods/ra/maps/allies-08a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: allies08a.lua, allies08a-AI.lua + Scripts: campaign-global.lua, allies08a.lua, allies08a-AI.lua MissionData: Briefing: Our latest technology, the Chronosphere, is housed in this research station. The timer represents the appointed time for the completion of a vital experiment. The Soviets have learned of this and are moving in. \n\nProtect the Chronosphere and the Advanced-Tech research center. Make sure the base is fully powered at the appointed time. If not, all will be lost! BriefingVideo: ally8.vqa diff --git a/mods/ra/maps/allies-08b/allies08b-AI.lua b/mods/ra/maps/allies-08b/allies08b-AI.lua index ab92d5965e..2573e17483 100644 --- a/mods/ra/maps/allies-08b/allies08b-AI.lua +++ b/mods/ra/maps/allies-08b/allies08b-AI.lua @@ -124,36 +124,7 @@ ProduceAircraft = function() Trigger.AfterDelay(DateTime.Seconds(ProductionInterval[Map.LobbyOption("difficulty")] / 2), ProduceAircraft) end - TargetAndAttack(mig) - end) -end - -TargetAndAttack = function(mig, target) - if mig.IsDead then - return - end - - if not target or target.IsDead or (not target.IsInWorld) then - local enemies = Utils.Where(greece.GetActors(), function(actor) - return actor.HasProperty("Health") and actor.Type ~= "brik" and mig.CanTarget(target) - end) - if #enemies > 0 then - target = Utils.Random(enemies) - end - end - - if target and mig.AmmoCount() > 0 and mig.CanTarget(target) then - mig.Attack(target) - else - mig.ReturnToBase() - end - - mig.CallFunc(function() - -- TODO: Replace this with an idle trigger once that works for aircraft - -- Add a delay of one tick to fix an endless recursive call - Trigger.AfterDelay(1, function() - TargetAndAttack(mig, target) - end) + InitializeAttackAircraft(mig, greece) end) end diff --git a/mods/ra/maps/allies-08b/rules.yaml b/mods/ra/maps/allies-08b/rules.yaml index 27f5445370..f2ac8de2ee 100644 --- a/mods/ra/maps/allies-08b/rules.yaml +++ b/mods/ra/maps/allies-08b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: allies08b.lua, allies08b-AI.lua + Scripts: campaign-global.lua, allies08b.lua, allies08b-AI.lua MissionData: Briefing: Our latest technology, the Chronosphere, is housed in this research station. The timer represents the appointed time for the completion of a vital experiment. The Soviets have learned of this and are moving in. \n\nProtect the Chronosphere and the Advanced-Tech research center. Make sure the base is fully powered at the appointed time. If not, all will be lost! BriefingVideo: ally8.vqa diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 01077cad4d..0531773526 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -32,6 +32,7 @@ Packages: ~desert.mix ra|bits ra|bits/desert + ra|bits/scripts ra|uibits MapFolders: