Beispiel #1
0
        const int MaxPathAge          = 50;     /* x 40ms ticks */

        public List <CPos> FindUnitPath(CPos from, CPos target, Actor self)
        {
            using (new PerfSample("Pathfinder"))
            {
                var cached = CachedPaths.FirstOrDefault(p => p.from == from && p.to == target && p.actor == self);
                if (cached != null)
                {
                    Log.Write("debug", "Actor {0} asked for a path from {1} tick(s) ago", self.ActorID, world.FrameNumber - cached.tick);
                    if (world.FrameNumber - cached.tick > MaxPathAge)
                    {
                        CachedPaths.Remove(cached);
                    }
                    return(new List <CPos>(cached.result));
                }

                var mi = self.Info.Traits.Get <MobileInfo>();

                var pb = FindBidiPath(
                    PathSearch.FromPoint(world, mi, self, target, from, true),
                    PathSearch.FromPoint(world, mi, self, from, target, true).InReverse()
                    );

                CheckSanePath2(pb, from, target);

                CachedPaths.RemoveAll(p => world.FrameNumber - p.tick > MaxPathAge);
                CachedPaths.Add(new CachedPath {
                    from = from, to = target, actor = self, result = pb, tick = world.FrameNumber
                });
                return(new List <CPos>(pb));
            }
        }
Beispiel #2
0
 // Scriptable move order
 // Ignores lane bias and nearby units
 public Move(CPos destination)
 {
     this.getPath = (self, mobile) =>
                    self.World.WorldActor.Trait <PathFinder>().FindPath(
         PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, destination, false)
         .WithoutLaneBias());
     this.destination = destination;
     this.nearEnough  = WRange.Zero;
 }
Beispiel #3
0
        public Move(CPos destination, Actor ignoreBuilding)
        {
            this.getPath = (self, mobile) =>
                           self.World.WorldActor.Trait <PathFinder>().FindPath(
                PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, destination, false)
                .WithIgnoredBuilding(ignoreBuilding));

            this.destination    = destination;
            this.nearEnough     = WRange.Zero;
            this.ignoreBuilding = ignoreBuilding;
        }
Beispiel #4
0
        // Scriptable move order
        // Ignores lane bias and nearby units
        public Move(Actor self, CPos destination)
        {
            mobile        = self.Trait <Mobile>();
            moveDisablers = self.TraitsImplementing <IDisableMove>();

            getPath = () =>
                      self.World.WorldActor.Trait <PathFinder>().FindPath(
                PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, destination, false)
                .WithoutLaneBias());
            this.destination = destination;
            this.nearEnough  = WRange.Zero;
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        const int MaxPathAge          = 50;     /* x 40ms ticks */

        public List <CPos> FindUnitPath(CPos from, CPos target, Actor self)
        {
            using (new PerfSample("Pathfinder"))
            {
                var cached = CachedPaths.FirstOrDefault(p => p.from == from && p.to == target && p.actor == self);
                if (cached != null)
                {
                    Log.Write("debug", "Actor {0} asked for a path from {1} tick(s) ago", self.ActorID, world.WorldTick - cached.tick);
                    if (world.WorldTick - cached.tick > MaxPathAge)
                    {
                        CachedPaths.Remove(cached);
                    }
                    return(new List <CPos>(cached.result));
                }

                var mi = self.Info.Traits.Get <MobileInfo>();

                // If a water-land transition is required, bail early
                var domainIndex = self.World.WorldActor.TraitOrDefault <DomainIndex>();
                if (domainIndex != null)
                {
                    var passable = mi.GetMovementClass(world.TileSet);
                    if (!domainIndex.IsPassable(from, target, (uint)passable))
                    {
                        return(emptyPath);
                    }
                }

                var pb = FindBidiPath(
                    PathSearch.FromPoint(world, mi, self, target, from, true),
                    PathSearch.FromPoint(world, mi, self, from, target, true).Reverse()
                    );

                CheckSanePath2(pb, from, target);

                CachedPaths.RemoveAll(p => world.WorldTick - p.tick > MaxPathAge);
                CachedPaths.Add(new CachedPath {
                    from = from, to = target, actor = self, result = pb, tick = world.WorldTick
                });
                return(new List <CPos>(pb));
            }
        }
Beispiel #7
0
        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);
            }
        }