Example #1
0
        public static bool LunarSpawnEligible(Vector3D checkCoords)
        {
            MyPlanet planet = GetNearestPlanet(checkCoords);

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

            IMyEntity planetEntity     = planet as IMyEntity;
            var       upDir            = Vector3D.Normalize(checkCoords - planetEntity.GetPosition());
            var       closestPathPoint = upDir * Settings.SpaceCargoShips.MinLunarSpawnHeight + checkCoords;

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

            return(true);
        }
        public static List <ImprovedSpawnGroup> GetPlanetaryInstallations(Vector3D playerCoords, out List <ImprovedSpawnGroup> smallStations, out List <ImprovedSpawnGroup> mediumStations, out List <ImprovedSpawnGroup> largeStations, out Dictionary <string, List <string> > validFactions)
        {
            smallStations  = new List <ImprovedSpawnGroup>();
            mediumStations = new List <ImprovedSpawnGroup>();
            largeStations  = new List <ImprovedSpawnGroup>();
            validFactions  = new Dictionary <string, List <string> >();

            MyPlanet planet             = SpawnResources.GetNearestPlanet(playerCoords);
            string   specificGroup      = "";
            var      planetRestrictions = new List <string>(Settings.General.PlanetSpawnsDisableList.ToList());

            SpawnGroupSublists.Clear();
            SmallSpawnGroupSublists.Clear();
            MediumSpawnGroupSublists.Clear();
            LargeSpawnGroupSublists.Clear();
            EligibleSpawnsByModId.Clear();
            EligibleSmallSpawnsByModId.Clear();
            EligibleMediumSpawnsByModId.Clear();
            EligibleLargeSpawnsByModId.Clear();

            if (planet != null)
            {
                if (planetRestrictions.Contains(planet.Generator.Id.SubtypeName) == true)
                {
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            bool specificSpawnRequest = false;

            if (SpawnGroupManager.AdminSpawnGroup != "")
            {
                specificGroup = SpawnGroupManager.AdminSpawnGroup;
                SpawnGroupManager.AdminSpawnGroup = "";
                specificSpawnRequest = true;
            }

            if (SpawnResources.IsPositionInGravity(playerCoords, planet) == false)
            {
                return(new List <ImprovedSpawnGroup>());
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();


            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (specificGroup != "" && spawnGroup.SpawnGroup.Id.SubtypeName != specificGroup)
                {
                    continue;
                }

                if (specificGroup == "" && spawnGroup.AdminSpawnOnly == true)
                {
                    continue;
                }

                if (spawnGroup.PlanetaryInstallation == false)
                {
                    continue;
                }

                if (spawnGroup.PlanetaryInstallationType != "Small" && spawnGroup.PlanetaryInstallationType != "Medium" && spawnGroup.PlanetaryInstallationType != "Large")
                {
                    continue;
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, playerCoords, planet, specificSpawnRequest) == false)
                {
                    continue;
                }

                var validFactionsList = SpawnResources.ValidNpcFactions(spawnGroup, playerCoords);

                if (validFactionsList.Count == 0)
                {
                    continue;
                }

                if (validFactions.ContainsKey(spawnGroup.SpawnGroupName) == false)
                {
                    validFactions.Add(spawnGroup.SpawnGroupName, validFactionsList);
                }

                if (spawnGroup.Frequency > 0)
                {
                    string modID = spawnGroup.SpawnGroup.Context.ModId;

                    if (string.IsNullOrEmpty(modID) == true)
                    {
                        modID = "KeenSWH";
                    }

                    if (SpawnGroupSublists.ContainsKey(modID) == false)
                    {
                        SpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                    }

                    if (spawnGroup.PlanetaryInstallationType == "Small")
                    {
                        if (SmallSpawnGroupSublists.ContainsKey(modID) == false)
                        {
                            SmallSpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                        }

                        if (EligibleSmallSpawnsByModId.ContainsKey(modID) == false)
                        {
                            EligibleSmallSpawnsByModId.Add(modID, 1);
                        }
                        else
                        {
                            EligibleSmallSpawnsByModId[modID] += 1;
                        }
                    }

                    if (spawnGroup.PlanetaryInstallationType == "Medium")
                    {
                        if (MediumSpawnGroupSublists.ContainsKey(modID) == false)
                        {
                            MediumSpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                        }

                        if (EligibleMediumSpawnsByModId.ContainsKey(modID) == false)
                        {
                            EligibleMediumSpawnsByModId.Add(modID, 1);
                        }
                        else
                        {
                            EligibleMediumSpawnsByModId[modID] += 1;
                        }
                    }

                    if (spawnGroup.PlanetaryInstallationType == "Large")
                    {
                        if (LargeSpawnGroupSublists.ContainsKey(modID) == false)
                        {
                            LargeSpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                        }

                        if (EligibleLargeSpawnsByModId.ContainsKey(modID) == false)
                        {
                            EligibleLargeSpawnsByModId.Add(modID, 1);
                        }
                        else
                        {
                            EligibleLargeSpawnsByModId[modID] += 1;
                        }
                    }

                    if (Settings.PlanetaryInstallations.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.PlanetaryInstallations.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.PlanetaryInstallations.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                        SpawnGroupSublists[modID].Add(spawnGroup);

                        if (spawnGroup.PlanetaryInstallationType == "Small")
                        {
                            smallStations.Add(spawnGroup);
                            SmallSpawnGroupSublists[modID].Add(spawnGroup);
                        }

                        if (spawnGroup.PlanetaryInstallationType == "Medium")
                        {
                            mediumStations.Add(spawnGroup);
                            MediumSpawnGroupSublists[modID].Add(spawnGroup);
                        }

                        if (spawnGroup.PlanetaryInstallationType == "Large")
                        {
                            largeStations.Add(spawnGroup);
                            LargeSpawnGroupSublists[modID].Add(spawnGroup);
                        }
                    }
                }
            }

            return(eligibleGroups);
        }
        public static string AttemptSpawn(Vector3D startCoords, IMyPlayer player)
        {
            if (Settings.General.UseMaxNpcGrids == true)
            {
                var totalNPCs = NPCWatcher.ActiveNPCs.Count;

                if (totalNPCs >= Settings.General.MaxGlobalNpcGrids)
                {
                    return("Spawning Aborted. Max Global NPCs Limit Reached.");
                }
            }

            if (NPCWatcher.ActiveNpcTypeLimitReachedForArea("PlanetaryInstallation", startCoords, Settings.PlanetaryInstallations.MaxShipsPerArea, Settings.PlanetaryInstallations.AreaSize) == true)
            {
                return("Too Many Planetary Installation Grids in Player Area");
            }

            MyPlanet planet = SpawnResources.GetNearestPlanet(startCoords);

            if (planet == null)
            {
                return("No Planets In Game World Found.");
            }
            else
            {
                if (SpawnResources.GetDistanceFromSurface(startCoords, planet) > Settings.PlanetaryInstallations.PlayerMaximumDistanceFromSurface || SpawnResources.IsPositionInGravity(startCoords, planet) == false)
                {
                    return("Player Not In Planet Gravity Or Too Far From Surface.");
                }
            }

            var planetEntity = planet as IMyEntity;

            if (MES_SessionCore.playerWatchList.ContainsKey(player) == true)
            {
                var playerSurface = SpawnResources.GetNearestSurfacePoint(player.GetPosition(), planet);

                if (MES_SessionCore.playerWatchList[player].InstallationDistanceCoordCheck == Vector3D.Zero)
                {
                    MES_SessionCore.playerWatchList[player].InstallationDistanceCoordCheck = playerSurface;
                    return("New Player Detected. Storing Position On Planet.");
                }

                if (Vector3D.Distance(MES_SessionCore.playerWatchList[player].InstallationDistanceCoordCheck, playerSurface) < Settings.PlanetaryInstallations.PlayerDistanceSpawnTrigger)
                {
                    Logger.AddMsg("Player Travelled: " + Vector3D.Distance(MES_SessionCore.playerWatchList[player].InstallationDistanceCoordCheck, playerSurface) + " Distance From Last Saved Position.");
                    return("Player Hasn't Traveled Far Enough Yet.");
                }

                MES_SessionCore.playerWatchList[player].InstallationDistanceCoordCheck = playerSurface;
            }
            else
            {
                return("Player Not In Watcher List... Although They Probably Should Be If The Script Got Here.");
            }

            var smallStations  = new List <ImprovedSpawnGroup>();
            var mediumStations = new List <ImprovedSpawnGroup>();
            var largeStations  = new List <ImprovedSpawnGroup>();
            var validFactions  = new Dictionary <string, List <string> >();
            var spawnGroupList = GetPlanetaryInstallations(startCoords, out smallStations, out mediumStations, out largeStations, out validFactions);

            if (Settings.General.UseModIdSelectionForSpawning == true)
            {
                spawnGroupList = SpawnResources.SelectSpawnGroupSublist(SpawnGroupSublists, EligibleSpawnsByModId);
                smallStations  = SpawnResources.SelectSpawnGroupSublist(SmallSpawnGroupSublists, EligibleSmallSpawnsByModId);
                mediumStations = SpawnResources.SelectSpawnGroupSublist(MediumSpawnGroupSublists, EligibleMediumSpawnsByModId);
                largeStations  = SpawnResources.SelectSpawnGroupSublist(LargeSpawnGroupSublists, EligibleLargeSpawnsByModId);
            }

            if (spawnGroupList.Count == 0)
            {
                return("No Eligible Spawn Groups Could Be Found To Spawn Near Player.");
            }

            Logger.AddMsg("Found " + (spawnGroupList.Count / 10).ToString() + " Potential Spawn Groups. Small: " + (smallStations.Count / 10).ToString() + " // Medium: " + (mediumStations.Count / 10).ToString() + " // Large: " + (largeStations.Count / 10).ToString(), true);

            string stationSize = "Small";

            spawnGroupList = smallStations;

            bool skippedAbsentSmall  = false;
            bool skippedAbsentMedium = false;
            bool skippedAbsentLarge  = false;

            //Start With Small Station Always, Try Chance For Medium.
            if (stationSize == "Small" && smallStations.Count == 0)
            {
                //No Small Stations Available For This Area, So Try Medium.
                skippedAbsentSmall = true;
                stationSize        = "Medium";
                spawnGroupList     = mediumStations;
            }
            else if (stationSize == "Small" && smallStations.Count != 0)
            {
                int    mediumChance = 0;
                string varName      = "MES-" + planetEntity.EntityId.ToString() + "-Medium";

                if (MyAPIGateway.Utilities.GetVariable <int>(varName, out mediumChance) == false)
                {
                    mediumChance = Settings.PlanetaryInstallations.MediumSpawnChanceBaseValue;
                    MyAPIGateway.Utilities.SetVariable <int>(varName, mediumChance);
                }

                if (SpawnResources.rnd.Next(0, 100) < mediumChance)
                {
                    stationSize    = "Medium";
                    spawnGroupList = mediumStations;
                }
            }

            if (stationSize == "Medium" && mediumStations.Count == 0)
            {
                //No Medium Stations Available For This Area, So Try Large.
                skippedAbsentMedium = true;
                stationSize         = "Large";
                spawnGroupList      = largeStations;
            }
            else if (stationSize == "Medium" && mediumStations.Count != 0)
            {
                int    largeChance = 0;
                string varName     = "MES-" + planetEntity.EntityId.ToString() + "-Large";

                if (MyAPIGateway.Utilities.GetVariable <int>(varName, out largeChance) == false)
                {
                    largeChance = Settings.PlanetaryInstallations.LargeSpawnChanceBaseValue;
                    MyAPIGateway.Utilities.SetVariable <int>(varName, largeChance);
                }

                if (SpawnResources.rnd.Next(0, 100) < largeChance)
                {
                    stationSize    = "Large";
                    spawnGroupList = largeStations;
                }
            }

            if (stationSize == "Large" && largeStations.Count == 0)
            {
                skippedAbsentLarge = true;
                stationSize        = "Medium";
                spawnGroupList     = mediumStations;

                if (mediumStations.Count == 0)
                {
                    skippedAbsentMedium = true;
                    stationSize         = "Small";
                    spawnGroupList      = smallStations;
                }
            }

            if (spawnGroupList.Count == 0)
            {
                return("Could Not Find Station Of Suitable Size For This Spawn Instance.");
            }

            var      spawnGroup  = spawnGroupList[SpawnResources.rnd.Next(0, spawnGroupList.Count)];
            Vector3D spawnCoords = Vector3D.Zero;

            Logger.StartTimer();

            if (GetSpawnCoords(spawnGroup, startCoords, out spawnCoords) == false)
            {
                Logger.AddMsg("Planetary Installation Spawn Coord Calculation Time: " + Logger.StopTimer(), true);
                return("Could Not Find Safe Position To Spawn " + stationSize + " Installation.");
            }

            Logger.AddMsg("Planetary Installation Spawn Coord Calculation Time: " + Logger.StopTimer(), true);

            //Get Directions
            var upDir                = Vector3D.Normalize(spawnCoords - planetEntity.GetPosition());
            var forwardDir           = Vector3D.CalculatePerpendicularVector(upDir);
            var spawnMatrix          = MatrixD.CreateWorld(spawnCoords, forwardDir, upDir);
            var successfulVoxelSpawn = false;

            foreach (var voxel in spawnGroup.SpawnGroup.Voxels)
            {
                var voxelSpawningPosition = Vector3D.Transform((Vector3D)voxel.Offset, spawnMatrix);

                try{
                    var voxelSpawn = MyAPIGateway.Session.VoxelMaps.CreateVoxelMapFromStorageName(voxel.StorageName, voxel.StorageName, voxelSpawningPosition);

                    if (Settings.PlanetaryInstallations.RemoveVoxelsIfGridRemoved == true && spawnGroup.RemoveVoxelsIfGridRemoved == true)
                    {
                        NPCWatcher.SpawnedVoxels.Add(voxelSpawn.EntityId.ToString(), voxelSpawn as IMyEntity);
                    }

                    successfulVoxelSpawn = true;
                }catch (Exception exc) {
                    Logger.AddMsg("Voxel Spawning For " + voxel.StorageName + " Failed");
                }
            }

            if (successfulVoxelSpawn == true)
            {
                var      voxelIdList  = new List <string>(NPCWatcher.SpawnedVoxels.Keys.ToList());
                string[] voxelIdArray = voxelIdList.ToArray();
                MyAPIGateway.Utilities.SetVariable <string[]>("MES-SpawnedVoxels", voxelIdArray);
            }

            long gridOwner      = 0;
            var  randFactionTag = spawnGroup.FactionOwner;

            if (validFactions.ContainsKey(spawnGroup.SpawnGroupName))
            {
                randFactionTag = validFactions[spawnGroup.SpawnGroupName][SpawnResources.rnd.Next(0, validFactions[spawnGroup.SpawnGroupName].Count)];
            }

            if (NPCWatcher.NPCFactionTagToFounder.ContainsKey(randFactionTag) == true)
            {
                gridOwner = NPCWatcher.NPCFactionTagToFounder[randFactionTag];
            }
            else
            {
                Logger.AddMsg("Could Not Find Faction Founder For: " + randFactionTag);
            }

            for (int i = 0; i < spawnGroup.SpawnGroup.Prefabs.Count; i++)
            {
                var prefab        = spawnGroup.SpawnGroup.Prefabs[i];
                var options       = SpawnGroupManager.CreateSpawningOptions(spawnGroup, prefab);
                var spawnPosition = Vector3D.Transform((Vector3D)prefab.Position, spawnMatrix);

                //Realign to Terrain
                var offsetSurfaceCoords = SpawnResources.GetNearestSurfacePoint(spawnPosition, planet);
                var offsetSurfaceMatrix = MatrixD.CreateWorld(offsetSurfaceCoords, forwardDir, upDir);
                var finalCoords         = Vector3D.Transform(new Vector3D(0, (double)prefab.Position.Y, 0), offsetSurfaceMatrix);

                var newForward = offsetSurfaceMatrix.Forward;
                var newUp      = offsetSurfaceMatrix.Up;

                GetReversedForwardDirections(spawnGroup, i, ref newForward);
                GetDerelictDirections(spawnGroup, i, finalCoords, ref newForward, ref newUp);

                var speedL   = Vector3.Zero;
                var speedA   = Vector3.Zero;
                var gridList = new List <IMyCubeGrid>();

                //Grid Manipulation
                GridBuilderManipulation.ProcessPrefabForManipulation(prefab.SubtypeId, spawnGroup, "PlanetaryInstallation", prefab.Behaviour);

                try{
                    MyAPIGateway.PrefabManager.SpawnPrefab(gridList, prefab.SubtypeId, finalCoords, newForward, newUp, speedL, speedA, prefab.BeaconText, options, gridOwner);
                }catch (Exception exc) {
                }

                Logger.AddMsg("Installation Forward Vector: " + newForward.ToString(), true);
                var pendingNPC = new ActiveNPC();
                pendingNPC.SpawnGroup            = spawnGroup;
                pendingNPC.SpawnGroupName        = spawnGroup.SpawnGroupName;
                pendingNPC.InitialFaction        = randFactionTag;
                pendingNPC.faction               = MyAPIGateway.Session.Factions.TryGetFactionByTag(pendingNPC.InitialFaction);
                pendingNPC.Name                  = prefab.SubtypeId;
                pendingNPC.GridName              = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId).CubeGrids[0].DisplayName;
                pendingNPC.StartCoords           = finalCoords;
                pendingNPC.CurrentCoords         = finalCoords;
                pendingNPC.EndCoords             = finalCoords;
                pendingNPC.SpawnType             = "PlanetaryInstallation";
                pendingNPC.CleanupIgnore         = spawnGroup.IgnoreCleanupRules;
                pendingNPC.ForceStaticGrid       = spawnGroup.ForceStaticGrid;
                pendingNPC.KeenAiName            = prefab.Behaviour;
                pendingNPC.KeenAiTriggerDistance = prefab.BehaviourActivationDistance;

                if (spawnGroup.RandomizeWeapons == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if ((MES_SessionCore.NPCWeaponUpgradesModDetected == true || Settings.General.EnableGlobalNPCWeaponRandomizer == true) && spawnGroup.IgnoreWeaponRandomizerMod == false)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if (spawnGroup.ReplenishSystems == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                }

                NPCWatcher.PendingNPCs.Add(pendingNPC);
            }

            if (spawnGroup.PlanetaryInstallationType == "Small")
            {
                int    mediumChance = 0;
                string varName      = "MES-" + planetEntity.EntityId.ToString() + "-Medium";
                if (MyAPIGateway.Utilities.GetVariable <int>(varName, out mediumChance) == true)
                {
                    mediumChance += Settings.PlanetaryInstallations.MediumSpawnChanceIncrement;
                    MyAPIGateway.Utilities.SetVariable <int>(varName, mediumChance);
                }

                Logger.AddMsg("Medium Installation Spawning Chance Now Set To: " + mediumChance.ToString() + " / 100", true);
            }

            if (spawnGroup.PlanetaryInstallationType == "Medium" || skippedAbsentMedium == true)
            {
                int    mediumChance = 0;
                string varName      = "MES-" + planetEntity.EntityId.ToString() + "-Medium";
                if (MyAPIGateway.Utilities.GetVariable <int>(varName, out mediumChance) == true)
                {
                    mediumChance = Settings.PlanetaryInstallations.MediumSpawnChanceBaseValue;
                    MyAPIGateway.Utilities.SetVariable <int>(varName, mediumChance);
                }

                Logger.AddMsg("Medium Installation Spawning Chance Now Set To: " + mediumChance.ToString() + " / 100", true);

                int largeChance = 0;
                varName = "MES-" + planetEntity.EntityId.ToString() + "-Large";
                if (MyAPIGateway.Utilities.GetVariable <int>(varName, out largeChance) == true)
                {
                    largeChance += Settings.PlanetaryInstallations.LargeSpawnChanceIncrement;
                    MyAPIGateway.Utilities.SetVariable <int>(varName, largeChance);
                }

                Logger.AddMsg("Large Installation Spawning Chance Now Set To: " + largeChance.ToString() + " / 100", true);
            }

            if (spawnGroup.PlanetaryInstallationType == "Large" || skippedAbsentLarge == true)
            {
                int    largeChance = 0;
                string varName     = "MES-" + planetEntity.EntityId.ToString() + "-Large";
                if (MyAPIGateway.Utilities.GetVariable <int>(varName, out largeChance) == true)
                {
                    largeChance = Settings.PlanetaryInstallations.LargeSpawnChanceBaseValue;
                    MyAPIGateway.Utilities.SetVariable <int>(varName, largeChance);
                }

                Logger.AddMsg("Large Installation Spawning Chance Now Set To: " + largeChance.ToString() + " / 100", true);
            }

            if (spawnGroup.UniqueEncounter == true)
            {
                SpawnGroupManager.UniqueGroupsSpawned.Add(spawnGroup.SpawnGroup.Id.SubtypeName);
                string[] uniqueSpawnedArray = SpawnGroupManager.UniqueGroupsSpawned.ToArray();
                MyAPIGateway.Utilities.SetVariable <string[]>("MES-UniqueGroupsSpawned", uniqueSpawnedArray);
            }

            Logger.SkipNextMessage = false;
            return("Spawning Group - " + spawnGroup.SpawnGroup.Id.SubtypeName);
        }
        public static string AttemptSpawn(Vector3D startCoords)
        {
            if (Settings.General.UseMaxNpcGrids == true)
            {
                var totalNPCs = NPCWatcher.ActiveNPCs.Count;

                if (totalNPCs >= Settings.General.MaxGlobalNpcGrids)
                {
                    return("Spawning Aborted. Max Global NPCs Limit Reached.");
                }
            }

            if (NPCWatcher.ActiveNpcTypeLimitReachedForArea("SpaceCargoShip", startCoords, Settings.SpaceCargoShips.MaxShipsPerArea, Settings.SpaceCargoShips.AreaSize) == true)
            {
                return("Too Many Space Cargo Ship Grids in Player Area");
            }

            var validFactions  = new Dictionary <string, List <string> >();
            var spawnGroupList = GetSpaceCargoShips(startCoords, out validFactions);

            if (Settings.General.UseModIdSelectionForSpawning == true)
            {
                spawnGroupList = SpawnResources.SelectSpawnGroupSublist(SpawnGroupSublists, EligibleSpawnsByModId);
            }

            if (spawnGroupList.Count == 0)
            {
                return("No Eligible Spawn Groups Could Be Found To Spawn Near Player.");
            }

            var      spawnGroup      = spawnGroupList[SpawnResources.rnd.Next(0, spawnGroupList.Count)];
            var      startPathCoords = Vector3D.Zero;
            var      endPathCoords   = Vector3D.Zero;
            bool     successfulPath  = false;
            MyPlanet planet          = SpawnResources.GetNearestPlanet(startCoords);

            if (SpawnResources.LunarSpawnEligible(startCoords) == false)
            {
                successfulPath = CalculateRegularTravelPath(spawnGroup.SpawnGroup, startCoords, out startPathCoords, out endPathCoords);
            }
            else
            {
                successfulPath = CalculateLunarTravelPath(spawnGroup.SpawnGroup, startCoords, out startPathCoords, out endPathCoords);
            }

            if (successfulPath == false)
            {
                return("Could Not Generate Safe Travel Path For SpawnGroup.");
            }

            //Get Directions
            var  spawnForwardDir = Vector3D.Normalize(endPathCoords - startPathCoords);
            var  spawnUpDir      = Vector3D.CalculatePerpendicularVector(spawnForwardDir);
            var  spawnMatrix     = MatrixD.CreateWorld(startPathCoords, spawnForwardDir, spawnUpDir);
            long gridOwner       = 0;
            var  randFactionTag  = spawnGroup.FactionOwner;

            if (validFactions.ContainsKey(spawnGroup.SpawnGroupName))
            {
                randFactionTag = validFactions[spawnGroup.SpawnGroupName][SpawnResources.rnd.Next(0, validFactions[spawnGroup.SpawnGroupName].Count)];
            }

            if (NPCWatcher.NPCFactionTagToFounder.ContainsKey(randFactionTag) == true)
            {
                gridOwner = NPCWatcher.NPCFactionTagToFounder[randFactionTag];
            }
            else
            {
                Logger.AddMsg("Could Not Find Faction Founder For: " + randFactionTag);
            }

            foreach (var prefab in spawnGroup.SpawnGroup.Prefabs)
            {
                var options       = SpawnGroupManager.CreateSpawningOptions(spawnGroup, prefab);
                var spawnPosition = Vector3D.Transform((Vector3D)prefab.Position, spawnMatrix);
                var speedL        = prefab.Speed * (Vector3)spawnForwardDir;
                var speedA        = Vector3.Zero;
                var gridList      = new List <IMyCubeGrid>();


                //Speed Management
                if (Settings.SpaceCargoShips.UseMinimumSpeed == true && prefab.Speed < Settings.SpaceCargoShips.MinimumSpeed)
                {
                    speedL = Settings.SpaceCargoShips.MinimumSpeed * (Vector3)spawnForwardDir;
                }

                if (Settings.SpaceCargoShips.UseSpeedOverride == true)
                {
                    speedL = Settings.SpaceCargoShips.SpeedOverride * (Vector3)spawnForwardDir;
                }



                //Grid Manipulation
                GridBuilderManipulation.ProcessPrefabForManipulation(prefab.SubtypeId, spawnGroup, "SpaceCargoShip", prefab.Behaviour);

                try{
                    MyAPIGateway.PrefabManager.SpawnPrefab(gridList, prefab.SubtypeId, spawnPosition, spawnForwardDir, spawnUpDir, speedL, speedA, prefab.BeaconText, options, gridOwner);
                }catch (Exception exc) {
                    Logger.AddMsg("Something Went Wrong With Prefab Spawn Manager.", true);
                }

                var pendingNPC = new ActiveNPC();
                pendingNPC.SpawnGroupName        = spawnGroup.SpawnGroupName;
                pendingNPC.SpawnGroup            = spawnGroup;
                pendingNPC.InitialFaction        = randFactionTag;
                pendingNPC.faction               = MyAPIGateway.Session.Factions.TryGetFactionByTag(pendingNPC.InitialFaction);
                pendingNPC.Name                  = prefab.SubtypeId;
                pendingNPC.GridName              = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId).CubeGrids[0].DisplayName;
                pendingNPC.StartCoords           = startPathCoords;
                pendingNPC.CurrentCoords         = startPathCoords;
                pendingNPC.EndCoords             = endPathCoords;
                pendingNPC.SpawnType             = "SpaceCargoShip";
                pendingNPC.AutoPilotSpeed        = speedL.Length();
                pendingNPC.CleanupIgnore         = spawnGroup.IgnoreCleanupRules;
                pendingNPC.ForceStaticGrid       = spawnGroup.ForceStaticGrid;
                pendingNPC.KeenAiName            = prefab.Behaviour;
                pendingNPC.KeenAiTriggerDistance = prefab.BehaviourActivationDistance;

                if (string.IsNullOrEmpty(pendingNPC.KeenAiName) == false)
                {
                    Logger.AddMsg("Stock AI Detected In Prefab: " + prefab.SubtypeId + " in SpawnGroup: " + spawnGroup.SpawnGroup.Id.SubtypeName);
                }

                if (spawnGroup.RandomizeWeapons == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if ((MES_SessionCore.NPCWeaponUpgradesModDetected == true || Settings.General.EnableGlobalNPCWeaponRandomizer == true) && spawnGroup.IgnoreWeaponRandomizerMod == false)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if (spawnGroup.ReplenishSystems == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                }

                NPCWatcher.PendingNPCs.Add(pendingNPC);
            }

            Logger.SkipNextMessage = false;
            return("Spawning Group - " + spawnGroup.SpawnGroup.Id.SubtypeName);
        }
        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 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 List <ImprovedSpawnGroup> GetSpawnGroups(List <string> spawnGroups, Vector3D coords, out Dictionary <string, List <string> > validFactions)
        {
            MyPlanet planet             = SpawnResources.GetNearestPlanet(coords);
            var      planetRestrictions = new List <string>(Settings.General.PlanetSpawnsDisableList.ToList());

            validFactions = new Dictionary <string, List <string> >();

            if (planet != null)
            {
                if (planetRestrictions.Contains(planet.Generator.Id.SubtypeName) == true)
                {
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            string planetName = "";

            if (planet != null)
            {
                planetName = planet.Generator.Id.SubtypeId.ToString();
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();

            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (!spawnGroups.Contains(spawnGroup.SpawnGroupName))
                {
                    continue;
                }

                if (spawnGroup.RivalAiAnySpawn == false)
                {
                    if (planet == null && spawnGroup.RivalAiSpaceSpawn == false)
                    {
                        continue;
                    }

                    if (planet != null)
                    {
                        var airDensity = planet.GetAirDensity(coords);

                        if (spawnGroup.RivalAiAtmosphericSpawn == false || planet.HasAtmosphere == false || airDensity < 0.4f)
                        {
                            continue;
                        }
                    }
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, coords, planet, false) == false)
                {
                    continue;
                }

                var validFactionsList = SpawnResources.ValidNpcFactions(spawnGroup, coords);

                if (validFactionsList.Count == 0)
                {
                    continue;
                }

                if (validFactions.ContainsKey(spawnGroup.SpawnGroupName) == false)
                {
                    validFactions.Add(spawnGroup.SpawnGroupName, validFactionsList);
                }

                if (spawnGroup.Frequency > 0)
                {
                    if (Settings.SpaceCargoShips.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.SpaceCargoShips.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.SpaceCargoShips.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                    }
                }
            }

            return(eligibleGroups);
        }
        public static string AttemptSpawn(Vector3D startCoords, List <string> eligibleNames = null)
        {
            if (Settings.General.UseMaxNpcGrids == true)
            {
                var totalNPCs = NPCWatcher.ActiveNPCs.Count;

                if (totalNPCs >= Settings.General.MaxGlobalNpcGrids)
                {
                    return("Spawning Aborted. Max Global NPCs Limit Reached.");
                }
            }

            if (NPCWatcher.ActiveNpcTypeLimitReachedForArea("PlanetaryCargoShip", startCoords, Settings.PlanetaryCargoShips.MaxShipsPerArea, Settings.PlanetaryCargoShips.AreaSize) == true)
            {
                return("Too Many Planetary Cargo Ship Grids in Player Area");
            }

            MyPlanet planet = SpawnResources.GetNearestPlanet(startCoords);

            if (SpawnResources.GetDistanceFromSurface(startCoords, planet) > Settings.PlanetaryCargoShips.PlayerSurfaceAltitude)
            {
                return("Player Is Too Far From Planet Surface.");
            }

            KnownPlayerLocationManager.CleanExpiredLocations();
            var validFactions  = new Dictionary <string, List <string> >();
            var spawnGroupList = GetPlanetaryCargoShips(startCoords, eligibleNames, out validFactions);

            if (Settings.General.UseModIdSelectionForSpawning == true)
            {
                spawnGroupList = SpawnResources.SelectSpawnGroupSublist(SpawnGroupSublists, EligibleSpawnsByModId);
            }

            if (spawnGroupList.Count == 0)
            {
                return("No Eligible Spawn Groups Could Be Found To Spawn Near Player.");
            }

            var spawnGroup = spawnGroupList[SpawnResources.rnd.Next(0, spawnGroupList.Count)];

            Vector3D startPathCoords = Vector3D.Zero;
            Vector3D endPathCoords   = Vector3D.Zero;
            MatrixD  startMatrix     = MatrixD.CreateWorld(Vector3D.Zero, Vector3D.Forward, Vector3D.Up);

            bool successfulPath = CalculateAtmoTravelPath(spawnGroup, startCoords, planet, out startPathCoords, out endPathCoords, out startMatrix);

            if (successfulPath == false)
            {
                return("Could Not Generate Safe Travel Path For SpawnGroup.");
            }

            //Get Directions
            var  spawnForwardDir = startMatrix.Forward;
            var  spawnUpDir      = startMatrix.Up;
            var  spawnMatrix     = startMatrix;
            long gridOwner       = 0;
            var  randFactionTag  = spawnGroup.FactionOwner;

            if (validFactions.ContainsKey(spawnGroup.SpawnGroupName))
            {
                randFactionTag = validFactions[spawnGroup.SpawnGroupName][SpawnResources.rnd.Next(0, validFactions[spawnGroup.SpawnGroupName].Count)];
            }

            if (NPCWatcher.NPCFactionTagToFounder.ContainsKey(randFactionTag) == true)
            {
                gridOwner = NPCWatcher.NPCFactionTagToFounder[randFactionTag];
            }
            else
            {
                Logger.AddMsg("Could Not Find Faction Founder For: " + randFactionTag);
            }

            foreach (var prefab in spawnGroup.SpawnGroup.Prefabs)
            {
                if (spawnGroup.UseKnownPlayerLocations)
                {
                    KnownPlayerLocationManager.IncreaseSpawnCountOfLocations(startCoords, randFactionTag);
                }

                var options       = SpawnGroupManager.CreateSpawningOptions(spawnGroup, prefab);
                var spawnPosition = Vector3D.Transform((Vector3D)prefab.Position, spawnMatrix);
                var speedL        = prefab.Speed;
                var speedA        = Vector3.Zero;
                var gridList      = new List <IMyCubeGrid>();


                //Speed Management
                if (Settings.PlanetaryCargoShips.UseMinimumSpeed == true && prefab.Speed < Settings.PlanetaryCargoShips.MinimumSpeed)
                {
                    speedL = Settings.PlanetaryCargoShips.MinimumSpeed;
                }

                if (Settings.PlanetaryCargoShips.UseSpeedOverride == true)
                {
                    speedL = Settings.PlanetaryCargoShips.SpeedOverride;
                }



                /*//Character Injection - Start
                 * MyPrefabDefinition prefabDefB = null;
                 *
                 * if(SpawnGroupManager.prefabBackupList.ContainsKey(prefab.SubtypeId) == true){
                 *
                 *      prefabDefB = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId);
                 *
                 *      if(SpawnGroupManager.prefabBackupList[prefab.SubtypeId].Count == prefabDefB.CubeGrids.Length){
                 *
                 *              for(int i = 0; i < SpawnGroupManager.prefabBackupList[prefab.SubtypeId].Count; i++){
                 *
                 *                      var clonedGridOb = SpawnGroupManager.prefabBackupList[prefab.SubtypeId][i].Clone();
                 *                      prefabDefB.CubeGrids[i] = clonedGridOb as MyObjectBuilder_CubeGrid;
                 *
                 *              }
                 *
                 *      }
                 *
                 *      SpawnGroupManager.prefabBackupList.Remove(prefab.SubtypeId);
                 *
                 * }
                 *
                 * var injectedCharacters = false;
                 * if(spawnGroup.FillSeatsWithNpcCrew == true){
                 *
                 *      injectedCharacters = true;
                 *
                 *      if(prefabDefB == null){
                 *
                 *              prefabDefB = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId);
                 *
                 *      }
                 *
                 *      var backupGridList = new List<MyObjectBuilder_CubeGrid>();
                 *
                 *      for(int i = 0; i < prefabDefB.CubeGrids.Length; i++){
                 *
                 *              var clonedGridOb = prefabDefB.CubeGrids[i].Clone();
                 *              backupGridList.Add(clonedGridOb as MyObjectBuilder_CubeGrid);
                 *              GridUtilities.CreateAndAttachCrew(prefabDefB.CubeGrids[i], spawnGroup, gridOwner);
                 *
                 *      }
                 *
                 *      if(SpawnGroupManager.prefabBackupList.ContainsKey(prefab.SubtypeId) == false){
                 *
                 *              SpawnGroupManager.prefabBackupList.Add(prefab.SubtypeId, backupGridList);
                 *
                 *      }
                 *
                 * }
                 * //Character Injection - End*/

                //Grid Manipulation
                GridBuilderManipulation.ProcessPrefabForManipulation(prefab.SubtypeId, spawnGroup, "PlanetaryCargoShip", prefab.Behaviour);

                try{
                    MyAPIGateway.PrefabManager.SpawnPrefab(gridList, prefab.SubtypeId, spawnPosition, spawnForwardDir, spawnUpDir, Vector3.Zero, Vector3.Zero, !string.IsNullOrWhiteSpace(prefab.BeaconText) ? prefab.BeaconText : null, options, gridOwner);
                }catch (Exception exc) {
                }

                var pendingNPC = new ActiveNPC();
                pendingNPC.SpawnGroup            = spawnGroup;
                pendingNPC.SpawnGroupName        = spawnGroup.SpawnGroupName;
                pendingNPC.InitialFaction        = randFactionTag;
                pendingNPC.faction               = MyAPIGateway.Session.Factions.TryGetFactionByTag(pendingNPC.InitialFaction);
                pendingNPC.Name                  = prefab.SubtypeId;
                pendingNPC.GridName              = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId).CubeGrids[0].DisplayName;
                pendingNPC.StartCoords           = startPathCoords;
                pendingNPC.CurrentCoords         = startPathCoords;
                pendingNPC.EndCoords             = endPathCoords;
                pendingNPC.AutoPilotSpeed        = speedL;
                pendingNPC.Planet                = planet;
                pendingNPC.SpawnType             = "PlanetaryCargoShip";
                pendingNPC.CleanupIgnore         = spawnGroup.IgnoreCleanupRules;
                pendingNPC.ForceStaticGrid       = spawnGroup.ForceStaticGrid;
                pendingNPC.KeenAiName            = prefab.Behaviour;
                pendingNPC.KeenAiTriggerDistance = prefab.BehaviourActivationDistance;

                if (spawnGroup.RandomizeWeapons == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if ((MES_SessionCore.NPCWeaponUpgradesModDetected == true || Settings.General.EnableGlobalNPCWeaponRandomizer == true) && spawnGroup.IgnoreWeaponRandomizerMod == false)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if (spawnGroup.ReplenishSystems == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                }

                NPCWatcher.PendingNPCs.Add(pendingNPC);
            }

            Logger.SkipNextMessage = false;
            return("Spawning Group - " + spawnGroup.SpawnGroup.Id.SubtypeName);
        }
        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);
        }
