diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 06abd3f4c6..d17f859dd7 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -212,14 +212,16 @@ namespace OpenRA World.traitDict.AddTrait( this, trait ); } + public bool Destroyed { get; private set; } + public void Destroy() { - World.AddFrameEndTask( w => World.Remove( this ) ); + World.AddFrameEndTask( w => + { + World.Remove( this ); + World.traitDict.RemoveActor( this ); + Destroyed = true; + } ); } - - ~Actor() - { - World.traitDict.RemoveActor( this ); - } } } diff --git a/OpenRA.Game/TraitDictionary.cs b/OpenRA.Game/TraitDictionary.cs index 3ddaaf8343..1957f2a6a3 100755 --- a/OpenRA.Game/TraitDictionary.cs +++ b/OpenRA.Game/TraitDictionary.cs @@ -47,27 +47,35 @@ namespace OpenRA public bool Contains( Actor actor ) { + if( actor.Destroyed ) + throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) ); return ( (TraitContainer)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID ).Count() != 0; } public T Get( Actor actor ) { + if( actor.Destroyed ) + throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) ); return ( (TraitContainer)InnerGet( typeof( T ) ) ).Get( actor.ActorID ); } public T GetOrDefault( Actor actor ) { + if( actor.Destroyed ) + throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) ); return ( (TraitContainer)InnerGet( typeof( T ) ) ).GetOrDefault( actor.ActorID ); } public IEnumerable WithInterface( Actor actor ) { + if( actor.Destroyed ) + throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) ); return ( (TraitContainer)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID ); } public IEnumerable> ActorsWithTraitMultiple( World world ) { - return ( (TraitContainer)InnerGet( typeof( T ) ) ).All().Where( x => x.Actor.IsInWorld ); + return ( (TraitContainer)InnerGet( typeof( T ) ) ).All();//.Where( x => x.Actor.IsInWorld ); } public void RemoveActor( Actor a ) diff --git a/OpenRA.Game/Traits/Health.cs b/OpenRA.Game/Traits/Health.cs index dda3a2cd08..09fc31428d 100644 --- a/OpenRA.Game/Traits/Health.cs +++ b/OpenRA.Game/Traits/Health.cs @@ -88,20 +88,6 @@ namespace OpenRA.Traits damage = (int)(damage * modifier); hp -= damage; - if (hp <= 0) - { - hp = 0; - - attacker.Owner.Kills++; - self.Owner.Deaths++; - - if (RemoveOnDeath) - self.World.AddFrameEndTask(w => w.Remove(self)); - - Log.Write("debug", "{0} #{1} killed by {2} #{3}", self.Info.Name, self.ActorID, attacker.Info.Name, attacker.ActorID); - } - - if (hp > MaxHP) hp = MaxHP; foreach (var nd in self.TraitsImplementing()) nd.Damaged(self, new AttackInfo @@ -113,6 +99,21 @@ namespace OpenRA.Traits DamageStateChanged = this.DamageState != oldState, Warhead = warhead }); + + if (hp <= 0) + { + hp = 0; + + attacker.Owner.Kills++; + self.Owner.Deaths++; + + if( RemoveOnDeath ) + self.Destroy(); + + Log.Write("debug", "{0} #{1} killed by {2} #{3}", self.Info.Name, self.ActorID, attacker.Info.Name, attacker.ActorID); + } + + if (hp > MaxHP) hp = MaxHP; } } diff --git a/OpenRA.Game/Traits/World/SpatialBins.cs b/OpenRA.Game/Traits/World/SpatialBins.cs index ddaa22299e..33cb890f63 100644 --- a/OpenRA.Game/Traits/World/SpatialBins.cs +++ b/OpenRA.Game/Traits/World/SpatialBins.cs @@ -79,7 +79,7 @@ namespace OpenRA.Traits return ActorsInBins(a.X / scale, b.X / scale, a.Y / scale, b.Y / scale) .Distinct() - .Where(u => u.GetBounds(true).IntersectsWith(r)); + .Where(u => u.IsInWorld && u.GetBounds(true).IntersectsWith(r)); } } }