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)); }