/// <summary>
        /// Generates a random amount of moons for a planet
        /// </summary>
        /// <param name="parentPlanet"></param>
        /// <returns></returns>
        private MySystemPlanetMoon[] GeneratePlanetMoons(MySystemPlanet parentPlanet)
        {
            MyPluginLog.Log("Generating moons for planet " + parentPlanet.DisplayName);
            var settings = MySettingsSession.Static.Settings.GeneratorSettings;

            uint maxMoons = (uint)Math.Ceiling(parentPlanet.Diameter / 120000 * 2);

            maxMoons = (uint)Math.Min(maxMoons, settings.PlanetSettings.MinMaxMoons.Max);

            uint numMoons = (uint)MyRandom.Instance.Next(settings.PlanetSettings.MinMaxMoons.Min, (int)maxMoons + 1);

            numMoons = Math.Min(numMoons, 25);

            if (settings.SystemGenerator == SystemGenerationMethod.UNIQUE)
            {
                numMoons = Math.Min(numMoons, (uint)m_moons.Count);
            }

            MySystemPlanetMoon[] moons = new MySystemPlanetMoon[numMoons];

            for (int i = 0; i < numMoons; i++)
            {
                MyPluginLog.Log("Generating moon " + i);

                double distance = parentPlanet.Diameter * (i + 1) + parentPlanet.Diameter * MyRandom.Instance.GetRandomFloat(1f, 1.5f);
                double diameter;

                var definition = FindPlanetDefinitionForSize(parentPlanet.Diameter * 0.75f, out diameter, true);
                if (definition == null)
                {
                    return(moons);
                }

                Vector3D position;

                int tries2 = 0;

                do
                {
                    double angle = MyRandom.Instance.GetRandomFloat(0, (float)Math.PI * 2f);
                    position = new Vector3D(distance * Math.Sin(angle), distance * Math.Cos(angle), distance * Math.Sin(MyRandom.Instance.GetRandomFloat((float)-Math.PI / 2, (float)Math.PI / 2)));
                    position = Vector3D.Add(position, parentPlanet.CenterPosition);
                } while (IsMoonPositionObstructed(position, diameter, parentPlanet, moons) && ++tries2 < MAX_DEF_FIND_ROUNDS);

                MySystemPlanetMoon moon = new MySystemPlanetMoon();
                moon.CenterPosition = position;
                moon.Diameter       = diameter;
                moon.DisplayName    = GetMoonName(i, definition.Id.SubtypeId.String, parentPlanet.DisplayName);
                moon.SubtypeId      = definition.Id.SubtypeId.String;
                moon.ParentId       = parentPlanet.Id;

                moons[i] = moon;
            }

            MyPluginLog.Log("Generating moons for planet " + parentPlanet.DisplayName + " completed");

            return(moons);
        }
        /// <summary>
        /// Generates a ring for the given planet
        /// </summary>
        /// <param name="parentPlanet">Planet the ring is based on</param>
        /// <returns>The ring for the planet</returns>
        private MySystemAsteroids GenrateRing(MySystemPlanet parentPlanet)
        {
            MyPluginLog.Log("Generating ring for planet " + parentPlanet.DisplayName);

            var provider = MyAsteroidObjectsManager.Static.AsteroidObjectProviders[MyAsteroidRingProvider.TYPE_NAME];
            var ring     = provider.GenerateInstance(0, parentPlanet, 0);

            return(ring);
        }
