System modding - Stellaris Wiki (2024)

Version

System modding - Stellaris Wiki (1)

Please help with verifying or updating older sections of this article. At least some were last verified for version 3.4.

This article is for the PC version of Stellaris only.

This guide is for adding and modifying Solar Systems to the game.

  • 1 Game Map and System Creation
  • 2 Star classes
    • 2.1 Adding new star classes
    • 2.2 Vanilla star classes
  • 3 Solar system initializers
    • 3.1 Unary Systems
    • 3.2 Binary and Trinary Systems
      • 3.2.1 P-Type
      • 3.2.2 S-Type
    • 3.3 Usage
    • 3.4 General Advice

Game Map and System Creation[edit | edit source]

Stellaris appears to create the game map first using the \map files to create coordinates for the stars on the galaxy map, and then use the \star_classes file to pick what star class is at each coordinate, and then finalize the system with additional contents (planets, moons, asteroid belts) from the \system initializer files and \planet_classes files.

Star classes[edit | edit source]

Star classes can be found in common/star_classes. If you want to create one from scratch, create a new file and place it in that folder.

Note that "stars" and "star classes" are two different things: individual stars are considered the same as planets in the game code, and are found in common/planet_classes, while star classes refer to the classification of a solar system as a whole and will determine lighting, the system's icon in the galaxy map, and number of individual stars in a solar system. Information about modding individual stars can be found here.

Adding new star classes[edit | edit source]

Making a new star class is easy. Here's an example of a binary system that can be found in 00_star_classes:

sc_binary_1 = { # X-ray Binary Star System: Blue star around a Pulsar class = a_star icon = e_binary_star planet = { key = pc_a_star class = a_star } planet = { key = pc_pulsar class = pulsar } spawn_odds = 5 num_planets = { min = 4 max = 10 } pc_desert = { spawn_odds = 0 } pc_tropical = { spawn_odds = 0 } pc_arid = { spawn_odds = 0 } pc_continental = { spawn_odds = 0 } pc_ocean = { spawn_odds = 0 } pc_tundra = { spawn_odds = 0 } pc_arctic = { spawn_odds = 0 } pc_gaia = { spawn_odds = 0 } pc_alpine = { spawn_odds = 0 } pc_savannah = { spawn_odds = 0 } is_environmental_hazard = yes modifier = { ship_shield_reduction = 1.0 }}
  • "sc_binary_1" is the name of the star class used by the code. To assign the name the player will see, see localisation modding.
  • "class" is used to determine the system's lighting. You can use an existing one or create your own via gfx modding.
  • "icon" is the icon used by this system type in the galaxy view. By default it'll search for one that matches the star name ("binary_1_star" in this case) in the gfx/map/star_classes folder, but using "icon" lets you overwrite this with whatever icon you want.
  • While not included in the example above, you can also use "icon_scale = " to change the size of the icon on the galaxy map. 1 is default, 0.5 is half the size, etc.
  • "planet" is the type of star used by this star class by default. If it's a unary system with just one star, you don't need to write "class" again.
  • "spawn_odds" is exactly what it sounds like: the likelihood that this star class will spawn if it's used in a random list such as rl_standard_stars. If you don't plan to put it in a list, you can use any number or leave it out entirely.
  • "num_planets" is the number of planets that can be found in these systems. The number of planets in the solar system initializer will overwrite this by default, but if a random range is used there it'll use the number from here.
  • The planets' spawn odds are for if you want to alter the likelihood that certain planet classes will spawn in these systems. Neutron Stars, for example, have the values set to 0 by default since these systems won't be hospitable for life forms.
  • "is_environmental_hazard" marks the system as a hazard, obviously. The "modifier" applies a buff or debuff to ships and stations in the system.

Vanilla star classes[edit | edit source]

For reference, the existing star classes are the following:

IconClassStar typeEnvironmental effects
sc_bClass B Star
sc_aClass A Star
sc_fClass F Star
sc_gClass G Star
sc_kClass K Star
sc_mClass M Star
sc_m_giantClass M Red Giant
sc_tClass T Brown Dwarf
sc_black_holeBlack Hole +50% Disengagement Chance Reduction
+50% Emergency FTL Jump Cooldown
sc_neutron_starNeutron Star +50% Sublight Speed Reduction
sc_pulsarPulsar +100% Shield Nullification
sc_binary_1Binary Stars (A, Pulsar) +100% Shield Nullification
sc_binary_2Binary Stars (B, Neutron Star) +50% Sublight Speed Reduction
sc_binary_3Binary Stars (M Giant, B)
sc_binary_4Binary Stars (M Giant, F)
sc_binary_5Binary Stars (B, B)
sc_binary_6Binary Stars (M, G)
sc_binary_7Binary Stars (K, F)
sc_binary_8Binary Stars (G, F)
sc_binary_9Binary Stars (A, F)
sc_binary_10Binary Stars (A, T)
sc_trinary_1Trinary Stars (G, M, K)
sc_trinary_2Trinary Stars (B, A, F)
sc_trinary_3Trinary Stars (K, F, G)
sc_trinary_4Trinary Stars (B, K, T)

Solar system initializers[edit | edit source]

Solar systems are found in common/solar_system_initializers. If you want to create one from scratch, create a new file and place it in that folder.

For additional information, see example.txt inside the folder.

Unary Systems[edit | edit source]

A unary system consists of just one star and a handful of planets and moons. These are the most common types of systems in Stellaris, and we'll start our tutorial by making one.

@base_moon_distance = 10my_system_initializer = { name = "My System" class = "rl_standard_stars" asteroid_belt = { type = rocky_asteroid_belt radius = 70 } planet = { class = star size = { min = 25 max = 30 } orbit_distance = 0 orbit_angle = 1 } change_orbit = 10 planet = { class = pc_arid orbit_distance = 30 orbit_angle = { min = 90 max = 270 } init_effect = { prevent_anomaly = yes generate_primitives_on_planet = yes } change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } class = pc_molten orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } } change_orbit = 30 planet = { count = { min = 1 max = 4 } class = pc_asteroid orbit_distance = 0 orbit_angle = { min = 90 max = 270 } } planet = { count = { min = 3 max = 6 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } } neighbor_system = { trigger = { num_guaranteed_colonies >= 1 } distance = { min = 10 max = @distance } initializer = "sol_neighbor_t1_first_colony" }}

