| Scripts/orbits.js | "use strict";
this.name = "PlanetOrbits";
this.author = "Stranger";
this.description = "Adds planets on concentric orbits around the sun."
this.version = "1.8";
this.copyright = "This work is hereby placed in the public domain.";
/*
This script tightly based on Ebi, Kaks Orbits 1.2.1 script.
Original planet seeding procedure is overrided.
Moon filter radius increased to 2500 km.
Local year duration is a function of sun spectral class (reference to Sun Gear AstroLibrary included).
Periods of outer planets readjusted (0.5x multiplier added).
Original code reformatted to ease readings (yet too complicated to me!).
*/
function pow(x, y)
    {
    return Math.exp(y * Math.log(x));
    }
// Maximum number of planets to be added (See planetinfo.plist as well).
this.MaxPlanets = 8;
// Outer planet orbits scale factor
this.$scaleOrbits = 0.5;    // No works yet. Edit number in line 360 directly to have effect.
                            // Default scale value was 1.0. 
// Days per year of the Main planet
this.Yr = 360;
// Get weights by linearily interpolating the planet radii as defined
// by [X0,Y0] and [X1,Y1]. Those weights are used as multiplier when
// calculating orbital periods. If X0 or X1 are 0 or undefined "orbits"
// will select the minimum or maximum from the planets in the
// system.planets list.
this.X0 = 2500 * 10;		// planetinfo.plist minimum in game units
this.X1 = 18000 * 10;		// planetinfo.plist maximum in game units
this.Y0 = pow(2, 3.0 / 4.0);	// Compensate Keplers law and take square root
this.Y1 = pow(3.5, 3.0 / 4.0);  // Thus, scale radius by values in [2,3.5]
// System spread factor
this.SpreadFactor = 3.0;
// Add a random offset in the range [0, t*RandomOffsetFactor] to the
// orbital period t of a planet.
this.RandomOffsetFactor = 0.1;
// Log to logfile (1) and/or console (2)
this.Verbose = 0; //1|4;
// Oh man, it's too tricky to get the OXP initialization order right
// for Oolite. It may be random, therefore I offer the farsun
// functionality here as well. Shifts the sun and increases (or
// decreases if less than 1) its distance to the main planet by this
// factor. Thus, the value 1 will not show any effect.
this.FarsunMultiplier = 1; // 6;
this.Log = function(dest, msg)
    {
    if (dest & 1)
	log (msg);
    if (dest & 2)
	player.commsMessage(msg);
    }
this.startUp = this.reset = function()
    {
    this.systemDone = false;
    this.Log(this.Verbose & 1, "Initialising OXP " + this.name);
    }
this.shipWillLaunchFromStation  =  function()
    {
    if (!this.systemDone)
        {
        this.shipWillExitWitchspace();
        delete this.shipWillLaunchFromStation;
        }
    }
this.shipLaunchedFromStation = function()
    {
    if (!this.systemDone)
	this.shipExitedWitchspace();
    }
this.shipWillExitWitchspace = function()
    {
    if (system.isInterstellarSpace) return;
    var w = worldScripts.AstroLibrary;
    var sunRadius = system.sun.radius;
    var sunMass = w.$astroLib_sunMass(sunRadius);
    var mainYr = w.$astroLib_solPeriod(sunMass);
    this.Yr = mainYr;
    this.createOrbits();
    }
this.shipExitedWitchspace = function()
    {
    if (system.isInterstellarSpace) return;
    this.systemDone = true;
    if ((this.Verbose & (2|4)) == 0 || this.innerPlanets == 0)
	return;
    var msg =
	system.name + ": " +
	this.innerPlanets + "+" +
	this.outerPlanets + " planets";
    if (this.info != undefined)
	msg = msg + "[" + this.info + "]";
    this.Log(2, msg);
    }
this.isMoon = function(p)
    {
    // 10 * Radius from planetinfo.plist
    return !p.isMainPlanet && p.radius < 2500 * 10;
    }
this.mkPlanetIndex = function mkPlanetIndex()
    {
    function aPlanet(entity)
        {
        return entity.isPlanet
        }
  
    return system.filteredEntities(this, aPlanet, system.sun);
    }
this.planetsMinMax = function(x)
    {
    var needX0 = this.X0 == undefined || this.X0 == 0;
    var needX1 = this.X1 == undefined || this.X1 == 0;
    var np = system.planets.length;
    var x0 = +Infinity, x1 = 0;
    if (needX0 || needX1)
        {
        for (var i = 0; i < system.planets.length; ++i)
            {
            if (this.isMoon(system.planets[i]))
                {
                np--;
                continue;
                }
            if (system.planets[i].radius > x1)
            x1 = system.planets[i].radius;
            if (system.planets[i].radius < x0)
            x0 = system.planets[i].radius;
            }
        }
    x[0] = needX0 ? x0 : this.X0;
    x[1] = needX1 ? x1 : this.X1;
    return np;
    }
this.addPlanets = function(id)
    {
    // Add planets in system dependent order. Id is used here in two
    // ways:
    // - Its lower bits determine the planets in planetinfo.plist
    // - It represents a permutation and hence the order how the selected
    //   planets are added (see wikipedia for factoradic) and Entity-IDs
    //   are assigned.
    var selectPlanet1 = system.scrambledPseudoRandomNumber(163);
    var selectPlanet2 = system.scrambledPseudoRandomNumber(171);
    var selectPlanet3 = system.scrambledPseudoRandomNumber(179);
    var selectPlanet4 = system.scrambledPseudoRandomNumber(187);
    var selectPlanet5 = system.scrambledPseudoRandomNumber(195);
    var selectPlanet6 = system.scrambledPseudoRandomNumber(203);
    var selectPlanet7 = system.scrambledPseudoRandomNumber(211);
    var selectPlanet8 = system.scrambledPseudoRandomNumber(219);
    var selectPlanetData = [
    selectPlanet1,
    selectPlanet2,
    selectPlanet3,
    selectPlanet4,
    selectPlanet5,
    selectPlanet6,
    selectPlanet7,
    selectPlanet8
    ];
    var v = new Array(this.MaxPlanets), w = new Array(this.MaxPlanets);
    // Avoid huge factorials by grouping up to 12 planets.
    var mask = id;
    for (var i = 0; i < this.MaxPlanets && mask != 0 && id != 0; )
        {
        var m = 0, f = 1;
        // Type conversion prohibits use of the shift operator. Kind
        // of weird to apply "&" on a floating point number!
        for (; m < 12 && i < this.MaxPlanets; ++i, mask = Math.floor(mask / 2))
            if ((mask & 1) != 0)
            v[m] = i, w[m] = m, f *= ++m;
        var fn = id % f;	// fn = sum(j in [0..m-1]:j!*c[j]), c[j] <= j
        id = Math.floor(id / f);
        for (; m > 0; --m)
            {
            f /= m;
            var c = Math.floor(fn / f);
            fn -= f * c;
            this.Log(this.Verbose,
                "" + m + ":selecting oplanet" +
                (v[w[c]] + 1) + "," + w[c] + "," +
                c + "," + f + "," + fn);
            var addPlanetTagIn = v[w[c]];
            var addPlanetTagOut = 10*(addPlanetTagIn + 1) + Math.floor(selectPlanetData[addPlanetTagIn]*10);
            system.addPlanet("oplanet" + addPlanetTagOut);
//          system.addPlanet("oplanet" + (v[w[c]] + 1));
            for (; c + 1 < m; ++c)
            w[c] = w[c + 1];
            }
        }
    }
