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

View File

@@ -0,0 +1,310 @@
if Config.Framework ~= 'esx' then
return
end
ESX = exports['es_extended']:getSharedObject()
function GetPlayerData()
return ESX.GetPlayerData()
end
function TriggerServerCallback(name, cb, ...)
ESX.TriggerServerCallback(name, cb, ...)
end
local playerLoaded = ESX.IsPlayerLoaded()
function IsPlayerLoaded()
return playerLoaded
end
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
PlayerData = xPlayer
LocalPlayer.state:set('inv_busy', false, true)
Wait(1250)
for k, data in pairs(Config.WeaponRepairPoints) do
Config.WeaponRepairPoints[k].IsRepairing = data.IsRepairing
Config.WeaponRepairPoints[k].RepairingData = data.RepairingData
end
if Config.Crafting then
CreateBlips()
end
Wait(5000)
playerLoaded = true
end)
RegisterNetEvent('esx:onPlayerLogout')
AddEventHandler('esx:onPlayerLogout', function()
PlayerData = {}
LocalPlayer.state:set('inv_busy', true, true)
RemoveAllNearbyDrops()
for k in pairs(Config.WeaponRepairPoints) do
Config.WeaponRepairPoints[k].IsRepairing = false
Config.WeaponRepairPoints[k].RepairingData = {}
end
TriggerServerEvent('inventory:handleLogout')
end)
RegisterNetEvent('esx:setJob', function()
PlayerData = GetPlayerData()
if Config.Crafting then
CreateBlips()
end
end)
AddEventHandler('esx_status:onTick', function(status)
TriggerEvent('esx_status:getStatus', 'hunger', function(status)
hunger = status.val / 10000
end)
TriggerEvent('esx_status:getStatus', 'thirst', function(status)
thirst = status.val / 10000
end)
end)
function GetPlayerIdentifier()
return GetPlayerData().identifier
end
function GetPlayersInArea()
local playerPed = PlayerPedId()
return ESX.Game.GetPlayersInArea(GetEntityCoords(playerPed), 3.0)
end
function GetJobName()
return GetPlayerData()?.job?.name
end
function GetJobGrade()
return GetPlayerData().job.grade
end
function GetGang()
return false
end
function GetGangLevel()
return false
end
function SendTextMessage(msg, type)
if GetResourceState('qs-interface') == 'started' then
if type == 'inform' then
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fa-solid fa-file')
elseif type == 'error' then
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
elseif type == 'success' then
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
end
return
end
if type == 'inform' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'inform'
})
elseif type == 'error' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'error'
})
elseif type == 'success' then
lib.notify({
title = 'Inventory',
description = msg,
type = 'success'
})
end
end
function ShowHelpNotification(msg)
AddTextEntry('helpNotification', msg)
BeginTextCommandDisplayHelp('helpNotification')
EndTextCommandDisplayHelp(0, true, true, -1)
end
local texts = {}
if GetResourceState('qs-textui') == 'started' then
function DrawText3D(x, y, z, text, id, key)
local _id = id
if not texts[_id] then
CreateThread(function()
texts[_id] = 5
while texts[_id] > 0 do
texts[_id] = texts[_id] - 1
Wait(0)
end
texts[_id] = nil
exports['qs-textui']:DeleteDrawText3D(id)
Debug('Deleted text', id)
end)
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
end
texts[_id] = 5
end
else
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
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)
local factor = text:len() / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
end
function DrawText3Ds(x, y, z, text)
SetTextScale(0.35, 0.35)
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)
local factor = string.len(text) / 370
DrawRect(0.0, 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
function ToggleHud(bool)
if bool then
Debug('Event to show the hud [client/custom/framework/esx.lua line 174]')
DisplayRadar(true) -- You can enable or disable mini-map here
if GetResourceState('qs-interface') == 'started' then
exports['qs-interface']:ToggleHud(true)
end
else
Debug('Event to hide the hud [client/custom/framework/esx.lua line 174]')
DisplayRadar(false) -- You can enable or disable mini-map here
if GetResourceState('qs-interface') == 'started' then
exports['qs-interface']:ToggleHud(false)
end
end
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if GetResourceState('qs-interface') == 'started' then
local success = exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
})
if success then
onFinish()
else
onCancel()
end
return
end
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
function ProgressBarSync(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop)
if GetResourceState('qs-interface') == 'started' then
return exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = animation,
prop = prop
})
end
return lib.progressBar({
duration = duration,
label = label,
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = animation,
prop = prop
})
end
function SetPlayerStatus(values)
for name, value in pairs(values) do
if value > 0 then
TriggerEvent('esx_status:add', name, value)
else
TriggerEvent('esx_status:remove', name, -value)
end
end
end
function DropMarker(coords)
DrawMarker(20, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.15, 120, 10, 20, 155, false, false, false, 1, false, false, false)
end
function CanUseInventory()
local ped = PlayerPedId()
local wasabiHas = GetResourceState('wasabi_ambulance') == 'started'
if wasabiHas and exports.wasabi_ambulance:isPlayerDead() then
return false
end
if LocalPlayer.state.isDead and LocalPlayer.state.isDead == 1 then
return false
end
if GetEntityHealth(ped) >= 1 then
return true
end
return false
end
function checkEntityDead(id, entity)
if Player(id).state.isDead then
return true
end
local check = false
if GetEntityHealth(entity) <= 1 then
check = true
end
return check
end
function reputationCrafing(rep)
--- @param rep Name of reputation
return 99999
end
RegisterNetEvent('qs-inventory:client:updateItem', function(item, data)
if not ItemList[item] then
return
end
ItemList[item] = data
end)

View File

