diff --git a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs index ae1d62d1ed..23521334ea 100644 --- a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs @@ -120,9 +120,7 @@ namespace OpenRA.Mods.Common.Activities aircraft.MakeReservation(dest); QueueChild(new Land(self, Target.FromActor(dest), offset, facing)); - QueueChild(new Resupply(self, dest, WDist.Zero)); - if (aircraft.Info.FlightDynamics.HasFlag(FlightDynamic.TakeOffOnResupply) && !alwaysLand) - QueueChild(new TakeOff(self)); + QueueChild(new Resupply(self, dest, WDist.Zero, alwaysLand)); return true; } diff --git a/OpenRA.Mods.Common/Activities/Resupply.cs b/OpenRA.Mods.Common/Activities/Resupply.cs index bdb56091ba..1f45c91d01 100644 --- a/OpenRA.Mods.Common/Activities/Resupply.cs +++ b/OpenRA.Mods.Common/Activities/Resupply.cs @@ -32,16 +32,18 @@ namespace OpenRA.Mods.Common.Activities readonly ICallForTransport[] transportCallers; readonly IMove move; readonly Aircraft aircraft; + readonly bool stayOnResupplier; int remainingTicks; bool played; bool actualResupplyStarted; ResupplyType activeResupplyTypes = ResupplyType.None; - public Resupply(Actor self, Actor host, WDist closeEnough) + public Resupply(Actor self, Actor host, WDist closeEnough, bool stayOnResupplier = false) { this.host = Target.FromActor(host); this.closeEnough = closeEnough; + this.stayOnResupplier = stayOnResupplier; allRepairsUnits = host.TraitsImplementing().ToArray(); health = self.TraitOrDefault(); repairable = self.TraitOrDefault(); @@ -75,21 +77,8 @@ namespace OpenRA.Mods.Common.Activities foreach (var notifyResupply in notifyResupplies) notifyResupply.ResupplyTick(host.Actor, self, ResupplyType.None); - if (aircraft != null) - { - aircraft.AllowYieldingReservation(); - if (aircraft.Info.FlightDynamics.HasFlag(FlightDynamic.TakeOffOnResupply)) - Queue(new TakeOff(self)); - - return true; - } - else if (repairableNear != null) - return true; - else - { - QueueChild(move.MoveToTarget(self, host)); - return false; - } + OnResupplyEnding(self); + return true; } else if (IsCanceling || host.Type != TargetType.Actor || !host.Actor.IsInWorld || host.Actor.IsDead) { @@ -148,24 +137,39 @@ namespace OpenRA.Mods.Common.Activities if (activeResupplyTypes == 0) { - if (aircraft != null) - aircraft.AllowYieldingReservation(); - - if (self.CurrentActivity.NextActivity == null) - { - var rp = host.Actor.TraitOrDefault(); - if (rp != null) - Queue(move.MoveTo(rp.Location, repairableNear != null ? null : host.Actor)); - else if (repairableNear == null) - Queue(move.MoveToTarget(self, host)); - } - + OnResupplyEnding(self); return true; } return false; } + void OnResupplyEnding(Actor self) + { + if (aircraft != null) + { + aircraft.AllowYieldingReservation(); + if (!stayOnResupplier && aircraft.Info.FlightDynamics.HasFlag(FlightDynamic.TakeOffOnResupply)) + QueueChild(new TakeOff(self)); + } + else if (!stayOnResupplier) + { + // If there's no next activity, move to rallypoint if available, else just leave host if Repairable. + // Do nothing if RepairableNear (RepairableNear actors don't enter their host and will likely remain within closeEnough). + // If there's a next activity and we're not RepairableNear, first leave host if the next activity is not a Move. + if (self.CurrentActivity.NextActivity == null) + { + var rp = host.Actor.TraitOrDefault(); + if (rp != null) + QueueChild(move.MoveTo(rp.Location, repairableNear != null ? null : host.Actor)); + else if (repairableNear == null) + QueueChild(move.MoveToTarget(self, host)); + } + else if (repairableNear == null && !(self.CurrentActivity.NextActivity is Move)) + QueueChild(move.MoveToTarget(self, host)); + } + } + void RepairTick(Actor self) { // First active.