Sanitize harvester search behavior.

This commit is contained in:
tovl
2019-03-14 23:45:22 +01:00
committed by reaperrr
parent 8d8cade266
commit 1d590ac207
2 changed files with 41 additions and 49 deletions

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Activities
readonly IPathFinder pathFinder; readonly IPathFinder pathFinder;
readonly DomainIndex domainIndex; readonly DomainIndex domainIndex;
CPos? avoidCell; CPos? orderLocation;
public FindResources(Actor self) public FindResources(Actor self)
{ {
@@ -41,10 +41,18 @@ namespace OpenRA.Mods.Common.Activities
domainIndex = self.World.WorldActor.Trait<DomainIndex>(); domainIndex = self.World.WorldActor.Trait<DomainIndex>();
} }
public FindResources(Actor self, CPos avoidCell) public FindResources(Actor self, CPos orderLocation)
: this(self) : this(self)
{ {
this.avoidCell = avoidCell; this.orderLocation = orderLocation;
}
protected override void OnFirstRun(Actor self)
{
// Without this, multiple "Harvest" orders queued directly after each other
// will be skipped because the harvester starts off full.
if (harv.IsFull)
QueueChild(self, new DeliverResources(self));
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
@@ -59,7 +67,17 @@ namespace OpenRA.Mods.Common.Activities
return NextActivity; return NextActivity;
if (harv.IsFull) if (harv.IsFull)
{
return NextActivity; return NextActivity;
}
// If an explicit order is given, direct the harvester to the ordered location instead of the previous
// harvested cell for the initial search.
if (orderLocation != null)
{
harv.LastHarvestedCell = orderLocation;
orderLocation = null;
}
var closestHarvestablePosition = ClosestHarvestablePos(self); var closestHarvestablePosition = ClosestHarvestablePos(self);
@@ -67,7 +85,13 @@ namespace OpenRA.Mods.Common.Activities
// or get out of the way and do not disturb. // or get out of the way and do not disturb.
if (!closestHarvestablePosition.HasValue) if (!closestHarvestablePosition.HasValue)
{ {
// If no resources are found near the current field, search near the refinery instead.
// If that doesn't help, give up for now.
if (harv.LastHarvestedCell != null)
harv.LastHarvestedCell = null;
else
harv.LastSearchFailed = true; harv.LastSearchFailed = true;
var lastproc = harv.LastLinkedProc ?? harv.LinkedProc; var lastproc = harv.LastLinkedProc ?? harv.LinkedProc;
if (lastproc != null && !lastproc.Disposed) if (lastproc != null && !lastproc.Disposed)
{ {
@@ -95,10 +119,6 @@ namespace OpenRA.Mods.Common.Activities
harv.LastSearchFailed = false; harv.LastSearchFailed = false;
// If not given a direct order, assume ordered to the first resource location we find:
if (!harv.LastOrderLocation.HasValue)
harv.LastOrderLocation = closestHarvestablePosition;
foreach (var n in self.TraitsImplementing<INotifyHarvesterAction>()) foreach (var n in self.TraitsImplementing<INotifyHarvesterAction>())
n.MovingToResources(self, closestHarvestablePosition.Value, new FindResources(self)); n.MovingToResources(self, closestHarvestablePosition.Value, new FindResources(self));
@@ -118,8 +138,8 @@ namespace OpenRA.Mods.Common.Activities
return self.Location; return self.Location;
// Determine where to search from and how far to search: // Determine where to search from and how far to search:
var searchFromLoc = GetSearchFromLocation(self); var searchFromLoc = harv.LastHarvestedCell ?? GetSearchFromLocation(self);
var searchRadius = harv.LastOrderLocation.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius; var searchRadius = harv.LastHarvestedCell.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius;
var searchRadiusSquared = searchRadius * searchRadius; var searchRadiusSquared = searchRadius * searchRadius;
// Find any harvestable resources: // Find any harvestable resources:
@@ -128,14 +148,13 @@ namespace OpenRA.Mods.Common.Activities
domainIndex.IsPassable(self.Location, loc, locomotorInfo) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc)) domainIndex.IsPassable(self.Location, loc, locomotorInfo) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc))
.WithCustomCost(loc => .WithCustomCost(loc =>
{ {
if ((avoidCell.HasValue && loc == avoidCell.Value) || if ((loc - searchFromLoc).LengthSquared > searchRadiusSquared)
(loc - self.Location).LengthSquared > searchRadiusSquared)
return int.MaxValue; return int.MaxValue;
return 0; return 0;
}) })
.FromPoint(self.Location) .FromPoint(searchFromLoc)
.FromPoint(searchFromLoc)) .FromPoint(self.Location))
path = pathFinder.FindPath(search); path = pathFinder.FindPath(search);
if (path.Count > 0) if (path.Count > 0)
@@ -151,12 +170,12 @@ namespace OpenRA.Mods.Common.Activities
CPos GetSearchFromLocation(Actor self) CPos GetSearchFromLocation(Actor self)
{ {
if (harv.LastOrderLocation.HasValue) if (harv.LastLinkedProc != null)
return harv.LastOrderLocation.Value;
else if (harv.LastLinkedProc != null)
return harv.LastLinkedProc.Location + harv.LastLinkedProc.Trait<IAcceptResources>().DeliveryOffset; return harv.LastLinkedProc.Location + harv.LastLinkedProc.Trait<IAcceptResources>().DeliveryOffset;
else if (harv.LinkedProc != null)
if (harv.LinkedProc != null)
return harv.LinkedProc.Location + harv.LinkedProc.Trait<IAcceptResources>().DeliveryOffset; return harv.LinkedProc.Location + harv.LinkedProc.Trait<IAcceptResources>().DeliveryOffset;
return self.Location; return self.Location;
} }
} }

