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>
This commit is contained in:
419
mods/ra/maps/survival01/survival01.lua
Normal file
419
mods/ra/maps/survival01/survival01.lua
Normal file
@@ -0,0 +1,419 @@
|
||||
--[[
|
||||
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.
|
||||
]]
|
||||
|
||||
if Difficulty == "easy" then
|
||||
AttackAtFrameIncrement = DateTime.Seconds(22)
|
||||
AttackAtFrameIncrementInf = DateTime.Seconds(16)
|
||||
TimerTicks = DateTime.Minutes(15)
|
||||
IncrementTurningPoint = TimerTicks / 2
|
||||
DamageModifier = 0.5
|
||||
LongBowReinforcements = { "heli", "heli" }
|
||||
ParadropArtillery = true
|
||||
elseif Difficulty == "normal" then
|
||||
AttackAtFrameIncrement = DateTime.Seconds(18)
|
||||
AttackAtFrameIncrementInf = DateTime.Seconds(12)
|
||||
TimerTicks = DateTime.Minutes(20)
|
||||
IncrementTurningPoint = TimerTicks / 2
|
||||
MoreParas = true
|
||||
DamageModifier = 0.75
|
||||
LongBowReinforcements = { "heli", "heli" }
|
||||
else --Difficulty == "hard"
|
||||
AttackAtFrameIncrement = DateTime.Seconds(14)
|
||||
AttackAtFrameIncrementInf = DateTime.Seconds(8)
|
||||
TimerTicks = DateTime.Minutes(25)
|
||||
IncrementTurningPoint = DateTime.Minutes(10)
|
||||
MoreParas = true
|
||||
AttackAtFrameNaval = DateTime.Minutes(3) + DateTime.Seconds(45)
|
||||
SpawnNavalUnits = true
|
||||
DamageModifier = 1
|
||||
LongBowReinforcements = { "heli" }
|
||||
end
|
||||
|
||||
AlliedAirReinforcementsWaypoints =
|
||||
{
|
||||
{ AirReinforcementsEntry1.Location, AirReinforcementsRally1.Location },
|
||||
{ AirReinforcementsEntry2.Location, AirReinforcementsRally2.Location }
|
||||
}
|
||||
FrenchReinforcements = { "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "1tnk", "1tnk", "1tnk", "arty", "arty", "arty", "jeep", "jeep" }
|
||||
|
||||
SpawningSovietUnits = true
|
||||
SpawningInfantry = true
|
||||
AttackAtFrameInf = DateTime.Seconds(12)
|
||||
AttackAtFrame = DateTime.Seconds(18)
|
||||
SovietAttackGroupSize = 5
|
||||
SovietInfantryGroupSize = 7
|
||||
FactoryClearRange = 10
|
||||
ParadropTicks = DateTime.Seconds(30)
|
||||
ParadropWaypoints =
|
||||
{
|
||||
{ Angle.East + Angle.New(16), ParaDrop1},
|
||||
{ Angle.East - Angle.New(16), ParaDrop2},
|
||||
{ Angle.East + Angle.New(16), Alliesbase2},
|
||||
{ Angle.East - Angle.New(16), Alliesbase1}
|
||||
}
|
||||
NavalTransportPassengers = { "e1", "e1", "e2", "e4", "e4" }
|
||||
NavalReinforcementsWaypoints = { NavalWaypoint1, NavalWaypoint2, NavalWaypoint2, NavalWaypoint3 }
|
||||
Squad1 = { "e1", "e1" }
|
||||
Squad2 = { "e2", "e2" }
|
||||
SovietVehicles = { "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "v2rl", "v2rl", "ftrk", "ftrk", "ftrk", "apc", "apc" }
|
||||
SovietInfantry = { "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e4", "e4", "e3" }
|
||||
SovietEntryPoints = { SovietEntryPoint1, SovietEntryPoint2, SovietEntryPoint3, SovietEntryPoint4, SovietEntryPoint5 }
|
||||
SovietRallyPoints = { SovietRallyPoint1, SovietRallyPoint2, SovietRallyPoint3, SovietRallyPoint4, SovietRallyPoint5 }
|
||||
SovietGateRallyPoints = { AlliesBaseGate2, AlliesBaseGate2, AlliesBaseGate1, AlliesBaseGate1, AlliesBaseGate1 }
|
||||
|
||||
Airfields = { SovietAirfield1, SovietAirfield2, SovietAirfield3 }
|
||||
SovietBuildings = { Barrack1, SubPen, RadarDome, AdvancedPowerPlant1, AdvancedPowerPlant2, AdvancedPowerPlant3, WarFactory, Refinery, Silo1, Silo2, FlameTower1, FlameTower2, FlameTower3, Sam1, Sam2, Sam3, Sam4, SovietAirfield1, SovietAirfield2, SovietAirfield3 }
|
||||
|
||||
IdleTrigger = function(units, _)
|
||||
Utils.Do(units, function(unit)
|
||||
|
||||
if not unit.IsDead then
|
||||
Trigger.OnIdle(unit, function()
|
||||
local bool = Utils.All(units, function(unit) return unit.IsIdle end)
|
||||
if bool then
|
||||
SetupHuntTrigger(units)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnDamaged(unit, function()
|
||||
SetupHuntTrigger(units)
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(unit, function()
|
||||
Trigger.ClearAll(unit)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
SetupHuntTrigger = function(units)
|
||||
Utils.Do(units, function(unit)
|
||||
if not unit.IsDead then
|
||||
Trigger.ClearAll(unit)
|
||||
Trigger.AfterDelay(0, function()
|
||||
if not unit.IsDead then
|
||||
Trigger.OnIdle(unit, unit.Hunt)
|
||||
Trigger.OnCapture(unit, function()
|
||||
Trigger.ClearAll(unit)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Ticked = TimerTicks
|
||||
Tick = function()
|
||||
if KillObj and Soviets.HasNoRequiredUnits() then
|
||||
Allies.MarkCompletedObjective(KillObj)
|
||||
end
|
||||
|
||||
if Allies.HasNoRequiredUnits() then
|
||||
Soviets.MarkCompletedObjective(SovietObj)
|
||||
end
|
||||
|
||||
if Soviets.Resources > Soviets.ResourceCapacity / 2 then
|
||||
Soviets.Resources = Soviets.ResourceCapacity / 2
|
||||
end
|
||||
|
||||
if Ticked > 0 then
|
||||
if DateTime.Minutes(20) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "TwentyMinutesRemaining")
|
||||
|
||||
elseif DateTime.Minutes(10) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "TenMinutesRemaining")
|
||||
|
||||
elseif DateTime.Minutes(5) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "WarningFiveMinutesRemaining")
|
||||
|
||||
elseif DateTime.Minutes(4) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "WarningFourMinutesRemaining")
|
||||
|
||||
Trigger.AfterDelay(ParadropTicks, function()
|
||||
SendSovietParadrops(ParadropWaypoints[3])
|
||||
SendSovietParadrops(ParadropWaypoints[2])
|
||||
end)
|
||||
Trigger.AfterDelay(ParadropTicks * 2, function()
|
||||
SendSovietParadrops(ParadropWaypoints[4])
|
||||
SendSovietParadrops(ParadropWaypoints[1])
|
||||
end)
|
||||
|
||||
elseif DateTime.Minutes(3) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "WarningThreeMinutesRemaining")
|
||||
|
||||
elseif DateTime.Minutes(2) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "WarningTwoMinutesRemaining")
|
||||
|
||||
AttackAtFrameIncrement = DateTime.Seconds(4)
|
||||
AttackAtFrameIncrementInf = DateTime.Seconds(4)
|
||||
|
||||
elseif DateTime.Minutes(1) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "WarningOneMinuteRemaining")
|
||||
|
||||
elseif DateTime.Seconds(45) == Ticked then
|
||||
Media.PlaySpeechNotification(Allies, "AlliedForcesApproaching")
|
||||
end
|
||||
|
||||
if (Ticked % DateTime.Seconds(1)) == 0 then
|
||||
Timer = UserInterface.GetFluentMessage("french-reinforcements-arrive-in", { ["time"] = Utils.FormatTime(Ticked) })
|
||||
UserInterface.SetMissionText(Timer, TimerColor)
|
||||
end
|
||||
Ticked = Ticked - 1
|
||||
elseif Ticked == 0 then
|
||||
FinishTimer()
|
||||
TimerExpired()
|
||||
Ticked = Ticked - 1
|
||||
end
|
||||
end
|
||||
|
||||
FrenchAlliesArrived = UserInterface.GetFluentMessage("french-allies-arrived")
|
||||
FinishTimer = function()
|
||||
for i = 0, 9, 1 do
|
||||
local c = TimerColor
|
||||
if i % 2 == 0 then
|
||||
c = HSLColor.White
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(DateTime.Seconds(i), function() UserInterface.SetMissionText(FrenchAlliesArrived, c) end)
|
||||
end
|
||||
Trigger.AfterDelay(DateTime.Seconds(10), function() UserInterface.SetMissionText("") end)
|
||||
end
|
||||
|
||||
SendSovietParadrops = function(table)
|
||||
local aircraft = ParaTroopersPowerProxy.TargetParatroopers(table[2].CenterPosition, table[1])
|
||||
Utils.Do(aircraft, function(a)
|
||||
Trigger.OnPassengerExited(a, function(t, p)
|
||||
IdleHunt(p)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
SendSovietNavalReinforcements = function()
|
||||
if SpawnNavalUnits then
|
||||
local entry = NavalEntryPoint.Location
|
||||
local units = Reinforcements.ReinforceWithTransport(Soviets, "lst", NavalTransportPassengers, { entry, Utils.Random(NavalReinforcementsWaypoints).Location }, { entry })[2]
|
||||
Utils.Do(units, function(unit)
|
||||
Trigger.OnIdle(unit, unit.Hunt)
|
||||
end)
|
||||
|
||||
local delay = Utils.RandomInteger(AttackAtFrameNaval, AttackAtFrameNaval + DateTime.Minutes(2))
|
||||
|
||||
Trigger.AfterDelay(delay, SendSovietNavalReinforcements)
|
||||
end
|
||||
end
|
||||
|
||||
SpawnSovietInfantry = function()
|
||||
local units = { }
|
||||
for i = 0, SovietInfantryGroupSize - 1, 1 do
|
||||
local type = Utils.Random(SovietInfantry)
|
||||
units[i] = type
|
||||
end
|
||||
|
||||
Soviets.Build(units, function(soldiers)
|
||||
Trigger.AfterDelay(25, function() IdleTrigger(soldiers) end)
|
||||
end)
|
||||
end
|
||||
|
||||
SpawnSovietUnits = function()
|
||||
local units = { }
|
||||
for i = 0, SovietAttackGroupSize - 1, 1 do
|
||||
local type = Utils.Random(SovietVehicles)
|
||||
units[i] = type
|
||||
end
|
||||
|
||||
local route = Utils.RandomInteger(1, #SovietEntryPoints + 1)
|
||||
local attackers = Reinforcements.Reinforce(Soviets, units, { SovietEntryPoints[route].Location, SovietRallyPoints[route].Location })
|
||||
Trigger.AfterDelay(25, function()
|
||||
IdleTrigger(attackers, SovietGateRallyPoints[route].Location)
|
||||
end)
|
||||
end
|
||||
|
||||
SendInfantryWave = function()
|
||||
if SpawningInfantry then
|
||||
SpawnSovietInfantry()
|
||||
|
||||
if DateTime.GameTime < IncrementTurningPoint then
|
||||
AttackAtFrameIncrementInf = AttackAtFrameIncrementInf + Utils.RandomInteger(DateTime.Seconds(2), DateTime.Seconds(3))
|
||||
elseif not (AttackAtFrameIncrementInf <= DateTime.Seconds(4)) then
|
||||
AttackAtFrameIncrementInf = AttackAtFrameIncrementInf - Utils.RandomInteger(DateTime.Seconds(2), DateTime.Seconds(3))
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(AttackAtFrameInf + AttackAtFrameIncrementInf, SendInfantryWave)
|
||||
end
|
||||
end
|
||||
|
||||
SendVehicleWave = function()
|
||||
if SpawningSovietUnits then
|
||||
SpawnSovietUnits()
|
||||
|
||||
if DateTime.GameTime < IncrementTurningPoint then
|
||||
AttackAtFrameIncrement = AttackAtFrameIncrement + Utils.RandomInteger(DateTime.Seconds(4), DateTime.Seconds(6))
|
||||
elseif not (AttackAtFrameIncrement <= DateTime.Seconds(4)) then
|
||||
AttackAtFrameIncrement = AttackAtFrameIncrement - Utils.RandomInteger(DateTime.Seconds(4), DateTime.Seconds(6))
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(AttackAtFrame + AttackAtFrameIncrement, SendVehicleWave)
|
||||
end
|
||||
end
|
||||
|
||||
TimerExpired = function()
|
||||
SpawningSovietUnits = false
|
||||
SpawningInfantry = false
|
||||
SpawnNavalUnits = false
|
||||
|
||||
Beacon.New(Allies, SovietEntryPoint7.CenterPosition - WVec.New(3 * 1024, 0, 0))
|
||||
Media.PlaySpeechNotification(Allies, "AlliedReinforcementsArrived")
|
||||
Reinforcements.Reinforce(Allies, FrenchReinforcements, { SovietEntryPoint7.Location, Alliesbase.Location })
|
||||
|
||||
if DestroyObj then
|
||||
KillObj = AddPrimaryObjective(Allies, "takeover-reinforcements-kill-remaining-soviet-forces")
|
||||
else
|
||||
DestroyObj = AddPrimaryObjective(Allies, "takeover-reinforcements-dismantle-soviet-base")
|
||||
end
|
||||
|
||||
Allies.MarkCompletedObjective(SurviveObj)
|
||||
if not Allies.IsObjectiveCompleted(KillSams) then
|
||||
Allies.MarkFailedObjective(KillSams)
|
||||
end
|
||||
end
|
||||
|
||||
DropAlliedArtillery = function(facing, dropzone)
|
||||
local proxy = Actor.Create("powerproxy.allied", true, { Owner = Allies })
|
||||
proxy.TargetParatroopers(dropzone, facing)
|
||||
proxy.Destroy()
|
||||
end
|
||||
|
||||
SendLongBowReinforcements = function()
|
||||
Media.PlaySpeechNotification(Allies, "AlliedReinforcementsArrived")
|
||||
Reinforcements.Reinforce(Allies, LongBowReinforcements, AlliedAirReinforcementsWaypoints[1])
|
||||
Reinforcements.Reinforce(Allies, LongBowReinforcements, AlliedAirReinforcementsWaypoints[2])
|
||||
|
||||
if ParadropArtillery then
|
||||
local facing = Angle.New(Utils.RandomInteger(128, 384))
|
||||
DropAlliedArtillery(facing, Alliesbase.CenterPosition)
|
||||
end
|
||||
end
|
||||
|
||||
AddObjectives = function()
|
||||
InitObjectives(Allies)
|
||||
|
||||
SurviveObj = AddPrimaryObjective(Allies, "enforce-position-hold-until-reinforcements")
|
||||
KillSams = AddSecondaryObjective(Allies, "destroy-two-sams-before-reinforcements")
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("soviets-blocking-gps"))
|
||||
CaptureAirfields = AddSecondaryObjective(Allies, "capture-hold-soviet-airbase-northeast")
|
||||
SovietObj = AddPrimaryObjective(Soviets, "")
|
||||
|
||||
Trigger.OnPlayerWon(Allies, function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("french-survived-dismantled-soviet-presence"))
|
||||
end)
|
||||
end
|
||||
|
||||
InitMission = function()
|
||||
Camera.Position = Alliesbase.CenterPosition
|
||||
local camera1 = Actor.Create("camera.sam", true, { Owner = Allies, Location = Sam1.Location })
|
||||
local camera2 = Actor.Create("camera.sam", true, { Owner = Allies, Location = Sam2.Location })
|
||||
Trigger.OnKilled(Sam1, function()
|
||||
if camera1.IsInWorld then camera1.Destroy() end
|
||||
end)
|
||||
Trigger.OnKilled(Sam2, function()
|
||||
if camera2.IsInWorld then camera2.Destroy() end
|
||||
end)
|
||||
Trigger.OnAllKilledOrCaptured({ Sam1, Sam2 }, function()
|
||||
if not Allies.IsObjectiveFailed(KillSams) then
|
||||
Allies.MarkCompletedObjective(KillSams)
|
||||
SendLongBowReinforcements()
|
||||
end
|
||||
end)
|
||||
|
||||
local count = 0
|
||||
Utils.Do(Airfields, function(field)
|
||||
Trigger.OnCapture(field, function()
|
||||
count = count + 1
|
||||
if count == #Airfields then
|
||||
Allies.MarkCompletedObjective(CaptureAirfields)
|
||||
local atek = Actor.Create("atek.mission", true, { Owner = Allies, Location = HiddenATEK.Location })
|
||||
Trigger.AfterDelay(DateTime.Seconds(5), atek.Destroy)
|
||||
end
|
||||
end)
|
||||
Trigger.OnKilled(field, function()
|
||||
Allies.MarkFailedObjective(CaptureAirfields)
|
||||
end)
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(SovietBuildings, function()
|
||||
if DestroyObj then
|
||||
if not Soviets.HasNoRequiredUnits() then
|
||||
KillObj = AddPrimaryObjective(Allies, "kill-remaining-soviet-forces")
|
||||
end
|
||||
Allies.MarkCompletedObjective(DestroyObj)
|
||||
else
|
||||
DestroyObj = AddPrimaryObjective(Allies, "dismantle-nearby-soviet-base")
|
||||
Allies.MarkCompletedObjective(DestroyObj)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(DateTime.Seconds(1), function() Media.PlaySpeechNotification(Allies, "MissionTimerInitialised") end)
|
||||
TimerColor = Allies.Color
|
||||
end
|
||||
|
||||
SetupSoviets = function()
|
||||
Barrack1.IsPrimaryBuilding = true
|
||||
Barrack1.RallyPoint = SovietInfantryRally1.Location
|
||||
Trigger.OnKilledOrCaptured(Barrack1, function()
|
||||
SpawningInfantry = false
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(0, function()
|
||||
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 * DamageModifier then
|
||||
building.StartBuildingRepairs()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
Reinforcements.Reinforce(Soviets, Squad1, { AlliesBaseGate1.Location, Alliesbase1.Location })
|
||||
Reinforcements.Reinforce(Soviets, Squad2, { AlliesBaseGate2.Location, Alliesbase2.Location })
|
||||
|
||||
ParaTroopersPowerProxy = Actor.Create("powerproxy.paratroopers", false, { Owner = Soviets })
|
||||
Trigger.AfterDelay(ParadropTicks, function()
|
||||
SendSovietParadrops(ParadropWaypoints[1])
|
||||
SendSovietParadrops(ParadropWaypoints[2])
|
||||
end)
|
||||
Trigger.AfterDelay(ParadropTicks * 2, function()
|
||||
SendSovietParadrops(ParadropWaypoints[3])
|
||||
SendSovietParadrops(ParadropWaypoints[4])
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(AttackAtFrame, SendVehicleWave)
|
||||
Trigger.AfterDelay(AttackAtFrameInf, SendInfantryWave)
|
||||
|
||||
if MoreParas then
|
||||
local delay = Utils.RandomInteger(TimerTicks/3, TimerTicks*2/3)
|
||||
Trigger.AfterDelay(delay, function()
|
||||
SendSovietParadrops(ParadropWaypoints[Utils.RandomInteger(1,3)])
|
||||
SendSovietParadrops(ParadropWaypoints[Utils.RandomInteger(3,5)])
|
||||
end)
|
||||
end
|
||||
if SpawnNavalUnits then
|
||||
Trigger.AfterDelay(AttackAtFrameNaval, SendSovietNavalReinforcements)
|
||||
end
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
|
||||
Allies = Player.GetPlayer("Allies")
|
||||
Soviets = Player.GetPlayer("Soviets")
|
||||
|
||||
AddObjectives()
|
||||
InitMission()
|
||||
SetupSoviets()
|
||||
end
|
||||
Reference in New Issue
Block a user