@@ -0,0 +1,315 @@
if Config.Framework ~= 'qb' then
return
end
QBCore = exports['qb-core']:GetCoreObject()
if not Config.QBX then
WeaponList = QBCore.Shared.Weapons
ItemList = QBCore.Shared.Items
end
local playerLoaded = LocalPlayer.state['isLoggedIn']
function IsPlayerLoaded()
return playerLoaded
end
function GetPlayerData()
return QBCore.Functions.GetPlayerData()
end
function TriggerServerCallback(name, cb, ...)
QBCore.Functions.TriggerCallback(name, cb, ...)
end
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = GetPlayerData()
LocalPlayer.state:set('inv_busy', false, true)
Wait(1250)
for k, data in pairs(Config.WeaponRepairPoints) do
Config.WeaponRepairPoints[k].IsRepairing = data.IsRepairing
Config.WeaponRepairPoints[k].RepairingData = data.RepairingData
end
if Config.Crafting then
CreateBlips()
end
TriggerServerEvent(Config.InventoryPrefix .. ':server:OnLoadUpdateCash')
Wait(5000)
playerLoaded = true
end)
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
PlayerData = {}
LocalPlayer.state:set('inv_busy', true, true)
RemoveAllNearbyDrops()
for k in pairs(Config.WeaponRepairPoints) do
Config.WeaponRepairPoints[k].IsRepairing = false
Config.WeaponRepairPoints[k].RepairingData = {}
end
TriggerServerEvent('inventory:handleLogout')
end)
RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
PlayerData = val
if Config.Crafting then
CreateBlips()
end
end)
function GetPlayerIdentifier()
return GetPlayerData().citizenid
end
function GetPlayersInArea()
local playerPed = PlayerPedId()
return QBCore.Functions.GetPlayersFromCoords(GetEntityCoords(playerPed), 3.0)
end
function GetJobName()
return GetPlayerData()?.job?.name
end
function GetJobGrade()
return GetPlayerData().job.grade
end
function GetGang()
return false
end
function GetGangLevel()
return false
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)
AddTextEntry('helpNotification', msg)
BeginTextCommandDisplayHelp('helpNotification')
EndTextCommandDisplayHelp(0, true, true, -1)
end
local texts = {}
if GetResourceState('qs-textui') == 'started' then
function DrawText3D(x, y, z, text, id, key)
local _id = id
if not texts[_id] then
CreateThread(function()
texts[_id] = 5
while texts[_id] > 0 do
texts[_id] = texts[_id] - 1
Wait(0)
end
texts[_id] = nil
exports['qs-textui']:DeleteDrawText3D(id)
Debug('Deleted text', id)
end)
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
end
texts[_id] = 5
end
else
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
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)
local factor = text:len() / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
end
function DrawText3Ds(x, y, z, text)
SetTextScale(0.35, 0.35)
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)
local factor = string.len(text) / 370
DrawRect(0.0, 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
function ToggleHud(bool)
if bool then
Debug('Event to show the hud [client/custom/framework/esx.lua line 174]')
DisplayRadar(true) -- You can enable or disable mini-map here
if GetResourceState('qs-interface') == 'started' then
exports['qs-interface']:ToggleHud(true)
end
else
Debug('Event to hide the hud [client/custom/framework/esx.lua line 174]')
DisplayRadar(false) -- You can enable or disable mini-map here
if GetResourceState('qs-interface') == 'started' then
exports['qs-interface']:ToggleHud(false)
end
end
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if GetResourceState('qs-interface') == 'started' then
local success = exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
})
if success then
onFinish()
else
onCancel()
end
return
end
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flag
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end
function ProgressBarSync(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop)
if GetResourceState('qs-interface') == 'started' then
return exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = animation,
prop = prop
})
end
return lib.progressBar({
duration = duration,
label = label,
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = animation,
prop = prop
})
end
function DropMarker(coords)
DrawMarker(20, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.15, 120, 10, 20, 155, false, false, false, 1, false, false, false)
end
function SetPlayerStatus(values)
for name, value in pairs(values) do
-- compatibility for ESX style values
if value > 100 or value < -100 then
value = value * 0.0001
end
if name == 'hunger' then
TriggerServerEvent('inventory:consumables:addHunger', QBCore.Functions.GetPlayerData().metadata.hunger + value)
elseif name == 'thirst' then
TriggerServerEvent('inventory:consumables:addThirst', QBCore.Functions.GetPlayerData().metadata.thirst + value)
elseif name == 'stress' then
if value > 0 then
TriggerServerEvent('hud:server:GainStress', value)
else
value = math.abs(value)
TriggerServerEvent('hud:server:RelieveStress', value)
end
end
end
end
function CanUseInventory()
local check = false
local data = GetPlayerData()
if not data.metadata['isdead'] and not data.metadata['inlaststand'] and not data.metadata['ishandcuffed'] and not IsPauseMenuActive() then
check = true
end
return check
end
function checkEntityDead(id, entity)
local isDead = false
TriggerServerCallback(Config.InventoryPrefix .. ':server:checkDead', function(result)
isDead = result
end, id)
repeat Wait(250) until isDead ~= nil
return isDead
end
function reputationCrafing(rep)
local PlayerData = QBCore.Functions.GetPlayerData()
if not PlayerData then return 0 end
local reputation = PlayerData.metadata[rep] or 0
if reputation == nil then
reputation = 0
end
return reputation
end
RegisterNetEvent('QBCore:Client:OnSharedUpdate', function(type, item, data)
if type == 'Items' then
ItemList[item] = data
end
end)
RegisterNetEvent('QBCore:Client:OnSharedUpdateMultiple', function(type, data)
if type == 'Items' then
for k, v in pairs(data) do
ItemList[k] = v
end
end
end)

View File

@@ -0,0 +1,69 @@
RegisterNetEvent(Config.InventoryPrefix .. ':client:CraftItems', function(itemName, itemCosts, points, amount, toSlot, rep, time, chance)
local ped = PlayerPedId()
local itemData = ItemList[itemName:lower()]
local randomNum = math.random(1, 100)
SendNUIMessage({
action = 'close',
})
inInventory = false
if itemData['type'] == 'weapon' and tonumber(amount) > 1 then
return SendTextMessage(Lang('INVENTORY_NOTIFICATION_CRAFTING_WEAPONS'), 'error')
end
if chance then
Debug('Crafting started with a chance of ' .. randomNum .. '% and you had ' .. chance .. '%')
else
chance = 100
Debug('There is no chance option in your configuration or in this item, and the crafting chance is set to 100%')
end
isCrafting = true
time = time or 1000
ProgressBar('crafting_item', Lang('INVENTORY_PROGRESS_CRAFTING'), (time * amount), false, false, {
move = true,
car = true,
mouse = false,
combat = true,
}, {
animDict = 'mini@repair',
anim = 'fixing_a_player',
flags = 1,
}, {}, {}, function()
if randomNum <= chance then
Debug('Crafting successful with ' .. randomNum .. '% chance and you had ' .. chance .. '%')
itemData.count = tonumber(amount)
StopAnimTask(ped, 'mini@repair', 'fixing_a_player', 1.0)
else
Debug('Crafting failed with ' .. randomNum .. '% chance and you had ' .. chance .. '%')
StopAnimTask(ped, 'mini@repair', 'fixing_a_player', 1.0)
SendTextMessage(Lang('INVENTORY_NOTIFICATION_CRAFTING_FAILED'), 'inform')
Wait(550)
TaskPlayAnim(ped, 'gestures@m@standing@casual', 'gesture_damn', 8.0, -8.0, -1, 1, 0, false, false, false)
Wait(1250)
StopAnimTask(ped, 'gestures@m@standing@casual', 'gesture_damn', 1.0)
end
TriggerServerEvent(Config.InventoryPrefix .. ':server:CraftItems', itemName, itemCosts, points, amount, toSlot, rep, randomNum, chance)
isCrafting = false
end, function()
StopAnimTask(ped, 'mini@repair', 'fixing_a_player', 1.0)
isCrafting = false
end)
TriggerScreenblurFadeOut(300)
if Config.Clothing then DeletePedScreen() end
end)
-- RegisterCommand('tt', function(source, args)
-- ProgressBar('crafting_item', Lang('INVENTORY_PROGRESS_CRAFTING'), (1000), false, false, {
-- move = true,
-- car = true,
-- mouse = false,
-- combat = true,
-- }, {
-- animDict = 'mini@repair',
-- anim = 'fixing_a_player',
-- flags = 1,
-- }, {}, {}, function()
-- end, function()
-- end)
-- end, false)

View File

@@ -0,0 +1,10 @@
--[[
We recommend not modifying anything on this side, the Starter Items
are all in your server/custom/framework/esx.lua, it won't work in
qb-core since that framework has its native ones that do it automatically.
]]
AddEventHandler(Config.InventoryPrefix .. ':client:GiveStarterItems', function()
local id = PlayerId()
TriggerServerEvent(Config.InventoryPrefix .. ':server:GiveStarterItems', id)
end)

View File

