diff --git a/README.md b/README.md
index 0eb0c9b..7b7ea0f 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,26 @@
-# jim_bridge
-Framework bridge script
+# Jim_Bridge
+
+This script is intended to be used with my all my scripts (soon)
+
+It was started due to wanting to bring the same features from some scripts into others with minimal work and multiple updates
+- Having certain functions in one place(this script) makes it easier to update, enchance and fix things
+- This brings the possibility of branching to mutliple frameworks as I've added some already:
+ - `"qb-core"`
+ - `"qbx-core"`
+ - `"ox_core"`
+ - `"es_extended"` (requires ox_lib and ox_inventory)
+
+All the next updates of my scripts will use this script and be added as a dependancy
+
+------
+
+It was a tough decision to put it up on github instead of tebex and encrypted
+
+But I want this script to grow with help of others who know more about other cores
+
+---
+
+The installation of this script is simple
+- it just needs to start before any script that requires it
+- it can start before core scripts if you want
+- for `qb-core` I personally place this script in `resources > [standalone]`
\ No newline at end of file
diff --git a/crafting.lua b/crafting.lua
new file mode 100644
index 0000000..414ea97
--- /dev/null
+++ b/crafting.lua
@@ -0,0 +1,501 @@
+if GetResourceState(OXLibExport):find("start") then
+ createCallback(GetCurrentResourceName()..':server:GetStashItems', function(source, stashName) local stash = getStash(stashName) return stash end)
+else
+ createCallback(GetCurrentResourceName()..':server:GetStashItems', function(source, cb, stashName) local stash = getStash(stashName) cb(stash) end)
+end
+
+local timeout = 0
+local timing = false
+local stashItems = {}
+function GetStashTimeout(stashName, stop)
+ if stop then stashItems = {} timing = false timeout = 0 return end
+ if stashItems[1] then return true else
+ if timeout <= 0 then
+ stashItems = triggerCallback(GetCurrentResourceName()..':server:GetStashItems', stashName)
+ timeout = 15000
+ if not timing then
+ CreateThread(function()
+ timing = true
+ while timeout > 0 do timeout -= 1000 Wait(1000) end
+ timing = false stashItems = {} timeout = 0
+ end)
+ end
+ end
+ return false
+ end
+end
+
+local CraftLock = false
+function craftingMenu(data)
+ if CraftLock then return end
+ if data.stashName and not GetStashTimeout(data.stashName) then
+ --triggerNotify(nil, "Chacking", "success")
+ end
+ if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end
+ local Menu = {}
+ local Recipes = data.craftable.Recipes
+ for i = 1, #Recipes do
+ for k, v in pairs(Recipes[i]) do
+ if k ~= "amount" and k ~= "job" and k ~= "gang" then
+ if Recipes[i].job then hasjob = false
+ for l, b in pairs(data.craftable[i]["job"]) do
+ hasjob = hasJob(l)
+ end
+ end
+ local setheader, settext = "", ""
+ local text = ""
+ local disable = false
+ local checktable = {}
+ if Recipes[i].job and hasjob == false then else
+ for l, b in pairs(Recipes[i][tostring(k)]) do
+ if not Items[l] then print("^3Error^7: ^2Script can't find ingredient item in Shared Items - ^1"..l.."^7") return end
+ settext = settext..(settext ~= "" and br or "")..Items[l].label..(b > 1 and " x"..b or "")
+ if data.stashName then checktable[l] = stashhasItem(stashItems, l, b)
+ else checktable[l] = hasItem(l, b) end
+ Wait(0)
+ end
+ for _, v in pairs(checktable) do
+ if not v then
+ disable = true
+ break
+ end
+ end
+ setheader = Items[tostring(k)].label..(Recipes[i]["amount"] > 1 and " x"..Recipes[i]["amount"] or "")..(not disable and " ✔️" or "")
+ Menu[#Menu + 1] = {
+ isMenuHeader = disable,
+ icon = invImg(tostring(k)),
+ header = setheader, txt = settext,
+ onSelect = function()
+ local transdata = { item = k, craft = data.craftable.Recipes[i], craftable = data.craftable, coords = data.coords, stashName = data.stashName, onBack = data.onBack }
+ if Config.Crafting.MultiCraft then
+ multiCraft(transdata)
+ else
+ makeItem(transdata)
+ end
+ end,
+ }
+ end
+ end
+ end
+ end
+ openMenu(Menu, { header = data.craftable.Header, onBack = data.onBack or nil, canClose = true, onExit = function() end, })
+ lookEnt(data.coords)
+end
+
+function multiCraft(data) local Menu = {}
+ local success = Config.Crafting.MultiCraftAmounts
+ if data.stashName and not GetStashTimeout(data.stashName) then
+ --triggerNotify(nil, "Refreshing stashinfo", "success")
+ end
+ Menu[#Menu+1] = {
+ isMenuHeader = true,
+ icon = invImg(data.item),
+ header = Items[data.item].label,
+ }
+ for k in pairsByKeys(success) do
+ local settext = ""
+ for l, b in pairs(data.craft[data.item]) do
+ if data.stashName then
+ success[k] = stashhasItem(stashItems, l, (b * k))
+ else
+ success[k] = hasItem(l, (b * k))
+ end
+ settext = settext..(settext ~= "" and br or "")..Items[l].label..(b*k > 1 and "- x"..b*k or "")
+ Wait(0)
+ end
+ Menu[#Menu + 1] = {
+ isMenuHeader = not success[k],
+ header = "Craft - x"..k * data.craft.amount,
+ txt = settext,
+ onSelect = function ()
+ makeItem({item = data.item, craft = data.craft, craftable = data.craftable, amount = k, coords = data.coords, stashName = data.stashName, onBack = data.onBack })
+ end,
+ }
+ end
+ openMenu(Menu, { header = data.craftable.Header, onBack = function() craftingMenu(data) end, })
+end
+
+function makeItem(data)
+ if not CraftLock then CraftLock = true else return end
+ local bartime, bartext, animDict, anim = nil, nil, nil, nil
+ if data.craftable.progressBar then
+ bartime = data.craftable.progressBar.time
+ bartext = data.craftable.progressBar.label
+ else
+ bartime = 5000
+ bartext = Loc[Config.Lan].progressbar["progress_make"]
+ end
+ animDict = data.craftable.Anims.animDict or "amb@prop_human_parking_meter@male@idle_a"
+ anim = data.craftable.Anims.anim or "idle_a"
+
+ local amount = (data.amount and data.amount ~= 1) and data.amount or 1
+
+ local crafted = true
+ local crafting = true
+
+ local cam = createTempCam(PlayerPedId(), data.coords)
+ startTempCam(cam)
+
+ for i = 1, amount do
+ for _, v in pairs(data.craft) do
+ if type(v) == "table" then
+ for l, b in pairs(v) do
+ if crafting and progressBar({
+ label = "Using "..b.." "..Items[l].label,
+ time = 1000,
+ cancel = true,
+ dict = 'pickup_object',
+ anim = "putdown_low",
+ flag = 48,
+ icon = l,
+ }) then
+ --TriggerEvent('inventory:client:ItemBox', Items[l], "use", b) -- Show item box for each item
+ else
+ crafted = false
+ crafting = false
+ break
+ end
+ Wait(200)
+ end
+ if crafted then
+ if crafting and progressBar({
+ label = bartext..Items[data.item].label,
+ time = bartime,
+ cancel = true,
+ dict = animDict,
+ anim = anim,
+ flag = 8,
+ icon = data.item,
+ }) then
+ TriggerServerEvent(GetCurrentResourceName()..":Crafting:GetItem", data.item, data.craft, data.stashName)
+ else
+ crafting = false
+ break
+ end
+ end
+ end
+ end
+ Wait(500)
+ end
+ stopTempCam()
+ CraftLock = false
+ lockInv(false)
+ craftingMenu(data)
+ ClearPedTasks(PlayerPedId())
+end
+
+RegisterNetEvent(GetCurrentResourceName()..":Crafting:GetItem", function(ItemMake, craftable, stashName)
+ local src = source
+ local amount = 1
+ if stashName then
+ local stashItems = getStash(stashName)
+ if craftable["amount"] then amount = craftable["amount"] end
+ local itemRemove = {}
+ for k, v in pairs(craftable[ItemMake]) do
+ for l, b in pairs(stashItems) do
+ if k == b.name then
+ itemRemove[k] = v
+ end
+ end
+ end
+ stashRemoveItem(stashItems, stashName, itemRemove)
+ else
+ if craftable then
+ if craftable["amount"] then amount = craftable["amount"] end
+ for k, v in pairs(craftable[ItemMake]) do
+ TriggerEvent(GetCurrentResourceName()..":server:toggleItem", false, tostring(k), v, src)
+ end
+ end
+ end
+ TriggerEvent(GetCurrentResourceName()..":server:toggleItem", true, ItemMake, amount, src)
+end)
+
+--[[SHOPS]]--
+function openShop(data)
+ if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end
+ if GetResourceState(OXInv):find("start") then
+ exports[OXInv]:openInventory('shop', { type = data.shop })
+ else
+ TriggerServerEvent(Config.JimShops and "jim-shops:ShopOpen" or "inventory:server:OpenInventory", "shop", data.shop, data.items)
+ end
+ lookEnt(data.coords)
+end
+
+-- Client & Server side
+function hasItem(items, amount, src) local amount, count = amount and amount or 1, 0
+ if src then
+ if GetResourceState(OXInv):find("start") then
+ local item = exports[OXInv]:GetItem(src, items)
+ local amount = (amount or 1)
+ if item.count >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..item.count.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else if Config.System.Debug then
+ print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+
+ elseif GetResourceState(QSInv):find("start") then
+ for _, itemData in pairs(exports[QSInv]:GetInventory(src)) do
+ if itemData and (itemData.name == items) then
+ --if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+
+ elseif GetResourceState(CoreInv):find("start") then
+ local item = exports[CoreInv]:getItems('primary-'..src, items)
+
+ if item.amount >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..item.amount.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else if Config.System.Debug then
+ print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+
+ elseif GetResourceState(CodeMInv):find("start") then
+ local success = exports["codem-inventory"]:CheckItemValid(src, items, amount)
+ if success then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..amount.." "..tostring(items)) end
+ return true
+ end
+
+ elseif GetResourceState(CodeMInv):find("start") then
+ for _, itemData in pairs(exports[CodeMInv]:GetUserInventory(src)) do
+ if itemData and (itemData.name == items) then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+
+ else
+ for _, itemData in pairs(Core.Functions.GetPlayer(src).PlayerData.items) do
+ if itemData and (itemData.name == items) then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+ end
+ else
+ if GetResourceState(OXInv):find("start") then
+ local count = tonumber(exports[OXInv]:Search('count', items))
+ local amount = (amount or 1)
+ if count >= amount then if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items)) end return true
+ else if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end return false end
+
+ elseif GetResourceState(QSInv):find("start") then
+ for _, itemData in pairs(exports[QSInv]:GetInventory()) do
+ if itemData and (itemData.name == items) then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+
+ elseif GetResourceState(CoreInv):find("start") then
+ for _, itemData in pairs(exports[CoreInv]:getInventory('primary-'..GetPlayerServerId(PlayerPedId()))) do
+ if itemData and (itemData.name == items) then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items)) end
+ return true
+ else
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7") end
+ return false
+ end
+
+ elseif GetResourceState(CodeMInv):find("start") then
+ local success = exports[CodeMInv]:CheckItemValid(items, amount)
+ if success then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..amount.." "..tostring(items)) end
+ return true
+ end
+
+ elseif GetResourceState(QBInv):find("start") then
+ --if tonumber(GetResourceMetadata(QBInv, 'version')) <= 1.2 then
+ -- return exports[QBInv]:HasItem(items, amount)
+ --else
+ for _, itemData in pairs(Core.Functions.GetPlayerData().items) do
+ if itemData and (itemData.name == items) then
+ if Config.System.Debug then print("^6Bridge^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^3HasItem^7: ^5FOUND^7 ^3"..count.."^7/^3"..amount.." "..tostring(items))
+ end
+ return true
+ else
+ if Config.System.Debug then
+ print("^6Bridge^7: ^3HasItem^7: ^2"..tostring(items).." ^1NOT FOUND^7")
+ end
+ return false
+ end
+ -- end
+ end
+ end
+end
+
+-- Stash Items
+function openStash(data)
+ if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end
+ if GetResourceState(OXInv):find("start") then
+ exports[OXInv]:openInventory('stash', data.stash)
+ elseif GetResourceState(CodeMInv):find("start") then
+ exports[CodeMInv]:OpenStash(data.stash, 400000, 100)
+ else
+ TriggerEvent("inventory:client:SetCurrentStash", data.stash)
+ TriggerServerEvent("inventory:server:OpenInventory", "stash", data.stash)
+ end
+ lookEnt(data.coords)
+end
+
+function getStash(stashName)
+ local stashItems, items = {}, {}
+ if GetResourceState(OXInv):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Retrieving ^3Stash^2 with ^7ox_inventory") end
+ stashItems = exports[OXInv]:Inventory(stashName).items
+ elseif GetResourceState(QSInv):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Retrieving ^3Stash^2 with ^7qs-inventory") end
+ stashItems = exports[QSInv]:GetStashItems(stashName)
+ elseif GetResourceState(CodeMInv):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Retrieving ^3Stash^2 with ^7qs-inventory") end
+ stashItems = exports[CodeMInv]:GetInventoryItems('Stash', stashName)
+ elseif GetResourceState(QBInv):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Retrieving ^3Stash^2 with ^7qb-inventory") end
+ local result = MySQL.scalar.await('SELECT items FROM stashitems WHERE stash = ?', { stashName })
+ if result then stashItems = json.decode(result) end
+ end
+ if stashItems then
+ for _, item in pairs(stashItems) do
+ local itemInfo = Items[item.name:lower()]
+ if itemInfo then
+ items[item.slot] = {
+ name = itemInfo["name"],
+ amount = tonumber(item.amount) or tonumber(item.count),
+ info = item.info ~= nil and item.info or "",
+ label = itemInfo["label"],
+ description = itemInfo["description"] ~= nil and itemInfo["description"] or "",
+ weight = itemInfo["weight"],
+ type = itemInfo["type"],
+ unique = itemInfo["unique"],
+ useable = itemInfo["useable"],
+ image = itemInfo["image"],
+ slot = item.slot,
+ }
+ end
+ end
+ if Config.System.Debug then print("^6Bridge^7: ^3GetStashItems^7: ^2Stash information for ^7'^6"..stashName.."^7' ^2retrieved^7") end
+ end
+ return items
+end
+
+function stashRemoveItem(stashItems, stashName, items) local amount = amount and amount or 1
+ if GetResourceState(OXInv):find("start") then
+ for k, v in pairs(items) do
+ exports[OXInv]:RemoveItem(stashName, k, v)
+ if Config.System.Debug then print("^6Bridge^7: ^2Removing item from ^3Stash^2 with ^7"..OXInv, k, v) end
+ end
+ elseif GetResourceState(QSInv):find("start") then
+ for k, v in pairs(items) do
+ exports[QSInv]:RemoveItemIntoStash(stashName, k, v)
+ if Config.System.Debug then print("^6Bridge^7: ^2Removing item from ^3Stash^2 with ^7"..QSInv, k, v) end
+ end
+ elseif GetResourceState(CodeMInv):find("start") then
+ 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
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2None of this item left in stash ^3Stash^7", k, v)
+ end
+ stashItems[l] = nil
+ else
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Removing item from ^3Stash^2 with ^7"..CodeMInv, k, v)
+ end
+ stashItems[l].amount -= v
+ end
+ end
+ end
+ end
+ if Config.System.Debug then
+ print("^6Bridge^7: ^3saveStash^7: ^2Saving ^3QB^2 stash ^7'^6"..stashName.."^7'")
+ end
+ else
+ 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
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2None of this item left in stash ^3Stash^7", k, v)
+ end
+ stashItems[l] = nil
+ else
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Removing item from ^3Stash^2 with ^7"..QBInv, k, v)
+ end
+ stashItems[l].amount -= v
+ end
+ end
+ end
+ end
+ if Config.System.Debug then
+ print("^6Bridge^7: ^3saveStash^7: ^2Saving ^3QB^2 stash ^7'^6"..stashName.."^7'")
+ end
+ 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
+RegisterNetEvent(GetCurrentResourceName()..":server:stashRemoveItem", stashRemoveItem)
+
+function stashhasItem(stashItems, item, amount) local amount, count = amount and amount or 1, 0
+ for k, itemData in pairs(stashItems) do
+ if itemData and (itemData.name == item) then
+ --if Config.System.Debug then
+ -- print("^6Bridge^7: ^3stashHasItem^7: ^2Item^7: '^3"..tostring(item).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)")
+ --end
+ count += (itemData.amount or 1)
+ end
+ end
+ if count >= amount then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^3stashHasItem^7: ^2Items ^3"..item.." ^5FOUND^7 x^3"..count.."^7/^3"..amount.."^7") end
+ return
+ true
+ else
+ if Config.System.Debug then print("^6Bridge^7: ^3stashHasItem^7: ^2Items ^1NOT FOUND^7 "..json.encode(item)) end
+ return false
+ end
+end
\ No newline at end of file
diff --git a/exports.lua b/exports.lua
new file mode 100644
index 0000000..1a92d42
--- /dev/null
+++ b/exports.lua
@@ -0,0 +1,19 @@
+Exports = {
+ QBExport = "qb-core",
+ QBXExport = "qbx_core",
+ ESXExport = "es_extended",
+ OXCoreExport = "ox_core",
+
+ OXInv = "ox_inventory",
+ QBInv = "qb-inventory",
+ QSInv = "qs-inventory",
+ CoreInv = "core-inventory",
+ CodeMInv = "codem-inventory",
+
+ OXLibExport = "ox_lib",
+
+ QBMenuExport = "qb-menu",
+
+ QBTargetExport = "qb-target",
+ OXTargetExport = "ox_target"
+}
\ No newline at end of file
diff --git a/functions.lua b/functions.lua
new file mode 100644
index 0000000..c67f984
--- /dev/null
+++ b/functions.lua
@@ -0,0 +1,784 @@
+onDuty = false
+function jobCheck(job)
+ canDo = true
+ if not hasJob(job) or not onDuty then
+ triggerNotify(nil, Loc[Config.Lan].error["not_clockedin"])
+ canDo = false
+ end
+ return canDo
+end
+
+local time = 100
+function loadModel(model)
+ if not HasModelLoaded(model) then if Config.System.Debug then print("^6Bridge^7: ^2Loading Model^7: '^6"..model.."^7'") end
+ while not HasModelLoaded(model) do if time > 0 then time = time - 1 RequestModel(model)
+ else time = 1000 print("^6Bridge^7: ^3LoadModel^7: ^2Timed out loading model ^7'^6"..model.."^7'") break end
+ Wait(10) end
+ end
+end
+function unloadModel(model) if Config.System.Debug then print("^6Bridge^7: ^2Removing Model^7: '^6"..model.."^7'") end SetModelAsNoLongerNeeded(model) end
+function loadAnimDict(dict) if Config.System.Debug then print("^6Bridge^7: ^2Loading Anim Dictionary^7: '^6"..dict.."^7'") end while not HasAnimDictLoaded(dict) do RequestAnimDict(dict) Wait(5) end end
+function unloadAnimDict(dict) if Config.System.Debug then print("^6Bridge^7: ^2Removing Anim Dictionary^7: '^6"..dict.."^7'") end RemoveAnimDict(dict) end
+function loadPtfxDict(dict) if Config.System.Debug then if not HasNamedPtfxAssetLoaded(dict) then print("^6Bridge^7: ^2Loading Ptfx Dictionary^7: '^6"..dict.."^7'") end end while not HasNamedPtfxAssetLoaded(dict) do RequestNamedPtfxAsset(dict) Wait(5) end end
+function unloadPtfxDict(dict) if Config.System.Debug then print("^6Bridge^7: ^2Removing Ptfx Dictionary^7: '^6"..dict.."^7'") end RemoveNamedPtfxAsset(dict) end
+function loadTextureDict(dict) if Config.System.Debug then print("^6Bridge^7: ^2Loading Texture Dictionary^7: '^6"..dict.."^7'") end while not HasStreamedTextureDictLoaded(dict) do RequestNamedPtfxAsset(dict) Wait(5) end end
+
+function countTable(table) local i = 0 for keys in pairs(table) do i += 1 end return i end
+
+function pairsByKeys(t) local a = {} for n in pairs(t) do a[#a+1] = n end table.sort(a) local i = 0 local iter = function() i += 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end
+
+function playAnim(animDict, animName, duration, flag, ped)
+ loadAnimDict(animDict)
+ TaskPlayAnim(ped and ped or PlayerPedId(), animDict, animName, 1.0, -1.0, duration or 30000, flag or 50, 1, false, false, false)
+end
+
+function stopAnim(animDict, animName)
+ StopAnimTask(PlayerPedId(), animName, animDict)
+ unloadAnimDict(animDict)
+end
+
+function makeVeh(model, coords)
+ loadModel(model)
+ local veh = CreateVehicle(model, coords.x, coords.y, coords.z, coords.w, true, false)
+ SetVehicleHasBeenOwnedByPlayer(veh, true)
+ SetNetworkIdCanMigrate(NetworkGetNetworkIdFromEntity(veh), true)
+ Wait(100)
+ SetVehicleNeedsToBeHotwired(veh, false)
+ SetVehRadioStation(veh, 'OFF')
+ SetVehicleFuelLevel(veh, 100.0)
+ SetVehicleModKit(veh, 0)
+ SetVehicleOnGroundProperly(veh)
+ if Config.System.Debug then
+ local coords = { string.format("%.2f", coords.x), string.format("%.2f", coords.y), string.format("%.2f", coords.z), (string.format("%.2f", coords.w or 0.0)) }
+ print("^6Bridge^7: ^1Veh ^2Created^7: '^6"..veh.."^7' | ^2Hash^7: ^7'^6"..(model).."^7' | ^2Coord^7: ^5vec4^7(^6"..(coords[1]).."^7, ^6"..(coords[2]).."^7, ^6"..(coords[3]).."^7, ^6"..(coords[4]).."^7)")
+ end
+ unloadModel(model)
+ return veh
+end
+
+local Peds = {}
+local Props = {}
+function makePed(model, coords, freeze, collision, scenario, anim, synced)
+ loadModel(model)
+ local ped = CreatePed(0, model, coords.x, coords.y, coords.z-1.03, coords.w, synced and synced or true, false)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ FreezeEntityPosition(ped, freeze and freeze or true)
+
+ if collision then SetEntityNoCollisionEntity(ped, PlayerPedId(), false) end
+ if scenario then TaskStartScenarioInPlace(ped, scenario, 0, true) end
+ if anim then
+ loadAnimDict(anim[1])
+ TaskPlayAnim(ped, anim[1], anim[2], 0.5, 1.0, -1, 1, 0.2, 0, 0, 0)
+ end
+ if Config.System.Debug then
+ local coords = { string.format("%.2f", coords.x), string.format("%.2f", coords.y), string.format("%.2f", coords.z), (string.format("%.2f", coords.w or 0.0)) }
+ print("^6Bridge^7: ^1Ped ^2Created^7: '^6"..ped.."^7' | ^2Hash^7: ^7'^6"..(model).."^7' | ^2Coord^7: ^5vec4^7(^6"..(coords[1]).."^7, ^6"..(coords[2]).."^7, ^6"..(coords[3]).."^7, ^6"..(coords[4]).."^7)")
+ end
+ unloadModel(model)
+ Peds[#Peds+1] = ped
+ return ped
+end
+
+function makeProp(data, freeze, synced)
+ loadModel(data.prop)
+ local prop = CreateObject(data.prop, data.coords.x, data.coords.y, data.coords.z-1.03, synced or false, synced or false, false)
+ SetEntityHeading(prop, data.coords.w + 180.0)
+ FreezeEntityPosition(prop, freeze and freeze or 0)
+ if Config.System.Debug then
+ local coords = { string.format("%.2f", data.coords.x), string.format("%.2f", data.coords.y), string.format("%.2f", data.coords.z), (string.format("%.2f", data.coords.w or 0.0)) }
+ print("^6Bridge^7: ^1Prop ^2Created^7: '^6"..prop.."^7' | ^2Hash^7: ^7'^6"..(data.prop).."^7' | ^2Coord^7: ^5vec4^7(^6"..(coords[1]).."^7, ^6"..(coords[2]).."^7, ^6"..(coords[3]).."^7, ^6"..(coords[4]).."^7)")
+ end
+ unloadModel(data.prop)
+ Props[#Props+1] = prop
+ return prop
+end
+
+AddEventHandler('onResourceStop', function(r)
+ if r ~= GetCurrentResourceName() then return end
+ stopSpinner()
+ for i = 1, #Peds do DeletePed(Peds[i]) end
+ for i = 1, #Props do destroyProp(Props[i]) end
+end)
+
+function instantLookEnt(ent, ent2)
+ local p1 = GetEntityCoords(ent, true)
+ local p2 = GetEntityCoords(ent2, true)
+
+ local dx = p2.x - p1.x
+ local dy = p2.y - p1.y
+
+ local heading = GetHeadingFromVector_2d(dx, dy)
+ SetEntityHeading( ent, heading )
+end
+
+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)
+ if Config.System.Debug then print("^6Bridge^7: ^2Turning Player to^7: '^6"..json.encode(entity).."^7'") end
+ Wait(1500)
+ end
+ else
+ if DoesEntityExist(entity) then
+ if not IsPedHeadingTowardsPosition(ped, GetEntityCoords(entity), 30.0) then
+ TaskTurnPedToFaceCoord(ped, GetEntityCoords(entity), 1500)
+ if Config.System.Debug then print("^6Bridge^7: ^2Turning Player to^7: '^6"..entity.."^7'") end
+ Wait(1500)
+ end
+ end
+ end
+ end
+end
+
+function destroyProp(entity)
+ if Config.System.Debug then print("^6Bridge^7: ^2Destroying Prop^7: '^6"..entity.."^7'") end
+ if IsEntityAttachedToEntity(entity, PlayerPedId()) then
+ SetEntityAsMissionEntity(entity)
+ DetachEntity(entity, true, true)
+ end
+ DeleteObject(entity)
+end
+
+function pushVehicle(entity)
+ SetVehicleModKit(entity, 0)
+ if entity ~= 0 and DoesEntityExist(entity) then
+ if not NetworkHasControlOfEntity(entity) then
+ if Config.System.Debug then print("^6Bridge^7: ^3pushVehicle^7: ^2Requesting network control of vehicle^7.") end
+ NetworkRequestControlOfEntity(entity)
+ local timeout = 2000
+ while timeout > 0 and not NetworkHasControlOfEntity(entity) do
+ Wait(100)
+ timeout = timeout - 100
+ end
+ if NetworkHasControlOfEntity(entity) and Config.System.Debug then print("^6Bridge^7: ^3pushVehicle^7: ^2Network has control of entity^7.") end
+ end
+ if not IsEntityAMissionEntity(entity) then
+ if Config.System.Debug then print("^6Bridge^7: ^3pushVehicle^7: ^2Setting vehicle as a ^7'^2mission^7' &2entity^7.") end
+ SetEntityAsMissionEntity(entity, true, true)
+ local timeout = 2000
+ while timeout > 0 and not IsEntityAMissionEntity(entity) do
+ Wait(100)
+ timeout = timeout - 100
+ end
+ if IsEntityAMissionEntity(entity) and Config.System.Debug then print("^6Bridge^7: ^3pushVehicle^7: ^2Vehicle is a ^7'^2mission^7'^2 entity^7.") end
+ end
+ end
+end
+
+function makeBlip(data)
+ local blip = AddBlipForCoord(data.coords)
+ SetBlipAsShortRange(blip, true)
+ SetBlipSprite(blip, data.sprite or 106)
+ SetBlipColour(blip, data.col or 5)
+ SetBlipScale(blip, data.scale or 0.7)
+ SetBlipDisplay(blip, (data.disp or 6))
+ if data.category then SetBlipCategory(blip, data.category) end
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentString(tostring(data.name))
+ EndTextCommandSetBlipName(blip)
+ if Config.System.Debug then print("^6Bridge^7: ^6Blip ^2created for location^7: '^6"..data.name.."^7'") end
+ return blip
+end
+
+function makeEntityBlip(data)
+ AddBlipForEntity(data.entity)
+ local blip = GetBlipFromEntity(data.entity)
+ SetBlipAsShortRange(blip, true)
+ SetBlipSprite(blip, data.sprite or 106)
+ SetBlipColour(blip, data.col or 5)
+ SetBlipScale(blip, data.scale or 0.7)
+ SetBlipDisplay(blip, (data.disp or 6))
+ if data.category then SetBlipCategory(blip, data.category) end
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentString(tostring(data.name))
+ EndTextCommandSetBlipName(blip)
+ if Config.System.Debug then print("^6Bridge^7: ^6Blip ^2created for Entity^7: '^6"..data.name.."^7'") end
+ return blip
+end
+
+function lockInv(toggle)
+ FreezeEntityPosition(PlayerPedId(), toggle)
+ LocalPlayer.state:set("inv_busy", toggle, true)
+ TriggerEvent('inventory:client:busy:status', toggle)
+ TriggerEvent('canUseInventoryAndHotbar:toggle', not toggle)
+end
+
+function createTempCam(ent, coords)
+ local cam = nil
+ if Config.Crafting.craftCam then
+ if Config.System.Debug then
+ triggerNotify(nil, "ModCam Created", "success")
+ end
+ local camCoords = GetOffsetFromEntityInWorldCoords(ent, 1.2, -0.3, 0.8)
+ --local pedCoords = GetEntityCoords(PlayerPedId())
+ cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z+0.5, 1.0, 0.0, 0.0, 60.00, false, 0)
+ PointCamAtCoord(cam, coords)
+ end
+ return cam
+end
+
+function keyGen()
+ local charset = {
+ "q","w","e","r","t","y","u","i","o","p","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m",
+ "Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M",
+ "1","2","3","4","5","6","7","8","9","0"
+ }
+ local GeneratedID = ""
+ for i = 1, 3 do GeneratedID = GeneratedID..charset[math.random(1, #charset)] end
+ return GeneratedID
+end
+
+function startTempCam(cam)
+ if Config.Crafting.craftCam then
+ SetCamActive(cam, true)
+ RenderScriptCams(true, true, 1000, true, true)
+ end
+end
+function stopTempCam()
+ if Config.Crafting.craftCam then
+ CreateThread(function()
+ Wait(1000)
+ RenderScriptCams(false, true, 500, true, true)
+ DestroyAllCams()
+ end)
+ end
+end
+
+local inProgress = false
+function progressBar(data)
+ local result = nil
+ if data.cam then
+ startTempCam(data.cam)
+ end
+ if Config.System.ProgressBar == "ox" then
+ if exports[OXLibExport]:progressBar({
+ duration = Config.System.Debug and 1000 or data.time,
+ label = data.label,
+ useWhileDead = data.dead and data.dead or false,
+ canCancel = data.cancel and 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 = true
+ },
+ }) then
+ result = true
+ lockInv(false)
+ if data.cam then stopTempCam(data.cam) end
+ else
+ result = false
+ lockInv(false)
+ if data.cam then stopTempCam(data.cam) end
+ end
+ elseif Config.System.ProgressBar == "qb" then
+ Core.Functions.Progressbar("mechbar",
+ data.label,
+ Config.System.Debug and 1000 or data.time,
+ data.dead and data.dead or false,
+ data.cancel or true,
+ { disableMovement = true, disableCarMovement = true, disableMouse = false, disableCombat = true, },
+ { animDict = data.dict, anim = data.anim, flags = data.flag and data.flag or 32, task = data.task }, {}, {},
+ function()
+ result = true
+ lockInv(false)
+ if data.cam then
+ stopTempCam(data.cam)
+ end
+ end, function()
+ result = false
+ lockInv(false)
+ if data.cam then
+ stopTempCam(data.cam)
+ end
+ end, data.icon)
+ elseif Config.System.ProgressBar == "gta" then
+
+ --local wait, inProgress = (Config.System.Debug and 1000 or data.time), true
+ local wait = data.time
+ inProgress = true
+ if not (data.dead and data.dead or false) then
+ lockInv(true)
+ displaySpinner(data.label)
+ local ped = PlayerPedId()
+ if data.dict then
+ playAnim(data.dict, data.anim, -1, (data.flag == 8 and 32 or data.flag) or nil)
+ end
+ if data.task then
+ TaskStartScenarioInPlace(ped, data.task, -1, true)
+ end
+ while inProgress and wait > 0 do wait -= 15
+ local waitTimer = 0
+ DisablePlayerFiring(ped, true)
+ DisableControlAction(0, 25, true)
+ DisableControlAction(0, 21, true)
+ DisableControlAction(0, 30, true)
+ DisableControlAction(0, 31, true)
+ DisableControlAction(0, 36, true)
+ if data.cam ~= nil then
+ DisableControlAction(0, 1, true)
+ DisableControlAction(0, 2, true)
+ DisableControlAction(0, 106, true)
+ end
+ if data.cancel then
+ if IsControlJustReleased(0, 202) or IsControlJustReleased(0, 77) then
+ inProgress = false
+ waitTimer = 1500
+ displaySpinner(Loc[Config.Lan].error["cancel"])
+ end
+ end
+ Wait(waitTimer)
+ end
+ inProgress = false
+ if data.cam then stopTempCam(data.cam) end
+ if data.dict then stopAnim(data.dict, data.anim, ped) end
+ ClearPedTasks(ped)
+ end
+ lockInv(false)
+ stopSpinner()
+ result = (wait <= 0)
+ end
+ while result == nil do Wait(10) end
+ return result
+end
+
+function displaySpinner(text)
+ BeginTextCommandBusyspinnerOn('STRING')
+ AddTextComponentSubstringPlayerName(text)
+ EndTextCommandBusyspinnerOn(4)
+end
+
+function stopSpinner() if not IsDuplicityVersion() then BusyspinnerOff() end end
+
+function stopPropgressBar()
+ if Config.System.ProgressBar == "ox" then
+ exports[OXLibExport]:cancelProgress()
+ elseif Config.System.ProgressBar == "qb" then
+ TriggerEvent("progressbar:client:cancel")
+ elseif Config.System.ProgressBar == "gta" then
+ inProgress = false
+ BusyspinnerOff()
+ end
+end
+
+-- [[ OTHER ]] --
+function washHands(data)
+ lookEnt(data.coords)
+ local cam = createTempCam(PlayerPedId(), data.coords)
+ if progressBar({
+ label = Loc[Config.Lan].progressbar["progress_washing"],
+ time = 5000,
+ cancel = true,
+ dict = "mp_arresting",
+ anim = "a_uncuff",
+ flag = 32,
+ icon = "fas fa-hand-holding-droplet",
+ cam = cam
+ }) then
+ triggerNotify(nil, Loc[Config.Lan].success["washed_hands"], "success")
+ else
+ triggerNotify(nil, Loc[Config.Lan].error["cancel"], 'error')
+ end
+ ClearPedTasks(PlayerPedId())
+end
+
+function useToilet(data)
+ if data.urinal then
+ if progressBar({
+ label = "Using Urinal",
+ time = 5000,
+ cancel = true,
+ dict = "misscarsteal2peeing",
+ anim = "peeing_loop",
+ flag = 32
+ }) then
+ TriggerServerEvent(GetCurrentResourceName().."server:Urinal")else
+ lockInv(false)
+ triggerNotify(nil, Loc[Config.Lan].error["cancelled"], 'error')
+ end
+ else
+ TaskStartScenarioAtPosition(PlayerPedId(), "PROP_HUMAN_SEAT_CHAIR_MP_PLAYER", data.sitcoords.x, data.sitcoords.y, data.sitcoords.z, data.sitcoords[4], 0, 1, true)
+ if progressBar({
+ label = "Using Toilet",
+ time = 10000,
+ cancel = true
+ }) then
+ TriggerServerEvent(GetCurrentResourceName().."server:Urinal")
+ ClearPedTasks(PlayerPedId())
+ else
+ lockInv(false)
+ triggerNotify(nil, Loc[Config.Lan].error["cancelled"], 'error')
+ end
+ end
+end
+
+RegisterNetEvent(GetCurrentResourceName()..":server:Urinal", function()
+ local src = source
+ local Player = getPlayer(src)
+ local thirstamt = math.random(10,30)
+ local thirst = Player.thirst - thirstamt
+ setThirst(src, getPlayer(src).thirst - thirst)
+end)
+
+RegisterNetEvent(GetCurrentResourceName()..":server:setNeed", function(type, amount) local src = source
+ if type == "thirst" then
+ setThirst(src, amount)
+ elseif type == "thirst" then
+ setHunger(src, amount)
+ end
+end)
+
+function setThirst(src, thirst)
+ if GetResourceState(ESXExport):find("start") then
+ TriggerClientEvent('esx_status:add', src, 'thirst', thirst)
+ elseif GetResourceState(QBExport):find("start") or GetResourceState(QBXExport):find("start") then
+ local Player = QBCore.Functions.GetPlayer(src)
+ Player.Functions.SetMetaData('thirst', thirst)
+ TriggerClientEvent("hud:client:UpdateNeeds", src, thirst, Player.PlayerData.metadata.thirst)
+ end
+end
+
+function setHunger(src, hunger)
+ if GetResourceState(ESXExport):find("start") then
+ TriggerClientEvent('esx_status:add', src, 'hunger', hunger)
+ elseif GetResourceState(QBExport):find("start") or GetResourceState(QBXExport):find("start") then
+ local Player = QBCore.Functions.GetPlayer(src)
+ Player.Functions.SetMetaData('hunger', hunger)
+ TriggerClientEvent("hud:client:UpdateNeeds", src, hunger, Player.PlayerData.metadata.hunger)
+ end
+end
+
+function useDoor(data)
+ DoScreenFadeOut(500)
+ while not IsScreenFadedOut() do Wait(10) end
+ SetEntityCoords(PlayerPedId(), data.telecoords.xyz, 0, 0, 0, false)
+ SetEntityHeading(PlayerPedId(), data.telecoords.w)
+ DoScreenFadeIn(1000)
+ Wait(100)
+end
+
+-- [[CONSUME]] --
+function ConsumeSuccess(itemName, type)
+ ExecuteCommand("e c")
+ toggleItem(false, itemName, 1)
+ if GetResourceState(ESXEport):find("start") then
+ if Items[itemName].hunger then
+ TriggerServerEvent(GetCurrentResourceName()..":server:setNeed", "hunger", Items[itemName].hunger * 10000)
+ end
+ if Items[itemName].thirst then
+ TriggerServerEvent(GetCurrentResourceName()..":server:setNeed", "thirst", Items[itemName].thirst * 10000)
+ end
+ else
+ if Items[itemName].hunger then
+ TriggerServerEvent(GetCurrentResourceName()..":server:setNeed", "hunger", Core.Functions.GetPlayerData().metadata["hunger"] + Items[itemName].hunger)
+ end
+ if Items[itemName].thirst then
+ TriggerServerEvent(GetCurrentResourceName()..":server:setNeed", "thirst", Core.Functions.GetPlayerData().metadata["thirst"] + Items[itemName].thirst)
+ end
+ end
+ if type == "alcohol" then alcoholCount += 1
+ if alcoholCount > 1 and alcoholCount < 4 then TriggerEvent("evidence:client:SetStatus", "alcohol", 200) elseif alcoholCount >= 4 then TriggerEvent("evidence:client:SetStatus", "heavyalcohol", 200) AlienEffect() end
+ end
+ if Config.RewardItem == itemName then toggleItem(true, Config.RewardPool[math.random(1, #Config.RewardPool)], 1) end
+end
+
+function addItem(item, amount, info)
+ TriggerServerEvent(GetCurrentResourceName()..":server:toggleItem", true, item, amount)
+end
+
+function removeItem(item, amount)
+ TriggerServerEvent(GetCurrentResourceName()..":server:toggleItem", false, item, amount)
+end
+
+RegisterNetEvent(GetCurrentResourceName()..":server:toggleItem", function(give, item, amount, newsrc)
+ local src = newsrc or source
+ if Config.System.Debug then
+ print("^6Bridge^7: ^3toggleItem ^2triggered^7: ^6"..(tostring(give) == "true" and "addItem" or "removeItem").."^7 - ['^8"..tostring(item).."^7'] x"..(tostring(amount) or "1"))
+ end
+ local remamount = (amount and amount or 1)
+ if item == nil then return end
+ if give == 0 or give == false then
+ if hasItem(item, amount and amount or 1, src) then -- check if you still have the item
+ if GetResourceState(OXInv):find("start") then
+ local success = exports[OXInv]:RemoveItem(src, item, (amount and amount or 1), nil)
+ elseif GetResourceState(QSInv):find("start") then
+ local success = exports[QSInv]:RemoveItem(src, item, amount)
+ elseif GetResourceState(CoreInv):find("start") then
+ local success = exports[CoreInv]:removeItemExact('primary-'..src, item, amount)
+ elseif GetResourceState(CodeMInv):find("start") then
+ local success = exports[CodeMInv]:RemoveItem(src, item, amount)
+ elseif GetResourceState(QBInv):find("start") then
+ while remamount > 0 do
+ if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1) then end
+ remamount -= 1
+ end
+ if Config.Crafting.showItemBox then
+ TriggerClientEvent('inventory:client:ItemBox', src, Items[item], "remove", (amount and amount or 1))
+ end
+ end
+ if Config.System.Debug then
+ print("^6Bridge^7: ^1Removing ^2from Player^7(^2"..src.."^7) '^6"..Items[item].label.."^7(^2x^6"..((amount and amount or "1")).."^7)'")
+ end
+ else
+ dupeWarn(src, item) -- if not boot the player
+ end
+ else
+ local amount = amount and amount or 1
+ if GetResourceState(OXInv):find("start") then
+ local success = exports[OXInv]:AddItem(src, item, amount or 1, nil)
+ if Config.System.Debug then
+ print("^6Bridge^7: ^4Giving ^2Player^7(^2"..src.."^7) '^6"..Items[item].label.."^7(^2x^6"..((amount and amount or "1")).."^7) ^1OX^7'")
+ end
+ elseif GetResourceState(QSInv):find("start") then
+ local success = exports[QSInv]:AddItem(src, item, amount)
+ if Config.System.Debug then
+ print("^6Bridge^7: ^4Giving ^2Player^7(^2"..src.."^7) '^6"..Items[item].label.."^7(^2x^6"..((amount and amount or "1")).."^7) ^1QS^7'")
+ end
+ elseif GetResourceState(CoreInv):find("start") then
+ local success = exports[CoreInv]:addItem('primary-'..src, item, amount)
+ if Config.System.Debug then
+ print("^6Bridge^7: ^4Giving ^2Player^7(^2"..src.."^7) '^6"..Items[item].label.."^7(^2x^6"..((amount and amount or "1")).."^7) ^1Core^7'")
+ end
+ elseif GetResourceState(CodeMInv):find("start") then
+ local success = exports[CodeMInv]:AddItem(src, item, amount)
+ elseif GetResourceState(QBInv):find("start") then
+ if Core.Functions.GetPlayer(src).Functions.AddItem(item, amount or 1) then
+ --if Config.Crafting.showItemBox then
+ TriggerClientEvent("inventory:client:ItemBox", src, Items[item], "add", amount and amount or 1)
+ --end
+ end
+ end
+ end
+end)
+
+--Item Exploit protection
+function dupeWarn(src, item)
+ print("^5DupeWarn^7: (^1"..tostring(src).."^7) ^2Tried to remove item ^7('^3"..item.."^7')^2 but it wasn't there^7")
+ if Config.System.Debug == false then
+ DropPlayer(src, src.." ^1Kicked for attempting to duplicate items")
+ end
+ print("^5DupeWarn:^7: (^1"..tostring(src).."^7) ^2Dropped from server for item duplicating^7")
+end
+
+
+function toggleDuty()
+ if GetResourceState(QBExport):find("start") then
+ TriggerServerEvent("QBCore:ToggleDuty")
+ else
+ onDuty = not onDuty
+ if onDuty then
+ triggerNotify(nil, "Now on duty", "success")
+ else
+ triggerNotify(nil, "Now off duty", "success")
+ end
+ end
+end
+
+local function CheckVersion()
+ if IsDuplicityVersion() then
+ PerformHttpRequest('https://raw.githubusercontent.com/jimathy/UpdateVersions/master/'..GetCurrentResourceName()..'.txt', function(err, newestVersion, headers)
+ if not newestVersion then print("Currently unable to run a version check.") return end
+ local currentVersion = "^3"..GetResourceMetadata(GetCurrentResourceName(), 'version'):gsub("%.", "^7.^3").."^7"
+ newestVersion = "^3"..newestVersion:sub(1, -2):gsub("%.", "^7.^3").."^7"
+ print("^6Version Check^7: ^2Running^7: "..currentVersion.." ^2Latest^7: "..newestVersion)
+ print(newestVersion == currentVersion and '^6You are running the latest version.^7 ('..currentVersion..')' or "^1You are currently running an outdated version^7, ^1please update^7!")
+ end)
+ end
+end
+CheckVersion()
+
+--Screen Effects
+local alienEffect = false
+function AlienEffect()
+ if alienEffect then return else alienEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3AlienEffect^7() ^2activated") end
+ AnimpostfxPlay("DrugsMichaelAliensFightIn", 3.0, 0)
+ Wait(math.random(5000, 8000))
+ local Ped = PlayerPedId()
+ local animDict = "MOVE_M@DRUNK@VERYDRUNK"
+ loadAnimDict(animDict)
+ SetPedCanRagdoll(Ped, true)
+ ShakeGameplayCam('DRUNK_SHAKE', 2.80)
+ SetTimecycleModifier("Drunk")
+ SetPedMovementClipset(Ped, animDict, 1)
+ SetPedMotionBlur(Ped, true)
+ SetPedIsDrunk(Ped, true)
+ Wait(1500)
+ SetPedToRagdoll(Ped, 5000, 1000, 1, 0, 0, 0)
+ Wait(13500)
+ SetPedToRagdoll(Ped, 5000, 1000, 1, 0, 0, 0)
+ Wait(120500)
+ ClearTimecycleModifier()
+ ResetScenarioTypesEnabled()
+ ResetPedMovementClipset(Ped, 0)
+ SetPedIsDrunk(Ped, false)
+ SetPedMotionBlur(Ped, false)
+ AnimpostfxStopAll()
+ ShakeGameplayCam('DRUNK_SHAKE', 0.0)
+ AnimpostfxPlay("DrugsMichaelAliensFight", 3.0, 0)
+ Wait(math.random(45000, 60000))
+ AnimpostfxPlay("DrugsMichaelAliensFightOut", 3.0, 0)
+ AnimpostfxStop("DrugsMichaelAliensFightIn")
+ AnimpostfxStop("DrugsMichaelAliensFight")
+ AnimpostfxStop("DrugsMichaelAliensFightOut")
+ alienEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3AlienEffect^7() ^2stopped") end
+end
+local weedEffect = false
+function WeedEffect()
+ if weedEffect then return else weedEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3WeedEffect^7() ^2activated") end
+ AnimpostfxPlay("DrugsMichaelAliensFightIn", 3.0, 0)
+ Wait(math.random(3000, 20000))
+ AnimpostfxPlay("DrugsMichaelAliensFight", 3.0, 0)
+ Wait(math.random(15000, 20000))
+ AnimpostfxPlay("DrugsMichaelAliensFightOut", 3.0, 0)
+ AnimpostfxStop("DrugsMichaelAliensFightIn")
+ AnimpostfxStop("DrugsMichaelAliensFight")
+ AnimpostfxStop("DrugsMichaelAliensFightOut")
+ weedEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3WeedEffect^7() ^2stopped") end
+end
+local trevorEffect = false
+function TrevorEffect()
+ if trevorEffect then return else trevorEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3TrevorEffect^7() ^2activated") end
+ AnimpostfxPlay("DrugsTrevorClownsFightIn", 3.0, 0)
+ Wait(3000)
+ AnimpostfxPlay("DrugsTrevorClownsFight", 3.0, 0)
+ Wait(30000)
+ AnimpostfxPlay("DrugsTrevorClownsFightOut", 3.0, 0)
+ AnimpostfxStop("DrugsTrevorClownsFight")
+ AnimpostfxStop("DrugsTrevorClownsFightIn")
+ AnimpostfxStop("DrugsTrevorClownsFightOut")
+ trevorEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3TrevorEffect^7() ^2stopped") end
+end
+local turboEffect = false
+function TurboEffect()
+ if turboEffect then return else turboEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3TurboEffect^7() ^2activated") end
+ AnimpostfxPlay('RaceTurbo', 0, true)
+ SetTimecycleModifier('rply_motionblur')
+ ShakeGameplayCam('SKY_DIVING_SHAKE', 0.25)
+ Wait(30000)
+ StopGameplayCamShaking(true)
+ SetTransitionTimecycleModifier('default', 0.35)
+ Wait(1000)
+ ClearTimecycleModifier()
+ AnimpostfxStop('RaceTurbo')
+ turboEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3TurboEffect^7() ^2stopped") end
+end
+local rampageEffect = false
+function RampageEffect()
+ if rampageEffect then return else rampageEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3RampageEffect^7() ^2activated") end
+ AnimpostfxPlay('Rampage', 0, true)
+ SetTimecycleModifier('rply_motionblur')
+ ShakeGameplayCam('SKY_DIVING_SHAKE', 0.25)
+ Wait(30000)
+ StopGameplayCamShaking(true)
+ SetTransitionTimecycleModifier('default', 0.35)
+ Wait(1000)
+ ClearTimecycleModifier()
+ AnimpostfxStop('Rampage')
+ rampageEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3RampageEffect^7() ^2stopped") end
+end
+local focusEffect = false
+function FocusEffect()
+ if focusEffect then return else focusEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3FocusEffect^7() ^2activated") end
+ Wait(1000)
+ AnimpostfxPlay('FocusIn', 0, true)
+ Wait(30000)
+ AnimpostfxStop('FocusIn')
+ focusEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3FocusEffect^7() ^2stopped") end
+end
+local NightVisionEffect = false
+function NightVisionEffect()
+ if NightVisionEffect then return else NightVisionEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3NightVisionEffect^7() ^2activated") end
+ SetNightvision(true)
+ Wait(math.random(3000, 4000)) -- FEEL FREE TO CHANGE THIS
+ SetNightvision(false)
+ SetSeethrough(false)
+ NightVisionEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3NightVisionEffect^7() ^2stopped") end
+end
+local thermalEffect = false
+function ThermalEffect()
+ if thermalEffect then return else thermalEffect = true end
+ if Config.System.Debug then print("^5Debug^7: ^3ThermalEffect^7() ^2activated") end
+ SetNightvision(true)
+ SetSeethrough(true)
+ Wait(math.random(2000, 3000)) -- FEEL FREE TO CHANGE THIS
+ SetNightvision(false)
+ SetSeethrough(false)
+ thermalEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3ThermalEffect^7() ^2stopped") end
+end
+
+--Built-in Buff effects
+local healEffect = false
+function HealEffect(data)
+ if healEffect then return end
+ if Config.System.Debug then print("^5Debug^7: ^3HealEffect^7() ^2activated") end
+ healEffect = true
+ local count = (data[1] / 1000)
+ while count > 0 do
+ Wait(1000)
+ count -= 1
+ SetEntityHealth(PlayerPedId(), GetEntityHealth(PlayerPedId()) + data[2])
+ end
+ healEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3HealEffect^7() ^2stopped") end
+end
+
+local staminaEffect = false
+function StaminaEffect(data)
+ if staminaEffect then return end
+ if Config.System.Debug then print("^5Debug^7: ^3StaminaEffect^7() ^2activated") end
+ staminaEffect = true
+ local startStamina = (data[1] / 1000)
+ SetRunSprintMultiplierForPlayer(PlayerId(), 1.49)
+ while startStamina > 0 do
+ Wait(1000)
+ if math.random(5, 100) < 10 then RestorePlayerStamina(PlayerId(), data[2]) end
+ startStamina -= 1
+ if math.random(5, 100) < 51 then end
+ end
+ startStamina = 0
+ SetRunSprintMultiplierForPlayer(PlayerId(), 1.0)
+ staminaEffect = false
+ if Config.System.Debug then print("^5Debug^7: ^3StaminaEffect^7() ^2stopped") end
+end
+
+function StopEffects() -- Used to clear up any effects stuck on screen
+ if Config.System.Debug then print("^5Debug^7: ^2All screen effects stopped") end
+ ShakeGameplayCam('DRUNK_SHAKE', 0.0)
+ SetPedToRagdoll(PlayerPedId(), 5000, 1000, 1, 0, 0, 0)
+ ClearTimecycleModifier()
+ ResetScenarioTypesEnabled()
+ ResetPedMovementClipset(PlayerPedId(), 0)
+ SetPedIsDrunk(PlayerPedId(), false)
+ SetPedMotionBlur(PlayerPedId(), false)
+ SetNightvision(false)
+ SetSeethrough(false)
+ AnimpostfxStop("DrugsMichaelAliensFightIn")
+ AnimpostfxStop("DrugsMichaelAliensFight")
+ AnimpostfxStop("DrugsMichaelAliensFightOut")
+ AnimpostfxStop("DrugsTrevorClownsFight")
+ AnimpostfxStop("DrugsTrevorClownsFightIn")
+ AnimpostfxStop("DrugsTrevorClownsFightOut")
+ AnimpostfxStop('RaceTurbo')
+ AnimpostfxStop('FocusIn')
+ AnimpostfxStop('Rampage')
+end
\ No newline at end of file
diff --git a/fxmanifest.lua b/fxmanifest.lua
new file mode 100644
index 0000000..338c4d3
--- /dev/null
+++ b/fxmanifest.lua
@@ -0,0 +1,14 @@
+name "Jim_Bridge"
+author "Jimathy"
+version "help"
+description "Framework Bridge By Jimathy"
+fx_version "cerulean"
+game "gta5"
+lua54 'yes'
+
+files {
+ 'exports.lua',
+ 'functions.lua',
+ 'wrapper.lua',
+ 'crafting.lua',
+}
\ No newline at end of file
diff --git a/wrapper.lua b/wrapper.lua
new file mode 100644
index 0000000..628f772
--- /dev/null
+++ b/wrapper.lua
@@ -0,0 +1,1009 @@
+Items, Vehicles, Jobs, Gangs, Core, ESX = {}, nil, nil, nil, nil, nil
+
+OXLibExport = Exports and Exports.OXLibExport or ""
+
+QBXExport = Exports and Exports.QBXExport or ""
+QBExport = Exports and Exports.QBExport or ""
+ESXExport = Exports and Exports.ESXExport or ""
+OXCoreExport = Exports and Exports.OXCoreExport or ""
+
+OXInv = Exports and Exports.OXInv or ""
+QBInv = Exports and Exports.QBInv or ""
+QSInv = Exports and Exports.QSInv or ""
+CoreInv = Exports and Exports.CoreInv or ""
+
+QBMenuExport = Exports and Exports.QBMenuExport or ""
+
+QBTargetExport = Exports and Exports.QBTargetExport or ""
+OXTargetExport = Exports and Exports.OXTargetExport or ""
+
+for k, v in pairs(Exports) do
+ if GetResourceState(v):find("start") then print("^6Bridge^7: '^3"..v.."^7' ^2export found ^7") end
+end
+
+-- Load item lists from qb-core or ox_lib
+if GetResourceState(OXInv):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Items^2 from ^7"..OXInv)
+ Items = exports[OXInv]:Items()
+ for k, v in pairs(Items) do
+ if v.client then
+ if v.client.image then Items[k].image = (Items[k].client.image):gsub("nui://"..OXInv.."/web/images/","")
+ else Items[k].image = k..".png" end
+ if v.client.hunger then Items[k].hunger = v.client.hunger end
+ if v.client.thirst then Items[k].thirst = v.client.thirst end
+ end
+ end
+elseif GetResourceState(QBExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Items^2 from ^7"..QBExport)
+ Core = exports[QBExport]:GetCoreObject()
+ Items = Core.Shared.Items
+elseif GetResourceState(ESXExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Items^2 from ^7"..ESXExport)
+ ESX = exports[ESXExport]:getSharedObject()
+ Items = ESX.Items
+end
+
+-- Load Vehicles
+if GetResourceState(QBXExport):find("start") then
+ Core = exports[QBExport]:GetCoreObject()
+ print("^6Bridge^7: ^2Loading ^3Vehicles^2 from ^7"..QBXExport)
+ Vehicles = exports[QBXExport]:GetVehiclesByHash()
+elseif GetResourceState(QBExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Vehicles^2 from ^7"..QBExport)
+ Core = exports[QBExport]:GetCoreObject()
+ RegisterNetEvent('QBCore:Client:UpdateObject', function()
+ Core = exports[QBExport]:GetCoreObject()
+ end)
+ Vehicles = Core.Shared.Vehicles
+elseif GetResourceState(OXCoreExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Vehicles^2 from ^7"..OXCoreExport)
+ for k, v in pairs(Ox.GetVehicleData()) do
+ Vehicles = Vehicles or {}
+ Vehicles[k] = { model = k, price = v.price, name = v.name, brand = v.make }
+ end
+elseif GetResourceState(ESXExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Vehicles^2 from ^7"..ESXExport)
+ CreateThread(function()
+ if IsDuplicityVersion() then
+ createCallback(GetCurrentResourceName()..":getVehiclesPrices", function(source)
+ Vehicles = MySQL.query.await('SELECT model, price, name FROM vehicles')
+ return Vehicles
+ end)
+ end
+ if not IsDuplicityVersion() then
+ local TempVehicles = triggerCallback(GetCurrentResourceName()..":getVehiclesPrices")
+ for _, v in pairs(TempVehicles) do
+ Vehicles = Vehicles or {}
+ Vehicles[v.model] = { model = v.model, price = v.price, name = v.name, brand = GetMakeNameFromVehicleModel(v.model):lower():gsub("^%l", string.upper) }
+ end
+ end
+ end)
+end
+
+-- Load Jobs
+if GetResourceState(QBXExport):find("start") then
+ Core = exports[QBExport]:GetCoreObject()
+ print("^6Bridge^7: ^2Loading ^3Jobs^7/^3Gangs^2 from ^7"..QBXExport)
+ Jobs = exports[QBXExport]:GetJobs()
+ Gangs = exports[QBXExport]:GetGangs()
+
+elseif GetResourceState(OXCoreExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Jobs^7/^3Gangs^2 from ^7"..OXCoreExport)
+ CreateThread(function()
+ if IsDuplicityVersion() then
+ createCallback(GetCurrentResourceName()..":getOxGroups", function(source)
+ Jobs = MySQL.query.await('SELECT * FROM `ox_groups`')
+ return Jobs
+ end)
+ else
+ local TempJobs = triggerCallback(GetCurrentResourceName()..":getOxGroups")
+ for k, v in pairs(TempJobs) do
+ local grades = {}
+ for i = 1, #v.grades do grades[i] = { name = grades[i], isboss = (i == #v.grades)} end
+ Jobs = Jobs or {}
+ Jobs[v.name] = { label = v.label, grades = grades, }
+ end
+ end
+ end)
+
+elseif GetResourceState(QBExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Jobs^7/^3Gangs^2 from ^7"..QBExport)
+ Core = Core or exports[QBExport]:GetCoreObject()
+ RegisterNetEvent('QBCore:Client:UpdateObject', function() Core = exports[QBExport]:GetCoreObject() end)
+ Jobs = Core.Shared.Jobs
+ Gangs = Core.Shared.Gangs
+
+elseif GetResourceState(ESXExport):find("start") then
+ print("^6Bridge^7: ^2Loading ^3Jobs^7/^3Gangs^2 from ^7"..ESXExport)
+ ESX = exports[ESXExport]:getSharedObject()
+ if IsDuplicityVersion() then
+ Jobs = ESX.GetJobs()
+ for k, v in pairs(Jobs) do
+ local count = countTable(Jobs[k].grades)-1
+ Jobs[k].grades[tostring(count)].isBoss = true
+ end
+ Gangs = Jobs
+ end
+ CreateThread(function()
+ while not ESX do Wait(0) end
+ if IsDuplicityVersion() then
+ createCallback(GetCurrentResourceName()..":getJobs", function(source)
+ return Jobs
+ end)
+ end
+ if not IsDuplicityVersion() then
+ Jobs = triggerCallback(GetCurrentResourceName()..":getJobs")
+ Gangs = Jobs
+ end
+ end)
+end
+
+function makeBossRoles(role)
+ local boss = {}
+ if Jobs and Jobs[role] then
+ for grade in pairs(Jobs[role].grades) do
+ if Jobs[role].grades[grade].isboss then
+ if boss[role] then
+ if boss[role] > tonumber(grade) then boss[role] = tonumber(grade) end
+ else boss[role] = tonumber(grade) end
+ end
+ end
+ elseif Gangs and Gangs[role] then
+ for grade in pairs(Gangs[role].grades) do
+ if Gangs[role].grades[grade].isboss then
+ if boss[role] then
+ if boss[role] > tonumber(grade) then boss[role] = tonumber(grade) end
+ else boss[role] = tonumber(grade) end
+ end
+ end
+ end
+ return boss
+end
+
+function createPoly(data) local Location = nil
+ if GetResourceState(OXLibExport):find("start") then -- if it finds ox_lib, use it instead of PolyZone
+ if Config.System.Debug then print("^6Bridge^7: ^2Creating new poly with ^7 "..OXLibExport.." "..data.name) end
+ for i = 1, #data.points do
+ data.points[i] = vec3(data.points[i].x, data.points[i].y, 12.0)
+ end
+ data.thickness = 1000
+ Location = lib.zones.poly(data)
+ elseif GetResourceState("PolyZone"):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Creating new poly with ^7PolyZone "..data.name) end
+ Location = PolyZone:Create(data.points, { name = data.name, debugPoly = data.debug })
+ Location:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ data.onEnter()
+ else
+ data.onExit()
+ end
+ end)
+ end
+end
+
+function createCirclePoly(data) local Location = nil
+ if GetResourceState(OXLibExport):find("start") then -- if it finds ox_lib, use it instead of PolyZone
+ if Config.System.Debug then print("^6Bridge^7: ^2Creating new ^3Cricle^2 poly with ^7"..OXLibExport.." "..data.name) end
+ Location = lib.zones.sphere(data)
+ elseif GetResourceState("PolyZone"):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Creating new ^3Cricle^2 poly with ^7PolyZone ".. data.name) end
+ Location = CircleZone:Create(data.coords, data.radius, { name = data.name, debugPoly = Config.System.Debug})
+ Location:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ data.onEnter()
+ else
+ data.onExit()
+ end
+ end)
+ end
+end
+
+function openMenu(Menu, data)
+ if Config.System.Menu == "ox" then
+ if data.onBack then
+ table.insert(Menu, 1, { icon = "fas fa-circle-arrow-left",
+ title = "Return",
+ onSelect = data.onBack,
+ })
+ end
+ for k in pairs(Menu) do
+ if not Menu[k].title then
+ if Menu[k].header ~= nil and Menu[k].header ~= "" then
+ Menu[k].title = Menu[k].header
+ if Menu[k].txt then Menu[k].description = Menu[k].txt else Menu[k].description = "" end
+ else
+ Menu[k].title = Menu[k].txt
+ end
+ end
+ if Menu[k].params then
+ Menu[k].event = Menu[k].params.event
+ Menu[k].args = Menu[k].params.args or {}
+ end
+ if Menu[k].isMenuHeader then
+ Menu[k].disabled = true
+ end
+ end
+ lib.registerContext({id = 'Menu', title = data.header..br..br..(data.headertxt and data.headertxt or ""), position = 'top-right', options = Menu, canClose = data.canClose and data.canClose or nil, onExit = data.onExit and data.onExit or nil, })
+ lib.showContext("Menu")
+ elseif Config.System.Menu == "qb" then
+ if data.onBack then
+ table.insert(Menu, 1, { icon = "fas fa-circle-arrow-left",
+ header = " ", txt = "Return",
+ params = {
+ isAction = true,
+ event = data.onBack,
+ }
+ })
+ elseif data.canClose then
+ table.insert(Menu, 1, { icon = "fas fa-circle-xmark",
+ header = " ", txt = "Close",
+ params = {
+ isAction = true,
+ event = data.onExit and data.onExit or (function() exports[QBMenuExport]:closeMenu() end),
+ }
+ })
+ end
+ if data.header ~= nil then
+ local tempMenu = {}
+ for k, v in pairs(Menu) do tempMenu[k+1] = v end
+ tempMenu[1] = { header = data.header, txt = data.headertxt and data.headertxt or "", isMenuHeader = true }
+ Menu = tempMenu
+ end
+ for k in pairs(Menu) do
+ if Menu[k].onSelect then
+ Menu[k].params = {
+ isAction = true,
+ event = Menu[k].onSelect,
+ }
+ end
+ if not Menu[k].header then Menu[k].header = " " end
+ if Menu[k].arrow then Menu[k].icon = "fas fa-angle-right" end
+ end
+ exports[QBMenuExport]:openMenu(Menu)
+ elseif Config.System.Menu == "gta" then
+ WarMenu.CreateMenu(tostring(Menu),
+ data.header,
+ data.headertxt or " ",
+ { titleColor = { 222, 255, 255 },
+ maxOptionCountOnScreen = 15,
+ width = 0.25,
+ x = 0.7,
+ })
+ if WarMenu.IsAnyMenuOpened() then return end
+ WarMenu.OpenMenu(tostring(Menu))
+ CreateThread(function()
+ local close = true
+ while true do
+ if WarMenu.Begin(tostring(Menu)) then
+ if data.onBack then
+ if WarMenu.SpriteButton("Return", 'commonmenu', "arrowleft", 127, 127, 127) then
+ WarMenu.CloseMenu()
+ Wait(10)
+ data.onBack()
+ end
+ end
+ for k in pairs(Menu) do
+ local pressed = WarMenu.Button(Menu[k].header)
+ if not Menu[k].header then
+ Menu[k].header = Menu[k].txt
+ Menu[k].txt = nil
+ end
+ if Menu[k].txt and Menu[k].txt ~= "" and WarMenu.IsItemHovered() then
+ if Menu[k].disabled or Menu[k].isMenuHeader then
+ WarMenu.ToolTip("~r~"..Menu[k].txt, 0.18, true)
+ else
+ WarMenu.ToolTip(
+ (Menu[k].blip and "~BLIP_".."8".."~ " or "")..
+ Menu[k].txt:gsub("%:", ":~g~"):gsub("%\n", "\n~s~"), 0.18,
+ true)
+ end
+ end
+ if pressed and not Menu[k].isMenuHeader then
+ WarMenu.CloseMenu()
+ close = false
+ Menu[k].onSelect()
+ end
+ end
+ WarMenu.End()
+ else
+ return
+ end
+ if not WarMenu.IsAnyMenuOpened() and close then
+ stopTempCam(cam)
+ if data.onExit then data.onExit() end
+ end
+ Wait(0)
+ end
+ end)
+ elseif Config.System.Menu == "esx" then -- can't display more than one line - BIG problem for crafting menus mainly
+ for k in pairs(Menu) do
+ Menu[k].label = Menu[k].header
+ Menu[k].name = "button"..k
+ end
+ if data.canClose then
+ table.insert(Menu, 1, {
+ icon = "fas fa-circle-xmark",
+ label = "Close",
+ name = "close",
+ onSelect = data.onExit
+ })
+ end
+ if data.onBack then
+ table.insert(Menu, 1, {
+ icon = "fas fa-circle-arrow-left",
+ label = "Return",
+ name = "return",
+ onSelect = data.onback
+ })
+ end
+
+ ESX.UI.Menu.Open("default", GetCurrentResourceName(), "Example_Menu", {
+ title = data.header,
+ align = 'top-right',
+ elements = Menu
+ },
+ function(menuData, menu) -- OnSelect Function
+ for k in pairs(Menu) do
+ if menuData.current.name == Menu[k].name then
+ menu.close()
+ Wait(10)
+ Menu[k].onSelect()
+ end
+ end
+ end,
+ function(data, menu)
+ menu.close() -- close menu
+ end)
+ end
+end
+
+br = (Config.System.Menu == "ox" or Config.System.Menu == "gta") and "\n" or "
"
+
+function isOx() return (Config.System.Menu == "ox" or Config.System.Menu == "gta") end
+
+function isWarMenuOpen() if Config.System.Menu == "gta" then return WarMenu.IsAnyMenuOpened() else return false end end
+
+-- Targets --
+local targetEntities = {}
+function createEntityTarget(entity, opts, dist)
+ targetEntities[#targetEntities+1] = entity
+ if GetResourceState(OXTargetExport):find("start") then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Creating new ^3Entity^2 target with ^6"..OXTargetExport.." ^7"..entity)
+ end
+ local options = {}
+ for i = 1, #opts do
+ options[i] = {
+ icon = opts[i].icon,
+ label = opts[i].label,
+ item = opts[i].item or nil,
+ groups = opts[i].job or opts[i].gang,
+ onSelect = opts[i].action,
+ canInteract = function(_, distance)
+ return distance < dist and true or false
+ end
+ }
+ end
+ exports[OXTargetExport]:addLocalEntity(entity, options)
+ elseif GetResourceState(QBTargetExport):find("start") then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Creating new ^3Entity^2 target with ^6"..QBTargetExport.." ^7"..entity)
+ end
+ local options = { options = opts, distance = dist }
+ exports[QBTargetExport]:AddTargetEntity(entity, options)
+ end
+end
+
+local boxTargets = {}
+function createBoxTarget(data, opts, dist)
+ if GetResourceState(OXTargetExport):find("start") then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Creating new ^3Box^2 target with ^6"..OXTargetExport.." ^7"..data[1])
+ end
+ local options = {}
+ for i = 1, #opts do
+ options[i] = {
+ icon = opts[i].icon,
+ label = opts[i].label,
+ item = opts[i].item or nil,
+ groups = opts[i].job or opts[i].gang,
+ onSelect = opts[i].onSelect or opts[i].action,
+ canInteract = function(_, distance)
+ return distance < dist and true or false
+ end
+ }
+ end
+ if not data[5].useZ then
+ local z = data[2].z + math.abs(data[5].maxZ - data[5].minZ) / 2
+ data[2] = vec3(data[2].x, data[2].y, z)
+ end
+ local target = exports[OXTargetExport]:addBoxZone({
+ coords = data[2],
+ size = vec3(data[4], data[3], (data[5].useZ or not data[5].maxZ) and data[2].z or math.abs(data[5].maxZ - data[5].minZ)),
+ rotation = data[5].heading,
+ debug = data[5].debugPoly,
+ options = options
+ })
+ boxTargets[#boxTargets+1] = target
+ return target
+ elseif GetResourceState(QBTargetExport):find("start") then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Creating new ^3Box^2 target with ^6"..QBTargetExport.." ^7"..data[1])
+ end
+ local options = { options = opts, distance = dist }
+ local target = exports[QBTargetExport]:AddBoxZone(data[1], data[2], data[3], data[4], data[5], options)
+ boxTargets[#boxTargets+1] = target
+ return target
+ end
+end
+
+function removeEntityTarget(entity)
+ if GetResourceState(QBTargetExport):find("start") then exports[QBTargetExport]:RemoveTargetEntity(entity) end
+ if GetResourceState(OXTargetExport):find("start") then exports[OXTargetExport]:removeLocalEntity(entity, nil) end
+end
+
+function removeZoneTarget(target)
+ if GetResourceState(QBTargetExport):find("start") then exports[QBTargetExport]:RemoveZone(target) end
+ if GetResourceState(OXTargetExport):find("start") then exports[OXTargetExport]:removeZone(target, true) end
+end
+
+AddEventHandler('onResourceStop', function(r)
+ if r ~= GetCurrentResourceName() then return end
+ for i = 1, #targetEntities do
+ if GetResourceState(OXTargetExport):find("start") then exports[OXTargetExport]:removeLocalEntity(targetEntities[i], nil)
+ elseif GetResourceState(QBTargetExport):find("start") then exports[QBTargetExport]:RemoveTargetEntity(targetEntities[i]) end
+ end
+ for i = 1, #boxTargets do
+ if GetResourceState(OXTargetExport):find("start") then exports[OXTargetExport]:removeZone(boxTargets[i], true)
+ elseif GetResourceState(QBTargetExport):find("start") then exports[QBTargetExport]:RemoveZone(boxTargets[i].name) end
+ end
+end)
+
+-- NOTIFICATIONS --
+function triggerNotify(title, message, type, src)
+ if Config.System.Notify == "okok" then
+ if not src then TriggerEvent('okokNotify:Alert', title, message, 6000, type)
+ else TriggerClientEvent('okokNotify:Alert', src, title, message, 6000, type) end
+ elseif Config.System.Notify == "qb" then
+ if not src then TriggerEvent("QBCore:Notify", message, type)
+ else TriggerClientEvent("QBCore:Notify", src, message, type) end
+ elseif Config.System.Notify == "ox" then
+ if not src then TriggerEvent('ox_lib:notify', {title = title, description = message, type = type or "success"})
+ else TriggerClientEvent('ox_lib:notify', src, { type = type or "success", title = title, description = message }) end
+ elseif Config.System.Notify == "gta" then
+ if not src then TriggerEvent(GetCurrentResourceName()..":DisplayGTANotify", title, message)
+ else TriggerClientEvent(GetCurrentResourceName()..":DisplayGTANotify", src, title, message) end
+ elseif Config.System.Notify == "esx" then
+ if not src then exports["esx_notify"]:Notify(type, 4000, message)
+ else TriggerClientEvent(GetCurrentResourceName()..":DisplayESXNotify", src, type, title, message) end
+ end
+end
+
+RegisterNetEvent(GetCurrentResourceName()..":DisplayESXNotify", function(type, title, text)
+ exports["esx_notify"]:Notify(type, 4000, message)
+end)
+
+RegisterNetEvent(GetCurrentResourceName()..":DisplayGTANotify", function(title, text) local iconTable = {}
+ if GetCurrentResourceName() == "jim-npcservice" then
+ iconTable = {
+ [Loc[Config.Lan].notify["taxiname"]] = "CHAR_TAXI",
+ [Loc[Config.Lan].notify["limoname"]] = "CHAR_CASINO",
+ [Loc[Config.Lan].notify["ambiname"]] = "CHAR_CALL911",
+ [Loc[Config.Lan].notify["pilotname"]] = "CHAR_DEFAULT",
+ [Loc[Config.Lan].notify["planename"]] = "CHAR_BOATSITE2",
+ [Loc[Config.Lan].notify["heliname"]] = "CHAR_BOATSITE2",
+ }
+ end
+ BeginTextCommandThefeedPost("STRING")
+ AddTextComponentSubstringKeyboardDisplay(text)
+ EndTextCommandThefeedPostMessagetext(iconTable[title] or "CHAR_DEFAULT", iconTable[title] or "CHAR_DEFAULT", true, 1, title, nil, text);
+ EndTextCommandThefeedPostTicker(true, false)
+end)
+
+--DrawText
+function drawText(image, input, style) local text = ""
+ if Config.System.drawText == "qb" then
+ for i = 1, #input do
+ text = text..input[i]..""..(input[i+1] ~= nil and "
" or "") end
+ local text = text:gsub("%:", ":")
+ if image then
+ text = '
'..text
+ end
+ exports[CoreExport]:DrawText(text, 'left')
+
+ elseif Config.System.drawText == "ox" then
+ for k, v in pairs(input) do
+ input[k] = v.." \n"
+ end
+ lib.showTextUI(table.concat(input), { icon = radarTable[image], position = 'left-center' })
+
+ elseif Config.System.drawText == "gta" then
+ 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.."~"))
+ elseif Config.System.drawText == "esx" then
+ for i = 1, #input do
+ text = text..input[i]..""..(input[i+1] ~= nil and "
" or "") end
+ local text = text:gsub("%:", ":")
+ if image then
+ text = '
'..text
+ end
+ ESX.TextUI(text, nil)
+ end
+end
+
+function hideText()
+ if Config.System.drawText == "qb" then
+ exports[CoreExport]:HideText()
+ elseif Config.System.drawText == "ox" then
+ lib.hideTextUI()
+ elseif Config.System.drawText == "gta" then
+ ClearAllHelpMessages()
+ elseif Config.System.drawText == "esx" then
+ ESX.HideUI()
+ end
+end
+
+function DisplayHelpMsg(text)
+ BeginTextCommandDisplayHelp("STRING")
+ AddTextComponentScaleform(text)
+ EndTextCommandDisplayHelp(0, true, false, -1)
+end
+
+-- Callbacks
+function createCallback(callbackName, funct)
+ if GetResourceState(OXLibExport):find("start") then
+ if Config and Config.System.Debug then print("^6Bridge^7: ^2Registering ^3Callback^2 with ^7"..OXLibExport, callbackName) end
+ lib.callback.register(callbackName, funct)
+ elseif GetResourceState(QBExport):find("start") then
+ if Config and Config.System.Debug then print("^6Bridge^7: ^2Registering ^3Callback^2 with ^7"..QBExport, callbackName) end
+ Core = exports[QBExport]:GetCoreObject()
+ Core.Functions.CreateCallback(callbackName, funct)
+ elseif GetResourceState(ESXExport):find("start") then
+ if Config and Config.System.Debug then print("^6Bridge^7: ^2Registering ^3Callback^2 with ^7"..ESXExport, callbackName) end
+ ESX.RegisterServerCallback(callbackName, funct)
+ else
+ print("^6Bridge^7: ^1ERROR^7: ^3Can't find any script to register callback with", callbackName)
+ end
+end
+
+function triggerCallback(callBackName, value) local result = nil
+ if GetResourceState(OXLibExport):find("start") then
+ if Config and Config.System.Debug then print("^6Bridge^7: ^2Triggering ^3Callback^2 with ^7"..OXLibExport, callBackName) end
+ result = lib.callback.await(callBackName, false, value)
+ elseif GetResourceState(QBExport):find("start") then
+ if Config and Config.System.Debug then print("^6Bridge^7: ^2Triggering ^3Callback^2 with ^7"..QBExport, callBackName) end
+ local p = promise.new()
+ Core.Functions.TriggerCallback(callBackName, function(cb) p:resolve(cb) end, value)
+ result = Citizen.Await(p)
+ elseif GetResourceState(ESXExport):find("start") then
+ if Config and Config.System.Debug then print("^6Bridge^7: ^2Triggering ^3Callback^2 with ^7"..ESXExport, callBackName) end
+ local p = promise.new()
+ ESX.TriggerServerCallback(callBackName, function(cb) p:resolve(cb) end, value)
+ result = Citizen.Await(p)
+ else
+ print("^6Bridge^7: ^1ERROR^7: ^3Can't find any script to trigger callback with", callBackName)
+ end
+ return result
+end
+
+-- onPlayerLoaded events
+function onPlayerLoaded(func)
+ if GetResourceState(QBExport):find("start") or GetResourceState(QBXExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering ^3onPlayerLoaded^2 with ^7"..QBExport) end
+ AddEventHandler('QBCore:Client:OnPlayerLoaded', func)
+ elseif GetResourceState(ESXExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering ^3onPlayerLoaded^2 with ^7"..ESXExport) end
+ AddEventHandler('esx:playerLoaded', func)
+ elseif GetResourceState(OXCoreExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering ^3onPlayerLoaded^2 with ^7"..OXLibExport) end
+ AddEventHandler('ox:playerLoaded', func)
+ end
+end
+
+-- INPUT --
+function createInput(title, opts)
+ local dialog = nil
+ local options = {}
+ if Config.Input.Menu == "ox" then
+ for i = 1, #opts do
+ if opts[i].type == "radio" then
+ for k in pairs(opts[i].options) do
+ opts[i].options[k].label = opts[i].options[k].text
+ end
+ options[i] = {
+ type = "select",
+ isRequired = opts[i].isRequired,
+ label = opts[i].label,
+ name = opts[i].name,
+ default = opts[i].options[1].value,
+ options = opts[i].options,
+ }
+ end
+ if opts[i].type == "number" then
+ options[i] = {
+ type = "number",
+ label = opts[i].text.." - "..opts[i].txt,
+ isRequired = opts[i].isRequired,
+ name = opts[i].name,
+ options = opts[i].options,
+ min = opts[i].min,
+ max = opts[i].max,
+ default = opts[i].default,
+ }
+ end
+ end
+ dialog = exports[OXLibExport]:inputDialog(title, options)
+ return dialog
+ end
+ if Config.Input.Menu == "qb" then
+ dialog = exports['qb-input']:ShowInput({ header = title, submitText = "Pay", inputs = opts })
+ return dialog
+ end
+ if Config.Input.Menu == "gta" then
+ WarMenu.CreateMenu(tostring(opts),
+ title,
+ " ",
+ { titleColor = { 222, 255, 255 },
+ maxOptionCountOnScreen = 15,
+ width = 0.25,
+ x = 0.7,
+ })
+ if WarMenu.IsAnyMenuOpened() then return end
+ WarMenu.OpenMenu(tostring(opts))
+ local close = true
+ local _comboBoxItems = { }
+ local _comboBoxIndex = { 1, 1 }
+ while true do
+ if WarMenu.Begin(tostring(opts)) then
+ for i = 1, #opts do
+ if opts[i].type == "radio" then
+ for k in pairs(opts[i].options) do
+ if not _comboBoxItems[i] then _comboBoxItems[i] = {} end
+ _comboBoxItems[i][k] = opts[i].options[k].text
+ end
+ local _, comboBoxIndex = WarMenu.ComboBox(opts[i].label, _comboBoxItems[i], _comboBoxIndex[i])
+ if _comboBoxIndex[i] ~= comboBoxIndex then
+ _comboBoxIndex[i] = comboBoxIndex
+ end
+ end
+ if opts[i].type == "number" then
+ for b = 1, opts[i].max do
+ if not _comboBoxItems[i] then _comboBoxItems[i] = {} end
+ _comboBoxItems[i][b] = b
+ end
+ local _, comboBoxIndex = WarMenu.ComboBox(opts[i].text, _comboBoxItems[i], _comboBoxIndex[i])
+ if _comboBoxIndex[i] ~= comboBoxIndex then
+ _comboBoxIndex[i] = comboBoxIndex
+ end
+ end
+ end
+ local pressed = WarMenu.Button("Pay")
+ if pressed then
+ WarMenu.CloseMenu()
+ close = false
+ local result = {}
+ for i = 1, #_comboBoxIndex do
+ result[i] = _comboBoxItems[i][_comboBoxIndex[i]]
+ end
+ return result
+ end
+ WarMenu.End()
+ else
+ return
+ end
+ if not WarMenu.IsAnyMenuOpened() and close then
+ if data.onExit then data.onExit() end
+ end
+ Wait(0)
+ end
+ end
+end
+
+-- Get Vehile Info --
+local lastCar = nil
+local carInfo = {}
+function searchCar(vehicle)
+ if lastCar ~= vehicle then -- If same car, use previous info
+ lastCar = vehicle
+ carInfo = {}
+ local model = GetEntityModel(vehicle)
+ local classlist = {
+ "Compacts", --1
+ "Sedans", --2
+ "SUVs", --3
+ "Coupes", --4
+ "Muscle", --5
+ "Sports Classics", --6
+ "Sports", --7
+ "Super", --8
+ "Motorcycles", --9
+ "Off-road", --10
+ "Industrial", --11
+ "Utility", --12
+ "Vans", --13
+ "Cycles", --14
+ "Boats", --15
+ "Helicopters", --16
+ "Planes", --17
+ "Service", --18
+ "Emergency", --19
+ "Military", --20
+ "Commercial", --21
+ "Trains", --22
+ }
+ if Vehicles then
+ for k, v in pairs(Vehicles) do
+ if tonumber(v.hash) == model or GetHashKey(v.hash) == model or GetHashKey(v.model) == model then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Vehicle info found in^7 ^4Vehicles^7 ^2table^7: ^6"..(v.hash and v.hash or v.model).. " ^7(^6"..Vehicles[k].name.."^7)")
+ end
+ carInfo.name = Vehicles[k].name.." "..Vehicles[k].brand
+ carInfo.price = Vehicles[k].price
+ carInfo.class = classlist[GetVehicleClass(vehicle) + 1], GetVehicleClass(vehicle)
+ break
+ end
+ end
+
+ if not carInfo.name then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Vehicle ^1not ^2found in ^4vehicles^7 ^2table^7: ^6"..model.." ^7(^6"..GetDisplayNameFromVehicleModel(model):lower().."^7)")
+ end
+ carInfo.name = string.upper(GetMakeNameFromVehicleModel(model).." "..GetDisplayNameFromVehicleModel(model))
+ carInfo.price = 0
+ carInfo.class = classlist[GetVehicleClass(vehicle) + 1], GetVehicleClass(vehicle)
+ end
+ return carInfo
+ else
+ if not carInfo.name then
+ if Config.System.Debug then
+ print("^6Bridge^7: ^2Vehicle ^1not ^2found in ^4vehicles^7 ^2table^7: ^6"..model.." ^7(^6"..GetDisplayNameFromVehicleModel(model):lower().."^7)")
+ end
+ carInfo.name = string.upper(GetMakeNameFromVehicleModel(model).." "..GetDisplayNameFromVehicleModel(model))
+ carInfo.price = 0
+ carInfo.class = classlist[GetVehicleClass(vehicle) + 1], GetVehicleClass(vehicle)
+ end
+ end
+ else
+ return carInfo
+ end
+end
+
+-- Vehicle Properties --
+function getVehicleProperties(vehicle)
+ local properties = {}
+ if vehicle == nil then return nil end
+ if GetResourceState(OXLibExport):find("start") then
+ properties = lib.getVehicleProperties(vehicle)
+ elseif GetResourceState(QBExport):find("start") then
+ properties = Core.Functions.GetVehicleProperties(vehicle)
+ end
+ return properties
+end
+
+function setVehicleProperties(vehicle, props)
+ if not DoesEntityExist(vehicle) then
+ print(("Unable to set vehicle properties for '%s' (entity does not exist)"):
+ format(vehicle))
+ end
+ if GetResourceState(OXLibExport):find("start") then
+ lib.setVehicleProperties(vehicle, props)
+ elseif GetResourceState(QBExport):find("start") then
+ Core.Functions.SetVehicleProperties(vehicle, props)
+ end
+end
+
+RegisterNetEvent(GetCurrentResourceName()..":server:ChargePlayer", function(cost, type) local src = source
+ if Config.System.Debug then print("^6Bridge^7: ^2Charging ^2Player: '^6"..cost.."^7'", type) end
+ if type == "cash" then
+ if GetResourceState(OXInv):find("start") then
+ exports[OXInv]:RemoveItem(src, "money", cost)
+ elseif GetResourceState(QBExport):find("start") then
+ Core.Functions.GetPlayer(src).Functions.RemoveMoney("cash", cost)
+ elseif GetResourceState(ESXExport):find("start") then
+ local Player = ESX.GetPlayerFromId(src)
+ Player.removeMoney(cost, "")
+ end
+ end
+ if type == "bank" then
+ if GetResourceState(QBExport):find("start") or GetResourceState(QBXExport):find("start") then
+ Core.Functions.GetPlayer(src).Functions.RemoveMoney("bank", cost)
+ elseif GetResourceState(ESXExport):find("start") then
+ local Player = ESX.GetPlayerFromId(src)
+ Player.removeMoney(cost, "")
+ end
+ end
+end)
+
+function createUseableItem(item, funct)
+ if GetResourceState(ESXExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering item as ^3Useable^2 with ^7es_extended", item) end
+ while not ESX do Wait(0) end
+ ESX.RegisterUsableItem(item, funct)
+ elseif GetResourceState(QBExport):find("start") and not GetResourceState(QBXExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering item as ^3Useable^2 with ^7qb-core", item) end
+ Core.Functions.CreateUseableItem(item, funct)
+ elseif GetResourceState(QBXExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering item as ^3Useable^2 with ^7qbx_core", item) end
+ exports[QBXExport]:CreateUseableItem(item, funct)
+ end
+end
+
+function hasJob(job, src) local hasJob = false
+ if src then
+ if GetResourceState(ESXExport):find("start") then
+ local info = ESX.GetPlayerFromId(src).job
+ while not info do
+ info = ESX.GetPlayerData(src).job
+ Wait(100)
+ end
+ if info.name == job then hasJob = true end
+
+ elseif GetResourceState(OXCoreExport):find("start") then
+ local chunk = assert(load(LoadResourceFile('ox_core', ('imports/%s.lua'):format('server')), ('@@ox_core/%s'):format(file)))
+ chunk()
+ local player = Ox.GetPlayer(tonumber(src))
+ for k, v in pairs(player.getGroups()) do
+ if k == job then hasJob = true end
+ end
+
+ elseif GetResourceState(QBXExport):find("start") then
+ local jobinfo = exports[QBXExport]:GetPlayer(src).PlayerData.job
+ if jobinfo.name == job then hasJob = true end
+ local ganginfo = exports[QBXExport]:GetPlayer(src).PlayerData.gang
+ if ganginfo.name == job then hasJob = true end
+ else
+ local jobinfo = exports[QBExport]:GetPlayer(src).PlayerData.job
+ if jobinfo.name == job then hasJob = true end
+ local ganginfo = exports[QBExport]:GetPlayer(src).PlayerData.gang
+ if ganginfo.name == job then hasJob = true end
+ end
+ else
+ if GetResourceState(ESXExport):find("start") then
+ while not ESX do Wait(10) end
+ local info = ESX.GetPlayerData().job
+ while not info do
+ info = ESX.GetPlayerData().job
+ Wait(100)
+ end
+ if info.name == job then hasJob = true end
+
+ elseif GetResourceState(OXCoreExport):find("start") then
+ for k, v in pairs(exports[OXCoreExport]:GetPlayerData().groups) do
+ if k == job then hasJob = true end break
+ end
+
+ elseif GetResourceState(QBXExport):find("start") then
+ local jobinfo = QBX.PlayerData.job
+ if jobinfo.name == job then hasJob = true end
+ local ganginfo = QBX.PlayerData.gang
+ if ganginfo.name == job then hasJob = true end
+ else
+ local info = nil
+ Core.Functions.GetPlayerData(function(PlayerData)
+ info = PlayerData
+ end)
+ local jobinfo = info.job
+ if jobinfo.name == job then hasJob = true end
+ local ganginfo = info.gang
+ if ganginfo.name == job then hasJob = true end
+ end
+ end
+ return hasJob
+end
+
+function getPlayer(src) local Player = {}
+ if Config.System.Debug then print("^6Bridge^7: ^2Getting ^3Player^2 info^7") end
+ if src then -- If called from server
+ if GetResourceState(ESXExport):find("start") then
+ local info = ESX.GetPlayerFromId(src)
+ Player = {
+ name = info.getName(),
+ cash = info.getMoney(),
+ bank = info.getAccount("bank").money,
+ }
+ elseif GetResourceState(OXCoreExport):find("start") 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(tonumber(src))
+ Player = {
+ name = ('%s %s'):format(player.firstName, player.lastName),
+ cash = exports[OXInv]:Search(src, 'count', "money"),
+ bank = 0,
+ }
+ elseif GetResourceState(QBXExport):find("start") then
+ local info = exports[QBXExport]:GetPlayer(src)
+ Player = {
+ name = info.PlayerData.charinfo.firstname.." "..info.PlayerData.charinfo.lastname,
+ cash = exports[OXInv]:Search(src, 'count', "money"),
+ bank = info.Functions.GetMoney("bank"),
+ }
+ elseif GetResourceState(QBExport):find("start") and not GetResourceState(QBXExport):find("start") then
+ local info = Core.Functions.GetPlayer(tonumber(src))
+ Player = {
+ name = info.PlayerData.charinfo.firstname.." "..info.PlayerData.charinfo.lastname,
+ cash = info.PlayerData.money["cash"],
+ bank = info.PlayerData.money["bank"],
+ }
+ end
+ else
+ if ESX ~= nil then
+ local info = ESX.GetPlayerData()
+ local cash, bank = 0, 0
+ for k, v in pairs(ESX.GetPlayerData().accounts) do
+ if v.name == "money" then cash = v.money end
+ if v.name == "bank" then bank = v.money end
+ end
+ Player = {
+ name = ('%s %s'):format(info.firstName, info.lastName),
+ cash = cash,
+ bank = bank,
+ }
+ elseif GetResourceState(OXCoreExport):find("start") then
+ local info = exports[OXCoreExport]:GetPlayerData()
+ Player = {
+ name = info.firstName.." "..info.lastName,
+ cash = exports[OXInv]:Search('count', "money"),
+ bank = 0,
+ }
+ elseif GetResourceState(QBXExport):find("start") then
+ local info = exports[QBXExport]:GetPlayerData()
+ Player = {
+ name = info.charinfo.firstname.." "..info.charinfo.lastname,
+ cash = info.money["cash"],
+ bank = info.money["bank"],
+ }
+ else
+ local info = nil
+ Core.Functions.GetPlayerData(function(PlayerData)
+ info = PlayerData
+ end)
+ Player = {
+ name = info.charinfo.firstname.." "..info.charinfo.lastname,
+ cash = info.money["cash"],
+ bank = info.money["bank"],
+ }
+ end
+ end
+ return Player
+end
+
+function registerCommand(command, options)
+ if GetResourceState(OXLibExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering ^3Command^2 with ^7"..OXLibExport, command) end
+ lib.addCommand(command, { help = options[1], restricted = options[5] and "group."..options[5] or nil }, options[4])
+ elseif GetResourceState(QBExport):find("start") and not GetResourceState(QBXExport):find("start") then
+ if Config.System.Debug then print("^6Bridge^7: ^2Registering ^3Command^2 with ^7qb-core"..QBExport, command) end
+ Core.Commands.Add(command, options[1], options[2], options[3], options[4], options[5] and options[5] or nil)
+ end
+end
+
+function invImg(item)
+ local imgLink = ""
+ if item ~= "" and Items[item] then
+ if GetResourceState(OXInv):find("start") then
+ imgLink = "nui://"..OXInv.."/web/images/"..Items[item].image
+ elseif GetResourceState(QSInv and QSInv or ""):find("start") then
+ imgLink = "nui://"..QSInv.."/html/images/"..Items[item].image
+ elseif GetResourceState(CoreInv and CoreInv or ""):find("start") then
+ imgLink = "nui://"..CoreInv.."/html/img/"..Items[item].image
+ elseif GetResourceState(QBInv and QBInv or ""):find("start") then
+ imgLink = "nui://"..QBInv.."/html/images/"..Items[item].image
+ end
+ end
+ return imgLink
+end
+
+function registerStash(name, label)
+ if GetResourceState(OXInv):find("start") then
+ --print("Registering OX Stash:", name, label)
+ exports[OXInv]:RegisterStash(name, label, 50, 4000000)
+ elseif GetResourceState(QSInv):find("start") then
+ --print("Registering QS Stash:", name, label)
+ exports[QSInv]:RegisterStash(name, 50, 4000000)
+ end
+end
+-- IN NO WAY PERFECT --
\ No newline at end of file