Guide to adding new content to CDDA for first time modders

The Guide to Adding New Content to CDDA for 1st Time Modders now lives on github and you should follow that fine hand-crafted link to the current version.

This thread is meant to provide a quick, accessible overview of how to add specific features to CDDA. It’s intended for people who want to add a thing, but don’t know where to start.

Hey, what if CDDA had a

All of these can be added to the game by editing text files, because they’re data files and most of CDDA’s data is stored in a text file format called JSON.

A brief intro to JSON

CDDA’s data files are stored in a text format called JSON. JSON looks complicated and intimidating when you first start, but it is just text. You can learn to read it and understand it, and then it isn’t mysterious.

True story - I’ve been a professional programmer for more than 20 years. When I first started dealing with JSON a couple of years ago, I thought it was complicated, mysterious, and intimidating. But I learned a bit about and now I can write JSON and even write guides telling other people about JSON.

Why should I care about JSON?

JSON defines that game’s data. If you add JSON to the game that matches the game’s expectations about what a bit of JSON should look like, you can add new content to the game.

You can edit JSON with a text editor, like notepad++ on Windows. Notepad++ has a syntax highlighting mode that understands JSON, so it will help highlight possible mistakes. On Linux, you can use any text editor that you prefer and most of them have JSON syntax modes.

JSON Overview

CDDA’s data files are stored in data/json inside the game’s folder. Each JSON file has content that looks something like this:

[
  {
    "id": "sig_40",
    "type": "GUN",
    "reload_noise_volume": 10,
    "name": "SIG Pro .40",
    "name_plural": "SIG Pro .40",
    "description": "Originally marketed as a lightweight and compact alternative to older SIG handguns, the Pro .40 is popular among European police forces.",
    "weight": 680,
    "volume": 2,
    "price": 75000,
    "to_hit": -2,
    "bashing": 8,
    "material": [ "steel", "plastic" ]
  }
]

JSON has 5 types of things in it:

  • lists are collections of other things, and are enclosed in brackets like this [ "thing", "other thing" ]. items in a list are separated by commas.
  • objects are also collections of other things, but each item in an object consists of a key and a value, like this "volume": 2, . Again, items are separated by commas, and the entire object is enclosed in braces likes this { "sample_object": "value" }
  • strings are words or sentences, and are always enclosed in quotes like this "string". the keys of an object are strings.
  • numbers are numbers, and aren’t enclosed in quotes.
  • true and false are special words that are never enclosed in quotes. they’re referred to as booleans.

So the sample bit of JSON above is a list with a single object in it. that object has several keys, some of which have string values, others have number values, and one has a list value and that list is made up of string values.

About file locations

All files locations below start in the game’s folder. So if your game is in C:\Users\bob\Cataclysm, then data/json/items/gun/50.json is at C:\Users\bob\Catacylsm\data\json\items\gun\50.json. Also, I’m a Linux guy and I use slashes the right way to separate folders so if you’re on Windows, you’ll need to convert my “/” to Windows-style “\”.

Also, although the game stores certain JSON objects in certain files or folders, it’s the content of the objects that matter, not the location. Even though 7.62mm rifles are normally defined in data/json/items/gun/762,json, you can define one in data/json/skills.json and it will still work.

Continued in getting started

(This document now lives on the CDDA github wiki so you should probably check there for the most up to date version)

26 Likes

Getting Started

Here’s a bunch of links that contain more information about how set yourself up to make a change to CDDA:

https://github.com/AMurkin/CDDA-GitHub-Start is an illustrated tutorial on setting up a github account, forking and cloning the repo, and pushing a PR.

http://cddawiki.chezzo.com/cdda_wiki/index.php?title=Contributing has the same information in th middle. You can 100% ignore all the stuff about compiling, but it’s the same process to share JSON and code changes, so set up a github account.

Technically, you can just edit the files in your game’s data/json folder, but if you do that while in a git repo, then git will automatically keep track of your changes.

This is mostly about the mod manager app, but it gives the basics of setting up a new mod: http://cddawiki.chezzo.com/cdda_wiki/index.php?title=Mod_manager

There’s a fair bit of documentation in the game already:


Start with the modding guide:


then the general JSON format guide:

Before you contribute, make sure you read the JSON style guide and the manual of style for descriptive text:


More on adding specific types of content

4 Likes

Adding a new recipe

Recipes determine what you can craft. They’re relatively easy to add.