@@ -0,0 +1,137 @@
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',
'crafting',
'attachment_crafting',
'traphouse',
'customcrafting'
}
RegisterNetEvent(Config.InventoryPrefix .. ':client:OpenInventory', function(PlayerAmmo, inventory, other, otherName)
if not inventory then return Error('Inventory is not working, clear the inventory column [sql] to continue.') end
inventory = FormatItemsToInfo(inventory)
ToggleHud(false)
ToggleHotbar(false)
SetFocus(true)
IdleCamera(true)
SetPedCanPlayAmbientAnims(PlayerPedId(), false)
SetResourceKvp('idleCam', 'off')
if other then
currentOtherInventory = other.name
end
OpenedInventoryCoords = GetEntityCoords(PlayerPedId())
TriggerServerCallback(Config.InventoryPrefix .. ':server:QualityDecay', function(data)
local hungerValue = hunger
local thirstValue = thirst
if Config.Framework == 'qb' then
local data = GetPlayerData()
hungerValue = data.metadata and data.metadata.hunger
thirstValue = data.metadata and data.metadata.thirst
end
local PlayerSlots = Config.InventoryWeight.slots
if not Config.BlockedSlot then
PlayerSlots = Config.InventoryWeight.slots - 1
end
inventory = data.inventory
inventory = SyncEquippedWeaponAmmoOnOpen(inventory)
other = data.other
data = GetPlayerData()
if Config.Framework == 'esx' then
firstName = data.firstName or ''
lastName = data.lastName or ''
for i = 1, #data.accounts do
if data.accounts[i].name == 'money' then
money = data.accounts[i].money or 'Not found'
elseif data.accounts[i].name == 'bank' then
bank = data.accounts[i].money or 'Not found'
elseif data.accounts[i].name == 'black_money' then
blackmoney = data.accounts[i].money or 'Not found'
end
end
elseif Config.Framework == 'qb' then
firstName = data.charinfo.firstname or ''
lastName = data.charinfo.lastname or ''
money = data.money.cash or 'Not found'
bank = data.money.bank or 'Not found'
blackmoney = data.money.crypto or 'Not found'
end
SendNUIMessage({
action = 'open',
inventory = inventory,
slots = PlayerSlots,
other = other,
maxweight = Config.InventoryWeight.weight,
Ammo = PlayerAmmo,
playerName = firstName .. ' ' .. lastName,
logo = Config.Logo,
openAnimation = Config.OpenInventoryScene,
optionClothes = Config.InventoryOptions.clothes,
optionConfiguration = Config.InventoryOptions.configuration,
optionHealth = Config.InventoryOptions.health,
optionArmor = Config.InventoryOptions.armor,
optionHunger = Config.InventoryOptions.hunger,
optionThirst = Config.InventoryOptions.thirst,
optionId = Config.InventoryOptions.id,
optionMoney = Config.InventoryOptions.money,
optionBank = Config.InventoryOptions.bank,
optionBlackMoney = Config.InventoryOptions.blackmoney,
playerhp = GetEntityHealth(PlayerPedId()),
playerarmor = GetPedArmour(PlayerPedId()),
playerhunger = hungerValue or 0,
playerthirst = thirstValue or 0,
playerId = GetPlayerServerId(PlayerId()),
playerMoney = money,
playerBank = bank,
playerBlackMoney = blackmoney,
notStolenItems = Config.notStolenItems,
notStoredItems = Config.notStoredItems,
labelChanger = Config.LabelChange
})
inInventory = true
if table.includes(checkDistanceInventories, otherName) then
CheckNearbyOtherInventory()
end
end, inventory, other)
if not Config.Handsup then return end
checkPlayerRobbery(other)
end)

View File

@@ -0,0 +1,48 @@
if not Config.UseTarget then
local nearby = false
CreateThread(function()
while true do
local sleep = 1000
if nearby then
DrawText3D(Config.SellItems[nearby].coords.x, Config.SellItems[nearby].coords.y, Config.SellItems[nearby].coords.z, Lang('INVENTORY_TEXT_SELLING'), 'selling', 'E')
sleep = 1
if IsControlJustPressed(0, 38) then
local PawnshopItems = {}
PawnshopItems.label = nearby
PawnshopItems.items = Config.SellItems[nearby].items
PawnshopItems.slots = #Config.SellItems[nearby].items
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'selling', 'itemselling_' .. nearby, PawnshopItems)
end
end
Wait(sleep)
end
end)
CreateThread(function()
for k, v in pairs(Config.SellItems) do
if v.blip and v.blip.active then
local ff = v.blip
local blip = AddBlipForCoord(v.coords)
SetBlipSprite(blip, ff.sprite)
SetBlipColour(blip, ff.color)
SetBlipScale(blip, ff.scale)
BeginTextCommandSetBlipName('STRING')
AddTextComponentString(ff.name)
EndTextCommandSetBlipName(blip)
SetBlipAsShortRange(blip, true)
end
end
end)
CreateThread(function()
while true do
local playercoords = GetEntityCoords(PlayerPedId())
local finded = false
for k, v in pairs(Config.SellItems) do
if #(playercoords - v.coords) <= 2 then finded = k end
end
nearby = finded
Wait(700)
end
end)
end

View File

@@ -0,0 +1,72 @@
RegisterNetEvent(Config.InventoryPrefix .. ':client:UseWeapon', function(weaponData, shootbool)
if FiringWeapon then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_STOP_FIRING'), 'error')
return false
end
local ped = PlayerPedId()
local weaponName = tostring(weaponData.name)
local weaponHash = joaat(weaponData.name)
for i = 1, #Config.WeaponTints do
if tostring(GetHashKey(weaponName)) == Config.WeaponTints[i].hash then
AddReplaceTexture(Config.WeaponTints[i].ytd, Config.WeaponTints[i].texture, Config.WeaponTints[i].ytd, Config.WeaponTints[i].texture)
break
end
end
if currentWeapon == weaponName then
TriggerEvent('weapons:client:DrawWeapon', nil)
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
RemoveAllPedWeapons(ped, true)
TriggerEvent('weapons:client:SetCurrentWeapon', nil, shootbool)
currentWeapon = nil
elseif weaponName == 'weapon_stickybomb' or weaponName == 'weapon_pipebomb' or weaponName == 'weapon_smokegrenade' or weaponName == 'weapon_flare' or weaponName == 'weapon_proxmine' or weaponName == 'weapon_ball' or weaponName == 'weapon_molotov' or weaponName == 'weapon_grenade' or weaponName == 'weapon_bzgas' then
TriggerEvent('weapons:client:DrawWeapon', weaponName)
GiveWeaponToPed(ped, weaponHash, 1, false, false)
SetPedAmmo(ped, weaponHash, 1)
SetCurrentPedWeapon(ped, weaponHash, true)
TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool)
TriggerServerEvent(Config.InventoryPrefix .. ':server:RemoveItem', weaponName, 1)
currentWeapon = weaponName
elseif weaponName == 'weapon_snowball' then
TriggerEvent('weapons:client:DrawWeapon', weaponName)
GiveWeaponToPed(ped, weaponHash, 10, false, false)
SetPedAmmo(ped, weaponHash, 10)
SetCurrentPedWeapon(ped, weaponHash, true)
TriggerServerEvent(Config.InventoryPrefix .. ':server:snowball', 'remove')
TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool)
currentWeapon = weaponName
elseif weaponName == 'weapon_petrolcan' then
GiveWeaponToPed(ped, weaponHash, 10, false, false)
SetPedAmmo(ped, weaponHash, weaponData.info.ammo or 4500)
SetCurrentPedWeapon(ped, weaponHash, true)
TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool)
currentWeapon = weaponName
else
TriggerEvent('weapons:client:DrawWeapon', weaponName)
TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool)
local ammo = tonumber(weaponData.info.ammo) or 0
if weaponName == 'weapon_petrolcan' or weaponName == 'weapon_fireextinguisher' then
ammo = 4000
end
GiveWeaponToPed(ped, weaponHash, ammo, false, false)
SetPedAmmo(ped, weaponHash, ammo)
SetCurrentPedWeapon(ped, weaponHash, true)
if weaponData.info.attachments then
for _, attachment in pairs(weaponData.info.attachments) do
if attachment.tint then
if attachment.urltint ~= 'none' then
ChangeWeaponTintWithUrl(weaponHash, attachment.urltint)
else
SetPedWeaponTintIndex(ped, weaponHash, attachment.tint)
end
else
GiveWeaponComponentToPed(ped, weaponHash, joaat(attachment.component))
end
end
end
currentWeapon = weaponName
end
end)

View File

