Lay mines in order from start to end.

This commit is contained in:
Paul Chote
2019-08-16 22:40:45 +00:00
committed by teinarss
parent 3a51cf0ef8
commit 9aec48aec3
2 changed files with 41 additions and 33 deletions

View File

@@ -32,25 +32,41 @@ namespace OpenRA.Mods.Cnc.Activities
bool returnToBase;
Actor rearmTarget;
public LayMines(Actor self, CPos[] minefield)
public LayMines(Actor self, List<CPos> minefield = null)
{
minelayer = self.Trait<Minelayer>();
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
movement = self.Trait<IMove>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
if (minefield != null)
this.minefield = minefield.ToList();
this.minefield = minefield;
ChildHasPriority = false;
}
protected override void OnFirstRun(Actor self)
{
if (minefield == null)
minefield = new CPos[] { self.Location }.ToList();
minefield = new List<CPos> { self.Location };
}
CPos? NextValidCell(Actor self)
{
if (minefield != null)
foreach (var c in minefield)
if (CanLayMine(self, c))
return c;
return null;
}
public override bool Tick(Actor self)
{
// Remove cells that have already been mined
minefield.RemoveAll(c => self.World.ActorMap.GetActorsAt(c)
.Any(a => a.Info.Name == minelayer.Info.Mine.ToLowerInvariant()));
if (!TickChild(self))
return false;
returnToBase = false;
if (IsCanceling)
@@ -74,7 +90,7 @@ namespace OpenRA.Mods.Cnc.Activities
return false;
}
if ((minefield == null || minefield.Contains(self.Location)) && ShouldLayMine(self, self.Location))
if ((minefield == null || minefield.Contains(self.Location)) && CanLayMine(self, self.Location))
{
LayMine(self);
QueueChild(new Wait(20)); // A little wait after placing each mine, for show
@@ -82,18 +98,11 @@ namespace OpenRA.Mods.Cnc.Activities
return false;
}
if (minefield != null && minefield.Count > 0)
var nextCell = NextValidCell(self);
if (nextCell != null)
{
// Don't get stuck forever here
for (var n = 0; n < 20; n++)
{
var p = minefield.Random(self.World.SharedRandom);
if (ShouldLayMine(self, p))
{
QueueChild(movement.MoveTo(p, 0));
return false;
}
}
QueueChild(movement.MoveTo(nextCell.Value, 0));
return false;
}
// TODO: Return somewhere likely to be safe (near rearm building) so we're not sitting out in the minefield.
@@ -108,15 +117,17 @@ namespace OpenRA.Mods.Cnc.Activities
if (minefield == null || minefield.Count == 0)
yield break;
yield return new TargetLineNode(Target.FromCell(self.World, minefield[0]), Color.Crimson);
var nextCell = NextValidCell(self);
if (nextCell != null)
yield return new TargetLineNode(Target.FromCell(self.World, nextCell.Value), Color.Crimson);
foreach (var c in minefield)
yield return new TargetLineNode(Target.FromCell(self.World, c), Color.Crimson, tile: minelayer.Tile);
}
static bool ShouldLayMine(Actor self, CPos p)
static bool CanLayMine(Actor self, CPos p)
{
// If there is no unit (other than me) here, we want to place a mine here
// If there is no unit (other than me) here, we can place a mine here
return self.World.ActorMap.GetActorsAt(p).All(a => a == self);
}
@@ -130,12 +141,11 @@ namespace OpenRA.Mods.Cnc.Activities
pool.TakeAmmo(self, 1);
}
self.World.AddFrameEndTask(
w => w.CreateActor(minelayer.Info.Mine, new TypeDictionary
{
new LocationInit(self.Location),
new OwnerInit(self.Owner),
}));
self.World.AddFrameEndTask(w => w.CreateActor(minelayer.Info.Mine, new TypeDictionary
{
new LocationInit(self.Location),
new OwnerInit(self.Owner),
}));
}
}
}

View File

@@ -41,9 +41,6 @@ namespace OpenRA.Mods.Cnc.Traits
{
public readonly MinelayerInfo Info;
// TODO: [Sync] when sync can cope with arrays!
public CPos[] Minefield = null;
public readonly Sprite Tile;
[Sync]
@@ -104,15 +101,16 @@ namespace OpenRA.Mods.Cnc.Traits
if (order.OrderString == "BeginMinefield")
minefieldStart = cell;
else if (order.OrderString == "PlaceMine")
self.QueueActivity(order.Queued, new LayMines(self, null));
self.QueueActivity(order.Queued, new LayMines(self));
else if (order.OrderString == "PlaceMinefield")
{
var movement = self.Trait<IPositionable>();
Minefield = GetMinefieldCells(minefieldStart, cell, Info.MinefieldDepth)
.Where(p => movement.CanEnterCell(p, null, false)).ToArray();
var minefield = GetMinefieldCells(minefieldStart, cell, Info.MinefieldDepth)
.Where(c => movement.CanEnterCell(c, null, false))
.OrderBy(c => (c - minefieldStart).LengthSquared).ToList();
self.QueueActivity(order.Queued, new LayMines(self, Minefield));
self.QueueActivity(order.Queued, new LayMines(self, minefield));
self.ShowTargetLines();
}
}