View File

@@ -82,14 +82,14 @@ namespace OpenRA.Mods.Common.Traits
} }
public class Harvester : IIssueOrder, IResolveOrder, IPips, IOrderVoice, public class Harvester : IIssueOrder, IResolveOrder, IPips, IOrderVoice,
ISpeedModifier, ISync, INotifyCreated, INotifyIdle, INotifyBlockingMove ISpeedModifier, ISync, INotifyCreated, INotifyIdle
{ {
public readonly HarvesterInfo Info; public readonly HarvesterInfo Info;
readonly Mobile mobile; readonly Mobile mobile;
readonly ResourceLayer resLayer; readonly ResourceLayer resLayer;
readonly ResourceClaimLayer claimLayer; readonly ResourceClaimLayer claimLayer;
readonly Dictionary<ResourceTypeInfo, int> contents = new Dictionary<ResourceTypeInfo, int>(); readonly Dictionary<ResourceTypeInfo, int> contents = new Dictionary<ResourceTypeInfo, int>();
bool idleSmart = false; bool idleSmart;
INotifyHarvesterAction[] notifyHarvesterAction; INotifyHarvesterAction[] notifyHarvesterAction;
ConditionManager conditionManager; ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken; int conditionToken = ConditionManager.InvalidConditionToken;
@@ -101,7 +101,6 @@ namespace OpenRA.Mods.Common.Traits
[Sync] public Actor LinkedProc = null; [Sync] public Actor LinkedProc = null;
[Sync] int currentUnloadTicks; [Sync] int currentUnloadTicks;
public CPos? LastHarvestedCell = null; public CPos? LastHarvestedCell = null;
public CPos? LastOrderLocation = null;
[Sync] [Sync]
public int ContentValue public int ContentValue
@@ -121,6 +120,7 @@ namespace OpenRA.Mods.Common.Traits
mobile = self.Trait<Mobile>(); mobile = self.Trait<Mobile>();
resLayer = self.World.WorldActor.Trait<ResourceLayer>(); resLayer = self.World.WorldActor.Trait<ResourceLayer>();
claimLayer = self.World.WorldActor.Trait<ResourceClaimLayer>(); claimLayer = self.World.WorldActor.Trait<ResourceClaimLayer>();
idleSmart = info.SearchOnCreation;
self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null))); self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null)));
} }
@@ -130,8 +130,6 @@ namespace OpenRA.Mods.Common.Traits
notifyHarvesterAction = self.TraitsImplementing<INotifyHarvesterAction>().ToArray(); notifyHarvesterAction = self.TraitsImplementing<INotifyHarvesterAction>().ToArray();
conditionManager = self.TraitOrDefault<ConditionManager>(); conditionManager = self.TraitOrDefault<ConditionManager>();
UpdateCondition(self); UpdateCondition(self);
if (Info.SearchOnCreation)
idleSmart = true;
} }
public void SetProcLines(Actor proc) public void SetProcLines(Actor proc)
@@ -242,26 +240,6 @@ namespace OpenRA.Mods.Common.Traits
UpdateCondition(self); UpdateCondition(self);
} }
void INotifyBlockingMove.OnNotifyBlockingMove(Actor self, Actor blocking)
{
// I'm blocking someone else from moving to my location:
var act = self.CurrentActivity;
// If I'm just waiting around then get out of the way:
if (act is Wait)
{
self.CancelActivity();
var cell = self.Location;
var moveTo = mobile.NearestMoveableCell(cell, 2, 5);
self.QueueActivity(mobile.MoveTo(moveTo, 0));
self.SetTargetLine(Target.FromCell(self.World, moveTo), Color.Gray, false);
// Find more resources but not at this location:
self.QueueActivity(new FindResources(self, cell));
}
}
void INotifyIdle.TickIdle(Actor self) void INotifyIdle.TickIdle(Actor self)
{ {
// Should we be intelligent while idle? // Should we be intelligent while idle?
@@ -383,12 +361,7 @@ namespace OpenRA.Mods.Common.Traits
self.SetTargetLine(Target.FromCell(self.World, loc), Color.Red); self.SetTargetLine(Target.FromCell(self.World, loc), Color.Red);
// FindResources takes care of calling INotifyHarvesterAction // FindResources takes care of calling INotifyHarvesterAction
self.QueueActivity(order.Queued, new FindResources(self)); self.QueueActivity(order.Queued, new FindResources(self, loc));
LastOrderLocation = loc;
// This prevents harvesters returning to an empty patch when the player orders them to a new patch:
LastHarvestedCell = LastOrderLocation;
} }
else if (order.OrderString == "Deliver") else if (order.OrderString == "Deliver")
{ {