diff --git a/OpenRA.Mods.Cnc/Activities/LayMines.cs b/OpenRA.Mods.Cnc/Activities/LayMines.cs index 999bded40a..d427d56baa 100644 --- a/OpenRA.Mods.Cnc/Activities/LayMines.cs +++ b/OpenRA.Mods.Cnc/Activities/LayMines.cs @@ -100,12 +100,17 @@ namespace OpenRA.Mods.Cnc.Activities return true; } - public void CleanPlacedMines(Actor self) + public void CleanMineField(Actor self) { // Remove cells that have already been mined + // or that are revealed to be unmineable. if (minefield != null) + { + var positionable = (IPositionable)movement; minefield.RemoveAll(c => self.World.ActorMap.GetActorsAt(c) - .Any(a => a.Info.Name == minelayer.Info.Mine.ToLowerInvariant())); + .Any(a => a.Info.Name == minelayer.Info.Mine.ToLowerInvariant()) || + (!positionable.CanEnterCell(c, null, BlockedByActor.Immovable) && !self.World.FogObscures(c))); + } } public override IEnumerable TargetLineNodes(Actor self) diff --git a/OpenRA.Mods.Cnc/Traits/Minelayer.cs b/OpenRA.Mods.Cnc/Traits/Minelayer.cs index 47d6c8162a..6a5f84dfc9 100644 --- a/OpenRA.Mods.Cnc/Traits/Minelayer.cs +++ b/OpenRA.Mods.Cnc/Traits/Minelayer.cs @@ -34,6 +34,15 @@ namespace OpenRA.Mods.Cnc.Traits [Desc("Voice to use when ordered to lay a minefield.")] public readonly string Voice = "Action"; + [Desc("Sprite overlay to use for valid minefield cells.")] + public readonly string TileValidName = "build-valid"; + + [Desc("Sprite overlay to use for invalid minefield cells.")] + public readonly string TileInvalidName = "build-invalid"; + + [Desc("Sprite overlay to use for minefield cells hidden behind fog or shroud.")] + public readonly string TileUnknownName = "build-unknown"; + public object Create(ActorInitializer init) { return new Minelayer(init.Self, this); } } @@ -49,12 +58,11 @@ namespace OpenRA.Mods.Cnc.Traits public Minelayer(Actor self, MinelayerInfo info) { Info = info; - var tileset = self.World.Map.Tileset.ToLowerInvariant(); - if (self.World.Map.Rules.Sequences.HasSequence("overlay", "build-valid-{0}".F(tileset))) - Tile = self.World.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0); + if (self.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(Info.TileValidName, tileset))) + Tile = self.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(Info.TileValidName, tileset)).GetSprite(0); else - Tile = self.World.Map.Rules.Sequences.GetSequence("overlay", "build-valid").GetSprite(0); + Tile = self.World.Map.Rules.Sequences.GetSequence("overlay", Info.TileValidName).GetSprite(0); } IEnumerable IIssueOrder.Orders @@ -107,7 +115,7 @@ namespace OpenRA.Mods.Cnc.Traits var movement = self.Trait(); var minefield = GetMinefieldCells(minefieldStart, cell, Info.MinefieldDepth) - .Where(c => movement.CanEnterCell(c, null, BlockedByActor.None)) + .Where(c => movement.CanEnterCell(c, null, BlockedByActor.Immovable) || self.World.FogObscures(c)) .OrderBy(c => (c - minefieldStart).LengthSquared).ToList(); self.QueueActivity(order.Queued, new LayMines(self, minefield)); @@ -119,7 +127,7 @@ namespace OpenRA.Mods.Cnc.Traits { if (self.CurrentActivity != null) foreach (var field in self.CurrentActivity.ActivitiesImplementing()) - field.CleanPlacedMines(self); + field.CleanMineField(self); } string IOrderVoice.VoicePhraseForOrder(Actor self, Order order) @@ -153,6 +161,7 @@ namespace OpenRA.Mods.Cnc.Traits { readonly List minelayers; readonly Sprite tileOk; + readonly Sprite tileUnknown; readonly Sprite tileBlocked; readonly CPos minefieldStart; readonly bool queued; @@ -163,13 +172,22 @@ namespace OpenRA.Mods.Cnc.Traits minefieldStart = xy; this.queued = queued; + var minelayer = a.Trait(); var tileset = a.World.Map.Tileset.ToLowerInvariant(); - if (a.World.Map.Rules.Sequences.HasSequence("overlay", "build-valid-{0}".F(tileset))) - tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0); + if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileValidName, tileset))) + tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileValidName, tileset)).GetSprite(0); else - tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", "build-valid").GetSprite(0); + tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileValidName).GetSprite(0); - tileBlocked = a.World.Map.Rules.Sequences.GetSequence("overlay", "build-invalid").GetSprite(0); + if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileUnknownName, tileset))) + tileUnknown = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileUnknownName, tileset)).GetSprite(0); + else + tileUnknown = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileUnknownName).GetSprite(0); + + if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileInvalidName, tileset))) + tileBlocked = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileInvalidName, tileset)).GetSprite(0); + else + tileBlocked = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileInvalidName).GetSprite(0); } public void AddMinelayer(Actor a, CPos xy) @@ -216,7 +234,12 @@ namespace OpenRA.Mods.Cnc.Traits var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var c in minefield) { - var tile = movement.CanEnterCell(c, null, BlockedByActor.None) && !world.ShroudObscures(c) ? tileOk : tileBlocked; + var tile = tileOk; + if (world.FogObscures(c)) + tile = tileUnknown; + else if (!movement.CanEnterCell(c, null, BlockedByActor.Immovable)) + tile = tileBlocked; + yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c), WVec.Zero, -511, pal, 1f, true); } diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index 133ff379fc..c7730a7ba6 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -499,6 +499,7 @@ MNLY: Range: 4c0 Minelayer: Mine: MINV + TileUnknownName: build-valid MineImmune: AmmoPool: Ammo: 5