Guide to adding new content to CDDA for first time modders

How do I give you one million hearts?


I would like to second AskaHope on this.

I volunteer as tribute. @Mlangsdorf if you message me once you have everything you want posted, I would be willing to compile it into a single document.

If you want to express your appreciation, use these documents to add new, interesting content to the game. I’m putting recipes and items first because they’re easy to define and describe, but I would so much rather see more missions and quests and NPC dialogue than another gun or piece of armor.


I surely will! I’ve been trying to mess with JSONs for quite a while, but this will help a lot!

Just wanted to say I appreciate what you’re doing here. So much of what I learned about modding Cata was trial and lots of error. The old modding docs are helpful but also out of date.


Adding a new map locations

Map locations can be added to the game in JSON. I’m not a maps guy, so I’m mostly going to point people to the docs and offer some advice. Also, lots of people figure out how to add new locations so it may not be too difficult.

A map location is defined across multiple files.

  • The basic map, including monsters, NPCs, vehicles, traps, and items, is defined in a file in data/json/mapgen/ . data/json/mapgen/fire_station.json is the fire station, for instance, and it’s a good reference because it’s a moderately complicated, single tile design that only has one variant so you can look at the JSON and compare it to the game and make sense of it.
  • Maps can have their palettes defined in the mapgen/ JSON file, or in a separate file that is customarily stored in data/json/mapgen_palettes/
  • One or more maps can be collected into an overmap special, defined in data/json/overmap/specials.json. The JSON objects in this file control how a map spawns, where it is relation to a city, etc.
  • data/json/overmap_connections.json and data/json/overmap_terrain.json also deal with mapgen, but frankly I don’t understand how and you should not mess with them absent better information.

The main document for mapgen is It’s a little confusing at places, but you can basically ignore the sections on LUA and focus on the JSON sections.

More on data/json/specials.json

  • "sym" represents the symbol used. You can look at other mapgen entries to match up ‘correct’ symbols.
  • "color" is the color.
  • "see_cost" determines how far away you can spot the location, though I’m not 100% on how it works. I think you have a maximum number of tile-equivalents you can see, and a tile with a higher “see_cost” counts as more tile-equivalents.
  • "mon_density" affects the density of creatures you place in your mapgen entry.
  • "flags" are special tags that have particular effects. For example, I believe the flag “SIDEWALK” will attempt to attach your location to a sidewalk. So if you’re making a house or readily accessible building, you want that flag.
  • Important Note! There is an "occurrences" field in each object in specials.json, which is a list of two numbers like this [ 0, 4 ]. The first number is the minimum number of times your special will appear on an overmap, and the correct value for that number is always 0. Not 1, not 2, not 4, it should be 0. I know your overmap special is extra special and you want to see it on every map, but nevertheless, the minimum number of occurrences is 0.
    The second number is the maximum number of occurrences, which can be any number greater than 0.

Also, I’m going to take this moment to admit that I am not much of a JSON developer, so if other people have additional ideas, comments, or suggestions, please correct my mistakes and bad advice.


Well, regarding overmap_terrain – as far as I’m aware (though I’m also not terribly experienced), this file mainly determines how your new location will look on the map.

IE: name determines what is displayed when that maptile is selected.
“sym” represents the symbol used. You can look at other mapgen entries to match up ‘correct’ symbols.
“color” is the color.
I believe “see_cost” determines how far away you can spot the location, though I’m not 100% on how it works.
“mon_density” affects the density of creatures you place in your mapgen entry.
“flags” are special tags that have particular effects. For example, I believe the flag “SIDEWALK” will attempt to attach your location to a sidewalk. So if you’re making a house or readily accessible building, you want that flag.

These flags can do wonky things depending on how you set up your mapgen entry and will probably require some trial and error.

I believe the “NO_ROTATE” flag will always spawn your mapgen oriented in the way you design it in your entry.

I can’t be super-specific, but this information would have been helpful to know when I started out, so, there it is. I read a lot of this somewhere but I don’t know where. x_x


Adding more NPC dialogue

