Configuration
This section includes all configurable files for the selected script. Most settings are configured automatically, but each config.lua file contains a header comment explaining the purpose and usage of every configuration type. Be sure to read the header of each file carefully to fully understand how to customize and adapt the system for QBCORE, ESX, or standalone environments, ensuring seamless integration with your server.
qs-inventory/config/config.lua
--──────────────────────────────────────────────────────────────────────────────
-- Quasar Store · Configuration Guidelines
--──────────────────────────────────────────────────────────────────────────────
-- This configuration file defines all adjustable parameters for the script.
-- Comments are standardized to help you identify which sections you can safely edit.
--
-- • [EDIT] – Safe for users to modify. Adjust these values as needed.
-- • [INFO] – Informational note describing what the variable or block does.
-- • [ADV] – Advanced settings. Change only if you understand the logic behind it.
-- • [CORE] – Core functionality. Do not modify unless you are a developer.
-- • [AUTO] – Automatically handled by the system. Never edit manually.
--
-- Always make a backup before editing configuration files.
-- Incorrect changes in [CORE] or [AUTO] sections can break the resource.
--──────────────────────────────────────────────────────────────────────────────
Config = Config or {} -- [CORE]
Locales = Locales or {} -- [CORE]
--──────────────────────────────────────────────────────────────────────────────
-- Language Selection [EDIT]
-- [INFO] Choose your preferred language. Files in locales/* (you can add your own).
--──────────────────────────────────────────────────────────────────────────────
Config.Language = 'en' -- [EDIT] See list in docs header.
--──────────────────────────────────────────────────────────────────────────────
-- Framework Detection [AUTO]
-- [INFO] Auto-detects ESX/QB/QBX. If renamed/custom, set manually and adapt hooks.
--──────────────────────────────────────────────────────────────────────────────
local frameworks = { -- [CORE] resource → alias
['es_extended'] = 'esx',
['qb-core'] = 'qb',
['qbx_core'] = 'qb'
}
Config.Framework = DependencyCheck(frameworks) or 'none' -- [AUTO]
local qbxHas = GetResourceState('qbx_core') == 'started' -- [AUTO]
Config.QBX = qbxHas -- [AUTO]
--──────────────────────────────────────────────────────────────────────────────
-- Security [ADV]
-- [INFO] Disables client-side shop generation via `inventory:server:OpenInventory`.
-- [INFO] If enabled, register/open shops via server exports/events.
--──────────────────────────────────────────────────────────────────────────────
-- Server exports: CreateShop / OpenShop
-- Server event: inventory:openShop
-- Example (client): TriggerServerEvent('inventory:openShop', 'shop_name')
Config.DisableShopGenerationOnClient = false -- [EDIT] true disables client shop generation.
--──────────────────────────────────────────────────────────────────────────────
-- Backward Compatibility / Migration [ADV]
-- [INFO] One-time data migration from old inventory. Revert to false after completion.
--──────────────────────────────────────────────────────────────────────────────
Config.FetchOldInventory = false -- [EDIT] Set true only once to migrate; then set back to false.
--──────────────────────────────────────────────────────────────────────────────
-- Targeting [EDIT]
-- [INFO] Enable support for qb-target / ox_target interactions.
--──────────────────────────────────────────────────────────────────────────────
Config.UseTarget = false -- [EDIT] true enables target; false uses default interactions.
--──────────────────────────────────────────────────────────────────────────────
-- General Behavior [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Transparent inventory background (character always visible; you can hear nearby players).
Config.TransparentBackground = false -- [EDIT]
Config.ServerName = 'QUASAR' -- [EDIT] Short name shown in pause menu.
Config.ThrowKeybind = 'E' -- [EDIT] Keybind for throw item; set false to disable.
Config.GiveItemHideName = false -- [EDIT] Hide item name when giving; show only item id.
Config.OpenProgressBar = false -- [EDIT] Progress bar on open to reduce dupes risk.
Config.EnableSounds = true -- [EDIT] Toggle inventory UI sounds.
Config.EnableThrow = true -- [EDIT] Allow throwing items from inventory.
Config.UseJonskaItemThrow = false -- [ADV] Use custom throw implementation (see custom/misc/jonska.lua).
Config.PlaceableItems = true -- [EDIT] Allow placeable items behavior.
--──────────────────────────────────────────────────────────────────────────────
-- Robbery / Interaction Rules [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.Handsup = true -- [EDIT] Enable hands-up feature and robbery options.
Config.StealDeadPlayer = true -- [EDIT] Allow looting dead players.
Config.StealWithoutWeapons = false -- [EDIT] Only rob if target has hands up without a weapon.
--──────────────────────────────────────────────────────────────────────────────
-- Inventory & Drop Capacity [EDIT]
-- [INFO] Changing weights/slots on a live server can require wipes to avoid dupes.
--──────────────────────────────────────────────────────────────────────────────
Config.InventoryWeight = { -- [EDIT]
['weight'] = 120000, -- [INFO] Max carry weight (grams).
['slots'] = 41, -- [INFO] Total slots (set 40 to remove 6th protected slot).
}
Config.DropWeight = { -- [EDIT]
['weight'] = 20000000, -- [INFO] Max total drop weight (grams).
['slots'] = 130, -- [INFO] Max slots per dropped stash.
}
--──────────────────────────────────────────────────────────────────────────────
-- Item Label Customization [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.LabelChange = true -- [EDIT] Allow players to rename items.
Config.LabelChangePrice = false -- [EDIT] Set price (number) or false for free.
Config.BlockedLabelChangeItems = { -- [EDIT] Items that cannot be renamed.
['money'] = true,
['phone'] = true,
}
--──────────────────────────────────────────────────────────────────────────────
-- Hotbar Usage [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.UsableItemsFromHotbar = true -- [EDIT] Allow using from slots 1–5.
Config.BlockedItemsHotbar = { -- [EDIT] Items blocked from hotbar use.
'lockpick',
-- add more…
}
--──────────────────────────────────────────────────────────────────────────────
-- Backpack / One-Per-Item Rules [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.OnePerItem = { -- [EDIT] Max quantity per item type.
['backpack'] = 1,
}
Config.notStolenItems = { -- [EDIT] Items that cannot be stolen from players.
['id_card'] = true,
['water_bottle'] = true,
['tosti'] = true,
}
Config.notStoredItems = { -- [EDIT] Items that cannot be placed in stashes.
['backpack'] = true,
}
--──────────────────────────────────────────────────────────────────────────────
-- Pages / UI Sections [EDIT]
-- [INFO] Disabling a page fully removes its code & UI editability.
--──────────────────────────────────────────────────────────────────────────────
Config.Pages = { -- [EDIT]
['clothing'] = true,
['pause_menu'] = true,
['quest'] = true,
}
--──────────────────────────────────────────────────────────────────────────────
-- Armor System [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.DrawableArmor = 100 -- [EDIT] Armor points granted by vest.
Config.Clothing = Config.Pages.clothing -- [AUTO] Mirror clothing page toggle.
---@type ClotheSlot[] -- [INFO] Inventory-wearable clothing slots.
Config.ClothingSlots = { -- [EDIT]
{ name='helmet', slot=1, type='head', wearType='prop', componentId=0, anim={ dict='mp_masks@standard_car@ds@', anim='put_on_mask', flags=49 } },
{ name='mask', slot=2, type='head', wearType='drawable', componentId=1, anim={ dict='mp_masks@standard_car@ds@', anim='put_on_mask', flags=49 } },
{ name='glasses',slot=3, type='head', wearType='prop', componentId=1, anim={ dict='clothingspecs', anim='take_off', flags=49 } },
{ name='torso', slot=4, type='body', wearType='drawable', componentId=11, anim={ dict='missmic4', anim='michael_tux_fidget',flags=49 } },
{ name='tshirt', slot=5, type='body', wearType='drawable', componentId=8, anim={ dict='clothingtie', anim='try_tie_negative_a',flags=49 } },
{ name='jeans', slot=6, type='body', wearType='drawable', componentId=4, anim={ dict='missmic4', anim='michael_tux_fidget',flags=49 } },
{ name='arms', slot=7, type='body', wearType='drawable', componentId=3, anim={ dict='nmt_3_rcm-10', anim='cs_nigel_dual-10', flags=49 } },
{ name='shoes', slot=8, type='body', wearType='drawable', componentId=6, anim={ dict='random@domestic', anim='pickup_low', flags=49 } },
{ name='ears', slot=9, type='body', wearType='prop', componentId=2, anim={ dict='mp_cp_stolen_tut', anim='b_think', flags=49 } },
{ name='bag', slot=10, type='addon',wearType='drawable', componentId=5, anim={ dict='anim@heists@ornate_bank@grab_cash', anim='intro', flags=49 } },
{ name='watch', slot=11, type='addon',wearType='prop', componentId=6, anim={ dict='nmt_3_rcm-10', anim='cs_nigel_dual-10', flags=49 } },
{ name='bracelets',slot=12,type='addon',wearType='prop', componentId=7, anim={ dict='nmt_3_rcm-10', anim='cs_nigel_dual-10', flags=49 } },
{ name='chain', slot=13, type='addon',wearType='drawable', componentId=7, anim={ dict='nmt_3_rcm-10', anim='cs_nigel_dual-10', flags=49 } },
{ name='vest', slot=14, type='addon',wearType='drawable', componentId=9, anim={ dict='nmt_3_rcm-10', anim='cs_nigel_dual-10', flags=49 } },
}
-- [ADV] If you disable armor system, vest slot is removed dynamically.
if not Config.EnableArmor then
Config.ClothingSlots = table.filter(Config.ClothingSlots, function(v) return v.name ~= 'vest' end) -- [ADV]
end
Config.EnableArmor = true -- [EDIT] Toggle the armor mechanic on/off.
--──────────────────────────────────────────────────────────────────────────────
-- Leveling / Quests [EDIT]
-- [INFO] XP curve & quest definitions for the inventory progression features.
--──────────────────────────────────────────────────────────────────────────────
Config.LevelingDifficulty = 1.5 -- [EDIT] XP multiplier per level (e.g., 1.5 = 50% more XP each level)
Config.DefaultSkill = { -- [EDIT] Default starting stats for new players
level = 1, -- [EDIT]
xp = 0 -- [EDIT]
}
---@type CreateQuest[] -- [INFO] Quest definitions consumed by the quest system.
Config.Quests = { -- [EDIT] Add/remove or tweak rewards/requirements
{ name='open_inventory', title='What’s in the Bag?', description='Open your inventory for the first time and check what you’re carrying with you.', reward=100, requiredLevel=0 },
{ name='use_sandwich', title='A Tasty Start', description='Enjoy your first sandwich to recover a bit of energy. You can buy one at any market.', reward=200, requiredLevel=1, item='sandwich' },
{ name='use_phone', title='Connected World', description='Use a phone to explore its features. Purchase one from the market if you don’t have it.', reward=200, requiredLevel=2, item='phone' },
{ name='use_water', title='Essential Hydration', description='Stay hydrated by drinking a bottle of water. You can find it in the market or a store.', reward=150, requiredLevel=3, item='water' },
{ name='use_carbinerifle',title='Locked & Loaded', description='Test a carbine rifle for the first time. Make sure to stay safe while doing so.', reward=350, requiredLevel=5, item='weapon_carbinerifle' },
{ name='complete_5_quests', title='Rising Adventurer', description='Complete 5 quests to prove you’re ready for bigger challenges.', reward=200, requiredLevel=0, questCount=5 },
{ name='complete_10_quests', title='Battle-Tested', description='Complete 10 quests and show your dedication to the journey.', reward=300, requiredLevel=0, questCount=10 },
{ name='complete_30_quests', title='Seasoned Hero', description='Complete 30 quests and earn recognition as a true adventurer.', reward=600, requiredLevel=0, questCount=30 },
{ name='complete_50_quests', title='Mythical Champion', description='Complete 50 quests and ascend to mythical status among players.', reward=1000, requiredLevel=0, questCount=50 },
{ name='complete_100_quests', title='Master of All Quests',description='Complete 100 quests and dominate the world of adventures.', reward=2000, requiredLevel=0, questCount=100 },
{ name='epic_item', title='Wielder of the Epic', description='Find and equip an epic item to show your elite potential.', reward=300, requiredLevel=0, itemRarity='epic' },
{ name='legendary_item', title='Bearer of Legends', description='Use a legendary item to mark your place among the elite.', reward=500, requiredLevel=0, itemRarity='legendary' },
{ name='add_attachment', title='Weapon Specialist', description='Enhance your weapon with an attachment to increase its power.', reward=1000, requiredLevel=0 },
{ name='reload_weapon', title='Locked and Loaded', description='Reload your weapon at least 5 times—stay sharp and ready.', reward=150, requiredLevel=0 },
{ name='change_color', title='Style It Your Way', description='Customize your inventory color and make it uniquely yours.', reward=400, requiredLevel=0 },
{ name='give_item_to_player', title='The Generous One', description='Give an item to another player and strengthen community bonds.', reward=500, requiredLevel=0 },
{ name='level_5', title='Level 5 Unlocked', description='Reach level 5 and unlock new abilities in your journey.', reward=500, requiredLevel=5 },
{ name='level_10', title='Onward to Level 10', description='Reach level 10 and take your skills to the next tier.', reward=1000, requiredLevel=10 },
{ name='level_20', title='Veteran Status', description='Reach level 20 and establish yourself as a seasoned player.', reward=2000, requiredLevel=20 },
{ name='level_50', title='Elite Ascension', description='Reach level 50 and claim your place among the elite.', reward=3000, requiredLevel=50 },
{ name='repair_weapon', title='Weaponsmith', description='Repair a damaged weapon and keep it ready for battle.', reward=1000, requiredLevel=0 },
}
--──────────────────────────────────────────────────────────────────────────────
-- Appearance / Clothing Bridge [AUTO]
-- [INFO] Detects supported appearance/clothing systems.
-- [ADV] Override if your resource names are custom/renamed.
--──────────────────────────────────────────────────────────────────────────────
local appearances = { -- [CORE] resource → alias
['illenium-appearance'] = 'illenium',
['qs-appearance'] = 'illenium',
['rcore_clothing'] = 'rcore',
['esx_skin'] = 'esx',
['qb-clothing'] = 'qb'
}
Config.Appearance = DependencyCheck(appearances) or 'standalone' -- [AUTO]
--──────────────────────────────────────────────────────────────────────────────
-- Clothing Behavior [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.TakePreviousClothes = false -- [EDIT] Return previously worn clothes to inventory on change.
--──────────────────────────────────────────────────────────────────────────────
-- World Drops [EDIT]
-- [INFO] Visuals & timing for dropped items in the world.
--──────────────────────────────────────────────────────────────────────────────
Config.ItemDropObject = `prop_paper_bag_small` -- [EDIT] Model hash for world drop object (false = no object).
Config.DropRefreshTime = 15 * 60 -- [EDIT] Refresh interval (seconds) for dropped stashes.
Config.MaxDropViewDistance = 9.5 -- [EDIT] Max distance to render drop labels/markers.
--──────────────────────────────────────────────────────────────────────────────
-- Gender Labels [EDIT]
-- [INFO] Used by UI and clothing pages. Extend if needed.
--──────────────────────────────────────────────────────────────────────────────
Config.Genders = {
['m'] = 'Male',
['f'] = 'Female',
[1] = 'Male',
[2] = 'Female'
}
--──────────────────────────────────────────────────────────────────────────────
-- Visual / UI Configuration [EDIT]
-- [INFO] Controls animations, idle camera, item mini-icons, rarities, and defaults.
-- [ADV] Changing CSS strings or icon classes affects the web UI directly.
--──────────────────────────────────────────────────────────────────────────────
-- Open animation & idle camera
Config.OpenInventoryAnim = true -- [EDIT] Play an animation when opening the inventory.
Config.IdleCamera = true -- [EDIT] Enable idle camera while inventory is open.
--──────────────────────────────────────────────────────────────────────────────
-- Item Mini Icons [EDIT]
-- [INFO] FontAwesome icon classes used in the inventory list/grid.
-- [INFO] Reference: https://fontawesome.com/ (ensure the class exists in your UI build).
--──────────────────────────────────────────────────────────────────────────────
Config.ItemMiniIcons = { -- [EDIT] Map item name → icon class.
['tosti'] = {
icon = 'fa-solid fa-utensils', -- [EDIT]
},
['water_bottle'] = {
icon = 'fa-solid fa-utensils', -- [EDIT]
},
}
--──────────────────────────────────────────────────────────────────────────────
-- Item Rarities (UI) [EDIT]
-- [INFO] Visual gradients for item rarity backgrounds (CSS snippets).
-- [ADV] Keep CSS minimal; avoid breaking the theme cascade.
--──────────────────────────────────────────────────────────────────────────────
Config.ItemRarities = {
{
name = 'common', -- [EDIT]
css = 'background-image: linear-gradient(to top, rgba(211,211,211,0.5), rgba(211,211,211,0) 60%) !important',
},
{
name = 'epic', -- [EDIT]
css = 'background-image: linear-gradient(to top, rgba(128,0,128,0.5), rgba(128,0,128,0) 60%) !important',
},
{
name = 'legendary',-- [EDIT]
css = 'background-image: linear-gradient(to top, rgba(255,215,0,0.5), rgba(255,215,0,0) 60%) !important',
},
}
--──────────────────────────────────────────────────────────────────────────────
-- Default Character Appearance [EDIT]
-- [INFO] Fallback drawables/props when no saved outfit is present.
-- [INFO] Indices correspond to GTA component ids (drawable/texture indexes).
-- [ADV] If you use custom clothes, adapt these to valid component indices.
--──────────────────────────────────────────────────────────────────────────────
Config.Defaults = {
['female'] = { -- [EDIT]
torso = 18,
jeans = 19,
shoes = 34,
arms = 15,
helmet = -1,
glasses = -1,
mask = 0,
tshirt = 2,
ears = -1,
bag = 0,
watch = -1,
chain = 0,
bracelets = -1,
vest = 0,
},
['male'] = { -- [EDIT]
torso = 15,
jeans = 14,
shoes = 34,
arms = 15,
helmet = -1,
glasses = -1,
mask = 0,
tshirt = 15,
ears = -1,
bag = 0,
watch = -1,
chain = 0,
bracelets = -1,
vest = 0
}
}
--──────────────────────────────────────────────────────────────────────────────
-- Pause Menu [EDIT]
-- [INFO] Controls the in-inventory pause menu, social links, and announcements.
--──────────────────────────────────────────────────────────────────────────────
Config.UseInventoryPauseMenuByDefault = true -- [EDIT] Open inventory pause menu when pressing ESC.
Config.DiscordLink = 'https://discord.gg/quasarstore' -- [EDIT] Discord link shown in pause menu.
Config.YoutubeLink = 'https://www.youtube.com/@quasarstore' -- [EDIT] YouTube link shown in pause menu.
-- [EDIT] News/announcements shown in the pause menu (newest first recommended).
Config.Announcements = {
{ title = 'Server Launch', message = 'The server is now live. Begin your journey and shape your destiny.', date = '2024-05-01 12:00:00' },
{ title = 'New Skill System', message = 'Our custom skill system is now active. Earn experience and unlock unique abilities.', date = '2024-05-03 14:30:00' },
{ title = 'Weekly Patch Deployed', message = 'Bug fixes, new content and performance improvements have been added. See patch notes on Discord.', date = '2024-05-05 10:00:00' },
{ title = 'Criminal Update', message = 'New heist routes and robbery mechanics are now available. Plan carefully, the cops are smarter.', date = '2024-05-06 17:00:00' },
{ title = 'Staff Applications Open', message = 'We’re recruiting active and mature players for the staff team. Apply now via the forum.', date = '2024-05-07 09:00:00' },
{ title = 'Skill Tree Expansion', message = 'New branches have been added to the skill tree. Customize your character even further.', date = '2024-05-08 13:00:00' },
{ title = 'Vehicle Economy Tweaks', message = 'Vehicle prices and insurance systems have been rebalanced to improve realism.', date = '2024-05-09 11:30:00' },
{ title = 'Roleplay Events Incoming',message = 'Major in-game events are planned this weekend. Stay tuned and be ready to participate.', date = '2024-05-10 19:00:00' },
}
--──────────────────────────────────────────────────────────────────────────────
-- Key Bindings [EDIT]
-- [INFO] Keyboard shortcuts for common inventory actions.
-- [ADV] Ensure keys don’t conflict with framework or other resources.
--──────────────────────────────────────────────────────────────────────────────
Config.KeyBinds = {
['inventory'] = 'TAB', -- [EDIT] Open inventory
['hotbar'] = 'Z', -- [EDIT] Show hotbar
['reload'] = 'R', -- [EDIT] Reload action
['handsup'] = 'X', -- [EDIT] Hands-up / robbery gesture
}
--──────────────────────────────────────────────────────────────────────────────
-- Debug & Persistence [ADV]
-- [INFO] Development-time diagnostics and periodic DB saves.
-- [WARN] Verbose logs and frequent saves can affect performance.
--──────────────────────────────────────────────────────────────────────────────
-- Interval notes:
-- [INFO] Inventories are saved on change after a delay; avoid frequent resource restarts.
-- [INFO] Use `/save-inventories` before restarting to force-save all players.
Config.Debug = true -- [ADV] Enable detailed console prints/logs (disable in production).
Config.ZoneDebug = false -- [ADV] Extra zone/poly debug output.
Config.InventoryPrefix = 'inventory' -- [ADV] Namespace prefix; changing requires codebase-wide updates.
Config.SaveInventoryInterval= 12500 -- [ADV] Milliseconds debounce before saving after changes.
Config.BypassQbInventory = true -- [ADV] Use qs-inventory even if qb-inventory exists (set false only if you know the implications).
--──────────────────────────────────────────────────────────────────────────────
-- Free Mode Keys (Editor / Placement) [EDIT]
-- [INFO] Controls for free-move/edit camera & object manipulation.
--──────────────────────────────────────────────────────────────────────────────
Config.FreeModeKeys = {
ChangeKey = Keys['LEFTCTRL'], -- [EDIT] Toggle free mode.
MoreSpeed = Keys['.'], -- [EDIT] Increase movement speed.
LessSpeed = Keys[','], -- [EDIT] Decrease movement speed.
MoveToTop = Keys['TOP'], -- [EDIT] Move up.
MoveToDown = Keys['DOWN'], -- [EDIT] Move down.
MoveToForward = Keys['TOP'], -- [EDIT] Move forward.
MoveToBack = Keys['DOWN'], -- [EDIT] Move backward.
MoveToRight = Keys['RIGHT'], -- [EDIT] Strafe right.
MoveToLeft = Keys['LEFT'], -- [EDIT] Strafe left.
RotateToTop = Keys['6'], -- [EDIT] Rotate up.
RotateToDown = Keys['7'], -- [EDIT] Rotate down.
RotateToLeft = Keys['8'], -- [EDIT] Rotate left.
RotateToRight = Keys['9'], -- [EDIT] Rotate right.
TiltToTop = Keys['Z'], -- [EDIT] Tilt up.
TiltToDown = Keys['X'], -- [EDIT] Tilt down.
TiltToLeft = Keys['C'], -- [EDIT] Tilt left.
TiltToRight = Keys['V'], -- [EDIT] Tilt right.
StickToTheGround = Keys['LEFTALT'], -- [EDIT] Snap object to ground.
}
--──────────────────────────────────────────────────────────────────────────────
-- Action Controls (Editor Hotkeys) [EDIT]
-- [INFO] Keybinds for point editing, rotation, elevation, and confirmations.
--──────────────────────────────────────────────────────────────────────────────
ActionControls = {
leftClick = { label = 'Place Object', codes = { 24 } }, -- [EDIT]
forward = { label = 'Forward +/-', codes = { 33, 32 } }, -- [EDIT] Move forward/backward
right = { label = 'Right +/-', codes = { 35, 34 } }, -- [EDIT] Move left/right
up = { label = 'Up +/-', codes = { 52, 51 } }, -- [EDIT] Raise/lower vertically
add_point = { label = 'Add Point', codes = { 24 } }, -- [EDIT]
undo_point = { label = 'Undo Last', codes = { 25 } }, -- [EDIT]
rotate_z = { label = 'RotateZ +/-', codes = { 20, 79 } }, -- [EDIT] Z-axis rotation
rotate_z_scroll = { label = 'RotateZ +/-', codes = { 17, 16 } }, -- [EDIT] Z-axis via scroll modifiers
offset_z = { label = 'Offset Z +/-', codes = { 44, 46 } }, -- [EDIT] Vertical offset
boundary_height = { label = 'Z Boundary +/-', codes = { 20, 73 } }, -- [EDIT] Change Z boundary
done = { label = 'Done', codes = { 191 } }, -- [EDIT] Confirm/finish
cancel = { label = 'Cancel', codes = { 194 } }, -- [EDIT] Cancel current action
throw = { label = 'Throw', codes = { 24, 25 } }, -- [EDIT] Throw current weapon
}
--──────────────────────────────────────────────────────────────────────────────
-- Free Camera Options [EDIT]
-- [INFO] Tuning for editor/preview camera movement & rotation speeds.
--──────────────────────────────────────────────────────────────────────────────
CameraOptions = {
lookSpeedX = 1000.0, -- [EDIT] Horizontal look speed
lookSpeedY = 1000.0, -- [EDIT] Vertical look speed
moveSpeed = 20.0, -- [EDIT] Movement speed
climbSpeed = 10.0, -- [EDIT] Vertical climb speed
rotateSpeed= 20.0, -- [EDIT] Rotation speed
}qs-inventory/config/crafting.lua
--──────────────────────────────────────────────────────────────────────────────
-- Crafting System [EDIT]
-- [INFO] Enables/disables the standalone crafting system.
-- [INFO] Supports success rates, rep requirements (QB only), and multiple tables.
--──────────────────────────────────────────────────────────────────────────────
Config.Crafting = true -- [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- Reputation System (QBCore only) [EDIT]
-- [INFO] Locks recipes behind rep thresholds; uses `craftingrep` or `attachmentcraftingrep`.
--──────────────────────────────────────────────────────────────────────────────
Config.CraftingReputation = false -- [EDIT] Enable reputation-based crafting.
Config.ThresholdItems = false -- [EDIT] Show only if rep >= threshold.
--──────────────────────────────────────────────────────────────────────────────
-- Example Crafting Function [INFO]
-- [INFO] Example to open a custom crafting UI using exports and server events.
--──────────────────────────────────────────────────────────────────────────────
function OpenCrafting()
local CustomCrafting = {
[1] = {
name = 'weapon_pistol',
amount = 50,
info = {},
costs = { ['tosti'] = 1 },
type = 'weapon',
slot = 1,
rep = 'attachmentcraftingrep',
points = 1,
threshold = 0,
time = 5500,
chance = 100
},
[2] = {
name = 'water_bottle',
amount = 1,
info = {},
costs = { ['tosti'] = 1 },
type = 'item',
slot = 2,
rep = 'attachmentcraftingrep',
points = 1,
threshold = 0,
time = 8500,
chance = 100
},
}
local items = exports['qs-inventory']:SetUpCrafing(CustomCrafting)
local crafting = { label = 'Craft', items = items }
TriggerServerEvent('inventory:server:SetInventoryItems', items)
TriggerServerEvent('inventory:server:OpenInventory', 'customcrafting', crafting.label, crafting)
end
--──────────────────────────────────────────────────────────────────────────────
-- Crafting Tables [EDIT]
-- [INFO] Define job/location-based crafting stations with unique items.
--──────────────────────────────────────────────────────────────────────────────
Config.CraftingTables = {
[1] = {
name = 'Police Crafting',
isjob = 'police',
grades = 'all',
text = '[E] - Police Craft',
blip = {
enabled = true,
title = 'Police Crafting',
scale = 1.0,
display = 4,
colour = 0,
id = 365
},
location = vec3(459.771, -989.050, 24.898),
items = {
[1] = {
name = 'weapon_pistol',
amount = 50,
info = {},
costs = {
['iron'] = 80,
['metalscrap'] = 70,
['rubber'] = 8,
['steel'] = 60,
['lockpick'] = 5,
},
type = 'weapon',
slot = 1,
rep = 'attachmentcraftingrep',
points = 1,
threshold = 0,
time = 5500,
chance = 100
},
[2] = {
name = 'weapon_smg',
amount = 1,
info = {},
costs = {
['iron'] = 80,
['metalscrap'] = 120,
['rubber'] = 10,
['steel'] = 65,
['lockpick'] = 10,
},
type = 'weapon',
slot = 2,
rep = 'attachmentcraftingrep',
points = 1,
threshold = 0,
time = 8500,
chance = 100
},
[3] = {
name = 'weapon_carbinerifle',
amount = 1,
info = {},
costs = {
['iron'] = 120,
['metalscrap'] = 120,
['rubber'] = 20,
['steel'] = 90,
['lockpick'] = 14,
},
type = 'weapon',
slot = 3,
rep = 'craftingrep',
points = 2,
threshold = 0,
time = 12000,
chance = 100
}
}
},
[2] = {
name = 'Attachment Crafting',
isjob = false,
grades = 'all',
text = '[E] - Craft Attachment',
blip = {
enabled = true,
title = 'Attachment Crafting',
scale = 1.0,
display = 4,
colour = 0,
id = 365
},
location = vec3(90.303, 3745.503, 39.771),
items = {
[1] = {
name = 'pistol_extendedclip',
amount = 50,
info = {},
costs = {
['metalscrap'] = 140,
['steel'] = 250,
['rubber'] = 60,
},
type = 'item',
slot = 1,
rep = 'attachmentcraftingrep',
points = 1,
threshold = 0,
time = 8000,
chance = 90
},
[2] = {
name = 'pistol_suppressor',
amount = 50,
info = {},
costs = {
['metalscrap'] = 165,
['steel'] = 285,
['rubber'] = 75,
},
type = 'item',
slot = 2,
rep = 'attachmentcraftingrep',
points = 1,
threshold = 0,
time = 8000,
chance = 90
},
}
},
}
qs-inventory/config/customWeapons.lua
--──────────────────────────────────────────────────────────────────────────────
-- Custom Weapons [EDIT]
-- [INFO] Map weapon names to allowed attachments and durability loss per shot.
-- [INFO] You must also register these in items.lua and weapons.lua.
-- [REF] Example reference: https://github.com/NoobySloth/Custom-Weapons/tree/main
--──────────────────────────────────────────────────────────────────────────────
Config.CustomWeapons = {
-- -- Example:
-- ['WEAPON_AK47'] = {
-- attachments = {
-- defaultclip = { component = 'COMPONENT_AK47_CLIP_01', item = 'rifle_defaultclip' }, -- [EDIT]
-- extendedclip = { component = 'COMPONENT_AK47_CLIP_02', item = 'rifle_extendedclip' }, -- [EDIT]
-- -- Add more: scope = { component = 'COMPONENT_AK47_SCOPE', item = 'rifle_scope' },
-- },
-- durability = 0.15 -- [EDIT] Durability decay per shot (0.0–1.0; higher = wears faster)
-- },
}qs-inventory/config/defaultColors.js
//──────────────────────────────────────────────────────────────────────────────
// UI Color Configuration [EDIT]
// [INFO] Defines the visual theme for the interface: colors, opacity, and backgrounds.
// [TIP] Use HEX color codes (#RRGGBB) and opacity values between 0.0–1.0.
//──────────────────────────────────────────────────────────────────────────────
//──────────────────────────────────────────────────────────────────────────────
// Base Colors [EDIT]
//──────────────────────────────────────────────────────────────────────────────
const defaultPrimaryColor = "#00A3FF"; // [EDIT] Primary UI color for buttons, highlights, and key elements.
const defaultPrimaryOpacity = "1"; // [EDIT] Opacity for primary color (0.0–1.0).
const defaultSecondaryColor = "#28343C"; // [EDIT] Secondary color for side panels and secondary areas.
const defaultSecondaryOpacity = "0.8"; // [EDIT] Opacity for secondary color.
const defaultBorderColor = "#0190e1"; // [EDIT] Border color for buttons, boxes, and inputs.
const defaultBorderOpacity = "1"; // [EDIT] Opacity for border color.
const defaultBorderRadius = "1px"; // [EDIT] Corner roundness for UI elements.
const defaultTextColor = "#FFFFFF"; // [EDIT] Text color for readability on dark backgrounds.
//──────────────────────────────────────────────────────────────────────────────
// Background Presets [EDIT]
// [INFO] List of available gradient backgrounds for the UI.
// [TIP] The one marked with "default: true" is preselected on first use.
//──────────────────────────────────────────────────────────────────────────────
const backgrounds = [
{ model: "qs_gradient_01", image: "1.webp" },
{ model: "qs_gradient_02", image: "2.webp" },
{ model: "qs_gradient_03", image: "3.webp" },
{ model: "qs_gradient_04", image: "4.webp" },
{ model: "qs_gradient_05", image: "5.webp" },
{ model: "qs_gradient_06", image: "6.webp" },
{ model: "qs_gradient_07", image: "7.webp" },
{ model: "qs_gradient_08", image: "8.webp" },
{ model: "qs_gradient_09", image: "9.webp" },
{ model: "qs_gradient_010", image: "10.webp" },
{ model: "qs_gradient_011", image: "11.webp" },
{ model: "qs_gradient_012", image: "12.webp" },
{ model: "qs_gradient_013", image: "13.webp" },
{ model: "qs_gradient_014", image: "14.webp" },
{ model: "qs_gradient_015", image: "15.webp" },
{ model: "qs_gradient_016", image: "16.webp" },
{ model: "qs_gradient_017", image: "17.webp" },
{ model: "qs_gradient_018", image: "18.webp" },
{ model: "qs_gradient_019", image: "19.webp" },
{ model: "qs_gradient_020", image: "20.webp" },
{ model: "qs_gradient_021", image: "21.webp" },
{ model: "qs_gradient_022", image: "22.webp", default: true },
{ model: "qs_gradient_023", image: "23.webp" },
{ model: "qs_gradient_024", image: "24.webp" },
{ model: "qs_gradient_025", image: "25.webp" },
{ model: "qs_gradient_026", image: "26.webp" },
{ model: "qs_gradient_027", image: "27.webp" },
{ model: "qs_gradient_028", image: "28.webp" },
{ model: "qs_gradient_029", image: "29.webp" },
{ model: "qs_gradient_030", image: "30.webp" },
{ model: "qs_gradient_031", image: "31.webp" },
];
qs-inventory/config/garbage.lua
--──────────────────────────────────────────────────────────────────────────────
-- Garbage Loot System [EDIT]
-- [INFO] Configure dumpster props and their randomized loot tables.
-- [INFO] Works with target-based interaction; safe to ignore if you don’t use targets.
--──────────────────────────────────────────────────────────────────────────────
Config.GarbageItems = {} -- [CORE] Runtime cache (leave as is).
--──────────────────────────────────────────────────────────────────────────────
-- Garbage Props [EDIT]
-- [INFO] World object names that act as searchable garbage containers.
--──────────────────────────────────────────────────────────────────────────────
Config.GarbageObjects = {
'prop_dumpster_02a', -- Standard dumpster
'prop_dumpster_4b', -- Large blue dumpster
'prop_dumpster_4a', -- Large green dumpster
'prop_dumpster_3a', -- Small gray dumpster
'prop_dumpster_02b', -- Alt model
'prop_dumpster_01a', -- Basic model
}
--──────────────────────────────────────────────────────────────────────────────
-- Loot Tables per Prop [EDIT]
-- [INFO] Map prop hash → container definition (label, slot count, and item pools).
-- [INFO] Each items section contains “rolls” with possible item entries.
-- [TIP] Adjust amount.min/max to tune rewards. Add/remove entries freely.
--──────────────────────────────────────────────────────────────────────────────
Config.GarbageItemsForProp = {
-- prop_dumpster_02a -------------------------------------------------------
[joaat('prop_dumpster_02a')] = {
label = 'Garbage', -- [EDIT] Container label shown to players.
slots = 30, -- [EDIT] Max virtual slots inside this container.
items = {
[1] = { -- Roll 1
[1] = { name = 'aluminum', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
[2] = { -- Roll 2
[1] = { name = 'iron', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'steel', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
}
},
-- prop_dumpster_4b --------------------------------------------------------
[joaat('prop_dumpster_4b')] = {
label = 'Garbage',
slots = 30,
items = {
[1] = {
[1] = { name = 'aluminum', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'plastic', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
[2] = {
[1] = { name = 'plastic', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
}
},
-- prop_dumpster_4a --------------------------------------------------------
[joaat('prop_dumpster_4a')] = {
label = 'Garbage',
slots = 30,
items = {
[1] = {
[1] = { name = 'aluminum', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
[2] = {
[1] = { name = 'glass', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'joint', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
}
},
-- prop_dumpster_3a --------------------------------------------------------
[joaat('prop_dumpster_3a')] = {
label = 'Garbage',
slots = 30,
items = {
[1] = {
[1] = { name = 'aluminum', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'lighter', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
[2] = {
[1] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'rubber', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
}
},
-- prop_dumpster_02b -------------------------------------------------------
[joaat('prop_dumpster_02b')] = {
label = 'Garbage',
slots = 30,
items = {
[1] = {
[1] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'rubber', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
[2] = {
[1] = { name = 'iron', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'steel', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
}
},
-- prop_dumpster_01a -------------------------------------------------------
[joaat('prop_dumpster_01a')] = {
label = 'Garbage',
slots = 30,
items = {
[1] = {
[1] = { name = 'plastic', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
[2] = {
[1] = { name = 'lighter', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 1 },
[2] = { name = 'metalscrap', amount = { min = 1, max = 5 }, info = {}, type = 'item', slot = 2 },
},
}
},
}
qs-inventory/config/selling.lua
--──────────────────────────────────────────────────────────────────────────────
-- Seller / Vending Stores [CORE]
-- [INFO] Define NPC stores with coords, optional blip, and sellable items.
-- [EDIT] Duplicate an entry to add a new store. Keep field names unchanged.
--──────────────────────────────────────────────────────────────────────────────
Config.SellItems = {
['Seller item'] = {
coords = vec3(2682.7588, 3284.8857, 55.2103), -- Store location
blip = { -- Map blip (set active=false to hide)
active = true,
name = 'Seller',
sprite = 89,
color = 1,
scale = 0.5,
account = 'money' -- 'money', 'bank', etc.
},
items = {
{ name = 'sandwich', price = 3, amount = 1, info = {}, type = 'item', slot = 1 },
{ name = 'tosti', price = 2, amount = 1, info = {}, type = 'item', slot = 2 },
{ name = 'water_bottle', price = 2, amount = 1, info = {}, type = 'item', slot = 3 },
}
},
['24/7'] = {
coords = vec3(2679.9326, 3276.6897, 54.4058),
blip = {
active = true,
name = '24/7 Store',
sprite = 89,
color = 1,
scale = 0.5,
account = 'money'
},
items = {
{ name = 'tosti', price = 1, amount = 1, info = {}, type = 'item', slot = 1 },
}
},
}
qs-inventory/config/storage.lua
--──────────────────────────────────────────────────────────────────────────────
-- Container / Storage Items [CORE]
-- [INFO] Define items that behave as containers (mini-inventories).
-- [EDIT] Each entry sets capacity, slot count, and default contents.
-- [TIP] Weight must be lower than parent item weight to prevent nesting.
--──────────────────────────────────────────────────────────────────────────────
Config.Storage = {
[1] = {
name = "cigarettebox", -- [EDIT] Container item name.
label = "Cigarette Box", -- [EDIT] Display label in inventory.
weight = 50, -- [EDIT] Max weight this container can hold.
slots = 1, -- [EDIT] Slot count inside container.
items = {
[1] = {
name = "cigarette",
label = "Cigarette",
description = "A single cigarette",
useable = true,
type = "item",
amount = 20,
weight = 1,
unique = false,
slot = 1,
info = {},
},
-- Add more items here.
}
},
-- Add more storage containers here.
}
qs-inventory/config/vehicles.lua
--──────────────────────────────────────────────────────────────────────────────
-- Vehicle Storage / Access [CORE]
-- [INFO] Ownership gates, police overrides, and per-class/per-model capacity.
-- [EDIT] Toggle usage in vehicles; tune trunk/glovebox weights & slots.
--──────────────────────────────────────────────────────────────────────────────
Config.IsVehicleOwned = false -- [EDIT] If true, only owned vehicles persist trunk data.
Config.UseItemInVehicle = true -- [EDIT] Disable item usage in vehicles when false.
Config.WeaponsOnVehicle = true -- [EDIT] Disable weapon storage in vehicles when false (perf impact).
-- Access rules
Config.OpenTrunkAll = true -- [EDIT] Anyone can open any trunk.
Config.OpenTrunkPolice = true -- [EDIT] Police can open trunks when restricted.
Config.OpenTrunkPoliceGrade = 0 -- [EDIT] Min police grade for trunk override.
Config.OpenGloveboxesAll = true -- [EDIT] Anyone can open any glovebox.
Config.OpenGloveboxesPolice = true -- [EDIT] Police can open gloveboxes when restricted.
Config.OpenGloveboxesPoliceGrade = 0 -- [EDIT] Min police grade for glovebox override.
--──────────────────────────────────────────────────────────────────────────────
-- Class Defaults (FiveM vehicle classes) [DATA]
-- [INFO] Per-class glovebox/trunk capacities. See: _0x29439776AAA00A62 list.
--──────────────────────────────────────────────────────────────────────────────
Config.VehicleClass = {
[0] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 38000, slots = 30 } }, -- Compacts
[1] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 50000, slots = 40 } }, -- Sedans
[2] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 75000, slots = 50 } }, -- SUVs
[3] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 42000, slots = 35 } }, -- Coupes
[4] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 38000, slots = 30 } }, -- Muscle
[5] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 30000, slots = 25 } }, -- Sports Classics
[6] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 30000, slots = 25 } }, -- Sports
[7] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 30000, slots = 25 } }, -- Super
[8] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 15000, slots = 15 } }, -- Motorcycles
[9] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 60000, slots = 35 } }, -- Off-road
[10] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 60000, slots = 35 } }, -- Industrial
[11] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 60000, slots = 35 } }, -- Utility
[12] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 35 } }, -- Vans
[13] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 0, slots = 0 } }, -- Cycles
[14] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Boats
[15] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Helicopters
[16] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Planes
[17] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Service
[18] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Emergency
[19] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Military
[20] = { glovebox = { maxweight = 100000, slots = 5 }, trunk = { maxweight = 120000, slots = 50 } }, -- Commercial
}
--──────────────────────────────────────────────────────────────────────────────
-- Per-Model Overrides [DATA]
-- [INFO] Use joaat(model) for exact model capacities regardless of class.
--──────────────────────────────────────────────────────────────────────────────
Config.CustomTrunk = {
[joaat('adder')] = { slots = 5, maxweight = 100000 },
}
Config.CustomGlovebox = {
[joaat('adder')] = { slots = 5, maxweight = 100000 },
}
--──────────────────────────────────────────────────────────────────────────────
-- Front Trunk (Rear-Engine Vehicles) [DATA]
-- [INFO] Marks models whose trunk opens at the front (rear-engine layout).
--──────────────────────────────────────────────────────────────────────────────
Config.BackEngineVehicles = {
[`ninef`] = true, [`ninef2`] = true,
[`adder`] = true, [`vagner`] = true, [`t20`] = true,
[`infernus`] = true, [`zentorno`] = true, [`reaper`] = true,
[`comet2`] = true, [`comet3`] = true, [`jester`] = true,
[`jester2`] = true, [`cheetah`] = true, [`cheetah2`] = true,
[`prototipo`] = true, [`turismor`] = true, [`pfister811`] = true,
[`ardent`] = true, [`nero`] = true, [`nero2`] = true,
[`tempesta`] = true, [`vacca`] = true, [`bullet`] = true,
[`osiris`] = true, [`entityxf`] = true, [`turismo2`] = true,
[`fmj`] = true, [`re7b`] = true, [`tyrus`] = true,
[`italigtb`] = true, [`penetrator`] = true, [`monroe`] = true,
[`stingergt`] = true, [`surfer`] = true, [`surfer2`] = true,
[`gp1`] = true, [`autarch`] = true, [`tyrant`] = true,
-- Add more models as needed…
}
qs-inventory/config/vending.lua
--──────────────────────────────────────────────────────────────────────────────
-- Vending Machines Configuration [EDIT]
-- [INFO] Defines categories of items sold by vending machines and links models
-- in the world to those categories for interactive purchasing.
-- [TIP] Duplicate entries to create new categories or machine types.
--──────────────────────────────────────────────────────────────────────────────
Config.VendingMachines = {
['drinks'] = { -- Category: Drinks
Label = 'Drinks',
Items = {
[1] = {
name = 'kurkakola', -- [EDIT] Item name
price = 4, -- [EDIT] Item price
amount = 50, -- [EDIT] Stock quantity
info = {}, -- [INFO] Optional metadata
type = 'item', -- [CORE] Usually 'item'
slot = 1, -- [INFO] UI slot position
},
[2] = {
name = 'water_bottle',
price = 4,
amount = 50,
info = {},
type = 'item',
slot = 2,
},
},
},
['candy'] = { -- Category: Candy
Label = 'Candy',
Items = {
[1] = {
name = 'chocolate', -- [EDIT] Candy item
price = 4,
amount = 50,
info = {},
type = 'item',
slot = 1,
},
},
},
['coffee'] = { -- Category: Coffee
Label = 'Coffee',
Items = {
[1] = {
name = 'coffee', -- [EDIT] Coffee drink
price = 4,
amount = 50,
info = {},
type = 'item',
slot = 1,
},
},
},
['water'] = { -- Category: Water
Label = 'Water',
Items = {
[1] = {
name = 'water_bottle', -- [EDIT] Water bottle
price = 4,
amount = 50,
info = {},
type = 'item',
slot = 1,
},
},
},
}
--──────────────────────────────────────────────────────────────────────────────
-- Vending Models [EDIT]
-- [INFO] Map vending prop models to the categories above.
-- [TIP] You can assign different models to sell different item groups.
--──────────────────────────────────────────────────────────────────────────────
Config.Vendings = {
[1] = {
Model = 'prop_vend_coffe_01', -- [EDIT] Coffee vending prop
Category = 'coffee', -- [LINK] Uses items from 'coffee'
},
[2] = {
Model = 'prop_vend_water_01', -- [EDIT] Water vending prop
Category = 'water', -- [LINK] Uses items from 'water'
},
[3] = {
Model = 'prop_watercooler', -- [EDIT] Standard water cooler
Category = 'water', -- [LINK] Shares 'water' category
},
[4] = {
Model = 'prop_watercooler_Dark', -- [EDIT] Dark variant water cooler
Category = 'water', -- [LINK] Uses 'water' category
},
[5] = {
Model = 'prop_vend_snak_01', -- [EDIT] Snack vending prop
Category = 'candy', -- [LINK] Uses 'candy' category
},
[6] = {
Model = 'prop_vend_snak_01_tu', -- [EDIT] Snack vending variant
Category = 'candy', -- [LINK] Uses 'candy' category
},
[7] = {
Model = 'prop_vend_fridge01', -- [EDIT] Fridge vending machine
Category = 'drinks', -- [LINK] Uses 'drinks' category
},
[8] = {
Model = 'prop_vend_soda_01', -- [EDIT] Soda vending machine type 1
Category = 'drinks', -- [LINK] Uses 'drinks' category
},
[9] = {
Model = 'prop_vend_soda_02', -- [EDIT] Soda vending machine type 2
Category = 'drinks', -- [LINK] Uses 'drinks' category
},
}
qs-inventory/config/weapons.lua
--[[────────────────────────────────────────────────────────────────────────────
Weapons Configuration [EDIT]
[INFO] Centralized settings for weapons: tints removal, allowed ammo items,
blocked durability weapons, attachment lines, throwables, and per-weapon
durability multipliers.
Main configurations:
• Config.RemoveTintAfterRemoving – Remove tints when weapon is discarded. [EDIT]
• Config.ForceToOnlyOneMagazine – Enforce single magazine usage at a time. [EDIT]
• Config.DurabilityBlockedWeapons – Weapons exempt from durability loss. [EDIT]
• Config.WeaponAttachmentLines – UI bones/offsets for attachment lines. [ADV]
• Config.Throwables – Allowed throwable items. [EDIT]
• Config.AmmoItems – Mappings between items and GTA ammo types. [EDIT]
• Config.DurabilityMultiplier – Wear rates per weapon (higher = faster). [EDIT]
────────────────────────────────────────────────────────────────────────────]]
--──────────────────────────────────────────────────────────────────────────────
-- General Toggles [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.RemoveTintAfterRemoving = false -- [EDIT] If true, weapon tints are removed when the weapon is discarded
Config.ForceToOnlyOneMagazine = true -- [EDIT] If true, player can use only one magazine at a time (swap when empty)
--──────────────────────────────────────────────────────────────────────────────
-- Durability: Blocked Weapons [EDIT]
-- [INFO] Any weapon listed here will not lose durability.
--──────────────────────────────────────────────────────────────────────────────
Config.DurabilityBlockedWeapons = {
'weapon_stungun',
'weapon_nightstick',
'weapon_flashlight',
'weapon_unarmed',
}
--──────────────────────────────────────────────────────────────────────────────
-- Attachment Lines (Bones & Offsets) [ADV]
-- [INFO] Configure how attachment helper lines are drawn in UI/preview.
-- [TIP] Add/adjust bones and 2D offsets to match your weapon models.
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponAttachmentLines = {
['suppressor'] = {
bones = { 'WAPSupp', 'WAPSupp_2' }, -- [EDIT] Bone names used for suppressor line
offset = vec2(-25, -20), -- [EDIT] 2D offset for UI placement
},
['flash'] = {
bones = { 'WAPFlshLasr', 'WAPFlshLasr_2' },
offset = vec2(5, 24)
},
['scope'] = {
bones = { 'WAPScop', 'WAPScop_2' },
offset = vec2(5, -25),
},
['barrel'] = {
bones = { 'Gun_GripR', 'Gun_GripR_2' },
offset = vec2(20, 20),
},
['grip'] = {
bones = { 'WAPGrip', 'WAPGrip_2' },
offset = vec2(-20, 20),
},
['clip'] = {
bones = { 'WAPClip', 'WAPClip_2' },
offset = vec2(-40, 10),
},
['tint'] = {
default = true, -- [INFO] Mark as default-visible helper
offset = vec2(20, 0),
}
}
--──────────────────────────────────────────────────────────────────────────────
-- Throwables [EDIT]
-- [INFO] Allowed throwable items usable by players.
-- [TIP] Remove or add names to restrict/expand throwables.
--──────────────────────────────────────────────────────────────────────────────
Config.Throwables = {
'ball',
'bzgas',
'flare',
'grenade',
'molotov',
'pipebomb',
'proxmine',
'smokegrenade',
'snowball',
'stickybomb',
'newspaper',
}
--──────────────────────────────────────────────────────────────────────────────
-- Ammo Items Mapping [EDIT]
-- [INFO] Map inventory items to GTA ammo types. "isForEveryWeapon" applies to all.
-- [TIP] Keep item names aligned with your items database.
--──────────────────────────────────────────────────────────────────────────────
---@type table<number, {item: string, type?: string, isForEveryWeapon?: boolean}>
Config.AmmoItems = {
{ item = 'pistol_ammo', type = 'AMMO_PISTOL' },
{ item = 'rifle_ammo', type = 'AMMO_RIFLE' },
{ item = 'smg_ammo', type = 'AMMO_SMG' },
{ item = 'shotgun_ammo', type = 'AMMO_SHOTGUN' },
{ item = 'mg_ammo', type = 'AMMO_MG' },
{ item = 'emp_ammo', type = 'AMMO_EMPLAUNCHER' },
{ item = 'rpg_ammo', type = 'AMMO_RPG' },
{ item = 'grenadelauncher_ammo', type = 'AMMO_GRENADELAUNCHER' },
{ item = 'snp_ammo', type = 'AMMO_SNIPER' },
{ item = 'master_ammo', isForEveryWeapon = true }, -- [INFO] Universal ammo item
}
--──────────────────────────────────────────────────────────────────────────────
-- Durability Multipliers [EDIT]
-- [INFO] Wear rates per weapon hash/key. Higher values = faster degradation.
-- [TIP] Tune per-family to balance gameplay. 0.0 disables wear (not recommended).
--──────────────────────────────────────────────────────────────────────────────
Config.DurabilityMultiplier = {
-- Melee Weapons ---------------------------------------------------------- [EDIT]
weapon_dagger = 0.15,
weapon_bat = 0.15,
weapon_bottle = 0.15,
weapon_crowbar = 0.15,
weapon_candycane = 0.15,
weapon_golfclub = 0.15,
weapon_hammer = 0.15,
weapon_hatchet = 0.15,
weapon_knuckle = 0.15,
weapon_knife = 0.15,
weapon_machete = 0.15,
weapon_switchblade = 0.15,
weapon_wrench = 0.15,
weapon_battleaxe = 0.15,
weapon_poolcue = 0.15,
weapon_briefcase = 0.15,
weapon_briefcase_02 = 0.15,
weapon_garbagebag = 0.15,
weapon_handcuffs = 0.15,
weapon_bread = 0.15,
weapon_stone_hatchet = 0.15,
-- Handguns --------------------------------------------------------------- [EDIT]
weapon_pistol = 0.15,
weapon_pistol_mk2 = 0.15,
weapon_combatpistol = 0.15,
weapon_appistol = 0.15,
weapon_pistol50 = 0.15,
weapon_snspistol = 0.15,
weapon_heavypistol = 0.15,
weapon_vintagepistol = 0.15,
weapon_flaregun = 0.15,
weapon_marksmanpistol = 0.15,
weapon_revolver = 0.15,
weapon_revolver_mk2 = 0.15,
weapon_doubleaction = 0.15,
weapon_snspistol_mk2 = 0.15,
weapon_raypistol = 0.15,
weapon_ceramicpistol = 0.15,
weapon_navyrevolver = 0.15,
weapon_gadgetpistol = 0.15,
weapon_pistolxm3 = 0.15,
-- Submachine Guns -------------------------------------------------------- [EDIT]
weapon_microsmg = 0.15,
weapon_smg = 0.15,
weapon_smg_mk2 = 0.15,
weapon_assaultsmg = 0.15,
weapon_combatpdw = 0.15,
weapon_machinepistol = 0.15,
weapon_minismg = 0.15,
weapon_raycarbine = 0.15,
-- Shotguns --------------------------------------------------------------- [EDIT]
weapon_pumpshotgun = 0.15,
weapon_sawnoffshotgun = 0.15,
weapon_assaultshotgun = 0.15,
weapon_bullpupshotgun = 0.15,
weapon_musket = 0.15,
weapon_heavyshotgun = 0.15,
weapon_dbshotgun = 0.15,
weapon_autoshotgun = 0.15,
weapon_pumpshotgun_mk2 = 0.15,
weapon_combatshotgun = 0.15,
-- Assault Rifles --------------------------------------------------------- [EDIT]
weapon_assaultrifle = 0.15,
weapon_assaultrifle_mk2 = 0.15,
weapon_carbinerifle = 0.15,
weapon_carbinerifle_mk2 = 0.15,
weapon_advancedrifle = 0.15,
weapon_specialcarbine = 0.15,
weapon_bullpuprifle = 0.15,
weapon_compactrifle = 0.15,
weapon_specialcarbine_mk2 = 0.15,
weapon_bullpuprifle_mk2 = 0.15,
weapon_militaryrifle = 0.15,
weapon_heavyrifle = 0.15,
-- Light Machine Guns ----------------------------------------------------- [EDIT]
weapon_mg = 0.15,
weapon_combatmg = 0.15,
weapon_gusenberg = 0.15,
weapon_combatmg_mk2 = 0.15,
-- Sniper Rifles ---------------------------------------------------------- [EDIT]
weapon_sniperrifle = 0.15,
weapon_heavysniper = 0.15,
weapon_marksmanrifle = 0.15,
weapon_remotesniper = 0.15,
weapon_heavysniper_mk2 = 0.15,
weapon_marksmanrifle_mk2 = 0.15,
-- Heavy Weapons ---------------------------------------------------------- [EDIT]
weapon_rpg = 0.15,
weapon_grenadelauncher = 0.15,
weapon_grenadelauncher_smoke = 0.15,
weapon_emplauncher = 0.15,
weapon_minigun = 0.15,
weapon_firework = 0.15,
weapon_railgun = 0.15,
weapon_hominglauncher = 0.15,
weapon_compactlauncher = 0.15,
weapon_rayminigun = 0.15,
weapon_railgunxm3 = 0.15,
-- Throwables ------------------------------------------------------------- [EDIT]
weapon_grenade = 0.15,
weapon_bzgas = 0.15,
weapon_molotov = 0.15,
weapon_stickybomb = 0.15,
weapon_proxmine = 0.15,
weapon_snowball = 0.15,
weapon_pipebomb = 0.15,
weapon_ball = 0.15,
weapon_smokegrenade = 0.15,
weapon_flare = 0.15,
-- Miscellaneous ---------------------------------------------------------- [EDIT]
weapon_petrolcan = 0.15,
weapon_fireextinguisher = 0.15,
weapon_hazardcan = 0.15,
weapon_fertilizercan = 0.15,
}
--[[────────────────────────────────────────────────────────────────────────────
Weapon Repair & Accessories Configuration [EDIT]
[INFO] Centralized settings for weapon maintenance, part stealing, and
attachments/tints. Duplicate or extend blocks to fit your gameplay.
Main configurations:
• Config.WeaponRepairItemAddition – Amount added to the repair-kit item. [EDIT]
• Config.WeaponRepairPoints – World repair points (coords/state/data). [EDIT]
• Config.WeaponRepairCosts – Repair price per weapon category. [EDIT]
• Config.CanStealWeaponParts – Enable stealing of weapon parts. [EDIT]
• Config.WeaponPartStealChance – % chance to successfully steal a part. [EDIT]
• Config.AvailableWeaponParts – List of stealable part item names. [EDIT]
• Config.WeaponAttachments – Per-weapon tints/attachments mapping. [ADV]
────────────────────────────────────────────────────────────────────────────]]
--──────────────────────────────────────────────────────────────────────────────
-- Repair: General [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponRepairItemAddition = 10 -- [EDIT] Amount added to the repair kit item on use
--──────────────────────────────────────────────────────────────────────────────
-- Repair: Points [EDIT]
-- [INFO] Define as many repair points as needed. Each entry tracks its state.
-- [TIP] Use unique indices and valid vector3 coordinates.
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponRepairPoints = {
[1] = {
coords = vector3(964.02, -1267.41, 34.97), -- [EDIT] World position
IsRepairing = false, -- [INFO] Runtime flag (do not edit manually)
RepairingData= {}, -- [INFO] Runtime data (filled by script)
},
-- [TIP] Copy/paste to add more repair points with unique indices
}
--──────────────────────────────────────────────────────────────────────────────
-- Repair: Costs [EDIT]
-- [INFO] Prices per weapon category. Tune to your economy.
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponRepairCosts = {
pistol = 1000, -- [EDIT] Pistols
smg = 3000, -- [EDIT] Submachine guns
mg = 4000, -- [EDIT] Machine guns
rifle = 5000, -- [EDIT] Rifles
sniper = 7000, -- [EDIT] Sniper rifles
shotgun = 6000, -- [EDIT] Shotguns
}
--──────────────────────────────────────────────────────────────────────────────
-- Stealing: Weapon Parts [EDIT]
-- [INFO] Enables a system to loot generic parts/items from weapons.
-- [TIP] Increase chance for easier gameplay; decrease for harder.
--──────────────────────────────────────────────────────────────────────────────
Config.CanStealWeaponParts = false -- [EDIT] Toggle weapon-part stealing
Config.WeaponPartStealChance = 20 -- [EDIT] Success chance (1–100)
Config.AvailableWeaponParts = { -- [EDIT] Stealable part item names
'electronickit',
'ironoxide',
'metalscrap',
-- [TIP] Add more items as needed (must exist in your items database)
}
--[[────────────────────────────────────────────────────────────────────────────
Accessories (Tints & Attachments) [ADV]
[INFO] Configure per-weapon components. Each key is a GTA weapon name
(e.g., 'WEAPON_PISTOL'). Each attachment needs:
• component – GTA component hash/string
• item – Item name consumed/required to apply
Naming guidelines:
• Tints: use <name>_weapontint (e.g., luxuryfinish_weapontint).
• Attachments: use <category>_<attachment> (e.g., pistol_suppressor).
• Do not prefix attachments with WEAPON_ (reserve for weapon keys only).
Reference: https://wiki.rage.mp/index.php?title=Weapons_Components
────────────────────────────────────────────────────────────────────────────]]
Config.WeaponAttachments = {
-- PISTOL WEAPONS
-- Example configuration for WEAPON_PISTOL attachments
['WEAPON_PISTOL'] = {
defaultclip = { component = 'COMPONENT_PISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_PISTOL_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP_02', item = 'pistol_suppressor' },
luxuryfinish = { component = 'COMPONENT_PISTOL_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
-- Adding attachments for WEAPON_COMBATPISTOL following similar structure
['WEAPON_COMBATPISTOL'] = {
defaultclip = { component = 'COMPONENT_COMBATPISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_COMBATPISTOL_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'pistol_suppressor' },
luxuryfinish = { component = 'COMPONENT_COMBATPISTOL_VARMOD_LOWRIDER', item = 'luxuryfinish_weapontint' }
},
['WEAPON_PISTOL50'] = {
defaultclip = { component = 'COMPONENT_PISTOL50_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_PISTOL50_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'pistol_suppressor' },
luxuryfinish = { component = 'COMPONENT_PISTOL50_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_APPISTOL'] = {
defaultclip = { component = 'COMPONENT_APPISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_APPISTOL_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'pistol_suppressor' },
luxuryfinish = { component = 'COMPONENT_APPISTOL_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_REVOLVER'] = {
defaultclip = { component = 'COMPONENT_REVOLVER_CLIP_01', item = 'pistol_defaultclip' },
luxuryfinish = { component = 'COMPONENT_REVOLVER_VARMOD_BOSS', item = 'luxuryfinish_weapontint' }
},
['WEAPON_SNSPISTOL'] = {
defaultclip = { component = 'COMPONENT_SNSPISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_SNSPISTOL_CLIP_02', item = 'pistol_extendedclip' },
grip = { component = 'COMPONENT_SNSPISTOL_VARMOD_LOWRIDER', item = 'pistol_grip' },
luxuryfinish = { component = 'COMPONENT_SNSPISTOL_VARMOD_LOWRIDER', item = 'luxuryfinish_weapontint' }
},
['WEAPON_HEAVYPISTOL'] = {
defaultclip = { component = 'COMPONENT_HEAVYPISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_HEAVYPISTOL_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'pistol_suppressor' },
grip = { component = 'COMPONENT_HEAVYPISTOL_VARMOD_LUXE', item = 'pistol_grip' },
luxuryfinish = { component = 'COMPONENT_HEAVYPISTOL_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_VINTAGEPISTOL'] = {
defaultclip = { component = 'COMPONENT_VINTAGEPISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_VINTAGEPISTOL_CLIP_02', item = 'pistol_extendedclip' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'pistol_suppressor' }
},
['WEAPON_CERAMICPISTOL'] = {
defaultclip = { component = 'COMPONENT_CERAMICPISTOL_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_CERAMICPISTOL_CLIP_02', item = 'pistol_extendedclip' },
suppressor = { component = 'COMPONENT_CERAMICPISTOL_SUPP', item = 'pistol_suppressor' }
},
['WEAPON_PISTOL_MK2'] = {
defaultclip = { component = 'COMPONENT_PISTOL_MK2_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_PISTOL_MK2_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH_02', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP_02', item = 'pistol_suppressor' },
compensator = { component = 'COMPONENT_AT_PI_COMP', item = 'pistol_compensator' },
holoscope = { component = 'COMPONENT_AT_PI_RAIL', item = 'pistol_holoscope' },
digicamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_02', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_03', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_04', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_05', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_06', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_07', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_08', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_09', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_10', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_11', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_PISTOL_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
['WEAPON_REVOLVER_MK2'] = {
defaultclip = { component = 'COMPONENT_REVOLVER_MK2_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_REVOLVER_MK2_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'pistol_flashlight' },
holoscope = { component = 'COMPONENT_AT_SIGHTS', item = 'pistol_holoscope' },
smallscope = { component = 'COMPONENT_AT_SCOPE_MACRO_MK2', item = 'pistol_smallscope' },
compensator = { component = 'COMPONENT_AT_PI_COMP_03', item = 'pistol_compensator' },
digicamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_02', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_03', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_04', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_05', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_06', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_07', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_08', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_09', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_10', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_11', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_REVOLVER_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
['WEAPON_SNSPISTOL_MK2'] = {
defaultclip = { component = 'COMPONENT_SNSPISTOL_MK2_CLIP_01', item = 'pistol_defaultclip' },
extendedclip = { component = 'COMPONENT_SNSPISTOL_MK2_CLIP_02', item = 'pistol_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH_03', item = 'pistol_flashlight' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'pistol_suppressor' },
compensator = { component = 'COMPONENT_AT_PI_COMP_02', item = 'pistol_compensator' },
digicamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_02', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_03', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_04', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_05', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_06', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_07', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_08', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_09', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_10', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_11', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_SNSPISTOL_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
-- SMG WEAPONS
['WEAPON_MICROSMG'] = {
defaultclip = { component = 'COMPONENT_MICROSMG_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_MICROSMG_CLIP_02', item = 'smg_extendedclip' },
flashlight = { component = 'COMPONENT_AT_PI_FLSH', item = 'smg_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MACRO', item = 'smg_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'smg_suppressor' },
luxuryfinish = { component = 'COMPONENT_MICROSMG_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_SMG'] = {
defaultclip = { component = 'COMPONENT_SMG_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_SMG_CLIP_02', item = 'smg_extendedclip' },
drum = { component = 'COMPONENT_SMG_CLIP_03', item = 'smg_drum' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'smg_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MACRO_02', item = 'smg_scope' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'smg_suppressor' },
luxuryfinish = { component = 'COMPONENT_SMG_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_ASSAULTSMG'] = {
defaultclip = { component = 'COMPONENT_ASSAULTSMG_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_ASSAULTSMG_CLIP_02', item = 'smg_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'smg_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MACRO', item = 'smg_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'smg_suppressor' },
luxuryfinish = { component = 'COMPONENT_ASSAULTSMG_VARMOD_LOWRIDER', item = 'luxuryfinish_weapontint' }
},
['WEAPON_MINISMG'] = {
defaultclip = { component = 'COMPONENT_MINISMG_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_MINISMG_CLIP_02', item = 'smg_extendedclip' }
},
['WEAPON_MACHINEPISTOL'] = {
defaultclip = { component = 'COMPONENT_MACHINEPISTOL_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_MACHINEPISTOL_CLIP_02', item = 'smg_extendedclip' },
drum = { component = 'COMPONENT_MACHINEPISTOL_CLIP_03', item = 'smg_drum' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'smg_suppressor' }
},
['WEAPON_COMBATPDW'] = {
defaultclip = { component = 'COMPONENT_COMBATPDW_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_COMBATPDW_CLIP_02', item = 'smg_extendedclip' },
drum = { component = 'COMPONENT_COMBATPDW_CLIP_03', item = 'smg_drum' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'smg_flashlight' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'smg_grip' },
scope = { component = 'COMPONENT_AT_SCOPE_SMALL', item = 'smg_scope' }
},
-- SMG MK2 WEAPONS
['WEAPON_SMG_MK2'] = {
defaultclip = { component = 'COMPONENT_SMG_MK2_CLIP_01', item = 'smg_defaultclip' },
extendedclip = { component = 'COMPONENT_SMG_MK2_CLIP_02', item = 'smg_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'smg_flashlight' },
holoscope = { component = 'COMPONENT_AT_SIGHTS_SMG', item = 'smg_holoscope' },
scope = { component = 'COMPONENT_AT_SCOPE_SMALL_SMG_MK2', item = 'smg_scope' },
drum = { component = 'COMPONENT_SMG_MK2_CLIP_Drum', item = 'smg_drum' },
suppressor = { component = 'COMPONENT_AT_PI_SUPP', item = 'smg_suppressor' },
barrel = { component = 'COMPONENT_AT_SB_BARREL_02', item = 'smg_barrel' },
digicamo = { component = 'COMPONENT_SMG_MK2_CAMO', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_SMG_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_SMG_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_SMG_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_SMG_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_SMG_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_SMG_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_SMG_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_SMG_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_SMG_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_SMG_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
-- SHOTGUNS
['WEAPON_PUMPSHOTGUN'] = {
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'shotgun_flashlight' },
suppressor = { component = 'COMPONENT_AT_SR_SUPP', item = 'shotgun_suppressor' },
luxuryfinish = { component = 'COMPONENT_PUMPSHOTGUN_VARMOD_LOWRIDER', item = 'luxuryfinish_weapontint' }
},
['WEAPON_SAWNOFFSHOTGUN'] = {
luxuryfinish = { component = 'COMPONENT_SAWNOFFSHOTGUN_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_ASSAULTSHOTGUN'] = {
defaultclip = { component = 'COMPONENT_ASSAULTSHOTGUN_CLIP_01', item = 'shotgun_defaultclip' },
extendedclip = { component = 'COMPONENT_ASSAULTSHOTGUN_CLIP_02', item = 'shotgun_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'shotgun_flashlight' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'shotgun_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'shotgun_grip' }
},
['WEAPON_BULLPUPSHOTGUN'] = {
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'shotgun_flashlight' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'shotgun_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'shotgun_grip' }
},
['WEAPON_HEAVYSHOTGUN'] = {
defaultclip = { component = 'COMPONENT_HEAVYSHOTGUN_CLIP_01', item = 'shotgun_defaultclip' },
extendedclip = { component = 'COMPONENT_HEAVYSHOTGUN_CLIP_02', item = 'shotgun_extendedclip' },
drum = { component = 'COMPONENT_HEAVYSHOTGUN_CLIP_03', item = 'shotgun_drum' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'shotgun_flashlight' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'shotgun_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'shotgun_grip' }
},
['WEAPON_COMBATSHOTGUN'] = {
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'shotgun_flashlight' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'shotgun_suppressor' }
},
['WEAPON_PUMPSHOTGUN_MK2'] = {
defaultclip = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CLIP_01', item = 'shotgun_defaultclip' },
extendedclip = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CLIP_02', item = 'shotgun_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'shotgun_flashlight' },
suppressor = { component = 'COMPONENT_AT_SR_SUPP_03', item = 'shotgun_suppressor' },
squaremuzzle = { component = 'COMPONENT_AT_MUZZLE_08', item = 'shotgun_squaredmuzzle' },
holoscope = { component = 'COMPONENT_AT_SCOPE_SMALL_MK2', item = 'shotgun_holoscope' },
scope = { component = 'COMPONENT_AT_SCOPE_SMALL_MK2', item = 'shotgun_scope' },
digicamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_PUMPSHOTGUN_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
-- RIFLES
['WEAPON_ASSAULTRIFLE'] = {
defaultclip = { component = 'COMPONENT_ASSAULTRIFLE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_ASSAULTRIFLE_CLIP_02', item = 'rifle_extendedclip' },
drum = { component = 'COMPONENT_ASSAULTRIFLE_CLIP_03', item = 'rifle_drum' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MACRO', item = 'rifle_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'rifle_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'rifle_grip' },
luxuryfinish = { component = 'COMPONENT_ASSAULTRIFLE_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_CARBINERIFLE'] = {
defaultclip = { component = 'COMPONENT_CARBINERIFLE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_CARBINERIFLE_CLIP_02', item = 'rifle_extendedclip' },
drum = { component = 'COMPONENT_CARBINERIFLE_CLIP_03', item = 'rifle_drum' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MEDIUM', item = 'rifle_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'rifle_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'rifle_grip' },
luxuryfinish = { component = 'COMPONENT_CARBINERIFLE_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_ADVANCEDRIFLE'] = {
defaultclip = { component = 'COMPONENT_ADVANCEDRIFLE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_ADVANCEDRIFLE_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_SMALL', item = 'rifle_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'rifle_suppressor' },
luxuryfinish = { component = 'COMPONENT_ADVANCEDRIFLE_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_SPECIALCARBINE'] = {
defaultclip = { component = 'COMPONENT_SPECIALCARBINE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_SPECIALCARBINE_CLIP_02', item = 'rifle_extendedclip' },
drum = { component = 'COMPONENT_SPECIALCARBINE_CLIP_03', item = 'rifle_drum' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MEDIUM', item = 'rifle_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'rifle_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'rifle_grip' },
luxuryfinish = { component = 'COMPONENT_SPECIALCARBINE_VARMOD_LOWRIDER', item = 'luxuryfinish_weapontint' }
},
['WEAPON_BULLPUPRIFLE'] = {
defaultclip = { component = 'COMPONENT_BULLPUPRIFLE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_BULLPUPRIFLE_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_SMALL', item = 'rifle_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'rifle_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'rifle_grip' },
luxuryfinish = { component = 'COMPONENT_BULLPUPRIFLE_VARMOD_LOW', item = 'luxuryfinish_weapontint' }
},
['WEAPON_COMPACTRIFLE'] = {
defaultclip = { component = 'COMPONENT_COMPACTRIFLE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_COMPACTRIFLE_CLIP_02', item = 'rifle_extendedclip' },
drum = { component = 'COMPONENT_COMPACTRIFLE_CLIP_03', item = 'rifle_drum' }
},
['WEAPON_HEAVYRIFLE'] = {
defaultclip = { component = 'COMPONENT_HEAVYRIFLE_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_HEAVYRIFLE_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_MEDIUM', item = 'rifle_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'rifle_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'rifle_grip' },
luxuryfinish = { component = 'COMPONENT_BULLPUPRIFLE_VARMOD_LOW', item = 'luxuryfinish_weapontint' }
},
['WEAPON_ASSAULTRIFLE_MK2'] = {
defaultclip = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
holographic = { component = 'COMPONENT_AT_SIGHTS', item = 'rifle_holoscope' },
smallscope = { component = 'COMPONENT_AT_SCOPE_MACRO_MK2', item = 'rifle_smallscope' },
largescope = { component = 'COMPONENT_AT_SCOPE_MEDIUM_MK2', item = 'rifle_largescope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'rifle_suppressor' },
digicamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_ASSAULTRIFLE_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
['WEAPON_CARBINERIFLE_MK2'] = {
defaultclip = { component = 'COMPONENT_CARBINERIFLE_MK2_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_CARBINERIFLE_MK2_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
holographic = { component = 'COMPONENT_AT_SIGHTS', item = 'rifle_holoscope' },
smallscope = { component = 'COMPONENT_AT_SCOPE_MACRO_MK2', item = 'rifle_smallscope' },
largescope = { component = 'COMPONENT_AT_SCOPE_MEDIUM_MK2', item = 'rifle_largescope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'rifle_suppressor' },
digicamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_CARBINERIFLE_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
['WEAPON_SPECIALCARBINE_MK2'] = {
defaultclip = { component = 'COMPONENT_SPECIALCARBINE_MK2_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_SPECIALCARBINE_MK2_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
holographic = { component = 'COMPONENT_AT_SIGHTS', item = 'rifle_holoscope' },
smallscope = { component = 'COMPONENT_AT_SCOPE_MACRO_MK2', item = 'rifle_smallscope' },
largescope = { component = 'COMPONENT_AT_SCOPE_MEDIUM_MK2', item = 'rifle_largescope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'rifle_suppressor' },
digicamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_SPECIALCARBINE_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
['WEAPON_BULLPUPRIFLE_MK2'] = {
defaultclip = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CLIP_01', item = 'rifle_defaultclip' },
extendedclip = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CLIP_02', item = 'rifle_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'rifle_flashlight' },
holographic = { component = 'COMPONENT_AT_SIGHTS', item = 'rifle_holoscope' },
smallscope = { component = 'COMPONENT_AT_SCOPE_MACRO_02_MK2', item = 'rifle_smallscope' },
largescope = { component = 'COMPONENT_AT_SCOPE_SMALL_MK2', item = 'rifle_largescope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'rifle_suppressor' },
digicamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO', item = 'digital_weapontint' },
brushcamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_BULLPUPRIFLE_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
},
-- SNIPERS
['WEAPON_SNIPERRIFLE'] = {
defaultclip = { component = 'COMPONENT_SNIPERRIFLE_CLIP_01', item = 'sniper_defaultclip' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP_02', item = 'sniper_suppressor' },
scope = { component = 'COMPONENT_AT_SCOPE_LARGE', item = 'sniper_scope' },
largescope = { component = 'COMPONENT_AT_SCOPE_MAX', item = 'sniper_largescope' }
},
['WEAPON_HEAVYSNIPER'] = {
defaultclip = { component = 'COMPONENT_HEAVYSNIPER_CLIP_01', item = 'sniper_defaultclip' },
scope = { component = 'COMPONENT_AT_SCOPE_LARGE', item = 'sniper_scope' },
largescope = { component = 'COMPONENT_AT_SCOPE_MAX', item = 'sniper_largescope' }
},
['WEAPON_MARKSMANRIFLE'] = {
defaultclip = { component = 'COMPONENT_MARKSMANRIFLE_CLIP_01', item = 'sniper_defaultclip' },
extendedclip = { component = 'COMPONENT_MARKSMANRIFLE_CLIP_02', item = 'sniper_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'sniper_flashlight' },
scope = { component = 'COMPONENT_AT_SCOPE_LARGE_FIXED_ZOOM', item = 'sniper_scope' },
suppressor = { component = 'COMPONENT_AT_AR_SUPP', item = 'sniper_suppressor' },
grip = { component = 'COMPONENT_AT_AR_AFGRIP', item = 'sniper_grip' },
luxuryfinish = { component = 'COMPONENT_MARKSMANRIFLE_VARMOD_LUXE', item = 'luxuryfinish_weapontint' }
},
['WEAPON_HEAVYSNIPER_MK2'] = {
defaultclip = { component = 'COMPONENT_HEAVYSNIPER_MK2_CLIP_01', item = 'sniper_defaultclip' },
extendedclip = { component = 'COMPONENT_HEAVYSNIPER_MK2_CLIP_02', item = 'sniper_extendedclip' },
flashlight = { component = 'COMPONENT_AT_AR_FLSH', item = 'sniper_flashlight' },
holographic = { component = 'COMPONENT_AT_SIGHTS', item = 'sniper_holoscope' },
smallscope = { component = 'COMPONENT_AT_SCOPE_SMALL_MK2', item = 'sniper_smallscope' },
largescope = { component = 'COMPONENT_AT_SCOPE_LARGE_MK2', item = 'sniper_largescope' },
suppressor = { component = 'COMPONENT_AT_SR_SUPP_03', item = 'sniper_suppressor' },
squaredmuzzle = { component = 'COMPONENT_AT_MUZZLE_08', item = 'sniper_squaredmuzzle' },
barrel = { component = 'COMPONENT_AT_SR_BARREL_02', item = 'sniper_barrel' },
digicamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO', item = 'weapon_digicamo' },
brushcamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_02', item = 'brushstroke_weapontint' },
woodcamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_03', item = 'woodland_weapontint' },
skullcamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_04', item = 'skull_weapontint' },
sessantacamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_05', item = 'sessanta_weapontint' },
perseuscamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_06', item = 'perseus_weapontint' },
leopardcamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_07', item = 'leopard_weapontint' },
zebracamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_08', item = 'zebra_weapontint' },
geocamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_09', item = 'geometric_weapontint' },
boomcamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_10', item = 'boom_weapontint' },
patriotcamo = { component = 'COMPONENT_HEAVYSNIPER_MK2_CAMO_IND_01', item = 'patriot_weapontint' }
}
-- Additional weapon attachments continue as needed
}
--[[────────────────────────────────────────────────────────────────────────────
Weapon Tints & Hashes Configuration [EDIT]
[INFO] Define custom tints for weapons by mapping weapon hashes to texture
dictionaries (YTD) and texture names. Use reliable sources (e.g. RAGE
MP Wiki) to obtain correct weapon hashes.
Fields per tint entry:
• name – Human-readable weapon name. [INFO]
• hash – Weapon hash (string or number). [EDIT]
• ytd – Texture dictionary name containing the texture. [EDIT]
• texture – Texture name applied to the weapon. [EDIT]
Usage:
• Add new entries with incremental numeric indices. [TIP]
• Keep YTD/texture names consistent with your assets. [TIP]
────────────────────────────────────────────────────────────────────────────]]
Config.WeaponTints = {
-- Pistols ---------------------------------------------------------------- [INFO]
[1] = { name = 'Pistol', hash = '453432689', ytd = 'w_pi_pistol', texture = 'w_pi_pistol' },
[2] = { name = 'Pistol Mk II', hash = '3219281620', ytd = 'w_pi_pistolmk2', texture = 'w_pi_pistolmk2' },
[3] = { name = 'Combat Pistol', hash = '1593441988', ytd = 'w_pi_combatpistol', texture = 'w_pi_combatpistol' },
[4] = { name = 'Pistol .50', hash = '-1716589765', ytd = 'w_pi_pistol50', texture = 'w_pi_pistol50' },
[5] = { name = 'SNS Pistol', hash = '-1076751822', ytd = 'w_pi_sns_pistol', texture = 'w_pi_sns_pistol' },
[6] = { name = 'Heavy Pistol', hash = '-771403250', ytd = 'w_pi_heavypistol', texture = 'w_pi_heavypistol' },
[7] = { name = 'Vintage Pistol', hash = '137902532', ytd = 'w_pi_vintage_pistol', texture = 'w_pi_vintage_pistol' },
[8] = { name = 'Marksman Pistol', hash = '-598887786', ytd = 'w_pi_singleshot', texture = 'w_pi_singleshot_dm' },
[9] = { name = 'Revolver', hash = '-1045183535', ytd = 'w_pi_revolver', texture = 'w_pi_revolver' },
[10] = { name = 'Stun Gun', hash = '911657153', ytd = 'w_pi_stungun', texture = 'w_pi_stungun' },
[11] = { name = 'Double-Action Revolver', hash = '-1746263880', ytd = 'w_pi_revolver', texture = 'w_pi_revolver' },
[12] = { name = 'Navy Revolver', hash = '-2056364401', ytd = 'w_pi_revolver', texture = 'w_pi_revolver' },
[13] = { name = 'Ceramic Pistol', hash = '727643628', ytd = 'w_pi_ceramic_pistol', texture = 'w_pi_ceramic_pistol' },
-- Submachine guns & PDW -------------------------------------------------- [INFO]
[14] = { name = 'Micro SMG', hash = '324215364', ytd = 'w_sb_microsmg', texture = 'w_sb_microsmg' },
[15] = { name = 'Machine Pistol', hash = '-619010992', ytd = 'w_sb_compactsmg', texture = 'w_sb_compactsmg' },
[16] = { name = 'SMG', hash = '736523883', ytd = 'w_sb_smg', texture = 'w_sb_smg' },
[17] = { name = 'SMG Mk II', hash = '2024373456', ytd = 'w_sb_smgmk2', texture = 'w_sb_smgmk2' },
[18] = { name = 'Assault SMG', hash = '-270015777', ytd = 'w_sb_assaultsmg', texture = 'w_sb_assaultsmg' },
[19] = { name = 'Mini SMG', hash = '-1121678507', ytd = 'w_sb_minismg', texture = 'w_sb_minismg_dm' },
[20] = { name = 'Combat PDW', hash = '171789620', ytd = 'w_sb_pdw', texture = 'w_sb_pdw' },
-- Assault rifles & carbines ---------------------------------------------- [INFO]
[21] = { name = 'Assault Rifle', hash = '-1074790547', ytd = 'w_ar_assaultrifle', texture = 'w_ar_assaultrifle' },
[22] = { name = 'Assault Rifle Mk II', hash = '961495388', ytd = 'w_ar_assaultriflemk2', texture = 'w_ar_assaultriflemk2' },
[23] = { name = 'Carbine Rifle', hash = '-2084633992', ytd = 'w_ar_carbinerifle', texture = 'w_ar_carbinerifle' },
[24] = { name = 'Carbine Rifle Mk II', hash = '-86904375', ytd = 'w_ar_carbineriflemk2', texture = 'w_ar_carbineriflemk2' },
[25] = { name = 'Special Carbine', hash = '-1063057011', ytd = 'w_ar_specialcarbine', texture = 'w_ar_specialcarbine_tint' },
[26] = { name = 'Special Carbine Mk II', hash = '-1768145561', ytd = 'w_ar_specialcarbine_mk2', texture = 'w_ar_specialcarbine_mk2' },
[27] = { name = 'Bullpup Rifle', hash = '2132975508', ytd = 'w_ar_bullpuprifle', texture = 'w_ar_bullpuprifle' },
-- Sniper rifles ----------------------------------------------------------- [INFO]
[28] = { name = 'Sniper Rifle', hash = '100416529', ytd = 'w_sr_sniperrifle', texture = 'w_sr_sniperrifle' },
[29] = { name = 'Heavy Sniper', hash = '205991906', ytd = 'w_sr_heavysniper', texture = 'w_sr_heavysniper' },
[30] = { name = 'Heavy Sniper Mk II', hash = '177293209', ytd = 'w_sr_heavysnipermk2', texture = 'w_sr_heavysnipermk2' },
[31] = { name = 'Marksman Rifle', hash = '-952879014', ytd = 'w_sr_marksmanrifle', texture = 'w_sr_marksmanrifle' },
-- Shotguns ---------------------------------------------------------------- [INFO]
[32] = { name = 'Pump Shotgun', hash = '487013001', ytd = 'w_sg_pumpshotgun', texture = 'w_sg_pumpshotgun' },
[33] = { name = 'Sawed-Off Shotgun', hash = '2017895192', ytd = 'w_sg_sawnoff', texture = 'w_sg_sawnoff' },
[34] = { name = 'Bullpup Shotgun', hash = '-1654528753', ytd = 'w_sg_bullpupshotgun', texture = 'w_sg_bullpupshotgun' },
[35] = { name = 'Double Barrel Shotgun', hash = '-275439685', ytd = 'w_sg_doublebarrel', texture = 'w_sg_doublebarrel_dm' },
-- Heavy & others ---------------------------------------------------------- [INFO]
[36] = { name = 'Railgun', hash = '1834241177', ytd = 'w_ar_railgun', texture = 'w_ar_railgun' },
[37] = { name = 'Minigun', hash = '1119849093', ytd = 'w_mg_minigun', texture = 'w_mg_minigun' },
[38] = { name = 'Widowmaker', hash = '-1238556825', ytd = 'w_mg_sminigun', texture = 'w_mg_sminigun' },
[39] = { name = 'Unholy Hellbringer', hash = '1198256469', ytd = 'w_ar_carbinerifle', texture = 'w_ar_carbinerifle' },
-- Pump Shotgun Mk II ------------------------------------------------------ [INFO]
[40] = { name = 'Pump Shotgun Mk II', hash = '1432025498', ytd = 'w_sg_pumpshotgunmk2', texture = 'w_sg_pumpshotgunmk2' },
-- [TIP] Add more entries below following the same structure --------------
}
--[[────────────────────────────────────────────────────────────────────────────
DO NOT MODIFY BELOW [CORE]
[INFO] The code below synchronizes weapon tints/attachments across the server.
Editing may break core functionality. Only change if you fully
understand the implications.
────────────────────────────────────────────────────────────────────────────]]
RegisterNetEvent('qb-weapons:getWeaponsAttachments', function(cb) -- [CORE]
cb(Config.WeaponAttachments) -- [CORE] Return current attachments configuration
end)
sharedExports('GetWeaponTints', function() -- [CORE]
return Config.WeaponTints -- [CORE] Export accessor for weapon tints
end)
--[[────────────────────────────────────────────────────────────────────────────
Attachment Items Configuration [EDIT]
[INFO] Map inventory items to attachment keys and categories. These items are
consumed or required when applying attachments to weapons.
Fields per entry:
• item – Inventory item name (must exist in your items database). [EDIT]
• attachment – Attachment key (e.g., 'suppressor', 'smallscope', 'grip').
Must match keys defined under Config.WeaponAttachments[...] . [LINK]
• type – Logical category used by the script (e.g., 'suppressor',
'scope', 'grip', 'clip', 'flash', 'tint'). [INFO]
Tips:
• Duplicate entries to add more items. Keep names consistent across configs. [TIP]
• Ensure the targeted weapon actually supports the specified attachment. [TIP]
────────────────────────────────────────────────────────────────────────────]]
---@type AttachmentItem[]
Config.WeaponAttachmentItems = {
-- Rifles
{
item = 'rifle_suppressor',
attachment = 'suppressor',
type = 'suppressor'
},
{
item = 'rifle_smallscope',
attachment = 'smallscope',
type = 'scope'
},
{
item = 'rifle_grip',
attachment = 'grip',
type = 'grip'
},
{
item = 'rifle_defaultclip',
attachment = 'defaultclip',
type = 'clip'
},
{
item = 'rifle_extendedclip',
attachment = 'extendedclip',
type = 'clip'
},
{
item = 'rifle_drum',
attachment = 'drum',
type = 'clip'
},
{
item = 'rifle_flashlight',
attachment = 'flashlight',
type = 'flash'
},
{
item = 'rifle_largescope',
attachment = 'largescope',
type = 'scope'
},
{
item = 'rifle_holoscope',
attachment = 'holographic',
type = 'scope'
},
-- Custom Tints
{
item = 'luxuryfinish_weapontint',
attachment = 'luxuryfinish',
type = 'tint'
},
{
item = 'digital_weapontint',
attachment = 'digicamo',
type = 'tint'
},
{
item = 'brushstroke_weapontint',
attachment = 'brushcamo',
type = 'tint'
},
{
item = 'woodland_weapontint',
attachment = 'woodcamo',
type = 'tint'
},
{
item = 'skull_weapontint',
attachment = 'skullcamo',
type = 'tint'
},
{
item = 'sessanta_weapontint',
attachment = 'sessantacamo',
type = 'tint'
},
{
item = 'perseus_weapontint',
attachment = 'perseuscamo',
type = 'tint'
},
{
item = 'leopard_weapontint',
attachment = 'leopardcamo',
type = 'tint'
},
{
item = 'zebra_weapontint',
attachment = 'zebracamo',
type = 'tint'
},
{
item = 'geometric_weapontint',
attachment = 'geocamo',
type = 'tint'
},
{
item = 'boom_weapontint',
attachment = 'boomcamo',
type = 'tint'
},
{
item = 'patriot_weapontint',
attachment = 'patriotcamo',
type = 'tint'
},
-- Sniper
{
item = 'sniper_suppressor',
attachment = 'suppressor',
type = 'suppressor'
},
{
item = 'sniper_scope',
attachment = 'scope',
type = 'scope'
},
{
item = 'sniper_defaultclip',
attachment = 'defaultclip',
type = 'clip'
},
{
item = 'sniper_extendedclip',
attachment = 'extendedclip',
type = 'clip'
},
{
item = 'sniper_squaredmuzzle',
attachment = 'squaredmuzzle',
type = 'suppressor'
},
{
item = 'sniper_barrel',
attachment = 'barrel',
type = 'barrel'
},
{
item = 'sniper_flashlight',
attachment = 'flashlight',
type = 'flash'
},
{
item = 'sniper_holoscope',
attachment = 'holographic',
type = 'scope'
},
{
item = 'sniper_smallscope',
attachment = 'smallscope',
type = 'scope'
},
{
item = 'sniper_largescope',
attachment = 'largescope',
type = 'scope'
},
{
item = 'sniper_grip',
attachment = 'grip',
type = 'grip'
},
-- Pistol
{
item = 'pistol_defaultclip',
attachment = 'clip',
type = 'clip'
},
{
item = 'pistol_extendedclip',
attachment = 'extendedclip',
type = 'clip'
},
{
item = 'pistol_flashlight',
attachment = 'flashlight',
type = 'flash'
},
{
item = 'pistol_suppressor',
attachment = 'suppressor',
type = 'suppressor'
},
{
item = 'pistol_holoscope',
attachment = 'holoscope',
type = 'scope'
},
{
item = 'pistol_smallscope',
attachment = 'scope',
type = 'scope'
},
{
item = 'pistol_compensator',
attachment = 'suppressor',
type = 'suppressor'
},
-- SMG
{
item = 'smg_defaultclip',
attachment = 'defaultclip',
type = 'clip'
},
{
item = 'smg_extendedclip',
attachment = 'extendedclip',
type = 'clip'
},
{
item = 'smg_suppressor',
attachment = 'suppressor',
type = 'suppressor'
},
{
item = 'smg_drum',
attachment = 'drum',
type = 'clip'
},
{
item = 'smg_scope',
attachment = 'scope',
type = 'scope'
},
{
item = 'smg_barrel',
attachment = 'barrel',
type = 'barrel'
},
-- Shotgun
{
item = 'shotgun_defaultclip',
attachment = 'defaultclip',
type = 'clip'
},
{
item = 'shotgun_extendedclip',
attachment = 'extendedclip',
type = 'clip'
},
{
item = 'shotgun_flashlight',
attachment = 'flashlight',
type = 'flash'
},
{
item = 'shotgun_suppressor',
attachment = 'suppressor',
type = 'suppressor'
},
{
item = 'shotgun_grip',
attachment = 'grip',
type = 'grip'
},
{
item = 'shotgun_drum',
attachment = 'drum',
type = 'clip'
},
{
item = 'shotgun_squaredmuzzle',
attachment = 'squaredmuzzle',
type = 'suppressor'
},
{
item = 'shotgun_holoscope',
attachment = 'holographic',
type = 'scope'
},
{
item = 'shotgun_smallscope',
attachment = 'smallscope',
type = 'scope'
},
-- Tints for every weapon
{
attachment = 'black_weapontint',
label = 'Black Tint',
type = 'tint',
item = 'black_weapontint',
tint = 0,
forEveryWeapon = true
},
{
attachment = 'green_weapontint',
label = 'Green Tint',
type = 'tint',
item = 'green_weapontint',
tint = 1,
forEveryWeapon = true
},
{
attachment = 'gold_weapontint',
label = 'Gold Tint',
type = 'tint',
item = 'gold_weapontint',
tint = 2,
forEveryWeapon = true
},
{
attachment = 'pink_weapontint',
label = 'Pink Tint',
type = 'tint',
item = 'pink_weapontint',
tint = 3,
forEveryWeapon = true
},
{
attachment = 'army_weapontint',
label = 'Army Tint',
type = 'tint',
item = 'army_weapontint',
tint = 4,
forEveryWeapon = true
},
{
attachment = 'lspd_weapontint',
label = 'LSPD Tint',
type = 'tint',
item = 'lspd_weapontint',
tint = 5,
forEveryWeapon = true
},
{
attachment = 'orange_weapontint',
label = 'Orange Tint',
type = 'tint',
item = 'orange_weapontint',
tint = 6,
forEveryWeapon = true
},
{
attachment = 'plat_weapontint',
label = 'Platinum Tint',
type = 'tint',
item = 'plat_weapontint',
tint = 7,
forEveryWeapon = true
},
{
item = 'weapontint_url',
attachment = 'weapontint_url',
type = 'tint',
isUrlTint = true,
tint = -1,
forEveryWeapon = true
}
}
--──────────────────────────────────────────────────────────────────────────────
-- Build cloned list of tint items [CORE]
--──────────────────────────────────────────────────────────────────────────────
local weaponTints = table.deepclone(table.filter(Config.WeaponAttachmentItems, function(item)
return item.type == 'tint'
end))
--──────────────────────────────────────────────────────────────────────────────
-- Inject universal attachments into each weapon entry [CORE]
-- [INFO] Items marked with `forEveryWeapon = true` are added under the key of
-- their `attachment` (or `item` as fallback) if not already present.
--──────────────────────────────────────────────────────────────────────────────
for weaponKey, weaponMap in pairs(Config.WeaponAttachments or {}) do
if type(weaponMap) == 'table' then
for _, it in pairs(Config.WeaponAttachmentItems or {}) do
if it.forEveryWeapon == true then
-- Prefer semantic key by attachment name; fallback to item name
local targetKey = it.attachment or it.item
-- Only set if not already defined by the weapon’s specific config
if targetKey and weaponMap[targetKey] == nil then
weaponMap[targetKey] = it
end
end
end
end
end
--──────────────────────────────────────────────────────────────────────────────
-- Accessors [CORE]
-- [INFO] Read-only getters used by other resources/UIs.
--──────────────────────────────────────────────────────────────────────────────
---@return AttachmentItem[]
function GetConfigTints()
return weaponTints -- [INFO] Return cloned list to avoid external mutation
end
sharedExports('getConfigWeaponTints', GetConfigTints)
sharedExports('GetWeaponAttachments', function()
return Config.WeaponAttachments
end)
sharedExports('GetWeaponAttachmentItems', function()
return Config.WeaponAttachmentItems
end)