Example #10
0
        public static List <ImprovedSpawnGroup> GetRandomEncounters(Vector3D playerCoords, out Dictionary <string, List <string> > validFactions)
        {
            MyPlanet planet        = SpawnResources.GetNearestPlanet(playerCoords);
            string   specificGroup = "";

            validFactions = new Dictionary <string, List <string> >();
            SpawnGroupSublists.Clear();
            EligibleSpawnsByModId.Clear();

            bool specificSpawnRequest = false;

            if (SpawnGroupManager.AdminSpawnGroup != "")
            {
                specificGroup = SpawnGroupManager.AdminSpawnGroup;
                SpawnGroupManager.AdminSpawnGroup = "";
                specificSpawnRequest = true;
            }

            if (SpawnResources.IsPositionInGravity(playerCoords, planet) == true)
            {
                return(new List <ImprovedSpawnGroup>());
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();

            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (specificGroup != "" && spawnGroup.SpawnGroup.Id.SubtypeName != specificGroup)
                {
                    continue;
                }

                if (specificGroup == "" && spawnGroup.AdminSpawnOnly == true)
                {
                    continue;
                }

                if (spawnGroup.SpaceRandomEncounter == false)
                {
                    continue;
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, playerCoords, planet, specificSpawnRequest) == false)
                {
                    continue;
                }

                var validFactionsList = SpawnResources.ValidNpcFactions(spawnGroup, playerCoords);

                if (validFactionsList.Count == 0)
                {
                    continue;
                }

                if (validFactions.ContainsKey(spawnGroup.SpawnGroupName) == false)
                {
                    validFactions.Add(spawnGroup.SpawnGroupName, validFactionsList);
                }

                if (spawnGroup.Frequency > 0)
                {
                    string modID = spawnGroup.SpawnGroup.Context.ModId;

                    if (string.IsNullOrEmpty(modID) == true)
                    {
                        modID = "KeenSWH";
                    }

                    if (SpawnGroupSublists.ContainsKey(modID) == false)
                    {
                        SpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                    }

                    if (EligibleSpawnsByModId.ContainsKey(modID) == false)
                    {
                        EligibleSpawnsByModId.Add(modID, 1);
                    }
                    else
                    {
                        EligibleSpawnsByModId[modID] += 1;
                    }

                    if (Settings.RandomEncounters.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.RandomEncounters.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.RandomEncounters.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                        SpawnGroupSublists[modID].Add(spawnGroup);
                    }
                }
            }

            return(eligibleGroups);
        }
        public static bool GetInitialSpawnCoords(Vector3D startCoords, out Vector3D spawnCoords)
        {
            spawnCoords = Vector3D.Zero;
            MyPlanet planet    = SpawnResources.GetNearestPlanet(startCoords);
            var      inGravity = SpawnResources.IsPositionInGravity(startCoords, planet);

            for (int i = 0; i < Settings.BossEncounters.PathCalculationAttempts; i++)
            {
                var testCoords = Vector3D.Zero;

                if (inGravity == false)
                {
                    var randDir  = Vector3D.Normalize(MyUtils.GetRandomVector3D());
                    var randDist = (double)SpawnResources.rnd.Next((int)Settings.BossEncounters.MinCoordsDistanceSpace, (int)Settings.BossEncounters.MaxCoordsDistanceSpace);
                    spawnCoords = randDir * randDist + startCoords;

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

                        if (SpawnResources.IsPositionInGravity(spawnCoords, planet) == true)
                        {
                            continue;
                        }
                    }
                }
                else
                {
                    var planetEntity  = planet as IMyEntity;
                    var upDir         = Vector3D.Normalize(startCoords - planetEntity.GetPosition());
                    var randDir       = SpawnResources.GetRandomCompassDirection(startCoords, planet);
                    var randDist      = (double)SpawnResources.rnd.Next((int)Settings.BossEncounters.MinCoordsDistancePlanet, (int)Settings.BossEncounters.MaxCoordsDistancePlanet);
                    var roughCoords   = randDir * randDist + startCoords;
                    var surfaceCoords = SpawnResources.GetNearestSurfacePoint(roughCoords, planet);
                    spawnCoords = upDir * Settings.BossEncounters.MinPlanetAltitude + surfaceCoords;

                    if (planet.GetAirDensity(spawnCoords) < Settings.BossEncounters.MinAirDensity)
                    {
                        spawnCoords = Vector3D.Zero;
                        continue;
                    }
                }

                if (spawnCoords == Vector3D.Zero)
                {
                    continue;
                }

                bool badCoords = false;

                foreach (var entity in SpawnResources.EntityList)
                {
                    if (Vector3D.Distance(spawnCoords, entity.GetPosition()) < Settings.BossEncounters.MinSignalDistFromOtherEntities)
                    {
                        badCoords = true;
                        break;
                    }
                }

                if (badCoords == false)
                {
                    if (SpawnResources.IsPositionInSafeZone(spawnCoords) == true)
                    {
                        badCoords = true;
                    }
                }

                if (badCoords == false)
                {
                    return(true);
                }
            }

            spawnCoords = Vector3D.Zero;
            return(false);
        }
        public static string AttemptSpawn(Vector3D startCoords)
        {
            if (Settings.General.UseMaxNpcGrids == true)
            {
                var totalNPCs = NPCWatcher.ActiveNPCs.Count;

                if (totalNPCs >= Settings.General.MaxGlobalNpcGrids)
                {
                    return("Spawning Aborted. Max Global NPCs Limit Reached.");
                }
            }

            if (NPCWatcher.ActiveNpcTypeLimitReachedForArea("BossEncounter", startCoords, Settings.BossEncounters.MaxShipsPerArea, Settings.BossEncounters.AreaSize) == true)
            {
                return("Too Many Boss Encounter Grids in Player Area");
            }

            var spawnCoords = Vector3D.Zero;

            if (GetInitialSpawnCoords(startCoords, out spawnCoords) == false)
            {
                return("Could Not Find Valid Coords For Boss Encounter Signal Generation.");
            }

            var spawnGroupList = GetBossEncounters(startCoords, spawnCoords);

            if (Settings.General.UseModIdSelectionForSpawning == true)
            {
                spawnGroupList = SpawnResources.SelectSpawnGroupSublist(SpawnGroupSublists, EligibleSpawnsByModId);
            }

            if (spawnGroupList.Count == 0)
            {
                return("No Eligible Spawn Groups Could Be Found To Spawn Near Player.");
            }

            var spawnGroup = spawnGroupList[SpawnResources.rnd.Next(0, spawnGroupList.Count)];

            var bossEncounter = new BossEncounter();

            bossEncounter.SpawnGroup     = spawnGroup;
            bossEncounter.SpawnGroupName = spawnGroup.SpawnGroupName;
            bossEncounter.Position       = spawnCoords;

            foreach (var player in MES_SessionCore.PlayerList)
            {
                if (player.IsBot == true || player.Character == null || IsPlayerInBossEncounter(player.IdentityId) == true)
                {
                    continue;
                }

                if (Vector3D.Distance(player.GetPosition(), spawnCoords) < Settings.BossEncounters.PlayersWithinDistance)
                {
                    bossEncounter.PlayersInEncounter.Add(player.IdentityId);
                }
                else
                {
                    continue;
                }

                if (spawnGroup.BossCustomAnnounceEnable == true)
                {
                    MyVisualScriptLogicProvider.SendChatMessage(spawnGroup.BossCustomAnnounceMessage, spawnGroup.BossCustomAnnounceAuthor, player.IdentityId, "Red");
                }

                /*
                 *              var syncData = new SyncData();
                 *              syncData.Instruction = "MESBossGPSCreate";
                 *              syncData.GpsName = spawnGroup.BossCustomGPSLabel;
                 *              syncData.GpsCoords = spawnCoords;
                 *              var sendData = MyAPIGateway.Utilities.SerializeToBinary<SyncData>(syncData);
                 *              bool sendStatus = MyAPIGateway.Multiplayer.SendMessageTo(8877, sendData, player.SteamUserId);
                 */
            }

            bossEncounter.CreateGpsForPlayers();
            NPCWatcher.BossEncounters.Add(bossEncounter);

            try {
                if (NPCWatcher.BossEncounters.Count > 0)
                {
                    BossEncounter[] encounterArray = NPCWatcher.BossEncounters.ToArray();
                    var             byteArray      = MyAPIGateway.Utilities.SerializeToBinary <BossEncounter[]>(encounterArray);
                    var             storedBossData = Convert.ToBase64String(byteArray);
                    MyAPIGateway.Utilities.SetVariable <string>("MES-ActiveBossEncounters", storedBossData);
                }
                else
                {
                    MyAPIGateway.Utilities.SetVariable <string>("MES-ActiveBossEncounters", "");
                }
            } catch (Exception e) {
                Logger.AddMsg("Something went wrong while getting Boss Encounter Data from Storage.");
                Logger.AddMsg(e.ToString(), true);
            }



            Logger.SkipNextMessage = false;
            return("Boss Encounter GPS Created with Spawngroup: " + spawnGroup.SpawnGroup.Id.SubtypeName);
        }
        public static bool SpawnBossEncounter(BossEncounter encounter)
        {
            MyPlanet planet    = SpawnResources.GetNearestPlanet(encounter.Position);
            var      inGravity = SpawnResources.IsPositionInGravity(encounter.Position, planet);

            for (int i = 0; i < Settings.BossEncounters.PathCalculationAttempts; i++)
            {
                bool gotMatrix  = false;
                var  tempMatrix = MatrixD.CreateWorld(Vector3D.Zero, Vector3D.Forward, Vector3D.Up);

                if (inGravity == false)
                {
                    var randDir     = Vector3D.Normalize(MyUtils.GetRandomVector3D());
                    var randDist    = (double)SpawnResources.rnd.Next((int)Settings.BossEncounters.MinSpawnDistFromCoords, (int)Settings.BossEncounters.MaxSpawnDistFromCoords);
                    var spawnCoords = randDir * randDist + encounter.Position;

                    if (SpawnResources.IsPositionInGravity(spawnCoords, planet) == true)
                    {
                        randDir    *= -1;
                        spawnCoords = randDir * randDist + encounter.Position;

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

                    var forwardDir = Vector3D.Normalize(encounter.Position - spawnCoords);
                    var upDir      = Vector3D.CalculatePerpendicularVector(forwardDir);
                    tempMatrix = MatrixD.CreateWorld(spawnCoords, forwardDir, upDir);
                    gotMatrix  = true;
                }
                else
                {
                    var planetEntity  = planet as IMyEntity;
                    var upDir         = Vector3D.Normalize(encounter.Position - planetEntity.GetPosition());
                    var randDir       = SpawnResources.GetRandomCompassDirection(encounter.Position, planet);
                    var randDist      = (double)SpawnResources.rnd.Next((int)Settings.BossEncounters.MinSpawnDistFromCoords, (int)Settings.BossEncounters.MaxSpawnDistFromCoords);
                    var roughCoords   = randDir * randDist + encounter.Position;
                    var surfaceCoords = SpawnResources.GetNearestSurfacePoint(roughCoords, planet);
                    var spawnCoords   = upDir * Settings.BossEncounters.MinPlanetAltitude + surfaceCoords;
                    tempMatrix = MatrixD.CreateWorld(spawnCoords, randDir * -1, upDir);
                    gotMatrix  = true;
                }

                if (gotMatrix == false)
                {
                    continue;
                }

                bool badCoords = false;

                foreach (var prefab in encounter.SpawnGroup.SpawnGroup.Prefabs)
                {
                    var offsetCoords = Vector3D.Transform((Vector3D)prefab.Position, tempMatrix);

                    foreach (var entity in SpawnResources.EntityList)
                    {
                        if (Vector3D.Distance(offsetCoords, entity.GetPosition()) < Settings.BossEncounters.MinSignalDistFromOtherEntities)
                        {
                            badCoords = true;
                            break;
                        }
                    }

                    if (badCoords == false)
                    {
                        if (SpawnResources.IsPositionInSafeZone(offsetCoords) == true)
                        {
                            badCoords = true;
                            break;
                        }
                    }

                    if (SpawnResources.IsPositionInGravity(offsetCoords, planet) == true)
                    {
                        if (SpawnResources.GetDistanceFromSurface(offsetCoords, planet) < Settings.BossEncounters.MinPlanetAltitude / 4)
                        {
                            badCoords = true;
                            break;
                        }
                    }
                }

                if (badCoords == true)
                {
                    continue;
                }

                //Spawn the things!
                Logger.SkipNextMessage = false;
                Logger.AddMsg("Boss Encounter SpawnGroup " + encounter.SpawnGroup.SpawnGroup.Id.SubtypeName + " Now Spawning.");

                foreach (var prefab in encounter.SpawnGroup.SpawnGroup.Prefabs)
                {
                    var  options       = SpawnGroupManager.CreateSpawningOptions(encounter.SpawnGroup, prefab);
                    var  spawnPosition = Vector3D.Transform((Vector3D)prefab.Position, tempMatrix);
                    var  speedL        = prefab.Speed * (Vector3)tempMatrix.Forward;
                    var  speedA        = Vector3.Zero;
                    var  gridList      = new List <IMyCubeGrid>();
                    long gridOwner     = 0;

                    //Speed Management
                    if (Settings.SpaceCargoShips.UseMinimumSpeed == true && prefab.Speed < Settings.SpaceCargoShips.MinimumSpeed)
                    {
                        speedL = Settings.SpaceCargoShips.MinimumSpeed * (Vector3)tempMatrix.Forward;
                    }

                    if (Settings.SpaceCargoShips.UseSpeedOverride == true)
                    {
                        speedL = Settings.SpaceCargoShips.SpeedOverride * (Vector3)tempMatrix.Forward;
                    }

                    if (NPCWatcher.NPCFactionTagToFounder.ContainsKey(encounter.SpawnGroup.FactionOwner) == true)
                    {
                        gridOwner = NPCWatcher.NPCFactionTagToFounder[encounter.SpawnGroup.FactionOwner];
                    }
                    else
                    {
                        Logger.AddMsg("Could Not Find Faction Founder For: " + encounter.SpawnGroup.FactionOwner);
                    }

                    //Grid Manipulation
                    GridBuilderManipulation.ProcessPrefabForManipulation(prefab.SubtypeId, encounter.SpawnGroup, "BossEncounter", prefab.Behaviour);

                    try{
                        MyAPIGateway.PrefabManager.SpawnPrefab(gridList, prefab.SubtypeId, spawnPosition, tempMatrix.Forward, tempMatrix.Up, speedL, speedA, prefab.BeaconText, options, gridOwner);
                    }catch (Exception exc) {
                    }

                    var pendingNPC = new ActiveNPC();
                    pendingNPC.SpawnGroup            = encounter.SpawnGroup;
                    pendingNPC.SpawnGroupName        = encounter.SpawnGroup.SpawnGroupName;
                    pendingNPC.InitialFaction        = encounter.SpawnGroup.FactionOwner;
                    pendingNPC.faction               = MyAPIGateway.Session.Factions.TryGetFactionByTag(pendingNPC.InitialFaction);
                    pendingNPC.Name                  = prefab.SubtypeId;
                    pendingNPC.GridName              = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId).CubeGrids[0].DisplayName;
                    pendingNPC.StartCoords           = spawnPosition;
                    pendingNPC.CurrentCoords         = spawnPosition;
                    pendingNPC.EndCoords             = spawnPosition;
                    pendingNPC.SpawnType             = "BossEncounter";
                    pendingNPC.CleanupIgnore         = encounter.SpawnGroup.IgnoreCleanupRules;
                    pendingNPC.ForceStaticGrid       = encounter.SpawnGroup.ForceStaticGrid;
                    pendingNPC.KeenAiName            = prefab.Behaviour;
                    pendingNPC.KeenAiTriggerDistance = prefab.BehaviourActivationDistance;

                    if (encounter.SpawnGroup.RandomizeWeapons == true)
                    {
                        pendingNPC.ReplenishedSystems = false;
                        pendingNPC.ReplacedWeapons    = true;
                    }
                    else if ((MES_SessionCore.NPCWeaponUpgradesModDetected == true || Settings.General.EnableGlobalNPCWeaponRandomizer == true) && encounter.SpawnGroup.IgnoreWeaponRandomizerMod == false)
                    {
                        pendingNPC.ReplenishedSystems = false;
                        pendingNPC.ReplacedWeapons    = true;
                    }
                    else if (encounter.SpawnGroup.ReplenishSystems == true)
                    {
                        pendingNPC.ReplenishedSystems = false;
                    }

                    if (inGravity == true)
                    {
                        pendingNPC.Planet = planet;
                    }

                    NPCWatcher.PendingNPCs.Add(pendingNPC);
                }

                return(true);
            }

            Logger.AddMsg("Could Not Find Safe Area To Spawn Boss Encounter");
            return(false);
        }
        public static List <ImprovedSpawnGroup> GetBossEncounters(Vector3D playerCoords, Vector3D spawnCoords)
        {
            MyPlanet planet             = SpawnResources.GetNearestPlanet(playerCoords);
            bool     spaceSpawn         = false;
            bool     planetSpawn        = false;
            string   specificGroup      = "";
            var      planetRestrictions = new List <string>(Settings.General.PlanetSpawnsDisableList.ToList());

            SpawnGroupSublists.Clear();
            EligibleSpawnsByModId.Clear();

            if (planet != null)
            {
                if (planetRestrictions.Contains(planet.Generator.Id.SubtypeName) == true)
                {
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            bool specificSpawnRequest = false;

            if (SpawnGroupManager.AdminSpawnGroup != "")
            {
                specificGroup = SpawnGroupManager.AdminSpawnGroup;
                SpawnGroupManager.AdminSpawnGroup = "";
                specificSpawnRequest = true;
            }

            if (SpawnResources.IsPositionInGravity(spawnCoords, planet) == true)
            {
                if (planet.GetAirDensity(spawnCoords) > Settings.BossEncounters.MinAirDensity)
                {
                    planetSpawn = true;
                }
            }
            else
            {
                spaceSpawn = true;
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();

            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (specificGroup != "" && spawnGroup.SpawnGroup.Id.SubtypeName != specificGroup)
                {
                    continue;
                }

                if (specificGroup == "" && spawnGroup.AdminSpawnOnly == true)
                {
                    continue;
                }

                bool eligibleGroup = false;

                if (spawnGroup.BossEncounterSpace == true && spaceSpawn == true)
                {
                    eligibleGroup = true;
                }

                if (spawnGroup.BossEncounterAtmo == true && planetSpawn == true)
                {
                    eligibleGroup = true;
                }

                if (spawnGroup.BossEncounterAny == true)
                {
                    eligibleGroup = true;
                }

                if (eligibleGroup == false)
                {
                    continue;
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, playerCoords, planet, specificSpawnRequest) == false)
                {
                    continue;
                }

                if (spawnGroup.Frequency > 0)
                {
                    string modID = spawnGroup.SpawnGroup.Context.ModId;

                    if (string.IsNullOrEmpty(modID) == true)
                    {
                        modID = "KeenSWH";
                    }

                    if (SpawnGroupSublists.ContainsKey(modID) == false)
                    {
                        SpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                    }

                    if (EligibleSpawnsByModId.ContainsKey(modID) == false)
                    {
                        EligibleSpawnsByModId.Add(modID, 1);
                    }
                    else
                    {
                        EligibleSpawnsByModId[modID] += 1;
                    }

                    if (Settings.BossEncounters.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.BossEncounters.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.BossEncounters.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                        SpawnGroupSublists[modID].Add(spawnGroup);
                    }
                }
            }

            return(eligibleGroups);
        }
        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 string AttemptSpawn(Vector3D startCoords, List <string> eligibleNames = null)
        {
            if (Settings.General.UseMaxNpcGrids == true)
            {
                var totalNPCs = NPCWatcher.ActiveNPCs.Count;

                if (totalNPCs >= Settings.General.MaxGlobalNpcGrids)
                {
                    return("Spawning Aborted. Max Global NPCs Limit Reached.");
                }
            }

            if (NPCWatcher.ActiveNpcTypeLimitReachedForArea("RandomEncounter", startCoords, Settings.RandomEncounters.MaxShipsPerArea, Settings.RandomEncounters.AreaSize) == true)
            {
                return("Too Many Random Encounter Grids in Player Area");
            }

            KnownPlayerLocationManager.CleanExpiredLocations();
            var validFactions  = new Dictionary <string, List <string> >();
            var spawnGroupList = GetRandomEncounters(startCoords, eligibleNames, out validFactions);

            if (Settings.General.UseModIdSelectionForSpawning == true)
            {
                spawnGroupList = SpawnResources.SelectSpawnGroupSublist(SpawnGroupSublists, EligibleSpawnsByModId);
            }

            if (spawnGroupList.Count == 0)
            {
                return("No Eligible Spawn Groups Could Be Found To Spawn Near Player.");
            }

            var      spawnGroup  = spawnGroupList[SpawnResources.rnd.Next(0, spawnGroupList.Count)];
            Vector3D spawnCoords = Vector3D.Zero;

            if (GetSpawnCoords(spawnGroup, startCoords, out spawnCoords) == false)
            {
                return("Could Not Find Safe Position To Spawn Encounter");
            }

            //Get Directions
            var spawnMatrix          = MatrixD.CreateWorld(spawnCoords);
            var successfulVoxelSpawn = false;
            var centerVoxelOffset    = false;

            foreach (var voxel in spawnGroup.SpawnGroup.Voxels)
            {
                spawnGroup.RotateFirstCockpitToForward = false;
                var voxelSpawningPosition = Vector3D.Transform((Vector3D)voxel.Offset, spawnMatrix);

                try {
                    var voxelSpawn = MyAPIGateway.Session.VoxelMaps.CreateVoxelMapFromStorageName(voxel.StorageName, voxel.StorageName, voxelSpawningPosition);

                    if (Settings.RandomEncounters.RemoveVoxelsIfGridRemoved == true && spawnGroup.RemoveVoxelsIfGridRemoved == true)
                    {
                        NPCWatcher.SpawnedVoxels.Add(voxelSpawn.EntityId.ToString(), voxelSpawn as IMyEntity);
                    }

                    successfulVoxelSpawn = true;
                } catch (Exception exc) {
                    Logger.AddMsg("Voxel Spawning For " + voxel.StorageName + " Failed");
                }
            }

            if (successfulVoxelSpawn == true)
            {
                var      voxelIdList  = new List <string>(NPCWatcher.SpawnedVoxels.Keys.ToList());
                string[] voxelIdArray = voxelIdList.ToArray();
                MyAPIGateway.Utilities.SetVariable <string[]>("MES-SpawnedVoxels", voxelIdArray);
            }

            long gridOwner      = 0;
            var  randFactionTag = spawnGroup.FactionOwner;

            if (validFactions.ContainsKey(spawnGroup.SpawnGroupName))
            {
                randFactionTag = validFactions[spawnGroup.SpawnGroupName][SpawnResources.rnd.Next(0, validFactions[spawnGroup.SpawnGroupName].Count)];
            }

            if (NPCWatcher.NPCFactionTagToFounder.ContainsKey(randFactionTag) == true)
            {
                gridOwner = NPCWatcher.NPCFactionTagToFounder[randFactionTag];
            }
            else
            {
                Logger.AddMsg("Could Not Find Faction Founder For: " + randFactionTag);
            }

            foreach (var prefab in spawnGroup.SpawnGroup.Prefabs)
            {
                if (spawnGroup.UseKnownPlayerLocations)
                {
                    KnownPlayerLocationManager.IncreaseSpawnCountOfLocations(startCoords, randFactionTag);
                }

                var options       = SpawnGroupManager.CreateSpawningOptions(spawnGroup, prefab);
                var spawnPosition = Vector3D.Transform((Vector3D)prefab.Position * (centerVoxelOffset ? 1 : 1), spawnMatrix);

                Logger.CreateDebugGPS("Prefab Spawn Coords", spawnPosition);
                var speedL   = Vector3.Zero;
                var speedA   = Vector3.Zero;
                var gridList = new List <IMyCubeGrid>();

                //Grid Manipulation
                GridBuilderManipulation.ProcessPrefabForManipulation(prefab.SubtypeId, spawnGroup, "RandomEncounter", prefab.Behaviour);

                try{
                    MyAPIGateway.PrefabManager.SpawnPrefab(gridList, prefab.SubtypeId, spawnPosition, spawnMatrix.Forward, spawnMatrix.Up, speedL, speedA, !string.IsNullOrWhiteSpace(prefab.BeaconText) ? prefab.BeaconText : null, options, gridOwner);
                }catch (Exception exc) {
                }

                var pendingNPC = new ActiveNPC();
                pendingNPC.SpawnGroupName        = spawnGroup.SpawnGroupName;
                pendingNPC.SpawnGroup            = spawnGroup;
                pendingNPC.InitialFaction        = randFactionTag;
                pendingNPC.faction               = MyAPIGateway.Session.Factions.TryGetFactionByTag(pendingNPC.InitialFaction);
                pendingNPC.Name                  = prefab.SubtypeId;
                pendingNPC.GridName              = MyDefinitionManager.Static.GetPrefabDefinition(prefab.SubtypeId).CubeGrids[0].DisplayName;
                pendingNPC.StartCoords           = spawnCoords;
                pendingNPC.CurrentCoords         = spawnCoords;
                pendingNPC.EndCoords             = spawnCoords;
                pendingNPC.SpawnType             = "RandomEncounter";
                pendingNPC.CleanupIgnore         = spawnGroup.IgnoreCleanupRules;
                pendingNPC.ForceStaticGrid       = spawnGroup.ForceStaticGrid;
                pendingNPC.KeenAiName            = prefab.Behaviour;
                pendingNPC.KeenAiTriggerDistance = prefab.BehaviourActivationDistance;

                if (spawnGroup.RandomizeWeapons == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if ((MES_SessionCore.NPCWeaponUpgradesModDetected == true || Settings.General.EnableGlobalNPCWeaponRandomizer == true) && spawnGroup.IgnoreWeaponRandomizerMod == false)
                {
                    pendingNPC.ReplenishedSystems = false;
                    pendingNPC.ReplacedWeapons    = true;
                }
                else if (spawnGroup.ReplenishSystems == true)
                {
                    pendingNPC.ReplenishedSystems = false;
                }

                NPCWatcher.PendingNPCs.Add(pendingNPC);
            }

            Logger.SkipNextMessage = false;
            return("Spawning Group - " + spawnGroup.SpawnGroup.Id.SubtypeName);
        }
        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);
        }
