diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 2fab1a1b8b..1cf4b8fcdb 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -43,15 +43,7 @@ namespace OpenRA public Rectangle Bounds { get; private set; } public Rectangle VisualBounds { get; private set; } public IEffectiveOwner EffectiveOwner { get; private set; } - public IOccupySpace OccupiesSpace - { - get - { - if (occupySpace == null) - occupySpace = Trait(); - return occupySpace; - } - } + public IOccupySpace OccupiesSpace { get; private set; } public bool IsIdle { get { return currentActivity == null; } } public bool IsDead { get { return Disposed || (health != null && health.IsDead); } } @@ -69,7 +61,6 @@ namespace OpenRA } } - IOccupySpace occupySpace; readonly IFacing facing; readonly IHealth health; readonly IRenderModifier[] renderModifiers; @@ -96,7 +87,14 @@ namespace OpenRA Info = world.Map.Rules.Actors[name]; foreach (var trait in Info.TraitsInConstructOrder()) + { AddTrait(trait.Create(init)); + + // Some traits rely on properties provided by IOccupySpace in their initialization, + // so we must ready it now, we cannot wait until all traits have finished construction. + if (trait is IOccupySpaceInfo) + OccupiesSpace = Trait(); + } } Bounds = DetermineBounds(); diff --git a/OpenRA.Mods.Common/AI/HackyAI.cs b/OpenRA.Mods.Common/AI/HackyAI.cs index 4bcf323ecc..5a7ace582e 100644 --- a/OpenRA.Mods.Common/AI/HackyAI.cs +++ b/OpenRA.Mods.Common/AI/HackyAI.cs @@ -574,7 +574,7 @@ namespace OpenRA.Mods.Common.AI // Pick something worth attacking owned by that player var target = World.Actors - .Where(a => a.Owner == enemy && a.Info.HasTraitInfo()) + .Where(a => a.Owner == enemy && a.OccupiesSpace != null) .ClosestTo(World.Map.CenterOfCell(GetRandomBaseCenter())); if (target == null) diff --git a/OpenRA.Mods.Common/ActorExts.cs b/OpenRA.Mods.Common/ActorExts.cs index 74f08d816a..44e9923e6b 100644 --- a/OpenRA.Mods.Common/ActorExts.cs +++ b/OpenRA.Mods.Common/ActorExts.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common if (self.IsDead) return false; - if (!self.Info.HasTraitInfo()) + if (self.OccupiesSpace == null) return false; if (!self.IsInWorld) diff --git a/OpenRA.Mods.Common/Traits/Production.cs b/OpenRA.Mods.Common/Traits/Production.cs index fe645740d0..d424c0eac8 100644 --- a/OpenRA.Mods.Common/Traits/Production.cs +++ b/OpenRA.Mods.Common/Traits/Production.cs @@ -35,12 +35,9 @@ namespace OpenRA.Mods.Common.Traits public readonly ProductionInfo Info; public string Faction { get; private set; } - readonly bool occupiesSpace; - public Production(ActorInitializer init, ProductionInfo info) { Info = info; - occupiesSpace = init.Self.Info.HasTraitInfo(); rp = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault()); Faction = init.Contains() ? init.Get() : init.Self.Owner.Faction.InternalName; } @@ -60,7 +57,7 @@ namespace OpenRA.Mods.Common.Traits new OwnerInit(self.Owner), }; - if (occupiesSpace) + if (self.OccupiesSpace != null) { exit = self.Location + exitinfo.ExitCell; var spawn = self.CenterPosition + exitinfo.SpawnOffset; @@ -122,7 +119,7 @@ namespace OpenRA.Mods.Common.Traits var exit = self.Info.TraitInfos().Shuffle(self.World.SharedRandom) .FirstOrDefault(e => CanUseExit(self, producee, e)); - if (exit != null || !occupiesSpace) + if (exit != null || self.OccupiesSpace == null) { DoProduction(self, producee, exit, factionVariant); return true; diff --git a/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs b/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs index 056d6f83b3..9b1ca95441 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs @@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits { public AmbientSound(Actor self, AmbientSoundInfo info) { - if (self.Info.HasTraitInfo()) + if (self.OccupiesSpace != null) Game.Sound.PlayLooped(info.SoundFile, self.CenterPosition); else Game.Sound.PlayLooped(info.SoundFile);