Configuration

29 min readUpdated 2 weeks ago

Configuration

The inventory keeps its settings in three files inside the resource folder:

  • micio/config/core.lua: debug output, interface language, the reserved slot rescue.
  • micio/config/grid.lua: grid sizes and durability stacking.
  • micio/config/ui.lua: interface, HUD, holding and giving, renaming, tooltip metadata.

ML Clothing keeps its own two files:

  • shared/config.lua: clothing slots, bags, armor plates, wear, bag blacklist.
  • shared/invadmin_config.lua: the admin panel.

Every other file of your ox_inventory install keeps working the way it does today, data/ included.

The admin panel has a Settings tab that reads the three inventory files and writes them back without stopping the server. Each key is shown with the one line spec written next to it in the file. A value is accepted only in the type the key already holds, and Language, UI.rarityStyle, UI.Hud.style and UI.Give.consent are offered as closed lists. The file is backed up before every change. The inventory reads these files at start, so restart the resource for a saved value to take effect.

Core

micio/config/core.lua
1MicioConfig.Debug = false
2
3MicioConfig.Rescue = {
4    enabled = true,
5    report = true,
6}
  • Debug, default false. Prints boot and slot rule detail to the server console.
  • Rescue.enabled, default true. Items sitting in a reserved slot are moved into free grid cells when the character loads, once per character. An item that finds no free cell stays in the slot it was in, and if the pass cannot complete, every item is left where it was saved.
  • Rescue.report, default true. Prints the capacity comparison at boot.

Grid

micio/config/grid.lua
1MicioConfig.Grid = {
2    playerCols = 8,
3    playerRows = 4,
4    secondaryCols = 6,
5    dropCols = 6,
6    dropRows = 4,
7    durabilityStackTolerance = 5,
8    durabilityStackPerItem = {},
9}
  • playerCols, default 8. Columns in the pocket grid.
  • playerRows, default 4. Rows in the pocket grid.
  • secondaryCols, default 6. Columns of the right hand panel for shops, vehicle storage and another player. A stash or container sizes itself from its own slot count instead, unless the script that created it set its columns: exports.ox_inventory:RegisterStash(id, label, { slots = 30, cols = 6 }, weight), or exports.ox_inventory:mlSetInventoryCols(id, cols) on a stash you did not register yourself.
  • dropCols, default 6. Columns of a bag left on the ground.
  • dropRows, default 4. Rows of a bag left on the ground.
  • durabilityStackTolerance, default 5. Percentage points two durability values may differ and still stack in one slot. 0 stacks only identical values.
  • durabilityStackPerItem, default {}. Per item override of the tolerance above, written as ['sandwich'] = 25.

Player capacity follows the grid: playerCols times playerRows cells of pocket space, with the reserved slots on top of that count. Size the inventory here rather than with a slot count.

A grid under 8 cells, or a playerCols or playerRows that is not a whole number of at least 1, is refused at boot. A warning names micio/config/grid.lua and 8 by 4 is used instead. The reserved slots sit outside the grid and never constrain it. secondaryCols, dropCols and dropRows fall back to 6, 6 and 4 the same way, without a warning.

Interface

micio/config/ui.lua
1MicioConfig.UI = {
2    defaultTheme = '#00d4aa',
3    rarityStyle = 'border',
4    enableThemePicker = true,
5    virtualPed = true,
6    stockBadge = false,
7    walkWhileOpen = true,
8    family = 'tactical',
9    families = { 'tactical', 'glass', 'slate' },
10    defaultScale = 100,
11    defaultOpacity = 100,
12    layoutVersion = 1,
13    layoutStudio = false,
14}
  • defaultTheme, default '#00d4aa'. Accent colour a player starts with, any hex value.
  • rarityStyle, default 'border'. How rarity shows on a slot. Accepts border, full or glow.
  • enableThemePicker, default true. Lets each player pick an accent colour. Turn it off to keep everyone on defaultTheme.
  • virtualPed, default true. Shows the live character preview next to the inventory. Needs ML Clothing running. If ox_inventory:virtualPed is already set in server.cfg, that convar wins and this key is ignored: remove the line to drive the preview from here.
  • stockBadge, default false. Marks stackable items with a badge on the slot and a line in the tooltip.
  • walkWhileOpen, default true. Movement keys and sprint stay active while the inventory is open. While a text field has the cursor the keys type. false holds the player in place.
  • family, default 'tactical'. Style family a player starts with.
  • families, default { 'tactical', 'glass', 'slate' }. Families offered in the settings. Each name is a file in web/themes/. A saved choice missing from the list falls back to family.
  • defaultScale, default 100. Interface scale a player starts with, percent.
  • defaultOpacity, default 100. Background opacity a player starts with, percent.
  • layoutVersion, default 1. Raise it and every player gets the panel positions from Panels once, their own saved positions cleared.
  • layoutStudio, default false. Adds the layout studio button to the settings. See below.

