diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 5d13d93dc9..d1438a37d6 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -286,6 +286,7 @@ namespace OpenRA.Mods.Common.Traits public bool RequireForceMove; readonly int creationActivityDelay; + readonly CPos[] creationRallyPoint; bool notify = true; @@ -320,6 +321,7 @@ namespace OpenRA.Mods.Common.Traits Facing = init.GetValue(Info.InitialFacing); creationActivityDelay = init.GetValue(0); + creationRallyPoint = init.GetOrDefault()?.Value; } public WDist LandAltitude @@ -1219,19 +1221,21 @@ namespace OpenRA.Mods.Common.Traits Activity ICreationActivity.GetCreationActivity() { - return new AssociateWithAirfieldActivity(self, creationActivityDelay); + return new AssociateWithAirfieldActivity(self, creationActivityDelay, creationRallyPoint); } sealed class AssociateWithAirfieldActivity : Activity { readonly Aircraft aircraft; readonly int delay; + readonly CPos[] rallyPoint; - public AssociateWithAirfieldActivity(Actor self, int delay = 0) + public AssociateWithAirfieldActivity(Actor self, int delay, CPos[] rallyPoint) { aircraft = self.Trait(); IsInterruptible = false; this.delay = delay; + this.rallyPoint = rallyPoint; } protected override void OnFirstRun(Actor self) @@ -1253,8 +1257,14 @@ namespace OpenRA.Mods.Common.Traits return true; } - if (self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length <= aircraft.LandAltitude.Length) - QueueChild(new TakeOff(self)); + if (rallyPoint != null && aircraft.Info.TakeOffOnCreation) + { + foreach (var cell in rallyPoint) + self.QueueActivity(new AttackMoveActivity(self, () => aircraft.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed))); + } + else + if (self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length <= aircraft.LandAltitude.Length) + QueueChild(new TakeOff(self)); aircraft.UnReserve(); return true; diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index abbc81fe4d..78a87c4b84 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -177,6 +177,7 @@ namespace OpenRA.Mods.Common.Traits readonly bool returnToCellOnCreation; readonly bool returnToCellOnCreationRecalculateSubCell = true; readonly int creationActivityDelay; + readonly CPos[] creationRallypoint; #region IMove CurrentMovementTypes MovementType movementTypes; @@ -298,6 +299,7 @@ namespace OpenRA.Mods.Common.Traits } creationActivityDelay = init.GetValue(0); + creationRallypoint = init.GetOrDefault()?.Value; } protected override void Created(Actor self) @@ -967,9 +969,38 @@ namespace OpenRA.Mods.Common.Traits } } + public class LeaveProductionActivity : Activity + { + readonly Mobile mobile; + readonly int delay; + readonly CPos[] rallyPoint; + readonly ReturnToCellActivity returnToCell; + + public LeaveProductionActivity(Actor self, int delay, CPos[] rallyPoint, ReturnToCellActivity returnToCell) + { + mobile = self.Trait(); + IsInterruptible = false; + this.delay = delay; + this.rallyPoint = rallyPoint; + this.returnToCell = returnToCell; + } + + protected override void OnFirstRun(Actor self) + { + if (returnToCell != null) + self.QueueActivity(returnToCell); + else if (delay > 0) + self.QueueActivity(new Wait(delay)); + + if (rallyPoint != null) + foreach (var cell in rallyPoint) + self.QueueActivity(new AttackMoveActivity(self, () => mobile.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed))); + } + } + Activity ICreationActivity.GetCreationActivity() { - return returnToCellOnCreation ? new ReturnToCellActivity(self, creationActivityDelay, returnToCellOnCreationRecalculateSubCell) : null; + return new LeaveProductionActivity(self, creationActivityDelay, creationRallypoint, returnToCellOnCreation ? new ReturnToCellActivity(self, creationActivityDelay, returnToCellOnCreationRecalculateSubCell) : null); } sealed class MoveOrderTargeter : IOrderTargeter diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index 0f3ada004c..7d6f7f202f 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -11,7 +11,6 @@ using System; using System.Collections.Generic; -using OpenRA.Mods.Common.Activities; using OpenRA.Primitives; using OpenRA.Traits; @@ -82,18 +81,15 @@ namespace OpenRA.Mods.Common.Traits td.Add(new CenterPositionInit(spawn)); td.Add(new FacingInit(initialFacing)); if (exitinfo != null) + { td.Add(new CreationActivityDelayInit(exitinfo.ExitDelay)); + td.Add(new RallyPointInit(exitLocations.ToArray())); + } } self.World.AddFrameEndTask(w => { var newUnit = self.World.CreateActor(producee.Name, td); - - var move = newUnit.TraitOrDefault(); - if (exitinfo != null && move != null) - foreach (var cell in exitLocations) - newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed))); - if (!self.IsDead) foreach (var t in self.TraitsImplementing()) t.UnitProduced(self, newUnit, exit); @@ -143,4 +139,10 @@ namespace OpenRA.Mods.Common.Traits mobileInfo.CanEnterCell(self.World, self, self.Location + s.ExitCell, ignoreActor: self); } } + + public class RallyPointInit : ValueActorInit, ISingleInstanceInit + { + public RallyPointInit(CPos[] value) + : base(value) { } + } }