@@ -0,0 +1,175 @@
local isAdminGiveItemOpen = false
local currentPlayers = {}
local currentItems = {}
local selectedPlayer = nil
local selectedItem = nil
-- Open the admin giveitem interface
RegisterNetEvent('inventory:admin:openGiveItemInterface', function()
Debug('Opening admin interface...')
if isAdminGiveItemOpen then
return
end
isAdminGiveItemOpen = true
SetNuiFocus(true, true)
-- Get initial data
GetOnlinePlayers()
GetAllItems()
-- Open the UI
SendNUIMessage({
action = 'openAdminGiveItem',
data = {
title = 'Admin Give Item System',
subtitle = 'Player item giving system'
}
})
end)
-- Get online players
function GetOnlinePlayers()
lib.callback('inventory:admin:getOnlinePlayers', false, function(players)
currentPlayers = players
SendNUIMessage({
action = 'updatePlayers',
data = players
})
end)
end
-- Get all items
function GetAllItems()
local items = {}
for itemName, itemData in pairs(ItemList) do
table.insert(items, {
name = itemName,
label = itemData.label,
type = itemData.type,
weight = itemData.weight,
unique = itemData.unique or false,
image = itemData.image or 'default.png'
})
end
-- Sort items alphabetically
table.sort(items, function(a, b)
return a.label < b.label
end)
SendNUIMessage({
action = 'updateItems',
data = items
})
end
-- Search players
function SearchPlayers(searchTerm)
lib.callback('inventory:admin:searchPlayers', false, function(players)
currentPlayers = players
SendNUIMessage({
action = 'updatePlayers',
data = players
})
end, searchTerm)
end
-- Search items
function SearchItems(searchTerm)
local items = {}
local searchLower = string.lower(searchTerm or '')
for itemName, itemData in pairs(ItemList) do
local itemLabelLower = string.lower(itemData.label)
local itemNameLower = string.lower(itemName)
if searchLower == '' or
string.find(itemLabelLower, searchLower, 1, true) or
string.find(itemNameLower, searchLower, 1, true) then
table.insert(items, {
name = itemName,
label = itemData.label,
type = itemData.type,
weight = itemData.weight,
unique = itemData.unique or false,
image = itemData.image or 'default.png'
})
end
end
-- Sort items alphabetically
table.sort(items, function(a, b)
return a.label < b.label
end)
SendNUIMessage({
action = 'updateItems',
data = items
})
end
function GiveItemToPlayer(targetId, itemName, amount, metadata)
lib.callback('inventory:admin:giveItem', false, function(success, message)
if success then
SendTextMessage(message, 'success')
CloseAdminGiveItemInterface()
else
SendTextMessage(message, 'error')
end
end, targetId, itemName, amount, metadata)
end
-- Close admin giveitem interface
function CloseAdminGiveItemInterface()
Debug('Closing admin interface...')
isAdminGiveItemOpen = false
SetNuiFocus(false, false)
SendNUIMessage({
action = 'closeAdminGiveItem'
})
end
-- NUI Callbacks
RegisterNUICallback('closeAdminGiveItem', function(data, cb)
CloseAdminGiveItemInterface()
cb('ok')
end)
RegisterNUICallback('searchPlayers', function(data, cb)
SearchPlayers(data.searchTerm)
cb('ok')
end)
RegisterNUICallback('searchItems', function(data, cb)
SearchItems(data.searchTerm)
cb('ok')
end)
RegisterNUICallback('selectPlayer', function(data, cb)
selectedPlayer = data.player
SendNUIMessage({
action = 'updateSelectedPlayer',
data = data.player
})
cb('ok')
end)
RegisterNUICallback('selectItem', function(data, cb)
selectedItem = data.item
SendNUIMessage({
action = 'updateSelectedItem',
data = data.item
})
cb('ok')
end)
RegisterNUICallback('giveItem', function(data, cb)
local player = data.player
local item = data.item
local amount = tonumber(data.amount) or 1
local metadata = data.metadata or ''
GiveItemToPlayer(player.id, item.name, amount, metadata)
cb('ok')
end)

View File

@@ -0,0 +1,208 @@
RegisterNetEvent(Config.InventoryPrefix .. ':client:openVending')
AddEventHandler(Config.InventoryPrefix .. ':client:openVending', function(Data)
local Category = Data['category']
TriggerServerEvent('inventory:openVending', Category)
end)
local spamCount = 0
local lastSpamId = nil
local inventory_opening_anim = {
-- dict = 'mp_player_inteat@burger',
-- clip = 'mp_player_int_eat_burger_fp'
}
local inventory_opening_disable = {
move = true,
car = true,
mouse = true,
combat = true
}
local openingInv = false
RegisterCommand('inventory', function()
if inInventory then
return Debug('Inventory is already open')
end
if Config.OpenProgressBar and openingInv then return end
if IsNuiFocused() then return Debug('NUI Focused') end
if spamCount > 2 then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_SPAM'), 'error')
return
end
spamCount = spamCount + 1
lastSpamId = math.random(1, 999999)
local spamId = lastSpamId
SetTimeout(1000, function()
if spamId == lastSpamId then
spamCount = 0
end
end)
if LocalPlayer.state.inv_busy or not CanUseInventory() then
Warning("You can't use this action because inv_busy is active (avoids dupes)")
return SendTextMessage(Lang('INVENTORY_NOTIFICATION_NOT_ACCESSIBLE'), 'error')
end
if Config.OpenProgressBar then
openingInv = true
local success = ProgressBarSync('inventory', 'Inventory opening', 800, true, true, inventory_opening_disable, inventory_opening_anim)
openingInv = false
if not success then
print('failed')
return
end
end
if inInventory and not IsNuiFocused() then
SetFocus(true)
return
end
if not isCrafting and not inInventory and not inventoryDisabled then
if not IsPauseMenuActive() then
local ped = PlayerPedId()
local curVeh = nil
local VendingMachine = nil
local garbage = nil
local CurrentGarbage = {}
local entity, entityModel, data = GetNearbyGarbage()
if entity then
local x, y, z = table.unpack(GetEntityCoords(entity))
local _, floorZ = GetGroundZFor_3dCoord(x, y, z, false)
garbage = getOwnerFromCoordsForGarbage(vector3(x, y, floorZ))
CurrentGarbage.label = data.label
CurrentGarbage.items = data.items
CurrentGarbage.slots = data.slots
end
if not Config.UseTarget then
VendingMachine = GetClosestVending()
end
if IsPedInAnyVehicle(ped, false) then -- Is Player In Vehicle
local vehicle = GetVehiclePedIsIn(ped, false)
CurrentGlovebox = Trim(GetVehicleNumberPlateText(vehicle))
curVeh = vehicle
CurrentVehicle = nil
else
local vehicle = getClosestVehicle()
if vehicle ~= 0 and vehicle ~= nil then
local pos = GetEntityCoords(ped)
local dimensionMin, dimensionMax = GetModelDimensions(GetEntityModel(vehicle))
local trunkpos = GetOffsetFromEntityInWorldCoords(vehicle, 0.0, (dimensionMin.y), 0.0)
if (IsBackEngine(GetEntityModel(vehicle))) then
trunkpos = GetOffsetFromEntityInWorldCoords(vehicle, 0.0, (dimensionMax.y), 0.0)
end
if #(pos - trunkpos) < 1.5 and not IsPedInAnyVehicle(ped) then
if GetVehicleDoorLockStatus(vehicle) < 2 then
CurrentVehicle = Trim(GetVehicleNumberPlateText(vehicle))
curVeh = vehicle
CurrentGlovebox = nil
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_VEHICLE_LOCKED'), 'error')
return
end
else
CurrentVehicle = nil
end
else
CurrentVehicle = nil
end
end
if CurrentVehicle then -- Trunk
local vehicleClass = GetVehicleClass(curVeh)
Debug('Current vehicleClass of the vehicle that is being unlocked:', vehicleClass)
local maxweight = Config.VehicleClass[vehicleClass].trunk.maxweight or 60000
local slots = Config.VehicleClass[vehicleClass].trunk.slots or 35
local isCustomVehicle = Config.CustomTrunk[GetEntityModel(curVeh)]
if isCustomVehicle then
maxweight = isCustomVehicle.maxweight
slots = isCustomVehicle.slots
end
local other = {
maxweight = maxweight,
slots = slots,
}
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'trunk', CurrentVehicle, other)
OpenTrunk()
elseif CurrentGlovebox then
local vehicleClass = GetVehicleClass(curVeh)
Debug('Current vehicleClass of the vehicle that is being unlocked:', vehicleClass)
local maxweight = Config.VehicleClass[vehicleClass].glovebox.maxweight or 60000
local slots = Config.VehicleClass[vehicleClass].glovebox.slots or 35
local isCustomVehicle = Config.CustomGlovebox[GetEntityModel(curVeh)]
if isCustomVehicle then
maxweight = isCustomVehicle.maxweight
slots = isCustomVehicle.slots
end
local other = {
maxweight = maxweight,
slots = slots
}
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'glovebox', CurrentGlovebox, other)
elseif CurrentDrop ~= 0 then
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'drop', CurrentDrop)
elseif garbage then
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'garbage', garbage, CurrentGarbage, entityModel)
OpenGarbage()
elseif VendingMachine then
local vendingCategory = nil
local vendingModel = GetEntityModel(VendingMachine)
for _, vendingData in pairs(Config.Vendings) do
local vendingDataModel = GetHashKey(vendingData.Model)
if vendingDataModel == vendingModel then
vendingCategory = vendingData.Category
break
end
end
if vendingCategory then
TriggerEvent(Config.InventoryPrefix .. ':client:openVending', { category = vendingCategory })
end
else
OpenAnim()
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory')
end
end
end
end, false)
RegisterKeyMapping('inventory', Lang('INVENTORY_KEYMAPPING_OPEN_LABEL'), 'keyboard', Config.KeyBinds.inventory)
RegisterNetEvent(Config.InventoryPrefix .. ':client:OpenPlayerInventory')
AddEventHandler(Config.InventoryPrefix .. ':client:OpenPlayerInventory', function()
ExecuteCommand('inventory')
end)
RegisterCommand('hotbar', function()
if inventoryDisabled then return end
if IsNuiFocused() then return end
if LocalPlayer.state.inv_busy or not CanUseInventory() then
Warning("You can't use this action because inv_busy is active (avoids dupes)")
return
end
isHotbar = not isHotbar
if not IsPauseMenuActive() then
ToggleHotbar(isHotbar)
end
end, false)
RegisterKeyMapping('hotbar', Lang('INVENTORY_KEYMAPPING_HOTBAR_LABEL'), 'keyboard', Config.KeyBinds.hotbar)
RegisterKeyMapping('reloadweapon', Lang('INVENTORY_KEYMAPPING_RELOAD_LABEL'), 'keyboard', Config.KeyBinds.reload)
RegisterCommand('reloadweapon', function()
if not CurrentWeaponData?.name then return end
local weaponData = WeaponList[joaat(CurrentWeaponData?.name)]
if not weaponData then return end
if LocalPlayer.state.inv_busy or not CanUseInventory() then
Debug("You can't use this action because inv_busy is active (avoids dupes)")
return SendTextMessage(Lang('INVENTORY_NOTIFICATION_NOT_ACCESSIBLE'), 'error')
end
TriggerServerEvent('weapons:reloadWeapon', weaponData.ammotype)
end, false)

