Stellaris

Stellaris

Not enough ratings
"Lost Future" - Mod Guide - 2.3.1
By Atoombom007
Introduction
This guide intends to deconstruct one of my mods for Stellaris 2.3.1, in order to see what's behind the story and events. It also gives information about setting up the mod, very basic explanations of the mod code and how to create and import a custom building. All of this is mainly intended for those new to modding and have no idea how to get their (event) mod going.
Features
  • Event creation in Stellaris 2.3.1
  • Full mod files (text files)
  • Short explanations
  • How to create custom building in Photoshop/GIMP and save it
  • File structuring
   
Award
Favorite
Favorited
Unfavorite
Introduction
Hi fellow star explorers,

My name is Atoombom007, and creator of the workshop mod "Lost Future" story and the "Dutch Localization" mod. In this guide I deconstruct my "Lost Future" mod, and try to give you some insight to the work process that led to this mod. My motivation for this is mainly to illustrate how events work in Stellaris version 2.3.1 and give future modders a reference (foundation) to build upon or events resembling this one.

Objectives
These are the following objectives the guide tries to tackle:
  • Creating a Mod - (Uploading, Updating, et cetera)
  • Creating an event (chain)
  • Creating a custom building & icon
Prerequisite
This guide assumes that you have no prior Stellaris modding experience, but does expect you know and/or have access to the following:
  • Able to use a file browsing software (e.g. Windows Explorer)
  • Able to use a text editor (e.g. Microsoft Visual Studio Code is the preferred choice)
  • Access to an drawing program (GIMP, Photoshop, et cetera)

Compatibility
This lesson is created in Stellaris version 2.3.1 and in the Windows 10 environment. It is probable that the way events are coded will change in the future.

Specials Thanks-Awards Go To:
Give credit where credit's due! These people have been invaluable in helping me realize my mod, and without their tips, help and suggestions the mod wouldn't exist and neither would this guide! So, my immense gratitude goes to, in no particular order, to the following fellow star explorers:
  • James Fire
  • Thanatos996
  • Rogue Servitor
  • Dayshine
  • ViolentBeetle
  • Buttjunkie
  • Alberto Da Vinci
  • Persepheus
  • Courageous
  • FtdLulz
  • The Dadinator
  • Caligula

Changelog
Recent changes:
  • 16-06-2019:
    • Added new pictures and new code to better reflect the event progression.
  • 12-06-2019:
    • Completed updating the guide to reflect current game version 2.3.1
  • 08-06-2019:
    • Completed updating the guide to reflect current game version 2.3
  • 04-04-2019:
    • Updated the "Lost Future" mod to 2.2.7. However, no code changes were necessary so the current guide is unchanged.
  • 31-03-2019:
    • Updated the "Lost Future" mod to 2.2.6. However, no code changes were necessary so the current guide is unchanged.
  • 07-03-2019:
    • Updated the "Lost Future" mod to 2.2.5. However, no code changes were necessary so the current guide is unchanged.
  • 08-02-2019:
    • Completed updating the guide to reflect current game version 2.2.4
  • 13-12-2018:
    • Completed updating the guide to reflect current game version 2.2.1
  • 12-12-2018:
    • Started updating the content to reflect the current state of the "Lost Future" mod.
  • 28-11-2018:
    • Changed updating thumbnail notice in the "Mod Update" section
    • Changed mod updating process info in the "Mod Update" section
  • 30-08-2018:
    • First version of the guide uploaded.

If want to contact me, I can be found a the unofficial Stellaris Modding Den or leave a message here!
Unofficial Stellaris Modding Discord Server[discord.gg]
Mod Creation & More
In this section the following subjects will be discussed:
  • Creating a mod
  • Uploading a mod
  • Updating a mod
  • Adding a thumbnail to your mod

Creating a mod
There are two ways to create a mod: 1) we make the necessary files ourselves, 2) we let Stellaris create an mod file for us. In this case, we let Stellaris do the mod file creation.

1. This is the main menu when we select Stellaris from the Steam Library. In this case, it shows the library filled with other existing mods, and the mods already made, "Lost Future" and "Dutch Localization". In the upper right there is the Mod Tools button. Click on it to proceed.
- - - - - - - - - - - - - - - - - - - -
2. Now we see the mod menu, used to Create Mods or Upload Mods. After clicking the Create Mod button, the main screen to the right within the dialog appears.
As the names suggest, Available Mods requires you to give a name to your mod. Make it short and simple (or long and complicated, if your mod requires so).
Directory is important, as this will be the name of the file used for your mod. It is advisable to give your directory the same name as your mod (for example, "Lost Future" becomes "lost_future", "Super Powered Dyson Sphere" becomes "super_powered_dyson_sphere", et cetera).
Supported Version can be left alone. Stellaris will automatically give you the correct version, as this determines for which version of the game the mod is compatible with. But feel free to change this if your mod is only for previous versions of the game. However, do not expect that the mod in question will function correctly in newer game versions.
Mod Tags lets you select what category/categories your mod falls in. It allows others to quickly find your mod. Is it an event? Is it a ship? Is it made for balance, an Empire or more?
3. After pressing the Create Mod button, the dialog will inform you a new mod has been created. You created a "mod"!
- - - - - - - - - - - - - - - - - - - -
4. Where do you find your mods? Usually you find them here:
C:\Users\[username]\Documents\Paradox Interactive\Stellaris\mod
Important: everything you are going to mod, should end up in the file, not the MOD file.
All mods follow the file structure from the game, thus it requires you to do the same! If not, your mod won't work (or worse)!
As you may notice from the picture, the language is different (Dutch for the curious ones), although the same in function. The current directory shows my two personal mods. One of them is an ordinary map, the other a MOD-file. MOD-files can only be opened using a special text editor, in this case, Visual Studio Code (or Notepad++).
- - - - - - - - - - - - - - - - - - - -
5. This is the MOD file for the lost_future mod. It contains essential information, such as its name, version, and tags.
- - - - - - - - - - - - - - - - - - - -
Uploading a mod
Although very premature at this point, you could upload your mod to Steam.
6. After clicking on upload mod, you can select which mods you want to upload. After selecting Lost Future, it will give you a summary of the MOD data. Now you can either fetch or upload the mod.
  • Fetch = looks on Steam Workshop if the mod already exists. If not, it will create a new one.
  • Upload = uploads your mod to the Steam Workshop. Importantly, also updates your mod on Steam after you made modifications.
After clicking Upload, the mod will be uploaded to the Steam Workshop. Head over to the Stellaris Workshop and search for your mod, to see if it's there!
- - - - - - - - - - - - - - - - - - - -
7. Hooray!
- - - - - - - - - - - - - - - - - - - -
Updating your mod
Updating your mod is easy. Should you wish to update your mod on Steam after making post-release changes, first click on "Fetch" and it should say the mod has been found on the Steam Workshop. Then click "Upload" after selecting your mod, and the dialog tells you the mod upload was succesful. Now your mod on the Steam Workshop has been updated as well.

TIP: Should you wish to make different descriptions depending on what languages you speak, this is possible! However, do NOT change the mod name in any case! There will be a mismatch between the name of your mod and the mod found on the Steam Workshop. For example, for those using the English language for Steam would see "Dutch Localization" but also those who are using the Dutch language setting. But the mod's description would be in Dutch!
- - - - - - - - - - - - - - - - - - - -
Adding a thumbnail to your mod
Optional, but it sure looks fancy and recognisable!

