diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index e5aa229606..d7b966e92d 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -132,6 +132,7 @@ namespace OpenRA.Traits } public interface IMove : ITeleportable { int Altitude { get; set; } } + public interface INotifyBlockingMove { void OnNotifyBlockingMove(Actor self, Actor blocking, CPos cell); } public interface IFacing { diff --git a/OpenRA.Mods.RA/Activities/FindResources.cs b/OpenRA.Mods.RA/Activities/FindResources.cs index f85e7b1479..d50f2b1cfd 100755 --- a/OpenRA.Mods.RA/Activities/FindResources.cs +++ b/OpenRA.Mods.RA/Activities/FindResources.cs @@ -20,6 +20,17 @@ namespace OpenRA.Mods.RA.Activities { public class FindResources : Activity { + CPos avoidCell; + + public FindResources() + { + } + + public FindResources(CPos avoidCell) + { + this.avoidCell = avoidCell; + } + public override Activity Tick(Actor self) { if (IsCanceled || NextActivity != null) return NextActivity; @@ -53,6 +64,8 @@ namespace OpenRA.Mods.RA.Activities }) .WithHeuristic(loc => { + if (loc == avoidCell) return 1; + // Don't harvest out of range: int distSquared = (loc - (harv.LastOrderLocation ?? harv.LinkedProc.Location)).LengthSquared; if (distSquared > (12 * 12)) @@ -69,6 +82,7 @@ namespace OpenRA.Mods.RA.Activities ResourceClaim claim; if (territory.IsClaimedByAnyoneElse(self, loc, out claim)) return 1; +#if false // Is anyone covering the location already? // NOTE(jsd): This is required to prevent harvester deadlocking. var unitsAtLoc = @@ -76,6 +90,7 @@ namespace OpenRA.Mods.RA.Activities where u != self select u; if (unitsAtLoc.Any()) return 1; +#endif return 0; }) @@ -90,23 +105,24 @@ namespace OpenRA.Mods.RA.Activities { // Get out of the way if we are: harv.UnblockRefinery(self); + int randFrames = 125 + self.World.SharedRandom.Next(-35, 35); if (NextActivity != null) - return Util.SequenceActivities(NextActivity, new Wait(90), this); + return Util.SequenceActivities(NextActivity, new Wait(randFrames), new FindResources()); else - return Util.SequenceActivities(new Wait(90), this); + return Util.SequenceActivities(new Wait(randFrames), new FindResources()); } } // Attempt to claim a resource as ours: if (!territory.ClaimResource(self, path[0])) - return Util.SequenceActivities(new Wait(25), this); + return Util.SequenceActivities(new Wait(25), new FindResources()); // If not given a direct order, assume ordered to the first resource location we find: if (harv.LastOrderLocation == null) harv.LastOrderLocation = path[0]; self.SetTargetLine(Target.FromCell(path[0]), Color.Red, false); - return Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), this); + return Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), new FindResources()); } public override IEnumerable GetTargets(Actor self) diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index d44a9cc6e6..eb3d45d962 100644 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -30,7 +30,8 @@ namespace OpenRA.Mods.RA } public class Harvester : IIssueOrder, IResolveOrder, IPips, - IExplodeModifier, IOrderVoice, ISpeedModifier, ISync, INotifyResourceClaimLost, INotifyIdle + IExplodeModifier, IOrderVoice, ISpeedModifier, ISync, + INotifyResourceClaimLost, INotifyIdle, INotifyBlockingMove { Dictionary contents = new Dictionary(); @@ -120,16 +121,31 @@ namespace OpenRA.Mods.RA // Get out of the way: var mobile = self.Trait(); var harv = self.Trait(); - // TODO: would like an interruptible move here var moveTo = harv.LastHarvestedCell ?? (deliveryLoc + new CVec(0, 4)); self.QueueActivity(mobile.MoveTo(moveTo, 1)); self.SetTargetLine(Target.FromCell(moveTo), Color.Red, false); self.World.WorldActor.Trait().ClaimResource(self, moveTo); + self.QueueActivity(new FindResources()); return; } } } + public void OnNotifyBlockingMove(Actor self, Actor blocking, CPos cell) + { + // I'm blocking someone else from moving to my location: + Activity act = self.GetCurrentActivity(); + // If I'm just waiting around, then get out of the way: + if (act.GetType() == typeof(Wait)) + { + self.CancelActivity(); + var mobile = self.Trait(); + self.QueueActivity(mobile.MoveTo(mobile.NearestMoveableCell(cell, 2, 5), 0)); + // Find more resources but not at this location: + self.QueueActivity(new FindResources(cell)); + } + } + public void TickIdle(Actor self) { // Are we not empty? Deliver resources: diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 7fbf9fef59..820ea0fcdf 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -178,6 +178,11 @@ namespace OpenRA.Mods.RA.Move var nudge = blocker.TraitOrDefault(); if (nudge != null) nudge.OnNudge(blocker, self, false); + + // Notify the blocker that he's blocking our move: + INotifyBlockingMove moveBlocked; + if ((moveBlocked = blocker.TraitOrDefault()) != null) + moveBlocked.OnNotifyBlockingMove(blocker, self, nextCell); } Pair? PopPath(Actor self, Mobile mobile)