this.createOrbits = function()
    {
    this.outerPlanets = 0;
    this.innerPlanets = 0;
    var s = system.sun;
    // Is there system.witchpoint?
    var w = system.shipsWithPrimaryRole("buoy-witchpoint")[0];
    var pm = system.mainPlanet;
    if (!s || !w || !pm)
	return;
    s.position=(pm.position.add(
	s.position.subtract(pm.position).multiply(this.FarsunMultiplier)));
    function PlanetVecs(s, w, p)
        {
        // "this" for sizzies:(
        this.s = s;
        this.sp = p.subtract(s);
        this.dist = this.sp.magnitude();
        // Rotation axis, perpendicular to the plane of triangle [s,p,w]
        this.rx = this.sp.cross(w.subtract(s)).direction();
        this.q = new Quaternion (1,0,0,0);
        this.rotateQ = function(q, axis, angle)
            {
            // Ahruman's replacement for buggy Quaternion.rotate()
            angle *= 0.5;
            axis = axis.multiply(Math.sin(angle));
            return q.multiply([Math.cos(angle), axis.x, axis.y, axis.z]);
            }
        this.position = function(a, d)
            {
            // Move sun to origin, rotate planet, and translate back again
            return this.s.add(this.sp.rotateBy(
            this.rotateQ(this.q, this.rx, a)).multiply(d));
            }
        }
    var pv = new PlanetVecs(s.position, w.position, pm.position);
    function SystemId(name)
        {
        this.prime = 29;
        this.name = name;
        this.code = 0;
        this.charToInt = function(c)
            {
            var l = "abcdefghijklmnopqrstuvwxyz";
            var i = l.indexOf(c);
            if (i >= 0)
            return i;
            var u = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            i = u.indexOf(c);
            return i >= 0 ? i : 0; 
            }
        this.nextPrime = function()
            {
            var p = this.prime;
            if ((p & 1) == 0)
            ++p;
            for (;;)
                {
                p += 2;
                for (var i = 3; ; i += 2)
                    {
                    if (i * i > p)
                    return this.prime = p;
                    if (p % i == 0)
                    break;
                    }
                }
            }
        this.calcCode = function()
            {
            // Use letters of n as digits of number with base prime.
            var l = this.name.length;
            var x = 0;
            var pp = 1;
            for (var i = 0; i < l; ++i)
                {
                x += this.charToInt (this.name.charAt(i)) * pp;
                pp *= this.prime;
                }
            return this.code = x;
            }
        }
    // Derive numbers from system name
    var id = new SystemId(system.name);
    id.calcCode();
    this.Log (this.Verbose, system.name + ":id is " + id.code);
    this.addPlanets(id.code);
    this.innerPlanets = 1;
    var x = [+Infinity, 0];
    var np = this.planetsMinMax(x);
    if (np <= 1)
    return;
    function Map(x0, y0, x1, y1)
        {
        var m, X0 = x0, Y0 = y0;
        if (x0 == x1 || y0 == y1)
            {
            m = (y0 + y1) / 2;
            this.interpolate = function(x) { return m; }
            }
        else
            {
            m = (y1 - y0) / (x1 - x0);
            this.interpolate = function(x) { return Y0 + m * (x - X0); }
            }
        }
    var map = new Map(x[0], this.Y0, x[1], this.Y1);
    function PlanetWeights(p, s)
        {
        this.c = 0, this.p = p, this.s = s;
        this.product = function() { return this.s * this.c * this.p; }
        this.next = function() { this.p = this.c; }
        }
    var ow = new PlanetWeights(
	map.interpolate(pm.radius),    
	pow(this.SpreadFactor, 1.0 / (np - 1)));
    var iw = new PlanetWeights(ow.p, ow.s);
    function InnerOrbitalPeriod(orbits, s)
        {
        this.t = orbits.Yr;
        var r = orbits.RandomOffsetFactor;
        r /= 1 + r;
        var f = orbits.Yr / (orbits.Y1 * orbits.Y1 * s);
        this.calc = function(id, iw)
            {
            var mod = this.t * r;
            return this.t - id.code % mod - f * iw.product();
            }
        }
    var iop = new InnerOrbitalPeriod(this, iw.s);
    function OuterOrbitalPeriod(orbits)
        {
        this.t = orbits.Yr;
        var r = orbits.RandomOffsetFactor;
        var f = orbits.Yr;
        this.calc = function(id, ow)
            {
            var t = this.t + 0.5 * f * ow.product();
            var mod = t * r;
            if (mod != 0)
            t += id.code % mod;
            return t;
            }
        }
    var oop = new OuterOrbitalPeriod(this);
    // Grrr, need an index sorted by Entity.ID as planets[] order may
    // change on different system entries.
    var planetsarray = this.mkPlanetIndex();
    var today = clock.days + id.code;
    var a = 2.0 * Math.PI * (today % this.Yr) / this.Yr;
    var info = (180 * a / Math.PI).toFixed();
    this.Log(this.Verbose, system.name + ":" +
	     today + "," +
	     ow.p.toFixed(4) + "," +
	     ow.s.toFixed(4) + "," +
	     (pm.radius  / 10).toFixed()+ "," +
	     (180 * a / Math.PI).toFixed());
    // Pretend to rotate the main planet.
    var pmOffset = pm.position.subtract(pv.position(a, 1));
    for (var i = 0; i < planetsarray.length; ++i)
        {
        var pi = planetsarray[i];
        if (pi.isMainPlanet || this.isMoon(pi))
            continue;
        iw.c = ow.c = map.interpolate(pi.radius);
        id.nextPrime();
        id.calcCode();
        // Current planet's days per year. Try to make it an inner
        // planet. If that fails it will be an outer planet.
        var d;
        var t = iop.calc(id, iw);
        var inner = t > this.Yr / 3;
        if (inner)
            {
            // Orbit Radius in planet-sun units (3. Kepler's law)
            d = pow(t / this.Yr, 2.0 / 3.0);
            inner =
            // idea: 0.3 * pv.dist / pm.r <= d * pv.dist / pi.r 
            pm.radius * d >= pi.radius * 0.3  &&
            d * pv.dist > 15 * s.radius;
            }
        if (!inner)
            {
            t = oop.calc(id, ow);
            d = pow(t / this.Yr, 2.0 / 3.0);
            }
        // Current angle in radians
        var a = 2.0 * Math.PI * (today % t) / t;
        var aa = (180.0 * a / Math.PI).toFixed();
        this.Log(this.Verbose,
            system.name + "[" + i + "]" + ":" +
            id.prime + "," +
            id.code + "," +
            (pi.radius / 10).toFixed() + "," +
            ow.c.toFixed(4) + "," +
            t.toFixed() + "," +
            d.toFixed(4) + "," +
            aa);
        pi.position=pv.position(a, d).add(pmOffset);
        if (inner)
            {
            iw.next(), iop.t = t, ++this.innerPlanets;
            info = aa + "," + info;
            }
        else
            {
            ow.next(), oop.t = t, ++this.outerPlanets;
            info = info + "," + aa;
            }
        }
    s.position=(s.position.add(pmOffset));
    this.info = info;
    }
 | 
                
                    | Scripts/planet_engine.js | "use strict";