Add a picture, self-made or otherwise, to your mod file. Name your picture exactly as your mod name. It's very important that the mod file also "knows" where you picture is, so edit this in the MOD file.
8. See the following line:
picture="lost_future_mod_[number].jpg"
This makes sure the picture is linked to your mod, so when uploading your mod will have a nice thumbnail! Don't forget the quotation marks!
- - - - - - - - - - - - - - - - - - - -
IMPORTANT: Changing the thumbnail is possible after uploading!
In case you made changes to the mod and you made a new thumbnail to reflect the changes (2.2.7--> 2.3.1), this is easily done!
  • Close Stellaris Mod launcher before editing your [name].MOD file!
  • Open .MOD file of your mod located in .../Stellaris/mod/[Mod Name] using Visual Studio Code or likewise.
  • Edit line picture="picturename.jpg" beneath the tags line, to reflect the name of your new image; for example, picture="picturename_2.jpg"
  • Save the modified .MOD file.
  • Place your new image in your mod folder alongside your old image, .../Stellaris/mod/[Mod Name]. Leave the old image within the mod.
    • Nothing happens to the old image when uploading a new mod version but it is good practice to have a back-up if it fails.
  • Double check whether the image name and the name you identified in picture="picturename.jpg" are exactly the same.
  • Close Visual Studio Code.
  • Start Stellaris Launcher
  • Via "Manage Mods" tab, select your mod and click '''Fetch'''
  • You receive a message the mod was found on the Steam Workshop. If not, you probably made a typo within the .MOD file, so check the file again and save!
  • Click on '''Upload Mod'''
  • You receive a message in the lower right of the dialog that the Mod Upload was successful!
  • Check in your Workshop whether the new thumbnail was correctly uploaded.
- - - - - - - - - - - - - - - - - - - -
Events
In this section and the other sections these subjects will be discussed:
  • References
  • Creating an event
  • Examination of "Lost Future" files
  • File structuring

References
When creating your mod, you sure have an idea what your mod is about. To save time, try to find mods that resemble your idea. You get to know how the mod structure would look like and what files are necessary. Also look for the files in Stellaris itself. This way you can find examples how code is built up. All necessary Stellaris files are usually located here:
C:\Program Files (x86)\Steam\steamapps\common\Stellaris
In almost all case, take a look at the common files.
C:\Program Files (x86)\Steam\steamapps\common\Stellaris\common
This file contains a lot of the elements used in the game. Sometimes, each folder contains a readme.txt file, showing all the variables one can use in their mod. Although it goes beyond the scope of this guide to discuss each and every single element.
- - - - - - - - - - - - - - - - - - - - -

Creating an event
Due to changes in 2.0, some changes in how to write events have been introduced. Instead of 4 different files, you only need 2:
  • anomaly_category file = this file contains the category of the event, and contains information about a possible anomaly a research ship will find.
  • anomaly_events file = this file contains the cool stuff, and shows what the anomaly actually was. This usually results in flavor text, options and results, which depend on your choices (or not). This file could also be used to trigger events on their own, without the need of the occurance of an anomaly. These would contain a chain of events, or an event chain.
- - - - - - - - - - - - - - - - - - - - -

File structuring
Before I started I looked for references on how to construct my event, and some existing mods were very helpful to get a look inside the creation process (and file structuring process...) of the event I had in mind. In this case, I need:
  • anomaly category
  • anomaly events
  • special project
  • a building
  • in-game text file
Important:give your files mod-specific prefixes to prevent conflicts with other mods (useful tip by Courageous, ViolentBeetle and FtDLulz). In my case, I gave them the prefix proap_et_cetera.

Furthermore, mods usually work with an special character set, in this case UTF-8 BOM. Almost all files are .txt files, with the exception of the in-game text file, which is saved as an .yml file.
Regardless, in the case of creating events, there are 3 necessary files:
  • proap_anomaly_category.txt = file containing the anomaly category encountered
  • proap_anomaly_events.txt = file containing the events in-game
  • proap_events_l_english.yml = file containing all the text shown in-game

However, because the event makes use of certain external events in order to for other to begin, these other files have to be made as well:
  • on_actions
  • static_modifiers
