Add single-player mission 'Intervention'
This commit is contained in:
BIN
mods/ra/maps/intervention/map.bin
Normal file
BIN
mods/ra/maps/intervention/map.bin
Normal file
Binary file not shown.
BIN
mods/ra/maps/intervention/map.png
Normal file
BIN
mods/ra/maps/intervention/map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
2339
mods/ra/maps/intervention/map.yaml
Normal file
2339
mods/ra/maps/intervention/map.yaml
Normal file
File diff suppressed because it is too large
Load Diff
286
mods/ra/maps/intervention/mission.lua
Normal file
286
mods/ra/maps/intervention/mission.lua
Normal file
@@ -0,0 +1,286 @@
|
||||
difficulty = OpenRA.GetDifficulty()
|
||||
|
||||
if difficulty == "Medium" then
|
||||
BaseRaidInterval = Utils.Minutes(3)
|
||||
BaseFrontAttackInterval = Utils.Minutes(3) + Utils.Seconds(30)
|
||||
BaseRearAttackInterval = Utils.Minutes(8)
|
||||
UBoatPatrolDelay = Utils.Minutes(2) + Utils.Seconds(30)
|
||||
BaseFrontAttackWpts = { PatrolWpt1, BaseRaidWpt1 }
|
||||
else
|
||||
BaseRaidInterval = Utils.Minutes(2) + Utils.Seconds(30)
|
||||
BaseFrontAttackInterval = Utils.Minutes(2)
|
||||
BaseRearAttackInterval = Utils.Minutes(5)
|
||||
UBoatPatrolDelay = Utils.Minutes(2)
|
||||
BaseFrontAttackWpts = { PatrolWpt1 }
|
||||
end
|
||||
|
||||
Village = { FarmHouse1, FarmHouse2, FarmHouse3, FarmHouse4, FarmHouse5, FarmHouse6, FarmHouse7, FarmHouse8, FarmHouse9, Church }
|
||||
VillageRaidInterval = Utils.Minutes(3)
|
||||
VillageRaidAircraft = { "mig", "mig" }
|
||||
VillageRaidWpts = { VillageRaidWpt1, VillageRaidWpt2 }
|
||||
|
||||
BaseRaidAircraft = { "mig", "mig" }
|
||||
BaseRaidWpts = { UboatPatrolWpt1, BaseRaidWpt2 }
|
||||
|
||||
BaseFrontAttackUnits = {
|
||||
{ Barracks, {"e3", "e3", "e1", "e1", "e1"} },
|
||||
{ WarFactory, {"3tnk", "3tnk", "apc"} }
|
||||
}
|
||||
|
||||
BaseRearAttackUnits = {
|
||||
{ Barracks, {"e3", "e3", "e1", "e1"} },
|
||||
{ WarFactory, {"3tnk", "3tnk", "v2rl"} }
|
||||
}
|
||||
BaseRearAttackWpts = { GroundAttackWpt1, BaseRearAttackWpt1, BaseRearAttackWpt2, BaseRearAttackWpt3 }
|
||||
|
||||
SovietHarvesters = { Harvester1, Harvester2, Harvester3 }
|
||||
HarvesterGuard = { HarvGuard1, HarvGuard2, HarvGuard3 }
|
||||
|
||||
UBoats = { Uboat1, Uboat2, Uboat3, Uboat4, Uboat5, Uboat6 }
|
||||
UboatPatrolWpts1 = { UboatPatrolWpt1, UboatPatrolWpt2, UboatPatrolWpt3, UboatPatrolWpt4 }
|
||||
UboatPatrolWpts2 = { UboatPatrolWpt4, UboatPatrolWpt2, UboatPatrolWpt1 }
|
||||
UBoatPatrolUnits = { { SubPen, {"ss"} } }
|
||||
|
||||
HunterSubs = { { SubPen, {"ss", "ss"} } }
|
||||
|
||||
GroundPatrolWpts = { PatrolWpt1, PatrolWpt2 }
|
||||
GroundPatrolUnits = {
|
||||
{ { Barracks, {"e1", "e1", "e1", "e3", "e3", "dog"} } },
|
||||
{ { WarFactory, {"apc", "apc", "ftrk"} } },
|
||||
{ { WarFactory, {"3tnk", "3tnk"} } }
|
||||
}
|
||||
|
||||
Reinforcements.ReinforceAir = function(owner, planeNames, entrypoint, rallypoint, interval, onCreateFunc)
|
||||
local facing = { Map.GetFacing(CPos.op_Subtraction(rallypoint.Location, entrypoint.Location), 0), "Int32" }
|
||||
local flight = { }
|
||||
|
||||
for i, planeName in ipairs(planeNames) do
|
||||
local plane = Actor.Create(planeName, { AddToWorld = false, Location = entrypoint.Location, Owner = owner, Facing = facing })
|
||||
local enterLocation = entrypoint.Location
|
||||
local enterPosition = WPos.op_Addition(entrypoint.CenterPosition, WVec.New(0, 0, Rules.InitialAltitude(planeName)))
|
||||
flight[i] = plane
|
||||
OpenRA.RunAfterDelay((i - 1) * interval, function()
|
||||
World:Add(plane)
|
||||
Actor.Fly(plane, rallypoint.CenterPosition)
|
||||
if onCreateFunc ~= nil then
|
||||
onCreateFunc(plane)
|
||||
end
|
||||
end)
|
||||
end
|
||||
return flight
|
||||
end
|
||||
|
||||
FollowWaypoints = function(team, waypoints)
|
||||
Utils.Do(waypoints, function(wpt)
|
||||
Team.Do(team, function(a) Actor.Fly(a, wpt.CenterPosition) end)
|
||||
end)
|
||||
end
|
||||
|
||||
PlaneExitMap = function(actor, exitPoint)
|
||||
if not Actor.IsDead(actor) then
|
||||
Actor.Stop(actor)
|
||||
Actor.Fly(actor, exitPoint.CenterPosition)
|
||||
Actor.FlyOffMap(actor)
|
||||
Actor.RemoveSelf(actor)
|
||||
end
|
||||
end
|
||||
|
||||
BaseRaid = function()
|
||||
local base = Map.FindStructuresInBox(player, AlliedAreaTopLeft, AlliedAreaBottomRight)
|
||||
if #base == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local target = base[OpenRA.GetRandomInteger(1, #base + 1)]
|
||||
|
||||
local flight = Team.New(Reinforcements.ReinforceAir(soviets, BaseRaidAircraft, BaseRaidEntrypoint, BaseRaidWpts[1], Utils.Seconds(1)))
|
||||
FollowWaypoints(flight, BaseRaidWpts)
|
||||
|
||||
-- this is a workaround for bug #4482
|
||||
Actor.OnDamaged(target, function()
|
||||
Team.Do(flight, function(plane)
|
||||
PlaneExitMap(plane, VillageRaidEntrypoint)
|
||||
end)
|
||||
end)
|
||||
|
||||
Team.Do(flight, function(plane)
|
||||
Actor.FlyAttackActor(plane, target)
|
||||
end)
|
||||
|
||||
OpenRA.RunAfterDelay(BaseRaidInterval, BaseRaid)
|
||||
end
|
||||
|
||||
VillageRaid = function()
|
||||
local target = nil
|
||||
Utils.Do(Village, function(tgt)
|
||||
if target == nil and not Actor.IsDead(tgt) then
|
||||
target = tgt
|
||||
return
|
||||
end
|
||||
end)
|
||||
|
||||
if target == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local flight = Team.New(Reinforcements.ReinforceAir(soviets, VillageRaidAircraft, VillageRaidEntrypoint, VillageRaidWpts[1], Utils.Seconds(1)))
|
||||
FollowWaypoints(flight, VillageRaidWpts)
|
||||
|
||||
-- this is a workaround for bug #4482
|
||||
Actor.OnDamaged(target, function()
|
||||
Team.Do(flight, function(actor)
|
||||
PlaneExitMap(actor, BaseRaidEntrypoint)
|
||||
end)
|
||||
end)
|
||||
|
||||
Team.Do(flight, function(plane)
|
||||
Actor.FlyAttackActor(plane, target)
|
||||
end)
|
||||
|
||||
OpenRA.RunAfterDelay(VillageRaidInterval, VillageRaid)
|
||||
end
|
||||
|
||||
SendUboatPatrol = function(team)
|
||||
OpenRA.RunAfterDelay(UBoatPatrolDelay, function()
|
||||
if difficulty == "Medium" then
|
||||
Team.Patrol(team, UboatPatrolWpts1, 0, false)
|
||||
else
|
||||
Team.Do(team, Actor.Hunt)
|
||||
end
|
||||
OpenRA.RunAfterDelay(Utils.Minutes(2), function()
|
||||
Team.Do(team, Actor.Stop)
|
||||
Team.Patrol(team, UboatPatrolWpts2)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
SendGroundPatrol = function(team)
|
||||
Team.Patrol(team, GroundPatrolWpts, Utils.Seconds(3))
|
||||
Team.Do(team, function(actor) Actor.OnIdle(actor, Actor.Hunt) end)
|
||||
|
||||
Team.AddEventHandler(team.OnAllKilled, function()
|
||||
Production.BuildTeamFromTemplate(soviets, GroundPatrolUnits[OpenRA.GetRandomInteger(1, #GroundPatrolUnits + 1)], SendGroundPatrol)
|
||||
end)
|
||||
end
|
||||
|
||||
BaseFrontAttack = function(team)
|
||||
Team.Patrol(team, BaseFrontAttackWpts, 0, false)
|
||||
Team.Do(team, function(actor) Actor.OnIdle(actor, Actor.Hunt) end)
|
||||
OpenRA.RunAfterDelay(BaseFrontAttackInterval, function() Production.BuildTeamFromTemplate(soviets, BaseFrontAttackUnits, BaseFrontAttack) end)
|
||||
end
|
||||
|
||||
BaseRearAttack = function(team)
|
||||
Team.Patrol(team, BaseRearAttackWpts, 0, false)
|
||||
Team.Do(team, function(actor) Actor.OnIdle(actor, Actor.Hunt) end)
|
||||
OpenRA.RunAfterDelay(BaseRearAttackInterval, function() Production.BuildTeamFromTemplate(soviets, BaseRearAttackUnits, BaseRearAttack) end)
|
||||
end
|
||||
|
||||
InsertMCV = function ()
|
||||
local mcv = Actor.Create("mcv", { Owner = player, Location = MCVInsertLocation.Location, Facing = Facing.North })
|
||||
Actor.Move(mcv, MCVDeployLocation.Location)
|
||||
Actor.DeployTransform(mcv)
|
||||
end
|
||||
|
||||
SetupWorld = function()
|
||||
if difficulty ~= "Medium" then
|
||||
Actor.RemoveSelf(EasyMine)
|
||||
end
|
||||
|
||||
Utils.Do(SovietHarvesters, Actor.Harvest)
|
||||
|
||||
harvesterGuard = Team.New(HarvesterGuard)
|
||||
Utils.Do(SovietHarvesters, function(harvester)
|
||||
Actor.OnDamaged(harvester, function(h)
|
||||
Team.Do(harvesterGuard, function(g)
|
||||
Actor.Stop(g)
|
||||
Actor.AttackMove(g, h.Location, 3)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
Utils.Do(UBoats, function(a) Actor.SetStance(a, "Defend") end)
|
||||
|
||||
Utils.Do(Actor.ActorsWithTrait("RepairableBuilding"), function(building)
|
||||
if Actor.Owner(building) == soviets then
|
||||
Actor.OnDamaged(building, function(b)
|
||||
Actor.RepairBuilding(b)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
Production.SetRallyPoint(WarFactory, Rallypoint)
|
||||
Production.EventHandlers.Setup(soviets)
|
||||
|
||||
-- RunAfterDelay is used so that the 'Building captured' and 'Mission accomplished' sounds don't play at the same time
|
||||
Actor.OnCaptured(AirForceHQ, function() OpenRA.RunAfterDelay(Utils.Seconds(3), MissionAccomplished) end)
|
||||
Actor.OnKilled(AirForceHQ, MissionFailed)
|
||||
|
||||
village = Team.New(Village)
|
||||
Team.AddEventHandler(village.OnAllKilled, MissionFailed)
|
||||
end
|
||||
|
||||
tick = 0
|
||||
alliedBaseEstablished = false
|
||||
Tick = function()
|
||||
tick = tick + 1
|
||||
|
||||
if OpenRA.GetOre(soviets) > (OpenRA.GetOreCapacity(soviets) * 0.75) then
|
||||
Mission.TickTakeOre(soviets)
|
||||
end
|
||||
|
||||
if Mission.RequiredUnitsAreDestroyed(player) then
|
||||
OpenRA.RunAfterDelay(Utils.Seconds(1), MissionFailed)
|
||||
end
|
||||
|
||||
if not alliedBaseEstablished and tick > Utils.Minutes(5) and tick % Utils.Seconds(10) == 0 then
|
||||
-- FIXME: replace with cell trigger when available
|
||||
local base = Map.FindStructuresInBox(player, AlliedAreaTopLeft, AlliedAreaBottomRight)
|
||||
if #base > 0 then
|
||||
alliedBaseEstablished = true
|
||||
|
||||
OpenRA.RunAfterDelay(BaseFrontAttackInterval, function()
|
||||
Production.BuildTeamFromTemplate(soviets, BaseFrontAttackUnits, BaseFrontAttack)
|
||||
|
||||
local plane, paratroopers = SupportPowers.Paradrop(soviets, "badr", {"e1", "e1", "e1", "e3", "e3"}, BaseRaidEntrypoint.Location, MCVDeployLocation.Location)
|
||||
Utils.Do(paratroopers, function(actor) Actor.OnIdle(actor, Actor.Hunt) end)
|
||||
end)
|
||||
|
||||
OpenRA.RunAfterDelay(BaseRearAttackInterval, function()
|
||||
Production.BuildTeamFromTemplate(soviets, BaseRearAttackUnits, BaseRearAttack)
|
||||
end)
|
||||
|
||||
Production.BuildTeamFromTemplate(soviets, HunterSubs, function(team)
|
||||
Team.Do(team, function(actor) Actor.OnIdle(actor, Actor.Hunt) end)
|
||||
end)
|
||||
|
||||
OpenRA.RunAfterDelay(BaseRaidInterval, BaseRaid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
player = OpenRA.GetPlayer("Allies")
|
||||
soviets = OpenRA.GetPlayer("Soviets")
|
||||
civvies = OpenRA.GetPlayer("Civilians")
|
||||
|
||||
SetupWorld()
|
||||
|
||||
OpenRA.RunAfterDelay(1, function()
|
||||
Production.BuildTeamFromTemplate(soviets, UBoatPatrolUnits, SendUboatPatrol)
|
||||
Production.BuildTeamFromTemplate(soviets, GroundPatrolUnits[OpenRA.GetRandomInteger(1, #GroundPatrolUnits + 1)], SendGroundPatrol)
|
||||
end)
|
||||
OpenRA.RunAfterDelay(VillageRaidInterval, VillageRaid)
|
||||
|
||||
InsertMCV()
|
||||
|
||||
OpenRA.SetViewportCenterPosition(Camera.CenterPosition)
|
||||
OpenRA.RunAfterDelay(Utils.Seconds(5), function() Actor.RemoveSelf(Camera) end)
|
||||
end
|
||||
|
||||
MissionFailed = function()
|
||||
Mission.MissionOver(nil, { player }, false)
|
||||
end
|
||||
|
||||
MissionAccomplished = function()
|
||||
Mission.MissionOver({ player }, nil, false)
|
||||
end
|
||||
@@ -1,3 +1,4 @@
|
||||
Missions:
|
||||
mods/ra/maps/allies-01-classic
|
||||
mods/ra/maps/allies-02-classic
|
||||
mods/ra/maps/allies-02-classic
|
||||
mods/ra/maps/intervention
|
||||
|
||||
Reference in New Issue
Block a user