diff --git a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs index 5a65f23249..7d154f04d3 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs @@ -89,8 +89,8 @@ namespace OpenRA.Mods.Common.Activities } } - var exit = dest.Info.FirstExitOrDefault(null); - var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero; + var exit = dest.FirstExitOrDefault(null); + var offset = exit != null ? exit.Info.SpawnOffset : WVec.Zero; if (ShouldLandAtBuilding(self, dest)) { diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 75860ee2ac..e0239bea0a 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -750,8 +750,8 @@ namespace OpenRA.Mods.Common.Traits Action enter = () => { - var exit = targetActor.Info.FirstExitOrDefault(null); - var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero; + var exit = targetActor.FirstExitOrDefault(null); + var offset = exit != null ? exit.Info.SpawnOffset : WVec.Zero; self.QueueActivity(new HeliFly(self, Target.FromPos(targetActor.CenterPosition + offset))); self.QueueActivity(new Turn(self, Info.InitialFacing)); diff --git a/OpenRA.Mods.Common/Traits/Buildings/Exit.cs b/OpenRA.Mods.Common/Traits/Buildings/Exit.cs index dff89ad6fe..8311da7e35 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Exit.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Exit.cs @@ -17,7 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Where the unit should leave the building. Multiples are allowed if IDs are added: Exit@2, ...")] - public class ExitInfo : TraitInfo, Requires + public class ExitInfo : ConditionalTraitInfo, Requires { [Desc("Offset at which that the exiting actor is spawned relative to the center of the producing actor.")] public readonly WVec SpawnOffset = WVec.Zero; @@ -34,41 +34,48 @@ namespace OpenRA.Mods.Common.Traits [Desc("Number of ticks to wait before moving into the world.")] public readonly int ExitDelay = 0; + + public override object Create(ActorInitializer init) { return new Exit(init, this); } } - public class Exit { } + public class Exit : ConditionalTrait + { + public Exit(ActorInitializer init, ExitInfo info) + : base(info) { } + } public static class ExitExts { - public static ExitInfo FirstExitOrDefault(this ActorInfo info, string productionType = null) + public static Exit FirstExitOrDefault(this Actor actor, string productionType = null) { - var all = info.TraitInfos(); + var all = actor.TraitsImplementing() + .Where(Exts.IsTraitEnabled); + if (string.IsNullOrEmpty(productionType)) - return all.FirstOrDefault(e => e.ProductionTypes.Count == 0); - return all.FirstOrDefault(e => e.ProductionTypes.Count == 0 || e.ProductionTypes.Contains(productionType)); + return all.FirstOrDefault(e => e.Info.ProductionTypes.Count == 0); + + return all.FirstOrDefault(e => e.Info.ProductionTypes.Count == 0 || e.Info.ProductionTypes.Contains(productionType)); } - public static IEnumerable Exits(this ActorInfo info, string productionType = null) + public static IEnumerable Exits(this Actor actor, string productionType = null) { - var all = info.TraitInfos(); + var all = actor.TraitsImplementing() + .Where(Exts.IsTraitEnabled); + if (string.IsNullOrEmpty(productionType)) - return all.Where(e => e.ProductionTypes.Count == 0); - return all.Where(e => e.ProductionTypes.Count == 0 || e.ProductionTypes.Contains(productionType)); + return all.Where(e => e.Info.ProductionTypes.Count == 0); + + return all.Where(e => e.Info.ProductionTypes.Count == 0 || e.Info.ProductionTypes.Contains(productionType)); } - public static ExitInfo RandomExitOrDefault(this ActorInfo info, World world, string productionType, Func p = null) + public static Exit RandomExitOrDefault(this Actor actor, World world, string productionType, Func p = null) { - var allOfType = Exits(info, productionType); + var allOfType = Exits(actor, productionType); if (!allOfType.Any()) return null; var shuffled = allOfType.Shuffle(world.SharedRandom); return p != null ? shuffled.FirstOrDefault(p) : shuffled.First(); } - - public static ExitInfo RandomExitOrDefault(this Actor self, string productionType, Func p = null) - { - return RandomExitOrDefault(self.Info, self.World, productionType, p); - } } } diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index 3ce04d0777..960ab00fac 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -119,14 +119,14 @@ namespace OpenRA.Mods.Common.Traits }); } - protected virtual ExitInfo SelectExit(Actor self, ActorInfo producee, string productionType, Func p) + protected virtual Exit SelectExit(Actor self, ActorInfo producee, string productionType, Func p) { - return self.RandomExitOrDefault(productionType, p); + return self.RandomExitOrDefault(self.World, productionType, p); } - protected ExitInfo SelectExit(Actor self, ActorInfo producee, string productionType) + protected Exit SelectExit(Actor self, ActorInfo producee, string productionType) { - return SelectExit(self, producee, productionType, e => CanUseExit(self, producee, e)); + return SelectExit(self, producee, productionType, e => CanUseExit(self, producee, e.Info)); } public virtual bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits) @@ -139,7 +139,7 @@ namespace OpenRA.Mods.Common.Traits if (exit != null || self.OccupiesSpace == null) { - DoProduction(self, producee, exit, productionType, inits); + DoProduction(self, producee, exit.Info, productionType, inits); return true; } diff --git a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs index 30bebf2362..86ce3abed5 100644 --- a/OpenRA.Mods.Common/Traits/ProductionParadrop.cs +++ b/OpenRA.Mods.Common/Traits/ProductionParadrop.cs @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits // Start a fixed distance away: the width of the map. // This makes the production timing independent of spawnpoint - var dropPos = exit != null ? self.Location + exit.ExitCell : self.Location; + var dropPos = exit != null ? self.Location + exit.Info.ExitCell : self.Location; var startPos = dropPos + new CVec(owner.World.Map.Bounds.Width, 0); var endPos = new CPos(owner.World.Map.Bounds.Left - 5, dropPos.Y); @@ -87,7 +87,7 @@ namespace OpenRA.Mods.Common.Traits foreach (var cargo in self.TraitsImplementing()) cargo.Delivered(self); - self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, productionType, inits)); + self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit.Info, productionType, 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); }));