Files
OpenRA/mods/ra/maps/negotiations/negotiations-reinforcements.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

398 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.
]]
ReinforceAllies = function()
Media.PlaySpeechNotification(Greece, "ReinforcementsArrived")
local proxy = SpawnMiscActor("paradrop.allies", GoodGuy, TanyaDrop.Location, DateTime.Seconds(1))
local planes = proxy.TargetParatroopers(TanyaDrop.CenterPosition, Angle.SouthEast)
Utils.Do(planes, function(plane)
Trigger.OnPassengerExited(plane, function(_, passenger)
passenger.Owner = Greece
end)
Trigger.OnAllKilled(plane.Passengers, CheckAlliedDestruction)
end)
local demoTypes = { "2tnk", "2tnk", "2tnk", "dtrk" }
local artilleryTypes = {"2tnk", "2tnk", "arty", "arty", "mech", "mech", "mech" }
local groundPath = { WestRoadEntry.Location, WestRoadRally.Location }
local demoTeam = Reinforcements.Reinforce(Greece, demoTypes, groundPath)
Trigger.OnAllKilled(demoTeam, CheckAlliedDestruction)
Trigger.AfterDelay(DateTime.Seconds(30), function()
if AlliesDefeated then
return
end
Media.PlaySpeechNotification(Greece, "ReinforcementsArrived")
local artilleryTeam = Reinforcements.Reinforce(Greece, artilleryTypes, groundPath)
Trigger.OnAllKilled(artilleryTeam, CheckAlliedDestruction)
end)
end
ReinforceChronoTanks = function(locations)
if ChronoTanksReinforced then
return
end
ChronoTanksReinforced = true
Media.PlaySoundNotification(Greece, "Chronoshift")
Utils.Do(locations, function(location)
local proxy = SpawnMiscActor("powerproxy.chronoshift", GoodGuy, location, DateTime.Seconds(1))
local tank = Actor.Create("ctnk", true, { Owner = Greece, Facing = Angle.NorthWest })
local payload = { [tank] = location }
proxy.Chronoshift(payload)
end)
end
ReinforceTanya = function()
local path = { WestRoadEntry.Location, TanyaDrop.Location }
local plane = Reinforcements.Reinforce(Greece, { "badr.tanya" }, path)[1]
local passengers = { TanyaType }
Trigger.OnAddedToWorld(plane, function()
Utils.Do(passengers, function(type)
local passenger = Actor.Create(type, false, { Owner = Greece })
plane.LoadPassenger(passenger)
Trigger.OnKilled(passenger, OnTanyaKilled)
Tanya = passenger
AnnounceTanyaRules(passenger)
end)
plane.Paradrop(path[2])
end)
end
AnnounceTanyaRules = function(tanya)
if Difficulty == "easy" then
return
end
Trigger.OnAddedToWorld(tanya, function()
Trigger.AfterDelay(DateTime.Seconds(1), function()
Media.DisplayMessage(UserInterface.GetFluentMessage("tanya-rules-of-engagement"), tanya.TooltipName)
Media.PlaySoundNotification(Greece, "AlertBleep")
end)
end)
end
ReinforceLongbows = function()
if SoutheastTurret.IsDead then
return
end
local goals = { LongbowGoal1, LongbowGoal2, LongbowGoal3 }
local spawnOffset = 0
Utils.Do(goals, function(goal)
local entry = { LongbowEntry.Location + CVec.New(spawnOffset, 15) }
Reinforcements.Reinforce(GoodGuy, { "heli" }, entry, 0, function(helicopter)
helicopter.Wait(DateTime.Seconds(1))
helicopter.AttackMove(goal.Location)
-- Original behavior was to fire at the ground until out of ammo.
Trigger.OnKilled(SoutheastTurret, function()
helicopter.Stop()
helicopter.Wait(10)
helicopter.Move(LongbowExit.Location, 1)
helicopter.Destroy()
end)
end)
spawnOffset = spawnOffset + 5
end)
end
ReinforceBadGuy = function()
-- If ForwardCommand dies early, the General will be busy hunting.
if General.IsDead or ForwardCommand.IsDead then
return
end
BadGuyReinforced = true
Media.PlaySpeechNotification(Greece, "SignalFlareWest")
local flare = SpawnFlare(NorthFlare.Location)
Trigger.OnKilled(General, function()
RemoveActor(flare, DateTime.Seconds(30))
end)
local waterCamera = SpawnPlayerCamera(NorthWaterEntry.Location, -1)
local boatPath = { NorthWaterEntry.Location, BuilderBeach.Location }
local cargo = Reinforcements.ReinforceWithTransport(BadGuy, "lst", { "mcv" }, boatPath, { boatPath[1] })[2]
Utils.Do(cargo, function(builder)
Trigger.OnKilled(builder, CheckNewBase)
Trigger.OnAddedToWorld(builder, function()
local builderCamera = SpawnPlayerCamera(builder.Location, -1, "camera.small")
builder.Move(BuilderRally.Location)
builder.CallFunc(function()
RemoveActor(waterCamera)
RemoveActor(builderCamera)
end)
builder.Deploy()
end)
end)
end
ReinforceNorthChinook = function()
local delay = DateTime.Seconds(4)
local camera = SpawnPlayerCamera(NorthChinookUnload.Location, -1, "camera.small", delay + DateTime.Seconds(2))
Trigger.AfterDelay(delay, function()
local transport = Actor.Create("tran.north", true, { Owner = USSR, Location = NorthChinookEntry.Location, Facing = Angle.South })
local passengers = transport.Passengers
transport.UnloadPassengers(NorthChinookUnload.Location)
transport.Move(SouthChinookExit.Location)
transport.Destroy()
Trigger.OnPassengerExited(transport, function()
if transport.PassengerCount > 0 then
return
end
-- Original unload is slow. Mimic the timing with a short pause.
Trigger.AfterDelay(DateTime.Seconds(3), function()
OrderNorthChinookSoldiers(passengers, camera)
end)
end)
Trigger.OnAnyKilled(passengers, function()
RemoveActor(camera, DateTime.Seconds(1))
end)
end)
end
OrderNorthChinookSoldiers = function(soldiers, camera)
local patrolPath =
{
VillageNortheast.Location,
VillageNorthwest.Location,
VillageSouthwest.Location,
VillageSoutheast.Location
}
local liveSoldiers = Utils.Where(soldiers, IsAlive)
Utils.Do(liveSoldiers, function(soldier)
soldier.AttackMove(NorthChinookRally.Location)
soldier.CallFunc(function()
Trigger.AfterDelay(1, function()
if not AreAllIdleOrDead(liveSoldiers) then
return
end
RemoveActor(camera, DateTime.Seconds(1))
GroupAttackMove(liveSoldiers, VillageBridgeCenter.Location, 2)
GroupTightPatrol(liveSoldiers, patrolPath, true)
GroupHuntOnDamaged(liveSoldiers, Greece)
end)
end)
end)
end
ReinforceVillagePatrol = function()
if VillagePatrolSent then
return
end
VillagePatrolSent = true
local path =
{
VillageSoutheast.Location,
VillageSouthwest.Location,
VillageNorthwest.Location,
VillageNortheast.Location
}
local types = { "e1", "e1", "e2", "dog" }
local origin = { VillagePatrolEntry.Location }
local group = Reinforcements.Reinforce(USSR, types, origin, 0)
GroupTightPatrol(group, path, true)
end
ReinforceGuardHouse = function(intruderType)
if GuardHouse.IsDead then
return
end
local goal = GuideBarrelGoal.Location
if intruderType == TanyaType then
goal = PrisonReveal.Location
end
for i = 1, 4 do
Trigger.AfterDelay(i * 5, function()
local guard = Actor.Create("e1", true, { Owner = USSR, Location = GuardHouseSpawn.Location, SubCell = 4, Facing = Angle.SouthWest })
guard.Move(GuardHouseExit.Location)
guard.AttackMove(goal)
IdleHunt(guard)
end)
end
end
ReinforceHardTeams = function()
if Difficulty ~= "hard" then
return
end
ReinforceBaseDefenders()
ReinforceNorthBeachGuards()
ReinforceV2Team()
ReinforceNorthEdgeGuards()
PrepareSouthChinook()
ReinforceHardDogs()
end
ReinforceBaseDefenders = function()
local origin = BadGuyRally.Location + CVec.New(2, 2)
local types = { "3tnk", "3tnk" }
local defenders = Reinforcements.Reinforce(USSR, types, { origin }, 0, function(actor)
actor.Wait(1)
actor.Scatter()
end)
GroupHuntOnDamaged(defenders, Greece)
local structures = { RoadTurretWest, RoadTurretEast, ForwardPower, ForwardCommand, ForwardTech }
Trigger.OnAnyKilled(structures, function()
GroupIdleHunt(defenders)
end)
end
ReinforceNorthBeachGuards = function()
local types = { "e1", "e1", "e2", "e1" }
local patrolPath = { VillageNortheast.Location, VillageSouthwest.Location }
local soldiers = Reinforcements.Reinforce(USSR, types, { NorthFlare.Location }, 0, function(actor)
actor.Scatter()
end)
Trigger.OnEnteredFootprint({ GeneralRally.Location }, function(actor, id)
if actor.Type ~= "gnrl" then
return
end
Trigger.RemoveFootprintTrigger(id)
GroupHuntOnDamaged(soldiers, Greece)
Utils.Do(soldiers, function(soldier)
if soldier.IsDead then
return
end
soldier.AttackMove(BadGuyRally.Location)
soldier.AttackMove(GuideBarrelGoal.Location)
soldier.AttackMove(VillageNorthwest.Location)
soldier.Patrol(patrolPath, true)
end)
end)
end
ReinforceV2Team = function()
local rocket = Actor.Create("v2rl", true, { Owner = USSR, Facing = Angle.West, Location = SamRocketEntry.Location })
Reinforcements.Reinforce(USSR, { "e1" }, { SamFenceReveal.Location }, 0, function(actor)
actor.Guard(rocket)
end)
end
PrepareSouthChinook = function()
local startPosition = SouthChinookEntry.CenterPosition + WVec.New(0, 0, Actor.CruiseAltitude("tran"))
Trigger.OnEnteredProximityTrigger(SouthChinookProximity.CenterPosition, WDist.FromCells(8), function(actor, id)
if actor.Type ~= TanyaType or not EscortFinished then
return
end
Trigger.RemoveProximityTrigger(id)
local transport = Actor.Create("tran.south", true, { Owner = USSR, CenterPosition = startPosition, Facing = Angle.East })
transport.UnloadPassengers(SouthChinookEntry.Location)
transport.Move(SouthChinookExit.Location)
transport.Destroy()
Utils.Do(transport.Passengers, function(passenger)
Trigger.OnAddedToWorld(passenger, function()
passenger.Wait(DateTime.Seconds(1))
IdleHunt(passenger)
end)
end)
end)
end
ReinforceNorthEdgeGuards = function()
local types = { "e1", "e1", "e2" }
local guards = Reinforcements.Reinforce(USSR, types, { NorthEdgeGuardEntry.Location }, 0, function(actor)
actor.Scatter()
end)
GroupHuntOnDamaged(guards, Greece)
end
ReinforceStartSoldiers = function()
local teams =
{
{
entry = { WestRoadEntry.Location },
types = { "e2", "e2", "e1" }
},
{
entry = { RoadTurretRifle2.Location },
types = { "e1", "e2", "e4" }
}
}
Utils.Do(teams, function(team)
local soldiers = Reinforcements.Reinforce(USSR, team.types, team.entry, 15, function(actor)
actor.AttackMove(TanyaDrop.Location)
actor.Hunt()
end)
Trigger.OnAnyKilled(soldiers, function()
IdleHunt(StartSoldier)
end)
end)
end
ReinforceHardDogs = function()
local startDog = Actor.Create("dog", true, { Owner = USSR, Location = WestRoadEntry.Location, Facing = Angle.South })
startDog.Move(WestRoadRally.Location + CVec.New(-1, 0))
PrepareStartDogAttack(startDog)
local turretDog = Actor.Create("dog.areaguard", true, { Owner = USSR, Location = LongbowGoal2.Location, Facing = Angle.SouthWest })
turretDog.AddTag("TurretDog")
Trigger.OnKilled(turretDog, function()
GroupIdleHunt(SoutheastTurretGuards)
end)
end
PrepareStartDogAttack = function(dog)
-- Tanya will take about 100 ticks/4 seconds to touch the ground.
local delay = DateTime.Seconds(5) + 5
Trigger.OnEnteredFootprint({ TanyaDrop.Location }, function(actor, id)
if actor.Type ~= TanyaType then
return
end
Trigger.RemoveFootprintTrigger(id)
Trigger.AfterDelay(delay, function()
if dog.IsDead or actor.IsDead then
return
end
dog.Attack(actor)
end)
end)
end