Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions OpenRA.Mods.CA/Traits/BotModules/BaseBuilderBotModuleCA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ public class BaseBuilderBotModuleCAInfo : ConditionalTraitInfo
[Desc("Radius in cells around building being considered for sale to scan for units")]
public readonly int SellScanRadius = 8;

[Desc("Delay (in ticks) between finding a good resource point to harvest.")]
public readonly int CheckBestResourceLocationInterval = 123;

public override object Create(ActorInitializer init) { return new BaseBuilderBotModuleCA(init.Self, this); }
}

Expand Down Expand Up @@ -192,9 +195,11 @@ public CPos GetRandomBaseCenter()
IPathFinder pathFinder;
IBotPositionsUpdated[] positionsUpdatedModules;
CPos initialBaseCenter;
public CPos? ResourceCenter;

readonly Stack<TraitPair<RallyPoint>> rallyPoints = new();
int assignRallyPointsTicks;
int checkBestResourceLocationTicks;

readonly BaseBuilderQueueManagerCA[] builders; // CA: Uses CA queue manager instead of engine version
int currentBuilderIndex = 0;
Expand Down Expand Up @@ -231,6 +236,7 @@ protected override void TraitEnabled(Actor self)
{
// Avoid all AIs reevaluating assignments on the same tick, randomize their initial evaluation delay.
assignRallyPointsTicks = world.LocalRandom.Next(0, Info.AssignRallyPointsInterval);
checkBestResourceLocationTicks = world.LocalRandom.Next(0, Info.CheckBestResourceLocationInterval);

var i = 0;

Expand Down Expand Up @@ -281,6 +287,31 @@ void IBotTick.BotTick(IBot bot)
}
}

if (--checkBestResourceLocationTicks <= 0 && resourceLayer != null)
{
checkBestResourceLocationTicks = Info.CheckBestResourceLocationInterval;

Actor bestconyard = null;
var best = int.MinValue;

foreach (var conyard in constructionYardBuildings.Actors.Where(a => !a.IsDead))
{
if (!world.Map.FindTilesInAnnulus(conyard.Location, Info.MinBaseRadius, Info.MaxBaseRadius).Any(a => resourceLayer.GetResource(a).Type != null))
continue;

var suitable = -world.FindActorsInCircle(conyard.CenterPosition, WDist.FromCells(Info.MaxBaseRadius))
.Count(a => (a.Owner.IsAlliedWith(player) && Info.RefineryTypes.Contains(a.Info.Name)) || a.Owner.RelationshipWith(player) == PlayerRelationship.Enemy);

if (suitable > best)
{
best = suitable;
bestconyard = conyard;
}
}

ResourceCenter = bestconyard?.Location;
}

BuildingsBeingProduced.Clear();

// PERF: We tick only one type of valid queue at a time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,13 +526,16 @@ ActorInfo ChooseBuildingToBuild(ProductionQueue queue)
// Try and place the refinery near a resource field
if (resourceLayer != null)
{
var nearbyResources = world.Map.FindTilesInAnnulus(baseCenter, baseBuilder.Info.MinBaseRadius, baseBuilder.Info.MaxBaseRadius)
// If we have failed to place to the best refinery point, try and place it near the base center
var resourceCenter = failCount > 0 ? baseCenter : (baseBuilder.ResourceCenter ?? baseCenter);

var nearbyResources = world.Map.FindTilesInAnnulus(resourceCenter, baseBuilder.Info.MinBaseRadius, baseBuilder.Info.MaxBaseRadius)
.Where(a => resourceLayer.GetResource(a).Type != null)
.Shuffle(world.LocalRandom).Take(baseBuilder.Info.MaxResourceCellsToCheck);

foreach (var r in nearbyResources)
{
var found = findPos(baseCenter, r, baseBuilder.Info.MinBaseRadius, baseBuilder.Info.MaxBaseRadius);
var found = findPos(resourceCenter, r, baseBuilder.Info.MinBaseRadius, baseBuilder.Info.MaxBaseRadius);
if (found != null)
return found;
}
Expand Down
Loading