this.name           = "PlanetEngine"; 
this.author         = "Stranger"; 
this.copyright      = "This script is hereby placed in the public domain."; 
this.version        = "1.7"; 
this.description    = "Gives info and define texture to additional planets genereted by Orbits";
this.$planetRadius = 6400;
this.$planetDensity = 5.525;
this.$planetEscapeVelocity = 11180;
this.$surfaceGravity = 1;
this.$atmosphereMass = 1;
this.$planetFlag = -1;
this.$orbitRadiusList = new Array();
this.$orbitPeriodList = new Array();
this.$insolationList = new Array();
this.$planetDensityList = new Array();
this.$planetMassList = new Array();
this.$escapeVelocityList = new Array();
this.$planetGravityList = new Array();
this.$atmosphereMassList = new Array();
this.$atmospherePressureList = new Array();
this.$atmosphereTemperatureList = new Array();
this.shipWillExitWitchspace = function()
    {
    if (system.isInterstellarSpace) return;
    this.$scriptDelay = new Timer(this, this.$scanSystem, 0.25);    //delay to set planet orbits!
    }
this.shipWillLaunchFromStation = function()
    {
    this.shipWillExitWitchspace();
    delete this.shipWillLaunchFromStation;
    }
this.shipApproachingPlanetSurface = function(planet) 
    {
    this.$planetFlag = planet.radius;
    }
this.shipDockedWithStation = function(station)
    {
    if(station.hasRole("planetFall_surface"))
        {
        this.$initInterface(station);    
        }
    }
this.$initInterface = function(station)
    {
	station.setInterface(this.name,{
		title:"Planet Data Sheet",
		category:"Ambience",
		summary:"Provide extended set of planetary data",
		callback:this.$setupMissionPage.bind(this)
        });
    }
this.$setupMissionPage = function()
    {
    if(this.$planetFlag > 25000)
        {
        this.$planetInfo();
        }
    else
        {
        this.$moonInfo();
        }
    }
