Skip to content

Beginner Tutorials

MagicJinn edited this page Dec 30, 2024 · 10 revisions

Welcome, delicious friends! This page is designed to be a comprehensive guide for those new to modding Sunless Sea, particularly using SDLS. It covers all aspects of modding currently supported by SDLS, and provides detailed instructions on getting started, editing existing content, creating new stories, and more! This guide is intended to be read in a linear manner, without very distinct chapters. For more segmented tutorials, refer to General Tutorials, and for detailed information about each component, see the Reference.

A basic understanding of coding concepts, particularly how JSON and JavaScript organize and store values, is recommended. While Sunless Sea is written in C#, many of the concepts still apply. A short introduction to JSON can be found here: What is JSON?

A few terms you should know:

  • Component: A type of JSON object used by the game, for example events and qualities, but also nested objects like Enhancements are components. Represented by {}.
  • Property: A field or entry in a JSON component/object. Formatted as "property key": value.

This guide can only take you so far on your modding journey. If you're stuck or want to see how things work in practice, take a look at the JSON files in %localappdata%low/Failbetter Games/Sunless Sea. Checking out how the basegame's JSON files work is a great way to learn by example. To find examples more suited to SDLS, you can download any mod that has a SDLS version.

Initial setup and tools, and editing existing content

While you may be eager to add new content to the game, knowing how to understand and edit existing content is a crucial tool in a Sunless Sea modder's toolkit. Part of this is understanding JSON structure, as mentioned in the introduction, but knowing how the game's content itself is structured is also extremely important. When adding new content to the game, you need to ensure it integrates smoothly with the existing content to make it accessible.

To get you started, you're gonna need a text editor. While you can technically make due with Windows' Notepad, this is not recommended at all. It's able to open, edit and save JSON files, but formatting and organisation are also essential to having a sustainable workflow.

Below are a few options for text editors/IDE's. This is not an exhaustive list, meaning there are many more options out there that might be superior, or suit your needs better.

Editor Features & Reasons To Use
Notepad++ The gold standard of general text file editing, offering very good performance and limited plugin support. A good option if you need to work on extremely big files, as actions like CTRL + H are significantly faster than in other IDE's. Lacks built in auto-formatting, which is a highly recommended feature.
Visual Studio Code The cooler Visual Studio! Great UI, built-in JSON formatter, and an amazing extension ecosystem. A standout feature, Breadcrumbs, helps keep things organized during JSON editing.
VSCodium For Microsoft haters. Raw source code for Visual Studio Code, without the Microsoft additions. All the great features of VSCode, but you might run into problems installing certain extensions.
Cursor Visual Studio Code fork with AI integration. Good for people who want to use AI to improve their workflow.

When editing existing content, it's essential to understand how the game loads data from JSON files. Due to limitations in Sunless Sea and SDLS 1.5.0 (current), a general rule applies: to modify existing content, including nested content, you must replace the content entirely.

Lets start with an example. You've made a mod that adds a new item, a Jar of Insanity, and you're sure the Alarming Scholar would take an interest, so you want to add it to the assortment of items she (he?) buys. Here are the steps you would follow.

  1. Navigate to and open %localappdata%low/Failbetter Games/Sunless Sea/entities/events.json
  2. Locate the event you want to add a ChildBranches component to (The Alarming Scholar). CTRL + F can help with this.
  3. Find the base of this event. VSCode Breadcrumbs can help with this. Copy the entirety of it (From the opening { to the closing }).
  4. Create a file in Failbetter Games/Sunless Sea/addons/YOUR_MOD_NAME/entities called eventsSDLS.json or events.sdls (SDLS.json is recommended while editing to help your IDE recognize the language, .sdls is recommended when distributing your mod).
  5. In your file, create an array, and paste the event inside: [your event].
  6. Add the new ChildBranch component to ChildBranches.

If done correctly, your version of the event has overwritten the old event. Be aware that the new copied event should contain all original ChildBranches, not just yours! For qualities, shops, etc, the process should be extremely similar.

We are now ready to create our first mod. For this, you will nagivate to C:\Users\USERNAME\AppData\LocalLow\Failbetter Games\Sunless Sea, which can also be written as %localappdata%low\Failbetter Games\Sunless Sea, which we will refer to as the PersistentDataPath. Inside this folder, you will find several subfolders. The folders named constants, encyclopedia, entities, geography, and images are of particular interest to modders; however, they contain the base game's content files and should not be modified directly. Instead, we will go into the folder called addon and create a folder here, with the name of your mod. Inside this folder, we can structure our mod. The game will attempt to load the folders mentioned earlier from this location, as well as the main folder, with the notable exception of images, which are only loaded from the base folder. What follows is a list of all JSON files the game tries to load on startup:

  • entities/qualities
  • entities/areas
  • entities/events
  • entities/exchanges
  • entities/personas
  • geography/TileRules
  • geography/Tiles
  • geography/TileSets
  • encyclopaedia/CombatAttacks
  • encyclopaedia/CombatItems
  • encyclopaedia/SpawnedEntities
  • encyclopaedia/Associations
  • encyclopaedia/Tutorials
  • encyclopaedia/Flavours
  • constants/combatconstants
  • constants/navigationconstants

Creating a quality

