diff --git a/OpenRA.Mods.RA/ProductionBar.cs b/OpenRA.Mods.RA/ProductionBar.cs index 198f82bcf5..dcc83e8da8 100644 --- a/OpenRA.Mods.RA/ProductionBar.cs +++ b/OpenRA.Mods.RA/ProductionBar.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Drawing; using System.Linq; using OpenRA.FileFormats; @@ -18,13 +19,49 @@ namespace OpenRA.Mods.RA [Desc("Visualizes the remaining build time of actor produced here.")] class ProductionBarInfo : ITraitInfo { - public object Create(ActorInitializer init) { return new ProductionBar( init.self ); } + [Desc("Production queue type, for actors with multiple queues.")] + public readonly string ProductionType = null; + + public object Create(ActorInitializer init) { return new ProductionBar(init.self, this); } } - class ProductionBar : ISelectionBar + class ProductionBar : ISelectionBar, ITick { - Actor self; - public ProductionBar(Actor self) { this.self = self; } + readonly ProductionBarInfo info; + readonly Actor self; + ProductionQueue queue; + float value; + + public ProductionBar(Actor self, ProductionBarInfo info) + { + this.self = self; + this.info = info; + } + + public void Tick(Actor self) + { + if (queue == null) + { + var type = info.ProductionType ?? self.Trait().Info.Produces.First(); + + // Per-actor queue + queue = self.TraitsImplementing() + .FirstOrDefault(q => type == null || type == q.Info.Type); + + if (queue == null) + { + // No queues available - check for classic production queues + queue = self.Owner.PlayerActor.TraitsImplementing() + .FirstOrDefault(q => type == null || type == q.Info.Type); + } + + if (queue == null) + throw new InvalidOperationException("No queues available for production type '{0}'".F(type)); + } + + var current = queue.CurrentItem(); + value = current != null ? 1 - (float)current.RemainingCost / current.TotalCost : 0; + } public float GetValue() { @@ -32,18 +69,7 @@ namespace OpenRA.Mods.RA if (!self.Owner.IsAlliedWith(self.World.RenderPlayer)) return 0; - var queue = self.TraitsImplementing().FirstOrDefault(q => q.CurrentItem() != null); - if (queue == null) - { - var produces = self.Trait().Info.Produces; - queue = self.Owner.PlayerActor.TraitsImplementing() - .FirstOrDefault(q => produces.Contains(q.Info.Type)); - } - - if (queue == null || queue.CurrentItem() == null) - return 0f; - - return 1 - (float)queue.CurrentItem().RemainingCost / queue.CurrentItem().TotalCost; + return value; } public Color GetColor() { return Color.SkyBlue; } diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index a1f07b2c2b..ffb638bfa1 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -41,7 +41,10 @@ FACT: QueuedAudio: Building ReadyAudio: ConstructionComplete BaseBuilding: - ProductionBar: + ProductionBar@Building: + ProductionType: Building + ProductionBar@Defense: + ProductionType: Defense BaseProvider: Cooldown: 75 Range: 14 diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index aead769339..d31607dcfc 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -810,7 +810,10 @@ FACT: IntoActor: mcv Offset: 1,1 Facing: 96 - ProductionBar: + ProductionBar@Building: + ProductionType: Building + ProductionBar@Defense: + ProductionType: Defense DeadBuildingState: BaseProvider: Range: 16 diff --git a/mods/ts/rules/structures.yaml b/mods/ts/rules/structures.yaml index 68b2484bee..adac71c289 100644 --- a/mods/ts/rules/structures.yaml +++ b/mods/ts/rules/structures.yaml @@ -29,7 +29,10 @@ GACNST: IntoActor: mcv Offset: 1,1 Facing: 96 - ProductionBar: + ProductionBar@Building: + ProductionType: Building + ProductionBar@Defense: + ProductionType: Defense -Sellable: WithIdleOverlay@TOP: Sequence: idle-top