Default layout

micio/config/ui.lua
1MicioConfig.UI.Panels = {
2    pockets = { x = 28, y = 3.7 },
3    clothing = { x = 2, y = 4 },
4    weapons = { x = 28, y = 36 },
5    armor = { x = 68, y = 37 },
6    bag = { x = 68, y = 3.7 },
7    secondary = { x = 64.6, y = 55.6 },
8    shop = { x = 64.6, y = 40 },
9    crafting = { x = 64.6, y = 40 },
10    loot = { x = 64.6, y = 55.6 },
11    settings = { x = 40, y = 20 },
12}

Top left corner of each panel as a percent of screen width and height, so one layout holds on every resolution. A player who drags a panel keeps that position on their own machine until you raise layoutVersion.

To build the layout in game: set layoutStudio = true, restart the resource, open the settings and press Open next to Layout studio. Every panel appears at once with sample items, the shop and the crafting bench included. Drag them where you want them, set the family, the accent colour, the scale and the opacity from the settings, then press Copy layout. The snippet lands in the clipboard and in the F8 console, with layoutVersion already raised by one. Paste it at the end of micio/config/ui.lua, where it overrides the keys above it, set layoutStudio back to false and restart.

Style families

Three families ship in web/themes/, one CSS file each: tactical.css, dark; glass.css, light and translucent, tinted by the accent colour; slate.css, flat neutral grey with square corners. A family is a set of CSS custom properties on :root[data-family='name'] plus any extra rules. To add one, copy a file under a new name, edit it and add the name to families. The file is loaded at start and on every switch.

Panel and slot backgrounds are computed from the accent colour and the background opacity, starting from the bases the family declares. A base is a grey level from 0 to 255 and an alpha from 0 to 1:

web/themes/glass.css
1:root[data-family='glass'] {
2    --fam-tint: 0.18;
3    --fam-bg-primary: 240 0.84;
4    --fam-bg-secondary: 236 0.86;
5    --fam-bg-slot: 255 0.62;
6    --fam-bg-slot-hover: 255 0.9;
7    --fam-bg-slot-empty: 250 0.34;
8    --fam-bg-overlay: 246 0.97;
9}

--fam-tint moves each grey toward the accent colour: 0 neutral, 1 the accent itself. The alpha is scaled by the background opacity. --fam-alpha-floor sets the lowest point of that scale, so a light family keeps its text readable at the bottom of the slider: glass uses 0.85. A missing base takes the tactical value.

The tokens every family defines:

Property — What it paints

--surface-1 — Panel backgrounds

--surface-2 — Slots and cards

--surface-3 — Hovered or raised elements

--surface-empty — Empty slots

--line — Hairlines and borders

--line-strong — Borders of hovered or focused elements

--ink — Primary text

--ink-dim — Secondary text

--ink-faint — Placeholder text and disabled controls

--shadow — Shadow colour under floating elements

--backdrop — Full-screen dim behind dialogs

--accent-primary and --accent-rgb come from the player's choice in the settings. Rarity colours, durability gradients and ammo tones are the same in every family.

Screen effects

micio/config/ui.lua
1MicioConfig.UI.Effects = {
2    enabled = true,
3    blur = false,
4    tint = true,
5    vignette = 0.6,
6}
  • enabled, default true. Vignette behind the open inventory; the character preview stays clear. Players can switch it off in the settings.
  • blur, default false. true blurs the game world while the inventory is open, character preview included. ML Inventory drives the blur itself, so inventory:screenblur can stay false.
  • tint, default true. Vignette in the player's accent colour instead of black.
  • vignette, default 0.6. Edge darkness, 0 to 1.

