2025-03-08 13:44:05 +00:00
|
|
|
--[[
|
|
|
|
|
Usable Items & Inventory Utilities Module
|
|
|
|
|
-------------------------------------------
|
|
|
|
|
This module provides functions for:
|
|
|
|
|
• Registering items as usable across different inventory systems (ESX, QBcore, QBX).
|
|
|
|
|
• Retrieving an item's image as a NUI link.
|
|
|
|
|
• Adding and removing items from a player's inventory.
|
|
|
|
|
• Toggling items in inventory (with server event for exploit protection).
|
|
|
|
|
• Checking for item duplication exploits.
|
|
|
|
|
• Handling tool durability mechanics.
|
|
|
|
|
• Checking item availability and retrieving inventory.
|
|
|
|
|
• Granting random rewards from a reward pool.
|
|
|
|
|
• Checking if a player can carry specific items based on weight.
|
|
|
|
|
]]
|
2025-03-26 21:43:48 +00:00
|
|
|
validTokens = {}
|
2025-03-08 13:44:05 +00:00
|
|
|
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Registering Usable Items
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- Registers an item as usable for ESX, QBcore, or QBX.
|
|
|
|
|
---
|
|
|
|
|
--- @param item string The name of the item.
|
|
|
|
|
--- @param funct function The function to execute when the item is used.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @usage
|
2025-03-01 12:58:43 +00:00
|
|
|
--- ```lua
|
|
|
|
|
--- createUseableItem("health_potion", function(source)
|
|
|
|
|
--- -- Code to consume the health potion
|
|
|
|
|
--- end)
|
|
|
|
|
--- ```
|
|
|
|
|
function createUseableItem(item, funct)
|
2025-06-20 18:03:08 +01:00
|
|
|
if doesItemExist(item) then
|
|
|
|
|
local itemResource = ""
|
|
|
|
|
if isStarted(ESXExport) then
|
|
|
|
|
itemResource = ESXExport
|
|
|
|
|
while not ESX do Wait(0) end
|
|
|
|
|
ESX.RegisterUsableItem(item, funct)
|
2025-05-01 17:49:37 +01:00
|
|
|
|
2025-06-20 18:03:08 +01:00
|
|
|
elseif isStarted(QBExport) and not isStarted(QBXExport) then
|
|
|
|
|
itemResource = QBExport
|
|
|
|
|
Core.Functions.CreateUseableItem(item, funct)
|
2025-05-01 17:49:37 +01:00
|
|
|
|
2025-06-20 18:03:08 +01:00
|
|
|
elseif isStarted(QBXExport) then
|
|
|
|
|
itemResource = QBXExport
|
|
|
|
|
exports[QBXExport]:CreateUseableItem(item, funct)
|
2025-05-01 17:49:37 +01:00
|
|
|
|
2025-06-20 18:03:08 +01:00
|
|
|
elseif isStarted(RSGExport) then
|
|
|
|
|
itemResource = RSGExport
|
|
|
|
|
Core.Functions.CreateUseableItem(item, funct)
|
2025-05-01 17:49:37 +01:00
|
|
|
|
2025-06-20 18:03:08 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if itemResource ~= "" then
|
|
|
|
|
debugPrint("^6Bridge^7: ^2Registering ^3UsableItem^2 with ^4"..itemResource.."^7:", item)
|
|
|
|
|
else
|
|
|
|
|
debugPrint("^4ERROR^7: No supported framework detected for registering usable item: ^3"..item.."^7")
|
|
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
else
|
2025-06-20 18:03:08 +01:00
|
|
|
print("^1ERROR^7: ^1Tried to make item usable but it didn't exist^7: "..item)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Adding and Removing Items
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
2025-03-01 12:58:43 +00:00
|
|
|
--- Adds an item to a player's inventory.
|
|
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Triggers a server event (or local event) to add the specified item.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param item string The item name.
|
|
|
|
|
--- @param amount number The quantity to add.
|
|
|
|
|
--- @param info table|nil Additional metadata for the item.
|
|
|
|
|
--- @param src number|nil Optional player source; if nil, defaults to the caller.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @usage
|
2025-03-01 12:58:43 +00:00
|
|
|
--- ```lua
|
|
|
|
|
--- addItem("health_potion", 2, { quality = "high" })
|
|
|
|
|
--- ```
|
|
|
|
|
function addItem(item, amount, info, src)
|
2025-04-07 20:52:59 +01:00
|
|
|
if not Items[item] then
|
|
|
|
|
print("^6Bridge^7: ^1Error^7 - ^2Tried to give ^7'^3"..item.."^7'^2 but it doesn't exist")
|
|
|
|
|
return
|
|
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
|
2025-03-01 12:58:43 +00:00
|
|
|
if src then
|
|
|
|
|
TriggerEvent(getScript()..":server:toggleItem", true, item, amount, src, info)
|
|
|
|
|
else
|
2025-04-07 20:52:59 +01:00
|
|
|
TriggerServerEvent(getScript()..":server:toggleItem", true, item, amount, nil, info, nil, currentToken)
|
2025-03-26 21:43:48 +00:00
|
|
|
currentToken = nil -- clear client cached token
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Removes an item from a player's inventory.
|
|
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Triggers a server event (or local event) to remove the specified item.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param item string The item name.
|
|
|
|
|
--- @param amount number The quantity to remove.
|
|
|
|
|
--- @param src number|nil Optional player source.
|
|
|
|
|
--- @param slot number|nil Optional inventory slot.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @usage
|
2025-03-01 12:58:43 +00:00
|
|
|
--- ```lua
|
|
|
|
|
--- removeItem("health_potion", 1)
|
|
|
|
|
--- ```
|
2025-03-06 23:49:07 +00:00
|
|
|
function removeItem(item, amount, src, slot)
|
2025-03-08 13:44:05 +00:00
|
|
|
if not Items[item] then
|
|
|
|
|
print("^6Bridge^7: ^1Error^7 - ^2Tried to remove ^7'^3"..item.."^7'^2 but it doesn't exist")
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-01 12:58:43 +00:00
|
|
|
if src then
|
2025-04-07 20:52:59 +01:00
|
|
|
debugPrint(src)
|
2025-03-06 23:49:07 +00:00
|
|
|
TriggerEvent(getScript()..":server:toggleItem", false, item, amount, src, nil, slot)
|
2025-03-01 12:58:43 +00:00
|
|
|
else
|
2025-03-06 23:49:07 +00:00
|
|
|
TriggerServerEvent(getScript()..":server:toggleItem", false, item, amount, nil, nil, slot)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Toggle Items (Server Event)
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- Server event handler to toggle (add or remove) an item from a player's inventory.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- This function validates the item, then calls the appropriate export functions based on the active inventory system.
|
|
|
|
|
--- It also includes exploit protection via the dupeWarn function.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param give boolean True to add the item, false to remove.
|
|
|
|
|
--- @param item string The item name.
|
|
|
|
|
--- @param amount number The quantity.
|
|
|
|
|
--- @param newsrc number|nil The player source; defaults to event source.
|
|
|
|
|
--- @param info table|nil Additional metadata.
|
|
|
|
|
--- @param slot number|nil Optional inventory slot.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @usage
|
2025-03-01 12:58:43 +00:00
|
|
|
--- ```lua
|
2025-03-08 13:44:05 +00:00
|
|
|
--- TriggerServerEvent(getScript()..":server:toggleItem", true, "health_potion", 1)
|
2025-03-01 12:58:43 +00:00
|
|
|
--- ```
|
2025-04-07 20:52:59 +01:00
|
|
|
RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount, newsrc, info, slot, token)
|
2025-05-05 11:44:51 +01:00
|
|
|
--debugPrint(GetInvokingResource())
|
2025-04-07 20:52:59 +01:00
|
|
|
if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= "qb-core" then
|
|
|
|
|
debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital function was called from an external resource^7")
|
|
|
|
|
return
|
|
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
if not Items[item] then
|
|
|
|
|
print("^6Bridge^7: ^1Error^7 - ^2Tried to "..(tostring(give) == "true" and "add" or "remove").." '^3"..item.."^7' but it doesn't exist")
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2025-04-07 20:52:59 +01:00
|
|
|
local src = newsrc or source
|
2025-03-26 21:43:48 +00:00
|
|
|
if (give == true or give == 1) then
|
2025-05-05 11:44:51 +01:00
|
|
|
if newsrc == nil then -- this must be coming from client this would be blank
|
|
|
|
|
if not checkToken(src, token, "item", item) then
|
|
|
|
|
return
|
2025-03-26 21:43:48 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
local action = (tostring(give) == "true" and "addItem" or "removeItem")
|
|
|
|
|
local remamount = amount or 1
|
2025-03-01 12:58:43 +00:00
|
|
|
if item == nil then return end
|
2025-03-08 13:44:05 +00:00
|
|
|
|
|
|
|
|
-- Grab the current inventory (you can expand usage of 'inv' if needed)
|
|
|
|
|
local invName = ""
|
2025-03-01 12:58:43 +00:00
|
|
|
if give == 0 or give == false then
|
2025-03-08 13:44:05 +00:00
|
|
|
if not hasItem(item, amount or 1, src) then
|
|
|
|
|
dupeWarn(src, item, amount)
|
|
|
|
|
|
|
|
|
|
else
|
2025-05-07 12:58:39 +01:00
|
|
|
if isStarted(OXInv) then
|
|
|
|
|
invName = OXInv
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[OXInv]:RemoveItem(src, item, remamount, nil)
|
|
|
|
|
|
2025-05-07 12:58:39 +01:00
|
|
|
elseif isStarted(QSInv) then
|
|
|
|
|
invName = QSInv
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[QSInv]:RemoveItem(src, item, remamount)
|
|
|
|
|
|
2025-05-07 12:58:39 +01:00
|
|
|
elseif isStarted(CoreInv) then
|
|
|
|
|
invName = CoreInv
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[CoreInv]:removeItem(src, item, remamount)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-05-07 12:58:39 +01:00
|
|
|
elseif isStarted(OrigenInv) then
|
|
|
|
|
invName = OrigenInv
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[OrigenInv]:removeItem(src, item, remamount)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-05-07 12:58:39 +01:00
|
|
|
elseif isStarted(CodeMInv) then
|
|
|
|
|
invName = CodeMInv
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[CodeMInv]:RemoveItem(src, item, remamount)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-05-07 12:58:39 +01:00
|
|
|
elseif isStarted(TgiannInv) then
|
|
|
|
|
invName = TgiannInv
|
2025-04-30 17:53:26 +01:00
|
|
|
exports[TgiannInv]:RemoveItem(src, item, remamount)
|
|
|
|
|
|
2025-06-13 23:25:32 +01:00
|
|
|
elseif isStarted(JPRInv) then
|
|
|
|
|
invName = JPRInv
|
|
|
|
|
while remamount > 0 do
|
|
|
|
|
if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then
|
|
|
|
|
remamount -= 1
|
|
|
|
|
else
|
|
|
|
|
print("^1Error removing "..item.." Amount left: "..remamount)
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if Config.Crafting ~= nil and Config.Crafting.showItemBox then
|
|
|
|
|
TriggerClientEvent("inventory:client:ItemBox", src, Items[item], "remove", amount or 1)
|
|
|
|
|
end
|
|
|
|
|
|
2025-05-07 12:58:39 +01:00
|
|
|
elseif isStarted(QBInv) then
|
|
|
|
|
invName = QBInv
|
2025-03-01 12:58:43 +00:00
|
|
|
while remamount > 0 do
|
2025-03-06 23:49:07 +00:00
|
|
|
if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then
|
2025-03-01 12:58:43 +00:00
|
|
|
remamount -= 1
|
|
|
|
|
else
|
2025-03-08 13:44:05 +00:00
|
|
|
print("^1Error removing "..item.." Amount left: "..remamount)
|
2025-03-01 12:58:43 +00:00
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-06-11 18:43:31 +01:00
|
|
|
if Config.Crafting ~= nil and Config.Crafting.showItemBox then
|
2025-03-08 13:44:05 +00:00
|
|
|
TriggerClientEvent((isStarted(QBInv) and QBInvNew and "qb-" or "").."inventory:client:ItemBox", src, Items[item], "remove", amount or 1)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
2025-05-07 12:58:39 +01:00
|
|
|
|
|
|
|
|
elseif isStarted(PSInv) then
|
|
|
|
|
invName = PSInv
|
2025-03-01 12:58:43 +00:00
|
|
|
while remamount > 0 do
|
2025-03-08 13:44:05 +00:00
|
|
|
if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then
|
2025-03-01 12:58:43 +00:00
|
|
|
remamount -= 1
|
|
|
|
|
else
|
2025-03-08 13:44:05 +00:00
|
|
|
print("^1Error removing "..item.." Amount left: "..remamount)
|
2025-03-01 12:58:43 +00:00
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-06-11 18:43:31 +01:00
|
|
|
if Config.Crafting ~= nil and Config.Crafting.showItemBox then
|
2025-03-08 13:44:05 +00:00
|
|
|
TriggerClientEvent("inventory:client:ItemBox", src, Items[item], "remove", amount or 1)
|
|
|
|
|
end
|
2025-04-07 20:52:59 +01:00
|
|
|
|
|
|
|
|
elseif isStarted(RSGInv) then invName = RSGInv
|
|
|
|
|
while remamount > 0 do
|
|
|
|
|
if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then
|
|
|
|
|
remamount -= 1
|
|
|
|
|
else
|
|
|
|
|
print("^1Error removing "..item.." Amount left: "..remamount)
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-06-11 18:43:31 +01:00
|
|
|
if Config.Crafting ~= nil and Config.Crafting.showItemBox then
|
2025-04-07 20:52:59 +01:00
|
|
|
TriggerClientEvent("rsg-inventory:client:ItemBox", src, Items[item], "remove", amount or 1)
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
end
|
|
|
|
|
-----
|
|
|
|
|
-- Fallback for if no inventory found:
|
|
|
|
|
-----
|
|
|
|
|
if invName == "" then
|
|
|
|
|
if isStarted(QBExport) or isStarted(QBXExport) then -- if qbcore or qbxcore, just use core functions
|
|
|
|
|
invName = isStarted(QBXExport) and QBXExport or isStarted(QBExport) and QBExport
|
|
|
|
|
Core.Functions.GetPlayer(src).Functions.RemoveItem(item, remamount, slot)
|
|
|
|
|
|
|
|
|
|
elseif ESX and isStarted(ESXExport) then -- if esx then use core functions
|
|
|
|
|
invName = ESX
|
|
|
|
|
ESX.GetPlayerFromId(src).removeInventoryItem(item, remamount)
|
|
|
|
|
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
end
|
|
|
|
|
-- Final check for if inventory was found
|
|
|
|
|
if invName == "" then
|
|
|
|
|
print("^4ERROR^7: No Inventory detected - Check starter.lua")
|
2025-03-01 12:58:43 +00:00
|
|
|
else
|
2025-03-08 13:44:05 +00:00
|
|
|
debugPrint("^6Bridge^7: ^3"..action.."^7["..invName.."] Player("..src..") "..Items[item].label.."("..item..") x"..(amount or 1))
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
2025-03-08 13:44:05 +00:00
|
|
|
local amountToAdd = amount or 1
|
|
|
|
|
if isStarted(OXInv) then invName = OXInv
|
2025-05-15 15:31:41 +01:00
|
|
|
jsonPrint(info)
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[OXInv]:AddItem(src, item, amountToAdd, info, slot)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(QSInv) then invName = QSInv
|
|
|
|
|
exports[QSInv]:AddItem(src, item, amountToAdd, slot, info)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(CoreInv) then invName = CoreInv
|
|
|
|
|
exports[CoreInv]:addItem(src, item, amountToAdd, info)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(CodeMInv) then invName = CodeMInv
|
|
|
|
|
exports[CodeMInv]:AddItem(src, item, amountToAdd, slot, info)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(OrigenInv) then invName = OrigenInv
|
|
|
|
|
exports[OrigenInv]:addItem(src, item, amountToAdd, info, slot)
|
|
|
|
|
|
2025-04-30 17:53:26 +01:00
|
|
|
elseif isStarted(TgiannInv) then invName = TgiannInv
|
|
|
|
|
exports[TgiannInv]:AddItem(src, item, amountToAdd, slot, info)
|
|
|
|
|
|
2025-06-13 23:25:32 +01:00
|
|
|
elseif isStarted(JPRInv) then invName = JPRInv
|
|
|
|
|
if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then
|
|
|
|
|
if Config.Crafting ~= nil and Config.Crafting.showItemBox then
|
|
|
|
|
TriggerClientEvent("ps-inventory:client:ItemBox", src, Items[item], "add", amountToAdd)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(QBInv) then invName = QBInv
|
|
|
|
|
if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then
|
|
|
|
|
TriggerClientEvent((isStarted(QBInv) and QBInvNew and "qb-" or "").."inventory:client:ItemBox", src, Items[item], "add", amountToAdd)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(PSInv) then invName = PSInv
|
|
|
|
|
if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then
|
2025-06-11 18:43:31 +01:00
|
|
|
if Config.Crafting ~= nil and Config.Crafting.showItemBox then
|
2025-05-07 12:58:39 +01:00
|
|
|
TriggerClientEvent("ps-inventory:client:ItemBox", src, Items[item], "add", amountToAdd)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
2025-05-07 12:58:39 +01:00
|
|
|
|
|
|
|
|
elseif isStarted(RSGInv) then invName = RSGInv
|
|
|
|
|
if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then
|
|
|
|
|
TriggerClientEvent("rsg-inventory:client:ItemBox", src, Items[item], "add", amountToAdd)
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if invName == "" then
|
|
|
|
|
if isStarted(QBExport) or isStarted(QBXExport) then -- if qbcore or qbxcore, just use core functions
|
|
|
|
|
invName = isStarted(QBXExport) and QBXExport or isStarted(QBExport) and QBExport
|
|
|
|
|
Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info)
|
|
|
|
|
|
|
|
|
|
elseif ESX and isStarted(ESXExport) then -- if esx then use core functions
|
|
|
|
|
invName = ESX
|
|
|
|
|
ESX.GetPlayerFromId(src).addInventoryItem(item, amountToAdd)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Final check for if inventory was found
|
|
|
|
|
if invName == "" then
|
|
|
|
|
print("^4ERROR^7: No Inventory detected - Check starter.lua")
|
2025-03-01 12:58:43 +00:00
|
|
|
else
|
2025-03-08 13:44:05 +00:00
|
|
|
debugPrint("^6Bridge^7: ^3"..action.."^7["..invName.."] Player("..src..") "..Items[item].label.."("..item..") x"..(amount or 1))
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Exploit Protection
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- Warns and kicks a player if they try to remove an item they don't have.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param src number The player's source ID.
|
|
|
|
|
--- @param item string The item name.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
|
|
|
|
--- @usage
|
|
|
|
|
--- ```lua
|
|
|
|
|
--- dupeWarn(playerId, "health_potion")
|
|
|
|
|
--- ```
|
2025-05-04 20:33:51 +01:00
|
|
|
function dupeWarn(src, item, message)
|
2025-03-01 12:58:43 +00:00
|
|
|
local name = getPlayer(src).name
|
2025-05-04 20:33:51 +01:00
|
|
|
print(message or "^5DupeWarn^7: "..name.." (^1"..tostring(src).."^7) ^2Tried to remove item '^3"..item.."^7'^2 but it wasn't there^7")
|
2025-03-01 12:58:43 +00:00
|
|
|
if not debugMode then
|
2025-05-04 20:33:51 +01:00
|
|
|
DropPlayer(src, name.."("..tostring(src)..") kicked by exploit protection")
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
2025-05-04 20:33:51 +01:00
|
|
|
print("^5DupeWarn^7: "..name.."(^1"..tostring(src).."^7) ^2Dropped from server - exploit protection^7")
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Tool Durability & Metadata
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- Reduces the durability of a tool by a specified damage amount.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- If durability reaches zero or below, the tool is removed and a break sound is played.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param data table Contains:
|
|
|
|
|
--- - item (string): The tool's name.
|
|
|
|
|
--- - damage (number): The damage % to apply.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
|
|
|
|
--- @usage
|
|
|
|
|
--- ```lua
|
|
|
|
|
--- breakTool({ item = "drill", damage = 10 })
|
|
|
|
|
--- ```
|
|
|
|
|
function breakTool(data) -- WIP
|
|
|
|
|
local durability, slot = getDurability(data.item)
|
|
|
|
|
if not durability then durability = 100 end
|
|
|
|
|
durability -= data.damage
|
|
|
|
|
if durability <= 0 then
|
|
|
|
|
removeItem(data.item, 1)
|
|
|
|
|
local breakId = GetSoundId()
|
|
|
|
|
PlaySoundFromEntity(breakId, "Drill_Pin_Break", PlayerPedId(), "DLC_HEIST_FLEECA_SOUNDSET", 1, 0)
|
|
|
|
|
else
|
|
|
|
|
TriggerServerEvent(getScript()..":server:setMetaData", { item = data.item, slot = slot, metadata = { durability = durability } })
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Retrieves the durability and slot number of an item in a player's inventory.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Searches through the player's inventory for the specified item.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param item string The item name.
|
|
|
|
|
--- @return number|nil number The durability, or nil if not found.
|
|
|
|
|
--- @return number|nil number The slot number, or nil if not found.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
|
|
|
|
--- @usage
|
|
|
|
|
--- ```lua
|
|
|
|
|
--- local durability, slot = getDurability("drill")
|
|
|
|
|
--- if durability then
|
|
|
|
|
--- print("Durability:", durability)
|
2025-03-08 13:44:05 +00:00
|
|
|
--- print("Slot:", slot)
|
2025-03-01 12:58:43 +00:00
|
|
|
--- end
|
|
|
|
|
--- ```
|
|
|
|
|
function getDurability(item)
|
|
|
|
|
local lowestSlot = 100
|
|
|
|
|
local durability = nil
|
2025-06-13 23:25:32 +01:00
|
|
|
if isStarted(QBInv) or isStarted(PSInv) or isStarted(RSGInv) or isStarted(JPRInv) then
|
2025-03-01 12:58:43 +00:00
|
|
|
local itemcheck = Core.Functions.GetPlayerData().items
|
2025-03-08 20:55:05 +00:00
|
|
|
for k, v in pairs(itemcheck) do
|
2025-03-01 12:58:43 +00:00
|
|
|
if v.name == item then
|
|
|
|
|
if v.slot <= lowestSlot then
|
|
|
|
|
lowestSlot = v.slot
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = itemcheck[k].info and itemcheck[k].info.durability or nil
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(OXInv) then
|
|
|
|
|
local itemcheck = exports[OXInv]:Search('slots', item)
|
2025-03-08 20:55:05 +00:00
|
|
|
for k, v in pairs(itemcheck) do
|
2025-03-01 12:58:43 +00:00
|
|
|
if v.slot <= lowestSlot then
|
|
|
|
|
debugPrint(v.slot, itemcheck[k].metadata.durability)
|
|
|
|
|
lowestSlot = v.slot
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = v.metadata and v.metadata.durability or nil
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(QSInv) then
|
|
|
|
|
local itemcheck = exports[QSInv]:getUserInventory()
|
2025-03-08 13:44:05 +00:00
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
if v.name == item and v.slot <= lowestSlot then
|
|
|
|
|
lowestSlot = v.slot
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = v.info and v.info.durability or nil
|
2025-03-08 13:44:05 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(CoreInv) then
|
|
|
|
|
local itemcheck = exports[CoreInv]:getInventory()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
if v.name == item and v.slot <= lowestSlot then
|
|
|
|
|
lowestSlot = v.slot
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = v.metadata and v.metadata.durability or nil
|
2025-03-08 13:44:05 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(CodeMInv) then
|
|
|
|
|
local itemcheck = exports[CodeMInv]:GetClientPlayerInventory()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
2025-05-02 22:20:26 +01:00
|
|
|
if v.name == item and tonumber(v.slot) <= lowestSlot then
|
|
|
|
|
lowestSlot = tonumber(v.slot)
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = v.info and v.info.durability or nil
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(OrigenInv) then
|
|
|
|
|
local itemcheck = exports[OrigenInv]:getPlayerInventory()
|
2025-03-08 13:44:05 +00:00
|
|
|
for _, v in pairs(itemcheck) do
|
2025-03-01 12:58:43 +00:00
|
|
|
if v.name == item and v.slot <= lowestSlot then
|
|
|
|
|
lowestSlot = v.slot
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = v.metadata and v.metadata.durability or nil
|
2025-03-08 13:44:05 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-04-30 17:53:26 +01:00
|
|
|
if isStarted(TgiannInv) then
|
|
|
|
|
local itemcheck = exports[TgiannInv]:GetPlayerItems()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
if v.name == item and v.slot <= lowestSlot then
|
|
|
|
|
lowestSlot = v.slot
|
2025-05-02 22:16:51 +01:00
|
|
|
durability = v.metadata and v.metadata.durability or nil
|
2025-04-30 17:53:26 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-- For ESX default inventory (es_extended)
|
|
|
|
|
if ESX and isStarted(ESXExport) then
|
|
|
|
|
local xPlayer = ESX.GetPlayerData() or {}
|
|
|
|
|
if xPlayer.inventory then
|
|
|
|
|
for _, v in ipairs(xPlayer.inventory) do
|
|
|
|
|
if v.name == item then
|
|
|
|
|
-- Optionally use a slot field if available; otherwise, use the index
|
|
|
|
|
if v.slot and v.slot <= lowestSlot then
|
|
|
|
|
lowestSlot = v.slot
|
|
|
|
|
end
|
|
|
|
|
if v.metadata and v.metadata.durability then
|
|
|
|
|
durability = v.metadata.durability
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
|
2025-03-01 12:58:43 +00:00
|
|
|
return durability, lowestSlot
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Server event handler to set metadata for an item.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Updates item metadata (e.g. durability) for the player's inventory based on slot.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param data table Contains:
|
|
|
|
|
--- - item (string): The item name.
|
|
|
|
|
--- - slot (number): The inventory slot.
|
|
|
|
|
--- - metadata (table): The metadata to set.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @usage
|
2025-03-01 12:58:43 +00:00
|
|
|
--- ```lua
|
|
|
|
|
--- TriggerServerEvent("script:server:setMetaData", { item = "drill", slot = 5, metadata = { durability = 80 } })
|
|
|
|
|
--- ```
|
2025-06-26 19:57:03 +01:00
|
|
|
RegisterNetEvent(getScript()..":server:setMetaData", function(data, src)
|
|
|
|
|
local src = src or source
|
2025-06-13 23:25:32 +01:00
|
|
|
if isStarted(QBInv) or isStarted(PSInv) or isStarted(RSGInv) or isStarted(JPRInv) then
|
2025-06-26 19:57:03 +01:00
|
|
|
--debugPrint(src, data.item, 1, data.slot)
|
2025-03-01 12:58:43 +00:00
|
|
|
local Player = Core.Functions.GetPlayer(src)
|
|
|
|
|
Player.PlayerData.items[data.slot].info = data.metadata
|
2025-06-26 19:57:03 +01:00
|
|
|
if data.metadata.durability then
|
|
|
|
|
Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
Player.Functions.SetInventory(Player.PlayerData.items)
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(OXInv) then
|
2025-06-26 19:57:03 +01:00
|
|
|
exports[OXInv]:SetMetadata(src, data.slot, data.metadata)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
|
|
|
|
elseif isStarted(QSInv) then
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[QSInv]:SetItemMetadata(src, data.slot, data.metadata)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
|
|
|
|
elseif isStarted(CoreInv) then
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[CoreInv]:setMetadata(src, data.slot, data.metadata)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
|
|
|
|
elseif isStarted(CodeMInv) then
|
2025-03-08 13:44:05 +00:00
|
|
|
exports[CodeMInv]:SetItemMetadata(src, data.slot, data.metadata)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(OrigenInv) then
|
|
|
|
|
exports[OrigenInv]:setMetadata(src, data.slot, data.metadata)
|
2025-04-30 17:53:26 +01:00
|
|
|
|
|
|
|
|
elseif isStarted(TgiannInv) then
|
|
|
|
|
exports[TgiannInv]:UpdateItemMetadata(src, data.item, data.slot, data.metadata)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
end)
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Random Reward
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- Grants a random reward from a predefined reward pool if the player is eligible.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Checks if the item qualifies for a reward, removes the item, then calculates a random reward based on rarity.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param itemName string The item name to check.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
|
|
|
|
---@usage
|
|
|
|
|
--- ```lua
|
|
|
|
|
--- getRandomReward("gold_ring")
|
|
|
|
|
--- ```
|
2025-03-08 13:44:05 +00:00
|
|
|
function getRandomReward(itemName)
|
2025-03-01 12:58:43 +00:00
|
|
|
if Config.Rewards.RewardPool then
|
|
|
|
|
local reward = false
|
2025-03-08 13:44:05 +00:00
|
|
|
if type(Config.Rewards.RewardItem) == "string" then
|
|
|
|
|
Config.Rewards.RewardItem = { Config.Rewards.RewardItem }
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
for k, v in pairs(Config.Rewards.RewardItem) do
|
2025-03-08 13:44:05 +00:00
|
|
|
if v == itemName then
|
|
|
|
|
reward = true
|
|
|
|
|
break
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
if reward then
|
|
|
|
|
removeItem(itemName, 1)
|
|
|
|
|
local totalRarity = 0
|
2025-03-08 13:44:05 +00:00
|
|
|
for i = 1, #Config.Rewards.RewardPool do
|
2025-03-01 12:58:43 +00:00
|
|
|
totalRarity += Config.Rewards.RewardPool[i].rarity
|
|
|
|
|
end
|
2025-03-08 13:44:05 +00:00
|
|
|
debugPrint("^6Bridge^7: ^3getRandomReward^7: Total Rarity '"..totalRarity.."'")
|
2025-03-01 12:58:43 +00:00
|
|
|
local randomNum = math.random(1, totalRarity)
|
2025-03-08 13:44:05 +00:00
|
|
|
debugPrint("^6Bridge^7: ^3getRandomReward^7: Random Number '"..randomNum.."'")
|
2025-03-01 12:58:43 +00:00
|
|
|
local currentRarity = 0
|
2025-03-08 13:44:05 +00:00
|
|
|
for i = 1, #Config.Rewards.RewardPool do
|
2025-03-01 12:58:43 +00:00
|
|
|
currentRarity += Config.Rewards.RewardPool[i].rarity
|
|
|
|
|
if randomNum <= currentRarity then
|
|
|
|
|
debugPrint("^6Bridge^7: ^3getRandomReward^7: ^2Selected toy ^7'^6"..Config.Rewards.RewardPool[i].item.."^7'")
|
|
|
|
|
addItem(Config.Rewards.RewardPool[i].item, 1)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Carry Capacity Check
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- Checks if a player can carry the specified items based on weight.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- Calculates the current total weight in the player's inventory and determines whether adding the new items would exceed capacity.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @param itemTable table A table where keys are item names and values are required quantities.
|
|
|
|
|
--- @param src number The player's source ID.
|
|
|
|
|
--- @return table A table mapping each item to a boolean indicating if it can be carried.
|
2025-03-01 12:58:43 +00:00
|
|
|
---
|
2025-03-08 13:44:05 +00:00
|
|
|
--- @usage
|
|
|
|
|
--- local carryCheck = canCarry({ ["health_potion"] = 2, ["mana_potion"] = 3 }, playerId)
|
|
|
|
|
--- if carryCheck["health_potion"] and carryCheck["mana_potion"] then
|
|
|
|
|
--- -- Player can carry items.
|
2025-03-01 12:58:43 +00:00
|
|
|
--- else
|
2025-03-08 13:44:05 +00:00
|
|
|
--- -- Notify player.
|
2025-03-01 12:58:43 +00:00
|
|
|
--- end
|
|
|
|
|
function canCarry(itemTable, src)
|
|
|
|
|
local resultTable = {}
|
|
|
|
|
if src then
|
|
|
|
|
if isStarted(OXInv) then
|
|
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
resultTable[k] = exports[OXInv]:CanCarryItem(src, k, v)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
elseif isStarted(QSInv) then
|
|
|
|
|
for k, v in pairs(itemTable) do
|
2025-03-08 13:44:05 +00:00
|
|
|
resultTable[k] = exports[QSInv]:CanCarryItem(src, k, v)
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
elseif isStarted(CoreInv) then
|
2025-03-08 13:44:05 +00:00
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
resultTable[k] = exports[CoreInv]:canCarry(src, k, v)
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
|
2025-03-08 13:44:05 +00:00
|
|
|
elseif isStarted(CodeMInv) then --- This really needs updating, their docs are confusing..
|
|
|
|
|
local items = getPlayerInv(src)
|
|
|
|
|
local totalWeight = 0
|
|
|
|
|
if not items then return false end
|
|
|
|
|
for _, item in pairs(items) do
|
|
|
|
|
totalWeight += (item.weight * item.amount)
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
for k, v in pairs(itemTable) do
|
2025-03-08 13:44:05 +00:00
|
|
|
local itemInfo = Items[k]
|
|
|
|
|
if not itemInfo then
|
|
|
|
|
resultTable[k] = true
|
|
|
|
|
else
|
|
|
|
|
resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
elseif isStarted(OrigenInv) then
|
|
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
resultTable[k] = exports[OrigenInv]:canCarryItem(src, k, v)
|
|
|
|
|
end
|
|
|
|
|
|
2025-04-30 17:53:26 +01:00
|
|
|
elseif isStarted(TgiannInv) then
|
|
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
resultTable[k] = exports[TgiannInv]:CanCarryItem(source, k, v)
|
|
|
|
|
end
|
|
|
|
|
|
2025-06-13 23:25:32 +01:00
|
|
|
elseif isStarted(JPRInv) then
|
|
|
|
|
local items = getPlayerInv(src)
|
|
|
|
|
local totalWeight = 0
|
|
|
|
|
if not items then return false end
|
|
|
|
|
for _, item in pairs(items) do
|
|
|
|
|
totalWeight += (item.weight * item.amount)
|
|
|
|
|
end
|
|
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
local itemInfo = Items[k]
|
|
|
|
|
if not itemInfo then
|
|
|
|
|
resultTable[k] = true
|
|
|
|
|
else
|
|
|
|
|
resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-04-07 20:52:59 +01:00
|
|
|
elseif isStarted(QBInv) then
|
2025-05-07 16:38:57 +01:00
|
|
|
if QBInvNew then
|
|
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
resultTable[k] = exports[QBInv]:CanAddItem(src, k, v)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
local items = getPlayerInv(src)
|
|
|
|
|
local totalWeight = 0
|
|
|
|
|
if not items then return false end
|
|
|
|
|
for _, item in pairs(items) do
|
|
|
|
|
totalWeight += (item.weight * item.amount)
|
|
|
|
|
end
|
|
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
local itemInfo = Items[k]
|
2025-05-26 16:21:25 +01:00
|
|
|
if not itemInfo then
|
2025-05-07 16:38:57 +01:00
|
|
|
resultTable[k] = true
|
|
|
|
|
else
|
|
|
|
|
resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-04-07 20:52:59 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
elseif isStarted(PSInv) then
|
2025-03-08 13:44:05 +00:00
|
|
|
local items = getPlayerInv(src)
|
|
|
|
|
local totalWeight = 0
|
2025-03-01 12:58:43 +00:00
|
|
|
if not items then return false end
|
2025-03-08 13:44:05 +00:00
|
|
|
for _, item in pairs(items) do
|
|
|
|
|
totalWeight += (item.weight * item.amount)
|
|
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
for k, v in pairs(itemTable) do
|
|
|
|
|
local itemInfo = Items[k]
|
2025-05-26 16:21:25 +01:00
|
|
|
if not itemInfo then
|
2025-03-01 12:58:43 +00:00
|
|
|
resultTable[k] = true
|
|
|
|
|
else
|
2025-03-08 13:44:05 +00:00
|
|
|
resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
2025-04-07 20:52:59 +01:00
|
|
|
end
|
2025-03-01 12:58:43 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return resultTable
|
2025-03-26 21:43:48 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Server Callback Registration
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
if isServer() then
|
|
|
|
|
createCallback(getScript()..":server:canCarry", function(source, itemTable)
|
|
|
|
|
local result = canCarry(itemTable, source)
|
|
|
|
|
return result
|
|
|
|
|
end)
|
|
|
|
|
|
2025-05-06 00:17:07 +01:00
|
|
|
createCallback(getScript()..":server:getMaxCarryCraft", function(source, data)
|
|
|
|
|
local src = source
|
|
|
|
|
local item = data.item
|
|
|
|
|
local max = data.max or 100
|
|
|
|
|
|
|
|
|
|
local maxCanCarry = 0
|
|
|
|
|
for i = 1, max do
|
|
|
|
|
local checkTable = {
|
|
|
|
|
[item] = i
|
|
|
|
|
}
|
|
|
|
|
local result = canCarry(checkTable, src)
|
|
|
|
|
if result[item] == true then
|
|
|
|
|
maxCanCarry = i
|
|
|
|
|
else
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return maxCanCarry
|
|
|
|
|
end)
|
2025-03-26 21:43:48 +00:00
|
|
|
end
|
2025-05-05 11:44:51 +01:00
|
|
|
|
2025-06-22 20:03:12 +01:00
|
|
|
function getMaxInvWeight()
|
|
|
|
|
local weight = 0
|
|
|
|
|
if isStarted(QBInv) then
|
|
|
|
|
if checkExportExists(QBInv, "GetMaxWeight") then
|
|
|
|
|
return exports[QBInv]:GetMaxWeight()
|
|
|
|
|
else
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if isStarted(PSInv) then
|
|
|
|
|
if checkExportExists(PSInv, "GetMaxWeight") then
|
|
|
|
|
return exports[PSInv]:GetMaxWeight()
|
|
|
|
|
else
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if isStarted(RSGInv) then
|
|
|
|
|
if checkExportExists(RSGInv, "GetMaxWeight") then
|
|
|
|
|
return exports[RSGInv]:GetMaxWeight()
|
|
|
|
|
else
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if isStarted(JPRInv) then
|
|
|
|
|
if checkExportExists(JPRInv, "GetMaxWeight") then
|
|
|
|
|
return exports[JPRInv]:GetMaxWeight()
|
|
|
|
|
else
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(OXInv) then
|
|
|
|
|
return exports[OXInv]:GetPlayerMaxWeight()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(QSInv) then
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(CoreInv) then
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(CodeMInv) then
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(OrigenInv) then
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(TgiannInv) then
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- For ESX default inventory (es_extended)
|
|
|
|
|
if ESX and isStarted(ESXExport) then
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return InventoryWeight
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function getCurrentInvWeight()
|
|
|
|
|
local weight = 0
|
|
|
|
|
if isStarted(QBInv) or isStarted(PSInv) or isStarted(RSGInv) or isStarted(JPRInv) then
|
|
|
|
|
local itemcheck = Core.Functions.GetPlayerData().items
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(OXInv) then
|
|
|
|
|
weight = exports[OXInv]:GetPlayerWeight()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(QSInv) then
|
|
|
|
|
local itemcheck = exports[QSInv]:getUserInventory()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(CoreInv) then
|
|
|
|
|
local itemcheck = exports[CoreInv]:getInventory()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(CodeMInv) then
|
|
|
|
|
local itemcheck = exports[CodeMInv]:GetClientPlayerInventory()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(OrigenInv) then
|
|
|
|
|
local itemcheck = exports[OrigenInv]:getPlayerInventory()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if isStarted(TgiannInv) then
|
|
|
|
|
local itemcheck = exports[TgiannInv]:GetPlayerItems()
|
|
|
|
|
for _, v in pairs(itemcheck) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- For ESX default inventory (es_extended)
|
|
|
|
|
if ESX and isStarted(ESXExport) then
|
|
|
|
|
local xPlayer = ESX.GetPlayerData() or {}
|
|
|
|
|
if xPlayer.inventory then
|
|
|
|
|
for _, v in pairs(xPlayer.inventory) do
|
|
|
|
|
weight += ((v.weight * v.amount) or 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return weight
|
|
|
|
|
end
|
|
|
|
|
|
2025-06-26 20:04:32 +01:00
|
|
|
function hasFreeInventorySlots(slots, src)
|
|
|
|
|
local inv = getPlayerInv(src)
|
|
|
|
|
if (countTable(inv) + slots) <= InventorySlots then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
2025-06-03 08:52:06 +01:00
|
|
|
-------------------------------------------------------------
|
|
|
|
|
-- Check Item Existance - return boolean(true,false)
|
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
--- checks whether an item exists in your item database
|
|
|
|
|
---
|
|
|
|
|
--- @param item string The item name.
|
|
|
|
|
---
|
|
|
|
|
--- @usage
|
|
|
|
|
--- ```lua
|
|
|
|
|
--- local item = "apple"
|
|
|
|
|
--- if doesItemExist(item) then print("item exists") end
|
|
|
|
|
--- ```
|
|
|
|
|
function doesItemExist(item)
|
|
|
|
|
if not item or item == "" then return false end
|
|
|
|
|
if Items[item] ~= nil then
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
return false
|
|
|
|
|
end
|