Route "Can i build X" queries via the appropriate ProductionQueue

This commit is contained in:
Paul Chote
2010-08-27 01:18:09 +12:00
parent 226fd167e7
commit 88dfbe657c
4 changed files with 52 additions and 43 deletions

View File

@@ -103,10 +103,9 @@ namespace OpenRA.Traits
{ {
if (p != p.World.LocalPlayer) return 0; // this only matters for local players. if (p != p.World.LocalPlayer) return 0; // this only matters for local players.
// todo: this will simplify once queues know about what they can build return p.World.Queries.WithTraitMultiple<ProductionQueue>()
var queues = p.World.Queries.WithTraitMultiple<ProductionQueue>().Where(a => a.Actor.Owner == p) .Where(a => a.Actor.Owner == p)
.Select(a => a.Trait.Info.Type).Distinct().ToArray(); .SelectMany(a => a.Trait.BuildableItems()).Distinct().Count();
return Rules.TechTree.BuildableItems(p, queues).Count();
} }
} }
} }

View File

@@ -46,9 +46,27 @@ namespace OpenRA.Traits
return Producing; return Producing;
} }
public IEnumerable<ActorInfo> AllItems()
{
return Rules.TechTree.AllBuildables(Info.Type)
.Where(a => a.Traits.Get<BuildableInfo>().Owner.Contains(self.Owner.Country.Race))
.OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder);
}
public IEnumerable<ActorInfo> BuildableItems()
{
return Rules.TechTree.BuildableItems(self.Owner, Info.Type).Select(b => Rules.Info[b.ToLowerInvariant()]);
}
public bool CanBuild(ActorInfo actor)
{
var buildings = Rules.TechTree.GatherBuildings( self.Owner );
return Rules.TechTree.CanBuild(actor, self.Owner, buildings);
}
public void Tick( Actor self ) public void Tick( Actor self )
{ {
while( Producing.Count > 0 && !Rules.TechTree.BuildableItems( self.Owner, Info.Type ).Contains( Producing[ 0 ].Item ) ) while( Producing.Count > 0 && !BuildableItems().Any(b => b.Name == Producing[ 0 ].Item) )
{ {
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(Producing[0].TotalCost - Producing[0].RemainingCost); // refund what's been paid so far. self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(Producing[0].TotalCost - Producing[0].RemainingCost); // refund what's been paid so far.
FinishProduction(); FinishProduction();
@@ -71,7 +89,7 @@ namespace OpenRA.Traits
var cost = unit.Traits.Contains<ValuedInfo>() ? unit.Traits.Get<ValuedInfo>().Cost : 0; var cost = unit.Traits.Contains<ValuedInfo>() ? unit.Traits.Get<ValuedInfo>().Cost : 0;
var time = GetBuildTime(order.TargetString); var time = GetBuildTime(order.TargetString);
if (!Rules.TechTree.BuildableItems(order.Player, bi.Queue).Contains(order.TargetString)) if (!BuildableItems().Any(b => b.Name == order.TargetString))
return; /* you can't build that!! */ return; /* you can't build that!! */
bool hasPlayedSound = false; bool hasPlayedSound = false;

View File

@@ -70,23 +70,23 @@ namespace OpenRA.Mods.RA
playerResources = p.PlayerActor.Trait<PlayerResources>(); playerResources = p.PlayerActor.Trait<PlayerResources>();
} }
int GetPowerProvidedBy(string building) int GetPowerProvidedBy(ActorInfo building)
{ {
var bi = Rules.Info[building].Traits.GetOrDefault<BuildingInfo>(); var bi = building.Traits.GetOrDefault<BuildingInfo>();
if (bi == null) return 0; if (bi == null) return 0;
return bi.Power; return bi.Power;
} }
string ChooseRandomUnitToBuild(string category) ActorInfo ChooseRandomUnitToBuild(ProductionQueue queue)
{ {
var buildableThings = Rules.TechTree.BuildableItems(p, category).ToArray(); var buildableThings = queue.BuildableItems();
if (buildableThings.Length == 0) return null; if (buildableThings.Count() == 0) return null;
return buildableThings[random.Next(buildableThings.Length)]; return buildableThings.ElementAtOrDefault(random.Next(buildableThings.Count()));
} }
string ChooseBuildingToBuild() ActorInfo ChooseBuildingToBuild(ProductionQueue queue)
{ {
var buildableThings = Rules.TechTree.BuildableItems(p, "Building").ToArray(); var buildableThings = queue.BuildableItems();
if (playerResources.PowerProvided <= playerResources.PowerDrained * 1.2) /* try to maintain 20% excess power */ if (playerResources.PowerProvided <= playerResources.PowerDrained * 1.2) /* try to maintain 20% excess power */
{ {
@@ -107,9 +107,9 @@ namespace OpenRA.Mods.RA
.Select( a => a.Actor.Info.Name ).ToArray(); .Select( a => a.Actor.Info.Name ).ToArray();
foreach (var frac in buildingFractions) foreach (var frac in buildingFractions)
if (buildableThings.Contains(frac.Key)) if (buildableThings.Any(b => b.Name == frac.Key))
if (myBuildings.Count(a => a == frac.Key) < frac.Value * myBuildings.Length) if (myBuildings.Count(a => a == frac.Key) < frac.Value * myBuildings.Length)
return frac.Key; return Rules.Info[frac.Key];
return null; return null;
} }
@@ -290,10 +290,10 @@ namespace OpenRA.Mods.RA
if (queue == null) if (queue == null)
return; return;
var unit = ChooseRandomUnitToBuild(category); var unit = ChooseRandomUnitToBuild(queue);
if (unit != null) if (unit != null)
{ {
Game.IssueOrder(Order.StartProduction(queue.self, unit, 1)); Game.IssueOrder(Order.StartProduction(queue.self, unit.Name, 1));
} }
} }
@@ -305,12 +305,15 @@ namespace OpenRA.Mods.RA
.Select(a => a.Trait) .Select(a => a.Trait)
.FirstOrDefault(); .FirstOrDefault();
if (queue == null)
return;
var currentBuilding = queue.CurrentItem(); var currentBuilding = queue.CurrentItem();
switch (state) switch (state)
{ {
case BuildState.ChooseItem: case BuildState.ChooseItem:
{ {
var item = ChooseBuildingToBuild(); var item = ChooseBuildingToBuild(queue);
if (item == null) if (item == null)
{ {
state = BuildState.WaitForFeedback; state = BuildState.WaitForFeedback;
@@ -319,7 +322,7 @@ namespace OpenRA.Mods.RA
else else
{ {
state = BuildState.WaitForProduction; state = BuildState.WaitForProduction;
Game.IssueOrder(Order.StartProduction(queue.self, item, 1)); Game.IssueOrder(Order.StartProduction(queue.self, item.Name, 1));
} }
} }
break; break;

View File

@@ -82,13 +82,10 @@ namespace OpenRA.Mods.RA.Widgets
.Select(p => p.Trait); .Select(p => p.Trait);
foreach (var queue in queues) foreach (var queue in queues)
if (!Rules.TechTree.BuildableItems(world.LocalPlayer, queue.Info.Type).Any()) if (queue.BuildableItems().Count() > 0)
{
if (CurrentQueue == queue)
CurrentQueue = null;
}
else
visibleTabs.Add(queue); visibleTabs.Add(queue);
else if (CurrentQueue == queue)
CurrentQueue = null;
if (CurrentQueue == null) if (CurrentQueue == null)
CurrentQueue = queues.FirstOrDefault(); CurrentQueue = queues.FirstOrDefault();
@@ -185,19 +182,15 @@ namespace OpenRA.Mods.RA.Widgets
string paletteCollection = "palette-" + world.LocalPlayer.Country.Race; string paletteCollection = "palette-" + world.LocalPlayer.Country.Race;
float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9); float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9);
var queueName = queue.Info.Type;
// Collect info // Collect info
var x = 0; var x = 0;
var y = 0; var y = 0;
var buildableItems = Rules.TechTree.BuildableItems(world.LocalPlayer, queueName).ToArray(); var buildableItems = queue.BuildableItems();
var allBuildables = Rules.TechTree.AllBuildables(queueName) var allBuildables = queue.AllItems();
.Where(a => a.Traits.Get<BuildableInfo>().Owner.Contains(world.LocalPlayer.Country.Race))
.OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder)
.ToArray();
var overlayBits = new List<Pair<Sprite, float2>>(); var overlayBits = new List<Pair<Sprite, float2>>();
numActualRows = Math.Max((allBuildables.Length + Columns - 1) / Columns, Rows); numActualRows = Math.Max((allBuildables.Count() + Columns - 1) / Columns, Rows);
// Palette Background // Palette Background
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9)); WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9));
@@ -260,10 +253,10 @@ namespace OpenRA.Mods.RA.Widgets
} }
} }
else else
if (!buildableItems.Contains(item.Name) || isBuildingSomething) if (!buildableItems.Any(a => a.Name == item.Name) || isBuildingSomething)
overlayBits.Add(Pair.New(cantBuild.Image, drawPos)); overlayBits.Add(Pair.New(cantBuild.Image, drawPos));
var closureName = buildableItems.Contains(item.Name) ? item.Name : null; var closureName = buildableItems.Any(a => a.Name == item.Name) ? item.Name : null;
buttons.Add(Pair.New(new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), HandleClick(closureName, world))); buttons.Add(Pair.New(new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), HandleClick(closureName, world)));
if (++x == Columns) { x = 0; y++; } if (++x == Columns) { x = 0; y++; }
@@ -444,8 +437,7 @@ namespace OpenRA.Mods.RA.Widgets
var tooltip = info.Traits.Get<TooltipInfo>(); var tooltip = info.Traits.Get<TooltipInfo>();
var buildable = info.Traits.Get<BuildableInfo>(); var buildable = info.Traits.Get<BuildableInfo>();
var cost = info.Traits.Get<ValuedInfo>().Cost; var cost = info.Traits.Get<ValuedInfo>().Cost;
var buildings = Rules.TechTree.GatherBuildings( pl ); var canBuildThis = CurrentQueue.CanBuild(info);
var canBuildThis = Rules.TechTree.CanBuild(info, pl, buildings);
var longDescSize = Game.Renderer.RegularFont.Measure(tooltip.Description.Replace("\\n", "\n")).Y; var longDescSize = Game.Renderer.RegularFont.Measure(tooltip.Description.Replace("\\n", "\n")).Y;
if (!canBuildThis) longDescSize += 8; if (!canBuildThis) longDescSize += 8;
@@ -494,15 +486,12 @@ namespace OpenRA.Mods.RA.Widgets
bool DoBuildingHotkey(char c, World world) bool DoBuildingHotkey(char c, World world)
{ {
if (!paletteOpen) return false; if (!paletteOpen) return false;
var toBuild = CurrentQueue.BuildableItems().FirstOrDefault(b => b.Traits.Get<BuildableInfo>().Hotkey == c.ToString());
var buildable = Rules.TechTree.BuildableItems(world.LocalPlayer, CurrentQueue.Info.Type);
var toBuild = buildable.FirstOrDefault(b => Rules.Info[b.ToLowerInvariant()].Traits.Get<BuildableInfo>().Hotkey == c.ToString());
if ( toBuild != null ) if ( toBuild != null )
{ {
Sound.Play(TabClick); Sound.Play(TabClick);
HandleBuildPalette(world, toBuild, true); HandleBuildPalette(world, toBuild.Name, true);
return true; return true;
} }