View File

@@ -0,0 +1,41 @@
local color = {} --[[@as Color]]
---@param data Color
RegisterNUICallback('updateColors', function(data, cb)
color.primaryColor = data.primaryColor or color.primaryColor
color.primaryOpacity = data.primaryOpacity or color.primaryOpacity
color.secondaryColor = data.secondaryColor or color.secondaryColor
color.secondaryOpacity = data.secondaryOpacity or color.secondaryOpacity
color.borderColor = data.borderColor or color.borderColor
color.borderOpacity = data.borderOpacity or color.borderOpacity
color.borderRadius = data.borderRadius or color.borderRadius
LocalPlayer.state:set('primaryColor', color.primaryColor, true)
LocalPlayer.state:set('primaryOpacity', color.primaryOpacity, true)
TriggerEvent('inventory:updateColors', color)
cb(true)
end)
exports('getColors', function()
return color
end)
local function handleThemeChange()
local handler
handler = AddEventHandler('inventory:updateColors', function()
if not IsPlayerLoaded() then
Debug('handleThemeChange', 'Player not loaded, skipping color update')
return
end
Debug('handleThemeChange', 'Theme color updated successfully')
RemoveEventHandler(handler)
handler = nil
end)
end
handleThemeChange()
TriggerEvent('inventory:updateColors')

View File

@@ -0,0 +1,41 @@
if not GetResourceState('jobs_creator') == 'missing' then
return
end
Warning('Started the compatibility module with jobs_creator')
CreateThread(function()
local other = {}
other.maxweight = 100000 -- Custom weight stash.
other.slots = 50 -- Custom slots spaces.
RegisterNetEvent('jobs_creator:stash:openStash', function(markerId)
local stashId = 'job_stash_' .. markerId
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'stash', stashId, other)
TriggerEvent(Config.InventoryPrefix .. ':client:SetCurrentStash', stashId)
end)
RegisterNetEvent('jobs_creator:safe:openSafe', function(markerId)
local safeId = 'job_safe_' .. markerId
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'stash', safeId, other)
TriggerEvent(Config.InventoryPrefix .. ':client:SetCurrentStash', safeId)
end)
RegisterNetEvent('jobs_creator:armory:openArmory', function(markerId)
local armoryId = 'job_armory_' .. markerId
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'stash', armoryId, other)
TriggerEvent(Config.InventoryPrefix .. ':client:SetCurrentStash', armoryId)
end)
RegisterNetEvent('jobs_creator:framework:ready', function()
-- Disables the default script search (otherwise there would be 2 searches)
exports['jobs_creator']:disableScriptEvent('jobs_creator:actions:search:searchPlayer')
end)
RegisterNetEvent('jobs_creator:actions:search:searchPlayer', function(targetServerId)
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'otherplayer', targetServerId)
end)
end)

View File

@@ -0,0 +1,10 @@
function JonskaItemThrow(item)
local data = {
name = item.name, -- needed for adding and removing item
label = item.label, -- MUST HAVE!
amount = item.amount, -- needed for adding and removing item
info = item.info, -- needed for adding item
created = item.created or 0 -- needed for adding item (if your inventory have decay system)
}
return exports['jonska-itemthrowing']:throwItem(data, item.name, item.amount)
end

View File