this.$scanSystem = function()
    {
    var w = worldScripts.AstroLibrary;
	var info = system.info;
    if (system.info.sun_radius)
		{
        var sunRadius = system.sun.radius;
		}
    var sunMass = w.$astroLib_sunMass(sunRadius);
    var sunTemperature = w.$astroLib_sunTemperature(sunRadius);
    var sunLuminosity = w.$astroLib_sunLuminosity(sunTemperature,sunRadius);
    var localYear = w.$astroLib_solPeriod(sunMass);
    var mainOrbitVector = new Vector3D(system.sun.position.subtract(system.mainPlanet.position));
    var ouScale = mainOrbitVector.magnitude();
    var planetRadius = this.$planetRadius;
    var planetDensity = this.$planetDensity;
    var escapeVelocity = this.$planetEscapeVelocity;
    var surfaceGravity = this.$surfaceGravity;
    var atmosphereMass = this.$atmosphereMass;
    var mainInsolation = sunLuminosity * Math.pow((50000000/ouScale),2);
    var insolation = mainInsolation;
    var meanTemperature = w.$astroLib_equilibriumTemperature(insolation);
    var equilibriumTemperature = meanTemperature;
    this.$orbitRadiusList = w.$astroLib_orbitRadius();
    for (let i=0; i<system.planets.length; i++)
        {
        planetRadius = system.planets[i].radius/10;        
        this.$orbitPeriodList[i] = localYear * Math.pow(this.$orbitRadiusList[i],1.5);
        this.$insolationList[i] = mainInsolation * Math.pow(this.$orbitRadiusList[i],-2);
        insolation = this.$insolationList[i];
        meanTemperature = w.$astroLib_equilibriumTemperature(insolation);
        equilibriumTemperature = meanTemperature;
        if(planetRadius < 10000)
            {
            this.$planetDensityList[i] = w.$astroLib_planetDensity(planetRadius, equilibriumTemperature);
            }
        else
            {
            if(planetRadius < 15000)
                {
                this.$planetDensityList[i] = 0.5 + 1.5 * (15000 - planetRadius)/5000 + 0.25 * system.scrambledPseudoRandomNumber(i);
                }
            else
                {
                this.$planetDensityList[i] = 0.5 + 0.75 * (planetRadius - 15000)/2500 + 0.25 * system.scrambledPseudoRandomNumber(i);
                }
            }
        planetDensity =  this.$planetDensityList[i];
        this.$planetMassList[i] = planetDensity/this.$planetDensity * Math.pow((planetRadius/this.$planetRadius),3);
        this.$escapeVelocityList[i] = this.$planetEscapeVelocity * planetRadius/this.$planetRadius * Math.sqrt(planetDensity/this.$planetDensity);
        escapeVelocity = this.$escapeVelocityList[i];
        this.$planetGravityList[i] = escapeVelocity * escapeVelocity / (planetRadius * 1000) / (9.81*2);
        surfaceGravity =  this.$planetGravityList[i];
        this.$atmosphereMassList[i] = w.$astroLib_atmosphereMass(planetRadius, escapeVelocity, equilibriumTemperature);
        if(planetRadius < 10000)
            {
            atmosphereMass = this.$atmosphereMassList[i];
            this.$atmospherePressureList[i] = atmosphereMass * surfaceGravity;
            }
        else
            {
            this.$atmospherePressureList[i] = 1;
            atmosphereMass = 1 / surfaceGravity;
            }
        this.$atmosphereTemperatureList[i] = w.$astroLib_atmosphereTemperature(equilibriumTemperature, atmosphereMass);
        }
    this.$paintPlanet();
    }
