Lay mines in order from start to end.
This commit is contained in:
@@ -32,25 +32,41 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
bool returnToBase;
|
bool returnToBase;
|
||||||
Actor rearmTarget;
|
Actor rearmTarget;
|
||||||
|
|
||||||
public LayMines(Actor self, CPos[] minefield)
|
public LayMines(Actor self, List<CPos> minefield = null)
|
||||||
{
|
{
|
||||||
minelayer = self.Trait<Minelayer>();
|
minelayer = self.Trait<Minelayer>();
|
||||||
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
|
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
|
||||||
movement = self.Trait<IMove>();
|
movement = self.Trait<IMove>();
|
||||||
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
|
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
|
||||||
|
this.minefield = minefield;
|
||||||
if (minefield != null)
|
ChildHasPriority = false;
|
||||||
this.minefield = minefield.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFirstRun(Actor self)
|
protected override void OnFirstRun(Actor self)
|
||||||
{
|
{
|
||||||
if (minefield == null)
|
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)
|
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;
|
returnToBase = false;
|
||||||
|
|
||||||
if (IsCanceling)
|
if (IsCanceling)
|
||||||
@@ -74,7 +90,7 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
return false;
|
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);
|
LayMine(self);
|
||||||
QueueChild(new Wait(20)); // A little wait after placing each mine, for show
|
QueueChild(new Wait(20)); // A little wait after placing each mine, for show
|
||||||
@@ -82,19 +98,12 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minefield != null && minefield.Count > 0)
|
var nextCell = NextValidCell(self);
|
||||||
|
if (nextCell != null)
|
||||||
{
|
{
|
||||||
// Don't get stuck forever here
|
QueueChild(movement.MoveTo(nextCell.Value, 0));
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Return somewhere likely to be safe (near rearm building) so we're not sitting out in the minefield.
|
// TODO: Return somewhere likely to be safe (near rearm building) so we're not sitting out in the minefield.
|
||||||
return true;
|
return true;
|
||||||
@@ -108,15 +117,17 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
if (minefield == null || minefield.Count == 0)
|
if (minefield == null || minefield.Count == 0)
|
||||||
yield break;
|
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)
|
foreach (var c in minefield)
|
||||||
yield return new TargetLineNode(Target.FromCell(self.World, c), Color.Crimson, tile: minelayer.Tile);
|
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);
|
return self.World.ActorMap.GetActorsAt(p).All(a => a == self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,8 +141,7 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
pool.TakeAmmo(self, 1);
|
pool.TakeAmmo(self, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.World.AddFrameEndTask(
|
self.World.AddFrameEndTask(w => w.CreateActor(minelayer.Info.Mine, new TypeDictionary
|
||||||
w => w.CreateActor(minelayer.Info.Mine, new TypeDictionary
|
|
||||||
{
|
{
|
||||||
new LocationInit(self.Location),
|
new LocationInit(self.Location),
|
||||||
new OwnerInit(self.Owner),
|
new OwnerInit(self.Owner),
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
{
|
{
|
||||||
public readonly MinelayerInfo Info;
|
public readonly MinelayerInfo Info;
|
||||||
|
|
||||||
// TODO: [Sync] when sync can cope with arrays!
|
|
||||||
public CPos[] Minefield = null;
|
|
||||||
|
|
||||||
public readonly Sprite Tile;
|
public readonly Sprite Tile;
|
||||||
|
|
||||||
[Sync]
|
[Sync]
|
||||||
@@ -104,15 +101,16 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
if (order.OrderString == "BeginMinefield")
|
if (order.OrderString == "BeginMinefield")
|
||||||
minefieldStart = cell;
|
minefieldStart = cell;
|
||||||
else if (order.OrderString == "PlaceMine")
|
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")
|
else if (order.OrderString == "PlaceMinefield")
|
||||||
{
|
{
|
||||||
var movement = self.Trait<IPositionable>();
|
var movement = self.Trait<IPositionable>();
|
||||||
|
|
||||||
Minefield = GetMinefieldCells(minefieldStart, cell, Info.MinefieldDepth)
|
var minefield = GetMinefieldCells(minefieldStart, cell, Info.MinefieldDepth)
|
||||||
.Where(p => movement.CanEnterCell(p, null, false)).ToArray();
|
.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();
|
self.ShowTargetLines();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user