Back to Cataclysm Dda

Recipes

doc/JSON/ITEM_CRAFT_AND_DISASSEMBLY.md

1.0.033.1 KB
Original Source
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

Contents

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Recipes

Crafting recipes are defined as a JSON object with the following fields:

jsonc
"result": "javelin",         // ID of resulting item
"activity_level": "LIGHT_EXERCISE", // (Mandatory) Options are NO_EXERCISE, LIGHT_EXERCISE, MODERATE_EXERCISE, BRISK_EXERCISE, ACTIVE_EXERCISE, EXTRA_EXERCISE. How energy intensive of an activity this craft is. E.g. making an anvil is much more exercise than cooking a fish.
"byproducts": [ [ "" ] ],    // Optional (default: empty). Additional items generated by crafting this recipe.
"byproduct_group": [         // Optional (default: empty). Same as above, but using item group definitions.
  { "item": "item_id_1", "count": [ 1, 4 ] },
  { "item": "item_id_2", "charges": [ 8, 15 ] },
],
"category": "CC_WEAPON",     // Category of crafting recipe. CC_NONCRAFT used for disassembly recipes
"subcategory": "CSC_WEAPON_PIERCING",
"id_suffix": "",             // Optional (default: empty string). Some suffix to make the ident of the recipe unique. The ident of the recipe is "<id-of-result><id_suffix>".
"variant": "javelin_striped", // Optional (default: empty string). Specifies a variant of the result that this recipe will always produce. This will append the variant's id to the recipe ident "<id-of-result>_<variant_id>".
"override": false,           // Optional (default: false). If false and the ident of the recipe is already used by another recipe, loading of recipes fails. If true and a recipe with the ident is already defined, the existing recipe is replaced by the new recipe.
"delete_flags": [ "CANNIBALISM" ], // Optional (default: empty list). Flags specified here will be removed from the resultant item upon crafting. This will override flag inheritance, but *will not* delete flags that are part of the item type itself.
"skill_used": "fabrication", // Skill trained and used for success checks
"skills_required": [["survival", 1], ["throw", 2]], // Skills required to unlock recipe
"book_learn": {	             // (optional) Books that this recipe can be learned from.
    "textbook_anarch" : {    // ID of the book the recipe can be learned from
        "skill_level" : 7,   // Skill level at which it can be learned
        "recipe_name" : "something", // (optional) Name of the recipe as it should appear in the book's description (default is the name of resulting item of the recipe)
        "hidden" : true },   // (optional) If set to true, recipe will not be shown in the description of the book
    "textbook_gaswarfare" : { // Additional book this recipe can be learnt from.
        "skill_level" : 8
    }
},
"difficulty": 3,             // Difficulty of success check
"time": "5 m",               // Preferred time to perform recipe, can specify in minutes, hours etc.
"morale_modifier": [ -5, "2 hours" ], // Optional (int, time duration). Any morale penalty or bonus conferred by crafting this recipe. Penalties are conferred at the start of crafting, bonuses upon completion. The second member of the pair is how long the morale will last. Decay always starts after half of the total time.
"reversible": true,          // Can be disassembled. Time taken is as long as to craft the item.
"reversible": { "time": "30 s" }, // Can be disassembled. Time to disassemble as specified.
"autolearn": true,           // Automatically learned upon gaining required skills
"autolearn" : [              // Automatically learned upon gaining listed skills
    [ "survival", 2 ],
    [ "fabrication", 3 ]
],
"decomp_learn" : 4,          // Can be learned by disassembling an item of same type as result at this level of the skill_used
"decomp_learn" : [           // Can be learned by disassembling an item of same type as result at specified levels of skills
    [ "survival", 1 ],
    [ "fabrication", 2 ]
],
"proficiencies" : [ // The proficiencies related to this recipe
    {
      "proficiency": "prof_knapping", // The id of a proficiency
      "required": false, // Whether or not you must have the proficiency to craft it. Incompatible with `time_multiplier`
      "time_multiplier": 2.0 // The multiplier on time taken to craft this recipe if you do not have this proficiency
      "skill_penalty": 1.5 // The effective skill penalty when crafting without this proficiency. Defaults to 1.0. Multiple proficiencies will add to this value.
      "learning_time_multiplier": 1.2 // The multiplier on learning speed for this proficiency. By default, it's the time of the recipe, divided by the time multiplier, and by the number of proficiencies that can also be learned from it.
      "max_experience": "15 m" // This recipe cannot raise your experience for that proficiency above 15 minutes worth.
    }
]
"contained": true, // Boolean value which defines if the resulting item comes in its designated container. Automatically set to true if any container is defined in the recipe. 
"container": "jar_glass_sealed", //The resulting item will be contained by the item set here, overrides default container.
"container_variant": "jar_glass_sealed_strawberry_picture", //The container specified above will spawn as the specified variant, overrides the normal weighted behavior.
"batch_time_factors": ..., // See below for details
"charges": 2,                // Number of resulting items/charges per craft. Uses default charges if not set. If a container is set, this is the amount that gets put inside it, capped by container capacity.
"result_mult": 2,            // Multiplier for resulting items. Also multiplies container items.
"flags": [                   // A set of strings describing boolean features of the recipe
  "BLIND_EASY",
  "ANOTHERFLAG"
],
"result_eocs": [ {"id": "TEST", "effect": { "u_message": "You feel Test" } } // List of inline effect_on_conditions or effect_on_condition ids that attempt to activate when this recipe is successfully finished.  If a value is provided a result becomes optional, though a name and id will be needed if it is missing.  If no result is provided and a description is present, "description" will be displayed as the result on the crafting gui.
], 
"name" : "%s with quern", // optional string to further describe recipe where %s is the recipe result name. Example if the result name is "flour", the final name will be "flour with quern". Especially useful for recipes with "id_suffix" that produce the same result as other recipes.
"description": "foobar.  your name is <u_name>" // if crafting result is not an item, this text will be shown. Support color and NPC tags
"construction_blueprint": "camp", // an optional string containing an update_mapgen_id.  Used by faction camps to upgrade their buildings
"on_display": false,         // this is a hidden construction item, used by faction camps to calculate construction times but not available to the player
"qualities": [               // Generic qualities of tools needed to craft
  { "id": "CUT", "level": 1, "amount": 1 }
],
"tools": [                   // Specific tools needed to craft
[
  [ "fire", -1 ]             // Charges consumed when tool is used, -1 means no charges are consumed
]],
"using": [                   // Requirement IDs and multipliers of tools and materials used
  [ "req_a", 3 ],            // Second number multiplies requirement materials by that amount
  [ "req_b", 5 ],            // Need 3x everything in req_a, 5x everything in req_b
],
"components": [              // Items (or item alternatives) required to craft this recipe
  [
    [ "item_a", 5 ]          // First ingredient: need 5 of item_a
  ],
  [
    [ "item_b", 2 ],         // Also need 2 of item_b...
    [ "item_c", 4 ]          // OR 4 of item_c (but do not need both)
  ],
  [
    // ... any number of other component ingredients (see below)
  ]
],
"component_blacklist": [     // List of item types that don't get added to result item components. Reversible recipes won't recover these and comestibles will not include them in calorie calculations.
  "item_a",
  "item_b"
]

