diff --git a/OpenRA.Mods.Cnc/Activities/LayMines.cs b/OpenRA.Mods.Cnc/Activities/LayMines.cs index 7b3c289607..9b3e7e63ac 100644 --- a/OpenRA.Mods.Cnc/Activities/LayMines.cs +++ b/OpenRA.Mods.Cnc/Activities/LayMines.cs @@ -22,23 +22,29 @@ namespace OpenRA.Mods.Cnc.Activities // Assumes you have Minelayer on that unit public class LayMines : Activity { - readonly Minelayer minelayer; readonly MinelayerInfo info; readonly AmmoPool[] ammoPools; readonly IMove movement; readonly RearmableInfo rearmableInfo; + readonly CPos[] minefield; - public LayMines(Actor self) + public LayMines(Actor self, CPos[] minefield) { - minelayer = self.TraitOrDefault(); info = self.Info.TraitInfo(); ammoPools = self.TraitsImplementing().ToArray(); movement = self.Trait(); rearmableInfo = self.Info.TraitInfoOrDefault(); + this.minefield = minefield; } public override Activity Tick(Actor self) { + if (ChildActivity != null) + { + ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); + return this; + } + if (IsCanceling) return NextActivity; @@ -50,36 +56,39 @@ namespace OpenRA.Mods.Cnc.Activities .ClosestTo(self); if (rearmTarget == null) - return new Wait(20); + return NextActivity; // Add a CloseEnough range of 512 to the Rearm/Repair activities in order to ensure that we're at the host actor - return ActivityUtils.SequenceActivities(self, - new MoveAdjacentTo(self, Target.FromActor(rearmTarget)), - movement.MoveTo(self.World.Map.CellContaining(rearmTarget.CenterPosition), rearmTarget), - new Rearm(self, rearmTarget, new WDist(512)), - new Repair(self, rearmTarget, new WDist(512)), - this); + QueueChild(self, new MoveAdjacentTo(self, Target.FromActor(rearmTarget)), true); + QueueChild(self, movement.MoveTo(self.World.Map.CellContaining(rearmTarget.CenterPosition), rearmTarget)); + QueueChild(self, new Rearm(self, rearmTarget, new WDist(512))); + QueueChild(self, new Repair(self, rearmTarget, new WDist(512))); + return this; } - if (minelayer.Minefield.Contains(self.Location) && ShouldLayMine(self, self.Location)) + if ((minefield == null || minefield.Contains(self.Location)) && ShouldLayMine(self, self.Location)) { LayMine(self); - return ActivityUtils.SequenceActivities(self, new Wait(20), this); // A little wait after placing each mine, for show + QueueChild(self, new Wait(20), true); // A little wait after placing each mine, for show + return this; } - if (minelayer.Minefield.Length > 0) + if (minefield != null && minefield.Length > 0) { // Don't get stuck forever here for (var n = 0; n < 20; n++) { - var p = minelayer.Minefield.Random(self.World.SharedRandom); + var p = minefield.Random(self.World.SharedRandom); if (ShouldLayMine(self, p)) - return ActivityUtils.SequenceActivities(self, movement.MoveTo(p, 0), this); + { + QueueChild(self, movement.MoveTo(p, 0), true); + return this; + } } } // TODO: Return somewhere likely to be safe (near rearm building) so we're not sitting out in the minefield. - return new Wait(20); // nothing to do here + return NextActivity; } static bool ShouldLayMine(Actor self, CPos p) diff --git a/OpenRA.Mods.Cnc/Traits/Minelayer.cs b/OpenRA.Mods.Cnc/Traits/Minelayer.cs index 3339aa3cf4..5650328bf9 100644 --- a/OpenRA.Mods.Cnc/Traits/Minelayer.cs +++ b/OpenRA.Mods.Cnc/Traits/Minelayer.cs @@ -70,11 +70,11 @@ namespace OpenRA.Mods.Cnc.Traits if (self.World.OrderGenerator is MinefieldOrderGenerator) ((MinefieldOrderGenerator)self.World.OrderGenerator).AddMinelayer(self, start); else - self.World.OrderGenerator = new MinefieldOrderGenerator(self, start); + self.World.OrderGenerator = new MinefieldOrderGenerator(self, start, queued); - return new Order("BeginMinefield", self, Target.FromCell(self.World, start), false); + return new Order("BeginMinefield", self, Target.FromCell(self.World, start), queued); case "PlaceMine": - return new Order("PlaceMine", self, Target.FromCell(self.World, self.Location), false); + return new Order("PlaceMine", self, Target.FromCell(self.World, self.Location), queued); default: return null; } @@ -96,12 +96,7 @@ namespace OpenRA.Mods.Cnc.Traits if (order.OrderString == "BeginMinefield") minefieldStart = cell; else if (order.OrderString == "PlaceMine") - { - minefieldStart = cell; - Minefield = new[] { cell }; - self.CancelActivity(); - self.QueueActivity(new LayMines(self)); - } + self.QueueActivity(order.Queued, new LayMines(self, null)); else if (order.OrderString == "PlaceMinefield") { var movement = self.Trait(); @@ -112,8 +107,7 @@ namespace OpenRA.Mods.Cnc.Traits if (Minefield.Length == 1 && Minefield[0] != self.Location) self.SetTargetLine(Target.FromCell(self.World, Minefield[0]), Color.Red); - self.CancelActivity(); - self.QueueActivity(new LayMines(self)); + self.QueueActivity(order.Queued, new LayMines(self, Minefield)); } } @@ -167,11 +161,13 @@ namespace OpenRA.Mods.Cnc.Traits readonly Sprite tileOk; readonly Sprite tileBlocked; readonly CPos minefieldStart; + readonly bool queued; - public MinefieldOrderGenerator(Actor a, CPos xy) + public MinefieldOrderGenerator(Actor a, CPos xy, bool queued) { minelayers = new List() { a }; minefieldStart = xy; + this.queued = queued; var tileset = a.World.Map.Tileset.ToLowerInvariant(); tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0); @@ -201,7 +197,7 @@ namespace OpenRA.Mods.Cnc.Traits { minelayers.First().World.CancelInputMode(); foreach (var minelayer in minelayers) - yield return new Order("PlaceMinefield", minelayer, Target.FromCell(world, cell), false); + yield return new Order("PlaceMinefield", minelayer, Target.FromCell(world, cell), queued); } }