diff --git a/OpenRA.Game/Traits/DrawLineToTarget.cs b/OpenRA.Game/Traits/DrawLineToTarget.cs index 5f6dcc7a41..2c72b9489c 100644 --- a/OpenRA.Game/Traits/DrawLineToTarget.cs +++ b/OpenRA.Game/Traits/DrawLineToTarget.cs @@ -11,6 +11,7 @@ using System.Drawing; using OpenRA.Graphics; using OpenRA.Effects; +using System.Collections.Generic; namespace OpenRA.Traits { @@ -25,7 +26,7 @@ namespace OpenRA.Traits { Actor self; DrawLineToTargetInfo Info; - Target target; + List targets; Color c; int lifetime; @@ -33,7 +34,16 @@ namespace OpenRA.Traits public void SetTarget(Actor self, Target target, Color c, bool display) { - this.target = target; + this.targets = new List { target }; + this.c = c; + + if (display) + lifetime = Info.Ticks; + } + + public void SetTargets(Actor self, List targets, Color c, bool display) + { + this.targets = targets; this.c = c; if (display) @@ -42,13 +52,13 @@ namespace OpenRA.Traits public void RenderAfterWorld(WorldRenderer wr) { - if (self.IsIdle) return; + //if (self.IsIdle) return; var force = Game.GetModifierKeys().HasModifier(Modifiers.Alt); if ((lifetime <= 0 || --lifetime <= 0) && !force) return; - if (!target.IsValid) + if (targets == null || targets.Count == 0) return; var move = self.TraitOrDefault(); @@ -56,9 +66,15 @@ namespace OpenRA.Traits var wlr = Game.Renderer.WorldLineRenderer; - wlr.DrawLine(origin, target.CenterLocation.ToFloat2(), c, c); - DrawTargetMarker(wlr, target.CenterLocation.ToFloat2()); - DrawTargetMarker(wlr, origin); + foreach (var target in targets) + { + if (!target.IsValid) + continue; + + wlr.DrawLine(origin, target.CenterLocation.ToFloat2(), c, c); + DrawTargetMarker(wlr, target.CenterLocation.ToFloat2()); + DrawTargetMarker(wlr, origin); + } } void DrawTargetMarker(LineRenderer wlr, float2 p) @@ -72,6 +88,18 @@ namespace OpenRA.Traits public static class LineTargetExts { + public static void SetTargetLines(this Actor self, List targets, Color color) + { + var line = self.TraitOrDefault(); + if (line != null) + { + self.World.AddFrameEndTask(w => + { + line.SetTargets(self, targets, color, false); + }); + } + } + public static void SetTargetLine(this Actor self, Target target, Color color) { self.SetTargetLine(target, color, true); diff --git a/OpenRA.Mods.RA/Activities/DeliverResources.cs b/OpenRA.Mods.RA/Activities/DeliverResources.cs index c1835a90b6..0e865827bc 100755 --- a/OpenRA.Mods.RA/Activities/DeliverResources.cs +++ b/OpenRA.Mods.RA/Activities/DeliverResources.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Activities } else { - harv.LinkedProc = harv.OwnerLinkedProc; + harv.LinkProc(self, harv.OwnerLinkedProc); } if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld) diff --git a/OpenRA.Mods.RA/Activities/FindResources.cs b/OpenRA.Mods.RA/Activities/FindResources.cs index d50f2b1cfd..8702f44a35 100755 --- a/OpenRA.Mods.RA/Activities/FindResources.cs +++ b/OpenRA.Mods.RA/Activities/FindResources.cs @@ -82,16 +82,6 @@ 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 = - from u in self.World.FindUnits(loc.ToPPos(), loc.ToPPos() + PVecInt.OneCell) - where u != self - select u; - if (unitsAtLoc.Any()) return 1; -#endif - return 0; }) .FromPoint(self.Location) diff --git a/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs b/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs index a94a6693a9..48af370a76 100644 --- a/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs +++ b/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.RA return this; case State.Complete: harv.LastLinkedProc = harv.LinkedProc; - harv.LinkedProc = null; + harv.LinkProc(self, null); return NextActivity; } throw new InvalidOperationException("Invalid harvester dock state"); diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index eb3d45d962..385bf5c459 100644 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -50,10 +50,36 @@ namespace OpenRA.Mods.RA self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null))); } + public void SetProcLines(Actor proc) + { + if (proc == null) return; + + var linkedHarvs = proc.World.ActorsWithTrait() + .Where(a => a.Trait.LinkedProc == proc) + .Select(a => Target.FromActor(a.Actor)) + .ToList(); + + proc.SetTargetLines(linkedHarvs, Color.Gold); + } + + public void LinkProc(Actor self, Actor proc) + { + var oldProc = LinkedProc; + LinkedProc = proc; + SetProcLines(oldProc); + SetProcLines(proc); + } + + public void UnlinkProc(Actor self, Actor proc) + { + if (LinkedProc == proc) + ChooseNewProc(self, proc); + } + public void ChooseNewProc(Actor self, Actor ignore) { - LinkedProc = ClosestProc(self, ignore); LastLinkedProc = null; + LinkProc(self, ClosestProc(self, ignore)); } public void ContinueHarvesting(Actor self) @@ -121,9 +147,11 @@ namespace OpenRA.Mods.RA // Get out of the way: var mobile = self.Trait(); var harv = self.Trait(); + var moveTo = harv.LastHarvestedCell ?? (deliveryLoc + new CVec(0, 4)); self.QueueActivity(mobile.MoveTo(moveTo, 1)); - self.SetTargetLine(Target.FromCell(moveTo), Color.Red, false); + self.SetTargetLine(Target.FromCell(moveTo), Color.Gray, false); + self.World.WorldActor.Trait().ClaimResource(self, moveTo); self.QueueActivity(new FindResources()); return; @@ -140,7 +168,11 @@ namespace OpenRA.Mods.RA { self.CancelActivity(); var mobile = self.Trait(); - self.QueueActivity(mobile.MoveTo(mobile.NearestMoveableCell(cell, 2, 5), 0)); + + var moveTo = mobile.NearestMoveableCell(cell, 2, 5); + self.QueueActivity(mobile.MoveTo(moveTo, 0)); + self.SetTargetLine(Target.FromCell(moveTo), Color.Gray, false); + // Find more resources but not at this location: self.QueueActivity(new FindResources(cell)); } @@ -218,7 +250,7 @@ namespace OpenRA.Mods.RA if (order.OrderString == "Harvest") { // NOTE: An explicit harvest order allows the harvester to decide which refinery to deliver to. - OwnerLinkedProc = null; + LinkProc(self, OwnerLinkedProc = null); var mobile = self.Trait(); self.CancelActivity(); @@ -245,7 +277,7 @@ namespace OpenRA.Mods.RA return; if (order.TargetActor != OwnerLinkedProc) - LinkedProc = OwnerLinkedProc = order.TargetActor; + LinkProc(self, OwnerLinkedProc = order.TargetActor); if (IsEmpty) return; @@ -257,12 +289,6 @@ namespace OpenRA.Mods.RA } } - public void UnlinkProc(Actor self, Actor proc) - { - if (LinkedProc == proc) - ChooseNewProc(self, proc); - } - public void OnNotifyResourceClaimLost(Actor self, ResourceClaim claim, Actor claimer) { if (self == claimer) return; diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 8a9ba07358..795943cd18 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -872,6 +872,7 @@ PROC: PipCount: 17 Capacity: 2000 IronCurtainable: + DrawLineToTarget: CustomSellValue: Value: 600 FreeActor: