diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 67919c0759..dbb39bf033 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -55,6 +55,10 @@ namespace OpenRA.Mods.Common.Traits [Desc("The upgrades to grant to self while airborne.")] public readonly string[] AirborneUpgrades = { }; + [UpgradeGrantedReference] + [Desc("The upgrades to grant to self while at cruise altitude.")] + public readonly string[] CruisingUpgrades = { }; + [Desc("Can the actor hover in place mid-air? If not, then the actor will have to remain in motion (circle around).")] public readonly bool CanHover = false; @@ -100,29 +104,7 @@ namespace OpenRA.Mods.Common.Traits public int ROT { get { return Info.ROT; } } bool airborne; - bool IsAirborne - { - get - { - return airborne; - } - - set - { - if (airborne == value) - return; - airborne = value; - if (um != null) - { - if (airborne) - foreach (var u in Info.AirborneUpgrades) - um.GrantUpgrade(self, u, this); - else - foreach (var u in Info.AirborneUpgrades) - um.RevokeUpgrade(self, u, this); - } - } - } + bool cruising; public Aircraft(ActorInitializer init, AircraftInfo info) { @@ -149,8 +131,11 @@ namespace OpenRA.Mods.Common.Traits self.World.ActorMap.AddInfluence(self, this); self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); - if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= Info.MinAirborneAltitude) - IsAirborne = true; + var altitude = self.World.Map.DistanceAboveTerrain(CenterPosition); + if (altitude.Length >= Info.MinAirborneAltitude) + OnAirborneAltitudeReached(); + if (altitude == Info.CruiseAltitude) + OnCruisingAltitudeReached(); } bool firstTick = true; @@ -369,7 +354,17 @@ namespace OpenRA.Mods.Common.Traits self.World.ScreenMap.Update(self); self.World.ActorMap.UpdatePosition(self, this); - IsAirborne = self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= Info.MinAirborneAltitude; + var altitude = self.World.Map.DistanceAboveTerrain(CenterPosition); + var isAirborne = altitude.Length >= Info.MinAirborneAltitude; + if (isAirborne && !airborne) + OnAirborneAltitudeReached(); + else if (!isAirborne && airborne) + OnAirborneAltitudeLeft(); + var isCruising = altitude == Info.CruiseAltitude; + if (isCruising && !cruising) + OnCruisingAltitudeReached(); + else if (!isCruising && cruising) + OnCruisingAltitudeLeft(); } #endregion @@ -610,9 +605,58 @@ namespace OpenRA.Mods.Common.Traits self.World.ActorMap.RemoveInfluence(self, this); self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); - IsAirborne = false; + OnCruisingAltitudeLeft(); + OnAirborneAltitudeLeft(); } + #region Airborne upgrades + + void OnAirborneAltitudeReached() + { + if (airborne) + return; + airborne = true; + if (um != null) + foreach (var u in Info.AirborneUpgrades) + um.GrantUpgrade(self, u, this); + } + + void OnAirborneAltitudeLeft() + { + if (!airborne) + return; + airborne = false; + if (um != null) + foreach (var u in Info.AirborneUpgrades) + um.RevokeUpgrade(self, u, this); + } + + #endregion + + #region Cruising upgrades + + void OnCruisingAltitudeReached() + { + if (cruising) + return; + cruising = true; + if (um != null) + foreach (var u in Info.CruisingUpgrades) + um.GrantUpgrade(self, u, this); + } + + void OnCruisingAltitudeLeft() + { + if (!cruising) + return; + cruising = false; + if (um != null) + foreach (var u in Info.CruisingUpgrades) + um.RevokeUpgrade(self, u, this); + } + + #endregion + public void Disposing(Actor self) { UnReserve(); diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index 7e5ca40f69..e31ef10108 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -135,6 +135,7 @@ RepairBuildings: hpad LandWhenIdle: false AirborneUpgrades: airborne + CruisingUpgrades: cruising CanHover: True HiddenUnderFog: Type: CenterPosition @@ -150,7 +151,9 @@ GenericName: Helicopter WithFacingSpriteBody: WithShadow: - Hovers: + Hovers@CRUISING: + UpgradeTypes: cruising + UpgradeMinEnabledLevel: 1 MustBeDestroyed: Voiced: VoiceSet: VehicleVoice diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 798ebf032f..6a6da42e55 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -353,6 +353,7 @@ RepairBuildings: fix RearmBuildings: afld AirborneUpgrades: airborne + CruisingUpgrades: cruising Targetable@GROUND: TargetTypes: Ground, Repair, Vehicle UpgradeTypes: airborne @@ -396,7 +397,9 @@ CanHover: True GpsDot: String: Helicopter - Hovers: + Hovers@CRUISING: + UpgradeTypes: cruising + UpgradeMinEnabledLevel: 1 ^BasicBuilding: Inherits@1: ^ExistsInWorld @@ -625,6 +628,7 @@ GenericName: Destroyed Plane Aircraft: AirborneUpgrades: airborne + CruisingUpgrades: cruising FallsToEarth: Spins: False Moves: True @@ -637,6 +641,7 @@ GenericName: Destroyed Helicopter Aircraft: AirborneUpgrades: airborne + CruisingUpgrades: cruising CanHover: True FallsToEarth: diff --git a/mods/ts/rules/aircraft.yaml b/mods/ts/rules/aircraft.yaml index 5b050cab69..8abe01ed8a 100644 --- a/mods/ts/rules/aircraft.yaml +++ b/mods/ts/rules/aircraft.yaml @@ -59,7 +59,6 @@ DSHP: MaxWeight: 5 PipCount: 5 UnloadVoice: Move - Hovers: ORCA: Inherits: ^Helicopter @@ -98,9 +97,6 @@ ORCA: PipTypeEmpty: AmmoEmpty AutoTarget: RenderSprites: - Hovers@AIRBORNE: - UpgradeTypes: airborne - UpgradeMinEnabledLevel: 1 ORCAB: Inherits: ^Plane @@ -144,8 +140,8 @@ ORCAB: PipTypeEmpty: AmmoEmpty AutoTarget: RenderSprites: - Hovers@AIRBORNE: - UpgradeTypes: airborne + Hovers@CRUISING: + UpgradeTypes: cruising UpgradeMinEnabledLevel: 1 ORCATRAN: @@ -179,9 +175,6 @@ ORCATRAN: MaxWeight: 5 PipCount: 5 UnloadVoice: Move - Hovers@AIRBORNE: - UpgradeTypes: airborne - UpgradeMinEnabledLevel: 1 TRNSPORT: Inherits: ^Helicopter @@ -211,9 +204,6 @@ TRNSPORT: Range: 2c0 Type: CenterPosition RenderSprites: - Hovers@AIRBORNE: - UpgradeTypes: airborne - UpgradeMinEnabledLevel: 1 Selectable: Bounds: 44,32,0,-8 @@ -298,9 +288,6 @@ APACHE: WithSpriteRotorOverlay: Offset: 85,0,384 RenderSprites: - Hovers@AIRBORNE: - UpgradeTypes: airborne - UpgradeMinEnabledLevel: 1 HUNTER: Inherits@1: ^GainsExperience @@ -331,7 +318,9 @@ HUNTER: RenderSprites: Image: GGHUNT WithFacingSpriteBody: - Hovers: + Hovers@CRUISING: + UpgradeTypes: cruising + UpgradeMinEnabledLevel: 1 QuantizeFacingsFromSequence: AutoSelectionSize: DrawLineToTarget: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 0da8cfcfaa..0175ad847a 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -472,6 +472,13 @@ Selectable: SelectionDecorations: Palette: pips + Aircraft: + AirborneUpgrades: airborne + CruisingUpgrades: cruising + RepairBuildings: gadept + RearmBuildings: gahpad, nahpad + LandWhenIdle: no + Voice: Move Voiced: VoiceSet: Heli HiddenUnderFog: @@ -492,23 +499,18 @@ ^Helicopter: Inherits: ^Aircraft Aircraft: - RepairBuildings: gadept - RearmBuildings: gahpad, nahpad LandWhenIdle: no CruiseAltitude: 2048 - Voice: Move - AirborneUpgrades: airborne CanHover: True + Hovers@CRUISING: + UpgradeTypes: cruising + UpgradeMinEnabledLevel: 1 ^Plane: Inherits: ^Aircraft Aircraft: - RepairBuildings: gadept - RearmBuildings: gahpad, nahpad LandWhenIdle: no CruiseAltitude: 2560 - Voice: Move - AirborneUpgrades: airborne ReturnOnIdle: ^Viceroid: