Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 999 per-actor production queue limit. #15006

Merged
merged 4 commits into from Apr 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 68 additions & 7 deletions OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs
Expand Up @@ -41,18 +41,29 @@ public class ProductionQueueInfo : ITraitInfo
[Desc("This percentage value is multiplied with actor cost to translate into build time (lower means faster).")]
public readonly int BuildDurationModifier = 100;

[Desc("Maximum number of a single actor type that can be queued (0 = infinite).")]
public readonly int ItemLimit = 999;

[Desc("Maximum number of items that can be queued across all actor types (0 = infinite).")]
public readonly int QueueLimit = 0;

[Desc("The build time is multiplied with this value on low power.")]
public readonly int LowPowerSlowdown = 3;

[Desc("Notification played when production is complete.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string ReadyAudio = "UnitReady";

[Desc("Notification played when you can't train another unit",
[Desc("Notification played when you can't train another actor",
"when the build limit exceeded or the exit is jammed.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string BlockedAudio = "NoBuild";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might this cause #15071? You removed NoBuild from the notifications but I don't see any overwrites for BlockedAudio.


[Desc("Notification played when you can't queue another actor",
"when the queue length limit is exceeded.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string LimitedAudio = null;

[Desc("Notification played when user clicks on the build palette icon.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string QueuedAudio = "Training";
Expand Down Expand Up @@ -285,6 +296,42 @@ protected virtual void TickInner(Actor self, bool allProductionPaused)
queue[0].Tick(playerResources);
}

public bool CanQueue(ActorInfo actor, out string notificationAudio)
{
notificationAudio = Info.BlockedAudio;

var bi = actor.TraitInfoOrDefault<BuildableInfo>();
if (bi == null)
return false;

if (!developerMode.AllTech)
{
if (Info.QueueLimit > 0 && queue.Count >= Info.QueueLimit)
{
notificationAudio = Info.LimitedAudio;
return false;
}

var queueCount = queue.Count(i => i.Item == actor.Name);
if (Info.ItemLimit > 0 && queueCount >= Info.ItemLimit)
{
notificationAudio = Info.LimitedAudio;
return false;
}

if (bi.BuildLimit > 0)
{
var owned = self.Owner.World.ActorsHavingTrait<Buildable>()
.Count(a => a.Info.Name == actor.Name && a.Owner == self.Owner);
if (queueCount + owned >= bi.BuildLimit)
return false;
}
}

notificationAudio = Info.QueuedAudio;
return true;
}

public void ResolveOrder(Actor self, Order order)
{
if (!Enabled)
Expand All @@ -307,11 +354,20 @@ public void ResolveOrder(Actor self, Order order)

// Check if the player is trying to build more units that they are allowed
var fromLimit = int.MaxValue;
if (!developerMode.AllTech && bi.BuildLimit > 0)
if (!developerMode.AllTech)
{
var inQueue = queue.Count(pi => pi.Item == order.TargetString);
var owned = self.Owner.World.ActorsHavingTrait<Buildable>().Count(a => a.Info.Name == order.TargetString && a.Owner == self.Owner);
fromLimit = bi.BuildLimit - (inQueue + owned);
if (Info.QueueLimit > 0)
fromLimit = Info.QueueLimit - queue.Count;

if (Info.ItemLimit > 0)
fromLimit = Math.Min(fromLimit, Info.ItemLimit - queue.Count(i => i.Item == order.TargetString));

if (bi.BuildLimit > 0)
{
var inQueue = queue.Count(pi => pi.Item == order.TargetString);
var owned = self.Owner.World.ActorsHavingTrait<Buildable>().Count(a => a.Info.Name == order.TargetString && a.Owner == self.Owner);
fromLimit = Math.Min(fromLimit, bi.BuildLimit - (inQueue + owned));
}

if (fromLimit <= 0)
return;
Expand Down Expand Up @@ -371,10 +427,11 @@ public virtual int GetBuildTime(ActorInfo unit, BuildableInfo bi)
protected void CancelProduction(string itemName, uint numberToCancel)
{
for (var i = 0; i < numberToCancel; i++)
CancelProductionInner(itemName);
if (!CancelProductionInner(itemName))
break;
}

void CancelProductionInner(string itemName)
bool CancelProductionInner(string itemName)
{
var lastIndex = queue.FindLastIndex(a => a.Item == itemName);

Expand All @@ -388,6 +445,10 @@ void CancelProductionInner(string itemName)
playerResources.GiveCash(item.TotalCost - item.RemainingCost);
FinishProduction();
}
else
return false;

return true;
}

public void FinishProduction()
Expand Down
16 changes: 12 additions & 4 deletions OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs
Expand Up @@ -275,13 +275,21 @@ bool HandleLeftClick(ProductionItem item, ProductionIcon icon, int handleCount)
return true;
}

if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name))
var buildable = CurrentQueue.BuildableItems().FirstOrDefault(a => a.Name == icon.Name);

if (buildable != null)
{
// Queue a new item
Game.Sound.Play(SoundType.UI, TabClick);
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Faction.InternalName);
World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount));
return true;
string notification;
var canQueue = CurrentQueue.CanQueue(buildable, out notification);
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", notification, World.LocalPlayer.Faction.InternalName);

if (canQueue)
{
World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount));
return true;
}
}

return false;
Expand Down
10 changes: 10 additions & 0 deletions mods/cnc/rules/structures.yaml
Expand Up @@ -33,27 +33,31 @@ FACT:
LowPowerSlowdown: 2
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
ProductionQueue@NodBuilding:
Type: Building.Nod
Factions: nod
Group: Building
LowPowerSlowdown: 2
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
ProductionQueue@GDIDefense:
Type: Defence.GDI
Factions: gdi
Group: Defence
LowPowerSlowdown: 3
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
ProductionQueue@NodDefense:
Type: Defence.Nod
Factions: nod
Group: Defence
LowPowerSlowdown: 3
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
BaseBuilding:
ProductionBar@BuildingGDI:
ProductionType: Building.GDI
Expand Down Expand Up @@ -290,6 +294,7 @@ PYLE:
Group: Infantry
RequireOwner: false
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
ProductionBar:
Power:
Amount: -20
Expand Down Expand Up @@ -335,6 +340,7 @@ HAND:
Group: Infantry
RequireOwner: false
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
ProductionBar:
Power:
Amount: -20
Expand Down Expand Up @@ -387,6 +393,7 @@ AFLD:
RequireOwner: false
LowPowerSlowdown: 3
ReadyAudio:
LimitedAudio: BuildingInProgress
ProductionBar:
Power:
Amount: -50
Expand Down Expand Up @@ -439,6 +446,7 @@ WEAP:
RequireOwner: false
Group: Vehicle
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
ProductionBar:
Power:
Amount: -50
Expand Down Expand Up @@ -481,11 +489,13 @@ HPAD:
Factions: gdi
Group: Aircraft
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
ProductionQueue@Nod:
Type: Aircraft.Nod
Factions: nod
Group: Aircraft
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
ProductionBar@GDI:
ProductionType: Aircraft.GDI
ProductionBar@Nod:
Expand Down
1 change: 1 addition & 0 deletions mods/cnc/rules/tech.yaml
Expand Up @@ -71,6 +71,7 @@ BIO:
Group: Infantry
RequireOwner: false
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
ProductionBar:
RallyPoint:
Offset: -1,-1
Expand Down
6 changes: 6 additions & 0 deletions mods/ra/rules/player.yaml
Expand Up @@ -6,32 +6,38 @@ Player:
LowPowerSlowdown: 3
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Defense:
Type: Defense
LowPowerSlowdown: 3
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Vehicle:
Type: Vehicle
LowPowerSlowdown: 3
QueuedAudio: Building
LimitedAudio: BuildingInProgress
SpeedUp: True
BuildTimeSpeedReduction: 100, 75, 60, 50
ClassicProductionQueue@Infantry:
Type: Infantry
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Ship:
Type: Ship
LowPowerSlowdown: 3
QueuedAudio: Building
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Aircraft:
Type: Aircraft
LowPowerSlowdown: 3
QueuedAudio: Building
LimitedAudio: BuildingInProgress
SpeedUp: True
PlaceBuilding:
SupportPowerManager:
Expand Down
2 changes: 1 addition & 1 deletion mods/ts/audio/speech-generic.yaml
Expand Up @@ -47,7 +47,7 @@ Speech:
NavalUnitLost: 00-i074
NewOptions: 00-i032
NewTerrainDiscovered: 00-i198
NoBuild: 00-i064
BuildingInProgress: 00-i064
OnHold: 00-i218
OurAllyIsUnderAttack: 00-i308
PlayerHasResigned: 00-i252
Expand Down
5 changes: 5 additions & 0 deletions mods/ts/rules/player.yaml
Expand Up @@ -8,28 +8,33 @@ Player:
LowPowerSlowdown: 3
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Defense:
Type: Defense
BuildDurationModifier: 120
LowPowerSlowdown: 3
QueuedAudio: Building
ReadyAudio: ConstructionComplete
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Vehicle:
Type: Vehicle
BuildDurationModifier: 120
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Infantry:
Type: Infantry
BuildDurationModifier: 120
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
SpeedUp: True
ClassicProductionQueue@Air:
Type: Air
BuildDurationModifier: 120
LowPowerSlowdown: 3
LimitedAudio: BuildingInProgress
SpeedUp: True
PlaceBuilding:
Palette: placebuilding
Expand Down