diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index b46ba20325..f29d2ca8ce 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -752,7 +752,6 @@ - @@ -792,6 +791,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDisabled.cs b/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDisabled.cs new file mode 100644 index 0000000000..0b5c16226d --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDisabled.cs @@ -0,0 +1,60 @@ +#region Copyright & License Information +/* + * Copyright 2007-2017 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("Applies a condition to the actor when it is disabled.", + "This is a temporary shim to help migration away from the legacy IDisable code")] + public class GrantConditionOnDisabledInfo : ITraitInfo, Requires + { + [FieldLoader.Require] + [GrantedConditionReference] + [Desc("Condition to grant.")] + public readonly string Condition = null; + + public object Create(ActorInitializer init) { return new GrantConditionOnDisabled(this); } + } + + public class GrantConditionOnDisabled : INotifyCreated, ITick + { + readonly GrantConditionOnDisabledInfo info; + + ConditionManager conditionManager; + int conditionToken = ConditionManager.InvalidConditionToken; + + public GrantConditionOnDisabled(GrantConditionOnDisabledInfo info) + { + this.info = info; + } + + void INotifyCreated.Created(Actor self) + { + conditionManager = self.TraitOrDefault(); + + // Set initial disabled state + Tick(self); + } + + public void Tick(Actor self) + { + if (conditionManager == null) + return; + + var disabled = self.IsDisabled(); + if (disabled && conditionToken == ConditionManager.InvalidConditionToken) + conditionToken = conditionManager.GrantCondition(self, info.Condition); + else if (!disabled && conditionToken != ConditionManager.InvalidConditionToken) + conditionToken = conditionManager.RevokeCondition(self, conditionToken); + } + } +} diff --git a/OpenRA.Mods.Common/Traits/Radar/JamsRadar.cs b/OpenRA.Mods.Common/Traits/Radar/JamsRadar.cs deleted file mode 100644 index 349c3dbb44..0000000000 --- a/OpenRA.Mods.Common/Traits/Radar/JamsRadar.cs +++ /dev/null @@ -1,37 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2017 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. For more - * information, see COPYING. - */ -#endregion - -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits.Radar -{ - [Desc("When an actor with this trait is in range of an actor with ProvidesRadar, it will temporarily disable the radar minimap for the enemy player.")] - public class JamsRadarInfo : ITraitInfo - { - [Desc("Range for jamming.")] - public readonly WDist Range = WDist.Zero; - - [Desc("Which diplomatic stances are affected.")] - public readonly Stance Stances = Stance.Enemy | Stance.Neutral; - - public object Create(ActorInitializer init) { return new JamsRadar(this); } - } - - public class JamsRadar - { - public readonly JamsRadarInfo Info; - - public JamsRadar(JamsRadarInfo info) - { - Info = info; - } - } -} diff --git a/OpenRA.Mods.Common/Traits/Radar/ProvidesRadar.cs b/OpenRA.Mods.Common/Traits/Radar/ProvidesRadar.cs index 282877e887..ce67918f7b 100644 --- a/OpenRA.Mods.Common/Traits/Radar/ProvidesRadar.cs +++ b/OpenRA.Mods.Common/Traits/Radar/ProvidesRadar.cs @@ -15,21 +15,14 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Radar { [Desc("This actor enables the radar minimap.")] - public class ProvidesRadarInfo : TraitInfo { } - - public class ProvidesRadar : ITick + public class ProvidesRadarInfo : ConditionalTraitInfo { - public bool IsActive { get; private set; } + public override object Create(ActorInitializer init) { return new ProvidesRadar(this); } + } - public void Tick(Actor self) { IsActive = UpdateActive(self); } - - static bool UpdateActive(Actor self) - { - // Check if powered - if (self.IsDisabled()) return false; - - return self.World.ActorsWithTrait().All(a => !a.Trait.Info.Stances.HasStance(a.Actor.Owner.Stances[self.Owner]) - || (self.CenterPosition - a.Actor.CenterPosition).HorizontalLengthSquared > a.Trait.Info.Range.LengthSquared); - } + public class ProvidesRadar : ConditionalTrait + { + public ProvidesRadar(ProvidesRadarInfo info) + : base(info) { } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index c200197044..efceb98227 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -746,6 +746,36 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + if (engineVersion < 20170121) + { + if (node.Key.StartsWith("ProvidesRadar", StringComparison.Ordinal)) + { + if (node.Value.Nodes.Any(n => n.Key == "RequiresCondition")) + Console.WriteLine("You must manually add the `disabled` condition to the ProvidesRadar RequiresCondition expression"); + else + node.Value.Nodes.Add(new MiniYamlNode("RequiresCondition", "!disabled")); + + if (!parent.Value.Nodes.Any(n => n.Key == "GrantConditionOnDisabled@IDISABLE")) + addNodes.Add(new MiniYamlNode("GrantConditionOnDisabled@IDISABLE", new MiniYaml("", + new List() { new MiniYamlNode("Condition", "disabled") }))); + } + + if (node.Key.StartsWith("JamsRadar", StringComparison.Ordinal)) + { + Console.WriteLine("JamsRadar has been replaced with trait conditions."); + Console.WriteLine("You must manually add the `jammed` condition to the ProvidesRadar traits that you want to be affected."); + Console.WriteLine("You must manually add a WithRangeCircle trait to render the radar jamming range."); + RenameNodeKey(node, "ProximityExternalCondition@JAMMER"); + var stances = node.Value.Nodes.FirstOrDefault(n => n.Key == "Stances"); + if (stances != null) + stances.Key = "ValidStances"; + else + node.Value.Nodes.Add(new MiniYamlNode("ValidStances", "Enemy, Neutral")); + + node.Value.Nodes.Add(new MiniYamlNode("Condition", "jammed")); + } + } + UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs index 38a2624ce0..fde9e38201 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var ticker = widget.Get("RADAR_TICKER"); ticker.OnTick = () => { - radarEnabled = devMode.DisableShroud || world.ActorsHavingTrait(r => r.IsActive) + radarEnabled = devMode.DisableShroud || world.ActorsHavingTrait(r => !r.IsTraitDisabled) .Any(a => a.Owner == world.LocalPlayer); if (radarEnabled != cachedRadarEnabled) diff --git a/OpenRA.Mods.RA/Traits/Render/RenderJammerCircle.cs b/OpenRA.Mods.RA/Traits/Render/RenderJammerCircle.cs index cdddbbec45..27a86f150b 100644 --- a/OpenRA.Mods.RA/Traits/Render/RenderJammerCircle.cs +++ b/OpenRA.Mods.RA/Traits/Render/RenderJammerCircle.cs @@ -35,17 +35,6 @@ namespace OpenRA.Mods.RA.Traits Color.FromArgb(96, Color.Black)); } - var jamsRadar = ai.TraitInfoOrDefault(); - if (jamsRadar != null) - { - yield return new RangeCircleRenderable( - centerPosition, - jamsRadar.Range, - 0, - Color.FromArgb(128, Color.Blue), - Color.FromArgb(96, Color.Black)); - } - foreach (var a in w.ActorsWithTrait()) if (a.Actor.Owner.IsAlliedWith(w.RenderPlayer)) foreach (var r in a.Trait.RenderAboveShroud(a.Actor, wr)) @@ -70,17 +59,6 @@ namespace OpenRA.Mods.RA.Traits Color.FromArgb(128, Color.Red), Color.FromArgb(96, Color.Black)); } - - var jamsRadar = self.Info.TraitInfoOrDefault(); - if (jamsRadar != null) - { - yield return new RangeCircleRenderable( - self.CenterPosition, - jamsRadar.Range, - 0, - Color.FromArgb(128, Color.Blue), - Color.FromArgb(96, Color.Black)); - } } } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs index 9f2acbd3b0..0c8d87ec6c 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs @@ -100,7 +100,7 @@ namespace OpenRA.Mods.RA.Traits owner.GpsAdd(self); } - bool NoActiveRadar { get { return !self.World.ActorsHavingTrait(r => r.IsActive).Any(a => a.Owner == self.Owner); } } + bool NoActiveRadar { get { return !self.World.ActorsHavingTrait(r => !r.IsTraitDisabled).Any(a => a.Owner == self.Owner); } } bool wasDisabled; void ITick.Tick(Actor self) diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 216b00b90c..e7309de5cc 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -472,6 +472,7 @@ HQ: Range: 10c0 Bib: ProvidesRadar: + RequiresCondition: !disabled RenderDetectionCircle: DetectCloaked: Range: 5c0 @@ -496,6 +497,8 @@ HQ: SupportPowerChargeBar: Power: Amount: -50 + GrantConditionOnDisabled@IDISABLE: + Condition: disabled FIX: Inherits: ^BaseBuilding @@ -564,6 +567,7 @@ EYE: Range: 10c0 Bib: ProvidesRadar: + RequiresCondition: !disabled RenderDetectionCircle: DetectCloaked: Range: 5c0 @@ -585,6 +589,8 @@ EYE: Power: Amount: -200 ProvidesPrerequisite@buildingname: + GrantConditionOnDisabled@IDISABLE: + Condition: disabled TMPL: Inherits: ^BaseBuilding diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index fb1d077e7b..c9cb0a489a 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -515,6 +515,7 @@ outpost: RevealsShroud: Range: 4c768 ProvidesRadar: + RequiresCondition: !disabled RenderSprites: Image: outpost.harkonnen FactionImages: @@ -528,6 +529,8 @@ outpost: Power: Amount: -125 ProvidesPrerequisite@buildingname: + GrantConditionOnDisabled@IDISABLE: + Condition: disabled starport: Inherits: ^Building diff --git a/mods/ra/maps/soviet-01/rules.yaml b/mods/ra/maps/soviet-01/rules.yaml index 5e63de596f..6b5406173f 100644 --- a/mods/ra/maps/soviet-01/rules.yaml +++ b/mods/ra/maps/soviet-01/rules.yaml @@ -18,8 +18,10 @@ V01: JEEP: Explodes: - JamsRadar: + ProximityExternalCondition@JAMMER: Range: 10c0 + ValidStances: Enemy, Neutral + Condition: jammed YAK: Buildable: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 490a26c410..4826c4d4e1 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -515,6 +515,9 @@ DOME: Range: 10c0 Bib: ProvidesRadar: + RequiresCondition: !jammed && !disabled + ExternalConditions@JAMMED: + Conditions: jammed InfiltrateForExploration: DetectCloaked: Range: 10c0 @@ -522,6 +525,8 @@ DOME: Power: Amount: -40 ProvidesPrerequisite@buildingname: + GrantConditionOnDisabled@IDISABLE: + Condition: disabled PBOX: Inherits: ^Defense diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index afec84f2b2..e804430d6b 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -540,8 +540,14 @@ MRJ: WithIdleOverlay@SPINNER: Sequence: spinner Offset: -256,0,256 - JamsRadar: + ProximityExternalCondition@JAMMER: Range: 15c0 + ValidStances: Enemy, Neutral + Condition: jammed + WithRangeCircle@JAMMER: + Type: jammer + Range: 15c0 + Color: 0000FF80 JamsMissiles: Range: 4c0 DeflectionStances: Neutral, Enemy diff --git a/mods/ts/rules/gdi-structures.yaml b/mods/ts/rules/gdi-structures.yaml index 19f495c6f4..1fe59cf0e0 100644 --- a/mods/ts/rules/gdi-structures.yaml +++ b/mods/ts/rules/gdi-structures.yaml @@ -314,6 +314,7 @@ GARADR: PowerupSpeech: EnablePower PowerdownSpeech: DisablePower ProvidesRadar: + RequiresCondition: !disabled InfiltrateForExploration: DetectCloaked: Range: 10c0 @@ -331,6 +332,8 @@ GARADR: ProvidesPrerequisite@buildingname: SelectionDecorations: VisualBounds: 96, 118, 0, -38 + GrantConditionOnDisabled@IDISABLE: + Condition: disabled GATECH: Inherits: ^Building diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index 2e4e978bc8..8eda74a8b6 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -273,6 +273,7 @@ NARADR: PowerupSpeech: EnablePower PowerdownSpeech: DisablePower ProvidesRadar: + RequiresCondition: !disabled InfiltrateForExploration: DetectCloaked: Range: 10c0 @@ -290,6 +291,8 @@ NARADR: ProvidesPrerequisite@buildingname: SelectionDecorations: VisualBounds: 96, 72, 0, -12 + GrantConditionOnDisabled@IDISABLE: + Condition: disabled NATECH: Inherits: ^Building