From 7f677f1842bf5f11b209959cb781032783eaa1a1 Mon Sep 17 00:00:00 2001 From: Gustas <37534529+PunkPun@users.noreply.github.com> Date: Thu, 29 Sep 2022 19:27:06 +0300 Subject: [PATCH] Allow driving under crates and crushable units --- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 41 ++++++++--------------- OpenRA.Mods.Common/Traits/Crates/Crate.cs | 8 ++--- OpenRA.Mods.Common/Traits/Crushable.cs | 6 +--- OpenRA.Mods.Common/Traits/Mobile.cs | 37 +++++++------------- 4 files changed, 30 insertions(+), 62 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index c39b4d11ee..ba4b6823c5 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -830,41 +830,28 @@ namespace OpenRA.Mods.Common.Traits public void FinishedMoving(Actor self) { - // Only make actor crush if it is on the ground + // Only crush actors on having landed if (!self.IsAtGroundLevel()) return; - var actors = self.World.ActorMap.GetActorsAt(TopLeft).Where(a => a != self).ToList(); - if (!AnyCrushables(actors)) - return; - - var notifiers = actors.SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))); - foreach (var notifyCrushed in notifiers) - notifyCrushed.Trait.OnCrush(notifyCrushed.Actor, self, Info.Crushes); - } - - bool AnyCrushables(List actors) - { - var crushables = actors.SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))).ToList(); - if (crushables.Count == 0) - return false; - - foreach (var crushes in crushables) - if (crushes.Trait.CrushableBy(crushes.Actor, self, Info.Crushes)) - return true; - - return false; + CrushAction(self, (notifyCrushed) => notifyCrushed.OnCrush); } public void EnteringCell(Actor self) { - var actors = self.World.ActorMap.GetActorsAt(TopLeft).Where(a => a != self).ToList(); - if (!AnyCrushables(actors)) - return; + CrushAction(self, (notifyCrushed) => notifyCrushed.WarnCrush); + } - var notifiers = actors.SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))); - foreach (var notifyCrushed in notifiers) - notifyCrushed.Trait.WarnCrush(notifyCrushed.Actor, self, Info.Crushes); + void CrushAction(Actor self, Func>> action) + { + var crushables = self.World.ActorMap.GetActorsAt(TopLeft).Where(a => a != self) + .SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))); + + // Only crush actors that are on the ground level + foreach (var crushable in crushables) + if (crushable.Trait.CrushableBy(crushable.Actor, self, Info.Crushes) && crushable.Actor.IsAtGroundLevel()) + foreach (var notifyCrushed in crushable.Actor.TraitsImplementing()) + action(notifyCrushed)(crushable.Actor, self, Info.Crushes); } public void AddInfluence(IEnumerable landingCells) diff --git a/OpenRA.Mods.Common/Traits/Crates/Crate.cs b/OpenRA.Mods.Common/Traits/Crates/Crate.cs index e591880566..6b9969d0a1 100644 --- a/OpenRA.Mods.Common/Traits/Crates/Crate.cs +++ b/OpenRA.Mods.Common/Traits/Crates/Crate.cs @@ -103,8 +103,7 @@ namespace OpenRA.Mods.Common.Traits void INotifyCrushed.OnCrush(Actor self, Actor crusher, BitSet crushClasses) { - // Crate can only be crushed if it is not in the air. - if (!self.IsAtGroundLevel() || !crushClasses.Contains(info.CrushClass)) + if (!crushClasses.Contains(info.CrushClass)) return; OnCrushInner(crusher); @@ -231,13 +230,12 @@ namespace OpenRA.Mods.Common.Traits bool ICrushable.CrushableBy(Actor self, Actor crusher, BitSet crushClasses) { - // Crate can only be crushed if it is not in the air. - return self.IsAtGroundLevel() && crushClasses.Contains(info.CrushClass); + return crushClasses.Contains(info.CrushClass); } LongBitSet ICrushable.CrushableBy(Actor self, BitSet crushClasses) { - return self.IsAtGroundLevel() && crushClasses.Contains(info.CrushClass) ? self.World.AllPlayersMask : self.World.NoPlayersMask; + return crushClasses.Contains(info.CrushClass) ? self.World.AllPlayersMask : self.World.NoPlayersMask; } void INotifyAddedToWorld.AddedToWorld(Actor self) diff --git a/OpenRA.Mods.Common/Traits/Crushable.cs b/OpenRA.Mods.Common/Traits/Crushable.cs index d1cbb5bc98..315d8792ce 100644 --- a/OpenRA.Mods.Common/Traits/Crushable.cs +++ b/OpenRA.Mods.Common/Traits/Crushable.cs @@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Traits LongBitSet ICrushable.CrushableBy(Actor self, BitSet crushClasses) { - if (IsTraitDisabled || !self.IsAtGroundLevel() || !Info.CrushClasses.Overlaps(crushClasses)) + if (IsTraitDisabled || !Info.CrushClasses.Overlaps(crushClasses)) return self.World.NoPlayersMask; return Info.CrushedByFriendlies ? self.World.AllPlayersMask : self.World.AllPlayersMask.Except(self.Owner.AlliedPlayersMask); @@ -78,10 +78,6 @@ namespace OpenRA.Mods.Common.Traits 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)) return false; diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index f776b1703a..74d8ed61d7 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -567,30 +567,23 @@ namespace OpenRA.Mods.Common.Traits foreach (var n in notifyFinishedMoving) n.FinishedMoving(self, fromCell.Layer, toCell.Layer); - // Only make actor crush if it is on the ground + // Only crush actors on having landed if (!self.IsAtGroundLevel()) return; - var actors = self.World.ActorMap.GetActorsAt(ToCell, ToSubCell).Where(a => a != self).ToList(); - if (!AnyCrushables(actors)) - return; - - var notifiers = actors.SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))); - foreach (var notifyCrushed in notifiers) - notifyCrushed.Trait.OnCrush(notifyCrushed.Actor, self, Info.LocomotorInfo.Crushes); + CrushAction(self, (notifyCrushed) => notifyCrushed.OnCrush); } - bool AnyCrushables(List actors) + void CrushAction(Actor self, Func>> action) { - var crushables = actors.SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))).ToList(); - if (crushables.Count == 0) - return false; + var crushables = self.World.ActorMap.GetActorsAt(ToCell, ToSubCell).Where(a => a != self) + .SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))); - foreach (var crushes in crushables) - if (crushes.Trait.CrushableBy(crushes.Actor, self, Info.LocomotorInfo.Crushes)) - return true; - - return false; + // Only crush actors that are on the ground level + foreach (var crushable in crushables) + if (crushable.Trait.CrushableBy(crushable.Actor, self, Info.LocomotorInfo.Crushes) && crushable.Actor.IsAtGroundLevel()) + foreach (var notifyCrushed in crushable.Actor.TraitsImplementing()) + action(notifyCrushed)(crushable.Actor, self, Info.LocomotorInfo.Crushes); } public void AddInfluence() @@ -792,17 +785,11 @@ namespace OpenRA.Mods.Common.Traits public void EnteringCell(Actor self) { - // Only make actor crush if it is on the ground + // Only crush actors on having landed if (!self.IsAtGroundLevel()) return; - var actors = self.World.ActorMap.GetActorsAt(ToCell).Where(a => a != self).ToList(); - if (!AnyCrushables(actors)) - return; - - var notifiers = actors.SelectMany(a => a.TraitsImplementing().Select(t => new TraitPair(a, t))); - foreach (var notifyCrushed in notifiers) - notifyCrushed.Trait.WarnCrush(notifyCrushed.Actor, self, Info.LocomotorInfo.Crushes); + CrushAction(self, (notifyCrushed) => notifyCrushed.WarnCrush); } public Activity MoveTo(Func> pathFunc) { return new Move(self, pathFunc); }