Keys

micio/config/ui.lua
1MicioConfig.UI.Keys = {
2    wheel = 'z',
3    hotkeys = { '1', '2', '3', '4', '5' },
4    hud = 'TAB',
5}
6
7MicioConfig.UI.Wheel = {
8    enabled = true,
9}
  • wheel, default 'z'. Opens the item wheel. Rebindable per player in the FiveM keybind settings.
  • hotkeys, default { '1', '2', '3', '4', '5' }. Keys of the five quick slots, in order. Rebindable per player.
  • hud, default 'TAB'. Shows the HUD while Hud.mode is 'key'. Rebindable per player.
  • Wheel.enabled, default true. false removes the radial wheel and its key. The quick slots and their keys stay.

The keys for the item in hand are under Holding and giving items below. The key that opens the inventory itself belongs to ox_inventory and stays in its inventory:keys convar.

micio/config/ui.lua
1MicioConfig.UI.Give = {
2    consent = 'prompt',
3    timeout = 15,
4    distance = 5.0,
5    acceptKey = 'Y',
6    declineKey = 'N',
7}
  • consent, default 'prompt'. prompt opens a dialog on the receiver's screen with the giver's name, the item image, label and count, and waits for the answer. auto hands the item over at once, also when the Give block is absent.
  • timeout, default 15. Seconds the receiver has to answer. When the time runs out the offer lapses and the giver is told.
  • distance, default 5.0. Metres the two players may be apart while an offer is open. Past that the offer is refused before it starts, and an offer already waiting is cancelled and both players are told. Values are held between 1.0 and 50.0.
  • acceptKey, default 'Y'. Accepts an offer. Each player can rebind it in the FiveM keybind settings.
  • declineKey, default 'N'. Declines an offer. Also rebindable.

The dialog sits in the middle of the screen with an Accept and a Decline button, the countdown, and the two keys printed under the buttons as shortcuts. It works with the inventory closed: the offer takes the mouse cursor while it waits, the player keeps walking and driving, and the cursor goes back to the game as soon as the dialog closes. Escape declines.

Give from the item context menu and the handover of the item in hand both go through this. The server holds the item until the answer arrives, then checks that both players are still connected, still within distance and still holding the same item in the same slot before it moves anything.

After a declined or lapsed offer the giver waits a few seconds before offering again.

While prompt is on, the ox_inventory:giveItem server event is refused: another resource cannot move an item out of a player's pockets without the receiver seeing the offer. Resources that hand out items should use exports.ox_inventory:AddItem instead.

HUD

The HUD is drawn while the inventory is closed: a card for the weapon in slot 1, a slimmer card for slot 2, and the five quick slots of the item wheel. The card of the weapon in hand takes the accent colour and shows magazine and reserve, red with an empty magazine, yellow with no reserve. The other weapon is dimmed. A weapon drawn from any other slot gets its own card while it is in hand. Each quick slot shows the item, its count, its wear and its key.

micio/config/ui.lua
1MicioConfig.UI.Hud = {
2    enabled = true,
3    style = 'tactical',
4    locked = false,
5    x = 97,
6    y = 96,
7    scale = 100,
8    emptySlots = true,
9    mode = 'always',
10    showSeconds = 5,
11}
  • enabled, default true. Draws the HUD.
  • style, default 'tactical'. tactical dark cards with a rarity edge, classic rounded cards in the inventory colours, minimal flat, rarity cards filled with the rarity colour, glass light translucent cards. Unknown values fall back to tactical.
  • locked, default false. true holds every player to the style, position and scale set here.
  • x, default 97. Percent of screen width. 60 or more aligns the HUD to its right edge, 40 or less to its left edge, anything between centres it.
  • y, default 96. Percent of screen height for the bottom edge of the HUD.
  • scale, default 100. Percent, 60 to 140.
  • emptySlots, default true. false hides empty quick slots.
  • mode, default 'always'. always keeps the HUD on screen. key shows it for showSeconds after Keys.hud or a quick slot key.
  • showSeconds, default 5. Seconds on screen in key mode. A new press restarts the count.

Edit mode closes the inventory and leaves the cursor on the HUD. Drag it, change the style, Enter or Done keeps the layout, Escape restores the previous one.

Holding and giving items

micio/config/ui.lua
1MicioConfig.UI.Hold = {
2    enabled = true,
3    useKey = 'G',
4    stowKey = 'X',
5    give = true,
6    giveKey = 'H',
7    giveDistance = 2.5,
8    blockControls = {},
9}
  • enabled, default true. Using an item that has portions takes it into the hand instead of consuming it at once.
  • useKey, default 'G'. Takes a portion from the item in hand. Each player can rebind it in the FiveM keybind settings.
  • stowKey, default 'X'. Puts the item in hand away.
  • give, default true. Allows handing the item in hand to a player standing in front.
  • giveKey, default 'H'. Starts aiming at the player to hand it to. Also rebindable.
  • giveDistance, default 2.5. Metres between the two players for the handover to be accepted.
  • blockControls, default {}. Extra control ids kept dead while an item is in hand. The keys above are already covered.

Renaming

micio/config/ui.lua
1MicioConfig.UI.Rename = {
2    enabled = true,
3    blacklist = {},
4}
  • enabled, default true. Lets players give an item their own name from its context menu. Every item is renamable while this is on.
  • blacklist, default {}. Item names players may not rename, written as { 'water', 'bandage' }.

Tooltip metadata

micio/config/ui.lua
1MicioConfig.UI.Tooltip = {
2    metadataWhitelist = { 'type', 'registered' },
3    showUnlisted = false,
4    metadataPerItem = {},
5}
  • metadataWhitelist, default { 'type', 'registered' }. Metadata keys shown in the tooltip. Keys registered through ox_inventory's displayMetadata are added on their own and need no entry here.
  • showUnlisted, default false. true shows every metadata key the item carries instead of the list above.
  • metadataPerItem, default {}. Per item override: ['note'] = { 'author' } adds keys for that item, true shows all of them, false shows none.

These keys are rendered elsewhere in the tooltip and are left out of the metadata list: description, image, imageurl, label, weight, durability, degrade, serial, ammo, components, rotated, source. A key whose value is empty, or is itself a table, is left out as well, whitelisted or not.

Per player settings

Accent colour, interface scale, background opacity, panel positions and the HUD position, style and scale are saved on the player's own machine. The values above are what a player who has changed nothing starts with. Hud.locked takes the HUD back under owner control.

Item fields

Grid size, rarity, category and stack cap are set per item in data/items.lua, and from the item editor in the admin panel.

  • width and height: cells the item takes in the grid. Set both or neither: if either one is missing or is not a number, the item is 1 by 1.
  • grid: shorthand for the two above, written as '2x1'. On ammo, weapon components and tints only the width is taken and the height stays 1.
  • maxstock: how many units fit in one slot. Without it a slot holds any amount of that item.
  • rarity: common, uncommon, rare, epic or legendary. Defaults to common, and drives the slot colour and the rarity sort.
  • category: the tab the item falls into. Defaults to misc.
  • description: the text under the item name in the tooltip. {key} in the text is replaced with the value of that metadata key, and a description in the item metadata wins over the one in the definition. The text is rendered with **bold**, *italic*, lines starting with - or * as bullets, and line breaks kept.
  • portions: number of servings the item is used in, from 2 to 20. The item goes into the hand instead of being consumed at once, each use takes one serving and applies its share of the item's status effects. Ignored on weapons, ammo, weapon components and tints.
  • use: food, drink or smoke. Sets the action label and the wording of the portions line in the tooltip. Without it the kind is read from the status effects the item applies.
  • decay and returndecay: with decay set and returndecay naming another item, one unit of that item is added to the inventory when the durability timer runs out.

ox_inventory's own item fields keep their meaning, displayMetadata included.

ox_inventory settings

Every inventory: convar you already set keeps its normal meaning.

