Guide to adding new content to CDDA for first time modders

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.
1 Like

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.

1 Like

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.

Yeah I’ve never used it, but it should give you an idea of where to start.

no, not at all, i’ve seen that setting ridiculous values as the threshold is a worthless course of action that’s assured to be broken by updates to the game later, that’s why i’m focused on entire removal.

so… no advice at all on how to remove game mechanics via a mod?

Yes and no.

Generally, when you’re talking significant changes to game mechanics such as removing rot and freeze, you’re going to need C++ support. And while I am more than willing to help a programmer out, I don’t have any experience in teaching people to become programmers.

So, while I’m pretty sure that this:

diff --git a/src/item.cpp b/src/item.cpp
index b362b413d3..0a3d2e2d2e 100644
--- a/src/item.cpp
+++ b/src/item.cpp
@@ -3894,7 +3894,7 @@ std::set<matec_id> item::get_techniques() const
 
 bool item::goes_bad() const
 {
-    if( has_flag( "PROCESSING" ) ) {
+    if( has_flag( "PROCESSING" ) || get_option<bool>( "DISABLE_ROT" ) ) {
         return false;
     }
     if( is_corpse() ) {

would be a key part of a maintainable approach to disabling rot, if that doesn’t mean much to you, then my only advice would be to search on the web for some c++ tutorials and learn enough programming that it makes sense. I’m sorry if that isn’t a satisfactory answer but that’s really the best I have to offer.

1 Like

it’s an answer, i certainly can’t handle anything to do with c++ programming, thanks for responding.
i mean, i’m sure i probably could, i understand what an if statement is and i think i follow the logic statements there as well, but the rest i’d have to learn from the ground up, i’ve never really even toyed around with c++ yet, the only time i did would be the cheat codes in the old carmageddon game that decrypted the game files so you can edit them to your liking.