/// <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); }
/// <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(); } }
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); }