diff --git a/OpenRA.Game/PathFinder.cs b/OpenRA.Game/PathFinder.cs index 4fbc4fe903..9821506316 100644 --- a/OpenRA.Game/PathFinder.cs +++ b/OpenRA.Game/PathFinder.cs @@ -60,7 +60,7 @@ namespace OpenRA List CachedPaths = new List(); const int MaxPathAge = 50; /* x 40ms ticks */ - public List FindUnitPath( int2 from, int2 target, UnitMovementType umt ) + public List FindUnitPath(int2 from, int2 target, UnitMovementType umt) { using (new PerfSample("find_unit_path")) { @@ -72,8 +72,11 @@ namespace OpenRA } var pb = FindBidiPath( - PathSearch.FromPoint(world, target, from, umt, false).WithCustomBlocker(AvoidUnitsNear(from, 4)), - PathSearch.FromPoint(world, from, target, umt, false).WithCustomBlocker(AvoidUnitsNear(from, 4))); + PathSearch.FromPoint(world, target, from, umt, false) + .WithCustomBlocker(AvoidUnitsNear(from, 4)), + PathSearch.FromPoint(world, from, target, umt, false) + .WithCustomBlocker(AvoidUnitsNear(from, 4)) + .InReverse()); CheckSanePath2(pb, from, target); @@ -90,7 +93,9 @@ namespace OpenRA var tilesInRange = world.FindTilesInCircle(target, range) .Where( t => world.IsPathableCell( t, umt ) ); - var path = FindPath( PathSearch.FromPoints( world, tilesInRange, src, umt, false ).WithCustomBlocker(AvoidUnitsNear(src, 4))); + var path = FindPath( PathSearch.FromPoints( world, tilesInRange, src, umt, false ) + .WithCustomBlocker(AvoidUnitsNear(src, 4)) + .InReverse()); path.Reverse(); return path; } diff --git a/OpenRA.Game/PathSearch.cs b/OpenRA.Game/PathSearch.cs index 60f8f42fc0..f2a70f2cad 100755 --- a/OpenRA.Game/PathSearch.cs +++ b/OpenRA.Game/PathSearch.cs @@ -38,6 +38,7 @@ namespace OpenRA Func customBlock; public bool checkForBlocked; public Actor ignoreBuilding; + public bool inReverse; BuildingInfluence buildingInfluence; UnitInfluence unitInfluence; @@ -53,6 +54,12 @@ namespace OpenRA resources = world.WorldActor.traits.Get(); } + public PathSearch InReverse() + { + inReverse = true; + return this; + } + public PathSearch WithCustomBlocker(Func customBlock) { this.customBlock = customBlock; @@ -65,6 +72,8 @@ namespace OpenRA return this; } + const float LaneBias = .5f; + public int2 Expand( World world, float[][ , ] passableCost ) { var p = queue.Pop(); @@ -107,10 +116,13 @@ namespace OpenRA float cellCost = ((d.X * d.Y != 0) ? 1.414213563f : 1.0f) * costHere; // directional bonuses for smoother flow! - if (((newHere.X & 1) == 0) && d.Y < 0) cellCost -= .1f; - else if (((newHere.X & 1) == 1) && d.Y > 0) cellCost -= .1f; - if (((newHere.Y & 1) == 0) && d.X < 0) cellCost -= .1f; - else if (((newHere.Y & 1) == 1) && d.X > 0) cellCost -= .1f; + var ux = (newHere.X + (inReverse ? 1 : 0) & 1); + var uy = (newHere.Y + (inReverse ? 1 : 0) & 1); + + if (ux == 0 && d.Y < 0) cellCost += LaneBias; + else if (ux == 1 && d.Y > 0) cellCost += LaneBias; + if (uy == 0 && d.X < 0) cellCost += LaneBias; + else if (uy == 1 && d.X > 0) cellCost += LaneBias; float newCost = cellInfo[ p.Location.X, p.Location.Y ].MinCost + cellCost;