diff --git a/OpenRA.Mods.Common/Activities/Air/Fly.cs b/OpenRA.Mods.Common/Activities/Air/Fly.cs index ac1884f1b4..5293e3047b 100644 --- a/OpenRA.Mods.Common/Activities/Air/Fly.cs +++ b/OpenRA.Mods.Common/Activities/Air/Fly.cs @@ -26,7 +26,6 @@ namespace OpenRA.Mods.Common.Activities Target target; Target lastVisibleTarget; bool useLastVisibleTarget; - bool soundPlayed; public Fly(Actor self, Target t, WPos? initialTargetPosition = null, Color? targetLineColor = null) { @@ -103,6 +102,13 @@ namespace OpenRA.Mods.Common.Activities public override Activity Tick(Actor self) { + if (ChildActivity != null) + { + ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); + if (ChildActivity != null) + return this; + } + // Refuse to take off if it would land immediately again. if (aircraft.ForceLanding) Cancel(self); @@ -110,6 +116,13 @@ namespace OpenRA.Mods.Common.Activities if (IsCanceling) return NextActivity; + var dat = self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition); + if (dat <= aircraft.LandAltitude) + { + QueueChild(self, new TakeOff(self, target), true); + return this; + } + bool targetIsHiddenActor; target = target.Recalculate(self.Owner, out targetIsHiddenActor); if (!targetIsHiddenActor && target.Type == TargetType.Actor) @@ -126,25 +139,6 @@ namespace OpenRA.Mods.Common.Activities if (useLastVisibleTarget && !lastVisibleTarget.IsValidFor(self)) return NextActivity; - var dat = self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition); - - // We are taking off, so remove influence in ground cells. - if (dat <= aircraft.LandAltitude) - { - if (!soundPlayed && aircraft.Info.TakeoffSounds.Length > 0) - { - Game.Sound.Play(SoundType.World, aircraft.Info.TakeoffSounds, self.World, aircraft.CenterPosition); - soundPlayed = true; - } - - aircraft.RemoveInfluence(); - } - - // If we're a VTOL, rise before flying forward - if (aircraft.Info.VTOL) - if (VerticalTakeOffOrLandTick(self, aircraft, aircraft.Facing, aircraft.Info.CruiseAltitude)) - return this; - var checkTarget = useLastVisibleTarget ? lastVisibleTarget : target; var delta = checkTarget.CenterPosition - self.CenterPosition; var desiredFacing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : aircraft.Facing; @@ -188,10 +182,7 @@ namespace OpenRA.Mods.Common.Activities return NextActivity; } - // Don't turn until we've reached the cruise altitude - if (dat < aircraft.Info.CruiseAltitude) - desiredFacing = aircraft.Facing; - else if (!aircraft.Info.CanHover) + if (!aircraft.Info.CanHover) { // Using the turn rate, compute a hypothetical circle traced by a continuous turn. // If it contains the destination point, it's unreachable without more complex manuvering. diff --git a/OpenRA.Mods.Common/Activities/Air/TakeOff.cs b/OpenRA.Mods.Common/Activities/Air/TakeOff.cs index 10f37734b2..55ed7c7b09 100644 --- a/OpenRA.Mods.Common/Activities/Air/TakeOff.cs +++ b/OpenRA.Mods.Common/Activities/Air/TakeOff.cs @@ -12,6 +12,7 @@ using System; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { @@ -19,23 +20,51 @@ namespace OpenRA.Mods.Common.Activities { readonly Aircraft aircraft; readonly IMove move; - Func moveToRallyPoint; + readonly Target target; + bool moveToRallyPoint; - public TakeOff(Actor self) + public TakeOff(Actor self, Target target) { aircraft = self.Trait(); move = self.Trait(); - moveToRallyPoint = (actor, activity, pos) => NextActivity == null; + this.target = target; } - public TakeOff(Actor self, Func moveToRallyPoint) - : this(self) + public TakeOff(Actor self) + : this(self, Target.FromCell(self.World, self.Location)) { - this.moveToRallyPoint = moveToRallyPoint; + var host = aircraft.GetActorBelow(); + var rp = host != null ? host.TraitOrDefault() : null; + + var rallyPointDestination = rp != null ? rp.Location : + (host != null ? self.World.Map.CellContaining(host.CenterPosition) : self.Location); + + this.target = Target.FromCell(self.World, rallyPointDestination); + moveToRallyPoint = NextActivity == null && rallyPointDestination != self.Location; + } + + protected override void OnFirstRun(Actor self) + { + if (aircraft.ForceLanding) + return; + + // We are taking off, so remove reservation and influence in ground cells. + aircraft.UnReserve(); + aircraft.RemoveInfluence(); + + if (aircraft.Info.TakeoffSounds.Length > 0) + Game.Sound.Play(SoundType.World, aircraft.Info.TakeoffSounds, self.World, aircraft.CenterPosition); } public override Activity Tick(Actor self) { + if (ChildActivity != null) + { + ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); + if (ChildActivity != null) + return this; + } + // Refuse to take off if it would land immediately again. if (aircraft.ForceLanding) { @@ -43,17 +72,29 @@ namespace OpenRA.Mods.Common.Activities return NextActivity; } - aircraft.UnReserve(); + var dat = self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition); + if (dat < aircraft.Info.CruiseAltitude) + { + // If we're a VTOL, rise before flying forward + if (aircraft.Info.VTOL) + { + Fly.VerticalTakeOffOrLandTick(self, aircraft, aircraft.Facing, aircraft.Info.CruiseAltitude); + return this; + } + else + { + Fly.FlyTick(self, aircraft, aircraft.Facing, aircraft.Info.CruiseAltitude); + return this; + } + } - var host = aircraft.GetActorBelow(); - var hasHost = host != null; - var rp = hasHost ? host.TraitOrDefault() : null; - - var destination = rp != null ? rp.Location : - (hasHost ? self.World.Map.CellContaining(host.CenterPosition) : self.Location); - - if (moveToRallyPoint(self, this, destination)) - return new AttackMoveActivity(self, () => move.MoveTo(destination, 1)); + // Checking for NextActivity == null again in case another activity was queued while taking off + if (moveToRallyPoint && NextActivity == null) + { + QueueChild(self, new AttackMoveActivity(self, () => move.MoveToTarget(self, target)), true); + moveToRallyPoint = false; + return this; + } return NextActivity; } diff --git a/OpenRA.Mods.Common/Activities/Resupply.cs b/OpenRA.Mods.Common/Activities/Resupply.cs index 7996493fbe..27dc9c944e 100644 --- a/OpenRA.Mods.Common/Activities/Resupply.cs +++ b/OpenRA.Mods.Common/Activities/Resupply.cs @@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Activities { aircraft.AllowYieldingReservation(); if (aircraft.Info.TakeOffOnResupply) - Queue(self, new TakeOff(self, (a, b, c) => NextActivity == null && b.NextActivity == null)); + Queue(self, new TakeOff(self)); } return NextActivity; diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 70da646160..37aeb67661 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -795,13 +795,7 @@ namespace OpenRA.Mods.Common.Traits public Activity MoveToTarget(Actor self, Target target, WPos? initialTargetPosition = null, Color? targetLineColor = null) { - if (!Info.CanHover) - return new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5), - initialTargetPosition, targetLineColor); - - return ActivityUtils.SequenceActivities(self, - new Fly(self, target, initialTargetPosition, targetLineColor), - new Turn(self, Info.InitialFacing)); + return new Fly(self, target, initialTargetPosition, targetLineColor); } public Activity MoveIntoTarget(Actor self, Target target)