{ "$schema": "https://json-schema.org/draft-07/schema", "$docs": { "title": "Celestial Body Schema", "description": "Schema for a celestial body in New Horizons" }, "$defs": { "vector3": { "type": "object", "additionalProperties": false, "properties": { "x": { "type": "number", "default": 0 }, "y": { "type": "number", "default": 0 }, "z": { "type": "number", "default": 0 } } }, "vector2": { "type": "object", "additionalProperties": false, "properties": { "x": { "type": "number", "default": 0 }, "y": { "type": "number", "default": 0 } } }, "wholeVector2": { "type": "object", "additionalProperties": false, "properties": { "x": { "type": "integer", "default": 0 }, "y": { "type": "integer", "default": 0 } } }, "colorPart": { "type": "integer", "default": 0, "minimum": 0 }, "color": { "type": "object", "additionalProperties": false, "properties": { "R": { "$ref": "#/$defs/colorPart" }, "G": { "$ref": "#/$defs/colorPart" }, "B": { "$ref": "#/$defs/colorPart" }, "A": { "$ref": "#/$defs/colorPart", "default": 255 } } }, "angle": { "type": "number", "default": 0, "minimum": 0, "maximum": 360 }, "curve": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "time": { "type": "integer", "default": 0 }, "value": { "type": "number", "default": 0 } } } }, "procGen": { "type": "object", "additionalProperties": false, "properties": { "scale": { "type": "number", "minimum": 0, "description": "Average surface size" }, "colour": { "$ref": "#/$defs/color", "description": "Colour of the terrain." } } } }, "title": "Body", "description": "A planet or body to generate", "type": "object", "required": [ "name" ], "additionalProperties": false, "properties": { "$schema": { "type": "string" }, "name": { "type": "string", "description": "Unique name of your planet" }, "starSystem": { "type": "string", "description": "Unique star system containing your planet", "default": "SolarSystem" }, "destroy": { "type": "boolean", "description": "`true` if you want to delete this planet", "default": false }, "childrenToDestroy": { "type": "string", "description": "A list of paths to child GameObjects to destroy on this planet", "default": [] }, "Base": { "type": "object", "additionalProperties": false, "properties": { "hasMapMarker": { "type": "boolean", "default": false, "description": "If the body should have a marker on the map screen." }, "hasAmbientLight": { "type": "boolean", "default": false, "description": "If the dark side of the body should have some slight amount of light" }, "surfaceGravity": { "type": "number", "default": 12, "description": "The acceleration due to gravity felt as the surfaceSize. Timber Hearth has 12 for reference" }, "gravityFallOff": { "type": "string", "enum": [ "linear", "inverseSquared" ], "default": "linear", "description": "How gravity falls off with distance. Most planets use linear but the sun and some moons use inverseSquared." }, "surfaceSize": { "type": "number", "default": 100, "description": "A scale height used for a number of things. Should be the approximate radius of the body." }, "sphereOfInfluence": { "type": "number", "default": 0, "description": "An override for the radius of the planet's gravitational sphere of influence. Optional" }, "groundSize": { "type": "number", "default": 0, "description": "Radius of a simple sphere used as the ground for the planet. If you want to use more complex terrain, leave this as 0." }, "hasCometTail": { "type": "boolean", "default": false, "description": "If you want the body to have a tail like the Interloper." }, "cometTailRotation": { "$ref": "#/$defs/vector3", "description": "If it has a comet tail, it'll be oriented according to these Euler angles." }, "hasReferenceFrame": { "type": "boolean", "default": true, "description": "Allows the object to be targeted on the map." }, "centerOfSolarSystem": { "type": "boolean", "default": false, "description": "Set this to true if you are replacing the sun with a different body. Only one object in a star system should ever have this set to true." }, "isSatellite": { "type": "boolean", "default": false, "description": "Is this body an artificial satellite of a planet/moon/star?" }, "cloakRadius": { "type": "number", "default": 0, "description": "Radius of the cloaking field around the planet. It's a bit finicky so experiment with different values. If you don't want a cloak, leave this as 0." }, "invulnerableToSun": { "type": "boolean", "default": false, "description": "Can this planet survive entering a star?" } } }, "Atmosphere": { "type": "object", "additionalProperties": false, "properties": { "size": { "type": "number", "default": 0, "description": "Scale height of the atmosphere" }, "cloudTint": { "$ref": "#/$defs/color", "description": "Colour of the cloud layer. Only relevant if \"cloud\" has a value" }, "cloud": { "type": "string", "description": "Relative filepath to the cloud texture, if the planet has clouds." }, "cloudCap": { "type": "string", "description": "Relative filepath to the cloud cap texture, if the planet has clouds." }, "cloudRamp": { "type": "string", "description": "Relative filepath to the cloud ramp texture, if the planet has clouds. If you don't put anything here it will be auto-generated." }, "useBasicCloudShader": { "type": "boolean", "default": false, "description": "Set to `false` in order to use Giant's deep shader. Set to `true` to just apply the cloud texture as is." }, "shadowsOnClouds": { "type": "boolean", "default": true, "description": "If the top layer should have shadows. Set to false if you're making a brown dwarf." }, "fogTint": { "$ref": "#/$defs/color", "description": "Colour of fog on the planet, if you put fog." }, "fogDensity": { "type": "number", "minimum": 0, "maximum": 1, "description": "How dense the fog is, if you put fog." }, "fogSize": { "type": "number", "description": "Radius of fog sphere, independent of the atmosphere. This has to be set for there to be fog.", "minimum": 0 }, "hasRain": { "type": "boolean", "default": false }, "hasSnow": { "type": "boolean", "default": false }, "hasOxygen": { "type": "boolean", "default": false, "description": "Lets you survive on the planet without a suit." }, "hasAtmosphere": { "type": "boolean", "default": false, "description": "Whether we use an atmospheric shader on the planet. Doesn't affect clouds, fog, rain, snow, oxygen, etc. Purely visual." }, "atmosphereTint": { "$ref": "#/$defs/color", "description": "Colour of atmospheric shader on the planet." } } }, "Orbit": { "type": "object", "additionalProperties": false, "properties": { "semiMajorAxis": { "type": "integer", "default": 5000, "minimum": 0, "description": "The semi-major axis of the ellipse that is the body's orbit. For a circular orbit this is the radius." }, "inclination": { "$ref": "#/$defs/angle", "description": "The angle (in degrees) between the body's orbit and the plane of the star system" }, "primaryBody": { "type": "string", "default": "Sun", "description": "The name of the body this one will orbit around" }, "isMoon": { "type": "boolean", "description": "Is this the moon of a planet? Used for determining when its name is shown on the map." }, "longitudeOfAscendingNode": { "$ref": "#/$defs/angle", "description": "An angle (in degrees) defining the point where the orbit of the body rises above the orbital plane if it has nonzero inclination." }, "eccentricity": { "type": "number", "default": 0, "minimum": 0, "maximum": 0.99999, "description": "At 0 the orbit is a circle. The closer to 1 it is, the more oval-shaped the orbit is." }, "argumentOfPeriapsis": { "$ref": "#/$defs/angle", "description": "An angle (in degrees) defining the location of the periapsis (the closest distance to it's primary body) if it has nonzero eccentricity." }, "trueAnomaly": { "$ref": "#/$defs/angle", "description": "Where the planet should start off in its orbit in terms of the central angle." }, "axialTilt": { "$ref": "#/$defs/angle", "description": "The angle between the normal to the orbital plane and its axis of rotation." }, "siderealPeriod": { "type": "number", "default": 0, "description": "Rotation period in minutes." }, "isTidallyLocked": { "type": "boolean", "default": false, "description": "Should the body always have one side facing its primary?" }, "alignmentAxis": { "$ref": "#/$defs/vector3", "description": "If it is tidally locked, this direction will face towards the primary. Ex: Interloper uses `0, -1, 0`. Most planets will want something like `-1, 0, 0`." }, "showOrbitLine": { "type": "boolean", "default": false, "description": "Referring to the orbit line in the map screen." }, "isStatic": { "type": "boolean", "default": false, "description": "Is the body meant to stay in one place without moving?" }, "tint": { "$ref": "#/$defs/color", "description": "Colour of the orbit-line in the map view." }, "trackingOrbitLine": { "type": "boolean", "default": false, "description": "Should we just draw a line behind its orbit instead of the entire circle/ellipse?" } } }, "Ring": { "type": "object", "additionalProperties": false, "properties": { "innerRadius": { "type": "number", "default": 0, "minimum": 0, "description": "Inner radius of the disk " }, "outerRadius": { "type": "number", "default": 0, "minimum": 0 }, "inclination": { "type": "number", "default": 0, "description": "Angle between the rings and the equatorial plane of the planet." }, "longitudeOfAscendingNode": { "$ref": "#/$defs/angle", "description": "Angle defining the point where the rings rise up from the planet's equatorial plane if inclination is nonzero." }, "texture": { "type": "string", "description": "Relative filepath to the texture used for the rings." }, "rotationSpeed": { "type": "number", "default": 0, "description": "Allows the rings to rotate." }, "curve": { "$ref": "#/$defs/curve", "description": "Allows the rings to grow/shrink with time." } } }, "HeightMap": { "type": "object", "additionalProperties": false, "properties": { "heightMap": { "type": "string", "description": "Relative filepath to the texture used for the terrain height" }, "textureMap": { "type": "string", "description": "Relative filepath to the texture used for the terrain." }, "minHeight": { "type": "number", "minimum": 0, "description": "The lowest points on your planet will be at this height." }, "maxHeight": { "type": "number", "minimum": 0, "description": "The highest points on your planet will be at this height." } } }, "ProcGen": { "$ref": "#/$defs/procGen" }, "AsteroidBelt": { "type": "object", "additionalProperties": false, "properties": { "innerRadius": { "type": "number", "default": 0, "minimum": 0 }, "outerRadius": { "type": "number", "default": 0, "minimum": 0 }, "inclination": { "$ref": "#/$defs/angle", "description": "Angle between the rings and the equatorial plane of the planet." }, "longitudeOfAscendingNode": { "$ref": "#/$defs/angle", "description": "Angle defining the point where the rings rise up from the planet's equatorial plane if inclination is nonzero." }, "randomSeed": { "type": "integer", "default": 0, "description": "Number used to randomize asteroid positions" }, "procGen": { "$ref": "#/$defs/procGen" } } }, "Star": { "type": "object", "additionalProperties": false, "properties": { "size": { "type": "number", "default": 2000, "minimum": 0, "description": "Radius of the star." }, "tint": { "$ref": "#/$defs/color", "description": "Colour of the star." }, "solarFlareTint": { "$ref": "#/$defs/color", "description": "Colour of the solar flares. The shader is a bit weird so the value you put won't exactly reflect what you see. Try experimenting with different colours to see what works." }, "lightTint": { "$ref": "#/$defs/color", "description": "Colour of the light given off." }, "solarLuminosity": { "type": "number", "minimum": 0, "description": "Relative strength of the light compared to the sun", "default": 1 }, "hasAtmosphere": { "type": "boolean", "default": true, "description": "The default sun has its own atmosphere that is different from regular planets. If you want that, set this to true." }, "curve": { "$ref": "#/$defs/curve", "description": "Allows the star to shrink/grow over time." } } }, "FocalPoint": { "type": "object", "additionalProperties": false, "description": "Use this to create the focal point that two objects can orbit in a binary system", "properties": { "primary": { "type": "string", "description": "The larger of the two bodies in the binary pair." }, "secondary": { "type": "string", "description": "The smaller of the two bodies in the binary pair." } } }, "Props": { "type": "object", "additionalProperties": false, "properties": { "scatter": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "count": { "type": "integer" }, "path": { "type": "string", "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle" }, "assetBundle": { "type": "string", "description": "Relative filepath to an asset-bundle" }, "offset": { "$ref": "#/$defs/vector3" }, "rotation": { "$ref": "#/$defs/vector3", "description": "Euler angle degrees" }, "scale": { "type": "number", "default": 1, "description": "How many props to scatter around the planet." } } } }, "details": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "path": { "type": "string", "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle" }, "assetBundle": { "type": "string", "description": "Relative filepath to an asset-bundle" }, "position": { "$ref": "#/$defs/vector3" }, "rotation": { "$ref": "#/$defs/vector3", "description": "Euler angle degrees" }, "scale": { "type": "number", "default": 1 }, "alignToNormal": { "type": "boolean", "description": "Do we override rotation and try to automatically align this object to stand upright on the body's surface?", "default": false } }, "scale": { "type": "number", "default": 1 } } }, "dialogue": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "position": { "$ref": "#/$defs/vector3", "description": "When you enter into dialogue, you will look here." }, "radius": { "type": "number", "default": 0, "description": "Radius of the spherical collision volume where you get the \"talk to\" prompt when looking at. If you use a remoteTriggerPosition, this will instead be the size of the volume that will trigger the dialogue when you enter it." }, "xmlFile": { "type": "string", "description": "Relative path to the xml file defining the dialogue." }, "remoteTriggerPosition": { "$ref": "#/$defs/vector3", "description": "Allows you to trigger dialogue from a distance when you walk into an area." }, "blockAfterPersistentCondition": { "type": "string", "description": "Prevents the dialogue from being created after a specific persistent condition is set. Useful for remote dialogue triggers that you want to have happen only once." } } } }, "reveal": { "type": "array", "description": "A set of volumes that reveal ship log fact", "items": { "type": "object", "additionalProperties": false, "properties": { "revealOn": { "type": "string", "enum": [ "enter", "observe", "snapshot" ], "description": "'enter', 'observe', or 'snapshot' what needs to be done to the volume to unlock the facts" }, "reveals": { "type": "array", "description": "A list of facts to reveal", "items": { "type": "string" } }, "position": { "$ref": "#/$defs/vector3", "description": "The position to place the volume at" }, "radius": { "type": "number", "description": "The radius of the volume", "default": 1.0 }, "maxDistance": { "type": "number", "description": "The max distance the user can be away from the volume to reveal the fact (snapshot and observe only)" }, "maxAngle": { "$ref": "#/$defs/angle", "description": "The max view angle (in degrees) the player can see the volume with to unlock the fact", "default": 180.0 } } } }, "entryLocation": { "type": "array", "description": "A set of locations for ship log entries", "items": { "type": "object", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "The ID of the entry this location is for" }, "cloaked": { "type": "boolean", "description": "Whether this entry location is in a cloaking field", "default": false }, "position": { "$ref": "#/$defs/vector3", "description": "The position of this entry location" } } } }, "geysers": { "type": "array", "description": "A set of geysers", "items": { "type": "object", "additionalProperties": false, "properties": { "position": { "$ref": "#/$defs/vector3", "description": "The position of this geyser" } } } } } }, "Spawn": { "type": "object", "additionalProperties": false, "properties": { "playerSpawnPoint": { "$ref": "#/$defs/vector3", "description": "If you want the player to spawn on the new body, set a value for this. Press \"P\" in game with Debug mode on to have the game log the position you're looking at to find a good value for this." }, "shipSpawnPoint": { "$ref": "#/$defs/vector3" }, "startWithSuit": { "type": "boolean", "default": false, "description": "If you spawn on a planet with no oxygen, you probably want to set this to true ;)" } } }, "Signal": { "type": "object", "additionalProperties": false, "properties": { "signals": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "position": { "$ref": "#/$defs/vector3" }, "frequency": { "type": "string", "description": "The frequency ID of the signal. The built-in game values are \"Default\", \"Traveler\", \"Quantum\", \"EscapePod\", \"Statue\", \"WarpCore\", \"HideAndSeek\", and \"Radio\". You can also put a custom value." }, "name": { "type": "string", "description": "The unique ID of the signal." }, "audioClip": { "type": "string", "description": "Name of an existing AudioClip in the game that will player over the signal." }, "audioFilePath": { "type": "string", "description": "Relative filepath to the .wav file to use as the audio. Mutually exclusive with audioClip" }, "reveals": { "type": "string", "description": "A ship log fact to reveal when the signal is identified" }, "sourceRadius": { "type": "number", "default": 1, "description": "Radius of the sphere giving off the signal" }, "detectionRadius": { "type": "number", "minimum": 0, "description": "How close the player must get to the signal to detect it. This is when you get the \"Unknown Signal Detected\" notification." }, "identificationRadius": { "type": "number", "minimum": 0, "description": "How close the player must get to the signal to identify it. This is when you learn its name." }, "onlyAudibleToScope": { "type": "boolean", "default": true, "description": "False if the player can hear the signal without equipping the signal-scope." }, "insideCloak": { "type": "boolean", "default": false, "description": "Only set to true if you are putting this signal inside a cloaking field." } } } } } }, "Singularity": { "type": "object", "additionalProperties": false, "properties": { "size": { "type": "number", "default": 0, "minimum": 0, "description": "Radius of the singularity. Note that this isn't the same as the event horizon, but includes the entire volume that has warped effects in it." }, "pairedSingularity": { "type": "string", "description": "The name of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill the player" }, "targetStarSystem": { "type": "string", "description": "If you want a black hole to load a new star system scene, put its name here. Optional." }, "type": { "type": "string", "enum": [ "BlackHole", "WhiteHole" ] }, "position": { "$ref": "#/$defs/vector3" } } }, "Water": { "type": "object", "additionalProperties": false, "properties": { "size": { "type": "number", "default": 0 }, "tint": { "$ref": "#/$defs/color" }, "curve": { "$ref": "#/$defs/curve" } } }, "Lava": { "type": "object", "additionalProperties": false, "properties": { "size": { "type": "number", "default": 0 }, "tint": { "$ref": "#/$defs/color" }, "curve": { "$ref": "#/$defs/curve" } } }, "Sand": { "type": "object", "additionalProperties": false, "properties": { "size": { "type": "number", "default": 0 }, "tint": { "$ref": "#/$defs/color" }, "curve": { "$ref": "#/$defs/curve" } } }, "Funnel": { "type": "object", "additionalProperties": false, "properties": { "target": { "type": "string", "description": "The body that the funnel is pouring onto" }, "type": { "type": "string", "enum": [ "Sand", "Water", "Lava", "Star" ], "default": "Sand" }, "tint": { "$ref": "#/$defs/color" }, "curve": { "$ref": "#/$defs/curve" } } }, "ShipLog": { "type": "object", "additionalProperties": false, "properties": { "xmlFile": { "type": "string", "description": "The relative path to the xml file to load ship log entries from." }, "spriteFolder": { "type": "string", "description": "A path to the folder where entry sprites are stored." }, "initialReveal": { "type": "array", "description": "A list of fact IDs to reveal when the game starts.", "items": { "type": "string" } }, "entryPositions": { "type": "array", "description": "A set of positions to use instead of automatic layout in rumor mode.", "items": { "type": "object", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "The name of the entry to apply the position to." }, "position": { "$ref": "#/$defs/vector2" } } } }, "MapMode": { "type": "object", "additionalProperties": false, "properties": { "revealedSprite": { "type": "string", "description": "The path to the sprite to show when the planet is revealed in map mode." }, "outlineSprite": { "type": "string", "description": "The path to the sprite to show when the planet is unexplored in map mode." }, "manualPosition": { "$ref": "#/$defs/vector2", "description": "Manually place this planet at the specified position." }, "manualNavigationPosition": { "$ref": "#/$defs/wholeVector2", "description": "Specify where this planet is in terms of navigation." }, "scale": { "type": "number", "description": "Scale to apply to the planet in map mode.", "default": 1 }, "invisibleWhenHidden": { "type": "boolean", "description": "Hide the planet completely if unexplored instead of showing an outline.", "default": false }, "offset": { "type": "number", "description": "Extra distance to apply to this object in map mode.", "default": 0 }, "remove": { "type": "boolean", "description": "Completely remove this planet (and it's children) from map mode.", "default": false }, "details": { "type": "array", "description": "Place non-selectable object in map mode (like sand funnels).", "items": { "type": "object", "additionalProperties": false, "properties": { "revealedSprite": { "type": "string", "description": "The sprite to show when the parent AstroBody is revealed." }, "outlineSprite": { "type": "string", "description": "The sprite to show when the parent AstroBody is rumored/unexplored." }, "rotation": { "$refs": "#/$defs/angle", "description": "The angle in degrees to rotate the detail." }, "invisibleWhenHidden": { "type": "boolean", "description": "Whether to completely hide this detail when the parent AstroBody is unexplored.", "default": false }, "position": { "$ref": "#/$defs/vector2", "description": "The position (relative to the parent) to place the detail." }, "scale": { "$ref": "#/$defs/vector2", "description": "The amount to scale the x and y-axis of the detail by." } } } } } }, "Curiosities": { "type": "array", "description": "A set of colors to apply to curiosities.", "items": { "type": "object", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "The ID of the curiosity to apply the color to." }, "color": { "$ref": "#/$defs/color", "description": "The color to apply to entries with this curiosity." }, "highlightColor": { "$ref": "#/$defs/color", "description": "The color to apply to highlighted entries with this curiosity." } } } } } } } }