From eeaa4613115a8b4148a7a6523aaf940301f1e8dd Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 18 Sep 2016 14:11:29 +0100 Subject: [PATCH 1/5] Avoid landing-dances when issuing mixed full/empty aircraft RTB orders. --- .../Activities/Air/HeliReturnToBase.cs | 33 +++++++++++++++---- .../Activities/Air/ReturnToBase.cs | 29 +++++++++++++--- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 4 +-- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs index 471352b9c1..df7ba1519a 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs @@ -19,10 +19,12 @@ namespace OpenRA.Mods.Common.Activities public class HeliReturnToBase : Activity { readonly Aircraft heli; + readonly bool alwaysLand; - public HeliReturnToBase(Actor self) + public HeliReturnToBase(Actor self, bool alwaysLand = true) { heli = self.Trait(); + this.alwaysLand = alwaysLand; } public Actor ChooseHelipad(Actor self) @@ -68,17 +70,36 @@ namespace OpenRA.Mods.Common.Activities } } - heli.MakeReservation(dest); - var exit = dest.Info.TraitInfos().FirstOrDefault(); var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero; + if (ShouldLandAtBuilding(self, dest)) + { + heli.MakeReservation(dest); + + return ActivityUtils.SequenceActivities( + new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)), + new Turn(self, initialFacing), + new HeliLand(self, false), + new ResupplyAircraft(self), + NextActivity); + } + return ActivityUtils.SequenceActivities( new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)), - new Turn(self, initialFacing), - new HeliLand(self, false), - new ResupplyAircraft(self), NextActivity); } + + bool ShouldLandAtBuilding(Actor self, Actor dest) + { + if (alwaysLand) + return true; + + if (heli.Info.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged) + return true; + + return heli.Info.RearmBuildings.Contains(dest.Info.Name) && self.TraitsImplementing() + .Any(p => !p.Info.SelfReloads && !p.FullAmmo()); + } } } diff --git a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs index 9ca9e7aaeb..209276872e 100644 --- a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs @@ -22,13 +22,15 @@ namespace OpenRA.Mods.Common.Activities { readonly Aircraft plane; readonly AircraftInfo planeInfo; + readonly bool alwaysLand; bool isCalculated; Actor dest; WPos w1, w2, w3; - public ReturnToBase(Actor self, Actor dest = null) + public ReturnToBase(Actor self, Actor dest = null, bool alwaysLand = true) { this.dest = dest; + this.alwaysLand = alwaysLand; plane = self.Trait(); planeInfo = self.Info.TraitInfo(); } @@ -51,8 +53,6 @@ namespace OpenRA.Mods.Common.Activities if (dest == null) return; - plane.MakeReservation(dest); - var landPos = dest.CenterPosition; var altitude = planeInfo.CruiseAltitude.Length; @@ -94,6 +94,18 @@ namespace OpenRA.Mods.Common.Activities isCalculated = true; } + bool ShouldLandAtBuilding(Actor self, Actor dest) + { + if (alwaysLand) + return true; + + if (planeInfo.RepairBuildings.Contains(dest.Info.Name) && self.GetDamageState() != DamageState.Undamaged) + return true; + + return planeInfo.RearmBuildings.Contains(dest.Info.Name) && self.TraitsImplementing() + .Any(p => !p.Info.SelfReloads && !p.FullAmmo()); + } + public override Activity Tick(Actor self) { if (IsCanceled || self.IsDead) @@ -128,8 +140,15 @@ namespace OpenRA.Mods.Common.Activities // Fix a problem when the airplane is send to resupply near the airport landingProcedures.Add(new Fly(self, Target.FromPos(w3), WDist.Zero, new WDist(turnRadius / 2))); - landingProcedures.Add(new Land(self, Target.FromActor(dest))); - landingProcedures.Add(new ResupplyAircraft(self)); + + if (ShouldLandAtBuilding(self, dest)) + { + plane.MakeReservation(dest); + + landingProcedures.Add(new Land(self, Target.FromActor(dest))); + landingProcedures.Add(new ResupplyAircraft(self)); + } + landingProcedures.Add(NextActivity); return ActivityUtils.SequenceActivities(landingProcedures.ToArray()); diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 6789a96670..2e45b300b1 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -618,9 +618,9 @@ namespace OpenRA.Mods.Common.Traits UnReserve(); self.CancelActivity(); if (IsPlane) - self.QueueActivity(new ReturnToBase(self)); + self.QueueActivity(new ReturnToBase(self, null, false)); else - self.QueueActivity(new HeliReturnToBase(self)); + self.QueueActivity(new HeliReturnToBase(self, false)); self.QueueActivity(new ResupplyAircraft(self)); } From 6eafaeecf6aa15edfcf3d7a3b008c86ea834b529 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 25 Sep 2016 15:26:23 +0100 Subject: [PATCH 2/5] Remove unnecessarily queued ResupplyAircraft activity. --- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 2e45b300b1..f183dd936e 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -621,8 +621,6 @@ namespace OpenRA.Mods.Common.Traits self.QueueActivity(new ReturnToBase(self, null, false)); else self.QueueActivity(new HeliReturnToBase(self, false)); - - self.QueueActivity(new ResupplyAircraft(self)); } } From ea65ac542e1af104634b7bab4a66ff620988c149 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 25 Sep 2016 15:44:46 +0100 Subject: [PATCH 3/5] Add AbortOnResupply property to cancel aircraft activities on resupply. --- OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs | 2 +- OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs | 3 ++- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs index df7ba1519a..cf9a32f272 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs @@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Activities new Turn(self, initialFacing), new HeliLand(self, false), new ResupplyAircraft(self), - NextActivity); + !heli.Info.AbortOnResupply ? NextActivity : null); } return ActivityUtils.SequenceActivities( diff --git a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs index 209276872e..eab7914ec3 100644 --- a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs @@ -149,7 +149,8 @@ namespace OpenRA.Mods.Common.Activities landingProcedures.Add(new ResupplyAircraft(self)); } - landingProcedures.Add(NextActivity); + if (!planeInfo.AbortOnResupply) + landingProcedures.Add(NextActivity); return ActivityUtils.SequenceActivities(landingProcedures.ToArray()); } diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index f183dd936e..4a84fe62b2 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -69,6 +69,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Does this actor need to turn before landing?")] public readonly bool TurnToLand = false; + [Desc("Does this actor cancel its previous activity after resupplying?")] + public readonly bool AbortOnResupply = false; + public readonly WDist LandAltitude = WDist.Zero; [Desc("How fast this actor ascends or descends when using horizontal take off/landing.")] From 3487d6bad5fc0b8b62ae52a2b0c99aabafc88a4f Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 25 Sep 2016 15:45:23 +0100 Subject: [PATCH 4/5] Change aircraft default to move to rally point after resupplying. --- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 4a84fe62b2..5d28ba48f3 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits public readonly bool TurnToLand = false; [Desc("Does this actor cancel its previous activity after resupplying?")] - public readonly bool AbortOnResupply = false; + public readonly bool AbortOnResupply = true; public readonly WDist LandAltitude = WDist.Zero; From 34b10dcb77f636f7cfdb1932998290ce25eed5af Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 26 Sep 2016 17:48:25 +0100 Subject: [PATCH 5/5] Hack around the Lua API. --- OpenRA.Mods.Common/Activities/Air/FlyAttack.cs | 2 +- OpenRA.Mods.Common/Activities/Air/HeliAttack.cs | 2 +- OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs | 6 ++++-- OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs | 6 ++++-- .../Scripting/Properties/AircraftProperties.cs | 4 ++-- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 10 +++++----- OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs | 2 +- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/OpenRA.Mods.Common/Activities/Air/FlyAttack.cs b/OpenRA.Mods.Common/Activities/Air/FlyAttack.cs index bfa00d0493..a1b31b1b92 100644 --- a/OpenRA.Mods.Common/Activities/Air/FlyAttack.cs +++ b/OpenRA.Mods.Common/Activities/Air/FlyAttack.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Activities // TODO: This should check whether there is ammo left that is actually suitable for the target if (ammoPools.All(x => !x.Info.SelfReloads && !x.HasAmmo())) - return ActivityUtils.SequenceActivities(new ReturnToBase(self), this); + return ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this); if (attackPlane != null) attackPlane.DoAttack(self, target); diff --git a/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs b/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs index 8a429e6f01..339591b33e 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs @@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Activities // If any AmmoPool is depleted and no weapon is valid against target, return to helipad to reload and then resume the activity if (ammoPools.Any(x => !x.Info.SelfReloads && !x.HasAmmo()) && !attackHeli.HasAnyValidWeapons(target)) - return ActivityUtils.SequenceActivities(new HeliReturnToBase(self), this); + return ActivityUtils.SequenceActivities(new HeliReturnToBase(self, helicopter.Info.AbortOnResupply), this); var dist = target.CenterPosition - self.CenterPosition; diff --git a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs index cf9a32f272..98b6adc019 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs @@ -20,11 +20,13 @@ namespace OpenRA.Mods.Common.Activities { readonly Aircraft heli; readonly bool alwaysLand; + readonly bool abortOnResupply; - public HeliReturnToBase(Actor self, bool alwaysLand = true) + public HeliReturnToBase(Actor self, bool abortOnResupply, bool alwaysLand = true) { heli = self.Trait(); this.alwaysLand = alwaysLand; + this.abortOnResupply = abortOnResupply; } public Actor ChooseHelipad(Actor self) @@ -82,7 +84,7 @@ namespace OpenRA.Mods.Common.Activities new Turn(self, initialFacing), new HeliLand(self, false), new ResupplyAircraft(self), - !heli.Info.AbortOnResupply ? NextActivity : null); + !abortOnResupply ? NextActivity : null); } return ActivityUtils.SequenceActivities( diff --git a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs index eab7914ec3..446c9ca281 100644 --- a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs @@ -23,14 +23,16 @@ namespace OpenRA.Mods.Common.Activities readonly Aircraft plane; readonly AircraftInfo planeInfo; readonly bool alwaysLand; + readonly bool abortOnResupply; bool isCalculated; Actor dest; WPos w1, w2, w3; - public ReturnToBase(Actor self, Actor dest = null, bool alwaysLand = true) + public ReturnToBase(Actor self, bool abortOnResupply, Actor dest = null, bool alwaysLand = true) { this.dest = dest; this.alwaysLand = alwaysLand; + this.abortOnResupply = abortOnResupply; plane = self.Trait(); planeInfo = self.Info.TraitInfo(); } @@ -149,7 +151,7 @@ namespace OpenRA.Mods.Common.Activities landingProcedures.Add(new ResupplyAircraft(self)); } - if (!planeInfo.AbortOnResupply) + if (!abortOnResupply) landingProcedures.Add(NextActivity); return ActivityUtils.SequenceActivities(landingProcedures.ToArray()); diff --git a/OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs index 439697f88a..13b71c126d 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs @@ -42,9 +42,9 @@ namespace OpenRA.Mods.Common.Scripting public void ReturnToBase(Actor airfield = null) { if (isPlane) - Self.QueueActivity(new ReturnToBase(Self, airfield)); + Self.QueueActivity(new ReturnToBase(Self, false, airfield)); else - Self.QueueActivity(new HeliReturnToBase(Self)); + Self.QueueActivity(new HeliReturnToBase(Self, false)); } [ScriptActorPropertyActivity] diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 5d28ba48f3..b3097617b4 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -562,9 +562,9 @@ namespace OpenRA.Mods.Common.Traits if (Reservable.IsReserved(order.TargetActor)) { if (IsPlane) - self.QueueActivity(new ReturnToBase(self)); + self.QueueActivity(new ReturnToBase(self, Info.AbortOnResupply)); else - self.QueueActivity(new HeliReturnToBase(self)); + self.QueueActivity(new HeliReturnToBase(self, Info.AbortOnResupply)); } else { @@ -573,7 +573,7 @@ namespace OpenRA.Mods.Common.Traits if (IsPlane) { self.QueueActivity(order.Queued, ActivityUtils.SequenceActivities( - new ReturnToBase(self, order.TargetActor), + new ReturnToBase(self, Info.AbortOnResupply, order.TargetActor), new ResupplyAircraft(self))); } else @@ -621,9 +621,9 @@ namespace OpenRA.Mods.Common.Traits UnReserve(); self.CancelActivity(); if (IsPlane) - self.QueueActivity(new ReturnToBase(self, null, false)); + self.QueueActivity(new ReturnToBase(self, Info.AbortOnResupply, null, false)); else - self.QueueActivity(new HeliReturnToBase(self, false)); + self.QueueActivity(new HeliReturnToBase(self, Info.AbortOnResupply, false)); } } diff --git a/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs b/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs index 78e1847462..d6843e56c2 100644 --- a/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs +++ b/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits var airfield = ReturnToBase.ChooseAirfield(self, true); if (airfield != null) { - self.QueueActivity(new ReturnToBase(self, airfield)); + self.QueueActivity(new ReturnToBase(self, aircraftInfo.AbortOnResupply, airfield)); self.QueueActivity(new ResupplyAircraft(self)); } else