Every option in data/koja/core.lua, interact.lua, admin.lua, rarity.lua and staff.lua, plus the upstream data files Koja extends.
Configuration#
Koja Inventory adds five config files in data/koja/. They return plain Lua tables and are merged into one config on start.
File What is in it data/koja/core.luaSlot layout, default player settings, clothing, weight, throwing, plates, fast actions, ped preview data/koja/interact.luaGive, trade, search animation, ox_target options, discovery, shops, weapon attachments data/koja/admin.luaAdmin command, roles, addon toggles, history and security defaults data/koja/rarity.luaThe default rarities data/koja/staff.luaStaff identifiers (server only, never sent to clients)
The upstream files in data/ (items.lua, weapons.lua, shops.lua, stashes.lua, crafting.lua...) keep their ox_inventory format. Koja only adds optional fields, listed at the end of this page and in Items .
Restart the resource after changing a file.
The admin panel wins
Most of these values are only defaults. What you change in the admin panel — addon toggles, rarities, items, shops, stashes, benches, clothing, world containers, security, locales — is stored in the database and overrides the files.
Slot layout#
data/koja/core.lua
baseSlots = 25 ,
pockets = 5 ,
Option Default What it does pockets5Slots 1..pockets are the Pockets row (hotbar) baseSlots25Slots up to this number are always unlocked. Slots above it, up to inventory:slots, need a backpack
Default player settings#
Every player can change these in the Settings tab (see Player settings ). Their choice is saved on their PC (client KVP koja_inv_settings); these are the values for new players and for the Reset button.
data/koja/core.lua
defaults = {
accent = '#F5A623' ,
secondary = 'rgba(25,26,26,0.98)' ,
rows = 6 ,
scale = 100 ,
clothingPanel = 'center' ,
theme = 'v2' ,
font = 'Poppins' ,
clothingInventory = true ,
pedCamera = true ,
notifyStyle = 'compact' ,
sharp = false ,
streamer = false ,
sounds = true ,
},
Option Values What it does accent, secondaryCSS colour Main colour and panel background rows4–8 Visible rows of the inventory grid scale70–130 UI scale in percent clothingPanelleft, center, rightWhere the clothes panel and ped preview sit themev2, ferrofluid, minimal, dotted, antigravityInventory style fontPoppins, Inter, Montserrat, Rajdhani, BarlowUI font clothingInventoryboolean Shows Your clothes next to the inventory pedCameraboolean false keeps the gameplay camera; the ped is shown inside the UI insteadnotifyStylecompact, minimalItem added / removed popups while the inventory is closed sharpboolean Square corners streamerboolean Streamer mode soundsboolean UI sounds
settingsLimits holds the allowed ranges and values used to clean saved settings (rows = { 4, 8 }, scale = { 70, 130 }, the panel positions and themes). Change it only if you add a theme to the UI yourself.
Clothing#
data/koja/core.lua
clothing = {
enabled = true ,
imageResource = 'illenium-appearance' ,
saveAppearance = true ,
adoptAppearance = true ,
externalAppearance = true ,
hiddenSlots = { 'underwear_top' , 'underwear_bottom' },
slots = { ... },
nakedMale = { ... },
nakedFemale = { ... },
genericItem = 'clothing' ,
hangerItem = 'clothing_hanger' ,
undressAnim = { dict = 'clothingtie' , clip = 'try_tie_negative_a' , duration = 1200 },
},
Option What it does enabledClothing as items. Also switchable live as the Clothing as items addon imageResourceResource that exports getClothingImage(gender, category, drawable, texture) — illenium-appearance with Koja Appearance saveAppearanceSaves the ped appearance through illenium-appearance / fivem-appearance after every change adoptAppearanceClothes the ped already wears become clothing items when the matching slot is empty externalAppearanceAn appearance saved by a skin menu or outfit wins over the worn items: changed pieces are rewritten, removed or named pieces go back to the inventory. Bag and vest stay items hiddenSlotsSlots tracked as worn but not shown in the UI slotsThe clothing slots, in UI order. See below nakedMale, nakedFemale[componentId] = { drawable, texture } applied when a slot is empty (freemode peds). Props are clearedgenericItemItem given when you undress a piece that has no item of its own hangerItemThe hanger item used by the Put on hanger fast action undressAnimAnimation played while dressing / undressing
Clothing slots#
Each entry of slots:
data/koja/core.lua
{ key = 'torso' , label = 'Torso' , icon = 'layers' , column = 'left' , kind = 'component' , id = 11 , category = 'jackets' },
Field What it is keySlot key used in the code and in the locale (clothing_slot_<key>) label, iconFallback label and Lucide icon name columnleft or right of the pedkind, idcomponent + component id, or prop + prop idcategoryCategory key used for the image lookup (hats, masks, jackets...)
The default slots: hat, mask, glasses, ears, chain, tshirt, torso, arms, vest, bag, pants, shoes, watch, bracelet, decals, plus the hidden underwear_top and underwear_bottom.
Weight and overload#
data/koja/core.lua
weight = {
enabled = true ,
overloadPct = 0.85 ,
clipset = 'move_m@hobo@a' ,
moveRate = 0.85 ,
disableSprintPct = 0.97 ,
staminaDrain = 2.5 ,
sweat = true ,
sweatAmount = 80.0 ,
},
Option What it does overloadPctEffects start at this fraction of the max weight clipsetMovement clipset while overloaded. false = none moveRateMove rate while overloaded disableSprintPctNo sprint or jump from this fraction of the max weight staminaDrainStamina points lost per second while running overloaded sweat, sweatAmountSweat on the ped while overloaded
Live switch: the Weight effects addon.
Throwing#
data/koja/core.lua
throw = {
enabled = true ,
anyItem = true ,
maxDistance = 30.0 ,
minForce = 6.0 ,
maxForce = 22.0 ,
forcePerKg = 1.2 ,
defaultProp = 'prop_cs_cardbox_01' ,
landTimeout = 7000 ,
aimTimeout = 15000 ,
keys = { throw = 24 , cancel = 25 },
anim = nil ,
weapons = { ... },
},
Option What it does anyItemEvery item can be thrown unless its definition says throwable = false. With false, only items with throwable = true maxDistanceThe server rejects landings further than this from the thrower minForce, maxForce, forcePerKgThrow force; heavier stacks fly shorter defaultPropProp thrown when the item has no prop landTimeoutMilliseconds before the prop position is taken as the landing point aimTimeoutMilliseconds of aiming before the throw is cancelled keysControl ids while aiming: throw (24, left mouse) and cancel (25, right mouse) anim{ dict, clip, release } to force one throw animation. nil uses the built-in list
Throwing the weapon in hand#
data/koja/core.lua
weapons = {
enabled = true ,
mapper = 'mouse_button' ,
key = 'MOUSE_MIDDLE' ,
minHold = 250 ,
chargeTime = 1200 ,
minCharge = 0.45 ,
maxDistance = nil ,
denyProjectiles = true ,
allow = nil ,
deny = { 'WEAPON_UNARMED' , 'WEAPON_PETROLCAN' , 'WEAPON_HAZARDCAN' , 'WEAPON_FERTILIZERCAN' , 'WEAPON_FIREEXTINGUISHER' , 'WEAPON_STUNGUN_MP' },
},
Option What it does mapper, keyDefault key of the koja_throw_weapon keybind. Players can rebind it in the FiveM key bindings minHoldReleasing earlier cancels (no accidental throws) chargeTime, minChargeHolding charges the force from minCharge to 100% over chargeTime ms maxDistancenil = throw.maxDistancedenyProjectilesGrenades, molotovs and other thrown weapons cannot be thrown this way allownil = every weapon, or a list of weapon namesdenyWeapons that can never be thrown
Armour plates#
data/koja/core.lua
plates = {
enabled = true ,
maxPerVest = 3 ,
vests = { armor_vest = true },
types = { plate_light = 25 , plate_medium = 50 , plate_heavy = 100 },
},
Option What it does maxPerVestPlates one vest can hold vestsItems that accept plates, besides any item whose clothing.id is 9 typesArmour per plate item, used when the item has no plate = { armor = n }
Ped armour is the sum of the plates, capped at 100.
Fast actions#
data/koja/core.lua
fastActions = {
{ id = 'handsup' , label = 'Hands up' , icon = 'hand' },
{ id = 'undress' , label = 'Undress' , icon = 'shirt' },
{ id = 'hanger' , label = 'Put on hanger' , icon = 'archive' },
{ id = 'trade' , label = 'Trade' , icon = 'repeat' },
{ id = 'give' , label = 'Give' , icon = 'hand-helping' },
},
The buttons of the Fast actions row. Remove an entry to hide it. Labels can be translated with the locale key fast_action_<id>.
Item text limits#
data/koja/core.lua
item = { renameMax = 32 , describeMax = 160 },
Maximum length of a renamed item label and of a custom description.
Ped preview#
data/koja/core.lua
pedMode = 'clone' ,
ped = {
distance = 2.6 ,
height = 0.15 ,
fov = 38.0 ,
offset = { left = 0.95 , center = 0.0 , right = - 0.95 },
},
status = { interval = 500 },
Option What it does pedModeclone = a camera frames your ped where the clothes panel is. pause = the pause-menu ped on a dark background. Also switchable on the admin Addon Management pageped.distance, height, fovCamera of clone mode ped.offsetSideways camera offset per clothes panel position status.intervalMilliseconds between health / armour / hunger / thirst updates in the clothes panel
Give#
data/koja/interact.lua
give = {
distance = 3.0 ,
marker = { type = 25 , scale = 1.1 , color = { 196 , 255 , 64 , 180 } },
},
distance is the max distance between giver and receiver. marker is the ground circle drawn under the targeted player.
Trade#
data/koja/interact.lua
trade = {
distance = 3.0 ,
timeout = 30 ,
sessionTimeout = 300 ,
maxOffers = 12 ,
keys = { accept = 'Y' , decline = 'N' },
},
Option What it does distanceMax distance to send and keep a trade timeoutSeconds a trade request stays valid sessionTimeoutSeconds of inactivity before a running trade is cancelled maxOffersMax different slots one player can offer keysDefault keys of the koja_trade_accept / koja_trade_decline keybinds (used while the inventory is closed)
World containers#
data/koja/interact.lua
search = {
enabled = true ,
dumpster = { dict = 'amb@prop_human_bum_bin@base' , clip = 'base' },
trunk = { dict = 'mini@repair' , clip = 'fixing_a_ped' },
},
target = {
enabled = true ,
},
Option What it does search.enabledLooping search animation while a dumpster or trunk inventory is open. Not played in a vehicle search.<type>Animation per inventory type target.enabledExtra ox_target options (search dumpster, open trunk, stash and evidence zones) while the server runs without inventory:target. Needs ox_target started. Ignored when inventory:target is on
Both switches can be changed live on the admin World containers page, together with the loot tables.
Discovery#
data/koja/interact.lua
discovery = {
enabled = true ,
types = { 'player' , 'drop' , 'stash' , 'trunk' , 'glovebox' },
skipOwned = true ,
memory = 600 ,
},
Option What it does typesInventory types where items have to be discovered skipOwnedStashes owned by the player are never "discovered" memorySeconds the server remembers what a player already searched
The search time per item comes from its rarity (discoveryTime in data/koja/rarity.lua).
Shops#
data/koja/interact.lua
shop = {
defaultPayment = { 'cash' , 'card' },
cashItem = 'money' ,
interaction = {
enabled = true ,
distance = 2.0 ,
drawDistance = 8.0 ,
key = 38 ,
keyLabel = 'E' ,
},
dui = {
enabled = true ,
size = 0.3 ,
maxHeight = 0.11 ,
},
},
Option What it does defaultPaymentPayment methods of shops that do not set paymentMethods. cash = the cashItem item, card = the framework bank account cashItemItem used for cash payments interaction.enabledThe built-in floating "press E" prompt for shops that do not set it themselves interaction.distance, drawDistanceDistance to press the key / to see the prompt interaction.key, keyLabelControl id and label dui.enabledDraws the prompt as a 3D card in the player's inventory style. Falls back to a text prompt when disabled or when the card fails to load dui.sizeCard height in metres dui.maxHeightOn-screen height cap (fraction of the screen) when standing next to it
Weapon attachments#
data/koja/interact.lua
attachments = {
interval = 30 ,
fov = 32.0 ,
distance = 1.1 ,
rotateSpeed = 0.35 ,
pitchSpeed = 0.25 ,
maxPitch = 45.0 ,
minFov = 14.0 ,
maxFov = 50.0 ,
zoomStep = 2.0 ,
smoothing = 0.07 ,
bones = { ... },
fallback = { ... },
types = { 'muzzle' , 'flashlight' , 'scope' , 'magazine' , 'grip' , 'barrel' , 'skin' , 'tint' },
labels = { ... },
},
Option What it does intervalMilliseconds between marker position updates fov, distanceCamera FOV and distance (scaled by the weapon length) rotateSpeed, pitchSpeed, maxPitchMouse rotation of the weapon minFov, maxFov, zoomStepMouse wheel zoom smoothingEasing of rotation and zoom in seconds (0 = instant) bonesWeapon bones searched, in order, for each marker type fallbackMarker position (fraction of the weapon bounding box) when no bone exists types, labelsMarker types in UI order and their labels
Admin#
data/koja/admin.lua
admin = {
command = 'invadmin' ,
key = nil ,
superAce = 'group.admin' ,
rateLimit = { calls = 30 , window = 3000 },
roles = { ... },
},
Option What it does commandChat command that opens the admin panel. false disables it keyOptional keybind, e.g. 'F10' (registered as koja_invadmin) superAceAce that grants every admin page rateLimitMax admin calls per window (ms) per player rolesDefault roles, created in the database on first start: owner, admin, moderator, support. After that, edit them on the Permissions page
Role perms map a page key to true (['*'] = true = every page). Page keys: home, addons, items, rarity, players, history, security, clothing, shops, stashes, permissions, locales.
Addon toggles#
data/koja/admin.lua
features = {
clothing = { default = true , label = 'Clothing as items' , description = '...' },
-- ...
},
default is used until an admin changes the toggle on Addon Management ; after that the database value wins. Disabled features fall back to stock ox_inventory behaviour.
Key Feature clothingClothing as items backpackBackpacks ministashMini stashes throwThrowing weightEffectsWeight effects platesPlate armour discoveryItem discovery tradeTrading giveHover & give shops3d3D shop interaction attachmentsWeapon 3D attachments multiselectMulti-select (SHIFT + click) renameRename & describe historyInventory history
History#
data/koja/admin.lua
history = {
enabled = true ,
retentionDays = 30 ,
flushInterval = 5000 ,
maxBuffer = 500 ,
ignore = {},
},
Option What it does retentionDaysRows older than this are removed on start and every 6 hours. 0 keeps them forever flushIntervalMilliseconds between buffered database inserts maxBufferForces a flush when the buffer gets this big ignoreActions never logged, e.g. { open = true, close = true }
Security#
data/koja/admin.lua
security = {
autoKick = false ,
logHookRejections = true ,
trimPlates = true ,
emergencyLock = false ,
distanceCheck = true ,
maxDistance = 10.0 ,
logLevel = 1 ,
evidenceGrade = 2 ,
retention = 100 ,
imageHosts = { 'r2.fivemanage.com' , 'i.fmfile.com' },
severe = { malformed = true , locked_slot = true , exploit = true },
},
Option What it does autoKickDrops players on severe reports logHookRejections, trimPlates, logLevel, evidenceGradeLive mirrors of inventory:loghookrejection, inventory:trimplate, inventory:loglevel, inventory:evidencegrade emergencyLockBlocks every inventory open. Never saved, so it is off after a restart distanceCheck, maxDistanceReports drops and opens from further than maxDistance metres retentionRecent reports kept in memory for the Security page imageHostsHosts allowed in metadata image URLs (inventory:validhosts) severeReport kinds that count as severe (and trigger autoKick)
Rarities#
data/koja/rarity.lua
rarities = {
{ name = 'common' , label = 'Common' , color = '#9AA0A6' , discoveryTime = 0 , revealTimer = false },
{ name = 'uncommon' , label = 'Uncommon' , color = '#2ECC71' , discoveryTime = 2 , revealTimer = true },
{ name = 'rare' , label = 'Rare' , color = '#3498DB' , discoveryTime = 4 , revealTimer = true },
{ name = 'epic' , label = 'Epic' , color = '#9B59B6' , discoveryTime = 6 , revealTimer = true },
{ name = 'legendary' , label = 'Legendary' , color = '#F39C12' , discoveryTime = 8 , revealTimer = true },
{ name = 'mythic' , label = 'Mythic' , color = '#E74C3C' , discoveryTime = 10 , revealTimer = true },
},
Field What it does nameKey used by items (rarity = 'rare') label, colorShown in tooltips; the colour tints slot borders and labels discoveryTimeSeconds an item of this rarity stays "Discovering..." in other inventories revealTimerShows a countdown on the slot while it is discovered
Items without a rarity are common. Edits on the Edit Rarity page are stored in koja_inv_rarities and override this file.
Staff#
data/koja/staff.lua
return {
[ 'license:0123456789abcdef' ] = 'owner' ,
}
Identifier → role name. Accepted identifiers: license:, license2:, discord:, fivem:, steam:.
This file is not in the manifest files, so clients never download it. Staff added on the Permissions page is stored in the database and merged on top.
Upstream data files#
File What Koja adds data/items.luaOptional item fields (rarity, throwable, prop, unique, isStash, hanger, backpack, clothing, plate, tint) — see Items data/weapons.luaComponent type decides the marker of the 3D attachments view (sight is shown as scope) data/shops.luapaymentMethods, interaction and icon per shop — see Features data/crafting.luaduration per recipe is shown in the crafting panel; count may be { min, max } — see Features data/stashes.luaUnchanged. Stashes can also be created on the Stashes admin page