NPC dialogue is partially implemented in JSON and partially implemented in C++ code. Most of the dialogue to command an NPC companion such as faction camp missions or setting combat priorities is still hardcoded. But almost all general dialogue, including assigning missions to the player, can be done through JSON.

NPC dialogue is stored in data/json/npcs/ , specifically the TALK_*.json files and talk_tags.json. The dialogue system is extensively documented in, but it’s one of the things I maintain so I’ll talk about it a little more.

Dialogue consists of talk_topics, where each talk_topic has a "dynamic_line" that the NPC says, and then a "responses" list of things that the player can say in response. This is the talk_topic object for the Old Guard Rep at the evacuee center:

    "id": "TALK_OLD_GUARD_REP",
    "type": "talk_topic",
    "dynamic_line": { "u_has_any_trait": [ "PROF_FED" ], "yes": "Marshal...", "no": "Citizen..." },
    "responses": [
      { "text": "Who are you?", "topic": "TALK_OLD_GUARD_REP_NEW" },
      { "text": "Heard anything about the outside world?", "topic": "TALK_OLD_GUARD_REP_WORLD" },
      { "text": "Is there any way I can join the 'Old Guard'?", "topic": "TALK_OLD_GUARD_REP_ASK_JOIN" },
      { "text": "Does the Old Guard need anything?", "topic": "TALK_MISSION_LIST" },
      { "text": "Well, bye.", "topic": "TALK_DONE" }
    "//": "TODO: The rep should know whether you're actually a sworn officer: Wearing the badge without the trait => Bad idea"

Dynamic Lines

Dynamic lines can be strings, lists, or objects, and any string can be replaced by a list or objected repeatedly. So that dynamic line could be expanded to provide a lot more variety like this:

"dynamic_line": {
  "u_has_any_trait": [ "PROF_FED" ], 
  "yes": [
    "Marshal, it's good to see you."
    "What can I do for you, Marshal?"
  "no": {
    "u_is_wearing": "badge_marshal",
      "yes": [
        "Where did you get that badge?",
        "Why are you pretending to be a US Marshal?",
        "Explain yourself!  You're no <swear> Marshal, but you're wearing the badge!"
      "no": [
        "Can I help you?",
        "Is there something you need?",
          "u_male": [
            "You look capable, I may have some work for you."
          "u_female": [ 
            "Hello miss, the US government is an equal opportunity employer."


"<greet>" and "<swear" are examples of snippets. Snippets are stored in data/json/npcs/talk_tags.json, and are lists of strings. When the dialogue system gets ready to display text that includes a snippet, it randomly selects a snippet from the list and inserts it in the text. So that "<greet>" would reference the greet snippet:

  "type" : "snippet",
  "category" : "<greet>",
  "text" : [
    "Hey <name_g>.",
    "Greetings <name_g>.",
    "Hi <name_g><punc> You okay?",
    "<name_g><punc>  Let's talk.",
    "Well hey there.",
    "<name_g><punc>  Hello.",
    "What's up, <name_g>?",
    "You okay, <name_g>?",
    "Hello, <name_g>.",
    "Hi <name_g>"

and the Old Guard Rep would have 12 new lines that he would randomly say to you.
Snippets can also reference other snippets, such as the references to which is a snippet for punctuation or to <name_g> which are various friendly references.

Existing talk_topics don’t take nearly as much advantage of snippets as they could, and a good learning project for someone who wanted to get started contributing would be to add a bunch of snippet references and new snippets to the existing dialogue.


Responses are the options for things that the player can say in response to the NPC. There is a whole system for deciding which responses to display, and then having various changes to the game get triggered when the player chooses them. It’s all documented in, linked above.

Also, the "text" section of a response is a bit of dialogue, and can use snippets just like dynamic lines do. Player responses could also use more snippets.

A friendly offer

The existing filters for dynamic lines and responses were the ones necessary to get the game’s existing dialogue out of the C++ hardcode into JSON. They are by no means all the filters that you might want for some piece of dialogue you’re working on. Similarly for response effects.

If you are working on NPC dialogue for vanilla game, or for a mod that is included in the game’s CleverRaven repo at github, and find you need a filter or effect that doesn’t exist, please PM me here or on reddit or on the CDDA Discord or open a github issue and I’ll try to add it in a reasonably timely manner.


New missions can mostly be added in JSONs, but it’s another large topic.


Adding more NPC dialogue part 2: New NPCs

In addition to normal dialogue, NPCs have mission dialogue and class information. I’m going to start with the class information first.

NPC classes and templates

NPC classes are defined in data/json/npcs/classes.json. The JSON object looks like this:

    "type": "npc_class",
    "id": "NC_JUNK_SHOPKEEP",
    "name": "Shopkeep",
    "job_description": "I'm a local shopkeeper.",
    "common": false,
    "bonus_per": { "one_in": 4 },
    "shopkeeper_item_group": "NC_JUNK_SHOPKEEP_misc",
    "skills": [
        "skill": "ALL",
        "level": { "mul": [ { "one_in": 3 }, { "sum": [ { "dice": [ 2, 2 ] }, { "constant": -2 }, { "one_in": 4 } ] } ] }
      { "skill": "speech", "bonus": { "rng": [ 1, 5 ] } },
      { "skill": "barter", "bonus": { "rng": [ 2, 4 ] } }
    "traits": [ [ "FLEET2", 100 ] ]

Relevant bits:

  • "type" has to “npc_class”
  • "id" can be anything, but custom is to start with NC_
  • "name" can also be anything.
  • "job_description" is what the NPCs answers with if you asking what he’s doing.
  • "bonus_per",“bonus_str”,“bonus_dex”, and“bonus_int`” are any increases to the NPC’s Perception, Strength, Dexterity, or Intelligence. These bonuses can be negative to reduce the value. I’ll describe the format later.
  • "skills" is a list of bonuses to skills, with the skill ids taken from data/json/skills.json
  • "traits" is a list of possible traits. Each possible trait has a trait’s "id" from data/json/mutations.json and a value from 0 to 100 that is the percent chance that trait will appear, so this shopkeeper will always have FLEET2.

skill and stat bonus and level format

  • "rng": [ X, Y ] means a randomly determined number between X and Y
  • { "one_in": X } means 1 on a randomly determined chance that occurs 1 time in X attempts and 0 otherwise.
  • { "dice": [ X, Y ] } means a randomly determined number generated by summing X randomly determined numbers with values from 1 to Y
  • { "sum": [ X, Y, Z ] } means the sum of X, Y, and Z, where X, Y, and Z can be any of the previous or a mul (below) value.
  • { "mul": [ X, Y ] } means X * Y. X and Y can be one of the previous expressions.

So 1 in 4 shopkeepers will have Perception 9 and the rest will have Perception 8. For each skill, each shopkeeper has a 1 in 3 chance of of having a random skill value between 0 and 2 with 50% of them being 1, and 1 in 4 of those skills will actually be between 1 and 3.

NPC Equipment

Each NPC class can have equipment lists associated with it. These are stored in the data/json/NC_*.json file corresponding to the NPC’s class name (though this structure might change shortly). Inside each equipment list file are a bunch of item_groups, as described in the item creation guide above.

NPC Templates

NPC classes aren’t super interesting. NPC templates are more important. They’re the data structures that determine what missions an NPC can provide and what talk_topic the NPC starts talking about. NPC templates are also what you specify in a location’s mapgen to actually spawn an NPC.

Templates are stored in data/json/npcs/npcs.json, and look like this:

  "type" : "npc",
  "id" : "evac_merchant",
  "//" : "Appears in the refugee center as shopkeeper with missions.  Faction critical.",
  "name_suffix" : "Merchant",
  "class" : "NC_EVAC_SHOPKEEP",
  "attitude" : 0,
  "mission" : 3,
  "chat" : "TALK_EVAC_MERCHANT",
  "mission_offered" : "MISSION_FREE_MERCHANTS_EVAC_1",
  "faction" : "free_merchants"

Relevant bits:

  • "type" must be “npc”
  • "id" can be anything, but it’s the template’s ID for mapgen spawn functions
  • "name_suffix" is a string appended to the NPC’s randomly generated name.
  • "class" must be a valid NPC class "id", as described above.
  • "attitude" must be one of these numbers, with the corresponding attitude
    • 0 = null, NPC can do their own thing
    • 1 = talk, NPC will attempt to approach the player and talk to them
    • 3 = follow, NPC is a friend of the player and can be commanded
    • 7 = defend, NPC stays where they are at defends themselves
    • 10 = kill, NPC attempts to kill the player
    • 11 = flee, NPC flees from the player
  • "mission" must be one of these numbers, with corresponding behavior
    • 0 = null, NPC can do their own thing
    • 3 = shopkeep, NPC stays in one place but will attempt to trade with the player
    • 7 = guard, NPC stays exactly where it is
  • "chat" is the first talk_topic that the NPC will use when the player talks to them - after that, they’ll use the talk_topic based on the player’s response.
  • "mission_offered" is the first mission the NPC will offer if the player asks about missions. I’ll talk about that more in the mission guide below.
  • "faction" is the faction "id" from data/json/npcs/factions.json. Factions are mostly nonsense, but they determine how the NPC reacts to the player initially, and some factions will attack the player on sight.

How to a completely new NPC

  1. Optionally, create an NPC class in data/json/npcs/classes.json, and create the item groups for the class’ gear in data/json/npcs/NC_CLASSNAME.json
  2. Optionally, create the NPC template in data/json/npcs/npcs.json. Assign it the new class or an existing class. If you want the NPC to talk to the player and not run off, give it "attitude": 0 and "mission": 7.
  3. Optionally, create a sequence of talk_topics for the NPC’s dialogue, and assign the first talk topic to the NPC template’s chat.
  4. Optionally, create a mission quest chain, and assign the first mission to the NPC template’s mission_offered.
  5. Really optionally, add a new faction to data/json/npcs/factions.npc and assign the new faction to the NPC template’s faction.
  6. Put the NPC on some overmap terrain definition using "place_npcs" and specifying the template in the "class" entry.

Adding more NPC dialogue part 3: New Missions

NPCs can give the player missions. Mission structure is fairly complicated and some parts of it aren’t in JSON yet, but you can add simple fetch quests and monster kill quests in JSON.

Mission data is stored in data/json/npcs/missiondef.json. There’s some documentation at but I’m going to expand on it. Each mission looks like this:

    "id": "MISSION_RANCH_NURSE_9",
    "type": "mission_definition",
    "name": "Find Advanced Emergency Care",
    "goal": "MGOAL_FIND_ITEM",
    "difficulty": 5,
    "value": 50000,
    "item": "emergency_book",
    "start": "ranch_nurse_8",
    "origins": [ "ORIGIN_SECONDARY" ],
    "followup": "MISSION_RANCH_NURSE_10",
    "dialogue": {
      "describe": "We need help...",
      "offer": "Have you heard of a book called the 'Guide to Advanced Emergency Care?'  I really need a copy.  The doctor is requesting a lot of supplies that I'm not familiar with but I believe I could make if I could get a copy of the book.",
      "accepted": "I'm counting on you.",
      "rejected": "Come back when you get a chance, we need skilled survivors.",
      "advice": "Libraries are the only place I'd think to look.",
      "inquire": "Do you have the Guide to Advanced Emergency Care?",
      "success": "Thank you for your assistance.",
      "success_lie": "What good does this do us?",
      "failure": "It was a lost cause anyways..."

Relevant bits:

  • "id" is the internal mission ID
  • "type" must be “mission_definition”
  • "name" is the sentence displayed when you look up your missions, so make it as clear as possible
  • "value" is the cash value of the mission, in cents. So a mission worth $500 in goods on completion has a value of 50000
  • "goal" is a special string. Currently, JSON only missions can only really take “MGOAL_FIND_ITEM”, “MGOAL_KILL_MONSTER_TYPE”, and “MGOAL_KILL_MONSTER_SPEC”.
    • MGOAL_FIND ITEM means the player must find any copy of an item and bring it back.
    • MGOAL_KILL_MONSTER_TYPE means the player must kill a number of a specific type of monster, like shocker brutes.
    • MGOAL_KILL_MONSTER_SPEC means the player must kill a number of a specific monster species, like MUTANTS
  • "item" is the "id" of the item to retrieve, from data/json/items/
  • "count" is an optional number that is number of items to retrieve. if it is absent, only 1 item is needed.
  • "monster_species" is the monster "species" to kill for MGOAL_KILL_MONSTER_SPEC. You can find a list of species in data/json/species.json.
  • "monster_type" is the monster "id" for MGOAL_KILL_MONSTER_TYPE, from data/json/monsters.json and data/json/monsters/
  • "monster_kill_goal" is the number of monsters to kill
  • "start" can either be
    • an optional reference to a hardcoded, C++ function that sets up the mission at its start. “start” is optional, and existing start functions often don’t have anything to do with the mission - for instance, almost all the Tacoma Commune/Refugee Ranch start functions involve building up the ranch, and the mission is still valid even if they didn’t run.
    • an object containing information on a target overmap special and target terrain. See the doc for details.
  • "end" is an optional reference to a hardcoded, C++ function that concludes the mission. See above.
  • "origins" is a list of types of NPCs that can generate the mission.
    • “ORIGIN_SECONDARY” means that it comes from the "followup" of another mission.
    • “ORIGIN_OPENER_NPC” means that the starting NPC can have this mission
    • “ORIGIN_ANY_NPC” means that any random NPC can have this mission
  • "followup" is a mission "id" that the NPC will offer after the player completes this mission successfully.
  • "dialogue" is an object, with each value being a dynamic line that the NPC says in response to the player asking about the mission. These are normal dynamic lines, as described above, and can use dynamic line filters and snippets
    • "describe" is what the NPC says to indicate they have a mission
    • "offer" is what the NPC says to further describe the mission, specify what the player needs to do, and indicate how the NPC will reward the player
    • "advice" is what the NPC will say if the player asks for advice on the quest
    • the other values have fairly self-explanatory names

Any NPC that has missions needs to either have their "chat" talk_topic added to the first talk_topic in data/json/npcs/TALK_COMMON_MISSION.json, or have a responses entry like this:

      { "text": "Can I do anything for you?", "topic": "TALK_MISSION_LIST" },

Reaching the TALK_MISSION_LIST talk_topic will cause CDDA to display the data/json/missiondef.json data for the NPC’s current missions. It’s not necessary for you do anything other than make sure that your missions have valid "dialogue" objects.


Adding New Monsters

You can add new monsters in JSON. I’ve never really done it, so I’m mostly going to point you to the documentation at but I’ll throw in a few more notes.

Monster JSON is stored in data/json/monsters/ and data/json/monsters.json.
Monster special attacks are stored in data/json/monsterattacks.json, but a lot of monster special attacks are hardcoded in C++ so I believe that file is really sparse.

Monsters have two sets of item_groups associated with them. First are data/json/monsterdrops/ and data/json/monster_drops.json, which contain the items that monsters such as zombies drop when they die, and are standard item groups defined by data/json/harvest.json contains information on what you get when you butcher a creature. This file is under very active development right at this moment, and I really have no idea how it works and as far as I know it’s not documented yet. You can look through it and try to figure it out.

monsters also have a monstergroups JSON object, which controls what monsters spawn where in a random function. This is partially documented in doc/, so I refer you back to that.

Finally, monsters have factions, which are defined in data/json/monster_factions.json. These objects are described in


Adding new effects

Effects are things like sickness, poison, or drug effects. They’re also generally useful for applying a status condition on a monster or NPC that you go back and check later.

Effects are mostly stored in data/json/effects.json, and described in

Books and comestible (food/drink/medicine) items can have morale modifiers. I’m not sure if there’s a general system for morale modifiers or not.


Adding new vehicle parts

New vehicle parts can be added in JSON. Most interactions between vehicle parts and the rest of the game unfortunately have to be hardcoded, but there’s still a fair bit you can do only in JSON.

Vehicle parts are stored in data/json/vehicle_parts.json and data/json/vehicleparts/ . Please try to put new things in the appropriate file inside of data/json/vehicleparts/ instead of the generic file at data/json/vehicle_parts.json.
Vehicle parts are mostly documented in the general JSON document at

A vehicle part JSON looks like this:

    "type": "vehicle_part",
    "id": "folding_seat",
    "name": "foldable seat",
    "symbol": "#",
    "color": "red",
    "broken_symbol": "*",
    "broken_color": "red",
    "damage_modifier": 10,
    "durability": 20,
    "description": "A crude seat, too uncomfortable to sleep in.",
    "item": "sheet",
    "folded_volume": 10,
    "location": "anywhere",
    "requirements": {
      "install": { "time": 20000, "skills": [ [ "mechanics", 2 ] ], "qualities": [ { "id": "WRENCH", "level": 2 } ] },
      "repair": { "skills": [ [ "mechanics", 2 ] ], "time": 2000, "using": [ [ "welding_standard", 5 ] ] },
      "removal": { "skills": [ [ "mechanics", 2 ] ], "qualities": [ { "id": "WRENCH", "level": 2 } ] }
    "flags": [ "SEAT", "BOARDABLE", "FOLDABLE" ],
    "breaks_into": [ { "item": "rag", "count": [ 1, 6 ] } ]

Some key bits:

  • "type" must be “vehicle_part”
  • "id" must be unique among all vehicle parts, but a vehicle_part and an item can share the same "id".
  • "item" is the part that is required to install the vehicle_part. Vehicle parts inherit their weight and storage capacity from their item.
  • "flags" are special keywords that tell the vehicle code how to interact with an item. They are generally documented in
  • "location" controls where the vehicle part can be installed. No vehicle can have two items in the same location of the same tile, unless the location is “ANYWHERE”. Valid locations include:
    • “under” - wheels and things under the chassis
    • “structure” - the frame of the vehicle
    • “center” - on top of the fame, used for major items like seats, welding rigs, windshields, and aisles
    • “engine_block”, “fuel_source” - beneath the center item, used for engines and fuel storage respectively
    • “on_ceiling” - hanging from the vehicle’s roof
    • “on_roof” - on the vehicle’s roof, used for turrets and solar panels
    • “armor” - on the vehicle’s outer frame, protecting other components

Spawning vehicle parts

vehicle_parts only exist while they’re on a vehicle. If you want to a add a vehicle_part to the game and have it spawn, you need to either add it to a vehicle that spawns, or add the vehicle_part’s "item" to an item_group.

Engines and fuel

You can add entirely new engines that consume arbitrary solid or liquid fuels. If you want to add a super-engine that consumes water, you can do that.

Fuels are items, and have JSON that looks like this:

    "id": "chem_ethanol",
    "type": "AMMO",
    "name": "ethanol",
    "name_plural": "ethanol",
    "description": "Extremely pure alcohol suitable for use as a component in chemical reactions.  You could also water it down and drink it, or use it as fuel in alcohol-burning stoves.",
    "weight": 1,
    "volume": "200ml",
    "count": 250,
    "stack_size": 200,
    "category": "chems",
    "phase": "liquid",
    "symbol": "~",
    "color": "white",
    "ammo_type": "conc_alcohol",
    "fuel": {
      "energy": 15.6,
      "explosion_data": { "chance_hot": 5, "chance_cold": 10, "factor": 0.2, "fiery": true, "size_factor": 0.1 }

The important bit here is the "fuel" object at the end, and the really important bit is the "energy" value, which is the energy in MJ/L that the fuel provides. For real world fuels, you can look that number up on wikipedia; for imaginary fuels, just know that gasoline has an energy around 35.

Engines look (more or less, the in game engines use a lot of copy-from to simplify) like this:

    "id": "engine_steam_makeshift",
    "type": "vehicle_part",
    "location": "engine_block",
    "symbol": "*",
    "color": "light_red",
    "broken_color": "red",
    "damage_modifier": 80,
    "item": "steam_watts_small",
    "difficulty": 4,
    "durability": 200,
    "fuel_type": "coal_lump",
    "fuel_options": [ "coal_lump", "charcoal" ],
    "cold_affects_start": true,
    "backfire_threshold": 0.25,
    "backfire_freq": 20,
    "noise_factor": 15,
    "damaged_power_factor": 0.25,
    "m2c": 65,
    "epower": 0,
    "power": 55950,
    "energy_consumption": 150000,
    "description": "A closed cycle, external combustion steam engine.  Burns coal or charcoal from a bunker in the vehicle to produce steam."

relevant bits:

  • "flags" must include “ENGINE”, and if you can power an alternator off this engine, “E_ALTERNATOR”.
  • "m2c" is the ratio of the engine’s safe power to the engine’s maximum power - the higher this value, the faster the vehicle’s safe velocity
  • "epower" is how much electrical power in watts it takes to operate the engine. This represents spark plugs in most combustion engines. It should be a negative value, because a positive value means the engine generates electrical power independent of an alternator.
  • "power" is how much motive power in watts the engine produces at maximum output. 1 HP = 746 watts, so this is an 80 HP engine.
  • "energy_consumption" is how much fuel the engine consumes at maximum power, again measured in watts. Each turn an engine is operating, it consumes energy_consumption * 1 second * strain joules of energy, where strain is current acceleration / maximum acceleration (plus some idle consumption to power any alternators). Every liter of fuel provides its "energy" * 1,000,000 joules of energy, so energy_consumption * strain / 1000 / energy is the number of liquid fuel charges consumed each turn.
    Energy_consumption should be a number that is larger than power, because that’s how real life physics works.
  • "fuel_type" and "fuel_opts" - the "id" of the engine’s preferred fuel type, and a list of "id"s of any alternate fuel types. So this steam engine prefers coal but can burn charcoal.

Adding new vehicles

New vehicles can also be added in JSON. This is relatively straightforward, but nevertheless tricky to get correct.

Vehicles are stored in the files in data/json/vehicles/ . The JSON is mostly documented at so this is just highlights.

The JSON looks like this:

    "id": "quad_bike",
    "type": "vehicle",
    "name": "Quad Bike",
    "blueprint": [
      [ "O O" ],
      [ "=#>" ],
      [ "O O" ]
    "parts": [
      { "x": 0, "y": 0, "parts": [ "frame_vertical_2", "saddle", "controls", "controls_electronic", "horn_car" ] },
      { "x": 1, "y": 0, "parts": [ "frame_cover","engine_vtwin", "alternator_motorbike", "battery_motorbike", "headlight", { "part": "tank_small", "fuel": "gasoline" }, "plating_steel" ] },
      { "x": -1, "y": 0, "parts": [ "frame_horizontal", "muffler", "trunk" ] },
      { "x": 1, "y": 1, "parts": [ "frame_horizontal", "wheel_motorbike_steerable" ] },
      { "x": 1, "y": -1, "parts": [ "frame_horizontal", "wheel_motorbike_steerable" ] },
      { "x": -1, "y": -1, "parts": [ "frame_horizontal", "wheel_motorbike" ] },
      { "x": -1, "y": 1, "parts": [ "frame_horizontal", "wheel_motorbike" ] }
    "items": [ { "x": -1, "y": 0, "chance": 10, "items": [ "helmet_motor" ] } ]

The important bit is the "parts" list. Each object in the parts list consists of an X, Y co-ordinate pair and a list of vehicle_parts in the "parts" value. The X value increases to the right, the Y value increases to the bottom, and vehicle is assuming to be facing due east. Yes, I know the vehicle interaction menu has the vehicle facing due north, it’s completely confusing.

Each object in the main “parts” list is installed before the next object, and each vehicle_part in each object’s “parts” list is installed in left to right order. The game’s engine actually builds the vehicle, one part at a time, and will fail to load if you attempt an illegal installation. So you have to be sure that all your parts lists start with a frame, and that each frame after the first frame has a frame adjacent to it. Engines have to be installed before alternators, seats before seat belts, turret mounts before turret weapons, and so on.

There’s also an "items" list at the very end, which is a collection of item_groups that controls what items might randomly spawn with the vehicle.

Spawning Vehicles

New vehicles need to be added to a vehicle group in order to spawn in the game. The vehicle groups are stored in data/json/road_vehicles.json, data/json/vehicle_groups.json, and in the various location’s mapgen files in data/json/mapgen/ .

road_vehicles.json is really complicated, but vehicle_groups.json is just lists of vehicles and the weighted spawn chance.

1 Like

Adding mutations, bionics, martial arts, furniture, terrain, materials, skills, and whatnot

I’m going to be honest with you: there’s a lot of other stuff that can be added by manipulating JSON files. Some of it is pretty advanced.

In general, though, read the docs at, look through the JSON files, and experiment.

Bionics and Mutations

Although you can add mutations and bionics, most of them have a lot of hard-coded interaction and require C++ support.


Mod or mainline

When you have an idea for new content, you have two options for introducing it to the game: you can either add it as an optional mod in data/mods/ , or to the mainline content in data/json . I wrote these guides under the assumption that you are going to add mainline content, because that’s what you probably should do.

Why not a mod?

A lot of stuff gets added to the game via mods. Adding content through mods makes a lot of sense when dealing with a commercial, closed source, game. But CDDA is open source, and welcomes contribution. Content that’s in a mod gets updated haphazardly at best, and sometimes mods get broken when the mainline game changes underneath them. Content that is in mainline is much more likely to get updated when the game changes.

You should add new content to a mod if, and only if, your new content wouldn’t be the kind of thing that most players would want to see. If you want to add a new mission chain where the Old Guard rep sends you out to assassinate rival faction leaders (please add a mission chain like this!), that should be in mainline. If you want to add a total overhaul of the game around an alien invasion called Cataclysm: Enemy Unknown (please add a total overhaul of the game like this!), that content should be in a mod.

In general, there’s very few good reasons to add content via a mod and lots of reasons not to.

1 Like

Getting your content merged in mainline

The process for getting your new content merged goes like this:

  1. Fork and clone the repo, develop your new content, test it.
  2. Use the web linter ( to make sure your JSON content matches CDDA’s JSON style (
  3. Commit your changes and push them to your repo.
  4. Go to and open a new pull request. Read the instructions in the pull request and format your summary line correctly.
  5. Wait an hour or so, and then review your pull request. If there’s a line toward the bottom that says “Some checks were not successful” then the automatic tests failed and your new content will not be added until the tests pass. There’s 3 lines below that, for “continuous-integration/travis-ci/pr”, “continuous-integration/appveyor/pr”, and “gorgon-ghprb” and all 3 have a “Details” link next to them. Find the tests that is failing, click on the “Details” link, and read every single word and link on that page until you find out why your test is failing. Then fix it and push a new set of changes.
  6. Repeat step 5 until your PR has a green check mark and a “All checks have passed” line.
  7. Wait some more. Possibly for 3-4 days.
  8. At some point, someone who isn’t a first time modder will review your PR and request that you make changes. Make them. There’s a slight chance that the reviewer is requesting a nonsense change, and if so, defend your content, but most likely they know more than you do and you should make the requested changes.
  9. Repeat steps 7 and 8 until no one is requesting any changes and at least a week has passed since you last updated.
  10. At this point - when your PR passes all tests, you’ve made all the requested changes, and you’ve waited at a week - and not sooner, if your PR hasn’t been merged, then you should get on the CDDA discord and ask what needs to be done to get your PR merged.
  11. At some point, your PR will be merged. Bask in the glory of contributing to CDDA, and then get started on your next PR.

I may have made the process of submitting a PR sound difficult, but the CDDA community is friendly and welcoming to new content. There’s just a process that you need to go through, because there are a lot more people who want to add new content than there are people who can review content for inclusion. Be patient, ask for advice, and soon you’ll have a “Great contributor” tag after your name on Discourse.

I hope this guide helps. Please PM me on the CDDA Discord,, or (I’m mlangsdorf just about everywhere) if you have questions or need some help.


@mlangsdorf would it be possible to change temperature through JSON? I was looking to make a brutal winter mod :slight_smile: as i feel like its currently more of a benefit then something to be feared.

Temperatures are controlled by the "weather" object in the "region_settings" objects data/json/regional_map_settings.json.

It looks like you can create a “region_overlay” object to update the weather - see data/mods/BrightNights/regional_map_settings.json for an example that sets the default temperature to 0 C instead of 6.5 C.