As before, let's go over each element one by one.

@base_moon_distance = 10my_system_initializer = { name = "My System" class = "rl_standard_stars" asteroid_belt = { type = rocky_asteroid_belt radius = 70 }
  • "@base_moon_distance" is a variable that can be set in each solar system initializer file. It's not strictly needed, but can be useful if you want to play around with moon orbit distances en masse rather than one at a time. All vanilla solar systems use 10 by default.
  • "my_system_initializer" is, again, the name the game code uses to identify this system. No need for localisation this time; the name the player will see is right there below it (in this case, "My System").
  • "class" is, of course, the star class. You can use a specific class such as sc_b, or a random list such as rl_standard_stars, which chooses a random one based on the spawn_odds in each star's code.
  • "asteroid_belt" adds an asteroid belt at a certain distance from the center of the system -- not necessarily from the sun! We'll get to that later. The valid types can be found in Stellaris/common/00_asteroid_belts; usually you'll use either rocky or icy. You can also mod new ones in if desired.

Now for the system's sun. Note that the star is, as I mentioned above, considered a planet by the game engine.

 planet = { class = star size = { min = 25 max = 30 } orbit_distance = 0 orbit_angle = 1 }
  • "class", in the context of a planet refers to the planet class. Using "class = star" will make it the star class that matches the star type, so if we'd used sc_b above, the star would be pc_b_star -- a Class B Star. You can use pc_b_star anyway if you want, but that can cause complications with star lighting and, in a binary/trinary system, planet naming. More on that below. Anyway, just using "class = star" for the stars is recommended unless you have a good reason not to.
  • "size" is the size of the planet. This used to refer to the number of planet tiles, but since tiles are obsolete in general and useless on stars anyway, it just makes the star appear bigger or smaller. A size range of 20-35 is recommended for stars, since smaller than that looks silly and larger can swallow up ships flying overhead.
  • "orbit_distance" is the distance from the previous element, or if no such element exists, the system's center. For the lone star in a system, you naturally want this to be 0.
  • "orbit_angle" is the orbital angle from the previous planet, so if the previous had an angle of 30, using "orbit_angle = 20" would give it an overall angle of 50. Again, for the central star, this doesn't matter so you can use any old number. Most vanilla stars use 1 for some reason, so that's what I did here.

Now that the star is done, let's move on to the first planet.

 change_orbit = 10 planet = { class = pc_arid orbit_distance = 30 orbit_angle = { min = 90 max = 270 } init_effect = { prevent_anomaly = yes generate_primitives_on_planet = yes }
  • "change_orbit" increases the spacing between planets (in the system scope), or between a planet and its first moon (in the planet scope).
  • "class = pc_arid", so it will be an Arid World.
  • "orbit_distance = 30" adds 30 units of space between the planet and the last element (in this case, "change_orbit = 10", so its total distance from the sun is 40 units).
  • "orbit_angle = { min = 90 max = 270 )" is pretty straightforward: a random angle, within ninety degrees of the previous element.
  • "init_effect" allows you to apply effects and scripted effects to the planet upon system generation. It can also be used in the system scope if you want to apply an effect to the system as a whole instead of just one planet.
    • "prevent_anomaly" is an effect that disables anomalies from appearing on this planet.
    • "generate_primitives_on_planet" is a scripted effect that creates a pre-FTL species on this planet.

Now for a moon.

 change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } class = pc_molten orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } }
  • "change_orbit = @base_moon_distance" here adds 10 units of distance between the planet and its moon as indicated in the @ variable.
  • "count = { min = 0 max = 1 }" to randomize the number of moons between 0 and 1. You can go as high or as low as you want with this, though usually in vanilla you won't find more than 1 moon unless the planet is a gas giant.
  • "class = pc_molten" (for a Molten World).
  • "orbit_distance = 5" (for a total of 15, including the "change_orbit" above).
  • "orbit_angle = { min = 90 max = 270 }", for the same randomized orbit angles as used in the planet itself.
 change_orbit = 30 planet = { count = { min = 1 max = 4 } class = pc_asteroid orbit_distance = 0 orbit_angle = { min = 90 max = 270 } }

