diff --git a/OpenRA.Mods.RA/Activities/HeliAttack.cs b/OpenRA.Mods.RA/Activities/HeliAttack.cs index 9ee57be9d6..14bd3ea24a 100644 --- a/OpenRA.Mods.RA/Activities/HeliAttack.cs +++ b/OpenRA.Mods.RA/Activities/HeliAttack.cs @@ -39,8 +39,10 @@ namespace OpenRA.Mods.RA.Activities var limitedAmmo = self.traits.GetOrDefault(); if (limitedAmmo != null && !limitedAmmo.HasAmmo()) + { + self.QueueActivity(new HeliReturn()); return NextActivity; - + } var unit = self.traits.Get(); var info = self.Info.Traits.Get(); diff --git a/OpenRA.Mods.RA/Activities/HeliFly.cs b/OpenRA.Mods.RA/Activities/HeliFly.cs index dd6b78a95c..7525948f01 100644 --- a/OpenRA.Mods.RA/Activities/HeliFly.cs +++ b/OpenRA.Mods.RA/Activities/HeliFly.cs @@ -21,6 +21,7 @@ using System; using OpenRA.GameRules; using OpenRA.Traits; +using System.Linq; namespace OpenRA.Mods.RA.Activities { @@ -48,8 +49,16 @@ namespace OpenRA.Mods.RA.Activities unit.Altitude += Math.Sign(info.CruiseAltitude - unit.Altitude); return this; } - - var dist = Dest - self.CenterLocation; + + // Prevent multiple units from stacking together + var otherHelis = self.World.FindUnitsInCircle(self.CenterLocation, info.IdealSeparation) + .Where(a => a.traits.Contains()); + + var f = otherHelis + .Select(h => GetRepulseForce(self, h)) + .Aggregate(float2.Zero, (a, b) => a + b); + + var dist = Dest - self.CenterLocation + f; if (float2.WithinEpsilon(float2.Zero, dist, 2)) { self.CenterLocation = Dest; @@ -67,6 +76,19 @@ namespace OpenRA.Mods.RA.Activities return this; } + + // Todo: Duplicated from HeliAttack + const float Epsilon = .5f; + float2 GetRepulseForce(Actor self, Actor h) + { + if (self == h) + return float2.Zero; + var d = self.CenterLocation - h.CenterLocation; + if (d.LengthSquared < Epsilon) + return float2.FromAngle((float)self.World.SharedRandom.NextDouble() * 3.14f); + + return (2 / d.LengthSquared) * d; + } public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } } diff --git a/OpenRA.Mods.RA/AttackHeli.cs b/OpenRA.Mods.RA/AttackHeli.cs index 6a3a28f54a..03394eacef 100644 --- a/OpenRA.Mods.RA/AttackHeli.cs +++ b/OpenRA.Mods.RA/AttackHeli.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. * This file is part of OpenRA. @@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA { target = order.TargetActor; self.QueueActivity(new HeliAttack(order.TargetActor)); - self.QueueActivity(new HeliReturn()); + //self.QueueActivity(new HeliReturn()); } } } diff --git a/OpenRA.Mods.RA/Helicopter.cs b/OpenRA.Mods.RA/Helicopter.cs index 5e9fadf2c0..f1be6b177f 100644 --- a/OpenRA.Mods.RA/Helicopter.cs +++ b/OpenRA.Mods.RA/Helicopter.cs @@ -33,6 +33,7 @@ namespace OpenRA.Mods.RA public readonly string[] RearmBuildings = { "hpad" }; public readonly int CruiseAltitude = 20; public readonly int IdealSeparation = 80; + public readonly bool LandWhenIdle = true; public object Create(Actor self) { return new Helicopter(self); } } @@ -78,8 +79,12 @@ namespace OpenRA.Mods.RA { self.CancelActivity(); self.QueueActivity(new HeliFly(Util.CenterOfCell(order.TargetLocation))); - self.QueueActivity(new Turn(self.Info.Traits.GetOrDefault().InitialFacing)); - self.QueueActivity(new HeliLand(true)); + + if (self.Info.Traits.Get().LandWhenIdle) + { + self.QueueActivity(new Turn(self.Info.Traits.GetOrDefault().InitialFacing)); + self.QueueActivity(new HeliLand(true)); + } } if (order.OrderString == "Enter") diff --git a/mods/cnc/vehicles.yaml b/mods/cnc/vehicles.yaml index 671290a380..8aea79eb39 100644 --- a/mods/cnc/vehicles.yaml +++ b/mods/cnc/vehicles.yaml @@ -418,7 +418,7 @@ HELI: Buildable: Icon: heliicnh BuildPaletteOrder: 60 - Prerequisites: hpad + Prerequisites: hpad, hq BuiltAt: hpad Owner: nod Cost: 1200 @@ -438,6 +438,7 @@ HELI: PrimaryOffset: -5,0,0,2 SecondaryOffset: 5,0,0,2 Helicopter: + LandWhenIdle: no RenderUnitRotor: PrimaryOffset: 0,0,0,-2 WithShadow: @@ -449,7 +450,7 @@ ORCA: Buildable: Icon: orcaicnh BuildPaletteOrder: 60 - Prerequisites: hpad + Prerequisites: hpad, hq BuiltAt: hpad Owner: gdi Cost: 1200 @@ -469,6 +470,7 @@ ORCA: PrimaryOffset: -5,0,0,2 SecondaryOffset: 5,0,0,2 Helicopter: + LandWhenIdle: no RenderUnit: WithShadow: LimitedAmmo: