diff --git a/OpenRA.Mods.D2k/AttackSwallow.cs b/OpenRA.Mods.D2k/AttackSwallow.cs index 9e04d0ceb0..0732f0fa9a 100644 --- a/OpenRA.Mods.D2k/AttackSwallow.cs +++ b/OpenRA.Mods.D2k/AttackSwallow.cs @@ -17,9 +17,10 @@ namespace OpenRA.Mods.D2k class AttackSwallowInfo : AttackFrontalInfo { [Desc("The number of ticks it takes to return underground.")] - public int ReturnTime = 60; + public readonly int ReturnTime = 60; + [Desc("The number of ticks it takes to get in place under the target to attack.")] - public int AttackTime = 30; + public readonly int AttackTime = 30; public readonly string WormAttackNotification = "WormAttack"; diff --git a/OpenRA.Mods.D2k/SwallowActor.cs b/OpenRA.Mods.D2k/SwallowActor.cs index 01b5688cb9..e581fbb571 100644 --- a/OpenRA.Mods.D2k/SwallowActor.cs +++ b/OpenRA.Mods.D2k/SwallowActor.cs @@ -55,12 +55,14 @@ namespace OpenRA.Mods.D2k bool WormAttack(Actor worm) { var targetLocation = target.Actor.Location; + // The target has moved too far away if ((location - targetLocation).Length > NearEnough) return false; var lunch = worm.World.ActorMap.GetUnitsAt(targetLocation) .Where(t => !t.Equals(worm) && weapon.IsValidAgainst(t, worm)); + if (!lunch.Any()) return false; @@ -100,31 +102,33 @@ namespace OpenRA.Mods.D2k return this; } - if (stance == AttackState.ReturningUnderground) // Wait for the worm to get back underground + // Wait for the worm to get back underground + if (stance == AttackState.ReturningUnderground) { - if (self.World.SharedRandom.Next() % 2 == 0) // There is a 50-50 chance that the worm would just go away + // There is a 50-50 chance that the worm would just go away + if (self.World.SharedRandom.Next() % 2 == 0) { self.CancelActivity(); self.World.AddFrameEndTask(w => w.Remove(self)); + var wormManager = self.World.WorldActor.TraitOrDefault(); if (wormManager != null) wormManager.DecreaseWorms(); } else - { renderUnit.DefaultAnimation.ReplaceAnim("idle"); - } + return NextActivity; } - if (stance == AttackState.Burrowed) // Wait for the worm to get in position + // Wait for the worm to get in position + if (stance == AttackState.Burrowed) { // This is so that the worm cancels an attack against a target that has reached solid rock if (!positionable.CanEnterCell(target.Actor.Location, null, false)) return NextActivity; - var success = WormAttack(self); - if (!success) + if (!WormAttack(self)) { renderUnit.DefaultAnimation.ReplaceAnim("idle"); return NextActivity; diff --git a/OpenRA.Mods.D2k/WormManager.cs b/OpenRA.Mods.D2k/WormManager.cs index 867d68e5c8..deb74aca5c 100644 --- a/OpenRA.Mods.D2k/WormManager.cs +++ b/OpenRA.Mods.D2k/WormManager.cs @@ -40,12 +40,13 @@ namespace OpenRA.Mods.D2k class WormManager : ITick { - int countdown; - int wormsPresent; readonly WormManagerInfo info; readonly Lazy spawnPoints; readonly Lazy radarPings; + int countdown; + int wormsPresent; + public WormManager(WormManagerInfo info, Actor self) { this.info = info; @@ -72,9 +73,12 @@ namespace OpenRA.Mods.D2k var wormLocations = new List(); - wormLocations.Add(SpawnWorm(self)); - while (wormsPresent < info.Minimum) + do + { + // Always spawn at least one worm, plus however many + // more we need to reach the defined minimum count. wormLocations.Add(SpawnWorm(self)); + } while (wormsPresent < info.Minimum); AnnounceWormSign(self, wormLocations); } @@ -87,6 +91,7 @@ namespace OpenRA.Mods.D2k new OwnerInit(w.Players.First(x => x.PlayerName == info.WormOwnerPlayer)), new LocationInit(spawnPoint.Location) })); + wormsPresent++; return spawnPoint.CenterPosition; @@ -112,7 +117,6 @@ namespace OpenRA.Mods.D2k foreach (var wormLocation in wormLocations) radarPings.Value.Add(() => true, wormLocation, Color.Red, 50); - } } diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index 89ba53efc7..a1bf0f5abe 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -145,11 +145,8 @@ namespace OpenRA.Mods.RA public bool HasAnyValidWeapons(Target t) { - if (Info.AttackRequiresEnteringCell) - { - if (!positionable.Value.CanEnterCell(t.Actor.Location, null, false)) - return false; - } + if (Info.AttackRequiresEnteringCell && !positionable.Value.CanEnterCell(t.Actor.Location, null, false)) + return false; return Armaments.Any(a => a.Weapon.IsValidAgainst(t, self.World, self)); } diff --git a/OpenRA.Mods.RA/Attack/AttackWander.cs b/OpenRA.Mods.RA/Attack/AttackWander.cs index b9174fe3e2..e3c4f4b2ce 100644 --- a/OpenRA.Mods.RA/Attack/AttackWander.cs +++ b/OpenRA.Mods.RA/Attack/AttackWander.cs @@ -27,14 +27,15 @@ namespace OpenRA.Mods.RA class AttackWander : INotifyIdle { + readonly AttackMove attackMove; + readonly AttackWanderInfo info; + int ticksIdle; int effectiveMoveRadius; - readonly AttackMove attackMove; - readonly AttackWanderInfo Info; public AttackWander(Actor self, AttackWanderInfo info) { - Info = info; + this.info = info; effectiveMoveRadius = info.WanderMoveRadius; attackMove = self.TraitOrDefault(); } @@ -47,16 +48,16 @@ namespace OpenRA.Mods.RA if (!self.World.Map.Contains(targetCell)) { // If MoveRadius is too big there might not be a valid cell to order the attack to (if actor is on a small island and can't leave) - if (++ticksIdle % Info.MoveReductionRadiusScale == 0) + if (++ticksIdle % info.MoveReductionRadiusScale == 0) effectiveMoveRadius--; - return; // We'll be back the next tick; better to sit idle for a few seconds than prolongue this tick indefinitely with a loop + return; // We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop } attackMove.ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = targetCell }); ticksIdle = 0; - effectiveMoveRadius = Info.WanderMoveRadius; + effectiveMoveRadius = info.WanderMoveRadius; } } }