Time to fill out the asteroid belt. We use "@change_orbit" again, this time keeping a close eye on the number used so that the total number of space used matches the 70 defined in the asteroid belt at the top of the file. Now we add the asteroids, making sure that "orbit_distance = 0" for all of them. We want them inside the asteroid belt, after all! "orbit_angle" is a little tricky here: since the asteroids are all in the same orbit, it's possible that they might clip together. You can get away from that by directly choosing their specific orbit angles.

If your asteroid belt is icy rather than rocky, use "pc_ice_asteroid" instead of "pc_asteroid". If it's crystalline, use "pc_crystal_asteroid" or "pc_rare_crystal_asteroid".

 planet = { count = { min = 3 max = 6 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } }

More planets! We'll leave "class = " out for these ones, allowing them to spawn as whatever the game engine wants them to be (based on the criteria spelled out in common/star_classes). The number of planets is also randomized between 3 and 6, each of which has 0 to 1 moons.

 neighbor_system = { trigger = { num_guaranteed_colonies >= 1 } distance = { min = 10 max = @distance } initializer = "sol_neighbor_t1_first_colony" }}
  • "neighbor_system" tells the game to spawn another, specific system within a certain distance of this system, and under what criteria. Pretty self-explanatory.

Binary and Trinary Systems[edit | edit source]

Some star systems have two or three suns, respectively. Such systems can be pretty complex in real life (just ask Mintaka!) but generally there are two types of binary/trinary systems, classified as "P-Type" and "S-Type".

P-Type[edit | edit source]

P-Type (or "circumbinary") systems have planets that orbit the barycenter of both (or all three) stars simultaneously. Sirius is an example of this kind of system, as is Tatooine in the Star Wars universe.

