diff --git a/OpenRA.Mods.RA/Scripting/Properties/TransportProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/TransportProperties.cs index a8ead8b424..069e1c7fac 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/TransportProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/TransportProperties.cs @@ -11,6 +11,7 @@ using System.Linq; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.RA.Traits; using OpenRA.Scripting; using OpenRA.Traits; @@ -65,4 +66,22 @@ namespace OpenRA.Mods.RA.Scripting Self.QueueActivity(new RemoveSelf()); } } + + [ScriptGlobal("Air Support Powers")] + public class ParatroopersProperties : ScriptActorProperties, Requires + { + readonly ParatroopersPower pp; + + public ParatroopersProperties(ScriptContext context, Actor self) + : base(context, self) + { + pp = self.TraitsImplementing().First(); + } + + [Desc("Activate the actor's Paratroopers Power. Returns the dropped units.")] + public Actor[] SendParatroopers(WPos target, bool randomize = true, int facing = 0) + { + return pp.SendParatroopers(Self, target, randomize, facing); + } + } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs index 4e6540aed5..7951cf67e3 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs @@ -61,13 +61,22 @@ namespace OpenRA.Mods.RA.Traits { base.Activate(self, order, manager); + SendParatroopers(self, self.World.Map.CenterOfCell(order.TargetLocation)); + } + + public Actor[] SendParatroopers(Actor self, WPos target, bool randomize = true, int dropFacing = 0) + { + var units = new List(); + var info = Info as ParatroopersPowerInfo; - var dropFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); - var dropRotation = WRot.FromFacing(dropFacing); - var delta = new WVec(0, -1024, 0).Rotate(dropRotation); + + if (randomize) + dropFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); var altitude = self.World.Map.Rules.Actors[info.UnitType].Traits.Get().CruiseAltitude.Range; - var target = self.World.Map.CenterOfCell(order.TargetLocation) + new WVec(0, 0, altitude); + var dropRotation = WRot.FromFacing(dropFacing); + var delta = new WVec(0, -1024, 0).Rotate(dropRotation); + target = target + new WVec(0, 0, altitude); var startEdge = target - (self.World.Map.DistanceToEdge(target, -delta) + info.Cordon).Range * delta / 1024; var finishEdge = target + (self.World.Map.DistanceToEdge(target, delta) + info.Cordon).Range * delta / 1024; @@ -84,7 +93,7 @@ namespace OpenRA.Mods.RA.Traits { camera = w.CreateActor(info.CameraActor, new TypeDictionary { - new LocationInit(order.TargetLocation), + new LocationInit(self.World.Map.CellContaining(target)), new OwnerInit(self.Owner), }); }); @@ -128,6 +137,14 @@ namespace OpenRA.Mods.RA.Traits } }; + foreach (var p in info.DropItems) + { + var unit = self.World.CreateActor(false, p.ToLowerInvariant(), + new TypeDictionary { new OwnerInit(self.Owner) }); + + units.Add(unit); + } + self.World.AddFrameEndTask(w => { var notification = self.Owner.IsAlliedWith(self.World.RenderPlayer) ? Info.LaunchSound : Info.IncomingSound; @@ -162,13 +179,13 @@ namespace OpenRA.Mods.RA.Traits drop.OnRemovedFromWorld += onExitRange; var cargo = a.Trait(); - var passengers = info.DropItems.Skip(added).Take(passengersPerPlane); + var passengers = units.Skip(added).Take(passengersPerPlane); added += passengersPerPlane; foreach (var p in passengers) - cargo.Load(a, self.World.CreateActor(false, p.ToLowerInvariant(), - new TypeDictionary { new OwnerInit(a.Owner) })); + cargo.Load(a, p); + a.QueueActivity(new Fly(a, Target.FromPos(target + spawnOffset))); a.QueueActivity(new Fly(a, Target.FromPos(finishEdge + spawnOffset))); a.QueueActivity(new RemoveSelf()); aircraftInRange.Add(a, false); @@ -180,8 +197,8 @@ namespace OpenRA.Mods.RA.Traits var distance = (target - startEdge).HorizontalLength; beacon = new Beacon( - order.Player, - self.World.Map.CenterOfCell(order.TargetLocation), + self.Owner, + target, Info.BeaconPalettePrefix, Info.BeaconPoster, Info.BeaconPosterPalette, @@ -190,6 +207,8 @@ namespace OpenRA.Mods.RA.Traits w.Add(beacon); } }); + + return units.ToArray(); } } } diff --git a/mods/ra/maps/allies-03a/allies03a.lua b/mods/ra/maps/allies-03a/allies03a.lua index 0d21906e41..2f9929bafb 100644 --- a/mods/ra/maps/allies-03a/allies03a.lua +++ b/mods/ra/maps/allies-03a/allies03a.lua @@ -1,6 +1,5 @@ ProductionUnits = { "e1", "e1", "e2" } ProductionBuildings = { USSRBarracks1, USSRBarracks2 } -ParatroopersReinforcements = { "e1", "e1", "e1", "e2", "e2" } TransportReinforcements = { "e1", "e1", "e1", "e2", "e2" } FirstUSSRBase = { USSRFlameTower1, USSRBarracks1, USSRPowerPlant1, USSRPowerPlant2, USSRConstructionYard1, USSRTechCenter, USSRBaseGuard1, USSRBaseGuard2, USSRBaseGuard3, USSRBaseGuard4, USSRBaseGuard5, USSRBaseGuard6, USSRBaseGuard7, USSRBaseGuard8 } SecondUSSRBase = { USSRBarracks2, USSRKennel, USSRRadarDome, USSRBaseGuard10, USSRBaseGuard11, USSRBaseGuard12, USSRBaseGuard13, USSRBaseGuard14 } @@ -59,14 +58,19 @@ SendAlliedUnits = function() Trigger.OnKilled(Tanya, function() player.MarkFailedObjective(TanyaSurvive) end) end -SendUSSRParadrops = function(units, entry, dropzone) - local plane = Actor.Create("badr", true, { Owner = ussr, Location = entry }) - Utils.Do(units, function(type) - local unit = Actor.Create(type, false, { Owner = ussr }) - plane.LoadPassenger(unit) +SendUSSRParadrops = function() + local powerproxy = Actor.Create("powerproxy.paratroopers", false, { Owner = ussr }) + local unitsA = powerproxy.SendParatroopers(ParadropLZ.CenterPosition, false, 128 + 32) + local unitsB = powerproxy.SendParatroopers(ParadropLZ.CenterPosition, false, 128 - 32) + + Utils.Do(unitsA, function(unit) IdleHunt(unit) end) - plane.Paradrop(dropzone) + Utils.Do(unitsB, function(unit) + IdleHunt(unit) + end) + + powerproxy.Destroy() end SendUSSRWaterTransport = function() @@ -215,8 +219,7 @@ InitTriggers = function() if a.Owner == player and not paradropsTriggered then paradropsTriggered = true Trigger.RemoveFootprintTrigger(id) - SendUSSRParadrops(ParatroopersReinforcements, ParadropTransportEntry1.Location, ParadropLZ.Location) - SendUSSRParadrops(ParatroopersReinforcements, ParadropTransportEntry2.Location, ParadropLZ.Location) + SendUSSRParadrops() end end) Trigger.OnEnteredFootprint(ReinforcementsTriggerArea, function(a, id) diff --git a/mods/ra/maps/allies-03a/map.yaml b/mods/ra/maps/allies-03a/map.yaml index 1320705d45..72552473c8 100644 --- a/mods/ra/maps/allies-03a/map.yaml +++ b/mods/ra/maps/allies-03a/map.yaml @@ -1304,12 +1304,6 @@ Actors: LargeCameraWaypoint: waypoint Location: 71,65 Owner: Neutral - ParadropTransportEntry1: waypoint - Location: 66,38 - Owner: Neutral - ParadropTransportEntry2: waypoint - Location: 85,38 - Owner: Neutral ParadropLZ: waypoint Location: 73,57 Owner: Neutral @@ -1378,6 +1372,9 @@ Rules: ^Crate: Tooltip: ShowOwnerRow: false + powerproxy.paratroopers: + ParatroopersPower: + DropItems: E1,E1,E1,E2,E2 HACKE6: Inherits: E6 -RepairsBridges: diff --git a/mods/ra/maps/desert-shellmap/desert-shellmap.lua b/mods/ra/maps/desert-shellmap/desert-shellmap.lua index 0f16c9185a..34efded0f9 100644 --- a/mods/ra/maps/desert-shellmap/desert-shellmap.lua +++ b/mods/ra/maps/desert-shellmap/desert-shellmap.lua @@ -1,7 +1,7 @@ if DateTime.IsHalloween then UnitTypes = { "ant", "ant", "ant" } BeachUnitTypes = { "ant", "ant" } - ParadropUnitTypes = { "zombie", "zombie", "zombie", "zombie", "zombie" } + ProxyType = "powerproxy.parazombies" ProducedUnitTypes = { { AlliedBarracks1, { "e1", "e3" } }, @@ -15,7 +15,7 @@ if DateTime.IsHalloween then else UnitTypes = { "3tnk", "ftrk", "ttnk", "apc" } BeachUnitTypes = { "e1", "e2", "e3", "e4", "e1", "e2", "e3", "e4", "e1", "e2", "e3", "e4", "e1", "e2", "e3", "e4" } - ParadropUnitTypes = { "e1", "e1", "e2", "e3", "e4" } + ProxyType = "powerproxy.paratroopers" ProducedUnitTypes = { { AlliedBarracks1, { "e1", "e3" } }, @@ -83,17 +83,13 @@ InsertAlliedChinookReinforcements = function(entry, hpad) end ParadropSovietUnits = function() - local lz = Utils.Random(ParadropWaypoints).Location - local start = Map.CenterOfCell(Map.RandomEdgeCell()) + WVec.New(0, 0, Actor.CruiseAltitude("badr")) - local transport = Actor.Create("badr", true, { CenterPosition = start, Owner = soviets, Facing = (Map.CenterOfCell(lz) - start).Facing }) + local lz = Utils.Random(ParadropWaypoints) + local units = powerproxy.SendParatroopers(lz.CenterPosition) - Utils.Do(ParadropUnitTypes, function(type) - local a = Actor.Create(type, false, { Owner = soviets }) + Utils.Do(units, function(a) BindActorTriggers(a) - transport.LoadPassenger(a) end) - transport.Paradrop(lz) Trigger.AfterDelay(DateTime.Seconds(35), ParadropSovietUnits) end @@ -139,7 +135,7 @@ speed = 5 Tick = function() ticks = ticks + 1 - + local t = (ticks + 45) % (360 * speed) * (math.pi / 180) / speed; Camera.Position = viewportOrigin + WVec.New(19200 * math.sin(t), 20480 * math.cos(t), 0) end @@ -154,6 +150,7 @@ WorldLoaded = function() ShipAlliedUnits() InsertAlliedChinookReinforcements(Chinook1Entry, HeliPad1) InsertAlliedChinookReinforcements(Chinook2Entry, HeliPad2) + powerproxy = Actor.Create(ProxyType, false, { Owner = soviets }) ParadropSovietUnits() Trigger.AfterDelay(DateTime.Seconds(5), ChronoshiftAlliedUnits) Utils.Do(ProducedUnitTypes, ProduceUnits) diff --git a/mods/ra/maps/desert-shellmap/map.yaml b/mods/ra/maps/desert-shellmap/map.yaml index f5f376f650..dc307a8a5a 100644 --- a/mods/ra/maps/desert-shellmap/map.yaml +++ b/mods/ra/maps/desert-shellmap/map.yaml @@ -1331,6 +1331,15 @@ Rules: HP: 200 E7: -Selectable: + powerproxy.paratroopers: + ParatroopersPower: + DisplayBeacon: false + DropItems: E1,E1,E2,E3,E4 + powerproxy.parazombies: + ParatroopersPower: + DropItems: ZOMBIE,ZOMBIE,ZOMBIE,ZOMBIE,ZOMBIE + QuantizedFacings: 8 + DisplayBeacon: false Sequences: diff --git a/mods/ra/maps/intervention/intervention.lua b/mods/ra/maps/intervention/intervention.lua index 03d7268292..ea1b620036 100644 --- a/mods/ra/maps/intervention/intervention.lua +++ b/mods/ra/maps/intervention/intervention.lua @@ -54,19 +54,16 @@ GroundPatrolUnits = { "apc", "apc", "ftrk" }, { "3tnk", "3tnk" } } -Paratroopers = { "e1", "e1", "e1", "e3", "e3" } ParadropSovietUnits = function() - local start = BaseRaidEntrypoint.CenterPosition + WVec.New(0, 0, Actor.CruiseAltitude("badr")) - local transport = Actor.Create("badr", true, { CenterPosition = start, Owner = soviets, Facing = (Map.CenterOfCell(MCVDeployLocation.Location) - start).Facing }) + local powerproxy = Actor.Create("powerproxy.paratroopers", false, { Owner = soviets }) + local units = powerproxy.SendParatroopers(MCVDeployLocation.CenterPosition, false, 256 - 53) - Utils.Do(Paratroopers, function(type) - local a = Actor.Create(type, false, { Owner = soviets }) - transport.LoadPassenger(a) - Trigger.OnIdle(a, function(b) b.Hunt() end) + Utils.Do(units, function(a) + Trigger.OnIdle(a, a.Hunt) end) - transport.Paradrop(MCVDeployLocation.Location) + powerproxy.Destroy() end AirRaid = function(planeTypes, ingress, egress, target) diff --git a/mods/ra/maps/survival01/map.yaml b/mods/ra/maps/survival01/map.yaml index 5ba871360e..df6116f0c4 100644 --- a/mods/ra/maps/survival01/map.yaml +++ b/mods/ra/maps/survival01/map.yaml @@ -1248,6 +1248,9 @@ Rules: GenericVisibility: Enemy, Ally, Neutral GenericStancePrefix: false ShowOwnerRow: false + powerproxy.paratroopers: + ParatroopersPower: + DropItems: E1,E1,E1,E2,E2 CAMERA.sam: Inherits: CAMERA RevealsShroud: diff --git a/mods/ra/maps/survival01/survival01.lua b/mods/ra/maps/survival01/survival01.lua index 8d85ebe831..3bf4fc7a89 100644 --- a/mods/ra/maps/survival01/survival01.lua +++ b/mods/ra/maps/survival01/survival01.lua @@ -44,13 +44,12 @@ SovietAttackGroupSize = 5 SovietInfantryGroupSize = 7 FactoryClearRange = 10 ParadropTicks = DateTime.Seconds(30) -BadgerPassengers = { "e1", "e1", "e1", "e2", "e2" } ParadropWaypoints = { - { BadgerEntryPoint1.Location, ParaDrop1.Location }, - { BadgerEntryPoint2.Location, ParaDrop2.Location }, - { BadgerEntryPoint1.Location, Alliesbase2.Location }, - { BadgerEntryPoint2.Location, Alliesbase1.Location } + { 192 + 4, ParaDrop1}, + { 192 - 4, ParaDrop2}, + { 192 + 4, Alliesbase2}, + { 192 - 4, Alliesbase1} } NavalTransportPassengers = { "e1", "e1", "e2", "e4", "e4" } NavalReinforcementsWaypoints = { NavalWaypoint1, NavalWaypoint2, NavalWaypoint2, NavalWaypoint3 } @@ -120,13 +119,11 @@ Tick = function() end SendSovietParadrops = function(table) - local plane = Actor.Create("badr", true, { Owner = soviets, Location = table[1] }) - Utils.Do(BadgerPassengers, function(type) - local unit = Actor.Create(type, false, { Owner = soviets }) - plane.LoadPassenger(unit) + local units = powerproxy.SendParatroopers(table[2].CenterPosition, false, table[1]) + + Utils.Do(units, function(unit) Trigger.OnIdle(unit, unit.Hunt) end) - plane.Paradrop(table[2]) end SendSovietNavalReinforcements = function() @@ -357,6 +354,7 @@ SetupSoviets = function() Reinforcements.Reinforce(soviets, Squad1, { AlliesBaseGate1.Location, Alliesbase1.Location }) Reinforcements.Reinforce(soviets, Squad2, { AlliesBaseGate2.Location, Alliesbase2.Location }) + powerproxy = Actor.Create("powerproxy.paratroopers", false, { Owner = soviets }) Trigger.AfterDelay(ParadropTicks, function() SendSovietParadrops(ParadropWaypoints[1]) SendSovietParadrops(ParadropWaypoints[2]) diff --git a/mods/ra/rules/misc.yaml b/mods/ra/rules/misc.yaml index 3984bd1897..454463a981 100644 --- a/mods/ra/rules/misc.yaml +++ b/mods/ra/rules/misc.yaml @@ -329,6 +329,19 @@ powerproxy.sonarpulse: EffectSequence: moveflsh EffectPalette: moveflash +powerproxy.paratroopers: + ParatroopersPower: + Icon: paratroopers + Description: Paratroopers + LongDesc: A Badger drops a squad of infantry\nanywhere on the map. + DropItems: E1,E1,E1,E3,E3 + SelectTargetSound: slcttgt1.aud + AllowImpassableCells: false + QuantizedFacings: 8 + CameraActor: camera.paradrop + DisplayBeacon: true + BeaconPoster: pinficon + mpspawn: Immobile: OccupiesSpace: false