On qb-core, set setr inventory:framework "qbx" in server.cfg. ox_inventory only accepts esx, nd, ox or qbx in that convar, and reads its database table names from it. With qbx set, qb-core support loads whenever qb-core is running and qbx_core is not. The server prints a warning at boot when qb-core runs with any other value.

The grid is the exception. inventory:slots, inventory:gridcols, inventory:gridrows, inventory:secondarygridcols, inventory:dropcols and inventory:dropslots are written at boot from micio/config/grid.lua, so a line for any of them in server.cfg has no effect.

inventory:imagepath and inventory:screenblur are only given a value when you have not set one: an unset inventory:screenblur is written as false. Setting it true while the character preview is on blurs the preview with the rest of the frame, and the server says so at boot. Pointing inventory:imagepath at a resource that is not on the server is also reported at boot: item icons go missing there and in every other script that reads the convar.

set vs setr

Use setr for a convar the interface reads and set for server only values such as webhooks and loot tables. A client facing convar written with plain set never reaches the client, which then falls back to its built in default with no error anywhere.

Language

The inventory reads its own strings from micio/translations/.

micio/config/core.lua
1MicioConfig.Language = 'auto'
  • Language, default 'auto'. Follows the ox:locale convar. Set a language code present in micio/translations/ to force one regardless of the convar.
server.cfg
1setr ox:locale "en"

ox_inventory's own messages keep coming from its locales/ folder.

ML Clothing reads its in game strings from its own locales/ folder, and 'auto' follows the same convar.

shared/config.lua
1Config.Language = 'auto'
  • Config.Language, default 'auto'. Follows the ox:locale convar, for the in game messages and for the admin panel alike. Set a language code present in locales/ to force one regardless of the convar.

ML Clothing configuration

General

shared/config.lua
1Config.Debug = false
  • Config.Debug, default false. Prints diagnostic lines to the console. Keep it false in production.

Notifications

Each entry toggles one player message. Set an entry to false to suppress it.

shared/config.lua
1Config.Notifications = {
2    outfit_updated = true,
3    clothing_slot_occupied = true,
4    plate_inserted = true,
5    bag_item_blocked = true,
6}
  • outfit_updated, default true. Tells the player the worn outfit was saved.
  • clothing_slot_occupied, default true. Tells the player an item was refused because the clothing slot it belongs to is taken.
  • plate_inserted, default true. Tells the player an armor plate went into the carrier.
  • bag_item_blocked, default true. Tells the player an item was refused entry into a bag by the bag blacklist.

Bags

shared/config.lua
1Config.BagEffect = true
2
3Config.Bag = {
4    DefaultWeight = 5000,
5    DefaultCols = 3,
6    DefaultRows = 3,
7
8    SpeedTable = {
9        { 0,  1.00 },
10        { 5,  0.97 },
11        { 10, 0.93 },
12        { 15, 0.88 },
13        { 18, 0.82 },
14        { 27, 0.75 },
15        { 36, 0.65 },
16        { 40, 0.55 },
17    },
18}
  • Config.BagEffect, default true. A worn bag slows the player down by the weight it carries.
  • Config.Bag.DefaultWeight, default 5000. Bag capacity in grams used when the worn bag drawable has no entry in Config.BagSizes.
  • Config.Bag.DefaultCols, default 3. Columns of the bag grid used with that default weight.
  • Config.Bag.DefaultRows, default 3. Rows of the bag grid used with that default weight.
  • Config.Bag.SpeedTable: pairs of { weight_kg, speed_multiplier }, interpolated linearly from the weight the bag carries. 0 kg gives full speed, 40 kg gives 0.55.

Bag sizes

shared/config.lua
1Config.BagSizes = {
2    female = {
3        [111] = { weight = 10000, cols = 4, rows = 4},
4        [125] = { weight = 15000, cols = 6, rows = 4},
5    },
6    male = {
7        [111] = { weight = 15000, cols = 6, rows = 4},
8        [113] = { weight = 10000, cols = 4, rows = 4},
9    },
10}
  • Config.BagSizes: maps the drawable index of the worn bag, per gender, to a stash size. Each entry sets weight in grams, cols and rows. A drawable with no entry falls back to Config.Bag.DefaultWeight and the default grid. The file ships a long table for male and female. The block above is an extract. Edit, add or remove indices to match your bag models.

