diff --git a/OpenRA.Mods.Common/Activities/LayMines.cs b/OpenRA.Mods.Common/Activities/LayMines.cs index 853a75b97c..2c93d90e55 100644 --- a/OpenRA.Mods.Common/Activities/LayMines.cs +++ b/OpenRA.Mods.Common/Activities/LayMines.cs @@ -30,6 +30,7 @@ namespace OpenRA.Mods.Common.Activities List minefield; bool returnToBase; Actor rearmTarget; + bool layingMine; public LayMines(Actor self, List minefield = null) { @@ -61,7 +62,26 @@ namespace OpenRA.Mods.Common.Activities returnToBase = false; if (IsCanceling) + { + if (layingMine) + foreach (var t in self.TraitsImplementing()) + t.MineLayingCanceled(self, self.Location); + return true; + } + + if (layingMine) + { + layingMine = false; + if (LayMine(self)) + { + if (minelayer.Info.AfterLayingDelay > 0) + { + QueueChild(new Wait(minelayer.Info.AfterLayingDelay)); + return false; + } + } + } if ((minefield == null || minefield.Contains(self.Location)) && CanLayMine(self, self.Location)) { @@ -82,9 +102,20 @@ namespace OpenRA.Mods.Common.Activities return false; } - LayMine(self); - QueueChild(new Wait(20)); // A little wait after placing each mine, for show - minefield.Remove(self.Location); + if (!StartLayingMine(self)) + return false; + + if (minelayer.Info.PreLayDelay == 0) + { + if (LayMine(self) && minelayer.Info.AfterLayingDelay > 0) + QueueChild(new Wait(minelayer.Info.AfterLayingDelay)); + } + else + { + layingMine = true; + QueueChild(new Wait(minelayer.Info.PreLayDelay)); + } + return false; } @@ -136,20 +167,38 @@ namespace OpenRA.Mods.Common.Activities return self.World.ActorMap.GetActorsAt(p).All(a => a == self); } - void LayMine(Actor self) + bool StartLayingMine(Actor self) { if (ammoPools != null) { var pool = ammoPools.FirstOrDefault(x => x.Info.Name == minelayer.Info.AmmoPoolName); if (pool == null) - return; + return false; - pool.TakeAmmo(self, minelayer.Info.AmmoUsage); + if (pool.CurrentAmmoCount < minelayer.Info.AmmoUsage) + return false; } foreach (var t in self.TraitsImplementing()) t.MineLaying(self, self.Location); + return true; + } + + bool LayMine(Actor self) + { + if (ammoPools != null) + { + var pool = ammoPools.FirstOrDefault(x => x.Info.Name == minelayer.Info.AmmoPoolName); + if (pool == null) + return false; + + if (!pool.TakeAmmo(self, minelayer.Info.AmmoUsage)) + return false; + } + + minefield.Remove(self.Location); + self.World.AddFrameEndTask(w => { var mine = w.CreateActor(minelayer.Info.Mine, new TypeDictionary @@ -161,6 +210,8 @@ namespace OpenRA.Mods.Common.Activities foreach (var t in self.TraitsImplementing()) t.MineLaid(self, mine); }); + + return true; } } } diff --git a/OpenRA.Mods.Common/Traits/Minelayer.cs b/OpenRA.Mods.Common/Traits/Minelayer.cs index d90ea08ed6..cd314c70f5 100644 --- a/OpenRA.Mods.Common/Traits/Minelayer.cs +++ b/OpenRA.Mods.Common/Traits/Minelayer.cs @@ -63,6 +63,12 @@ namespace OpenRA.Mods.Common.Traits [Desc("Ammo the minelayer consumes per mine.")] public readonly int AmmoUsage = 1; + [Desc("Number of ticks it takes to lay a mine.")] + public readonly int PreLayDelay = 0; + + [Desc("Number of ticks for the minelayer to wait after laying a mine. The wait can be interrupted by a player order.")] + public readonly int AfterLayingDelay = 20; + public override object Create(ActorInitializer init) { return new Minelayer(init.Self, this); } } diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index af39012be5..218e889b9c 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -159,7 +159,12 @@ namespace OpenRA.Mods.Common.Traits public interface INotifyDelivery { void IncomingDelivery(Actor self); void Delivered(Actor self); } [RequireExplicitImplementation] - public interface INotifyMineLaying { void MineLaying(Actor self, CPos location); void MineLaid(Actor self, Actor mine); } + public interface INotifyMineLaying + { + void MineLaying(Actor self, CPos location); + void MineLaid(Actor self, Actor mine); + void MineLayingCanceled(Actor self, CPos location); + } [RequireExplicitImplementation] public interface INotifyDockHost { void Docked(Actor self, Actor client); void Undocked(Actor self, Actor client); }