Example #1
0
        /// <summary>
        /// Checks to see if the navigator can reciprocally go back and forth between a cell
        /// and another cell, checking only if they are immediately reachable.
        /// </summary>
        /// <param name="fromCell">The cell where the navigator is currently located.</param>
        /// <param name="toCell">The potential destination cell.</param>
        /// <param name="navGrid">The navigation grid to use for lookups.</param>
        /// <param name="startNavType">The navigation type to use.</param>
        /// <param name="abilities">The current navigator abilities.</param>
        /// <param name="newFlags">The flags available for this path.</param>
        /// <returns>true if navigation can be performed, both ways, or false otherwise.</returns>
        private static bool CanNavigateReciprocal(int fromCell, int toCell, NavGrid navGrid,
                                                  NavType startNavType, PathFinderAbilities abilities, PathFlags flags)
        {
            var  grid = PathFinder.PathGrid;
            bool ok   = false;
            // Find a link from this cell to the target cell
            var link = FindLinkToCell(fromCell, toCell, navGrid, startNavType);

            if (link.link != InvalidHandle)
            {
                var endNavType = link.endNavType;
                var pp         = new PathFinder.PotentialPath(toCell, endNavType, flags);
                int uwCost     = grid.GetCell(toCell, endNavType, out _).underwaterCost;
                // Can navigate there, and has a link back?
                if (abilities.TraversePath(ref pp, fromCell, startNavType, link.cost, link.
                                           transitionId, uwCost) && (link = FindLinkToCell(toCell, fromCell,
                                                                                           navGrid, endNavType)).link != InvalidHandle)
                {
                    pp.cell    = fromCell;
                    pp.navType = startNavType;
                    uwCost     = grid.GetCell(fromCell, startNavType, out _).underwaterCost;
                    ok         = abilities.TraversePath(ref pp, toCell, endNavType, link.cost,
                                                        link.transitionId, uwCost);
                }
            }
            return(ok);
        }
Example #2
0
        /// <summary>
        /// Checks to see if this cached path is still valid. If not, the cached parameters are
        /// updated assuming that pathing is recalculated.
        /// </summary>
        /// <param name="navGrid">The navigation grid to use.</param>
        /// <param name="newCell">The starting cell.</param>
        /// <param name="navType">The navigation type currently in use.</param>
        /// <param name="abilities">The path finder's current abilities.</param>
        /// <param name="newFlags">The path finder's current flags.</param>
        /// <returns>true if cached information can be used, or false otherwise.</returns>
        public bool CheckAndUpdate(NavGrid navGrid, int newCell, NavType navType,
                                   PathFinderAbilities abilities, PathFlags newFlags)
        {
            if (navGrid == null)
            {
                throw new ArgumentNullException("navGrid");
            }
            if (abilities == null)
            {
                throw new ArgumentNullException("abilities");
            }
            bool ok = false;

            if (NavFences.AllFences.TryGetValue(navGrid.id, out NavFences fences))
            {
                long serial = fences.CurrentSerial;
                if (serial == globalSerial && flags == newFlags)
                {
                    ok = (cell == newCell) || CanNavigateReciprocal(cell, newCell, navGrid,
                                                                    navType, abilities, newFlags);
                }
                else
                {
                    // Guaranteed out of date
                    flags        = newFlags;
                    globalSerial = serial;
                }
                cell = newCell;
            }
            return(ok);
        }
 public static void Run(NavGrid nav_grid, PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query, ref Path path)
 {
     Run(nav_grid, abilities, potential_path, query);
     if (query.GetResultCell() != InvalidCell)
     {
         BuildResultPath(query.GetResultCell(), query.GetResultNavType(), ref path);
     }
     else
     {
         path.Clear();
     }
 }
