Guides/13

Item files

Describe a weapon, a piece of armor, ammunition or a misc item in a short file, and let esx build make the records.

An item file describes one item of a mod: its name, the vanilla record that it starts from, its values, its meshes, its sounds and its recipe. esx build makes the records. You do not write batch operations for a weapon or for a piece of armor.

An item file is items/<name>.toml in the project folder. The build expands the item files in file name order, before the records files.

Start from a vanilla record

esx item new writes a starter file. Each value in it is the value of the vanilla record, so the file builds as it is.

esx --data '/path/to/Fallout 4/Data' item new weapon 10mm --name 'Service pistol' -o mymod/items/10-pistol.toml
esx item new weapon 10mm --name 'Service pistol' --standalone -o mymod/items/10-pistol.toml
esx item new armor ClothesMinutemanHat --name 'Bounty hunter hat' -o mymod/items/30-hat.toml
esx build mymod

The kinds are weapon, armor, ammo and misc. Without -o the command prints the file. --standalone is for a weapon with its own parts. It writes one [part.NAME] table for each part of the default combination of the vanilla weapon, the ammunition as a new record, and the sound keyword with its sound maps.

--standalone --all-parts writes one table for each part of the masters that fits the vanilla weapon, with its vanilla recipe and a loose mod. For the vanilla 10mm that is 36 part tables, and the file builds as it is into 120 records:

esx item new weapon 10mm --name 'Service pistol' --standalone --all-parts -o mymod/items/10-pistol.toml

A part fits the weapon when its filter (MNAM) has a family keyword of the weapon. A mod collection gets no table. Remove the tables of the parts that your weapon does not need.

A weapon

A weapon without a [part.NAME] table shares the parts of the vanilla weapon. It is a copy of the vanilla weapon with other values:

kind = "weapon"
name = "Service pistol"
from = "10mm"
damage = 30
capacity = 8
weight = 3.5
value = 120
ammo = "Ammo10mm"

A weapon with part tables has its own part family. This is the pattern for a gun with its own meshes:

kind = "weapon"
name = "Service pistol"
from = "10mm"
damage = 30
capacity = 8
weight = 3.5
value = 120
ammo = "Ammo10mm"

[part.Receiver]
from = "mod_10mm_Receiver_Standard"
name = "Service receiver"
model = 'Weapons\Service\Receiver.nif'

[part.Grip]
from = "mod_10mm_Grip_Standard"
name = "Service grip"
model = 'Weapons\Service\Grip.nif'

[part.Barrel]
from = "mod_10mm_Barrel_VeryShort"
name = "Service barrel"
model = 'Weapons\Service\Barrel.nif'

[part.Mag]
from = "mod_10mm_Mag_Small"
name = "Service magazine"
model = 'Weapons\Service\Mag.nif'

[part.Scope]
from = "mod_10mm_Scope_SightsIron"
name = "Service sights"

[part.Muzzle]
from = "mod_Null_Muzzle"

[recipe]
workbench = "WorkbenchChemlab"
category = "RecipeUtility"
description = "Make a service pistol."
components = { c_Steel = 6, c_Screws = 2, c_Wood = 1 }

From these 41 lines the build makes 9 records with 72 operations: the family keyword ServicePistolFamily, the weapon ServicePistol, six parts and the recipe. For a weapon with parts the build does this:

  • It makes the family keyword with the type Mod Association and puts it on the weapon in place of the vanilla family keyword.
  • It copies each part and sets the filters of the copy to the new family. A part without the key loose_mod loses the link to the vanilla loose mod.
  • It replaces the object template of the weapon with a default combination that has one part for each slot, so that no vanilla part stays on the weapon.
  • It removes the texture hashes of each model that the file changes.

The table [ammo] makes new ammunition for the weapon, and the table [sounds] makes sound records and a sound keyword. esx item new weapon --standalone writes both.

Alternative parts, recipes and loose mods

The slot of a part is its attach point: attach_point of the table, else the attach point of the vanilla part. No key names a slot. Two part tables with one attach point are alternative parts, and the default combination has one of them.

kind = "weapon"
name = "Service pistol"
from = "10mm"

[part.Receiver]
from = "mod_10mm_Receiver_Standard"
recipe = { components = { c_Gears = 1, c_Oil = 2, c_Steel = 2, c_Screws = 1 } }
loose_mod = { value = 20 }

[part.Grip]
from = "mod_10mm_Grip_Standard"
recipe = { components = { c_Steel = 1, c_Wood = 2 } }
loose_mod = {}

[part.Mag]
from = "mod_10mm_Mag_Small"
recipe = { components = { c_Steel = 2 } }
loose_mod = {}

[part.Barrel]
from = "mod_10mm_Barrel_VeryShort"
default = true
recipe = { components = { c_Steel = 2 } }
loose_mod = {}

[part.BarrelLong]
from = "mod_10mm_Barrel_Short"
name = "Long service barrel"
recipe = { components = { c_Steel = 3, c_Screws = 1 }, perks = ["GunNut01"] }
loose_mod = {}

