diff --git a/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs b/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs index 992ac6373a..0f00e48af4 100644 --- a/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs +++ b/OpenRA.Mods.Common/Traits/Infantry/ScaredyCat.cs @@ -9,6 +9,8 @@ */ #endregion +using System; +using System.Collections.Generic; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -28,6 +30,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Chance (out of 100) the unit has to enter panic mode when attacking.")] public readonly int AttackPanicChance = 20; + [Desc("The terrain types that this actor should avoid running on to while panicking.")] + public readonly HashSet AvoidTerrainTypes = new HashSet(); + [SequenceReference(prefix: true)] public readonly string PanicSequencePrefix = "panic-"; @@ -39,6 +44,7 @@ namespace OpenRA.Mods.Common.Traits readonly ScaredyCatInfo info; readonly Mobile mobile; readonly Actor self; + readonly Func avoidTerrainFilter; [Sync] int panicStartedTick; @@ -52,6 +58,9 @@ namespace OpenRA.Mods.Common.Traits this.self = self; this.info = info; mobile = self.Trait(); + + if (info.AvoidTerrainTypes.Count > 0) + avoidTerrainFilter = c => info.AvoidTerrainTypes.Contains(self.World.Map.GetTerrainInfo(c).Type); } public void Panic() @@ -79,7 +88,10 @@ namespace OpenRA.Mods.Common.Traits if (!Panicking) return; - mobile.Nudge(self); + // Note: This is just a modified copy of Mobile.Nudge + var cell = mobile.GetAdjacentCell(self.Location, avoidTerrainFilter); + if (cell != null) + self.QueueActivity(false, mobile.MoveTo(cell.Value, 0)); } void INotifyDamage.Damaged(Actor self, AttackInfo e) diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index bc5e500c6f..b40428128b 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -364,14 +364,14 @@ namespace OpenRA.Mods.Common.Traits self.QueueActivity(false, MoveTo(cell.Value, 0)); } - public CPos? GetAdjacentCell(CPos nextCell) + public CPos? GetAdjacentCell(CPos nextCell, Func preferToAvoid = null) { var availCells = new List(); var notStupidCells = new List(); foreach (CVec direction in CVec.Directions) { var p = ToCell + direction; - if (CanEnterCell(p) && CanStayInCell(p)) + if (CanEnterCell(p) && CanStayInCell(p) && (preferToAvoid == null || !preferToAvoid(p))) availCells.Add(p); else if (p != nextCell && p != ToCell) notStupidCells.Add(p);