diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 753bbb3fc5..7a019c4fcb 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 bool creationByMap; readonly CPos[] creationRallyPoint; bool notify = true; @@ -312,12 +313,13 @@ namespace OpenRA.Mods.Common.Traits self = init.Self; var locationInit = init.GetOrDefault(); - if (locationInit != null) - SetPosition(self, locationInit.Value); - var centerPositionInit = init.GetOrDefault(); - if (centerPositionInit != null) - SetPosition(self, centerPositionInit.Value); + if (locationInit != null || centerPositionInit != null) + { + var pos = centerPositionInit?.Value ?? self.World.Map.CenterOfCell(locationInit.Value); + creationByMap = init.Contains(); + SetPosition(self, pos); + } Facing = init.GetValue(Info.InitialFacing); creationActivityDelay = init.GetValue(0); @@ -1220,8 +1222,8 @@ namespace OpenRA.Mods.Common.Traits Activity ICreationActivity.GetCreationActivity() { - if (creationRallyPoint != null || creationActivityDelay > 0) - return new AssociateWithAirfieldActivity(self, creationActivityDelay, creationRallyPoint); + if (creationRallyPoint != null || creationActivityDelay > 0 || creationByMap) + return new AssociateWithAirfieldActivity(this, creationActivityDelay, creationRallyPoint, creationByMap); return null; } @@ -1231,27 +1233,69 @@ namespace OpenRA.Mods.Common.Traits readonly Aircraft aircraft; readonly int delay; readonly CPos[] rallyPoint; + readonly bool creationByMap; - public AssociateWithAirfieldActivity(Actor self, int delay, CPos[] rallyPoint) + public AssociateWithAirfieldActivity(Aircraft self, int delay, CPos[] rallyPoint, bool creationByMap) { - aircraft = self.Trait(); + aircraft = self; this.delay = delay; this.rallyPoint = rallyPoint; + this.creationByMap = creationByMap; } protected override void OnFirstRun(Actor self) { - var host = aircraft.GetActorBelow(); - if (host != null) + var cpos = self.Location; + var pos = self.CenterPosition; + bool TryDock() { - aircraft.MakeReservation(host); + var host = aircraft.GetActorBelow(); + if (host != null) + { + // Center the actor on the resupplier. + var exit = host.NearestExitOrDefault(pos); + pos = host.CenterPosition; + pos = new WPos(pos.X, pos.Y, pos.Z - self.World.Map.DistanceAboveTerrain(pos).Length); + if (exit != null) + { + pos += exit.Info.SpawnOffset; + if (exit.Info.Facing != null) + aircraft.Facing = exit.Info.Facing.Value; + } - // Freshly created aircraft shouldn't block the exit, so we allow them to yield their reservation. - aircraft.AllowYieldingReservation(); + aircraft.AddInfluence(cpos); + aircraft.SetPosition(self, pos); + aircraft.MakeReservation(host); + + // Freshly created aircraft shouldn't block the exit, so we allow them to yield their reservation. + aircraft.AllowYieldingReservation(); + return true; + } + + return false; } - if (delay > 0) - QueueChild(new Wait(delay)); + if (creationByMap) + { + if (TryDock()) + return; + + pos = new WPos(pos.X, pos.Y, pos.Z - self.World.Map.DistanceAboveTerrain(pos).Length); + + if (!aircraft.Info.TakeOffOnCreation && aircraft.CanLand(cpos)) + { + aircraft.AddInfluence(cpos); + aircraft.SetPosition(self, pos); + } + else + aircraft.SetPosition(self, new WPos(pos.X, pos.Y, pos.Z + aircraft.Info.CruiseAltitude.Length)); + } + else + { + TryDock(); + if (delay > 0) + QueueChild(new Wait(delay)); + } } public override bool Tick(Actor self) @@ -1260,16 +1304,29 @@ namespace OpenRA.Mods.Common.Traits return true; if (rallyPoint != null && rallyPoint.Length > 0) - { foreach (var cell in rallyPoint) QueueChild(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(); + if (!creationByMap) + aircraft.UnReserve(); + return true; } + + public override IEnumerable GetTargets(Actor self) + { + if (ChildActivity != null) + return ChildActivity.GetTargets(self); + + return Target.None; + } + + public override IEnumerable TargetLineNodes(Actor self) + { + if (ChildActivity != null) + foreach (var n in ChildActivity.TargetLineNodes(self)) + yield return n; + } } public class AircraftMoveOrderTargeter : IOrderTargeter diff --git a/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs b/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs index c4337113a0..a781408cf4 100644 --- a/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs +++ b/OpenRA.Mods.Common/Traits/World/SpawnStartingUnits.cs @@ -94,6 +94,7 @@ namespace OpenRA.Mods.Common.Traits new OwnerInit(p), new SkipMakeAnimsInit(), new FacingInit(facing), + new SpawnedByMapInit(), }); } @@ -123,6 +124,7 @@ namespace OpenRA.Mods.Common.Traits new LocationInit(validCell), new SubCellInit(subCell), new FacingInit(facing), + new SpawnedByMapInit(), }); } } diff --git a/mods/d2k/rules/aircraft.yaml b/mods/d2k/rules/aircraft.yaml index 7a030b3214..e871bd55c3 100644 --- a/mods/d2k/rules/aircraft.yaml +++ b/mods/d2k/rules/aircraft.yaml @@ -18,6 +18,7 @@ carryall.reinforce: LandableTerrainTypes: Sand, Rock, Transition, Spice, SpiceSand, Dune, Concrete Repulsable: False AirborneCondition: airborne + CanForceLand: false CanSlide: True VTOL: true IdleTurnSpeed: 4