Some initial hacks towards multiple-infantry-per-cell. Make the pathfinder smart enough to do what we need, and remove a *lot* of stupid duplication. Needs more work.
This commit is contained in:
@@ -72,9 +72,9 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
var pb = FindBidiPath(
|
||||
PathSearch.FromPoint(world, target, from, umt, true)
|
||||
PathSearch.FromPoint(self, target, from, umt, true)
|
||||
.WithCustomBlocker(AvoidUnitsNear(from, 4, self)),
|
||||
PathSearch.FromPoint(world, from, target, umt, true)
|
||||
PathSearch.FromPoint(self, from, target, umt, true)
|
||||
.WithCustomBlocker(AvoidUnitsNear(from, 4, self))
|
||||
.InReverse());
|
||||
|
||||
@@ -90,10 +90,11 @@ namespace OpenRA
|
||||
{
|
||||
using( new PerfSample( "find_unit_path_multiple_src" ) )
|
||||
{
|
||||
var mobile = self.traits.Get<Mobile>();
|
||||
var tilesInRange = world.FindTilesInCircle(target, range)
|
||||
.Where( t => world.IsPathableCell( t, umt ) );
|
||||
.Where( t => mobile.CanEnterCell(t));
|
||||
|
||||
var path = FindPath( PathSearch.FromPoints( world, tilesInRange, src, umt, false )
|
||||
var path = FindPath( PathSearch.FromPoints( self, tilesInRange, src, umt, false )
|
||||
.WithCustomBlocker(AvoidUnitsNear(src, 4, self))
|
||||
.InReverse());
|
||||
path.Reverse();
|
||||
|
||||
@@ -37,14 +37,16 @@ namespace OpenRA
|
||||
Func<int2, bool> customBlock;
|
||||
public bool checkForBlocked;
|
||||
public Actor ignoreBuilding;
|
||||
Actor self;
|
||||
public bool inReverse;
|
||||
|
||||
BuildingInfluence buildingInfluence;
|
||||
UnitInfluence unitInfluence;
|
||||
|
||||
public PathSearch(World world)
|
||||
public PathSearch(Actor self)
|
||||
{
|
||||
this.world = world;
|
||||
this.self = self;
|
||||
world = self.World;
|
||||
cellInfo = InitCellInfo();
|
||||
queue = new PriorityQueue<PathDistance>();
|
||||
|
||||
@@ -70,6 +72,18 @@ namespace OpenRA
|
||||
return this;
|
||||
}
|
||||
|
||||
public PathSearch WithHeuristic(Func<int2, float> h)
|
||||
{
|
||||
heuristic = h;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PathSearch FromPoint(int2 from)
|
||||
{
|
||||
AddInitialCell( self.World, from );
|
||||
return this;
|
||||
}
|
||||
|
||||
const float LaneBias = .5f;
|
||||
|
||||
public int2 Expand( World world, float[][ , ] passableCost )
|
||||
@@ -101,8 +115,8 @@ namespace OpenRA
|
||||
if (!buildingInfluence.CanMoveHere(newHere, ignoreBuilding))
|
||||
continue;
|
||||
|
||||
// Replicate real-ra behavior of not being able to enter a cell if there is a mixture of crushable and uncrushable units
|
||||
if (checkForBlocked && (unitInfluence.GetUnitsAt(newHere).Any(a => !world.IsActorPathableToCrush(a, umt))))
|
||||
var mobile = self.traits.Get<Mobile>();
|
||||
if (checkForBlocked && !mobile.CanEnterCell(newHere))
|
||||
continue;
|
||||
|
||||
if (customBlock != null && customBlock(newHere))
|
||||
@@ -157,21 +171,29 @@ namespace OpenRA
|
||||
cellInfo[ location.X, location.Y ] = new CellInfo( 0, location, false );
|
||||
queue.Add( new PathDistance( heuristic( location ), location ) );
|
||||
}
|
||||
|
||||
public static PathSearch FromPoint( World world, int2 from, int2 target, UnitMovementType umt, bool checkForBlocked )
|
||||
|
||||
public static PathSearch Search( Actor self, UnitMovementType umt, bool checkForBlocked )
|
||||
{
|
||||
var search = new PathSearch(world) {
|
||||
var search = new PathSearch(self) {
|
||||
umt = umt,
|
||||
checkForBlocked = checkForBlocked };
|
||||
return search;
|
||||
}
|
||||
|
||||
public static PathSearch FromPoint( Actor self, int2 from, int2 target, UnitMovementType umt, bool checkForBlocked )
|
||||
{
|
||||
var search = new PathSearch(self) {
|
||||
heuristic = DefaultEstimator( target ),
|
||||
umt = umt,
|
||||
checkForBlocked = checkForBlocked };
|
||||
|
||||
search.AddInitialCell( world, from );
|
||||
search.AddInitialCell( self.World, from );
|
||||
return search;
|
||||
}
|
||||
|
||||
public static PathSearch FromPoints(World world, IEnumerable<int2> froms, int2 target, UnitMovementType umt, bool checkForBlocked)
|
||||
public static PathSearch FromPoints(Actor self, IEnumerable<int2> froms, int2 target, UnitMovementType umt, bool checkForBlocked)
|
||||
{
|
||||
var search = new PathSearch(world)
|
||||
var search = new PathSearch(self)
|
||||
{
|
||||
heuristic = DefaultEstimator(target),
|
||||
umt = umt,
|
||||
@@ -179,7 +201,7 @@ namespace OpenRA
|
||||
};
|
||||
|
||||
foreach (var sl in froms)
|
||||
search.AddInitialCell(world, sl);
|
||||
search.AddInitialCell(self.World, sl);
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace OpenRA.Traits.Activities
|
||||
{
|
||||
this.getPath = (self, mobile) =>
|
||||
self.World.PathFinder.FindPath(
|
||||
PathSearch.FromPoint( self.World, self.Location, destination, mobile.GetMovementType(), false )
|
||||
PathSearch.FromPoint( self, self.Location, destination, mobile.GetMovementType(), false )
|
||||
.WithCustomBlocker( self.World.PathFinder.AvoidUnitsNear( self.Location, 4, self ))
|
||||
.WithIgnoredBuilding( ignoreBuilding ));
|
||||
|
||||
@@ -89,17 +89,6 @@ namespace OpenRA.Traits.Activities
|
||||
this.nearEnough = 0;
|
||||
}
|
||||
|
||||
bool CanEnterCell( int2 c, Actor self )
|
||||
{
|
||||
if (!self.World.WorldActor.traits.Get<BuildingInfluence>().CanMoveHere(c)
|
||||
&& self.World.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(c) != ignoreBuilding)
|
||||
return false;
|
||||
|
||||
// Cannot enter a cell if any unit inside is uncrushable
|
||||
// This will need to be updated for multiple-infantry-in-a-cell
|
||||
return (!self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(c).Any(a => a != self && !self.World.IsActorCrushableByActor(a, self)));
|
||||
}
|
||||
|
||||
public IActivity Tick( Actor self )
|
||||
{
|
||||
var unit = self.traits.Get<Unit>();
|
||||
@@ -179,7 +168,7 @@ namespace OpenRA.Traits.Activities
|
||||
{
|
||||
if( path.Count == 0 ) return null;
|
||||
var nextCell = path[ path.Count - 1 ];
|
||||
if( !CanEnterCell( nextCell, self ) )
|
||||
if( !mobile.CanEnterCell( nextCell ) )
|
||||
{
|
||||
if( ( mobile.toCell - destination.Value ).LengthSquared <= nearEnough )
|
||||
{
|
||||
@@ -255,6 +244,8 @@ namespace OpenRA.Traits.Activities
|
||||
var frac = (float)moveFraction / moveFractionTotal;
|
||||
|
||||
self.CenterLocation = float2.Lerp( from, to, frac );
|
||||
// + self.traits.WithInterface<IOffsetCenterLocation>().Aggregate(float2.Zero, (a, x) => a + x.CenterOffset);
|
||||
|
||||
if( moveFraction >= moveFractionTotal )
|
||||
unit.Facing = toFacing & 0xFF;
|
||||
else
|
||||
|
||||
@@ -31,16 +31,6 @@ namespace OpenRA
|
||||
{
|
||||
public static class WorldUtils
|
||||
{
|
||||
public static bool IsPathableCell(this World world, int2 a, UnitMovementType umt)
|
||||
{
|
||||
if (world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(a) != null) return false;
|
||||
if (world.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(a).Any()) return false;
|
||||
|
||||
return world.Map.IsInMap(a.X, a.Y) &&
|
||||
Rules.TerrainTypes[world.TileSet.GetTerrainType(world.Map.MapTiles[a.X, a.Y])]
|
||||
.GetCost(umt) < float.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static bool IsCellBuildable(this World world, int2 a, bool waterBound)
|
||||
{
|
||||
return world.IsCellBuildable(a, waterBound, null);
|
||||
|
||||
Reference in New Issue
Block a user