public List <CPos> FindUnitPathToRange(CPos src, CPos target, int range, Actor self) { using (new PerfSample("Pathfinder")) { var mi = self.Info.Traits.Get <MobileInfo>(); var tilesInRange = world.FindTilesInCircle(target, range) .Where(t => mi.CanEnterCell(self.World, self, t, null, true, true)); var path = FindBidiPath( PathSearch.FromPoints(world, mi, self, tilesInRange, src, true), PathSearch.FromPoint(world, mi, self, src, target, true).InReverse() ); return(path); } }
public List <CPos> FindUnitPathToRange(CPos src, SubCell srcSub, WPos target, WRange range, Actor self) { using (new PerfSample("Pathfinder")) { var mi = self.Info.Traits.Get <MobileInfo>(); var targetCell = self.World.Map.CellContaining(target); var rangeSquared = range.Range * range.Range; // Correct for SubCell offset target -= MobileInfo.SubCellOffsets[srcSub]; // Select only the tiles that are within range from the requested SubCell // This assumes that the SubCell does not change during the path traversal var tilesInRange = world.Map.FindTilesInCircle(targetCell, range.Range / 1024 + 1) .Where(t => (world.Map.CenterOfCell(t) - target).LengthSquared <= rangeSquared && mi.CanEnterCell(self.World, self, t, null, true, true)); // See if there is any cell within range that does not involve a cross-domain request // Really, we only need to check the circle perimeter, but it's not clear that would be a performance win var domainIndex = self.World.WorldActor.TraitOrDefault <DomainIndex>(); if (domainIndex != null) { var passable = mi.GetMovementClass(world.TileSet); tilesInRange = new List <CPos>(tilesInRange.Where(t => domainIndex.IsPassable(src, t, (uint)passable))); if (!tilesInRange.Any()) { return(emptyPath); } } var path = FindBidiPath( PathSearch.FromPoints(world, mi, self, tilesInRange, src, true), PathSearch.FromPoint(world, mi, self, src, targetCell, true).Reverse() ); return(path); } }