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 Associationand 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_modloses 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
maleandfemale, the other body gets the same mesh when the vanilla addon has a mesh for it.male_first_personandfemale_first_personset the first person meshes. An addon that keeps a vanilla first person mesh gives the warningITEM_VANILLA_MESH. - The build sets the flag
Has FaceBones Modelof a mesh when the file<mesh>_faceBones.nifis beside the mesh inassets/. 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
fromrecord 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.