Recipes are stored in data/json/recipes . There are some subfolders there and subfiles like recipe_food.json. Just pick one that seems appropriate.

This is the JSON object for the salt (made from boiling water) recipe:

  {
    "type": "recipe",
    "result": "salt",
    "id_suffix": "from_salt_water",
    "category": "CC_FOOD",
    "subcategory": "CSC_FOOD_OTHER",
    "skill_used": "cooking",
    "difficulty": 0,
    "time": 90000,
    "autolearn": true,
    "batch_time_factors": [ 80, 4 ],
    "qualities": [ { "id": "BOIL", "level": 1 } ],
    "tools": [ [ [ "water_boiling_heat", 3, "LIST" ] ] ],
    "components": [ [ [ "salt_water", 10 ], [ "saline", 50 ] ] ]
  },

Important bits:

  • "type" has to be "recipe"
  • "result" is the "id" of the item that the recipe creates. items are defined in data/json/items/ and its subfolders.
  • "id_suffix" is used to differentiate two recipes that have the same results. It doesn’t really mean anything and you can put anything here as long as every recipe with the same result has a different id_suffix, but it’s good practice to use something that makes it easy to tell why each recipe is different.
  • "category" and "subcategory" are where the recipe will end up in the craft menu. You have to use a valid string in both cases, so look through the recipes to find one in the same category as your new recipe and use those values.
  • "skill_used" is the "ident" of the primary skill for the recipe. possible skills are in data/json/skills.json
  • "difficulty" is the number of the skill level where you have a high chance of automatically making this recipe.
  • “time” is the number of ticks to create a single result. 100 ticks is 1 turn or 6 seconds.
  • "autolearn" is true if you learn the recipe automatically when your skill reaches difficulty. Otherwise, there should be a "book_learn" entry, with a list of lists of references books and the skill level at which you get the recipe, like "book_learn": [ [ "cookbook_sushi", 3 ] ] for sushi veggy rolls. The books are refered to by “id” from data/json/items/ again.
  • "qualities" is a list of tool qualities you need to make the recipe. Available qualities are in data/json/tool_qualities.json and items define what tool qualities they provide. Items that provide qualities are not consumed by the recipe.
  • "tools' is a list of tool types you need, in addition to the qualities. While qualities is a list of objects, tools is a list of lists. Items that provide tools are not consumed by the recipe.
  • "components" is a list of lists of components that are consumed by the recipe. They break down like this:
    [ "water", 1] is a single component, where the first string is "id" of the item in the component, and the second number is the number of that item that is required.
    [ [ "water", 1 ], [ "water_clean", 1 ] ] is an options list. it’s a list of single components. either component can be used to satisfy the recipe. It can have as a single entry.
"components": [
  [ [ "scrap", 1 ] ],
  [ [ "water", 1 ], [ "water_clean", 1 ] ],
]

is the full components list, made up of options lists. So this recipe requires a piece of scrap metal and a unit of water or clean water.

So adding a new recipe requires that you have:

  • the id of resulting item
  • the ids of all components and tools
  • the qualities of any tools specified by quality
  • the ident of the skill
  • the difficulty of the crafting
  • the ids of any books used to learn the recipe
  • the time to make the recipe.
7 Likes

Is adding enemies or creatures something that can be done in JSON currently? If not, will it be in the future?

I had some ideas about tinkering with the Mi-go. They are supposed to be intelligent and have a society, albeit an evil axe murdering parody of one. I wanted to add marauding bands of Mi-go slavers, wielding cruel and exotic alien weapons.

Adding to the biodiversity of the game environment is something else I was considering. More wildlife, as well as mutant variants. Like tentacle deer or something.

1 Like

Monsters are JSON entities and can be added. I just forgot about them.

Vehicle parts are also JSON entities, but 90% of what people want to do with new vehicle parts require C++ coding so I’m going to address them last.

2 Likes

Someone - someone who doesn’t also have mountains of awesome code to write - should consider translating this to a doc on GitHub too.

1 Like

Adding a new items

Items are things in the game. They’re usually easy to add, but there are some subtle bits.

Items are stored in data/json/items/ . There are a lot of subfolders and subfiles, so try to pick the most appropriate one. Some guidelines:

  • melee weapons go in melee.json
  • guns go in the gun/ subfile for the gun’s ammo, while new ammo goes in ammo/, gun magazines go in magazine/
  • comestibles contains all food, drink, and medicine
  • vehicle parts go in vehicle/ but are a separate, complicated topic.
  • clothing and armor go in armor.json for the most part.

