fix(qb-core): add global CreateUsableItem alias for qs-inventory compatibility

qs-inventory apelează CreateUsableItem ca funcție globală, dar qb-core definea doar QBCore.Functions.CreateUseableItem (cu 'e'). Adăugat alias global + fix 16 stringuri sparte în items.lua care blocau parsarea.
This commit is contained in:
2026-04-02 00:08:19 +03:00
parent 096ccb6399
commit 978c9bc759
827 changed files with 3570 additions and 1015 deletions

2
.gitignore vendored
View File

@@ -13,3 +13,5 @@ cache/files/17mov_JobCenter/resource.rpf
_fix_dupes.py
_check_dupes.py
_find_dupes.py
artifacts/crashes/136f1640-ac9a-4693-824a-5ccd58f1b359-full.dmp
artifacts/crashes/136f1640-ac9a-4693-824a-5ccd58f1b359.dmp

24
_find_broken.py Normal file
View File

@@ -0,0 +1,24 @@
import re
path = r'E:\FiveMserver\server\resources\[framework]\[core]\qb-core\shared\items.lua'
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
lines = f.readlines()
broken = []
for i, line in enumerate(lines):
stripped = line.strip()
if "['description']" not in stripped:
continue
if "['name']" not in stripped:
continue
# Count single quotes after ['description']
idx = stripped.index("['description']")
after = stripped[idx:]
# Should end with ...'}, or ...'}},
# Check if description value has matching quotes
if after.count("'") % 2 != 0:
broken.append((i+1, stripped[:120]))
print(f"Found {len(broken)} broken strings:")
for ln, txt in broken:
print(f" L{ln}: {txt}")

34
_fix_strings.py Normal file
View File

@@ -0,0 +1,34 @@
import re
path = r'E:\FiveMserver\server\resources\[framework]\[core]\qb-core\shared\items.lua'
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# Fix pattern: find description strings that don't end with closing quote before },
# Pattern: ['description'] = 'text without closing quote},
# Should be: ['description'] = 'text with closing quote'},
fixed = 0
lines = content.split('\n')
new_lines = []
for line in lines:
if "['description']" in line and "['name']" in line:
idx = line.index("['description']")
after = line[idx:]
if after.count("'") % 2 != 0:
# Find the last }, and insert closing quote before it
# Pattern: some text}, -> some text'},
# Or: some text}}, -> some text'}},
line = re.sub(r"([^'])\},\s*$", r"\1'},", line)
line = re.sub(r"([^'])\}\},\s*$", r"\1'}},", line)
# Handle CRLF
line = re.sub(r"([^'])\},\r$", r"\1'},\r", line)
line = re.sub(r"([^'])\}\},\r$", r"\1'}},\r", line)
fixed += 1
new_lines.append(line)
with open(path, 'w', encoding='utf-8') as f:
f.write('\n'.join(new_lines))
print(f"Fixed {fixed} broken description strings")

View File

@@ -15,5 +15,4 @@ ensure minimap
ensure phone-props
ensure [casino]
ensure [stream]
ensure luxu_admin
ensure [weapons]
ensure luxu_admin

Binary file not shown.

View File

@@ -0,0 +1,93 @@
--[[
Hi dear customer or developer, here you can fully configure your server's
framework or you could even duplicate this file to create your own framework.
If you do not have much experience, we recommend you download the base version
of the framework that you use in its latest version and it will work perfectly.
]]
if Config.Framework ~= 'esx' then
return
end
ESX = exports['es_extended']:getSharedObject()
function GetPlayerData()
return ESX.GetPlayerData()
end
local first = true
RegisterNetEvent('esx:playerLoaded', function()
if first then
first = false
CreateThread(function()
Wait(1000)
GetPlayerData(function(PlayerData)
PlayerJob = PlayerData.job
SetPedArmour(PlayerPedId(), PlayerData.metadata['armor'])
currentarmor = PlayerData.metadata['armor']
startedsync = true
Wait(100)
if Config.VestTexture then
local ped = PlayerPedId()
local PlayerData = GetPlayerData()
local GetArmor = GetPedArmour(ped)
currentVest = GetPedDrawableVariation(ped, 9)
currentVestTexture = GetPedTextureVariation(ped, 9)
if GetArmor >= 1 then
SetVest()
elseif GetArmor >= 51 then
SetHeavyVest()
end
end
end)
end)
end
end)
function SendTextMessage(msg, type)
if type == 'inform' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'inform'
})
end
if type == 'error' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'error'
})
end
if type == 'success' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'success'
})
end
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
if onCancel then
onCancel()
end
end
end

View File

@@ -0,0 +1,112 @@
--[[
Hi dear customer or developer, here you can fully configure your server's
framework or you could even duplicate this file to create your own framework.
If you do not have much experience, we recommend you download the base version
of the framework that you use in its latest version and it will work perfectly.
]]
if Config.Framework ~= 'qb' then
return
end
QBCore = exports['qb-core']:GetCoreObject()
function GetPlayerData()
return QBCore.Functions.GetPlayers()
end
local first = true
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
if first then
first = false
CreateThread(function()
Wait(1000)
GetPlayerData(function(PlayerData)
PlayerJob = PlayerData.job
SetPedArmour(PlayerPedId(), PlayerData.metadata['armor'])
currentarmor = PlayerData.metadata['armor']
startedsync = true
Wait(100)
if Config.VestTexture then
local ped = PlayerPedId()
local PlayerData = QS.GetPlayerData()
local GetArmor = GetPedArmour(ped)
currentVest = GetPedDrawableVariation(ped, 9)
currentVestTexture = GetPedTextureVariation(ped, 9)
if GetArmor >= 1 then
SetVest()
elseif GetArmor >= 51 then
SetHeavyVest()
end
end
end)
end)
end
end)
function SendTextMessage(msg, type)
if type == 'inform' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'inform'
})
end
if type == 'error' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'error'
})
end
if type == 'success' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'success'
})
end
end
function ShowHelpNotification(msg)
BeginTextCommandDisplayHelp('STRING')
AddTextComponentSubstringPlayerName(msg)
EndTextCommandDisplayHelp(0, 0, false, -1)
end
function DrawText3D(x, y, z, text)
SetTextScale(0.4, 0.4)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
ClearDrawOrigin()
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
if onCancel then
onCancel()
end
end
end

View File

@@ -0,0 +1,33 @@
fx_version 'adamant'
game 'gta5'
lua54 'yes'
shared_scripts {
'@ox_lib/init.lua',
'shared/*.lua',
'locales/*.lua',
}
server_scripts {
'server/**/**/**.lua'
}
client_scripts {
'client/**/**/**.lua'
}
escrow_ignore {
'shared/config.lua',
'locales/*.lua',
'client/custom/framework/*.lua',
'server/custom/framework/*.lua',
}
dependencies {
'qs-inventory', -- Required.
'/server:4752', -- ⚠PLEASE READ⚠ This requires at least server build 4700 or higher
}
dependency '/assetpacks'

View File

@@ -0,0 +1,8 @@
Locales['de'] = {
["ARMOR_NOTIFICATION_ALREADY_HAVE"] = "Du hast schon eine Weste an",
["ARMOR_NOTIFICATION_DONT_HAVE"] = "Du hast keine Weste!",
["ARMOR_PROGRESS_USE_ARMOR"] = "Kugelsichere Weste Anziehen ...",
["ARMOR_PROGRESS_USE_HEAVYARMOR"] = "Schwere Weste Anziehen ...",
["ARMOR_PROGRESS_REMOVE_ARMOR"] = "Weste ausziehen ...",
}

View File

@@ -0,0 +1,8 @@
Locales['en'] = {
["ARMOR_NOTIFICATION_ALREADY_HAVE"] = "You already have a bulletproof vest",
["ARMOR_NOTIFICATION_DONT_HAVE"] = "You don't have a bulletproof vest",
["ARMOR_PROGRESS_USE_ARMOR"] = "Placing Armor ...",
["ARMOR_PROGRESS_USE_HEAVYARMOR"] = "Placing Heavy Armor ...",
["ARMOR_PROGRESS_REMOVE_ARMOR"] = "Removing Armor ...",
}

