Disallow units idling on service depot.
This commit is contained in:
@@ -146,7 +146,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
if (evaluateNearestMovableCell && destination.HasValue)
|
||||
{
|
||||
var movableDestination = mobile.NearestMoveableCell(destination.Value);
|
||||
destination = mobile.CanEnterCell(movableDestination) ? movableDestination : (CPos?)null;
|
||||
destination = mobile.CanEnterCell(movableDestination, check: BlockedByActor.Immovable) ? movableDestination : (CPos?)null;
|
||||
}
|
||||
|
||||
path = EvalPath(BlockedByActor.Stationary);
|
||||
@@ -160,8 +160,13 @@ namespace OpenRA.Mods.Common.Activities
|
||||
|
||||
// If the actor is inside a tunnel then we must let them move
|
||||
// all the way through before moving to the next activity
|
||||
if (IsCanceling && self.Location.Layer != CustomMovementLayerType.Tunnel)
|
||||
if (IsCanceling && self.Location.Layer != CustomMovementLayerType.Tunnel && mobile.CanStayInCell(mobile.ToCell))
|
||||
{
|
||||
if (path != null)
|
||||
path.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mobile.IsTraitDisabled || mobile.IsTraitPaused)
|
||||
return false;
|
||||
@@ -225,7 +230,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
{
|
||||
// Are we close enough?
|
||||
var cellRange = nearEnough.Length / 1024;
|
||||
if (!containsTemporaryBlocker && (mobile.ToCell - destination.Value).LengthSquared <= cellRange * cellRange)
|
||||
if (!containsTemporaryBlocker && (mobile.ToCell - destination.Value).LengthSquared <= cellRange * cellRange && mobile.CanStayInCell(mobile.ToCell))
|
||||
{
|
||||
path.Clear();
|
||||
return null;
|
||||
@@ -312,7 +317,9 @@ namespace OpenRA.Mods.Common.Activities
|
||||
|
||||
public override void Cancel(Actor self, bool keepQueue = false)
|
||||
{
|
||||
if (path != null)
|
||||
// We need to clear the path here in order to prevent MovePart queueing new instances of itself
|
||||
// when the unit is making a turn.
|
||||
if (path != null && mobile.CanStayInCell(mobile.ToCell))
|
||||
path.Clear();
|
||||
|
||||
base.Cancel(self, keepQueue);
|
||||
|
||||
@@ -23,7 +23,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Empty = '_',
|
||||
OccupiedPassable = '=',
|
||||
Occupied = 'x',
|
||||
OccupiedUntargetable = 'X'
|
||||
OccupiedUntargetable = 'X',
|
||||
OccupiedPassableTransitOnly = '+'
|
||||
}
|
||||
|
||||
public class BuildingInfo : ITraitInfo, IOccupySpaceInfo, IPlaceBuildingDecorationInfo
|
||||
@@ -107,6 +108,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedUntargetable))
|
||||
yield return t;
|
||||
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedPassableTransitOnly))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> FrozenUnderFogTiles(CPos location)
|
||||
@@ -118,13 +122,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> UnpathableTiles(CPos location)
|
||||
public IEnumerable<CPos> OccupiedTiles(CPos location)
|
||||
{
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.Occupied))
|
||||
yield return t;
|
||||
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedUntargetable))
|
||||
yield return t;
|
||||
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedPassableTransitOnly))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> PathableTiles(CPos location)
|
||||
@@ -136,6 +143,12 @@ namespace OpenRA.Mods.Common.Traits
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> TransitOnlyTiles(CPos location)
|
||||
{
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedPassableTransitOnly))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public WVec CenterOffset(World w)
|
||||
{
|
||||
var off = (w.Map.CenterOfCell(new CPos(Dimensions.X, Dimensions.Y)) - w.Map.CenterOfCell(new CPos(1, 1))) / 2;
|
||||
@@ -225,7 +238,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos topLeft, SubCell subCell = SubCell.Any)
|
||||
{
|
||||
var occupied = UnpathableTiles(topLeft)
|
||||
var occupied = OccupiedTiles(topLeft)
|
||||
.ToDictionary(c => c, c => SubCell.FullCell);
|
||||
|
||||
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
|
||||
@@ -255,6 +268,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
Pair<CPos, SubCell>[] occupiedCells;
|
||||
Pair<CPos, SubCell>[] targetableCells;
|
||||
CPos[] transitOnlyCells;
|
||||
|
||||
public CPos TopLeft { get { return topLeft; } }
|
||||
public WPos CenterPosition { get; private set; }
|
||||
@@ -266,17 +280,21 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Info = info;
|
||||
influence = self.World.WorldActor.Trait<BuildingInfluence>();
|
||||
|
||||
occupiedCells = Info.UnpathableTiles(TopLeft)
|
||||
occupiedCells = Info.OccupiedTiles(TopLeft)
|
||||
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray();
|
||||
|
||||
targetableCells = Info.FootprintTiles(TopLeft, FootprintCellType.Occupied)
|
||||
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray();
|
||||
|
||||
transitOnlyCells = Info.TransitOnlyTiles(TopLeft).ToArray();
|
||||
|
||||
CenterPosition = init.World.Map.CenterOfCell(topLeft) + Info.CenterOffset(init.World);
|
||||
}
|
||||
|
||||
public Pair<CPos, SubCell>[] OccupiedCells() { return occupiedCells; }
|
||||
|
||||
public CPos[] TransitOnlyCells() { return transitOnlyCells; }
|
||||
|
||||
Pair<CPos, SubCell>[] ITargetableCells.TargetableCells() { return targetableCells; }
|
||||
|
||||
void INotifyAddedToWorld.AddedToWorld(Actor self)
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
if (Info.Type == ExplosionType.Footprint && buildingInfo != null)
|
||||
{
|
||||
var cells = buildingInfo.UnpathableTiles(self.Location);
|
||||
var cells = buildingInfo.OccupiedTiles(self.Location);
|
||||
foreach (var c in cells)
|
||||
weapon.Impact(Target.FromPos(self.World.Map.CenterOfCell(c)), source, Enumerable.Empty<int>());
|
||||
|
||||
|
||||
@@ -102,6 +102,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return locomotor.CanMoveFreelyInto(self, cell, subCell, check, ignoreActor);
|
||||
}
|
||||
|
||||
public bool CanStayInCell(World world, CPos cell)
|
||||
{
|
||||
// PERF: Avoid repeated trait queries on the hot path
|
||||
if (locomotor == null)
|
||||
locomotor = world.WorldActor.TraitsImplementing<Locomotor>()
|
||||
.SingleOrDefault(l => l.Info.Name == Locomotor);
|
||||
|
||||
return locomotor.CanStayInCell(cell);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)
|
||||
{
|
||||
return new ReadOnlyDictionary<CPos, SubCell>(new Dictionary<CPos, SubCell>() { { location, subCell } });
|
||||
@@ -363,7 +373,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
foreach (CVec direction in CVec.Directions)
|
||||
{
|
||||
var p = ToCell + direction;
|
||||
if (CanEnterCell(p))
|
||||
if (CanEnterCell(p) && CanStayInCell(p))
|
||||
availCells.Add(p);
|
||||
else if (p != nextCell && p != ToCell)
|
||||
notStupidCells.Add(p);
|
||||
@@ -507,6 +517,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return Info.CanEnterCell(self.World, self, cell, ToSubCell, ignoreActor, check);
|
||||
}
|
||||
|
||||
public bool CanStayInCell(CPos cell)
|
||||
{
|
||||
return Info.CanStayInCell(self.World, cell);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Local IPositionable-related
|
||||
@@ -666,6 +681,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
QueueChild(mobile.VisualMove(self, pos, self.World.Map.CenterOfSubCell(cell, subCell)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Cancel(Actor self, bool keepQueue = false)
|
||||
{
|
||||
// If we are forbidden from stopping in this cell, use evaluateNearestMovableCell
|
||||
// to nudge us to the nearest cell that we can stop in.
|
||||
if (!mobile.CanStayInCell(cell))
|
||||
QueueChild(new Move(self, cell, WDist.Zero, null, true));
|
||||
|
||||
base.Cancel(self, keepQueue);
|
||||
}
|
||||
}
|
||||
|
||||
public Activity MoveToTarget(Actor self, Target target,
|
||||
@@ -743,11 +768,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (target.Layer != 0)
|
||||
target = new CPos(target.X, target.Y);
|
||||
|
||||
if (CanEnterCell(target))
|
||||
if (target == self.Location && CanStayInCell(target))
|
||||
return target;
|
||||
|
||||
if (CanEnterCell(target, check: BlockedByActor.Immovable) && CanStayInCell(target))
|
||||
return target;
|
||||
|
||||
foreach (var tile in self.World.Map.FindTilesInAnnulus(target, minRange, maxRange))
|
||||
if (CanEnterCell(tile))
|
||||
if (CanEnterCell(tile, check: BlockedByActor.Immovable) && CanStayInCell(tile))
|
||||
return tile;
|
||||
|
||||
// Couldn't find a cell
|
||||
|
||||
@@ -27,7 +27,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
HasStationaryActor = 2,
|
||||
HasMovableActor = 4,
|
||||
HasCrushableActor = 8,
|
||||
HasTemporaryBlocker = 16
|
||||
HasTemporaryBlocker = 16,
|
||||
HasTransitOnlyActor = 32,
|
||||
}
|
||||
|
||||
public static class LocomoterExts
|
||||
@@ -309,6 +310,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanStayInCell(CPos cell)
|
||||
{
|
||||
return !GetCache(cell).CellFlag.HasCellFlag(CellFlag.HasTransitOnlyActor);
|
||||
}
|
||||
|
||||
public SubCell GetAvailableSubCell(Actor self, CPos cell, BlockedByActor check, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null)
|
||||
{
|
||||
if (MovementCostForCell(cell) == short.MaxValue)
|
||||
@@ -496,6 +502,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var isMovable = mobile != null && !mobile.IsTraitDisabled && !mobile.IsTraitPaused && !mobile.IsImmovable;
|
||||
var isMoving = isMovable && mobile.CurrentMovementTypes.HasMovementType(MovementType.Horizontal);
|
||||
|
||||
var building = actor.OccupiesSpace as Building;
|
||||
var isTransitOnly = building != null && building.TransitOnlyCells().Contains(cell);
|
||||
|
||||
if (isTransitOnly)
|
||||
{
|
||||
cellFlag |= CellFlag.HasTransitOnlyActor;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crushables.Any())
|
||||
{
|
||||
cellFlag |= CellFlag.HasCrushableActor;
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
buildBlocked = sequences.GetSequence("overlay", "build-invalid").GetSprite(0);
|
||||
|
||||
var buildingInfo = ai.TraitInfo<BuildingInfo>();
|
||||
unpathableCells = new CachedTransform<CPos, List<CPos>>(topLeft => buildingInfo.UnpathableTiles(topLeft).ToList());
|
||||
unpathableCells = new CachedTransform<CPos, List<CPos>>(topLeft => buildingInfo.OccupiedTiles(topLeft).ToList());
|
||||
}
|
||||
|
||||
protected override IEnumerable<IRenderable> RenderFootprint(WorldRenderer wr, CPos topLeft, Dictionary<CPos, PlaceBuildingCellType> footprint,
|
||||
|
||||
@@ -678,7 +678,7 @@ FIX:
|
||||
Queue: Building.GDI, Building.Nod
|
||||
Description: Repairs vehicles
|
||||
Building:
|
||||
Footprint: _=_ === _=_
|
||||
Footprint: _+_ +++ _+_
|
||||
Dimensions: 3,3
|
||||
Selectable:
|
||||
Bounds: 64,34,0,3
|
||||
|
||||
@@ -881,7 +881,7 @@ repair_pad:
|
||||
Tooltip:
|
||||
Name: Repair Pad
|
||||
Building:
|
||||
Footprint: === === ===
|
||||
Footprint: +++ +++ +++
|
||||
Dimensions: 3,3
|
||||
Health:
|
||||
HP: 30000
|
||||
|
||||
@@ -1989,7 +1989,7 @@ FIX:
|
||||
Tooltip:
|
||||
Name: Service Depot
|
||||
Building:
|
||||
Footprint: _=_ === _=_
|
||||
Footprint: _+_ +++ _+_
|
||||
Dimensions: 3,3
|
||||
Selectable:
|
||||
Bounds: 68,34,0,3
|
||||
|
||||
@@ -320,7 +320,7 @@ GADEPT:
|
||||
Queue: Building
|
||||
Description: Repairs vehicles.
|
||||
Building:
|
||||
Footprint: === x== x==
|
||||
Footprint: =+= x++ x+=
|
||||
Dimensions: 3,3
|
||||
Selectable:
|
||||
Bounds: 96, 64, -6, -6
|
||||
|
||||
Reference in New Issue
Block a user