[part.Sights]
from = "mod_10mm_Scope_SightsIron"
recipe = { components = { c_Adhesive = 1, c_Steel = 1 } }
loose_mod = {}

[part.Reflex]
from = "mod_10mm_Scope_SightReflex"
recipe = { components = { c_Aluminum = 2, c_Glass = 1 }, perks = ["GunNut02"] }
loose_mod = {}

[part.NoMuzzle]
from = "mod_Null_Muzzle"
recipe = {}

[part.Suppressor]
from = "mod_10mm_Muzzle_Suppressor"
recipe = { components = { c_Aluminum = 6, c_Adhesive = 5, c_Plastic = 4, c_Screws = 3 }, perks = ["GunNut02"] }
loose_mod = { value = 22 }

[template.Scoped]
keyword = "if_tmp_Pistol_Scoped"
parts = ["BarrelLong", "Reflex"]

From these 53 lines the build makes 28 records with 173 operations: the family keyword, the weapon, 9 parts, 9 recipes and 8 loose mods. The default combination has 6 parts: Receiver, Grip, Mag, Barrel, Sights and NoMuzzle. The combination Scoped has BarrelLong and Reflex in place of Barrel and Sights.

The default part of a slot

Tables of the slot Default part
One part That part.
One part has default = true That part.
No part has default The first part of the slot in the order of the file.
Each part has default = false None. The slot stays empty, and the build gives the warning ITEM_SLOT_EMPTY.

Two parts of one slot with default = true are an error:

item file mymod/items/10-pistol.toml: `part.BarrelLong.default` is true for two parts of the slot ap_gun_Barrel: Barrel and BarrelLong. One part of a slot is in the default combination

The recipe of a part

No record comes without a key. A part without the key recipe has no recipe.

Key of recipe Use
components A map from a component to a count. Without it the recipe is free: recipe = {}. The vanilla null muzzle has a free recipe.
perks A list of perk editor IDs. Each perk is one HasPerk condition.
id The editor ID. Default: <part id>Recipe.
set, remove Element paths, as on each record.

recipe = false says that the part has no recipe by intent. The keys workbench and category are errors in the recipe of a part: a vanilla part recipe has neither.

The recipe is a new COBJ record with the part in CNAM, a count of 1, the components and the conditions. It has the same fields as the vanilla recipe co_mod_10mm_Muzzle_Suppressor.

The loose mod of a part

A loose mod is the misc item that the workbench gives when another part takes the place of the part. The build makes it as a copy of a vanilla loose mod, and the part names it in LNAM.

Key of loose_mod Use
from The vanilla loose mod (MISC) to copy. Default: the loose mod of the vanilla part. When the vanilla part has none, from is necessary.
name Default: the name of the weapon, a space, the name of the part.
value, weight Default: the values of the vanilla loose mod. The build writes value as it is.
id The editor ID. Default: <part id>LooseMod.
set, remove Element paths, as on each record.

Without the key loose_mod, the part has no loose mod.

Templates

A [template.NAME] table is one more combination of the object template. A leveled list selects it with the keyword.

Key Use
keyword An instantiation filter keyword of a master, for example if_tmp_Pistol_Scoped.
parts The part tables that differ from the default combination. For each slot the template has the named part, else the default part.
level_min, level_max The level range of the combination.

The name of the table is the name of the combination. Two parts of one slot in parts, or a name that is not a part table, are errors.

More slots, and two weapons with one set of parts

add_slots of the weapon adds attach point keywords to the slots of the weapon (APPR). add_slots of a part adds them to the slots of the part.

parts_of gives a weapon the parts of another weapon item. The weapon makes no part and no family. It gets the family keyword and the default parts of that item:

# items/20-carbine.toml
kind = "weapon"
name = "Service carbine"
from = "10mm"
parts_of = "10-pistol"

The other file must sort before this file. A weapon with parts_of and a [part.NAME] table is an error. A [template.NAME] table of the weapon names the parts of the other item.

Warnings of the parts

Code Condition
ITEM_SLOT_EMPTY A slot has parts and none is the default part.
ITEM_PART_NO_RECIPE A slot of the weapon has two or more parts, and a part of the weapon has no recipe key. The message lists the parts.
ITEM_PART_NO_LOOSE_MOD A part has a recipe with components and no loose_mod, and the vanilla part has a loose mod.

No game test proves the rules of the workbench yet. The records are copies of the vanilla record set, and a person must check the workbench menu.

Derive one item from another

An item with extends has each key of the other item and gives only the differences. A table joins the table of the other item key by key.

# items/20-carbine.toml
extends = "10-pistol"
name = "Service carbine"
damage = 38
weight = 5.0

[part.Barrel]
name = "Carbine barrel"
model = 'Weapons\Service\LongBarrel.nif'

[recipe]
description = "Make a service carbine."
components = { c_Wood = 4 }

The carbine gets its own records: ServiceCarbineFamily, ServiceCarbine, six parts and ServiceCarbineRecipe. Its recipe has the steel and the screws of the pistol and 4 wood. A weapon that extends a weapon uses the ammunition and the sounds of that weapon. It does not make them again.