Deconstruction - Anomaly_category
- - - - - - - - - - - - - - - - - - - - - - -
Examing the "Lost Future" files - 1
The anomaly category file is necessary for making what category our events belong to. Within the anomaly category you could have multiple on_success events, but with different random outcomes based on it's weighting. Let's examine the first file:
proap_anomaly_category.txt
#################################### ### Statue Categories by Atoombom007 ### #################################### #Finding Statue statue_category = { desc = "statue_category_desc" picture = GFX_evt_alien_ruins level = 5 spawn_chance = { base = 0 modifier = { add = 75 is_planet_class = pc_continental } } max_once_global = yes on_success = { 1 = proap.10000 } } }
Now, let's take it apart!
statue_category = { --> statue_category is the category name for the specific anomaly you encounter.
desc = "statue_category_desc" --> "desc =" gives you the text that goes with this anomaly, in the .yml file
picture = GFX_evt_alien_ruins --> "picture =" gives you a nice header picture for your anomaly. You can view them visiting http://tuttu.free.fr/Stellaris/event_pictures/
level = 5 --> The required level for a researcher to investigate it. Higher # translates to a longer investigation time.
spawn_chance = { --> Determines the chance how likely it is this anomaly will appear. Just putting a 1 does not work. Therefore, use the modifier, which changes the probability you will encounter the anomaly. In this case, when the planet is continental, it's 75% more likely the anomaly appears there. base = 0 modifier = { add = 75 is_planet_class = pc_continental <-- different conditions can be put here } }
The base spawn chance is always 0. You can modify the spawn chance by using add or factor, but beware: the base chance = 0, so using factor = 75, results in 0*75 = 0, so the anomaly will never spawn! You can guarantee the existence of your anomaly by using an event, but I have yet to figure out how this works.
max_once_global = yes ---> Determines whether the anomaly occurs just once in the whole game! This is a pretty special event, so I want the anomaly to occur only once. But if you don't come across it yourself... Bad luck!
You could use max_once = yes as well, this means the anomaly category will happen only once for every empire, AI or not.
on_success = { --> Displays the message when the anomaly is succesfully researched 1 = proap.10000 --> "1 =" is the chance you will trigger event proap.10000 (0.1 is 10%, 1.0 is 100%) }
on_fail = { --> Displays the message when investigating the anomaly fails. Absent in this event. The event will always succeed! } }

Deconstruction - Anomaly_events - 1
Examing the "Lost Future" files - 2
Within the anomaly_events file you determine what will happen after you investigated the encountered anomaly. Since this is a long list of code, it's split into multiple sections. Let's examine the second file:
proap_anomaly_events.txt
#################################### ### Statue Events by Atoombom007 ### #################################### namespace = proap # ROOT = ship scope # FROM = planet scope #Creates nearby continental planet nearby starting location of player event = { id = proap.9998 hide_window = yes fire_only_once= yes trigger = { #disable in multiplayers and for gestalts any_country = { is_ai = no } } immediate = { random_country = { limit = { is_ai = no } save_event_target_as = statue_player } random_system = { limit = { distance = { source = event_target:statue_player.capital_scope.solar_system use_bypasses = no min_jumps = 2 max_jumps = 5 } NOR = { any_system_planet = { OR = { is_colony = yes } } has_star_flag = enclave exists = owner } } random_system_planet = { limit = { NOR = { is_asteroid = yes is_colony = yes is_planet_class = pc_gas_giant is_planet_class = pc_nuked is_planet_class = pc_ai } AND = { planet_size > 8 planet_size < 12 } } log = "A suitable planet has been found, but..." clear_deposits = yes change_pc = pc_continental add_deposit = d_city_ruins add_deposit = d_city_ruins add_deposit = d_city_ruins add_deposit = d_city_ruins add_deposit = d_city_ruins add_deposit = d_crater add_deposit = d_crater add_deposit = d_green_hills add_deposit = d_green_hills add_deposit = d_green_hills add_deposit = d_strip_mine add_deposit = d_prosperous_mesa add_deposit = d_rushing_waterfalls add_deposit = d_rushing_waterfalls log = "A planet has been converted in the [this.GetName] system." log = "The players name is [statue_player.GetName]." log = "The capital of the player is [Root.Capital.GetName]." } } } } #Ship surveyes an uncolonized & unsurveyed continental planet which triggers the specific statue_category ship_event = { id = proap.9999 hide_window = yes is_triggered_only = yes fire_only_once = yes trigger = { from = { is_colonizable = yes is_colony = no is_planet_class = pc_continental } root.owner = { is_ai = no } } after = { from = { add_anomaly = statue_category prevent_anomaly = yes } } } ###Statue has been investigated ship_event = { id = proap.10000 title = "proap.10000.name" desc = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } text = proap.10000.desc } desc = { trigger = { owner = { has_authority = auth_machine_intelligence } } text = proap.10000.desc.mach } desc = { trigger = { owner = { has_authority = auth_hive_mind } } text = proap.10000.desc.hive } picture = "GFX_evt_alien_ruins" is_triggered_only = yes # immediate = { # log = "event proap.10000 has fired" # } option = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10000.a owner = { capital_scope = { enable_special_project = { name = "STATUE_RECONSTRUCTION" location = this owner = root.owner } } } } option = { trigger = { owner = { has_authority = auth_machine_intelligence } } name = proap.10000.a.mach owner = { capital_scope = { enable_special_project = { name = "STATUE_RECONSTRUCTION" location = this owner = root.owner } } } } option = { trigger = { owner = { has_authority = auth_hive_mind } } name = proap.10000.a.hive owner = { capital_scope = { enable_special_project = { name = "STATUE_RECONSTRUCTION" location = this owner = root.owner } } } } option = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10000.b custom_tooltip = proap.10000.tooltip hidden_effect = { owner = { add_resource = {influence = 100 } } } } option= { trigger = { owner = { has_authority = auth_machine_intelligence } } name = proap.10000.b.mach custom_tooltip = proap.10000.tooltip hidden_effect = { owner = { add_resource = {influence = 100 } } } } option= { trigger = { owner = { has_authority = auth_hive_mind } } name = proap.10000.b.hive custom_tooltip = proap.10000.tooltip hidden_effect = { owner = { add_resource = {influence = 100 } } } } } #Special Project Completed country_event = { id = proap.10001 title = "proap.10001.name" desc = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } text = proap.10001.desc } desc = { trigger = { owner = { has_authority = auth_machine_intelligence } } text = proap.10001.desc.mach } desc = { trigger = { owner = { has_authority = auth_hive_mind } } text = proap.10001.desc.hive } picture = GFX_evt_alien_ruins is_triggered_only = yes # immediate = { # log = "event proap.10001 has fired" # } option = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10001.a custom_tooltip = proap.10001.tooltip hidden_effect = { set_country_flag = statue_restored } } option = { trigger = { has_authority = auth_machine_intelligence } name = proap.10001.a.mach custom_tooltip = proap.10001.tooltip hidden_effect = { set_country_flag = statue_restored } } option = { trigger = { has_authority = auth_hive_mind } name = proap.10001.a.hive custom_tooltip = proap.10001.tooltip hidden_effect = { set_country_flag = statue_restored } } } #Checking presence of building and fire consequences event (proap.10005) planet_event = { id = proap.10002 hide_window = yes is_triggered_only = yes trigger = { has_building = building_aphroditestatue owner = { has_country_flag = statue_restored NOT = { has_country_flag = proap10002 } } } immediate = { owner = { country_event = { id = proap.10005 days = 180 } set_country_flag = proap10002 } } }
Deconstruction - Anomaly_events - 2
Now let's take it apart!
namespace = proap --> namespace works like the main reference for all events that use it. It's also useful for differentiating your mod from the base game events. Always use a custom namespace for your mod!
# ROOT = ship scope --> ROOT and FROM refer to the event locations, where the code is executed. It also is used for referencing either the planet or ship. As the # is in front of them they aren't used by the game, but is useful for reference. # FROM = planet scope
#Creates nearby continental planet nearby starting location of player event = { --> you can create events that are not tied to a specific scope, however most are id = proap.9998 --> this is the unique ID of this specific event. It is possible to use a mix, like proap.whathappensnow, but I would advise you to use a number instead, and increment it as you code on.
hide_window = yes --> the dialog isn't shown to players as it does not have anything to show fire_only_once= yes --> this event will only fire once trigger = { --> Events will only fire when certain conditions are met. It will be explained in more detail below. #disable in multiplayers and for gestalts any_country = { --> it will cycle through all countries... is_ai = no --> ...and only fire if a player empire is detected } }
immediate = { --> immediate effects are immediate. random_country = { --> cycle through the countries... limit = { --> limit limits the possible outcomes that can be used... is_ai = no --> ... in this case only non-AI countries are selected } save_event_target_as = statue_player --> the outcome of the cycle will have a player-specified event target, and the human player is saved as statue_player }
random_system = { --> it will cycle through random systems limited by... limit = { distance = { --> ...distance! source = event_target:statue_player.capital_scope.solar_system use_bypasses = no --> bypasses are wormholes min_jumps = 2 --> minimal jumps from capital world is 2 max_jumps = 5 --> maximal jumps from capital world is 5 }
A random system will be selected that is no less than 2, yet not farther than 5 jumps away from the home world. Source should be written as source = event_target:[event_target_name], in my case the statue_players' capital world in a solar system.
NOR = { --> same as NOT AND, like NOT A, NOT B & NOT C, et cetera any_system_planet = { --> cycle through any planet of a system... OR = { is_colony = yes --> ...that is a colony... } } has_star_flag = enclave --> ...the system is not occupied by enclave... exists = owner --> ...nor should the system belong to anyone. } }

random_system_planet = { --> cycle through the systems' planets limit = { NOR = { --> negating conditions... is_asteroid = yes --> ... is NOT an asteroid is_colony = yes --> ...is NOT a colony is_planet_class = pc_gas_giant --> ...is NOT a gas giant is_planet_class = pc_nuked --> ...is NOT Tomb world is_planet_class = pc_ai --> ... is NOT AI world } AND = { --> Multiple conditions that have to be fulfilled... planet_size > 8 --> ... size is higher than 8 planet_size < 12 --> ... not lower than 12 } } log = "A suitable planet has been found, but..." --> creates log messages in the game.log clear_deposits = yes --> clears all planet-side deposits change_pc = pc_continental --> changes planet class to continental add_deposit = d_city_ruins --> adds numerous blockers with varying extras add_deposit = d_city_ruins --> ... or deposits that can be used. add_deposit = d_city_ruins add_deposit = d_city_ruins add_deposit = d_city_ruins add_deposit = d_crater add_deposit = d_crater add_deposit = d_green_hills add_deposit = d_green_hills add_deposit = d_green_hills add_deposit = d_strip_mine add_deposit = d_prosperous_mesa add_deposit = d_rushing_waterfalls add_deposit = d_rushing_waterfalls log = "A planet has been converted in the [this.GetName] system." log = "The players name is [statue_player.GetName]." log = "The capital of the player is [Root.Capital.GetName]." --> 3 log entries for easy determination what the target is, and where the converted planet is located. } } } }
The above event will select a nearby planet, based on several conditions and convert it to a continental world and placing several deposits on it, should the player want to colonize it. This specific code is inspired from the Lost Emperor event from the More Events Mod.
ship_event = { id = proap.9999 hide_window = yes is_triggered_only = yes fire_only_once = yes trigger = { from = { is_colonizable = yes is_colony = no is_planet_class = pc_continental } root.owner = { is_ai = no } } after = { from = { add_anomaly = statue_category prevent_anomaly = yes } } }
The above piece of code is essential for my mod. What normally happens is that after you survey a planet with the science ship an anomaly category will spawn that when researched will execute new events. However, the chance of a specific anomaly category is quite random, which poses a problem for me. Because I always want my anomaly to spawn, and not find out 200 years later that the event never fired! So, we need to code an event that makes sure the event always spawns, which is the above one.
ship_event = { --> here we define where the events takes place and the range of its effects. It can also be country_event, capital_event, et cetera
id = proap.9999--> this is the unique ID of this specific event. It is possible to use a mix, like proap.whathappensnow, but I would advise you to use a number instead, and increment it as you code on.
hide_window = yes --> since we execute some code here, I don't want people to actually see a weird empty dialog!
is_triggered_only = yes --> this line means that the event will only take place when activated by another event. A variant is Mean Time To Happen, although it is less reliable (event happens at designated time or not at all)
trigger = { --> Events will only fire when certain conditions are met. It will be explained in more detail below. from = { --> from refers back to the planet itself. This has to do with scoping to targets is_colonizable = yes --> the planet must be colonizable is_colony = no --> planet cannot be a colony is_planet_class = pc_continental --> planet class must be a continental planet } root.owner = { --> root refers back to the ship, and owner refers to the owner of the ship is_ai = no --> the owner of the ship is not AI controlled } }
after = { --> after the conditions are met, the following will happen: from = { --> scoping to from = planet, as planets have anomalies add_anomaly = statue_category --> an anomaly category is added, namely statue_category prevent_anomaly = yes --> this prevents the addition of further anomalies by other events. } } }
Deconstruction - Anomaly_events - 3
Continuation of Anomaly_events
ship_event = { --> here we define where the events takes place and the range of its effects. It can also be country_event, capital_event, et cetera
id = proap.10000 --> this is the unique ID of this specific event. It is possible to use a mix, like proap.whathappensnow, but I would advise you to use a number instead, and increment it as you code on.
title = "proap.10000.name" --> Title refers to the name of the dialog. It references to the proap_events_l_english.yml file. Quotation marks are important!
desc = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } text = proap.10000.desc } desc = { trigger = { owner = { has_authority = auth_machine_intelligence } } text = proap.10000.desc.mach } desc = { trigger = { owner = { has_authority = auth_hive_mind } } text = proap.10000.desc.hive }
The above piece of code gives you three descriptions on what the anomaly actually was, and gives flavour text, based on whether your playing as an Machine Empire, Hive Mind or Organic Empire.
Owner refers back to the owner of the ship. Trigger checks the conditions that needs to be met, in order for the option to show. In this case "if owner of the ship neither has authority machine intelligence or hive mind, then show text description for regular empires". Everything within the Trigger will be evaluated so don't put the text = within it, as text = will be evaluated as well; which obviously is not possible!
picture = "GFX_evt_alien_ruins" --> picture = shows an relevant picture header location = FROM --> location shows where the camera will zoom in on, in this case the planet (=FROM) --> It's not included here though!
is_triggered_only = yes --> using this line means that the event will only take place when activated by another event. A variant is Mean Time To Happen, although it is less reliable (event happens at designated time or not at all)

Deconstruction - Anomaly_events - 4
Continuation of Anomaly_events
picture = "GFX_evt_alien_ruins" --> picture = shows an relevant picture header location = FROM --> location shows where the camera will zoom in on, in this case the planet (=FROM) --> This is currently not used here!
is_triggered_only = yes --> using this line means that the event will only take place when activated by another event. A variant is Mean Time To Happen, although it is less reliable (event happens at designated time or not at all)
option = { trigger = { <-- You only see the following text when you're a regular empire. owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10000.a owner = { capital_scope = { --> trigger this event for your capitol enable_special_project = { name = "STATUE_RECONSTRUCTION" --> enable a special project location = this --> it takes place at the capital owner = root.owner --> who gets the special project? The owner of root (ship's owner!) } } } } option = { trigger = { owner = { has_authority = auth_machine_intelligence } } <-- You only see the following text when you're a machine empire. name = proap.10000.a.mach owner = { capital_scope = { enable_special_project = { name = "STATUE_RECONSTRUCTION" location = this owner = root.owner } } } } option = { trigger = { owner = { has_authority = auth_hive_mind } } <-- You only see the following text when you're a hive mind empire. name = proap.10000.a.hive owner = { capital_scope = { enable_special_project = { name = "STATUE_RECONSTRUCTION" location = this owner = root.owner } } } } option = { trigger = { <-- Same as before! owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10000.b custom_tooltip = proap.10000.tooltip <-- Custom tooltip when hovering over option hidden_effect = { <-- hidden_effect obviously hides the effect what's beneath it owner = { from the tooltip. add_resource = {influence = 100 } } } } option= { trigger = { owner = { has_authority = auth_machine_intelligence } } name = proap.10000.b.mach custom_tooltip = proap.10000.tooltip hidden_effect = { owner = { add_resource = {influence = 100 } } } } option= { trigger = { owner = { has_authority = auth_hive_mind } } name = proap.10000.b.hive custom_tooltip = proap.10000.tooltip hidden_effect = { owner = { add_resource = {influence = 100 } } } } }
The previous line gives you six options or in-game text choices. Players could choose option A and enable a special project or choose B and receive Influence. Also, if you're a machine empire or hive mind the displayed text will change accordingly but the other options for hive minds/machine intelligence/organics won't be displayed, and vice versa. Marvelous!
#Special Project Completed country_event = { <-- This is a country event, because countries complete special projects! id = proap.10001 <-- event id title = "proap.10001.name" <-- Title of dialog desc = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } text = proap.10001.desc } desc = { trigger = { owner = { has_authority = auth_machine_intelligence } } text = proap.10001.desc.mach } desc = { trigger = { owner = { has_authority = auth_hive_mind } } text = proap.10001.desc.hive }
Three descriptions based on the empire of choice.
picture = GFX_evt_alien_ruins <-- The picture header of the event is_triggered_only = yes <-- this event is only fired when activated by another event # immediate = { <-- immediately executes code within block when this event fires # log = "event proap.10001 has fired" <-- log allows you to see whether some events # } have actually fired or not! These can be found in Documents/Stellaris/logs/game.txt option = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10001.a custom_tooltip = proap.10001.tooltip hidden_effect = { <-- the following effect is hidden, does not appear within tooltip set_country_flag = statue_restored <-- here we give a random flag to the country } and will be useful for our later events. This marks our country with an identifier. } option = { trigger = { has_authority = auth_machine_intelligence } name = proap.10001.a.mach <-- different flavour text custom_tooltip = proap.10001.tooltip <-- custom tooltip hidden_effect = { set_country_flag = statue_restored } } option = { trigger = { has_authority = auth_hive_mind } name = proap.10001.a.hive <-- different flavour text custom_tooltip = proap.10001.tooltip hidden_effect = { set_country_flag = statue_restored } } }
Above we completed the special project (SP) and we are given a flag. Flags are useful to be used in Triggers as they allow us to check whether a country/fleet/planet/pop meets our criteria and whether further events can be fired or not.
- - - - - - - - - - - - - - - - - - - - - -
Lost Future - Deconstruction - The Building
Now our country is given a flag when we complete the project and are given permission to build the Aphrodite statue as determined within the proap_buildings.txt file. However, I want there to be 1) consequences after the statue is completed that happen 6 months later, but also 2) immediate consequences upon completion. So, let's first look at the building code.
################################### ### Statue Building by Icohex ### ################################### building_aphroditestatue = { icon = "building_aphroditestatue" base_buildtime = 3650 can_build = yes base_cap_amount = 1 can_demolish = no can_be_disabled = yes can_be_ruined = yes category = unity potential = { planet.owner = { has_country_flag = statue_restored } is_capital = yes } resources = { category = planet_buildings cost = { influence = 500 minerals = 2000 } upkeep = { energy = 5 } produces = { unity = 20 } } country_modifier = { country_unity_produces_mult = 0.5 pop_ethic_pacifist_attraction_mult = 0.6 pop_ethic_egalitarian_attraction_mult = 0.6 }
Deconstruction - Buildings
Continuation of proap _buildings.txt Section
Now, let's break it down!
building_aphroditestatue = { --> define what the name of the building. In this case, building_[name].
icon = "building_aphroditestatue" --> What in-game icon should be displayed? Name your icon file the same as building_[name] if you have a custom icon.
base_buildtime = 2000--> how long does it take for the building to be completed? This is expressed in days, thus it takes 2000 days to complete the building.
can_build = yes --> we should be able to build the building! This is set to no in context of upgrade buildings.
base_cap_amount = 1 --> how many buildings of this type can be built on this planet? Only 1! Removing the line causes the building to be built over and over, like some vanilla buildings.
can_demolish = no --> can we manually demolish this building? No!
can_be_disabled = yes --> we can disable it, to save upkeep costs. However, the bonuses it gives are disabled as well!
can_be_ruined = yes --> this building can be ruined, or more colloquially, completely blown to smithereens!
category = unity --> determines to what category the building belongs to. I don't know whether there also buildings without a category
potential = { --> What restrictions are put on the construction of this building? planet.owner = {--> The planet owner can only build this structure if the country has the flag statue_restored and is a capital! has_country_flag = statue_restored } is_capital = yes }
resources = { <-- this block determines how the costs, resources it produces and upkeep category = planet_buildings <-- it a planet-side building cost = { <-- What does it cost to construct the building? Energy credits? Influence? Minerals? Perhaps even food? influence = 500 --> how much influence does it cost to construct the building? minerals = 2000 --> how much minerals does it cost to construct the building? } upkeep = { <-- what does it cost to keep the building running? Does it require gases, motes, energy, minerals? The specific resources are defined below energy = 5 <-- how much energy does it cost to keep it running? } produces = { --> what does the building produce? Food? Minerals? Unity? unity = 20 --> how much unity does the building generate? } }
country_modifier = { --> On what scope do the modifiers have an effect? Country/Ship/Army? country_unity_produces_mult = 0.5 --> Unity production is increased by 50%! pop_ethic_pacifist_attraction_mult = 0.6 --> Pacificist ethic attraction increase is 75%! pop_ethic_egalitarian_attraction_mult = 0.6 -->Egalitarian ethic attraction increase is 75%! }
ai_weight = { --> this determines what how much priority the AI has to build it weight = 100 --> These numbers can range from 0 to near infinity, although I don't know how it truly works... } }

Modding Thoughts: Ideally there would be a way to show the modifiers in the building depending on what empire you play as. There is something that fills this role, which is the triggered_planet_modifier, but the game does not allow to scope back to country level while being inside planet scope. A solution to this would be the triggered_country_modifier, but this does not yet exist. Below you'd find the working code for this, should it once be implemented.
# triggered_country_modifier = { # potential = { # exists = owner # owner = { # is_gestalt = yes # } # } # modifier = { # country_unity_produces_mult = 0.5 # } # } # triggered_country_modifier = { # potential = { # exists = owner # owner = { # is_regular_empire = yes # } # } # modifier = { # country_unity_produces_mult = 0.5 # pop_ethic_pacifist_attraction_mult = 0.5 # pop_ethic_egalitarian_attraction_mult = 0.5 # } # }
Continuation to Anomaly_events
Now we go back to our conditions, I mentioned earlier. I want there to be 1) consequences after the statue is completed that happen 6 months later, 2) but also immediate consequences upon completion.
#Checking presence of building and fire consequences event (proap.10005) planet_event = { id = proap.10002 hide_window = yes is_triggered_only = yes trigger = { has_building = building_aphroditestatue owner = { has_country_flag = statue_restored NOT = { has_country_flag = proap10002 } } } immediate = { owner = { country_event = { id = proap.10005 days = 180 } set_country_flag = proap10002 } } }
The above code will do the following:
  • What we want to do is that after building the building a timer is going to be run, so exactly 6 months after it's construction the Aftermath event kicks in.
  • It's a planet based event, with a hidden window. So we won't see a dialog when it's trigger conditions are met!
  • Trigger states that the planet needs to have the building_aphroditestatue and the planet's owner should have the flag statue_restored, and it does not have the country flag proap10002.
  • This allows us to trigger the event only when the country has the flag and does not have the associated given flag proap10002. If it meets the conditions, then the country will be immediately flagged with proap10002 and the next event will start.
  • Imagine what happens if the country does not have building_aphroditestatue. The country does not have the building, but it fulfills the requirement of not having the country flag proap10002, but it needs both, so nothing happens.
Let's break it down!
#Checking presence of building and fire consequences event (proap.10005) planet_event = { --> it's a planet event, as planets have buildings! id = proap.10002 --> event id name hide_window = yes --> we don't want to show this checking to the player! is_triggered_only = yes trigger = { --> limit the criteria for it to begin has_building = building_aphroditestatue --> the planet has the building owner = { --> the owner of the planet (the country) needs to have a specific flag has_country_flag = statue_restored --> this specific flag! NOT = { has_country_flag = proap10002 } --> the country can't have this flag! } }
Check the above again to understand what's happening here. It's quite tricky (I think), but very neat.
immediate = { --> immediately after passing the trigger criteria this happens owner = { --> the owner... country_event = { id = proap.10005 days = 180 } --> ... will see the next dialog in 180 days set_country_flag = proap10002 ... and is given an appropriate flag to prevent this event from firing a second time } } }
- - - - - - - - - - - - - - - - - - - - - - - -
Deconstruction - Anomaly_events - 5
Continuation of proap_anomaly_events
Let's continue with the proap_anomaly_events.txt file. The following event will fire as soon as the construction of the Aphrodite statue has been completed. A celebration!
#Construction of Project Aphrodite has been completed planet_event = { --> this is a planet_event, as the building is constructed on... yes, a planet! id = proap.10003 --> the name. Notice the increment in number! title = "proap.10003.name" --> the title linked to the localisation .yml file desc = { --> once more, the descriptions have been linked to your empire authority. trigger = { --> I'm someone who likes personalised texts... owner = { --> ... so I enjoy in creating these very much! NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } text = proap.10003.desc --> it gives the player the event is not a generic wall of text } desc = { trigger = { owner = { has_authority = auth_machine_intelligence } } text = proap.10003.desc.mach --> and gives an incentive to play as another empire } --> to see how other empire would possibly handle and view these events desc = { trigger = { owner = {has_authority = auth_hive_mind} } text = proap.10003.desc.hive } picture = GFX_evt_unity_symbol --> A fitting picture enhances player immersion! show_sound = event_celebration --> Yes, you did it! Sounds can be found in /common/Stellaris/sound/event in my case fires_only_once = yes trigger = { --> The event will only fire if... THIS = { has_building = building_aphroditestatue } --> the planet has the statue! THIS = Planet, because it refers back to it's current level of it's scope } immediate = { --> We need this in order for the notification message to pop up hidden_effect = { owner = { set_country_flag = statue_restored --> Two flags are given set_country_flag = statue_built } } } option = { --> different option for different empires... trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10003.a add_modifier = { --> I want regular empires to immediately get a Static Modifier. modifier = "a_grand_future" --> The name in .yml, it's defnition is in static_modifiers.txt days = 1825 --> how long does the modifier affects the country, expressed in days } } option = { trigger = { owner = { has_authority = auth_machine_intelligence } } name = proap.10003.a.mach --> no immediate empire modifier here... } option = { trigger = { owner = { has_authority = auth_hive_mind } } name = proap.10003.a.hive --> ... nor here! } }
The static modifier refers back to the modifier made in the proap_static_modifiers.txt. These will be defined there, and can vary from empire-wide effects or planet-wide effects. The static modifiers usually affects pops or empires for longer durations and are rewards (or penalties) by undergoing some events.
- - - - - - - - - - - - - - - - - - -
The following event is from the Utopia DLC, and I adapted it to suit my needs. Don't worry, you don't need the DLC to use such an event, it's merely the logic and structure I copied. Regardless, in the Utopia DLC you get notified of a dialog mentioning whether one of your friendly (or rather unfriendly) neighborhood aliens have built a megastructure. I want to know if the AI or somebody else got the statue before I did, so I need a notification event for that! Thus this creates the current event:
# Project Aphrodite Constructed Notification (HIDDEN) planet_event = { --> this is a planet_event, as the planet and the owner of the planet will be marked having the building... id = proap.10004 hide_window = yes --> we don't want to show the player this event! is_triggered_only = yes trigger = { --> checks whether the last changed building is the Aphrodite Statue and whether the owner does not have the flag statue_built last_building_changed = building_aphroditestatue NOT = { owner = { has_country_flag = statue_built } } } immediate = { --> The following will immediately trigger the next event, which is the notification Root.Solar_System = { save_event_target_as = statue_system } --> the "save_event_target_as = whatever" to save current scope under custom name. Any event or other script called after will know it and could refer to it with "event_target:whatever" as long as chain is not broken every_playable_country = { --> we cycle through all the playable empires and limit the following event whether they are AI controlled! limit = { is_ai = no } country_event = { id = proap.10006 } --> the next event is fired for non-AI empires } owner = { set_country_flag = projectaphrodite_completed }--> the planet with the statue gets another flag, to be used in the next event } }
The previous code is hidden and marks the planet and the owner of the planet with a new flag if it has the Aphrodite statue, and subsequently gives non-AI empires a notification the statue has been built. This means that you, the player, would get an event notifying you of its construction.
# Other empire has finished Project Aphrodite country_event = { -->This event is the actual notification, and is scoped to country. id = proap.10006 title = proap.10006.name desc = { text = proap.10006.desc trigger = { root = { has_country_flag = projectaphrodite_completed } owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } } desc = { text = proap.10006.desc.mach trigger = { root = { has_country_flag = projectaphrodite_completed } owner = { has_authority = auth_machine_intelligence } } } desc = { text = proap.10006.desc.hive trigger = { root = { has_country_flag = projectaphrodite_completed } owner = { has_authority = auth_hive_mind } } }
You may notice text = are sometimes above or beneath the trigger block. To be honest I don't know whether it affects performance, but it's safe to assume it first checks the conditions within the trigger, and then evaluates the other lines within the desc = block.
is_triggered_only = yes picture = GFX_evt_satellite_in_orbit show_sound = event_radio_chatter option = { --> different flavour text options for different empires trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10006.a } option = { trigger = { has_authority = auth_machine_intelligence } name = proap.10006.a.mach } option = { trigger = { has_authority = auth_hive_mind } name = proap.10006.a.hive } }
Deconstruction - Anomaly_events - 6
Continuation of proap_anomaly_events.txt - Last part
The last part is what the "long-term" consequences will be after you construct the building. In line with my idea, regular empires will see an division happening within population and the ethics they embrace. The number of Pops that will convert depend on the current number of Pops within your empire. For Hive Minds and Machine Intelligences, the idea of ethic conversion is not possible, so, I've given them production bonuses instead, which roughly equates to give regular empires the initial happiness boost.
#Construction consequences of Statue country_event = { --> ethic changes are tied to countries, so it's a country_event id = proap.10005 title = "proap.10005.name" desc = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } text = proap.10005.desc } desc = { trigger = { owner = { has_authority = auth_machine_intelligence } } text = proap.10005.desc.mach } desc = { trigger = { owner = {has_authority = auth_hive_mind} } text = proap.10005.desc.hive } picture = GFX_evt_galactic_senate is_triggered_only = yes option = { trigger = { owner = { NOR = { has_authority = auth_machine_intelligence has_authority = auth_hive_mind } } } name = proap.10005.a hidden_effect = { --> it's hidden, because I want players to find about it in a subtle way, noticing 1/3 of their pops have changed ethics! This creates some rather dynamic gameplay I think.
The following code creates an if/else_if loop. It goes through the conditions and when they are valid, it executes a code pieces. First you'll start with an if statement, after that you'll use else_if statements. What it does is that it will evaluate first the conditions within the if statement and if they're not satisfied it goes to the next else_if statement, until it has gone through all the statements. While statements allow effects to be applied again, and are usually paired with count = to indicate how often it should iterate through the conditions until it counted to the indicated number.
if= { --> first "if" limit = { --> number of pops within empire has to be under 25 num_pops <=25 } while = { --> if there are less than 25 Pops start the loop count = 10 --> for 10 times random_owned_pop = { --> goes through a random Pop limit = { --> applies changes only when... is_same_species = owner.species --> the owner specie is the same NOT = { has_ethic = "ethic_egalitarian" } --> it does not have the egalitarian ethic NOT = { is_robot_pop = yes} --> is not a robotic pop } pop_change_ethic = "ethic_egalitarian" --> if valid, then change ethic to egalitarian } } } else_if = { --> same story limit = { num_pops >=26 num_pops <=45 } while = { count = 15 random_owned_pop = { limit = { is_same_species = owner.species NOT = { has_ethic = "ethic_egalitarian" } NOT = { is_robot_pop = yes} } pop_change_ethic = "ethic_egalitarian" } } } else_if = { limit = { num_pops >=46 num_pops <=95 } while = { count = 25 random_owned_pop = { limit = { is_same_species = owner.species NOT = { has_ethic = "ethic_egalitarian" } NOT = { is_robot_pop = yes} } pop_change_ethic = "ethic_egalitarian" } } } else_if = { limit = { num_pops >=96 num_pops <=200 } while = { count = 44 random_owned_pop = { limit = { is_same_species = owner.species NOT = { has_ethic = "ethic_egalitarian" } NOT = { is_robot_pop = yes} } pop_change_ethic = "ethic_egalitarian" } } } else_if = { limit = { num_pops >=201 } while = { count = 60 random_owned_pop = { limit = { is_same_species = owner.species NOT = { has_ethic = "ethic_egalitarian" } NOT = { is_robot_pop = yes} } pop_change_ethic = "ethic_egalitarian" } } } } } option = { trigger = { has_authority = auth_machine_intelligence } name = proap.10005.a.mach add_modifier = { modifier = "enhanced_production_transmission" days = 1825 } } option = { trigger = { has_authority = auth_hive_mind } name = proap.10005.a.hive add_modifier = { modifier = "enhanced_production_link" days = 1825 } } }
This is the end of the proap_anomaly_events file. Next I discuss the localisation.
Deconstruction - Localisation
Examing the "Lost Future" files - Localisation
This file is where all your in-game shown text should be written. Without it, all the dialogs you see will be empty! It is useful to define headers to see when the text is used. The file settings should be set to an .yml with UTF8-BOM encoding as well.
Let's examine the file:
proap_events_l_english.yml
l_english: --> this line is always required! ############################################ ### Statue Anomaly & More by Atoombom007 ### ############################################ # ROOT = ship scope -->these are... relevant, but I am unsure how much. It's best to put them in regardless. # FROM = planet scope ################### # Category Text # ################### statue_category:0 "Lost Future" --> the 0's and 1's do not indicate anything relevant to gameplay. statue_category_desc:0 "TEXT" --> Adding them won't do anything, although I've added them anyway. ####################### # Anomaly Discovered # ####################### proap.10000.name:0 "Ruined Statue Reconstruction" --> Title of dialog proap.10000.desc:0 "TEXT" --> Description for regular empire proap.10000.desc.mach:0 "TEXT" --> Description for machine intelligence proap.10000.desc.hive:0 "TEXT" --> Description for hive mind proap.10000.a:1 "TEXT" proap.10000.a.mach:1 "TEXT" proap.10000.a.hive:1 "TEXT" proap.10000.b:1 "TEXT" proap.10000.b.mach:1 "TEXT" proap.10000.b.hive:1 "TEXT" proap.10000.tooltip:0 "TEXT" ####################### # Project Completed # ####################### STATUE_RECONSTRUCTION:0 "Reconstruction of the Statue" STATUE_RECONSTRUCTION_DESC:0 "TEXT" proap.10001.name:0 "Project Aphrodite" proap.10001.desc:0 "TEXT" proap.10001.desc.mach:0 "TEXT" proap.10001.desc.hive:0 "TEXT" proap.10001.a:0 "TEXT" proap.10001.a.mach:1 "TEXT" proap.10001.a.hive:1 "TEXT" proap.10001.tooltip:0 "Gives access to the Empire-unique §S£building $building_aphroditestatue$ Building§!." --> the symbols will be explained below! #################################### # Statue Construction Completed # #################################### proap.10003.name:0 "A Bright New Future" proap.10003.desc:0 "TEXT" proap.10003.desc.mach:0 "TEXT" proap.10003.desc.hive:0 "TEXT" proap.10003.a:1 "TEXT" proap.10003.a.mach:1 "TEXT" proap.10003.a.hive:1 "TEXT" #################################### # Statue Construction Consequences # #################################### proap.10005.name:0 "Construction Consequences" proap.10005.desc:0 "TEXT" proap.10005.desc.mach:0 "TEXT" proap.10005.desc.hive:0 "TEXT" proap.10005.a:1 "TEXT" proap.10005.a.mach:1 "TEXT" proap.10005.a.hive:1 "TEXT" ########################################### # Other Empire Completed Project Aphrodite # ############################################ proap.10006.name:0 "Future, Lost" proap.10006.desc:0 "TEXT" proap.10006.desc.mach:0 "TEXT" proap.10006.desc.hive:0 "TEXT" proap.10006.a:1 "TEXT" proap.10006.a.mach:1 "TEXT" proap.10006.a.hive:1 "TEXT" ####################### # Building Text # ####################### building_aphroditestatue:0 "Aphrodite Statue" --> building text building_aphroditestatue_desc:0 "TEXT" --> building description ###################### # Modifiers Text # ###################### enhanced_production_transmission:0 "Enhanced Production Transmission" enhanced_production_transmission_desc:0 "TEXT" enhanced_production_link:0 "Enhanced Mind Link" enhanced_production_link_desc:0 "TEXT" grand_future:0 "TEXT" grand_future_desc:0 "TEXT"
Above are all lines belonging to the anomaly_events and category_events and static_modifiers. Also notice the following line: "Gives access to the Empire-unique §S£building $building_aphroditestatue$ Building§!". I'll explain something about using colored text, special symbols and how to use them.
- - - - - - - - - - - - - -
The color scheme in Stellaris:
Code
Color
B
Blue
E
Teal
G
Green
H
Orange
L
Brown
M
Purple
P
Light red
R
Red
S
Dark orange
T
Light grey
Y
Yellow
!
Default