Example #18
0
        public static List <ImprovedSpawnGroup> GetSpawnGroups(List <string> spawnGroups, Vector3D coords, string factionOverride, out Dictionary <string, List <string> > validFactions)
        {
            var planetRestrictions = new List <string>(Settings.General.PlanetSpawnsDisableList.ToList());

            validFactions = new Dictionary <string, List <string> >();
            var environment = new EnvironmentEvaluation(coords);

            if (environment.NearestPlanet != null)
            {
                if (planetRestrictions.Contains(environment.NearestPlanetName) && environment.IsOnPlanet)
                {
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();

            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (!spawnGroups.Contains(spawnGroup.SpawnGroupName))
                {
                    continue;
                }

                if (spawnGroup.RivalAiAnySpawn == false && spawnGroup.RivalAiSpawn == false)
                {
                    if (environment.GravityAtPosition > 0 && spawnGroup.RivalAiSpaceSpawn)
                    {
                        continue;
                    }

                    if (environment.NearestPlanet != null)
                    {
                        if (spawnGroup.RivalAiAtmosphericSpawn == false || environment.NearestPlanet.HasAtmosphere == false || environment.AtmosphereAtPosition < 0.4f)
                        {
                            continue;
                        }
                    }
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, coords, environment, false) == false)
                {
                    continue;
                }

                var validFactionsList = SpawnResources.ValidNpcFactions(spawnGroup, coords, factionOverride);

                if (validFactionsList.Count == 0)
                {
                    continue;
                }

                if (validFactions.ContainsKey(spawnGroup.SpawnGroupName) == false)
                {
                    validFactions.Add(spawnGroup.SpawnGroupName, validFactionsList);
                }

                if (spawnGroup.Frequency > 0)
                {
                    if (Settings.SpaceCargoShips.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.SpaceCargoShips.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.SpaceCargoShips.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                    }
                }
            }

            return(eligibleGroups);
        }
        public static List <ImprovedSpawnGroup> GetPlanetaryCargoShips(Vector3D playerCoords, List <string> eligibleNames, out Dictionary <string, List <string> > validFactions)
        {
            string specificGroup      = "";
            var    planetRestrictions = new List <string>(Settings.General.PlanetSpawnsDisableList.ToList());

            validFactions = new Dictionary <string, List <string> >();
            SpawnGroupSublists.Clear();
            EligibleSpawnsByModId.Clear();
            var environment = new EnvironmentEvaluation(playerCoords);

            if (environment.NearestPlanet != null && environment.IsOnPlanet)
            {
                if (planetRestrictions.Contains(environment.NearestPlanetName) == true)
                {
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            bool specificSpawnRequest = false;

            if (SpawnGroupManager.AdminSpawnGroup != "")
            {
                specificGroup = SpawnGroupManager.AdminSpawnGroup;
                SpawnGroupManager.AdminSpawnGroup = "";
                specificSpawnRequest = true;
            }

            if (!environment.IsOnPlanet)
            {
                return(new List <ImprovedSpawnGroup>());
            }

            if (environment.NearestPlanet == null)
            {
                return(new List <ImprovedSpawnGroup>());
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();

            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (eligibleNames != null)
                {
                    if (!eligibleNames.Contains(spawnGroup.SpawnGroupName))
                    {
                        continue;
                    }
                }
                else
                {
                    if (specificGroup != "" && spawnGroup.SpawnGroup.Id.SubtypeName != specificGroup)
                    {
                        continue;
                    }

                    if (specificGroup == "" && spawnGroup.AdminSpawnOnly == true)
                    {
                        continue;
                    }
                }



                if (spawnGroup.AtmosphericCargoShip == false)
                {
                    continue;
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, playerCoords, environment, specificSpawnRequest) == false)
                {
                    continue;
                }

                var validFactionsList = SpawnResources.ValidNpcFactions(spawnGroup, playerCoords);

                if (validFactionsList.Count == 0)
                {
                    continue;
                }

                if (validFactions.ContainsKey(spawnGroup.SpawnGroupName) == false)
                {
                    validFactions.Add(spawnGroup.SpawnGroupName, validFactionsList);
                }

                if (spawnGroup.Frequency > 0)
                {
                    string modID = spawnGroup.SpawnGroup.Context.ModId;

                    if (string.IsNullOrEmpty(modID) == true)
                    {
                        modID = "KeenSWH";
                    }

                    if (SpawnGroupSublists.ContainsKey(modID) == false)
                    {
                        SpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                    }

                    if (EligibleSpawnsByModId.ContainsKey(modID) == false)
                    {
                        EligibleSpawnsByModId.Add(modID, 1);
                    }
                    else
                    {
                        EligibleSpawnsByModId[modID] += 1;
                    }

                    if (Settings.PlanetaryCargoShips.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.PlanetaryCargoShips.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.PlanetaryCargoShips.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                        SpawnGroupSublists[modID].Add(spawnGroup);
                    }
                }
            }

            return(eligibleGroups);
        }
Example #20
0
        public static List <ImprovedSpawnGroup> GetSpaceCargoShips(Vector3D playerCoords, List <string> eligibleNames, out Dictionary <string, List <string> > validFactions)
        {
            bool   allowLunar         = false;
            string specificGroup      = "";
            var    planetRestrictions = new List <string>(Settings.General.PlanetSpawnsDisableList.ToList());

            validFactions = new Dictionary <string, List <string> >();
            SpawnGroupSublists.Clear();
            EligibleSpawnsByModId.Clear();
            var environment = new EnvironmentEvaluation(playerCoords);

            if (environment.NearestPlanet != null)
            {
                if (planetRestrictions.Contains(environment.NearestPlanetName) && environment.IsOnPlanet)
                {
                    Logger.SpawnGroupDebug(Logger.DebugSpawnGroup, "Restricted Planet, No Spawns Allowed");
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            bool specificSpawnRequest = false;

            if (SpawnGroupManager.AdminSpawnGroup != "")
            {
                specificGroup = SpawnGroupManager.AdminSpawnGroup;
                SpawnGroupManager.AdminSpawnGroup = "";
                specificSpawnRequest = true;
            }

            if (environment.IsOnPlanet)
            {
                if (SpawnResources.LunarSpawnEligible(playerCoords) == true)
                {
                    allowLunar = true;
                }
                else
                {
                    Logger.SpawnGroupDebug("[No Spawn Group]", "On Planet and Cannot Spawn As Lunar, No Spawns Allowed");
                    return(new List <ImprovedSpawnGroup>());
                }
            }

            var eligibleGroups = new List <ImprovedSpawnGroup>();

            //Filter Eligible Groups To List
            foreach (var spawnGroup in SpawnGroupManager.SpawnGroups)
            {
                if (eligibleNames != null)
                {
                    if (!eligibleNames.Contains(spawnGroup.SpawnGroupName))
                    {
                        Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "Was not included in Groups From API Request");
                        continue;
                    }
                }
                else
                {
                    if (specificGroup != "" && spawnGroup.SpawnGroup.Id.SubtypeName != specificGroup)
                    {
                        Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "Doesn't Match Admin Spawn");
                        continue;
                    }

                    if (specificGroup == "" && spawnGroup.AdminSpawnOnly == true)
                    {
                        Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "Only Admin Spawn Allowed");
                        continue;
                    }
                }

                if (spawnGroup.SpaceCargoShip == false)
                {
                    if (allowLunar == true)
                    {
                        if (spawnGroup.LunarCargoShip == false)
                        {
                            Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "Is Not Space Cargo Ship Or Lunar");
                            continue;
                        }
                    }
                    else
                    {
                        Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "Is Not Space Cargo Ship");
                        continue;
                    }
                }

                if (SpawnResources.CheckCommonConditions(spawnGroup, playerCoords, environment, specificSpawnRequest) == false)
                {
                    Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "Common Conditions Failed");
                    continue;
                }

                var validFactionsList = SpawnResources.ValidNpcFactions(spawnGroup, playerCoords);

                if (validFactionsList.Count == 0)
                {
                    Logger.SpawnGroupDebug(spawnGroup.SpawnGroup.Id.SubtypeName, "No Valid Faction");
                    continue;
                }

                if (validFactions.ContainsKey(spawnGroup.SpawnGroupName) == false)
                {
                    validFactions.Add(spawnGroup.SpawnGroupName, validFactionsList);
                }

                if (spawnGroup.Frequency > 0)
                {
                    string modID = spawnGroup.SpawnGroup.Context.ModId;

                    if (string.IsNullOrEmpty(modID) == true)
                    {
                        modID = "KeenSWH";
                    }

                    if (SpawnGroupSublists.ContainsKey(modID) == false)
                    {
                        SpawnGroupSublists.Add(modID, new List <ImprovedSpawnGroup>());
                    }

                    if (EligibleSpawnsByModId.ContainsKey(modID) == false)
                    {
                        EligibleSpawnsByModId.Add(modID, 1);
                    }
                    else
                    {
                        EligibleSpawnsByModId[modID] += 1;
                    }

                    if (Settings.SpaceCargoShips.UseMaxSpawnGroupFrequency == true && spawnGroup.Frequency > Settings.SpaceCargoShips.MaxSpawnGroupFrequency * 10)
                    {
                        spawnGroup.Frequency = (int)Math.Round((double)Settings.SpaceCargoShips.MaxSpawnGroupFrequency * 10);
                    }

                    for (int i = 0; i < spawnGroup.Frequency; i++)
                    {
                        eligibleGroups.Add(spawnGroup);
                        SpawnGroupSublists[modID].Add(spawnGroup);
                    }
                }
            }

            return(eligibleGroups);
        }