doc/JSON/ITEM_CRAFT_AND_DISASSEMBLY.md
Contents
Crafting recipes are defined as a JSON object with the following fields:
"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.
"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:
"batch_time_factors": { "mode": "linear": "setup": "12 m" },
"batch_time_factors": { "mode": "linear": "setup": "12 m", "max": 20 },
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".
Each entry in the "steps" array is an object with these fields:
"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.
{
"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" ] ] ]
}
]
}
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.
Similar recipes may instead be nested allowing you to save space in the UI. This is done as such:
{
"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:
"category": "CC_*",
"subcategory": "CSC_*_NESTED",
The tool quality and component requirements for a recipe may be expressed in a combination of several ways, with these JSON fields:
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:
"components": [
[ [ "spear_wood", 1 ] ]
]
A single component may also have substitutions; for instance, to allow crafting from one "spear_wood" or one "pointy_stick":
"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:
"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:
"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.
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:
[
{
"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:
"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:
"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:
{
"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:
{
"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:
{
"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.:
{
"id": "bone_sturdy",
"type": "requirement",
"extend": {
"components": [
[
[ "frost_bone_human", 1 ],
[ "alien_bone", 1 ]
]
]
}
}
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.
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.
There are three* general methods of having items taken apart into other items:
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.
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.
{
"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" ]
},
| Field | Meaning |
|---|---|
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_used | Skill trained and used for success checks |
difficulty | Difficulty of success check, connected to skill_used |
time | (Mandatory) Time to perform the recipe; can specify in minutes, hours etc. |
using | Requirement IDs and multipliers of tools and materials used |
qualities | Qualities of tools needed to perform the disassembly |
tools | Specific tools needed to perform the disassembly |
components | (Mandatory) Items produced from completing the disassembly recipe; Items cannot have UNRECOVERABLE flag |
flags | A set of strings describing boolean features of the recipe; Supports BLIND_EASY and BLIND_HARD |
Things to note:
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 ignoredcopy-from support for uncraft recipes is extremely limited and it is best to avoid it where possibleuncraft folder inside of data\json"components": [ [ [ "burnt_out_bionic", 1 ], [ "scrap", 1 ] ] ],
skills_required field for uncraft recipes, but it has no effect eitherA 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:
result_mult reversible, but this will inadvertently cause infinite resource generation, as full recipe ingredients will be obtained from disassembling a single result itemUNRECOVERABLE flagUsing uncrafts and reversible crafting together:
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)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:
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 flagdisassemble option or menuSo 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:
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.