Factor logic for determining if an actor blocks movement into IsBlockedBy.

This commit is contained in:
RoosterDragon
2015-08-18 21:43:22 +01:00
parent 6414743f8e
commit ca75b5af30

View File

@@ -198,32 +198,42 @@ namespace OpenRA.Mods.Common.Traits
return true;
if (check.HasCellCondition(CellConditions.TransientActors))
{
var canIgnoreMovingAllies = self != null && !check.HasCellCondition(CellConditions.BlockedByMovers);
var needsCellExclusively = self == null || Crushes == null || !Crushes.Any();
foreach (var a in world.ActorMap.GetUnitsAt(cell))
{
if (a == ignoreActor)
continue;
// Neutral/enemy units are blockers. Allied units that are moving are not blockers.
if (canIgnoreMovingAllies && self.Owner.Stances[a.Owner] == Stance.Ally && IsMovingInMyDirection(self, a)) continue;
// Non-sharable unit can enter a cell with shareable units only if it can crush all of them.
if (needsCellExclusively)
foreach (var otherActor in world.ActorMap.GetUnitsAt(cell))
if (IsBlockedBy(self, otherActor, ignoreActor, check))
return false;
var crushables = a.TraitsImplementing<ICrushable>();
if (!crushables.Any())
return false;
foreach (var crushable in crushables)
if (!crushable.CrushableBy(Crushes, self.Owner))
return false;
}
}
return true;
}
bool IsBlockedBy(Actor self, Actor otherActor, Actor ignoreActor, CellConditions check)
{
// We are not blocked by the actor we are ignoring.
if (otherActor == ignoreActor)
return false;
// If the check allows: we are not blocked by allied units moving in our direction.
if (!check.HasCellCondition(CellConditions.BlockedByMovers) &&
self != null &&
self.Owner.Stances[otherActor.Owner] == Stance.Ally &&
IsMovingInMyDirection(self, otherActor))
return false;
// If we cannot crush the other actor in our way, we are blocked.
if (self == null || Crushes == null || Crushes.Length == 0)
return true;
// If the other actor in our way cannot be crushed, we are blocked.
var crushables = otherActor.TraitsImplementing<ICrushable>();
if (!crushables.Any())
return true;
foreach (var crushable in crushables)
if (!crushable.CrushableBy(Crushes, self.Owner))
return true;
// We are not blocked by the other actor.
return false;
}
public bool CanEnterCell(World world, Actor self, CPos cell, out int movementCost, Actor ignoreActor = null, CellConditions check = CellConditions.All)
{
if ((movementCost = MovementCostForCell(world, cell)) == int.MaxValue)
@@ -240,30 +250,7 @@ namespace OpenRA.Mods.Common.Traits
if (check.HasCellCondition(CellConditions.TransientActors))
{
var canIgnoreMovingAllies = self != null && !check.HasCellCondition(CellConditions.BlockedByMovers);
var needsCellExclusively = self == null || Crushes == null || !Crushes.Any();
Func<Actor, bool> checkTransient = a =>
{
if (a == ignoreActor)
return false;
// Neutral/enemy units are blockers. Allied units that are moving are not blockers.
if (canIgnoreMovingAllies && self.Owner.Stances[a.Owner] == Stance.Ally && IsMovingInMyDirection(self, a))
return false;
// Non-sharable unit can enter a cell with shareable units only if it can crush all of them.
if (needsCellExclusively)
return true;
var crushables = a.TraitsImplementing<ICrushable>();
if (!crushables.Any())
return true;
foreach (var crushable in crushables)
if (!crushable.CrushableBy(Crushes, self.Owner))
return true;
return false;
};
Func<Actor, bool> checkTransient = otherActor => IsBlockedBy(self, otherActor, ignoreActor, check);
if (!SharesCell)
return world.ActorMap.AnyUnitsAt(cell, SubCell.FullCell, checkTransient) ? SubCell.Invalid : SubCell.FullCell;