Files
OpenRA/mods/d2k/maps/atreides-05/atreides05.lua
let5sne.win10 9cf6ebb986
Some checks failed
Continuous Integration / Linux (.NET 8.0) (push) Has been cancelled
Continuous Integration / Windows (.NET 8.0) (push) Has been cancelled
Initial commit: OpenRA game engine
Fork from OpenRA/OpenRA with one-click launch script (start-ra.cmd)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 21:46:54 +08:00

431 lines
16 KiB
Lua

--[[
Copyright (c) The OpenRA Developers and Contributors
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 }
HarkonnenReinforcements =
{
easy =
{
{ "combat_tank_h", "trooper", "trooper", "trooper", "trooper" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper" }
},
normal =
{
{ "combat_tank_h", "trooper", "trooper", "trooper", "trooper" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "combat_tank_h", "light_inf", "trooper", "trooper", "quad" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" }
},
hard =
{
{ "combat_tank_h", "trooper", "trooper", "trooper", "trooper" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "combat_tank_h", "light_inf", "trooper", "trooper", "quad" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" },
{ "combat_tank_h", "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" },
{ "combat_tank_h", "combat_tank_h", "combat_tank_h", "combat_tank_h", "combat_tank_h", "combat_tank_h" }
}
}
HarkonnenInfantryReinforcements =
{
normal =
{
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper", "trooper" }
},
hard =
{
{ "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper", "trooper" }
}
}
InfantryPath = { HarkonnenEntry3.Location }
HarkonnenAttackDelay =
{
easy = DateTime.Minutes(3),
normal = DateTime.Minutes(2) + DateTime.Seconds(20),
hard = DateTime.Minutes(1)
}
HarkonnenAttackWaves =
{
easy = 5,
normal = 7,
hard = 9
}
MercenaryReinforcements =
{
easy =
{
{ "combat_tank_o", "combat_tank_o", "quad", "quad", "light_inf", "light_inf", "light_inf", "light_inf" },
{ "trike", "trike", "quad", "quad", "quad", "trike", "trike", "trike" },
{ "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper" }
},
normal =
{
{ "trike", "trike", "quad", "quad", "quad", "trike", "trike", "trike" },
{ "combat_tank_o", "combat_tank_o", "quad", "quad", "light_inf", "light_inf", "light_inf", "light_inf" },
{ "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_o", "combat_tank_o", "quad", "quad", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper" },
{ "trike", "trike", "quad", "quad", "quad", "trike", "trike", "trike", "trike", "trike", "trike" },
{ "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper" }
},
hard =
{
{ "combat_tank_o", "combat_tank_o", "quad", "quad", "light_inf", "light_inf", "light_inf", "light_inf" },
{ "trike", "trike", "quad", "quad", "quad", "trike", "trike", "trike" },
{ "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper" },
{ "trike", "trike", "quad", "quad", "quad", "trike", "trike", "trike", "trike", "trike", "trike" },
{ "combat_tank_o", "combat_tank_o", "quad", "quad", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper" },
{ "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_o", "combat_tank_o", "quad", "quad", "trike", "trike", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper" },
{ "trike", "trike", "quad", "quad", "quad", "trike", "trike", "trike", "trike", "trike", "trike", "quad", "quad" },
{ "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "combat_tank_o", "trike", "trike", "quad", "quad", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper" }
}
}
MercenaryAttackDelay =
{
easy = DateTime.Minutes(2) + DateTime.Seconds(40),
normal = DateTime.Minutes(1) + DateTime.Seconds(50),
hard = DateTime.Minutes(1) + DateTime.Seconds(10)
}
MercenaryAttackWaves =
{
easy = 3,
normal = 6,
hard = 9
}
MercenarySpawn = { HarkonnenRally4.Location + CVec.New(2, -2) }
-- Ordos tanks because those were intended for the Smugglers not the Atreides
ContrabandReinforcements = { "mcv", "quad", "quad", "combat_tank_o", "combat_tank_o", "combat_tank_o" }
SmugglerReinforcements = { "quad", "quad", "trike", "trike" }
InitialHarkonnenReinforcements = { "trooper", "trooper", "quad", "quad", "trike", "trike", "trike", "light_inf" }
HarkonnenPaths =
{
{ HarkonnenEntry1.Location, HarkonnenRally1.Location },
{ HarkonnenEntry1.Location, HarkonnenRally3.Location },
{ HarkonnenEntry1.Location, HarkonnenRally2.Location },
{ HarkonnenEntry1.Location, HarkonnenRally4.Location },
{ HarkonnenEntry2.Location }
}
AtreidesReinforcements = { "trike", "combat_tank_a" }
AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location }
ContrabandTimes =
{
easy = DateTime.Minutes(10),
normal = DateTime.Minutes(5),
hard = DateTime.Minutes(2) + DateTime.Seconds(30)
}
Wave = 0
SendHarkonnen = function()
Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty], function()
if Atreides.IsObjectiveCompleted(KillHarkonnen) then
return
end
Wave = Wave + 1
if InfantryReinforcements and Wave % 4 == 0 then
local inf = Reinforcements.Reinforce(Harkonnen, HarkonnenInfantryReinforcements[Difficulty][Wave/4], InfantryPath)
Utils.Do(inf, function(unit)
unit.AttackMove(HarkonnenAttackLocation)
IdleHunt(unit)
end)
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)
if Wave < HarkonnenAttackWaves[Difficulty] then
SendHarkonnen()
return
end
Trigger.AfterDelay(DateTime.Seconds(3), function() LastHarkonnenArrived = true end)
end)
end
MercWave = 0
SendMercenaries = function()
Trigger.AfterDelay(MercenaryAttackDelay[Difficulty], function()
MercWave = MercWave + 1
Media.DisplayMessage(UserInterface.GetFluentMessage("incoming-mercenary-force"), Mentat)
local units = Reinforcements.Reinforce(Mercenary, MercenaryReinforcements[Difficulty][MercWave], MercenarySpawn)
Utils.Do(units, function(unit)
unit.AttackMove(MercenaryAttackLocation1)
unit.AttackMove(MercenaryAttackLocation2)
IdleHunt(unit)
end)
if MercWave < MercenaryAttackWaves[Difficulty] then
SendMercenaries()
return
end
Trigger.AfterDelay(DateTime.Seconds(3), function() LastMercenariesArrived = true end)
end)
end
SendContraband = function(owner)
ContrabandArrived = true
UserInterface.SetMissionText(UserInterface.GetFluentMessage("contraband-has-arrived"), Atreides.Color)
local units = SmugglerReinforcements
if owner == Atreides then
units = ContrabandReinforcements
end
Reinforcements.ReinforceWithTransport(owner, "frigate", units, { ContrabandEntry.Location, Starport.Location + CVec.New(1, 1) }, { ContrabandExit.Location })
Trigger.AfterDelay(DateTime.Seconds(3), function()
if owner == Atreides then
Atreides.MarkCompletedObjective(CaptureStarport)
Media.DisplayMessage(UserInterface.GetFluentMessage("contraband-confiscated"), Mentat)
else
Atreides.MarkFailedObjective(CaptureStarport)
Media.DisplayMessage(UserInterface.GetFluentMessage("contraband-not-confiscated"), Mentat)
end
end)
Trigger.AfterDelay(DateTime.Seconds(5), function()
UserInterface.SetMissionText("")
end)
end
SmugglersAttack = function()
Utils.Do(SmugglerBase, function(building)
if not building.IsDead and building.Owner == Smuggler then
building.Sell()
end
end)
Trigger.AfterDelay(DateTime.Seconds(1), function()
Utils.Do(Smuggler.GetGroundAttackers(), function(unit)
IdleHunt(unit)
end)
end)
end
AttackNotifier = 0
Tick = function()
if Atreides.HasNoRequiredUnits() then
Harkonnen.MarkCompletedObjective(KillAtreides)
end
if LastHarkonnenArrived and not Atreides.IsObjectiveCompleted(KillHarkonnen) and Harkonnen.HasNoRequiredUnits() then
Media.DisplayMessage(UserInterface.GetFluentMessage("harkonnen-annihilated"), Mentat)
Atreides.MarkCompletedObjective(KillHarkonnen)
end
if LastMercenariesArrived and not Atreides.IsObjectiveCompleted(KillSmuggler) and Smuggler.HasNoRequiredUnits() and Mercenary.HasNoRequiredUnits() then
Media.DisplayMessage(UserInterface.GetFluentMessage("smugglers-annihilated"), Mentat)
Atreides.MarkCompletedObjective(KillSmuggler)
end
if LastHarvesterEaten[Harkonnen] and DateTime.GameTime % DateTime.Seconds(10) == 0 then
local units = Harkonnen.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[Harkonnen] = false
ProtectHarvester(units[1], Harkonnen, AttackGroupSize[Difficulty])
end
end
AttackNotifier = AttackNotifier - 1
if TimerTicks and not ContrabandArrived then
TimerTicks = TimerTicks - 1
if (TimerTicks % DateTime.Seconds(1)) == 0 then
local contrabandArrivesIn = UserInterface.GetFluentMessage("contraband-arrives-in", { ["time"] = Utils.FormatTime(TimerTicks)})
UserInterface.SetMissionText(contrabandArrivesIn, Atreides.Color)
end
if TimerTicks <= 0 then
SendContraband(Smuggler)
end
end
end
WorldLoaded = function()
Harkonnen = Player.GetPlayer("Harkonnen")
Smuggler = Player.GetPlayer("Smugglers")
Mercenary = Player.GetPlayer("Mercenaries")
Atreides = Player.GetPlayer("Atreides")
InfantryReinforcements = Difficulty ~= "easy"
InitObjectives(Atreides)
KillAtreides = AddPrimaryObjective(Harkonnen, "")
CaptureBarracks = AddPrimaryObjective(Atreides, "capture-barracks-sietch-tabr")
KillHarkonnen = AddSecondaryObjective(Atreides, "annihilate-harkonnen-units-reinforcements")
CaptureStarport = AddSecondaryObjective(Atreides, "capture-smuggler-starport-confiscate-contraband")
Camera.Position = ARefinery.CenterPosition
HarkonnenAttackLocation = AtreidesRally.Location
MercenaryAttackLocation1 = Starport.Location + CVec.New(-16, 0)
MercenaryAttackLocation2 = Starport.Location
Trigger.AfterDelay(DateTime.Seconds(2), function()
TimerTicks = ContrabandTimes[Difficulty]
local time = Utils.FormatTime(TimerTicks)
local contrabandApproaching = UserInterface.GetFluentMessage("contraband-approaching-starport-north-in", { ["time"] = time })
Media.DisplayMessage(contrabandApproaching, Mentat)
end)
Trigger.OnAllKilledOrCaptured(HarkonnenBase, function()
Utils.Do(Harkonnen.GetGroundAttackers(), IdleHunt)
end)
Trigger.OnKilled(Starport, function()
if not Atreides.IsObjectiveCompleted(CaptureStarport) then
ContrabandArrived = true
UserInterface.SetMissionText(UserInterface.GetFluentMessage("starport-destroyed-no-contraband"), Atreides.Color)
Atreides.MarkFailedObjective(CaptureStarport)
SmugglersAttack()
Trigger.AfterDelay(DateTime.Seconds(15), function()
UserInterface.SetMissionText("")
end)
end
if DefendStarport then
Atreides.MarkFailedObjective(DefendStarport)
end
end)
Trigger.OnDamaged(Starport, function(_, attacker)
if Starport.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Atreides then
return
end
if AttackNotifier <= 0 then
AttackNotifier = DateTime.Seconds(10)
Media.DisplayMessage(UserInterface.GetFluentMessage("do-not-destroy-starport"), Mentat)
local defenders = Smuggler.GetGroundAttackers()
if #defenders > 0 then
Utils.Do(defenders, function(unit)
unit.Guard(Starport)
end)
end
end
end)
Trigger.OnCapture(Starport, function()
DefendStarport = AddSecondaryObjective(Atreides, "defend-captured-starport")
Trigger.ClearAll(Starport)
Trigger.AfterDelay(0, function()
Trigger.OnRemovedFromWorld(Starport, function()
Atreides.MarkFailedObjective(DefendStarport)
end)
end)
if not ContrabandArrived then
SendContraband(Atreides)
end
SmugglersAttack()
end)
Trigger.OnKilled(HarkonnenBarracks, function()
Atreides.MarkFailedObjective(CaptureBarracks)
end)
Trigger.OnDamaged(HarkonnenBarracks, function()
if AttackNotifier <= 0 and HarkonnenBarracks.Health < HarkonnenBarracks.MaxHealth * 3/4 then
AttackNotifier = DateTime.Seconds(10)
Media.DisplayMessage(UserInterface.GetFluentMessage("do-not-destroy-barracks"), Mentat)
end
end)
Trigger.OnCapture(HarkonnenBarracks, function()
Media.DisplayMessage(UserInterface.GetFluentMessage("hostages-released"), Mentat)
if DefendStarport then
Atreides.MarkCompletedObjective(DefendStarport)
end
Trigger.AfterDelay(DateTime.Seconds(3), function()
Atreides.MarkCompletedObjective(CaptureBarracks)
end)
end)
SendHarkonnen()
Actor.Create("upgrade.barracks", true, { Owner = Harkonnen })
Actor.Create("upgrade.light", true, { Owner = Harkonnen })
Actor.Create("upgrade.heavy", true, { Owner = Harkonnen })
Trigger.AfterDelay(0, ActivateAI)
Trigger.AfterDelay(DateTime.Minutes(1), function()
Media.PlaySpeechNotification(Atreides, "Reinforce")
Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements, AtreidesPath, { AtreidesPath[1] })
end)
local smugglerWaypoint = SmugglerWaypoint1.Location
Trigger.OnEnteredFootprint({ smugglerWaypoint + CVec.New(-2, 0), smugglerWaypoint + CVec.New(-1, 0), smugglerWaypoint, smugglerWaypoint + CVec.New(1, -1), smugglerWaypoint + CVec.New(2, -1), SmugglerWaypoint3.Location }, function(a, id)
if not Warned and a.Owner == Atreides and a.Type ~= "carryall" then
Warned = true
Trigger.RemoveFootprintTrigger(id)
Media.DisplayMessage(UserInterface.GetFluentMessage("stay-away-from-starport"), UserInterface.GetFluentMessage("smuggler-leader"))
end
end)
Trigger.OnEnteredFootprint({ SmugglerWaypoint2.Location }, function(a, id)
if not Paid and a.Owner == Atreides and a.Type ~= "carryall" then
Paid = true
Trigger.RemoveFootprintTrigger(id)
Media.DisplayMessage(UserInterface.GetFluentMessage("were-warned-will-pay"), UserInterface.GetFluentMessage("smuggler-leader"))
Utils.Do(Smuggler.GetGroundAttackers(), function(unit)
unit.AttackMove(SmugglerWaypoint2.Location)
end)
Trigger.AfterDelay(DateTime.Seconds(3), function()
KillSmuggler = AddSecondaryObjective(Atreides, "destroy-smugglers-mercenaries")
SendMercenaries()
end)
end
end)
Trigger.OnEnteredProximityTrigger(HarkonnenBarracks.CenterPosition, WDist.New(5 * 1024), function(a, id)
if a.Owner == Atreides and a.Type ~= "carryall" then
Trigger.RemoveProximityTrigger(id)
Media.DisplayMessage(UserInterface.GetFluentMessage("capture-harkonnen-barracks-release-hostages"), Mentat)
StopInfantryProduction = true
end
end)
end