Beispiel #1
0
        /// <summary>
        /// Resolves set running out of nodes, either changing NodeDistance, moving the ship, or failing pathfinding.
        /// </summary>
        /// <param name="pnSet">The set that is out of nodes.</param>
        private void OutOfNodes(FindingSet pnSet)
        {
            if (pnSet.NodeDistance > FindingSet.MinNodeDistance)
            {
                pnSet.ChangeNodeDistance(true, m_canChangeCourse);
                return;
            }

            if (pnSet != m_forward)
            {
                Log.DebugLog("Failed set: " + ReportRelativePosition(pnSet.m_startPosition), Logger.severity.DEBUG);
                return;
            }

            if (MoveToArbitrary())
            {
                return;
            }

            // with line, failing is "normal"
            Log.DebugLog("Pathfinding failed", m_canChangeCourse ? Logger.severity.WARNING : Logger.severity.DEBUG);
            Logger.DebugNotify("Pathfinding failed", 10000, m_canChangeCourse ? Logger.severity.WARNING : Logger.severity.DEBUG);

//#if PROFILE
//			LogStats();
//#endif

            PathfindingFailed();
            return;
        }
Beispiel #2
0
        /// <summary>
        /// Called when a node is reached. Tests against targets and creates new nodes.
        /// </summary>
        /// <param name="pnSet">The active set.</param>
        /// <param name="currentNode">The node that was reached.</param>
        /// <param name="input">Param for CanTravelSegment, Offset and Direction should be correct.</param>
        /// <param name="proximity">Result from CanTravelSegment, how close the ship would come to an entity when traveling to this node from its parent.</param>
        private void ReachedNode(FindingSet pnSet, ref PathNode currentNode, ref PathTester.TestInput input, float proximity)
        {
            // impose a penalty for going near entities, this does not affect this node but will affect its children
            // this really helps prevent pathfinder getting stuck but the penalty might be too high
            float penalty = 10f * (100f - MathHelper.Clamp(proximity, 0f, 100f));

            Log.DebugLog(SetName(pnSet) + " Reached node: " + ReportRelativePosition(currentNode.Position) + " from " + ReportRelativePosition(pnSet.m_reachedNodes[currentNode.ParentKey].Position) +
                         ", reached: " + pnSet.m_reachedNodes.Count + ", open: " + pnSet.m_openNodes.Count + ", proximity: " + proximity + ", penalty: " + penalty);
            currentNode.DistToCur += penalty;
            long cNodePosHash = currentNode.Key;

            pnSet.m_reachedNodes.Add(cNodePosHash, currentNode);

            if (!m_canChangeCourse)
            {
                // test from current node position to destination
                Log.DebugLog(SetName(pnSet) + " Running backwards search", Logger.severity.ERROR, condition: pnSet != m_forward);
                Vector3D.Subtract(ref m_currentPosition, ref pnSet.m_referencePosition, out input.Offset);
                input.Length = (float)Vector3D.Distance(currentNode.Position, pnSet.m_referencePosition);
                if (CanTravelSegment(ref input, out proximity))
                {
                    Log.DebugLog(SetName(pnSet) + " Reached destination from node: " + ReportRelativePosition(currentNode.Position));
                    Log.DebugLog("Backwards start is not reference position", Logger.severity.ERROR, condition: m_backwardList[0].m_startPosition != pnSet.m_referencePosition);
                    BuildPath(cNodePosHash, m_backwardList[0], pnSet.m_referencePosition.GetHash());
                    return;
                }
#if SHOW_REACHED
                ShowPosition(currentNode, SetName(pnSet));
#endif
                return;
            }

            foreach (PathNodeSet target in pnSet.m_targets)
            {
                if (target.HasReached(cNodePosHash))
                {
                    Log.DebugLog(SetName(pnSet) + " Opposite set has same position");
                    if (pnSet == m_forward)
                    {
                        BuildPath(cNodePosHash, target, cNodePosHash);
                    }
                    else
                    {
                        BuildPath(cNodePosHash, pnSet, cNodePosHash);
                    }
                    return;
                }
            }

            Vector3D        obstructPosition = m_obstructingEntity.GetPosition();
            Vector3D        currentNodeWorld; Vector3D.Add(ref obstructPosition, ref currentNode.Position, out currentNodeWorld);
            BoundingSphereD sphere = new BoundingSphereD()
            {
                Center = currentNodeWorld, Radius = m_autopilotShipBoundingRadius + 100f
            };
            m_entitiesRepulse.Clear();             // use repulse list as prune/avoid is needed for CanTravelSegment
            MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref sphere, m_entitiesRepulse);
            if (m_entitiesRepulse.Count == 0 && BlueSkyReached(pnSet, currentNode, ref currentNodeWorld))
            {
                return;
            }

#if SHOW_REACHED
            ShowPosition(currentNode, SetName(pnSet));
#endif

            if (pnSet.NodeDistance < FindingSet.DefaultNodeDistance && pnSet.m_reachedNodes.Count % 10 == 0 && pnSet.m_openNodes.Count > 100)
            {
                Log.DebugLog("Reached: " + pnSet.m_reachedNodes.Count + ", trying with higher node distance");
                pnSet.ChangeNodeDistance(false, m_canChangeCourse);
                return;
            }

            pnSet.CreatePathNode(ref currentNode, m_canChangeCourse);
        }