From d7622f514300a097be33068b87159552e7e7cc30 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Thu, 14 Aug 2025 13:07:15 +0100 Subject: [PATCH 01/10] fix canCarry and add hasItem functions --- shared/itemcontrol.lua | 1998 ++++++++++++++++++++++------------------ 1 file changed, 1127 insertions(+), 871 deletions(-) diff --git a/shared/itemcontrol.lua b/shared/itemcontrol.lua index 80d5993..4b5c18f 100644 --- a/shared/itemcontrol.lua +++ b/shared/itemcontrol.lua @@ -16,577 +16,394 @@ validTokens = {} -- Function Compatability Table local InvFunc = { - { - invName = OXInv, - removeItem = function(src, item, remamount) - exports[OXInv]:RemoveItem(src, item, remamount, nil) - end, - addItem = function(src, item, amountToAdd, info, slot) - exports[OXInv]:AddItem(src, item, amountToAdd, info, slot) - end, - setItemMetadata = function(data, src) - exports[OXInv]:SetMetadata(src, data.slot, data.metadata) - end, - canCarry = function(itemTable, src) - local resultTable = {} - for k, v in pairs(itemTable) do - resultTable[k] = exports[OXInv]:CanCarryItem(src, k, v) - end - end, - getMaxInvWeight = function() - return exports[OXInv]:GetPlayerMaxWeight() - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = exports[OXInv]:GetInventoryItems(src) - else - grabInv = exports[OXInv]:GetPlayerItems() - end - return grabInv - end, - invImg = function(item) - return "nui://"..OXInv.."/web/images/"..(Items[item].image or "") - end, - openShop = function(data) - exports[OXInv]:openInventory('shop', { type = data.shop }) - end, - registerShop = function(name, label, items, society) - exports[OXInv]:RegisterShop(name, { - name = label, - inventory = items, - society = society, - }) - debugPrint("^6Bridge^7: ^2Registering ^5"..OXInv.." ^3Store^7:", name, "^4Label^7: "..label) - end, - openStash = function(data) - exports[OXInv]:openInventory('stash', data.stash) - end, - clearStash = function(stashId) - exports[OXInv]:ClearInventory(stashId) - end, - getStash = function(stashName) - local stash = exports[OXInv]:Inventory(stashName) - -- Add fallback if ox can't find the stash and returns a boolean - return type(stash) == "table" and stash.items or {} - end, - stashAddItem = function(stashItems, stashName, items) - - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - for _, name in pairs(stashName) do - local success = exports[OXInv]:RemoveItem(name, k, v) - if success then - debugPrint("^6Bridge^7: ^2Removing ^3"..OXInv.." ^2Stash item^7:", k, v) - break - end - end - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - exports[OXInv]:RegisterStash(name, label, slots or 50, weight or 4000000, owner or nil) - debugPrint("^6Bridge^7: ^2Registering ^4"..OXInv.." ^3Stash^7:", name, "^4Label^7: "..label) - end, - }, - { - invName = QSInv, - removeItem = function(src, item, remamount) - exports[QSInv]:RemoveItem(src, item, remamount) - end, - addItem = function(src, item, amountToAdd, info, slot) - exports[QSInv]:AddItem(src, item, amountToAdd, slot, info) - end, - setItemMetadata = function(data, src) - exports[QSInv]:SetItemMetadata(src, data.slot, data.metadata) - end, - canCarry = function(itemTable, src) - local resultTable = {} - for k, v in pairs(itemTable) do - resultTable[k] = exports[QSInv]:CanCarryItem(src, k, v) - end - end, - getMaxInvWeight = function() - return InventoryWeight - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = exports[QSInv]:GetInventory(src) - else - grabInv = exports[QSInv]:getUserInventory() - end - return grabInv - end, - invImg = function(item) - return "nui://"..QSInv.."/html/images/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) - end, - registerShop = function(name, label, items, society) - -- - end, - openStash = function(data) - TriggerEvent("inventory:client:SetCurrentStash", data.stash) - TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { - slots = data.slots or 50, - maxWeight = data.maxWeight or 600000 - }) - end, - clearStash = function(stashId) - exports[QSInv]:ClearOtherInventory('stash', stashId) - end, - getStash = function(stashName) - return exports[QSInv]:GetStashItems(stashName) - end, - stashAddItem = function(stashItems, stashName, items) - - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - exports[QSInv]:RemoveItemIntoStash(stashName, k, v) - debugPrint("^6Bridge^7: ^2Removing ^3"..QSInv.." ^2Stash item^7:", k, v) - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, - }, - { - invName = CoreInv, - removeItem = function(src, item, remamount) - exports[CoreInv]:removeItem(src, item, remamount) - end, - addItem = function(src, item, amountToAdd, info, slot) - exports[CoreInv]:addItem(src, item, amountToAdd, info) - end, - setItemMetadata = function(data, src) - exports[CoreInv]:setMetadata(src, data.slot, data.metadata) - end, - canCarry = function(itemTable, src) - local resultTable = {} - for k, v in pairs(itemTable) do - resultTable[k] = exports[CoreInv]:canCarry(src, k, v) - end - end, - getMaxInvWeight = function() - return InventoryWeight - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = exports[CoreInv]:getInventory(src) - else - grabInv = exports[CoreInv]:getInventory() - end - return grabInv - end, - invImg = function(item) - return "nui://"..CoreInv.."/html/img/"..(Items[item].image or "") - end, - openShop = function(data) - -- - end, - registerShop = function(name, label, items, society) - -- - end, - openStash = function(data) - TriggerServerEvent('core_inventory:server:openInventory', data.stash, 'stash') - end, - clearStash = function(stashId) - exports[CoreInv]:clearInventory("stash-"..stashId) - end, - getStash = function(stashName) - return exports[CoreInv]:getInventory(stashName) - end, - stashAddItem = function(stashItems, stashName, items) - - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - exports[CoreInv]:removeItemExact(stashName, k, v) - debugPrint("^6Bridge^7: ^2Removing ^3"..CoreInv.." ^2Stash item^7:", k, v) - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, - }, - { - invName = OrigenInv, - removeItem = function(src, item, remamount) - exports[OrigenInv]:removeItem(src, item, remamount) - end, - addItem = function(src, item, amountToAdd, info, slot) - exports[OrigenInv]:addItem(src, item, amountToAdd, info, slot) - end, - setItemMetadata = function(data, src) - exports[OrigenInv]:setMetadata(src, data.slot, data.metadata) - end, - canCarry = function(itemTable, src) - local resultTable = {} - for k, v in pairs(itemTable) do - resultTable[k] = exports[OrigenInv]:canCarryItem(src, k, v) - end - return resultTable - end, - getMaxInvWeight = function() - return InventoryWeight - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = exports[OXInv]:GetInventoryItems(src) - else - grabInv = exports[OXInv]:GetPlayerItems() - end - return grabInv - end, - invImg = function(item) - return "nui://"..OrigenInv.."/html/img/"..(Items[item].image or "") - end, - openShop = function(data) - -- - end, - registerShop = function(name, label, items, society) - -- - end, - openStash = function(data) - exports[OrigenInv]:openInventory('stash', data.stash, { label = data.label }) - end, - clearStash = function(stashId) - exports[OrigenInv]:ClearInventory(stashId) - end, - getStash = function(stashName) - return exports[OrigenInv]:getInventory(stashName) - end, - stashAddItem = function(stashItems, stashName, items) - - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - exports[OrigenInv]:RemoveFromStash(stashName, k, v) - debugPrint("^6Bridge^7: ^2Removing ^3"..OrigenInv.." ^2Stash item^7:", k, v) - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - exports[OrigenInv]:registerStash(name, label, slots or 50, weight or 4000000) - debugPrint("^6Bridge^7: ^2Registering ^4"..OrigenInv.." ^3Stash^7:", name, "^4Label^7: "..label) - end, - }, - { - invName = CodeMInv, - removeItem = function(src, item, remamount) - exports[CodeMInv]:RemoveItem(src, item, remamount) - end, - addItem = function(src, item, amountToAdd, info, slot) - exports[CodeMInv]:AddItem(src, item, amountToAdd, slot, info) - end, - setItemMetadata = function(data, src) - exports[CodeMInv]:SetItemMetadata(src, data.slot, data.metadata) - end, - canCarry = function(itemTable, src) - local resultTable = {} - 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 + { invName = OXInv, + removeItem = + function(src, item, remamount) + exports[OXInv]:RemoveItem(src, item, remamount, nil) + end, + addItem = + function(src, item, amountToAdd, info, slot) + exports[OXInv]:AddItem(src, item, amountToAdd, info, slot) + end, + setItemMetadata = + function(data, src) + exports[OXInv]:SetMetadata(src, data.slot, data.metadata) + end, + hasItem = + function(item, amount, src) + if src then + local serverItemCheck = exports[OXInv]:GetItem(src, item, nil, true) or 0 + return serverItemCheck >= amount, serverItemCheck else - resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight + local localItemCheck = exports[OXInv]:GetItemCount(item) or 0 + return localItemCheck >= amount, localItemCheck end - return resultTable - end - end, - getMaxInvWeight = function() - return InventoryWeight - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = exports[CodeMInv]:GetInventory(getPlayer(src).citizenId, src) - else - grabInv = exports[CodeMInv]:getUserInventory() - end - return grabInv - end, - invImg = function(item) - return "nui://"..CodeMInv.."/html/itemimages/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerEvent("codem-inventory:openshop", data.shop) - end, - registerShop = function(name, label, items, society) - -- - end, - openStash = function(data) - TriggerServerEvent('codem-inventory:server:openstash', data.stash, data.slots, data.maxWeight, data.label) - end, - clearStash = function(stashId) - exports[CodeMInv]:ClearInventory(stashId) - end, - getStash = function(stashName) - return exports[CodeMInv]:GetStashItems(stashName) - end, - stashAddItem = function(stashItems, stashName, items) + end, + canCarry = + function(itemTable, src) + local resultTable = {} + for k, v in pairs(itemTable) do + resultTable[k] = exports[OXInv]:CanCarryItem(src, k, v) + end + return resultTable + end, + getMaxInvWeight = + function() + return exports[OXInv]:GetPlayerMaxWeight() + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = exports[OXInv]:GetInventoryItems(src) + else + grabInv = exports[OXInv]:GetPlayerItems() + end + return grabInv + end, + invImg = + function(item) + return "nui://"..OXInv.."/web/images/"..(Items[item].image or "") + end, + openShop = + function(data) + exports[OXInv]:openInventory('shop', { type = data.shop }) + end, + registerShop = + function(name, label, items, society) + exports[OXInv]:RegisterShop(name, { + name = label, + inventory = items, + society = society, + }) + debugPrint("^6Bridge^7: ^2Registering ^5"..OXInv.." ^3Store^7:", name, "^4Label^7: "..label) + end, + openStash = + function(data) + exports[OXInv]:openInventory('stash', data.stash) + end, + clearStash = + function(stashId) + exports[OXInv]:ClearInventory(stashId) + end, + getStash = + function(stashName) + local stash = exports[OXInv]:Inventory(stashName) + -- Add fallback if ox can't find the stash and returns a boolean + return type(stash) == "table" and stash.items or {} + end, + stashAddItem = + function(stashItems, stashName, items) - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - for l in pairs(stashItems) do - if stashItems[l].name == k then - if (stashItems[l].amount - v) <= 0 then - stashItems[l] = nil - else - debugPrint("^6Bridge^7: ^2Removing ^3"..CodeMInv.." ^2Stash item^7:", k, v) - stashItems[l].amount -= v + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + for _, name in pairs(stashName) do + local success = exports[OXInv]:RemoveItem(name, k, v) + if success then + debugPrint("^6Bridge^7: ^2Removing ^3"..OXInv.." ^2Stash item^7:", k, v) + break end end end - end - exports[CodeMInv]:UpdateStash(stashName, stashItems) - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, + end, + registerStash = + function(name, label, slots, weight, owner, coords) + exports[OXInv]:RegisterStash(name, label, slots or 50, weight or 4000000, owner or nil) + debugPrint("^6Bridge^7: ^2Registering ^4"..OXInv.." ^3Stash^7:", name, "^4Label^7: "..label) + end, }, - { - invName = TgiannInv, - removeItem = function(src, item, remamount) - exports[TgiannInv]:RemoveItem(src, item, remamount) - end, - addItem = function(src, item, amountToAdd, info, slot) - exports[TgiannInv]:AddItem(src, item, amountToAdd, slot, info) - end, - setItemMetadata = function(data, src) - exports[TgiannInv]:UpdateItemMetadata(src, data.item, data.slot, data.metadata) - end, - canCarry = function(itemTable, src) - local resultTable = {} - for k, v in pairs(itemTable) do - resultTable[k] = exports[TgiannInv]:CanCarryItem(src, k, v) - end - return resultTable - end, - getMaxInvWeight = function() - return InventoryWeight - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = exports[TgiannInv]:GetPlayerItems(src) - else - grabInv = exports[TgiannInv]:GetPlayerItems() - end - return grabInv - end, - invImg = function(item) - return "nui://inventory_images/images/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - end, - registerShop = function(name, label, items, society) - exports[TgiannInv]:RegisterShop(name, items) - debugPrint("^6Bridge^7: ^2Registering ^5"..TgiannInv.." ^3Store^7:", name, "^4Label^7: "..label) - end, - openStash = function(data) - TriggerServerEvent(getScript()..':server:openServerStash', { - stashName = data.stash, - label = data.label, - maxweight = data.maxWeight or 600000, - slots = data.slots or 40 - }) - end, - clearStash = function(stashId) - exports[TgiannInv]:DeleteInventory("stash", stashId) - end, - getStash = function(stashName) - return exports[TgiannInv]:GetSecondaryInventoryItems("stash", stashName) - end, - stashAddItem = function(stashItems, stashName, items) - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - local itemData = exports[TgiannInv]:GetItemByNameFromSecondaryInventory("stash", stashName, k) - exports[TgiannInv]:RemoveItemFromSecondaryInventory("stash", stashName, k, v, itemData.slot, nil) - debugPrint("^6Bridge^7: ^2Removing ^3"..TgiannInv.." ^2Stash item^7:", k, v) - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - exports[TgiannInv]:RegisterStash(name, label, slots or 50, weight or 4000000) - debugPrint("^6Bridge^7: ^2Registering ^4"..TgiannInv.." ^3Stash^7:", name, "^4Label^7: "..label) - end, - }, - { - invName = JPRInv, - removeItem = function(src, item, remamount) - while remamount > 0 do - if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then - remamount -= 1 + { invName = QSInv, + removeItem = + function(src, item, remamount) + exports[QSInv]:RemoveItem(src, item, remamount) + end, + addItem = + function(src, item, amountToAdd, info, slot) + exports[QSInv]:AddItem(src, item, amountToAdd, slot, info) + end, + setItemMetadata = + function(data, src) + exports[QSInv]:SetItemMetadata(src, data.slot, data.metadata) + end, + hasItem = + function(item, amount, src) + if src then + local serverItemCheck = exports[QSInv]:GetItemTotalAmount(src, item) or 0 + return serverItemCheck >= amount, serverItemCheck else - print("^1Error removing "..item.." Amount left: "..remamount) - break + local localItemCheck = exports[QSInv]:Search(item) or 0 + return localItemCheck >= amount, localItemCheck end - end - if Config.Crafting ~= nil and Config.Crafting.showItemBox then - TriggerClientEvent("inventory:client:ItemBox", src, Items[item], "remove", amount or 1) - end - end, - addItem = function(src, item, amountToAdd, info, slot) - 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, + canCarry = + function(itemTable, src) + local resultTable = {} + for k, v in pairs(itemTable) do + resultTable[k] = exports[QSInv]:CanCarryItem(src, k, v) end - end - end, - setItemMetadata = function(data, src) - local Player = Core.Functions.GetPlayer(src) - Player.PlayerData.items[data.slot].info = data.metadata - if data.metadata.durability then - Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability - end - Player.Functions.SetInventory(Player.PlayerData.items) - end, - canCarry = function(itemTable, src) - local resultTable = {} - 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 - return resultTable - end, - getMaxInvWeight = function() - if checkExportExists(JPRInv, "GetMaxWeight") then - return exports[JPRInv]:GetMaxWeight() - else + return resultTable + end, + getMaxInvWeight = + function() return InventoryWeight - end - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = Core.Functions.GetPlayer(src).PlayerData.items - else - grabInv = Core.Functions.GetPlayerData().items - end - return grabInv - end, - invImg = function(item) - return "nui://"..JPRInv.."/html/images/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) - end, - registerShop = function(name, label, items, society) - -- - end, - openStash = function(data) - if QBInvNew then - TriggerServerEvent(getScript()..':server:openServerStash', { - stashName = data.stash, - label = data.label, - maxweight = data.maxWeight or 600000, - slots = data.slots or 40 - }) - else + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = exports[QSInv]:GetInventory(src) + else + grabInv = exports[QSInv]:getUserInventory() + end + return grabInv + end, + invImg = + function(item) + return "nui://"..QSInv.."/html/images/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + end, + registerShop = + function(name, label, items, society) + -- + end, + openStash = + function(data) TriggerEvent("inventory:client:SetCurrentStash", data.stash) TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { slots = data.slots or 50, maxWeight = data.maxWeight or 600000 }) - end - end, - clearStash = function(stashId) - MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['stash'] = stashId, - ['items'] = json.encode({}) - }) - end, - getStash = function(stashName) - local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) - if result then - return json.decode(result) - else - return {} - end - end, - stashAddItem = function(stashItems, stashName, items) + end, + clearStash = + function(stashId) + exports[QSInv]:ClearOtherInventory('stash', stashId) + end, + getStash = + function(stashName) + return exports[QSInv]:GetStashItems(stashName) + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + exports[QSInv]:RemoveItemIntoStash(stashName, k, v) + debugPrint("^6Bridge^7: ^2Removing ^3"..QSInv.." ^2Stash item^7:", k, v) + end + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, + }, - end, - stashRemoveItem = function(stashItems, stashName, items) - if not stashItems or not next(stashItems) then - stashItems = getStash(stashName) - end - for k, v in pairs(items) do - for l in pairs(stashItems) do - if stashItems[l].name == k then - if (stashItems[l].amount - v) <= 0 then - stashItems[l] = nil - else - debugPrint("^6Bridge^7: ^2Removing ^3"..JPRInv.." ^2Stash item^7:", k, v) - stashItems[l].amount -= v - end + { invName = CoreInv, + removeItem = + function(src, item, remamount) + exports[CoreInv]:removeItem(src, item, remamount) + end, + addItem = + function(src, item, amountToAdd, info, slot) + exports[CoreInv]:addItem(src, item, amountToAdd, info) + end, + setItemMetadata = + function(data, src) + exports[CoreInv]:setMetadata(src, data.slot, data.metadata) + end, + hasItem = + function(item, amount, src) + if src then + local serverItemCheck = exports[CoreInv]:getItemCount(src, item) or 0 + return serverItemCheck >= amount, serverItemCheck + else + local localItemCheck = exports[CoreInv]:getItemCount(item) or 0 + return localItemCheck >= amount, localItemCheck + end + end, + canCarry = + function(itemTable, src) + local resultTable = {} + for k, v in pairs(itemTable) do + resultTable[k] = exports[CoreInv]:canCarry(src, k, v) + end + return resultTable + end, + getMaxInvWeight = + function() + return InventoryWeight + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = exports[CoreInv]:getInventory(src) + else + grabInv = exports[CoreInv]:getInventory() + end + return grabInv + end, + invImg = + function(item) + return "nui://"..CoreInv.."/html/img/"..(Items[item].image or "") + end, + openShop = + function(data) + -- + end, + registerShop = + function(name, label, items, society) + -- + end, + openStash = + function(data) + TriggerServerEvent('core_inventory:server:openInventory', data.stash, 'stash') + end, + clearStash = + function(stashId) + exports[CoreInv]:clearInventory("stash-"..stashId) + end, + getStash = + function(stashName) + return exports[CoreInv]:getInventory(stashName) + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + exports[CoreInv]:removeItemExact(stashName, k, v) + debugPrint("^6Bridge^7: ^2Removing ^3"..CoreInv.." ^2Stash item^7:", k, v) + end + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, + }, + + { invName = OrigenInv, + removeItem = + function(src, item, remamount) + exports[OrigenInv]:removeItem(src, item, remamount) + end, + addItem = + function(src, item, amountToAdd, info, slot) + exports[OrigenInv]:addItem(src, item, amountToAdd, info, slot) + end, + setItemMetadata = + function(data, src) + exports[OrigenInv]:setMetadata(src, data.slot, data.metadata) + end, + hasItem = + function(item, amount, src) + if src then + local serverItemCheck = exports[OrigenInv]:getItemCount(src, item, false, false) or 0 + return serverItemCheck >= amount, serverItemCheck + else + local localItemCheck = exports[OrigenInv]:Search('count', item) or 0 + return localItemCheck >= amount, localItemCheck + end + end, + canCarry = + function(itemTable, src) + local resultTable = {} + for k, v in pairs(itemTable) do + resultTable[k] = exports[OrigenInv]:canCarryItem(src, k, v) + end + return resultTable + end, + getMaxInvWeight = + function() + return InventoryWeight + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = exports[OXInv]:GetInventoryItems(src) + else + grabInv = exports[OXInv]:GetPlayerItems() + end + return grabInv + end, + invImg = + function(item) + return "nui://"..OrigenInv.."/html/img/"..(Items[item].image or "") + end, + openShop = + function(data) + -- + end, + registerShop = + function(name, label, items, society) + -- + end, + openStash = + function(data) + exports[OrigenInv]:openInventory('stash', data.stash, { label = data.label }) + end, + clearStash = + function(stashId) + exports[OrigenInv]:ClearInventory(stashId) + end, + getStash = + function(stashName) + return exports[OrigenInv]:getInventory(stashName) + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + exports[OrigenInv]:RemoveFromStash(stashName, k, v) + debugPrint("^6Bridge^7: ^2Removing ^3"..OrigenInv.." ^2Stash item^7:", k, v) + end + end, + registerStash = + function(name, label, slots, weight, owner, coords) + exports[OrigenInv]:registerStash(name, label, slots or 50, weight or 4000000) + debugPrint("^6Bridge^7: ^2Registering ^4"..OrigenInv.." ^3Stash^7:", name, "^4Label^7: "..label) + end, + }, + + { invName = CodeMInv, + removeItem = + function(src, item, remamount) + exports[CodeMInv]:RemoveItem(src, item, remamount) + end, + addItem = + function(src, item, amountToAdd, info, slot) + exports[CodeMInv]:AddItem(src, item, amountToAdd, slot, info) + end, + setItemMetadata = + function(data, src) + exports[CodeMInv]:SetItemMetadata(src, data.slot, data.metadata) + end, + hasItem = + function(item, amount, src, invCache) + local count = 0 + for _, itemData in pairs(invCache) do + if itemData and itemData.name == item then + count += (itemData.amount or itemData.count or 1) end end - end - debugPrint("^6Bridge^7: ^3saveStash^7: ^2Saving ^3JPR^2 stash '^6"..stashName.."^7'") - MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['stash'] = stashName, - ['items'] = json.encode(stashItems) - }) - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, - }, - { - invName = QBInv, - removeItem = function(src, item, remamount) - if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, remamount, slot) then - TriggerClientEvent((isStarted(QBInv) and QBInvNew and "qb-" or "").."inventory:client:ItemBox", src, Items[item], "remove", amount or 1) - else - print("^1Error removing "..item.." Amount left: "..remamount) - end - end, - addItem = function(src, item, amountToAdd, info, slot) - 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) - end - end, - setItemMetadata = function(data, src) - local Player = Core.Functions.GetPlayer(src) - Player.PlayerData.items[data.slot].info = data.metadata - if data.metadata.durability then - Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability - end - Player.Functions.SetInventory(Player.PlayerData.items) - end, - canCarry = function(itemTable, src) - local resultTable = {} - if QBInvNew then - for k, v in pairs(itemTable) do - resultTable[k] = exports[QBInv]:CanAddItem(src, k, v) - end - else + return count >= amount, count + end, + canCarry = + function(itemTable, src) + local resultTable = {} local items = getPlayerInv(src) local totalWeight = 0 if not items then return false end @@ -601,93 +418,302 @@ local InvFunc = { resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight end end - end - return resultTable - end, - getMaxInvWeight = function() - if checkExportExists(QBInv, "GetMaxWeight") then - return exports[QBInv]:GetMaxWeight() - else + return resultTable + end, + getMaxInvWeight = + function() return InventoryWeight - end - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = Core.Functions.GetPlayer(src).PlayerData.items - else - grabInv = Core.Functions.GetPlayerData().items - end - return grabInv - end, - invImg = function(item) - return "nui://"..QBInv.."/html/images/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) - end, - registerShop = function(name, label, items, society) - if checkExportExists(QBInv, "CreateShop") then - exports[QBInv]:CreateShop({ - name = name, - label = label, - slots = #items, - items = items, - society = society, - }) - debugPrint("^6Bridge^7: ^2Registering ^5"..QBInv.." ^3Store^7:", name, "^4Label^7: "..label) - end - end, - openStash = function(data) - if QBInvNew then + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = exports[CodeMInv]:GetInventory(getPlayer(src).citizenId, src) + else + grabInv = exports[CodeMInv]:getUserInventory() + end + return grabInv + end, + invImg = + function(item) + return "nui://"..CodeMInv.."/html/itemimages/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerEvent("codem-inventory:openshop", data.shop) + end, + registerShop = + function(name, label, items, society) + -- + end, + openStash = + function(data) + TriggerServerEvent('codem-inventory:server:openstash', data.stash, data.slots, data.maxWeight, data.label) + end, + clearStash = + function(stashId) + exports[CodeMInv]:ClearInventory(stashId) + end, + getStash = + function(stashName) + return exports[CodeMInv]:GetStashItems(stashName) + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + for l in pairs(stashItems) do + if stashItems[l].name == k then + if (stashItems[l].amount - v) <= 0 then + stashItems[l] = nil + else + debugPrint("^6Bridge^7: ^2Removing ^3"..CodeMInv.." ^2Stash item^7:", k, v) + stashItems[l].amount -= v + end + end + end + end + exports[CodeMInv]:UpdateStash(stashName, stashItems) + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, + }, + + { invName = TgiannInv, + removeItem = + function(src, item, remamount) + exports[TgiannInv]:RemoveItem(src, item, remamount) + end, + addItem = + function(src, item, amountToAdd, info, slot) + exports[TgiannInv]:AddItem(src, item, amountToAdd, slot, info) + end, + setItemMetadata = + function(data, src) + exports[TgiannInv]:UpdateItemMetadata(src, data.item, data.slot, data.metadata) + end, + hasItem = + function(item, amount, src) + if src then + local serverItemCheck = exports[TgiannInv]:GetItem(src, item, nil, true) or 0 + return serverItemCheck >= amount, serverItemCheck + else + local localItemCheck = exports[TgiannInv]:GetItemCount(item) or 0 + return localItemCheck >= amount, localItemCheck + end + end, + canCarry = + function(itemTable, src) + local resultTable = {} + for k, v in pairs(itemTable) do + resultTable[k] = exports[TgiannInv]:CanCarryItem(src, k, v) + end + return resultTable + end, + getMaxInvWeight = + function() + return InventoryWeight + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = exports[TgiannInv]:GetPlayerItems(src) + else + grabInv = exports[TgiannInv]:GetPlayerItems() + end + return grabInv + end, + invImg = + function(item) + return "nui://inventory_images/images/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + end, + registerShop = + function(name, label, items, society) + exports[TgiannInv]:RegisterShop(name, items) + debugPrint("^6Bridge^7: ^2Registering ^5"..TgiannInv.." ^3Store^7:", name, "^4Label^7: "..label) + end, + openStash = + function(data) TriggerServerEvent(getScript()..':server:openServerStash', { stashName = data.stash, label = data.label, maxweight = data.maxWeight or 600000, slots = data.slots or 40 }) - else - TriggerEvent("inventory:client:SetCurrentStash", data.stash) - TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { - slots = data.slots or 50, - maxWeight = data.maxWeight or 600000 + end, + clearStash = + function(stashId) + exports[TgiannInv]:DeleteInventory("stash", stashId) + end, + getStash = + function(stashName) + return exports[TgiannInv]:GetSecondaryInventoryItems("stash", stashName) + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + local itemData = exports[TgiannInv]:GetItemByNameFromSecondaryInventory("stash", stashName, k) + exports[TgiannInv]:RemoveItemFromSecondaryInventory("stash", stashName, k, v, itemData.slot, nil) + debugPrint("^6Bridge^7: ^2Removing ^3"..TgiannInv.." ^2Stash item^7:", k, v) + end + end, + registerStash = + function(name, label, slots, weight, owner, coords) + exports[TgiannInv]:RegisterStash(name, label, slots or 50, weight or 4000000) + debugPrint("^6Bridge^7: ^2Registering ^4"..TgiannInv.." ^3Stash^7:", name, "^4Label^7: "..label) + end, + }, + + { invName = JPRInv, + removeItem = + function(src, item, remamount) + 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 + end, + addItem = + function(src, item, amountToAdd, info, slot) + 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 + end, + setItemMetadata = + function(data, src) + local Player = Core.Functions.GetPlayer(src) + Player.PlayerData.items[data.slot].info = data.metadata + if data.metadata.durability then + Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability + end + Player.Functions.SetInventory(Player.PlayerData.items) + end, + hasItem = + function(item, amount, src, invCache) + local count = 0 + for _, itemData in pairs(invCache) do + if itemData and itemData.name == item then + count += (itemData.amount or itemData.count or 1) + end + end + return count >= amount, count + end, + canCarry = + function(itemTable, src) + local resultTable = {} + 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 + return resultTable + end, + getMaxInvWeight = + function() + if checkExportExists(JPRInv, "GetMaxWeight") then + return exports[JPRInv]:GetMaxWeight() + else + return InventoryWeight + end + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = Core.Functions.GetPlayer(src).PlayerData.items + else + grabInv = Core.Functions.GetPlayerData().items + end + return grabInv + end, + invImg = + function(item) + return "nui://"..JPRInv.."/html/images/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + end, + registerShop = + function(name, label, items, society) + exports[JPRInv]:CreateShop({ + name = name, + label = label, + slots = #items, + items = items }) - end - end, - clearStash = function(stashId) - if QBInvNew then - exports[QBInv]:ClearStash(stashId) - else + end, + openStash = + function(data) + if QBInvNew then + TriggerServerEvent(getScript()..':server:openServerStash', { + stashName = data.stash, + label = data.label, + maxweight = data.maxWeight or 600000, + slots = data.slots or 40 + }) + else + TriggerEvent("inventory:client:SetCurrentStash", data.stash) + TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { + slots = data.slots or 50, + maxWeight = data.maxWeight or 600000 + }) + end + end, + clearStash = + function(stashId) MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { ['stash'] = stashId, ['items'] = json.encode({}) }) - end - end, - getStash = function(stashName) - if QBInvNew then - local result = exports[QBInv]:GetInventory(stashName) or {} - return result.items or {} - else + end, + getStash = + function(stashName) local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) if result then return json.decode(result) else return {} end - end - end, - stashAddItem = function(stashItems, stashName, items) - - end, - stashRemoveItem = function(stashItems, stashName, items) - if QBInvNew then - for k, v in pairs(items) do - exports[QBInv]:RemoveItem(stashName, k, v, false, 'crafting') - debugPrint("^6Bridge^7: ^2Removing ^3"..QBInv.." ^2Stash item^7:", k, v) - end - else + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) if not stashItems or not next(stashItems) then stashItems = getStash(stashName) end @@ -697,260 +723,491 @@ local InvFunc = { if (stashItems[l].amount - v) <= 0 then stashItems[l] = nil else - debugPrint("^6Bridge^7: ^2Removing ^3"..QBInv.." ^2Stash item^7:", k, v) + debugPrint("^6Bridge^7: ^2Removing ^3"..JPRInv.." ^2Stash item^7:", k, v) stashItems[l].amount -= v end end end end - debugPrint("^6Bridge^7: ^3saveStash^7: ^2Saving ^3QB^2 stash '^6"..stashName.."^7'") + debugPrint("^6Bridge^7: ^3saveStash^7: ^2Saving ^3JPR^2 stash '^6"..stashName.."^7'") MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { ['stash'] = stashName, ['items'] = json.encode(stashItems) }) - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, }, - { - invName = PSInv, - removeItem = function(src, item, remamount) - while remamount > 0 do - if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then - remamount -= 1 + + { invName = QBInv, + removeItem = + function(src, item, remamount) + if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, remamount, slot) then + TriggerClientEvent((isStarted(QBInv) and QBInvNew and "qb-" or "").."inventory:client:ItemBox", src, Items[item], "remove", amount or 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 - end, - addItem = function(src, item, amountToAdd, info, slot) - 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, + addItem = + function(src, item, amountToAdd, info, slot) + 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) end - end - end, - setItemMetadata = function(data, src) - --debugPrint(src, data.item, 1, data.slot) - local Player = Core.Functions.GetPlayer(src) - Player.PlayerData.items[data.slot].info = data.metadata - if data.metadata.durability then - Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability - end - Player.Functions.SetInventory(Player.PlayerData.items) - end, - canCarry = function(itemTable, src) - local resultTable = {} - 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 + end, + setItemMetadata = + function(data, src) + local Player = Core.Functions.GetPlayer(src) + Player.PlayerData.items[data.slot].info = data.metadata + if data.metadata.durability then + Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability + end + Player.Functions.SetInventory(Player.PlayerData.items) + end, + hasItem = + function(item, amount, src, invCache) + local count = 0 + for _, itemData in pairs(invCache) do + if itemData and itemData.name == item then + count += (itemData.amount or itemData.count or 1) + end + end + return count >= amount, count + end, + canCarry = + function(itemTable, src) + local resultTable = {} + if QBInvNew then + for k, v in pairs(itemTable) do + resultTable[k] = exports[QBInv]:CanAddItem(src, k, v) + end else - resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight + 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 end - end - return resultTable - end, - getMaxInvWeight = function() - if checkExportExists(PSInv, "GetMaxWeight") then - return exports[PSInv]:GetMaxWeight() - else - return InventoryWeight - end - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = Core.Functions.GetPlayer(src).PlayerData.items - else - grabInv = Core.Functions.GetPlayerData().items - end - return grabInv - end, - invImg = function(item) - return "nui://"..PSInv.."/html/images/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) - end, - registerShop = function(name, label, items, society) - if checkExportExists(PSInv, "CreateShop") then - exports[PSInv]:CreateShop({ + return resultTable + end, + getMaxInvWeight = + function() + if checkExportExists(QBInv, "GetMaxWeight") then + return exports[QBInv]:GetMaxWeight() + else + return InventoryWeight + end + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = Core.Functions.GetPlayer(src).PlayerData.items + else + grabInv = Core.Functions.GetPlayerData().items + end + return grabInv + end, + invImg = + function(item) + return "nui://"..QBInv.."/html/images/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + end, + registerShop = + function(name, label, items, society) + if checkExportExists(QBInv, "CreateShop") then + exports[QBInv]:CreateShop({ + name = name, + label = label, + slots = #items, + items = items, + society = society, + }) + debugPrint("^6Bridge^7: ^2Registering ^5"..QBInv.." ^3Store^7:", name, "^4Label^7: "..label) + end + end, + openStash = + function(data) + if QBInvNew then + TriggerServerEvent(getScript()..':server:openServerStash', { + stashName = data.stash, + label = data.label, + maxweight = data.maxWeight or 600000, + slots = data.slots or 40 + }) + else + TriggerEvent("inventory:client:SetCurrentStash", data.stash) + TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { + slots = data.slots or 50, + maxWeight = data.maxWeight or 600000 + }) + end + end, + clearStash = + function(stashId) + if QBInvNew then + exports[QBInv]:ClearStash(stashId) + else + MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['stash'] = stashId, + ['items'] = json.encode({}) + }) + end + end, + getStash = + function(stashName) + if QBInvNew then + local result = exports[QBInv]:GetInventory(stashName) or {} + return result.items or {} + else + local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) + if result then + return json.decode(result) + else + return {} + end + end + end, + stashAddItem = + function(stashItems, stashName, items) + -- + end, + stashRemoveItem = + function(stashItems, stashName, items) + if QBInvNew then + for k, v in pairs(items) do + exports[QBInv]:RemoveItem(stashName, k, v, false, 'crafting') + debugPrint("^6Bridge^7: ^2Removing ^3"..QBInv.." ^2Stash item^7:", k, v) + end + else + if not stashItems or not next(stashItems) then + stashItems = getStash(stashName) + end + for k, v in pairs(items) do + for l in pairs(stashItems) do + if stashItems[l].name == k then + if (stashItems[l].amount - v) <= 0 then + stashItems[l] = nil + else + debugPrint("^6Bridge^7: ^2Removing ^3"..QBInv.." ^2Stash item^7:", k, v) + stashItems[l].amount -= v + end + end + end + end + debugPrint("^6Bridge^7: ^3saveStash^7: ^2Saving ^3QB^2 stash '^6"..stashName.."^7'") + MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['stash'] = stashName, + ['items'] = json.encode(stashItems) + }) + end + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, + }, + + { invName = PSInv, + removeItem = + function(src, item, remamount) + 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 + end, + addItem = + function(src, item, amountToAdd, info, slot) + 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 + end, + setItemMetadata = + function(data, src) + --debugPrint(src, data.item, 1, data.slot) + local Player = Core.Functions.GetPlayer(src) + Player.PlayerData.items[data.slot].info = data.metadata + if data.metadata.durability then + Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability + end + Player.Functions.SetInventory(Player.PlayerData.items) + end, + hasItem = + function(item, amount, src, invCache) + local count = 0 + for _, itemData in pairs(invCache) do + if itemData and itemData.name == item then + count += (itemData.amount or itemData.count or 1) + end + end + return count >= amount, count + end, + canCarry = + function(itemTable, src) + local resultTable = {} + 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 + return resultTable + end, + getMaxInvWeight = + function() + if checkExportExists(PSInv, "GetMaxWeight") then + return exports[PSInv]:GetMaxWeight() + else + return InventoryWeight + end + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = Core.Functions.GetPlayer(src).PlayerData.items + else + grabInv = Core.Functions.GetPlayerData().items + end + return grabInv + end, + invImg = + function(item) + return "nui://"..PSInv.."/html/images/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + end, + registerShop = + function(name, label, items, society) + if checkExportExists(PSInv, "CreateShop") then + exports[PSInv]:CreateShop({ + name = name, + label = label, + slots = #items, + items = items, + society = society, + }) + debugPrint("^6Bridge^7: ^2Registering ^5"..PSInv.." ^3Store^7:", name, "^4Label^7: "..label) + end + end, + openStash = + function(data) + if QBInvNew then + TriggerServerEvent(getScript()..':server:openServerStash', { + stashName = data.stash, + label = data.label, + maxweight = data.maxWeight or 600000, + slots = data.slots or 40 + }) + else + TriggerEvent("ps-inventory:client:SetCurrentStash", data.stash) + TriggerEvent("inventory:client:SetCurrentStash", data.stash) + TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { + slots = data.slots or 50, + maxWeight = data.maxWeight or 600000 + }) + end + end, + clearStash = + function(stashId) + MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['stash'] = stashId, + ['items'] = json.encode({}) + }) + end, + getStash = + function(stashName) + local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) + if result then + return json.decode(result) + else + return {} + end + end, + stashAddItem = + function(stashItems, stashName, items) + + end, + stashRemoveItem = + function(stashItems, stashName, items) + if not stashItems or not next(stashItems) then + stashItems = getStash(stashName) + end + for k, v in pairs(items) do + for l in pairs(stashItems) do + if stashItems[l].name == k then + if (stashItems[l].amount - v) <= 0 then + stashItems[l] = nil + else + debugPrint("^6Bridge^7: ^2Removing ^3"..PSInv.." ^2Stash item^7:", k, v) + stashItems[l].amount -= v + end + end + end + end + debugPrint("^6Bridge^7: ^3saveStash^7: ^2Saving ^3PS^2 stash ^7'^6"..stashName.."^7'") + MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['stash'] = stashName, + ['items'] = json.encode(stashItems) + }) + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, + }, + + { invName = RSGInv, + removeItem = + function(src, item, remamount) + 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("rsg-inventory:client:ItemBox", src, Items[item], "remove", amount or 1) + end + end, + addItem = + function(src, item, amountToAdd, info, slot) + if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then + TriggerClientEvent("rsg-inventory:client:ItemBox", src, Items[item], "add", amountToAdd) + end + end, + setItemMetadata = + function(data, src) + local Player = Core.Functions.GetPlayer(src) + Player.PlayerData.items[data.slot].info = data.metadata + if data.metadata.durability then + Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability + end + Player.Functions.SetInventory(Player.PlayerData.items) + end, + hasItem = + function(item, amount, src, invCache) + local count = 0 + for _, itemData in pairs(invCache) do + if itemData and itemData.name == item then + count += (itemData.amount or itemData.count or 1) + end + end + return count >= amount, count + end, + canCarry = + function(itemTable, src) + local resultTable = {} + for k, v in pairs(itemTable) do + resultTable[k] = exports[OXInv]:CanCarryItem(src, k, v) + end + return resultTable + end, + getMaxInvWeight = + function() + if checkExportExists(RSGInv, "GetMaxWeight") then + return exports[RSGInv]:GetMaxWeight() + else + return InventoryWeight + end + end, + getPlayerInv = + function(src) + local grabInv = nil + if src then + grabInv = Core.Functions.GetPlayer(src).PlayerData.items + else + grabInv = Core.Functions.GetPlayerData().items + end + return grabInv + end, + invImg = + function(item) + return "nui://"..RSGInv.."/html/images/"..(Items[item].image or "") + end, + openShop = + function(data) + TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + end, + registerShop = + function(name, label, items, society) + exports[RSGInv]:CreateShop({ name = name, label = label, slots = #items, items = items, society = society, }) - debugPrint("^6Bridge^7: ^2Registering ^5"..PSInv.." ^3Store^7:", name, "^4Label^7: "..label) - end - end, - openStash = function(data) - if QBInvNew then + debugPrint("^6Bridge^7: ^2Registering ^5"..RSGInv.." ^3Store^7:", name, "^4Label^7: "..label) + end, + openStash = + function(data) TriggerServerEvent(getScript()..':server:openServerStash', { stashName = data.stash, label = data.label, maxweight = data.maxWeight or 600000, slots = data.slots or 40 }) - else - TriggerEvent("ps-inventory:client:SetCurrentStash", data.stash) - TriggerEvent("inventory:client:SetCurrentStash", data.stash) - TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash, { - slots = data.slots or 50, - maxWeight = data.maxWeight or 600000 - }) - end - end, - clearStash = function(stashId) - MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['stash'] = stashId, - ['items'] = json.encode({}) - }) - end, - getStash = function(stashName) - local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) - if result then - return json.decode(result) - else - return {} - end - end, - stashAddItem = function(stashItems, stashName, items) + end, + clearStash = + function(stashId) + exports[RSGInv]:ClearStash(stashId) + end, + getStash = + function(stashName) + return exports[RSGInv]:GetInventory(stashName) + end, + stashAddItem = + function(stashItems, stashName, items) - end, - stashRemoveItem = function(stashItems, stashName, items) - if not stashItems or not next(stashItems) then - stashItems = getStash(stashName) - end - for k, v in pairs(items) do - for l in pairs(stashItems) do - if stashItems[l].name == k then - if (stashItems[l].amount - v) <= 0 then - stashItems[l] = nil - else - debugPrint("^6Bridge^7: ^2Removing ^3"..PSInv.." ^2Stash item^7:", k, v) - stashItems[l].amount -= v - end - end + end, + stashRemoveItem = + function(stashItems, stashName, items) + for k, v in pairs(items) do + exports[RSGInv]:RemoveItem(stashName, k, v, false, 'crafting') + debugPrint("^6Bridge^7: ^2Removing ^3"..RSGInv.." ^2Stash item^7:", k, v) end - end - debugPrint("^6Bridge^7: ^3saveStash^7: ^2Saving ^3PS^2 stash ^7'^6"..stashName.."^7'") - MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['stash'] = stashName, - ['items'] = json.encode(stashItems) - }) - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, - }, - { - invName = RSGInv, - removeItem = function(src, item, remamount) - 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("rsg-inventory:client:ItemBox", src, Items[item], "remove", amount or 1) - end - end, - addItem = function(src, item, amountToAdd, info, slot) - if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then - TriggerClientEvent("rsg-inventory:client:ItemBox", src, Items[item], "add", amountToAdd) - end - end, - setItemMetadata = function(data, src) - local Player = Core.Functions.GetPlayer(src) - Player.PlayerData.items[data.slot].info = data.metadata - if data.metadata.durability then - Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability - end - Player.Functions.SetInventory(Player.PlayerData.items) - end, - canCarry = function(itemTable, src) - local resultTable = {} - for k, v in pairs(itemTable) do - resultTable[k] = exports[OXInv]:CanCarryItem(src, k, v) - end - return resultTable - end, - getMaxInvWeight = function() - if checkExportExists(RSGInv, "GetMaxWeight") then - return exports[RSGInv]:GetMaxWeight() - else - return InventoryWeight - end - end, - getPlayerInv = function(src) - local grabInv = nil - if src then - grabInv = Core.Functions.GetPlayer(src).PlayerData.items - else - grabInv = Core.Functions.GetPlayerData().items - end - return grabInv - end, - invImg = function(item) - return "nui://"..RSGInv.."/html/images/"..(Items[item].image or "") - end, - openShop = function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - end, - registerShop = function(name, label, items, society) - exports[RSGInv]:CreateShop({ - name = name, - label = label, - slots = #items, - items = items, - society = society, - }) - debugPrint("^6Bridge^7: ^2Registering ^5"..RSGInv.." ^3Store^7:", name, "^4Label^7: "..label) - end, - openStash = function(data) - TriggerServerEvent(getScript()..':server:openServerStash', { - stashName = data.stash, - label = data.label, - maxweight = data.maxWeight or 600000, - slots = data.slots or 40 - }) - end, - clearStash = function(stashId) - exports[RSGInv]:ClearStash(stashId) - end, - getStash = function(stashName) - return exports[RSGInv]:GetInventory(stashName) - end, - stashAddItem = function(stashItems, stashName, items) - - end, - stashRemoveItem = function(stashItems, stashName, items) - for k, v in pairs(items) do - exports[RSGInv]:RemoveItem(stashName, k, v, false, 'crafting') - debugPrint("^6Bridge^7: ^2Removing ^3"..RSGInv.." ^2Stash item^7:", k, v) - end - end, - registerStash = function(name, label, slots, weight, owner, coords) - -- - end, + end, + registerStash = + function(name, label, slots, weight, owner, coords) + -- + end, }, } @@ -1000,34 +1257,30 @@ function hasItem(items, amount, src) local grabInv, foundInv = getPlayerInv(src) if type(items) ~= "table" then items = { [items] = amount and amount or 1, } end - if grabInv then - local hasTable = {} - for item, amt in pairs(items) do - if not Items[item] then print("^4ERROR^7: ^2Script can't find ingredient item in Shared Items - ^1"..item.."^7") end + local hasTable = {} + for item, amt in pairs(items) do + if not doesItemExist(item) then + print("^4ERROR^7: ^2Script can't find ingredient item in Shared Items - ^1"..item.."^7") + end + for k, inv in ipairs(InvFunc) do + if isStarted(inv.invName) then + local hasItem, count = inv.hasItem(item, amt, src, grabInv) - local count = 0 - for _, itemData in pairs(grabInv) do - --jsonPrint(itemData) - if itemData and itemData.name == item then - count += (itemData.amount or itemData.count or 1) - end - end - foundInv = foundInv:gsub("%-", "^7-^6"):gsub("%_", "^7_^6") - local foundMessage = "^6Bridge^7: ^3hasItem^7[^6"..foundInv.."^7]: "..tostring(item).." ^3"..count.."^7/^3"..amt - if count >= amt then foundMessage = foundMessage.." ^5FOUND^7" else foundMessage = foundMessage .." ^1NOT FOUND^7" end - debugPrint(foundMessage) - hasTable[item] = { hasItem = count >= amt, count = count } - end - for k, v in pairs(hasTable) do - if not v.hasItem then - return false, hasTable + local foundMessage = "^6Bridge^7: ^3hasItem^7[^6"..foundInv.."^7]: "..tostring(item).." ^3"..count.."^7/^3"..amt + if count >= amt then foundMessage = foundMessage.." ^5FOUND^7" else foundMessage = foundMessage .." ^1NOT FOUND^7" end + debugPrint(foundMessage) + + hasTable[item] = { hasItem = hasItem, count = count } + break end end - return true, hasTable end - -- if can't find inventory, return false - print("^1Error^7: ^1Can't find players inventory for some reason") - return false, {} + for k, v in pairs(hasTable) do + if not v.hasItem then + return false, hasTable + end + end + return true, hasTable end --- Retrieves a player's inventory based on the active inventory system. @@ -1516,8 +1769,7 @@ function canCarry(itemTable, src) local resultTable = {} for _, inv in pairs(InvFunc) do if isStarted(inv.invName) then - resultTable = inv.canCarry(itemTable, src) - break + return inv.canCarry(itemTable, src) end end return resultTable @@ -2000,7 +2252,11 @@ function stashhasItem(stashItems, items, amount) hasTable[item] = { hasItem = (count >= requiredAmount), count = count } end - for k, v in pairs(hasTable) do if v.hasItem == false then return false, hasTable end end + for k, v in pairs(hasTable) do + if v.hasItem == false then + return false, hasTable + end + end return true, hasTable end From 0bcf1b7ed490338f2001dff9b824c5d0f3a3f39e Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Thu, 14 Aug 2025 13:34:55 +0100 Subject: [PATCH 02/10] Prefer export checks over QBInvNew Small changes for JPRInv too --- shared/itemcontrol.lua | 76 +++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/shared/itemcontrol.lua b/shared/itemcontrol.lua index 4b5c18f..1dfadc0 100644 --- a/shared/itemcontrol.lua +++ b/shared/itemcontrol.lua @@ -69,6 +69,9 @@ local InvFunc = { function(data) exports[OXInv]:openInventory('shop', { type = data.shop }) end, + serverOpenShop = function(shopName) + -- + end, registerShop = function(name, label, items, society) exports[OXInv]:RegisterShop(name, { @@ -168,6 +171,9 @@ local InvFunc = { function(data) TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) end, + serverOpenShop = function(shopName) + -- + end, registerShop = function(name, label, items, society) -- @@ -258,6 +264,10 @@ local InvFunc = { function(data) -- end, + serverOpenShop = + function(shopName) + -- + end, registerShop = function(name, label, items, society) -- @@ -344,6 +354,10 @@ local InvFunc = { function(data) -- end, + serverOpenShop = + function(shopName) + -- + end, registerShop = function(name, label, items, society) -- @@ -442,6 +456,10 @@ local InvFunc = { function(data) TriggerEvent("codem-inventory:openshop", data.shop) end, + serverOpenShop = + function(shopName) + -- + end, registerShop = function(name, label, items, society) -- @@ -537,6 +555,10 @@ local InvFunc = { function(data) TriggerServerEvent(getScript()..':server:openServerShop', data.shop) end, + serverOpenShop = + function(shopName) + exports[TgiannInv]:OpenShop(source, shopName) + end, registerShop = function(name, label, items, society) exports[TgiannInv]:RegisterShop(name, items) @@ -666,6 +688,12 @@ local InvFunc = { TriggerServerEvent(getScript()..':server:openServerShop', data.shop) TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) end, + serverOpenShop = + function(shopName) + if checkExportExists(JPRInv, "OpenShop") then + exports[JPRInv]:OpenShop(source, shopName) + end + end, registerShop = function(name, label, items, society) exports[JPRInv]:CreateShop({ @@ -701,11 +729,11 @@ local InvFunc = { end, getStash = function(stashName) - local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) - if result then - return json.decode(result) + if checkExportExists(JPRInv, "GetStashItems") then + return exports[JPRInv]:GetStashItems(stashName) or {} else - return {} + local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName }) + return result and json.decode(result) or {} end end, stashAddItem = @@ -778,7 +806,7 @@ local InvFunc = { canCarry = function(itemTable, src) local resultTable = {} - if QBInvNew then + if checkExportExists(QBInv, "CanAddItem") then for k, v in pairs(itemTable) do resultTable[k] = exports[QBInv]:CanAddItem(src, k, v) end @@ -827,6 +855,12 @@ local InvFunc = { TriggerServerEvent(getScript()..':server:openServerShop', data.shop) TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) end, + serverOpenShop = + function(shopName) + if checkExportExists(QBInv, "OpenShop") then + exports[QBInv]:OpenShop(source, shopName) + end + end, registerShop = function(name, label, items, society) if checkExportExists(QBInv, "CreateShop") then @@ -859,7 +893,7 @@ local InvFunc = { end, clearStash = function(stashId) - if QBInvNew then + if checkExportExists(QBInv, "ClearStash") then exports[QBInv]:ClearStash(stashId) else MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { @@ -888,7 +922,7 @@ local InvFunc = { end, stashRemoveItem = function(stashItems, stashName, items) - if QBInvNew then + if checkExportExists(QBInv, "RemoveItem") then for k, v in pairs(items) do exports[QBInv]:RemoveItem(stashName, k, v, false, 'crafting') debugPrint("^6Bridge^7: ^2Removing ^3"..QBInv.." ^2Stash item^7:", k, v) @@ -1011,6 +1045,12 @@ local InvFunc = { TriggerServerEvent(getScript()..':server:openServerShop', data.shop) TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) end, + serverOpenShop = + function(shopName) + if checkExportExists(PSInv, "OpenShop") then + exports[PSInv]:OpenShop(source, shopName) + end + end, registerShop = function(name, label, items, society) if checkExportExists(PSInv, "CreateShop") then @@ -1165,6 +1205,10 @@ local InvFunc = { function(data) TriggerServerEvent(getScript()..':server:openServerShop', data.shop) end, + serverOpenShop = + function(shopName) + exports[RSGInv]:OpenShop(source, shopName) + end, registerShop = function(name, label, items, society) exports[RSGInv]:CreateShop({ @@ -2508,18 +2552,12 @@ function openShop(data) end end -RegisterNetEvent(getScript()..':server:openServerShop', function(data) - if isStarted(QBInv) and checkExportExists(QBInv, "OpenShop") then - exports[QBInv]:OpenShop(source, data) - end - if isStarted(PSInv) and checkExportExists(PSInv, "OpenShop") then - exports[PSInv]:OpenShop(source, data) - end - if isStarted(TgiannInv) then - exports[TgiannInv]:OpenShop(source, data) - end - if isStarted(RSGInv) then - exports[RSGInv]:OpenShop(source, data) +RegisterNetEvent(getScript()..':server:openServerShop', function(shopName) + for _, inv in ipairs(InvFunc) do + if isStarted(inv.invName) then + inv.serverOpenShop(shopName) + break + end end end) From bfca6984579b5fd2f9e3e874c8c30dd399cf39ce Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Thu, 14 Aug 2025 20:08:09 +0100 Subject: [PATCH 03/10] More + optimization --- shared/crafting.lua | 6 +- shared/drawText.lua | 164 +++++++------- shared/helpers.lua | 2 - shared/itemcontrol.lua | 56 +++-- shared/jobfunctions.lua | 1 - shared/make/progressBars.lua | 408 +++++++++++++++++++---------------- shared/metaHandlers.lua | 158 +++++++++----- shared/notify.lua | 123 ++++++----- shared/phones.lua | 253 ++++++++++------------ shared/polyZone.lua | 9 +- shared/skillcheck.lua | 122 ++++++----- shared/societybank.lua | 209 +++++++++--------- shared/targets.lua | 321 ++++++++++++++------------- 13 files changed, 997 insertions(+), 835 deletions(-) diff --git a/shared/crafting.lua b/shared/crafting.lua index e050ce5..93da037 100644 --- a/shared/crafting.lua +++ b/shared/crafting.lua @@ -124,10 +124,12 @@ function craftingMenu(data) itemTable[l] = b end - while not canCarryTable do Wait(0) end + while not canCarryTable do + Wait(10) + end disable = not checkStashItem(data.stashName, itemTable) setheader = ((metadata and metadata.label) or (Items[tostring(k)] and Items[tostring(k)].label) or "error - "..tostring(k)) - ..(Recipes[i]["amount"] > 1 and " x"..Recipes[i]["amount"] or "") + ..(Recipes[i]["amount"] > 1 and " x"..Recipes[i]["amount"] or "") local statusEmoji = disable and " " or not canCarryTable[k] and " 📦" or " ✔️" local isNew = (Recipes[i]["hasCrafted"] ~= nil and craftedItems[k] == nil) and "✨ " or "" diff --git a/shared/drawText.lua b/shared/drawText.lua index f8a4281..ede6b53 100644 --- a/shared/drawText.lua +++ b/shared/drawText.lua @@ -8,96 +8,108 @@ -- Text system handlers local textHandlers = { qb = { - show = function(text, image) - if image then - text = ''..text - end - exports[QBExport]:DrawText(text, 'left') - end, - hide = function() - exports[QBExport]:HideText() - end + show = + function(text, image) + if image then + text = ''..text + end + exports[QBExport]:DrawText(text, 'left') + end, + hide = + function() + exports[QBExport]:HideText() + end, }, ox = { - show = function(input, image, oxStyleTable) - local inputCount = #input - for i = 1, inputCount do - input[i] = input[i] .. (i ~= inputCount and " \n" or "") - end - lib.showTextUI(table.concat(input), { - icon = (image and radarTable[image] or image) or nil, - position = 'left-center', - style = oxStyleTable - }) - end, - hide = function() - lib.hideTextUI() - end + show = + function(input, image, oxStyleTable) + local inputCount = #input + for i = 1, inputCount do + input[i] = input[i] .. (i ~= inputCount and " \n" or "") + end + lib.showTextUI(table.concat(input), { + icon = (image and radarTable[image] or image) or nil, + position = 'left-center', + style = oxStyleTable + }) + end, + hide = + function() + lib.hideTextUI() + end, }, lation = { - show = function(input, image) - local inputCount = #input - for i = 1, inputCount do - input[i] = input[i] .. (i ~= inputCount and " \n" or "") - end - exports.lation_ui:showText({ - description = table.concat(input), - keybind = nil, - icon = (image and radarTable[image] or image) or nil, - iconColor = '#3B82F6', - position = 'left-center' - }) - end, - hide = function() - exports.lation_ui:hideText() - end - }, - - gta = { - show = function(input, image, style) - local text = "" - for i = 1, #input do - if input[i] ~= "" then - text = text .. input[i] .. "\n~s~" + show = + function(input, image) + local inputCount = #input + for i = 1, inputCount do + input[i] = input[i] .. (i ~= inputCount and " \n" or "") end - end - if image then - text = "~BLIP_" .. image .. "~ " .. text - end - DisplayHelpMsg(text:gsub("%:", ":~" .. (style or "g") .. "~")) - end, - hide = function() - ClearAllHelpMessages() - end + exports.lation_ui:showText({ + description = table.concat(input), + keybind = nil, + icon = (image and radarTable[image] or image) or nil, + iconColor = '#3B82F6', + position = 'left-center' + }) + end, + hide = + function() + exports.lation_ui:hideText() + end, }, esx = { - show = function(text, image) - if image then - text = ''..text - end - ESX.TextUI(text, nil) - end, - hide = function() - ESX.HideUI() - end + show = + function(text, image) + if image then + text = ''..text + end + ESX.TextUI(text, nil) + end, + hide = + function() + ESX.HideUI() + end, + }, + + gta = { + show = + function(input, image, style) + local text = "" + for i = 1, #input do + if input[i] ~= "" then + text = text .. input[i] .. "\n~s~" + end + end + if image then + text = "~BLIP_" .. image .. "~ " .. text + end + DisplayHelpMsg(text:gsub("%:", ":~" .. (style or "g") .. "~")) + end, + hide = + function() + ClearAllHelpMessages() + end, }, red = { - show = function(input) - local text = "" - for i = 1, #input do - if input[i] ~= "" then - text = text .. input[i] .. "\n~q~" + show = + function(input) + local text = "" + for i = 1, #input do + if input[i] ~= "" then + text = text .. input[i] .. "\n~q~" + end end - end - TriggerEvent("jim-redui:DrawText", text) - end, - hide = function() - TriggerEvent("jim-redui:HideText") - end + TriggerEvent("jim-redui:DrawText", text) + end, + hide = + function() + TriggerEvent("jim-redui:HideText") + end, } } diff --git a/shared/helpers.lua b/shared/helpers.lua index 0ef454b..188077e 100644 --- a/shared/helpers.lua +++ b/shared/helpers.lua @@ -73,8 +73,6 @@ function checkExportExists(resource, export) end end - - ------------------------------------------------------------- -- Debugging and JSON Utilities ------------------------------------------------------------- diff --git a/shared/itemcontrol.lua b/shared/itemcontrol.lua index 1dfadc0..e6a912d 100644 --- a/shared/itemcontrol.lua +++ b/shared/itemcontrol.lua @@ -1306,7 +1306,8 @@ function hasItem(items, amount, src) if not doesItemExist(item) then print("^4ERROR^7: ^2Script can't find ingredient item in Shared Items - ^1"..item.."^7") end - for k, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then local hasItem, count = inv.hasItem(item, amt, src, grabInv) @@ -1344,7 +1345,8 @@ function getPlayerInv(src) local grabInv = nil local foundInv = "" - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then foundInv = inv.invName grabInv = inv.getPlayerInv(src) @@ -1380,7 +1382,8 @@ end function invImg(item) local imgLink = "" if item ~= "" and doesItemExist(item) then - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then imgLink = inv.invImg(item) break @@ -1535,10 +1538,10 @@ RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount, local src = (newsrc and tonumber(newsrc)) or source -- Only server resources may set newsrc; clients cannot. - if newsrc ~= nil and source ~= 0 then - debugPrint("^1DENY^7: client tried to set newsrc") - return - end + --if newsrc ~= nil and source ~= 0 then + -- debugPrint("^1DENY^7: client tried to set newsrc") + -- return + --end if (give == true or give == 1) then if newsrc == nil then -- this must be coming from client this would be blank @@ -1558,7 +1561,8 @@ RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount, dupeWarn(src, item, amount) else - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then invName = inv.invName inv.removeItem(src, item, remamount) @@ -1586,7 +1590,8 @@ RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount, end else local amountToAdd = amount or 1 - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then invName = inv.invName inv.addItem(src, item, amountToAdd, info, slot) @@ -1734,7 +1739,8 @@ end --- ``` RegisterNetEvent(getScript()..":server:setItemMetaData", function(data, src) local src = src or source - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then inv.setItemMetadata(data, src) break @@ -1811,7 +1817,8 @@ end --- end function canCarry(itemTable, src) local resultTable = {} - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then return inv.canCarry(itemTable, src) end @@ -1851,7 +1858,8 @@ end function getMaxInvWeight() local weight = 0 - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then weight = inv.getMaxInvWeight() break @@ -2106,7 +2114,8 @@ end function openStash(data) if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then inv.openStash(data) lookEnt(data.coords) @@ -2147,7 +2156,8 @@ RegisterNetEvent(getScript()..":server:openServerStash", function(data) end) function clearStash(stashId) - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then debugPrint("^5Bridge^7: ^2Clearing ^3"..inv.invName.."^2 Stash^7:", stashId) inv.clearStash(stashId) @@ -2180,7 +2190,8 @@ function getStash(stashName) end local stashItems, items = {}, {} - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then debugPrint("^6Bridge^7: ^2Retrieving ^3"..inv.invName.." ^2Stash^7:", stashName) stashItems = inv.getStash(stashName) @@ -2240,7 +2251,8 @@ function stashRemoveItem(stashItems, stashName, items) stashName = { stashName } end - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then inv.stashRemoveItem(stashItems, stashName[1], items) return @@ -2327,7 +2339,8 @@ end --- ) --- ``` function registerStash(name, label, slots, weight, owner, coords) - for _, inv in pairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then inv.registerStash(name, label, slots, weight, owner, coords) return @@ -2543,7 +2556,8 @@ function openShop(data) lookEnt(data.coords) end - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then inv.openShop(data) lookEnt(data.coords) @@ -2553,7 +2567,8 @@ function openShop(data) end RegisterNetEvent(getScript()..':server:openServerShop', function(shopName) - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then inv.serverOpenShop(shopName) break @@ -2575,7 +2590,8 @@ end) function registerShop(name, label, items, society) local shopResource = "" - for _, inv in ipairs(InvFunc) do + for i = 1, #InvFunc do + local inv = InvFunc[i] if isStarted(inv.invName) then shopResource = inv.invName inv.registerShop(name, label, items, society) diff --git a/shared/jobfunctions.lua b/shared/jobfunctions.lua index 7dff529..c304f9b 100644 --- a/shared/jobfunctions.lua +++ b/shared/jobfunctions.lua @@ -247,7 +247,6 @@ function useDoor(data) Wait(100) end - function openBossMenu(isGang, group) if isStarted("qb-management") then if isGang then diff --git a/shared/make/progressBars.lua b/shared/make/progressBars.lua index c5663db..3c7b77a 100644 --- a/shared/make/progressBars.lua +++ b/shared/make/progressBars.lua @@ -1,6 +1,226 @@ local inProgress = false local storedPID = nil + +local progressFunc = { + ox = { + start = function(data) + local options = { + duration = debugMode and 1000 or data.time, + label = data.label, + position = data.position or "bottom", + useWhileDead = data.dead or false, + canCancel = data.cancel or true, + anim = { + dict = data.dict, + clip = data.anim, + flag = (data.flag == 8 and 32 or data.flag) or nil, + scenario = data.task + }, + disable = { + combat = data.combat or true, + move = data.disableMovement or false, + car = data.disableMovement or false, + mouse = data.mouse or false + }, + } + if data.prop and data.prop.model then + options.prop = { + model = data.prop.model, + pos = data.prop.pos or vec3(0, 0, 0), + rot = data.prop.rot or vec3(0, 0, 0), + bone = data.prop.bone or 0 + } + end + if data.propTwo and data.propTwo.model then + options.propTwo = { + model = data.propTwo.model, + pos = data.propTwo.pos or vec3(0, 0, 0), + rot = data.propTwo.rot or vec3(0, 0, 0), + bone = data.propTwo.bone or 0 + } + end + if data.progressType == "circle" then + if exports[OXLibExport]:progressCircle(options) then + return true + else + return false + end + end + if not data.progressType or data.progressType == "bar" then + if exports[OXLibExport]:progressBar(options) then + return true + else + return false + end + end + end, + stop = function() + exports[OXLibExport]:cancelProgress() + end, + }, + + qb = { + start = function(data) + Core.Functions.Progressbar("progbar", + data.label, + debugMode and 1000 or data.time, + data.dead or false, + data.cancel or true, + { + disableMovement = data.disableMovement or false, + disableCarMovement = data.disableMovement or false, + disableMouse = data.disableMouse or false, + disableCombat = data.disableCombat or true, + }, + { + animDict = data.dict, + anim = data.anim, + flags = data.flag or 32, + task = data.task + }, + {}, {}, + function() + return true + end, function() + return false + end, data.icon) + end, + stop = function() + TriggerEvent("progressbar:client:cancel") + end, + }, + + qs = { + start = function(data) + if exports['qs-interface']:ProgressBar({ + duration = debugMode and 1000 or data.time, + label = data.label, + position = 'bottom', + useWhileDead = data.dead or false, + canCancel = data.cancel or true, + disable = data.disableMovement or false, + anim = { + dict = data.dict, + clip = data.anim, + flag = data.flag or 32 + }, + prop = nil + }) then + return true + else + return false + end + end, + stop = function() + --?? + TriggerEvent("progressbar:client:cancel") + end, + }, + + esx = { + start = function(data) + ESX.Progressbar(data.label, debugMode and 1000 or data.time, { + FreezePlayer = true, + animation = { + type = data.anim, + dict = data.dict, + scenario = data.task, + }, + onFinish = function() + return true + end, + onCancel = function() + return false + end + }) + end, + stop = function() + ESX.CancelProgressbar() + end, + }, + + lation = { + start = function(data) + if exports.lation_ui:progressBar({ + label = data.label, + description = nil, + duration = debugMode and 1000 or data.time, + icon = data.icon, + useWhileDead = data.dead or false, + disable = { + combat = data.combat or true, + move = data.disableMovement or false, + car = data.disableMovement or false, + }, + anim = { + dict = data.dict, + clip = data.anim, + flag = data.flag + }, + prop = { + model = data.prop and data.prop.model, + pos = data.prop and (data.prop.pos or vec3(0, 0, 0)), + rot = data.prop and (data.prop.rot or vec3(0, 0, 0)), + bone = data.prop and (data.prop.bone or 0) + } + }) then + return true + else + return false + end + end, + stop = function() + exports.lation_ui:cancelProgress() + end, + }, + + red = { + start = function(data) + if exports.jim_bridge:redProgressBar({ + label = data.label, + time = debugMode and 1000 or data.time, + dict = data.dict, + anim = data.anim, + flag = data.flag or 32, + task = data.task, + disableMovement = data.disableMovement or false, + cancel = data.cancel or true, + }) then + return true + else + return false + end + end, + stop = function() + exports.jim_bridge:stopProgressBar() + end, + }, + + gta = { + start = function(data) + + if exports.jim_bridge:gtaProgressBar({ + label = data.label, + time = debugMode and 1000 or data.time, + dict = data.dict, + anim = data.anim, + flag = data.flag or 32, + task = data.task, + disableMovement = data.disableMovement or false, + cancel = data.cancel or true, + }) then + return true + else + return false + end + end, + stop = function() + exports.jim_bridge:stopProgressBar() + end, + }, +} + --- Displays a progress bar using the configured progress bar system. --- --- This function handles displaying a progress bar to the player using the specified progress bar system (e.g., ox, qb, esx, gta). @@ -43,181 +263,11 @@ function progressBar(data) end local result = nil if data.cam then startTempCam(data.cam) end - if Config.System.ProgressBar == "ox" then - local options = { - duration = debugMode and 1000 or data.time, - label = data.label, - position = data.position or "bottom", - useWhileDead = data.dead or false, - canCancel = data.cancel or true, - anim = { - dict = data.dict, - clip = data.anim, - flag = (data.flag == 8 and 32 or data.flag) or nil, - scenario = data.task - }, - disable = { - combat = data.combat or true, - move = data.disableMovement or false, - car = data.disableMovement or false, - mouse = data.mouse or false - }, - } - if data.prop and data.prop.model then - options.prop = { - model = data.prop.model, - pos = data.prop.pos or vec3(0, 0, 0), - rot = data.prop.rot or vec3(0, 0, 0), - bone = data.prop.bone or 0 - } - end - if data.propTwo and data.propTwo.model then - options.propTwo = { - model = data.propTwo.model, - pos = data.propTwo.pos or vec3(0, 0, 0), - rot = data.propTwo.rot or vec3(0, 0, 0), - bone = data.propTwo.bone or 0 - } - end - if data.progressType == "circle" then - if exports[OXLibExport]:progressCircle(options) then - result = true - else - result = false - end - end - if not data.progressType or data.progressType == "bar" then - if exports[OXLibExport]:progressBar(options) then - result = true - else - result = false - end - end - - elseif Config.System.ProgressBar == "qb" then - Core.Functions.Progressbar("progbar", - data.label, - debugMode and 1000 or data.time, - data.dead or false, - data.cancel or true, - { - disableMovement = data.disableMovement or false, - disableCarMovement = data.disableMovement or false, - disableMouse = data.disableMouse or false, - disableCombat = data.disableCombat or true, - }, - { - animDict = data.dict, - anim = data.anim, - flags = data.flag or 32, - task = data.task - }, - {}, {}, - function() - result = true - end, function() - result = false - end, data.icon) - - elseif Config.System.ProgressBar == "qs" then -- documentation left intact based on qs interface - local qs_success = exports['qs-interface']:ProgressBar({ - duration = debugMode and 1000 or data.time, -- Duration of the progress bar (in milliseconds) - label = data.label, -- Text that will appear on the progress bar - position = 'bottom', -- Position of the progress bar on the screen (e.g., 'top', 'bottom', 'center') - useWhileDead = data.dead or false, -- Whether the progress bar shows when the player is dead (true/false) - canCancel = data.cancel or true, -- Whether the player can cancel the progress (true/false) - disable = data.disableMovement or false, -- Whether to disable player controls during the progress (true/false) - anim = { -- Animation to be played while the progress is happening - dict = data.dict, - clip = data.anim, - flag = data.flag or 32 -- Optional animation flags - }, - prop = nil -- Optional prop to show alongside the progress bar (can be nil) - }) - if qs_success then - result = true - else - result = false - end - - elseif Config.System.ProgressBar == "esx" then - ESX.Progressbar(data.label, debugMode and 1000 or data.time, { - FreezePlayer = true, - animation = { - type = data.anim, - dict = data.dict, - scenario = data.task, - }, - onFinish = function() - result = true - end, - onCancel = function() - result = false - end - }) - - elseif Config.System.ProgressBar == "lation" then - if exports.lation_ui:progressBar({ - label = data.label, - description = nil, - duration = debugMode and 1000 or data.time, - icon = data.icon, - useWhileDead = data.dead or false, - disable = { - combat = data.combat or true, - move = data.disableMovement or false, - car = data.disableMovement or false, - }, - anim = { - dict = data.dict, - clip = data.anim, - flag = data.flag - }, - prop = { - model = data.prop and data.prop.model, - pos = data.prop and (data.prop.pos or vec3(0, 0, 0)), - rot = data.prop and (data.prop.rot or vec3(0, 0, 0)), - bone = data.prop and (data.prop.bone or 0) - } - }) then - result = true - else - result = false - end - - elseif Config.System.ProgressBar == "red" then - -- Currently only uses jim-redui if you choose this option - if exports["jim_bridge"]:redProgressBar({ - label = data.label, - time = debugMode and 1000 or data.time, - dict = data.dict, - anim = data.anim, - flag = data.flag or 32, - task = data.task, - disableMovement = data.disableMovement or false, - cancel = data.cancel or true, - }) then - result = true - else - result = false - end - - elseif Config.System.ProgressBar == "gta" then - if exports["jim_bridge"]:gtaProgressBar({ - label = data.label, - time = debugMode and 1000 or data.time, - dict = data.dict, - anim = data.anim, - flag = data.flag or 32, - task = data.task, - disableMovement = data.disableMovement or false, - cancel = data.cancel or true, - }) then - result = true - else - result = false - end + if progressFunc[Config.System.ProgressBar].start(data) then + result = true + else + result = false end while result == nil do @@ -250,15 +300,7 @@ end --- --- This function cancels the progress bar based on the configured progress bar system, handling any necessary cleanup. function stopProgressBar() - if Config.System.ProgressBar == "ox" then - exports[OXLibExport]:cancelProgress() - elseif Config.System.ProgressBar == "qb" then - TriggerEvent("progressbar:client:cancel") - elseif Config.System.ProgressBar == "lation" then - exports.lation_ui:cancelProgress() - elseif Config.System.ProgressBar == "gta" or Config.System.ProgressBar == "red" then - exports["jim_bridge"]:stopProgressBar() - end + progressFunc[Config.System.ProgressBar].stop() end -- System to handle sending/sharing progress bars between players -- diff --git a/shared/metaHandlers.lua b/shared/metaHandlers.lua index 515d248..9e66d7f 100644 --- a/shared/metaHandlers.lua +++ b/shared/metaHandlers.lua @@ -6,6 +6,82 @@ for getting and setting metadata. ]] +local metaDataFunc = { + { framework = QBXExport, + GetPlayer = + function(src) + return exports[QBXExport]:GetCoreObject().Functions.GetPlayer(src) + end, + GetPlayerMetadata = + function(Player, dataToCheck) + return Player.PlayerData.metadata[dataToCheck] + end, + SetPlayerMetadata = + function(Player, key, value) + return Player.Functions.SetMetaData(key, value) + end, + }, + + { framework = QBExport, + GetPlayer = + function(src) + return exports[QBExport]:GetCoreObject().Functions.GetPlayer(src) + end, + GetPlayerMetadata = + function(Player, dataToCheck) + return Player.PlayerData.metadata[dataToCheck] + end, + SetPlayerMetadata = + function(Player, key, value) + return Player.Functions.SetMetaData(key, value) + end, + }, + + { framework = ESXExport, + GetPlayer = + function(src) + return ESX.GetPlayerFromId(src) + end, + GetPlayerMetadata = + function(Player, dataToCheck) + return Player.getMeta(dataToCheck) + end, + SetPlayerMetadata = + function(Player, key, value) + return Player.set(key, value) + end, + }, + + { framework = OXCoreExport, + GetPlayer = + function(src) + return exports[OXCoreExport]:GetPlayer(src) + end, + GetPlayerMetadata = + function(Player, dataToCheck) + return Player.get(dataToCheck) + end, + SetPlayerMetadata = + function(Player, key, value) + return Player.set(key, value) + end, + }, + + { framework = RSGExport, + GetPlayer = function(src) + exports[RSGExport]:GetCoreObject().Functions.GetPlayer(source) + end, + GetPlayerMetadata = function(Player, dataToCheck) + return Player.PlayerData.metadata[dataToCheck] + end, + SetPlayerMetadata = function(Player, key, value) + return Player.Functions.SetMetaData(key, value) + end, + }, + +} + + ------------------------------------------------------------- -- Player Retrieval ------------------------------------------------------------- @@ -20,26 +96,11 @@ --- local player = GetPlayer(playerId) --- ``` function GetPlayer(source) - if isStarted(QBExport) then - debugPrint("^6Bridge^7: ^3GetPlayer^7() QBExport") - return exports[QBExport]:GetCoreObject().Functions.GetPlayer(source) - - elseif isStarted(QBXExport) then - debugPrint("^6Bridge^7: ^3GetPlayer^7() QBOXExport") - return exports[QBXExport]:GetCoreObject().Functions.GetPlayer(source) - - elseif isStarted(ESXExport) then - debugPrint("^6Bridge^7: ^3GetPlayer^7() ESXExport") - return ESX.GetPlayerFromId(source) - - elseif isStarted(OXCoreExport) then - debugPrint("^6Bridge^7: ^3GetPlayer^7() OXCoreExport") - return exports[OXCoreExport]:GetPlayer(source) - - elseif isStarted(RSGExport) then - debugPrint("^6Bridge^7: ^3GetPlayer^7() RSGExport") - return exports[RSGExport]:GetCoreObject().Functions.GetPlayer(source) - + for i = 1, #metaDataFunc do + local framework = metaDataFunc[i] + if isStarted(framework.framework) then + return framework.GetPlayer(source) + end end return nil end @@ -61,26 +122,19 @@ end --- local myMeta = getPlayerMetadata(player, "myKey") --- ``` function getPlayerMetadata(player, key) + -- Assume this is client side and callback to server to get the data if not player then debugPrint("^6Bridge^7: ^3GetMetadata^7() calling server: "..key) return triggerCallback(getScript()..":server:GetMetadata", key) else - if isStarted(QBExport) or isStarted(QBXExport) then - debugPrint("^6Bridge^7: ^3GetMetadata^7() QBExport/QBXExport", key) - return player.PlayerData.metadata[key] - - elseif isStarted(ESXExport) then - debugPrint("^6Bridge^7: ^3GetMetadata^7() ESXExport", key) - return player.getMeta(key) - - elseif isStarted(OXCoreExport) then - debugPrint("^6Bridge^7: ^3GetMetadata^7() OXCoreExport", key) - return player.get(key) - - elseif isStarted(RSGExport) then - debugPrint("^6Bridge^7: ^3GetMetadata^7() RSGExport", key) - return player.PlayerData.metadata[key] + -- else grab server metadata about the player + for i = 1, #metaDataFunc do + local framework = metaDataFunc[i] + if isStarted(framework.framework) then + debugPrint("^6Bridge^7: ^3GetMetadata^7() ^3"..framework.framework.."^7", key) + return framework.GetPlayerMetadata(player, key) + end end end return nil @@ -123,34 +177,22 @@ end) --- setPlayerMetadata(player, "myKey", "newValue") --- ``` function setPlayerMetadata(player, key, value) - debugPrint("^6Bridge^7: ^3SetMetadata^7() setting metadata for key: "..key) - if isStarted(QBExport) or isStarted(QBXExport) then - debugPrint("^6Bridge^7: ^3SetMetadata^7() using QBExport/QBXExport") - player.Functions.SetMetaData(key, value) - - elseif isStarted(ESXExport) then - debugPrint("^6Bridge^7: ^3SetMetadata^7() using ESXExport") - player.setMeta(key, value) - - elseif isStarted(OXCoreExport) then - debugPrint("^6Bridge^7: ^3SetMetadata^7() using OXCoreExport") - player.set(key, value) - - elseif isStarted(RSGExport) then - debugPrint("^6Bridge^7: ^3SetMetadata^7() using RSGExport") - player.Functions.SetMetaData(key, value) - + debugPrint("^6Bridge^7: ^3SetMetadata^7() setting metadata^7...") + for i = 1, #metaDataFunc do + local framework = metaDataFunc[i] + if isStarted(framework.framework) then + debugPrint("^6Bridge^7: ^3SetMetadata^7() ^3"..framework.framework.."^7", key, value) + return framework.GetPlayerMetadata(player, key) + end end + debugPrint("^6Bridge^7: ^1Error setting metadata^7, ^1framework not supported^7?") end -- Register a server callback for setting metadata. createCallback(getScript()..":server:setPlayerMetadata", function(source, key, value) - debugPrint("SetMetadata callback triggered for source:", source, "key:", key, "value:", value) - local player = GetPlayer(source) - --[[if not player then - print("Error setting metadata: player not found for source "..tostring(source)) - return false - end]] + local src = source + debugPrint("SetMetadata callback triggered for source:", src, "key:", key, "value:", value) + local player = GetPlayer(src) setPlayerMetadata(player, key, value) print("Metadata set successfully.", key) return true diff --git a/shared/notify.lua b/shared/notify.lua index b8a6195..d6fd8f2 100644 --- a/shared/notify.lua +++ b/shared/notify.lua @@ -17,68 +17,91 @@ local notifyFunc = { okok = { - client = function(title, message, type) - TriggerEvent('okokNotify:Alert', title, message, 6000, type) - end, - server = function(title, message, type, src) - TriggerClientEvent('okokNotify:Alert', src, title, message, 6000, type) - end, + client = + function(title, message, type) + TriggerEvent('okokNotify:Alert', title, message, 6000, type) + end, + server = + function(title, message, type, src) + TriggerClientEvent('okokNotify:Alert', src, title, message, 6000, type) + end, }, + qb = { - client = function(title, message, type) - TriggerEvent("QBCore:Notify", message, type) - end, - server = function(title, message, type, src) - TriggerClientEvent("QBCore:Notify", src, message, type) - end, + client = + function(title, message, type) + TriggerEvent("QBCore:Notify", message, type) + end, + server = + function(title, message, type, src) + TriggerClientEvent("QBCore:Notify", src, message, type) + end, }, + qs = { - client = function(title, message, type) - exports['qs-interface']:AddNotify(message, title, 6000) - end, - server = function(title, message, type, src) - TriggerClientEvent('interface:notification', src, message, title, 6000) - end, + client = + function(title, message, type) + exports['qs-interface']:AddNotify(message, title, 6000) + end, + server = + function(title, message, type, src) + TriggerClientEvent('interface:notification', src, message, title, 6000) + end, }, + ox = { - client = function(title, message, type) - exports.ox_lib:notify({ title = title, description = message, type = type or "success" }) - end, - server = function(title, message, type, src) - TriggerClientEvent('ox_lib:notify', src, { title = title, description = message, type = type or "success" }) - end, - }, - gta = { - client = function(title, message, type) - exports.jim_bridge:Notify(title, message, type) - end, - server = function(title, message, type, src) - TriggerClientEvent("jim-bridge:Notify", src, title, message, type) - end, + client = + function(title, message, type) + exports.ox_lib:notify({ title = title, description = message, type = type or "success" }) + end, + server = + function(title, message, type, src) + TriggerClientEvent('ox_lib:notify', src, { title = title, description = message, type = type or "success" }) + end, }, + esx = { - client = function(title, message, type) - exports["esx_notify"]:Notify(type, 4000, message) - end, - server = function(title, message, type, src) - TriggerClientEvent(getScript()..":DisplayESXNotify", src, type, message) - end, + client = + function(title, message, type) + exports["esx_notify"]:Notify(type, 4000, message) + end, + server = + function(title, message, type, src) + TriggerClientEvent(getScript()..":DisplayESXNotify", src, type, message) + end, }, + lation = { - client = function(title, message, type) - exports.lation_ui:notify({ title = title, message = message, type = type or "success", }) - end, - server = function(title, message, type, src) - TriggerClientEvent("lation_ui:notify", src, { title = title, message = message, type = type or "success", }) - end, + client = + function(title, message, type) + exports.lation_ui:notify({ title = title, message = message, type = type or "success", }) + end, + server = + function(title, message, type, src) + TriggerClientEvent("lation_ui:notify", src, { title = title, message = message, type = type or "success", }) + end, }, + + gta = { + client = + function(title, message, type) + exports.jim_bridge:Notify(title, message, type) + end, + server = + function(title, message, type, src) + TriggerClientEvent("jim-bridge:Notify", src, title, message, type) + end, + }, + red = { - client = function(title, message, type) - TriggerEvent("jim-redui:Notify", title, message, type) - end, - server = function(title, message, type, src) - TriggerClientEvent("jim-redui:Notify", src, title, message, type) - end, + client = + function(title, message, type) + TriggerEvent("jim-redui:Notify", title, message, type) + end, + server = + function(title, message, type, src) + TriggerClientEvent("jim-redui:Notify", src, title, message, type) + end, }, } --- Displays notifications to the player using the configured notification system. diff --git a/shared/phones.lua b/shared/phones.lua index cf3ee5c..bfbefbf 100644 --- a/shared/phones.lua +++ b/shared/phones.lua @@ -13,102 +13,76 @@ - jpr-phonesystem ]] ---- Sends a phone mail using the detected phone system. ---- The function iterates through a prioritized list of supported phone systems. ---- Once an active system is found (via `isStarted`), the corresponding mail function is executed. ---- ---- @param data table A table containing the mail data. ---- - subject (string): The email subject. ---- - sender (string): The sender identifier. ---- - message (string): The email body content. ---- - actions (table|nil): Optional action buttons for the email. ---- @usage ---- sendPhoneMail({ ---- subject = "Welcome!", ---- sender = "Admin", ---- message = "Thank you for joining our server.", ---- actions = { ---- { label = "Reply", action = replyFunction } ---- } ---- }) -function sendPhoneMail(data) - -- Define each supported phone system and its corresponding mail-sending function. - local phoneSystems = { - { name = "gksphone", - send = function(mailData) - exports["gksphone"]:SendNewMail(mailData) +local phoneFunc = { + { phone = "gksphone", + sendMail = function(mailData) + exports["gksphone"]:SendNewMail(mailData) + end, + sendInvoice = + function(mailData) + -- Defensive check for required fields + local required = { "billedCitizenid", "amount", "job", "name", "billerCitizenid", "label" } + for _, field in ipairs(required) do + if mailData[field] == nil then + print("^1[jim-payments] ERROR:^0 Missing field '" .. field .. "' in mailData") + return + end + end + + MySQL.Async.execute( + 'INSERT INTO gksphone_invoices (citizenid, amount, society, sender, sendercitizenid, label) VALUES (@citizenid, @amount, @society, @sender, @sendercitizenid, @label)', + { + ['@citizenid'] = mailData.billedCitizenid, + ['@amount'] = mailData.amount, + ['@society'] = mailData.job, + ['@sender'] = mailData.name, + ['@sendercitizenid'] = mailData.billerCitizenid, + ['@label'] = mailData.label + } + ) end, - }, - { name = "yflip-phone", - send = function(mailData) + }, + { name = "yflip-phone", + sendMail = + function(mailData) TriggerServerEvent(getScript()..":yflip:SendMail", mailData) end, - }, - { name = "qs-smartphone", - send = function(mailData) + }, + { name = "qs-smartphone", + sendMail = + function(mailData) TriggerServerEvent('qs-smartphone:server:sendNewMail', mailData) end, - }, - { name = "qs-smartphone-pro", - send = function(mailData) + }, + { name = "qs-smartphone-pro", + sendMail = + function(mailData) TriggerServerEvent('phone:sendNewMail', mailData) end, - }, - { name = "roadphone", - send = function(mailData) + }, + { name = "roadphone", + sendMail = + function(mailData) -- Convert HTML line breaks to newlines for roadphone. mailData.message = mailData.message:gsub("%
", "\n") exports["roadphone"]:sendMail(mailData) end, - }, - { name = "lb-phone", - send = function(mailData) + }, + { name = "lb-phone", + sendMail = + function(mailData) -- Convert HTML line breaks to newlines for lb-phone. mailData.message = mailData.message:gsub("%
", "\n") TriggerServerEvent(getScript()..":lbphone:SendMail", mailData) end, - }, - { name = "qb-phone", - send = function(mailData) + }, + { name = "qb-phone", + sendMail = + function(mailData) TriggerServerEvent('qb-phone:server:sendNewMail', mailData) end, - }, - { name = "npwd_qbx_mail", - send = function(mailData) - TriggerServerEvent('qb-phone:server:sendNewMail', mailData) - end, - }, - { name = "jpr-phonesystem", - send = function(mailData) - TriggerServerEvent(getScript()..":jpr:SendMail", mailData) - end, - }, - { name = "ef-phone", - send = function(mailData) - TriggerServerEvent('qb-phone:server:sendNewMail', mailData) - end, - }, - } - - -- Check each phone system in order and use the first active one. - for _, phone in ipairs(phoneSystems) do - if isStarted(phone.name) then - debugPrint("^6Bridge^7[^3"..phone.name.."^7]: ^2Sending mail to player") - phone.send(data) - return true - end - end - print("^6Bridge^7: ^1ERROR ^2Sending mail to player ^7- ^2No supported phone found") - return false -end - -function sendPhoneInvoice(data) - if not data.src then return end - -- Define each supported phone system and its corresponding mail-sending function. - local phoneSystems = { - { - name = "qb-phone", - send = function(mailData) + sendInvoice = + function(mailData) -- Defensive check for required fields local required = { "billedCitizenid", "amount", "job", "name", "billerCitizenid", "src" } for _, field in ipairs(required) do @@ -134,74 +108,73 @@ function sendPhoneInvoice(data) end end ) - TriggerClientEvent('qb-phone:RefreshPhone', mailData.src) - end - }, - { - name = "codem-phone", - send = function(mailData) - -- Defensive check for required fields - local required = { "billedCitizenid", "amount", "job", "name", "billerCitizenid", "src" } - for _, field in ipairs(required) do - if mailData[field] == nil then - print("^1[jim-payments] ERROR:^0 Missing field '" .. field .. "' in mailData") - return - end - end + end, + }, + { name = "npwd_qbx_mail", + sendMail = + function(mailData) + TriggerServerEvent('qb-phone:server:sendNewMail', mailData) + end, + }, + { name = "jpr-phonesystem", + sendMail = + function(mailData) + TriggerServerEvent(getScript()..":jpr:SendMail", mailData) + end, + }, + { name = "ef-phone", + sendMail = + function(mailData) + TriggerServerEvent('qb-phone:server:sendNewMail', mailData) + end, + }, - -- Safe insert with all parameters present - MySQL.Async.insert( - 'INSERT INTO phone_invoices (citizenid, amount, society, sender, sendercitizenid) VALUES (?, ?, ?, ?, ?)', - { - mailData.billedCitizenid, - mailData.amount, - mailData.job, - mailData.name, - mailData.billerCitizenid - }, - function(id) - -- if id then - -- TriggerClientEvent('qb-phone:client:AcceptorDenyInvoice', mailData.src, id, mailData.name, mailData.job, mailData.billerCitizenid, mailData.amount, GetInvokingResource()) - -- end - end - ) +} - end - }, - { - name = "gksphone", - send = function(mailData) - -- Defensive check for required fields - local required = { "billedCitizenid", "amount", "job", "name", "billerCitizenid", "label" } - for _, field in ipairs(required) do - if mailData[field] == nil then - print("^1[jim-payments] ERROR:^0 Missing field '" .. field .. "' in mailData") - return - end - end +--- Sends a phone mail using the detected phone system. +--- The function iterates through a prioritized list of supported phone systems. +--- Once an active system is found (via `isStarted`), the corresponding mail function is executed. +--- +--- @param data table A table containing the mail data. +--- - subject (string): The email subject. +--- - sender (string): The sender identifier. +--- - message (string): The email body content. +--- - actions (table|nil): Optional action buttons for the email. +--- @usage +--- sendPhoneMail({ +--- subject = "Welcome!", +--- sender = "Admin", +--- message = "Thank you for joining our server.", +--- actions = { +--- { label = "Reply", action = replyFunction } +--- } +--- }) +function sendPhoneMail(mailData) + -- Check each phone system in order and use the first active one. + for i = 1, #phoneFunc do + local script = phoneFunc[i] + if isStarted(script.phone) and script.sendMail then + debugPrint("^6Bridge^7[^3"..script.phone.."^7]: ^2Sending mail to player") + script.sendMail(mailData) + return true + end + end + print("^6Bridge^7: ^1ERROR ^2Sending mail to player ^7- ^2No supported phone found") + return false +end - MySQL.Async.execute( - 'INSERT INTO gksphone_invoices (citizenid, amount, society, sender, sendercitizenid, label) VALUES (@citizenid, @amount, @society, @sender, @sendercitizenid, @label)', - { - ['@citizenid'] = mailData.billedCitizenid, - ['@amount'] = mailData.amount, - ['@society'] = mailData.job, - ['@sender'] = mailData.name, - ['@sendercitizenid'] = mailData.billerCitizenid, - ['@label'] = mailData.label - } - ) - end - } - } +function sendPhoneInvoice(data) + if not data.src then return end -- Check each phone system in order and use the first active one. - for _, phone in ipairs(phoneSystems) do - if isStarted(phone.name) then - debugPrint("^6Bridge^7[^3"..phone.name.."^7]: ^2Sending mail to player^7", data.src) - phone.send(data) + + for i = 1, #phoneFunc do + local script = phoneFunc[i] + if isStarted(script.phone) and script.sendInvoice then + debugPrint("^6Bridge^7[^3"..script.phone.."^7]: ^2Sending mail to player^7", data.src) + script.sendInvoice(data) return true end end diff --git a/shared/polyZone.lua b/shared/polyZone.lua index e594703..faf901a 100644 --- a/shared/polyZone.lua +++ b/shared/polyZone.lua @@ -100,7 +100,8 @@ local polyCreation = { ---}) ---``` function createPoly(data) - for _, script in ipairs(polyCreation) do + for i = 1, #polyCreation do + local script = polyCreation[i] if isStarted(script.polyZoneScript) then debugPrint("^6Bridge^7: ^2Creating new poly with ^7'^4"..script.polyZoneScript.."^7': "..data.name) return script.createPoly(data) @@ -140,7 +141,8 @@ end --- }) --- ``` function createCirclePoly(data) - for _, script in ipairs(polyCreation) do + for i = 1, #polyCreation do + local script = polyCreation[i] if isStarted(script.polyZoneScript) then debugPrint("^6Bridge^7: ^2Creating new ^3Cricle^2 poly with ^7"..script.polyZoneScript.." "..data.name) debugPrint("^6Bridge^7: ^2Zone Stats - Coords: "..formatCoord(data.coords).." Radius: "..data.radius) @@ -169,7 +171,8 @@ end --- removePolyZone(zone) --- ``` function removePolyZone(Location) - for _, script in ipairs(polyCreation) do + for i = 1, #polyCreation do + local script = polyCreation[i] if isStarted(script.polyZoneScript) then debugPrint("^6Bridge^7: ^2Removing ^3"..script.polyZoneScript.." ^2Zone^7") script.removeZone(Location) diff --git a/shared/skillcheck.lua b/shared/skillcheck.lua index 55940ae..ebf1efd 100644 --- a/shared/skillcheck.lua +++ b/shared/skillcheck.lua @@ -1,58 +1,72 @@ -local activeSkillCheck = false +local skillCheckFunc = { + qb = { + start = function(data) + local Skillbar = exports["qb-minigames"]:Skillbar() + if Skillbar then + return true + else + return false + end + end, + }, + ox = { + start = function(data) + local Skillbar = exports[OXLibExport]:skillCheck( + { + "easy", + "easy", + "easy" + }, + { + "1", + "2", + "3", + "4" + }) + if Skillbar then + return true + else + return false + end + end, + }, + gta = { + start = function(data) + local Skillbar = exports.jim_bridge:skillCheck() + if Skillbar then + return true + else + return false + end + end, + }, + lation = { + start = function(data) + local Skillbar = exports.lation_ui:skillCheck("", + { + "easy", + "easy", + "easy" + }, + { + "1", + "2", + "3", + "4" + }) + if Skillbar then + return true + else + return false + end + end, + }, + +} function skillCheck(data) - local result = false - - if Config.System.skillCheck == "qb" then - local Skillbar = exports["qb-minigames"]:Skillbar() - if Skillbar then - result = true - else - result = false - end - - elseif Config.System.skillCheck == "ox" then - local Skillbar = exports[OXLibExport]:skillCheck( - { - "easy", - "easy", - "easy" - }, - { - "1", - "2", - "3", - "4" - }) - if Skillbar then - result = true - else - result = false - end - elseif Config.System.skillCheck == "gta" then - exports.jim_bridge:skillCheck() - - elseif Config.System.skillCheck == "lation" then - local Skillbar = exports.lation_ui:skillCheck("", - { - "easy", - "easy", - "easy" - }, - { - "1", - "2", - "3", - "4" - }) - - if Skillbar then - result = true - else - result = false - end - else - result = true + if Config.System.skillCheck then + return skillCheckFunc[Config.System.skillCheck].start(data) end - return result + return true end \ No newline at end of file diff --git a/shared/societybank.lua b/shared/societybank.lua index 549211a..35078c8 100644 --- a/shared/societybank.lua +++ b/shared/societybank.lua @@ -12,112 +12,122 @@ ]] local societyFunc = { - { - bankName = "qb-banking", - getAccount = function(society) - if not exports["qb-banking"]:GetAccount(society) then - if Jobs[society] then - print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") - exports["qb-banking"]:CreateJobAccount(society, 0) - Wait(150) - elseif Gangs[society] then - print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") - exports["qb-banking"]:CreateGangAccount(society, 0) - Wait(150) + { bankName = "qb-banking", + getAccount = + function(society) + if not exports["qb-banking"]:GetAccount(society) then + if Jobs[society] then + print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") + exports["qb-banking"]:CreateJobAccount(society, 0) + Wait(150) + elseif Gangs[society] then + print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") + exports["qb-banking"]:CreateGangAccount(society, 0) + Wait(150) + end end - end - return exports["qb-banking"]:GetAccountBalance(society) - end, - chargeSociety = function(society, amount) - if not exports["qb-banking"]:GetAccount(society) then - if Jobs[society] then - print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") - exports["qb-banking"]:CreateJobAccount(society, 0) Wait(150) -- make new account if return "null" - elseif Gangs[society] then - print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") - exports["qb-banking"]:CreateGangAccount(society, 0) Wait(150) -- make new account if return "null" + return exports["qb-banking"]:GetAccountBalance(society) + end, + chargeSociety = + function(society, amount) + if not exports["qb-banking"]:GetAccount(society) then + if Jobs[society] then + print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") + exports["qb-banking"]:CreateJobAccount(society, 0) Wait(150) -- make new account if return "null" + elseif Gangs[society] then + print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") + exports["qb-banking"]:CreateGangAccount(society, 0) Wait(150) -- make new account if return "null" + end end - end - exports["qb-banking"]:RemoveMoney(society, amount) - end, - fundSociety = function(society, amount) - if not exports["qb-banking"]:GetAccount(society) then - if Jobs[society] then - print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") - exports["qb-banking"]:CreateJobAccount(society, 0) - Wait(150) - elseif Gangs[society] then - print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") - exports["qb-banking"]:CreateGangAccount(society, 0) - Wait(150) + exports["qb-banking"]:RemoveMoney(society, amount) + end, + fundSociety = + function(society, amount) + if not exports["qb-banking"]:GetAccount(society) then + if Jobs[society] then + print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") + exports["qb-banking"]:CreateJobAccount(society, 0) + Wait(150) + elseif Gangs[society] then + print("^6Bridge^7: ^2Making new bank account in ^7'^3qb-banking^7' ^2for ^7'^3"..society.."^7'") + exports["qb-banking"]:CreateGangAccount(society, 0) + Wait(150) + end end - end - exports["qb-banking"]:AddMoney(society, amount) - end, + exports["qb-banking"]:AddMoney(society, amount) + end, }, - { - bankName = "Renewed-Banking", - getAccount = function(society) - return exports["Renewed-Banking"]:getAccountMoney(society) - end, - chargeSociety = function(society, amount) - exports['Renewed-Banking']:removeAccountMoney(society, amount) - end, - fundSociety = function(society, amount) - exports['Renewed-Banking']:addAccountMoney(society, amount) - end, + { bankName = "Renewed-Banking", + getAccount = + function(society) + return exports["Renewed-Banking"]:getAccountMoney(society) + end, + chargeSociety = + function(society, amount) + exports['Renewed-Banking']:removeAccountMoney(society, amount) + end, + fundSociety = + function(society, amount) + exports['Renewed-Banking']:addAccountMoney(society, amount) + end, }, - { - bankName = "fd_banking", - getAccount = function(society) - return exports["fd_banking"]:GetAccount(society) - end, - chargeSociety = function(society, amount) - exports["fd_banking"]:RemoveMoney(society, amount) - end, - fundSociety = function(society, amount) - exports["fd_banking"]:AddMoney(society, amount) - end, + { bankName = "fd_banking", + getAccount = + function(society) + return exports["fd_banking"]:GetAccount(society) + end, + chargeSociety = + function(society, amount) + exports["fd_banking"]:RemoveMoney(society, amount) + end, + fundSociety = + function(society, amount) + exports["fd_banking"]:AddMoney(society, amount) + end, }, - { - bankName = "okokBanking", - getAccount = function(society) - return exports['okokBanking']:GetAccount(society) - end, - chargeSociety = function(society, amount) - exports['okokBanking']:RemoveMoney(society, amount) - end, - fundSociety = function(society, amount) - exports['okokBanking']:AddMoney(society, amount) - end, + { bankName = "okokBanking", + getAccount = + function(society) + return exports['okokBanking']:GetAccount(society) + end, + chargeSociety = + function(society, amount) + exports['okokBanking']:RemoveMoney(society, amount) + end, + fundSociety = + function(society, amount) + exports['okokBanking']:AddMoney(society, amount) + end, }, - { - bankName = "tgiann-bank", - getAccount = function(society) - if Jobs[society] then - return exports["tgiann-bank"]:GetJobAccountBalance(society) - else - return exports["tgiann-bank"]:GetGangAccountBalance(society) - end - end, - chargeSociety = function(society, amount) - if Jobs[society] then - exports["tgiann-bank"]:RemoveJobMoney(society, amount) - else - exports["tgiann-bank"]:RemoveGangMoney(society, amount) - end - end, - fundSociety = function(society, amount) - if Jobs[society] then - exports["tgiann-bank"]:AddJobMoney(society, amount) - else - exports["tgiann-bank"]:AddGangMoney(society, amount) - end - end, + { bankName = "tgiann-bank", + getAccount = + function(society) + if Jobs[society] then + return exports["tgiann-bank"]:GetJobAccountBalance(society) + else + return exports["tgiann-bank"]:GetGangAccountBalance(society) + end + end, + chargeSociety = + function(society, amount) + if Jobs[society] then + exports["tgiann-bank"]:RemoveJobMoney(society, amount) + else + exports["tgiann-bank"]:RemoveGangMoney(society, amount) + end + end, + fundSociety = + function(society, amount) + if Jobs[society] then + exports["tgiann-bank"]:AddJobMoney(society, amount) + else + exports["tgiann-bank"]:AddGangMoney(society, amount) + end + end, }, } @@ -134,7 +144,8 @@ function getSocietyAccount(society) local amount = 0 if society == nil or society == "none" then return amount end - for _, script in pairs(societyFunc) do + for i = 1, #societyFunc do + local script = societyFunc[i] if isStarted(script.bankName) then local amount = script.getAccount(society) debugPrint("^6Bridge^7: ^3"..script.bankName.."^7: ^2Retrieved account ^7'^6"..society.."^7' ($"..tostring(amount)..")") @@ -156,7 +167,8 @@ end --- ``` function chargeSociety(society, amount) - for _, script in pairs(societyFunc) do + for i = 1, #societyFunc do + local script = societyFunc[i] if isStarted(script.bankName) then script.chargeSociety(society, amount) local newAmount = getSocietyAccount(society) @@ -177,7 +189,8 @@ end --- ``` function fundSociety(society, amount) - for _, script in pairs(societyFunc) do + for i = 1, #societyFunc do + local script = societyFunc[i] if isStarted(script.bankName) then script.fundSociety(society, amount) local newAmount = getSocietyAccount(society) diff --git a/shared/targets.lua b/shared/targets.lua index 0dce114..fdf993c 100644 --- a/shared/targets.lua +++ b/shared/targets.lua @@ -18,172 +18,190 @@ ]] local targetFunc = { - { - targetName = OXTargetExport, - entityTarget = function(entity, opts, dist) - local options = {} - for i = 1, #opts do - options[i] = { - icon = opts[i].icon, - label = opts[i].label, - items = opts[i].item or nil, - groups = opts[i].job or opts[i].gang, - onSelect = opts[i].action, - distance = dist, - canInteract = opts[i].canInteract or nil, - } - end - exports[OXTargetExport]:addLocalEntity(entity, options) - end, + { targetName = OXTargetExport, + entityTarget = + function(entity, opts, dist) + local options = {} + for i = 1, #opts do + options[i] = { + icon = opts[i].icon, + label = opts[i].label, + items = opts[i].item or nil, + groups = opts[i].job or opts[i].gang, + onSelect = opts[i].action, + distance = dist, + canInteract = opts[i].canInteract or nil, + } + end + exports[OXTargetExport]:addLocalEntity(entity, options) + end, - boxTarget = function(data, opts, dist) - local options = {} - for i = 1, #opts do - options[i] = { - icon = opts[i].icon, - label = opts[i].label, - items = opts[i].item or nil, - groups = opts[i].groups or opts[i].job or opts[i].gang, - onSelect = opts[i].onSelect or opts[i].action, - distance = dist, - canInteract = opts[i].canInteract or nil, - } - end + boxTarget = + function(data, opts, dist) + local options = {} + for i = 1, #opts do + options[i] = { + icon = opts[i].icon, + label = opts[i].label, + items = opts[i].item or nil, + groups = opts[i].groups or opts[i].job or opts[i].gang, + onSelect = opts[i].onSelect or opts[i].action, + distance = dist, + canInteract = opts[i].canInteract or nil, + } + end - data[5].maxZ = data[5].maxZ or (data[2].z + 0.80) - data[5].minZ = data[5].minZ or data[2].z - 1.05 - local thickness = ((data[5].maxZ / 2) - (data[5].minZ / 2)) * 2 - local mid = data[5].maxZ - ((data[5].maxZ / 2) - (data[5].minZ / 2)) + data[5].maxZ = data[5].maxZ or (data[2].z + 0.80) + data[5].minZ = data[5].minZ or data[2].z - 1.05 + local thickness = ((data[5].maxZ / 2) - (data[5].minZ / 2)) * 2 + local mid = data[5].maxZ - ((data[5].maxZ / 2) - (data[5].minZ / 2)) - data[2] = vec3(data[2].x, data[2].y, mid) -- force the coord to middle of the minZ and maxZ + data[2] = vec3(data[2].x, data[2].y, mid) -- force the coord to middle of the minZ and maxZ - local target = exports[OXTargetExport]:addBoxZone({ - coords = data[2], - size = vec3(data[4], data[3], thickness), -- size uses the math to determine how high it needs to be - rotation = data[5].heading, - debug = data[5].debugPoly, - options = options - }) - return target - end, + local target = exports[OXTargetExport]:addBoxZone({ + coords = data[2], + size = vec3(data[4], data[3], thickness), -- size uses the math to determine how high it needs to be + rotation = data[5].heading, + debug = data[5].debugPoly, + options = options + }) + return target + end, - circleTarget = function(data, opts, dist) - local options = {} - for i = 1, #opts do - options[i] = { - icon = opts[i].icon, - label = opts[i].label, - items = opts[i].item or nil, - groups = opts[i].job or opts[i].gang, - onSelect = opts[i].onSelect or opts[i].action, - distance = dist, - canInteract = opts[i].canInteract or nil, - } - end - local target = exports[OXTargetExport]:addSphereZone({ - coords = data[2], - radius = data[3], - debug = data[4].debugPoly, - options = options - }) - return target - end, + circleTarget = + function(data, opts, dist) + local options = {} + for i = 1, #opts do + options[i] = { + icon = opts[i].icon, + label = opts[i].label, + items = opts[i].item or nil, + groups = opts[i].job or opts[i].gang, + onSelect = opts[i].onSelect or opts[i].action, + distance = dist, + canInteract = opts[i].canInteract or nil, + } + end + local target = exports[OXTargetExport]:addSphereZone({ + coords = data[2], + radius = data[3], + debug = data[4].debugPoly, + options = options + }) + return target + end, - modelTarget = function(models, opts, dist) - local options = {} - for i = 1, #opts do - options[i] = { - icon = opts[i].icon, - label = opts[i].label, - items = opts[i].item or nil, - groups = opts[i].job or opts[i].gang, - onSelect = opts[i].action, - distance = dist, - canInteract = opts[i].canInteract or nil, - } - end - exports[OXTargetExport]:addModel(models, options) - end, + modelTarget = + function(models, opts, dist) + local options = {} + for i = 1, #opts do + options[i] = { + icon = opts[i].icon, + label = opts[i].label, + items = opts[i].item or nil, + groups = opts[i].job or opts[i].gang, + onSelect = opts[i].action, + distance = dist, + canInteract = opts[i].canInteract or nil, + } + end + exports[OXTargetExport]:addModel(models, options) + end, - removeTargetEntity = function(entity) - exports[OXTargetExport]:removeLocalEntity(entity, nil) - end, + removeTargetEntity = + function(entity) + exports[OXTargetExport]:removeLocalEntity(entity, nil) + end, - removeTargetZone = function(target) - exports[OXTargetExport]:removeZone(target, true) - end, + removeTargetZone = + function(target) + exports[OXTargetExport]:removeZone(target, true) + end, - removeTargetModel = function(model) - exports[OXTargetExport]:removeModel(model, nil) - end, + removeTargetModel = + function(model) + exports[OXTargetExport]:removeModel(model, nil) + end, }, - { - targetName = QBTargetExport, - entityTarget = function(entity, opts, dist) - local options = { options = opts, distance = dist } - exports[QBTargetExport]:AddTargetEntity(entity, options) - end, + { targetName = QBTargetExport, + entityTarget = + function(entity, opts, dist) + local options = { options = opts, distance = dist } + exports[QBTargetExport]:AddTargetEntity(entity, options) + end, - boxTarget = function(data, opts, dist) - local options = { options = opts, distance = dist } - local target = exports[QBTargetExport]:AddBoxZone(data[1], data[2], data[3], data[4], data[5], options) - return data[1] - end, + boxTarget = + function(data, opts, dist) + local options = { options = opts, distance = dist } + local target = exports[QBTargetExport]:AddBoxZone(data[1], data[2], data[3], data[4], data[5], options) + return data[1] + end, - circleTarget = function(data, opts, dist) - local options = { options = opts, distance = dist } - local target = exports[QBTargetExport]:AddCircleZone(data[1], data[2], data[3], data[4], options) - return data[1] - end, + circleTarget = + function(data, opts, dist) + local options = { options = opts, distance = dist } + local target = exports[QBTargetExport]:AddCircleZone(data[1], data[2], data[3], data[4], options) + return data[1] + end, - modelTarget = function(models, opts, dist) - local options = { options = opts, distance = dist } - exports[QBTargetExport]:AddTargetModel(models, options) - end, + modelTarget = + function(models, opts, dist) + local options = { options = opts, distance = dist } + exports[QBTargetExport]:AddTargetModel(models, options) + end, - removeTargetEntity = function(entity) - exports[QBTargetExport]:RemoveTargetEntity(entity) - end, + removeTargetEntity = + function(entity) + exports[QBTargetExport]:RemoveTargetEntity(entity) + end, - removeTargetZone = function(target) - exports[QBTargetExport]:RemoveZone(target) - end, + removeTargetZone = + function(target) + exports[QBTargetExport]:RemoveZone(target) + end, - removeTargetModel = function(model) - exports[QBTargetExport]:RemoveTargetModel(model, "Test") - end, + removeTargetModel = + function(model) + exports[QBTargetExport]:RemoveTargetModel(model, "Test") + end, }, - { - targetName = "jim_bridge", - entityTarget = function(entity, opts, dist) - return exports.jim_bridge:createEntityTarget(entity, opts, dist) - end, + { targetName = "jim_bridge", + entityTarget = + function(entity, opts, dist) + return exports.jim_bridge:createEntityTarget(entity, opts, dist) + end, - boxTarget = function(data, opts, dist) - return exports.jim_bridge:createZoneTarget(data, opts, dist) - end, + boxTarget = + function(data, opts, dist) + return exports.jim_bridge:createZoneTarget(data, opts, dist) + end, - circleTarget = function(data, opts, dist) - return exports.jim_bridge:createZoneTarget(data, opts, dist) - end, + circleTarget = + function(data, opts, dist) + return exports.jim_bridge:createZoneTarget(data, opts, dist) + end, - modelTarget = function(models, opts, dist) - return exports.jim_bridge:createModelTarget(models, opts, dist) - end, + modelTarget = + function(models, opts, dist) + return exports.jim_bridge:createModelTarget(models, opts, dist) + end, - removeTargetEntity = function(entity) - exports.jim_bridge:removeEntityTarget(entity) - end, + removeTargetEntity = + function(entity) + exports.jim_bridge:removeEntityTarget(entity) + end, - removeTargetZone = function(target) - exports.jim_bridge:removeZoneTarget(target) - end, + removeTargetZone = + function(target) + exports.jim_bridge:removeZoneTarget(target) + end, - removeTargetModel = function(model) - exports.jim_bridge:removeZoneTarget(model) - end, + removeTargetModel = + function(model) + exports.jim_bridge:removeZoneTarget(model) + end, }, } @@ -243,7 +261,8 @@ function createEntityTarget(entity, opts, dist) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Entity ^2target with ^6"..script.targetName.." ^2for entity ^7"..entity) return script.entityTarget(entity, opts, dist) @@ -314,7 +333,8 @@ function createBoxTarget(data, opts, dist) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Box ^2target with ^6"..script.targetName.." ^7"..data[1]) local target = script.boxTarget(data, opts, dist) @@ -370,7 +390,8 @@ function createCircleTarget(data, opts, dist) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Sphere ^2target with ^6"..script.targetName.." ^7"..data[1]) local target = script.circleTarget(data, opts, dist) @@ -416,7 +437,8 @@ function createModelTarget(models, opts, dist) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Model ^2target with ^6"..script.targetName.."^7") local target = script.modelTarget(models, opts, dist) @@ -446,7 +468,8 @@ function removeEntityTarget(entity) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then script.removeTargetEntity(entity) break @@ -471,7 +494,8 @@ function removeZoneTarget(target) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then script.removeTargetZone(target) break @@ -494,7 +518,8 @@ function removeModelTarget(model) end -- Check for target script and use that - for _, script in pairs(targetFunc) do + for i = 1, #targetFunc do + local script = targetFunc[i] if isStarted(script.targetName) then script.removeTargetModel(model) break From 26c341c6ec74722fd79c8af5df5f3aae84947d30 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Thu, 14 Aug 2025 20:20:42 +0100 Subject: [PATCH 04/10] Create bossmenu compatibility table --- shared/jobfunctions.lua | 67 ++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/shared/jobfunctions.lua b/shared/jobfunctions.lua index c304f9b..e42537b 100644 --- a/shared/jobfunctions.lua +++ b/shared/jobfunctions.lua @@ -9,6 +9,58 @@ and teleporting via doors. ]] + +local bossMenuFunc = { + { name = "qb-management", + openBossMenu = function(isGang, group) + if isGang then + TriggerEvent("qb-gangmenu:client:OpenMenu") + else + TriggerEvent("qb-bossmenu:client:OpenMenu") + end + end, + }, + + { name = "qbx_management", + openBossMenu = function(isGang, group) + if isGang then + exports["qbx_management"]:OpenBossMenu("gang") + else + exports["qbx_management"]:OpenBossMenu("job") + end + end, + }, + + { name = "esx_society", + openBossMenu = function(isGang, group) + TriggerEvent('esx_society:openBossMenu', group, function() end, { wash = false }) + end, + }, + + { name = "tss-bossmenu", + openBossMenu = function(isGang, group) + TriggerEvent("tss-bossmenu:client:OpenMenu") + end, + }, + + { name = "okokBossMenu", + openBossMenu = function(isGang, group) + ExecuteCommand('openbossmenu') + end, + }, +} + +function openBossMenu(isGang, group) + for i = 1, #bossMenuFunc do + local bossmenu = bossMenuFunc[i] + if isStarted(bossmenu.name) then + bossmenu.openBossMenu(isGang, group) + return + end + end +end + + ------------------------------------------------------------- -- Global Duty Status ------------------------------------------------------------- @@ -245,19 +297,4 @@ function useDoor(data) SetEntityHeading(PlayerPedId(), data.telecoords.w) DoScreenFadeIn(1000) Wait(100) -end - -function openBossMenu(isGang, group) - if isStarted("qb-management") then - if isGang then - TriggerEvent("qb-gangmenu:client:OpenMenu") - else - TriggerEvent("qb-bossmenu:client:OpenMenu") - end - elseif isStarted("qbx_management") then - exports["qbx_management"]:OpenBossMenu(isGang and "gang" or "job") - - elseif isStarted("esx_society") then - TriggerEvent('esx_society:openBossMenu', group, function() end, { wash = false }) - end end \ No newline at end of file From 09887f3a9dab18f2bc78914290cfb2cadd23d581 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Thu, 14 Aug 2025 21:08:32 +0100 Subject: [PATCH 05/10] Create compatibility tables for `playerFunctions.lua` --- shared/helpers.lua | 61 +++ shared/playerfunctions.lua | 937 ++++++++++++++++++++----------------- 2 files changed, 566 insertions(+), 432 deletions(-) diff --git a/shared/helpers.lua b/shared/helpers.lua index 188077e..a3f32f0 100644 --- a/shared/helpers.lua +++ b/shared/helpers.lua @@ -580,6 +580,67 @@ function GetRandomTiming(tbl) return type(tbl) == "table" and math.random(tbl[1], tbl[2]) or tbl end +------------------------------------------------------------- +-- Player Movement +------------------------------------------------------------- + +--- Instantly turns an entity to face a target (entity or coordinates) without animation. +--- +--- @param ent number|nil The Ped to turn (defaults to player's Ped if nil). +--- @param ent2 number|vector3|nil The target entity or coordinates to face. +--- +--- @usage +--- ```lua +--- instantLookEnt(nil, vector3(200.0, 300.0, 40.0)) +--- instantLookEnt(ped1, ped2) +--- ``` +function instantLookEnt(ent, ent2) + local ped = ent or PlayerPedId() + local p1 = GetEntityCoords(ped, true) + local p2 = type(ent2) == "vector3" and ent2 or GetEntityCoords(ent2, true) + + local dx = p2.x - p1.x + local dy = p2.y - p1.y + local heading = GetHeadingFromVector_2d(dx, dy) + + debugPrint("^6Bridge^7: ^1Forced ^2Turning Player to^7: '^6"..formatCoord(p2).."^7'") + SetEntityHeading(ped, heading) +end + +--- Makes the player look towards a specific target with an animated turn. +--- +--- If the player is not already facing the target (entity or coordinates), a turning animation is triggered. +--- +--- @param entity number|vector3|vector4|nil The target to look at. +--- +--- @usage +--- ```lua +--- lookEnt(vector3(200.0, 300.0, 40.0)) +--- lookEnt(pedEntity) +--- ``` +function lookEnt(entity) + local ped = PlayerPedId() + if entity then + if type(entity) == "vector3" or type(entity) == "vector4" then + if not IsPedHeadingTowardsPosition(ped, entity.xyz, 30.0) then + TaskTurnPedToFaceCoord(ped, entity.xyz, 1500) + debugPrint("^6Bridge^7: ^2Turning Player to^7: '^6"..formatCoord(entity).."^7'") + Wait(1500) + end + else + if DoesEntityExist(entity) then + local entCoords = GetEntityCoords(entity) + if not IsPedHeadingTowardsPosition(ped, entCoords, 30.0) then + TaskTurnPedToFaceCoord(ped, entCoords, 1500) + debugPrint("^6Bridge^7: ^2Turning Player to^7: '^6"..entity.."^7' - '"..formatCoord(entCoords).."^7'") + Wait(1500) + end + end + end + end +end + + ------------------------------------------------------------- -- Material and Prop Functions ------------------------------------------------------------- diff --git a/shared/playerfunctions.lua b/shared/playerfunctions.lua index 72de934..7f627fb 100644 --- a/shared/playerfunctions.lua +++ b/shared/playerfunctions.lua @@ -12,68 +12,106 @@ ]] ------------------------------------------------------------- --- Player Movement +-- Server Event Handlers for Needs ------------------------------------------------------------- ---- Instantly turns an entity to face a target (entity or coordinates) without animation. +local hungerThirstFunc = { + { framework = QBXExport, + setThirst = + function(src, thirst) + local Player = Core.Functions.GetPlayer(src) + Player.Functions.SetMetaData('thirst', thirst) + TriggerClientEvent("hud:client:UpdateNeeds", src, Player.PlayerData.metadata.hunger, thirst) + end, + setHunger = + function(src, hunger) + local Player = Core.Functions.GetPlayer(src) + Player.Functions.SetMetaData('hunger', hunger) + TriggerClientEvent("hud:client:UpdateNeeds", src, hunger, Player.PlayerData.metadata.thirst) + end, + }, + + { framework = QBExport, + setThirst = + function(src, thirst) + local Player = Core.Functions.GetPlayer(src) + Player.Functions.SetMetaData('thirst', thirst) + TriggerClientEvent("hud:client:UpdateNeeds", src, Player.PlayerData.metadata.hunger, thirst) + end, + setHunger = + function(src, hunger) + local Player = Core.Functions.GetPlayer(src) + Player.Functions.SetMetaData('hunger', hunger) + TriggerClientEvent("hud:client:UpdateNeeds", src, hunger, Player.PlayerData.metadata.thirst) + end, + }, + + { framework = RSGExport, + setThirst = + function(src, thirst) + local Player = Core.Functions.GetPlayer(src) + Player.Functions.SetMetaData('thirst', thirst) + TriggerClientEvent("hud:client:UpdateNeeds", src, Player.PlayerData.metadata.hunger, thirst) + end, + setHunger = + function(src, hunger) + local Player = Core.Functions.GetPlayer(src) + Player.Functions.SetMetaData('hunger', hunger) + TriggerClientEvent("hud:client:UpdateNeeds", src, hunger, Player.PlayerData.metadata.thirst) + end, + }, + + { framework = ESXExport, + setThirst = + function(src, thirst) + TriggerClientEvent('esx_status:add', src, 'thirst', thirst) + end, + setHunger = + function(src, hunger) + TriggerClientEvent('esx_status:add', src, 'hunger', hunger) + end, + }, +} + +--- Sets the player's thirst level. --- ---- @param ent number|nil The Ped to turn (defaults to player's Ped if nil). ---- @param ent2 number|vector3|nil The target entity or coordinates to face. +--- @param src number The player's server ID. +--- @param thirst number The new thirst level. --- --- @usage --- ```lua ---- instantLookEnt(nil, vector3(200.0, 300.0, 40.0)) ---- instantLookEnt(ped1, ped2) +--- setThirst(playerId, 80) --- ``` -function instantLookEnt(ent, ent2) - local ped = ent or PlayerPedId() - local p1 = GetEntityCoords(ped, true) - local p2 = type(ent2) == "vector3" and ent2 or GetEntityCoords(ent2, true) - - local dx = p2.x - p1.x - local dy = p2.y - p1.y - local heading = GetHeadingFromVector_2d(dx, dy) - - debugPrint("^6Bridge^7: ^1Forced ^2Turning Player to^7: '^6"..formatCoord(p2).."^7'") - SetEntityHeading(ped, heading) -end - ---- Makes the player look towards a specific target with an animated turn. ---- ---- If the player is not already facing the target (entity or coordinates), a turning animation is triggered. ---- ---- @param entity number|vector3|vector4|nil The target to look at. ---- ---- @usage ---- ```lua ---- lookEnt(vector3(200.0, 300.0, 40.0)) ---- lookEnt(pedEntity) ---- ``` -function lookEnt(entity) - local ped = PlayerPedId() - if entity then - if type(entity) == "vector3" or type(entity) == "vector4" then - if not IsPedHeadingTowardsPosition(ped, entity.xyz, 30.0) then - TaskTurnPedToFaceCoord(ped, entity.xyz, 1500) - debugPrint("^6Bridge^7: ^2Turning Player to^7: '^6"..formatCoord(entity).."^7'") - Wait(1500) - end - else - if DoesEntityExist(entity) then - local entCoords = GetEntityCoords(entity) - if not IsPedHeadingTowardsPosition(ped, entCoords, 30.0) then - TaskTurnPedToFaceCoord(ped, entCoords, 1500) - debugPrint("^6Bridge^7: ^2Turning Player to^7: '^6"..entity.."^7' - '"..formatCoord(entCoords).."^7'") - Wait(1500) - end - end +function setThirst(src, thirst) + for i = 1, #hungerThirstFunc do + local framework = hungerThirstFunc[i] + if isStarted(framework.framework) then + debugPrint("^4Debug^7: ^2Adding ^3"..framework.framework.." ^2thirst^7: ^3"..thirst.." ^2to player^7: ^3"..src.."^7") + framework.setThirst(src, thirst) + return end end end -------------------------------------------------------------- --- Server Event Handlers for Needs -------------------------------------------------------------- +--- Sets the player's hunger level. +--- +--- @param src number The player's server ID. +--- @param hunger number The new hunger level. +--- +--- @usage +--- ```lua +--- setHunger(playerId, 60) +--- ``` +function setHunger(src, hunger) + for i = 1, #hungerThirstFunc do + local framework = hungerThirstFunc[i] + if isStarted(framework.framework) then + debugPrint("^4Debug^7: ^2Adding ^3"..framework.framework.." ^2hunger^7: ^3"..hunger.." ^2to player^7: ^3"..src.."^7") + framework.setHunger(src, hunger) + return + end + end +end --- Server event handler for urinal usage. --- Decreases player's thirst by a random amount. @@ -99,72 +137,94 @@ RegisterNetEvent(getScript()..":server:setNeed", function(needType, amount) end end) ---- Sets the player's thirst level. ---- ---- @param src number The player's server ID. ---- @param thirst number The new thirst level. ---- ---- @usage ---- ```lua ---- setThirst(playerId, 80) ---- ``` -function setThirst(src, thirst) - - debugPrint("^4Debug^7: ^2Adding thirst^7: ^3"..thirst.." ^2to player^7: ^3"..src.."^7") - if isStarted(ESXExport) then - TriggerClientEvent('esx_status:add', src, 'thirst', thirst) - - elseif isStarted(QBExport) or isStarted(QBXExport) or isStarted(RSGExport) then - local Player = Core.Functions.GetPlayer(src) - Player.Functions.SetMetaData('thirst', thirst) - TriggerClientEvent("hud:client:UpdateNeeds", src, Player.PlayerData.metadata.hunger, thirst) - - end - -end - ---- Sets the player's hunger level. ---- ---- @param src number The player's server ID. ---- @param hunger number The new hunger level. ---- ---- @usage ---- ```lua ---- setHunger(playerId, 60) ---- ``` -function setHunger(src, hunger) - - debugPrint("^4Debug^7: ^2Adding hunger^7: ^3"..hunger.." ^2to player^7: ^3"..src.."^7") - if isStarted(ESXExport) then - TriggerClientEvent('esx_status:add', src, 'hunger', hunger) - - elseif isStarted(QBExport) or isStarted(QBXExport) or isStarted(RSGExport) then - local Player = Core.Functions.GetPlayer(src) - Player.Functions.SetMetaData('hunger', hunger) - TriggerClientEvent("hud:client:UpdateNeeds", src, hunger, Player.PlayerData.metadata.thirst) - - end -end - ------------------------------------------------------------- -- Economy Event Handlers ------------------------------------------------------------- +local billPlayerFunc = { + jim = + function(data) + TriggerEvent("jim-payments:client:Charge", { + job = data.job, + gang = data.gang, + coords = data.coords.xyz, + img = data.img + }) + end, + okok = + function(data) + TriggerEvent("okokBilling:ToggleCreateInvoice") + end, +} + --- BillPlayer function billPlayer(data) - if not Config.System.Billing or Config.System.Billing == "jim" then - TriggerEvent("jim-payments:client:Charge", { - job = data.job, - gang = data.gang, - coords = data.coords.xyz, - img = data.img - }) - elseif Config.System.Billing == "okok" then - -- TriggerServerEvent("okokBilling:CreateCustomInvoice", target, price, reason, invoiceSource, society, societyName) - TriggerEvent("okokBilling:ToggleCreateInvoice") + if Config.System.Billing and billPlayerFunc[Config.System.Billing] then + billPlayerFunc[Config.System.Billing](data) + else + debugPrint("^1Error^7: ^1No billing script detected") end end +-- Money Handlers + +local moneyFunc = { + { framework = OXInv, + chargePlayer = + function(src, amount, moneyType) + return exports[OXInv]:RemoveItem(src, "money", amount) + end, + fundPlayer = + function(src, amount, moneyType) + return exports[OXInv]:AddItem(src, "money", amount) + end, + }, + + { framework = QBXExport, + chargePlayer = + function(src, amount, moneyType) + return Core.Functions.GetPlayer(src).Functions.RemoveMoney(moneyType or "cash", amount) + end, + fundPlayer = + function(src, amount, moneyType) + return Core.Functions.GetPlayer(src).Functions.AddMoney(moneyType or "cash", amount) + end, + }, + + { framework = QBExport, + chargePlayer = + function(src, amount, moneyType) + return Core.Functions.GetPlayer(src).Functions.RemoveMoney(moneyType or "cash", amount) + end, + fundPlayer = + function(src, amount, moneyType) + return Core.Functions.GetPlayer(src).Functions.AddMoney(moneyType or "cash", amount) + end, + }, + + { framework = RSGExport, + chargePlayer = + function(src, amount, moneyType) + return Core.Functions.GetPlayer(src).Functions.RemoveMoney(moneyType or "cash", amount) + end, + fundPlayer = + function(src, amount, moneyType) + return Core.Functions.GetPlayer(src).Functions.AddMoney(moneyType or "cash", amount) + end, + }, + + { framework = ESXExport, + chargePlayer = + function(src, amount, moneyType) + return ESX.GetPlayerFromId(src).removeMoney(amount, "") + end, + fundPlayer = + function(src, amount, moneyType) + return ESX.GetPlayerFromId(src).addMoney(amount, "") + end, + }, +} + --- Charges a player by removing money from their account. --- --- @param cost number The amount to charge. @@ -175,59 +235,33 @@ end --- ```lua --- chargePlayer(100, "cash", playerId) --- ``` +--- function chargePlayer(cost, moneyType, newsrc) local is_success = false local src = newsrc or source - local fundResource = "" - if cost < 0 then - debugPrint("^1Error^7: ^7SRC: ^3"..src.." ^2Tried to charge a minus value^7", cost) + + if cost <= 0 then + debugPrint("^1Error^7: ^7SRC: ^3"..src.." ^2Tried to charge a zero or minus value^7", cost) return end - if moneyType == "cash" then - if isStarted(OXInv) then fundResource = OXInv - is_success = exports[OXInv]:RemoveItem(src, "money", cost) - - elseif isStarted(QBExport) or isStarted(QBXExport) then - fundResource = QBExport - is_success = Core.Functions.GetPlayer(src).Functions.RemoveMoney("cash", cost) - - elseif isStarted(RSGExport) then - fundResource = RSGExport - is_success = Core.Functions.GetPlayer(src).Functions.RemoveMoney("cash", cost) - - elseif isStarted(ESXExport) then - fundResource = ESXExport - ESX.GetPlayerFromId(src).removeMoney(cost, "") - is_success = true + for i = 1, #moneyFunc do + local framework = moneyFunc[i] + if framework.framework == OXInv and moneyType == "bank" then goto skip end + if isStarted(framework.framework) then + debugPrint("^6Bridge^7: ^2Charging ^3"..framework.framework.." ^2Player^7: '^6"..cost.."^7'", moneyType) + is_success = framework.chargePlayer(src, cost, moneyType) + break end - elseif moneyType == "bank" then - if isStarted(QBExport) or isStarted(QBXExport) then - fundResource = QBExport - is_success = Core.Functions.GetPlayer(src).Functions.RemoveMoney("bank", cost) - - elseif isStarted(RSGExport) then - fundResource = RSGExport - is_success = Core.Functions.GetPlayer(src).Functions.RemoveMoney("bank", cost) - - elseif isStarted(ESXExport) then - fundResource = ESXExport - ESX.GetPlayerFromId(src).removeMoney(cost, "") - is_success = true - end - end - - if fundResource == "" then - print("Cannot charge player - check starter.lua") - else - debugPrint("^6Bridge^7: ^2Charging ^2Player^7: '^6"..cost.."^7'", moneyType, fundResource) + ::skip:: end return is_success end + RegisterNetEvent(getScript()..":server:ChargePlayer", function(cost, moneyType, newsrc) - debugPrint(GetInvokingResource()) 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") + print(GetInvokingResource()) + print("^1Error^7: ^1Possible exploit^7, ^1vital function was called from an external resource^7") return end chargePlayer(cost, moneyType, newsrc) @@ -246,48 +280,23 @@ end) function fundPlayer(fund, moneyType, newsrc) local is_success = false local src = newsrc or source - local fundResource = "" - if moneyType == "cash" then - if isStarted(OXInv) then - fundResource = OXInv - is_success = exports[OXInv]:AddItem(src, "money", fund) - - elseif isStarted(QBExport) or isStarted(QBXExport) then - fundResource = QBExport - is_success = Core.Functions.GetPlayer(src).Functions.AddMoney("cash", fund) - - elseif isStarted(RSGExport) then - fundResource = RSGExport - is_success = Core.Functions.GetPlayer(src).Functions.AddMoney("cash", fund) - - elseif isStarted(ESXExport) then - fundResource = ESXExport - ESX.GetPlayerFromId(src).addMoney(fund, "") - is_success = true - - end - elseif moneyType == "bank" then - if isStarted(QBExport) or isStarted(QBXExport) then - fundResource = QBExport - is_success = Core.Functions.GetPlayer(src).Functions.AddMoney("bank", fund) - - elseif isStarted(RSGExport) then - fundResource = RSGExport - is_success = Core.Functions.GetPlayer(src).Functions.AddMoney("bank", fund) - - elseif isStarted(ESXExport) then - fundResource = ESXExport - ESX.GetPlayerFromId(src).addMoney(fund, "") - is_success = true - end + if fund <= 0 then + debugPrint("^1Error^7: ^7SRC: ^3"..src.." ^2Tried to fund a zero or minus value^7", fund) + return end - if fundResource == "" then - print("Cannot fund player - check starter.lua") - else - debugPrint("^6Bridge^7: ^2Funding Player: '^2"..fund.."^7'", moneyType, fundResource) + for i = 1, #moneyFunc do + local framework = moneyFunc[i] + if framework.framework == OXInv and moneyType == "bank" then goto skip end + if isStarted(framework.framework) then + debugPrint("^6Bridge^7: ^2Funding ^3"..framework.framework.." ^2Player^7: '^6"..cost.."^7'", moneyType) + is_success = framework.chargePlayer(src, fund, moneyType) + break + end + ::skip:: end + return is_success end @@ -534,6 +543,303 @@ function hasJob(job, source, grade) return hasJobFlag, duty end +---------------------------------- +--- +local getPlayerFunc = { + { framework = ESXExport, + serverSide = + function(src) + local Player = {} + local info = ESX.GetPlayerFromId(src) + if not info then return {} end + Player = { + name = info.getName(), + cash = info.getMoney(), + bank = info.getAccount("bank").money, + + firstname = info.variables.firstName, + lastname = info.variables.lastName, + + source = info.source, + job = info.job.name, + --jobBoss = info.job.isboss, + --gang = info.gang.name, + --gangBoss = info.gang.isboss, + onDuty = info.job.onDuty, + --account = info.charinfo.account, + citizenId = info.identifier, + } + return Player + end, + + clientSide = + function() + local Player = {} + local info = ESX.GetPlayerData() + if not info.firstName then return {} end + + local cash, bank = 0, 0 + for _, v in pairs(info.accounts) do + if v.name == "money" then cash = v.money end + if v.name == "bank" then bank = v.money end + end + Player = { + firstname = info.firstName, + lastname = info.lastName, + name = info.firstName.." "..info.lastName, + cash = cash, + bank = bank, + source = GetPlayerServerId(PlayerId()), + job = info.job.name, + --jobBoss = info.job.isboss, + --gang = info.gang.name, + --gangBoss = info.gang.isboss, + onDuty = info.job.onDuty, + --account = info.charinfo.account, + citizenId = info.identifier, + isDead = IsEntityDead(PlayerPedId()), + isDown = IsPedDeadOrDying(PlayerPedId(), true) + } + return Player + end, + }, + + { framework = OXCoreExport, + serverSide = + function(src) + local Player = {} + local file = ('imports/%s.lua'):format('server') + local import = LoadResourceFile('ox_core', file) + local chunk = assert(load(import, ('@@ox_core/%s'):format(file))) + chunk() + local player = Ox.GetPlayer(src) + if not player then return {} end + Player = { + firstname = player.firstName, + lastname = player.lastName, + name = ('%s %s'):format(player.firstName, player.lastName), + cash = exports[OXInv]:Search(src, 'count', "money"), + bank = 0, + source = src, + --job = OxPlayer.getGroups(), + --jobBoss = info.job.isboss, + --gang = OxPlayer.getGroups(), + --gangBoss = info.gang.isboss, + --onDuty = info.job.onduty, + --account = info.charinfo.account, + citizenId = player.stateId, + } + return Player + end, + + clientSide = + function() + local Player = {} + if not OxPlayer.userId then return {} end + Player = { + firstname = OxPlayer.get("firstName"), + lastname = OxPlayer.get("lastName"), + name = OxPlayer.get("firstName").." "..OxPlayer.get("lastName"), + cash = exports[OXInv]:Search('count', "money"), + bank = 0, + source = GetPlayerServerId(PlayerId()), + job = OxPlayer.getGroups(), + --jobBoss = info.job.isboss, + gang = OxPlayer.getGroups(), + --gangBoss = info.gang.isboss, + --onDuty = info.job.onduty, + --account = info.charinfo.account, + citizenId = OxPlayer.userId, + isDead = IsEntityDead(PlayerPedId()), + isDown = IsPedDeadOrDying(PlayerPedId(), true) + } + return Player + end, + }, + + { framework = QBXExport, + serverSide = + function(src) + local Player = {} + local info = exports[QBXExport]:GetPlayer(src) + if not info then return {} end + Player = { + firstname = info.PlayerData.charinfo.firstname, + lastname = info.PlayerData.charinfo.lastname, + name = info.PlayerData.charinfo.firstname.." "..info.PlayerData.charinfo.lastname, + cash = exports[OXInv]:Search(src, 'count', "money"), + bank = info.Functions.GetMoney("bank"), + source = info.PlayerData.source, + job = info.PlayerData.job.name, + jobBoss = info.PlayerData.job.isboss, + jobInfo = info.PlayerData.job, + gang = info.PlayerData.gang.name, + gangInfo = info.PlayerData.gang, + gangBoss = info.PlayerData.gang.isboss, + onDuty = info.PlayerData.job.onduty, + account = info.PlayerData.charinfo.account, + citizenId = info.PlayerData.citizenid, + isDead = info.PlayerData.metadata["isdead"], + isDown = info.PlayerData.metadata["inlaststand"], + charInfo = info.charinfo, + } + return Player + end, + + clientSide = + function() + local Player = {} + local info = exports[QBXExport]:GetPlayerData() + if not info.charinfo then return {} end + Player = { + firstname = info.charinfo.firstname, + lastname = info.charinfo.lastname, + name = info.charinfo.firstname.." "..info.charinfo.lastname, + cash = info.money["cash"], + bank = info.money["bank"], + source = info.source, + job = info.job.name, + jobBoss = info.job.isboss, + jobInfo = info.job, + gang = info.gang.name, + gangBoss = info.gang.isboss, + gangInfo = info.gang, + onDuty = info.job.onduty, + account = info.charinfo.account, + citizenId = info.citizenid, + isDead = info.metadata["isdead"], + isDown = info.metadata["inlaststand"], + charInfo = info.charinfo, + } + return Player + end, + }, + + { framework = QBExport, + serverSide = + function(src) + local Player = {} + if Core.Functions.GetPlayer(src) then + local info = Core.Functions.GetPlayer(src).PlayerData + if not info then return {} end + Player = { + firstname = info.charinfo.firstname, + lastname = info.charinfo.lastname, + name = info.charinfo.firstname.." "..info.charinfo.lastname, + cash = info.money["cash"], + bank = info.money["bank"], + source = info.source, + job = info.job.name, + jobBoss = info.job.isboss, + jobInfo = info.job, + gang = info.gang.name, + gangBoss = info.gang.isboss, + gangInfo = info.gang, + onDuty = info.job.onduty, + account = info.charinfo.account, + citizenId = info.citizenid, + isDead = info.metadata["isdead"], + isDown = info.metadata["inlaststand"], + charInfo = info.charinfo, + } + end + return Player + end, + + clientSide = + function() + local Player = {} + local info = nil + Core.Functions.GetPlayerData(function(PlayerData) info = PlayerData end) + if not info.charinfo then return {} end + + Player = { + firstname = info.charinfo.firstname, + lastname = info.charinfo.lastname, + name = info.charinfo.firstname.." "..info.charinfo.lastname, + cash = info.money["cash"], + bank = info.money["bank"], + source = info.source, + job = info.job.name, + jobBoss = info.job.isboss, + jobInfo = info.job, + gang = info.gang.name, + gangBoss = info.gang.isboss, + gangInfo = info.gang, + onDuty = info.job.onduty, + account = info.charinfo.account, + citizenId = info.citizenid, + isDead = info.metadata["isdead"], + isDown = info.metadata["inlaststand"], + charInfo = info.charinfo, + } + return Player + end, + }, + + { framework = RSGExport, + serverSide = + function(src) + local Player = {} + if Core.Functions.GetPlayer(src) then + local info = Core.Functions.GetPlayer(src).PlayerData + if not info then return {} end + Player = { + firstname = info.charinfo.firstname, + lastname = info.charinfo.lastname, + name = info.charinfo.firstname.." "..info.charinfo.lastname, + cash = info.money["cash"], + bank = info.money["bank"], + source = info.source, + job = info.job.name, + jobBoss = info.job.isboss, + jobInfo = info.job, + gang = info.gang.name, + gangBoss = info.gang.isboss, + gangInfo = info.gang, + onDuty = info.job.onduty, + account = info.charinfo.account, + citizenId = info.citizenid, + isDead = info.metadata["isdead"], + isDown = info.metadata["inlaststand"], + charInfo = info.charinfo, + } + end + return Player + end, + + clientSide = + function() + local Player = {} + local info = nil + Core.Functions.GetPlayerData(function(PlayerData) info = PlayerData end) + if not info.charinfo then return {} end + + Player = { + firstname = info.charinfo.firstname, + lastname = info.charinfo.lastname, + name = info.charinfo.firstname.." "..info.charinfo.lastname, + cash = info.money["cash"], + bank = info.money["bank"], + source = info.source, + job = info.job.name, + jobBoss = info.job.isboss, + jobInfo = info.job, + gang = info.gang.name, + gangBoss = info.gang.isboss, + gangInfo = info.gang, + onDuty = info.job.onduty, + account = info.charinfo.account, + citizenId = info.citizenid, + isDead = info.metadata["isdead"], + isDown = info.metadata["inlaststand"], + charInfo = info.charinfo, + } + return Player + end, + }, +} + --- Retrieves basic player information (name, cash, bank, job, etc.) based on the active core/inventory system. --- --- Can be called server-side (passing a player source) or client-side (for current player). @@ -556,258 +862,25 @@ function getPlayer(source) --debugPrint("^6Bridge^7: ^2Getting ^3Player^2 info^7") if source then - local src = tonumber(source) - if isStarted(ESXExport) then - local info = ESX.GetPlayerFromId(src) - if not info then return {} end - Player = { - name = info.getName(), - cash = info.getMoney(), - bank = info.getAccount("bank").money, - firstname = info.variables.firstName, - lastname = info.variables.lastName, - - source = info.source, - job = info.job.name, - --jobBoss = info.job.isboss, - --gang = info.gang.name, - --gangBoss = info.gang.isboss, - onDuty = info.job.onDuty, - --account = info.charinfo.account, - citizenId = info.identifier, - } - - elseif isStarted(OXCoreExport) then - local file = ('imports/%s.lua'):format('server') - local import = LoadResourceFile('ox_core', file) - local chunk = assert(load(import, ('@@ox_core/%s'):format(file))) - chunk() - local player = Ox.GetPlayer(src) - if not player then return {} end - Player = { - firstname = player.firstName, - lastname = player.lastName, - name = ('%s %s'):format(player.firstName, player.lastName), - cash = exports[OXInv]:Search(src, 'count', "money"), - bank = 0, - source = src, - --job = OxPlayer.getGroups(), - --jobBoss = info.job.isboss, - --gang = OxPlayer.getGroups(), - --gangBoss = info.gang.isboss, - --onDuty = info.job.onduty, - --account = info.charinfo.account, - citizenId = player.stateId, - } - - elseif isStarted(QBXExport) then - local info = exports[QBXExport]:GetPlayer(src) - if not info then return {} end - Player = { - firstname = info.PlayerData.charinfo.firstname, - lastname = info.PlayerData.charinfo.lastname, - name = info.PlayerData.charinfo.firstname.." "..info.PlayerData.charinfo.lastname, - cash = exports[OXInv]:Search(src, 'count', "money"), - bank = info.Functions.GetMoney("bank"), - source = info.PlayerData.source, - job = info.PlayerData.job.name, - jobBoss = info.PlayerData.job.isboss, - jobInfo = info.PlayerData.job, - gang = info.PlayerData.gang.name, - gangInfo = info.PlayerData.gang, - gangBoss = info.PlayerData.gang.isboss, - onDuty = info.PlayerData.job.onduty, - account = info.PlayerData.charinfo.account, - citizenId = info.PlayerData.citizenid, - isDead = info.PlayerData.metadata["isdead"], - isDown = info.PlayerData.metadata["inlaststand"], - charInfo = info.charinfo, - } - - elseif isStarted(QBExport) and not isStarted(QBXExport) then - if Core.Functions.GetPlayer(src) then - local info = Core.Functions.GetPlayer(src).PlayerData - if not info then return {} end - Player = { - firstname = info.charinfo.firstname, - lastname = info.charinfo.lastname, - name = info.charinfo.firstname.." "..info.charinfo.lastname, - cash = info.money["cash"], - bank = info.money["bank"], - source = info.source, - job = info.job.name, - jobBoss = info.job.isboss, - jobInfo = info.job, - gang = info.gang.name, - gangBoss = info.gang.isboss, - gangInfo = info.gang, - onDuty = info.job.onduty, - account = info.charinfo.account, - citizenId = info.citizenid, - isDead = info.metadata["isdead"], - isDown = info.metadata["inlaststand"], - charInfo = info.charinfo, - } + for i = 1, #getPlayerFunc do + local framework = getPlayerFunc[i] + if isStarted(framework.framework) then + Player = framework.serverSide(source) + break end - - elseif isStarted(RSGExport) then - if Core.Functions.GetPlayer(src) then - local info = Core.Functions.GetPlayer(src).PlayerData - if not info then return {} end - Player = { - firstname = info.charinfo.firstname, - lastname = info.charinfo.lastname, - name = info.charinfo.firstname.." "..info.charinfo.lastname, - cash = info.money["cash"], - bank = info.money["bank"], - source = info.source, - job = info.job.name, - jobBoss = info.job.isboss, - jobInfo = info.job, - gang = info.gang.name, - gangBoss = info.gang.isboss, - gangInfo = info.gang, - onDuty = info.job.onduty, - account = info.charinfo.account, - citizenId = info.citizenid, - isDead = info.metadata["isdead"], - isDown = info.metadata["inlaststand"], - charInfo = info.charinfo, - } - - end - else - print("^4ERROR^7: ^2No Core detected for getPlayer() - Check starter.lua") end + else - -- Client-side: Get current player info. - if isStarted(ESXExport) and ESX ~= nil then - local info = ESX.GetPlayerData() - if not info.firstName then return {} end - local cash, bank = 0, 0 - for k, v in pairs(info.accounts) do - if v.name == "money" then cash = v.money end - if v.name == "bank" then bank = v.money end + for i = 1, #getPlayerFunc do + local framework = getPlayerFunc[i] + if isStarted(framework.framework) then + Player = framework.clientSide() + break end - Player = { - firstname = info.firstName, - lastname = info.lastName, - name = info.firstName.." "..info.lastName, - cash = cash, - bank = bank, - source = GetPlayerServerId(PlayerId()), - job = info.job.name, - --jobBoss = info.job.isboss, - --gang = info.gang.name, - --gangBoss = info.gang.isboss, - onDuty = info.job.onDuty, - --account = info.charinfo.account, - citizenId = info.identifier, - isDead = IsEntityDead(PlayerPedId()), - isDown = IsPedDeadOrDying(PlayerPedId(), true) - } - - elseif isStarted(OXCoreExport) then - if not OxPlayer.userId then return {} end - Player = { - firstname = OxPlayer.get("firstName"), - lastname = OxPlayer.get("lastName"), - name = OxPlayer.get("firstName").." "..OxPlayer.get("lastName"), - cash = exports[OXInv]:Search('count', "money"), - bank = 0, - source = GetPlayerServerId(PlayerId()), - job = OxPlayer.getGroups(), - --jobBoss = info.job.isboss, - gang = OxPlayer.getGroups(), - --gangBoss = info.gang.isboss, - --onDuty = info.job.onduty, - --account = info.charinfo.account, - citizenId = OxPlayer.userId, - isDead = IsEntityDead(PlayerPedId()), - isDown = IsPedDeadOrDying(PlayerPedId(), true) - } - - elseif isStarted(QBXExport) then - local info = exports[QBXExport]:GetPlayerData() - if not info.charinfo then return {} end - Player = { - firstname = info.charinfo.firstname, - lastname = info.charinfo.lastname, - name = info.charinfo.firstname.." "..info.charinfo.lastname, - cash = info.money["cash"], - bank = info.money["bank"], - source = info.source, - job = info.job.name, - jobBoss = info.job.isboss, - jobInfo = info.job, - gang = info.gang.name, - gangBoss = info.gang.isboss, - gangInfo = info.gang, - onDuty = info.job.onduty, - account = info.charinfo.account, - citizenId = info.citizenid, - isDead = info.metadata["isdead"], - isDown = info.metadata["inlaststand"], - charInfo = info.charinfo, - } - - elseif isStarted(QBExport) and not isStarted(QBXExport) then - local info = nil - Core.Functions.GetPlayerData(function(PlayerData) info = PlayerData end) - if not info.charinfo then return {} end - - Player = { - firstname = info.charinfo.firstname, - lastname = info.charinfo.lastname, - name = info.charinfo.firstname.." "..info.charinfo.lastname, - cash = info.money["cash"], - bank = info.money["bank"], - source = info.source, - job = info.job.name, - jobBoss = info.job.isboss, - jobInfo = info.job, - gang = info.gang.name, - gangBoss = info.gang.isboss, - gangInfo = info.gang, - onDuty = info.job.onduty, - account = info.charinfo.account, - citizenId = info.citizenid, - isDead = info.metadata["isdead"], - isDown = info.metadata["inlaststand"], - charInfo = info.charinfo, - } - - elseif isStarted(RSGExport) then - local info = nil - Core.Functions.GetPlayerData(function(PlayerData) info = PlayerData end) - if not info.charinfo then return {} end - - Player = { - firstname = info.charinfo.firstname, - lastname = info.charinfo.lastname, - name = info.charinfo.firstname.." "..info.charinfo.lastname, - cash = info.money["cash"], - bank = info.money["bank"], - source = info.source, - job = info.job.name, - jobBoss = info.job.isboss, - jobInfo = info.job, - gang = info.gang.name, - gangBoss = info.gang.isboss, - gangInfo = info.gang, - onDuty = info.job.onduty, - account = info.charinfo.account, - citizenId = info.citizenid, - isDead = info.metadata["isdead"], - isDown = info.metadata["inlaststand"], - charInfo = info.charinfo, - } - - else - print("^4ERROR^7: ^2No Core detected for hasJob ^7- ^2Check ^3starter^1.^2lua^7") end + end return Player end From ceeb9021d91bbbd179c61c6e914ea5cb7536ee57 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Fri, 15 Aug 2025 17:26:18 +0100 Subject: [PATCH 06/10] Raise version check messages to hourly --- _versioncheck.lua | 2 +- shared/_scriptversioncheck.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_versioncheck.lua b/_versioncheck.lua index 07988a9..2423e78 100644 --- a/_versioncheck.lua +++ b/_versioncheck.lua @@ -52,7 +52,7 @@ function CheckBridgeVersion() print((line:find("http") and "^7" or "^5")..line) end print("^1----------------------------------------------------------------------^7") - SetTimeout(1200000, function() + SetTimeout(3600000, function() CheckBridgeVersion() end) else diff --git a/shared/_scriptversioncheck.lua b/shared/_scriptversioncheck.lua index d771ffd..7562e26 100644 --- a/shared/_scriptversioncheck.lua +++ b/shared/_scriptversioncheck.lua @@ -87,7 +87,7 @@ function CheckVersion() end end print("^1----------------------------------------------------------------------^7") - SetTimeout(1200000, function() CheckVersion() end) + SetTimeout(3600000, function() CheckVersion() end) else print("^7'^3"..script.."^7' - ^5You are running a newer version ^7(^3"..currentVersionRaw.."^7 ← ^3"..newestVersion.."^7)") end From 85626d335603373b55a87bf01e950ec0f866e62d Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Fri, 15 Aug 2025 18:35:21 +0100 Subject: [PATCH 07/10] Fix qbx getplayer call --- shared/metaHandlers.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/metaHandlers.lua b/shared/metaHandlers.lua index 9e66d7f..9432c79 100644 --- a/shared/metaHandlers.lua +++ b/shared/metaHandlers.lua @@ -10,7 +10,7 @@ local metaDataFunc = { { framework = QBXExport, GetPlayer = function(src) - return exports[QBXExport]:GetCoreObject().Functions.GetPlayer(src) + return exports[QBXExport]:GetPlayer(src) end, GetPlayerMetadata = function(Player, dataToCheck) From 5f81bfa89954a84c886eaa0a12c48eedbb68dd0f Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Sun, 17 Aug 2025 02:10:21 +0100 Subject: [PATCH 08/10] Add distExploitCheck function (will be used soon) I'm adding distance based exploit protection to stashes, shops and selling shops to help fight exploiters Soon all these created through jim_bridge will refuse opening if its not "registered" correctly Basically, all my scripts will get updates to support this --- shared/_authToken.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/shared/_authToken.lua b/shared/_authToken.lua index e8de386..901aa32 100644 --- a/shared/_authToken.lua +++ b/shared/_authToken.lua @@ -115,4 +115,30 @@ else debugPrint("^1Auth^7: ^2Clearing Auth Event^7") TriggerServerEvent(getScript()..":clearAuthEventRequest") end, true) +end + +function distExploitCheck(table, src) + + if not table then + --print("^1Error^7: ^1This wasn^7'^1t reigstered correctly or this is an exploit attempt^1") + return false + end + + local ped = src and GetPlayerPed(src) or PlayerPedId() + local srcCoords = GetEntityCoords(ped) + local allow = false + + for i = 1, #table do + if #(table[i] - srcCoords) <= 10 then + return true + else + allow = false + end + end + + if not allow then + debugPrint(src and ("^1Src ^3"..src.." ").."^1Tried to open a registered shop/stash from over the distance limit^7") + return false + end + end \ No newline at end of file From 8b0e4d803f7ef61aab325819675004d494514fe5 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Sun, 17 Aug 2025 02:10:38 +0100 Subject: [PATCH 09/10] Fix typos breaking fundPlayer function --- shared/playerfunctions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/playerfunctions.lua b/shared/playerfunctions.lua index 7f627fb..82f0dd9 100644 --- a/shared/playerfunctions.lua +++ b/shared/playerfunctions.lua @@ -290,8 +290,8 @@ function fundPlayer(fund, moneyType, newsrc) local framework = moneyFunc[i] if framework.framework == OXInv and moneyType == "bank" then goto skip end if isStarted(framework.framework) then - debugPrint("^6Bridge^7: ^2Funding ^3"..framework.framework.." ^2Player^7: '^6"..cost.."^7'", moneyType) - is_success = framework.chargePlayer(src, fund, moneyType) + debugPrint("^6Bridge^7: ^2Funding ^3"..framework.framework.." ^2Player^7: '^6"..fund.."^7'", moneyType) + is_success = framework.fundPlayer(src, fund, moneyType) break end ::skip:: From bd94b14dad4d38b9ade736de201608d91de2e778 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Sun, 17 Aug 2025 02:20:13 +0100 Subject: [PATCH 10/10] Start working on coordinate based exploit checks These currently work as intended, but can't put in place yet because my scripts don't fully support it yet. But the base is there for it Also slip in `bannedItems` table so players can't the abuse sell items function to spawn cash --- shared/itemcontrol.lua | 186 ++++++++++++++++++++++++++++++++++------- 1 file changed, 154 insertions(+), 32 deletions(-) diff --git a/shared/itemcontrol.lua b/shared/itemcontrol.lua index e6a912d..a12da77 100644 --- a/shared/itemcontrol.lua +++ b/shared/itemcontrol.lua @@ -66,8 +66,8 @@ local InvFunc = { return "nui://"..OXInv.."/web/images/"..(Items[item].image or "") end, openShop = - function(data) - exports[OXInv]:openInventory('shop', { type = data.shop }) + function(name, label, items) + exports[OXInv]:openInventory('shop', { type = name }) end, serverOpenShop = function(shopName) -- @@ -168,8 +168,8 @@ local InvFunc = { return "nui://"..QSInv.."/html/images/"..(Items[item].image or "") end, openShop = - function(data) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + function(name, label, items) + TriggerServerEvent("inventory:server:OpenInventory", "shop", label, items) end, serverOpenShop = function(shopName) -- @@ -261,7 +261,7 @@ local InvFunc = { return "nui://"..CoreInv.."/html/img/"..(Items[item].image or "") end, openShop = - function(data) + function(name, label, items) -- end, serverOpenShop = @@ -351,7 +351,7 @@ local InvFunc = { return "nui://"..OrigenInv.."/html/img/"..(Items[item].image or "") end, openShop = - function(data) + function(name, label, items) -- end, serverOpenShop = @@ -453,8 +453,8 @@ local InvFunc = { return "nui://"..CodeMInv.."/html/itemimages/"..(Items[item].image or "") end, openShop = - function(data) - TriggerEvent("codem-inventory:openshop", data.shop) + function(name, label, items) + TriggerEvent("codem-inventory:openshop", name) end, serverOpenShop = function(shopName) @@ -552,8 +552,8 @@ local InvFunc = { return "nui://inventory_images/images/"..(Items[item].image or "") end, openShop = - function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + function(name, label, items) + TriggerServerEvent(getScript()..':server:openServerShop', name) end, serverOpenShop = function(shopName) @@ -684,9 +684,9 @@ local InvFunc = { return "nui://"..JPRInv.."/html/images/"..(Items[item].image or "") end, openShop = - function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + function(name, label, items) + TriggerServerEvent(getScript()..':server:openServerShop', name) + TriggerServerEvent("inventory:server:OpenInventory", "shop", label, items) end, serverOpenShop = function(shopName) @@ -851,9 +851,9 @@ local InvFunc = { return "nui://"..QBInv.."/html/images/"..(Items[item].image or "") end, openShop = - function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + function(name, label, items) + TriggerServerEvent(getScript()..':server:openServerShop', name) + TriggerServerEvent("inventory:server:OpenInventory", "shop", label, items) end, serverOpenShop = function(shopName) @@ -1041,9 +1041,9 @@ local InvFunc = { return "nui://"..PSInv.."/html/images/"..(Items[item].image or "") end, openShop = - function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) - TriggerServerEvent("inventory:server:OpenInventory", "shop", data.items.label, data.items) + function(name, label, items) + TriggerServerEvent(getScript()..':server:openServerShop', name) + TriggerServerEvent("inventory:server:OpenInventory", "shop", label, items) end, serverOpenShop = function(shopName) @@ -1202,8 +1202,8 @@ local InvFunc = { return "nui://"..RSGInv.."/html/images/"..(Items[item].image or "") end, openShop = - function(data) - TriggerServerEvent(getScript()..':server:openServerShop', data.shop) + function(name, label, items) + TriggerServerEvent(getScript()..':server:openServerShop', name) end, serverOpenShop = function(shopName) @@ -2093,6 +2093,14 @@ end ------------------------------------------------------------- -- Stash Opening Functions ------------------------------------------------------------- +--- +local stashExploitCheck = {} + +if isServer() then + createCallback(getScript()..":getRegisteredStashLocations", function(src, stashName) + return stashExploitCheck[stashName] + end) +end --- Opens a stash using the active inventory system. --- @@ -2114,6 +2122,15 @@ end function openStash(data) if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end + --local exploitCheck = triggerCallback(getScript()..":getRegisteredStashLocations", data.stash) + --if not exploitCheck then + -- print("^3Warning^7: ^2This isn't a registered stash^1, refusing call^7") + -- return + --end + --if not distExploitCheck(exploitCheck) then + -- return + --end + for i = 1, #InvFunc do local inv = InvFunc[i] if isStarted(inv.invName) then @@ -2138,6 +2155,15 @@ end -- Messy but not much else I can do about it. RegisterNetEvent(getScript()..":server:openServerStash", function(data) local src = source + + --if not stashExploitCheck[data.stashName] then + -- print("^3Warning^7: ^1Source^7: ^3"..src.." ^1Tried to open a shop^7: ^2This isn't a registered stash^1, refusing call^7") + -- return + --end + --if not distExploitCheck(stashExploitCheck[data.stashName]) then + -- return + --end + if isStarted(TgiannInv) then exports[TgiannInv]:OpenInventory(source, 'stash', data.stashName, data) end @@ -2346,6 +2372,12 @@ function registerStash(name, label, slots, weight, owner, coords) return end end + if coords then + stashExploitCheck[name] = stashExploitCheck[name] or {} + stashExploitCheck[name][#stashExploitCheck[name]+1] = coords + else + print("^3Warning^7: ^1Stash ^4"..name.." ^1doesn^7'^1t have coords^7, ^1this is exploitable^7, ^1add coords to ^3regiterStash^7()") + end end if isServer() then @@ -2395,6 +2427,13 @@ end) -- Selling Menu and Animation ------------------------------------------------------------- +local sellShopExploitCheck = {} +if isServer() then + createCallback(getScript()..":getRegisteredSellShopLocation", function(src, name) + return sellShopExploitCheck[name] or nil + end) +end + --- Opens a selling menu with available items and prices. --- --- @param data table Contains selling menu data: @@ -2417,6 +2456,16 @@ end) --- ``` function sellMenu(data) local origData = data + + --local exploitCheck = triggerCallback(getScript()..":getRegisteredSellShopLocation", data.name) + --if not exploitCheck then + -- print("^3Warning^7: ^2This isn't a registered store^1, refusing call^7") + -- return + --end + --if not distExploitCheck(exploitCheck) then + -- return + --end + local Menu = {} if data.sellTable.Items then local itemList = {} @@ -2431,7 +2480,9 @@ function sellMenu(data) txt = (Loc and Loc[Config.Lan]) and Loc[Config.Lan].info["sell_all"]..v.." "..Loc[Config.Lan].info["sell_each"] or "Sell ALL at $"..v.." each", onSelect = function() - sellAnim({ item = k, price = v, ped = data.ped, onBack = function() sellMenu(data) end }) + + local token = triggerCallback(AuthEvent) + sellAnim({ item = k, price = v, ped = data.ped, onBack = function() sellMenu(data) end }, token) end, } end @@ -2481,7 +2532,7 @@ end --- onBack = function() sellMenu(data) end, --- }) --- ``` -function sellAnim(data) +function sellAnim(data, token) if not hasItem(data.item, 1) then triggerNotify(nil, Loc[Config.Lan].error["dont_have"].." "..Items[data.item].label, "error") return @@ -2500,7 +2551,7 @@ function sellAnim(data) end end - TriggerServerEvent(getScript().."Sellitems", data) + TriggerServerEvent(getScript()..":Sellitems", data, token) lookEnt(data.ped) local dict = "mp_common" playAnim(dict, "givetake2_a", 0.3, 48) @@ -2513,23 +2564,63 @@ function sellAnim(data) end end +local bannedItems = { + money = true, + cash = true, + bank = true, + crypto = true, + blackmoney = true, + dirty_money = true, + markedbills = true +} + --- Server event handler for processing item sales. --- Removes sold items from inventory and funds the player based on the sale. -RegisterNetEvent(getScript().."Sellitems", function(data) +RegisterNetEvent(getScript()..":Sellitems", function(data, token) local src = source + + if not checkToken(src, token, "item", "cash") then + return + end + -- Check bannedItems list + for k, v in pairs(bannedItems) do + if data.item == k then + dupeWarn(src, data.item, "^3Source^7: "..src.." ^1Tried to spawn banned item with sell items function") + return + end + end + local hasItems, hasTable = hasItem(data.item, 1, src) if hasItems then removeItem(data.item, hasTable[data.item].count, src) + print((hasTable[data.item].count * data.price), data.price) fundPlayer((hasTable[data.item].count * data.price), "cash", src) else triggerNotify(nil, Loc[Config.Lan].error["dont_have"].." "..Items[data.item].label, "error", src) end end) +function registerSellShop(name, coords) + if coords and type(coords) == "vector3" then + print("Registered Sell Shop "..name.." Correctly") + sellShopExploitCheck[name] = sellShopExploitCheck[name] or {} + sellShopExploitCheck[name][#sellShopExploitCheck[name]+1] = coords + end +end + ------------------------------------------------------------- -- Shop Interface ------------------------------------------------------------- +-- Keep a local cache of all registered shops coords, if they are actually registering in the inventory or not +local shopExploitCheck = {} + +if isServer() then + createCallback(getScript()..":getRegisteredShopLocation", function(src, name) + return shopExploitCheck[name] or nil + end) +end + --- Opens a shop interface for the player. --- --- Checks job/gang restrictions, then uses the active inventory system to open the shop. @@ -2548,9 +2639,19 @@ end) --- }) --- ``` function openShop(data) - jsonPrint(data) + --jsonPrint(data) if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end + -- If shop has registered coords, limit players from being too far away from it when opening + --local exploitCheck = triggerCallback(getScript()..":getRegisteredShopLocation", data.shop) + --if not exploitCheck then + -- print("^3Warning^7: ^2This isn't a registered store^1, refusing call^7") + -- return + --end + --if not distExploitCheck(exploitCheck) then + -- return + --end + if Config.General.JimShops then TriggerServerEvent("jim-shops:ShopOpen", "shop", data.items.label, data.items) lookEnt(data.coords) @@ -2559,14 +2660,26 @@ function openShop(data) for i = 1, #InvFunc do local inv = InvFunc[i] if isStarted(inv.invName) then - inv.openShop(data) + inv.openShop(data.shop, data.items.label, data.items) lookEnt(data.coords) break end end + end RegisterNetEvent(getScript()..':server:openServerShop', function(shopName) + local src = source + + -- If shop has registered coords, limit players from being too far away from it when opening + --if not shopExploitCheck[data.shop] then + -- print("^3Warning^7: ^1Source^7: ^3"..src.." ^1Tried to open a shop^7: ^2This isn't a registered store^1, refusing call^7") + -- return + --end + --if not distExploitCheck(shopExploitCheck[data.shop]) then + -- return + --end + for i = 1, #InvFunc do local inv = InvFunc[i] if isStarted(inv.invName) then @@ -2574,10 +2687,10 @@ RegisterNetEvent(getScript()..':server:openServerShop', function(shopName) break end end + end) --- Registers a shop with the active inventory system. ---- Supports either OXInv or QBInv (with QBInvNew flag). --- --- @param name string Unique shop identifier. --- @param label string Display name for the shop. @@ -2587,21 +2700,30 @@ end) --- ```lua --- registerShop("weaponShop", "Weapon Shop", weaponItems, "society_weapons") --- ``` -function registerShop(name, label, items, society) +function registerShop(name, label, items, society, coords) local shopResource = "" for i = 1, #InvFunc do local inv = InvFunc[i] if isStarted(inv.invName) then - shopResource = inv.invName - inv.registerShop(name, label, items, society) + shopResource = inv.invName + inv.registerShop(name, label, items, society) break end end + -- If received coords, pass them to distance check cache + if coords and type(coords) == "vector3" then + --print("Registered Shop Correctly") + shopExploitCheck[name] = shopExploitCheck[name] or {} + shopExploitCheck[name][#shopExploitCheck[name]+1] = coords + else + print("^3Warning^7: ^1Store ^4"..name.." ^1doesn^7'^1t have coords^7, ^1this is exploitable^7, ^1add coords to ^3regiterShop^7()") + end + if shopResource ~= "" then debugPrint("^6Bridge^7: ^2Registering ^5"..shopResource.." ^3Store^7:", name, "^4Label^7: "..label) else -- debugPrint("^1ERROR^7: ^1Couldn't find supported inventory to register shop^7:", name) end -end \ No newline at end of file +end