Each of these can be used within the .yml files, and are marked by using the § sign (Alt+21) followed by the capital letter, a closing § and an !. Like this:
"Our §YCapital World§! is ours once more!"
- - - - - - - - - - - - - -
The £ symbol is used for the names of various system stats, including energy, minerals, influence, and the three research categories (engineering, physics and society). These pieces of code are replaced by small icons.
- - - - - - - - - - - - - -
The $ symbol is used to delimit strings defined elsewhere to be expanded in the current string, or system statistics in GUI elements. Thus:
"Gives access to the Empire-unique §S£building $building_aphroditestatue$ Building§!"
becomes
"Gives access to the Empire-unique [building icon] Aphrodite Statue Building§!"
- - - - - - - - - - - - - -
Deconstruction - special_projects, static_modifiers & on_actions
SP's, Static Modifiers & On_Actions
Now, I will discuss the special project, the static modifiers and the on_actions.

Special Projects
Special Projects are so special, they need to be investigated from the Situation Log. They mostly require research points from whatever category you see fit. Although it is possible to write multiple categories within it, I would advise against it as it might have unintended side-effects.
Let's go to the file!
############################################ ### Statue Special Project by Icohex ### ############################################ special_project = { key = "STATUE_RECONSTRUCTION" cost = 2000 days_to_research = 0 tech_department = engineering_technology picture = GFX_evt_alien_ruins location = no timelimit = 1035 event_scope = planet_event requirements = { } on_success = { owner = { country_event = { id = proap.10001 } } } on_fail = { } }
Now let's take it apart!
special_project = { --> it's a special project... Duh. key = "STATUE_RECONSTRUCTION" --> key refers to its unique name and in-game it's name is shown in the Situation Log. It does not have to be in capitals, but it's common practice. cost = 2000 --> the cost of your research days_to_research = 0 --> how long SP has to be researched, the alternative to cost tech_department = engineering_technology --> specific technology department picture = GFX_evt_alien_ruins --> a picture header shown in Situation Log location = no --> tied to specific location, in this case no, but it scopes back to country timelimit = 1035 --> how many days does the player have until the SP is lost/gone/destroyed? event_scope = planet_event --> the SP is done on planet_event requirements = { --> maybe you want to impose requirements, usually in relation to the science officer aboard a science vessel } on_success = { --> what happens if you succeed? owner = { --> the owner of the project, in this case, the country/empire country_event = { id = proap.10001 } --> a new event is launched! } } on_fail = { --> what happens if the project fails? Used in combination with ship investigations. } }
- - - - - - - - - - - - - - - - - - - - - - - -
Static Modifiers
Static modifiers are modifiers that are given random or through events to planets or empire. Usually there are pre-set icons for some of the modifiers, even though the name we give to the static_modifier can be very diverse. Let's take a look at the file!
proap_static_modifiers.txt
################################### # Empire Modifiers by Atoombom007 # ################################### enhanced_production_transmission = { --> the name of the transmission. Tip: don't use capitals! country_energy_produces_mult = 0.05 --> the various modifiers you can apply are astounding! You can apply them for Ships, Upkeep costs, Pop categories, and many more! country_minerals_produces_mult = 0.05 --> ... and in 2.2.4, there are nearly 12.000 modifiers! } enhanced_production_link = { --> two static modifiers for two empires country_energy_produces_mult = 0.05 --> increase of country energy production of 5% country_minerals_produces_mult = 0.05 --> increase of country mineral production of 5% } grand_future = { --> the static modifier for the regular empires pop_happiness = 0.10 --> general pop happiness increase of 10% }
Next is the proap_on_actions.txt file. On_actions are special as it contains events that happen within the game and certain events at a regular interval or when something happens. In our case, we have 3 events that rely on the completion of a building, irrespective what building has been completed. The event will only fire if the criteria within the event have been met, but it will check these events every time a building has been completed.
proap_on_actions.txt
#A building construction has been completed. # This = Planet # From = Tile on_building_complete = { --> when the events are being checked. events = { proap.10002 --> Checking presence of building and fire event proap.10005 proap.10003 --> Construction of Project Aphrodite has been completed proap.10004 --> Project Aphrodite Constructed Notification (HIDDEN) } }
# A ship has surveyed a planet. # Scope = Ship # From = Planet on_survey = { --> when the events are being checked. events = { proap.9999 --> is ship AI controlled or not, and start proap event chain } }
If would scroll back up and go to proap.9999 you see the line fire_only_once = yes, which means that that event only fires once. I might be wrong, but what happens is that when you find a planet that meets the conditions within the event, this event will be skipped, therefore decreasing memory load, which is a good thing!
Of course, other on_actions can be used as well, and these can be found in the vanilla game files.
Icon & Custom Building Creation
Icon & Custom Building Creation
In this section the following subjects will be discussed:
  • Setting up
  • Creating a custom building
  • Saving the custom building as DDS
  • Placing your DDS file in the correct folder
  • File structuring

Setting up
As we have now created our game files, it is time to create the building! In order to do that there are some things we need to have and know:
  • We need an drawing program, like GIMP, Photoshop ( I assume you know how they work)
  • My building icon is going to be 100x100 pixels at 72-200 dpi (dpi determines how finely detailed your picture will be).
    • IMPORTANT: as the icon is just 100x100 pixels, the surface is too tiny to properly draw anything! Therefore, I suggest you use a file at least 500x500 pixels, draw the building and save it as another file and edit its file size to 100x100 pixels later. I have to mention that no-one is very clear how large the icon size should be, therefore I made an estimation. In my case, 100x100 pixels was adequate.
  • The building icon needs to be saved as a DDS file
    • As I am not familiar with the specifics of DDS files, I cannot provide any useful technical information about it. However, the important thing is that Stellaris uses DDS files for it's ingame images, textures and more. I hope Paradox has an elegant explanation for using DDS files though...
  • You need GIMP and a GIMP DDS plug-in for creation of the DDS file.
Now, let's go to the drawing board!
- - - - - - - - - - - - - - - - - - - - - - -
Creating a custom building
Okay, there are some things that need to be mentioned. Depending on whether you use Photoshop or GIMP, you need to take some extra steps. I use Photoshop, but I assume GIMP has the same options.
  • Photoshop
    • Create a new file, name it "building_[name]" (no quotation marks), size is 500x500 pixels, dpi = 200
    • Draw your building and save your end result building as a building_[name].psd file. Don't forget to save often to prevent image loss!
      • IMPORTANT: You will make the image smaller in size, so a lot of details disappear!
      • IMPORTANT: Make sure the background is transparant!
    • If you're done, let's resize it! Click "Save as" and add "copy" to it's name ("building_aphroditestatue" becomes "building_aphroditestatuecopy"). This way you always have the original in case you're not satisfied. Now you have the original and copy windows opened. Close the original file window. With the copy opened, click "Picture--> Picture Size". Change the 500x500 pixels to 100x100 pixels and click "OK". The file size has now been changed!
      Add up all layers to one layer and save it as a PNG file, quality = 10.
  • GIMP
    • Repeat as for Photoshop.

This is an screenshot from my own custom building. Notice that the background is transparant!
- - - - - - - - - - - - - - - - - - - - - - -
Saving the custom building as DDS
Now comes the "tricky" part. As Stellaris uses DDS files, we have use GIMP! To my knowledge Photoshop does not have the option to create DDS files, thus we use GIMP.
  • Download GIMP
  • To download the GIMP DDS plug-in go to https://code.google.com/archive/p/gimp-dds/downloads. Select proper ZIP-file corresponding to your Windows systems (32-bit or 64-bit) and download it. Then unpack it in the following directory:
    C:\Program Files\GIMP 2\lib\gimp\2.0\plug-ins
  • Don't open the dds.exe file, it won't do anything.
  • If put in the proper plug-in file, it should be installed correctly now!
  • Open GIMP!
  • If you created your building in Photoshop, load the file you made in Photoshop into GIMP (There shouldn't be any problems loading the image). If you made the picture in GIMP, load the file in GIMP.
  • To save your file as a DDS, go to "File"-->"Export/Export As..." and open the submenu "Other extensions". Among the options there should now be the DDS image. Select it and click on export!
  • Your building has been turned into a DDS file and placed in location you specified. Congratulations!
- - - - - - - - - - - - - - - - - - - - - - -
Placing the DDS file in the correct folder
You now have the DDS file, but where to put it? Since we created a building it has to go into the buildings folder! Take a look:
C:\Users\[username]\Documents\Paradox Interactive\Stellaris\mod\[modname]\gfx\interface\icons\buildings
Since I declared the name of the building in the proap_buildings.txt file as building_aphroditestatue, the DDS file should have exactly the same name.
- - - - - - - - - - - - - - - - - - - - - - -
File structuring
Now all mod elements are in place. So, how does the mod file hierarchy look like?
If you want to create something else than an event, be sure to follow the file path just like in the Stellaris directory.
Conclusion
Conclusion
Now you know exactly know how to:
  • Create a Mod - (Uploading, Updating, et cetera)
  • Create an event
  • Create a custom building & icon and save it
The big question... How does it look in-game? Let's see!
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1. We encounter the anomaly!
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2. We gain a special project!
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4. The special project in the Situation Log.
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3. We complete the special project!
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4. We can build the building on our planet!
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5.After construction is complete, a celebratory event is triggered!
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6. Showing the statue on our capital world.
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7. Constructing the statue has long term consequences.
- - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Click here to go to the official "Lost Future" mod page!

Mission accomplished!
- - - - - - - - - - - - - - -
Epilogue
Epilogue
The most important thing to me is that new modders know how to create custom icons and events. Personally, the icon and event creation were important subjects to me, as both are not explained very well on the Stellaris wiki (the information is just plainly outdated). All in all, this guide has shown:
  • How to create events in Stellaris 2.3.1
  • How to create custom icons
I hope to have explained everything as clear as possible, and wish you luck with creating your own (event) mods!

Note I: As I am not a experienced modder, some things may not have been properly explained or insufficiently adressed. See Note III.
Note II: Visiting the official Paradox Stellaris Forum is the best way to get answers to your modding questions.
Note III: For additional official references go to the official Stellaris wikia[stellaris.paradoxwikis.com].
Note IV: Additional help can be found in the unofficial Discord channel for Stellaris. Problems I encountered during modding were solved by the help of people over there. Click the tag to discover the channel: Stellaris Modding Den[discord.gg].
3 Comments
Atoombom007  [author] Oct 7, 2018 @ 4:21am 
@kiwusek: Checked out the mod, and after installing it, it works as intended! I'll update the guide in the future to reflect your suggestion, along some other changes.
Atoombom007  [author] Sep 11, 2018 @ 4:15am 
@kiwusek: Thanks for the comment! :)
I'll check it out ASAP. It'll definitely save me some steps for creating those DDS files.
luna Sep 10, 2018 @ 1:14pm 
Hey awesome guide pretty clear and the more people that mod the better :)

Just wanted to mention that there seems to be dds options for Photoshop (see: https://www.nexusmods.com/skyrim/mods/76482/)

It seems that NVIDIA has stopped supporting their installer for the newest version of Photoshop and it's not a program I have used in a long time so I don't know how the landscape over there looks nowadays.