Armor and clothing

kind = "armor"
name = "Bounty hunter hat"
from = "ClothesMinutemanHat"
value = 20
weight = 0.3
world_model = 'MyMod\Hat\Hat_GO.nif'

[addon]
male = 'MyMod\Hat\Hat_M.nif'
female = 'MyMod\Hat\Hat_F.nif'

[recipe]
workbench = "WorkbenchChemlab"
category = "RecipeUtility"
components = { c_Leather = 3, c_Cloth = 2 }

The build makes the armor addon BountyHunterHatAddon, the armor BountyHunterHat and the recipe BountyHunterHatRecipe. The slots and the races are those of the vanilla armor.

  • [addon] is a copy of the first addon of the vanilla armor, with your meshes. Without the table, the armor keeps the vanilla addons.
  • With one of male and female, the other body gets the same mesh when the vanilla addon has a mesh for it. male_first_person and female_first_person set the first person meshes. An addon that keeps a vanilla first person mesh gives the warning ITEM_VANILLA_MESH.
  • The build sets the flag Has FaceBones Model of a mesh when the file <mesh>_faceBones.nif is beside the mesh in assets/. It clears the flag when the file is not there.

Ammunition, misc items and sounds

kind = "ammo"
name = "Service rounds"
from = "Ammo10mm"
model = 'Ammo\Service\Rounds.nif'
casing_model = 'Ammo\Service\Casing.nif'
kind = "misc"
name = "Feral ghoul finger"
from = "Pencil"
model = 'MyMod\Props\Finger.nif'

kind = "sounds" makes sound descriptors, a sound keyword and sound maps for one or more weapons. A weapon names the file: sounds = "20-sounds". esx help-topic items lists each key.

Editor IDs

The editor IDs come from the name. prefix is the first part of each editor ID. Its default is the letters and the digits of name, each word with a capital first letter: “Service pistol” gives ServicePistol.

Record Editor ID
The weapon, the armor, the ammunition or the misc item id, default <prefix>
Part family keyword family, default <prefix>Family
Part [part.Barrel] <prefix>Barrel
Recipe of a part <part id>Recipe, for example <prefix>BarrelRecipe
Loose mod of a part <part id>LooseMod, for example <prefix>BarrelLooseMod
Armor addon <prefix>Addon
Ammunition of a weapon <prefix>Ammo
Sound keyword <prefix>Sound
Recipe <prefix>Recipe; for the ammunition of a weapon <ammo id>Recipe

Each table has the key id to set its editor ID. A sound descriptor and a sound map have the editor ID that you write as their key.

What the keys do not cover

Each record has the keys set and remove, with element paths:

set = { 'DNAM\Speed' = 1.1 }
remove = ["EITM"]

A records file in records/ runs after the item files. It can change a record that an item file made.

See the operations

Nothing is hidden. The build writes the operations of each item file to build/records/items/<name>.json, as a batch document. esx item expand prints them without a build:

esx item expand mymod --item 30-hat
{"op": "copy", "record": "edid:AAClothesMinutemanHat", "from": "Fallout4.esm", "as_new": true, "edid": "BountyHunterHatAddon"}
{"op": "set", "record": "edid:BountyHunterHatAddon", "path": "Biped Model\\Male\\MOD2", "value": "MyMod\\Hat\\Hat_M.nif"}
{"op": "remove_element", "record": "edid:BountyHunterHatAddon", "path": "Biped Model\\Male\\MO2T"}

The report gives the key of the item file for each operation in keys.

To continue by hand, write the operations as records files and remove the item files:

esx item expand mymod --output mymod/records

The build then makes the same plugin from the records files.

Animations

An item file has no animation data. The animations of a weapon are in its behavior source, behavior/<name>/<name>.bhv. The source names the weapon by its editor ID:

weapon ServicePistol like Anims10mm {

Errors

An error names the file, the key and the keys of the table:

item file mymod/items/10-pistol.toml: `part.Barrel.mesh` is not a key of a part. The keys are id, from, name, model, attach_point, default, add_slots, properties, keywords, set, remove, recipe, loose_mod
Code in error.details.reason Cause
ITEM_FILE_INVALID An unknown key, a value of the wrong type, or a key that is missing.
ITEM_SOURCE_NOT_FOUND A from record is not in the masters, or it is another type of record.
ITEM_DUPLICATE_ID Two records have the same editor ID.
ITEM_OPERATION_FAILED An operation failed in the build. The message has the item file and the key.

Limits

  • An armor item changes one addon. The other addons of the vanilla armor stay.
  • A part can get a keyword only when the vanilla part has a Keywords property to copy.
  • A mod collection, a legendary template and a new attach point keyword need a records file.
  • An item file makes no leveled list. A template gives the keyword that a list of a records file selects.
  • A from record is a record of a master. A record that the project makes cannot be the source of a copy.
  • The item files run before the records files. An item cannot name a record that a records file makes.