From 5e5183549c0b3df51fc15ffc55773b7342a69fed Mon Sep 17 00:00:00 2001 From: abcdefg30 Date: Sun, 28 Oct 2018 18:39:45 +0000 Subject: [PATCH] Overhaul ProductionBar: - Is now a conditional trait - Now respects multiple Production trait instances - ProductionType is now required --- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../Traits/Render/ProductionBar.cs | 41 ++++++------ .../Rules/20180923/RequireProductionType.cs | 63 +++++++++++++++++++ OpenRA.Mods.Common/UpdateRules/UpdatePath.cs | 1 + mods/cnc/rules/structures.yaml | 4 ++ mods/cnc/rules/tech.yaml | 1 + mods/d2k/rules/structures.yaml | 6 ++ mods/ra/rules/structures.yaml | 8 +++ mods/ts/rules/gdi-structures.yaml | 3 + mods/ts/rules/nod-structures.yaml | 3 + 10 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 OpenRA.Mods.Common/UpdateRules/Rules/20180923/RequireProductionType.cs diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index ffcd625892..bdf595ff57 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -595,6 +595,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs b/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs index bda3e392a4..2d8b7954cc 100644 --- a/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs +++ b/OpenRA.Mods.Common/Traits/Render/ProductionBar.cs @@ -17,73 +17,72 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Visualizes the remaining build time of actor produced here.")] - class ProductionBarInfo : ITraitInfo, Requires + class ProductionBarInfo : ConditionalTraitInfo, Requires { + [FieldLoader.Require] [Desc("Production queue type, for actors with multiple queues.")] public readonly string ProductionType = null; public readonly Color Color = Color.SkyBlue; - public object Create(ActorInitializer init) { return new ProductionBar(init.Self, this); } + public override object Create(ActorInitializer init) { return new ProductionBar(init.Self, this); } } - class ProductionBar : ISelectionBar, ITick, INotifyCreated, INotifyOwnerChanged + class ProductionBar : ConditionalTrait, ISelectionBar, ITick, INotifyOwnerChanged { - readonly ProductionBarInfo info; readonly Actor self; ProductionQueue queue; float value; public ProductionBar(Actor self, ProductionBarInfo info) + : base(info) { this.self = self; - this.info = info; + } + + protected override void Created(Actor self) + { + base.Created(self); + FindQueue(); } void FindQueue() { - var type = info.ProductionType ?? self.Info.TraitInfo().Produces.First(); - // Per-actor queue // Note: this includes disabled queues, as each bar must bind to exactly one queue. queue = self.TraitsImplementing() - .FirstOrDefault(q => type == null || type == q.Info.Type); + .FirstOrDefault(q => Info.ProductionType == 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); + .FirstOrDefault(q => Info.ProductionType == q.Info.Type); } - - if (queue == null) - throw new InvalidOperationException("No queues available for production type '{0}'".F(type)); - } - - void INotifyCreated.Created(Actor self) - { - FindQueue(); } void ITick.Tick(Actor self) { + if (IsTraitDisabled) + return; + var current = queue.AllQueued().Where(i => i.Started).OrderBy(i => i.RemainingTime).FirstOrDefault(); value = current != null ? 1 - (float)current.RemainingCost / current.TotalCost : 0; } float ISelectionBar.GetValue() { - // only people we like should see our production status. - if (!self.Owner.IsAlliedWith(self.World.RenderPlayer)) + // Only people we like should see our production status. + if (IsTraitDisabled || !self.Owner.IsAlliedWith(self.World.RenderPlayer)) return 0; return value; } - Color ISelectionBar.GetColor() { return info.Color; } + Color ISelectionBar.GetColor() { return Info.Color; } bool ISelectionBar.DisplayWhenEmpty { get { return false; } } - public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) + void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { FindQueue(); } diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RequireProductionType.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RequireProductionType.cs new file mode 100644 index 0000000000..46b00458d0 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RequireProductionType.cs @@ -0,0 +1,63 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 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 System.Collections.Generic; +using System.Linq; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + public class RequireProductionType : UpdateRule + { + public override string Name { get { return "Require 'ProductionType' on 'ProductionBar'"; } } + public override string Description + { + get + { + return "The 'ProductionBar' trait now requires the 'ProductionType' to be set.\n" + + "The value will be automatically set to the first value in 'Produces' of the first 'Production' trait."; + } + } + + readonly string[] productionTraits = { "Production", "ProductionAirdrop", "ProductionParadrop", "ProductionFromMapEdge" }; + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + foreach (var pb in actorNode.ChildrenMatching("ProductionBar")) + { + var type = pb.LastChildMatching("ProductionType"); + if (type != null) + continue; + + MiniYamlNode production = null; + foreach (var trait in productionTraits) + { + if (production != null) + break; + + production = actorNode.ChildrenMatching(trait).FirstOrDefault(); + } + + if (production == null) + continue; + + var produces = production.LastChildMatching("Produces"); + if (produces == null) + continue; + + var toAdd = produces.NodeValue().FirstOrDefault(); + if (toAdd != null) + pb.AddNode("ProductionType", toAdd); + } + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index f4fcdf9287..787e3dad49 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -103,6 +103,7 @@ namespace OpenRA.Mods.Common.UpdateRules new AddRearmable(), new MergeAttackPlaneAndHeli(), new RemovedDemolishLocking(), + new RequireProductionType(), }) }; diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 9736c08ab2..c3538d130c 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -322,6 +322,7 @@ PYLE: OnHoldAudio: OnHold CancelledAudio: Cancelled ProductionBar: + ProductionType: Infantry.GDI Power: Amount: -20 ProvidesPrerequisite@buildingname: @@ -372,6 +373,7 @@ HAND: OnHoldAudio: OnHold CancelledAudio: Cancelled ProductionBar: + ProductionType: Infantry.Nod Power: Amount: -20 ProvidesPrerequisite@buildingname: @@ -431,6 +433,7 @@ AFLD: OnHoldAudio: OnHold CancelledAudio: Cancelled ProductionBar: + ProductionType: Vehicle.Nod Power: Amount: -40 ProvidesPrerequisite@buildingname: @@ -489,6 +492,7 @@ WEAP: OnHoldAudio: OnHold CancelledAudio: Cancelled ProductionBar: + ProductionType: Vehicle.GDI Power: Amount: -40 ProvidesPrerequisite@buildingname: diff --git a/mods/cnc/rules/tech.yaml b/mods/cnc/rules/tech.yaml index b4e31bb824..74e598b9e5 100644 --- a/mods/cnc/rules/tech.yaml +++ b/mods/cnc/rules/tech.yaml @@ -104,6 +104,7 @@ BIO: OnHoldAudio: OnHold CancelledAudio: Cancelled ProductionBar: + ProductionType: Biolab RallyPoint: Offset: -1,-1 SpawnActorOnDeath: diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index c68ce01b1f..d4bcec2cfc 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -89,6 +89,7 @@ construction_yard: ActorTypes: light_inf, light_inf, engineer BaseBuilding: ProductionBar: + ProductionType: Building Power: Amount: 20 RenderSprites: @@ -215,6 +216,7 @@ barracks: ProductionQueues: Infantry SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Infantry ProvidesPrerequisite@atreides: Prerequisite: barracks.atreides Factions: atreides @@ -426,6 +428,7 @@ light_factory: ProductionQueues: Vehicle SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Vehicle ProvidesPrerequisite@atreides: Prerequisite: light.atreides Factions: atreides @@ -507,6 +510,7 @@ heavy_factory: ProductionQueues: Armor SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Armor ProvidesPrerequisite@atreides: Prerequisite: heavy.atreides Factions: atreides @@ -669,6 +673,7 @@ starport: RequiresCondition: !build-incomplete Palette: starportlights ProductionBar: + ProductionType: Starport PrimaryBuilding: PrimaryCondition: primary ProductionQueues: Starport @@ -933,6 +938,7 @@ high_tech_factory: ProductionFromMapEdge: Produces: Aircraft, Upgrade ProductionBar: + ProductionType: Aircraft PrimaryBuilding: PrimaryCondition: primary ProductionQueues: Aircraft diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index a91d30e288..dac3ab1b67 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -205,6 +205,7 @@ SPEN: PlayerExperience: 15 RallyPoint: ProductionBar: + ProductionType: Ship Power: Amount: -30 DetectCloaked: @@ -326,6 +327,7 @@ SYRD: PlayerExperience: 15 RallyPoint: ProductionBar: + ProductionType: Ship Power: Amount: -30 DetectCloaked: @@ -1055,6 +1057,7 @@ WEAP: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Vehicle Power: Amount: -30 ProvidesPrerequisite@buildingname: @@ -1320,6 +1323,7 @@ HPAD: Produces: Aircraft, Helicopter Reservable: ProductionBar: + ProductionType: Aircraft PrimaryBuilding: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected @@ -1488,6 +1492,7 @@ AFLD: ClockSequence: clock CircleSequence: circles ProductionBar: + ProductionType: Aircraft SupportPowerChargeBar: PrimaryBuilding: PrimaryCondition: primary @@ -1684,6 +1689,7 @@ BARR: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Infantry ProvidesPrerequisite: Prerequisite: barracks ProvidesPrerequisite@soviet: @@ -1766,6 +1772,7 @@ KENN: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Infantry -SpawnActorsOnSell: Power: Amount: -10 @@ -1826,6 +1833,7 @@ TENT: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Infantry ProvidesPrerequisite@barracks: Prerequisite: barracks ProvidesPrerequisite@allies: diff --git a/mods/ts/rules/gdi-structures.yaml b/mods/ts/rules/gdi-structures.yaml index 78e156397b..587110bb34 100644 --- a/mods/ts/rules/gdi-structures.yaml +++ b/mods/ts/rules/gdi-structures.yaml @@ -110,6 +110,7 @@ GAPILE: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Infantry WithIdleOverlay@LIGHTS: RequiresCondition: !build-incomplete Sequence: idle-lights @@ -174,6 +175,7 @@ GAWEAP: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Vehicle WithIdleOverlay@ROOF: RequiresCondition: !build-incomplete Sequence: idle-roof @@ -242,6 +244,7 @@ GAHPAD: PlayerExperience: 15 StartRepairingNotification: Repairing ProductionBar: + ProductionType: Air WithIdleOverlay@PLATFORM: RequiresCondition: !build-incomplete Sequence: idle-platform diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index ceba1b6e02..c727e2b970 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -119,6 +119,7 @@ NAHAND: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Infantry WithIdleOverlay@LIGHTS: RequiresCondition: !build-incomplete Sequence: idle-lights @@ -180,6 +181,7 @@ NAWEAP: PrimaryCondition: primary SelectionNotification: PrimaryBuildingSelected ProductionBar: + ProductionType: Vehicle WithIdleOverlay@ROOF: RequiresCondition: !build-incomplete Sequence: idle-roof @@ -242,6 +244,7 @@ NAHPAD: PlayerExperience: 15 StartRepairingNotification: Repairing ProductionBar: + ProductionType: Air WithIdleOverlay@PLATFORM: RequiresCondition: !build-incomplete Sequence: idle-platform