P-Types are the easiest to make in Stellaris. Instead of a single star with "orbit_distance = 0", do the following:

 planet = { class = star size = { min = 30 max = 35 } orbit_distance = 15 orbit_angle = { min = 90 max = 270 } } planet = { class = star size = { min = 25 max = 30 } orbit_distance = 10 orbit_angle = 180 }

Then just add your planets as normal, change the star class to rl_binary_stars or rl_trinary_stars (or a specific class of either), and you're good to go!

  • Using "class = star" for both/all three stars will assign their class in accordance with the type of binary/trinary system: with "sc_binary_1", for instance, the first star will be A-class, and the second will be a Pulsar.
  • If it's a trinary instead of a binary:
    • Add a third star in the same manner.
    • Change the second star's orbit angle to 145.
    • Give the third star an orbit angle of 70, an orbit distance of 0, and a maximum size of 25.
  • The orbit distances, orbit angles, and star sizes are entirely up to you; the values given above just look the nicest in my opinion. Feel free to experiment!

S-Type[edit | edit source]

In S-Type systems, each star has its own system of planets. Think of them as two or three unary systems that are close enough together that you can travel between them without needing a hyperdrive. 40 Eridani is an example of such a system, as is Vulcan in the Star Trek universe.

To recap, a unary system with one sun has basically this structure:

 planet = { class = star size = { min = 25 max = 30 } orbit_distance = 0 orbit_angle = 1 } planet = { count = { min = 3 max = 6 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } }

The structure of an S-type star and its planets looks more like this:

 planet = { class = star size = { min = 25 max = 30 } orbit_distance = 0 orbit_angle = 1 satellite_naming_policy = upper_case_roman_numerals planet = { count = { min = 3 max = 6 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } satellite_naming_policy = lower_case_latin_letters change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } } }

See the differences?

  • In a unary system, the planets are all defined in the system scope. In an S-type binary or trinary system, the planets are defined in their specific star's scope. This ensures that they will have the correct orbit lines and names.
  • "satellite_naming_policy" indicates how this star's planets (or this planet's moons) will be named. A star should use "upper_case_roman_numerals" for its planets; planets should use "lower_case_latin_letters" for their moons.

A full S-type trinary system would look like this:

 planet = { class = star size = { min = 30 max = 35 } orbit_distance = 0 orbit_angle = 1 satellite_naming_policy = upper_case_roman_numerals planet = { count = { min = 3 max = 6 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } satellite_naming_policy = lower_case_latin_letters change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } } } planet = { class = star size = { min = 25 max = 30 } orbit_distance = 230 orbit_angle = { min = 90 max = 270 } satellite_naming_policy = upper_case_roman_numerals planet = { count = { min = 3 max = 5 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } satellite_naming_policy = lower_case_latin_letters change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } } } planet = { class = star size = { min = 20 max = 25 } orbit_distance = 0 orbit_angle = { min = 90 max = 270 } satellite_naming_policy = upper_case_roman_numerals planet = { count = { min = 2 max = 4 } orbit_distance = 20 orbit_angle = { min = 90 max = 270 } satellite_naming_policy = lower_case_latin_letters change_orbit = @base_moon_distance moon = { count = { min = 0 max = 1 } orbit_distance = 5 orbit_angle = { min = 90 max = 270 } } } }
  • The second star, Star B, orbits 230 units away from the first, Star A. This is because we don't want the two systems to overlap. Star A has up to six planets, each orbiting at a distance of 20, which gives us a maximum system width of 120. Star B has up to five, giving it a maximum width of 100. 120 + 100 = 220, so we use 230 to give them a little extra space.
  • The third star, Star C, orbits at the same distance from A as B but at a different angle. This isn't a hard requirement, you can space it out further if you want, but all the vanilla systems do it that way and it just looks nicer in my opinion. We don't want systems to be too big, or it'll take forever to cross them at sublight speeds.

Usage[edit | edit source]

