Guide to adding new content to CDDA for first time modders

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

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

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 https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_FLAGS.md.
  • "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,
    "flags": [ "ENGINE", "TOOL_WRENCH", "E_COMBUSTION", "E_ALTERNATOR", "E_HIGHER_SKILL", "E_HEATER" ],
    "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.
2 Likes

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

2 Likes

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 (http://dev.narc.ro/cataclysm/format.html) to make sure your JSON content matches CDDA’s JSON style (https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_STYLE.md).
  3. Commit your changes and push them to your repo.
  4. Go to https://github.com/CleverRaven/Cataclysm-DDA/pulls 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, discourse.cataclysmdda.org, or https://www.reddit.com/r/cataclysmdda/ (I’m mlangsdorf just about everywhere) if you have questions or need some help.

4 Likes

@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.

2 Likes

I’ve managed to get it to change the temperature, but i couldn’t figure out how to adjust winter temperatures independently, i’m not sure if region overlay was the way to go, i’ve tried tweaking the bright nights overlay and it didn’t affect the temperature at all (i tried waiting several days and no changes past the default temperature) the temperature kept at -9 during sundown mid winter.

however when i tweaked the “weather” temperatures in the regional_map_settings.json it did change the temperature, but made the other seasons cold as well (I’m hoping to mimic the temperatures im used to IRL 20-30 during summer and -30-40 during winter :open_mouth: )

I looked through the region settings documentation and flags but havent found anything in regards to weather and specific seasons. changing the default base temperature would be handy for a hardcore permanent winter playthrough though.

1 Like

i’ll be waiting for new PR merge from the community… its always great and fun to see new mods added to the game.

As of #29206 it is now possible to specify bionics in classe.json

    "bionics": [
      { "id": "bionic_id", "chance": x },
      { "id": "bionic_id", "chance": y }  ]

With x and y, a value between ]0 , 100], the probability to have the CBM

1 Like

SERIOUSLY comprehensive.

Thank you, @mlangsdorf for the time and effort required to compile this.

I’m going to devour this and start churning out content.

3 Likes

i’m considering at least giving a try to creating a mod that would totally remove both freezing and spoilage mechanics from the game so that players who want a vastly easier and less tedious experience can readily have this crutch.

i looked over the documentation linked above and still sort of drew a blank on how to totally remove features from the game via a mod.

There is already a mod that does this, if you use the launcher you will see it’s called no freeze.

right, but that’s only half of what i want, plus it doesn’t actually remove the ability of things to freeze as a mechanic, it just sets the threshold for when it should happen to a ridiculous number.

since it’s obvious you aren’t aware that mod has also been totally non-functional and broken for quite a while now too.