To create a quality, we will need to know where qualities live. Detailed information on where certain components live can be found in the Reference. Qualities live in qualities.json, in the entities folder. We must therefor create a folder called entities in our mod folder, and a file named qualities.json, but because we are using SDLS, we name the file qualitiesSDLS.json. Make sure to enable file extensions in windows. You can create a JSON file by right-clicking in the entities folder, selecting New > Text Document, naming it qualities.json, and confirming the name in the popup.

To get started, open the file in your preferred text editor and create an array []. All components must be inside an array (with the exception of constants), even if your mod only has a single component in the file. Inside this array, create a component [{}]. You can now start to give your quality properties, like a name and other important characteristics. For demonstration purposes, we'll be making a kitchen-sink sort of quality. Please keep in mind that regular qualities in the game are almost always much simpler than this.

Every quality needs a few important properties. Let's give it a name "Name": "Jar Of Insanity", Nature "Nature": "Thing", Category "Category": "Curiosity" and Id "Id": 5005021. These properties are the most important because they dictate how the quality will fundamentally be used and displayed. The Id is the most important property of any quality, because it is how other components refer to it. I recommend you keep track of the names and Ids of your qualities and events in a different document. This will make it much easier to reference them later. When choosing an Id, take into account Id Availability, and also to make it as unique as possible, to avoid the admittedly rare but cumbersome problem of duplicate Ids in multiple mods. I use the following scheme for Ids:

  • 5005: Personal signature that I use in all my mods
  • 02: Number of the mod. Legacy Yacht is 00, Sacks As A Mascot is 01, etc.
  • 1: Arbitrary number for this quality

Which results in an Id of 5005021.

We now have our quality, but it's a bit bland and minimal. We can give it a little more flavour by adding more properties. We will add a description "Description": "A jar of murky yellow liquid, almost indistinguisable from honey." and an image "Image": "honey". Both of these properties are self-explanatory and more info about them can be found in the reference.

[{
    "Name": "Jar Of Insanity",
    "Description": "A jar of murky yellow liquid, almost indistinguisable from honey.",
    "Image": "honey",
    "Nature": "Thing",
    "Category": "Curiosity",
    "Id": 5005021
}]

Now lets add some functionality to our quality. In most cases, the functionality of a quality is determined by the events that use it. For example, Admiralty's Favour doesn't do anything on its own, but it gets you access to new events and resources. There are a few ways a quality can have inherent functionality, and we'll cover these first before moving on to making events. The first way is by making the quality equippable. This is done by giving it an AssignToSlot property. There is a hardcoded list of slots qualities can be equipped to: ship equipment and officer roles. We'll now make the quality equippable to the Aft slot by setting AssignToSlot to its associated Id "AssignToSlot": {"Id": 102965}. Even though our quality is equippable, it still does not do anything. To make it useful, we can give it enhancements. A simple enhancement will look something like in The Monstrous Almanac, which simply increases a quality, pages, by 7. An example of a more complex enhancement is The Avid Supressor. It gives you an arbitrary quality, which is then used in an event. More on this later. To give a quality an enhancement, it will need an Id and a level, which can be positive or negative.

"Enhancements": [{
        "AssociatedQuality": {
            "Id": 102898
        },
        "Level": -3
    }]

Inkeeping with the theme of the quality, equipping it will reduce your pages (although there is an argument to be made it should increase Terror instead, which is possible, but comes with unintended consequences, because it is a capped quality).

Giving a quality an enhancement is only one of two ways to give it inherit functionality. The second is UseEvent. If a quality has a UseEvent property, right-clicking it will allow you to trigger the event specified. Examples include Officers, some combat items, and Strategic Information. Giving a quality a UseEvent looks like this:

"UseEvent": {
    "Id": 141886
},

For testing purposes, we set the Jar Of Insanity to open the Alarming Scholar event. After our changes, our quality should look like this:

[{
    "Name": "Jar Of Insanity",
    "Description": "A jar of murky yellow liquid, almost indistinguisable from honey.",
    "Image": "honey",
    "Nature": "Thing",
    "Category": "Curiosity",
    "Enhancements": [{
        "AssociatedQuality": {
            "Id": 102898
        },
        "Level": -3
    }],
    "AssignToSlot": {
        "Id": 102965
    },
    "UseEvent": {
        "Id": 141886
    },
    "Id": 5005021
}]

Now if we test ingame, left clicking the quality will show a new "Use" option, which will activate the event we specified. If you plan to make it consumable, you can create an event that consumes the quality. To make an item act like a consumable in combat, you can reference it in CombatItems.json, but you will be limited to the ExoticEffects the game provides, and CombatItems are beyond the scope of this tutorial.

This concludes the basics of creating qualities. The rest can be inferred by using common reasoning (for example, journal entries cannot have Enhancements, etc) and looking at the Reference. There are many small adjustments you can make to refine the look, feel, and functionality of your qualities, so be sure to explore what each property offers.

Creating an event

Now it is time to learn how to create an event. Events live in events.json, in the entities folder, so we will create a file called eventsSDLS.json next to our qualities file. We again start our file with [], and create an event component within [{}]. Just like qualities, there are a couple of properties (almost) all events should have. Lets give our event a name "Name": TODO, description "Description": TODO, and an Id "Id": 5005022.

Clone this wiki locally