diff --git a/OpenRA.Mods.Common/Traits/Crushable.cs b/OpenRA.Mods.Common/Traits/Crushable.cs index a1d985a498..80a1751150 100644 --- a/OpenRA.Mods.Common/Traits/Crushable.cs +++ b/OpenRA.Mods.Common/Traits/Crushable.cs @@ -16,7 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("This actor is crushable.")] - class CrushableInfo : ITraitInfo + class CrushableInfo : ConditionalTraitInfo { [Desc("Sound to play when being crushed.")] public readonly string CrushSound = null; @@ -27,18 +27,17 @@ namespace OpenRA.Mods.Common.Traits [Desc("Will friendly units just crush me instead of pathing around.")] public readonly bool CrushedByFriendlies = false; - public object Create(ActorInitializer init) { return new Crushable(init.Self, this); } + public override object Create(ActorInitializer init) { return new Crushable(init.Self, this); } } - class Crushable : ICrushable, INotifyCrushed + class Crushable : ConditionalTrait, ICrushable, INotifyCrushed { readonly Actor self; - readonly CrushableInfo info; public Crushable(Actor self, CrushableInfo info) + : base(info) { this.self = self; - this.info = info; } void INotifyCrushed.WarnCrush(Actor self, Actor crusher, HashSet crushClasses) @@ -47,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits return; var mobile = self.TraitOrDefault(); - if (mobile != null && self.World.SharedRandom.Next(100) <= info.WarnProbability) + if (mobile != null && self.World.SharedRandom.Next(100) <= Info.WarnProbability) mobile.Nudge(self, crusher, true); } @@ -56,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits if (!CrushableInner(crushClasses, crusher.Owner)) return; - Game.Sound.Play(SoundType.World, info.CrushSound, crusher.CenterPosition); + Game.Sound.Play(SoundType.World, Info.CrushSound, crusher.CenterPosition); self.Kill(crusher); } @@ -68,14 +67,17 @@ namespace OpenRA.Mods.Common.Traits bool CrushableInner(HashSet crushClasses, Player crushOwner) { + if (IsTraitDisabled) + return false; + // Only make actor crushable if it is on the ground. if (!self.IsAtGroundLevel()) return false; - if (!info.CrushedByFriendlies && crushOwner.IsAlliedWith(self.Owner)) + if (!Info.CrushedByFriendlies && crushOwner.IsAlliedWith(self.Owner)) return false; - return info.CrushClasses.Overlaps(crushClasses); + return Info.CrushClasses.Overlaps(crushClasses); } } } diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 4f4953a2c2..aca31d326f 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -326,20 +326,11 @@ namespace OpenRA.Mods.Common.Traits // If the other actor in our way cannot be crushed, we are blocked. // PERF: Avoid LINQ. var crushables = otherActor.TraitsImplementing(); - var lacksCrushability = true; foreach (var crushable in crushables) - { - lacksCrushability = false; - if (!crushable.CrushableBy(otherActor, self, Crushes)) - return true; - } + if (crushable.CrushableBy(otherActor, self, Crushes)) + return false; - // If there are no crushable traits at all, this means the other actor cannot be crushed - we are blocked. - if (lacksCrushability) - return true; - - // We are not blocked by the other actor. - return false; + return true; } public WorldMovementInfo GetWorldMovementInfo(World world) @@ -737,10 +728,10 @@ namespace OpenRA.Mods.Common.Traits return false; foreach (var crushes in crushables) - if (!crushes.Trait.CrushableBy(crushes.Actor, self, Info.Crushes)) - return false; + if (crushes.Trait.CrushableBy(crushes.Actor, self, Info.Crushes)) + return true; - return true; + return false; } public int MovementSpeedForCell(Actor self, CPos cell)