One thing I haven't gone over is usage -- how the game knows which system to generate. There are a few ways to do this, applied in the system scope.

  • "usage = misc_system_init" tells the game to randomly generate this system somewhere in the galaxy, based on the value entered for "usage_odds". You can also use modifiers for these if you want the system to spawn (or not) in a certain area of the galaxy. There's also "max_instances = " to ensure that you don't get more than X instances of these systems. For example:
usage = misc_system_initusage_odds = { base = 2000000 modifier = { factor = 0 is_bottleneck_system = yes }}max_instances = 1
  • "usage = empire_init" tells the game that this system is an empire homeworld, which either the player or the AI can end up with if they choose "Random" in the empire creation screen. If you use this, make sure the system has a planet with the following:
planet = { home_planet = yes init_effect = { generate_empire_home_planet = yes prevent_anomaly = yes }}
  • "usage = custom_empire" is mostly the same as above, except it tells the game that this system is a prescripted empire homeworld which can be chosen in the empire creation screen, like Sol and Deneb. Make sure to give the system a name and description via localisation.
  • If no usage value is used, or if "usage_odds = 0", the system will never spawn in the galaxy unless specifically called to by an event or another external means.

General Advice[edit | edit source]

  • Remember when I said that using "class = pc_b_star" is just as good as "class = star" most of the time? That's true in unary systems, but it can lead to problems with planet and star names in binary or trinary systems. If you want to hard-code a specific star class regardless of the system class, use "class = star" and then add "init_effect = { change_pc = pc_b_star }" underneath.
  • The same as above goes for giving planets specific names. If you name the third planet in the system "Joe", the fourth planet will use "StarName III" in its place. You can get around this by using "init_effect = { set_name = "Joe" }" instead.
  • All planets, ships, etc. in a system will always be lit from the system's center regardless of the location of the star(s). The devs are working on a fix for this but until then we just have to live with it.
  • Asteroids and Ringworld sections don't have visible orbital lines by default, but if they're placed in the star's scope (such as in an S-type binary system) they will have lines, which looks kind of messy. Make sure you place them in the system scope whenever possible.
  • And speaking of Ringworlds, their individual segments always face the center of the system regardless of which star they orbit.
  • Please note that "orbit_distance" does not default to 0! If you want it to orbit at the same distance as the previous planet or change_orbit, be sure to include "orbit_distance = 0"! Otherwise the orbit distance will be randomized, the range of which is not yet known.

Modding

EmpireEmpireEthicsGovernments • Civics • OriginsMandatesAgendasTraditions • Ascension perksEdictsPoliciesRelicsTechnologiesCustom empires
PopsJobsFactions
LeadersLeadersLeader traits
SpeciesSpeciesSpecies traits
PlanetsPlanetsPlanetary feature • Orbital depositBuildings • DistrictsPlanetary decisions
SystemsSystemsStarbasesMegastructuresBypassesMap
FleetsFleetsShips • Components
Land warfareArmiesBombardment stance
DiplomacyDiplomacy • Federations • Galactic communityOpinion modifiersCasus Belli • War goals
EventsEventsAnomaliesSpecial projectsArchaeological sites
GameplayGameplayDefinesResources • EconomyGame start
Dynamic moddingDynamic moddingEffectsConditionsScopesModifiersVariablesAIOn actions
Media/localisationMaya exporterPortraitsFlagsEvent picturesInterfaceIconsMusicLocalisation
OtherConsole commandsSave-game editingSteam WorkshopModding tutorial
System modding - Stellaris Wiki (2024)

References

Top Articles
Latest Posts
Article information

Author: Van Hayes

Last Updated:

Views: 6356

Rating: 4.6 / 5 (46 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Van Hayes

Birthday: 1994-06-07

Address: 2004 Kling Rapid, New Destiny, MT 64658-2367

Phone: +512425013758

Job: National Farming Director

Hobby: Reading, Polo, Genealogy, amateur radio, Scouting, Stand-up comedy, Cryptography

Introduction: My name is Van Hayes, I am a thankful, friendly, smiling, calm, powerful, fine, enthusiastic person who loves writing and wants to share my knowledge and understanding with you.