Initial commit: OpenRA game engine
Some checks failed
Continuous Integration / Linux (.NET 8.0) (push) Has been cancelled
Continuous Integration / Windows (.NET 8.0) (push) Has been cancelled

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:
let5sne.win10
2026-01-10 21:46:54 +08:00
commit 9cf6ebb986
4065 changed files with 635973 additions and 0 deletions

View File

@@ -0,0 +1,174 @@
--[[
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.
]]
AttackGroup = { }
AttackGroupSize = 10
BGAttackGroup = { }
BGAttackGroupSize = 6
SovietInfantry = { "e1", "e2", "e4" }
SovietVehicles = { "4tnk", "3tnk", "3tnk", "3tnk" }
SovietAircraftType = { "mig" }
Migs = { }
ProductionInterval =
{
easy = DateTime.Seconds(30),
normal = DateTime.Seconds(24),
hard = DateTime.Seconds(15)
}
SendBGAttackGroup = function()
if #BGAttackGroup < BGAttackGroupSize then
return
end
Utils.Do(BGAttackGroup, function(unit)
if not unit.IsDead then
Trigger.OnIdle(unit, unit.Hunt)
end
end)
BGAttackGroup = { }
end
ProduceBadGuyInfantry = function()
if BadGuyRax.IsDead or BadGuyRax.Owner ~= BadGuy then
return
end
BadGuy.Build({ Utils.Random(SovietInfantry) }, function(units)
table.insert(BGAttackGroup, units[1])
SendBGAttackGroup()
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceBadGuyInfantry)
end)
end
AttackWaypoints = { AttackWaypoint1, AttackWaypoint2 }
SendAttackGroup = function()
if #AttackGroup < AttackGroupSize then
return
end
local way = Utils.Random(AttackWaypoints)
Utils.Do(AttackGroup, function(unit)
if not unit.IsDead then
unit.AttackMove(way.Location)
Trigger.OnIdle(unit, unit.Hunt)
end
end)
AttackGroup = { }
end
ProduceInfantry = function()
if (USSRRax1.IsDead or USSRRax1.Owner ~= USSR) and (USSRRax2.IsDead or USSRRax2.Owner ~= USSR) then
return
end
USSR.Build({ Utils.Random(SovietInfantry) }, function(units)
table.insert(AttackGroup, units[1])
SendAttackGroup()
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceInfantry)
end)
end
ProduceVehicles = function()
if USSRWarFactory.IsDead or USSRWarFactory.Owner ~= USSR then
return
end
USSR.Build({ Utils.Random(SovietVehicles) }, function(units)
table.insert(AttackGroup, units[1])
SendAttackGroup()
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceVehicles)
end)
end
ProduceAircraft = function()
if (Airfield1.IsDead or Airfield1.Owner ~= BadGuy) and (Airfield2.IsDead or Airfield2.Owner ~= BadGuy) and (Airfield3.IsDead or Airfield3.Owner ~= BadGuy) and (Airfield4.IsDead or Airfield4.Owner ~= BadGuy) then
return
end
BadGuy.Build(SovietAircraftType, function(units)
local mig = units[1]
Migs[#Migs + 1] = mig
Trigger.OnKilled(mig, ProduceAircraft)
local alive = Utils.Where(Migs, function(y) return not y.IsDead end)
if #alive < 2 then
Trigger.AfterDelay(DateTime.Seconds(ProductionInterval[Difficulty] / 2), ProduceAircraft)
end
InitializeAttackAircraft(mig, Greece)
end)
end
ParadropDelay =
{
easy = { DateTime.Minutes(1), DateTime.Minutes(2) },
normal = { DateTime.Seconds(45), DateTime.Minutes(1) },
hard = { DateTime.Seconds(30), DateTime.Seconds(45) }
}
ParadropLZs = { ParaLZ1.CenterPosition, ParaLZ2.CenterPosition, ParaLZ3.CenterPosition, ParaLZ4.CenterPosition, ParaLZ5.CenterPosition }
Paradrop = function()
local aircraft = StandardDrop.TargetParatroopers(Utils.Random(ParadropLZs), Angle.NorthWest)
Utils.Do(aircraft, function(a)
Trigger.OnPassengerExited(a, function(t, p)
IdleHunt(p)
end)
end)
Trigger.AfterDelay(Utils.RandomInteger(ParadropDelay[1], ParadropDelay[2]), Paradrop)
end
BombDelays =
{
easy = 4,
normal = 3,
hard = 2
}
SendParabombs = function()
local targets = Utils.Where(Greece.GetActors(), function(actor)
return
actor.HasProperty("Sell") and
actor.Type ~= "brik" and
actor.Type ~= "sbag"
end)
if #targets > 0 then
local proxy = Actor.Create("powerproxy.parabombs", false, { Owner = USSR })
proxy.TargetAirstrike(Utils.Random(targets).CenterPosition, Angle.NorthWest)
proxy.Destroy()
end
Trigger.AfterDelay(DateTime.Minutes(BombDelays), SendParabombs)
end
ActivateAI = function()
ParadropDelay = ParadropDelay[Difficulty]
BombDelays = BombDelays[Difficulty]
local buildings = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == USSR and self.HasProperty("StartBuildingRepairs") end)
Utils.Do(buildings, function(actor)
Trigger.OnDamaged(actor, function(building)
if building.Owner == USSR and building.Health < building.MaxHealth * 3/4 then
building.StartBuildingRepairs()
end
end)
end)
ProduceBadGuyInfantry()
Trigger.AfterDelay(DateTime.Minutes(2), ProduceInfantry)
Trigger.AfterDelay(DateTime.Minutes(4), ProduceVehicles)
Trigger.AfterDelay(DateTime.Minutes(6), ProduceAircraft)
end