Пример #3
0
        /// <summary>
        /// Generates a planet for the star system.
        /// </summary>
        /// <param name="planetIndex">Index of the planet in the system</param>
        /// <param name="maxDiameter">The largest diameter the planet should have</param>
        /// <param name="orbitDistance">The distance the planet is away from Vector3D.Zero</param>
        /// <returns>A new MySystemPlanet</returns>
        private MySystemPlanet GeneratePlanet(int planetIndex, double maxDiameter, long orbitDistance)
        {
            MyPluginLog.Log("Generating new planet");

            var settings = MySettingsSession.Static.Settings.GeneratorSettings.PlanetSettings;

            var def = FindPlanetDefinitionForSize(maxDiameter);

            if (def == null)
            {
                MyPluginLog.Log("Could not load a planet definition for this planet.", LogLevel.WARNING);
                return(null);
            }


            var diameter = CalculatePlanetDiameter(def);

            var      angle     = MyRandom.Instance.GetRandomFloat(0, (float)(2 * Math.PI));
            var      elevation = MyRandom.Instance.GetRandomFloat((float)Math.PI / 180 * -5, (float)Math.PI / 180 * 5);
            Vector3D pos       = new Vector3D(orbitDistance * Math.Sin(angle), orbitDistance * Math.Cos(angle), orbitDistance * Math.Sin(elevation));

            string name = GetPlanetName(planetIndex, def.Id.SubtypeId.String);

            MySystemPlanet planet = new MySystemPlanet()
            {
                CenterPosition = pos,
                Diameter       = diameter,
                DisplayName    = name,
                Generated      = false,
                SubtypeId      = def.Id.SubtypeId.String,
            };

            if (MyRandom.Instance.NextFloat() < settings.BaseRingProbability * def.SurfaceGravity)
            {
                planet.ChildObjects.Add(GenrateRing(planet));
            }

            if (MyRandom.Instance.NextFloat() < settings.BaseMoonProbability * def.SurfaceGravity)
            {
                foreach (var moon in GeneratePlanetMoons(planet))
                {
                    if (moon == null)
                    {
                        continue;
                    }
                    planet.ChildObjects.Add(moon);
                }
            }
            MyPluginLog.Log("Planet generated");
            return(planet);
        }
        public override void GenerateObjects()
        {
            var system = MyStarSystemGenerator.Static.StarSystem;

            if (system == null || system.CenterObject == null)
            {
                return;
            }

            var objs = system.GetAllObjects();

            foreach (var obj in objs)
            {
                if (obj == null)
                {
                    continue;
                }
                if (obj.Type != MySystemObjectType.PLANET && obj.Type != MySystemObjectType.MOON)
                {
                    continue;
                }

                MySystemPlanet planet = obj as MySystemPlanet;

                if (planet.Generated)
                {
                    continue;
                }

                var definition = MyDefinitionManager.Static.GetDefinition <MyPlanetGeneratorDefinition>(MyStringHash.GetOrCompute(planet.SubtypeId));

                if (definition == null)
                {
                    continue;
                }

                long   id   = MyRandom.Instance.NextLong();
                string name = GetPlanetStorageName(planet);

                MyPlanet generatedPlanet = MyWorldGenerator.AddPlanet(name, planet.DisplayName, planet.SubtypeId, planet.CenterPosition - GetPlanetOffset(definition, planet.Diameter), m_seed, (float)planet.Diameter, true, id, false, true);
                if (generatedPlanet != null)
                {
                    generatedPlanet.DisplayNameText = planet.DisplayName;
                    generatedPlanet.AsteroidName    = planet.DisplayName;

                    planet.Generated = true;
                    planet.EntityId  = generatedPlanet.EntityId;
                }
            }
        }
        /// <summary>
        /// Spawns a planet in the system
        /// </summary>
        /// <param name="planet">Planet to spawn</param>
        /// <param name="position">Position to spawn at</param>
        private void SpawnPlanet(MySystemObject planet, Vector3D position)
        {
            if (planet.Type == MySystemObjectType.PLANET)
            {
                MySystemPlanet p = planet as MySystemPlanet;
                p.CenterPosition = position;

                MyStarSystemGenerator.Static.AddObjectToSystem(p, callback : delegate(bool success)
                {
                    if (!success)
                    {
                        MyPluginGuiHelper.DisplayError("Planet could not be spawned, because an object with the same id already exists. This error should not occour, so please try again.", "Error");
                    }
                });
            }
        }
        /// <summary>
        /// Action to spawn a planet
        /// </summary>
        /// <param name="coordSpawn">If the planet should be spawned at coordinates instead of direct placement</param>
        private void OnSpawnPlanet(bool coordSpawn = false)
        {
            StringBuilder name = new StringBuilder();

            m_nameBox.GetText(name);
            if (name.ToString().Trim().Length <= 3)
            {
                MyPluginGuiHelper.DisplayError("The name must be at least 4 letters long", "Error");
                return;
            }

            if (coordSpawn)
            {
                MyGuiScreenDialogCoordinate coordinateInput = new MyGuiScreenDialogCoordinate("Planet coordinate");

                coordinateInput.OnConfirmed += delegate(Vector3D coord)
                {
                    MySystemPlanet p = new MySystemPlanet()
                    {
                        CenterPosition = coord,
                        SubtypeId      = ((MyPlanetGeneratorDefinition)m_planetDefList.GetLastSelected().UserData).Id.SubtypeId.ToString(),
                        Generated      = false,
                        DisplayName    = name.ToString().Trim(),
                        Diameter       = m_planetSizeSlider.Value
                    };

                    SpawnPlanet(p, coord);
                };

                MyGuiSandbox.AddScreen(coordinateInput);
                return;
            }

            float          size   = m_planetSizeSlider.Value;
            MySystemPlanet planet = new MySystemPlanet()
            {
                CenterPosition = Vector3D.Zero,
                SubtypeId      = ((MyPlanetGeneratorDefinition)m_planetDefList.GetLastSelected().UserData).Id.SubtypeId.ToString(),
                Generated      = false,
                DisplayName    = name.ToString().Trim(),
                Diameter       = size
            };

            MyPluginItemsClipboard.Static.Activate(planet, SpawnPlanet, size);

            CloseScreenNow();
        }
        public override void UpdateBeforeSimulation()
        {
            base.UpdateBeforeSimulation();

            if (!MySettingsSession.Static.IsEnabled())
            {
                return;
            }

            CheckIntegrityOfSystem();

            List <MyEntityList.MyEntityListInfoItem> planets = MyEntityList.GetEntityList(MyEntityList.MyEntityTypeEnum.Planets);

            foreach (var p in planets)
            {
                var  e      = MyEntities.GetEntityById(p.EntityId) as MyPlanet;
                bool exists = false;

                foreach (var obj in StarSystem.GetAllObjects())
                {
                    if (obj is MySystemPlanet)
                    {
                        if ((obj as MySystemPlanet).EntityId == p.EntityId)
                        {
                            exists = true;
                        }
                    }
                }
                if (!exists)
                {
                    MySystemPlanet vanillaPlanet = new MySystemPlanet();
                    vanillaPlanet.CenterPosition = e.PositionComp.GetPosition();
                    vanillaPlanet.Diameter       = e.MaximumRadius * 2;
                    vanillaPlanet.DisplayName    = GetPlanetNameForPlanetStorageName(e.StorageName);
                    vanillaPlanet.Generated      = true;
                    vanillaPlanet.EntityId       = p.EntityId;

                    StarSystem.CenterObject.ChildObjects.Add(vanillaPlanet);
                }
            }
            AddAllPersistentGps();
        }
        /// <summary>
        /// Checks, whether a given position, where a moon with given diameter is located, is obstructed by moons or a planet or its ring.
        /// Helper method for GeneratePlanetMoons
        /// </summary>
        /// <param name="position">Position to check</param>
        /// <param name="moonDiameter">Diameter of moon</param>
        /// <param name="parentPlanet">Planet to check ring</param>
        /// <param name="moons">Moons to check</param>
        /// <returns></returns>
        private bool IsMoonPositionObstructed(Vector3D position, double moonDiameter, MySystemPlanet parentPlanet, MySystemPlanetMoon[] moons)
        {
            if (Vector3D.Distance(position, parentPlanet.CenterPosition) < moonDiameter + parentPlanet.Diameter)
            {
                return(true);
            }

            foreach (var child in parentPlanet.ChildObjects)
            {
                if (child.Type == MySystemObjectType.ASTEROIDS)
                {
                    var asteroid = child as MySystemAsteroids;
                    IMyAsteroidObjectShape shape = MyAsteroidObjectsManager.Static.AsteroidObjectProviders[asteroid.AsteroidTypeName].GetAsteroidObjectShape(asteroid);
                    if (Vector3D.Distance(shape.GetClosestPoint(position), position) <= moonDiameter)
                    {
                        return(true);
                    }
                }
                else
                {
                    if (child.GetType() == typeof(MySystemPlanet))
                    {
                        if (Vector3D.Distance(child.CenterPosition, position) < moonDiameter + (child as MySystemPlanet).Diameter)
                        {
                            return(true);
                        }
                    }
                }
            }

            foreach (var moon in moons)
            {
                if (moon == null)
                {
                    continue;
                }
                if (Vector3D.Distance(moon.CenterPosition, position) < moonDiameter + moon.Diameter)
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Generates a completely new system based on the
        /// world settings.
        /// </summary>
        /// <returns></returns>
        private MyObjectBuilder_SystemData GenerateNewStarSystem()
        {
            MyPluginLog.Log("Generating a new Solar system ...");

            int seed = MySession.Static.Settings.ProceduralSeed + Guid.NewGuid().GetHashCode();
            MyObjectBuilder_SystemData system = new MyObjectBuilder_SystemData();

            var settings = MySettingsSession.Static.Settings.GeneratorSettings;

            var orbitDistances       = settings.MinMaxOrbitDistance;
            var planetsAmount        = settings.MinMaxPlanets;
            var asteroidObjectAmount = settings.MinMaxAsteroidObjects;
            var worldSize            = settings.WorldSize;

            var asteroidProviders = MyAsteroidObjectsManager.Static.AsteroidObjectProviders;

            using (MyRandom.Instance.PushSeed(seed))
            {
                long planetCount          = MyRandom.Instance.Next(planetsAmount.Min, planetsAmount.Max + 1);
                long asteroidObjectCount  = MyRandom.Instance.Next(asteroidObjectAmount.Min, asteroidObjectAmount.Max + 1);
                long systemSize           = planetCount + asteroidObjectCount;
                int  currentPlanetIndex   = 0;
                int  currentAsteroidIndex = 0;
                long currentOrbitDistance = 0;

                double planetProb = planetCount / (double)(planetCount + asteroidObjectCount);

                if (m_suns.Count > 0)
                {
                    MyPlanetGeneratorDefinition sunDef = m_suns[MyRandom.Instance.Next(0, m_suns.Count)];
                    MySystemPlanet sun = new MySystemPlanet();
                    sun.CenterPosition = Vector3D.Zero;
                    sun.SubtypeId      = sunDef.Id.SubtypeId.String;
                    sun.DisplayName    = sunDef.Id.SubtypeId.String;
                    sun.Diameter       = CalculatePlanetDiameter(sunDef) * 2;
                    sun.ChildObjects   = new HashSet <MySystemObject>();
                    sun.Generated      = false;
                    sun.Type           = MySystemObjectType.PLANET;

                    system.CenterObject   = sun;
                    currentOrbitDistance += (long)sun.Diameter * 2 + (long)sunDef.AtmosphereHeight;
                }
                else
                {
                    system.CenterObject             = new MySystemObject();
                    system.CenterObject.Type        = MySystemObjectType.EMPTY;
                    system.CenterObject.DisplayName = "System center";
                }

                while (planetCount > 0 || asteroidObjectCount > 0)
                {
                    currentOrbitDistance += MyRandom.Instance.Next(orbitDistances.Min, orbitDistances.Max);

                    //Maybe rework to override orbit distance, so all objects fit
                    if (worldSize >= 0 && currentOrbitDistance >= worldSize)
                    {
                        return(system);
                    }

                    MySystemObject obj = null;

                    if (asteroidObjectCount <= 0 || (MyRandom.Instance.NextDouble() <= planetProb && planetCount > 0)) // Generate planet
                    {
                        obj = GeneratePlanet(currentPlanetIndex++, Math.Sin((system.Count() - 1) * Math.PI / systemSize), currentOrbitDistance);
                        planetCount--;
                    }
                    else if (asteroidObjectCount > 0) // Generate asteroid object
                    {
                        int providerIndex = MyRandom.Instance.Next(0, asteroidProviders.Keys.Count);
                        MyAbstractAsteroidObjectProvider provider = null;
                        foreach (var prov in asteroidProviders)
                        {
                            if (!prov.Value.IsSystemGeneratable())
                            {
                                continue;
                            }

                            if (providerIndex-- == 0)
                            {
                                provider = prov.Value;
                            }
                        }

                        if (provider == null)
                        {
                            continue;
                        }

                        obj = provider.GenerateInstance(currentAsteroidIndex++, null, currentOrbitDistance);

                        if (obj == null)
                        {
                            continue;
                        }

                        (obj as MySystemAsteroids).AsteroidTypeName = provider.GetTypeName();

                        asteroidObjectCount--;
                    }
                    if (obj == null)
                    {
                        continue;
                    }

                    obj.ParentId = system.CenterObject.Id;
                    system.CenterObject.ChildObjects.Add(obj);
                }
            }

            MyPluginLog.Log("Solar system generated ...");

            return(system);
        }
 /// <summary>
 /// Builds all elements to edit planets
 /// </summary>
 /// <param name="table">Table to add the elements to</param>
 /// <param name="planet">Planet item to build the edit menu for</param>
 private void BuildPlanetEditingMenu(MyGuiControlParentTableLayout table, MySystemPlanet planet)
 {
     table.AddTableRow(new MyGuiControlLabel(null, null, "This object cant be edited.", font: "Red"));
 }
 /// <summary>
 /// Returns the storage name for the given planet
 /// </summary>
 /// <param name="planet">Planet to get a storage name for</param>
 /// <returns>The storage name of the planet</returns>
 private string GetPlanetStorageName(MySystemPlanet planet)
 {
     return((planet.DisplayName + "-" + planet.SubtypeId).Replace(" ", "_"));
 }