public override void Randomize() { if (Hyperdrive.seedString == AstroUtils.KERBIN_SYSTEM_COORDS) { return; } float value = WarpRNG.GetValue(); // Atmosphere has a 75% chance of being generated if we are a planet // Atmosphere has a 10% chance of being generated if we are a moon if (value >= 0.25f && AstroUtils.IsSun(planetData.referenceBody) || value <= 0.1f) { hasAtmosphere = true; } if (hasAtmosphere) { value = WarpRNG.GetValue(); // 10% chance if atmosphere the atmosphere has oxygen if (value >= 0.9f) { hasOxygen = true; } atmosphereHeight = WarpRNG.GenerateFloat(0.5f, 15.0f); atmospherePressureMult = WarpRNG.GenerateFloat(0.1f, 15.0f); ambientColor = new Color(WarpRNG.GetValue() * 0.25f, WarpRNG.GetValue() * 0.25f, WarpRNG.GetValue() * 0.25f); } // Temperature measured by distance from sun if (!IsSun()) { double orbitHeight = planetData.semiMajorAxis / AstroUtils.MAX_SEMI_MAJOR_AXIS; double inverseMult = 1.0 - orbitHeight; tempMultiplier = 5.0f * (float)inverseMult; } }
private void CreateGravity() { float value = WarpRNG.GetValue(); float gravityMult = 0.0f; if (IsMoon()) { // Moons in KSP for the most part have SOIs which are greater than their real-life counterparts // SOI -> Gravity is not a 1:1 ratio; instead a moon's SOI is usually 7-8 times more powerful than its gravity // To skew the gravity data for moons, we use the formula y = (0.0788628 * x^2)-(0.788279 * x)+1.58089 // Note that values below 7.25 generate negative multipliers float randomGravity = WarpRNG.GenerateFloat(7.25f, 9f); gravityMult = (0.0788628f * randomGravity * randomGravity) - (0.788279f * randomGravity) + 1.58089f; } else { gravityMult = WarpRNG.GenerateFloat(0.15f, 2.0f); // There is a chance that a planet is a gas giant like Jool if (value <= 0.05f) { gravityMult *= 20.0f; } } // All gravity values are relative to Kerbin gravity = gravityMult * AstroUtils.KERBIN_GRAVITY; }
private void DeterminePlanetType() { // 5% chance of becoming a gas giant if (WarpRNG.GetValue() <= 0.05f) { isGasGiant = true; } }
private void RandomizeName() { if (randomizedName || Hyperdrive.seedString == AstroUtils.KERBIN_SYSTEM_COORDS) { return; } name = WarpRNG.GenerateName(); randomizedName = true; }
private void RandomizeRotation() { float value = WarpRNG.GenerateFloat(0.0f, 30.0f); rotationPeriod = value * 3600; if (WarpRNG.GetValue() < 0.10f) { rotationPeriod *= 30; } }
private void CreateReferenceBody(bool forcePlanet = false) { referenceBodyData = null; referenceBody = null; float value = WarpRNG.GetValue(); // Planet is in a solar orbit if any of these are true: // 1. RNG rolls a value above at or below 0.25 (25% chance) // 2. There is only one planet in the solar system (should never happen). // 3. We already have a moon orbiting us (no moons orbiting other moons) if (forcePlanet || value <= 0.25f || solarSystem.planetCount <= 1 || childBodies.Count > 0) { referenceBody = solarSystem.sun; referenceBodyData = solarSystem.sunData; } else { // We will be a moon List <int> attemptedInts = new List <int> (); int attempts = 0; // Toss out a candidate if any of the following is true: // 1. The reference body is null or us (causes KSP to crash) // 2. The reference body is a moon // 3. The reference body is smaller than us // Move us to solar orbit after 100 attempts. while ((referenceBody == null || referenceBody == planet || referenceBodyData.referenceBody != solarSystem.sun || referenceBody.Radius < planet.Radius)) { attempts++; // Keep track of already-attempted planets // Might change this to pull a list of all planets from the solar system and poll that int index = WarpRNG.GenerateInt(0, solarSystem.planetCount); if (attemptedInts.Contains(index)) { continue; } attemptedInts.Add(index); // Get the planet dictated by the random int referenceBodyData = solarSystem.GetPlanetByID(index); referenceBody = referenceBodyData.planet; if (attempts >= 100) { referenceBody = solarSystem.sun; referenceBodyData = solarSystem.sunData; break; } // Loop will do a logic check to make sure the chosen planet is valid // Will continue iterating until we have found a valid planet } } // Notify the solar system and the planet itself that our reference body has a new body orbiting it solarSystem.AddChildToPlanet(referenceBodyData, planet); // Update orbital data orbitData.referenceBody = referenceBody; }
private double CreateMoon() { float value = WarpRNG.GetValue(); // Floor resulting value at 1%, to be used later if (value < 0.0001f) { value = 0.0001f; } // Semi-Major Axis can be anywhere within the hill sphere of parent body double hillSphere = AstroUtils.CalculateHillSphere(referenceBodyData); double tempMajorAxis = hillSphere * value * 0.5; double parentAtmosphereHeight = planet.Radius + (sphereOfInfluence * 0.5) + referenceBody.Radius + (referenceBody.atmosphereScaleHeight * 1000.0 * Mathf.Log(1000000.0f)); while (tempMajorAxis < parentAtmosphereHeight) { // Inside planet's atmosphere value += WarpRNG.GenerateFloat(0.001f, 0.1f); tempMajorAxis = hillSphere * value; } foreach (int id in referenceBodyData.childDataIDs) { // This ensures we do not crash into other planets PlanetData childData = solarSystem.GetPlanetByID(id); double moonAxis = childData.semiMajorAxis; double moonMin = moonAxis - childData.planet.Radius - (childData.sphereOfInfluence * 0.5); double moonMax = moonAxis + childData.planet.Radius + (childData.sphereOfInfluence * 0.5); while (tempMajorAxis + planet.Radius >= moonMin && tempMajorAxis <= moonMax) { value += WarpRNG.GenerateFloat(0.001f, 0.1f); tempMajorAxis = hillSphere * value; } } if (tempMajorAxis > referenceBodyData.sphereOfInfluence) { Debugger.LogWarning("Rejecting " + planetData.planetID + " as a candidate due to bad SOI matchup. " + "Previous body: " + referenceBodyData.planetID); orbitData = new OrbitData(); orbitData.randomized = true; referenceBodyData = null; referenceBody = null; // Make us a planet instead CreateReferenceBody(true); CreateGravity(); CreateSphereOfInfluence(); Debugger.LogWarning("New body: " + referenceBodyData.planetID); return(CreatePlanet()); } return(tempMajorAxis); }
private double CreatePlanet() { // Find Semi-Major Axis in KAU (Kerbin Astronomical Units) double kerbinSemiMajorAxisMultiplier = WarpRNG.GenerateNormalRandom(); // Standard deviation of 2 kerbinSemiMajorAxisMultiplier *= 2.0; // Center it so it's roughly between 0.2 and 4 times Kerbin's orbit kerbinSemiMajorAxisMultiplier += 3.2; // Now we bias it a little bit (making it technically not a "true" normal distribution, but alas) // Really should use Math.Abs if (kerbinSemiMajorAxisMultiplier < 0) { kerbinSemiMajorAxisMultiplier *= -1.0; } if (kerbinSemiMajorAxisMultiplier < 0.05) { // Don't want to be too close to the sun kerbinSemiMajorAxisMultiplier += 0.05; } return(kerbinSemiMajorAxisMultiplier * AstroUtils.KERBAL_ASTRONOMICAL_UNIT); }
public void CreateOrbit() { if (orbitData.randomized || WarpDrivers.WarpDrive.seedString == AstroUtils.KERBIN_SYSTEM_COORDS) { // Already randomized data return; } orbitData = new OrbitData(); orbitData.randomized = true; if (IsSun()) { // Special case orbitData.referenceBody = solarSystem.sun; orbitData.semiMajorAxis = 0; return; } #region Reference Body CreateReferenceBody(); #endregion #region Gravity CreateGravity(); #endregion #region Sphere of Influence CreateSphereOfInfluence(); #endregion #region Semi-Major Axis double semiMajorAxis = AstroUtils.MAX_SEMI_MAJOR_AXIS; if (referenceBodyData.IsSun()) { semiMajorAxis = CreatePlanet(); } else { // Planet is moon semiMajorAxis = CreateMoon(); } // Remove eccentricity from the semi-major axis if (orbitData.eccentricity != 1.0f) { semiMajorAxis /= (1.0 - orbitData.eccentricity); } orbitData.semiMajorAxis = semiMajorAxis; #endregion #region Inclination // New way uses normal distribution double normalRNG = WarpRNG.GenerateNormalRandom(); double normalInc = normalRNG * 5.0; orbitData.inclination = normalInc; #endregion #region Eccentricity // Eccentricity must be a value between 0 and 0.99 // We prefer low values normalRNG = WarpRNG.GenerateNormalRandom(); // We want to try to clamp the range somewhere between 0 and 0.1, since that produces results most similar to KSP double eccentRNG = normalRNG * 0.01666667; eccentRNG += 0.05; if (eccentRNG < 0) { eccentRNG *= -1.0; } double eccentricity = eccentRNG; orbitData.eccentricity = eccentricity; #endregion #region Longitude Ascending Node int lan = WarpRNG.GenerateInt(0, 360); orbitData.longitudeAscendingNode = lan; #endregion #region Argument Of Periapsis int argumentOfPeriapsis = WarpRNG.GenerateInt(0, 360); orbitData.argumentOfPeriapsis = argumentOfPeriapsis; #endregion #region Mean Anomaly at Epoch float meanAnomalyAtEpoch = WarpRNG.GenerateFloat(0.0f, Mathf.PI * 2.0f); if (orbitData.semiMajorAxis < 0) { meanAnomalyAtEpoch /= Mathf.PI; meanAnomalyAtEpoch -= 1.0f; meanAnomalyAtEpoch *= 5.0f; } orbitData.meanAnomalyAtEpoch = meanAnomalyAtEpoch; #endregion #region Period double referenceMass = AstroUtils.MassInSolarMasses(referenceBody.Mass); double usMass = AstroUtils.MassInSolarMasses(planet.Mass); orbitData.period = AstroUtils.CalculatePeriodFromSemiMajorAxis(semiMajorAxis, referenceMass, usMass); #endregion }
public void CreateOrbit() { if (orbitData.randomized || Hyperdrive.seedString == AstroUtils.KERBIN_SYSTEM_COORDS) { // Already randomized data return; } orbitData = new OrbitData(); orbitData.randomized = true; if (IsSun()) { // Special case orbitData.referenceBody = solarSystem.sun; orbitData.semiMajorAxis = 0; return; } float value = WarpRNG.GetValue(); #region Reference Body referenceBodyData = null; referenceBody = null; // Planet is in a solar orbit if any of these are true: // 1. RNG rolls a value above at or below 0.25 (25% chance) // 2. There is only one planet in the solar system (should never happen). // 3. We already have a moon orbiting us (no moons orbiting other moons) if (value <= 0.25f || solarSystem.planetCount <= 1 || childBodies.Count > 0) { referenceBody = solarSystem.sun; referenceBodyData = solarSystem.sunData; } else { // We will be a moon List <int> attemptedInts = new List <int> (); int attempts = 0; // Toss out a candidate if any of the following is true: // 1. The reference body is null or us (causes KSP to crash) // 2. The reference body is a moon // 3. The reference body is smaller than us // Move us to solar orbit after 100 attempts. while ((referenceBody == null || referenceBody == planet || referenceBodyData.referenceBody != solarSystem.sun || referenceBody.Radius < planet.Radius)) { attempts++; // Keep track of already-attempted planets // Might change this to pull a list of all planets from the solar system and poll that int index = WarpRNG.GenerateInt(0, solarSystem.planetCount); if (attemptedInts.Contains(index)) { continue; } attemptedInts.Add(index); // Get the planet dictated by the random int referenceBodyData = solarSystem.GetPlanetByID(index); referenceBody = referenceBodyData.planet; if (attempts >= 100) { referenceBody = solarSystem.sun; referenceBodyData = solarSystem.sunData; break; } // Loop will do a logic check to make sure the chosen planet is valid // Will continue iterating until we have found a valid planet } } // Notify the solar system and the planet itself that our reference body has a new body orbiting it solarSystem.AddChildToPlanet(referenceBodyData, planet); // Update orbital data orbitData.referenceBody = referenceBody; #endregion #region Gravity float gravityMult = 0.0f; if (IsMoon()) { // Moons in KSP for the most part have SOIs which are greater than their real-life counterparts // SOI -> Gravity is not a 1:1 ratio; instead a moon's SOI is usually 7-8 times more powerful than its gravity // To skew the gravity data for moons, we use the formula y = (0.0788628 * x^2)-(0.788279 * x)+1.58089 // Note that values below 7.25 generate negative multipliers float randomGravity = WarpRNG.GenerateFloat(7.25f, 9f); gravityMult = (0.0788628f * randomGravity * randomGravity) - (0.788279f * randomGravity) + 1.58089f; } else { gravityMult = WarpRNG.GenerateFloat(0.15f, 2.0f); value = WarpRNG.GetValue(); // There is a chance that a planet is a gas giant like Jool if (value <= 0.05f) { gravityMult *= 20.0f; } } // All gravity values are relative to Kerbin gravity = gravityMult * AstroUtils.KERBIN_GRAVITY; #endregion #region Inclination // Inclination starts directly at orbital plane int inclination = 0; // Get new random value value = WarpRNG.GetValue(); if (value >= 0.975f) { // 2.5% chance of orbit being between 0 and 180 degrees inclination = WarpRNG.GenerateInt(0, 180); } else if (value >= 0.95f) { // 2.5% chance of orbit being between 0 and 60 degrees inclination = WarpRNG.GenerateInt(0, 60); } else if (value >= 0.925f) { // 2.5% chance of orbit being between 0 and 45 degrees inclination = WarpRNG.GenerateInt(0, 45); } else if (value >= 0.9f) { // 2.5% chance or orbit being between 0 and 25 degrees inclination = WarpRNG.GenerateInt(0, 25); } else if (value >= 0.6f) { // 30% chance of orbit being between 0 and 10 degrees inclination = WarpRNG.GenerateInt(0, 10); } else if (value > 0.1f) { // 50% chance of orbit being between 0 and 5 degrees inclination = WarpRNG.GenerateInt(0, 5); } else { // 10% chance of a 0 inclination orbit inclination = 0; } orbitData.inclination = inclination; #endregion #region Eccentricity // Eccentricity must be a value between 0 and 0.99 double eccentricity = WarpRNG.GetValue(); if (eccentricity == 1) { eccentricity = 0.99; } // For extreme values of eccentricity, tone it down a bit so planets don't buzz the sun so much if (eccentricity > 0.95) { eccentricity *= 0.5f; } else { // Below 0.25 eccentricity is ignored if (eccentricity <= 0.25) { // Values above 0.25 are toned down by 10% to keep orbits circlular eccentricity -= (eccentricity * 0.1f); } if (eccentricity <= 0.5) { // Values above 0.8 after being toned down are toned down by 25% eccentricity -= (eccentricity * 0.25f); } if (eccentricity <= 0.8) { // If values are *still* above 0.8, cut in half eccentricity *= 0.5f; } else { // Square resulting eccentricity to make orbits slightly more circular eccentricity *= eccentricity; } if (eccentricity < 0) { // Should never happen eccentricity = 0; } } orbitData.eccentricity = eccentricity; #endregion #region Sphere of Influence sphereOfInfluence = AstroUtils.CalculateSOIFromMass(planetData); if (sphereOfInfluence > AstroUtils.KERBIN_SOI * 30) { // This is where Jool's SOI caps out -- we don't want to go any larger sphereOfInfluence = AstroUtils.KERBIN_SOI * 30; } #endregion #region Semi-Major Axis double semiMajorAxis = AstroUtils.MAX_SEMI_MAJOR_AXIS; if (referenceBodyData.IsSun()) { // Special case: parent is sun // Find Semi-Major Axis in KAU (Kerbin Astronomical Units) // Min is 0.2 (~1.5 solar radii), max is 6.0 (Eeloo orbit) float kerbinSemiMajorAxisMultiplier = WarpRNG.GenerateFloat(0.02f, 6.0f); semiMajorAxis = kerbinSemiMajorAxisMultiplier * AstroUtils.KERBAL_ASTRONOMICAL_UNIT; } else { // Planet is moon value = WarpRNG.GetValue(); // Floor resulting value at 1%, to be used later if (value < 0.0001f) { value = 0.0001f; } // Semi-Major Axis can be anywhere within the hill sphere of parent body double hillSphere = AstroUtils.CalculateHillSphere(referenceBodyData); double tempMajorAxis = hillSphere * value; double parentAtmosphereHeight = planet.Radius + referenceBody.Radius + (referenceBody.atmosphereScaleHeight * 1000.0 * Mathf.Log(1000000.0f)); while (tempMajorAxis < parentAtmosphereHeight) { // Inside planet's atmosphere value += WarpRNG.GenerateFloat(0.001f, 0.1f); tempMajorAxis = semiMajorAxis * value; foreach (int id in referenceBodyData.childDataIDs) { // This ensures we do not crash into other planets PlanetData childData = solarSystem.GetPlanetByID(id); double moonAxis = childData.semiMajorAxis; double moonMin = moonAxis - childData.planet.Radius; double moonMax = moonAxis + childData.planet.Radius; while (tempMajorAxis + planet.Radius >= moonMin && tempMajorAxis <= moonMax) { value += WarpRNG.GenerateFloat(0.001f, 0.1f); tempMajorAxis = semiMajorAxis * value; } } } semiMajorAxis = tempMajorAxis; } // Remove eccentricity from the semi-major axis if (orbitData.eccentricity != 1.0f) { semiMajorAxis /= (1.0 - orbitData.eccentricity); } orbitData.semiMajorAxis = semiMajorAxis; #endregion #region Longitude Ascending Node int lan = WarpRNG.GenerateInt(0, 360); orbitData.longitudeAscendingNode = lan; #endregion #region Argument Of Periapsis int argumentOfPeriapsis = WarpRNG.GenerateInt(0, 360); orbitData.argumentOfPeriapsis = argumentOfPeriapsis; #endregion #region Mean Anomaly at Epoch float meanAnomalyAtEpoch = WarpRNG.GenerateFloat(0.0f, Mathf.PI * 2.0f); if (orbitData.semiMajorAxis < 0) { meanAnomalyAtEpoch /= Mathf.PI; meanAnomalyAtEpoch -= 1.0f; meanAnomalyAtEpoch *= 5.0f; } orbitData.meanAnomalyAtEpoch = meanAnomalyAtEpoch; #endregion #region Period orbitData.period = AstroUtils.CalculatePeriodFromSemiMajorAxis(orbitData.semiMajorAxis); #endregion }