View File

@@ -0,0 +1,174 @@
--[[
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.
]]
StartingUnits = { "mcv", "2tnk", "2tnk", "2tnk", "2tnk" }
MammothWays = { MammothWay1.Location, MammothWay2.Location, MammothWay3.Location, MammothWay4.Location, ParaLZ5.Location }
PeekersA = { Peekaboo1, Peekaboo2, Peekaboo3 }
PeekersB = { Peekaboo4, Peekaboo5 }
AmbushTeam = { "3tnk", "v2rl", "e2", "e2", "e4" }
NorthHarassFootprint = { CPos.New(24, 75), CPos.New(25, 75), CPos.New(26, 75), CPos.New(27, 75), CPos.New(36, 72), CPos.New(37, 72), CPos.New(38, 72), CPos.New(39, 72) }
NorthHarassTeam = { "e2", "e2", "e2", "3tnk" }
MissileSilos = { MissileSilo1, MissileSilo2, MissileSilo3, MissileSilo4 }
TimerColor = Player.GetPlayer("USSR").Color
TimerTicks = DateTime.Minutes(59) + DateTime.Seconds(42)
MissionStart = function()
Utils.Do(USSR.GetGroundAttackers(), function(unit)
Trigger.OnDamaged(unit, function() IdleHunt(unit) end)
end)
Reinforcements.Reinforce(Greece, StartingUnits, { MCVEntry.Location, MCVStop.Location })
PatrolMammoth.Patrol(MammothWays, true, 20)
Trigger.AfterDelay(DateTime.Seconds(10), function()
Utils.Do(PeekersA, function(unit)
if not unit.IsDead then
unit.AttackMove(MCVStop.Location)
IdleHunt(unit)
end
end)
end)
Trigger.AfterDelay(DateTime.Seconds(45), function()
Utils.Do(PeekersB, function(unit)
if not unit.IsDead then
unit.AttackMove(AttackWaypoint1.Location)
IdleHunt(unit)
end
end)
end)
end
MissionTriggers = function()
Trigger.OnKilled(CommandCenter, function()
USSR.MarkCompletedObjective(HoldOut)
end)
Trigger.OnEnteredProximityTrigger(FCom.CenterPosition, WDist.FromCells(15), function(actor, id)
if actor.Owner == Greece and not MissilesLaunched then
Trigger.RemoveProximityTrigger(id)
LaunchMissiles()
end
end)
Trigger.OnTimerExpired(function()
DateTime.TimeLimit = 0
Trigger.AfterDelay(1, function() UserInterface.SetMissionText(UserInterface.GetFluentMessage("we-are-too-late"), USSR.Color) end)
USSR.MarkCompletedObjective(HoldOut)
end)
Trigger.OnKilled(BridgeBarrel, function()
local bridge = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "bridge1" end)[1]
if not bridge.IsDead then
bridge.Kill()
end
end)
Trigger.OnEnteredProximityTrigger(OreAmbushTrigger.CenterPosition, WDist.FromCells(5), function(actor, id)
if actor.Owner == Greece and actor.Type == "harv" and not Map.LobbyOption("difficulty") == "easy" then
Trigger.RemoveProximityTrigger(id)
local ambush = Reinforcements.Reinforce(USSR, AmbushTeam, { OreAmbushEntry.Location})
Utils.Do(ambush, IdleHunt)
end
end)
local northFootTriggered
Trigger.OnEnteredFootprint(NorthHarassFootprint, function(actor, id)
if actor.Owner == Greece and not northFootTriggered then
Trigger.RemoveFootprintTrigger(id)
northFootTriggered = true
local northHarass = Reinforcements.Reinforce(USSR, NorthHarassTeam, { OreAmbushEntry.Location})
Utils.Do(northHarass, IdleHunt)
end
end)
end
LaunchMissiles = function()
MissilesLaunched = true
Actor.Create("camera", true, { Owner = Greece, Location = FCom.Location })
Camera.Position = FCom.CenterPosition
Media.PlaySpeechNotification(Greece, "AbombLaunchDetected")
MissileSilo1.ActivateNukePower(CPos.New(127, 127))
Trigger.AfterDelay(DateTime.Seconds(3), function()
Media.DisplayMessage(UserInterface.GetFluentMessage("incoming-transmission-capitalized"), UserInterface.GetFluentMessage("landcom-16-capitalized"))
Media.PlaySpeechNotification(Greece, "AbombLaunchDetected")
MissileSilo2.ActivateNukePower(CPos.New(127, 127))
end)
Trigger.AfterDelay(DateTime.Seconds(5), function()
Media.PlaySpeechNotification(Greece, "AbombLaunchDetected")
MissileSilo3.ActivateNukePower(CPos.New(127, 127))
end)
Trigger.AfterDelay(DateTime.Seconds(6), function()
Media.PlaySpeechNotification(Greece, "AbombLaunchDetected")
MissileSilo4.ActivateNukePower(CPos.New(127, 127))
end)
Trigger.AfterDelay(DateTime.Seconds(8), function()
local fmvStart = DateTime.GameTime
Media.PlayMovieFullscreen("ally10b.vqa", function()
-- Completing immediately indicates that the FMV is not available
-- Fall back to a text message
if fmvStart == DateTime.GameTime then
Media.DisplayMessage(UserInterface.GetFluentMessage("deactivate-four-missiles"), UserInterface.GetFluentMessage("landcom-16-capitalized"))
end
end)
end)
Trigger.AfterDelay(DateTime.Seconds(9), function()
CaptureFCom = AddPrimaryObjective(Greece, "capture-enemy-command-center")
DateTime.TimeLimit = TimerTicks
Media.PlaySpeechNotification(Greece, "TimerStarted")
Greece.MarkCompletedObjective(ApproachBase)
end)
Trigger.OnCapture(CommandCenter, function()
Greece.MarkCompletedObjective(CaptureFCom)
end)
Paradrop()
Trigger.AfterDelay(DateTime.Minutes(2), SendParabombs)
end
SilosDamaged = function()
if not MissilesLaunched then
LaunchMissiles()
end
end
Tick = function()
USSR.Cash = 50000
BadGuy.Cash = 50000
if Greece.HasNoRequiredUnits() then
USSR.MarkCompletedObjective(HoldOut)
end
end
WorldLoaded = function()
Greece = Player.GetPlayer("Greece")
USSR = Player.GetPlayer("USSR")
BadGuy = Player.GetPlayer("BadGuy")
InitObjectives(Greece)
HoldOut = AddPrimaryObjective(USSR, "")
ApproachBase = AddPrimaryObjective(Greece, "disable-atomic-weapons")
Camera.Position = DefaultCameraPosition.CenterPosition
StandardDrop = Actor.Create("paradrop", false, { Owner = USSR })
MissionStart()
MissionTriggers()
ActivateAI()
OnAnyDamaged(MissileSilos, SilosDamaged)
end