batch_time_factors

`batch_time_factors supports several formats, with two different scaling functions.

Logistic scaling provides savings of some percent once the batch reaches a certain size.

jsonc
"batch_time_factors": [ 25, 15 ], // legacy
"batch_time_factors": { "mode": "logistic", "percent": 25, "at": 15 }

This shows both formats for logistic scaling. The first number specifies the maximum crafting time reduction as a percentage, and the second number the minimal batch size to reach that number. If this recipe took 5000 moves, when made in a batch of 20, the last 5 units would take only 3750 moves to produce.

Linear scaling provides purely linear scaling. There are two parameters, the setup time T, and the max batch size M, which is optional. The time taken for a batch of size n for a recipe which takes t time is: (ceil(n/M) * T) + (n * (t - T)). If M is not specified, it defaults to n, simplifying to T + (n * (t - T)). In other words, max does not limit the max batch size, it merely specifies when the setup cost will be applied again. It is specified as follows:

jsonc
"batch_time_factors": { "mode": "linear": "setup": "12 m" },
"batch_time_factors": { "mode": "linear": "setup": "12 m", "max": 20 },

Recipe steps

Recipes can optionally define a "steps" array to split the craft into named phases. Each step has its own time, activity level, proficiencies, tools, qualities, and batch savings.

When "steps" is present, the following fields must appear per-step and must not appear at root level: "time", "activity_level", "tools", "qualities", "proficiencies", "batch_time_factors".

"using" is also not allowed at root level for step recipes. Step-level "using" is not yet supported.

"components" remains at root level. All other recipe fields ("result", "skill_used", "difficulty", "book_learn", "autolearn", etc.) also remain at root.

Step recipes cannot use "copy-from" or "abstract".

Step fields

Each entry in the "steps" array is an object with these fields:

jsonc
"name":               // (Mandatory) Translatable string.  Shown in the crafting progress message.
"time":               // (Mandatory) Duration (e.g. "5 m").  Must be > 0.
"activity_level":     // (Mandatory) Same values as the recipe-level field.
"proficiencies":      // (Optional)  Same format as recipe-level.  Only these proficiencies are
                      //             trained while the craft is in this step.
"tools":              // (Optional)  Same format as recipe-level.
"qualities":          // (Optional)  Same format as recipe-level.
"batch_time_factors": // (Optional)  Same format as recipe-level.

"components" at step level is not allowed.

Example

jsonc
{
  "type": "recipe",
  "result": "bread",
  "category": "CC_FOOD",
  "subcategory": "CSC_FOOD_BREAD",
  "skill_used": "cooking",
  "difficulty": 2,
  "charges": 10,
  "components": [
    [ [ "flour", 22 ], [ "bread_flour", 5 ] ],
    [ [ "yeast", 1 ] ],
    [ [ "water_clean", 2 ] ],
    [ [ "sugar", 4 ] ]
  ],
  "steps": [
    {
      "name": "Mix dough",
      "time": "5 m",
      "activity_level": "MODERATE_EXERCISE",
      "batch_time_factors": [ 25, 4 ],
      "proficiencies": [
        { "proficiency": "prof_food_prep" },
        { "proficiency": "prof_baking" },
        { "proficiency": "prof_baking_bread" }
      ]
    },
    {
      "name": "Let dough rise",
      "time": "10 m",
      "activity_level": "NO_EXERCISE",
      "batch_time_factors": [ 5, 4 ]
    },
    {
      "name": "Bake",
      "time": "5 m",
      "activity_level": "LIGHT_EXERCISE",
      "batch_time_factors": [ 50, 4 ],
      "qualities": [ { "id": "OVEN", "level": 1 } ],
      "tools": [ [ [ "surface_heat", 22, "LIST" ] ] ]
    }
  ]
}

Runtime behavior

  • All step tools and qualities are merged and checked at craft start.
  • The craft tracks a single overall progress bar.
  • The activity level changes as the craft moves between steps.
  • Proficiency training is limited to the proficiencies listed on the current step.
  • Batch savings are applied per-step and summed.
  • The current step name appears in the crafting progress message.

Practice recipes

Recipes may instead be defined with type "practice", to make them appear in the "PRACTICE" tab of the crafting menu. These recipes do not have a "result", but they may define "byproducts"/"byproduct_group". See PRACTICE_RECIPES.md for how to define them.

Nested recipes

Similar recipes may instead be nested allowing you to save space in the UI. This is done as such:

jsonc
{
  "id": "nested_steel_legs",
  "type": "nested_category",
  "activity_level": "BRISK_EXERCISE",
  "category": "CC_ARMOR",
  "subcategory": "CSC_ARMOR_LEGS",
  "name": "steel leg guards",
  "description": "Recipes related to constructing steel leg guards in various thickness and steel variants.",
  "skill_used": "fabrication",
  "nested_category_data": [
    "xl_armor_qt_heavy_leg_guard",
    "armor_qt_heavy_leg_guard",
    "xl_armor_ch_heavy_leg_guard",
    "armor_ch_heavy_leg_guard",
    "xl_armor_hc_heavy_leg_guard",
    "armor_hc_heavy_leg_guard",
    "xl_armor_mc_heavy_leg_guard",
    "armor_mc_heavy_leg_guard",
    "xl_armor_lc_heavy_leg_guard",
    "armor_lc_heavy_leg_guard",
    "xl_armor_qt_leg_guard",
    "armor_qt_leg_guard",
    "xl_armor_ch_leg_guard",
    "armor_ch_leg_guard",
    "xl_armor_hc_leg_guard",
    "armor_hc_leg_guard",
    "xl_armor_mc_leg_guard",
    "armor_mc_leg_guard",
    "xl_armor_lc_leg_guard",
    "armor_lc_leg_guard",
    "xl_armor_qt_light_leg_guard",
    "armor_qt_light_leg_guard",
    "xl_armor_ch_light_leg_guard",
    "armor_ch_light_leg_guard",
    "xl_armor_hc_light_leg_guard",
    "armor_hc_light_leg_guard",
    "xl_armor_mc_light_leg_guard",
    "armor_mc_light_leg_guard",
    "xl_armor_lc_light_leg_guard",
    "armor_lc_light_leg_guard"
  ],
  "difficulty": 5,
  "autolearn": [ [ "fabrication", 5 ] ]
}

So it is identical to a normal recipe with the addition of the "nested_category_data" which lists all of the recipe ID's that are in the category.

If you want to hide recipes that are nested you can set their category and subcategory as:

jsonc
"category": "CC_*",
"subcategory": "CSC_*_NESTED",

Recipe requirements

The tool quality and component requirements for a recipe may be expressed in a combination of several ways, with these JSON fields:

  • "qualities" defines item qualities like CUT or HAMMER, and quality levels needed to craft
  • "tools" lists item ids of tools (or several alternative tools) needed for crafting the recipe
  • "components" lists item or requirement ids, intended mainly for material ingredients
  • "using" gives requirement ids; the requirement may have nested tools, qualities, or components

These fields may be used similarly in uncrafting, constructions, vehicle parts, and vehicle faults. The first three fields are applicable to "requirement" definitions as well, and may be nested; see the requirements section.

A recipe's "components" lists all the required items or ingredients needed to craft the finished item from the recipe. Each component is given as an integer quantity of a specific item id or requirement id, or as a list of several alternative item/requirement quantities.

The syntax of a component in its simplest form is an item id and quantity. Continuing the "javelin" recipe, let's require a single "spear_wood" item:

jsonc
"components": [
  [ [ "spear_wood", 1 ] ]
]

A single component may also have substitutions; for instance, to allow crafting from one "spear_wood" or one "pointy_stick":

jsonc
"components": [
  [ [ "spear_wood", 1 ], [ "pointy_stick", 1 ] ]
]

Notice that the first example with only "spear_wood" was simply the degenerate case - a list of alternatives with only 1 alternative - which is why it was doubly nested in [ [ ... ] ].

The javelin would be better with some kind of leather or cloth grip. To require 2 rags, 1 leather, or 1 fur in addition to the wood spear or pointy stick:

jsonc
"components": [
  [ [ "spear_wood", 1 ], [ "pointy_stick", 1 ] ],
  [ [ "sheet_cotton", 2 ], [ "leather", 1 ], [ "fur", 1 ] ]
]

And to bind the grip onto the javelin, some sinew or thread should be required, which can have the "NO_RECOVER" keyword to indicate they cannot be recovered if the item is deconstructed:

jsonc
"components": [
  [ [ "spear_wood", 1 ], [ "pointy_stick", 1 ] ],
  [ [ "sheet_cotton", 2 ], [ "leather", 1 ], [ "fur", 1 ] ],
  [ [ "sinew", 20, "NO_RECOVER" ], [ "thread", 20, "NO_RECOVER" ] ]
]

Note: Related to "NO_RECOVER", some items such as "superglue" and "duct_tape" have an "UNRECOVERABLE" flag on the item itself, indicating they can never be reclaimed when disassembling. See JSON_FLAGS.md for how to use this and other item flags.

Defining common requirements

To avoid repeating commonly used sets of components, instead of an individual item id, provide the id of a requirement type, along with a quantity, and the "LIST" keyword. Typically these are defined within data/json/requirements.

For example if these grip_patch and grip_wrap requirements were defined:

jsonc
[
  {
    "id": "grip_patch",
    "type": "requirement",
    "components": [ [ [ "sheet_cotton", 2 ], [ "leather", 1 ], [ "fur", 1 ] ] ]
  },
  {
    "id": "grip_wrap",
    "type": "requirement",
    "components": [ [ [ "sinew", 20, "NO_RECOVER" ], [ "thread", 20, "NO_RECOVER" ] ] ]
  }
]

Then javelin recipe components could use 1 grip and 1 wrap, for example:

jsonc
"result": "javelin",
"components": [
  [ [ "spear_wood", 1 ], [ "pointy_stick", 1 ] ],
  [ [ "grip_patch", 1, "LIST" ] ],
  [ [ "grip_wrap", 1, "LIST" ] ]
]

And other recipes needing two such grips could simply require 2 of each:

jsonc
"result": "big_staff",
"components": [
  [ [ "stick_long", 1 ] ],
  [ [ "grip_patch", 2, "LIST" ] ],
  [ [ "grip_wrap", 2, "LIST" ] ]
]

The "using" field in a recipe works similarly, but "using" may only refer to requirement ids, not specific items or tools. A requirement included with "using" must also give a multiplier, telling how many units of that requirement are needed. As with "components", the "using" list is formatted as a collection of alternatives, even if there is only one alternative.

For instance, this "uncraft" recipe for a motorbike alternator uses either 20 units of the "soldering_standard" requirement, or 5 units of the "welding_standard" requirement:

jsonc
{
  "type": "uncraft",
  "result": "alternator_motorbike",
  "qualities": [ { "id": "SCREW", "level": 1 } ],
  "using": [ [ "soldering_standard", 20 ], [ "welding_standard", 5 ] ],
  "components": [ [ [ "power_supply", 1 ] ], [ [ "cable", 20 ] ], [ [ "bearing", 5 ] ], [ [ "scrap", 2 ] ] ]
}

Requirements may include "tools" or "qualities" in addition to "components". Here we have a standard soldering requirement needing either a "soldering_iron" or "toolset", plus 1 unit of the "solder_wire" component:

jsonc
{
  "id": "soldering_standard",
  "type": "requirement",
  "//": "Tools and materials needed for soldering metal items or electronics",
  "tools": [ [ [ "soldering_iron", 1 ], [ "toolset", 1 ] ] ],
  "components": [ [ [ "solder_wire", 1 ] ] ]
}

This simplifies recipes needing soldering, via the "using" field. For instance, a simple "tazer" recipe could require 10 units of the soldering requirement, along with some other components:

jsonc
{
  "type": "recipe",
  "result": "tazer",
  "using": [ [ "soldering_standard", 10 ] ],
  "components": [ [ [ "amplifier", 1 ] ], [ [ "power_supply", 1 ] ], [ [ "scrap", 2 ] ] ],
  "//": "..."
}

Requirements can be used not just for regular crafting and uncrafting recipes, but also for constructions and vehicle part installation and mending.

NOTE: Requirement lists included in mods overwrite the previously loaded requirement list with a matching id. This means that two mods modifying the same requirement id will overwrite each other. This can be avoided by using "extend" to extend from the previously loaded list. Ex.:

jsonc
{
  "id": "bone_sturdy",
  "type": "requirement",
  "extend": {
    "components": [
      [
        [ "frost_bone_human", 1 ],
        [ "alien_bone", 1 ]
      ]
    ]
  }
}

Overlapping recipe component requirements

If recipes have requirements which overlap, this makes it more difficult for the game to calculate whether it is possible to craft a recipe at all.

For example, the survivor telescope recipe has the following requirements (amongst others):

1 high-quality lens
AND
1 high-quality lens OR 1 small high-quality lens

These overlap because both list the high-quality lens.

A small amount of overlap (such as the above) can be handled, but if you have too many component lists which overlap in too many ways, then you may see an error during recipe finalization that your recipe is too complex. In this case, the game may not be able to correctly predict whether it can be crafted.

To work around this issue, if you do not wish to simplify the recipe requirements, you can introduce intermediate items to break the overlap. For example, if we wanted to simplify the above survivor telescope recipe we could introduce an intermediate item "survivor eyepiece", which requires one of either lens, and then the telescope would require a high-quality lens and an eyepiece. Overall, the requirements are the same, but neither recipe has any overlap.

Note: this is different from recipe steps, which split a single recipe into named phases with per-step tools and proficiencies but do not create intermediate items.

For more details, see this pull request and the related issue.

Item disassembly

Introduction

This document describes various methods of taking apart items in the game, as well as how these work and how the approach should be balanced. For furniture/terrain DECONSTRUCTION you're out of luck because we don't have a guide for it.

The three methods

There are three* general methods of having items taken apart into other items:

  • Uncraft recipes
  • Reversible crafting recipes
  • Salvaging (or Cutting Up)

The first two are able to be altered through JSON, while the other can only be enabled or disabled, with the type and amount of items it gives being calculated by the game from the item's JSON definition.

*Technically you could argue that butchery is a separate method as well, but given its highly unique nature, and the fact that it's not possible for it to violate the conservation of mass, it has been omitted for the purpose of this file.

Uncraft recipes

They are the most common and well known way of defining an item disassembly. With a syntax not unlike that of regular crafting recipes, they're fairly self-explanatory and easy to grasp.

jsonc
  {
    "result": "bio_blood_filter",
    "type": "uncraft",
    "activity_level": "LIGHT_EXERCISE",
    "skill_used": "electronics",
    "difficulty": 7,
    "time": "50 m",
    "using": [ [ "soldering_standard", 20 ] ],
    "tools": [ [ [ "boltcutters", -1 ], [ "toolset", -1 ] ] ],
    "qualities": [ { "id": "SCREW", "level": 1 } ],
    "components": [ [ [ "burnt_out_bionic", 1 ] ] ],
    "flags": [ "BLIND_HARD" ]
  },
FieldMeaning
result(Mandatory) The ID of the item being disassembled
type(Mandatory) The type of the recipe; if we want an uncraft recipe, it should always be uncraft
activity_level(Mandatory) How energy intensive of an activity this craft is. Options are NO_EXERCISE, LIGHT_EXERCISE, MODERATE_EXERCISE, BRISK_EXERCISE, ACTIVE_EXERCISE, EXTRA_EXERCISE
skill_usedSkill trained and used for success checks
difficultyDifficulty of success check, connected to skill_used
time(Mandatory) Time to perform the recipe; can specify in minutes, hours etc.
usingRequirement IDs and multipliers of tools and materials used
qualitiesQualities of tools needed to perform the disassembly
toolsSpecific tools needed to perform the disassembly
components(Mandatory) Items produced from completing the disassembly recipe; Items cannot have UNRECOVERABLE flag
flagsA set of strings describing boolean features of the recipe; Supports BLIND_EASY and BLIND_HARD

Things to note:

  • Simple disassemblies, such as smashing a skull or simply cutting apart metal with a hacksaw, should likely not use any skills
  • It is not possible to obtain items with UNRECOVERABLE flag through disassembly, either through uncraft recipes or reversible crafting recipes, however, defining them in the components field does not cause errors. They will simply be ignored
  • copy-from support for uncraft recipes is extremely limited and it is best to avoid it where possible
  • for the purposes of keeping things easy to find, future uncraft recipes should be included inside the uncraft folder inside of data\json
  • uncraft recipes do not support component lists, the syntax shown below does NOT work - only the first item read by the game has any effect
jsonc
"components": [ [ [ "burnt_out_bionic", 1 ], [ "scrap", 1 ] ] ],
  • due to not supporting component lists, and not remembering what items were used to craft the item that is being disassembled, uncraft recipes can be used to transmute resources by the players if not used alongside reversible crafting recipes - more info on that in Reversible crafting recipes
  • it is technically possible to define proficiencies for uncraft recipes, but they currently have no effect
  • similarly, it is possible to define a skills_required field for uncraft recipes, but it has no effect either

Reversible crafting recipes

A reversible recipe and an uncraft recipe are almost indistinguishable in game, with the only potential way to tell them apart being items crafted by the player through a reversible crafting recipe may yield different items upon disassembly than items of the same ID found spawned in the world. Having said that, they are quite different from the JSON side.

The first thing that comes to mind is - reversible crafting recipes are created through a singular field. Adding "reversible": "true to the recipe definition automatically creates a disassembly for the item the recipe is for. It is worth noting that unlike uncraft recipes, reversible crafting recipes support ingredient lists, but only in regards to items crafted by the player. If the item in question was crafted by the player, disassembling it will yield items used to craft it. If the item was spawned in the world, however, the disassembly will instead yield the first component combination the game reads off the recipe definition. Reversible crafting recipes also have their time, skills used, difficulty, and tools taken from the same crafting recipe they're created as a part of. Out of all those, time is the only one that can be overwritten directly in the crafting recipe. "reversible": { "time": "3 m" }, will make the disassembly take 3 minutes, regardless of how long the craft takes.

Things to note:

  • Reversible crafting recipes cannot have byproducts! Trying to make a recipe with byproducts reversible will not work.
  • On the other hand, it is possible to make recipes using result_mult reversible, but this will inadvertently cause infinite resource generation, as full recipe ingredients will be obtained from disassembling a single result item
  • All items used to craft the item will be obtained through the disassembly, with the exception of items with the UNRECOVERABLE flag
  • While unlike with uncraft recipes it is impossible to transmute materials through those, it is very easy to make nonsensical disassemblies through this method when it comes to required tools. Consider using the two methods alongside one another.
  • Making a recipe that crafts a specific item variant reversible will result in all variants of this item using the same disassembly

Using uncrafts and reversible crafting together:

  • Either of those methods will work alone, but they also interact if both are defined
  • If a crafting recipe has reversible: true, and the item has a manually defined uncraft recipe, what will happen is the uncraft recipe will be able to return components used to craft the specific item. In a case like this, the uncraft will supply all information exception for the components used to craft that item - this means that this combination can remember components (overcoming uncraft's weakness) AND avoid nonsensical tool requirements or difficulty levels (overcoming reversible crafting's weakness)

Salvaging / Cutting Up

This process is largely hardcoded, with the JSON side only consisting of defining whether a specific material is salvageable, and possible per-item salvaging disabling through flags. The only way to make an item that's normally salvageable not-salvageable is by either editing its material or adding the NO_SALVAGE flag.

To salvage an item with at least one salvageable material you must have a tool with the CUTTING quality. This process can only grant a singular type of resource (per material), with the amount calculated from the item's weight. How long the process takes is calculated from the item's size as well.

Any material with a salvaged_into field defined is considered salvageable.

Things to note:

  • A tool with 1 CUTTING quality is enough to salvage any item which is at least partially the listed material. As such, items that should require more powerful tools should be given the NO_SALVAGE flag
  • If an item has more than one material that can be salvaged, it will give resources corresponding to all of its materials. However, if the item is partially a material that cannot be salvaged, that material will be ignored, and no resources from it will be given
  • It is the only listed here method of taking an item apart which cannot be done through the disassemble option or menu
  • It does not work with charges well. Multiple charge-based item will be treated as a singular bigger item for the purpose of salvaging. 100 charge-based items weighing 1g equals to 1 normal item weighing 100g

Choosing the method

So you want to make a new disassembly recipe? First of all, I'm proud of you, but you probably should have some vague idea of which of the methods above you should pick, because they all have their pros and cons. Except salvaging, that's all cons - we're ignoring it for this part of the documentation.

You should use reversible crafting recipes if:

  • The item has a crafting recipe in the first place, which should be fairly self-explanatory
  • The recipe for this item does not produce byproducts
  • The tools needed for the craft make sense to be required for its disassembly as well. This disqualifies most of blacksmithing and metalworking as a whole, because needing a crucible to take apart tongs is ridiculous

If the following three are NOT true, you likely want a manually defined uncraft recipe, as you can omit skills and define tools required as you please.

Closing words (Or what you should remember when working with item disassembly in general)

  1. Conservation of mass is pretty damn important. You won't always be able to make sure there is no mass loss or generation - it is just not possible in more complex crafts due to our generic nature of resource items - but you should still try to minimize the amount of mass lost or generated whenever you're working on a recipe. After getting your recipe done, calculate the mass of the ingredients and compare it to the mass of the item to make sure you're not violating physics.
  2. Double check the syntax when it comes to uncraft recipes. They do not support lists, but the game doesn't realize that. You will not get an error, it is only on YOU to catch your missing brackets.
  3. It is not possible to have both an uncraft and a reversible recipe defined for the same item. The same goes for more than one uncraft. If this occurs, the game will only read one and ignore everything else altogether.