Kingdoms

Kingdoms are managed through the population service, population call handler, and population_faction.lua. To add our new playable kingdom we can take a look at the rayyas_children and northern_alliance mods.

The steps for adding monster populations are similar, check this other page.

  1. Create the population files.

    We can copy an existing population JSON file, they're usually inside stonehearth/services/server/population/data (for Rayya's Children and Northern Alliance mods, they're inside their data folder). Let's check the properties that we can find in these files:

    • "type": "kingdom" -- this file represents a kingdom / population.

    • "display_name" -- localized display name to show in the UI.

    • "kingdom_id" -- an identifier for the kingdom. Try to keep it unique, and only use lowercase and underscores by convention.

    • "favored_biome" -- URI of the favored biome. Normally favored biomes provide with enough resources for the base crafter job of your custom kingdom. When players choose to play with this kingdom in a non-favored biome, a warning will appear in the UI.

      icon The warning will only appear if we chose a vanilla kingdom that's not favored. For modded biomes it won't appear. Nevertheless, a "(favored)" text will appear next to the biome name, so that players know that in that biome they'll have all the resources for this kingdom's jobs.

    • "quote" -- unused legacy field.

    • "description" -- localized description that will appear in the list of playable kingdoms in the UI.

    • "post_selection_description" -- a localized description that will appear in the text at the left side of the screen after we select our kingdom. You may need to start it with a space.

    • "image" -- path to the image for the list of kingdoms. Usually 400x300 pixels.

    • "story_board_image" -- path to the image that will appear at the right side of the screen after we select our kingdom in the first embarkation screen. Normally depicts a couple citizens of our kingdom, with a transparent background (which is filled by the chosen biome).

    • "starting_talisman" -- URI of the first talisman that your kingdom will get. Once you place the banner, this talisman will be automatically created together with other items from the chosen loadout. Normally a talisman for a crafting job, so that the citizens can craft other talismans and unlock more jobs progressively.

    • "starting_resource" -- URI of the starting resource. After placing the banner, two items of this resource will be created together with the above. Normally a resource so that the initial crafter can craft a basic workbench and get the town started.

    • "job_index" -- URI of the job index for our custom kingdom. Take a look at how to create jobs to create your own custom jobs. You can also reuse the stonehearth ones if you want to.

      iconWe can add a "base_job" field to the jobs index to specify a different base job than "stonehearth:jobs:worker". You should only have one base job since the vanilla game doesn't support more than one. Normally it's a job that doesn't require a talisman, in case the player can't craft it for whatever reason. Take a look at how the Worker job is set up.

    • "inventory_capacity_equation" -- an equation to calculate how should the inventory capacity increase over time. For the vanilla game it's based on the number of hearthlings : "math.max(num_citizens * 150, 1200)".

    • "initial_town_name" -- a localized name that will be assigned to the town by default (the game will append a random number to it too). In the vanilla game, the first encounter of the town progression campaign allows the player to set a custom name for their town and to choose a bonus.

    • "camp_standard" -- URI of the camp standard that will appear when we place the banner for our town. In the vanilla game, the first encounter of the town progression campaign changes this banner to look different and grant a bonus.

    • "camp_hearth" -- optional field. We can specify a custom URI so that the firepit that appears after we place the banner is different. Mind that there are encounters in the vanilla campaigns that make use of the default firepit URI, so you may want to create your own campaigns for town progression instead.

    • "trappable_animals" -- URI of an index of trappable animals. Used for the "stonehearth:jobs:trapper" job, in the trapping service.

    • "default_material" -- a string containing material tags for the default building material. For example, for rayyas_children, when we open the builder in the UI, they will have the clay material selected by default.

    • "ordinal" -- an ordinal to order the kingdom in the list of playable kingdoms.

    • "roles": {} -- here's where we define how do the citizens of our new kingdom look like.

      For playable kingdoms, we have only one role, called "default". Inside it we normally have these entries:

      • "male" -- here we define the entities that will represent a male citizen of our population. There's a "uri" array containing the URIs of the entities (e.g. the male hearthlings), and a "given_names" array containing names for the male citizens to choose at random.

      • "female" -- same keys than for male, but pointing to the female citizen entities and female names.

        For hearthlings, the male/female entities basically inherit the base_human.json mixin, which contains all the common components and entity_data that they have, and then define their animation table (rig), and some model variants and customizations, to use in the roster screen.

      • "surnames" : [] -- an array containing surnames that will be chosen randomly for your citizens.

      • "attribute_distribution" -- here we can change the distribution of attribute points for the initial citizens (new citizens will have completely random stats).

        • "allocated_points" -- the "min" and "max" number of attribute points. Your citizens will have a random amount of points between "min" and "max" allocated for their stats (for example, with a minimum of 5 points it's not possible to get citizens with 1 mind / 1 body / 1 spirit during embarkation).

        • "point_limits" -- here we can modify the "min" and "max" amount of points for each of the stats ("mind", "body", "spirit"). These stats are attributes added in the base_human.json mixin, so if you're gonna reuse them (since the UI is prepared for that) make sure that your citizens have them defined in their attributes component too.

          Examples from the vanilla kingdoms would be the Ascendancy population, which starts with a minimum "spirit" of 2, Rayya's Children starts with a minimum "mind" of 2, and Northern Alliance starts with a minimum "body" of 2. But remember that new citizens will have completely random attributes.

    • "pet_names" : {} -- this section contains arrays for pet names. Each array corresponds to an "id" defined in the "stonehearth:species" section of the entity_data of the pets. There's also a "default" array for default names in case the game can't find an appropiate key.

    • "town_pieces" : {} -- these are pieces to compose the random town names that we can get when naming the town:

      • "optional_prefix" -- sometimes the town name will have a prefix from this array.
      • "town_name" -- an array of town names for your kingdom.
      • "suffix" -- an array of suffixes for your town name. Like the prefixes, not always will be used.
    • "task_groups": "stonehearth:data:player_task_groups" -- here we're assigning the task groups that are used for playable kingdoms. More on that in the advanced sections of the guide.

  2. Add an alias for the population file to the manifest.

    "aliases" : {
       "kingdoms:custom_kingdom" : "file(data/custom_kingdom.json)"
    }
    
  3. Add a mixinto to the playable kingdoms index.

    "mixintos" : {
       "stonehearth:playable_kingdom_index": "file(data/playable_kingdom_index.json)"
    }
    

    Our mixinto file will look like this:

    {
       "kingdoms": {
          "my_kingdom_id" : "my_mod:kingdoms:custom_kingdom"
       }
    }
    

    We use the "kingdom_id" as the key here, pointing to the alias of our population file.

  4. Make sure you have all the files you need.

    Now the kingdom should be playable. But we might want to set up additional things:

    • Custom campaigns -- by default we'll get all the campaigns that are not gated by kingdom, depending on the game difficulty that we choose. We should make a custom town progression campaign for our kingdom, or remove any campaign that we don't want using mixintos or mixintypes.

    • Custom music -- by default we'll get the music from the Ascendancy kingdom. If we want to customize the music that will play for our kingdom, we need to mixinto the sound constants:

      "mixintos" : {
         "stonehearth:data:sound_constants": "file(data/sound_constants.json)"
      }
      

      Our mixinto will look like this (shortened example):

      {
         "music": {
            "kingdoms": {
               "my_mod:kingdoms:custom_kingdom": {
                  "tier_to_day_music_track": {
                     "idle_day_music_tier_1": {
                        "track"  : [
                           "stonehearth:music:lvlmusic_ray_spring_1_day"
                        ],
                        "loop"   : false,
                        "fade_in": 2000,
                        "volume" : 40
                     },
                     "idle_day_music_tier_2": {
                        "track"  : [
                           "stonehearth:music:lvlmusic_ray_winter_2_day"
                        ],
                        "loop"   : false,
                        "fade_in": 2000,
                        "volume" : 40
                     },
                     "idle_day_music_tier_3": {
                        "track"  : [
                           "stonehearth:music:lvlmusic_ray_winter_3_day"
                        ],
                        "loop"   : false,
                        "fade_in": 2000,
                        "volume" : 40
                     }
                  },
                  "tier_to_night_music_track": {
                     "idle_night_music_tier_1": {
                        "track"  : [
                           "stonehearth:music:lvlmusic_ray_summer_2_night"
                        ],
                        "loop"   : false,
                        "fade_in": 2000,
                        "volume" : 40
                     },
                     "idle_night_music_tier_2": {
                        "track"  : [
                           "stonehearth:music:lvlmusic_ray_winter_2_night"
                        ],
                        "loop"   : false,
                        "fade_in": 2000,
                        "volume" : 40
                     },
                     "idle_night_music_tier_3": {
                        "track"  : [
                           "stonehearth:music:lvlmusic_ray_winter_3_night"
                        ],
                        "loop"   : false,
                        "fade_in": 2000,
                        "volume" : 40
                     }
                  }
               }
            }
         }
      }
      

      We've used existing tracks from the rayyas_children kingdom to show the difference (the files are in the stonehearth mod, that's why the aliases begin by stonehearth).

      Inside "kingdoms" we add a key with the URI of our kingdom. Then there are different sections for day and night music, and inside them, different groups depending on the town tier. We can add several tracks of music (the vanilla ones are in .ogg format, to save space), and one of them will be chosen randomly depending on the time of day and the current town tier.

      Each group also has a "loop" property, normally set to false, a "fade_in" in milliseconds, and a "volume" (from 0 to 100) in case we need to tune the volume because the music file has it too quiet/loud compared with other music/sounds in the game.

    • Custom UI -- we can optionally have different colors and images in the UI, like Rayya's Children and Northern Alliance do, by applying a deferred mod manifest after our kingdom is chosen. This will be covered in the hotloading manifests section.

  5. Finally, we can test our new kingdom. It's a lot of work to add a new kingdom but we can start by copying an existing one and after everything is renamed, go little by little adjusting all the jobs, campaigns, etc.