Set actor race (and icons) based on active producer.

This commit is contained in:
Paul Chote
2015-02-11 23:37:56 +00:00
parent 44159ecdd6
commit d1ed1bf0fb
7 changed files with 55 additions and 43 deletions

View File

@@ -27,13 +27,13 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Cargo aircraft used.")] [Desc("Cargo aircraft used.")]
[ActorReference] public readonly string ActorType = "c17"; [ActorReference] public readonly string ActorType = "c17";
public override object Create(ActorInitializer init) { return new ProductionAirdrop(this, init.Self); } public override object Create(ActorInitializer init) { return new ProductionAirdrop(init, this); }
} }
class ProductionAirdrop : Production class ProductionAirdrop : Production
{ {
public ProductionAirdrop(ProductionAirdropInfo info, Actor self) public ProductionAirdrop(ActorInitializer init, ProductionAirdropInfo info)
: base(info, self) { } : base(init, info) { }
public override bool Produce(Actor self, ActorInfo producee, string raceVariant) public override bool Produce(Actor self, ActorInfo producee, string raceVariant)
{ {

View File

@@ -15,7 +15,6 @@ using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics; using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Orders namespace OpenRA.Mods.Common.Orders
{ {
@@ -24,15 +23,18 @@ namespace OpenRA.Mods.Common.Orders
readonly Actor producer; readonly Actor producer;
readonly string building; readonly string building;
readonly BuildingInfo buildingInfo; readonly BuildingInfo buildingInfo;
readonly string race;
readonly Sprite buildOk;
readonly Sprite buildBlocked;
IActorPreview[] preview; IActorPreview[] preview;
Sprite buildOk, buildBlocked; bool initialized;
bool initialized = false;
public PlaceBuildingOrderGenerator(ProductionQueue queue, string name) public PlaceBuildingOrderGenerator(ProductionQueue queue, string name)
{ {
producer = queue.Actor; producer = queue.Actor;
building = name; building = name;
race = queue.MostLikelyProducer().Trait.Race;
// Clear selection if using Left-Click Orders // Clear selection if using Left-Click Orders
if (Game.Settings.Game.UseClassicMouseStyle) if (Game.Settings.Game.UseClassicMouseStyle)
@@ -122,7 +124,12 @@ namespace OpenRA.Mods.Common.Orders
{ {
if (!initialized) if (!initialized)
{ {
var init = new ActorPreviewInitializer(rules.Actors[building], producer.Owner, wr, new TypeDictionary()); var td = new TypeDictionary()
{
new RaceInit(race)
};
var init = new ActorPreviewInitializer(rules.Actors[building], producer.Owner, wr, td);
preview = rules.Actors[building].Traits.WithInterface<IRenderActorPreviewInfo>() preview = rules.Actors[building].Traits.WithInterface<IRenderActorPreviewInfo>()
.SelectMany(rpi => rpi.RenderPreview(init)) .SelectMany(rpi => rpi.RenderPreview(init))
.ToArray(); .ToArray();

View File

@@ -74,6 +74,16 @@ namespace OpenRA.Mods.Common.Traits
return isActive ? base.BuildableItems() : NoItems; return isActive ? base.BuildableItems() : NoItems;
} }
public override TraitPair<Production> MostLikelyProducer()
{
return self.World.ActorsWithTrait<Production>()
.Where(x => x.Actor.Owner == self.Owner
&& x.Trait.Info.Produces.Contains(Info.Type))
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
.ThenByDescending(x => x.Actor.ActorID)
.FirstOrDefault();
}
protected override bool BuildUnit(string name) protected override bool BuildUnit(string name)
{ {
// Find a production structure to build this actor // Find a production structure to build this actor
@@ -97,7 +107,7 @@ namespace OpenRA.Mods.Common.Traits
foreach (var p in producers.Where(p => !p.Actor.IsDisabled())) foreach (var p in producers.Where(p => !p.Actor.IsDisabled()))
{ {
if (p.Trait.Produce(p.Actor, ai, Race)) if (p.Trait.Produce(p.Actor, ai, p.Trait.Race))
{ {
FinishProduction(); FinishProduction();
return true; return true;

View File

@@ -38,6 +38,8 @@ namespace OpenRA.Mods.Common.Traits
if (queue == null) if (queue == null)
return; return;
var producer = queue.MostLikelyProducer();
var race = producer.Trait != null ? producer.Trait.Race : self.Owner.Country.Race;
var buildingInfo = unit.Traits.Get<BuildingInfo>(); var buildingInfo = unit.Traits.Get<BuildingInfo>();
if (order.OrderString == "LineBuild") if (order.OrderString == "LineBuild")
@@ -49,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
new LocationInit(t), new LocationInit(t),
new OwnerInit(order.Player), new OwnerInit(order.Player),
new RaceInit(queue.Race) new RaceInit(race)
}); });
if (playSounds) if (playSounds)
@@ -69,14 +71,16 @@ namespace OpenRA.Mods.Common.Traits
{ {
new LocationInit(order.TargetLocation), new LocationInit(order.TargetLocation),
new OwnerInit(order.Player), new OwnerInit(order.Player),
new RaceInit(queue.Race), new RaceInit(race),
}); });
foreach (var s in buildingInfo.BuildSounds) foreach (var s in buildingInfo.BuildSounds)
Sound.PlayToPlayer(order.Player, s, building.CenterPosition); Sound.PlayToPlayer(order.Player, s, building.CenterPosition);
} }
PlayBuildAnim(self, unit); if (producer.Actor != null)
foreach (var nbp in producer.Actor.TraitsImplementing<INotifyBuildingPlaced>())
nbp.BuildingPlaced(producer.Actor);
queue.FinishProduction(); queue.FinishProduction();
@@ -84,9 +88,9 @@ namespace OpenRA.Mods.Common.Traits
{ {
// May be null if the build anywhere cheat is active // May be null if the build anywhere cheat is active
// BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location // BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location
var producer = buildingInfo.FindBaseProvider(w, self.Owner, order.TargetLocation); var provider = buildingInfo.FindBaseProvider(w, self.Owner, order.TargetLocation);
if (producer != null) if (provider != null)
producer.Trait<BaseProvider>().BeginCooldown(); provider.Trait<BaseProvider>().BeginCooldown();
} }
if (GetNumBuildables(self.Owner) > prevItems) if (GetNumBuildables(self.Owner) > prevItems)
@@ -96,30 +100,11 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
// finds a construction yard (or equivalent) and runs its "build" animation.
static void PlayBuildAnim(Actor self, ActorInfo unit)
{
var bi = unit.Traits.GetOrDefault<BuildableInfo>();
if (bi == null)
return;
var producers = self.World.ActorsWithTrait<Production>()
.Where(x => x.Actor.Owner == self.Owner
&& x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Intersect(bi.Queue).Any())
.ToList();
var producer = producers.Where(x => x.Actor.IsPrimaryBuilding()).Concat(producers)
.FirstOrDefault();
if (producer.Actor == null)
return;
foreach (var nbp in producer.Actor.TraitsImplementing<INotifyBuildingPlaced>())
nbp.BuildingPlaced(producer.Actor);
}
static int GetNumBuildables(Player p) static int GetNumBuildables(Player p)
{ {
if (p != p.World.LocalPlayer) return 0; // this only matters for local players. // This only matters for local players.
if (p != p.World.LocalPlayer)
return 0;
return p.World.ActorsWithTrait<ProductionQueue>() return p.World.ActorsWithTrait<ProductionQueue>()
.Where(a => a.Actor.Owner == p) .Where(a => a.Actor.Owner == p)

View File

@@ -79,7 +79,6 @@ namespace OpenRA.Mods.Common.Traits
Dictionary<ActorInfo, ProductionState> produceable; Dictionary<ActorInfo, ProductionState> produceable;
List<ProductionItem> queue = new List<ProductionItem>(); List<ProductionItem> queue = new List<ProductionItem>();
// A list of things we are currently building
public Actor Actor { get { return self; } } public Actor Actor { get { return self; } }
[Sync] public int QueueLength { get { return queue.Count; } } [Sync] public int QueueLength { get { return queue.Count; } }
@@ -361,6 +360,13 @@ namespace OpenRA.Mods.Common.Traits
queue.Add(item); queue.Add(item);
} }
// Returns the actor/trait that is most likely (but not necessarily guaranteed) to produce something in this queue
public virtual TraitPair<Production> MostLikelyProducer()
{
var trait = self.TraitsImplementing<Production>().FirstOrDefault(p => p.Info.Produces.Contains(Info.Type));
return new TraitPair<Production> { Actor = self, Trait = trait };
}
// Builds a unit from the actor that holds this queue (1 queue per building) // Builds a unit from the actor that holds this queue (1 queue per building)
// Returns false if the unit can't be built // Returns false if the unit can't be built
protected virtual bool BuildUnit(string name) protected virtual bool BuildUnit(string name)

View File

@@ -24,18 +24,21 @@ namespace OpenRA.Mods.Common.Traits
[Desc("e.g. Infantry, Vehicles, Aircraft, Buildings")] [Desc("e.g. Infantry, Vehicles, Aircraft, Buildings")]
public readonly string[] Produces = { }; public readonly string[] Produces = { };
public virtual object Create(ActorInitializer init) { return new Production(this, init.Self); } public virtual object Create(ActorInitializer init) { return new Production(init, this); }
} }
public class Production public class Production
{ {
Lazy<RallyPoint> rp; readonly Lazy<RallyPoint> rp;
public ProductionInfo Info; public ProductionInfo Info;
public Production(ProductionInfo info, Actor self) public string Race { get; private set; }
public Production(ActorInitializer init, ProductionInfo info)
{ {
Info = info; Info = info;
rp = Exts.Lazy(() => self.IsDead ? null : self.TraitOrDefault<RallyPoint>()); rp = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault<RallyPoint>());
Race = init.Contains<RaceInit>() ? init.Get<RaceInit, string>() : init.Self.Owner.Country.Race;
} }
public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string raceVariant) public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string raceVariant)

View File

@@ -252,7 +252,8 @@ namespace OpenRA.Mods.Common.Widgets
public void RefreshIcons() public void RefreshIcons()
{ {
icons = new Dictionary<Rectangle, ProductionIcon>(); icons = new Dictionary<Rectangle, ProductionIcon>();
if (CurrentQueue == null) var producer = CurrentQueue != null ? CurrentQueue.MostLikelyProducer() : default(TraitPair<Production>);
if (CurrentQueue == null || producer.Trait == null)
{ {
if (DisplayedIconCount != 0) if (DisplayedIconCount != 0)
{ {
@@ -268,7 +269,7 @@ namespace OpenRA.Mods.Common.Widgets
var ks = Game.Settings.Keys; var ks = Game.Settings.Keys;
var rb = RenderBounds; var rb = RenderBounds;
var race = CurrentQueue.Actor.Owner.Country.Race; var race = producer.Trait.Race;
foreach (var item in AllBuildables.Skip(IconRowOffset * Columns).Take(MaxIconRowOffset * Columns)) foreach (var item in AllBuildables.Skip(IconRowOffset * Columns).Take(MaxIconRowOffset * Columns))
{ {