Add a global script for campaign missions in d2k

This commit is contained in:
abcdefg30
2017-06-21 16:25:53 +02:00
committed by reaperrr
parent 7f0c7cee0d
commit a942ca8f57
63 changed files with 1168 additions and 3476 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -7,40 +7,46 @@
information, see COPYING.
]]
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "light_inf" }
}
},
HarkonnenReinforcements["normal"] =
{
normal =
{
{ "light_inf", "light_inf" },
{ "light_inf", "light_inf", "light_inf" },
{ "light_inf", "trike" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
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

View File

@@ -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

View File

@@ -7,40 +7,46 @@
information, see COPYING.
]]
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "light_inf" }
}
},
HarkonnenReinforcements["normal"] =
{
normal =
{
{ "light_inf", "light_inf" },
{ "light_inf", "light_inf", "light_inf" },
{ "light_inf", "trike" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
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

View File

@@ -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

View File

@@ -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

View File

@@ -9,26 +9,27 @@
HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks }
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "light_inf", "light_inf", "trike", "trike" }
}
},
HarkonnenReinforcements["normal"] =
{
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" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
hard =
{
{ "trike", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "trike" },
@@ -38,6 +39,7 @@ HarkonnenReinforcements["hard"] =
{ "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

View File

@@ -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

View File

@@ -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

View File

@@ -9,26 +9,27 @@
HarkonnenBase = { HConyard, HOutpost, HBarracks }
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "light_inf", "light_inf", "trike", "trike" }
}
},
HarkonnenReinforcements["normal"] =
{
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" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
hard =
{
{ "trike", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "trike" },
@@ -38,6 +39,7 @@ HarkonnenReinforcements["hard"] =
{ "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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -7,40 +7,46 @@
information, see COPYING.
]]
AtreidesReinforcements = { }
AtreidesReinforcements["easy"] =
AtreidesReinforcements =
{
easy =
{
{ "light_inf", "light_inf" }
}
},
AtreidesReinforcements["normal"] =
{
normal =
{
{ "light_inf", "light_inf" },
{ "light_inf", "light_inf", "light_inf" },
{ "light_inf", "trike" },
}
{ "light_inf", "trike" }
},
AtreidesReinforcements["hard"] =
{
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

View File

@@ -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

View File

@@ -7,40 +7,46 @@
information, see COPYING.
]]
AtreidesReinforcements = { }
AtreidesReinforcements["easy"] =
AtreidesReinforcements =
{
easy =
{
{ "light_inf", "light_inf" }
}
},
AtreidesReinforcements["normal"] =
{
normal =
{
{ "light_inf", "light_inf" },
{ "light_inf", "light_inf", "light_inf" },
{ "light_inf", "trike" },
}
{ "light_inf", "trike" }
},
AtreidesReinforcements["hard"] =
{
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

View File

@@ -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

View File

@@ -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

View File

@@ -9,26 +9,27 @@
AtreidesBase = { AConyard, APower1, APower2, ABarracks, AOutpost }
AtreidesReinforcements = { }
AtreidesReinforcements["easy"] =
AtreidesReinforcements =
{
easy =
{
{ "light_inf", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "light_inf", "light_inf", "trike", "trike" }
}
},
AtreidesReinforcements["normal"] =
{
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" },
}
{ "light_inf", "trike" }
},
AtreidesReinforcements["hard"] =
{
hard =
{
{ "trike", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "trike" },
@@ -38,6 +39,7 @@ AtreidesReinforcements["hard"] =
{ "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

View File

@@ -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

View File

@@ -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

View File

@@ -9,26 +9,27 @@
AtreidesBase = { AConyard, APower1, APower2, ABarracks, ALightFactory }
AtreidesReinforcements = { }
AtreidesReinforcements["easy"] =
AtreidesReinforcements =
{
easy =
{
{ "light_inf", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "light_inf", "light_inf", "trike", "trike" }
}
},
AtreidesReinforcements["normal"] =
{
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" },
}
{ "light_inf", "trike" }
},
AtreidesReinforcements["hard"] =
{
hard =
{
{ "trike", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "trike" },
@@ -38,6 +39,7 @@ AtreidesReinforcements["hard"] =
{ "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

View File

@@ -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

View File

@@ -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

View File

@@ -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 =
{
@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
DefendAndRepairBase(atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(fremen, FremenBase, 0.75, AttackGroupSize[Difficulty])
ProduceInfantry()
ProduceVehicles()
ProduceTanks()
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

View File

@@ -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

View File

@@ -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

View File

@@ -7,40 +7,46 @@
information, see COPYING.
]]
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "light_inf" }
}
},
HarkonnenReinforcements["normal"] =
{
normal =
{
{ "light_inf", "light_inf" },
{ "light_inf", "light_inf", "light_inf" },
{ "light_inf", "trike" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
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

View File

@@ -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

View File

@@ -7,40 +7,46 @@
information, see COPYING.
]]
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "light_inf" }
}
},
HarkonnenReinforcements["normal"] =
{
normal =
{
{ "light_inf", "light_inf" },
{ "light_inf", "light_inf", "light_inf" },
{ "light_inf", "trike" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
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

View File

@@ -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

View File

@@ -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

View File

@@ -10,26 +10,27 @@
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 =
{
easy =
{
{ "light_inf", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "light_inf", "light_inf", "trike", "trike" }
}
},
HarkonnenReinforcements["normal"] =
{
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" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
hard =
{
{ "trike", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "trike" },
@@ -39,6 +40,7 @@ HarkonnenReinforcements["hard"] =
{ "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

View File

@@ -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

View File

@@ -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

View File

@@ -9,26 +9,27 @@
HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks, HOutpost }
HarkonnenReinforcements = { }
HarkonnenReinforcements["easy"] =
HarkonnenReinforcements =
{
easy =
{
{ "light_inf", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "light_inf", "light_inf", "trike", "trike" }
}
},
HarkonnenReinforcements["normal"] =
{
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" },
}
{ "light_inf", "trike" }
},
HarkonnenReinforcements["hard"] =
{
hard =
{
{ "trike", "trike" },
{ "light_inf", "trike" },
{ "light_inf", "trike" },
@@ -38,6 +39,7 @@ HarkonnenReinforcements["hard"] =
{ "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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
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
Produce(smuggler, EnemyInfantryTypes, SBarracks)
Produce(smuggler, SmugglerVehicleTypes, SLightFactory)
Produce(smuggler, SmugglerTankType, SHeavyFactory)
end)
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

View File

@@ -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")
@@ -131,33 +144,3 @@ WorldLoaded = 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)
end)
end

View File

@@ -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

View File

@@ -15,6 +15,7 @@ Packages:
~SOUND.RS
d2k|bits
d2k|bits/scripts
d2k|bits/tex
d2k|uibits