public bool IsOnEdge(ExplorationNode n, SceneExitDirections direction) { switch (direction) { case SceneExitDirections.North: return(n.TopLeft.X == NorthWest.X); case SceneExitDirections.East: return(n.BottomLeft.Y == NorthEast.Y); case SceneExitDirections.South: return(n.BottomRight.X == SouthEast.X); case SceneExitDirections.West: return(n.TopRight.Y == SouthWest.Y); } return(false); }
public static double PriorityDistanceFormula(ExplorationNode n) { var directionMultiplier = IsInPriorityDirection(n.NavigableCenter, 30) ? 4.5 : 1; var sceneConnectionDirectionMultiplier = IsInSceneConnectionDirection(n.NavigableCenter, 30) ? 1.25 : 1; var nodeInPrioritySceneMultiplier = n.Priority ? 2.25 : 0; var baseDistanceFactor = 50 / n.NavigableCenter.Distance(AdvDia.MyPosition) * 10; var canRayWalk = Core.Grids.CanRayWalk(AdvDia.MyPosition, n.NavigableCenter) ? 1.75 : 1; var edgeMultiplier = 1d; var visitedMultiplier = 1d; var exitSceneMultiplier = 1d; var exploredPercent = ExplorationGrid.Instance.WalkableNodes.Count(x => x.Scene.HasBeenVisited) / ExplorationGrid.Instance.WalkableNodes.Count(); // for now.. restrict this group of checks from effecting bounties. if (Core.Rift.IsInRift) { var isInExitScene = n.Scene.Name.Contains("Exit"); exitSceneMultiplier = isInExitScene ? 100 / n.Distance : 1; visitedMultiplier = n.Scene.HasBeenVisited && !isInExitScene ? 0.01f : 1f; // Ignore dead end scenes. if (n.Scene.ExitPositions.Count <= 1 && !isInExitScene) { return(0); } if (!Core.Grids.CanRayWalk(Core.Player.Position, n.NavigableCenter)) { return(0); } // Lower weight for scenes near the edge of an open style map. edgeMultiplier = (n.Scene.Name.Contains("Border") || n.Scene.Name.Contains("Edge")) && n.Distance <100 && exploredPercent> 0.85 ? 2.5 : 1; } return(baseDistanceFactor * exitSceneMultiplier * directionMultiplier * sceneConnectionDirectionMultiplier * (n.UnvisitedWeight + nodeInPrioritySceneMultiplier) * visitedMultiplier * edgeMultiplier * canRayWalk); }
private void CreateGrid(Scene.NavMesh mesh) { if (GridCreated) { return; } Cells = new List <WorldSceneCell>(); foreach (var navCell in mesh.Zone.NavZoneDef.NavCells) { Cells.Add(new WorldSceneCell(navCell, Min)); } if (SubScene != null) { foreach (var navCell in SubScene.Cells) { Cells.Add(navCell); } if (SubScene.SubScene != null) { foreach (var navCell in SubScene.SubScene.Cells) { Cells.Add(navCell); } } } var navBoxSize = ExplorationData.ExplorationNodeBoxSize; var searchBeginning = navBoxSize / 2; for (var x = Min.X + searchBeginning; x <= Max.X; x = x + navBoxSize) { for (var y = Min.Y + searchBeginning; y <= Max.Y; y = y + navBoxSize) { var navNode = new ExplorationNode(new Vector2(x, y), _boxSize, _boxTolerance, this); Nodes.Add(navNode); } } GridCreated = true; GridCreatedTime = DateTime.UtcNow; }
public NavigationNode(Vector3 center, float boxSize, ExplorationNode node, WorldSceneCell cell) { if (node != null) { _explorationNode = node; _scene = node.Scene; } if (cell != null) { NodeFlags = (NodeFlags)cell.NavCellFlags; } var halfSize = (float)boxSize / 2; Center = center.ToVector2(); TopLeft = Center + new Vector2(-(halfSize), -(halfSize)); BottomLeft = Center + new Vector2(-(halfSize), halfSize); TopRight = Center + new Vector2(halfSize, -(halfSize)); BottomRight = Center + new Vector2(halfSize, halfSize); NavigableCenter = center; NavigableCenter2D = Center; }
public static ExplorationNode NearestWeightedUnvisitedNode(HashSet <int> levelAreaIds, List <string> ignoreScenes = null) { var dynamicWorldId = AdvDia.CurrentWorldDynamicId; var myPosition = AdvDia.MyPosition; ExplorationNode node = null; using (new PerformanceLogger("NearestUnvisitedNodeLocation", true)) { var nearestNode = ExplorationGrid.Instance.GetNearestWalkableNodeToPosition(myPosition); if (Core.Rift.IsInRift && !Core.BlockedCheck.IsBlocked && !Core.StuckHandler.IsStuck) { //Core.Logger.Warn("in rift"); // In rift prefer the highest weight nodes because we dont need to explore everything, just need to find the exit. var closestUnvisitedNodes = ExplorationGrid.Instance.WalkableNodes .Where(n => !n.IsIgnored && !n.IsVisited && !n.IsBlacklisted && n.HasEnoughNavigableCells && n.DynamicWorldId == dynamicWorldId && levelAreaIds.Contains(n.LevelAreaId)) .OrderByDescending(n => n.Priority) .ThenByDescending(PriorityDistanceFormula); var closestUnvisitedNode = closestUnvisitedNodes.FirstOrDefault(); if (closestUnvisitedNode != null) { var weight = PriorityDistanceFormula(closestUnvisitedNode); Core.Logger.Debug(LogCategory.Exploration, $"Explore: Best Rift Weighted Node: [{closestUnvisitedNode.NavigableCenter.X},{closestUnvisitedNode.NavigableCenter.Y},{closestUnvisitedNode.NavigableCenter.Z}] Dist:{closestUnvisitedNode.Distance} Weight: {weight} {(closestUnvisitedNode.Priority ? "(Priority)" : "")} "); return(closestUnvisitedNode); } } // Try for nodes nearby walkable nodes first for (var i = 3; i <= 4; i++) { var closestUnvisitedNodes = ExplorationGrid.Instance.GetNeighbors(nearestNode, i) .Where(n => !n.IsIgnored && !n.IsVisited && !n.IsBlacklisted && n.HasEnoughNavigableCells && n.DynamicWorldId == dynamicWorldId && levelAreaIds.Contains(n.LevelAreaId) && Core.Grids.CanRayWalk(myPosition, n.NavigableCenter)) .OrderByDescending(n => n.Priority) .ThenBy(PriorityDistanceFormula); var closestUnvisitedNode = closestUnvisitedNodes.FirstOrDefault(); if (closestUnvisitedNode != null) { Core.Logger.Debug(LogCategory.Exploration, $"Explore: Selected Nearby Node: [{closestUnvisitedNode.NavigableCenter.X},{closestUnvisitedNode.NavigableCenter.Y},{closestUnvisitedNode.NavigableCenter.Z}] Dist:{closestUnvisitedNode.Distance} {(closestUnvisitedNode.Priority ? "(Priority)" : "")} "); return(closestUnvisitedNode); } } // Try any nearby nodes for (var i = 3; i <= 6; i++) { var closestUnvisitedNode = ExplorationGrid.Instance.GetNeighbors(nearestNode, i) .Where(n => !n.IsIgnored && !n.IsVisited && !n.IsBlacklisted && n.HasEnoughNavigableCells && n.DynamicWorldId == dynamicWorldId && levelAreaIds.Contains(n.LevelAreaId)) .OrderBy(PriorityDistanceFormula) .FirstOrDefault(); if (closestUnvisitedNode != null) { Core.Logger.Debug(LogCategory.Exploration, $"Explore: Selected Nearby Node: [{closestUnvisitedNode.NavigableCenter.X},{closestUnvisitedNode.NavigableCenter.Y},{closestUnvisitedNode.NavigableCenter.Z}] Dist:{closestUnvisitedNode.Distance} {(closestUnvisitedNode.Priority ? "(Priority)" : "")} "); return(closestUnvisitedNode); } } // Try any univisted node by distance. node = ExplorationGrid.Instance.WalkableNodes.Where(n => !n.IsIgnored && !n.IsVisited && !n.IsBlacklisted && //n.DynamicWorldId == dynamicWorldId && n.NavigableCenter.DistanceSqr(myPosition) > 20 //&& levelAreaIds.Contains(n.LevelAreaId) ) .OrderByDescending(PriorityDistanceFormula) .FirstOrDefault(); if (node != null) { Core.Logger.Debug(LogCategory.Exploration, $"Explore: Selected Nearby Node: [{node.NavigableCenter.X},{node.NavigableCenter.Y},{node.NavigableCenter.Z}] Dist:{node.Distance} {(node.Priority ? "(Priority)" : "")} "); return(node); } if (ExplorationGrid.Instance.NearestNode != null && !levelAreaIds.Contains(ZetaDia.CurrentLevelAreaSnoId)) { Core.Logger.Debug("[ExplorationLogic] Adventurer is trying to find nodes that are not in this LevelArea. DefinedIds='{0}' CurrentId='{0}'. Marking current area's nodes as valid.", string.Join(", ", levelAreaIds), ZetaDia.CurrentLevelAreaSnoId); levelAreaIds.Add(ZetaDia.CurrentLevelAreaSnoId); // Ignore level area match node = ExplorationGrid.Instance.WalkableNodes .Where(n => !n.IsIgnored && !n.IsVisited && !n.IsBlacklisted && n.DynamicWorldId == dynamicWorldId && n.NavigableCenter.DistanceSqr(myPosition) > 100) .OrderByDescending(PriorityDistanceFormula) .FirstOrDefault(); } if (node == null) { var allNodes = ExplorationGrid.Instance.WalkableNodes.Count(n => levelAreaIds.Contains(n.LevelAreaId)); var unvisitedNodes = ExplorationGrid.Instance.WalkableNodes.Count(n => !n.IsVisited && levelAreaIds.Contains(n.LevelAreaId)); Core.Logger.Log("[ExplorationLogic] Couldn't find any unvisited nodes. Current AdvDia.LevelAreaSnoIdId: {0}, " + "ZetaDia.CurrentLevelAreaSnoId: {3}, Total Nodes: {1} Unvisited Nodes: {2} Searching In [{4}] HasNavServerData={5}", AdvDia.CurrentLevelAreaId, allNodes, unvisitedNodes, ZetaDia.CurrentLevelAreaSnoId, string.Join(", ", levelAreaIds), AdvDia.MainGridProvider.Width != 0); //Core.Scenes.Reset(); } return(node); } }