diff --git a/OpenRA.Mods.Common/Traits/Render/SupportPowerChargeBar.cs b/OpenRA.Mods.Common/Traits/Render/SupportPowerChargeBar.cs index 8d26c979e7..8297b1ff68 100644 --- a/OpenRA.Mods.Common/Traits/Render/SupportPowerChargeBar.cs +++ b/OpenRA.Mods.Common/Traits/Render/SupportPowerChargeBar.cs @@ -15,38 +15,48 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { - [Desc("Display the time remaining until the super weapon attached to the actor is ready to the player and his allies.")] + [Desc("Display the time remaining until the super weapon attached to the actor is ready.")] class SupportPowerChargeBarInfo : ITraitInfo { + [Desc("Defines to which players the bar is to be shown.")] + public readonly Stance DisplayStances = Stance.Ally; + public readonly Color Color = Color.Magenta; public object Create(ActorInitializer init) { return new SupportPowerChargeBar(init.Self, this); } } - class SupportPowerChargeBar : ISelectionBar + class SupportPowerChargeBar : ISelectionBar, INotifyOwnerChanged { readonly Actor self; readonly SupportPowerChargeBarInfo info; + SupportPowerManager spm; public SupportPowerChargeBar(Actor self, SupportPowerChargeBarInfo info) { this.self = self; this.info = info; + spm = self.Owner.PlayerActor.Trait(); } float ISelectionBar.GetValue() { - if (!self.Owner.IsAlliedWith(self.World.RenderPlayer)) + var power = spm.GetPowersForActor(self).FirstOrDefault(sp => !sp.Disabled); + if (power == null) return 0; - var spm = self.Owner.PlayerActor.Trait(); - var power = spm.GetPowersForActor(self).FirstOrDefault(sp => !sp.Disabled); - - if (power == null) return 0; + var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer; + if (viewer != null && info.DisplayStances.HasStance(self.Owner.Stances[viewer])) + return 0; return 1 - (float)power.RemainingTime / power.TotalTime; } Color ISelectionBar.GetColor() { return info.Color; } + + void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) + { + spm = newOwner.PlayerActor.Trait(); + } } } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs index 881df0428a..184b65591a 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs @@ -44,7 +44,8 @@ namespace OpenRA.Mods.Common.Traits public readonly string IncomingSound = null; public readonly string IncomingSpeechNotification = null; - public readonly bool DisplayTimer = false; + [Desc("Defines to which players the timer is shown.")] + public readonly Stance DisplayTimerStances = Stance.None; [Desc("Palette used for the icon.")] [PaletteReference] public readonly string IconPalette = "chrome"; diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 7a1c039647..91d6fc7dec 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -291,6 +291,20 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + // DisplayTimer was replaced by DisplayTimerStances + if (engineVersion < 20160710) + { + if (node.Key == "DisplayTimer") + { + node.Key = "DisplayTimerStances"; + + if (node.Value.Value.ToLower() == "false") + node.Value.Value = "None"; + else + node.Value.Value = "Ally, Neutral, Enemy"; + } + } + UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1); } diff --git a/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs index 23945801e4..bd9038fd87 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowerTimerWidget.cs @@ -16,6 +16,7 @@ using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Traits; using OpenRA.Primitives; +using OpenRA.Traits; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets @@ -36,7 +37,7 @@ namespace OpenRA.Mods.Common.Widgets powers = world.ActorsWithTrait() .Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant) .SelectMany(s => s.Trait.Powers.Values) - .Where(p => p.Instances.Any() && p.Info.DisplayTimer && !p.Disabled); + .Where(p => p.Instances.Any() && p.Info.DisplayTimerStances != Stance.None && !p.Disabled); // Timers in replays should be synced to the effective game time, not the playback time. timestep = world.Timestep; @@ -46,7 +47,14 @@ namespace OpenRA.Mods.Common.Widgets public override void Tick() { - texts = powers.Select(p => + var displayedPowers = powers.Where(p => + { + var owner = p.Instances[0].Self.Owner; + var viewer = owner.World.RenderPlayer ?? owner.World.LocalPlayer; + return viewer == null || p.Info.DisplayTimerStances.HasStance(owner.Stances[viewer]); + }); + + texts = displayedPowers.Select(p => { var time = WidgetUtils.FormatTime(p.RemainingTime, false, timestep); var text = Format.F(p.Info.Description, time); diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 9c37afa3fb..100da51d67 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -32,7 +32,7 @@ MSLO: IncomingSpeechNotification: AbombLaunchDetected MissileWeapon: atomic SpawnOffset: 0,427,0 - DisplayTimer: True + DisplayTimerStances: Ally, Neutral, Enemy DisplayBeacon: True DisplayRadarPing: True BeaconPoster: atomicon @@ -771,7 +771,7 @@ ATEK: LongDesc: Reveals map terrain and provides tactical\ninformation. Requires power and active radar. RevealDelay: 15 LaunchSpeechNotification: SatelliteLaunched - DisplayTimer: True + DisplayTimerStances: Ally, Neutral, Enemy SupportPowerChargeBar: RequiresPower: DisabledOverlay: diff --git a/mods/ts/rules/nod-support.yaml b/mods/ts/rules/nod-support.yaml index 01a75b5794..8aa1bd9167 100644 --- a/mods/ts/rules/nod-support.yaml +++ b/mods/ts/rules/nod-support.yaml @@ -243,7 +243,7 @@ NAMISL: LaunchSound: icbm1.aud MissileWeapon: ClusterMissile SpawnOffset: 0,427,0 - DisplayTimer: False + DisplayTimerStances: None DisplayBeacon: False DisplayRadarPing: True BeaconPoster: