From 68ad9163ffd2e0c1d6b80b332564bf92b7b5b6cb Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Mon, 2 Dec 2024 20:26:32 +0000 Subject: [PATCH] Fix BaseBuilderBotModule.LocomotorsForProducibles. Account for per-actor production (e.g. ProductionQueue) and per-player production (e.g. ClassicProductionQueue). This requires resolving the Production and ProductionQueue traits on both the producing actor, and the owning player actor. When setting rally points, check the actor didn't die first. --- .../Traits/BotModules/BaseBuilderBotModule.cs | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs b/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs index 81b827e0f5..8f35138d52 100644 --- a/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs +++ b/OpenRA.Mods.Common/Traits/BotModules/BaseBuilderBotModule.cs @@ -240,7 +240,7 @@ namespace OpenRA.Mods.Common.Traits for (var i = 0; i < updateCount; i++) { var rp = rallyPoints.Pop(); - if (rp.Actor.Owner == player) + if (rp.Actor.Owner == player && !rp.Actor.Disposed) SetRallyPoint(bot, rp); } } @@ -343,23 +343,37 @@ namespace OpenRA.Mods.Common.Traits Locomotor[] LocomotorsForProducibles(Actor producer) { - var buildingInfo = producer.Info.TraitInfoOrDefault(); - var productionInfo = producer.Info.TraitInfoOrDefault(); - var locomotors = Array.Empty(); + // Per-actor production + var productions = producer.TraitsImplementing(); - if (productionInfo != null && productionInfo.Produces.Length > 0) + // Player-wide production + if (!productions.Any()) + productions = producer.World.ActorsWithTrait().Where(x => x.Actor.Owner != producer.Owner).Select(x => x.Trait); + + var produces = productions.SelectMany(p => p.Info.Produces).ToHashSet(); + var locomotors = Array.Empty(); + if (produces.Count > 0) { - var productionQueues = producer.Owner.PlayerActor.TraitsImplementing() - .Where(pq => productionInfo.Produces.Contains(pq.Info.Type)); + // Per-actor production + var productionQueues = producer.TraitsImplementing(); + + // Player-wide production + if (!productionQueues.Any()) + productionQueues = producer.Owner.PlayerActor.TraitsImplementing(); + + productionQueues = productionQueues.Where(pq => produces.Contains(pq.Info.Type)); + var producibles = productionQueues.SelectMany(pq => pq.BuildableItems()); var locomotorNames = producibles .Select(p => p.TraitInfoOrDefault()) .Where(mi => mi != null) .Select(mi => mi.Locomotor) .ToHashSet(); - locomotors = world.WorldActor.TraitsImplementing() - .Where(l => locomotorNames.Contains(l.Info.Name)) - .ToArray(); + + if (locomotorNames.Count != 0) + locomotors = world.WorldActor.TraitsImplementing() + .Where(l => locomotorNames.Contains(l.Info.Name)) + .ToArray(); } return locomotors;