@@ -0,0 +1,190 @@
if not Config.Handsup then
return
end
local lib, anim = 'missminuteman_1ig_2', 'handsup_base'
local canHandsUp = true
local deadPlayer = false
local function LoadAnimDict(dict)
if HasAnimDictLoaded(dict) then return end
RequestAnimDict(dict)
while not HasAnimDictLoaded(dict) do
Wait(10)
end
end
RegisterKeyMapping('handsup', Lang('INVENTORY_KEYMAPPING_HANDSUP_LABEL'), 'keyboard', Config.KeyBinds.handsup)
RegisterCommand('handsup', function()
if not IsPedInAnyVehicle(PlayerPedId(), false) and GetEntityHealth(PlayerPedId()) > 1 then
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)
RegisterNetEvent(Config.InventoryPrefix .. ':client:RobPlayer')
AddEventHandler(Config.InventoryPrefix .. ':client:RobPlayer', function(TargetId)
local ped = PlayerPedId()
if IsPedArmed(ped, 1) or IsPedArmed(ped, 2) or IsPedArmed(ped, 4) or deadPlayer or Config.StealWithoutWeapons then
SendNUIMessage({
action = 'RobPlayer',
TargetId = TargetId,
})
end
deadPlayer = false
end)
local function checkPlayerIsNear(targetPlayer)
CreateThread(function()
while true do
Wait(100)
local targetPed = GetPlayerPed(targetPlayer)
if not DoesEntityExist(targetPed) or NetworkIsPlayerActive(targetPlayer) == false then
TriggerEvent(Config.InventoryPrefix .. ':client:closeinv')
SendTextMessage(Lang('INVENTORY_NOTIFICATION_ROBBERY_AWAY'), 'inform')
break
end
local playerCoords = GetEntityCoords(PlayerPedId())
local targetCoords = GetEntityCoords(targetPed)
local distance = #(playerCoords - targetCoords)
if distance > 5 then
Wait(500)
TriggerEvent(Config.InventoryPrefix .. ':client:closeinv')
SendTextMessage(Lang('INVENTORY_NOTIFICATION_ROBBERY_AWAY'), 'inform')
break
end
end
end)
end
RegisterNetEvent(Config.InventoryPrefix .. ':client:search', function()
local player, distance = GetClosestPlayer(GetEntityCoords(PlayerPedId()))
if player ~= -1 and distance < 2.5 then
local playerId = GetPlayerServerId(player)
local searchPlayerPed = GetPlayerPed(player)
if IsEntityPlayingAnim(searchPlayerPed, 'missminuteman_1ig_2', 'handsup_base', 3) or Config.StealDeadPlayer and checkEntityDead(playerId, searchPlayerPed) or GetEntityHealth(searchPlayerPed) <= 0 then
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'otherplayer', playerId)
checkPlayerIsNear(player)
inRobbery = true
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_HANDSUP'), 'error')
end
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_PLAYERS'), 'error')
end
end)
RegisterNetEvent(Config.InventoryPrefix .. ':client:playerRobbery')
AddEventHandler(Config.InventoryPrefix .. ':client:playerRobbery', function()
local player, distance = GetClosestPlayer(GetEntityCoords(PlayerPedId()))
if player ~= -1 and distance < 3.0 then
local searchPlayerPed = GetPlayerPed(player)
local playerId = GetPlayerServerId(player)
TriggerEvent(Config.InventoryPrefix .. ':client:forceCloseInventory')
Wait(500)
if checkEntityDead(playerId, searchPlayerPed) then
RequestAnimDict('amb@world_human_gardener_plant@male@base')
while not HasAnimDictLoaded('amb@world_human_gardener_plant@male@base') do
Wait(100)
end
TaskPlayAnim(PlayerPedId(), 'amb@world_human_gardener_plant@male@base', 'base', 8.0, -8, -1, 1, 0, 0, 0, 0)
ProgressBar('steal_playerdead', Lang('INVENTORY_PROGRESS_STEAL'), 5500, false, true, {
move = true,
car = true,
mouse = false,
combat = true,
}, {}, {}, {}, function() -- Done
TaskPlayAnim(PlayerPedId(), 'amb@world_human_gardener_plant@male@base', 'base', 8.0, -8, -1, 1, 0, 0, 0, 0)
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'otherplayer', playerId)
checkPlayerIsNear(player)
inRobbery = true
end, function() -- Cancel
ClearPedTasks(PlayerPedId())
end)
return
end
if DoesEntityExist(searchPlayerPed) and IsEntityPlayingAnim(searchPlayerPed, lib, anim, 3) and not checkEntityDead(playerId, searchPlayerPed) then
LoadAnimDict('combat@aim_variations@arrest')
TaskPlayAnim(PlayerPedId(), 'combat@aim_variations@arrest', 'cop_med_arrest_01', 8.0, -8, -1, 1, 0, 0, 0, 0)
ProgressBar('steal_player', Lang('INVENTORY_PROGRESS_STEAL'), 5500, false, true, {
move = true,
car = true,
mouse = false,
combat = true,
}, {}, {}, {}, function() -- Done
TaskPlayAnim(PlayerPedId(), 'combat@aim_variations@arrest', 'cop_med_arrest_01', 8.0, -8, -1, 1, 0, 0, 0, 0)
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'otherplayer', playerId)
SetPedConfigFlag(PlayerPedId(), 36, true)
checkPlayerIsNear(player)
inRobbery = true
end, function() -- Cancel
ClearPedTasks(PlayerPedId())
end)
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_HANDSUP'), 'error')
end
end
end)
function checkPlayerRobbery(other)
if other and other.id then
local target = tonumber(other.id)
local playerTarget = GetPlayerFromServerId(target)
local pedTarget = GetPlayerPed(playerTarget)
if other ~= nil then
currentOtherInventory = other.name
end
if target and DoesEntityExist(pedTarget) then
local pos = GetEntityCoords(playerPed)
local targetPos = GetEntityCoords(pedTarget)
local distance = GetDistanceBetweenCoords(pos.x, pos.y, pos.z, targetPos.x, targetPos.y, targetPos.z, true)
if distance < 3.0 then
inInventory = true
deadPlayer = true
StealingPed = pedTarget
TriggerEvent(Config.InventoryPrefix .. ':client:RobPlayer', target)
end
end
else
local closestPlayer, closestDistance = GetClosestPlayer(GetEntityCoords(PlayerPedId()))
if closestPlayer and closestPlayer ~= -1 and closestDistance < 3.0 then
local playerId = GetPlayerServerId(closestPlayer)
local searchPlayerPed = GetPlayerPed(closestPlayer)
if searchPlayerPed and searchPlayerPed ~= 0 then
if Config.StealDeadPlayer and checkEntityDead(playerId, searchPlayerPed) then
inInventory = true
deadPlayer = true
StealingPed = searchPlayerPed
TriggerEvent(Config.InventoryPrefix .. ':client:RobPlayer', playerId)
end
if IsEntityPlayingAnim(searchPlayerPed, lib, anim, 3) then
inInventory = true
deadPlayer = false
StealingPed = searchPlayerPed
TriggerEvent(Config.InventoryPrefix .. ':client:RobPlayer', playerId)
end
end
end
end
end
RegisterNetEvent('inventory:robClosestPlayer', function()
checkPlayerRobbery()
end)

View File

@@ -0,0 +1,7 @@
local function exportHandler(exportName, func)
AddEventHandler(('__cfx_export_qb-inventory_%s'):format(exportName), function(setCB)
setCB(func)
end)
end
exportHandler('HasItem', HasItem)

View File

@@ -0,0 +1,122 @@
if not Config.UseTarget then
return
end
local target_name = GetResourceState('ox_target'):find('started') and 'qtarget' or 'qb-target'
CreateThread(function()
-- Selling
for k, v in pairs(Config.SellItems) do
exports[target_name]:AddBoxZone(k .. '_selling', vec3(v['coords'].x, v['coords'].y, v['coords'].z), 1.5, 1.5, {
name = k .. '_selling',
heading = 90.0,
debugPoly = Config.ZoneDebug,
minZ = v['coords'].z - 1,
maxZ = v['coords'].z + 1,
}, {
options = {
{
type = 'client',
icon = 'fa-solid fa-cash-register',
label = Lang('INVENTORY_TEXT_SELLING'),
canInteract = function(entity, distance, data)
return true
end,
action = function(entity)
local PawnshopItems = {}
PawnshopItems.label = k
PawnshopItems.items = v['items']
PawnshopItems.slots = #v['items']
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'selling', 'itemselling_' .. k, PawnshopItems)
end,
},
},
distance = 2.5
})
end
-- Crafting
if Config.Crafting then
for k, v in pairs(Config.CraftingTables) do
exports[target_name]:AddBoxZone(k .. '_crafting', vec3(v.location.x, v.location.y, v.location.z), 2.5, 2.5, {
name = k .. '_crafting',
heading = 90.0,
debugPoly = Config.ZoneDebug,
minZ = v.location.z - 1,
maxZ = v.location.z + 1,
}, {
options = {
{
type = 'client',
icon = 'fa-solid fa-hammer',
label = 'Crafting',
canInteract = function(entity, distance, data)
return true
end,
action = function(entity)
if isCrafting then return end
if v.isjob then
if IsPlayerAuthorized(v) then
CurrentCrafting = k
local crafting = {
label = v.name,
items = GeneralInfos(k)
}
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'crafting', math.random(1, 99), crafting)
end
else
CurrentCrafting = k
local crafting = {
label = v.name,
items = GeneralInfos(k)
}
TriggerServerEvent(Config.InventoryPrefix .. ':server:OpenInventory', 'crafting', math.random(1, 99), crafting)
end
end,
},
},
distance = 2.5
})
end
end
-- Vending shops
if Config.Vendings then
for k, v in pairs(Config.Vendings) do
exports[target_name]:AddTargetModel(v['Model'], {
options = {
{
icon = 'fa-solid fa-cash-register',
label = 'Vending',
action = function()
TriggerEvent(Config.InventoryPrefix .. ':client:openVending', { category = v['Category'] })
end
},
},
distance = 2.5
})
end
end
-- Gargabe Code
exports[target_name]:AddTargetModel(Config.GarbageObjects, {
options = {
{
icon = 'fa-solid fa-trash',
label = 'Open Garbage',
action = function()
ExecuteCommand('inventory')
end
},
},
distance = 1.0
})
end)
function AddTargetEntity(entity, options, distance)
distance = distance or 5.0
exports[target_name]:AddTargetEntity(entity, {
options = options,
distance = distance
})
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

