Last updated: December 10th, 2018. Latest version here.

Seasons and weather


Seasons are defined in the main JSON file of the biomes. A small example of how to setup seasons:

  "seasons": {
     "spring": {
        "display_name": "i18n(stonehearth:data.biome.temperate.seasons.spring.display_name)",
        "description": "i18n(stonehearth:data.biome.temperate.seasons.spring.description)",
        "start_day": 0,
        "weather": [
              "uri": "stonehearth:weather:sunny",
              "weight": 10
     "summer": {
        "display_name": "i18n(stonehearth:data.biome.temperate.seasons.summer.display_name)",
        "description": "i18n(stonehearth:data.biome.temperate.seasons.summer.description)",
        "start_day": 21,
        "weather": [
              "uri": "stonehearth:weather:thunderstorm",
              "weight": 4
     "autumn": {
        "display_name": "i18n(stonehearth:data.biome.temperate.seasons.autumn.display_name)",
        "description": "i18n(stonehearth:data.biome.temperate.seasons.autumn.description)",
        "start_day": 42,
        "weather": [
              "uri": "stonehearth:weather:windy",
              "weight": 6
     "winter": {
        "display_name": "i18n(stonehearth:data.biome.temperate.seasons.winter.display_name)",
        "description": "i18n(stonehearth:data.biome.temperate.seasons.winter.description)",
        "start_day": 63,
        "weather": [
              "uri": "stonehearth:weather:snow",
              "weight": 6

We'll use custom keys as identifiers for the seasons (for example, "spring" / "summer" / "autumn" / "winter"). We can have an arbitrary number of seasons, but we'll need to make sure that they fit within the year.

You can check the length of the different time intervals in stonehearth/data/calendar/calendar_constants.json. By default they're setup like the real-world time, except for days (we have only 7 days per month). It is not advisable to change the calendar constants, since they might affect other mods and there can be code that depends on them. The names of the months can be found in the calendar constants too, if you want to change them.

Inside each season identifier, we have some properties:

  • "display_name" -- the localized name for the season that will be displayed in the UI (in the map embarkation screen, in the crops list -since crops have preferred seasons- and when we hover over the month name below the sun widget).

  • "description" -- the localized description for the season. It will appear when we hover over the season name in the map embark screen and in the month name under the sun widget.

  • "start_day" -- this determines the duration of the season. Internally, we start on day 0, so for the example above, spring's start day is 0 and summer's start day is 21, so the duration of spring is 3 in-game months (remember, 7 days per month).

    We manually express this duration in the description of the season, but the tooltip for the month name under the sun widget also has a counter telling when the season ends, since we don't start the game exactly at day 1 of the first month, but rather at the start of the chosen season, which happens in the middle of the first week of the corresponding month (for spring would be the first month, for summer the fourth, etc).

    We can make seasons last a different amount of months. For example, in the arctic biome winter lasts for 7 months, while spring and autumn last for 1 month and summer lasts for 3 months.

  • "weather" : [] -- an array of objects containing a weather URI and its weight. This way we can define different weather for each season and make some weather types more frequent than other ones. For how to create your own weather, see below.


For creating a custom weather type we'll need to create several files. Existing weather can be found in stonehearth/data/weather, so we can copy one from there, rename it and edit the files.

First let's add the alias to our manifest so that we don't forget about it and we can use it in our custom biomes or add it to existing biomes from the stonehearth mod:

  "aliases" : {
     "weather:sprinkles_rain" : "file(data/weather/sprinkles_rain/sprinkles_rain.json)"

The sprinkles_rain.json file would have the following properties:

  • "display_name" -- the localized name for the weather, which will be shown in the tooltip when we hover over the weather forecast under the sun widget.

  • "description" -- the localized description that will be shown in the weather's tooltip. Here we can include the bonuses or disadvantages that the weather has. We can inline HTML tags in the text of the tooltip for better formatting.

  • "icon" -- path to the icon for our weather that will be shown in the forecast.

  • "sky_settings" -- URI of the sky settings file. See below.

  • "thoughts": [] -- array of thoughts for this weather. A random thought from this list will be added to every hearthling whenever the weather is active. If we include a thought more than once in the array we'll be changing its probability (there'll be more chances for it to be chosen).

    These URIs are not aliases, but rather a string composed of keys from the thoughts index. See here for more information.

  • "ambient_sound_key" -- this points to an identifier (for example, "rain") that will be used in the sound service to play ambient sound when this weather is active. You can reuse an existing identifier from stonehearth/data/sounds/sound_constants.json or inject a custom one there via a mixinto.

  • "camera_attached_effect" -- URI of the effect to attach to the camera. It is an optional field. We normally use them for rain, snow, etc. These effects use cubemitters whose emitter has a CUBOID surface, so that it can cover all the camera view.

  • "subject_matter" -- URI of the subject matter for this weather (for example, "candyland:subjects:weather:sprinkles_rain"). For weather subjects we normally use 2D icons similar to those for the forecast, and save them inside the same folder than the other weather files. The subject matter file (sprinkles_rain_subject.json) would contain something like this:

       "type": "entity",
       "components": {
       "entity_data": {
          "stonehearth:thought_bubble_icon":  {
             "image":  "file(sprinkles_rain_subject.png)"

    The subject will be added to the list of conversation subjects of hearthlings when the weather is active.

  • "plant_growth_time_multiplier" -- optional field. It's a multiplier for the growth rate of plants. If we include it, plant growth will be affected when this weather is active, so we can make plants and crops grow faster or slower.

  • "vision_multiplier" -- optional field. A multiplier for the vision radius, usually a decimal number (from 0 to 1). Depending on your graphic settings this might vary or not have effect, but this field is used to make your settlement be less visible when you zoom out from it. A good example would be the foggy weather with the fallback renderer disabled. When zooming out from your settlement, you'll see it get a bit obscured under a fog, and when you zoom in, you'll be able to see it sharp.

  • "hide_cloud_shadows" -- optional boolean to hide the clouds shadows that appear on the ground, for cloudy days, clear skies, etc.

  • "snow_accumulation_per_minute" -- optional field. A really small value between 0 and 1 (it's per in-game minutes). It will make the top of the horizontal surfaces be covered by a flat layer of snow, which gets more opaque over time. Surfaces below other surfaces won't get snow on them. If this value is negative, it will remove the snow layer slowly, if there's snow from a previous day. The color of the snow is controlled in a shader, check the SNOW_COVER entry in stonehearth/data/horde/materials/fullscreen_quad_material.json. Check also stonehearth/services/client/weather_render/weather_render_service.lua for how we render the weather effects.

  • "is_dark_during_daytime" -- optional field, false by default. When true, hearthlings will keep the fire pit lit during the day (normally we use it for bad weather like rain, snow, etc).

  • "unsheltered_debuff", "unsheltered_animal_debuff" and "unsheltered_resistance_buff" -- optional fields that point to URIS of buffs. When we define them, our hearthlings will get the "unsheltered_debuff" applied and our pasture animals will get the "unsheltered_animal_debuff" applied when this weather is active. If our hearthlings or animals have the buff defined for "unsheltered_resistance_buff" (for example, by equipping some winter clothes), then they won't get the unsheltered debuffs.

  • "controller" -- optional field. It's the URI of a Lua script (remember to add it to the "controllers" section in your manifest!) that will be run when this weather is active. Some examples would be "stonehearth:weather_scripts:foggy", which spawns undead when the foggy weather is active, and "stonehearth:weather_scripts:thunderstorm", which makes thunderbolts appear randomly and hurt hearthlings and trees.

  • "renderer" -- optional field. It's the URI of a Lua script (it must be declared in the "client_controllers" section of your manifest!). Examples would be "stonehearth:weather_renderers:titanstorm" and "stonehearth:weather_renderers:windy". We can access client services from them and render things on the client side (like the gusts of wind effects, which aren't attached to the camera).

Sky settings

The sky is rendered via stonehearth/services/client/sky_renderer/sky_renderer_service.lua. The sky_settings.json file referenced in the weather's JSON file contains data regarding the sky for the weather.

It has these fields:

  • "sky_gradient" -- path to an image file (usually a 256x256 pixels PNG). From left to right, it represents in-game time (starting at midnight), and from top to bottom it represents top to bottom of the sky.

    You can reuse existing gradients (they are inside subfolders of stonehearth/data/texture_gradient/skybox) or create your own ones. The length of each gradient depends on what do you want the sky to look like at each time of day, perhaps you want more slower transitions or shorter ones.

    These are the percentages across the sky gradient where these time events occur:

    midnight           0
    sunrise_start      10
    sunrise_peak_start 20
    sunrise_peak_mid   25
    sunrise_peak_end   30
    sunrise_end        40
    midday             50
    sunset_start       60
    sunset_peak_start  70
    sunset_peak_mid    75
    sunset_peak_end    80
    sunset_end         90
    day_length        100
  • celestials": [] -- an array containing parameters for the celestials. Normally it contains 2 entries, one for the sun and another one for the moon, with the following properties:

    • "name" -- an identifier for the celestial (e.g. "sun").

    • "shadows_enabled" -- a boolean to enable/disable shadows for this celestial object (normally set to true).

    • "light_colors" : [] -- an array containing maps of "time" (which points to an identifier for the time of day), and "value" (an array containing an RGB color in decimal format).

      If the light color is [0,0,0] the light will get disabled (e.g. we disable the sun during nighttime and the moon during daylight). The times of day used here are defined in the sky_renderer service, but you can just copy an existing sky_settings file to get them.

    • "ambient_colors" -- similar to the light colors, also useful for the low quality renderer.

    • "angles" -- angles on x, y, z for the directional lights. Only the most important light can cast shadows.

    • "depth_offset_values" -- depth offsets for the light.

  • "params" -- parameters for the fog.

    • "height_fog" -- at each time of day, which fog height (in world space), fog thickness factor, fog noise factor and fog distance factor there should be.
    • "height_fog2" -- at each time of day, which fog noise scale on X, fog noise scale on Z and fog noise speed there should be.
    • "height_fog_color_mult" -- the color for the fog at each time of day.
    • "scattering" -- at each time of day, the hue shift, saturation factor, value factor, and sun brightness for the scattering of the light that there should be.
  • "colors" -- more parameters.

    • "starfield_brightness" -- the colors for the stars. Usually we set them to [0,0,0] during the day time so that they are disabled.

We can test the sky gradient using the Time Slider debug tool.