Allow units to give way when path is blocked by oncoming unit.

This commit is contained in:
tovl
2019-04-12 19:26:22 +02:00
committed by RoosterDragon
parent 32309bb8ea
commit 4a609bbee8
25 changed files with 309 additions and 184 deletions

View File

@@ -30,37 +30,47 @@ namespace OpenRA.Mods.Common.Pathfinder
this.cacheStorage = cacheStorage;
}
public List<CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor)
public List<CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor, BlockedByActor check)
{
using (new PerfSample("Pathfinder"))
{
var key = "FindUnitPath" + self.ActorID + source.X + source.Y + target.X + target.Y;
var cachedPath = cacheStorage.Retrieve(key);
if (cachedPath != null)
return cachedPath;
// Only cache path when transient actors are ignored, otherwise there is no guarantee that the path
// is still valid at the next check.
if (check == BlockedByActor.None)
{
var cachedPath = cacheStorage.Retrieve(key);
if (cachedPath != null)
return cachedPath;
}
var pb = pathFinder.FindUnitPath(source, target, self, ignoreActor);
var pb = pathFinder.FindUnitPath(source, target, self, ignoreActor, check);
cacheStorage.Store(key, pb);
if (check == BlockedByActor.None)
cacheStorage.Store(key, pb);
return pb;
}
}
public List<CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WDist range, Actor self)
public List<CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WDist range, Actor self, BlockedByActor check)
{
using (new PerfSample("Pathfinder"))
{
var key = "FindUnitPathToRange" + self.ActorID + source.X + source.Y + target.X + target.Y;
var cachedPath = cacheStorage.Retrieve(key);
if (cachedPath != null)
return cachedPath;
if (check == BlockedByActor.None)
{
var cachedPath = cacheStorage.Retrieve(key);
if (cachedPath != null)
return cachedPath;
}
var pb = pathFinder.FindUnitPathToRange(source, srcSub, target, range, self);
var pb = pathFinder.FindUnitPathToRange(source, srcSub, target, range, self, check);
cacheStorage.Store(key, pb);
if (check == BlockedByActor.None)
cacheStorage.Store(key, pb);
return pb;
}

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Pathfinder
{
@@ -82,7 +83,7 @@ namespace OpenRA.Mods.Common.Pathfinder
public bool InReverse { get; set; }
public Actor IgnoreActor { get; set; }
readonly CellConditions checkConditions;
readonly BlockedByActor checkConditions;
readonly Locomotor locomotor;
readonly LocomotorInfo.WorldMovementInfo worldMovementInfo;
readonly CellInfoLayerPool.PooledCellInfoLayer pooledLayer;
@@ -92,7 +93,7 @@ namespace OpenRA.Mods.Common.Pathfinder
readonly Dictionary<byte, Pair<ICustomMovementLayer, CellLayer<CellInfo>>> customLayerInfo =
new Dictionary<byte, Pair<ICustomMovementLayer, CellLayer<CellInfo>>>();
public PathGraph(CellInfoLayerPool layerPool, Locomotor locomotor, Actor actor, World world, bool checkForBlocked)
public PathGraph(CellInfoLayerPool layerPool, Locomotor locomotor, Actor actor, World world, BlockedByActor check)
{
pooledLayer = layerPool.Get();
groundInfo = pooledLayer.GetLayer();
@@ -108,7 +109,7 @@ namespace OpenRA.Mods.Common.Pathfinder
worldMovementInfo = locomotorInfo.GetWorldMovementInfo(world);
Actor = actor;
LaneBias = 1;
checkConditions = checkForBlocked ? CellConditions.TransientActors : CellConditions.None;
checkConditions = check;
checkTerrainHeight = world.Map.Grid.MaximumTerrainHeight > 0;
}
@@ -172,8 +173,7 @@ namespace OpenRA.Mods.Common.Pathfinder
int GetCostToNode(CPos destNode, CVec direction)
{
var movementCost = locomotor.MovementCostToEnterCell(Actor, destNode, IgnoreActor, checkConditions);
var movementCost = locomotor.MovementCostToEnterCell(Actor, destNode, checkConditions, IgnoreActor);
if (movementCost != short.MaxValue && !(CustomBlock != null && CustomBlock(destNode)))
return CalculateCellCost(destNode, direction, movementCost);

View File

@@ -15,6 +15,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Pathfinder
{
@@ -45,18 +46,18 @@ namespace OpenRA.Mods.Common.Pathfinder
considered = new LinkedList<Pair<CPos, int>>();
}
public static IPathSearch Search(World world, Locomotor locomotor, Actor self, bool checkForBlocked, Func<CPos, bool> goalCondition)
public static IPathSearch Search(World world, Locomotor locomotor, Actor self, BlockedByActor check, Func<CPos, bool> goalCondition)
{
var graph = new PathGraph(LayerPoolForWorld(world), locomotor, self, world, checkForBlocked);
var graph = new PathGraph(LayerPoolForWorld(world), locomotor, self, world, check);
var search = new PathSearch(graph);
search.isGoal = goalCondition;
search.heuristic = loc => 0;
return search;
}
public static IPathSearch FromPoint(World world, Locomotor locomotor, Actor self, CPos @from, CPos target, bool checkForBlocked)
public static IPathSearch FromPoint(World world, Locomotor locomotor, Actor self, CPos @from, CPos target, BlockedByActor check)
{
var graph = new PathGraph(LayerPoolForWorld(world), locomotor, self, world, checkForBlocked);
var graph = new PathGraph(LayerPoolForWorld(world), locomotor, self, world, check);
var search = new PathSearch(graph)
{
heuristic = DefaultEstimator(target)
@@ -74,9 +75,9 @@ namespace OpenRA.Mods.Common.Pathfinder
return search;
}
public static IPathSearch FromPoints(World world, Locomotor locomotor, Actor self, IEnumerable<CPos> froms, CPos target, bool checkForBlocked)
public static IPathSearch FromPoints(World world, Locomotor locomotor, Actor self, IEnumerable<CPos> froms, CPos target, BlockedByActor check)
{
var graph = new PathGraph(LayerPoolForWorld(world), locomotor, self, world, checkForBlocked);
var graph = new PathGraph(LayerPoolForWorld(world), locomotor, self, world, check);
var search = new PathSearch(graph)
{
heuristic = DefaultEstimator(target)