@@ -0,0 +1,37 @@
TriggerEvent('chat:addSuggestion', '/giveitem', 'Administrative command to give items to another player', {
{ name = 'id', help = 'Id of the player to whom the item will be delivered' },
{ name = 'item', help = 'Name of the item to deliver' },
{ name = 'amount', help = 'Quantity of the item, if it is a weapon it will be ammo' },
})
TriggerEvent('chat:addSuggestion', '/giveweapon', 'Administrative command to give weapons to another player', {
{ name = 'id', help = 'Id of the player to whom the weapon will be delivered' },
{ name = 'weapon', help = 'Name of the weapon to deliver' },
{ name = 'ammo', help = 'Amount of ammo for the weapon' },
})
TriggerEvent('chat:addSuggestion', '/resetinv', 'Administrative command to reset an inventory, it will not delete it', {
{ name = 'type', help = 'Type of inventory to reset, example: [stash], [trunk], [glovebox]' },
})
TriggerEvent('chat:addSuggestion', '/clearinv', 'Administrative command to remove all items of a certain player', {
{ name = 'id', help = 'Enter the id of the player whose inventory you want to empty' },
})
TriggerEvent('chat:addSuggestion', '/repairweapon', 'Administrative command to repair certain players weapons', {
{ name = 'id', help = 'Select the id of the player to repair his weapon' },
})
TriggerEvent('chat:addSuggestion', '/openinventorytarget', 'Administrative command to check the inventory of a target player', {
{ name = 'id', help = 'Select player id' },
})
TriggerEvent('chat:addSuggestion', '/inventory', 'Command to open the inventory, useful for keybinds', {})
TriggerEvent('chat:addSuggestion', '/hotbar', 'Command to open the hotbar inventory, useful for keybinds', {})
TriggerEvent('chat:addSuggestion', '/handsup', 'Command to raise your arms, useful for keybinds, if you have your arms raised they can steal you', {})
TriggerEvent('chat:addSuggestion', '/reloadweapon', 'Command to reload your weapon, useful for keybinds', {})
TriggerEvent('chat:addSuggestion', '/randomitems', 'Administrative command that delivers various random items to your inventory, helps with debugging', {})
TriggerEvent('chat:addSuggestion', '/searchplayer', 'Command to steal from a nearby player, although we recommend doing it with the NUI raising his hands', {})
TriggerEvent('chat:addSuggestion', '/rob', 'Exclusive qb command to steal players, used for police job frequently', {})
TriggerEvent('chat:addSuggestion', '/invitems', 'Example of code used for getInventory, it will return all the items in your inventory', {})
TriggerEvent('chat:addSuggestion', '/dataitem', 'Example command to give an item with customizable and automatic metadata', {})

View File

@@ -0,0 +1,426 @@
local PlayerData = GetPlayerData()
local CanShoot, MultiplierAmount = true, 0
CurrentWeaponData = {}
local weaponTrackingActive = false
exports('GetCurrentWeapon', function()
return CurrentWeaponData
end)
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)
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
local playerVeh = GetVehiclePedIsIn(playerPed, false)
TriggerEvent('weapons:ResetHolster')
SetCurrentPedWeapon(playerPed, GetHashKey('WEAPON_UNARMED'), true)
RemoveAllPedWeapons(playerPed, true)
currentWeapon = nil
end
end
end)
RegisterNetEvent('weapons:client:SyncRepairShops', function(NewData, key)
Config.WeaponRepairPoints[key].IsRepairing = NewData.IsRepairing
Config.WeaponRepairPoints[key].RepairingData = NewData.RepairingData
end)
FiringWeapon = false
CreateThread(function()
while true do
local ped = PlayerPedId()
if IsPedArmed(ped, 7) == 1 and not inInventory then
if IsControlJustPressed(0, 24) or IsDisabledControlJustPressed(0, 24) then
FiringWeapon = true
elseif IsControlJustReleased(0, 24) or IsDisabledControlJustReleased(0, 24) and not inInventory then
FiringWeapon = false
end
end
Wait(0)
end
end)
CreateThread(function()
while true do
local ped = PlayerPedId()
local weapon = GetSelectedPedWeapon(ped)
if WeaponList[weapon] and WeaponList[weapon]['name'] == 'weapon_unarmed' and FiringWeapon then
FiringWeapon = false
end
Wait(500)
end
end)
---@return AttachmentItem?
local function componentIsTint(component)
local tints = GetConfigTints()
local attachment = table.find(tints, function(tint)
return tint.attachment == component
end)
return attachment
end
RegisterNetEvent('addAttachment', function(component, urltint)
local ped = PlayerPedId()
local weapon = GetSelectedPedWeapon(ped)
local WeaponData = WeaponList[weapon]
local tintData = componentIsTint(component)
if tintData then
if tintData.isUrlTint then
for i = 1, #Config.WeaponTints do
if tostring(weapon) == Config.WeaponTints[i].hash then
local txd = CreateRuntimeTxd(Config.WeaponTints[i].name)
local duiObj = CreateDui(urltint, 250, 250)
local dui = GetDuiHandle(duiObj)
CreateRuntimeTextureFromDuiHandle(txd, 'skin', dui)
while not IsDuiAvailable(duiObj) do Wait(150) end
AddReplaceTexture(Config.WeaponTints[i].ytd, Config.WeaponTints[i].texture, Config.WeaponTints[i].name, 'skin')
break
end
end
else
SetPedWeaponTintIndex(ped, weapon, tintData.tint)
end
return
end
GiveWeaponComponentToPed(ped, GetHashKey(WeaponData.name), GetHashKey(component))
end)
RegisterNetEvent('weapons:client:SetCurrentWeapon', function(data, bool)
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
end)
RegisterNetEvent('weapons:client:SetWeaponQuality', function(amount)
if CurrentWeaponData and next(CurrentWeaponData) then
TriggerServerEvent('weapons:server:SetWeaponQuality', CurrentWeaponData, amount)
TriggerEvent('weapons:client:SetCurrentWeapon', CurrentWeaponData, true)
end
end)
RegisterNetEvent('weapons:client:masterAmmo', function(amount, itemData)
local ped = PlayerPedId()
local weapon = GetSelectedPedWeapon(ped)
if CurrentWeaponData and WeaponList[weapon] and WeaponList[weapon]['name'] ~= 'weapon_unarmed' then
local weaponAmmoType = WeaponList[weapon]['ammotype']
if not weaponAmmoType then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_AMMO'), 'error')
return
end
TriggerEvent('weapons:client:AddAmmo', weaponAmmoType, amount, itemData, true)
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_WEAPON'), 'error')
end
end)
lib.callback.register('weapons:addAmmo', function(itemData)
local ped = cache.ped
if IsPedReloading(ped) then
return
end
local weapon = GetSelectedPedWeapon(ped)
if not CurrentWeaponData or not WeaponList[weapon] or WeaponList[weapon]['name'] == 'weapon_unarmed' then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_WEAPON'), 'error')
return
end
local total = GetAmmoInPedWeapon(ped, weapon)
local retval = GetMaxAmmoInClip(ped, weapon, 1)
local _, ammoclip = GetAmmoInClip(ped, weapon)
local _, maxammo = GetMaxAmmo(ped, weapon)
if IsPedInAnyVehicle(ped, false) and Config.ForceToOnlyOneMagazine then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_VEHICLE_ITEMS'), 'error')
return
end
if Config.ForceToOnlyOneMagazine and total > 0 then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_MAGAZINE_LIMIT'), 'error')
return
end
if not retval then
return
end
retval = tonumber(retval)
if maxammo ~= total then
TriggerServerCallback('weapon:server:GetWeaponAmmo', function(ammo)
if ammo then
SetAmmoInClip(ped, weapon, 0)
AddAmmoToPed(ped, weapon, retval + ammoclip)
TriggerServerEvent('weapons:server:AddWeaponAmmo', CurrentWeaponData, total + retval)
--TriggerServerEvent("weapons:server:UpdateWeaponAmmo", CurrentWeaponData, total + retval)
TriggerServerEvent('weapons:server:removeWeaponAmmoItem', itemData)
end
end, CurrentWeaponData)
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_MAX_AMMO'), 'error')
end
end)
RegisterNetEvent('weapons:client:AddAmmo', function(ammoType, amount, itemData, masterAmmo)
local ped = PlayerPedId()
if IsPedReloading(ped) then
return -- SendTextMessage('Do not spam the reload', 'error')
end
local weapon = GetSelectedPedWeapon(ped)
if not CurrentWeaponData or not WeaponList[weapon] or WeaponList[weapon]['name'] == 'weapon_unarmed' then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_WEAPON'), 'error')
return
end
local weaponAmmoType = type(WeaponList[weapon]['ammotype']) == 'table' and WeaponList[weapon]['ammotype'] or { WeaponList[weapon]['ammotype'] }
if not table.includes(weaponAmmoType, ammoType:upper()) then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_AMMO'), 'error')
return
end
local total = GetAmmoInPedWeapon(ped, weapon)
local retval = GetMaxAmmoInClip(ped, weapon, 1)
local _, ammoclip = GetAmmoInClip(ped, weapon)
local _, maxammo = GetMaxAmmo(ped, weapon)
if IsPedInAnyVehicle(ped, false) and Config.ForceToOnlyOneMagazine then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_VEHICLE_ITEMS'), 'error')
return
end
if Config.ForceToOnlyOneMagazine and total > 0 then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_MAGAZINE_LIMIT'), 'error')
return
end
if retval then
retval = tonumber(retval)
itemData = lib.callback.await('weapons:GetWeaponAmmoItem', 0, ammoType, masterAmmo)
if not itemData then
print('Nice try forehead :)')
return
end
if maxammo ~= total then
TriggerServerCallback('weapon:server:GetWeaponAmmo', function(ammo)
if ammo then
SetAmmoInClip(ped, weapon, 0)
AddAmmoToPed(ped, weapon, retval + ammoclip)
TriggerServerEvent('weapons:server:AddWeaponAmmo', CurrentWeaponData, total + retval)
--TriggerServerEvent("weapons:server:UpdateWeaponAmmo", CurrentWeaponData, total + retval)
TriggerServerEvent('weapons:server:removeWeaponAmmoItem', itemData)
end
end, CurrentWeaponData)
else
SendTextMessage(Lang('INVENTORY_NOTIFICATION_MAX_AMMO'), 'error')
end
end
end)
RegisterNetEvent('weapons:client:ConfigureTint')
AddEventHandler('weapons:client:ConfigureTint', function(ItemData)
TintItemData = ItemData
SetFocus(true)
SendNUIMessage({
action = 'showTintMenu'
})
end)
function closeGui()
SetFocus(false)
SendNUIMessage({ action = 'hide' })
end
RegisterNUICallback('quit', function(data, cb)
closeGui()
TintItemData = {}
cb('ok')
end)
RegisterNUICallback('addtinturl', function(data, cb)
closeGui()
SendTextMessage(Lang('INVENTORY_NOTIFICATION_CUSTOM_TINT_ADDED') .. ' ' .. data.urldatatint, 'success')
local tinturl = tostring(data.urldatatint)
TriggerServerEvent('weapons:server:AddUrlTint', TintItemData, tinturl)
Wait(5)
TintItemData = {}
cb('ok')
end)
RegisterNetEvent('weapons:client:EquipAttachment', function(ItemData, attachment, WeaponData)
if WeaponData then
TriggerServerEvent('weapons:server:EquipAttachment', ItemData, WeaponData, Config.WeaponAttachments[WeaponData.name:upper()][attachment], true)
return
end
local ped = PlayerPedId()
local weapon = GetSelectedPedWeapon(ped)
local WeaponData = WeaponList[weapon]
if weapon == `WEAPON_UNARMED` then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_NO_WEAPON'), 'error')
return
end
WeaponData.name = WeaponData.name:upper()
if not Config.WeaponAttachments[WeaponData.name] then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_ATTACHMENT_NOT_COMPATIBLE'), 'error')
return
end
if not Config.WeaponAttachments[WeaponData.name][attachment] then
SendTextMessage(Lang('INVENTORY_NOTIFICATION_ATTACHMENT_NOT_COMPATIBLE'), 'error')
return
end
if Config.WeaponAttachments[WeaponData.name][attachment]['item'] == ItemData.name then
TriggerServerEvent('weapons:server:EquipAttachment', ItemData, CurrentWeaponData, Config.WeaponAttachments[WeaponData.name][attachment])
return
end
SendTextMessage(Lang('INVENTORY_NOTIFICATION_ATTACHMENT_NOT_COMPATIBLE'), 'error')
end)
function SplitStr(str, delimiter)
local result = {}
local from = 1
local delim_from, delim_to = string.find(str, delimiter, from)
while delim_from do
result[#result + 1] = string.sub(str, from, delim_from - 1)
from = delim_to + 1
delim_from, delim_to = string.find(str, delimiter, from)
end
result[#result + 1] = string.sub(str, from)
return result
end
CreateThread(function()
SetWeaponsNoAutoswap(true)
end)
RegisterNetEvent(Config.InventoryPrefix .. ':client:LegacyFuel', function(fuel)
Debug('Your gasoline can has: %', fuel)
TriggerServerEvent('weapons:server:UpdateWeaponAmmo', CurrentWeaponData, fuel)
TriggerServerEvent('weapons:server:UpdateWeaponQuality', CurrentWeaponData, 1, fuel)
end)
---@param data ServerProgressBar
lib.callback.register('inventory:progressBarSync', function(data)
Debug('Progress bar sync: ', data)
local success = ProgressBarSync(data.name, data.label, data.duration, data.useWhileDead, data.canCancel, data.disableControls, data.anim, data.prop)
return success
end)
CreateThread(function()
while true do
local inRange = false
local ped = PlayerPedId()
local pos = GetEntityCoords(ped)
for k, data in pairs(Config.WeaponRepairPoints) do
local distance = #(pos - data.coords)
if distance < 10 then
inRange = true
if distance < 1 then
if data.IsRepairing then
if data.RepairingData.CitizenId ~= GetPlayerIdentifier() then
DrawText3Ds(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_NOT_AVAILABLE'))
else
if not data.RepairingData.Ready then
DrawText3Ds(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_REPAIRED'))
else
DrawText3D(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_TAKE'), 'repair_take1', 'E')
end
end
else
if CurrentWeaponData and next(CurrentWeaponData) then
if not data.RepairingData.Ready then
local WeaponData = WeaponList[GetHashKey(CurrentWeaponData.name)]
DrawText3D(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_PRICE') .. Config.WeaponRepairCosts[WeaponData.weapontype], 'repair_weapon', 'E')
if IsControlJustPressed(0, 38) then
TriggerServerCallback('weapons:server:RepairWeapon', function(HasMoney)
if HasMoney then
CurrentWeaponData = {}
end
end, k, CurrentWeaponData)
end
else
if data.RepairingData.CitizenId ~= GetPlayerIdentifier() then
DrawText3Ds(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_NOT_AVAILABLE'))
else
DrawText3D(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_TAKE'), 'repair_take2', 'E')
if IsControlJustPressed(0, 38) then
TriggerServerEvent('weapons:server:TakeBackWeapon', k, data)
end
end
end
else
if data.RepairingData.CitizenId == nil then
DrawText3Ds(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_NO_WEAPON'))
elseif data.RepairingData.CitizenId == GetPlayerIdentifier() then
DrawText3D(data.coords.x, data.coords.y, data.coords.z, Lang('INVENTORY_TEXT_REPAIR_TAKE'), 'repair_take3', 'E')
if IsControlJustPressed(0, 38) then
TriggerServerEvent('weapons:server:TakeBackWeapon', k, data)
end
end
end
end
end
end
end
if not inRange then
Wait(1250)
end
Wait(3)
end
end)