From 57143087d733e6708d0b0a016373baadd6324f6c Mon Sep 17 00:00:00 2001 From: Gustas <37534529+PunkPun@users.noreply.github.com> Date: Fri, 14 Oct 2022 12:56:40 +0300 Subject: [PATCH] Fix Aircraft not updating influence when changing height Occupied cells was defined by height yet we didn't update actor map on changing height. This in some scenarios could have caused the aircraft to forget to remove its influence from actor map --- OpenRA.Mods.Common/Activities/Air/TakeOff.cs | 3 ++ OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 35 +++++++++++++------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/OpenRA.Mods.Common/Activities/Air/TakeOff.cs b/OpenRA.Mods.Common/Activities/Air/TakeOff.cs index 2ed1d5a5ab..31f43ce496 100644 --- a/OpenRA.Mods.Common/Activities/Air/TakeOff.cs +++ b/OpenRA.Mods.Common/Activities/Air/TakeOff.cs @@ -34,6 +34,9 @@ namespace OpenRA.Mods.Common.Activities // We are taking off, so remove influence in ground cells. aircraft.RemoveInfluence(); + if (self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length > aircraft.Info.MinAirborneAltitude) + return; + if (aircraft.Info.TakeoffSounds.Length > 0) Game.Sound.Play(SoundType.World, aircraft.Info.TakeoffSounds, self.World, aircraft.CenterPosition); diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 13362c8d5c..fca6ceec08 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -281,7 +281,7 @@ namespace OpenRA.Mods.Common.Traits public bool MayYieldReservation { get; private set; } public bool ForceLanding { get; private set; } - IEnumerable landingCells = Enumerable.Empty(); + (CPos, SubCell)[] landingCells = Array.Empty<(CPos, SubCell)>(); bool requireForceMove; readonly int creationActivityDelay; @@ -622,10 +622,7 @@ namespace OpenRA.Mods.Common.Traits public (CPos Cell, SubCell SubCell)[] OccupiedCells() { - if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= Info.MinAirborneAltitude) - return landingCells.Select(c => (c, SubCell.FullCell)).ToArray(); - - return new[] { (TopLeft, SubCell.FullCell) }; + return landingCells; } public WVec FlyStep(WAngle facing) @@ -804,10 +801,24 @@ namespace OpenRA.Mods.Common.Traits if (!self.IsInWorld) return; - self.World.UpdateMaps(self, this); - var altitude = self.World.Map.DistanceAboveTerrain(CenterPosition); + // LandingCells define OccupiedCells, so we need to keep current position with LandindCells in sync. + // Though we don't want to update LandingCells when the unit is airborn, as when non-VTOL units reserve + // their landing position it is expected for their landing cell to not match their current position. + if (HasInfluence() && altitude.Length <= Info.MinAirborneAltitude) + { + var currentPos = new[] { (TopLeft, SubCell.FullCell) }; + if (landingCells.SequenceEqual(currentPos)) + { + self.World.ActorMap.RemoveInfluence(self, this); + landingCells = currentPos; + self.World.ActorMap.AddInfluence(self, this); + } + } + + self.World.UpdateMaps(self, this); + var isAirborne = altitude.Length >= Info.MinAirborneAltitude; if (isAirborne && !airborne) OnAirborneAltitudeReached(); @@ -854,9 +865,9 @@ namespace OpenRA.Mods.Common.Traits action(notifyCrushed)(crushable.Actor, self, Info.Crushes); } - public void AddInfluence(IEnumerable landingCells) + public void AddInfluence((CPos, SubCell)[] landingCells) { - if (this.landingCells.Any()) + if (HasInfluence()) throw new InvalidOperationException( $"Cannot {nameof(AddInfluence)} until previous influence is removed with {nameof(RemoveInfluence)}"); @@ -867,7 +878,7 @@ namespace OpenRA.Mods.Common.Traits public void AddInfluence(CPos landingCell) { - AddInfluence(new[] { landingCell }); + AddInfluence(new[] { (landingCell, SubCell.FullCell) }); } public void RemoveInfluence() @@ -875,12 +886,12 @@ namespace OpenRA.Mods.Common.Traits if (self.IsInWorld) self.World.ActorMap.RemoveInfluence(self, this); - landingCells = Enumerable.Empty(); + landingCells = Array.Empty<(CPos, SubCell)>(); } public bool HasInfluence() { - return landingCells.Any() || self.World.Map.DistanceAboveTerrain(CenterPosition).Length < Info.MinAirborneAltitude; + return landingCells.Length > 0; } #endregion