Merge pull request #6948 from pchote/revert-production-desync
Closes #6910 Closes #6925 Closes #6933
This commit is contained in:
@@ -155,19 +155,19 @@ namespace OpenRA
|
||||
return new Order("Command", null, false) { IsImmediate = true, TargetString = text };
|
||||
}
|
||||
|
||||
public static Order StartProduction(Actor subject, int queueID, string item, int count)
|
||||
public static Order StartProduction(Actor subject, string item, int count)
|
||||
{
|
||||
return new Order("StartProduction", subject, false) { TargetString = item, ExtraLocation = new CPos(queueID, count) };
|
||||
return new Order("StartProduction", subject, false) { ExtraData = (uint)count, TargetString = item };
|
||||
}
|
||||
|
||||
public static Order PauseProduction(Actor subject, int queueID, string item, bool pause)
|
||||
public static Order PauseProduction(Actor subject, string item, bool pause)
|
||||
{
|
||||
return new Order("PauseProduction", subject, false) { TargetString = item, ExtraLocation = new CPos(queueID, pause ? 1 : 0) };
|
||||
return new Order("PauseProduction", subject, false) { ExtraData = pause ? 1u : 0u, TargetString = item };
|
||||
}
|
||||
|
||||
public static Order CancelProduction(Actor subject, int queueID, string item, int count)
|
||||
public static Order CancelProduction(Actor subject, string item, int count)
|
||||
{
|
||||
return new Order("CancelProduction", subject, false) { TargetString = item, ExtraLocation = new CPos(queueID, count) };
|
||||
return new Order("CancelProduction", subject, false) { ExtraData = (uint)count, TargetString = item };
|
||||
}
|
||||
|
||||
// For scripting special powers
|
||||
|
||||
@@ -383,7 +383,7 @@ namespace OpenRA.Mods.D2k.Widgets
|
||||
|
||||
if (producing.Paused)
|
||||
{
|
||||
world.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, CurrentQueue.QueueID, item, false));
|
||||
world.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, item, false));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -412,12 +412,12 @@ namespace OpenRA.Mods.D2k.Widgets
|
||||
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, world.LocalPlayer.Country.Race);
|
||||
var numberToCancel = Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1;
|
||||
|
||||
world.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, CurrentQueue.QueueID, item, numberToCancel));
|
||||
world.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, item, numberToCancel));
|
||||
}
|
||||
else
|
||||
{
|
||||
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, world.LocalPlayer.Country.Race);
|
||||
world.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, CurrentQueue.QueueID, item, true));
|
||||
world.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, item, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,7 +425,7 @@ namespace OpenRA.Mods.D2k.Widgets
|
||||
|
||||
void StartProduction(World world, string item)
|
||||
{
|
||||
world.IssueOrder(Order.StartProduction(CurrentQueue.Actor, CurrentQueue.QueueID, item,
|
||||
world.IssueOrder(Order.StartProduction(CurrentQueue.Actor, item,
|
||||
Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
return false;
|
||||
|
||||
HackyAI.BotDebug("AI: {0} is starting production of {1}".F(player, item.Name));
|
||||
world.IssueOrder(Order.StartProduction(queue.Actor, queue.QueueID, item.Name, 1));
|
||||
world.IssueOrder(Order.StartProduction(queue.Actor, item.Name, 1));
|
||||
}
|
||||
|
||||
// Production is complete
|
||||
@@ -89,7 +89,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
if (location == null)
|
||||
{
|
||||
HackyAI.BotDebug("AI: {0} has nowhere to place {1}".F(player, currentBuilding.Item));
|
||||
world.IssueOrder(Order.CancelProduction(queue.Actor, queue.QueueID, currentBuilding.Item, 1));
|
||||
world.IssueOrder(Order.CancelProduction(queue.Actor, currentBuilding.Item, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -886,7 +886,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
ChooseUnitToBuild(queue);
|
||||
|
||||
if (unit != null && Info.UnitsToBuild.Any(u => u.Key == unit.Name))
|
||||
world.IssueOrder(Order.StartProduction(queue.Actor, queue.QueueID, unit.Name, 1));
|
||||
world.IssueOrder(Order.StartProduction(queue.Actor, unit.Name, 1));
|
||||
}
|
||||
|
||||
void BuildUnit(string category, string name)
|
||||
@@ -896,7 +896,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
return;
|
||||
|
||||
if (Map.Rules.Actors[name] != null)
|
||||
world.IssueOrder(Order.StartProduction(queue.Actor, queue.QueueID, name, 1));
|
||||
world.IssueOrder(Order.StartProduction(queue.Actor, name, 1));
|
||||
}
|
||||
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
|
||||
@@ -69,10 +69,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public class ProductionQueue : IResolveOrder, ITick, ITechTreeElement, INotifyOwnerChanged, INotifyKilled, INotifySold, ISync, INotifyTransform
|
||||
{
|
||||
static int nextQueueID = 1;
|
||||
|
||||
public readonly ProductionQueueInfo Info;
|
||||
public readonly int QueueID;
|
||||
readonly Actor self;
|
||||
|
||||
// Will change if the owner changes
|
||||
@@ -83,7 +80,6 @@ namespace OpenRA.Mods.RA
|
||||
// A list of things we could possibly build
|
||||
Dictionary<ActorInfo, ProductionState> produceable;
|
||||
List<ProductionItem> queue = new List<ProductionItem>();
|
||||
bool allTech = false;
|
||||
|
||||
// A list of things we are currently building
|
||||
public Actor Actor { get { return self; } }
|
||||
@@ -97,8 +93,6 @@ namespace OpenRA.Mods.RA
|
||||
[Sync] public bool Enabled { get; private set; }
|
||||
|
||||
public string Race { get; private set; }
|
||||
public int Name = 0;
|
||||
public string DisplayName = "";
|
||||
|
||||
public ProductionQueue(ActorInitializer init, Actor playerActor, ProductionQueueInfo info)
|
||||
{
|
||||
@@ -109,8 +103,7 @@ namespace OpenRA.Mods.RA
|
||||
developerMode = playerActor.Trait<DeveloperMode>();
|
||||
|
||||
Race = init.Contains<RaceInit>() ? init.Get<RaceInit, string>() : self.Owner.Country.Race;
|
||||
Enabled = (!Info.Race.Any() || Info.Race.Contains(Race)) || developerMode.AllTech;
|
||||
QueueID = nextQueueID++;
|
||||
Enabled = !info.Race.Any() || info.Race.Contains(Race);
|
||||
|
||||
CacheProduceables(playerActor);
|
||||
}
|
||||
@@ -136,7 +129,7 @@ namespace OpenRA.Mods.RA
|
||||
if (!Info.Sticky)
|
||||
{
|
||||
Race = self.Owner.Country.Race;
|
||||
Enabled = (!Info.Race.Any() || Info.Race.Contains(Race)) || developerMode.AllTech;
|
||||
Enabled = !Info.Race.Any() || Info.Race.Contains(Race);
|
||||
}
|
||||
|
||||
// Regenerate the produceables and tech tree state
|
||||
@@ -244,27 +237,6 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public virtual void Tick(Actor self)
|
||||
{
|
||||
if (self.World.AllowDevCommands && developerMode.AllTech != allTech)
|
||||
{
|
||||
allTech = developerMode.AllTech;
|
||||
|
||||
Enabled = (!Info.Race.Any() || Info.Race.Contains(Race)) || developerMode.AllTech;
|
||||
OnOwnerChanged(self, self.Owner, self.Owner);
|
||||
|
||||
self.World.AddFrameEndTask((World w) => {
|
||||
var selected = w.Selection.Contains(self);
|
||||
var controlgroup = w.Selection.GetControlGroupForActor(self);
|
||||
|
||||
w.Remove(self); // force production palettes to update
|
||||
w.Add(self);
|
||||
|
||||
if (selected)
|
||||
w.Selection.Add(w, self);
|
||||
if (controlgroup.HasValue)
|
||||
w.Selection.AddToControlGroup(self, controlgroup.Value);
|
||||
});
|
||||
}
|
||||
|
||||
while (queue.Count > 0 && BuildableItems().All(b => b.Name != queue[0].Item))
|
||||
{
|
||||
playerResources.GiveCash(queue[0].TotalCost - queue[0].RemainingCost); // refund what's been paid so far.
|
||||
@@ -284,9 +256,6 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
case "StartProduction":
|
||||
{
|
||||
if (order.ExtraLocation.X != QueueID)
|
||||
return;
|
||||
|
||||
var unit = self.World.Map.Rules.Actors[order.TargetString];
|
||||
var bi = unit.Traits.Get<BuildableInfo>();
|
||||
if (!bi.Queue.Contains(Info.Type))
|
||||
@@ -310,7 +279,7 @@ namespace OpenRA.Mods.RA
|
||||
return;
|
||||
}
|
||||
|
||||
var amountToBuild = Math.Min(fromLimit, order.ExtraLocation.Y);
|
||||
var amountToBuild = Math.Min(fromLimit, order.ExtraData);
|
||||
for (var n = 0; n < amountToBuild; n++)
|
||||
{
|
||||
var hasPlayedSound = false;
|
||||
@@ -338,19 +307,15 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
case "PauseProduction":
|
||||
{
|
||||
if (order.ExtraLocation.X != QueueID)
|
||||
return;
|
||||
if (queue.Count > 0 && queue[0].Item == order.TargetString)
|
||||
queue[0].Pause(order.ExtraLocation.Y != 0);
|
||||
queue[0].Pause(order.ExtraData != 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "CancelProduction":
|
||||
{
|
||||
if (order.ExtraLocation.X != QueueID)
|
||||
return;
|
||||
CancelProduction(order.TargetString, (uint)order.ExtraLocation.Y);
|
||||
CancelProduction(order.TargetString, order.ExtraData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
}
|
||||
|
||||
foreach (var actorType in actorTypes)
|
||||
queue.ResolveOrder(self, Order.StartProduction(self, queue.QueueID, actorType, 1));
|
||||
queue.ResolveOrder(self, Order.StartProduction(self, actorType, 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
foreach (var actorType in actorTypes)
|
||||
{
|
||||
var queue = queues[typeToQueueMap[actorType]];
|
||||
queue.ResolveOrder(queue.Actor, Order.StartProduction(queue.Actor, queue.QueueID, actorType, 1));
|
||||
queue.ResolveOrder(queue.Actor, Order.StartProduction(queue.Actor, actorType, 1));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -150,14 +150,14 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
{
|
||||
// Resume a paused item
|
||||
Sound.Play(TabClick);
|
||||
World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, CurrentQueue.QueueID, icon.Name, false));
|
||||
World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
|
||||
}
|
||||
else if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name))
|
||||
{
|
||||
// Queue a new item
|
||||
Sound.Play(TabClick);
|
||||
Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race);
|
||||
World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, CurrentQueue.QueueID, icon.Name,
|
||||
World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name,
|
||||
handleMultiple ? 5 : 1));
|
||||
}
|
||||
else
|
||||
@@ -174,13 +174,13 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
if (first.Paused || first.Done || first.TotalCost == first.RemainingCost)
|
||||
{
|
||||
Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race);
|
||||
World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, CurrentQueue.QueueID, icon.Name,
|
||||
World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, icon.Name,
|
||||
handleMultiple ? 5 : 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race);
|
||||
World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, CurrentQueue.QueueID, icon.Name, true));
|
||||
World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, true));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -18,43 +18,42 @@ using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Widgets
|
||||
{
|
||||
public class ProductionTab
|
||||
{
|
||||
public string Name;
|
||||
public ProductionQueue Queue;
|
||||
}
|
||||
|
||||
public class ProductionTabGroup
|
||||
{
|
||||
public List<ProductionQueue> Tabs = new List<ProductionQueue>();
|
||||
public List<ProductionTab> Tabs = new List<ProductionTab>();
|
||||
public string Group;
|
||||
public bool Alert { get { return Tabs.Any(t => t.CurrentDone); } }
|
||||
public int NextQueueName = 1;
|
||||
public bool Alert { get { return Tabs.Any(t => t.Queue.CurrentDone); } }
|
||||
|
||||
public void Update(IEnumerable<ProductionQueue> allQueues)
|
||||
{
|
||||
var queues = allQueues.Where(q => q.Info.Group == Group).ToList();
|
||||
var names = new Queue<int>(Enumerable.Range(1, queues.Count).Except(queues.Select(q => q.Name)));
|
||||
var tabs = new List<ProductionTab>();
|
||||
|
||||
// Assign names based on available numbers
|
||||
foreach (var queue in queues.Where(q => q.Name == 0))
|
||||
// Remove stale queues
|
||||
foreach (var t in Tabs)
|
||||
{
|
||||
foreach (var q in queues.Where(q => q.Name > 0))
|
||||
if (queue.Actor == q.Actor)
|
||||
queue.Name = q.Name;
|
||||
|
||||
if (queue.Name == 0)
|
||||
queue.Name = names.Dequeue();
|
||||
if (!queues.Contains(t.Queue))
|
||||
continue;
|
||||
|
||||
tabs.Add(t);
|
||||
queues.Remove(t.Queue);
|
||||
}
|
||||
|
||||
Tabs = queues.OrderBy(q => q.Name).ToList();
|
||||
|
||||
// distinction between tabs of the same actor
|
||||
foreach (var group in queues.GroupBy(q => q.Actor))
|
||||
{
|
||||
if (group.Count() > 1)
|
||||
// Add new queues
|
||||
foreach (var queue in queues)
|
||||
tabs.Add(new ProductionTab()
|
||||
{
|
||||
var n = 'a';
|
||||
foreach (var queue in group)
|
||||
queue.DisplayName = queue.Name + (n++).ToString();
|
||||
}
|
||||
else
|
||||
group.First().DisplayName = group.First().Name.ToString();
|
||||
|
||||
}
|
||||
Name = (NextQueueName++).ToString(),
|
||||
Queue = queue
|
||||
});
|
||||
Tabs = tabs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +98,7 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
return true;
|
||||
|
||||
// Prioritize alerted queues
|
||||
var queues = Groups[queueGroup].Tabs.Select(t => t)
|
||||
var queues = Groups[queueGroup].Tabs.Select(t => t.Queue)
|
||||
.OrderByDescending(q => q.CurrentDone ? 1 : 0)
|
||||
.ToList();
|
||||
|
||||
@@ -172,13 +171,13 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
{
|
||||
var rect = new Rectangle(origin.X + contentWidth, origin.Y, TabWidth, rb.Height);
|
||||
var hover = !leftHover && !rightHover && Ui.MouseOverWidget == this && rect.Contains(Viewport.LastMousePos);
|
||||
var baseName = tab == CurrentQueue ? "button-highlighted" : "button";
|
||||
var baseName = tab.Queue == CurrentQueue ? "button-highlighted" : "button";
|
||||
ButtonWidget.DrawBackground(baseName, rect, false, false, hover, false);
|
||||
contentWidth += TabWidth - 1;
|
||||
|
||||
var textSize = font.Measure(tab.DisplayName);
|
||||
var textSize = font.Measure(tab.Name);
|
||||
var position = new int2(rect.X + (rect.Width - textSize.X) / 2, rect.Y + (rect.Height - textSize.Y) / 2);
|
||||
font.DrawTextWithContrast(tab.DisplayName, position, tab.CurrentDone ? Color.Gold : Color.White, Color.Black, 1);
|
||||
font.DrawTextWithContrast(tab.Name, position, tab.Queue.CurrentDone ? Color.Gold : Color.White, Color.Black, 1);
|
||||
}
|
||||
|
||||
Game.Renderer.DisableScissor();
|
||||
@@ -211,7 +210,7 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
.Select(g => g.Key).FirstOrDefault();
|
||||
|
||||
// Queue destroyed, others of same type: switch to another tab
|
||||
else if (!Groups[queueGroup].Tabs.Contains(CurrentQueue))
|
||||
else if (!Groups[queueGroup].Tabs.Select(t => t.Queue).Contains(CurrentQueue))
|
||||
SelectNextTab(false);
|
||||
}
|
||||
}
|
||||
@@ -265,7 +264,7 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
var offsetloc = mi.Location - new int2(leftButtonRect.Right - 1 + (int)listOffset, leftButtonRect.Y);
|
||||
if (offsetloc.X > 0 && offsetloc.X < contentWidth)
|
||||
{
|
||||
CurrentQueue = Groups[queueGroup].Tabs[offsetloc.X / (TabWidth - 1)];
|
||||
CurrentQueue = Groups[queueGroup].Tabs[offsetloc.X / (TabWidth - 1)].Queue;
|
||||
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "ClickSound", null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user