View File

@@ -0,0 +1,8 @@
Locales['es'] = {
["ARMOR_NOTIFICATION_ALREADY_HAVE"] = "Ya tienes un chaleco antibalas",
["ARMOR_NOTIFICATION_DONT_HAVE"] = "No tienes un chaleco antibalas",
["ARMOR_PROGRESS_USE_ARMOR"] = "Colocando Armor...",
["ARMOR_PROGRESS_USE_HEAVYARMOR"] = "Colocando Heavy Armor...",
["ARMOR_PROGRESS_REMOVE_ARMOR"] = "Quitando Armor...",
}

View File

@@ -0,0 +1,8 @@
Locales['it'] = {
["ARMOR_NOTIFICATION_ALREADY_HAVE"] = "Hai già un giubbotto anti-proiettile",
["ARMOR_NOTIFICATION_DONT_HAVE"] = "Non hai un giubbotto anti-proiettile",
["ARMOR_PROGRESS_USE_ARMOR"] = "Indossando giubbotto anti-proiettile...",
["ARMOR_PROGRESS_USE_HEAVYARMOR"] = "Indossando giubbotto anti-proiettile pesante...",
["ARMOR_PROGRESS_REMOVE_ARMOR"] = "Togliendo armatura...",
}

View File

@@ -0,0 +1,34 @@
--[[
Hi dear customer or developer, here you can fully configure your server's
framework or you could even duplicate this file to create your own framework.
If you do not have much experience, we recommend you download the base version
of the framework that you use in its latest version and it will work perfectly.
]]
if Config.Framework ~= 'esx' then
return
end
ESX = exports['es_extended']:getSharedObject()
function RegisterUsableItem(name, cb)
exports['qs-inventory']:CreateUsableItem(name, cb)
end
function GetPlayerFromId(source)
return ESX.GetPlayerFromId(source)
end
function GetIdentifier(source)
return ESX.GetPlayerFromId(source).identifier
end
function AddItem(source, item, count, slot)
exports['qs-inventory']:AddItem(source, item, count, slot)
end
function RemoveItem(source, item, count)
local xPlayer = GetPlayerFromId(source)
xPlayer.removeInventoryItem(item, count)
end

View File

@@ -0,0 +1,34 @@
--[[
Hi dear customer or developer, here you can fully configure your server's
framework or you could even duplicate this file to create your own framework.
If you do not have much experience, we recommend you download the base version
of the framework that you use in its latest version and it will work perfectly.
]]
if Config.Framework ~= 'qb' then
return
end
QBCore = exports['qb-core']:GetCoreObject()
function RegisterUsableItem(name, cb)
exports['qs-inventory']:CreateUsableItem(name, cb)
end
function GetPlayerFromId(player)
return QBCore.Functions.GetPlayer(player)
end
function GetIdentifier(player)
return QBCore.Functions.GetPlayer(player).PlayerData.citizenid
end
function AddItem(source, item, count, slot)
exports['qs-inventory']:AddItem(source, item, count, slot)
end
function RemoveItem(source, item, count)
local xPlayer = GetPlayerFromId(source)
xPlayer.Functions.RemoveItem(item, count)
end

View File

