Sanitize harvester search behavior.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user