public static bool CalculateAtmoTravelPath(ImprovedSpawnGroup spawnGroup, Vector3D startCoords, MyPlanet planet, out Vector3D startPathCoords, out Vector3D endPathCoords, out MatrixD startMatrix)
        {
            startPathCoords = Vector3D.Zero;
            endPathCoords   = Vector3D.Zero;
            startMatrix     = MatrixD.CreateWorld(Vector3D.Zero, Vector3D.Forward, Vector3D.Up);
            SpawnResources.RefreshEntityLists();

            if (planet == null)
            {
                return(false);
            }

            var planetEntity = planet as IMyEntity;

            for (int i = 0; i < Settings.PlanetaryCargoShips.MaxSpawnAttempts; i++)
            {
                //Get Starting Point
                var randDirFromPlayer = SpawnResources.GetRandomCompassDirection(startCoords, planet);
                var pathDist          = SpawnResources.GetRandomPathDist(Settings.PlanetaryCargoShips.MinPathDistanceFromPlayer, Settings.PlanetaryCargoShips.MaxPathDistanceFromPlayer);
                var midPointSurface   = SpawnResources.GetNearestSurfacePoint(randDirFromPlayer * pathDist + startCoords, planet);
                var upDir             = Vector3D.Normalize(midPointSurface - planetEntity.GetPosition());
                var altitudeFromMid   = SpawnResources.GetRandomPathDist(Settings.PlanetaryCargoShips.MinSpawningAltitude, Settings.PlanetaryCargoShips.MaxSpawningAltitude);
                var tempStartPath     = upDir * altitudeFromMid + midPointSurface;

                if (spawnGroup.PlanetRequiresAtmo == true && planet.GetAirDensity(tempStartPath) < Settings.PlanetaryCargoShips.MinAirDensity)
                {
                    tempStartPath = upDir * Settings.PlanetaryCargoShips.MinSpawningAltitude + midPointSurface;

                    if (spawnGroup.PlanetRequiresAtmo == true && planet.GetAirDensity(tempStartPath) < Settings.PlanetaryCargoShips.MinAirDensity)
                    {
                        continue;
                    }
                }

                if (SpawnResources.IsPositionNearEntities(tempStartPath, Settings.PlanetaryCargoShips.MinSpawnFromGrids) == true)
                {
                    continue;
                }

                var startCoordsDistFromCenter = Vector3D.Distance(planetEntity.GetPosition(), tempStartPath);

                //Get Ending Point
                var randPathDir  = SpawnResources.GetRandomCompassDirection(tempStartPath, planet);
                var randPathDist = SpawnResources.GetRandomPathDist(Settings.PlanetaryCargoShips.MinPathDistance, Settings.PlanetaryCargoShips.MaxPathDistance);
                var endPathA     = randPathDir * randPathDist + tempStartPath;
                var endPathB     = -randPathDir * randPathDist + tempStartPath;
                var tempEndPath  = Vector3D.Zero;

                if (Vector3D.Distance(endPathA, startCoords) < Vector3D.Distance(endPathB, startCoords))
                {
                    tempEndPath = endPathA;
                }
                else
                {
                    tempEndPath  = endPathB;
                    randPathDir *= -1;
                }

                //TODO: Set At Same Height From Sealevel As Start
                var endUpDir = Vector3D.Normalize(tempEndPath - planetEntity.GetPosition());
                tempEndPath = endUpDir * startCoordsDistFromCenter + planetEntity.GetPosition();

                //Check Path
                var  tempMatrix  = MatrixD.CreateWorld(tempStartPath, randPathDir, upDir);
                var  truePathDir = Vector3D.Normalize(tempEndPath - tempStartPath);
                bool badPath     = false;

                foreach (var prefab in spawnGroup.SpawnGroup.Prefabs)
                {
                    var    modifiedStart = Vector3D.Transform((Vector3D)prefab.Position, tempMatrix);
                    double totalSteps    = 0;

                    while (totalSteps < randPathDist)
                    {
                        var testPath = totalSteps * truePathDir + modifiedStart;

                        if (SpawnResources.IsPositionInSafeZone(testPath) == true)
                        {
                            badPath = true;
                            break;
                        }

                        if (SpawnResources.GetDistanceFromSurface(testPath, planet) < Settings.PlanetaryCargoShips.MinPathAltitude)
                        {
                            badPath = true;
                            break;
                        }

                        totalSteps += Settings.PlanetaryCargoShips.PathStepCheckDistance;
                    }

                    if (badPath == true)
                    {
                        break;
                    }
                }

                if (badPath == true)
                {
                    continue;
                }

                startPathCoords = tempStartPath;
                endPathCoords   = tempEndPath;
                startMatrix     = tempMatrix;
                return(true);
            }

            return(false);
        }
        public static bool GetSpawnCoords(ImprovedSpawnGroup spawnGroup, Vector3D startCoords, out Vector3D spawnCoords)
        {
            spawnCoords = Vector3D.Zero;
            SpawnResources.RefreshEntityLists();
            MyPlanet planet        = SpawnResources.GetNearestPlanet(startCoords);
            var      planetEntity  = planet as IMyEntity;
            double   extraDistance = 0;
            double   terrainVarianceCheckTarget = Settings.PlanetaryInstallations.SmallTerrainCheckDistance;

            if (planetEntity == null || planet == null)
            {
                Logger.AddMsg("Planet Somehow Doesn't Exist... Even Though It Should If Script Got Here...", true);
                return(false);
            }

            if (spawnGroup.PlanetaryInstallationType == "Medium")
            {
                extraDistance = Settings.PlanetaryInstallations.MediumSpawnDistanceIncrement;
                terrainVarianceCheckTarget = Settings.PlanetaryInstallations.MediumTerrainCheckDistance;
            }

            if (spawnGroup.PlanetaryInstallationType == "Large")
            {
                extraDistance = Settings.PlanetaryInstallations.LargeSpawnDistanceIncrement;
                terrainVarianceCheckTarget = Settings.PlanetaryInstallations.LargeTerrainCheckDistance;
            }

            var startDist    = Settings.PlanetaryInstallations.MinimumSpawnDistanceFromPlayers + extraDistance;
            var endDist      = Settings.PlanetaryInstallations.MaximumSpawnDistanceFromPlayers + extraDistance;
            var upDir        = Vector3D.Normalize(startCoords - planetEntity.GetPosition());
            var forwardDir   = Vector3D.Normalize(MyUtils.GetRandomPerpendicularVector(ref upDir));
            var searchMatrix = MatrixD.CreateWorld(startCoords, forwardDir, upDir);

            //Searches in 8 directions from the player position
            var searchDirections = new List <Vector3D>();

            searchDirections.Add(searchMatrix.Forward);
            searchDirections.Add(searchMatrix.Backward);
            searchDirections.Add(searchMatrix.Left);
            searchDirections.Add(searchMatrix.Right);

            if (Settings.PlanetaryInstallations.AggressivePathCheck == true)
            {
                searchDirections.Add(Vector3D.Normalize(searchMatrix.Forward + searchMatrix.Left));
                searchDirections.Add(Vector3D.Normalize(searchMatrix.Forward + searchMatrix.Right));
                searchDirections.Add(Vector3D.Normalize(searchMatrix.Backward + searchMatrix.Left));
                searchDirections.Add(Vector3D.Normalize(searchMatrix.Backward + searchMatrix.Right));
            }

            int debugSpawnPointAttempts = 0;
            int searchDirectionAttempts = 0;

            foreach (var searchDirection in searchDirections)
            {
                searchDirectionAttempts++;
                double searchIncrement = startDist;

                while (searchIncrement < endDist)
                {
                    debugSpawnPointAttempts++;
                    var checkCoords   = searchDirection * searchIncrement + startCoords;
                    var surfaceCoords = SpawnResources.GetNearestSurfacePoint(checkCoords, planet);

                    if (SpawnResources.IsPositionNearEntity(surfaceCoords, Settings.PlanetaryInstallations.MinimumSpawnDistanceFromOtherGrids) == true || SpawnResources.IsPositionInSafeZone(surfaceCoords) == true)
                    {
                        searchIncrement += Settings.PlanetaryInstallations.SearchPathIncrement;
                        continue;
                    }

                    var checkUpDir      = Vector3D.Normalize(surfaceCoords - planetEntity.GetPosition());
                    var checkForwardDir = Vector3D.Normalize(MyUtils.GetRandomPerpendicularVector(ref checkUpDir));
                    var checkMatrix     = MatrixD.CreateWorld(surfaceCoords, checkForwardDir, checkUpDir);

                    var checkDirections = new List <Vector3D>();
                    checkDirections.Add(checkMatrix.Forward);
                    checkDirections.Add(checkMatrix.Backward);
                    checkDirections.Add(checkMatrix.Left);
                    checkDirections.Add(checkMatrix.Right);

                    if (Settings.PlanetaryInstallations.AggressiveTerrainCheck == true)
                    {
                        checkDirections.Add(Vector3D.Normalize(checkMatrix.Forward + checkMatrix.Left));
                        checkDirections.Add(Vector3D.Normalize(checkMatrix.Forward + checkMatrix.Right));
                        checkDirections.Add(Vector3D.Normalize(checkMatrix.Backward + checkMatrix.Left));
                        checkDirections.Add(Vector3D.Normalize(checkMatrix.Backward + checkMatrix.Right));
                    }

                    var  distToCore  = Vector3D.Distance(surfaceCoords, planetEntity.GetPosition());
                    bool badPosition = false;

                    if (spawnGroup.SkipTerrainCheck == false)
                    {
                        foreach (var checkDirection in checkDirections)
                        {
                            double terrainCheckIncrement = 0;

                            while (terrainCheckIncrement < terrainVarianceCheckTarget)
                            {
                                var checkTerrainCoords        = checkDirection * terrainCheckIncrement + surfaceCoords;
                                var checkTerrainSurfaceCoords = SpawnResources.GetNearestSurfacePoint(checkTerrainCoords, planet);
                                var checkDistToCore           = Vector3D.Distance(checkTerrainSurfaceCoords, planetEntity.GetPosition());
                                var elevationDiff             = checkDistToCore - distToCore;

                                if (elevationDiff < Settings.PlanetaryInstallations.MinimumTerrainVariance || elevationDiff > Settings.PlanetaryInstallations.MaximumTerrainVariance)
                                {
                                    badPosition = true;
                                    break;
                                }

                                terrainCheckIncrement += Settings.PlanetaryInstallations.TerrainCheckIncrementDistance;
                            }

                            if (badPosition == true)
                            {
                                break;
                            }
                        }
                    }



                    if (badPosition == false)
                    {
                        spawnCoords = surfaceCoords;
                        Logger.AddMsg("Found Installation Site After: " + debugSpawnPointAttempts.ToString() + " Attempts", true);
                        Logger.AddMsg("Search Directions Used: " + searchDirectionAttempts.ToString(), true);
                        return(true);
                    }

                    searchIncrement += Settings.PlanetaryInstallations.SearchPathIncrement;
                }
            }

            Logger.AddMsg("Could Not Find Installation Site After: " + debugSpawnPointAttempts.ToString() + " Attempts", true);
            return(false);
        }
        public static bool CalculateRegularTravelPath(MySpawnGroupDefinition spawnGroup, Vector3D startCoords, out Vector3D startPathCoords, out Vector3D endPathCoords)
        {
            startPathCoords = Vector3D.Zero;
            endPathCoords   = Vector3D.Zero;
            SpawnResources.RefreshEntityLists();
            MyPlanet         planet         = SpawnResources.GetNearestPlanet(startCoords);
            List <IMyEntity> nearbyEntities = new List <IMyEntity>();

            for (int i = 0; i < Settings.SpaceCargoShips.MaxSpawnAttempts; i++)
            {
                var randDir = Vector3D.Normalize(MyUtils.GetRandomVector3D());

                var closestPathDist  = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistanceFromPlayer, (int)Settings.SpaceCargoShips.MaxPathDistanceFromPlayer);
                var closestPathPoint = randDir * closestPathDist + startCoords;

                bool tryInvertedDir = SpawnResources.IsPositionInGravity(closestPathPoint, planet);

                if (tryInvertedDir == true)
                {
                    randDir          = randDir * -1;
                    closestPathPoint = randDir * closestPathDist + startCoords;

                    if (SpawnResources.IsPositionInGravity(closestPathPoint, planet) == true)
                    {
                        continue;
                    }
                }

                var pathDist     = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistance, (int)Settings.SpaceCargoShips.MaxPathDistance);
                var pathDir      = Vector3D.Normalize(MyUtils.GetRandomPerpendicularVector(ref randDir));
                var pathHalfDist = pathDist / 2;

                var tempPathStart = pathDir * pathHalfDist + closestPathPoint;
                pathDir = pathDir * -1;
                var tempPathEnd = pathDir * pathHalfDist + closestPathPoint;

                bool badPath = false;

                IHitInfo hitInfo = null;

                if (MyAPIGateway.Physics.CastLongRay(tempPathStart, tempPathEnd, out hitInfo, true) == true)
                {
                    continue;
                }

                foreach (var entity in SpawnResources.EntityList)
                {
                    if (Vector3D.Distance(tempPathStart, entity.GetPosition()) < Settings.SpaceCargoShips.MinSpawnDistFromEntities)
                    {
                        badPath = true;
                        break;
                    }
                }

                if (badPath == true)
                {
                    continue;
                }

                var upDir      = Vector3D.CalculatePerpendicularVector(pathDir);
                var pathMatrix = MatrixD.CreateWorld(tempPathStart, pathDir, upDir);

                foreach (var prefab in spawnGroup.Prefabs)
                {
                    double stepDistance    = 0;
                    var    tempPrefabStart = Vector3D.Transform((Vector3D)prefab.Position, pathMatrix);

                    while (stepDistance < pathDist)
                    {
                        stepDistance += Settings.SpaceCargoShips.PathCheckStep;
                        var pathCheckCoords = pathDir * stepDistance + tempPrefabStart;

                        if (SpawnResources.IsPositionInSafeZone(pathCheckCoords) == true || SpawnResources.IsPositionInGravity(pathCheckCoords, planet) == true)
                        {
                            badPath = true;
                            break;
                        }
                    }

                    if (badPath == true)
                    {
                        break;
                    }
                }

                if (badPath == true)
                {
                    continue;
                }

                startPathCoords = tempPathStart;
                endPathCoords   = tempPathEnd;
                return(true);
            }

            return(false);
        }
        public static bool CalculateLunarTravelPath(MySpawnGroupDefinition spawnGroup, Vector3D startCoords, out Vector3D startPathCoords, out Vector3D endPathCoords)
        {
            startPathCoords = Vector3D.Zero;
            endPathCoords   = Vector3D.Zero;
            SpawnResources.RefreshEntityLists();
            MyPlanet planet = SpawnResources.GetNearestPlanet(startCoords);

            if (planet == null)
            {
                return(false);
            }

            var planetEntity = planet as IMyEntity;

            for (int i = 0; i < Settings.SpaceCargoShips.MaxSpawnAttempts; i++)
            {
                var spawnAltitude = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinLunarSpawnHeight, (int)Settings.SpaceCargoShips.MaxLunarSpawnHeight);
                var abovePlayer   = SpawnResources.CreateDirectionAndTarget(planetEntity.GetPosition(), startCoords, startCoords, spawnAltitude);
                var midpointDist  = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistanceFromPlayer, (int)Settings.SpaceCargoShips.MaxPathDistanceFromPlayer);
                var pathMidpoint  = SpawnResources.GetRandomCompassDirection(abovePlayer, planet) * midpointDist + abovePlayer;
                var pathDist      = (double)SpawnResources.rnd.Next((int)Settings.SpaceCargoShips.MinPathDistance, (int)Settings.SpaceCargoShips.MaxPathDistance);
                var pathDir       = SpawnResources.GetRandomCompassDirection(abovePlayer, planet);
                var pathHalfDist  = pathDist / 2;

                var tempPathStart = pathDir * pathHalfDist + pathMidpoint;
                pathDir = pathDir * -1;
                var tempPathEnd = pathDir * pathHalfDist + pathMidpoint;

                bool badPath = false;

                IHitInfo hitInfo = null;

                if (MyAPIGateway.Physics.CastLongRay(tempPathStart, tempPathEnd, out hitInfo, true) == true)
                {
                    continue;
                }


                foreach (var entity in SpawnResources.EntityList)
                {
                    if (Vector3D.Distance(tempPathStart, entity.GetPosition()) < Settings.SpaceCargoShips.MinSpawnDistFromEntities)
                    {
                        badPath = true;
                        break;
                    }
                }

                if (badPath == true)
                {
                    continue;
                }

                var upDir      = Vector3D.CalculatePerpendicularVector(pathDir);
                var pathMatrix = MatrixD.CreateWorld(tempPathStart, pathDir, upDir);

                foreach (var prefab in spawnGroup.Prefabs)
                {
                    double stepDistance    = 0;
                    var    tempPrefabStart = Vector3D.Transform((Vector3D)prefab.Position, pathMatrix);

                    while (stepDistance < pathDist)
                    {
                        stepDistance += Settings.SpaceCargoShips.PathCheckStep;
                        var pathCheckCoords = pathDir * stepDistance + tempPrefabStart;

                        if (SpawnResources.IsPositionInSafeZone(pathCheckCoords) == true || SpawnResources.IsPositionInGravity(pathCheckCoords, planet) == true)
                        {
                            badPath = true;
                            break;
                        }
                    }

                    if (badPath == true)
                    {
                        break;
                    }
                }

                if (badPath == true)
                {
                    continue;
                }

                startPathCoords = tempPathStart;
                endPathCoords   = tempPathEnd;

                return(true);
            }

            return(false);
        }
        public static bool GetSpawnCoords(ImprovedSpawnGroup spawnGroup, Vector3D startCoords, out Vector3D spawnCoords)
        {
            spawnCoords = Vector3D.Zero;
            SpawnResources.RefreshEntityLists();
            MyPlanet planet = SpawnResources.GetNearestPlanet(spawnCoords);

            for (int i = 0; i < Settings.RandomEncounters.SpawnAttempts; i++)
            {
                var spawnDir        = Vector3D.Normalize(MyUtils.GetRandomVector3D());
                var randDist        = (double)SpawnResources.rnd.Next((int)Settings.RandomEncounters.MinSpawnDistanceFromPlayer, (int)Settings.RandomEncounters.MaxSpawnDistanceFromPlayer);
                var tempSpawnCoords = spawnDir * randDist + startCoords;

                if (SpawnResources.IsPositionInGravity(tempSpawnCoords, planet) == true)
                {
                    spawnDir       *= -1;
                    tempSpawnCoords = spawnDir * randDist + startCoords;

                    if (SpawnResources.IsPositionInGravity(tempSpawnCoords, planet) == true)
                    {
                        continue;
                    }
                }

                var tempMatrix = MatrixD.CreateWorld(tempSpawnCoords);
                var badPath    = false;

                foreach (var prefab in spawnGroup.SpawnGroup.Prefabs)
                {
                    var prefabCoords = Vector3D.Transform((Vector3D)prefab.Position, tempMatrix);
                    planet = SpawnResources.GetNearestPlanet(prefabCoords);

                    foreach (var entity in SpawnResources.EntityList)
                    {
                        if (Vector3D.Distance(entity.GetPosition(), prefabCoords) < Settings.RandomEncounters.MinDistanceFromOtherEntities)
                        {
                            badPath = true;
                            break;
                        }
                    }

                    if (SpawnResources.IsPositionInSafeZone(prefabCoords) == true || SpawnResources.IsPositionInGravity(prefabCoords, planet) == true)
                    {
                        badPath = true;
                        break;
                    }

                    if (badPath == true)
                    {
                        break;
                    }
                }

                if (badPath == true)
                {
                    continue;
                }

                spawnCoords = tempSpawnCoords;
                return(true);
            }

            return(false);
        }