From 267d89a459170b227c9f4b6482dbebec34632c0f Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 26 Aug 2010 21:16:39 +1200 Subject: [PATCH] Remove BS from ProductionQueue. Move ProductionQueue onto a structure for queue-per-building. --- OpenRA.Game/Network/Order.cs | 15 ++ .../Orders/PlaceBuildingOrderGenerator.cs | 11 +- OpenRA.Game/Traits/Player/PlaceBuilding.cs | 22 +-- OpenRA.Game/Traits/Player/ProductionQueue.cs | 126 +++++++++-------- OpenRA.Game/Traits/Production.cs | 3 + OpenRA.Mods.RA/HackyAI.cs | 37 +++-- OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs | 129 +++++++++--------- .../World/ChooseBuildTabOnSelect.cs | 4 +- mods/cnc/system.yaml | 20 ++- 9 files changed, 209 insertions(+), 158 deletions(-) diff --git a/OpenRA.Game/Network/Order.cs b/OpenRA.Game/Network/Order.cs index 848bd69c26..55609a2526 100755 --- a/OpenRA.Game/Network/Order.cs +++ b/OpenRA.Game/Network/Order.cs @@ -177,6 +177,21 @@ namespace OpenRA return new Order("Command", null, text) { IsImmediate = true }; } + public static Order StartProduction(Actor subject, string item, int count) + { + return new Order("StartProduction", subject, new int2( count, 0 ), item ); + } + + public static Order PauseProduction(Actor subject, string item, bool pause) + { + return new Order("PauseProduction", subject, new int2( pause ? 1 : 0, 0 ), item); + } + + public static Order CancelProduction(Actor subject, string item) + { + return new Order("CancelProduction", subject, item); + } + public static Order StartProduction(Player subject, string item, int count) { return new Order("StartProduction", subject.PlayerActor, new int2( count, 0 ), item ); diff --git a/OpenRA.Game/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Game/Orders/PlaceBuildingOrderGenerator.cs index d99dffe0e9..96904be7e7 100644 --- a/OpenRA.Game/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Game/Orders/PlaceBuildingOrderGenerator.cs @@ -9,6 +9,7 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.GameRules; using OpenRA.Traits; @@ -56,8 +57,14 @@ namespace OpenRA.Orders public void Tick( World world ) { - var producing = Producer.Trait().CurrentItem( Rules.Info[ Building ].Category ); - if (producing == null || producing.Item != Building || producing.RemainingTime != 0) + // Find the queue with the target actor + var queue = Producer.TraitsImplementing() + .Where(p => p.CurrentItem() != null && + p.CurrentItem().Item == Building && + p.CurrentItem().RemainingTime == 0) + .FirstOrDefault(); + + if (queue == null) world.CancelInputMode(); } diff --git a/OpenRA.Game/Traits/Player/PlaceBuilding.cs b/OpenRA.Game/Traits/Player/PlaceBuilding.cs index 20cbc25784..8512d1fa50 100644 --- a/OpenRA.Game/Traits/Player/PlaceBuilding.cs +++ b/OpenRA.Game/Traits/Player/PlaceBuilding.cs @@ -26,14 +26,20 @@ namespace OpenRA.Traits self.World.AddFrameEndTask(w => { var prevItems = GetNumBuildables(self.Owner); - - var queue = self.Trait(); - var unit = Rules.Info[order.TargetString]; - var producing = queue.CurrentItem(unit.Category); - - if (producing == null || producing.Item != order.TargetString || producing.RemainingTime != 0) + + // Find the queue with the target actor + var queue = w.Queries.WithTraitMultiple() + .Where(p => p.Actor.Owner == self.Owner && + p.Trait.CurrentItem() != null && + p.Trait.CurrentItem().Item == order.TargetString && + p.Trait.CurrentItem().RemainingTime == 0) + .Select(p => p.Trait) + .FirstOrDefault(); + + if (queue == null) return; - + + var unit = Rules.Info[order.TargetString]; var buildingInfo = unit.Traits.Get(); if (order.OrderString == "LineBuild") @@ -66,7 +72,7 @@ namespace OpenRA.Traits PlayBuildAnim( self, unit ); - queue.FinishProduction(unit.Category); + queue.FinishProduction(); if (GetNumBuildables(self.Owner) > prevItems) w.Add(new DelayedAction(10, diff --git a/OpenRA.Game/Traits/Player/ProductionQueue.cs b/OpenRA.Game/Traits/Player/ProductionQueue.cs index d59ae6f2bd..7df741ab62 100644 --- a/OpenRA.Game/Traits/Player/ProductionQueue.cs +++ b/OpenRA.Game/Traits/Player/ProductionQueue.cs @@ -17,32 +17,44 @@ namespace OpenRA.Traits { public class ProductionQueueInfo : ITraitInfo { + public readonly string Type = null; public float BuildSpeed = 0.4f; public readonly int LowPowerSlowdown = 3; - public object Create(ActorInitializer init) { return new ProductionQueue(init.self); } + public object Create(ActorInitializer init) { return new ProductionQueue(init.self, this); } } public class ProductionQueue : IResolveOrder, ITick { - Actor self; + public readonly Actor self; + public ProductionQueueInfo Info; + // TODO: sync this + List Producing = new List(); - public ProductionQueue( Actor self ) + public ProductionQueue( Actor self, ProductionQueueInfo info ) { this.self = self; + this.Info = info; } - public void Tick( Actor self ) + public ProductionItem CurrentItem() { - foreach( var p in production.OrderBy( p => p.Key ) ) + return Producing.ElementAtOrDefault(0); + } + + public IEnumerable AllItems() + { + return Producing; + } + + public void Tick( Actor self ) + { + while( Producing.Count > 0 && !Rules.TechTree.BuildableItems( self.Owner, Info.Type ).Contains( Producing[ 0 ].Item ) ) { - while( p.Value.Count > 0 && !Rules.TechTree.BuildableItems( self.Owner, p.Key ).Contains( p.Value[ 0 ].Item ) ) - { - self.Owner.PlayerActor.Trait().GiveCash(p.Value[0].TotalCost - p.Value[0].RemainingCost); // refund what's been paid so far. - FinishProduction(p.Key); - } - if( p.Value.Count > 0 ) - ( p.Value )[ 0 ].Tick( self.Owner ); + self.Owner.PlayerActor.Trait().GiveCash(Producing[0].TotalCost - Producing[0].RemainingCost); // refund what's been paid so far. + FinishProduction(); } + if( Producing.Count > 0 ) + Producing[ 0 ].Tick( self.Owner ); } public void ResolveOrder( Actor self, Order order ) @@ -51,19 +63,21 @@ namespace OpenRA.Traits { case "StartProduction": { + var unit = Rules.Info[order.TargetString]; + if (unit.Category != Info.Type) + return; /* Not built by this queue */ + + var cost = unit.Traits.Contains() ? unit.Traits.Get().Cost : 0; + var time = GetBuildTime(order.TargetString); + + if (!Rules.TechTree.BuildableItems(order.Player, unit.Category).Contains(order.TargetString)) + return; /* you can't build that!! */ + + bool hasPlayedSound = false; + for (var n = 0; n < order.TargetLocation.X; n++) // repeat count { - var unit = Rules.Info[order.TargetString]; - var cost = unit.Traits.Contains() ? unit.Traits.Get().Cost : 0; - var time = GetBuildTime(self, order.TargetString); - - if (!Rules.TechTree.BuildableItems(order.Player, unit.Category).Contains(order.TargetString)) - return; /* you can't build that!! */ - - bool hasPlayedSound = false; - - BeginProduction(unit.Category, - new ProductionItem(order.TargetString, (int)time, cost, + BeginProduction(new ProductionItem(order.TargetString, (int)time, cost, () => self.World.AddFrameEndTask( _ => { @@ -82,9 +96,11 @@ namespace OpenRA.Traits } case "PauseProduction": { - var producing = CurrentItem( Rules.Info[ order.TargetString ].Category ); - if( producing != null && producing.Item == order.TargetString ) - producing.Paused = ( order.TargetLocation.X != 0 ); + if (Rules.Info[ order.TargetString ].Category != Info.Type) + return; /* Not built by this queue */ + + if( Producing.Count > 0 && Producing[0].Item == order.TargetString ) + Producing[0].Paused = ( order.TargetLocation.X != 0 ); break; } case "CancelProduction": @@ -95,65 +111,50 @@ namespace OpenRA.Traits } } - public static int GetBuildTime(Actor self, String unitString) + public int GetBuildTime(String unitString) { var unit = Rules.Info[unitString]; if (unit == null || ! unit.Traits.Contains()) return 0; - if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.Trait().FastBuild) return 0; + if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.Owner.PlayerActor.Trait().FastBuild) return 0; var cost = unit.Traits.Contains() ? unit.Traits.Get().Cost : 0; var time = cost - * self.Owner.PlayerActor.Info.Traits.Get().BuildSpeed /* todo: country-specific build speed bonus */ + * Info.BuildSpeed * (25 * 60) /* frames per min */ /* todo: build acceleration, if we do that */ / 1000; return (int) time; } - // Key: Production category. - // TODO: sync this - readonly Cache> production - = new Cache>( _ => new List() ); - - public ProductionItem CurrentItem(string category) - { - return production[category].ElementAtOrDefault(0); - } - - public IEnumerable AllItems(string category) - { - return production[category]; - } - void CancelProduction( string itemName ) { var category = Rules.Info[itemName].Category; - var queue = production[ category ]; - if (queue.Count == 0) return; - - var lastIndex = queue.FindLastIndex( a => a.Item == itemName ); + + if (category != Info.Type || Producing.Count == 0) + return; // Nothing to do here + + var lastIndex = Producing.FindLastIndex( a => a.Item == itemName ); if (lastIndex > 0) { - queue.RemoveAt(lastIndex); + Producing.RemoveAt(lastIndex); } else if( lastIndex == 0 ) { - var item = queue[0]; + var item = Producing[0]; self.Owner.PlayerActor.Trait().GiveCash(item.TotalCost - item.RemainingCost); // refund what's been paid so far. - FinishProduction(category); + FinishProduction(); } } - public void FinishProduction( string category ) + public void FinishProduction() { - var queue = production[category]; - if (queue.Count == 0) return; - queue.RemoveAt(0); + if (Producing.Count == 0) return; + Producing.RemoveAt(0); } - void BeginProduction( string group, ProductionItem item ) + void BeginProduction( ProductionItem item ) { - production[group].Add(item); + Producing.Add(item); } static bool IsDisabledBuilding(Actor a) @@ -163,13 +164,10 @@ namespace OpenRA.Traits } void BuildUnit( string name ) - { - var newUnitType = Rules.Info[ name ]; - var producerTypes = Rules.TechTree.UnitBuiltAt( newUnitType ); - + { var producers = self.World.Queries.OwnedBy[self.Owner] .WithTrait() - .Where(x => producerTypes.Contains(x.Actor.Info)) + .Where(x => x.Trait.Info.Produces.Contains(Info.Type)) .OrderByDescending(x => x.Actor.IsPrimaryBuilding() ? 1 : 0 ) // prioritize the primary. .ToArray(); @@ -183,9 +181,9 @@ namespace OpenRA.Traits { if (IsDisabledBuilding(p.Actor)) continue; - if (p.Trait.Produce(p.Actor, newUnitType)) + if (p.Trait.Produce(p.Actor, Rules.Info[ name ])) { - FinishProduction(newUnitType.Category); + FinishProduction(); break; } } diff --git a/OpenRA.Game/Traits/Production.cs b/OpenRA.Game/Traits/Production.cs index 29acb9a795..97dccecb79 100755 --- a/OpenRA.Game/Traits/Production.cs +++ b/OpenRA.Game/Traits/Production.cs @@ -26,8 +26,11 @@ namespace OpenRA.Traits public class Production { public readonly List> Spawns = new List>(); + public ProductionInfo Info; public Production(ProductionInfo info) { + Info = info; + if (info.SpawnOffsets == null || info.ExitCells == null) return; diff --git a/OpenRA.Mods.RA/HackyAI.cs b/OpenRA.Mods.RA/HackyAI.cs index 5ea0ff2313..152a2b0fd8 100644 --- a/OpenRA.Mods.RA/HackyAI.cs +++ b/OpenRA.Mods.RA/HackyAI.cs @@ -29,7 +29,6 @@ namespace OpenRA.Mods.RA bool enabled; int ticks; Player p; - ProductionQueue productionQueue; PlayerResources playerResources; int2 baseCenter; Random random = new Random(); //we do not use the synced random number generator. @@ -68,7 +67,6 @@ namespace OpenRA.Mods.RA this.p = p; enabled = true; - productionQueue = p.PlayerActor.Trait(); playerResources = p.PlayerActor.Trait(); } @@ -262,7 +260,7 @@ namespace OpenRA.Mods.RA private void DeployMcv(Actor self) { - /* find our mcv and deploy it */ + /* find our mcv and deploy it */ var mcv = self.World.Queries.OwnedBy[p] .FirstOrDefault(a => a.Info == Rules.Info["mcv"]); @@ -278,20 +276,33 @@ namespace OpenRA.Mods.RA //Build a random unit of the given type. Not going to be needed once there is actual AI... private void BuildRandom(string category) { - var unitInProduction = productionQueue.CurrentItem(category); - if (unitInProduction == null) - { - var unit = ChooseRandomUnitToBuild(category); - if (unit != null) - { - Game.IssueOrder(Order.StartProduction(p, unit, 1)); - } - } + // Pick a free queue + var queue = Game.world.Queries.WithTraitMultiple() + .Where(a => a.Actor.Owner == p && + a.Trait.Info.Type == category && + a.Trait.CurrentItem() == null) + .Select(a => a.Trait) + .FirstOrDefault(); + + if (queue == null) + return; + + var unit = ChooseRandomUnitToBuild(category); + if (unit != null) + { + Game.IssueOrder(Order.StartProduction(p, unit, 1)); + } } private void BuildBuildings() { - var currentBuilding = productionQueue.CurrentItem("Building"); + // Pick a free queue + var queue = Game.world.Queries.WithTraitMultiple() + .Where(a => a.Actor.Owner == p && a.Trait.Info.Type == "Building") + .Select(a => a.Trait) + .FirstOrDefault(); + + var currentBuilding = queue.CurrentItem(); switch (state) { case BuildState.ChooseItem: diff --git a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs index 58430c97bc..5243a6622a 100755 --- a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs +++ b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs @@ -25,10 +25,12 @@ namespace OpenRA.Mods.RA.Widgets public int Columns = 3; public int Rows = 5; - string currentTab = null; + ProductionQueue CurrentQueue = null; + List visibleTabs = new List(); + bool paletteOpen = false; Dictionary tabImageNames; - Dictionary tabSprites; + Dictionary iconSprites; static float2 paletteOpenOrigin = new float2(Game.viewport.Width - 215, 280); static float2 paletteClosedOrigin = new float2(Game.viewport.Width - 16, 280); static float2 paletteOrigin = paletteClosedOrigin; @@ -43,7 +45,6 @@ namespace OpenRA.Mods.RA.Widgets public readonly string BuildPaletteOpen = "bleep13.aud"; public readonly string BuildPaletteClose = "bleep13.aud"; public readonly string TabClick = "ramenu1.aud"; - List visibleTabs = new List(); public BuildPaletteWidget() : base() { } @@ -57,7 +58,7 @@ namespace OpenRA.Mods.RA.Widgets ready.PlayRepeating("ready"); clock = new Animation("clock"); - tabSprites = Rules.Info.Values + iconSprites = Rules.Info.Values .Where(u => u.Traits.Contains()) .ToDictionary( u => u.Name, @@ -71,29 +72,33 @@ namespace OpenRA.Mods.RA.Widgets n => i.ToString()))) .ToDictionary(a => a.First, a => a.Second); - IsVisible = () => { return currentTab != null || (currentTab == null && !paletteOpen); }; + IsVisible = () => { return CurrentQueue != null || (CurrentQueue == null && !paletteOpen); }; } public override Rectangle EventBounds { - get { return new Rectangle((int)(paletteOrigin.X) - 24, (int)(paletteOrigin.Y), 215, 48 * numActualRows); - } + get { return new Rectangle((int)(paletteOrigin.X) - 24, (int)(paletteOrigin.Y), 215, 48 * numActualRows); } } public override void Tick(World world) { visibleTabs.Clear(); - foreach (var q in tabImageNames) - if (!Rules.TechTree.BuildableItems(world.LocalPlayer, q.Key).Any()) + + var queues = world.Queries.WithTraitMultiple() + .Where(p => p.Actor.Owner == world.LocalPlayer) + .Select(p => p.Trait); + + foreach (var queue in queues) + if (!Rules.TechTree.BuildableItems(world.LocalPlayer, queue.Info.Type).Any()) { - if (currentTab == q.Key) - currentTab = null; + if (CurrentQueue == queue) + CurrentQueue = null; } else - visibleTabs.Add(q.Key); + visibleTabs.Add(queue); - if (currentTab == null) - currentTab = visibleTabs.FirstOrDefault(); + if (CurrentQueue == null) + CurrentQueue = queues.FirstOrDefault(); TickPaletteAnimation(world); @@ -131,12 +136,12 @@ namespace OpenRA.Mods.RA.Widgets } } - public void SetCurrentTab(string produces) + public void SetCurrentTab(ProductionQueue queue) { if (!paletteOpen) paletteAnimating = true; paletteOpen = true; - currentTab = produces; + CurrentQueue = queue; } public override bool HandleKeyPressInner(KeyInput e) @@ -175,23 +180,21 @@ namespace OpenRA.Mods.RA.Widgets public override void DrawInner(World world) { if (!IsVisible()) return; - paletteHeight = DrawPalette(world, currentTab); + // todo: fix + paletteHeight = DrawPalette(world, CurrentQueue); DrawBuildTabs(world, paletteHeight); } - int DrawPalette(World world, string queueName) + int DrawPalette(World world, ProductionQueue queue) { - string paletteCollection = "palette-" + world.LocalPlayer.Country.Race; - buttons.Clear(); - - + if (queue == null) return 0; + + string paletteCollection = "palette-" + world.LocalPlayer.Country.Race; float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9); - - if (queueName == null) return 0; - + var queueName = queue.Info.Type; + // Collect info - var x = 0; var y = 0; var buildableItems = Rules.TechTree.BuildableItems(world.LocalPlayer, queueName).ToArray(); @@ -200,8 +203,6 @@ namespace OpenRA.Mods.RA.Widgets .OrderBy(a => a.Traits.Get().BuildPaletteOrder) .ToArray(); - var queue = world.LocalPlayer.PlayerActor.Trait(); - var overlayBits = new List>(); numActualRows = Math.Max((allBuildables.Length + Columns - 1) / Columns, Rows); @@ -218,14 +219,14 @@ namespace OpenRA.Mods.RA.Widgets // Icons string tooltipItem = null; + var isBuildingSomething = queue.CurrentItem() != null; foreach (var item in allBuildables) { var rect = new RectangleF(origin.X + x * 64, origin.Y + 48 * y, 64, 48); var drawPos = new float2(rect.Location); - var isBuildingSomething = queue.CurrentItem(queueName) != null; - WidgetUtils.DrawSHP(tabSprites[item.Name], drawPos); - - var firstOfThis = queue.AllItems(queueName).FirstOrDefault(a => a.Item == item.Name); + WidgetUtils.DrawSHP(iconSprites[item.Name], drawPos); + + var firstOfThis = queue.AllItems().FirstOrDefault(a => a.Item == item.Name); if (rect.Contains(Viewport.LastMousePos.ToPoint())) tooltipItem = item.Name; @@ -251,8 +252,8 @@ namespace OpenRA.Mods.RA.Widgets overlayBits.Add(Pair.New(ready.Image, overlayPos)); } - var repeats = queue.AllItems(queueName).Count(a => a.Item == item.Name); - if (repeats > 1 || queue.CurrentItem(queueName) != firstOfThis) + var repeats = queue.AllItems().Count(a => a.Item == item.Name); + if (repeats > 1 || queue.CurrentItem() != firstOfThis) { var offset = -22; var digits = repeats.ToString(); @@ -311,7 +312,7 @@ namespace OpenRA.Mods.RA.Widgets }; } - Action HandleTabClick(string button, World world) + Action HandleTabClick(ProductionQueue queue, World world) { return mi => { if (mi.Button != MouseButton.Left) @@ -319,8 +320,8 @@ namespace OpenRA.Mods.RA.Widgets Sound.Play(TabClick); var wasOpen = paletteOpen; - paletteOpen = (currentTab == button && wasOpen) ? false : true; - currentTab = button; + paletteOpen = (CurrentQueue == queue && wasOpen) ? false : true; + CurrentQueue = queue; if (wasOpen != paletteOpen) paletteAnimating = true; }; @@ -338,13 +339,12 @@ namespace OpenRA.Mods.RA.Widgets { var player = world.LocalPlayer; var unit = Rules.Info[item]; - var queue = player.PlayerActor.Trait(); var eva = world.WorldActor.Info.Traits.Get(); - var producing = queue.AllItems(unit.Category).FirstOrDefault( a => a.Item == item ); + var producing = CurrentQueue.AllItems().FirstOrDefault( a => a.Item == item ); if (isLmb) { - if (producing != null && producing == queue.CurrentItem(unit.Category)) + if (producing != null && producing == CurrentQueue.CurrentItem()) { if (producing.Done) { @@ -355,7 +355,7 @@ namespace OpenRA.Mods.RA.Widgets if (producing.Paused) { - Game.IssueOrder(Order.PauseProduction(player, item, false)); + Game.IssueOrder(Order.PauseProduction(CurrentQueue.self, item, false)); return; } } @@ -370,12 +370,12 @@ namespace OpenRA.Mods.RA.Widgets if (producing.Paused || producing.Done || producing.TotalCost == producing.RemainingCost) { Sound.Play(eva.CancelledAudio); - Game.IssueOrder(Order.CancelProduction(player, item)); + Game.IssueOrder(Order.CancelProduction(CurrentQueue.self, item)); } else { Sound.Play(eva.OnHoldAudio); - Game.IssueOrder(Order.PauseProduction(player, item, true)); + Game.IssueOrder(Order.PauseProduction(CurrentQueue.self, item, true)); } } } @@ -387,18 +387,10 @@ namespace OpenRA.Mods.RA.Widgets var unit = Rules.Info[item]; Sound.Play(unit.Traits.Contains() ? eva.BuildingSelectAudio : eva.UnitSelectAudio); - Game.IssueOrder(Order.StartProduction(world.LocalPlayer, item, + + Game.IssueOrder(Order.StartProduction(CurrentQueue.self, item, Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1)); } - - static Dictionary CategoryNameRemaps = new Dictionary - { - { "Building", "Structures" }, - { "Defense", "Defenses" }, - { "Plane", "Aircraft" }, - { "Ship", "Ships" }, - { "Vehicle", "Vehicles" }, - }; void DrawBuildTabs( World world, int paletteHeight) { @@ -408,26 +400,27 @@ namespace OpenRA.Mods.RA.Widgets var y = paletteOrigin.Y + 9; tabs.Clear(); - var queue = world.LocalPlayer.PlayerActor.Trait(); + + var queues = world.Queries.WithTraitMultiple() + .Where(p => p.Actor.Owner == world.LocalPlayer) + .Select(p => p.Trait); - foreach (var q in tabImageNames) - { - var groupName = q.Key; - if (!visibleTabs.Contains(groupName)) - continue; - + foreach (var queue in queues) + { string[] tabKeys = { "normal", "ready", "selected" }; - var producing = queue.CurrentItem(groupName); - var index = q.Key == currentTab ? 2 : (producing != null && producing.Done) ? 1 : 0; + var producing = queue.CurrentItem(); + var index = queue == CurrentQueue ? 2 : (producing != null && producing.Done) ? 1 : 0; + var race = world.LocalPlayer.Country.Race; - WidgetUtils.DrawRGBA(ChromeProvider.GetImage("tabs-"+tabKeys[index], race+"-"+q.Key), new float2(x, y)); + WidgetUtils.DrawRGBA(ChromeProvider.GetImage("tabs-"+tabKeys[index], race+"-"+queue.Info.Type), new float2(x, y)); var rect = new Rectangle((int)x,(int)y,(int)tabWidth,(int)tabHeight); - tabs.Add(Pair.New(rect, HandleTabClick(groupName, world))); + tabs.Add(Pair.New(rect, HandleTabClick(queue, world))); if (rect.Contains(Viewport.LastMousePos.ToPoint())) { - var text = CategoryNameRemaps.ContainsKey(groupName) ? CategoryNameRemaps[groupName] : groupName; + //var text = CategoryNameRemaps.ContainsKey(groupName) ? CategoryNameRemaps[groupName] : groupName; + var text = queue.Info.Type; var sz = Game.Renderer.BoldFont.Measure(text); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB((int)rect.Left - sz.X - 30, (int)rect.Top, (int)rect.Left - 5, (int)rect.Bottom), @@ -478,7 +471,7 @@ namespace OpenRA.Mods.RA.Widgets (resources.DisplayCash + resources.DisplayOre >= cost ? Color.White : Color.Red )); var lowpower = resources.GetPowerState() != PowerState.Normal; - var time = ProductionQueue.GetBuildTime(pl.PlayerActor, info.Name) + var time = CurrentQueue.GetBuildTime(info.Name) * ((lowpower)? pl.PlayerActor.Info.Traits.Get().LowPowerSlowdown : 1); DrawRightAligned(WorldUtils.FormatTime(time), pos + new int2(-5, 35), lowpower ? Color.Red: Color.White); @@ -511,7 +504,7 @@ namespace OpenRA.Mods.RA.Widgets { if (!paletteOpen) return false; - var buildable = Rules.TechTree.BuildableItems(world.LocalPlayer, currentTab); + var buildable = Rules.TechTree.BuildableItems(world.LocalPlayer, CurrentQueue.Info.Type); var toBuild = buildable.FirstOrDefault(b => Rules.Info[b.ToLowerInvariant()].Traits.Get().Hotkey == c.ToString()); @@ -530,7 +523,7 @@ namespace OpenRA.Mods.RA.Widgets int size = visibleTabs.Count(); if (size > 0) { - int current = visibleTabs.IndexOf(currentTab); + int current = visibleTabs.IndexOf(CurrentQueue); if (!shift) { if (current + 1 >= size) diff --git a/OpenRA.Mods.RA/World/ChooseBuildTabOnSelect.cs b/OpenRA.Mods.RA/World/ChooseBuildTabOnSelect.cs index 7cf76682bb..356d6ffcd8 100644 --- a/OpenRA.Mods.RA/World/ChooseBuildTabOnSelect.cs +++ b/OpenRA.Mods.RA/World/ChooseBuildTabOnSelect.cs @@ -40,8 +40,8 @@ namespace OpenRA.Mods.RA.Widgets if (produces == null) return; - Widget.RootWidget.GetWidget("INGAME_BUILD_PALETTE") - .SetCurrentTab(produces); + //Widget.RootWidget.GetWidget("INGAME_BUILD_PALETTE") + // .SetCurrentTab(produces); } } } diff --git a/mods/cnc/system.yaml b/mods/cnc/system.yaml index 93b93dbf38..538d009938 100644 --- a/mods/cnc/system.yaml +++ b/mods/cnc/system.yaml @@ -1,5 +1,22 @@ Player: - ProductionQueue: + ProductionQueue@Building: + Type: Building + BuildSpeed: .4 + LowPowerSlowdown: 3 + ProductionQueue@Defense: + Type: Defense + BuildSpeed: .4 + LowPowerSlowdown: 3 + ProductionQueue@Infantry: + Type: Infantry + BuildSpeed: .4 + LowPowerSlowdown: 3 + ProductionQueue@Vehicle: + Type: Vehicle + BuildSpeed: .4 + LowPowerSlowdown: 3 + ProductionQueue@Plane: + Type: Plane BuildSpeed: .4 LowPowerSlowdown: 3 PlaceBuilding: @@ -41,6 +58,7 @@ Player: InitialCash: 5000 ActorGroupProxy: DeveloperMode: + HackyAI: World: ScreenShaker: