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,282 @@
--[[
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.
]]
StartingCash = 15000
InfantryAttackPaths = { WaypointGroupBaseFrontal, WaypointGroupRightFlankInf, WaypointGroupVillageRight }
VehicleAttackPaths = { WaypointGroupBaseFrontal, WaypointGroupRightFlank, WaypointGroupVillageRight }
ArtyAttackPaths = { WaypointGroupBaseFrontal, ArtyWaypoints1, ArtyWaypoints2 }
InfantryProductionTypes = { "e1", "e3", "e3", "e3", "e4", "e4", "e4" }
VehicleProductionTypes = { "bggy", "ltnk" }
ArtyProductionType = { "arty" }
VehicleAutoProductionTypes = { "bggy", "bggy", "ltnk", "ltnk", "arty" }
HarvesterProductionType = { "harv" }
InfantryGroupSize = { hard = 8, normal = 6, easy = 4 }
InfantryAttackGroup = { }
InfantryProductionCooldown = { hard = DateTime.Seconds(40), normal = DateTime.Seconds(60), easy = DateTime.Seconds(80) }
VehicleGroupSize = { hard = 4, normal = 3, easy = 2 }
VehicleAttackGroup = { }
VehicleProductionCooldown = { hard = DateTime.Seconds(60), normal = DateTime.Seconds(90), easy = DateTime.Seconds(120) }
ArtyGroupSize = { hard = 2, normal = 1, easy = 1 }
ArtyAttackGroup = { }
ArtyProductionCooldown = { hard = DateTime.Seconds(60), normal = DateTime.Seconds(75), easy = DateTime.Seconds(100) }
NodBase = { handofnod, nodairfield, nodrefinery, nodradar, NodYard, nodpower1, nodpower2, nodpower3, nodpower4, nodpower5, gun1, gun2, gun3, gun4, nodsilo1, nodsilo2, nodsilo3}
BaseRadar = { type = "hq", pos = CPos.New(5, 6), cost = 1000 }
BaseRefinery = { type = "proc", pos = CPos.New(8, 7), cost = 1500 }
BaseSilo1 = { type = "silo", pos = CPos.New(6, 5), cost = 100 }
BaseSilo2 = { type = "silo", pos = CPos.New(8, 5), cost = 100 }
BaseSilo3 = { type = "silo", pos = CPos.New(10, 5), cost = 100 }
BaseGun1 = { type = "gun", pos = CPos.New( 7, 18), cost = 600 }
BaseGun2 = { type = "gun", pos = CPos.New( 11, 18), cost = 600 }
BaseGun3 = { type = "gun", pos = CPos.New( 45, 16), cost = 600 }
BaseGun4 = { type = "gun", pos = CPos.New( 50, 16), cost = 600 }
BaseNuke1 = { type = "nuke", pos = CPos.New( 13, 13), cost = 500 }
BaseNuke2 = { type = "nuke", pos = CPos.New( 50, 5), cost = 500 }
BaseNuke3 = { type = "nuke", pos = CPos.New( 5, 9), cost = 500 }
BaseNuke4 = { type = "nuke", pos = CPos.New( 52, 5), cost = 500 }
BaseNuke5 = { type = "nuke", pos = CPos.New( 48, 5), cost = 500 }
InfantryProduction = { type = "hand", pos = CPos.New(5, 12), cost = 500 }
VehicleProduction = { type = "afld", pos = CPos.New(52, 8), cost = 2000 }
BaseBuildings = { BaseRadar, BaseRefinery, BaseNuke1, BaseNuke2, BaseNuke3, BaseNuke4, BaseNuke5, InfantryProduction, VehicleProduction, BaseGun1, BaseGun2, BaseGun3, BaseGun4, BaseSilo1, BaseSilo2, BaseSilo3 }
BuildBuilding = function(building, cyard)
if CyardIsBuilding or Nod.Cash < building.cost then
Trigger.AfterDelay(DateTime.Seconds(10), function() BuildBuilding(building, cyard) end)
return
end
CyardIsBuilding = true
Nod.Cash = Nod.Cash - building.cost
Trigger.AfterDelay(Actor.BuildTime(building.type), function()
CyardIsBuilding = false
if cyard.IsDead or cyard.Owner ~= Nod then
Nod.Cash = Nod.Cash + building.cost
return
end
local actor = Actor.Create(building.type, true, { Owner = Nod, Location = building.pos })
if actor.Type == 'hand' or actor.Type == 'pyle' then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(actor) end)
elseif actor.Type == 'afld' or actor.Type == 'weap' then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(actor) end)
end
Trigger.OnKilled(actor, function()
BuildBuilding(building, cyard)
end)
RepairBuilding(GDI, actor, 0.75)
end)
end
CheckForHarvester = function()
local harv = Nod.GetActorsByType("harv")
return #harv > 0
end
ProduceHarvester = function(building)
if building.IsDead or building.Owner ~= Nod then
return
end
if not BuildingHarvester then
BuildingHarvester = true
building.Build(HarvesterProductionType, function()
BuildingHarvester = false
end)
end
end
ProduceInfantry = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9))
local toBuild = { Utils.Random(InfantryProductionTypes) }
local Path = Utils.Random(InfantryAttackPaths)
building.Build(toBuild, function(unit)
InfantryAttackGroup[#InfantryAttackGroup + 1] = unit[1]
if #InfantryAttackGroup >= InfantryGroupSize[Difficulty] then
MoveAndHunt(InfantryAttackGroup, Path)
InfantryAttackGroup = { }
Trigger.AfterDelay(InfantryProductionCooldown[Difficulty], function() ProduceInfantry(building) end)
else
Trigger.AfterDelay(delay, function() ProduceAutocreateInfantry(building) end)
end
end)
end
-- We want every 2nd produced infantry to be free for the Auto attack teams
ProduceAutocreateInfantry = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9))
local toBuild = { Utils.Random(InfantryProductionTypes) }
building.Build(toBuild, function(unit)
Trigger.AfterDelay(delay, function() ProduceInfantry(building) end)
end)
end
ProduceVehicle = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
ProduceHarvester(building)
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
local toBuild = { Utils.Random(VehicleProductionTypes) }
local Path = Utils.Random(VehicleAttackPaths)
building.Build(toBuild, function(unit)
VehicleAttackGroup[#VehicleAttackGroup + 1] = unit[1]
if #VehicleAttackGroup >= VehicleGroupSize[Difficulty] then
MoveAndHunt(VehicleAttackGroup, Path)
VehicleAttackGroup = { }
Trigger.AfterDelay(VehicleProductionCooldown[Difficulty], function() ProduceArty(building) end)
else
Trigger.AfterDelay(delay, function() ProduceAutocreateVehicle(building) end)
end
end)
end
-- We want every 2nd produced vehicle to be free for the Auto attack teams
ProduceAutocreateVehicle = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
ProduceHarvester(building)
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
local toBuild = { Utils.Random(VehicleProductionTypes) }
building.Build(toBuild, function(unit)
Trigger.AfterDelay(delay, function() ProduceVehicle(building) end)
end)
end
ProduceArty = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
ProduceHarvester(building)
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceArty(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
local toBuild = { Utils.Random(ArtyProductionType) }
local Path = Utils.Random(ArtyAttackPaths)
building.Build(toBuild, function(unit)
ArtyAttackGroup[#ArtyAttackGroup + 1] = unit[1]
if #ArtyAttackGroup >= ArtyGroupSize[Difficulty] then
MoveAndHunt(ArtyAttackGroup, Path)
ArtyAttackGroup = { }
Trigger.AfterDelay(ArtyProductionCooldown[Difficulty], function() ProduceVehicle(building) end)
else
Trigger.AfterDelay(delay, function() ProduceArty(building) end)
end
end)
end
StartAI = function()
Nod.Cash = StartingCash
end
Trigger.OnAllKilledOrCaptured(NodBase, function()
Utils.Do(Nod.GetGroundAttackers(), IdleHunt)
end)
Trigger.OnKilled(nodrefinery, function()
BuildBuilding(BaseRefinery, NodYard)
end)
Trigger.OnKilled(nodradar, function()
BuildBuilding(BaseRadar, NodYard)
end)
Trigger.OnKilled(nodpower1, function()
BuildBuilding(BaseNuke1, NodYard)
end)
Trigger.OnKilled(nodpower2, function()
BuildBuilding(BaseNuke2, NodYard)
end)
Trigger.OnKilled(nodpower3, function()
BuildBuilding(BaseNuke3, NodYard)
end)
Trigger.OnKilled(nodpower4, function()
BuildBuilding(BaseNuke4, NodYard)
end)
Trigger.OnKilled(nodpower5, function()
BuildBuilding(BaseNuke5, NodYard)
end)
Trigger.OnKilled(gun1, function()
BuildBuilding(BaseGun1, NodYard)
end)
Trigger.OnKilled(gun2, function()
BuildBuilding(BaseGun2, NodYard)
end)
Trigger.OnKilled(gun3, function()
BuildBuilding(BaseGun3, NodYard)
end)
Trigger.OnKilled(gun4, function()
BuildBuilding(BaseGun4, NodYard)
end)
Trigger.OnKilled(nodsilo1, function()
BuildBuilding(BaseSilo1, NodYard)
end)
Trigger.OnKilled(nodsilo2, function()
BuildBuilding(BaseSilo2, NodYard)
end)
Trigger.OnKilled(nodsilo3, function()
BuildBuilding(BaseSilo3, NodYard)
end)
Trigger.OnKilled(handofnod, function()
BuildBuilding(InfantryProduction, NodYard)
end)
Trigger.OnKilled(nodairfield, function()
BuildBuilding(VehicleProduction, NodYard)
end)

View File

@@ -0,0 +1,191 @@
--[[
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.
]]
SamSites = { sam1, sam2, sam3, sam4, sam5 }
NodRetaliateIfDestroyedUnits = { harv1, bggy, ltnk1, ltnk2, ltnk3, arty1, arty2, arty3}
Arty1Delay = { hard = 0, normal = 8, easy = 20 }
Arty2Delay = { hard = 10, normal = 20, easy = 40 }
TerrorTankDelay = { hard = 40, normal = 50, easy = 75 }
TerrorHeliDelay = { hard = 130, normal = 170, easy = 210 }
BaseHeliDelay = { hard = 100, normal = 130, easy = 160 }
NodHelis =
{
{ delay = DateTime.Seconds(TerrorHeliDelay[Difficulty]), entry = { DefaultChinookTarget.Location, waypoint14.Location }, types = { "e1", "e1", "e4", "e4", "e4" } }, --TERROR, wp14, attack civilians - all 170 timeunits
{ delay = DateTime.Seconds(0), entry = { DefaultChinookTarget.Location, waypoint13.Location }, types = { "e3", "e3", "e3", "e4", "e4" } }, --Air1, wp13, attack base - triggered on killed units, Harv, some tanks and some buggys...
{ delay = DateTime.Seconds(BaseHeliDelay[Difficulty]), entry = { DefaultChinookTarget.Location, waypoint0.Location }, types = { "e1", "e3", "e3", "e4", "e4" } } --Air2, wp0, attack base - all 130 timeunits
}
CivilianCasualties = 0
CiviliansKilledThreshold = { hard = 5, normal = 9, easy = 13 } --total 14
Civilians = { civ1, civ2, civ3, civ4, civ5, civ6, civ7, civ8, civ9, civ10, civ11, civ12, civ13, civ14 }
WaypointGroupVillageRight = { waypoint17, waypoint3, waypoint0 }
WaypointGroupVillageLeft = { waypoint17, waypoint14 }
WaypointGroupBaseFrontal = { waypoint7, waypoint11, waypoint31 }
WaypointGroupRightFlankInf = { waypoint7, waypoint8, waypoint10, waypoint8, waypoint9, waypoint31 }
WaypointGroupRightFlank = { waypoint7, waypoint8, waypoint13, waypoint31 }
ArtyWaypoints1 = { waypoint1 }
ArtyWaypoints2 = { waypoint2 }
ArtyWaypoints3 = { waypoint6, waypoint2 }
AutocreateDelay = { hard = 60, normal = 80, easy = 100 }
Auto2 = { units = { ['e4'] = 3, ['e3'] = 4 }, waypoints = WaypointGroupVillageLeft, delay = AutocreateDelay[Difficulty] }
Auto3 = { units = { ['ltnk'] = 1, ['arty'] = 2 }, waypoints = WaypointGroupBaseFrontal, delay = AutocreateDelay[Difficulty] }
Auto4 = { units = { ['arty'] = 2 }, waypoints = ArtyWaypoints1, delay = AutocreateDelay[Difficulty] }
Auto1 = { units = { ['e4'] = 3, ['e3'] = 4 }, waypoints = WaypointGroupBaseFrontal, delay = AutocreateDelay[Difficulty] }
Auto5 = { units = { ['arty'] = 1 }, waypoints = ArtyWaypoints2, delay = AutocreateDelay[Difficulty] }
Auto6 = { units = { ['ltnk'] = 1, ['e4'] = 2 }, waypoints = WaypointGroupBaseFrontal, delay = AutocreateDelay[Difficulty] }
Auto7 = { units = { ['ltnk'] = 1, ['bggy'] = 3 }, waypoints = WaypointGroupBaseFrontal, delay = AutocreateDelay[Difficulty] }
Auto8 = { units = { ['e4'] = 3, ['e3'] = 5 }, waypoints = WaypointGroupRightFlankInf, delay = AutocreateDelay[Difficulty] }
AutoAttackWaves = { Auto2, Auto3, Auto4, Auto1, Auto5, Auto6, Auto7, Auto8 }
StationaryGuardUnits = { Actor237, Actor238, Actor231, ltnk1, ltnk2, Actor233, ltnk3, arty1, arty2, arty3, bggy, Actor240, Actor242, Actor243, Actor227, Actor228, Actor229 }
StartStationaryGuards = function(StationaryGuards)
Utils.Do(StationaryGuards, function(unit)
if not unit.IsDead then
unit.Patrol( { unit.Location } , true, 20)
end
end)
end
SendWaves = function(counter, Waves)
if counter <= #Waves then
local team = Waves[counter]
for type, amount in pairs(team.units) do
MoveAndHunt(Utils.Take(amount, Nod.GetActorsByType(type)), team.waypoints)
end
Trigger.AfterDelay(DateTime.Seconds(team.delay), function() SendWaves(counter + 1, Waves) end)
end
end
SendHeli = function(heli)
local units = Reinforcements.ReinforceWithTransport(Nod, "tran", heli.types, heli.entry, { heli.entry[1] })
Utils.Do(units[2], function(actor)
actor.Hunt()
Trigger.OnIdle(actor, actor.Hunt)
end)
if heli.delay == DateTime.Seconds(0) then
return
end
Trigger.AfterDelay(heli.delay, function() SendHeli(heli) end)
end
MoveInitialArty = function(arty, waypoints)
local units = { arty }
MoveAndIdle(units, waypoints)
end
TankTerror = function(tank)
local units = { tank }
MoveAndHunt(units, WaypointGroupVillageLeft)
end
WorldLoaded = function()
GDI = Player.GetPlayer("GDI")
Nod = Player.GetPlayer("Nod")
Camera.Position = DefaultCameraPosition.CenterPosition
StartStationaryGuards(StationaryGuardUnits)
StartAI()
InitObjectives(GDI)
ProtectMoebius = AddPrimaryObjective(GDI, "protect-mobius")
Trigger.OnKilled(DrMoebius, function()
GDI.MarkFailedObjective(ProtectMoebius)
end)
ProtectHospital = AddPrimaryObjective(GDI, "protect-hospital")
Trigger.OnKilled(Hospital, function()
GDI.MarkFailedObjective(ProtectHospital)
end)
CiviliansKilledThreshold = CiviliansKilledThreshold[Difficulty]
local civilians = 14 - CiviliansKilledThreshold
local keepCiviliansAlive = UserInterface.GetFluentMessage("keep-civilians-alive", { ["civilians"] = civilians })
ProtectCivilians = AddPrimaryObjective(GDI, keepCiviliansAlive)
Utils.Do(Civilians, function(civilian)
Trigger.OnKilled(civilian, function()
CivilianCasualties = CivilianCasualties + 1
if CiviliansKilledThreshold < CivilianCasualties then
GDI.MarkFailedObjective(ProtectCivilians)
end
end)
end)
SecureArea = AddPrimaryObjective(GDI, "destroy-nod-bases")
KillGDI = AddPrimaryObjective(Nod, "")
AirSupport = AddSecondaryObjective(GDI, "destroy-sams")
Trigger.OnAllKilled(SamSites, function()
GDI.MarkCompletedObjective(AirSupport)
Actor.Create("airstrike.proxy", true, { Owner = GDI })
end)
Actor.Create("flare", true, { Owner = GDI, Location = DefaultFlareLocation.Location })
Trigger.AfterDelay(DateTime.Minutes(1), function() SendWaves(1, AutoAttackWaves) end)
Trigger.AfterDelay(DateTime.Minutes(2), function() ProduceInfantry(handofnod) end)
Trigger.AfterDelay(DateTime.Minutes(3), function() ProduceVehicle(nodairfield) end)
local InitialArrivingUnits =
{
{ units = { Actor252, Actor253, Actor223, Actor225, Actor222, Actor258, Actor259, Actor260, Actor261, Actor254, Actor255, Actor256, Actor257 }, distance = -1 },
{ units = { Actor218, Actor220, Actor224, Actor226 }, distance = -2 },
{ units = { gdiAPC1 }, distance = -3 }
}
Utils.Do(InitialArrivingUnits, function(group)
Utils.Do(group.units, function(unit)
unit.Move(unit.Location + CVec.New(0, group.distance), 0)
end)
end)
Utils.Do(NodHelis, function(heli)
if heli.delay == DateTime.Seconds(0) then -- heli1 comes only when specific units are killed, see below
return
end
Trigger.AfterDelay(heli.delay, function() SendHeli(heli) end)
end)
-- units destroyed, send heli, eg. harv, tnk, bggy,...
Utils.Do(NodRetaliateIfDestroyedUnits, function(unit)
Trigger.OnKilled(unit, function()
SendHeli(NodHelis[2])
end)
end)
Trigger.AfterDelay(DateTime.Seconds(Arty1Delay[Difficulty]), function() MoveInitialArty(earlyarty1, ArtyWaypoints1) end)
Trigger.AfterDelay(DateTime.Seconds(Arty2Delay[Difficulty]), function() MoveInitialArty(earlyarty2, ArtyWaypoints2) end)
Trigger.AfterDelay(DateTime.Seconds(TerrorTankDelay[Difficulty]), function() TankTerror(terrortank) end)
end
Tick = function()
if DateTime.GameTime > DateTime.Seconds(5) then
if GDI.HasNoRequiredUnits() then
Nod.MarkCompletedObjective(KillGDI)
end
if Nod.HasNoRequiredUnits() then
GDI.MarkCompletedObjective(SecureArea)
GDI.MarkCompletedObjective(ProtectMoebius)
GDI.MarkCompletedObjective(ProtectHospital)
GDI.MarkCompletedObjective(ProtectCivilians)
end
end
end

Binary file not shown.

View File

@@ -0,0 +1,7 @@
## rules.yaml
briefing =
Dr. Mobius is setting up a Hospital to treat civilians in the region who are falling ill from Tiberium exposure.
Protect Mobius and the civilians.
Eliminate Nod presence in the area.

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
World:
LuaScript:
Scripts: campaign.lua, utils.lua, gdi08b.lua, gdi08b-AI.lua
MusicPlaylist:
StartingMusic: march
VictoryMusic: gdi_win1
MissionData:
Briefing: briefing
BackgroundVideo: tbrinfo1.vqa
StartVideo: desolat.vqa
LossVideo: gdilose.vqa
WinVideo: hellvaly.vqa
BriefingVideo: gdi8b.vqa
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
Locked: false
MapOptions:
ShortGameCheckboxLocked: True
ShortGameCheckboxEnabled: True
SmudgeLayer@SCORCH:
InitialSmudges:
30,43: sc3,0
10,21: sc5,0
7,20: sc5,0
9,19: sc1,0
6,19: sc3,0
5,18: sc4,0
40,8: sc4,0
19,8: sc4,0
36,7: sc6,0
35,7: sc6,0
34,7: sc5,0
19,7: sc3,0
18,7: sc2,0
15,7: sc1,0
37,6: sc2,0
17,6: sc2,0
34,5: sc3,0
20,5: sc6,0
19,5: sc4,0
38,4: sc1,0
37,4: sc6,0
18,4: sc5,0
SmudgeLayer@CRATER:
InitialSmudges:
36,6: cr1,0
ATWR:
Buildable:
Prerequisites: ~disabled
NUK2:
Buildable:
Prerequisites: ~disabled
HPAD:
Buildable:
Prerequisites: ~disabled
BRIK:
Buildable:
Prerequisites: ~disabled
EYE:
Buildable:
Prerequisites: ~disabled
OBLI:
Buildable:
Prerequisites: ~disabled
TMPL:
Buildable:
Prerequisites: ~disabled
HTNK:
Buildable:
Prerequisites: ~disabled
TRAN:
Buildable:
Prerequisites: ~disabled
ORCA:
Buildable:
Prerequisites: ~disabled
RMBO:
Buildable:
Prerequisites: ~disabled
MSAM:
Buildable:
Prerequisites: ~disabled
MCV:
Buildable:
Prerequisites: ~disabled
BOAT:
Buildable:
Prerequisites: ~disabled
FTNK:
Buildable:
Prerequisites: ~disabled
STNK:
Buildable:
Prerequisites: ~disabled
ARTY:
RevealsShroud:
Range: 10c0
HARV:
Harvester:
SearchFromProcRadius: 64
HELI:
Buildable:
Prerequisites: ~disabled
E5:
Buildable:
Prerequisites: ~disabled
MLRS:
Buildable:
Prerequisites: ~disabled
SAM:
Buildable:
Prerequisites: ~disabled
^Bridge:
DamageMultiplier@INVULNERABLE:
Modifier: 0
BRIDGEHUT:
-Targetable:
CYCL:
Buildable:
Prerequisites: ~disabled
SBAG:
Buildable:
Queue: Support.GDI, Support.Nod
GUN:
Buildable:
Queue: Support.GDI, Support.Nod
airstrike.proxy:
AirstrikePower:
SquadSize: 2
SquadOffset: -1536, 1024, 0
HQ:
Tooltip:
-AirstrikePower:
Buildable:
Description: actor-hq-description
^CivInfantry:
Health:
HP: 3500
Wanders:
MinMoveDelay: 500
MaxMoveDelay: 1000
ActorLostNotification:
Notification: CivilianKilled
TextNotification: civilian-killed
NotifyAll: true