private bool ShouldReinitPath() { // This prevents re-initializing the path too often if (MySandboxGame.TotalGamePlayTimeInMilliseconds - m_lastInitTime < 1000) { return(false); } // Otherwise, the path needs to be reinitialized only when the target entity moves return(m_goal.ShouldReinitPath()); }
private void ExpandPath(Vector3D currentPosition) { if (m_pathNodePosition >= m_pathNodes.Count - 1) { ProfilerShort.Begin("GenerateHighLevelPath"); GenerateHighLevelPath(); ProfilerShort.End(); } if (m_pathNodePosition >= m_pathNodes.Count) { return; } MyPath <MyNavigationPrimitive> path = null; bool isLastPath = false; m_expandedPath.Clear(); if (m_pathNodePosition + 1 < m_pathNodes.Count) { if (m_pathNodes[m_pathNodePosition].IsExpanded) { if (m_pathNodes[m_pathNodePosition + 1].IsExpanded) { IMyHighLevelComponent component = m_pathNodes[m_pathNodePosition].GetComponent(); IMyHighLevelComponent otherComponent = m_pathNodes[m_pathNodePosition + 1].GetComponent(); // CH: TODO: Preallocate the functions to avoid using lambdas. ProfilerShort.Begin("FindPath to next compo"); path = m_pathfinding.FindPath(m_currentPrimitive, m_goal.PathfindingHeuristic, (prim) => otherComponent.Contains(prim) ? 0.0f : float.PositiveInfinity, (prim) => component.Contains(prim) || otherComponent.Contains(prim)); ProfilerShort.End(); } else { Debug.Assert(!MyFakes.SHOW_PATH_EXPANSION_ASSERTS, "First hierarchy path node is expanded, but the second one is not! First two nodes should always be expanded so that pathfinding can be done."); } } else { Debug.Assert(!MyFakes.SHOW_PATH_EXPANSION_ASSERTS, "Nodes of smart path are not expanded!"); } } else { if (m_pathNodes[m_pathNodePosition].IsExpanded) { // Try to find a path to a goal primitive inside the last high level component. // If the last primitive of the found path is not in the last high level component, add that component to the goal's ignore list IMyHighLevelComponent component = m_pathNodes[m_pathNodePosition].GetComponent(); ProfilerShort.Begin("FindPath to goal in the last component"); path = m_pathfinding.FindPath(m_currentPrimitive, m_goal.PathfindingHeuristic, (prim) => component.Contains(prim) ? m_goal.TerminationCriterion(prim) : 30.0f, (prim) => component.Contains(prim)); ProfilerShort.End(); if (path != null) { // We reached goal if (path.Count != 0 && component.Contains(path[path.Count - 1].Vertex as MyNavigationPrimitive)) { isLastPath = true; } // We reached other component (goal could not be reached in this component) else { m_goal.IgnoreHighLevel(m_pathNodes[m_pathNodePosition]); } } } else { Debug.Assert(!MyFakes.SHOW_PATH_EXPANSION_ASSERTS, "Nodes of smart path are not expanded!"); } } if (path == null || path.Count == 0) { return; } Vector3D end = default(Vector3D); var lastPrimitive = path[path.Count - 1].Vertex as MyNavigationPrimitive; if (isLastPath) { Vector3 endPoint = m_goal.Destination.GetBestPoint(lastPrimitive.WorldPosition); Vector3 localEnd = lastPrimitive.Group.GlobalToLocal(endPoint); localEnd = lastPrimitive.ProjectLocalPoint(localEnd); end = lastPrimitive.Group.LocalToGlobal(localEnd); } else { end = lastPrimitive.WorldPosition; } RefineFoundPath(ref currentPosition, ref end, path); // If the path is too short, don't use it to prevent jerking in stuck situations if (m_pathNodes.Count <= 1 && isLastPath && m_expandedPath.Count > 0 && path.Count <= 2 && !m_goal.ShouldReinitPath()) { Vector4D end4D = m_expandedPath[m_expandedPath.Count - 1]; // Here, 256 is just a small enough value to catch most false-positives if (Vector3D.DistanceSquared(currentPosition, end) < end4D.W * end4D.W / 256) { m_expandedPath.Clear(); } } }