this.$planetInfo = function()
    {
    var planetRadius_scaled;
    var planetMass_scaled;
    var escapeVelocity_scaled;
    var surfaceGravity_scaled;
    var atmospherePressure_scaled;
    for (let i=0; i<system.planets.length; i++)
        {
        if(this.$planetFlag == system.planets[i].radius)
            {
            this.$reportFlag = i;
            }
        }
    var r = this.$reportFlag;
    if(system.planets[r].radius < 75000)
        {
        planetRadius_scaled = system.planets[r].radius / 10;          // default planet scale
        }
    else
        {
        if(system.planets[r].radius >= 75000 && system.planets[r].radius < 100000)
            {
            planetRadius_scaled = (75000 + (system.planets[r].radius - 75000) * 2) / 10;    // super-earth - 2x increment
            }
        else
            {
            if(system.planets[r].radius >= 100000 && system.planets[r].radius < 125000)
                {
                planetRadius_scaled = (150000 + (system.planets[r].radius - 100000) * 4) / 10;    // ice giant - 4x increment
                }
            else
                {
                if(system.planets[r].radius >= 125000)
                    {
                    planetRadius_scaled = (250000 + (system.planets[r].radius - 125000) * 10) / 10;     // gas giant - 10x increment
                    }
                }
            }
        }
    var scale_factor = planetRadius_scaled / system.planets[r].radius * 10;
    planetMass_scaled = this.$planetMassList[r] * Math.pow(scale_factor,3);
    escapeVelocity_scaled = this.$escapeVelocityList[r]/1000 * scale_factor;
    surfaceGravity_scaled = this.$planetGravityList[r] * scale_factor;
    atmospherePressure_scaled = this.$atmospherePressureList[r] * scale_factor;
    if(system.planets[r].radius >= 100000)
        {
        atmospherePressure_scaled = 1;
        }
    if (this.$atmospherePressureList[r] < 0.001)
        {
        atmospherePressure_scaled = 0;
        }
    var planetInfo = "ORBITAL DATA" + "\n"
    + "Orbit radius: " +  this.$orbitRadiusList[r].toFixed(3) + " OU" + "\n"
    + "Orbital period: " + this.$orbitPeriodList[r].toFixed(3) + " days" + "\n"
    + "PHYSICAL DATA" + "\n"
    + "Radius: " + planetRadius_scaled + " km" + "\n"
    + "Mean density: " + this.$planetDensityList[r].toFixed(3) + " g/cm3" + "\n"
    + "Mass: " + planetMass_scaled.toFixed(3) + " TU" + "\n"
    + "Escape velocity: " + escapeVelocity_scaled.toFixed(3) + " km/s" + "\n"
    + "Surface gravity: " + surfaceGravity_scaled.toFixed(3) + " G" + "\n"
    + "Atmosphere pressure: " + atmospherePressure_scaled.toPrecision(4) + " bar" + "\n"
    + "Surface temperature: " + this.$atmosphereTemperatureList[r].toFixed(1) + " K" + "\n";
    mission.runScreen({
        title: "Planet Data Sheet",
//        background: {name: "specialCargoLoad.png", height: 480 },
        message: planetInfo,}
        );
    }
this.$moonInfo = function()
    {
    var w = worldScripts.SpawnMoons;
    for (let i=0; i<system.planets.length; i++)
        {
        if (this.$planetFlag == system.planets[i].radius)
            {
            this.$reportFlag = i;
            }
        }
    var r = this.$reportFlag;
    var moonRadius = system.planets[r].radius;
    var moonOrbitRadius;
    var moonOrbitPeriod;
    var p = w.$targetPlanet_Jovian;
    var moonOrbitVelocity;
    if (moonRadius >= 12500 && moonRadius < 15000)
        {
        moonOrbitRadius = w.$orbitRadius_Luna;
        moonOrbitPeriod = w.$orbitPeriod_Luna / 1440;
        }
    if (moonRadius >= 15000 && moonRadius < 17500)
        {
        moonOrbitRadius = w.$orbitRadius_Selene;
        moonOrbitPeriod = w.$orbitPeriod_Selene / 1440;
        }
    if(moonRadius >= 17500 && moonRadius < 20000)
        {
        moonOrbitRadius = w.$orbitRadius_ZeusInner;
        moonOrbitVelocity = Math.sqrt(this.$escapeVelocityList[p]*this.$escapeVelocityList[p]/moonOrbitRadius/2);
        moonOrbitPeriod = 2.0 * Math.PI * (moonOrbitRadius * system.planets[p].radius * 100 / moonOrbitVelocity) / 86400;
        }
    if(moonRadius >= 20000 && moonRadius < 25000)
        {
        moonOrbitRadius = w.$orbitRadius_ZeusOuter;
        moonOrbitVelocity = Math.sqrt(this.$escapeVelocityList[p]*this.$escapeVelocityList[p]/moonOrbitRadius/2);
        moonOrbitPeriod = 2.0 * Math.PI * (moonOrbitRadius * system.planets[p].radius * 100 / moonOrbitVelocity) / 86400;
        }
    //
    var moonInfo = "ORBITAL DATA" + "\n"
    + "Orbit radius: " +  moonOrbitRadius.toFixed(3) + " R" + "\n"
    + "Orbital period: " + moonOrbitPeriod.toFixed(3) + " days" + "\n"
    + "PHYSICAL DATA" + "\n"
    + "Radius: " + system.planets[r].radius/10 + " km" + "\n"
    + "Mean density: " + this.$planetDensityList[r].toFixed(3) + " g/cm3" + "\n"
    + "Mass: " + this.$planetMassList[r].toFixed(2) + " TU" + "\n"
    + "Escape velocity: " + (this.$escapeVelocityList[r]/1000).toFixed(3) + " km/s" + "\n"
    + "Surface gravity: " + this.$planetGravityList[r].toFixed(3) + " G" + "\n"
    + "Atmosphere pressure: " + this.$atmospherePressureList[r].toPrecision(4) + " bar" + "\n"
    + "Surface temperature: " + this.$atmosphereTemperatureList[r].toFixed(1) + " K" + "\n";
    mission.runScreen({
        title: "Moon Data Sheet",
//        background: {name: "specialCargoLoad.png", height: 480 },
        message: moonInfo,}
        );
    }