@@ -0,0 +1,103 @@
Config = {}
Locales = {}
local esxHas = GetResourceState('es_extended') == 'started'
local qbHas = GetResourceState('qb-core') == 'started'
local qbxHas = GetResourceState('qbx_core') == 'started'
Config.Framework = esxHas and 'esx' or qbHas and 'qb' or qbxHas and 'qb' or 'esx'
--[[
Set the primary language for the resource.
Choose one of the default languages located in locales/*.
If your desired language is not listed, feel free to create your own!
]]
Config.Language = 'en'
--[[
General configuration settings for the resource.
Customize each option as needed.
]]
Config.Progressbar = { -- Timer durations for progress bars (in milliseconds).
UseArmor = 5000, -- Duration for applying regular armor.
UseHeavyArmor = 5000, -- Duration for applying heavy armor.
ResetArmor = 2500 -- Duration for removing the armor.
}
Config.SetPedArmour = { -- Amount of armor applied to the player.
UseArmor = 50, -- Armor value for regular armor.
UseHeavyArmor = 100, -- Armor value for heavy armor.
ResetArmor = 0 -- Armor value when the vest is removed.
}
--[[
Command used to remove the player's vest.
]]
Config.ResetArmor = 'resetarmor' -- Command to reset/remove your vest.
--[[
Configuration to check if a player has a vest equipped.
]]
Config.VestTexture = true -- Should vest textures be used? (true = Yes, false = No)
Config.CheckVest = {
check = false, -- Enable automatic vest checks? (true = Yes, false = No)
time = 30000 -- Frequency of checks (in milliseconds). Ignored if check = false.
}
--[[
Vest configuration based on player gender.
Customize the vest components for both male and female characters.
]]
Config.Vest = {
male = {
['bproof_1'] = 6, -- Main vest component ID for males.
['bproof_2'] = 1 -- Secondary vest texture ID for males.
},
female = {
['bproof_1'] = 0, -- Main vest component ID for females.
['bproof_2'] = 0 -- Secondary vest texture ID for females.
},
maleHeavy = {
['bproof_1'] = 27, -- Main heavy vest component ID for males.
['bproof_2'] = 2 -- Secondary heavy vest texture ID for males.
},
femaleHeavy = {
['bproof_1'] = 6, -- Main heavy vest component ID for females.
['bproof_2'] = 0 -- Secondary heavy vest texture ID for females.
}
}
--[[
Editable functions to handle vest application or removal.
These functions are only executed if VestTexture is set to true.
]]
function SetVest() -- Function to apply the regular vest texture.
local isMale = GetEntityModel(PlayerPedId()) == joaat('mp_m_freemode_01')
local vest = isMale and Config.Vest.male or Config.Vest.female
SetPedComponentVariation(PlayerPedId(), 9, vest['bproof_1'], vest['bproof_2'], 0)
end
function SetHeavyVest() -- Function to apply the heavy vest texture.
local isMale = GetEntityModel(PlayerPedId()) == joaat('mp_m_freemode_01')
local vest = isMale and Config.Vest.maleHeavy or Config.Vest.femaleHeavy
SetPedComponentVariation(PlayerPedId(), 9, vest['bproof_1'], vest['bproof_2'], 0)
end
function RemoveVest() -- Function to remove the vest texture.
SetPedComponentVariation(PlayerPedId(), 9, 0, 1, 0)
end
--[[
Debug mode configuration.
When enabled, detailed debug prints/logs are displayed for development purposes.
Use this only during development/testing phases.
]]
Config.Debug = false

View File

@@ -0,0 +1,90 @@
--[[
Hi dear customer or developer, here you can fully configure your server's
framework or you could even duplicate this file to create your own framework.
If you do not have much experience, we recommend you download the base version
of the framework that you use in its latest version and it will work perfectly.
]]
if Config.Framework ~= 'esx' then
return
end
ESX = exports['es_extended']:getSharedObject()
RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
Wait(10000)
StartThread()
end)
AddEventHandler('onClientResourceStart', function(resourceName)
if (GetCurrentResourceName() == resourceName) then
ESX = exports['es_extended']:getSharedObject()
Wait(10000)
StartThread()
end
end)
function getSex()
local promise = promise.new()
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
promise:resolve(skin.sex)
end)
return Citizen.Await(promise)
end
function OpenStash(metadata)
local other = {}
other.maxweight = metadata.weight
other.slots = metadata.slots
TriggerServerEvent('inventory:server:OpenInventory', 'stash', 'Backpack_' .. metadata.ID, other)
TriggerEvent('inventory:client:SetCurrentStash', 'Backpack_' .. metadata.ID)
repeat Wait(1000) until IsNuiFocused() == false
TriggerEvent('backpacks:client:close', metadata.ID)
end
function SendTextMessage(msg, type)
if type == 'inform' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'inform'
})
end
if type == 'error' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'error'
})
end
if type == 'success' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'success'
})
end
end
function Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end

View File

@@ -0,0 +1,85 @@
--[[
Hi dear customer or developer, here you can fully configure your server's
framework or you could even duplicate this file to create your own framework.
If you do not have much experience, we recommend you download the base version
of the framework that you use in its latest version and it will work perfectly.
]]
if Config.Framework ~= 'qb' then
return
end
QBCore = exports['qb-core']:GetCoreObject()
RegisterNetEvent('QBCore:Client:OnPlayerLoaded')
AddEventHandler('QBCore:Client:OnPlayerLoaded', function(xPlayer)
Wait(10000)
StartThread()
end)
AddEventHandler('onClientResourceStart', function(resourceName)
if (GetCurrentResourceName() == resourceName) then
QBCore = exports['qb-core']:GetCoreObject()
Wait(10000)
StartThread()
end
end)
function getSex()
return QBCore.Functions.GetPlayerData()?.charinfo?.gender
end
function OpenStash(metadata)
local other = {}
other.maxweight = metadata.weight
other.slots = metadata.slots
TriggerServerEvent('inventory:server:OpenInventory', 'stash', 'Backpack_' .. metadata.ID, other)
TriggerEvent('inventory:client:SetCurrentStash', 'Backpack_' .. metadata.ID)
repeat Wait(1000) until IsNuiFocused() == false
TriggerEvent('backpacks:client:close', metadata.ID)
end
function SendTextMessage(msg, type)
if type == 'inform' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'inform'
})
end
if type == 'error' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'error'
})
end
if type == 'success' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'success'
})
end
end
function Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end

View File

@@ -0,0 +1,47 @@
if Config.Menu ~= 'esx_menu_default' then
return
end
function CreateBackpack(ID)
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'create_password',
{
title = Lang('CREATE_PASSWORD'),
}, function(data, menu)
local length = string.len(data.value)
if length <= 0 then
SendTextMessage(Lang('BAD_PASSWORD'), 'error')
elseif length < Config.PasswordLength.min then
SendTextMessage(Lang('MORE_PASSWORD'), 'error')
elseif length > Config.PasswordLength.max then
SendTextMessage(Lang('LESS_PASSWORD'), 'error')
else
SendTextMessage(Lang('ADDED_PASSWORD'), 'success')
TriggerServerEvent('backpacks:server:add_password', { ID = ID, password = data.value })
menu.close()
end
end, function(data, menu)
menu.close()
end)
end
function CheckMeta(backpack_metadata)
if backpack_metadata.locked then
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'enter_password',
{
title = Lang('INTRODUCE_PASSWORD'),
}, function(data, menu)
if backpack_metadata.password == data.value then
menu.close()
backpack_metadata.trypassword = data.value
OpenBackpack(backpack_metadata)
else
SendTextMessage(Lang('BAD_PASSWORD'), 'error')
menu.close()
end
end, function(data, menu)
menu.close()
end)
else
OpenBackpack(backpack_metadata)
end
end

View File

@@ -0,0 +1,48 @@
if Config.Menu ~= 'ox_lib' then
return
end
function CreateBackpack(ID)
if not lib then
print('You need to uncomment the ox_lib export on line 10 of qs-backpacks/fxmanifest.lua')
return
end
local keyboard1 = lib.inputDialog(Lang('CREATE_PASSWORD') .. ' Min ' .. Config.PasswordLength.min .. ' Max ' .. Config.PasswordLength.max, { Lang('INTRODUCE_PASSWORD_2') })
if not keyboard1 then return end
local pass = tostring(keyboard1[1])
local length = string.len(pass)
if length <= 0 then
SendTextMessage(Lang('BAD_PASSWORD'), 'error')
return
end
if length < Config.PasswordLength.min then
SendTextMessage(Lang('MORE_PASSWORD'), 'error')
return
end
if length > Config.PasswordLength.max then
SendTextMessage(Lang('LESS_PASSWORD'), 'error')
return
end
SendTextMessage(Lang('ADDED_PASSWORD'), 'success')
TriggerServerEvent('backpacks:server:add_password', { ID = ID, password = pass })
end
function CheckMeta(backpack_metadata)
if backpack_metadata.locked then
if not lib then
print('You need to uncomment the ox_lib export on line 10 of qs-backpacks/fxmanifest.lua')
return
end
local data = lib.inputDialog(Lang('INTRODUCE_PASSWORD'), { Lang('INTRODUCE_PASSWORD_2') })
if not data then
SendTextMessage(Lang('BAD_PASSWORD'), 'error')
return
end
backpack_metadata.trypassword = data[1]
OpenBackpack(backpack_metadata)
else
OpenBackpack(backpack_metadata)
end
end

View File

@@ -0,0 +1,64 @@
if Config.Menu ~= 'qb-menu' then
return
end
function CreateBackpack(ID)
local inputData = exports['qb-input']:ShowInput({
header = Lang('CREATE_PASSWORD') .. ' Min ' .. Config.PasswordLength.min .. ' Max ' .. Config.PasswordLength.max,
inputs = {
{
type = 'password',
isRequired = true,
name = 'pass', -- name of the input should be unique otherwise it might override
type = 'password', -- type of the input
text = Lang('INTRODUCE_PASSWORD_2'),
},
}
})
if inputData then
if not inputData.pass then return end
local length = string.len(inputData.pass)
if length <= 0 then
SendTextMessage(Lang('BAD_PASSWORD'), 'error')
return
end
if length < Config.PasswordLength.min then
SendTextMessage(Lang('MORE_PASSWORD'), 'error')
return
end
if length > Config.PasswordLength.max then
SendTextMessage(Lang('LESS_PASSWORD'), 'error')
return
end
SendTextMessage(Lang('ADDED_PASSWORD'), 'success')
TriggerServerEvent('backpacks:server:add_password', { ID = ID, password = inputData.pass })
end
end
function CheckMeta(backpack_metadata)
if backpack_metadata.locked then
local inputData = exports['qb-input']:ShowInput({
header = Lang('INTRODUCE_PASSWORD'),
inputs = {
{
type = 'password',
isRequired = true,
name = 'pass',
text = Lang('INTRODUCE_PASSWORD')
},
}
})
if inputData then
if not inputData.pass then
SendTextMessage(Lang('BAD_PASSWORD'), 'error')
return
end
backpack_metadata.trypassword = inputData.pass
OpenBackpack(backpack_metadata)
end
else
OpenBackpack(backpack_metadata)
end
end

View File

@@ -0,0 +1,32 @@
if Config.SkinScript ~= 'esx_skin' then
return
end
function putClothes(backpack)
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
local clothes = {
male = { ['bags_1'] = backpack.cloth['male'].bag['item'], ['bags_2'] = backpack.cloth['male'].bag['texture'] },
female = { ['bags_1'] = backpack.cloth['female'].bag['item'], ['bags_2'] = backpack.cloth['male'].bag['texture'] },
}
if skin.sex == 0 then
TriggerEvent('skinchanger:loadClothes', skin, clothes.male)
elseif skin.sex == 1 then
TriggerEvent('skinchanger:loadClothes', skin, clothes.female)
end
end)
end
function RemoveClothes()
local cloth = {
male = { ['bags_1'] = 0 },
female = { ['bags_1'] = 0 },
}
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
if skin.sex == 0 then
TriggerEvent('skinchanger:loadClothes', skin, cloth.male)
elseif skin.sex == 1 then
TriggerEvent('skinchanger:loadClothes', skin, cloth.female)
end
end)
end

View File

@@ -0,0 +1,19 @@
if Config.SkinScript ~= 'illenium-appearance' then
return
end
function putClothes(backpack)
if getSex() == 0 then
TriggerEvent('qb-clothing:client:loadOutfit', { outfitData = backpack.cloth['male'] })
else
TriggerEvent('qb-clothing:client:loadOutfit', { outfitData = backpack.cloth['female'] })
end
end
function RemoveClothes()
TriggerEvent('qb-clothing:client:loadOutfit', {
outfitData = {
['bag'] = { item = -1, texture = 0 }
}
})
end

View File

@@ -0,0 +1,19 @@
if Config.SkinScript ~= 'qb-clothing' then
return
end
function putClothes(backpack)
if getSex() == 0 then
TriggerEvent('qb-clothing:client:loadOutfit', { outfitData = backpack.cloth['male'] })
else
TriggerEvent('qb-clothing:client:loadOutfit', { outfitData = backpack.cloth['female'] })
end
end
function RemoveClothes()
TriggerEvent('qb-clothing:client:loadOutfit', {
outfitData = {
['bag'] = { item = -1, texture = 0 }
}
})
end

View File

@@ -0,0 +1,34 @@
fx_version 'adamant'
game 'gta5'
lua54 'yes'
shared_scripts {
'@ox_lib/init.lua',
'shared/*.lua',
'locales/*.lua',
'client/shared.lua'
}
server_scripts {
'server/**/**/**.lua'
}
client_scripts {
'client/**/**/**.lua'
}
escrow_ignore {
'shared/*.lua',
'locales/*.lua',
'client/custom/**/*.lua'
}
dependencies {
'/server:4752', -- ⚠PLEASE READ⚠ This requires at least server build 4700 or higher
'/assetpacks',
'qs-inventory'
}
dependency '/assetpacks'

View File

@@ -0,0 +1,60 @@
# FOR QBCore `qb-core/shared/items`
```lua
['backpack'] = { ['name'] = 'backpack', ['label'] = 'backpack', ['weight'] = 0, ['type'] = 'item', ['image'] = 'backpack.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'No have' },
['backpack2'] = { ['name'] = 'backpack2', ['label'] = 'backpack2', ['weight'] = 0, ['type'] = 'item', ['image'] = 'backpack2.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'No have' },
['briefcase'] = { ['name'] = 'briefcase', ['label'] = 'briefcase', ['weight'] = 0, ['type'] = 'item', ['image'] = 'briefcase.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'No have' },
['paramedicbag'] = { ['name'] = 'paramedicbag', ['label'] = 'paramedicbag', ['weight'] = 0, ['type'] = 'item', ['image'] = 'paramedicbag.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'No have' },
```
# FOR ESX `qs-inventory/shared/items.lua`
```lua
['backpack'] = {
['name'] = 'backpack',
['label'] = 'backpack',
['weight'] = 0,
['type'] = 'item',
['image'] = 'backpack.png',
['unique'] = true,
['useable'] = true,
['shouldClose'] = true,
['combinable'] = nil,
['description'] = 'No have'
},
['backpack2'] = {
['name'] = 'backpack2',
['label'] = 'backpack2',
['weight'] = 0,
['type'] = 'item',
['image'] = 'backpack2.png',
['unique'] = true,
['useable'] = true,
['shouldClose'] = true,
['combinable'] = nil,
['description'] = 'No have'
},
['briefcase'] = {
['name'] = 'briefcase',
['label'] = 'briefcase',
['weight'] = 0,
['type'] = 'item',
['image'] = 'briefcase.png',
['unique'] = true,
['useable'] = true,
['shouldClose'] = true,
['combinable'] = nil,
['description'] = 'No have'
},
['paramedicbag'] = {
['name'] = 'paramedicbag',
['label'] = 'paramedicbag',
['weight'] = 0,
['type'] = 'item',
['image'] = 'paramedicbag.png',
['unique'] = true,
['useable'] = true,
['shouldClose'] = true,
['combinable'] = nil,
['description'] = 'No have'
},
```

View File

@@ -0,0 +1,14 @@
Locales['cs'] = {
['INTRODUCE_PASSWORD'] = 'Zadejte heslo',
['INTRODUCE_PASSWORD_2'] = 'Heslo',
['CREATE_PASSWORD'] = 'Vytvořit heslo',
['OPEN'] = 'Otevírám...',
['CLOSE'] = 'Zavírám...',
['BAD_PASSWORD'] = 'Nesprávné heslo...',
['ADDED_PASSWORD'] = 'Přidáno heslo..',
['MORE_PASSWORD'] = 'Heslo musí mít více znaků',
['LESS_PASSWORD'] = 'Heslo musí mít méně znaků',
['EMPLY_PASSWORD'] = 'Musíte něco vložit',
['NO_BACKPACK'] = 'Batoh nemáte po ruce.',
['FAILED_PASSWORD'] = 'Nepodařilo se přidat heslo.',
}

View File

@@ -0,0 +1,14 @@
Locales['de'] = {
['INTRODUCE_PASSWORD'] = 'Passwort eingeben',
['INTRODUCE_PASSWORD_2'] = 'Passwort',
['CREATE_PASSWORD'] = 'Erstelle ein Passwort',
['OPEN'] = 'Öffnen...',
['CLOSE'] = 'Schließen...',
['BAD_PASSWORD'] = 'Falsches Passwort...',
['ADDED_PASSWORD'] = 'Passwort hinzugefügt...',
['MORE_PASSWORD'] = 'Das Passwort muss länger sein',
['LESS_PASSWORD'] = 'Das Passwort muss kürzer sein',
['EMPLY_PASSWORD'] = 'Du musst ein Passwort eingeben',
['NO_BACKPACK'] = 'Der Rucksack befindet sich nicht in deiner Hand.',
['FAILED_PASSWORD'] = 'Passwort konnte nicht hinzugefügt werden.',
}

View File

@@ -0,0 +1,14 @@
Locales['en'] = {
['INTRODUCE_PASSWORD'] = 'Enter the password',
['INTRODUCE_PASSWORD_2'] = 'Password',
['CREATE_PASSWORD'] = 'Create a password',
['OPEN'] = 'Opening...',
['CLOSE'] = 'Closing...',
['BAD_PASSWORD'] = 'Incorrect password...',
['ADDED_PASSWORD'] = 'Added password..',
['MORE_PASSWORD'] = 'The password must have more characters',
['LESS_PASSWORD'] = 'The password must have fewer characters',
['EMPLY_PASSWORD'] = 'You need to put something',
['NO_BACKPACK'] = 'Backpack is not on your hand.',
['FAILED_PASSWORD'] = 'Failed to add password.',
}

View File

@@ -0,0 +1,14 @@
Locales['es'] = {
['INTRODUCE_PASSWORD'] = 'Introduce la contraseña',
['INTRODUCE_PASSWORD_2'] = 'Contraseña',
['CREATE_PASSWORD'] = 'Crea una contraseña',
['OPEN'] = 'Abriendo...',
['CLOSE'] = 'Cerrando...',
['BAD_PASSWORD'] = 'Contraseña incorrecta...',
['ADDED_PASSWORD'] = 'Contraseña incorrecta...',
['MORE_PASSWORD'] = 'La contraseña tiene que tener mas caracteres',
['LESS_PASSWORD'] = 'La contraseña tiene que tener menos caracteres',
['EMPLY_PASSWORD'] = 'Necesitas poner algo',
['NO_BACKPACK'] = 'La mochila no esta en tu mano.',
['FAILED_PASSWORD'] = 'No pudiste agregar la contraseña.',
}

View File

@@ -0,0 +1,14 @@
Locales['fr'] = {
['INTRODUCE_PASSWORD'] = 'Entrer un mot de passe',
['INTRODUCE_PASSWORD_2'] = 'Mot de passe',
['CREATE_PASSWORD'] = 'Créez votre mot de passe',
['OPEN'] = 'Ouverture...',
['CLOSE'] = 'Fermeture...',
['BAD_PASSWORD'] = 'Mot de passe incorrect...',
['ADDED_PASSWORD'] = 'Nouveau mot de passe..',
['MORE_PASSWORD'] = 'Votre mot de passe est trop court.',
['LESS_PASSWORD'] = 'Votre mot de passe est trop long.',
['EMPLY_PASSWORD'] = 'Vous devez remplir les champs.',
['NO_BACKPACK'] = "Le sac n'est pas dans votre inventaire.",
['FAILED_PASSWORD'] = "Erreur lors de l'ajout du mot de passe.",
}

View File

@@ -0,0 +1,14 @@
Locales['hu'] = {
['INTRODUCE_PASSWORD'] = 'Írja be a jelszót',
['INTRODUCE_PASSWORD_2'] = 'Jelszó',
['CREATE_PASSWORD'] = 'Hozzon létre egy jelszót',
['OPEN'] = 'Nyítás...',
['CLOSE'] = 'Zárás...',
['BAD_PASSWORD'] = 'hibás jelszó...',
['ADDED_PASSWORD'] = 'Hozzáadta jelszót..',
['MORE_PASSWORD'] = 'A jelszónak több karakterből kell állnia',
['LESS_PASSWORD'] = 'A jelszónak kevesebb karakterből kell állnia',
['EMPLY_PASSWORD'] = 'Be kell tenni valamit,',
['NO_BACKPACK'] = 'A hátizsák nincs a kezedben.',
['FAILED_PASSWORD'] = 'Nem sikerült a jelszó hozzáadása.',
}

View File

@@ -0,0 +1,14 @@
Locales['nl'] = {
['INTRODUCE_PASSWORD'] = 'Vul wachtwoord in',
['INTRODUCE_PASSWORD_2'] = 'Wachtwoord',
['CREATE_PASSWORD'] = 'Wachtwoord aanmaken',
['OPEN'] = 'Openen...',
['CLOSE'] = 'Sluiten...',
['BAD_PASSWORD'] = 'Onjuist wachtwoord...',
['ADDED_PASSWORD'] = 'Wachtwoord toegevoegd..',
['MORE_PASSWORD'] = 'Het wachtwoord voldoet niet aan de hoeveelheid tekens',
['LESS_PASSWORD'] = 'Het wachtwoord heeft teveel tekens',
['EMPLY_PASSWORD'] = 'Je moet iets ingeven',
['NO_BACKPACK'] = 'Je draagt momenteel geen tas in je hand.',
['FAILED_PASSWORD'] = 'Wachtwoord toevoegen mislukt.',
}

View File

@@ -0,0 +1,14 @@
Locales['pl'] = {
['INTRODUCE_PASSWORD'] = 'Wprowadź hasło',
['INTRODUCE_PASSWORD_2'] = 'Podaj hasło',
['CREATE_PASSWORD'] = 'Utwórz hasło',
['OPEN'] = 'Otwarcie...',
['CLOSE'] = 'Zamknięcie...',
['BAD_PASSWORD'] = 'Nieprawidłowe hasło...',
['ADDED_PASSWORD'] = 'Dodane hasło...',
['MORE_PASSWORD'] = 'Hasło musi mieć więcej znaków',
['LESS_PASSWORD'] = 'Hasło musi mieć mniej znaków',
['EMPLY_PASSWORD'] = 'Musisz coś wpisać',
['NO_BACKPACK'] = 'Plecak nie jest pod ręką',
['FAILED_PASSWORD'] = 'Nie udało się dodać hasła.',
}

View File

@@ -0,0 +1,14 @@
Locales['pt'] = {
['INTRODUCE_PASSWORD'] = 'Insira a senha',
['INTRODUCE_PASSWORD_2'] = 'Senha',
['CREATE_PASSWORD'] = 'Criar senha',
['OPEN'] = 'Abrindo...',
['CLOSE'] = 'Fechando...',
['BAD_PASSWORD'] = 'Senha incorreta...',
['ADDED_PASSWORD'] = 'Password adicionada.',
['MORE_PASSWORD'] = 'Senha muito curta',
['LESS_PASSWORD'] = 'Senha muito longa',
['EMPLY_PASSWORD'] = 'É necessário inserir algum valor',
['NO_BACKPACK'] = 'A mochila não está na sua mão.',
['FAILED_PASSWORD'] = 'Erro ao adicionar a senha.',
}

View File

@@ -0,0 +1,151 @@
Config = Config or {}
-- Clarification if you are going to create more backpacks you have to add the information in these parts:
-- qs-inventory/config/metadata.js
-- Save information
--[[
} else if (itemData.name == "YOUR_BACKPACK_NAME") {
$(".item-info-title").html("<p>" + label + "</p>");
$(".item-info-description").html(
"<p><strong>ID: </strong><span>" +
itemData.info.ID +
"</span></p><p><strong>Weight: </strong><span>" +
itemData.info.weight +
"</span></p><p><strong>Slots: </strong><span>" +
itemData.info.slots +
"</span></p>"
);
]]
-- qs-inventory/server/custom/GiveItemToPlayer.lua
-- For giveitem admin
--[[
elseif itemData["name"] == "YOUR_BACKPACK_NAME" then
info.ID = 'backpack_'..math.random(111111,999999)
info.weight = 10000
info.slots = 10
]]
-- (IMPORTANT INTEGRATION WITH qs-advancedshops or qs-shops)
-- If you want to add the backpack to a qs-shop, you must add an ID to the item. this is the example :
--[[
qs-shops/config/config.lua or qs-advancedshops/config/shops.lua
[1] = {
name = "backpack",
label = 'Backpack',
price = 250,
amount = 100,
info = {}, -- If you put here info = {}, it will automatically take the weight of your configuration
type = "item",
slot = 1,
},
[2] = {
name = "my_custom_backpack",
label = 'UwU Backpack',
price = 250,
amount = 100,
info = { ID = 'ID_'..math.random(111111,999999), weight = 10000 , slots = 10}, -- If you put this information, it will take the information you put in it
type = "item",
slot = 2,
},
]]
-- (important) do not use both prop and cloth at same time just one.
Config.Items = {
['backpack'] = { --- Item name
slots = 10, -- Change in `qs-inventory/server/custom/GiveItemToPlayer.lua`
weight = 100000, -- Change in `qs-inventory/server/custom/GiveItemToPlayer.lua`
locked = false, -- If you want to have a password change false to true
prop = {
model = 'vw_prop_vw_backpack_01a',
animation = {
dict = 'amb@world_human_hiker_standing@female@base',
anim = 'base',
bone = 'Back', -- LeftHand | RightHand
attaching_position = {
x = -0.20, -- Up - Down
y = -0.10, -- Forward Backward
z = 0.0, -- Left - Right
x_rotation = 10.0,
y_rotation = 90.0,
z_rotation = 175.0,
}
},
},
},
['backpack2'] = {
slots = 6, -- Change in `qs-inventory/server/custom/GiveItemToPlayer.lua`
weight = 10000, -- Change in `qs-inventory/server/custom/GiveItemToPlayer.lua`
cloth = {
male = {
['bag'] = { item = 45, texture = 0 }
},
female = {
['bag'] = { item = 45, texture = 0 }
}
}
},
['briefcase'] = {
slots = 3,
weight = 5000,
locked = true, -- If you want to have a password change false to true
prop = {
model = 'prop_ld_suitcase_01',
animation = {
dict = 'missheistdocksprep1hold_cellphone',
anim = 'static',
bone = 'RightHand',
attaching_position = {
x = 0.10,
y = 0.0,
z = 0.0,
x_rotation = 0.0,
y_rotation = 280.0,
z_rotation = 53.0,
}
},
},
},
['paramedicbag'] = {
slots = 10, -- Change in `qs-inventory/server/custom/GiveItemToPlayer.lua`
weight = 10000, -- Change in `qs-inventory/server/custom/GiveItemToPlayer.lua`
prop = {
model = 'xm_prop_smug_crate_s_medical',
animation = {
dict = 'missheistdocksprep1hold_cellphone',
anim = 'static',
bone = 'RightHand',
attaching_position = {
x = 0.29,
y = -0.05,
z = 0.0,
x_rotation = -25.0,
y_rotation = 280.0,
z_rotation = 75.0,
}
},
}
},
}
Config.Bones = {
bones = {
['RightHand'] = {
bone = 57005,
current_active_porp = nil,
slot = -1,
},
['Back'] = {
bone = 24818,
current_active_porp = nil,
slot = -1,
},
['LeftHand'] = {
bone = 18905,
current_active_porp = nil,
slot = -1,
},
}
}

View File

@@ -0,0 +1,92 @@
Config = Config or {}
Locales = Locales or {}
local esxHas = GetResourceState('es_extended') == 'started'
local qbHas = GetResourceState('qb-core') == 'started'
local qbxHas = GetResourceState('qbx_core') == 'started'
Config.Framework = esxHas and 'esx' or qbHas and 'qb' or qbxHas and 'qb' or 'esx'
--[[
Language settings.
Define the language file located in the locales folder.
]]
Config.Language = 'en' -- Set your lang in locales folder
--[[
Skin script configuration.
Supported options:
- 'qb-clothing': For servers using QBCore's clothing script.
- 'illenium-appearance': For servers using Illenium Appearance.
- 'esx_skin': For servers using the ESX Skin system.
]]
Config.SkinScript = 'illenium-appearance' -- 'qb-clothing', 'illenium-appearance', 'esx_skin'
--[[
Menu system configuration.
Supported options:
- 'qb-menu': For QBCore's menu system.
- 'ox_lib': For Ox Library's menu system.
- 'esx_menu_default': For ESX's default menu system.
]]
Config.Menu = 'qb-menu' -- 'qb-menu', 'ox_lib', 'esx_menu_default'
--[[
Hotbar slots configuration.
Specify the slots that will act as your hotbar.
Use an array of numbers, where each number represents a slot.
]]
Config.Hotbar = {
1, 2, 3, 4, 5
}
--[[
Backpack opening/closing duration.
Configure the time (in seconds) it takes to open or close the backpack.
]]
Config.duration = {
open = 1, -- Time in seconds to open the backpack.
close = 1 -- Time in seconds to close the backpack.
}
--[[
Password length settings.
Define the minimum and maximum length for passwords when required.
]]
Config.PasswordLength = {
min = 3, -- Minimum password length.
max = 5 -- Maximum password length.
}
--[[
Animation configuration for different backpack actions.
Each action includes:
- Dict: The animation dictionary used for the action.
- Anim: The specific animation name.
- Flag: The animation flag (e.g., 49 = upper body only).
]]
Config.Animation = {
close = { -- Animation for closing the backpack.
Dict = 'clothingshirt', -- Animation dictionary.
Anim = 'try_shirt_positive_d', -- Animation name.
Flag = 49 -- Animation flag.
},
open = { -- Animation for opening the backpack.
Dict = 'clothingshirt', -- Animation dictionary.
Anim = 'try_shirt_positive_d', -- Animation name.
Flag = 49 -- Animation flag.
},
inBackpack = { -- Animation for interacting with items in the backpack.
Dict = 'clothingshirt', -- Animation dictionary.
Anim = 'try_shirt_positive_d' -- Animation name.
},
}

View File

@@ -1,3 +1,34 @@
local function SyncEquippedWeaponAmmoOnOpen(inventory)
if not inventory then return inventory end
local ped = cache.ped
local weaponHash = GetSelectedPedWeapon(ped)
local weaponData = WeaponList and WeaponList[weaponHash]
if not weaponData or weaponData.name == 'weapon_unarmed' then
return inventory
end
local ammo = GetAmmoInPedWeapon(ped, weaponHash) or 0
-- Prefer the equipped slot if CurrentWeaponData is available.
local preferredSlot = CurrentWeaponData and CurrentWeaponData.slot
if preferredSlot and inventory[preferredSlot] and inventory[preferredSlot].name == weaponData.name then
inventory[preferredSlot].info = inventory[preferredSlot].info or {}
inventory[preferredSlot].info.ammo = ammo
return inventory
end
for _, item in pairs(inventory) do
if item and item.type == 'weapon' and item.name == weaponData.name then
item.info = item.info or {}
item.info.ammo = ammo
break
end
end
return inventory
end
local checkDistanceInventories = {
'shop',
'stash',
@@ -38,6 +69,7 @@ RegisterNetEvent(Config.InventoryPrefix .. ':client:OpenInventory', function(Pla
end
inventory = data.inventory
inventory = SyncEquippedWeaponAmmoOnOpen(inventory)
other = data.other
data = GetPlayerData()

View File

@@ -2,7 +2,7 @@ if not GetResourceState('jobs_creator') == 'missing' then
return
end
-- Warning('Started the compatibility module with jobs_creator')
Warning('Started the compatibility module with jobs_creator')
CreateThread(function()
local other = {}

View File

@@ -15,28 +15,22 @@ local function LoadAnimDict(dict)
end
end
RegisterKeyMapping('+handsup', Lang('INVENTORY_KEYMAPPING_HANDSUP_LABEL'), 'keyboard', Config.KeyBinds.handsup)
RegisterKeyMapping('handsup', Lang('INVENTORY_KEYMAPPING_HANDSUP_LABEL'), 'keyboard', Config.KeyBinds.handsup)
local handsUpActive = false
RegisterCommand('+handsup', function()
RegisterCommand('handsup', function()
if not IsPedInAnyVehicle(PlayerPedId(), false) and GetEntityHealth(PlayerPedId()) > 1 then
if canHandsUp and not handsUpActive then
handsUpActive = true
RequestAnimDict(lib)
while not HasAnimDictLoaded(lib) do
Wait(100)
end
SetCurrentPedWeapon(PlayerPedId(), GetHashKey('WEAPON_UNARMED'), true)
TaskPlayAnim(PlayerPedId(), lib, anim, 2.0, 2.5, -1, 49, 0, 0, 0, 0)
RequestAnimDict(lib)
while not HasAnimDictLoaded(lib) do
Wait(100)
end
SetCurrentPedWeapon(PlayerPedId(), GetHashKey('WEAPON_UNARMED'), true)
if IsEntityPlayingAnim(PlayerPedId(), lib, anim, 3) then
ClearPedSecondaryTask(PlayerPedId())
else
if canHandsUp then
TaskPlayAnim(PlayerPedId(), lib, anim, 2.0, 2.5, -1, 49, 0, 0, 0, 0)
end
end
end
end)
RegisterCommand('-handsup', function()
if handsUpActive then
handsUpActive = false
ClearPedSecondaryTask(PlayerPedId())
end
end)

View File

@@ -0,0 +1,31 @@
if not Config.Debug then
return
end
Debug('Debug Command', 'inventory:openStash command initialized')
RegisterCommand('inventory:openStash', function(source, args)
local id = args[1] or source
local stashId = 'inventory_debug_stash' .. id
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'stash', stashId)
TriggerEvent(Config.InventoryPrefix .. ':client:SetCurrentStash', stashId)
end)
Debug('Debug Command', 'inventory:search command initialized')
RegisterCommand('inventory:search', function(source, args)
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'otherplayer', tonumber(args[1]))
end)
Debug('Debug Command', 'inventory:openOther command initialized')
RegisterCommand('inventory:openOther', function(source, args, raw)
local target = tonumber(args[1])
if not target then
Debug('Debug Command', 'Invalid target ID')
return
end
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'otherplayer', target)
end)
TriggerEvent('chat:addSuggestion', '/inventory:openOther', 'Open inventory of another player', {
{ name = 'targetId', help = 'Target player ID' },
})

View File

@@ -2,6 +2,8 @@ local PlayerData = GetPlayerData()
local CanShoot, MultiplierAmount = true, 0
CurrentWeaponData = {}
local weaponTrackingActive = false
exports('GetCurrentWeapon', function()
return CurrentWeaponData
end)
@@ -10,6 +12,55 @@ lib.callback.register('weapons:client:GetCurrentWeapon', function()
return CurrentWeaponData
end)
local function SyncWeaponToServer()
if not CurrentWeaponData or not CurrentWeaponData.info or not CurrentWeaponData.name then return end
local ammo = CurrentWeaponData.info.ammo or 0
TriggerServerEvent('weapons:server:UpdateWeaponAmmo', CurrentWeaponData, ammo)
if MultiplierAmount > 0 then
TriggerServerEvent('weapons:server:UpdateWeaponQuality', CurrentWeaponData, MultiplierAmount, ammo)
MultiplierAmount = 0
end
end
local function StartWeaponTracking()
if weaponTrackingActive then return end
weaponTrackingActive = true
CreateThread(function()
while weaponTrackingActive and CurrentWeaponData and next(CurrentWeaponData) do
local ped = PlayerPedId()
local weapon = GetSelectedPedWeapon(ped)
if weapon ~= `WEAPON_UNARMED` and CurrentWeaponData.info then
CurrentWeaponData.info.ammo = GetAmmoInPedWeapon(ped, weapon)
end
if IsPedShooting(ped) then
if CanShoot then
if weapon and weapon ~= 0 and WeaponList[weapon] then
MultiplierAmount = MultiplierAmount + 1
end
else
if weapon ~= `WEAPON_UNARMED` then
TriggerEvent(Config.InventoryPrefix .. ':client:CheckWeapon', WeaponList[weapon]['name'])
SendTextMessage(Lang('INVENTORY_NOTIFICATION_WEAPON_BROKEN'), 'error')
MultiplierAmount = 0
end
end
end
Wait(100)
end
weaponTrackingActive = false
end)
end
local function StopWeaponTracking()
weaponTrackingActive = false
end
CreateThread(function()
while not Config.WeaponsOnVehicle do
Wait(250)
@@ -92,12 +143,19 @@ RegisterNetEvent('addAttachment', function(component, urltint)
end)
RegisterNetEvent('weapons:client:SetCurrentWeapon', function(data, bool)
if data ~= false then
if CurrentWeaponData and next(CurrentWeaponData) then
SyncWeaponToServer()
StopWeaponTracking()
end
if data ~= false and data ~= nil then
CurrentWeaponData = data
CanShoot = bool
StartWeaponTracking()
else
CurrentWeaponData = {}
CanShoot = bool
end
CanShoot = bool
end)
RegisterNetEvent('weapons:client:SetWeaponQuality', function(amount)
@@ -291,52 +349,6 @@ CreateThread(function()
SetWeaponsNoAutoswap(true)
end)
LastUpdatedAmmoTime = nil
CreateThread(function()
while true do
local ped = PlayerPedId()
if GetSelectedPedWeapon(ped) ~= `WEAPON_UNARMED` and CurrentWeaponData?.info and (IsControlJustReleased(0, 24) or IsDisabledControlJustReleased(0, 24)) then
local weapon = GetSelectedPedWeapon(ped)
local ammo = GetAmmoInPedWeapon(ped, weapon)
TriggerServerEvent('weapons:server:UpdateWeaponAmmo', CurrentWeaponData, tonumber(ammo))
CurrentWeaponData.info.ammo = ammo
LastUpdatedAmmoTime = GetGameTimer()
if MultiplierAmount > 0 then
TriggerServerEvent('weapons:server:UpdateWeaponQuality', CurrentWeaponData, MultiplierAmount, ammo)
MultiplierAmount = 0
end
end
Wait(0)
end
end)
CreateThread(function()
while true do
local ped = PlayerPedId()
if CurrentWeaponData and next(CurrentWeaponData) then
if IsPedShooting(ped) or IsControlJustPressed(0, 24) then
local weapon = GetSelectedPedWeapon(ped)
if CanShoot then
if weapon and weapon ~= 0 and WeaponList[weapon] then
TriggerServerCallback('prison:server:checkThrowable', function(result)
if result or GetAmmoInPedWeapon(ped, weapon) <= 0 then return end
MultiplierAmount += 1
end, weapon)
Wait(200)
end
else
if weapon ~= `WEAPON_UNARMED` then
TriggerEvent(Config.InventoryPrefix .. ':client:CheckWeapon', WeaponList[weapon]['name'])
SendTextMessage(Lang('INVENTORY_NOTIFICATION_WEAPON_BROKEN'), 'error')
MultiplierAmount = 0
end
end
end
end
Wait(0)
end
end)
RegisterNetEvent(Config.InventoryPrefix .. ':client:LegacyFuel', function(fuel)
Debug('Your gasoline can has: %', fuel)
TriggerServerEvent('weapons:server:UpdateWeaponAmmo', CurrentWeaponData, fuel)

View File

@@ -36,7 +36,7 @@ Locales = Locales or {} -- [CORE] Language packs container.
-- 'ar','bg','ca','cs','da','de','el','en','es','fa','fr','hi','hu','it','ja',
-- 'ko','nl','no','pl','pt','ro','ru','sl','sv','th','tr','zh-CN','zh-TW'
--──────────────────────────────────────────────────────────────────────────────
Config.Language = 'ro' -- [EDIT]
Config.Language = 'en' -- [EDIT]
--[[ [INFO]
Choose your preferred language!
@@ -123,7 +123,7 @@ Config.KQPlaceableItems = false -- [EDIT] Use KQ
-- [INFO] Changing weight/slots can require wipes to avoid dupes. Be cautious.
--──────────────────────────────────────────────────────────────────────────────
Config.InventoryWeight = { -- [EDIT]
weight = 5000, -- [INFO] Max weight (grams).
weight = 120000, -- [INFO] Max weight (grams).
slots = 41, -- [INFO] Set 40 to remove protected 6th slot.
}
@@ -138,7 +138,7 @@ Config.DropWeight = { -- [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- Label Change [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.LabelChange = false -- [EDIT] Allow item renaming.
Config.LabelChange = true -- [EDIT] Allow item renaming.
Config.LabelChangePrice = false -- [EDIT] Price or false for free.
Config.BlockedLabelChangeItems = { -- [EDIT] Items that cannot be renamed.
money = true,
@@ -358,8 +358,8 @@ Config.InventoryOptions = {
['thirst'] = true, -- [EDIT] Show thirst
['id'] = true, -- [EDIT] Show player ID
['money'] = true, -- [EDIT] Show cash
['bank'] = false, -- [EDIT] Show bank balance
['blackmoney'] = false, -- [EDIT] Show black money
['bank'] = true, -- [EDIT] Show bank balance
['blackmoney'] = true, -- [EDIT] Show black money
}
--──────────────────────────────────────────────────────────────────────────────
@@ -442,7 +442,7 @@ Config.KeyBinds = { -- [EDIT]
-- Debug & Development Tools [EDIT]
-- [INFO] Enables development logs and debugging prints. Use only during testing.
--──────────────────────────────────────────────────────────────────────────────
Config.Debug = false -- [EDIT] Detailed console prints
Config.Debug = true -- [EDIT] Detailed console prints
Config.ZoneDebug = false -- [EDIT] Display additional zone debug info
Config.InventoryPrefix = 'inventory' -- [ADV] Internal prefix; changing requires code adjustments
Config.SaveInventoryInterval = 12500 -- [EDIT] Autosave interval (ms)

View File

@@ -107,130 +107,130 @@ end
-- [INFO] Define mesas de crafteo por job/ubicación, con blip y recetas propias.
--──────────────────────────────────────────────────────────────────────────────
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.771423, -989.050537, 24.898926),
-- 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.303299, 3745.503418, 39.771484),
-- 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
-- },
-- }
-- },
[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.771423, -989.050537, 24.898926),
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.303299, 3745.503418, 39.771484),
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
},
}
},
-- Continue with the same structure for the other Crafting Tables...
}

View File

@@ -19,10 +19,10 @@
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] General behavior toggles for tints, magazines and durability exclusions.
--──────────────────────────────────────────────────────────────────────────────
Config.RemoveTintAfterRemoving = false -- [EDIT] Remove weapon tints when discarded/removed.
Config.ForceToOnlyOneMagazine = true -- [EDIT] Only one magazine in use at a time.
Config.RemoveTintAfterRemoving = false -- [EDIT] Remove weapon tints when discarded/removed.
Config.ForceToOnlyOneMagazine = true -- [EDIT] Only one magazine in use at a time.
Config.DurabilityBlockedWeapons = { -- [EDIT] Weapons excluded from durability loss.
Config.DurabilityBlockedWeapons = { -- [EDIT] Weapons excluded from durability loss.
'weapon_stungun',
'weapon_nightstick',
'weapon_flashlight',
@@ -34,14 +34,14 @@ Config.DurabilityBlockedWeapons = { -- [EDIT] Weapons excluded from durabili
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Customize UI line anchors for attachments on weapon preview.
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponAttachmentLines = {
['suppressor'] = { bones = { 'WAPSupp', 'WAPSupp_2' }, offset = vec2(-25, -20) },
['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, offset = vec2( 20, 0) },
Config.WeaponAttachmentLines = {
['suppressor'] = { bones = { 'WAPSupp', 'WAPSupp_2' }, offset = vec2(-25, -20) },
['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, offset = vec2(20, 0) },
}
--──────────────────────────────────────────────────────────────────────────────
@@ -49,7 +49,7 @@ Config.WeaponAttachmentLines = {
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] List of throwable items enabled in the game.
--──────────────────────────────────────────────────────────────────────────────
Config.Throwables = {
Config.Throwables = {
'ball',
'bzgas',
'flare',
@@ -69,18 +69,18 @@ Config.Throwables = {
-- [INFO] Maps inventory ammo items to native ammo types. `isForEveryWeapon` acts as a wildcard.
--──────────────────────────────────────────────────────────────────────────────
---@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 = 'police_rifle_ammo', type = 'AMMO_POLICE_RIFLE' },
{ item = 'master_ammo', isForEveryWeapon = true },
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 = 'police_rifle_ammo', type = 'AMMO_POLICE_RIFLE' },
{ item = 'master_ammo', isForEveryWeapon = true },
}
--──────────────────────────────────────────────────────────────────────────────
@@ -88,131 +88,131 @@ Config.AmmoItems = {
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Higher numbers degrade faster. Tune per weapon to balance your economy/combat.
--──────────────────────────────────────────────────────────────────────────────
Config.DurabilityMultiplier = {
Config.DurabilityMultiplier = {
-- Melee
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,
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
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,
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
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,
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
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,
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
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,
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
weapon_mg = 0.15,
weapon_combatmg = 0.15,
weapon_gusenberg = 0.15,
weapon_combatmg_mk2 = 0.15,
weapon_mg = 0.15,
weapon_combatmg = 0.15,
weapon_gusenberg = 0.15,
weapon_combatmg_mk2 = 0.15,
-- Sniper Rifles
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,
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
weapon_rpg = 0.15,
weapon_grenadelauncher = 0.15,
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,
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
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,
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,
-- Misc
weapon_petrolcan = 0.15,
weapon_fireextinguisher = 0.15,
weapon_hazardcan = 0.15,
weapon_fertilizercan = 0.15,
weapon_petrolcan = 0.15,
weapon_fireextinguisher = 0.15,
weapon_hazardcan = 0.15,
weapon_fertilizercan = 0.15,
}
--──────────────────────────────────────────────────────────────────────────────
@@ -222,7 +222,7 @@ Config.DurabilityMultiplier = {
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponRepairItemAddition = 10 -- [EDIT] Amount added to repair kit usage counter.
Config.WeaponRepairPoints = {
Config.WeaponRepairPoints = {
[1] = {
coords = vector3(964.02, -1267.41, 34.97), -- [EDIT] Location of repair station.
IsRepairing = false, -- [AUTO] Tracks ongoing repair.
@@ -231,7 +231,7 @@ Config.WeaponRepairPoints = {
-- [EDIT] Add more repair points if needed.
}
Config.WeaponRepairCosts = {
Config.WeaponRepairCosts = {
['Pistol'] = 1000,
['Submachine Gun'] = 3000,
['Light Machine Gun'] = 4000,
@@ -246,10 +246,10 @@ Config.WeaponRepairCosts = {
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Enables the ability to steal weapon parts with a configurable chance.
--──────────────────────────────────────────────────────────────────────────────
Config.CanStealWeaponParts = false -- [EDIT] Toggle ability to steal weapon parts.
Config.WeaponPartStealChance = 20 -- [EDIT] Probability (1100) for successful part theft.
Config.CanStealWeaponParts = false -- [EDIT] Toggle ability to steal weapon parts.
Config.WeaponPartStealChance = 20 -- [EDIT] Probability (1100) for successful part theft.
Config.AvailableWeaponParts = { -- [EDIT] Items obtainable via part stealing.
Config.AvailableWeaponParts = { -- [EDIT] Items obtainable via part stealing.
'electronickit',
'ironoxide',
'metalscrap',
@@ -263,16 +263,16 @@ Config.AvailableWeaponParts = { -- [EDIT] Items obtainable via part stealing
-- Each attachment includes a component, label, and item link.
-- Naming convention: use clear identifiers like pistol_flashlight or rifle_scope.
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponAttachments = {
Config.WeaponAttachments = {
--──────────────────────────────────────────────────────────────────────────
-- Pistol Attachments [EDIT]
--──────────────────────────────────────────────────────────────────────────
['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' },
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' },
},
['WEAPON_COMBATPISTOL'] = {
defaultclip = { component = 'COMPONENT_COMBATPISTOL_CLIP_01', item = 'pistol_defaultclip' },
@@ -676,6 +676,7 @@ Config.WeaponAttachments = {
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' },
thermalscope = { component = 'COMPONENT_AT_SCOPE_THERMAL', item = 'sniper_thermalscope' },
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' },
@@ -702,60 +703,60 @@ Config.WeaponAttachments = {
-- Entry format:
-- [index] = { name = 'Weapon Name', hash = 'WeaponHashCode', ytd = 'TextureDictionary', texture = 'TextureName' }
--──────────────────────────────────────────────────────────────────────────────
Config.WeaponTints = {
Config.WeaponTints = {
-- Pistols
[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' },
[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' },
-- SMGs / MGs
[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' },
[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
[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' },
[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' },
-- Snipers
[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' },
[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
[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' },
[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' },
-- Others
[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' },
[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
[40] = { name = 'Pump Shotgun Mk II', hash = '1432025498', ytd = 'w_sg_pumpshotgunmk2', texture = 'w_sg_pumpshotgunmk2' },
[40] = { name = 'Pump Shotgun Mk II', hash = '1432025498', ytd = 'w_sg_pumpshotgunmk2', texture = 'w_sg_pumpshotgunmk2' },
}
--──────────────────────────────────────────────────────────────────────────────
@@ -1171,4 +1172,4 @@ end)
exports('GetWeaponAttachmentItems', function()
return Config.WeaponAttachmentItems
end)
end)

View File

@@ -4,7 +4,7 @@ game 'gta5'
lua54 'yes'
version '3.7.16'
version '3.7.22'
name 'qs-inventory'
author 'Quasar Store'
@@ -74,7 +74,8 @@ escrow_ignore {
'server/custom/webhook/*.lua',
'server/custom/misc/*.lua',
'client/modules/weapons.lua',
'server/modules/weapons.lua'
'server/modules/weapons.lua',
'client/modules/debug.lua'
}
dependencies {

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Some files were not shown because too many files have changed in this diff Show More