Example #4
0
            internal static bool Prefix(PathProber __instance, int cell, NavType nav_type,
                                        PathFinder.PotentialPath.Flags flags, NavGrid nav_grid,
                                        PathFinderAbilities abilities)
            {
                // If nothing has changed since last time, it is a hit!
                var  cached = PathCacher.Lookup(__instance);
                bool hit;

                if (hit = cached.CheckAndUpdate(nav_grid, cell, nav_type, abilities, flags))
                {
                    Interlocked.Increment(ref hits);
                }
                Interlocked.Increment(ref total);
                return(!hit);
            }
    public static void Run(NavGrid nav_grid, PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query)
    {
        int     result_cell     = InvalidCell;
        NavType result_nav_type = NavType.NumNavTypes;

        query.ClearResult();
        if (Grid.IsValidCell(potential_path.cell))
        {
            FindPaths(nav_grid, ref abilities, potential_path, query, Temp.Potentials, ref result_cell, ref result_nav_type);
            if (result_cell != InvalidCell)
            {
                bool is_cell_in_range = false;
                Cell cell             = PathGrid.GetCell(result_cell, result_nav_type, out is_cell_in_range);
                query.SetResult(result_cell, cell.cost, result_nav_type);
            }
        }
    }
    private static void FindPaths(NavGrid nav_grid, ref PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query, PotentialList potentials, ref int result_cell, ref NavType result_nav_type)
    {
        potentials.Clear();
        PathGrid.ResetUpdate();
        PathGrid.BeginUpdate(potential_path.cell, false);
        bool is_cell_in_range;
        Cell cell_data = PathGrid.GetCell(potential_path, out is_cell_in_range);

        AddPotential(potential_path, Grid.InvalidCell, NavType.NumNavTypes, 0, 0, -1, potentials, PathGrid, ref cell_data);
        int num = 2147483647;

        while (potentials.Count > 0)
        {
            KeyValuePair <int, PotentialPath> keyValuePair = potentials.Next();
            cell_data = PathGrid.GetCell(keyValuePair.Value, out is_cell_in_range);
            if (cell_data.cost != keyValuePair.Key)
            {
                continue;
            }
            int num2;
            if (cell_data.navType != NavType.Tube)
            {
                PotentialPath value = keyValuePair.Value;
                if (query.IsMatch(value.cell, cell_data.parent, cell_data.cost))
                {
                    num2 = ((cell_data.cost < num) ? 1 : 0);
                    goto IL_00cc;
                }
            }
            num2 = 0;
            goto IL_00cc;
IL_00cc:
            if (num2 != 0)
            {
                PotentialPath value2 = keyValuePair.Value;
                result_cell     = value2.cell;
                num             = cell_data.cost;
                result_nav_type = cell_data.navType;
                break;
            }
            AddPotentials(nav_grid.potentialScratchPad, keyValuePair.Value, cell_data.cost, cell_data.underwaterCost, ref abilities, query, nav_grid.maxLinksPerCell, nav_grid.Links, potentials, PathGrid, cell_data.parent, cell_data.parentNavType);
        }
        PathGrid.EndUpdate(true);
    }
    public void UpdateProbe(NavGrid nav_grid, int cell, NavType nav_type, PathFinderAbilities abilities, PathFinder.PotentialPath.Flags flags)
    {
        if (scratchPad == null)
        {
            scratchPad = new PathFinder.PotentialScratchPad(nav_grid.maxLinksPerCell);
        }
        bool flag  = updateCount == -1;
        bool flag2 = Potentials.Count == 0 || flag;

        PathGrid.BeginUpdate(cell, !flag2);
        bool is_cell_in_range;

        if (flag2)
        {
            updateCount = 0;
            PathFinder.Cell          cell_data      = PathGrid.GetCell(cell, nav_type, out is_cell_in_range);
            PathFinder.PotentialPath potential_path = new PathFinder.PotentialPath(cell, nav_type, flags);
            PathFinder.AddPotential(potential_path, Grid.InvalidCell, NavType.NumNavTypes, 0, 0, -1, Potentials, PathGrid, ref cell_data);
        }
        int num = (potentialCellsPerUpdate > 0 && !flag) ? potentialCellsPerUpdate : 2147483647;

        updateCount++;
        while (Potentials.Count > 0 && num > 0)
        {
            KeyValuePair <int, PathFinder.PotentialPath> keyValuePair = Potentials.Next();
            num--;
            PathFinder.Cell cell2 = PathGrid.GetCell(keyValuePair.Value, out is_cell_in_range);
            if (cell2.cost == keyValuePair.Key)
            {
                PathFinder.AddPotentials(scratchPad, keyValuePair.Value, cell2.cost, cell2.underwaterCost, ref abilities, null, nav_grid.maxLinksPerCell, nav_grid.Links, Potentials, PathGrid, cell2.parent, cell2.parentNavType);
            }
        }
        bool flag3 = Potentials.Count == 0;

        PathGrid.EndUpdate(flag3);
        if (flag3 && updateCount > 25)
        {
            KProfiler.AddEvent("PathProberUpdateCountExceeded");
        }
    }
 public static bool ValidatePath(NavGrid nav_grid, PathFinderAbilities abilities, ref Path path)
 {
     if (!path.IsValid())
     {
         return(false);
     }
     for (int i = 0; i < path.nodes.Count; i++)
     {
         Path.Node node = path.nodes[i];
         if (i < path.nodes.Count - 1)
         {
             Path.Node    node2 = path.nodes[i + 1];
             int          num   = node.cell * nav_grid.maxLinksPerCell;
             bool         flag  = false;
             NavGrid.Link link  = nav_grid.Links[num];
             while (link.link != InvalidHandle)
             {
                 if (link.link == node2.cell && node2.navType == link.endNavType && node.navType == link.startNavType)
                 {
                     PotentialPath path2 = new PotentialPath(node.cell, node.navType, PotentialPath.Flags.None);
                     flag = abilities.TraversePath(ref path2, node.cell, node.navType, 0, link.transitionId, 0);
                     if (flag)
                     {
                         break;
                     }
                 }
                 num++;
                 link = nav_grid.Links[num];
             }
             if (!flag)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
 public void SetAbilities(PathFinderAbilities abilities)
 {
     this.abilities = abilities;
 }
    private bool ValidatePath(ref PathFinder.Path path)
    {
        PathFinderAbilities currentAbilities = GetCurrentAbilities();

        return(PathFinder.ValidatePath(NavGrid, currentAbilities, ref path));
    }
 public virtual bool IsTraversable(PathFinder.PotentialPath path, int from_cell, int cost, int transition_id, PathFinderAbilities abilities)
 {
     return(true);
 }
    public static void AddPotentials(PotentialScratchPad potential_scratch_pad, PotentialPath potential, int cost, int underwater_cost, ref PathFinderAbilities abilities, PathFinderQuery query, int max_links_per_cell, NavGrid.Link[] links, PotentialList potentials, PathGrid path_grid, int parent_cell, NavType parent_nav_type)
    {
        int num = 0;

        NavGrid.Link[] linksWithCorrectNavType = potential_scratch_pad.linksWithCorrectNavType;
        int            num2 = potential.cell * max_links_per_cell;

        NavGrid.Link link = links[num2];
        for (int link2 = link.link; link2 != InvalidHandle; link2 = link.link)
        {
            if (link.startNavType == potential.navType && (parent_cell != link2 || parent_nav_type != link.startNavType))
            {
                linksWithCorrectNavType[num++] = link;
            }
            num2++;
            link = links[num2];
        }
        int num4 = 0;

        PotentialScratchPad.PathGridCellData[] linksInCellRange = potential_scratch_pad.linksInCellRange;
        for (int i = 0; i < num; i++)
        {
            NavGrid.Link link3            = linksWithCorrectNavType[i];
            int          link4            = link3.link;
            bool         is_cell_in_range = false;
            Cell         cell             = path_grid.GetCell(link4, link3.endNavType, out is_cell_in_range);
            if (is_cell_in_range)
            {
                int  num5  = cost + link3.cost;
                bool flag  = cell.cost == -1;
                bool flag2 = num5 < cell.cost;
                if (flag || flag2)
                {
                    linksInCellRange[num4++] = new PotentialScratchPad.PathGridCellData
                    {
                        pathGridCell = cell,
                        link         = link3
                    };
                }
            }
        }
        for (int j = 0; j < num4; j++)
        {
            PotentialScratchPad.PathGridCellData pathGridCellData = linksInCellRange[j];
            NavGrid.Link link5 = pathGridCellData.link;
            int          link6 = link5.link;
            pathGridCellData.isSubmerged = IsSubmerged(link6);
            linksInCellRange[j]          = pathGridCellData;
        }
        for (int k = 0; k < num4; k++)
        {
            PotentialScratchPad.PathGridCellData pathGridCellData2 = linksInCellRange[k];
            NavGrid.Link  link7     = pathGridCellData2.link;
            int           link8     = link7.link;
            Cell          cell_data = pathGridCellData2.pathGridCell;
            int           num7      = cost + link7.cost;
            PotentialPath path      = potential;
            path.cell    = link8;
            path.navType = link7.endNavType;
            int underwater_cost2;
            if (pathGridCellData2.isSubmerged)
            {
                underwater_cost2 = underwater_cost + 1;
                int submergedPathCostPenalty = abilities.GetSubmergedPathCostPenalty(path, link7);
                num7 += submergedPathCostPenalty;
            }
            else
            {
                underwater_cost2 = 0;
            }
            PotentialPath.Flags flags = path.flags;
            bool flag3 = abilities.TraversePath(ref path, potential.cell, potential.navType, num7, link7.transitionId, underwater_cost2);
            if (path.flags != flags)
            {
                KProfiler.AddEvent("NavChange");
            }
            if (flag3)
            {
                AddPotential(path, potential.cell, potential.navType, num7, underwater_cost2, link7.transitionId, potentials, path_grid, ref cell_data);
            }
        }
    }
 public static void UpdatePath(NavGrid nav_grid, PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query, ref Path path)
 {
     Run(nav_grid, abilities, potential_path, query, ref path);
 }