Armor plates

shared/config.lua
1Config.SyncPlatesEveryHit = true
2Config.UseBrokenPlates = true
3Config.BrokenPlateItem = 'brokenplate'
4
5Config.HeavyDrawables = {
6    male = { 12, 13, 15, 18 },
7    female = { 22, 23, 25, 28 },
8}
9
10Config.Plates = {
11    ['heavyplate'] = 50,
12    ['lightplate'] = 25,
13    ['brokenplate'] = 0,
14}
  • Config.SyncPlatesEveryHit, default true. Plate health is written back on every damage event, so plate wear survives a disconnect at the cost of more frequent writes.
  • Config.UseBrokenPlates, default true. A plate that reaches zero health becomes the broken plate item.
  • Config.BrokenPlateItem, default 'brokenplate'. Item name used for a destroyed plate. It has to be a registered item.
  • Config.HeavyDrawables: vest drawable indices, per gender, that make a plate carrier a heavy carrier. A heavy carrier holds two plates, any other carrier holds one, and the carrier stash is sized to match. Movement is not affected by this list.
  • Config.Plates: maps each plate item name to its armor value. A new plate is created with that value as its health, clamped to 50, so a value above 50 has no extra effect. The armor a carrier grants is the sum of the health of the plates inside it, capped at 100: two 50 point plates in a heavy carrier fill the bar.

Clothing items

shared/config.lua
1Config.ClothingItems = {
2    hat        = { slot = 11, type = 'prop',      componentId = 0 },
3    undershirt = { slot = 12, type = 'component', componentId = 8 },
4    jacket     = { slot = 13, type = 'component', componentId = 11 },
5    bodyarmor  = { slot = 14, type = 'component', componentId = 9 },
6    gloves     = { slot = 15, type = 'component', componentId = 3 },
7    pants      = { slot = 16, type = 'component', componentId = 4 },
8    shoes      = { slot = 17, type = 'component', componentId = 6 },
9    mask       = { slot = 18, type = 'component', componentId = 1 },
10    glasses    = { slot = 19, type = 'prop',      componentId = 1 },
11    earrings   = { slot = 20, type = 'prop',      componentId = 2 },
12    chain      = { slot = 21, type = 'component', componentId = 7 },
13    bracelet   = { slot = 22, type = 'prop',      componentId = 7 },
14    watch      = { slot = 23, type = 'prop',      componentId = 6 },
15    bag        = { slot = 24, type = 'component', componentId = 5 },
16    decals     = { slot = 25, type = 'component', componentId = 10 },
17}
  • Config.ClothingItems: the map from item name to inventory slot and ped component. Each entry has three fields.
  • slot: the inventory slot the item locks into, unique per item. The shipped values run 11 to 25.
  • type: 'component' for a ped component, 'prop' for a ped prop.
  • componentId: the game component or prop index the item drives.
  • Config.ClothesSlotID, Config.ValidSlotsPerItem and Config.ComponentMapping are built from this table when the resource loads. Leave them alone.
Slot 14 is the plate carrier

bodyarmor uses slot 14 and drives the plate carrier. Do not remap it and do not add it to the wear system. Its durability comes from the plates inside it.

Default clothing

shared/config.lua
1Config.DefaultClothing = {
2    male = {
3        mask       = { draw = 0, text = 0 },
4        hat        = { draw = -1, text = -1 },
5        pants      = { draw = 21, text = 0 },
6        shoes      = { draw = 34, text = 0 },
7    },
8    female = {
9        pants      = { draw = 15, text = 0 },
10        shoes      = { draw = 35, text = 0 },
11    },
12}
  • Config.DefaultClothing: the drawable and texture applied to a clothing slot when its item is removed, per gender. -1 clears the component or prop. The file ships an entry for each of the 15 clothing slots in both genders. The block above is an extract.

Plate sync cooldown

shared/config.lua
1Config.AntiExploit = {
2    ArmorSyncCooldown = 150,
3}
  • ArmorSyncCooldown, default 150. Minimum milliseconds between two plate damage reports from the same player. Raise it on a server where players take hits in fast bursts, lower it only if plate wear feels late.

