diff --git a/OpenRA.Mods.Common/Activities/DeliverResources.cs b/OpenRA.Mods.Common/Activities/DeliverResources.cs index 1bfe5637fb..5983ba1190 100644 --- a/OpenRA.Mods.Common/Activities/DeliverResources.cs +++ b/OpenRA.Mods.Common/Activities/DeliverResources.cs @@ -18,17 +18,26 @@ namespace OpenRA.Mods.Common.Activities public class DeliverResources : Activity { const int NextChooseTime = 100; + + readonly IMove movement; + readonly Harvester harv; + readonly HarvesterInfo harvInfo; + bool isDocking; int chosenTicks; + public DeliverResources(Actor self) + { + movement = self.Trait(); + harv = self.Trait(); + harvInfo = self.Info.Traits.Get(); + } + public override Activity Tick(Actor self) { if (NextActivity != null) return NextActivity; - var movement = self.Trait(); - var harv = self.Trait(); - // Find the nearest best refinery if not explicitly ordered to a specific refinery: if (harv.OwnerLinkedProc == null || !harv.OwnerLinkedProc.IsInWorld) { @@ -46,8 +55,9 @@ namespace OpenRA.Mods.Common.Activities if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld) harv.ChooseNewProc(self, null); - if (harv.LinkedProc == null) // no procs exist; check again in 1s. - return Util.SequenceActivities(new Wait(25), this); + // No refineries exist; check again after delay defined in Harvester. + if (harv.LinkedProc == null) + return Util.SequenceActivities(new Wait(harvInfo.SearchForDeliveryBuildingDelay), this); var proc = harv.LinkedProc; var iao = proc.Trait(); @@ -56,7 +66,7 @@ namespace OpenRA.Mods.Common.Activities if (self.Location != proc.Location + iao.DeliveryOffset) { var notify = self.TraitsImplementing(); - var next = new DeliverResources(); + var next = new DeliverResources(self); foreach (var n in notify) n.MovingToRefinery(self, proc.Location + iao.DeliveryOffset, next); diff --git a/OpenRA.Mods.Common/Activities/FindResources.cs b/OpenRA.Mods.Common/Activities/FindResources.cs index d2f3444f1a..efe54b8db4 100644 --- a/OpenRA.Mods.Common/Activities/FindResources.cs +++ b/OpenRA.Mods.Common/Activities/FindResources.cs @@ -21,31 +21,42 @@ namespace OpenRA.Mods.Common.Activities { public class FindResources : Activity { + readonly Harvester harv; + readonly HarvesterInfo harvInfo; + readonly Mobile mobile; + readonly MobileInfo mobileInfo; + readonly ResourceLayer resLayer; + readonly ResourceClaimLayer territory; + readonly IPathFinder pathFinder; + CPos? avoidCell; - public FindResources() + public FindResources(Actor self) { + harv = self.Trait(); + harvInfo = self.Info.Traits.Get(); + mobile = self.Trait(); + mobileInfo = self.Info.Traits.Get(); + resLayer = self.World.WorldActor.Trait(); + territory = self.World.WorldActor.TraitOrDefault(); + pathFinder = self.World.WorldActor.Trait(); } - public FindResources(CPos avoidCell) + public FindResources(Actor self, CPos avoidCell) + : this(self) { this.avoidCell = avoidCell; } public override Activity Tick(Actor self) { - if (IsCanceled || NextActivity != null) return NextActivity; + if (IsCanceled || NextActivity != null) + return NextActivity; - var harv = self.Trait(); + var deliver = new DeliverResources(self); if (harv.IsFull) - return Util.SequenceActivities(new DeliverResources(), NextActivity); - - 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.TraitOrDefault(); + return Util.SequenceActivities(deliver, NextActivity); // Determine where to search from and how far to search: var searchFromLoc = harv.LastOrderLocation ?? (harv.LastLinkedProc ?? harv.LinkedProc ?? self).Location; @@ -53,7 +64,7 @@ namespace OpenRA.Mods.Common.Activities var searchRadiusSquared = searchRadius * searchRadius; // Find harvestable resources nearby: - var path = self.World.WorldActor.Trait().FindPath( + var path = pathFinder.FindPath( PathSearch.Search(self.World, mobileInfo, self, true) .WithHeuristic(loc => { @@ -87,19 +98,21 @@ namespace OpenRA.Mods.Common.Activities }) .FromPoint(self.Location)); + var next = this; + if (path.Count == 0) { if (!harv.IsEmpty) - return new DeliverResources(); + return deliver; else { // Get out of the way if we are: harv.UnblockRefinery(self); - var randFrames = 125 + self.World.SharedRandom.Next(-35, 35); + var randFrames = self.World.SharedRandom.Next(90, 160); if (NextActivity != null) - return Util.SequenceActivities(NextActivity, new Wait(randFrames), new FindResources()); + return Util.SequenceActivities(NextActivity, new Wait(randFrames), next); else - return Util.SequenceActivities(new Wait(randFrames), new FindResources()); + return Util.SequenceActivities(new Wait(randFrames), next); } } @@ -107,7 +120,7 @@ namespace OpenRA.Mods.Common.Activities if (territory != null) { if (!territory.ClaimResource(self, path[0])) - return Util.SequenceActivities(new Wait(25), new FindResources()); + return Util.SequenceActivities(new Wait(25), next); } // If not given a direct order, assume ordered to the first resource location we find: @@ -117,11 +130,10 @@ namespace OpenRA.Mods.Common.Activities self.SetTargetLine(Target.FromCell(self.World, path[0]), Color.Red, false); var notify = self.TraitsImplementing(); - var next = new FindResources(); foreach (var n in notify) n.MovingToResources(self, path[0], next); - return Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), new FindResources()); + return Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(self), next); } // Diagonal distance heuristic @@ -138,54 +150,4 @@ namespace OpenRA.Mods.Common.Activities yield return Target.FromCell(self.World, self.Location); } } - - public class HarvestResource : Activity - { - public override Activity Tick(Actor self) - { - var territory = self.World.WorldActor.TraitOrDefault(); - if (IsCanceled) - { - if (territory != null) - territory.UnclaimByActor(self); - return NextActivity; - } - - var harv = self.Trait(); - var harvInfo = self.Info.Traits.Get(); - harv.LastHarvestedCell = self.Location; - - if (harv.IsFull) - { - if (territory != null) - territory.UnclaimByActor(self); - return NextActivity; - } - - // Turn to one of the harvestable facings - if (harvInfo.HarvestFacings != 0) - { - var facing = self.Trait().Facing; - var desired = Util.QuantizeFacing(facing, harvInfo.HarvestFacings) * (256 / harvInfo.HarvestFacings); - if (desired != facing) - return Util.SequenceActivities(new Turn(self, desired), this); - } - - var resLayer = self.World.WorldActor.Trait(); - var resource = resLayer.Harvest(self.Location); - if (resource == null) - { - if (territory != null) - territory.UnclaimByActor(self); - return NextActivity; - } - - harv.AcceptResource(resource); - - foreach (var t in self.TraitsImplementing()) - t.Harvested(self, resource); - - return Util.SequenceActivities(new Wait(harvInfo.LoadTicksPerBale), this); - } - } } diff --git a/OpenRA.Mods.Common/Activities/HarvestResource.cs b/OpenRA.Mods.Common/Activities/HarvestResource.cs new file mode 100644 index 0000000000..71bed722f3 --- /dev/null +++ b/OpenRA.Mods.Common/Activities/HarvestResource.cs @@ -0,0 +1,77 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using OpenRA.Activities; +using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Activities +{ + public class HarvestResource : Activity + { + readonly Harvester harv; + readonly HarvesterInfo harvInfo; + readonly IFacing facing; + readonly ResourceClaimLayer territory; + readonly ResourceLayer resLayer; + + public HarvestResource(Actor self) + { + harv = self.Trait(); + harvInfo = self.Info.Traits.Get(); + facing = self.Trait(); + territory = self.World.WorldActor.TraitOrDefault(); + resLayer = self.World.WorldActor.Trait(); + } + + public override Activity Tick(Actor self) + { + if (IsCanceled) + { + if (territory != null) + territory.UnclaimByActor(self); + return NextActivity; + } + + harv.LastHarvestedCell = self.Location; + + if (harv.IsFull) + { + if (territory != null) + territory.UnclaimByActor(self); + return NextActivity; + } + + // Turn to one of the harvestable facings + if (harvInfo.HarvestFacings != 0) + { + var current = facing.Facing; + var desired = Util.QuantizeFacing(current, harvInfo.HarvestFacings) * (256 / harvInfo.HarvestFacings); + if (desired != current) + return Util.SequenceActivities(new Turn(self, desired), this); + } + + var resource = resLayer.Harvest(self.Location); + if (resource == null) + { + if (territory != null) + territory.UnclaimByActor(self); + return NextActivity; + } + + harv.AcceptResource(resource); + + foreach (var t in self.TraitsImplementing()) + t.Harvested(self, resource); + + return Util.SequenceActivities(new Wait(harvInfo.LoadTicksPerBale), this); + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 0a6abc5ec1..149fdf1133 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -112,6 +112,7 @@ + diff --git a/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs b/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs index 910c09b012..bbb597841a 100644 --- a/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs +++ b/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs @@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Pathfinder public abstract IEnumerable> Considered { get; } - public Player Owner { get { return this.Graph.Actor.Owner; } } + public Player Owner { get { return Graph.Actor.Owner; } } public int MaxCost { get; protected set; } public bool Debug { get; set; } string id; @@ -184,7 +184,7 @@ namespace OpenRA.Mods.Common.Pathfinder public IPathSearch FromPoint(CPos from) { - if (this.Graph.World.Map.Contains(from)) + if (Graph.World.Map.Contains(from)) AddInitialCell(from); return this; diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs index 86c70bdf63..32db23f576 100644 --- a/OpenRA.Mods.Common/Traits/Harvester.cs +++ b/OpenRA.Mods.Common/Traits/Harvester.cs @@ -19,10 +19,13 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class HarvesterInfo : ITraitInfo + public class HarvesterInfo : ITraitInfo, Requires { public readonly string[] DeliveryBuildings = { }; + [Desc("How long (in ticks) to wait until (re-)checking for a nearby available DeliveryBuilding if not yet linked to one.")] + public readonly int SearchForDeliveryBuildingDelay = 125; + [Desc("How much resources it can carry.")] public readonly int Capacity = 28; @@ -62,6 +65,7 @@ namespace OpenRA.Mods.Common.Traits INotifyResourceClaimLost, INotifyIdle, INotifyBlockingMove, INotifyBuildComplete { readonly HarvesterInfo info; + readonly Mobile mobile; Dictionary contents = new Dictionary(); [Sync] public Actor OwnerLinkedProc = null; @@ -76,19 +80,20 @@ namespace OpenRA.Mods.Common.Traits public Harvester(Actor self, HarvesterInfo info) { this.info = info; + mobile = self.Trait(); self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null))); } public void Created(Actor self) { if (info.SearchOnCreation) - self.QueueActivity(new FindResources()); + self.QueueActivity(new FindResources(self)); } public void BuildingComplete(Actor self) { if (info.SearchOnCreation) - self.QueueActivity(new FindResources()); + self.QueueActivity(new FindResources(self)); } public void SetProcLines(Actor proc) @@ -128,7 +133,7 @@ namespace OpenRA.Mods.Common.Traits { // Move out of the refinery dock and continue harvesting: UnblockRefinery(self); - self.QueueActivity(new FindResources()); + self.QueueActivity(new FindResources(self)); } bool IsAcceptableProcType(Actor proc) @@ -137,7 +142,7 @@ namespace OpenRA.Mods.Common.Traits info.DeliveryBuildings.Contains(proc.Info.Name); } - Actor ClosestProc(Actor self, Actor ignore) + public Actor ClosestProc(Actor self, Actor ignore) { // Find all refineries and their occupancy count: var refs = ( @@ -150,14 +155,16 @@ namespace OpenRA.Mods.Common.Traits var mi = self.Info.Traits.Get(); var path = self.World.WorldActor.Trait().FindPath( PathSearch.FromPoints(self.World, mi, self, refs.Values.Select(r => r.Location), self.Location, false) - .WithCustomCost((loc) => + .WithCustomCost(loc => { - if (!refs.ContainsKey(loc)) return 0; + if (!refs.ContainsKey(loc)) + return 0; var occupancy = refs[loc].Occupancy; // 4 harvesters clogs up the refinery's delivery location: - if (occupancy >= 3) return int.MaxValue; + if (occupancy >= 3) + return int.MaxValue; // Prefer refineries with less occupancy (multiplier is to offset distance cost): return occupancy * 12; @@ -189,22 +196,20 @@ namespace OpenRA.Mods.Common.Traits if (self.Location == deliveryLoc) { // Get out of the way: - var mobile = self.Trait(); - var harv = self.Trait(); - - var moveTo = harv.LastHarvestedCell ?? (deliveryLoc + new CVec(0, 4)); + var moveTo = LastHarvestedCell ?? (deliveryLoc + new CVec(0, 4)); self.QueueActivity(mobile.MoveTo(moveTo, 1)); self.SetTargetLine(Target.FromCell(self.World, moveTo), Color.Gray, false); var territory = self.World.WorldActor.TraitOrDefault(); - if (territory != null) territory.ClaimResource(self, moveTo); + if (territory != null) + territory.ClaimResource(self, moveTo); var notify = self.TraitsImplementing(); - var next = new FindResources(); + var next = new FindResources(self); foreach (var n in notify) n.MovingToResources(self, moveTo, next); - self.QueueActivity(new FindResources()); + self.QueueActivity(new FindResources(self)); return; } } @@ -219,7 +224,6 @@ namespace OpenRA.Mods.Common.Traits if (act is Wait) { self.CancelActivity(); - var mobile = self.Trait(); var cell = self.Location; var moveTo = mobile.NearestMoveableCell(cell, 2, 5); @@ -227,7 +231,7 @@ namespace OpenRA.Mods.Common.Traits self.SetTargetLine(Target.FromCell(self.World, moveTo), Color.Gray, false); // Find more resources but not at this location: - self.QueueActivity(new FindResources(cell)); + self.QueueActivity(new FindResources(self, cell)); } } @@ -239,7 +243,7 @@ namespace OpenRA.Mods.Common.Traits // Are we not empty? Deliver resources: if (!IsEmpty) { - self.QueueActivity(new DeliverResources()); + self.QueueActivity(new DeliverResources(self)); return; } @@ -316,7 +320,6 @@ namespace OpenRA.Mods.Common.Traits self.CancelActivity(); - var mobile = self.Trait(); if (order.TargetLocation != CPos.Zero) { var loc = order.TargetLocation; @@ -338,7 +341,7 @@ namespace OpenRA.Mods.Common.Traits self.SetTargetLine(Target.FromCell(self.World, loc), Color.Red); var notify = self.TraitsImplementing(); - var next = new FindResources(); + var next = new FindResources(self); foreach (var n in notify) n.MovingToResources(self, loc, next); @@ -361,7 +364,7 @@ namespace OpenRA.Mods.Common.Traits // This prevents harvesters returning to an empty patch when the player orders them to a new patch: LastHarvestedCell = LastOrderLocation; - self.QueueActivity(new FindResources()); + self.QueueActivity(new FindResources(self)); } else if (order.OrderString == "Deliver") { @@ -381,10 +384,11 @@ namespace OpenRA.Mods.Common.Traits self.SetTargetLine(Target.FromOrder(self.World, order), Color.Green); self.CancelActivity(); - self.QueueActivity(new DeliverResources()); + + var next = new DeliverResources(self); + self.QueueActivity(next); var notify = self.TraitsImplementing(); - var next = new DeliverResources(); foreach (var n in notify) n.MovingToRefinery(self, order.TargetLocation, next); } @@ -421,9 +425,9 @@ namespace OpenRA.Mods.Common.Traits if (!harvInfo.Resources.Contains(resType.Info.Name)) return Constants.CellCost; - // Another harvester has claimed this resource: if (territory != null) { + // Another harvester has claimed this resource: ResourceClaim claim; if (territory.IsClaimedByAnyoneElse(self, loc, out claim)) return Constants.CellCost; @@ -445,7 +449,7 @@ namespace OpenRA.Mods.Common.Traits // Our claim on a resource was stolen, find more unclaimed resources: self.CancelActivity(); - self.QueueActivity(new FindResources()); + self.QueueActivity(new FindResources(self)); } PipType GetPipAt(int i)