items have a lot of different fields in their objects, so I’m just going to highlight the most important ones. For everything else, read https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_INFO.md and https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_FLAGS.md

  {
    "id": "hide_bag",
    "copy-from": "raw_leather",
    "type": "COMESTIBLE",
    "category": "clothing",
    "name": "hide bag",
    "description": "The raw skin of an animal, quickly turned into a makeshift bag for storage.  It will still rot, and needs to be cured and tanned.",
    "symbol": "[",
    "color": "pink",
    "looks_like": "swag_bag",
    "armor_data": {
      "covers": [ "ARM_EITHER", "HAND_EITHER" ],
      "coverage": 5,
      "encumbrance": 100,
      "storage": 60,
      "material_thickness": 1,
      "flags": [ "OVERSIZE", "BELTED", "RESTRICT_HANDS", "WATER_FRIENDLY" ]
    }
  },

  • "id" is the internal reference string for the item, and must be unique among all other items.
  • "type" is the type of item. Items can have multiple types, like the hide_bag technically being edible (required so it will rot) but having armor data so you can wear it.
  • "category" is the category the item will be sorted in for inventory lists. It is unrelated to the item’s type - you can food in the clothing category, armor in the tool category, whatever makes sense.
  • "copy-from" is a special field. It references another item’s "id" and means use that item’s values except where they differ from this item’s. In general, you should use copy-from as much as possible because it reduces the number of things that future developers will need to change when making a change. For instance, almost all guns are copy-froms for a a single abstract gun, which means if there is a change made to how guns work, that single abstract gun gets changed and all the other guns get the change automatically.
  • "looks_like" contains the "id" of another item that the item might look like. If a tileset doesn’t have a tile for your new item, it will check if it has a tile for the looks_like and use that instead.

Special item considerations

  • an entirely new gun will need a new item for the gun, a new item for the ammunition, and a new item for the detachable magazine, if any. You’ll have to create all three. In general, please don’t create new ammunition until you have a solid understanding of adding items, but its more acceptable to create new guns and new magazines.
  • books with recipes don’t define the recipes they contain. Instead, the recipes reference the books. So if you want to create a Tex-Mex cookbook, you have to create an item for the book and then go through the food recipes and references to the book in the recipe’s "book_learn" fields.

Spawning items

Adding an item’s definition just defines the item. It doesn’t make it show up in the game. To do that, you’ll need to add the item to one or more item_groups.

Item_groups mostly live in data/json/itemgroups/ and data/json/item_groups. There’s an entire doc on item groups that explains it very well: https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/ITEM_SPAWN.md
Some locations have their own item groups that are defined in the location’s definition in data/json/mapgen/ , so you may need to add stuff there, too.

Don’t forget the recipes

If an item should be craftable, you should also add a recipe for it. See the previous post.

Sample process: Adding a new gun

  1. Add the new gun to the gun’s caliber JSON file in data/json/items/gun/
  2. Add the new gun’s new magazines (if any) to the gun’s caliber JSON file in data/json/items/magazine/
  3. Add the gun and magazine to one or more item groups in data/json/item_groups.json, data/json/itemgroups/, and/or data/json/mapgen/
  4. If the gun or magazine can be crafted, add recipes for them in data/json/recipes/
9 Likes

How do I give you one million hearts?

2 Likes

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.

7 Likes

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.

2 Likes

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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md. 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.
4 Likes

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.

2 Likes

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

3 Likes

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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/NPCs.md, 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...",
    "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": [
        "Citizen...",
        "Can I help you?",
        "Is there something you need?",
        "<greet>",
        {
          "u_male": [
            "Sir.",
            "You look capable, I may have some work for you."
          ],
          "u_female": [ 
            "Ma'am",
            "Hello miss, the US government is an equal opportunity employer."
          ]
        }
      ]
   }
 }
}

Snippets

"<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

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 NPCs.md, 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.

Missions

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

2 Likes

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.
3 Likes

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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MISSIONS_JSON.md 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.

3 Likes

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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_INFO.md. 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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/ITEM_SPAWN.md. 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/MONSTERS.md, 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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_INFO.md.

2 Likes

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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/EFFECTS_JSON.md

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.

2 Likes