this.$paintPlanet = function()
    {
    if (system.isInterstellarSpace) return;
    var paintPlanet1 = system.scrambledPseudoRandomNumber(161);
    var paintPlanet2 = system.scrambledPseudoRandomNumber(162);
    var paintPlanet3 = system.scrambledPseudoRandomNumber(163);
    var paintPlanet4 = system.scrambledPseudoRandomNumber(164);
    var paintPlanet5 = system.scrambledPseudoRandomNumber(165);
    var paintPlanet6 = system.scrambledPseudoRandomNumber(166);
    var paintPlanet7 = system.scrambledPseudoRandomNumber(167);
    var paintPlanet8 = system.scrambledPseudoRandomNumber(168);
    var paintPlanet9 = system.scrambledPseudoRandomNumber(169);
    var paintPlanet10 = system.scrambledPseudoRandomNumber(170);
    var paintPlanet11 = system.scrambledPseudoRandomNumber(171);
    var paintPlanet12 = system.scrambledPseudoRandomNumber(172);
    var aeolisShift = Math.floor(5 * paintPlanet1) + 1;
    var aeolisTexture = ('oplanet_Aeolis' + aeolisShift + '.png');          // Set 1 - Cold wind-eroded deserts
    var aphroditeShift = Math.floor(5 * paintPlanet2) + 1;
    var aphroditeTexture = ('oplanet_Aphrodite' + aphroditeShift + '.png'); // Set 2 - Venus class superdense atmosphere with opaque clouds
    var aresShift = Math.floor(5 * paintPlanet3) + 1;
    var aresTexture = ('oplanet_Ares' + aresShift + '.png');                // Set 3 - Mars class cold desert with impact craters
    var boreusShift = Math.floor(5 * paintPlanet4) + 1;
    var boreusTexture = ('oplanet_Boreus' + boreusShift + '.png');          // Set 4 - Snowball Earth
    var cronusShift = Math.floor(5 * paintPlanet5) + 1;
    var cronusTexture = ('oplanet_Cronus' + cronusShift + '.png');          // Set 5 - Saturn class gas giants
    var hadesShift = Math.floor(5 * paintPlanet6) + 1;
    var hadesTexture = ('oplanet_Hades' + hadesShift + '.png');             // Set 6 - Pluto class ice worlds
    var hermesShift = Math.floor(5 * paintPlanet7) + 1;
    var hermesTexture = ('oplanet_Hermes' + hermesShift + '.png');          // Set 7 - Mercury class heavy cratered dry airless deserts
    var phaethonShift = Math.floor(5 * paintPlanet8) + 1;
    var phaethonTexture = ('oplanet_Phaethon' + phaethonShift + '.png');    // Set 8 - Warm Mars without permafrost and polar caps
    var poseidonShift = Math.floor(5 * paintPlanet9) + 1;
    var poseidonTexture = ('oplanet_Poseidon' + poseidonShift + '.png');    // Set 9 - Neptune class ice giants
    var setShift = Math.floor(5 * paintPlanet10) + 1;
    var setTexture = ('oplanet_Set' + setShift + '.png');                   // Set 10 - Warm sandy deserts
    var typhonShift = Math.floor(5 * paintPlanet11) + 1;
    var typhonTexture = ('oplanet_Typhon' + typhonShift + '.png');          // Set 11 - Hot volcanic worlds
    var zeusShift = Math.floor(5 * paintPlanet12) + 1;
    var zeusTexture = ('oplanet_Zeus' + zeusShift + '.png');                // Set 12 - Jupiter class gas giant
    var w = worldScripts.AstroLibrary;
    var planetOrbitScan = w.$astroLib_orbitRadius();
    var surfaceTemp;
    var surfaceAirPressure;
    var textureIndex;
    var planetTexture;
    for (let i=0; i<system.planets.length; i++) 
        {
        surfaceTemp = this.$atmosphereTemperatureList[i];
        surfaceAirPressure = this.$atmospherePressureList[i];
        // Mercury analog
        if(system.planets[i].radius >= 27500 && system.planets[i].radius < 30000 && system.planets[i] != system.mainPlanet)
            {
            system.planets[i].texture = hermesTexture;
            }  
        // Snowball Earth OR Venus analog
        if(system.planets[i].radius >= 50000 && system.planets[i].radius < 75000 && system.planets[i] != system.mainPlanet)
            {
            if(surfaceAirPressure < 0.01)
                {
                system.planets[i].texture = hermesTexture;
                }
            else
                {
                if(surfaceAirPressure >= 2.5)
                    {
                    system.planets[i].texture = aphroditeTexture;
                    }
                else
                    {
                    textureIndex = this.$climateIndex(surfaceTemp, surfaceAirPressure);
                    switch (textureIndex)
                        {
                        case 2: planetTexture = aeolisTexture; break;
                        case 3: planetTexture = aeolisTexture; break;
                        case 4: planetTexture = setTexture; break;
                        case 20: planetTexture = boreusTexture; break;
                        case 30: planetTexture = aeolisTexture; break;
                        case 40: planetTexture = typhonTexture; break;
                        default: planetTexture = aeolisTexture;
                        }
                    system.planets[i].texture = planetTexture;
                    }
                }
            }
        // Mars analog
        if(system.planets[i].radius >= 30000 && system.planets[i].radius < 50000 && system.planets[i] != system.mainPlanet)
            {            
            if(surfaceAirPressure < 0.01)
                {
                system.planets[i].texture = hermesTexture;
                }
            else
                {
                if(surfaceAirPressure >= 2.5)
                    {
                    system.planets[i].texture = aphroditeTexture;
                    }
                else
                    {
                    textureIndex = this.$climateIndex(surfaceTemp, surfaceAirPressure);
                    switch (textureIndex)
                        {
                        case 2: planetTexture = aresTexture; break;
                        case 3: planetTexture = phaethonTexture; break;
                        case 4: planetTexture = setTexture; break;
                        case 20: planetTexture = aeolisTexture; break;
                        case 30: planetTexture = aeolisTexture; break;
                        case 40: planetTexture = setTexture; break;
                        default: planetTexture = aresTexture;
                        }
                    system.planets[i].texture = planetTexture;
                    }
                }
            }
        // Super Earth
        if(system.planets[i].radius >= 75000 && system.planets[i].radius < 100000 && system.planets[i] != system.mainPlanet)
            {
            system.planets[i].texture = aphroditeTexture;
            }
        // Jupiter analog
        if(system.planets[i].radius >= 150000 && system.planets[i].radius < 175000 && system.planets[i] != system.mainPlanet)
            {
            system.planets[i].texture = zeusTexture;
            } 
        // Saturn analog
        if(system.planets[i].radius >= 125000 && system.planets[i].radius < 150000 && system.planets[i] != system.mainPlanet)
            {
            system.planets[i].texture = cronusTexture;
            } 
        // Neptune analog
        if(system.planets[i].radius >= 100000 && system.planets[i].radius < 125000 && system.planets[i] != system.mainPlanet)
            {
            system.planets[i].texture = poseidonTexture;
            }
        // Pluto analog
        if(system.planets[i].radius >= 25000 && system.planets[i].radius < 27500 && system.planets[i] != system.mainPlanet)
            {
            var orbitHadejan = planetOrbitScan[i];
            if(orbitHadejan > 1)
                {
                system.planets[i].texture = hadesTexture;
                }
            else
                {
                system.planets[i].texture = hermesTexture;
                }
            }
        }
    }
this.$climateIndex = function(surfaceTemp, surfaceAirPressure)
    {
    var tempIndex;
    var pressureIndex;
    var climateIndex;
    if(surfaceTemp < 273)
        {
        tempIndex = 2;
        }
    else
        {
        if(surfaceTemp >= 373)
            {
            tempIndex = 4;
            }
        else
            {
            tempIndex = 3;
            }
        }
    if(surfaceAirPressure < 0.25)
        {
        pressureIndex = 1;
        }
    else
        {
        pressureIndex = 10;
        }
    climateIndex = tempIndex * pressureIndex;
    return climateIndex;
    } |