From 4db2cf6b2bb1ecb2656c5502e08242109e21862c Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Jun 2014 21:29:14 +1200 Subject: [PATCH] Propagate race to produced actors. --- OpenRA.Mods.Cnc/ProductionAirdrop.cs | 5 +++-- .../Widgets/ProductionPaletteWidget.cs | 2 +- OpenRA.Mods.RA/AI/BaseBuilder.cs | 1 + .../Orders/PlaceBuildingOrderGenerator.cs | 16 +++++++++------ .../Player/ClassicProductionQueue.cs | 2 +- OpenRA.Mods.RA/Player/PlaceBuilding.cs | 20 ++++++++++--------- OpenRA.Mods.RA/Player/ProductionQueue.cs | 15 +++++++------- OpenRA.Mods.RA/Production.cs | 15 +++++++++----- .../Properties/ProductionProperties.cs | 4 ++-- OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs | 2 +- 10 files changed, 48 insertions(+), 34 deletions(-) diff --git a/OpenRA.Mods.Cnc/ProductionAirdrop.cs b/OpenRA.Mods.Cnc/ProductionAirdrop.cs index 509672c3f6..176ea0d5e9 100644 --- a/OpenRA.Mods.Cnc/ProductionAirdrop.cs +++ b/OpenRA.Mods.Cnc/ProductionAirdrop.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc public ProductionAirdrop(ProductionAirdropInfo info, Actor self) : base(info, self) { } - public override bool Produce(Actor self, ActorInfo producee) + public override bool Produce(Actor self, ActorInfo producee, string raceVariant) { var owner = self.Owner; @@ -69,7 +69,8 @@ namespace OpenRA.Mods.Cnc foreach (var cargo in self.TraitsImplementing()) cargo.Delivered(self); - self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit)); + + self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, raceVariant)); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Country.Race); })); diff --git a/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs index 564d79b5a6..dfcb3b8e8a 100644 --- a/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs +++ b/OpenRA.Mods.Cnc/Widgets/ProductionPaletteWidget.cs @@ -125,7 +125,7 @@ namespace OpenRA.Mods.Cnc.Widgets if (first != null && first.Done && actor.Traits.Contains()) { Sound.Play(TabClick); - World.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue.Actor, icon.Name); + World.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue, icon.Name); } else if (first != null && first.Paused) { diff --git a/OpenRA.Mods.RA/AI/BaseBuilder.cs b/OpenRA.Mods.RA/AI/BaseBuilder.cs index 4c280a17b3..ab1c5ca8fa 100644 --- a/OpenRA.Mods.RA/AI/BaseBuilder.cs +++ b/OpenRA.Mods.RA/AI/BaseBuilder.cs @@ -85,6 +85,7 @@ namespace OpenRA.Mods.RA.AI { TargetLocation = location.Value, TargetString = currentBuilding.Item, + TargetActor = queue.Actor, SuppressVisualFeedback = true }); } diff --git a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs index e39f22ed63..46ee716d4d 100644 --- a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs @@ -22,19 +22,22 @@ namespace OpenRA.Mods.RA.Orders readonly Actor Producer; readonly string Building; readonly BuildingInfo BuildingInfo; + IEnumerable preview; Sprite buildOk, buildBlocked; bool initialized = false; - public PlaceBuildingOrderGenerator(Actor producer, string name) + public PlaceBuildingOrderGenerator(ProductionQueue queue, string name) { - Producer = producer; + Producer = queue.Actor; Building = name; - var tileset = producer.World.TileSet.Id.ToLowerInvariant(); - BuildingInfo = producer.World.Map.Rules.Actors[Building].Traits.Get(); - buildOk = producer.World.Map.SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0); - buildBlocked = producer.World.Map.SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0); + var map = Producer.World.Map; + var tileset = Producer.World.TileSet.Id.ToLowerInvariant(); + BuildingInfo = map.Rules.Actors[Building].Traits.Get(); + + buildOk = map.SequenceProvider.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0); + buildBlocked = map.SequenceProvider.GetSequence("overlay", "build-invalid").GetSprite(0); } public IEnumerable Order(World world, CPos xy, MouseInput mi) @@ -65,6 +68,7 @@ namespace OpenRA.Mods.RA.Orders yield return new Order(isLineBuild ? "LineBuild" : "PlaceBuilding", Producer.Owner.PlayerActor, false) { TargetLocation = topLeft, + TargetActor = Producer, TargetString = Building, SuppressVisualFeedback = true }; diff --git a/OpenRA.Mods.RA/Player/ClassicProductionQueue.cs b/OpenRA.Mods.RA/Player/ClassicProductionQueue.cs index f20ec6ca6c..b914006e6b 100644 --- a/OpenRA.Mods.RA/Player/ClassicProductionQueue.cs +++ b/OpenRA.Mods.RA/Player/ClassicProductionQueue.cs @@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA foreach (var p in producers.Where(p => !p.Actor.IsDisabled())) { - if (p.Trait.Produce(p.Actor, self.World.Map.Rules.Actors[name])) + if (p.Trait.Produce(p.Actor, self.World.Map.Rules.Actors[name], Race)) { FinishProduction(); return true; diff --git a/OpenRA.Mods.RA/Player/PlaceBuilding.cs b/OpenRA.Mods.RA/Player/PlaceBuilding.cs index f3a82fa9c5..a2ad8c04fb 100644 --- a/OpenRA.Mods.RA/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.RA/Player/PlaceBuilding.cs @@ -28,19 +28,17 @@ namespace OpenRA.Mods.RA { var prevItems = GetNumBuildables(self.Owner); - // Find the queue with the target actor - var queue = w.ActorsWithTrait() - .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 (order.TargetActor.IsDead()) + return; + + var unit = self.World.Map.Rules.Actors[order.TargetString]; + var queue = order.TargetActor.TraitsImplementing() + .FirstOrDefault(q => q.CanBuild(unit)); if (queue == null) return; - var unit = self.World.Map.Rules.Actors[order.TargetString]; + var buildingInfo = unit.Traits.Get(); if (order.OrderString == "LineBuild") @@ -52,11 +50,13 @@ namespace OpenRA.Mods.RA { new LocationInit(t), new OwnerInit(order.Player), + new RaceInit(queue.Race) }); if (playSounds) foreach (var s in buildingInfo.BuildSounds) Sound.PlayToPlayer(order.Player, s, building.CenterPosition); + playSounds = false; } } @@ -72,7 +72,9 @@ namespace OpenRA.Mods.RA { new LocationInit(order.TargetLocation), new OwnerInit(order.Player), + new RaceInit(queue.Race), }); + foreach (var s in buildingInfo.BuildSounds) Sound.PlayToPlayer(order.Player, s, building.CenterPosition); } diff --git a/OpenRA.Mods.RA/Player/ProductionQueue.cs b/OpenRA.Mods.RA/Player/ProductionQueue.cs index 1747226d34..fd426bf728 100644 --- a/OpenRA.Mods.RA/Player/ProductionQueue.cs +++ b/OpenRA.Mods.RA/Player/ProductionQueue.cs @@ -75,7 +75,6 @@ namespace OpenRA.Mods.RA PowerManager playerPower; PlayerResources playerResources; DeveloperMode developerMode; - string race; // A list of things we could possibly build Dictionary produceable; @@ -92,6 +91,8 @@ namespace OpenRA.Mods.RA [Sync] public bool CurrentDone { get { return QueueLength != 0 && queue[0].Done; } } [Sync] public bool Enabled { get; private set; } + public string Race { get; private set; } + public ProductionQueue(ActorInitializer init, Actor playerActor, ProductionQueueInfo info) { self = init.self; @@ -100,8 +101,8 @@ namespace OpenRA.Mods.RA playerPower = playerActor.Trait(); developerMode = playerActor.Trait(); - race = init.Contains() ? init.Get() : self.Owner.Country.Race; - Enabled = !info.Race.Any() || info.Race.Contains(race); + Race = init.Contains() ? init.Get() : self.Owner.Country.Race; + Enabled = !info.Race.Any() || info.Race.Contains(Race); CacheProduceables(playerActor); } @@ -125,8 +126,8 @@ namespace OpenRA.Mods.RA if (!Info.Sticky) { - race = self.Owner.Country.Race; - Enabled = !Info.Race.Any() || Info.Race.Contains(race); + Race = self.Owner.Country.Race; + Enabled = !Info.Race.Any() || Info.Race.Contains(Race); } // Regenerate the produceables and tech tree state @@ -153,7 +154,7 @@ namespace OpenRA.Mods.RA var bi = a.Traits.Get(); // Can our race build this by satisfying normal prerequisites? - var buildable = !Info.RequireOwner || bi.Owner.Contains(race); + var buildable = !Info.RequireOwner || bi.Owner.Contains(Race); // Checks if Prerequisites want to hide the Actor from buildQueue if they are false produceable.Add(a, new ProductionState { Visible = buildable }); @@ -370,7 +371,7 @@ namespace OpenRA.Mods.RA } var sp = self.TraitsImplementing().FirstOrDefault(p => p.Info.Produces.Contains(Info.Type)); - if (sp != null && !self.IsDisabled() && sp.Produce(self, self.World.Map.Rules.Actors[name])) + if (sp != null && !self.IsDisabled() && sp.Produce(self, self.World.Map.Rules.Actors[name], Race)) { FinishProduction(); return true; diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index 01e4f26d06..15000c5751 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -53,7 +53,7 @@ namespace OpenRA.Mods.RA rp = Exts.Lazy(() => self.IsDead() ? null : self.TraitOrDefault()); } - public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) + public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string raceVariant) { var exit = self.Location + exitinfo.ExitCell; var spawn = self.CenterPosition + exitinfo.SpawnOffset; @@ -68,13 +68,18 @@ namespace OpenRA.Mods.RA self.World.AddFrameEndTask(w => { - var newUnit = self.World.CreateActor(producee.Name, new TypeDictionary + var td = new TypeDictionary { new OwnerInit(self.Owner), new LocationInit(exit), new CenterPositionInit(spawn), new FacingInit(initialFacing) - }); + }; + + if (raceVariant != null) + td.Add(new RaceInit(raceVariant)); + + var newUnit = self.World.CreateActor(producee.Name, td); var move = newUnit.TraitOrDefault(); if (move != null) @@ -96,7 +101,7 @@ namespace OpenRA.Mods.RA }); } - public virtual bool Produce(Actor self, ActorInfo producee) + public virtual bool Produce(Actor self, ActorInfo producee, string raceVariant) { if (Reservable.IsReserved(self)) return false; @@ -107,7 +112,7 @@ namespace OpenRA.Mods.RA if (exit != null) { - DoProduction(self, producee, exit); + DoProduction(self, producee, exit, raceVariant); return true; } diff --git a/OpenRA.Mods.RA/Scripting/Properties/ProductionProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/ProductionProperties.cs index cf8431829c..d51c43bdd8 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/ProductionProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/ProductionProperties.cs @@ -28,13 +28,13 @@ namespace OpenRA.Mods.RA.Scripting [ScriptActorPropertyActivity] [Desc("Build a unit, ignoring the production queue. The activity will wait if the exit is blocked")] - public void Produce(string actorType) + public void Produce(string actorType, string raceVariant = null) { ActorInfo actorInfo; if (!self.World.Map.Rules.Actors.TryGetValue(actorType, out actorInfo)) throw new LuaException("Unknown actor type '{0}'".F(actorType)); - self.QueueActivity(new WaitFor(() => p.Produce(self, actorInfo))); + self.QueueActivity(new WaitFor(() => p.Produce(self, actorInfo, raceVariant))); } } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs index 9f649d6523..eb967a22c1 100644 --- a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs +++ b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs @@ -366,7 +366,7 @@ namespace OpenRA.Mods.RA.Widgets if (producing.Done) { if (unit.Traits.Contains()) - world.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue.Actor, item); + world.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue, item); else StartProduction(world, item); return;