From a942ca8f57ac2b2b1a72dd32d16471e97c842cc6 Mon Sep 17 00:00:00 2001 From: abcdefg30 Date: Wed, 21 Jun 2017 16:25:53 +0200 Subject: [PATCH] Add a global script for campaign missions in d2k --- OpenRA.sln | 1 + mods/d2k/bits/scripts/campaign-global.lua | 192 ++++++++++++++++++ mods/d2k/maps/atreides-01a/atreides01a.lua | 106 ++++------ mods/d2k/maps/atreides-01a/rules.yaml | 2 +- mods/d2k/maps/atreides-01b/atreides01b.lua | 106 ++++------ mods/d2k/maps/atreides-01b/rules.yaml | 2 +- mods/d2k/maps/atreides-02a/atreides02a-AI.lua | 112 +--------- mods/d2k/maps/atreides-02a/atreides02a.lua | 128 ++++-------- mods/d2k/maps/atreides-02a/rules.yaml | 2 +- mods/d2k/maps/atreides-02b/atreides02b-AI.lua | 112 +--------- mods/d2k/maps/atreides-02b/atreides02b.lua | 108 +++------- mods/d2k/maps/atreides-02b/rules.yaml | 2 +- mods/d2k/maps/atreides-03a/atreides03a-AI.lua | 145 ++----------- mods/d2k/maps/atreides-03a/atreides03a.lua | 70 ++----- mods/d2k/maps/atreides-03a/rules.yaml | 2 +- mods/d2k/maps/atreides-03b/atreides03b-AI.lua | 115 +---------- mods/d2k/maps/atreides-03b/atreides03b.lua | 65 ++---- mods/d2k/maps/atreides-03b/rules.yaml | 2 +- mods/d2k/maps/atreides-04/atreides04-AI.lua | 139 ++----------- mods/d2k/maps/atreides-04/atreides04.lua | 78 ++----- mods/d2k/maps/atreides-04/rules.yaml | 2 +- mods/d2k/maps/atreides-05/atreides05-AI.lua | 172 +++------------- mods/d2k/maps/atreides-05/atreides05.lua | 51 ++--- mods/d2k/maps/atreides-05/rules.yaml | 2 +- mods/d2k/maps/harkonnen-01a/harkonnen01a.lua | 106 ++++------ mods/d2k/maps/harkonnen-01a/rules.yaml | 2 +- mods/d2k/maps/harkonnen-01b/harkonnen01b.lua | 106 ++++------ mods/d2k/maps/harkonnen-01b/rules.yaml | 2 +- .../maps/harkonnen-02a/harkonnen02a-AI.lua | 112 +--------- mods/d2k/maps/harkonnen-02a/harkonnen02a.lua | 128 ++++-------- mods/d2k/maps/harkonnen-02a/rules.yaml | 2 +- .../maps/harkonnen-02b/harkonnen02b-AI.lua | 137 +------------ mods/d2k/maps/harkonnen-02b/harkonnen02b.lua | 128 ++++-------- mods/d2k/maps/harkonnen-02b/rules.yaml | 2 +- .../maps/harkonnen-03a/harkonnen03a-AI.lua | 148 ++------------ mods/d2k/maps/harkonnen-03a/harkonnen03a.lua | 96 +++------ mods/d2k/maps/harkonnen-03a/rules.yaml | 2 +- .../maps/harkonnen-03b/harkonnen03b-AI.lua | 145 ++----------- mods/d2k/maps/harkonnen-03b/harkonnen03b.lua | 88 ++------ mods/d2k/maps/harkonnen-03b/rules.yaml | 2 +- mods/d2k/maps/harkonnen-04/harkonnen04-AI.lua | 184 ++--------------- mods/d2k/maps/harkonnen-04/harkonnen04.lua | 126 ++++-------- mods/d2k/maps/harkonnen-04/rules.yaml | 2 +- mods/d2k/maps/ordos-01a/ordos01a.lua | 106 ++++------ mods/d2k/maps/ordos-01a/rules.yaml | 2 +- mods/d2k/maps/ordos-01b/ordos01b.lua | 106 ++++------ mods/d2k/maps/ordos-01b/rules.yaml | 2 +- mods/d2k/maps/ordos-02a/ordos02a-AI.lua | 112 +--------- mods/d2k/maps/ordos-02a/ordos02a.lua | 142 +++++-------- mods/d2k/maps/ordos-02a/rules.yaml | 2 +- mods/d2k/maps/ordos-02b/ordos02b-AI.lua | 112 +--------- mods/d2k/maps/ordos-02b/ordos02b.lua | 108 +++------- mods/d2k/maps/ordos-02b/rules.yaml | 2 +- mods/d2k/maps/ordos-03a/ordos03a-AI.lua | 145 ++----------- mods/d2k/maps/ordos-03a/ordos03a.lua | 82 ++------ mods/d2k/maps/ordos-03a/rules.yaml | 2 +- mods/d2k/maps/ordos-03b/ordos03b-AI.lua | 145 ++----------- mods/d2k/maps/ordos-03b/ordos03b.lua | 86 ++------ mods/d2k/maps/ordos-03b/rules.yaml | 2 +- mods/d2k/maps/ordos-04/ordos04-AI.lua | 174 +++------------- mods/d2k/maps/ordos-04/ordos04.lua | 77 +++---- mods/d2k/maps/ordos-04/rules.yaml | 2 +- mods/d2k/mod.yaml | 1 + 63 files changed, 1168 insertions(+), 3476 deletions(-) create mode 100644 mods/d2k/bits/scripts/campaign-global.lua diff --git a/OpenRA.sln b/OpenRA.sln index b224e36d75..3e6310ac8d 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -100,6 +100,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Red Alert Lua scripts", "Re EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dune 2000 Lua scripts", "Dune 2000 Lua scripts", "{06B1AE07-DDB0-4287-8700-A8CD9A0E652E}" ProjectSection(SolutionItems) = preProject + mods\d2k\bits\scripts\campaign-global.lua = mods\d2k\bits\scripts\campaign-global.lua mods\d2k\maps\atreides-01a\atreides01a.lua = mods\d2k\maps\atreides-01a\atreides01a.lua mods\d2k\maps\atreides-01b\atreides01b.lua = mods\d2k\maps\atreides-01b\atreides01b.lua mods\d2k\maps\atreides-02a\atreides02a-AI.lua = mods\d2k\maps\atreides-02a\atreides02a-AI.lua diff --git a/mods/d2k/bits/scripts/campaign-global.lua b/mods/d2k/bits/scripts/campaign-global.lua new file mode 100644 index 0000000000..16f1bdde8f --- /dev/null +++ b/mods/d2k/bits/scripts/campaign-global.lua @@ -0,0 +1,192 @@ +--[[ + Copyright 2007-2017 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. +]] + +Difficulty = Map.LobbyOption("difficulty") + +IdleHunt = function(actor) + if not actor.IsDead then + Trigger.OnIdle(actor, actor.Hunt) + end +end + +InitObjectives = function(player) + Trigger.OnObjectiveAdded(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") + end) + + Trigger.OnObjectiveCompleted(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") + end) + Trigger.OnObjectiveFailed(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") + end) + + Trigger.OnPlayerLost(player, function() + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlaySpeechNotification(player, "Lose") + end) + end) + Trigger.OnPlayerWon(player, function() + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlaySpeechNotification(player, "Win") + end) + end) +end + +SendCarryallReinforcements = function(player, currentWave, totalWaves, delay, pathFunction, unitTypes, customCondition, customHuntFunction) + Trigger.AfterDelay(delay, function() + if customCondition and customCondition() then + return + end + + currentWave = currentWave + 1 + if currentWave > totalWaves then + return + end + + local path = pathFunction() + local units = Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", unitTypes[currentWave], path, { path[1] })[2] + + if not customHuntFunction then + customHuntFunction = IdleHunt + end + Utils.Do(units, customHuntFunction) + + SendCarryallReinforcements(player, currentWave, totalWaves, delay, pathFunction, unitTypes, customCondition, customHuntFunction) + end) +end + +TriggerCarryallReinforcements = function(triggeringPlayer, reinforcingPlayer, area, unitTypes, path, customCondition) + local fired = false + Trigger.OnEnteredFootprint(area, function(a, id) + if customCondition and customCondition() then + return + end + + if not fired and a.Owner == triggeringPlayer and a.Type ~= "carryall" then + fired = true + Trigger.RemoveFootprintTrigger(id) + local units = Reinforcements.ReinforceWithTransport(reinforcingPlayer, "carryall.reinforce", unitTypes, path, { path[1] })[2] + Utils.Do(units, IdleHunt) + end + end) +end + +-- Used for the AI: + +IdlingUnits = { } +Attacking = { } +HoldProduction = { } +HarvesterKilled = { } + +SetupAttackGroup = function(owner, size) + local units = { } + + for i = 0, size, 1 do + if #IdlingUnits[owner] == 0 then + return units + end + + local number = Utils.RandomInteger(1, #IdlingUnits[owner] + 1) + + if IdlingUnits[owner][number] and not IdlingUnits[owner][number].IsDead then + units[i] = IdlingUnits[owner][number] + table.remove(IdlingUnits[owner], number) + end + end + + return units +end + +SendAttack = function(owner, size) + if Attacking[owner] then + return + end + Attacking[owner] = true + HoldProduction[owner] = true + + local units = SetupAttackGroup(owner, size) + Utils.Do(units, IdleHunt) + + Trigger.OnAllRemovedFromWorld(units, function() + Attacking[owner] = false + HoldProduction[owner] = false + end) +end + +DefendActor = function(unit, defendingPlayer, defenderCount) + Trigger.OnDamaged(unit, function(self, attacker) + + -- Don't try to attack spiceblooms + if attacker and attacker.Type == "spicebloom" then + return + end + + if Attacking[defendingPlayer] then + return + end + Attacking[defendingPlayer] = true + + local Guards = SetupAttackGroup(defendingPlayer, defenderCount) + + if #Guards <= 0 then + Attacking[defendingPlayer] = false + return + end + + Utils.Do(Guards, function(unit) + if not self.IsDead then + unit.AttackMove(self.Location) + end + IdleHunt(unit) + end) + + Trigger.OnAllRemovedFromWorld(Guards, function() Attacking[defendingPlayer] = false end) + end) +end + +ProtectHarvester = function(unit, owner, defenderCount) + DefendActor(unit, owner, defenderCount) + Trigger.OnKilled(unit, function() HarvesterKilled[unit.Owner] = true end) +end + +RepairBuilding = function(owner, actor, modifier) + Trigger.OnDamaged(actor, function(building) + if building.Owner == owner and building.Health < building.MaxHealth * modifier then + building.StartBuildingRepairs() + end + end) +end + +DefendAndRepairBase = function(owner, baseBuildings, modifier, defenderCount) + Utils.Do(baseBuildings, function(actor) + DefendActor(actor, owner, defenderCount) + RepairBuilding(owner, actor, modifier) + end) +end + +ProduceUnits = function(player, factory, delay, toBuild, attackSize, attackThresholdSize) + if factory.IsDead or factory.Owner ~= player then + return + end + + if HoldProduction[player] then + Trigger.AfterDelay(DateTime.Minutes(1), function() ProduceUnits(player, factory, delay, toBuild, attackSize, attackThresholdSize) end) + return + end + + player.Build(toBuild(), function(unit) + IdlingUnits[player][#IdlingUnits[player] + 1] = unit[1] + Trigger.AfterDelay(delay(), function() ProduceUnits(player, factory, delay, toBuild, attackSize, attackThresholdSize) end) + + if #IdlingUnits[player] >= attackThresholdSize then + SendAttack(player, attackSize) + end + end) +end diff --git a/mods/d2k/maps/atreides-01a/atreides01a.lua b/mods/d2k/maps/atreides-01a/atreides01a.lua index f2b18eb380..8fff222bd5 100644 --- a/mods/d2k/maps/atreides-01a/atreides01a.lua +++ b/mods/d2k/maps/atreides-01a/atreides01a.lua @@ -7,40 +7,46 @@ information, see COPYING. ]] -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "light_inf" } -} + easy = + { + { "light_inf", "light_inf" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location, HarkonnenWaypoint4.Location } HarkonnenAttackDelay = DateTime.Seconds(30) -HarkonnenAttackWaves = { } -HarkonnenAttackWaves["easy"] = 1 -HarkonnenAttackWaves["normal"] = 5 -HarkonnenAttackWaves["hard"] = 12 +HarkonnenAttackWaves = +{ + easy = 1, + normal = 5, + hard = 12 +} -ToHarvest = { } -ToHarvest["easy"] = 2500 -ToHarvest["normal"] = 3000 -ToHarvest["hard"] = 3500 +ToHarvest = +{ + easy = 2500, + normal = 3000, + hard = 3500 +} AtreidesReinforcements = { "light_inf", "light_inf", "light_inf" } AtreidesEntryPath = { AtreidesWaypoint.Location, AtreidesRally.Location } @@ -53,19 +59,12 @@ Messages = "Build a Silo to store additional Spice." } - -IdleHunt = function(actor) - if not actor.IsDead then - Trigger.OnIdle(actor, actor.Hunt) - end -end - Tick = function() if HarkonnenArrived and harkonnen.HasNoRequiredUnits() then player.MarkCompletedObjective(KillHarkonnen) end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -86,14 +85,19 @@ Tick = function() Media.DisplayMessage(Messages[4], "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() player = Player.GetPlayer("Atreides") harkonnen = Player.GetPlayer("Harkonnen") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") Trigger.OnRemovedFromWorld(AtreidesConyard, function() local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) @@ -114,12 +118,12 @@ WorldLoaded = function() Reinforcements.Reinforce(player, AtreidesReinforcements, AtreidesEntryPath) end) - WavesLeft = HarkonnenAttackWaves[Map.LobbyOption("difficulty")] + WavesLeft = HarkonnenAttackWaves[Difficulty] SendReinforcements() end SendReinforcements = function() - local units = HarkonnenReinforcements[Map.LobbyOption("difficulty")] + local units = HarkonnenReinforcements[Difficulty] local delay = Utils.RandomInteger(HarkonnenAttackDelay - DateTime.Seconds(2), HarkonnenAttackDelay) HarkonnenAttackDelay = HarkonnenAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) if HarkonnenAttackDelay < 0 then HarkonnenAttackDelay = 0 end @@ -135,31 +139,3 @@ SendReinforcements = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-01a/rules.yaml b/mods/d2k/maps/atreides-01a/rules.yaml index 526a85599a..29fd1aea88 100644 --- a/mods/d2k/maps/atreides-01a/rules.yaml +++ b/mods/d2k/maps/atreides-01a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides01a.lua + Scripts: campaign-global.lua, atreides01a.lua MissionData: Briefing: Harvest Spice from the Imperial Basin. Construct a Spice Refinery and defend it against the Harkonnen troops scattered throughout the basin. You have been assigned only limited offensive forces - use them wisely.\n\nYou will have to learn the subtleties of mining as you go, but remember to build Silos to store the Spice. When you run out of storage space you can not gather more Spice. Also, any building without adequate concrete foundation will need immediate repair and be vulnerable to erosive damage from the harsh environment. Your greatest adversary may be the elements.\n\nGood luck.\n BriefingVideo: A_BR01_E.VQA diff --git a/mods/d2k/maps/atreides-01b/atreides01b.lua b/mods/d2k/maps/atreides-01b/atreides01b.lua index 5996bc5bd7..869f9988c0 100644 --- a/mods/d2k/maps/atreides-01b/atreides01b.lua +++ b/mods/d2k/maps/atreides-01b/atreides01b.lua @@ -7,40 +7,46 @@ information, see COPYING. ]] -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "light_inf" } -} + easy = + { + { "light_inf", "light_inf" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location, HarkonnenWaypoint4.Location } HarkonnenAttackDelay = DateTime.Seconds(30) -HarkonnenAttackWaves = { } -HarkonnenAttackWaves["easy"] = 1 -HarkonnenAttackWaves["normal"] = 5 -HarkonnenAttackWaves["hard"] = 12 +HarkonnenAttackWaves = +{ + easy = 1, + normal = 5, + hard = 12 +} -ToHarvest = { } -ToHarvest["easy"] = 2500 -ToHarvest["normal"] = 3000 -ToHarvest["hard"] = 3500 +ToHarvest = +{ + easy = 2500, + normal = 3000, + hard = 3500 +} AtreidesReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf" } AtreidesEntryPath = { AtreidesWaypoint.Location, AtreidesRally.Location } @@ -53,19 +59,12 @@ Messages = "Build a Silo to store additional Spice." } - -IdleHunt = function(actor) - if not actor.IsDead then - Trigger.OnIdle(actor, actor.Hunt) - end -end - Tick = function() if HarkonnenArrived and harkonnen.HasNoRequiredUnits() then player.MarkCompletedObjective(KillHarkonnen) end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -86,14 +85,19 @@ Tick = function() Media.DisplayMessage(Messages[4], "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() player = Player.GetPlayer("Atreides") harkonnen = Player.GetPlayer("Harkonnen") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") Trigger.OnRemovedFromWorld(AtreidesConyard, function() local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) @@ -114,12 +118,12 @@ WorldLoaded = function() Reinforcements.Reinforce(player, AtreidesReinforcements, AtreidesEntryPath) end) - WavesLeft = HarkonnenAttackWaves[Map.LobbyOption("difficulty")] + WavesLeft = HarkonnenAttackWaves[Difficulty] SendReinforcements() end SendReinforcements = function() - local units = HarkonnenReinforcements[Map.LobbyOption("difficulty")] + local units = HarkonnenReinforcements[Difficulty] local delay = Utils.RandomInteger(HarkonnenAttackDelay - DateTime.Seconds(2), HarkonnenAttackDelay) HarkonnenAttackDelay = HarkonnenAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) if HarkonnenAttackDelay < 0 then HarkonnenAttackDelay = 0 end @@ -135,31 +139,3 @@ SendReinforcements = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-01b/rules.yaml b/mods/d2k/maps/atreides-01b/rules.yaml index 77e9b912c2..b31308eca7 100644 --- a/mods/d2k/maps/atreides-01b/rules.yaml +++ b/mods/d2k/maps/atreides-01b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides01b.lua + Scripts: campaign-global.lua, atreides01b.lua MissionData: Briefing: Harvest Spice from the Imperial Basin. Construct a Spice Refinery and defend it against the Harkonnen troops scattered throughout the basin. You have been assigned only limited offensive forces - use them wisely.\n\nYou will have to learn the subtleties of mining as you go, but remember to build Silos to store the Spice. When you run out of storage space you can not gather more Spice. Also, any building without adequate concrete foundation will need immediate repair and be vulnerable to erosive damage from the harsh environment. Your greatest adversary may be the elements.\n\nGood luck.\n BriefingVideo: A_BR01_E.VQA diff --git a/mods/d2k/maps/atreides-02a/atreides02a-AI.lua b/mods/d2k/maps/atreides-02a/atreides02a-AI.lua index 35d65c3fa1..2adc8e7838 100644 --- a/mods/d2k/maps/atreides-02a/atreides02a-AI.lua +++ b/mods/d2k/maps/atreides-02a/atreides02a-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -14,6 +13,7 @@ AttackGroupSize = normal = 8, hard = 10 } + AttackDelays = { easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, @@ -23,108 +23,12 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() - ProduceInfantry() + IdlingUnits[harkonnen] = { } + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) + + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local toBuild = function() return HarkonnenInfantryTypes end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + ProduceUnits(harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/atreides-02a/atreides02a.lua b/mods/d2k/maps/atreides-02a/atreides02a.lua index 1a0802ae07..319c7f72a4 100644 --- a/mods/d2k/maps/atreides-02a/atreides02a.lua +++ b/mods/d2k/maps/atreides-02a/atreides02a.lua @@ -9,35 +9,37 @@ HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks } -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" } -} + easy = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "trike", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "trike", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenAttackPaths = @@ -48,35 +50,19 @@ HarkonnenAttackPaths = { HarkonnenEntry2.Location, HarkonnenRally4.Location } } -HarkonnenAttackDelay = { } -HarkonnenAttackDelay["easy"] = DateTime.Minutes(5) -HarkonnenAttackDelay["normal"] = DateTime.Minutes(2) + DateTime.Seconds(40) -HarkonnenAttackDelay["hard"] = DateTime.Minutes(1) + DateTime.Seconds(20) +HarkonnenAttackDelay = +{ + easy = DateTime.Minutes(5), + normal = DateTime.Minutes(2) + DateTime.Seconds(40), + hard = DateTime.Minutes(1) + DateTime.Seconds(20) +} -HarkonnenAttackWaves = { } -HarkonnenAttackWaves["easy"] = 3 -HarkonnenAttackWaves["normal"] = 6 -HarkonnenAttackWaves["hard"] = 9 - -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Map.LobbyOption("difficulty")], function() - wave = wave + 1 - if wave > HarkonnenAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(HarkonnenAttackPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendHarkonnen() - end) -end - -IdleHunt = function(unit) - Trigger.OnIdle(unit, unit.Hunt) -end +HarkonnenAttackWaves = +{ + easy = 3, + normal = 6, + hard = 9 +} Tick = function() if player.HasNoRequiredUnits() then @@ -93,7 +79,9 @@ WorldLoaded = function() harkonnen = Player.GetPlayer("Harkonnen") player = Player.GetPlayer("Atreides") - InitObjectives() + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") + KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") Camera.Position = AConyard.CenterPosition @@ -101,33 +89,7 @@ WorldLoaded = function() Utils.Do(harkonnen.GetGroundAttackers(), IdleHunt) end) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenAttackPaths) end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty]) Trigger.AfterDelay(0, ActivateAI) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") - KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-02a/rules.yaml b/mods/d2k/maps/atreides-02a/rules.yaml index 4518bb5e17..dfdbd6182e 100644 --- a/mods/d2k/maps/atreides-02a/rules.yaml +++ b/mods/d2k/maps/atreides-02a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides02a.lua, atreides02a-AI.lua + Scripts: campaign-global.lua, atreides02a.lua, atreides02a-AI.lua MissionData: Briefing: Infiltrate the Imperial Basin and build up our forces until they are strong enough to eradicate the local Harkonnen presence.\n\nThe Harkonnen are reinforcing their troops by air, so be on your guard. Use the Outpost's radar to detect attacks from unexpected quarters.\n\nBe careful when mining the Spice. Spice mounds grow out of the sand. While a vital source of Spice, Spice mounds can damage or destroy any unit that blunders into them.\n\nGood luck.\n BriefingVideo: A_BR02_E.VQA diff --git a/mods/d2k/maps/atreides-02b/atreides02b-AI.lua b/mods/d2k/maps/atreides-02b/atreides02b-AI.lua index 35d65c3fa1..2adc8e7838 100644 --- a/mods/d2k/maps/atreides-02b/atreides02b-AI.lua +++ b/mods/d2k/maps/atreides-02b/atreides02b-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -14,6 +13,7 @@ AttackGroupSize = normal = 8, hard = 10 } + AttackDelays = { easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, @@ -23,108 +23,12 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() - ProduceInfantry() + IdlingUnits[harkonnen] = { } + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) + + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local toBuild = function() return HarkonnenInfantryTypes end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + ProduceUnits(harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/atreides-02b/atreides02b.lua b/mods/d2k/maps/atreides-02b/atreides02b.lua index 8a50a698ad..35fe57c1b2 100644 --- a/mods/d2k/maps/atreides-02b/atreides02b.lua +++ b/mods/d2k/maps/atreides-02b/atreides02b.lua @@ -9,35 +9,37 @@ HarkonnenBase = { HConyard, HOutpost, HBarracks } -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" } -} + easy = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "trike", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "trike", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenAttackPaths = @@ -62,26 +64,6 @@ HarkonnenAttackWaves = hard = 9 } -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Map.LobbyOption("difficulty")], function() - wave = wave + 1 - if wave > HarkonnenAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(HarkonnenAttackPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendHarkonnen() - end) -end - -IdleHunt = function(unit) - Trigger.OnIdle(unit, unit.Hunt) -end - Tick = function() if player.HasNoRequiredUnits() then harkonnen.MarkCompletedObjective(KillAtreides) @@ -97,7 +79,9 @@ WorldLoaded = function() harkonnen = Player.GetPlayer("Harkonnen") player = Player.GetPlayer("Atreides") - InitObjectives() + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") + KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") Camera.Position = AConyard.CenterPosition @@ -105,33 +89,7 @@ WorldLoaded = function() Utils.Do(harkonnen.GetGroundAttackers(), IdleHunt) end) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenAttackPaths) end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty]) Trigger.AfterDelay(0, ActivateAI) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") - KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-02b/rules.yaml b/mods/d2k/maps/atreides-02b/rules.yaml index 51272370d3..3000ea3039 100644 --- a/mods/d2k/maps/atreides-02b/rules.yaml +++ b/mods/d2k/maps/atreides-02b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides02b.lua, atreides02b-AI.lua + Scripts: campaign-global.lua, atreides02b.lua, atreides02b-AI.lua MissionData: Briefing: Infiltrate the Imperial Basin and build up our forces until they are strong enough to eradicate the local Harkonnen presence.\n\nThe Harkonnen are reinforcing their troops by air, so be on your guard. Use the Outpost's radar to detect attacks from unexpected quarters.\n\nBe careful when mining the Spice. Spice mounds grow out of the sand. While a vital source of Spice, Spice mounds can damage or destroy any unit that blunders into them.\n\nGood luck.\n BriefingVideo: A_BR02_E.VQA diff --git a/mods/d2k/maps/atreides-03a/atreides03a-AI.lua b/mods/d2k/maps/atreides-03a/atreides03a-AI.lua index c06dd77498..20ce90a9e2 100644 --- a/mods/d2k/maps/atreides-03a/atreides03a-AI.lua +++ b/mods/d2k/maps/atreides-03a/atreides03a-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -24,148 +23,30 @@ AttackDelays = OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } OrdosVehicleTypes = { "raider", "raider", "quad" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(ordos, InitialOrdosReinforcements, OrdosPaths[2]) - IdlingUnits[#IdlingUnits + 1] = OTrooper1 - IdlingUnits[#IdlingUnits + 1] = OTrooper2 - IdlingUnits[#IdlingUnits + 1] = ORaider + IdlingUnits[ordos] = Reinforcements.Reinforce(ordos, InitialOrdosReinforcements, OrdosPaths[2]) + IdlingUnits[ordos][#IdlingUnits + 1] = OTrooper1 + IdlingUnits[ordos][#IdlingUnits + 1] = OTrooper2 + IdlingUnits[ordos][#IdlingUnits + 1] = ORaider - Utils.Do(OrdosBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if OBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(OrdosInfantryTypes) } - ordos.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if OLightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(OrdosVehicleTypes) } - ordos.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) + DefendAndRepairBase(ordos, OrdosBase, 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() + HarvesterKilled[ordos] = true Trigger.AfterDelay(0, InitAIUnits) OConyard.Produce(AtreidesUpgrades[1]) OConyard.Produce(AtreidesUpgrades[2]) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end + local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + -- Finish the upgrades first before trying to build something Trigger.AfterDelay(DateTime.Seconds(14), function() - ProduceInfantry() - ProduceVehicles() + ProduceUnits(ordos, OBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(ordos, OLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end) end diff --git a/mods/d2k/maps/atreides-03a/atreides03a.lua b/mods/d2k/maps/atreides-03a/atreides03a.lua index c5086dd3e6..750de28126 100644 --- a/mods/d2k/maps/atreides-03a/atreides03a.lua +++ b/mods/d2k/maps/atreides-03a/atreides03a.lua @@ -6,6 +6,7 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] + OrdosBase = { OBarracks, OWindTrap1, OWindTrap2, OWindTrap3, OWindTrap4, OLightFactory, OOutpost, OConyard, ORefinery, OSilo1, OSilo2, OSilo3, OSilo4 } OrdosReinforcements = @@ -76,25 +77,6 @@ AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location } AtreidesBaseBuildings = { "barracks", "light_factory" } AtreidesUpgrades = { "upgrade.barracks", "upgrade.light" } -wave = 0 -SendOrdos = function() - Trigger.AfterDelay(OrdosAttackDelay[Map.LobbyOption("difficulty")], function() - if player.IsObjectiveCompleted(KillOrdos) then - return - end - - wave = wave + 1 - if wave > OrdosAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local units = Reinforcements.ReinforceWithTransport(ordos, "carryall.reinforce", OrdosReinforcements[Map.LobbyOption("difficulty")][wave], OrdosPaths[1], { OrdosPaths[1][1] })[2] - Utils.Do(units, IdleHunt) - - SendOrdos() - end) -end - MessageCheck = function(index) return #player.GetActorsByType(AtreidesBaseBuildings[index]) > 0 and not player.HasPrerequisites({ AtreidesUpgrades[index] }) end @@ -109,16 +91,16 @@ Tick = function() player.MarkCompletedObjective(KillOrdos) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[ordos] then local units = ordos.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[ordos] = false + ProtectHarvester(units[1], ordos, AttackGroupSize[Difficulty]) end end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -126,14 +108,19 @@ Tick = function() Media.DisplayMessage("Upgrade barracks and light factory to produce more advanced units.", "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() ordos = Player.GetPlayer("Ordos") player = Player.GetPlayer("Atreides") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillAtreides = ordos.AddPrimaryObjective("Kill all Atreides units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillOrdos = player.AddSecondaryObjective("Eliminate all Ordos units and reinforcements\nin the area.") Camera.Position = AConyard.CenterPosition @@ -141,38 +128,13 @@ WorldLoaded = function() Utils.Do(ordos.GetGroundAttackers(), IdleHunt) end) - SendOrdos() + local path = function() return OrdosPaths[1] end + local waveCondition = function() return player.IsObjectiveCompleted(KillOrdos) end + SendCarryallReinforcements(ordos, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition) ActivateAI() Trigger.AfterDelay(DateTime.Minutes(2) + DateTime.Seconds(30), function() + Media.PlaySpeechNotification(player, "Reinforce") Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", AtreidesReinforcements, AtreidesPath, { AtreidesPath[1] }) end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = ordos.AddPrimaryObjective("Kill all Atreides units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillOrdos = player.AddSecondaryObjective("Eliminate all Ordos units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-03a/rules.yaml b/mods/d2k/maps/atreides-03a/rules.yaml index c001897c55..c379d4efc6 100644 --- a/mods/d2k/maps/atreides-03a/rules.yaml +++ b/mods/d2k/maps/atreides-03a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides03a.lua, atreides03a-AI.lua + Scripts: campaign-global.lua, atreides03a.lua, atreides03a-AI.lua MissionData: Briefing: Bring the Atreides forces up to combat strength - quickly. Guard against surprise attacks and ensure Spice production.\n\nThe Ordos forces are light but numerous. To combat the Ordos, you have been granted license to produce Quads, which have a greater anti-vehicle capability than Trikes. Upgrade your Light Factories to allow production of these units.\n\nMeet any agression with overwhelming force.\n\nGood luck.\n BriefingVideo: A_BR03_E.VQA diff --git a/mods/d2k/maps/atreides-03b/atreides03b-AI.lua b/mods/d2k/maps/atreides-03b/atreides03b-AI.lua index 1f12cdca70..631bc2ef48 100644 --- a/mods/d2k/maps/atreides-03b/atreides03b-AI.lua +++ b/mods/d2k/maps/atreides-03b/atreides03b-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -24,117 +23,23 @@ AttackDelays = OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Difficulty], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, IdleHunt) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(ordos, InitialOrdosReinforcements, OrdosPaths[2]) - - Utils.Do(OrdosBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if OBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - local toBuild = { Utils.Random(OrdosInfantryTypes) } - ordos.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) + IdlingUnits[ordos] = Reinforcements.Reinforce(ordos, InitialOrdosReinforcements, OrdosPaths[2]) + DefendAndRepairBase(ordos, OrdosBase, 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() + HarvesterKilled[ordos] = true Trigger.AfterDelay(0, InitAIUnits) OConyard.Produce(AtreidesUpgrades[1]) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local toBuild = function() return { Utils.Random(OrdosInfantryTypes) } end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + -- Finish the upgrades first before trying to build something - Trigger.AfterDelay(DateTime.Seconds(14), ProduceInfantry) + Trigger.AfterDelay(DateTime.Seconds(14), function() + ProduceUnits(ordos, OBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) + end) end diff --git a/mods/d2k/maps/atreides-03b/atreides03b.lua b/mods/d2k/maps/atreides-03b/atreides03b.lua index 623611950a..56b4f710db 100644 --- a/mods/d2k/maps/atreides-03b/atreides03b.lua +++ b/mods/d2k/maps/atreides-03b/atreides03b.lua @@ -6,6 +6,7 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] + OrdosBase = { OBarracks, OWindTrap1, OWindTrap2, OOutpost, OConyard, ORefinery, OSilo } OrdosReinforcements = @@ -76,25 +77,6 @@ AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location } AtreidesBaseBuildings = { "barracks", "light_factory" } AtreidesUpgrades = { "upgrade.barracks", "upgrade.light" } -wave = 0 -SendOrdos = function() - Trigger.AfterDelay(OrdosAttackDelay[Difficulty], function() - if player.IsObjectiveCompleted(KillOrdos) then - return - end - - wave = wave + 1 - if wave > OrdosAttackWaves[Difficulty] then - return - end - - local units = Reinforcements.ReinforceWithTransport(ordos, "carryall.reinforce", OrdosReinforcements[Difficulty][wave], OrdosPaths[1], { OrdosPaths[1][1] })[2] - Utils.Do(units, IdleHunt) - - SendOrdos() - end) -end - MessageCheck = function(index) return #player.GetActorsByType(AtreidesBaseBuildings[index]) > 0 and not player.HasPrerequisites({ AtreidesUpgrades[index] }) end @@ -109,12 +91,12 @@ Tick = function() player.MarkCompletedObjective(KillOrdos) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[ordos] then local units = ordos.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[ordos] = false + ProtectHarvester(units[1], ordos, AttackGroupSize[Difficulty]) end end @@ -133,10 +115,12 @@ WorldLoaded = function() ordos = Player.GetPlayer("Ordos") player = Player.GetPlayer("Atreides") - Difficulty = Map.LobbyOption("difficulty") SpiceToHarvest = ToHarvest[Difficulty] - InitObjectives() + InitObjectives(player) + KillAtreides = ordos.AddPrimaryObjective("Kill all Atreides units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillOrdos = player.AddSecondaryObjective("Eliminate all Ordos units and reinforcements\nin the area.") Camera.Position = AConyard.CenterPosition @@ -144,38 +128,13 @@ WorldLoaded = function() Utils.Do(ordos.GetGroundAttackers(), IdleHunt) end) - SendOrdos() + local path = function() return OrdosPaths[1] end + local waveCondition = function() return player.IsObjectiveCompleted(KillOrdos) end + SendCarryallReinforcements(ordos, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition) ActivateAI() Trigger.AfterDelay(DateTime.Minutes(2) + DateTime.Seconds(30), function() + Media.PlaySpeechNotification(player, "Reinforce") Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", AtreidesReinforcements, AtreidesPath, { AtreidesPath[1] }) end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = ordos.AddPrimaryObjective("Kill all Atreides units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") - KillOrdos = player.AddSecondaryObjective("Eliminate all Ordos units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-03b/rules.yaml b/mods/d2k/maps/atreides-03b/rules.yaml index 3581a30e09..e1313c5841 100644 --- a/mods/d2k/maps/atreides-03b/rules.yaml +++ b/mods/d2k/maps/atreides-03b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides03b.lua, atreides03b-AI.lua + Scripts: campaign-global.lua, atreides03b.lua, atreides03b-AI.lua MissionData: Briefing: Bring the Atreides forces up to combat strength - quickly. Guard against surprise attacks and ensure Spice production.\n\nThe Ordos forces are light but numerous. To combat the Ordos, you have been granted license to produce Quads, which have a greater anti-vehicle capability than Trikes. Upgrade your Light Factories to allow production of these units.\n\nMeet any agression with overwhelming force.\n\nGood luck.\n BriefingVideo: A_BR03_E.VQA diff --git a/mods/d2k/maps/atreides-04/atreides04-AI.lua b/mods/d2k/maps/atreides-04/atreides04-AI.lua index 7a08e7b2e9..818541ed0c 100644 --- a/mods/d2k/maps/atreides-04/atreides04-AI.lua +++ b/mods/d2k/maps/atreides-04/atreides04-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -25,37 +24,15 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" } HarkonnenTankType = { "combat_tank_h" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Difficulty] do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then +-- Overwrite the template function because of the message +SendAttack = function(owner, size) + if Attacking[owner] then return end - Attacking = true - HoldProduction = true + Attacking[owner] = true + HoldProduction[owner] = true - local units = SetupAttackGroup() + local units = SetupAttackGroup(owner, size) Utils.Do(units, IdleHunt) if #units > 0 then @@ -63,107 +40,27 @@ SendAttack = function() end Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if Defending then - return - end - Defending = true - - -- Don't try to attack spiceblooms - if attacker and attacker.Type == "spicebloom" then - return - end - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - Defending = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() Defending = false end) + Attacking[owner] = false + HoldProduction[owner] = false end) end InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(harkonnen, InitialHarkonnenReinforcements, HarkonnenPaths[1]) + IdlingUnits[harkonnen] = Reinforcements.Reinforce(harkonnen, InitialHarkonnenReinforcements, HarkonnenPaths[1]) - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Owner == harkonnen and building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HarkonnenBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) -end - - -ProduceTanks = function() - if HarkonnenHeavyFact.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceTanks) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - harkonnen.Build(HarkonnenTankType, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceTanks) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() + HarvesterKilled[harkonnen] = true InitAIUnits() FremenProduction() - ProduceInfantry() - ProduceTanks() + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end + local tanksToBuild = function() return HarkonnenTankType end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + + ProduceUnits(harkonnen, HarkonnenBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(harkonnen, HarkonnenHeavyFact, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/atreides-04/atreides04.lua b/mods/d2k/maps/atreides-04/atreides04.lua index e1f3e24ab3..6c8e3f91b5 100644 --- a/mods/d2k/maps/atreides-04/atreides04.lua +++ b/mods/d2k/maps/atreides-04/atreides04.lua @@ -6,6 +6,7 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] + HarkonnenBase = { HarkonnenOutpost, HarkonnenRefinery, HarkonnenHeavyFact, HarkonnenTurret1, HarkonnenTurret2, HarkonnenBarracks, HarkonnenSilo1, HarkonnenSilo2, HarkonnenWindTrap1, HarkonnenWindTrap2, HarkonnenWindTrap3, HarkonnenWindTrap4, HarkonnenWindTrap5 } HarkonnenReinforcements = @@ -89,29 +90,6 @@ IntegrityLevel = hard = 100 } -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty], function() - if player.IsObjectiveCompleted(KillHarkonnen) then - return - end - - wave = wave + 1 - if wave > HarkonnenAttackWaves[Difficulty] then - return - end - - local entryPath = Utils.Random(HarkonnenPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Difficulty][wave], entryPath, { entryPath[1] })[2] - Utils.Do(units, function(unit) - unit.AttackMove(HarkonnenAttackLocation) - IdleHunt(unit) - end) - - SendHarkonnen() - end) -end - FremenProduction = function() if Sietch.IsDead then return @@ -119,7 +97,7 @@ FremenProduction = function() local delay = Utils.RandomInteger(FremenInterval[Difficulty][1], FremenInterval[Difficulty][2] + 1) fremen.Build({ "nsfremen" }, function() - Trigger.AfterDelay(delay, ProduceInfantry) + Trigger.AfterDelay(delay, FremenProduction) end) end @@ -136,12 +114,12 @@ Tick = function() player.MarkCompletedObjective(KeepIntegrity) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[harkonnen] then local units = harkonnen.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[harkonnen] = false + ProtectHarvester(units[1], harkonnen, AttackGroupSize[Difficulty]) end end @@ -161,9 +139,11 @@ WorldLoaded = function() fremen = Player.GetPlayer("Fremen") player = Player.GetPlayer("Atreides") - Difficulty = Map.LobbyOption("difficulty") - - InitObjectives() + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") + ProtectFremen = player.AddPrimaryObjective("Protect the Fremen Sietch.") + KillHarkonnen = player.AddPrimaryObjective("Destroy the Harkonnen.") + KeepIntegrity = player.AddSecondaryObjective("Keep the Sietch " .. IntegrityLevel[Difficulty] .. "% intact!") Camera.Position = AConyard.CenterPosition HarkonnenAttackLocation = AConyard.Location @@ -196,7 +176,14 @@ WorldLoaded = function() end end) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenPaths) end + local waveCondition = function() return player.IsObjectiveCompleted(KillHarkonnen) end + local huntFunction = function(unit) + unit.AttackMove(HarkonnenAttackLocation) + IdleHunt(unit) + end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition, huntFunction) + Actor.Create("upgrade.barracks", true, { Owner = harkonnen }) Trigger.AfterDelay(0, ActivateAI) @@ -217,32 +204,3 @@ WorldLoaded = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") - ProtectFremen = player.AddPrimaryObjective("Protect the Fremen Sietch.") - KillHarkonnen = player.AddPrimaryObjective("Destroy the Harkonnen.") - KeepIntegrity = player.AddSecondaryObjective("Keep the Sietch " .. IntegrityLevel[Difficulty] .. "% intact!") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-04/rules.yaml b/mods/d2k/maps/atreides-04/rules.yaml index 2671ac81e8..0f598792fb 100644 --- a/mods/d2k/maps/atreides-04/rules.yaml +++ b/mods/d2k/maps/atreides-04/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides04.lua, atreides04-AI.lua + Scripts: campaign-global.lua, atreides04.lua, atreides04-AI.lua MissionData: Briefing: Our scouts have discovered the hidden Fremen base. The Harkonnen blockade of the Fremen must be broken.\n\nPowerful Harkonnen forces to the South are massing for an assault on the Fremen. Heavy forces have been allocated to you to smash through the Harkonnen fortifications and come to the aid of the Fremen.\n\nGood luck.\n BriefingVideo: A_BR04_E.VQA diff --git a/mods/d2k/maps/atreides-05/atreides05-AI.lua b/mods/d2k/maps/atreides-05/atreides05-AI.lua index 637a1080c5..71418ee0b0 100644 --- a/mods/d2k/maps/atreides-05/atreides05-AI.lua +++ b/mods/d2k/maps/atreides-05/atreides05-AI.lua @@ -1,4 +1,11 @@ -IdlingUnits = { } +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -18,114 +25,26 @@ HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "troo HarkonnenVehicleTypes = { "trike", "trike", "trike", "quad", "quad" } HarkonnenTankType = { "combat_tank_h" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Difficulty] do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - unit.AttackMove(HarkonnenAttackLocation) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if Defending then - return - end - Defending = true - - -- Don't try to attack spiceblooms - if attacker and attacker.Type == "spicebloom" then - return - end - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - Defending = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() Defending = false end) - end) -end - -RepairBuilding = function(owner, actor) - Trigger.OnDamaged(actor, function(building) - if building.Owner == owner and building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) -end - InitAIUnits = function() - IdlingUnits = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", InitialHarkonnenReinforcements, HarkonnenPaths[1], { HarkonnenPaths[1][1] })[2] + IdlingUnits[harkonnen] = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", InitialHarkonnenReinforcements, HarkonnenPaths[1], { HarkonnenPaths[1][1] })[2] - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - RepairBuilding(harkonnen, actor) - end) - - DefendActor(HarkonnenBarracks) - RepairBuilding(harkonnen, HarkonnenBarracks) + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) + DefendActor(HarkonnenBarracks, harkonnen, AttackGroupSize[Difficulty]) + RepairBuilding(harkonnen, HarkonnenBarracks, 0.75) Utils.Do(SmugglerBase, function(actor) - RepairBuilding(smuggler, actor) + RepairBuilding(smuggler, actor, 0.75) end) - RepairBuilding(smuggler, Starport) + RepairBuilding(smuggler, Starport, 0.75) end +-- Not using ProduceUnits because of the custom StopInfantryProduction condition ProduceInfantry = function() if StopInfantryProduction or HarkonnenBarracks.IsDead or HarkonnenBarracks.Owner ~= harkonnen then return end - if HoldProduction then + if HoldProduction[harkonnen] then Trigger.AfterDelay(DateTime.Seconds(30), ProduceInfantry) return end @@ -133,63 +52,26 @@ ProduceInfantry = function() local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) local toBuild = { Utils.Random(HarkonnenInfantryTypes) } harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] + IdlingUnits[harkonnen][#IdlingUnits[harkonnen] + 1] = unit[1] Trigger.AfterDelay(delay, ProduceInfantry) - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if HarkonnenLightFactory.IsDead or HarkonnenLightFactory.Owner ~= harkonnen then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - local toBuild = { Utils.Random(HarkonnenVehicleTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) -end - -ProduceTanks = function() - if HarkonnenHeavyFactory.IsDead or HarkonnenHeavyFactory.Owner ~= harkonnen then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceTanks) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - harkonnen.Build(HarkonnenTankType, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceTanks) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() + if #IdlingUnits[harkonnen] >= (AttackGroupSize[Difficulty] * 2.5) then + SendAttack(harkonnen, AttackGroupSize[Difficulty]) end end) end ActivateAI = function() harkonnen.Cash = 15000 + HarvesterKilled[harkonnen] = true InitAIUnits() + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end + local tanksToBuild = function() return HarkonnenTankType end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + ProduceInfantry() - ProduceVehicles() - ProduceTanks() + ProduceUnits(harkonnen, HarkonnenLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(harkonnen, HarkonnenHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/atreides-05/atreides05.lua b/mods/d2k/maps/atreides-05/atreides05.lua index 1f0532dbb4..d5d4245211 100644 --- a/mods/d2k/maps/atreides-05/atreides05.lua +++ b/mods/d2k/maps/atreides-05/atreides05.lua @@ -1,3 +1,12 @@ +--[[ + Copyright 2007-2017 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. +]] + HarkonnenBase = { HarkonnenConstructionYard, HarkonnenWindTrap1, HarkonnenWindTrap2, HarkonnenWindTrap3, HarkonnenWindTrap4, HarkonnenWindTrap5, HarkonnenWindTrap6, HarkonnenWindTrap7, HarkonnenWindTrap8, HarkonnenSilo1, HarkonnenSilo2, HarkonnenSilo3, HarkonnenSilo4, HarkonnenGunTurret1, HarkonnenGunTurret2, HarkonnenGunTurret3, HarkonnenGunTurret4, HarkonnenGunTurret5, HarkonnenGunTurret6, HarkonnenGunTurret7, HarkonnenHeavyFactory, HarkonnenRefinery, HarkonnenOutpost, HarkonnenLightFactory } SmugglerBase = { SmugglerWindTrap1, SmugglerWindTrap2 } @@ -251,12 +260,12 @@ Tick = function() player.MarkCompletedObjective(KillSmuggler) end - if HarvesterKilled and DateTime.GameTime % DateTime.Seconds(30) then + if HarvesterKilled[harkonnen] and DateTime.GameTime % DateTime.Seconds(30) then local units = harkonnen.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[harkonnen] = false + ProtectHarvester(units[1], harkonnen, AttackGroupSize[Difficulty]) end end @@ -278,10 +287,13 @@ WorldLoaded = function() mercenary = Player.GetPlayer("Mercenaries") player = Player.GetPlayer("Atreides") - Difficulty = Map.LobbyOption("difficulty") InfantryReinforcements = Difficulty ~= "easy" - InitObjectives() + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") + CaptureBarracks = player.AddPrimaryObjective("Capture the Barracks at Sietch Tabr.") + KillHarkonnen = player.AddSecondaryObjective("Annihilate all other Harkonnen units\nand reinforcements.") + CaptureStarport = player.AddSecondaryObjective("Capture the Smuggler Starport and\nconfiscate the contraband.") Camera.Position = ARefinery.CenterPosition HarkonnenAttackLocation = AtreidesRally.Location @@ -412,32 +424,3 @@ WorldLoaded = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Atreides units.") - CaptureBarracks = player.AddPrimaryObjective("Capture the Barracks at Sietch Tabr.") - KillHarkonnen = player.AddSecondaryObjective("Annihilate all other Harkonnen units\nand reinforcements.") - CaptureStarport = player.AddSecondaryObjective("Capture the Smuggler Starport and\nconfiscate the contraband.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/atreides-05/rules.yaml b/mods/d2k/maps/atreides-05/rules.yaml index 55c4e5951e..1da8afca2a 100644 --- a/mods/d2k/maps/atreides-05/rules.yaml +++ b/mods/d2k/maps/atreides-05/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: atreides05.lua, atreides05-AI.lua + Scripts: campaign-global.lua, atreides05.lua, atreides05-AI.lua MissionData: Briefing: According to our spies, the Fremen are being held at the far Northwest corner of Sietch Tabr. Push your way through the Harkonnen ranks to rescue the hostages.\n\nScout the terrain before you launch the main assault. Our Engineers must reach the Barracks and capture it intact. The rest of the base can be razed to the ground.\n\nAdditionally, there are rumors of an illegal Smuggling operation in the area. A large shipment of contraband is expected at the Smuggler's Starport. If you can the Starport before the contraband arrives, you will be able to confiscate it for the Atreides war effort.\n\nBe warned, the Smugglers have Mercenary allies who may assist them if you interfere.\n\nGood luck.\n BriefingVideo: A_BR05_E.VQA diff --git a/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua b/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua index e92bedb8aa..40e59e2b47 100644 --- a/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua +++ b/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua @@ -7,40 +7,46 @@ information, see COPYING. ]] -AtreidesReinforcements = { } -AtreidesReinforcements["easy"] = +AtreidesReinforcements = { - { "light_inf", "light_inf" } -} + easy = + { + { "light_inf", "light_inf" } + }, -AtreidesReinforcements["normal"] = -{ - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -AtreidesReinforcements["hard"] = -{ - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location } AtreidesAttackDelay = DateTime.Seconds(30) -AtreidesAttackWaves = { } -AtreidesAttackWaves["easy"] = 1 -AtreidesAttackWaves["normal"] = 5 -AtreidesAttackWaves["hard"] = 12 +AtreidesAttackWaves = +{ + easy = 1, + normal = 5, + hard = 12 +} -ToHarvest = { } -ToHarvest["easy"] = 2500 -ToHarvest["normal"] = 3000 -ToHarvest["hard"] = 3500 +ToHarvest = +{ + easy = 2500, + normal = 3000, + hard = 3500 +} HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" } HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location } @@ -53,19 +59,12 @@ Messages = "Build a Silo to store additional Spice." } - -IdleHunt = function(actor) - if not actor.IsDead then - Trigger.OnIdle(actor, actor.Hunt) - end -end - Tick = function() if AtreidesArrived and atreides.HasNoRequiredUnits() then player.MarkCompletedObjective(KillAtreides) end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -86,14 +85,19 @@ Tick = function() Media.DisplayMessage(Messages[4], "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() player = Player.GetPlayer("Harkonnen") atreides = Player.GetPlayer("Atreides") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillAtreides = player.AddSecondaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") Trigger.OnRemovedFromWorld(HarkonnenConyard, function() local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) @@ -114,12 +118,12 @@ WorldLoaded = function() Reinforcements.Reinforce(player, HarkonnenReinforcements, HarkonnenEntryPath) end) - WavesLeft = AtreidesAttackWaves[Map.LobbyOption("difficulty")] + WavesLeft = AtreidesAttackWaves[Difficulty] SendReinforcements() end SendReinforcements = function() - local units = AtreidesReinforcements[Map.LobbyOption("difficulty")] + local units = AtreidesReinforcements[Difficulty] local delay = Utils.RandomInteger(AtreidesAttackDelay - DateTime.Seconds(2), AtreidesAttackDelay) AtreidesAttackDelay = AtreidesAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) if AtreidesAttackDelay < 0 then AtreidesAttackDelay = 0 end @@ -135,31 +139,3 @@ SendReinforcements = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillAtreides = player.AddSecondaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/harkonnen-01a/rules.yaml b/mods/d2k/maps/harkonnen-01a/rules.yaml index 4b3ea5f422..2d22acec06 100644 --- a/mods/d2k/maps/harkonnen-01a/rules.yaml +++ b/mods/d2k/maps/harkonnen-01a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen01a.lua + Scripts: campaign-global.lua, harkonnen01a.lua MissionData: Briefing: Mine the Spice from the Imperial Basin, before the Atreides try to seize the area. Execute anyone who tries to stop you.\n\nBuild Silos to store the Spice. Remember to place buildings on concrete foundations to prevent erosion and gradual decline. To build without concrete would be inefficient. Inefficiency will not be tolerated.\n BriefingVideo: H_BR01_E.VQA diff --git a/mods/d2k/maps/harkonnen-01b/harkonnen01b.lua b/mods/d2k/maps/harkonnen-01b/harkonnen01b.lua index e92bedb8aa..40e59e2b47 100644 --- a/mods/d2k/maps/harkonnen-01b/harkonnen01b.lua +++ b/mods/d2k/maps/harkonnen-01b/harkonnen01b.lua @@ -7,40 +7,46 @@ information, see COPYING. ]] -AtreidesReinforcements = { } -AtreidesReinforcements["easy"] = +AtreidesReinforcements = { - { "light_inf", "light_inf" } -} + easy = + { + { "light_inf", "light_inf" } + }, -AtreidesReinforcements["normal"] = -{ - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -AtreidesReinforcements["hard"] = -{ - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location } AtreidesAttackDelay = DateTime.Seconds(30) -AtreidesAttackWaves = { } -AtreidesAttackWaves["easy"] = 1 -AtreidesAttackWaves["normal"] = 5 -AtreidesAttackWaves["hard"] = 12 +AtreidesAttackWaves = +{ + easy = 1, + normal = 5, + hard = 12 +} -ToHarvest = { } -ToHarvest["easy"] = 2500 -ToHarvest["normal"] = 3000 -ToHarvest["hard"] = 3500 +ToHarvest = +{ + easy = 2500, + normal = 3000, + hard = 3500 +} HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" } HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location } @@ -53,19 +59,12 @@ Messages = "Build a Silo to store additional Spice." } - -IdleHunt = function(actor) - if not actor.IsDead then - Trigger.OnIdle(actor, actor.Hunt) - end -end - Tick = function() if AtreidesArrived and atreides.HasNoRequiredUnits() then player.MarkCompletedObjective(KillAtreides) end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -86,14 +85,19 @@ Tick = function() Media.DisplayMessage(Messages[4], "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() player = Player.GetPlayer("Harkonnen") atreides = Player.GetPlayer("Atreides") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillAtreides = player.AddSecondaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") Trigger.OnRemovedFromWorld(HarkonnenConyard, function() local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) @@ -114,12 +118,12 @@ WorldLoaded = function() Reinforcements.Reinforce(player, HarkonnenReinforcements, HarkonnenEntryPath) end) - WavesLeft = AtreidesAttackWaves[Map.LobbyOption("difficulty")] + WavesLeft = AtreidesAttackWaves[Difficulty] SendReinforcements() end SendReinforcements = function() - local units = AtreidesReinforcements[Map.LobbyOption("difficulty")] + local units = AtreidesReinforcements[Difficulty] local delay = Utils.RandomInteger(AtreidesAttackDelay - DateTime.Seconds(2), AtreidesAttackDelay) AtreidesAttackDelay = AtreidesAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) if AtreidesAttackDelay < 0 then AtreidesAttackDelay = 0 end @@ -135,31 +139,3 @@ SendReinforcements = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillAtreides = player.AddSecondaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/harkonnen-01b/rules.yaml b/mods/d2k/maps/harkonnen-01b/rules.yaml index 21640684d1..1d110cfb33 100644 --- a/mods/d2k/maps/harkonnen-01b/rules.yaml +++ b/mods/d2k/maps/harkonnen-01b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen01b.lua + Scripts: campaign-global.lua, harkonnen01b.lua MissionData: Briefing: Mine the Spice from the Imperial Basin, before the Atreides try to seize the area. Execute anyone who tries to stop you.\n\nBuild Silos to store the Spice. Remember to place buildings on concrete foundations to prevent erosion and gradual decline. To build without concrete would be inefficient. Inefficiency will not be tolerated.\n BriefingVideo: H_BR01_E.VQA diff --git a/mods/d2k/maps/harkonnen-02a/harkonnen02a-AI.lua b/mods/d2k/maps/harkonnen-02a/harkonnen02a-AI.lua index 021015a580..57e42b695f 100644 --- a/mods/d2k/maps/harkonnen-02a/harkonnen02a-AI.lua +++ b/mods/d2k/maps/harkonnen-02a/harkonnen02a-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -14,6 +13,7 @@ AttackGroupSize = normal = 8, hard = 10 } + AttackDelays = { easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, @@ -23,108 +23,12 @@ AttackDelays = AtreidesInfantryTypes = { "light_inf" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(AtreidesBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if ABarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesInfantryTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() - ProduceInfantry() + IdlingUnits[atreides] = { } + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local toBuild = function() return AtreidesInfantryTypes end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + + DefendAndRepairBase(atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) + ProduceUnits(atreides, ABarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/harkonnen-02a/harkonnen02a.lua b/mods/d2k/maps/harkonnen-02a/harkonnen02a.lua index d599c43fe9..314a16c69e 100644 --- a/mods/d2k/maps/harkonnen-02a/harkonnen02a.lua +++ b/mods/d2k/maps/harkonnen-02a/harkonnen02a.lua @@ -9,35 +9,37 @@ AtreidesBase = { AConyard, APower1, APower2, ABarracks, AOutpost } -AtreidesReinforcements = { } -AtreidesReinforcements["easy"] = +AtreidesReinforcements = { - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" } -} + easy = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" } + }, -AtreidesReinforcements["normal"] = -{ - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -AtreidesReinforcements["hard"] = -{ - { "trike", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "trike", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } AtreidesAttackPaths = @@ -48,35 +50,19 @@ AtreidesAttackPaths = { AtreidesEntry2.Location, AtreidesRally3.Location } } -AtreidesAttackDelay = { } -AtreidesAttackDelay["easy"] = DateTime.Minutes(5) -AtreidesAttackDelay["normal"] = DateTime.Minutes(2) + DateTime.Seconds(40) -AtreidesAttackDelay["hard"] = DateTime.Minutes(1) + DateTime.Seconds(20) +AtreidesAttackDelay = +{ + easy = DateTime.Minutes(5), + normal = DateTime.Minutes(2) + DateTime.Seconds(40), + hard = DateTime.Minutes(1) + DateTime.Seconds(20) +} -AtreidesAttackWaves = { } -AtreidesAttackWaves["easy"] = 3 -AtreidesAttackWaves["normal"] = 6 -AtreidesAttackWaves["hard"] = 9 - -wave = 0 -SendAtreides = function() - Trigger.AfterDelay(AtreidesAttackDelay[Map.LobbyOption("difficulty")], function() - wave = wave + 1 - if wave > AtreidesAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(AtreidesAttackPaths) - local units = Reinforcements.ReinforceWithTransport(atreides, "carryall.reinforce", AtreidesReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendAtreides() - end) -end - -IdleHunt = function(unit) - Trigger.OnIdle(unit, unit.Hunt) -end +AtreidesAttackWaves = +{ + easy = 3, + normal = 6, + hard = 9 +} Tick = function() if player.HasNoRequiredUnits() then @@ -93,7 +79,9 @@ WorldLoaded = function() atreides = Player.GetPlayer("Atreides") player = Player.GetPlayer("Harkonnen") - InitObjectives() + InitObjectives(player) + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + KillAtreides = player.AddPrimaryObjective("Destroy all Atreides forces.") Camera.Position = HConyard.CenterPosition @@ -101,33 +89,7 @@ WorldLoaded = function() Utils.Do(atreides.GetGroundAttackers(), IdleHunt) end) - SendAtreides() + local path = function() return Utils.Random(AtreidesAttackPaths) end + SendCarryallReinforcements(atreides, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty]) Trigger.AfterDelay(0, ActivateAI) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - KillAtreides = player.AddPrimaryObjective("Destroy all Atreides forces.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/harkonnen-02a/rules.yaml b/mods/d2k/maps/harkonnen-02a/rules.yaml index c5d4d9964f..cf2942a270 100644 --- a/mods/d2k/maps/harkonnen-02a/rules.yaml +++ b/mods/d2k/maps/harkonnen-02a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen02a.lua, harkonnen02a-AI.lua + Scripts: campaign-global.lua, harkonnen02a.lua, harkonnen02a-AI.lua MissionData: Briefing: Strengthen your forces at our mining camp in the Imperial Basin. We must punish the Atreides for their insolence. Teach them the consequences of opposing House Harkonnen.\n\nOur radar will help you find your targets.\n BriefingVideo: H_BR02_E.VQA diff --git a/mods/d2k/maps/harkonnen-02b/harkonnen02b-AI.lua b/mods/d2k/maps/harkonnen-02b/harkonnen02b-AI.lua index 7049ed35fc..8db7627c02 100644 --- a/mods/d2k/maps/harkonnen-02b/harkonnen02b-AI.lua +++ b/mods/d2k/maps/harkonnen-02b/harkonnen02b-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -14,6 +13,7 @@ AttackGroupSize = normal = 8, hard = 10 } + AttackDelays = { easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, @@ -24,131 +24,14 @@ AttackDelays = AtreidesInfantryTypes = { "light_inf" } AtreidesVehicleTypes = { "trike" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(AtreidesBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if ABarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesInfantryTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if ALightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesVehicleTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() - ProduceInfantry() - ProduceVehicles() + IdlingUnits[atreides] = { } + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return AtreidesInfantryTypes end + local vehilcesToBuild = function() return AtreidesVehicleTypes end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + + DefendAndRepairBase(atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) + ProduceUnits(atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/harkonnen-02b/harkonnen02b.lua b/mods/d2k/maps/harkonnen-02b/harkonnen02b.lua index eb58d41036..9342d9a444 100644 --- a/mods/d2k/maps/harkonnen-02b/harkonnen02b.lua +++ b/mods/d2k/maps/harkonnen-02b/harkonnen02b.lua @@ -9,35 +9,37 @@ AtreidesBase = { AConyard, APower1, APower2, ABarracks, ALightFactory } -AtreidesReinforcements = { } -AtreidesReinforcements["easy"] = +AtreidesReinforcements = { - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" } -} + easy = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" } + }, -AtreidesReinforcements["normal"] = -{ - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -AtreidesReinforcements["hard"] = -{ - { "trike", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "trike", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } AtreidesAttackPaths = @@ -48,35 +50,19 @@ AtreidesAttackPaths = { AtreidesEntry2.Location, AtreidesRally3.Location } } -AtreidesAttackDelay = { } -AtreidesAttackDelay["easy"] = DateTime.Minutes(5) -AtreidesAttackDelay["normal"] = DateTime.Minutes(2) + DateTime.Seconds(40) -AtreidesAttackDelay["hard"] = DateTime.Minutes(1) + DateTime.Seconds(20) +AtreidesAttackDelay = +{ + easy = DateTime.Minutes(5), + normal = DateTime.Minutes(2) + DateTime.Seconds(40), + hard = DateTime.Minutes(1) + DateTime.Seconds(20) +} -AtreidesAttackWaves = { } -AtreidesAttackWaves["easy"] = 3 -AtreidesAttackWaves["normal"] = 6 -AtreidesAttackWaves["hard"] = 9 - -wave = 0 -SendAtreides = function() - Trigger.AfterDelay(AtreidesAttackDelay[Map.LobbyOption("difficulty")], function() - wave = wave + 1 - if wave > AtreidesAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(AtreidesAttackPaths) - local units = Reinforcements.ReinforceWithTransport(atreides, "carryall.reinforce", AtreidesReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendAtreides() - end) -end - -IdleHunt = function(unit) - Trigger.OnIdle(unit, unit.Hunt) -end +AtreidesAttackWaves = +{ + easy = 3, + normal = 6, + hard = 9 +} Tick = function() if player.HasNoRequiredUnits() then @@ -93,7 +79,9 @@ WorldLoaded = function() atreides = Player.GetPlayer("Atreides") player = Player.GetPlayer("Harkonnen") - InitObjectives() + InitObjectives(player) + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + KillAtreides = player.AddPrimaryObjective("Destroy all Atreides forces.") Camera.Position = HConyard.CenterPosition @@ -101,33 +89,7 @@ WorldLoaded = function() Utils.Do(atreides.GetGroundAttackers(), IdleHunt) end) - SendAtreides() + local path = function() return Utils.Random(AtreidesAttackPaths) end + SendCarryallReinforcements(atreides, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty]) Trigger.AfterDelay(0, ActivateAI) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - KillAtreides = player.AddPrimaryObjective("Destroy all Atreides forces.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/harkonnen-02b/rules.yaml b/mods/d2k/maps/harkonnen-02b/rules.yaml index 483ad53132..42f4d04023 100644 --- a/mods/d2k/maps/harkonnen-02b/rules.yaml +++ b/mods/d2k/maps/harkonnen-02b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen02b.lua, harkonnen02b-AI.lua + Scripts: campaign-global.lua, harkonnen02b.lua, harkonnen02b-AI.lua MissionData: Briefing: Strengthen your forces at our mining camp in the Imperial Basin. We must punish the Atreides for their insolence. Teach them the consequences of opposing House Harkonnen.\n\nOur radar will help you find your targets.\n BriefingVideo: H_BR02_E.VQA diff --git a/mods/d2k/maps/harkonnen-03a/harkonnen03a-AI.lua b/mods/d2k/maps/harkonnen-03a/harkonnen03a-AI.lua index a92a678f3e..b79fd8089b 100644 --- a/mods/d2k/maps/harkonnen-03a/harkonnen03a-AI.lua +++ b/mods/d2k/maps/harkonnen-03a/harkonnen03a-AI.lua @@ -1,4 +1,11 @@ -IdlingUnits = { } +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -17,141 +24,22 @@ AttackDelays = AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } AtreidesVehicleTypes = { "trike", "trike", "quad" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if IsAttacking then - return - end - IsAttacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - IsAttacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(AtreidesBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if ABarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesInfantryTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if ALightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesVehicleTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - Trigger.AfterDelay(0, InitAIUnits) + IdlingUnits[atreides] = { } + HarvesterKilled[atreides] = true + DefendAndRepairBase(atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) AConyard.Produce(HarkonnenUpgrades[1]) AConyard.Produce(HarkonnenUpgrades[2]) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end + local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + -- Finish the upgrades first before trying to build something Trigger.AfterDelay(DateTime.Seconds(14), function() - ProduceInfantry() - ProduceVehicles() + ProduceUnits(atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end) end diff --git a/mods/d2k/maps/harkonnen-03a/harkonnen03a.lua b/mods/d2k/maps/harkonnen-03a/harkonnen03a.lua index 9c3e8b233e..6154063d7d 100644 --- a/mods/d2k/maps/harkonnen-03a/harkonnen03a.lua +++ b/mods/d2k/maps/harkonnen-03a/harkonnen03a.lua @@ -1,3 +1,12 @@ +--[[ + Copyright 2007-2017 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. +]] + AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, ALightFactory, AOutpost, AConyard, ARefinery, ASilo } AtreidesBaseAreaTriggers = { @@ -53,7 +62,7 @@ AtreidesAttackWaves = hard = 9 } -AtreidesHunters = +AtreidesHunters = { { "trooper", "trooper", "trooper", "trooper" }, { "trike", "trike", "trike" }, @@ -69,7 +78,7 @@ AtreidesPaths = { AtreidesEntry3.Location, AtreidesRally3.Location } } -AtreidesHunterPaths = +AtreidesHunterPaths = { { AtreidesEntry4.Location, AtreidesRally4.Location }, { AtreidesEntry5.Location, AtreidesRally5.Location }, @@ -84,40 +93,10 @@ HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location } HarkonnenBaseBuildings = { "barracks", "light_factory" } HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" } -wave = 0 -SendAtreides = function() - Trigger.AfterDelay(AtreidesAttackDelay[Map.LobbyOption("difficulty")], function() - if player.IsObjectiveCompleted(KillAtreides) then - return - end - - wave = wave + 1 - if wave > AtreidesAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(AtreidesPaths) - local units = Reinforcements.ReinforceWithTransport(atreides, "carryall.reinforce", AtreidesReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendAtreides() - end) -end - MessageCheck = function(index) return #player.GetActorsByType(HarkonnenBaseBuildings[index]) > 0 and not player.HasPrerequisites({ HarkonnenUpgrades[index] }) end -SendHunters = function(areaTrigger, unit, path, check) - Trigger.OnEnteredFootprint(areaTrigger, function(a, id) - if not check and a.Owner == player then - local units = Reinforcements.ReinforceWithTransport(atreides, "carryall.reinforce", unit, path, { path[1] })[2] - Utils.Do(units, IdleHunt) - check = true - end - end) -end - Tick = function() if player.HasNoRequiredUnits() then atreides.MarkCompletedObjective(KillHarkonnen) @@ -128,12 +107,12 @@ Tick = function() player.MarkCompletedObjective(KillAtreides) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[atreides] then local units = atreides.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[atreides] = false + ProtectHarvester(units[1], atreides, AttackGroupSize[Difficulty]) end end @@ -146,7 +125,9 @@ WorldLoaded = function() atreides = Player.GetPlayer("Atreides") player = Player.GetPlayer("Harkonnen") - InitObjectives() + InitObjectives(player) + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + KillAtreides = player.AddPrimaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") Camera.Position = HConyard.CenterPosition @@ -154,43 +135,18 @@ WorldLoaded = function() Utils.Do(atreides.GetGroundAttackers(), IdleHunt) end) - SendAtreides() - ActivateAI() + local path = function() return Utils.Random(AtreidesPaths) end + local waveCondition = function() return player.IsObjectiveCompleted(KillAtreides) end + SendCarryallReinforcements(atreides, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition) + Trigger.AfterDelay(0, ActivateAI) Trigger.AfterDelay(DateTime.Minutes(2) + DateTime.Seconds(30), function() Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", HarkonnenReinforcements, HarkonnenPath, { HarkonnenPath[1] }) end) - SendHunters(AtreidesBaseAreaTriggers[1], AtreidesHunters[1], AtreidesHunterPaths[1], HuntersSent1) - SendHunters(AtreidesBaseAreaTriggers[1], AtreidesHunters[2], AtreidesHunterPaths[2], HuntersSent2) - SendHunters(AtreidesBaseAreaTriggers[2], AtreidesHunters[3], AtreidesHunterPaths[3], HuntersSent3) - SendHunters(AtreidesBaseAreaTriggers[2], AtreidesHunters[4], AtreidesHunterPaths[4], HuntersSent4) - SendHunters(AtreidesBaseAreaTriggers[3], AtreidesHunters[5], AtreidesHunterPaths[5], HuntersSent5) -end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - KillAtreides = player.AddPrimaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[1], AtreidesHunters[1], AtreidesHunterPaths[1]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[1], AtreidesHunters[2], AtreidesHunterPaths[2]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[3], AtreidesHunterPaths[3]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[4], AtreidesHunterPaths[4]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[3], AtreidesHunters[5], AtreidesHunterPaths[5]) end diff --git a/mods/d2k/maps/harkonnen-03a/rules.yaml b/mods/d2k/maps/harkonnen-03a/rules.yaml index 22abfebc3a..b15b893234 100644 --- a/mods/d2k/maps/harkonnen-03a/rules.yaml +++ b/mods/d2k/maps/harkonnen-03a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen03a.lua, harkonnen03a-AI.lua + Scripts: campaign-global.lua, harkonnen03a.lua, harkonnen03a-AI.lua MissionData: Briefing: Attack and destroy the Atreides base at Sietch Tabr. Strike hard and eliminate all resistance.\n\nHeavier Quad vehicles will be made available for your attack. Upgrade your Light Factory to gain access to these vehicles.\n BriefingVideo: H_BR03_E.VQA diff --git a/mods/d2k/maps/harkonnen-03b/harkonnen03b-AI.lua b/mods/d2k/maps/harkonnen-03b/harkonnen03b-AI.lua index 6b142317ae..5cf7d247e0 100644 --- a/mods/d2k/maps/harkonnen-03b/harkonnen03b-AI.lua +++ b/mods/d2k/maps/harkonnen-03b/harkonnen03b-AI.lua @@ -1,4 +1,11 @@ -IdlingUnits = { } +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -17,143 +24,27 @@ AttackDelays = AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } AtreidesVehicleTypes = { "trike", "trike", "quad" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if IsAttacking then - return - end - IsAttacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - IsAttacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(atreides, AtreidesInitialReinforcements, AtreidesInitialPath) + IdlingUnits[atreides] = Reinforcements.Reinforce(atreides, AtreidesInitialReinforcements, AtreidesInitialPath) - Utils.Do(AtreidesBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if ABarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesInfantryTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if ALightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(AtreidesVehicleTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) + DefendAndRepairBase(atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() + HarvesterKilled[atreides] = true Trigger.AfterDelay(0, InitAIUnits) AConyard.Produce(HarkonnenUpgrades[1]) AConyard.Produce(HarkonnenUpgrades[2]) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end + local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + -- Finish the upgrades first before trying to build something Trigger.AfterDelay(DateTime.Seconds(14), function() - ProduceInfantry() - ProduceVehicles() + ProduceUnits(atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end) end diff --git a/mods/d2k/maps/harkonnen-03b/harkonnen03b.lua b/mods/d2k/maps/harkonnen-03b/harkonnen03b.lua index 06cca7efdb..4b51896ef8 100644 --- a/mods/d2k/maps/harkonnen-03b/harkonnen03b.lua +++ b/mods/d2k/maps/harkonnen-03b/harkonnen03b.lua @@ -1,3 +1,12 @@ +--[[ + Copyright 2007-2017 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. +]] + AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, AWindTrap3, ALightFactory, AOutpost, AConyard, ARefinery, ASilo1, ASilo2, ASilo3, ASilo4 } AtreidesBaseAreaTriggers = { @@ -86,40 +95,10 @@ HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location } HarkonnenBaseBuildings = { "barracks", "light_factory" } HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" } -wave = 0 -SendAtreides = function() - Trigger.AfterDelay(AtreidesAttackDelay[Map.LobbyOption("difficulty")], function() - if player.IsObjectiveCompleted(KillAtreides) then - return - end - - wave = wave + 1 - if wave > AtreidesAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(AtreidesPaths) - local units = Reinforcements.ReinforceWithTransport(atreides, "carryall.reinforce", AtreidesReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendAtreides() - end) -end - MessageCheck = function(index) return #player.GetActorsByType(HarkonnenBaseBuildings[index]) > 0 and not player.HasPrerequisites({ HarkonnenUpgrades[index] }) end -SendHunters = function(areaTrigger, unit, path, check) - Trigger.OnEnteredFootprint(areaTrigger, function(a, id) - if not check and a.Owner == player then - local units = Reinforcements.ReinforceWithTransport(atreides, "carryall.reinforce", unit, path, { path[1] })[2] - Utils.Do(units, IdleHunt) - check = true - end - end) -end - Tick = function() if player.HasNoRequiredUnits() then atreides.MarkCompletedObjective(KillHarkonnen) @@ -130,12 +109,12 @@ Tick = function() player.MarkCompletedObjective(KillAtreides) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[atreides] then local units = atreides.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[atreides] = false + ProtectHarvester(units[1], atreides, AttackGroupSize[Difficulty]) end end @@ -148,7 +127,9 @@ WorldLoaded = function() atreides = Player.GetPlayer("Atreides") player = Player.GetPlayer("Harkonnen") - InitObjectives() + InitObjectives(player) + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + KillAtreides = player.AddPrimaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") Camera.Position = HConyard.CenterPosition @@ -156,42 +137,17 @@ WorldLoaded = function() Utils.Do(atreides.GetGroundAttackers(), IdleHunt) end) - SendAtreides() + local path = function() return Utils.Random(AtreidesPaths) end + local waveCondition = function() return player.IsObjectiveCompleted(KillAtreides) end + SendCarryallReinforcements(atreides, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition) ActivateAI() Trigger.AfterDelay(DateTime.Minutes(2) + DateTime.Seconds(30), function() Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", HarkonnenReinforcements, HarkonnenPath, { HarkonnenPath[1] }) end) - SendHunters(AtreidesBaseAreaTriggers[1], AtreidesHunters[1], AtreidesHunterPaths[1], HuntersSent1) - SendHunters(AtreidesBaseAreaTriggers[2], AtreidesHunters[2], AtreidesHunterPaths[2], HuntersSent2) - SendHunters(AtreidesBaseAreaTriggers[3], AtreidesHunters[3], AtreidesHunterPaths[3], HuntersSent3) - SendHunters(AtreidesBaseAreaTriggers[4], AtreidesHunters[4], AtreidesHunterPaths[4], HuntersSent4) -end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - KillAtreides = player.AddPrimaryObjective("Eliminate all Atreides units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[1], AtreidesHunters[1], AtreidesHunterPaths[1]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[2], AtreidesHunterPaths[2]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[3], AtreidesHunters[3], AtreidesHunterPaths[3]) + TriggerCarryallReinforcements(player, atreides, AtreidesBaseAreaTriggers[4], AtreidesHunters[4], AtreidesHunterPaths[4]) end diff --git a/mods/d2k/maps/harkonnen-03b/rules.yaml b/mods/d2k/maps/harkonnen-03b/rules.yaml index c8c4c01645..da91aebaad 100644 --- a/mods/d2k/maps/harkonnen-03b/rules.yaml +++ b/mods/d2k/maps/harkonnen-03b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen03b.lua, harkonnen03b-AI.lua + Scripts: campaign-global.lua, harkonnen03b.lua, harkonnen03b-AI.lua MissionData: Briefing: Attack and destroy the Atreides base at Sietch Tabr. Strike hard and eliminate all resistance.\n\nHeavier Quad vehicles will be made available for your attack. Upgrade your Light Factory to gain access to these vehicles.\n BriefingVideo: H_BR03_E.VQA diff --git a/mods/d2k/maps/harkonnen-04/harkonnen04-AI.lua b/mods/d2k/maps/harkonnen-04/harkonnen04-AI.lua index a647f84f6d..525ac463ba 100644 --- a/mods/d2k/maps/harkonnen-04/harkonnen04-AI.lua +++ b/mods/d2k/maps/harkonnen-04/harkonnen04-AI.lua @@ -1,4 +1,11 @@ -IdlingUnits = { } +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -18,168 +25,21 @@ AtreidesInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "troop AtreidesVehicleTypes = { "trike", "trike", "quad" } AtreidesTankType = { "combat_tank_a" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Difficulty] do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, IdleHunt) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if Defending then - return - end - Defending = true - - -- Don't try to attack spiceblooms - if attacker and attacker.Type == "spicebloom" then - return - end - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - Defending = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() Defending = false end) - end) -end - -InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(atreides, InitialAtreidesReinforcements[1], AtreidesPaths[2]), Reinforcements.Reinforce(atreides, InitialAtreidesReinforcements[2], AtreidesPaths[3]) -end - -RepairBase = function(house) - Utils.Do(Base[house.Name], function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Owner == house and building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if ABarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - local toBuild = { Utils.Random(AtreidesInfantryTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if ALightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - local toBuild = { Utils.Random(AtreidesVehicleTypes) } - atreides.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) -end - -ProduceTanks = function() - if AHeavyFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Seconds(30), ProduceTanks) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - atreides.Build(AtreidesTankType, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceTanks) - - if #IdlingUnits >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() + IdlingUnits[fremen] = { } + IdlingUnits[atreides] = Reinforcements.Reinforce(atreides, InitialAtreidesReinforcements[1], AtreidesPaths[2]), Reinforcements.Reinforce(atreides, InitialAtreidesReinforcements[2], AtreidesPaths[3]) FremenProduction() - - RepairBase(atreides) - RepairBase(fremen) - ProduceInfantry() - ProduceVehicles() - ProduceTanks() + DefendAndRepairBase(atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) + DefendAndRepairBase(fremen, FremenBase, 0.75, AttackGroupSize[Difficulty]) + + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end + local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end + local tanksToBuild = function() return AtreidesTankType end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + + ProduceUnits(atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(atreides, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/harkonnen-04/harkonnen04.lua b/mods/d2k/maps/harkonnen-04/harkonnen04.lua index 16947d4bca..7cd0c300f1 100644 --- a/mods/d2k/maps/harkonnen-04/harkonnen04.lua +++ b/mods/d2k/maps/harkonnen-04/harkonnen04.lua @@ -1,8 +1,14 @@ -Base = -{ - Atreides = { AConyard, AOutpost, ARefinery, AHeavyFactory, ALightFactory, AGunt1, AGunt2, ABarracks, ASilo, APower1, APower2, APower3, APower4, APower5, APower6 }, - Fremen = { FGunt1, FGunt2 } -} +--[[ + Copyright 2007-2017 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. +]] + +AtreidesBase = { AConyard, AOutpost, ARefinery, AHeavyFactory, ALightFactory, AGunt1, AGunt2, ABarracks, ASilo, APower1, APower2, APower3, APower4, APower5, APower6 } +FremenBase = { FGunt1, FGunt2 } BaseAreaTriggers = { @@ -110,55 +116,14 @@ FremenInterval = hard = { DateTime.Minutes(3) + DateTime.Seconds(40), DateTime.Minutes(4) } } -wave = 0 -SendFremen = function() - Trigger.AfterDelay(FremenAttackDelay[Difficulty], function() - if player.IsObjectiveCompleted(KillFremen) then - return - end - - wave = wave + 1 - if wave > FremenAttackWaves[Difficulty] then - return - end - - local entryPath = Utils.Random(FremenPaths) - local units = Reinforcements.ReinforceWithTransport(fremen, "carryall.reinforce", FremenReinforcements[Difficulty][wave], entryPath, { entryPath[1] })[2] - Utils.Do(units, function(unit) - unit.AttackMove(FremenAttackLocation) - IdleHunt(unit) - end) - - SendFremen() - end) -end - -SendHunters = function(areaTrigger, unit, path, house, objective, check) - Trigger.OnEnteredFootprint(areaTrigger, function(a, id) - if player.IsObjectiveCompleted(objective) then - return - end - - if not check and a.Owner == player then - local units = Reinforcements.ReinforceWithTransport(house, "carryall.reinforce", unit, path, { path[1] })[2] - Utils.Do(units, IdleHunt) - check = true - end - end) -end - FremenProduction = function() - Trigger.OnAllKilled(Sietches, function() - SietchesAreDestroyed = true - end) - if SietchesAreDestroyed then return end local delay = Utils.RandomInteger(FremenInterval[Difficulty][1], FremenInterval[Difficulty][2] + 1) fremen.Build({ "nsfremen" }, function() - Trigger.AfterDelay(delay, ProduceInfantry) + Trigger.AfterDelay(delay, FremenProduction) end) end @@ -177,12 +142,12 @@ Tick = function() player.MarkCompletedObjective(KillFremen) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[atreides] then local units = atreides.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[atreides] = false + ProtectHarvester(units[1], atreides, AttackGroupSize[Difficulty]) end end end @@ -192,18 +157,30 @@ WorldLoaded = function() fremen = Player.GetPlayer("Fremen") player = Player.GetPlayer("Harkonnen") - Difficulty = Map.LobbyOption("difficulty") - - InitObjectives() + InitObjectives(player) + KillAtreides = player.AddPrimaryObjective("Destroy the Atreiedes.") + KillFremen = player.AddPrimaryObjective("Destroy the Fremen.") + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") Camera.Position = HConyard.CenterPosition FremenAttackLocation = HConyard.Location - Trigger.OnAllKilledOrCaptured(Base[atreides.Name], function() + Trigger.OnAllKilledOrCaptured(AtreidesBase, function() Utils.Do(atreides.GetGroundAttackers(), IdleHunt) end) - SendFremen() + Trigger.OnAllKilled(Sietches, function() + SietchesAreDestroyed = true + end) + + local path = function() return Utils.Random(FremenPaths) end + local waveCondition = function() return player.IsObjectiveCompleted(KillFremen) end + local huntFunction = function(unit) + unit.AttackMove(FremenAttackLocation) + IdleHunt(unit) + end + SendCarryallReinforcements(fremen, 0, FremenAttackWaves[Difficulty], FremenAttackDelay[Difficulty], path, FremenReinforcements[Difficulty], waveCondition, huntFunction) + Actor.Create("upgrade.barracks", true, { Owner = atreides }) Actor.Create("upgrade.light", true, { Owner = atreides }) Trigger.AfterDelay(0, ActivateAI) @@ -217,36 +194,11 @@ WorldLoaded = function() Media.DisplayMessage("Fremen concentrations spotted to the North and Southwest.", "Mentat") end) - SendHunters(BaseAreaTriggers[1], AtreidesHunters, AtreidesPaths[1], atreides, KillAtreides, HuntersSent1) - SendHunters(BaseAreaTriggers[1], FremenHunters[1], FremenHunterPaths[3], fremen, KillFremen, HuntersSent2) - SendHunters(BaseAreaTriggers[2], FremenHunters[2], FremenHunterPaths[2], fremen, KillFremen, HuntersSent3) - SendHunters(BaseAreaTriggers[3], FremenHunters[3], FremenHunterPaths[1], fremen, KillFremen, HuntersSent4) -end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = player.AddPrimaryObjective("Destroy the Atreiedes.") - KillFremen = player.AddPrimaryObjective("Destroy the Fremen.") - KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) + local atreidesCondition = function() return player.IsObjectiveCompleted(KillAtreides) end + TriggerCarryallReinforcements(player, atreides, BaseAreaTriggers[1], AtreidesHunters, AtreidesPaths[1], atreidesCondition) + + local fremenCondition = function() return player.IsObjectiveCompleted(KillFremen) end + TriggerCarryallReinforcements(player, fremen, BaseAreaTriggers[1], FremenHunters[1], FremenHunterPaths[3], fremenCondition) + TriggerCarryallReinforcements(player, fremen, BaseAreaTriggers[2], FremenHunters[2], FremenHunterPaths[2], fremenCondition) + TriggerCarryallReinforcements(player, fremen, BaseAreaTriggers[3], FremenHunters[3], FremenHunterPaths[1], fremenCondition) end diff --git a/mods/d2k/maps/harkonnen-04/rules.yaml b/mods/d2k/maps/harkonnen-04/rules.yaml index 353897b4c0..f2e4bca9ab 100644 --- a/mods/d2k/maps/harkonnen-04/rules.yaml +++ b/mods/d2k/maps/harkonnen-04/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: harkonnen04.lua, harkonnen04-AI.lua + Scripts: campaign-global.lua, harkonnen04.lua, harkonnen04-AI.lua MissionData: Briefing: The native Fremen must be dealt with. Assemble a strike force to lead a sweep through the mountains. Seek out the Fremen hold, and destroy it. If any House responds, destroy it.\n\nTanks have been deployed to grind the Fremen beneath their treads. Demonstrate the power of House Harkonnen. BriefingVideo: H_BR04_E.VQA diff --git a/mods/d2k/maps/ordos-01a/ordos01a.lua b/mods/d2k/maps/ordos-01a/ordos01a.lua index 2be3615af2..abd7ee9b1c 100644 --- a/mods/d2k/maps/ordos-01a/ordos01a.lua +++ b/mods/d2k/maps/ordos-01a/ordos01a.lua @@ -7,40 +7,46 @@ information, see COPYING. ]] -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "light_inf" } -} + easy = + { + { "light_inf", "light_inf" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location } HarkonnenAttackDelay = DateTime.Seconds(30) -HarkonnenAttackWaves = { } -HarkonnenAttackWaves["easy"] = 1 -HarkonnenAttackWaves["normal"] = 5 -HarkonnenAttackWaves["hard"] = 12 +HarkonnenAttackWaves = +{ + easy = 1, + normal = 5, + hard = 12 +} -ToHarvest = { } -ToHarvest["easy"] = 2500 -ToHarvest["normal"] = 3000 -ToHarvest["hard"] = 3500 +ToHarvest = +{ + easy = 2500, + normal = 3000, + hard = 3500 +} OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" } OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location } @@ -53,19 +59,12 @@ Messages = "Build a Silo to store additional Spice." } - -IdleHunt = function(actor) - if not actor.IsDead then - Trigger.OnIdle(actor, actor.Hunt) - end -end - Tick = function() if HarkonnenArrived and harkonnen.HasNoRequiredUnits() then player.MarkCompletedObjective(KillHarkonnen) end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -86,14 +85,19 @@ Tick = function() Media.DisplayMessage(Messages[4], "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() player = Player.GetPlayer("Ordos") harkonnen = Player.GetPlayer("Harkonnen") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") Trigger.OnRemovedFromWorld(OrdosConyard, function() local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) @@ -114,12 +118,12 @@ WorldLoaded = function() Reinforcements.Reinforce(player, OrdosReinforcements, OrdosEntryPath) end) - WavesLeft = HarkonnenAttackWaves[Map.LobbyOption("difficulty")] + WavesLeft = HarkonnenAttackWaves[Difficulty] SendReinforcements() end SendReinforcements = function() - local units = HarkonnenReinforcements[Map.LobbyOption("difficulty")] + local units = HarkonnenReinforcements[Difficulty] local delay = Utils.RandomInteger(HarkonnenAttackDelay - DateTime.Seconds(2), HarkonnenAttackDelay) HarkonnenAttackDelay = HarkonnenAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) if HarkonnenAttackDelay < 0 then HarkonnenAttackDelay = 0 end @@ -135,31 +139,3 @@ SendReinforcements = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/ordos-01a/rules.yaml b/mods/d2k/maps/ordos-01a/rules.yaml index 39fbd235e9..8994ccf91b 100644 --- a/mods/d2k/maps/ordos-01a/rules.yaml +++ b/mods/d2k/maps/ordos-01a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos01a.lua + Scripts: campaign-global.lua, ordos01a.lua MissionData: Briefing: Spice is wealth. Serve the Ordos by harvesting Spice in the Imperial Basin. If Harkonnen forces attempt to interrupt the flow of the Spice - neutralize them.\n\nEfficiency dictates that Silos must be built to avoid loss of Spice. Build concrete foundations to avoid unnecessary damage from the elements. To do otherwise is wasteful. BriefingVideo: O_BR01_E.VQA diff --git a/mods/d2k/maps/ordos-01b/ordos01b.lua b/mods/d2k/maps/ordos-01b/ordos01b.lua index 5487467751..68cf01e4a4 100644 --- a/mods/d2k/maps/ordos-01b/ordos01b.lua +++ b/mods/d2k/maps/ordos-01b/ordos01b.lua @@ -7,40 +7,46 @@ information, see COPYING. ]] -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "light_inf" } -} + easy = + { + { "light_inf", "light_inf" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location, HarkonnenWaypoint4.Location } HarkonnenAttackDelay = DateTime.Seconds(30) -HarkonnenAttackWaves = { } -HarkonnenAttackWaves["easy"] = 1 -HarkonnenAttackWaves["normal"] = 5 -HarkonnenAttackWaves["hard"] = 12 +HarkonnenAttackWaves = +{ + easy = 1, + normal = 5, + hard = 12 +} -ToHarvest = { } -ToHarvest["easy"] = 2500 -ToHarvest["normal"] = 3000 -ToHarvest["hard"] = 3500 +ToHarvest = +{ + easy = 2500, + normal = 3000, + hard = 3500 +} OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" } OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location } @@ -53,19 +59,12 @@ Messages = "Build a Silo to store additional Spice." } - -IdleHunt = function(actor) - if not actor.IsDead then - Trigger.OnIdle(actor, actor.Hunt) - end -end - Tick = function() if HarkonnenArrived and harkonnen.HasNoRequiredUnits() then player.MarkCompletedObjective(KillHarkonnen) end - if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + if player.Resources > SpiceToHarvest - 1 then player.MarkCompletedObjective(GatherSpice) end @@ -86,14 +85,19 @@ Tick = function() Media.DisplayMessage(Messages[4], "Mentat") end - UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. SpiceToHarvest, player.Color) end WorldLoaded = function() player = Player.GetPlayer("Ordos") harkonnen = Player.GetPlayer("Harkonnen") - InitObjectives() + SpiceToHarvest = ToHarvest[Difficulty] + + InitObjectives(player) + KillAtreides = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(SpiceToHarvest) .. " Solaris worth of Spice.") + KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") Trigger.OnRemovedFromWorld(OrdosConyard, function() local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) @@ -114,12 +118,12 @@ WorldLoaded = function() Reinforcements.Reinforce(player, OrdosReinforcements, OrdosEntryPath) end) - WavesLeft = HarkonnenAttackWaves[Map.LobbyOption("difficulty")] + WavesLeft = HarkonnenAttackWaves[Difficulty] SendReinforcements() end SendReinforcements = function() - local units = HarkonnenReinforcements[Map.LobbyOption("difficulty")] + local units = HarkonnenReinforcements[Difficulty] local delay = Utils.RandomInteger(HarkonnenAttackDelay - DateTime.Seconds(2), HarkonnenAttackDelay) HarkonnenAttackDelay = HarkonnenAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) if HarkonnenAttackDelay < 0 then HarkonnenAttackDelay = 0 end @@ -135,31 +139,3 @@ SendReinforcements = function() end end) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillAtreides = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") - KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/ordos-01b/rules.yaml b/mods/d2k/maps/ordos-01b/rules.yaml index 3937cacdc6..43ef9be36f 100644 --- a/mods/d2k/maps/ordos-01b/rules.yaml +++ b/mods/d2k/maps/ordos-01b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos01b.lua + Scripts: campaign-global.lua, ordos01b.lua MissionData: Briefing: Spice is wealth. Serve the Ordos by harvesting Spice in the Imperial Basin. If Harkonnen forces attempt to interrupt the flow of the Spice - neutralize them.\n\nEfficiency dictates that Silos must be built to avoid loss of Spice. Build concrete foundations to avoid unnecessary damage from the elements. To do otherwise is wasteful. BriefingVideo: O_BR01_E.VQA diff --git a/mods/d2k/maps/ordos-02a/ordos02a-AI.lua b/mods/d2k/maps/ordos-02a/ordos02a-AI.lua index 35d65c3fa1..595938de38 100644 --- a/mods/d2k/maps/ordos-02a/ordos02a-AI.lua +++ b/mods/d2k/maps/ordos-02a/ordos02a-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -14,6 +13,7 @@ AttackGroupSize = normal = 8, hard = 10 } + AttackDelays = { easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, @@ -23,108 +23,12 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() - ProduceInfantry() + IdlingUnits[harkonnen] = { } + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local toBuild = function() return HarkonnenInfantryTypes end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) + ProduceUnits(harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/ordos-02a/ordos02a.lua b/mods/d2k/maps/ordos-02a/ordos02a.lua index b6fa5ba3b7..7d6bfbc92a 100644 --- a/mods/d2k/maps/ordos-02a/ordos02a.lua +++ b/mods/d2k/maps/ordos-02a/ordos02a.lua @@ -10,35 +10,37 @@ HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks, HOutpost } HarkonnenBaseAreaTrigger = { CPos.New(31, 37), CPos.New(32, 37), CPos.New(33, 37), CPos.New(34, 37), CPos.New(35, 37), CPos.New(36, 37), CPos.New(37, 37), CPos.New(38, 37), CPos.New(39, 37), CPos.New(40, 37), CPos.New(41, 37), CPos.New(42, 37), CPos.New(42, 38), CPos.New(42, 39), CPos.New(42, 40), CPos.New(42, 41), CPos.New(42, 42), CPos.New(42, 43), CPos.New(42, 44), CPos.New(42, 45), CPos.New(42, 46), CPos.New(42, 47), CPos.New(42, 48), CPos.New(42, 49) } -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" } -} + easy = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "trike", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "trike", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenAttackPaths = @@ -61,49 +63,23 @@ InitialHarkonnenReinforcements = { "light_inf", "light_inf" } } -HarkonnenAttackDelay = { } -HarkonnenAttackDelay["easy"] = DateTime.Minutes(5) -HarkonnenAttackDelay["normal"] = DateTime.Minutes(2) + DateTime.Seconds(40) -HarkonnenAttackDelay["hard"] = DateTime.Minutes(1) + DateTime.Seconds(20) +HarkonnenAttackDelay = +{ + easy = DateTime.Minutes(5), + normal = DateTime.Minutes(2) + DateTime.Seconds(40), + hard = DateTime.Minutes(1) + DateTime.Seconds(20) +} -HarkonnenAttackWaves = { } -HarkonnenAttackWaves["easy"] = 3 -HarkonnenAttackWaves["normal"] = 6 -HarkonnenAttackWaves["hard"] = 9 +HarkonnenAttackWaves = +{ + easy = 3, + normal = 6, + hard = 9 +} OrdosReinforcements = { "light_inf", "light_inf", "raider" } OrdosEntryPath = { OrdosEntry.Location, OrdosRally.Location } -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Map.LobbyOption("difficulty")], function() - wave = wave + 1 - if wave > HarkonnenAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(HarkonnenAttackPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendHarkonnen() - end) -end - -IdleHunt = function(unit) - Trigger.OnIdle(unit, unit.Hunt) -end - -SendInitialUnits = function(areaTrigger, unit, path, check) - Trigger.OnEnteredFootprint(areaTrigger, function(a, id) - if not check and a.Owner == player then - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", unit, path, { path[1] })[2] - Utils.Do(units, IdleHunt) - check = true - end - end) -end - Tick = function() if player.HasNoRequiredUnits() then harkonnen.MarkCompletedObjective(KillOrdos) @@ -119,7 +95,9 @@ WorldLoaded = function() harkonnen = Player.GetPlayer("Harkonnen") player = Player.GetPlayer("Ordos") - InitObjectives() + InitObjectives(player) + KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") Camera.Position = OConyard.CenterPosition @@ -132,36 +110,10 @@ WorldLoaded = function() Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", OrdosReinforcements, OrdosEntryPath, { OrdosEntryPath[1] }) end) - SendInitialUnits(HarkonnenBaseAreaTrigger, InitialHarkonnenReinforcements[1], InitialHarkonnenReinforcementsPaths[1], InitialReinforcementsSent1) - SendInitialUnits(HarkonnenBaseAreaTrigger, InitialHarkonnenReinforcements[2], InitialHarkonnenReinforcementsPaths[2], InitialReinforcementsSent2) + TriggerCarryallReinforcements(player, harkonnen, HarkonnenBaseAreaTrigger, InitialHarkonnenReinforcements[1], InitialHarkonnenReinforcementsPaths[1]) + TriggerCarryallReinforcements(player, harkonnen, HarkonnenBaseAreaTrigger, InitialHarkonnenReinforcements[2], InitialHarkonnenReinforcementsPaths[2]) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenAttackPaths) end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty]) Trigger.AfterDelay(0, ActivateAI) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/ordos-02a/rules.yaml b/mods/d2k/maps/ordos-02a/rules.yaml index c56754e16b..a29ee83bfc 100644 --- a/mods/d2k/maps/ordos-02a/rules.yaml +++ b/mods/d2k/maps/ordos-02a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos02a.lua, ordos02a-AI.lua + Scripts: campaign-global.lua, ordos02a.lua, ordos02a-AI.lua MissionData: Briefing: Harkonnen forces are weakened in the Imperial Basin. Use the sensors in our Outpost to find them. Strike hard and destroy everything.\n BriefingVideo: O_BR02_E.VQA diff --git a/mods/d2k/maps/ordos-02b/ordos02b-AI.lua b/mods/d2k/maps/ordos-02b/ordos02b-AI.lua index 35d65c3fa1..595938de38 100644 --- a/mods/d2k/maps/ordos-02b/ordos02b-AI.lua +++ b/mods/d2k/maps/ordos-02b/ordos02b-AI.lua @@ -6,7 +6,6 @@ the License, or (at your option) any later version. For more information, see COPYING. ]] -IdlingUnits = { } AttackGroupSize = { @@ -14,6 +13,7 @@ AttackGroupSize = normal = 8, hard = 10 } + AttackDelays = { easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, @@ -23,108 +23,12 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf" } -AttackOnGoing = false -HoldProduction = false -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if Attacking then - return - end - Attacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - Attacking = false - HoldProduction = false - end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - -InitAIUnits = function() - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - ActivateAI = function() - InitAIUnits() - ProduceInfantry() + IdlingUnits[harkonnen] = { } + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local toBuild = function() return HarkonnenInfantryTypes end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) + ProduceUnits(harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) end diff --git a/mods/d2k/maps/ordos-02b/ordos02b.lua b/mods/d2k/maps/ordos-02b/ordos02b.lua index 20638c0306..12a7920e16 100644 --- a/mods/d2k/maps/ordos-02b/ordos02b.lua +++ b/mods/d2k/maps/ordos-02b/ordos02b.lua @@ -9,35 +9,37 @@ HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks, HOutpost } -HarkonnenReinforcements = { } -HarkonnenReinforcements["easy"] = +HarkonnenReinforcements = { - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" } -} + easy = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" } + }, -HarkonnenReinforcements["normal"] = -{ - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, -} + normal = + { + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" } + }, -HarkonnenReinforcements["hard"] = -{ - { "trike", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "trike" }, - { "light_inf", "light_inf", "light_inf", "trike", "trike" }, - { "light_inf", "light_inf" }, - { "trike", "trike" }, - { "light_inf", "light_inf", "light_inf" }, - { "light_inf", "trike" }, - { "trike", "trike" } + hard = + { + { "trike", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "trike" }, + { "light_inf", "light_inf", "light_inf", "trike", "trike" }, + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } + } } HarkonnenAttackPaths = @@ -62,26 +64,6 @@ HarkonnenAttackWaves = hard = 9 } -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Map.LobbyOption("difficulty")], function() - wave = wave + 1 - if wave > HarkonnenAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(HarkonnenAttackPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendHarkonnen() - end) -end - -IdleHunt = function(unit) - Trigger.OnIdle(unit, unit.Hunt) -end - Tick = function() if player.HasNoRequiredUnits() then harkonnen.MarkCompletedObjective(KillOrdos) @@ -97,7 +79,9 @@ WorldLoaded = function() harkonnen = Player.GetPlayer("Harkonnen") player = Player.GetPlayer("Ordos") - InitObjectives() + InitObjectives(player) + KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") Camera.Position = OConyard.CenterPosition @@ -105,33 +89,7 @@ WorldLoaded = function() Utils.Do(harkonnen.GetGroundAttackers(), IdleHunt) end) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenAttackPaths) end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty]) Trigger.AfterDelay(0, ActivateAI) end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - KillHarkonnen = player.AddPrimaryObjective("Destroy all Harkonnen forces.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) -end diff --git a/mods/d2k/maps/ordos-02b/rules.yaml b/mods/d2k/maps/ordos-02b/rules.yaml index c5f2ec3637..ac0751796e 100644 --- a/mods/d2k/maps/ordos-02b/rules.yaml +++ b/mods/d2k/maps/ordos-02b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos02b.lua, ordos02b-AI.lua + Scripts: campaign-global.lua, ordos02b.lua, ordos02b-AI.lua MissionData: Briefing: Harkonnen forces are weakened in the Imperial Basin. Use the sensors in our Outpost to find them. Strike hard and destroy everything.\n BriefingVideo: O_BR02_E.VQA diff --git a/mods/d2k/maps/ordos-03a/ordos03a-AI.lua b/mods/d2k/maps/ordos-03a/ordos03a-AI.lua index 29fc817363..d1a5204fac 100644 --- a/mods/d2k/maps/ordos-03a/ordos03a-AI.lua +++ b/mods/d2k/maps/ordos-03a/ordos03a-AI.lua @@ -1,4 +1,11 @@ -IdlingUnits = { } +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -17,143 +24,27 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } HarkonnenVehicleTypes = { "trike", "trike", "quad" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if IsAttacking then - return - end - IsAttacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - IsAttacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath) + IdlingUnits[harkonnen] = Reinforcements.Reinforce(harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath) - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if HLightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenVehicleTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() + HarvesterKilled[harkonnen] = true Trigger.AfterDelay(0, InitAIUnits) HConyard.Produce(OrdosUpgrades[1]) HConyard.Produce(OrdosUpgrades[2]) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end + local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + -- Finish the upgrades first before trying to build something Trigger.AfterDelay(DateTime.Seconds(14), function() - ProduceInfantry() - ProduceVehicles() + ProduceUnits(harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(harkonnen, HLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end) end diff --git a/mods/d2k/maps/ordos-03a/ordos03a.lua b/mods/d2k/maps/ordos-03a/ordos03a.lua index 9efa91f242..97d714cf97 100644 --- a/mods/d2k/maps/ordos-03a/ordos03a.lua +++ b/mods/d2k/maps/ordos-03a/ordos03a.lua @@ -1,3 +1,12 @@ +--[[ + Copyright 2007-2017 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. +]] + HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 } HarkonnenBaseAreaTrigger = { CPos.New(2, 58), CPos.New(3, 58), CPos.New(4, 58), CPos.New(5, 58), CPos.New(6, 58), CPos.New(7, 58), CPos.New(8, 58), CPos.New(9, 58), CPos.New(10, 58), CPos.New(11, 58), CPos.New(12, 58), CPos.New(13, 58), CPos.New(14, 58), CPos.New(15, 58), CPos.New(16, 58), CPos.New(16, 59), CPos.New(16, 60) } @@ -67,40 +76,10 @@ OrdosPath = { OrdosEntry.Location, OrdosRally.Location } OrdosBaseBuildings = { "barracks", "light_factory" } OrdosUpgrades = { "upgrade.barracks", "upgrade.light" } -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Map.LobbyOption("difficulty")], function() - if player.IsObjectiveCompleted(KillHarkonnen) then - return - end - - wave = wave + 1 - if wave > HarkonnenAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(HarkonnenPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendHarkonnen() - end) -end - MessageCheck = function(index) return #player.GetActorsByType(OrdosBaseBuildings[index]) > 0 and not player.HasPrerequisites({ OrdosUpgrades[index] }) end -SendHunters = function(areaTrigger, unit, path, check) - Trigger.OnEnteredFootprint(areaTrigger, function(a, id) - if not check and a.Owner == player then - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", unit, path, { path[1] })[2] - Utils.Do(units, IdleHunt) - check = true - end - end) -end - Tick = function() if player.HasNoRequiredUnits() then harkonnen.MarkCompletedObjective(KillOrdos) @@ -111,12 +90,12 @@ Tick = function() player.MarkCompletedObjective(KillHarkonnen) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[harkonnen] then local units = harkonnen.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[harkonnen] = false + ProtectHarvester(units[1], harkonnen, AttackGroupSize[Difficulty]) end end @@ -129,7 +108,9 @@ WorldLoaded = function() harkonnen = Player.GetPlayer("Harkonnen") player = Player.GetPlayer("Ordos") - InitObjectives() + InitObjectives(player) + KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + KillHarkonnen = player.AddPrimaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") Camera.Position = OConyard.CenterPosition @@ -137,39 +118,14 @@ WorldLoaded = function() Utils.Do(harkonnen.GetGroundAttackers(), IdleHunt) end) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenPaths) end + local waveCondition = function() return player.IsObjectiveCompleted(KillHarkonnen) end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition) ActivateAI() Trigger.AfterDelay(DateTime.Minutes(2) + DateTime.Seconds(30), function() Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", OrdosReinforcements, OrdosPath, { OrdosPath[1] }) end) - SendHunters(HarkonnenBaseAreaTrigger, HarkonnenHunters, HarkonnenHunterPath, HuntersSent) -end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - KillHarkonnen = player.AddPrimaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) + TriggerCarryallReinforcements(player, harkonnen, HarkonnenBaseAreaTrigger, HarkonnenHunters, HarkonnenHunterPath) end diff --git a/mods/d2k/maps/ordos-03a/rules.yaml b/mods/d2k/maps/ordos-03a/rules.yaml index 6afd90147e..fec7b69ad9 100644 --- a/mods/d2k/maps/ordos-03a/rules.yaml +++ b/mods/d2k/maps/ordos-03a/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos03a.lua, ordos03a-AI.lua + Scripts: campaign-global.lua, ordos03a.lua, ordos03a-AI.lua MissionData: Briefing: The Harkonnen hinder the production of Spice. A Harkonnen attack will disrupt efficient production. Inefficiency cannot be tolerated. The Harkonnen must be eliminated.\n\nNew weapons are available - the Quads. Newer weapons are more powerful. Powerful weapons ensure victory. BriefingVideo: O_BR03_E.VQA diff --git a/mods/d2k/maps/ordos-03b/ordos03b-AI.lua b/mods/d2k/maps/ordos-03b/ordos03b-AI.lua index 29fc817363..d1a5204fac 100644 --- a/mods/d2k/maps/ordos-03b/ordos03b-AI.lua +++ b/mods/d2k/maps/ordos-03b/ordos03b-AI.lua @@ -1,4 +1,11 @@ -IdlingUnits = { } +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -17,143 +24,27 @@ AttackDelays = HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } HarkonnenVehicleTypes = { "trike", "trike", "quad" } -HarvesterKilled = true - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function() - local units = { } - - for i = 0, AttackGroupSize[Map.LobbyOption("difficulty")], 1 do - if #IdlingUnits == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits + 1) - - if IdlingUnits[number] and not IdlingUnits[number].IsDead then - units[i] = IdlingUnits[number] - table.remove(IdlingUnits, number) - end - end - - return units -end - -SendAttack = function() - if IsAttacking then - return - end - IsAttacking = true - HoldProduction = true - - local units = SetupAttackGroup() - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - IsAttacking = false - HoldProduction = false - end) -end - -ProtectHarvester = function(unit) - DefendActor(unit) - Trigger.OnKilled(unit, function() HarvesterKilled = true end) -end - -DefendActor = function(unit) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing then - return - end - AttackOnGoing = true - - local Guards = SetupAttackGroup() - - if #Guards <= 0 then - AttackOnGoing = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing = false end) - end) -end - InitAIUnits = function() - IdlingUnits = Reinforcements.Reinforce(harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath) + IdlingUnits[harkonnen] = Reinforcements.Reinforce(harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath) - Utils.Do(HarkonnenBase, function(actor) - DefendActor(actor) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 then - building.StartBuildingRepairs() - end - end) - end) -end - -ProduceInfantry = function() - if HBarracks.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceInfantry) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenInfantryTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceInfantry) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) -end - -ProduceVehicles = function() - if HLightFactory.IsDead then - return - end - - if HoldProduction then - Trigger.AfterDelay(DateTime.Minutes(1), ProduceVehicles) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Map.LobbyOption("difficulty")][1], AttackDelays[Map.LobbyOption("difficulty")][2] + 1) - local toBuild = { Utils.Random(HarkonnenVehicleTypes) } - harkonnen.Build(toBuild, function(unit) - IdlingUnits[#IdlingUnits + 1] = unit[1] - Trigger.AfterDelay(delay, ProduceVehicles) - - if #IdlingUnits >= (AttackGroupSize[Map.LobbyOption("difficulty")] * 2.5) then - SendAttack() - end - end) + DefendAndRepairBase(harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() + HarvesterKilled[harkonnen] = true Trigger.AfterDelay(0, InitAIUnits) HConyard.Produce(OrdosUpgrades[1]) HConyard.Produce(OrdosUpgrades[2]) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end + local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end + local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 + -- Finish the upgrades first before trying to build something Trigger.AfterDelay(DateTime.Seconds(14), function() - ProduceInfantry() - ProduceVehicles() + ProduceUnits(harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) + ProduceUnits(harkonnen, HLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) end) end diff --git a/mods/d2k/maps/ordos-03b/ordos03b.lua b/mods/d2k/maps/ordos-03b/ordos03b.lua index 0ade233892..a4db82cab2 100644 --- a/mods/d2k/maps/ordos-03b/ordos03b.lua +++ b/mods/d2k/maps/ordos-03b/ordos03b.lua @@ -1,3 +1,12 @@ +--[[ + Copyright 2007-2017 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. +]] + HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HWindTrap3, HWindTrap4, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 } HarkonnenBaseAreaTrigger = { CPos.New(2, 58), CPos.New(3, 58), CPos.New(4, 58), CPos.New(5, 58), CPos.New(6, 58), CPos.New(7, 58), CPos.New(8, 58), CPos.New(9, 58), CPos.New(10, 58), CPos.New(11, 58), CPos.New(12, 58), CPos.New(13, 58), CPos.New(14, 58), CPos.New(15, 58), CPos.New(16, 58), CPos.New(16, 59), CPos.New(16, 60) } @@ -96,40 +105,10 @@ OrdosReinforcementDelays = OrdosBaseBuildings = { "barracks", "light_factory" } OrdosUpgrades = { "upgrade.barracks", "upgrade.light" } -wave = 0 -SendHarkonnen = function() - Trigger.AfterDelay(HarkonnenAttackDelay[Map.LobbyOption("difficulty")], function() - if player.IsObjectiveCompleted(KillHarkonnen) then - return - end - - wave = wave + 1 - if wave > HarkonnenAttackWaves[Map.LobbyOption("difficulty")] then - return - end - - local path = Utils.Random(HarkonnenPaths) - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", HarkonnenReinforcements[Map.LobbyOption("difficulty")][wave], path, { path[1] })[2] - Utils.Do(units, IdleHunt) - - SendHarkonnen() - end) -end - MessageCheck = function(index) return #player.GetActorsByType(OrdosBaseBuildings[index]) > 0 and not player.HasPrerequisites({ OrdosUpgrades[index] }) end -SendHunters = function(areaTrigger, unit, path, check) - Trigger.OnEnteredFootprint(areaTrigger, function(a, id) - if not check and a.Owner == player then - local units = Reinforcements.ReinforceWithTransport(harkonnen, "carryall.reinforce", unit, path, { path[1] })[2] - Utils.Do(units, IdleHunt) - check = true - end - end) -end - SendOrdosReinforcements = function(timer, unit, path) Trigger.AfterDelay(timer, function() Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", unit, path, { path[1] }) @@ -148,12 +127,12 @@ Tick = function() player.MarkCompletedObjective(KillHarkonnen) end - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[harkonnen] then local units = harkonnen.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled = false - ProtectHarvester(units[1]) + HarvesterKilled[harkonnen] = false + ProtectHarvester(units[1], harkonnen, AttackGroupSize[Difficulty]) end end @@ -166,7 +145,9 @@ WorldLoaded = function() harkonnen = Player.GetPlayer("Harkonnen") player = Player.GetPlayer("Ordos") - InitObjectives() + InitObjectives(player) + KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + KillHarkonnen = player.AddPrimaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") Camera.Position = OConyard.CenterPosition @@ -174,7 +155,9 @@ WorldLoaded = function() Utils.Do(harkonnen.GetGroundAttackers(), IdleHunt) end) - SendHarkonnen() + local path = function() return Utils.Random(HarkonnenPaths) end + local waveCondition = function() return player.IsObjectiveCompleted(KillHarkonnen) end + SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition) ActivateAI() SendOrdosReinforcements(OrdosReinforcementDelays[1], OrdosReinforcements[1], OrdosPaths[1]) @@ -184,34 +167,7 @@ WorldLoaded = function() Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", OrdosReinforcements[2], OrdosPaths[2], { OrdosPaths[2][1] }) end) - SendHunters(HarkonnenBaseAreaTrigger, HarkonnenHunters[1], HarkonnenHunterPaths[1], HuntersSent1) - SendHunters(HarkonnenBaseAreaTrigger, HarkonnenHunters[2], HarkonnenHunterPaths[2], HuntersSent2) - SendHunters(HarkonnenBaseAreaTrigger, HarkonnenHunters[3], HarkonnenHunterPaths[3], HuntersSent3) -end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - KillHarkonnen = player.AddPrimaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) - end) + TriggerCarryallReinforcements(player, harkonnen, HarkonnenBaseAreaTrigger, HarkonnenHunters[1], HarkonnenHunterPaths[1]) + TriggerCarryallReinforcements(player, harkonnen, HarkonnenBaseAreaTrigger, HarkonnenHunters[2], HarkonnenHunterPaths[2]) + TriggerCarryallReinforcements(player, harkonnen, HarkonnenBaseAreaTrigger, HarkonnenHunters[3], HarkonnenHunterPaths[3]) end diff --git a/mods/d2k/maps/ordos-03b/rules.yaml b/mods/d2k/maps/ordos-03b/rules.yaml index ab94d01146..aba6501201 100644 --- a/mods/d2k/maps/ordos-03b/rules.yaml +++ b/mods/d2k/maps/ordos-03b/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos03b.lua, ordos03b-AI.lua + Scripts: campaign-global.lua, ordos03b.lua, ordos03b-AI.lua MissionData: Briefing: The Harkonnen hinder the production of Spice. A Harkonnen attack will disrupt efficient production. Inefficiency cannot be tolerated. The Harkonnen must be eliminated.\n\nNew weapons are available - the Quads. Newer weapons are more powerful. Powerful weapons ensure victory. BriefingVideo: O_BR03_E.VQA diff --git a/mods/d2k/maps/ordos-04/ordos04-AI.lua b/mods/d2k/maps/ordos-04/ordos04-AI.lua index f4c7d37e94..8177a8664a 100644 --- a/mods/d2k/maps/ordos-04/ordos04-AI.lua +++ b/mods/d2k/maps/ordos-04/ordos04-AI.lua @@ -1,8 +1,11 @@ -IdlingUnits = -{ - Harkonnen = { }, - Smugglers = { } -} +--[[ + Copyright 2007-2017 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. +]] AttackGroupSize = { @@ -26,155 +29,30 @@ HarkonnenTankType = { "combat_tank_h" } SmugglerVehicleTypes = { "raider", "raider", "quad" } SmugglerTankType = { "combat_tank_o" } -IsAttacking = -{ - Harkonnen = false, - Smugglers = false -} - -AttackOnGoing = -{ - Harkonnen = false, - Smugglers = false -} - -HoldProduction = -{ - Harkonnen = false, - Smugglers = false -} - -HarvesterKilled = -{ - Harkonnen = true, - Smugglers = true -} - -IdleHunt = function(unit) if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end end - -SetupAttackGroup = function(house) - local units = { } - - for i = 0, AttackGroupSize[Difficulty], 1 do - if #IdlingUnits[house.Name] == 0 then - return units - end - - local number = Utils.RandomInteger(1, #IdlingUnits[house.Name]) - - if IdlingUnits[house.Name][number] and not IdlingUnits[house.Name][number].IsDead then - units[i] = IdlingUnits[house.Name][number] - table.remove(IdlingUnits[house.Name], number) - end - end - - return units -end - -SendAttack = function(house) - if IsAttacking[house.Name] then - return - end - IsAttacking[house.Name] = true - HoldProduction[house.Name] = true - - local units = SetupAttackGroup(house) - Utils.Do(units, function(unit) - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(units, function() - IsAttacking[house.Name] = false - HoldProduction[house.Name] = false - end) -end - -ProtectHarvester = function(unit, house) - DefendActor(unit, house) - Trigger.OnKilled(unit, function() HarvesterKilled[house.Name] = true end) -end - -DefendActor = function(unit, house) - Trigger.OnDamaged(unit, function(self, attacker) - if AttackOnGoing[house.Name] then - return - end - AttackOnGoing[house.Name] = true - - -- Don't try to attack spiceblooms - if attacker and attacker.Type == "spicebloom" then - return - end - - local Guards = SetupAttackGroup(house) - - if #Guards <= 0 then - AttackOnGoing[house.Name] = false - return - end - - Utils.Do(Guards, function(unit) - if not self.IsDead then - unit.AttackMove(self.Location) - end - IdleHunt(unit) - end) - - Trigger.OnAllRemovedFromWorld(Guards, function() AttackOnGoing[house.Name] = false end) - end) -end - InitAIUnits = function(house) - IdlingUnits[house.Name] = Reinforcements.Reinforce(house, InitialReinforcements[house.Name], InitialReinforcementsPaths[house.Name]) + HarvesterKilled[house] = true + IdlingUnits[house] = Reinforcements.Reinforce(house, InitialReinforcements[house.Name], InitialReinforcementsPaths[house.Name]) - Utils.Do(Base[house.Name], function(actor) - DefendActor(actor, house) - Trigger.OnDamaged(actor, function(building) - if building.Health < building.MaxHealth * 3/4 and building.Owner.Name == house.Name then - building.StartBuildingRepairs() - end - end) - end) -end - -Produce = function(house, units, factory) - if factory.IsDead then - return - end - - if HoldProduction[house.Name] then - Trigger.AfterDelay(DateTime.Seconds(30), function() Produce(house, units, factory) end) - return - end - - local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) - local toBuild = { Utils.Random(units) } - house.Build(toBuild, function(unit) - local unitCount = 1 - if IdlingUnits[house.Name] then - unitCount = 1 + #IdlingUnits[house.Name] - end - IdlingUnits[house.Name][unitCount] = unit[1] - Trigger.AfterDelay(delay, function() Produce(house, units, factory) end) - - if unitCount >= (AttackGroupSize[Difficulty] * 2.5) then - SendAttack(house) - end - end) + DefendAndRepairBase(house, Base[house.Name], 0.75, AttackGroupSize[Difficulty]) end ActivateAI = function() InitAIUnits(harkonnen) InitAIUnits(smuggler) - -- Finish the upgrades first before trying to build something - Trigger.AfterDelay(DateTime.Seconds(14), function() - Produce(harkonnen, EnemyInfantryTypes, HBarracks) - Produce(harkonnen, HarkonnenVehicleTypes, HLightFactory) - Produce(harkonnen, HarkonnenTankType, HHeavyFactory) - - Produce(smuggler, EnemyInfantryTypes, SBarracks) - Produce(smuggler, SmugglerVehicleTypes, SLightFactory) - Produce(smuggler, SmugglerTankType, SHeavyFactory) - end) + local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end + local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end + local hVehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end + local hTanksToBuild = function() return HarkonnenTankType end + local sVehiclesToBuild = function() return { Utils.Random(SmugglerVehicleTypes) } end + local sTanksToBuild = function() return SmugglerTankType end + local attackTresholdSize = AttackGroupSize[Difficulty] * 2.5 + + ProduceUnits(harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize) + ProduceUnits(harkonnen, HLightFactory, delay, hVehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize) + ProduceUnits(harkonnen, HHeavyFactory, delay, hTanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize) + + ProduceUnits(smuggler, SBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize) + ProduceUnits(smuggler, SLightFactory, delay, sVehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize) + ProduceUnits(smuggler, SHeavyFactory, delay, sTanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize) end diff --git a/mods/d2k/maps/ordos-04/ordos04.lua b/mods/d2k/maps/ordos-04/ordos04.lua index 725bd1831e..47a4df7802 100644 --- a/mods/d2k/maps/ordos-04/ordos04.lua +++ b/mods/d2k/maps/ordos-04/ordos04.lua @@ -1,3 +1,12 @@ +--[[ + Copyright 2007-2017 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. +]] + Base = { Harkonnen = { HRefinery, SHeavyFactory, SLightFactory, HGunTurret1, HGunTurret2, HGunTurret3, HGunTurret4, HGunTurret5, SBarracks, HPower1, HPower2, HPower3, HPower4 }, @@ -62,12 +71,12 @@ Hunt = function(house) end CheckHarvester = function(house) - if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[house.Name] then + if DateTime.GameTime % DateTime.Seconds(30) and HarvesterKilled[house] then local units = house.GetActorsByType("harvester") if #units > 0 then - HarvesterKilled[house.Name] = false - ProtectHarvester(units[1], house) + HarvesterKilled[house] = false + ProtectHarvester(units[1], house, AttackGroupSize[Difficulty]) end end end @@ -86,15 +95,6 @@ Tick = function() CheckHarvester(harkonnen) CheckHarvester(smuggler) - - if SOutpost.IsDead then - player.MarkFailedObjective(CaptureOutpost) - end - - if SOutpost.Owner == player then - player.MarkCompletedObjective(CaptureOutpost) - smuggler.MarkFailedObjective(DefendOutpost) - end end WorldLoaded = function() @@ -102,9 +102,12 @@ WorldLoaded = function() smuggler = Player.GetPlayer("Smugglers") player = Player.GetPlayer("Ordos") - Difficulty = Map.LobbyOption("difficulty") - - InitObjectives() + InitObjectives(player) + KillOrdosH = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + KillOrdosS = smuggler.AddSecondaryObjective("Kill all Ordos units.") + DefendOutpost = smuggler.AddPrimaryObjective("Don't let the outpost to be captured or destroyed.") + CaptureOutpost = player.AddPrimaryObjective("Capture the Smuggler Outpost.") + KillHarkonnen = player.AddSecondaryObjective("Destroy the Harkonnen.") Camera.Position = OConyard.CenterPosition HarkonnenAttackLocation = OConyard.Location @@ -115,12 +118,22 @@ WorldLoaded = function() SendHarkonnen(LightInfantryRushersPaths[1]) SendHarkonnen(LightInfantryRushersPaths[2]) SendHarkonnen(LightInfantryRushersPaths[3]) - ActivateAI() Actor.Create("upgrade.barracks", true, { Owner = harkonnen }) Actor.Create("upgrade.light", true, { Owner = harkonnen }) Actor.Create("upgrade.barracks", true, { Owner = smuggler }) Actor.Create("upgrade.light", true, { Owner = smuggler }) + Trigger.AfterDelay(0, ActivateAI) + + Trigger.OnKilled(SOutpost, function() + player.MarkFailedObjective(CaptureOutpost) + end) + Trigger.OnCapture(SOutpost, function() + Trigger.AfterDelay(DateTime.Seconds(2), function() + player.MarkCompletedObjective(CaptureOutpost) + smuggler.MarkFailedObjective(DefendOutpost) + end) + end) Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty] - DateTime.Seconds(5), function() Media.PlaySpeechNotification(player, "Reinforce") @@ -128,36 +141,6 @@ WorldLoaded = function() end) Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty], function() - Media.DisplayMessage("WARNING: Large force approaching!", "Mentat") - end) -end - -InitObjectives = function() - Trigger.OnObjectiveAdded(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") - end) - - KillOrdosH = harkonnen.AddPrimaryObjective("Kill all Ordos units.") - KillOrdosS = smuggler.AddSecondaryObjective("Kill all Ordos units.") - DefendOutpost = smuggler.AddPrimaryObjective("Don't let the outpost to be captured or destroyed.") - CaptureOutpost = player.AddPrimaryObjective("Capture the Smuggler Outpost.") - KillHarkonnen = player.AddSecondaryObjective("Destroy the Harkonnen.") - - Trigger.OnObjectiveCompleted(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") - end) - Trigger.OnObjectiveFailed(player, function(p, id) - Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") - end) - - Trigger.OnPlayerLost(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Lose") - end) - end) - Trigger.OnPlayerWon(player, function() - Trigger.AfterDelay(DateTime.Seconds(1), function() - Media.PlaySpeechNotification(player, "Win") - end) + Media.DisplayMessage("WARNING: Large force approaching!", "Mentat") end) end diff --git a/mods/d2k/maps/ordos-04/rules.yaml b/mods/d2k/maps/ordos-04/rules.yaml index 7f9a95f4ce..f94214410f 100644 --- a/mods/d2k/maps/ordos-04/rules.yaml +++ b/mods/d2k/maps/ordos-04/rules.yaml @@ -4,7 +4,7 @@ Player: World: LuaScript: - Scripts: ordos04.lua, ordos04-AI.lua + Scripts: campaign-global.lua, ordos04.lua, ordos04-AI.lua MissionData: Briefing: The Smugglers at Sietch Tabr must be neutralized. Capture the Outpost where their families have taken shelter as insurance. The children's lives will assure the loyalties of their fathers. Use an Engineer to enter and capture the building.\n\nThe Smugglers' new partners, the Harkonnen, may attempt to protect them. Harkonnen firepower is great, but we have recently acquired tanks that may counter this.\n\nEnsure our investment is used wisely.\n BriefingVideo: O_BR04_E.VQA diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 43768456ec..c8d6c9d57c 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -15,6 +15,7 @@ Packages: ~SOUND.RS d2k|bits + d2k|bits/scripts d2k|bits/tex d2k|uibits