diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index e4378cee19..6102305334 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -40,34 +40,38 @@ namespace OpenRA public Group Group; public int Generation; - Lazy bounds; - Lazy visualBounds; - Lazy facing; - Lazy health; - Lazy occupySpace; - Lazy effectiveOwner; - - public Rectangle Bounds { get { return bounds.Value; } } - public Rectangle VisualBounds { get { return visualBounds.Value; } } - public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } } - public IEffectiveOwner EffectiveOwner { get { return effectiveOwner.Value; } } + 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 bool IsIdle { get { return currentActivity == null; } } - public bool IsDead { get { return Disposed || (health.Value == null ? false : health.Value.IsDead); } } + public bool IsDead { get { return Disposed || (health != null && health.IsDead); } } - public CPos Location { get { return occupySpace.Value.TopLeft; } } - public WPos CenterPosition { get { return occupySpace.Value.CenterPosition; } } + public CPos Location { get { return OccupiesSpace.TopLeft; } } + public WPos CenterPosition { get { return OccupiesSpace.CenterPosition; } } public WRot Orientation { get { // TODO: Support non-zero pitch/roll in IFacing (IOrientation?) - var facingValue = facing.Value != null ? facing.Value.Facing : 0; + var facingValue = facing != null ? facing.Facing : 0; return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facingValue)); } } + IOccupySpace occupySpace; + readonly IFacing facing; + readonly Health health; readonly IRenderModifier[] renderModifiers; readonly IRender[] renders; readonly IDisable[] disables; @@ -83,8 +87,6 @@ namespace OpenRA if (initDict.Contains()) Owner = init.Get(); - occupySpace = Exts.Lazy(() => TraitOrDefault()); - if (name != null) { name = name.ToLowerInvariant(); @@ -97,38 +99,11 @@ namespace OpenRA AddTrait(trait.Create(init)); } - facing = Exts.Lazy(() => TraitOrDefault()); - health = Exts.Lazy(() => TraitOrDefault()); - effectiveOwner = Exts.Lazy(() => TraitOrDefault()); - - bounds = Exts.Lazy(() => - { - var si = Info.TraitInfoOrDefault(); - var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : - TraitsImplementing().Select(x => x.SelectionSize(this)).FirstOrDefault(); - - var offset = -size / 2; - if (si != null && si.Bounds != null && si.Bounds.Length > 2) - offset += new int2(si.Bounds[2], si.Bounds[3]); - - return new Rectangle(offset.X, offset.Y, size.X, size.Y); - }); - - visualBounds = Exts.Lazy(() => - { - var sd = Info.TraitInfoOrDefault(); - if (sd == null || sd.SelectionBoxBounds == null) - return bounds.Value; - - var size = new int2(sd.SelectionBoxBounds[0], sd.SelectionBoxBounds[1]); - - var offset = -size / 2; - if (sd.SelectionBoxBounds.Length > 2) - offset += new int2(sd.SelectionBoxBounds[2], sd.SelectionBoxBounds[3]); - - return new Rectangle(offset.X, offset.Y, size.X, size.Y); - }); - + Bounds = DetermineBounds(); + VisualBounds = DetermineVisualBounds(); + EffectiveOwner = TraitOrDefault(); + facing = TraitOrDefault(); + health = TraitOrDefault(); renderModifiers = TraitsImplementing().ToArray(); renders = TraitsImplementing().ToArray(); disables = TraitsImplementing().ToArray(); @@ -136,6 +111,34 @@ namespace OpenRA defaultVisibility = Trait(); } + Rectangle DetermineBounds() + { + var si = Info.TraitInfoOrDefault(); + var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : + TraitsImplementing().Select(x => x.SelectionSize(this)).FirstOrDefault(); + + var offset = -size / 2; + if (si != null && si.Bounds != null && si.Bounds.Length > 2) + offset += new int2(si.Bounds[2], si.Bounds[3]); + + return new Rectangle(offset.X, offset.Y, size.X, size.Y); + } + + Rectangle DetermineVisualBounds() + { + var sd = Info.TraitInfoOrDefault(); + if (sd == null || sd.SelectionBoxBounds == null) + return Bounds; + + var size = new int2(sd.SelectionBoxBounds[0], sd.SelectionBoxBounds[1]); + + var offset = -size / 2; + if (sd.SelectionBoxBounds.Length > 2) + offset += new int2(sd.SelectionBoxBounds[2], sd.SelectionBoxBounds[3]); + + return new Rectangle(offset.X, offset.Y, size.X, size.Y); + } + public void Tick() { var wasIdle = IsIdle; @@ -280,10 +283,10 @@ namespace OpenRA public void Kill(Actor attacker) { - if (health.Value == null) + if (health == null) return; - health.Value.InflictDamage(this, attacker, health.Value.MaxHP, null, true); + health.InflictDamage(this, attacker, health.MaxHP, null, true); } public bool IsDisabled()