Stash prefixes

shared/config.lua
1Config.Stash = {
2    PlateCarrierPrefix = 'platecarrier_',
3    BagPrefix = 'playerbag_',
4}
  • Config.Stash.PlateCarrierPrefix, default 'platecarrier_'. Identifier prefix for plate carrier stashes.
  • Config.Stash.BagPrefix, default 'playerbag_'. Identifier prefix for bag stashes.

Both build unique stash identifiers. Leave them alone unless they collide with another resource, and change them only on a fresh database: existing stashes keep the old identifier.

Bag blacklist

shared/config.lua
1Config.BagBlacklist = {
2    enabled          = true,
3    denyBagInsideBag = true,
4
5    items = {
6    },
7
8    prefixes = {
9        'blueprint_',
10    },
11}
  • enabled, default true. Master switch for the filter. false turns it off.
  • denyBagInsideBag, default true. Refuses a bag item put inside another bag.
  • items, default empty. Exact item names refused entry into a bag.
  • prefixes, default { 'blueprint_' }. Any item whose name starts with one of these strings is refused.

The filter runs when the item is moved into a bag. A match refuses the move and the item stays where it was. The message the player gets is toggled by Config.Notifications.bag_item_blocked.

Wear and decay

shared/config.lua
1Config.WearDecay = {
2    Enabled      = true,
3    Time         = '60m',
4    OnDepleted   = 'break',
5    Notify       = true,
6
7    Repairable   = false,
8    RepairItem   = 'repair_kit',
9    RepairCount  = 1,
10    RepairAmount = 100,
11
12    Items = {
13        ['antirad_mask'] = {
14            time = '30m',
15            male = {
16                { component = 1, drawable = 244, texture = 0 },
17                { component = 1, drawable = 247, texture = 0 },
18            },
19        },
20        ['antirad_suit'] = {
21            time = '60m',
22            unisex = {
23                { component = 11, drawable = 660, texture = 0 },
24                { component = 11, drawable = 731, texture = 0 },
25            },
26        },
27    },
28}
  • Enabled, default true. Master switch for the wear system. With it on, the pieces listed under Items lose durability while worn.
  • Time, default '60m'. How long a piece lasts while worn. Takes a number with a unit suffix ('45s', '30m', '2h', '1d') or a plain number, read as minutes. Entries without their own time use this value.
  • OnDepleted, default 'break'. What happens at zero durability. 'break' keeps the piece worn but broken, giving no protection, and flags it so other resources can react. 'remove' takes it off instead.
  • Notify, default true. Tells the player when a piece breaks.
  • Repairable, default false. With false a worn piece cannot be repaired with an item and the player equips a fresh one to get the protection back.
  • RepairItem, default 'repair_kit'. Item consumed to repair a worn piece.
  • RepairCount, default 1. How many of that item a repair consumes.
  • RepairAmount, default 100. Durability restored by one repair.
  • Items: the pieces the wear system watches, keyed by a name of your choice. An entry can match by drawable, by item name, or by both. For drawables, list component, drawable and texture under male, female or unisex. For item names, use item = 'hazmat_suit', or a list of names. An entry may set its own time, for example ['work_gloves'] = { time = '30m', item = 'work_gloves' }. The repair defaults can be overridden per entry with repairItem, repairCount and repairAmount, and repairItem = false makes that piece impossible to repair.

A fuller Items table, with entries matched by drawable, by item name, and with their own repair rules:

shared/config.lua
1Config.WearDecay.Items = {
2    ['gas_mask'] = {
3        time = '60m',
4        male   = { { component = 1, drawable = 247, texture = 0 } },
5        female = { { component = 1, drawable = 247, texture = 0 } },
6        repairItem = 'mask_filter', repairCount = 2, repairAmount = 100,
7    },
8    ['hazmat_suit'] = {
9        time = '2h',
10        item = 'hazmat_suit',
11        repairItem = 'duct_tape', repairCount = 3, repairAmount = 50,
12    },
13    ['work_gloves'] = { time = '30m', item = 'work_gloves' },
14    ['dust_mask']   = { time = '10m', item = 'dust_mask', repairItem = false },
15}

Repair happens when a player uses the repair item from the inventory: the most worn piece that uses that item is repaired, repairCount of the item is consumed and repairAmount durability comes back. In the table above a gas mask needs two mask filters, a hazmat suit needs three rolls of duct tape and only gets half its durability back, and a dust mask is thrown away when it breaks. Every repair item has to exist in data/items.lua:

data/items.lua
1['repair_kit']  = { label = 'Repair Kit',  weight = 500, stack = true, close = true },
2['mask_filter'] = { label = 'Mask Filter', weight = 100, stack = true, close = true },
3['duct_tape']   = { label = 'Duct Tape',   weight = 100, stack = true, close = true },

A broken piece is exposed to other resources through the ml_clothingBroken state bag, the wear exports and the OnGearBroken and OnGearRepaired hooks, all on the developer page.

An item the wear system manages must not also carry decay or degrade in your items file. Both write the same durability value.

Admin panel

The admin panel reads its own file.

shared/invadmin_config.lua
1Config.AdminAce = nil
2Config.Command = 'invadmin'
3Config.OpenKey = nil
4Config.DefaultTheme = 'default'
5Config.MinimizeKey = 'F9'
6Config.ClothingCatalogUrl = 'http://127.0.0.1:3960/api/catalog'
  • Config.AdminAce, default nil. An ACE permission that opens the panel. A player holding it passes the admin check. Left nil, access falls back to the framework admin group.
  • Config.Command, default 'invadmin'. The chat command that opens the panel.
  • Config.OpenKey, default nil. Key that opens the panel, for example 'F7'. Set to a non empty string, a keybind is registered and each player can rebind it. Left nil, the panel opens by command only.
  • Config.DefaultTheme, default 'default'. The panel theme a player starts on.
  • Config.MinimizeKey, default 'F9'. Shrinks the open panel to a pill and brings it back.
  • Config.ClothingCatalogUrl, default 'http://127.0.0.1:3960/api/catalog'. Endpoint the Clothing tab reads its catalog from. When the URL answers with anything other than a 200 and a JSON body, the Clothing tab shows an empty catalog.
shared/invadmin_config.lua
1Config.RateLimit = {
2    list = 500,
3    get = 400,
4    save = 1500,
5    delete = 1500,
6    upload = 1500,
7    playerList = 500,
8    playerGet = 400,
9    playerGive = 800,
10    playerRemove = 800,
11    stashList = 500,
12    stashGet = 400,
13    stashSave = 1500,
14    stashDelete = 1500,
15    weapons = 500,
16    weapon_get = 400,
17    clothingImages = 150,
18    playerImages = 150,
19}
  • Config.RateLimit: cooldown in milliseconds per panel action. Higher values throttle that action harder. The list and get actions run on every navigation, so raising those two is what makes the panel feel unresponsive.
shared/invadmin_config.lua
1Config.Editor = {
2    MaxGrid = 5,
3    NamePrefix = 'custom_',
4    MaxImageBytes = 524288,
5}
  • MaxGrid, default 5. Largest width or height the item editor accepts.
  • NamePrefix, default 'custom_'. Prefix added to the name of an item created in the editor.
  • MaxImageBytes, default 524288. Largest item image the editor accepts, in bytes.
shared/invadmin_config.lua
1Config.DiscordWebhook = {
2    Default = 'INSERT_WEBHOOK_LINK_HERE',
3    GiveItem = 'INSERT_WEBHOOK_LINK_HERE',
4    RemoveItem = 'INSERT_WEBHOOK_LINK_HERE',
5    ItemEdit = 'INSERT_WEBHOOK_LINK_HERE',
6    ShopEdit = 'INSERT_WEBHOOK_LINK_HERE',
7    InventoryEdit = 'INSERT_WEBHOOK_LINK_HERE',
8    ClothingGive = 'INSERT_WEBHOOK_LINK_HERE',
9}
  • Config.DiscordWebhook: one webhook per action, so each kind of admin action can land in its own channel. An entry left on the placeholder falls back to Default, and a Default left on the placeholder turns that log off. A value is only used when it starts with http.