Files
OpenRA/mods/ra/maps/evacuation/evacuation.lua
2023-03-28 11:45:15 +02:00

358 lines
11 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.
]]
DeathThreshold =
{
easy = 200,
normal = 100,
}
TanyaType = "e7"
if Difficulty ~= "easy" then
TanyaType = "e7.noautotarget"
end
RepairTriggerThreshold =
{
easy = 50,
normal = 75,
}
Sams = { Sam1, Sam2, Sam3, Sam4 }
TownUnits =
{
Einstein, Engineer,
TownUnit01, TownUnit02, TownUnit03, TownUnit04, TownUnit05, TownUnit06, TownUnit07,
TownUnit08, TownUnit09, TownUnit10, TownUnit11, TownUnit12, TownUnit13, TownUnit14,
}
ParabombDelay = DateTime.Seconds(30)
ParatroopersDelay = DateTime.Minutes(5)
Paratroopers =
{
{
proxy = "powerproxy.paras1",
entry = BadgerEntryPoint1.Location,
drop = BadgerDropPoint1.Location,
},
{
proxy = "powerproxy.paras2",
entry = BadgerEntryPoint1.Location + CVec.New(3, 0),
drop = BadgerDropPoint2.Location,
},
{
proxy = "powerproxy.paras2",
entry = BadgerEntryPoint1.Location + CVec.New(6, 0),
drop = BadgerDropPoint3.Location,
},
}
AttackGroup = { }
AttackGroupSize = 5
SovietInfantry = { "e1", "e2", "e3" }
SovietVehiclesUpgradeDelay = DateTime.Minutes(4)
SovietVehicleType = "Normal"
SovietVehicles =
{
Normal = { "3tnk" },
Upgraded = { "3tnk", "v2rl" },
}
ProductionInterval =
{
easy = DateTime.Seconds(10),
normal = DateTime.Seconds(2),
}
ReinforcementsDelay = DateTime.Minutes(16)
ReinforcementsUnits = { "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "1tnk", "1tnk", "jeep", "e1",
"e1", "e1", "e1", "e3", "e3", "mcv", "truk", "truk", "truk", "truk", "truk", "truk" }
SpawnAlliedReinforcements = function()
if Allies2.IsLocalPlayer then
UserInterface.SetMissionText("")
Media.PlaySpeechNotification(Allies2, "AlliedReinforcementsArrived")
end
Reinforcements.Reinforce(Allies2, ReinforcementsUnits, { ReinforcementsEntryPoint.Location, Allies2BasePoint.Location })
end
Yak = nil
YakAttack = function()
local targets = Map.ActorsInCircle(YakAttackPoint.CenterPosition, WDist.FromCells(10), function(a)
return a.Owner == Allies1 and not a.IsDead and a ~= Einstein and a ~= Tanya and a ~= Engineer and Yak.CanTarget(a)
end)
if (#targets > 0) then
Yak.Attack(Utils.Random(targets))
end
Yak.Move(Map.ClosestEdgeCell(Yak.Location))
Yak.Destroy()
Trigger.OnRemovedFromWorld(Yak, function()
Yak = nil
end)
end
SovietTownAttack = function()
local units = Utils.Shuffle(Utils.Where(Map.ActorsWithTag("TownAttacker"), function(a) return not a.IsDead end))
Utils.Do(Utils.Take(5, units), function(unit)
unit.AttackMove(TownPoint.Location)
Trigger.OnIdle(unit, unit.Hunt)
end)
end
SendParabombs = function()
local proxy = Actor.Create("powerproxy.parabombs", false, { Owner = Soviets })
proxy.TargetAirstrike(ParabombPoint1.CenterPosition, (BadgerEntryPoint2.CenterPosition - ParabombPoint1.CenterPosition).Facing)
proxy.TargetAirstrike(ParabombPoint2.CenterPosition, (Map.CenterOfCell(BadgerEntryPoint2.Location + CVec.New(0, 3)) - ParabombPoint2.CenterPosition).Facing)
proxy.Destroy()
end
SendParatroopers = function()
Utils.Do(Paratroopers, function(para)
local proxy = Actor.Create(para.proxy, false, { Owner = Soviets })
local target = Map.CenterOfCell(para.drop)
local dir = target - Map.CenterOfCell(para.entry)
local aircraft = proxy.TargetParatroopers(target, dir.Facing)
Utils.Do(aircraft, function(a)
Trigger.OnPassengerExited(a, function(t, p)
IdleHunt(p)
end)
end)
proxy.Destroy()
end)
end
SendAttackGroup = function()
if #AttackGroup < AttackGroupSize then
return
end
Utils.Do(AttackGroup, function(unit)
if not unit.IsDead then
Trigger.OnIdle(unit, unit.Hunt)
end
end)
AttackGroup = { }
end
ProduceInfantry = function()
if SovietBarracks.IsDead or SovietBarracks.Owner ~= Soviets then
return
end
Soviets.Build({ Utils.Random(SovietInfantry) }, function(units)
table.insert(AttackGroup, units[1])
SendAttackGroup()
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceInfantry)
end)
end
ProduceVehicles = function()
if SovietWarFactory.IsDead or SovietWarFactory.Owner ~= Soviets then
return
end
Soviets.Build({ Utils.Random(SovietVehicles[SovietVehicleType]) }, function(units)
table.insert(AttackGroup, units[1])
SendAttackGroup()
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceVehicles)
end)
end
NumBaseBuildings = function()
local buildings = Map.ActorsInBox(AlliedBaseTopLeft.CenterPosition, AlliedBaseBottomRight.CenterPosition, function(a)
return not a.IsDead and a.Owner == Allies2 and a.HasProperty("StartBuildingRepairs")
end)
return #buildings
end
Tick = function()
if DateTime.GameTime > 1 and DateTime.GameTime % 25 == 0 and NumBaseBuildings() == 0 then
Allies2.MarkFailedObjective(HoldPositionObjective)
end
if not Allies2.IsObjectiveCompleted(CutSovietPowerObjective) and Soviets.PowerState ~= "Normal" then
Allies2.MarkCompletedObjective(CutSovietPowerObjective)
end
if not Allies2.IsObjectiveCompleted(LimitLossesObjective) and Allies2.UnitsLost > DeathThreshold[Difficulty] then
Allies2.MarkFailedObjective(LimitLossesObjective)
end
if Allies2.IsLocalPlayer and DateTime.GameTime <= ReinforcementsDelay then
if DateTime.GameTime % DateTime.Seconds(1) == 0 then
local time = Utils.FormatTime(ReinforcementsDelay - DateTime.GameTime)
local timer = UserInterface.Translate("allied-reinforcements-arrive-in", { ["time"] = time })
UserInterface.SetMissionText(timer)
end
else
UserInterface.SetMissionText("")
end
end
SetupSoviets = function()
Soviets.Cash = 1000
if Difficulty == "easy" then
Utils.Do(Sams, function(sam)
local camera = Actor.Create("Camera.SAM", true, { Owner = Allies1, Location = sam.Location })
Trigger.OnKilledOrCaptured(sam, function()
camera.Destroy()
end)
end)
end
local buildings = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == Soviets and self.HasProperty("StartBuildingRepairs") end)
Utils.Do(buildings, function(actor)
Trigger.OnDamaged(actor, function(building)
if building.Owner == Soviets and building.Health < (building.MaxHealth * RepairTriggerThreshold[Difficulty] / 100) then
building.StartBuildingRepairs()
end
end)
end)
SovietBarracks.IsPrimaryBuilding = true
SovietBarracks.RallyPoint = SovietRallyPoint.Location
SovietWarFactory.IsPrimaryBuilding = true
SovietWarFactory.RallyPoint = SovietRallyPoint.Location
Trigger.AfterDelay(SovietVehiclesUpgradeDelay, function() SovietVehicleType = "Upgraded" end)
Trigger.AfterDelay(0, function()
ProduceInfantry()
ProduceVehicles()
end)
end
SetupTriggers = function()
Trigger.OnKilled(Tanya, function()
Allies1.MarkFailedObjective(TanyaMustSurviveObjective)
end)
Trigger.OnAllKilledOrCaptured(Sams, function()
Allies1.MarkCompletedObjective(DestroySamSitesObjective)
ExtractEinsteinObjective = AddPrimaryObjective(Allies1, "wait-for-helicopter-extract-einstein")
Actor.Create("flare", true, { Owner = Allies1, Location = ExtractionLZ.Location + CVec.New(1, -1) })
Beacon.New(Allies1, ExtractionLZ.CenterPosition)
Media.PlaySpeechNotification(Allies1, "SignalFlareNorth")
ExtractionHeli = Reinforcements.ReinforceWithTransport(Allies1, "tran", nil, { ExtractionLZEntryPoint.Location, ExtractionLZ.Location })[1]
Trigger.OnKilled(ExtractionHeli, function()
Allies1.MarkFailedObjective(ExtractEinsteinObjective)
end)
Trigger.OnPassengerEntered(ExtractionHeli, function(heli, passenger)
if passenger == Einstein then
heli.Move(ExtractionLZEntryPoint.Location)
heli.Destroy()
Trigger.OnRemovedFromWorld(heli, function()
Allies2.MarkCompletedObjective(LimitLossesObjective)
Allies2.MarkCompletedObjective(HoldPositionObjective)
Allies1.MarkCompletedObjective(TanyaMustSurviveObjective)
Allies1.MarkCompletedObjective(EinsteinSurvivalObjective)
Allies1.MarkCompletedObjective(ExtractEinsteinObjective)
end)
end
end)
end)
Trigger.OnEnteredProximityTrigger(TownPoint.CenterPosition, WDist.FromCells(15), function(actor, trigger)
if actor.Owner == Allies1 then
ReassignActors(TownUnits, Neutral, Allies1)
Utils.Do(TownUnits, function(a) a.Stance = "Defend" end)
Allies1.MarkCompletedObjective(FindEinsteinObjective)
EinsteinSurvivalObjective = AddPrimaryObjective(Allies1, "keep-einstein-alive-at-all-costs")
Trigger.OnKilled(Einstein, function()
Allies1.MarkFailedObjective(EinsteinSurvivalObjective)
end)
Trigger.RemoveProximityTrigger(trigger)
SovietTownAttack()
end
end)
Trigger.OnEnteredProximityTrigger(YakAttackPoint.CenterPosition, WDist.FromCells(5), function(actor, trigger)
if not (Yak == nil or Yak.IsDead) or actor.Owner ~= Allies1 then
return
end
Yak = Actor.Create("yak", true, { Owner = Soviets, Location = YakEntryPoint.Location, CenterPosition = YakEntryPoint.CenterPosition + WVec.New(0, 0, Actor.CruiseAltitude("yak")) })
Yak.Move(YakAttackPoint.Location + CVec.New(0, -10))
Yak.CallFunc(YakAttack)
end)
Trigger.AfterDelay(ParabombDelay, SendParabombs)
Trigger.AfterDelay(ParatroopersDelay, SendParatroopers)
Trigger.AfterDelay(ReinforcementsDelay, SpawnAlliedReinforcements)
end
SpawnTanya = function()
Tanya = Actor.Create(TanyaType, true, { Owner = Allies1, Location = TanyaLocation.Location })
if Difficulty ~= "easy" and Allies1.IsLocalPlayer then
Trigger.AfterDelay(DateTime.Seconds(2), function()
Media.DisplayMessage(UserInterface.Translate("tanya-rules-of-engagement"), UserInterface.Translate("tanya"))
end)
end
end
ReassignActors = function(actors, from, to)
Utils.Do(actors, function(a)
if a.Owner == from then
a.Owner = to
a.Stance = "Defend"
end
end)
end
WorldLoaded = function()
Neutral = Player.GetPlayer("Neutral")
-- Allies is the pre-set owner of units that get assigned to either the second player, if any, or the first player otherwise.
Allies = Player.GetPlayer("Allies")
-- Allies1 is the player starting on the right, controlling Tanya
Allies1 = Player.GetPlayer("Allies1")
-- Allies2 is the player starting on the left, defending the base
Allies2 = Player.GetPlayer("Allies2")
Soviets = Player.GetPlayer("Soviets")
Utils.Do({ Allies1, Allies2 }, function(player)
if player and player.IsLocalPlayer then
InitObjectives(player)
end
end)
if not Allies2 or Allies2.IsLocalPlayer then
Camera.Position = Allies2BasePoint.CenterPosition
else
Camera.Position = ChinookHusk.CenterPosition
end
if not Allies2 then
Allies2 = Allies1
end
ReassignActors(Map.ActorsInWorld, Allies, Allies2)
SpawnTanya()
TanyaMustSurviveObjective = AddPrimaryObjective(Allies1, "tanya-survive")
FindEinsteinObjective = AddPrimaryObjective(Allies1, "find-einstein-crashed-helicopter")
DestroySamSitesObjective = AddPrimaryObjective(Allies1, "destroy-sam-sites")
HoldPositionObjective = AddPrimaryObjective(Allies2, "hold-position-protect-base")
local dontLoseMoreThan = UserInterface.Translate("keep-civilians-alive", { ["units"] = DeathThreshold[Difficulty] })
LimitLossesObjective = AddSecondaryObjective(Allies2, dontLoseMoreThan)
CutSovietPowerObjective = AddSecondaryObjective(Allies2, "take-out-the-soviet-power-grid")
SetupTriggers()
SetupSoviets()
end