Pathing considers reachability of source cells consistently.

Using the local pathfinder, you could not find a path to an unreachable destination cell, but it was possible to find a path from an unreachable source cell if there was a reachable cells adjacent to it.

The hierarchical pathfinder did not have this behaviour and considering an unreachable source cell to block attempts to find a path.

Now, we unify the pathfinders to use a consistent behaviour, allowing paths from unreachable source cells to be found.
This commit is contained in:
RoosterDragon
2022-10-25 20:23:53 +01:00
committed by abcdefg30
parent bedfa622d7
commit a85ac26367
6 changed files with 145 additions and 60 deletions

View File

@@ -211,10 +211,8 @@ namespace OpenRA.Mods.Common.Traits
bool CanEnterCell(Actor self, CPos cell)
{
if (mobile.locomotor.MovementCostForCell(cell) == PathGraph.MovementCostForUnreachableCell)
return false;
return mobile.locomotor.CanMoveFreelyInto(self, cell, BlockedByActor.All, null);
return mobile.locomotor.MovementCostToEnterCell(
self, cell, BlockedByActor.All, null) != PathGraph.MovementCostForUnreachableCell;
}
}
}

View File

@@ -124,10 +124,8 @@ namespace OpenRA.Mods.Common.Traits
locomotor = world.WorldActor.TraitsImplementing<Locomotor>()
.SingleOrDefault(l => l.Info.Name == Locomotor);
if (locomotor.MovementCostForCell(cell) == PathGraph.MovementCostForUnreachableCell)
return false;
return locomotor.CanMoveFreelyInto(self, cell, subCell, check, ignoreActor);
return locomotor.MovementCostToEnterCell(
self, cell, check, ignoreActor, subCell) != PathGraph.MovementCostForUnreachableCell;
}
public bool CanStayInCell(World world, CPos cell)

View File

@@ -204,24 +204,30 @@ namespace OpenRA.Mods.Common.Traits
return terrainInfos[index].Speed;
}
public short MovementCostToEnterCell(Actor actor, CPos destNode, BlockedByActor check, Actor ignoreActor, SubCell subCell = SubCell.FullCell)
{
var cellCost = MovementCostForCell(destNode);
if (cellCost == PathGraph.MovementCostForUnreachableCell ||
!CanMoveFreelyInto(actor, destNode, subCell, check, ignoreActor))
return PathGraph.MovementCostForUnreachableCell;
return cellCost;
}
public short MovementCostToEnterCell(Actor actor, CPos srcNode, CPos destNode, BlockedByActor check, Actor ignoreActor)
{
var cellCost = MovementCostForCell(destNode, srcNode);
if (cellCost == PathGraph.MovementCostForUnreachableCell ||
!CanMoveFreelyInto(actor, destNode, check, ignoreActor))
!CanMoveFreelyInto(actor, destNode, SubCell.FullCell, check, ignoreActor))
return PathGraph.MovementCostForUnreachableCell;
return cellCost;
}
// Determines whether the actor is blocked by other Actors
public bool CanMoveFreelyInto(Actor actor, CPos cell, BlockedByActor check, Actor ignoreActor)
{
return CanMoveFreelyInto(actor, cell, SubCell.FullCell, check, ignoreActor);
}
public bool CanMoveFreelyInto(Actor actor, CPos cell, SubCell subCell, BlockedByActor check, Actor ignoreActor)
bool CanMoveFreelyInto(Actor actor, CPos cell, SubCell subCell, BlockedByActor check, Actor ignoreActor)
{
// If the check allows: We are not blocked by other actors.
if (check == BlockedByActor.None)

View File

@@ -93,11 +93,9 @@ namespace OpenRA.Mods.Common.Traits
var locomotor = GetActorLocomotor(self);
// If the target cell is inaccessible, bail early.
var inaccessible =
!world.Map.Contains(target) ||
!locomotor.CanMoveFreelyInto(self, target, check, ignoreActor) ||
(customCost != null && customCost(target) == PathGraph.PathCostForInvalidPath);
if (inaccessible)
// The destination cell must allow movement and also have a reachable movement cost.
if (!PathSearch.CellAllowsMovement(self.World, locomotor, target, customCost)
|| locomotor.MovementCostToEnterCell(self, target, check, ignoreActor) == PathGraph.MovementCostForUnreachableCell)
return NoPath;
// When searching from only one source cell, some optimizations are possible.
@@ -109,8 +107,8 @@ namespace OpenRA.Mods.Common.Traits
if (source.Layer == target.Layer && (source - target).LengthSquared < 3)
{
// If the source cell is inaccessible, there is no path.
if (!world.Map.Contains(source) ||
(customCost != null && customCost(source) == PathGraph.PathCostForInvalidPath))
// Unlike the destination cell, the source cell is allowed to have an unreachable movement cost.
if (!PathSearch.CellAllowsMovement(self.World, locomotor, source, customCost))
return NoPath;
return new List<CPos>(2) { target, source };
}