diff --git a/OpenRA.Mods.Cnc/Traits/Buildings/ClonesProducedUnits.cs b/OpenRA.Mods.Cnc/Traits/Buildings/ClonesProducedUnits.cs index b3134f7420..d6c6699a28 100644 --- a/OpenRA.Mods.Cnc/Traits/Buildings/ClonesProducedUnits.cs +++ b/OpenRA.Mods.Cnc/Traits/Buildings/ClonesProducedUnits.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using OpenRA.Mods.Common; using OpenRA.Mods.Common.Traits; +using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits @@ -49,7 +50,13 @@ namespace OpenRA.Mods.Cnc.Traits if (ci == null || !info.CloneableTypes.Overlaps(ci.Types)) return; - production.Produce(self, produced.Info, faction); + var inits = new TypeDictionary + { + new OwnerInit(self.Owner), + new FactionInit(BuildableInfo.GetInitialFaction(produced.Info, faction)) + }; + + production.Produce(self, produced.Info, inits); } } } diff --git a/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs b/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs index b0c1057018..3d5c582985 100644 --- a/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs +++ b/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs @@ -9,6 +9,7 @@ */ #endregion +using System.Collections.Generic; using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common; @@ -38,7 +39,7 @@ namespace OpenRA.Mods.Cnc.Traits this.info = info; } - public override bool Produce(Actor self, ActorInfo producee, string factionVariant) + public override bool Produce(Actor self, ActorInfo producee, TypeDictionary inits) { var owner = self.Owner; var aircraftInfo = self.World.Map.Rules.Actors[info.ActorType].TraitInfo(); @@ -79,7 +80,7 @@ namespace OpenRA.Mods.Cnc.Traits foreach (var cargo in self.TraitsImplementing()) cargo.Delivered(self); - self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, factionVariant)); + self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, inits)); Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName); })); diff --git a/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs index 349c8b9645..17985e4327 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs @@ -15,6 +15,7 @@ using System.Linq; using Eluant; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Traits; +using OpenRA.Primitives; using OpenRA.Scripting; using OpenRA.Traits; @@ -39,7 +40,14 @@ namespace OpenRA.Mods.Common.Scripting 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, factionVariant))); + var faction = factionVariant ?? BuildableInfo.GetInitialFaction(actorInfo, p.Faction); + var inits = new TypeDictionary + { + new OwnerInit(Self.Owner), + new FactionInit(faction) + }; + + Self.QueueActivity(new WaitFor(() => p.Produce(Self, actorInfo, inits))); } } diff --git a/OpenRA.Mods.Common/Traits/Buildable.cs b/OpenRA.Mods.Common/Traits/Buildable.cs index d8b716e092..7cbca90871 100644 --- a/OpenRA.Mods.Common/Traits/Buildable.cs +++ b/OpenRA.Mods.Common/Traits/Buildable.cs @@ -51,6 +51,12 @@ namespace OpenRA.Mods.Common.Traits [Desc("Text shown in the production tooltip.")] [Translate] public readonly string Description = ""; + + public static string GetInitialFaction(ActorInfo ai, string defaultFaction) + { + var bi = ai.TraitInfoOrDefault(); + return bi != null ? bi.ForceFaction ?? defaultFaction : defaultFaction; + } } public class Buildable { } diff --git a/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs index d506b4a85a..ceeddb9aa7 100644 --- a/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -105,7 +106,13 @@ namespace OpenRA.Mods.Common.Traits foreach (var p in producers.Where(p => !p.Actor.IsDisabled())) { - if (p.Trait.Produce(p.Actor, unit, p.Trait.Faction)) + var inits = new TypeDictionary + { + new OwnerInit(self.Owner), + new FactionInit(BuildableInfo.GetInitialFaction(unit, p.Trait.Faction)) + }; + + if (p.Trait.Produce(p.Actor, unit, inits)) { FinishProduction(); return true; diff --git a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs index f0c2b08eb6..440881266e 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -381,8 +382,14 @@ namespace OpenRA.Mods.Common.Traits return true; } + var inits = new TypeDictionary + { + new OwnerInit(self.Owner), + new FactionInit(BuildableInfo.GetInitialFaction(unit, Faction)) + }; + var sp = self.TraitsImplementing().FirstOrDefault(p => p.Info.Produces.Contains(Info.Type)); - if (sp != null && !self.IsDisabled() && sp.Produce(self, unit, Faction)) + if (sp != null && !self.IsDisabled() && sp.Produce(self, unit, inits)) { FinishProduction(); return true; diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index 74540541c1..0ca1190ae5 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -49,20 +49,16 @@ namespace OpenRA.Mods.Common.Traits building = self.TraitOrDefault(); } - public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string factionVariant) + public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, TypeDictionary inits) { var exit = CPos.Zero; var exitLocation = CPos.Zero; var target = Target.Invalid; - var bi = producee.TraitInfoOrDefault(); - if (bi != null && bi.ForceFaction != null) - factionVariant = bi.ForceFaction; - - var td = new TypeDictionary - { - new OwnerInit(self.Owner), - }; + // Clone the initializer dictionary for the new actor + var td = new TypeDictionary(); + foreach (var init in inits) + td.Add(init); if (self.OccupiesSpace != null) { @@ -93,9 +89,6 @@ namespace OpenRA.Mods.Common.Traits self.World.AddFrameEndTask(w => { - if (factionVariant != null) - td.Add(new FactionInit(factionVariant)); - var newUnit = self.World.CreateActor(producee.Name, td); var move = newUnit.TraitOrDefault(); @@ -127,7 +120,7 @@ namespace OpenRA.Mods.Common.Traits }); } - public virtual bool Produce(Actor self, ActorInfo producee, string factionVariant) + public virtual bool Produce(Actor self, ActorInfo producee, TypeDictionary inits) { if (Reservable.IsReserved(self) || (building != null && building.Locked)) return false; @@ -138,7 +131,7 @@ namespace OpenRA.Mods.Common.Traits if (exit != null || self.OccupiesSpace == null) { - DoProduction(self, producee, exit, factionVariant); + DoProduction(self, producee, exit, inits); return true; } diff --git a/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs b/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs index e485f7e47b..1df656037c 100644 --- a/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs +++ b/OpenRA.Mods.Common/Traits/ProductionFromMapEdge.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits rp = self.TraitOrDefault(); } - public override bool Produce(Actor self, ActorInfo producee, string factionVariant) + public override bool Produce(Actor self, ActorInfo producee, TypeDictionary inits) { var aircraftInfo = producee.TraitInfoOrDefault(); var mobileInfo = producee.TraitInfoOrDefault(); @@ -74,16 +74,13 @@ namespace OpenRA.Mods.Common.Traits self.World.AddFrameEndTask(w => { - var td = new TypeDictionary - { - new OwnerInit(self.Owner), - new LocationInit(location.Value), - new CenterPositionInit(pos), - new FacingInit(initialFacing) - }; + var td = new TypeDictionary(); + foreach (var init in inits) + td.Add(init); - if (factionVariant != null) - td.Add(new FactionInit(factionVariant)); + td.Add(new LocationInit(location.Value)); + td.Add(new CenterPositionInit(pos)); + td.Add(new FacingInit(initialFacing)); var newUnit = self.World.CreateActor(producee.Name, td); diff --git a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs index a4bce0945b..2f8c2e249a 100644 --- a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs +++ b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits rp = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault()); } - public override bool Produce(Actor self, ActorInfo producee, string factionVariant) + public override bool Produce(Actor self, ActorInfo producee, TypeDictionary inits) { var owner = self.Owner; @@ -85,7 +85,7 @@ namespace OpenRA.Mods.Common.Traits foreach (var cargo in self.TraitsImplementing()) cargo.Delivered(self); - self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, factionVariant)); + self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, inits)); Game.Sound.Play(SoundType.World, info.ChuteSound, self.CenterPosition); Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName); })); @@ -97,7 +97,7 @@ namespace OpenRA.Mods.Common.Traits return true; } - public override void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string factionVariant) + public override void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, TypeDictionary inits) { var exit = CPos.Zero; var exitLocation = CPos.Zero; @@ -106,15 +106,12 @@ namespace OpenRA.Mods.Common.Traits var info = (ProductionParadropInfo)Info; var actorType = info.ActorType; - var bi = producee.TraitInfoOrDefault(); - if (bi != null && bi.ForceFaction != null) - factionVariant = bi.ForceFaction; - var altitude = self.World.Map.Rules.Actors[actorType].TraitInfo().CruiseAltitude; - var td = new TypeDictionary - { - new OwnerInit(self.Owner), - }; + + // Clone the initializer dictionary for the new actor + var td = new TypeDictionary(); + foreach (var init in inits) + td.Add(init); if (self.OccupiesSpace != null) { @@ -134,9 +131,6 @@ namespace OpenRA.Mods.Common.Traits self.World.AddFrameEndTask(w => { - if (factionVariant != null) - td.Add(new FactionInit(factionVariant)); - var newUnit = self.World.CreateActor(producee.Name, td); newUnit.QueueActivity(new Parachute(newUnit, newUnit.CenterPosition, self)); diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/ProduceActorPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/ProduceActorPower.cs index e574ced864..fb5b6233f5 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/ProduceActorPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/ProduceActorPower.cs @@ -10,6 +10,7 @@ #endregion using System.Linq; +using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -64,8 +65,19 @@ namespace OpenRA.Mods.Common.Traits var activated = false; if (sp != null) + { foreach (var name in info.Actors) - activated |= sp.Produce(self, self.World.Map.Rules.Actors[name], faction); + { + var ai = self.World.Map.Rules.Actors[name]; + var inits = new TypeDictionary + { + new OwnerInit(self.Owner), + new FactionInit(BuildableInfo.GetInitialFaction(ai, faction)) + }; + + activated |= sp.Produce(self, ai, inits); + } + } if (activated) Game.Sound.PlayNotification(self.World.Map.Rules, manager.Self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName);