Пример #1
0
        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());
        }
Пример #2
0
        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();
                }
            }
        }