Binary file not shown.

View File

@@ -0,0 +1,2 @@
## rules.yaml
briefing = Kosygin has indicated that this is the site of Stalin's main atomic weapons plant. Use extreme care in approaching the Soviet base -- we don't know if any atomic bombs are armed. Take the facility offline and destroy any atomic weapons that exist.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
World:
LuaScript:
Scripts: campaign.lua, utils.lua, allies10a.lua, allies10a-AI.lua
MissionData:
BriefingVideo: ally10.vqa
LossVideo: trinity.vqa
StartVideo: mcv_land.vqa
Briefing: briefing
ScriptLobbyDropdown@difficulty:
ID: difficulty
Label: dropdown-difficulty.label
Description: dropdown-difficulty.description
Values:
easy: options-difficulty.easy
normal: options-difficulty.normal
hard: options-difficulty.hard
Default: normal
TimeLimitManager:
SkipTimerExpiredNotification: true
CountdownLabel: MISSION_TEXT
CountdownText: Missiles reach their targets in {0}
Player:
PlayerResources:
DefaultCash: 6500
PARADROP:
ParatroopersPower:
DropItems: E1, E1, E1, E2, E2
FCOM:
Capturable:
Types: building
MSLO:
-WithColoredOverlay@IDISABLE:
NukePower:
DisplayTimerRelationships: Neutral
Buildable:
Prerequisites: ~disabled
Capturable:
Types: ~disabled
FTRK:
Buildable:
Prerequisites: ~disabled
MCV:
Buildable:
Prerequisites: ~disabled
MRJ:
Buildable:
Prerequisites: ~disabled
HPAD:
Buildable:
Prerequisites: ~disabled
E7:
Buildable:
Prerequisites: ~disabled
E7.noautotarget:
Buildable:
Prerequisites: ~disabled
PDOX:
Buildable:
Prerequisites: ~disabled
IRON:
Buildable:
Prerequisites: ~disabled
SYRD:
Buildable:
Prerequisites: ~disabled
SPEN:
Buildable:
Prerequisites: ~disabled
QTNK:
Buildable:
Prerequisites: ~disabled
TTNK:
Buildable:
Prerequisites: ~disabled
SHOK:
Buildable:
Prerequisites: ~disabled
DTRK:
Buildable:
Prerequisites: ~disabled

View File

@@ -0,0 +1,3 @@
Atomic:
-Warhead@21Shake:
-Warhead@22FlashEffect: