diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index 599ac7d95b..7bb15d84e6 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -441,28 +441,34 @@ namespace OpenRA.Mods.RA.AI return target; } - internal Actor FindClosestEnemy(WPos pos) + bool IsValidTarget(Actor a, Actor targeter) { - var allEnemyUnits = world.Actors - .Where(unit => p.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait() && - unit.HasTrait()).ToList(); + if (p.Stances[a.Owner] != Stance.Enemy) + return false; - if (allEnemyUnits.Count > 0) - return allEnemyUnits.ClosestTo(pos); + // TODO: We shouldn't need to check this explicitly + if (!a.HasTrait()) + return false; - return null; + var targetable = a.TraitOrDefault(); + if (targetable == null || !targetable.TargetableBy(a, targeter)) + return false; + + return true; } - internal Actor FindClosestEnemy(WPos pos, WRange radius) + internal Actor FindClosestEnemy(Actor targeter, WPos pos) { - var enemyUnits = world.FindActorsInCircle(pos, radius) - .Where(unit => p.Stances[unit.Owner] == Stance.Enemy && - !unit.HasTrait() && unit.HasTrait()).ToList(); + return world.Actors + .Where(unit => IsValidTarget(unit, targeter)) + .ClosestTo(pos); + } - if (enemyUnits.Count > 0) - return enemyUnits.ClosestTo(pos); - - return null; + internal Actor FindClosestEnemy(Actor targeter, WPos pos, WRange radius) + { + return world.FindActorsInCircle(pos, radius) + .Where(unit => IsValidTarget(unit, targeter)) + .ClosestTo(pos); } List FindEnemyConstructionYards() diff --git a/OpenRA.Mods.RA/AI/States/AirStates.cs b/OpenRA.Mods.RA/AI/States/AirStates.cs index 99d7a7dcb1..24449d50cc 100644 --- a/OpenRA.Mods.RA/AI/States/AirStates.cs +++ b/OpenRA.Mods.RA/AI/States/AirStates.cs @@ -183,8 +183,8 @@ namespace OpenRA.Mods.RA.AI if (!owner.TargetIsValid) { - var a = owner.units.Random(owner.random); - var closestEnemy = owner.bot.FindClosestEnemy(a.CenterPosition); + var targeter = owner.units.Random(owner.random); + var closestEnemy = owner.bot.FindClosestEnemy(targeter, targeter.CenterPosition); if (closestEnemy != null) owner.Target = closestEnemy; else diff --git a/OpenRA.Mods.RA/AI/States/GroundStates.cs b/OpenRA.Mods.RA/AI/States/GroundStates.cs index 1846c9758b..aee6455ecb 100644 --- a/OpenRA.Mods.RA/AI/States/GroundStates.cs +++ b/OpenRA.Mods.RA/AI/States/GroundStates.cs @@ -33,8 +33,11 @@ namespace OpenRA.Mods.RA.AI if (!owner.TargetIsValid) { - var t = owner.bot.FindClosestEnemy(owner.units.FirstOrDefault().CenterPosition); - if (t == null) return; + var targeter = owner.units.First(); + var t = owner.bot.FindClosestEnemy(targeter, targeter.CenterPosition); + if (t == null) + return; + owner.Target = t; } @@ -71,7 +74,8 @@ namespace OpenRA.Mods.RA.AI if (!owner.TargetIsValid) { - var closestEnemy = owner.bot.FindClosestEnemy(owner.units.Random(owner.random).CenterPosition); + var targeter = owner.units.Random(owner.random); + var closestEnemy = owner.bot.FindClosestEnemy(targeter, targeter.CenterPosition); if (closestEnemy != null) owner.Target = closestEnemy; else @@ -129,7 +133,8 @@ namespace OpenRA.Mods.RA.AI if (!owner.TargetIsValid) { - var closestEnemy = owner.bot.FindClosestEnemy(owner.units.Random(owner.random).CenterPosition); + var targeter = owner.units.Random(owner.random); + var closestEnemy = owner.bot.FindClosestEnemy(targeter, targeter.CenterPosition); if (closestEnemy != null) owner.Target = closestEnemy; else @@ -141,7 +146,7 @@ namespace OpenRA.Mods.RA.AI foreach (var a in owner.units) if (!BusyAttack(a)) - owner.world.IssueOrder(new Order("Attack", a, false) { TargetActor = owner.bot.FindClosestEnemy(a.CenterPosition) }); + owner.world.IssueOrder(new Order("Attack", a, false) { TargetActor = owner.bot.FindClosestEnemy(a, a.CenterPosition) }); if (ShouldFlee(owner)) { diff --git a/OpenRA.Mods.RA/AI/States/ProtectionStates.cs b/OpenRA.Mods.RA/AI/States/ProtectionStates.cs index ff40ec8219..d473457e7f 100644 --- a/OpenRA.Mods.RA/AI/States/ProtectionStates.cs +++ b/OpenRA.Mods.RA/AI/States/ProtectionStates.cs @@ -32,7 +32,8 @@ namespace OpenRA.Mods.RA.AI if (!owner.TargetIsValid) { - owner.Target = owner.bot.FindClosestEnemy(owner.CenterPosition, WRange.FromCells(8)); + var targeter = owner.units.FirstOrDefault(); + owner.Target = owner.bot.FindClosestEnemy(targeter, owner.CenterPosition, WRange.FromCells(8)); if (owner.Target == null) {