diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index 28c5346768..4fcb2bee83 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -260,6 +260,25 @@ namespace OpenRA.Mods.RA.AI else assignRolesTicks = Info.AssignRolesInterval; + // Find idle harvesters and give them orders: + foreach (var a in activeUnits) + { + var harv = a.TraitOrDefault(); + if (harv == null) continue; + if (!a.IsIdle) + { + Activity act = a.GetCurrentActivity(); + // A Wait activity is technically idle: + if ((act.GetType() != typeof(OpenRA.Mods.RA.Activities.Wait)) && + (act.NextActivity == null || act.NextActivity.GetType() != typeof(OpenRA.Mods.RA.Activities.FindResources))) + continue; + } + if (!harv.IsEmpty) continue; + + // Tell the idle harvester to quit slacking: + world.IssueOrder(new Order("Harvest", a, false)); + } + var newUnits = self.World.ActorsWithTrait() .Where(a => a.Actor.Owner == p && !a.Actor.HasTrait() && !activeUnits.Contains(a.Actor)) @@ -275,12 +294,12 @@ namespace OpenRA.Mods.RA.AI activeUnits.Add(a); } - + /* Create an attack force when we have enough units around our base. */ // (don't bother leaving any behind for defense.) int randomizedSquadSize = Info.SquadSize - 4 + random.Next(200); - + if (unitsHangingAroundTheBase.Count >= randomizedSquadSize) { BotDebug("Launch an attack."); @@ -426,7 +445,7 @@ namespace OpenRA.Mods.RA.AI world.IssueOrder(new Order("DeployTransform", mcv, false)); } else - BotDebug("AI: Can't find BaseBuildUnit."); + BotDebug("AI: Can't find BaseBuildUnit."); } internal IEnumerable FindQueues(string category) diff --git a/OpenRA.Mods.RA/Activities/FindResources.cs b/OpenRA.Mods.RA/Activities/FindResources.cs index 8702f44a35..f8101db3c6 100755 --- a/OpenRA.Mods.RA/Activities/FindResources.cs +++ b/OpenRA.Mods.RA/Activities/FindResources.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Activities { public class FindResources : Activity { - CPos avoidCell; + CPos? avoidCell; public FindResources() { @@ -64,7 +64,8 @@ namespace OpenRA.Mods.RA.Activities }) .WithHeuristic(loc => { - if (loc == avoidCell) return 1; + // Avoid this cell: + if (avoidCell.HasValue && loc == avoidCell.Value) return 1; // Don't harvest out of range: int distSquared = (loc - (harv.LastOrderLocation ?? harv.LinkedProc.Location)).LengthSquared; diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index a1aa65a180..2641bba766 100644 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -268,6 +268,20 @@ namespace OpenRA.Mods.RA LastOrderLocation = loc; } + else + { + // A bot order gives us a CPos.Zero TargetLocation, so find some good resources for him: + CPos? loc = FindNextResourceForBot(self); + // No more resources? Oh well. + if (!loc.HasValue) + return; + + self.QueueActivity(mobile.MoveTo(loc.Value, 0)); + self.SetTargetLine(Target.FromCell(loc.Value), Color.Red); + + LastOrderLocation = loc; + } + self.QueueActivity(new FindResources()); } else if (order.OrderString == "Deliver") @@ -290,6 +304,42 @@ namespace OpenRA.Mods.RA } } + CPos? FindNextResourceForBot(Actor self) + { + // NOTE: This is only used for the AI to find the next available resource to harvest. + var harvInfo = self.Info.Traits.Get(); + var mobile = self.Trait(); + var mobileInfo = self.Info.Traits.Get(); + var resLayer = self.World.WorldActor.Trait(); + var territory = self.World.WorldActor.Trait(); + + // Find any harvestable resources: + var path = self.World.WorldActor.Trait().FindPath( + PathSearch.Search(self.World, mobileInfo, self.Owner, true) + .WithHeuristic(loc => + { + // Get the resource at this location: + var resType = resLayer.GetResource(loc); + + if (resType == null) return 1; + // Can the harvester collect this kind of resource? + if (!harvInfo.Resources.Contains(resType.info.Name)) return 1; + + // Another harvester has claimed this resource: + ResourceClaim claim; + if (territory.IsClaimedByAnyoneElse(self, loc, out claim)) return 1; + + return 0; + }) + .FromPoint(self.Location) + ); + + if (path.Count == 0) + return (CPos?)null; + + return path[0]; + } + public void OnNotifyResourceClaimLost(Actor self, ResourceClaim claim, Actor claimer) { if (self == claimer) return;