diff --git a/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs b/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs index 61f58b8d2d..32fbee25e7 100644 --- a/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs @@ -26,21 +26,35 @@ namespace OpenRA.Mods.Common.Orders return OrderInner(world, mi); } - IEnumerable OrderInner(World world, MouseInput mi) + static IEnumerable OrderInner(World world, MouseInput mi) { - if (mi.Button == MouseButton.Left) - { - var underCursor = world.ScreenMap.ActorsAt(mi) - .FirstOrDefault(a => !world.FogObscures(a) && a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) - && a.TraitsImplementing().Any(t => !t.IsTraitDisabled)); + if (mi.Button != MouseButton.Left) + yield break; - if (underCursor == null) - yield break; + var underCursor = world.ScreenMap.ActorsAt(mi) + .FirstOrDefault(a => a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && !world.FogObscures(a)); - if (underCursor.Info.Traits.Contains() - && underCursor.GetDamageState() > DamageState.Undamaged) - yield return new Order("RepairBuilding", world.LocalPlayer.PlayerActor, false) { TargetActor = underCursor }; - } + if (underCursor == null) + yield break; + + if (underCursor.GetDamageState() == DamageState.Undamaged) + yield break; + + // Repair a building. + if (underCursor.Info.Traits.Contains()) + yield return new Order("RepairBuilding", world.LocalPlayer.PlayerActor, false) { TargetActor = underCursor }; + + // Test for generic Repairable (used on units). + var repairable = underCursor.TraitOrDefault(); + if (repairable == null) + yield break; + + // Find a building to repair at. + var repairBuilding = repairable.FindRepairBuilding(underCursor); + if (repairBuilding == null) + yield break; + + yield return new Order("Repair", underCursor, false) { TargetActor = repairBuilding }; } public void Tick(World world) diff --git a/OpenRA.Mods.Common/Traits/Repairable.cs b/OpenRA.Mods.Common/Traits/Repairable.cs index b275311bfa..4f6cfb54e2 100644 --- a/OpenRA.Mods.Common/Traits/Repairable.cs +++ b/OpenRA.Mods.Common/Traits/Repairable.cs @@ -108,5 +108,17 @@ namespace OpenRA.Mods.Common.Traits })); } } + + public Actor FindRepairBuilding(Actor self) + { + var repairBuilding = self.World.ActorsWithTrait() + .Where(a => !a.Actor.IsDead && a.Actor.IsInWorld + && a.Actor.Owner == self.Owner && + info.RepairBuildings.Contains(a.Actor.Info.Name)) + .OrderBy(p => (self.Location - p.Actor.Location).LengthSquared); + + // Worst case FirstOrDefault() will return a TraitPair, which is OK. + return repairBuilding.FirstOrDefault().Actor; + } } }