Framework, Utils & More
Quality of life scripts for your FiveM server. Performance optimized resources that install in minutes, with free updates and support that actually answers.
bridge/framework/client.lua
lua
function IsJobBoss(job)
if GetResourceState('qbx_core') == 'started' then
local data = exports.qbx_core:GetPlayerData()
return data.job.name == job and data.job.grade.isboss
elseif GetResourceState('qb-core') == 'started' then
local PlayerData = exports['qb-core']:GetCoreObject().Functions.GetPlayerData()
return PlayerData.job.name == job and PlayerData.job.grade.isboss
else
return false
end
end
function GetJobLabel(job)
if GetResourceState('qbx_core') == 'started' then
local jobInfo = exports.qbx_core:GetJobs()[job]
return jobInfo and jobInfo.label or 'None'
elseif GetResourceState('qb-core') == 'started' then
local jobInfo = exports['qb-core']:GetCoreObject().Shared.Jobs[job]
return jobInfo and jobInfo.label or 'None'
else
return 'None'
end
end
CreateThread(function()
local timeout = 30000
while GetResourceState('ox_inventory') ~= 'missing' and timeout > 0 do
Wait(1000)
timeout = timeout - 1000
if GetResourceState('ox_inventory') == 'started' then
exports.ox_inventory:displayMetadata({ job = 'Job' })
end
end
end)
-- For Inventory Use
local function useBusinessPos(data, slot)
if not slot.metadata or not next(slot.metadata) then Notify("Not valid machine") return end
PlayEmote()
local jobName = slot.metadata?.jobName or GetJobLabel()
local input = lib.inputDialog('Point of Sale (POS): '..jobName or slot.metadata.job, {
{type = 'number', label = 'Person ID', icon = 'credit-card', min = 1},
{type = 'number', label = 'Amount', icon = 'credit-card', min = 1},
{type = 'input', label = 'Reason', icon = 'circle-question'},
{type = 'select', label = 'Payment Mode', options = { { value = "cash", label = "Cash" }, { value = "bank", label = "Card" } }, default = "cash", required = true},
})
CancelEmote()
if input then
if not input[1] then Notify("Person ID not provided") return end
if not input[2] then Notify("Amount not provided") return end
if not input[3] then Notify("Reason not provided") return end
if not input[4] then Notify("Payment mode not provided") return end
TriggerServerEvent('payments:server:sendPaymentRequest', input, slot.metadata.job)
end
end
RegisterNetEvent('payments:client:useBusinessPos', function(data)
useBusinessPos(nil, data)
end)
exports('useBusinessPos', useBusinessPos)
-- For Inventory Use
local function useGeneralPos()
PlayEmote()
local input = lib.inputDialog('Point of Sale (POS)', {
{type = 'number', label = 'Person ID', icon = 'credit-card', min = 1},
{type = 'number', label = 'Amount', icon = 'credit-card', min = 1},
{type = 'input', label = 'Reason', icon = 'circle-question'},
{type = 'select', label = 'Payment Mode', options = { { value = "cash", label = "Cash" }, { value = "bank", label = "Card" } }, default = "cash", required = true},
})
CancelEmote()
if input then
if not input[1] then Notify("Person ID not provided") return end
if not input[2] then Notify("Amount not provided") return end
if not input[3] then Notify("Reason not provided") return end
if not input[4] then Notify("Payment mode not provided") return end
TriggerServerEvent('payments:server:sendPaymentRequest', input)
end
end
RegisterNetEvent('payments:client:useGeneralPos', useGeneralPos)
exports('useGeneralPos', useGeneralPos)bridge/framework/server.lua
lua
function GetJobLabel(job)
if GetResourceState('qbx_core') == 'started' then
local jobInfo = exports.qbx_core:GetJobs()[job]
return jobInfo and jobInfo.label or 'None'
elseif GetResourceState('qb-core') == 'started' then
local jobInfo = exports['qb-core']:GetCoreObject().Shared.Jobs[job]
return jobInfo and jobInfo.label or 'None'
end
end
function GetPlayer(src)
if GetResourceState('qbx_core') == 'started' then
local player = exports.qbx_core:GetPlayer(src)
return player and {
source = player.PlayerData.source,
name = string.format('%s %s', player.PlayerData.charinfo.firstname, player.PlayerData.charinfo.lastname),
cash = player.PlayerData.money.cash,
bank = player.PlayerData.money.bank,
addMoney = function(mtype, amount, reason)
return player.Functions.AddMoney(mtype, amount, reason)
end,
removeMoney = function(mtype, amount, reason)
return player.Functions.RemoveMoney(mtype, amount, reason)
end
}
elseif GetResourceState('qb-core') == 'started' then
local player = exports['qb-core']:GetCoreObject().Functions.GetPlayer(src)
return player and {
source = player.PlayerData.source,
name = string.format('%s %s', player.PlayerData.charinfo.firstname, player.PlayerData.charinfo.lastname),
cash = player.PlayerData.money.cash,
bank = player.PlayerData.money.bank,
addMoney = function(mtype, amount, reason)
return player.Functions.AddMoney(mtype, amount, reason)
end,
removeMoney = function(mtype, amount, reason)
return player.Functions.RemoveMoney(mtype, amount, reason)
end
}
end
end
function HasItem(src, item, amount)
if GetResourceState('ox_inventory') == 'started' then
local count = exports.ox_inventory:GetItem(src, item, nil, true)
return (count and count >= amount) or 0
elseif GetResourceState('qb-inventory') == 'started' then
return exports['qb-inventory']:HasItem(src, item, amount)
elseif GetResourceState('qs-inventory') == 'started' then
local totalAmount = exports['qs-inventory']:GetItemTotalAmount(src, item)
return (totalAmount and totalAmount >= amount)
end
end
function AddItem(src, item, amount, metadata)
if GetResourceState('ox_inventory') == 'started' then
return exports.ox_inventory:AddItem(src, item, amount, metadata)
elseif GetResourceState('qb-inventory') == 'started' then
return exports['qb-inventory']:AddItem(src, item, amount, nil, metadata)
elseif GetResourceState('qs-inventory') == 'started' then
return exports['qs-inventory']:AddItem(src, item, amount, nil, metadata)
end
end
function RemoveItem(src, item, amount)
if GetResourceState('ox_inventory') == 'started' then
return exports.ox_inventory:RemoveItem(src, item, amount)
elseif GetResourceState('qb-inventory') == 'started' then
return exports['qb-inventory']:RemoveItem(src, item, amount)
elseif GetResourceState('qs-inventory') == 'started' then
return exports['qs-inventory']:RemoveItem(src, item, amount)
end
end
function AddMoneyToAccount(accountName, amount, reason)
if GetResourceState('qb-banking') == 'started' then
return exports['qb-banking']:AddMoney(accountName, amount, reason)
elseif GetResourceState('snipe-banking') == 'started' then
return exports['snipe-banking']:AddMoneyToAccount(accountName, amount, reason)
elseif GetResourceState('Renewed-Banking') == 'started' then
return exports['Renewed-Banking']:addAccountMoney(accountName, amount)
elseif GetResourceState('qb-management') == 'started' then
return exports["qb-management"]:AddMoney(accountName, amount, reason)
elseif GetResourceState('fd_banking') == 'started' then
return exports['fd_banking']:AddMoney(accountName, amount, reason)
elseif GetResourceState('okokBanking') == 'started' then
return exports['okokBanking']:AddMoney(accountName, amount, reason)
elseif GetResourceState('kartik-banking') == 'started' then
return exports['kartik-banking']:AddAccountMoney(accountName, amount, reason)
else
return false
end
end
CreateThread(function ()
local timeout = 60000
if GetResourceState('qb-inventory') ~= 'missing' then
while GetResourceState('qb-inventory') ~= 'started' and timeout > 0 do
Wait(1000)
timeout = timeout - 1000
end
exports['qb-core']:CreateUseableItem('businesspos', function(source, item)
local Player = exports['qb-core']:GetPlayer(source)
if not Player.Functions.GetItemByName(item.name) then return end
item.metadata = item.info
TriggerClientEvent('payments:client:useBusinessPos', source, item)
end)
exports['qb-core']:CreateUseableItem('generalpos', function(source, item)
local Player = exports['qb-core']:GetPlayer(source)
if not Player.Functions.GetItemByName(item.name) then return end
TriggerClientEvent('payments:client:useGeneralPos', source)
end)
elseif GetResourceState('qs-inventory') ~= 'missing' then
while GetResourceState('qs-inventory') ~= 'started' and timeout > 0 do
Wait(1000)
timeout = timeout - 1000
end
exports['qs-inventory']:CreateUsableItem('generalpos', function(source, item)
if item.metadata and item.metadata.quality then
TriggerClientEvent('payments:client:useGeneralPos', source, item)
end
end)
exports['qs-inventory']:CreateUsableItem('businesspos', function(source, item)
if item.metadata and item.metadata.quality then
TriggerClientEvent('payments:client:useBusinessPos', source)
end
end)
end
end)bridge/utils/client.lua
lua
function Notify(msg, type)
lib.notify({ description = msg, type = type })
if Config.Notify == 'qb' then
TriggerEvent("QBCore:Notify", msg, type, 10000)
elseif Config.Notify == 'ox' then
lib.notify({ description = msg, type = type, duration = 10000 })
elseif Config.Notify == 'snappy-phone' then
local data = {
title = 'Payment Terminal',
icon = 'cash-register',
description = msg,
duration = 5000,
}
exports['snappy-phone']:sendNotification(data)
elseif Config.Notify == 'lb-phone' then
local data = {
title = 'Payment Terminal',
content = msg
}
exports['lb-phone']:SendNotification(data)
elseif Config.Notify == 'yseries' then
TriggerServerEvent('yseries:server:qb-phone-bridge:send-notification', 'Payment Terminal', mst, 15000, GetPlayerServerId(PlayerId()))
end
end
function PlayEmote()
if GetResourceState('scully_emotemenu') == 'started' then
exports.scully_emotemenu:playEmoteByCommand('terminal')
elseif GetResourceState('rpemotes') == 'started' then
exports.rpemotes:EmoteCommandStart('terminal')
end
end
function CancelEmote()
if GetResourceState('scully_emotemenu') == 'started' then
exports.scully_emotemenu:cancelEmote()
elseif GetResourceState('rpemotes') == 'started' then
exports.rpemotes:EmoteCancel()
end
end
function RequestConfirmation(data)
local title = 'Payment Request: ' .. string.upper(data.name)
local description = string.format('Payment of $%d requested for %s', data.amount, data.reason)
if Config.Phone == 'snappy-phone' then
local status = exports['snappy-phone']:sendConfirmation({
title = title,
description = description,
icon = 'credit-card',
duration = 10000,
})
return status
elseif Config.Phone == 'lb-phone' then
local result = promise:new()
local notificationEvent
CreateThread(function()
notificationEvent = RegisterNetEvent('lbphone:notificationResponse', function(response)
result:resolve(response.status)
RemoveEventHandler(notificationEvent)
end)
end)
exports['lb-phone']:SendNotification({
title = title,
content = description,
customData = {
buttons = {
{ title = "Accept", event = "lbphone:notificationResponse", data = { status = true } },
{ title = "Decline", event = "lbphone:notificationResponse", data = { status = false } }
}
}
})
SetTimeout(15000, function()
result:resolve(false)
end)
local response = Citizen.Await(result)
return response
elseif Config.Phone == 'yseries' then
local result = promise:new()
local notificationEvent
CreateThread(function()
notificationEvent = RegisterNetEvent('yseries:notificationResponse', function(response)
result:resolve(response)
RemoveEventHandler(notificationEvent)
end)
end)
lib.callback.await('yseries:custom:sendMail', false, {
title = title,
sender = 'paymentshub@mayaalokam.com',
senderDisplayName = 'Payments Hub',
content = description,
actions = {
{
label = "Accept",
data = {
event = "yseries:notificationResponse",
isServer = false,
data = true,
shouldClose = true
}
},
{
label = "Decline",
data = {
event = "yseries:notificationResponse",
isServer = false,
data = false,
shouldClose = true
}
}
}
})
SetTimeout(15000, function()
result:resolve(false)
end)
local response = Citizen.Await(result)
return response
end
end
CreateThread(function()
for _, data in pairs(Config.Registers) do
local point = lib.points.new({
coords = vec3(data.coords.x, data.coords.y, data.coords.z),
distance = data.distance,
name = data.name,
job = data.job
})
function point:onEnter()
lib.showTextUI('[E] Access Register')
end
function point:onExit()
lib.hideTextUI()
end
function point:nearby()
if self.currentDistance < 2 and IsControlJustReleased(0, 46) then
local options = {
{
title = 'Charge Customer',
icon = 'fa-solid fa-cash-register',
onSelect = function()
exports['cad-payments']:OpenChargeMenu(self.job)
end
},
}
if IsJobBoss(self.job) then
options[#options + 1] = {
title = 'Collect Cash',
icon = 'fa-solid fa-cash-register',
onSelect = function()
exports['cad-payments']:OpenCashRegister(self.job)
end
}
end
lib.registerContext({
id = 'payments_register',
title = self.name,
options = options
})
lib.showContext('payments_register')
end
end
end
end)
bridge/utils/server.lua
lua
local webhooks = {
['police'] = '',
['ambulance'] = '',
['mechanic'] = '',
}
function Notify(src, msg, type)
if Config.Notify == 'qb' then
TriggerClientEvent("QBCore:Notify", src, msg, type, 5000)
elseif Config.Notify == 'ox' then
TriggerClientEvent("ox_lib:notify", src, {
description = msg,
type = type,
duration = 5000
})
elseif Config.Notify == 'snappy-phone' then
TriggerClientEvent('phone:client:notification', src, {
title = 'Payment Terminal',
icon = 'cash-register',
description = msg,
duration = 5000,
})
elseif Config.Notify == 'lb-phone' then
exports["lb-phone"]:SendNotification(src, {
title = 'Payment Terminal',
content = msg
})
elseif Config.Notify == 'yseries' then
exports.yseries:SendNotification({
title = 'Payment Terminal',
text = msg,
timeout = 5000,
icon = 'https://cdn-icons-png.flaticon.com/128/4645/4645352.png'
}, 'source', src)
end
end
function Sendlog(logName, logType, message)
if not webhooks[logName] then return end
local _data = json.encode({
username = "Payments Portal",
embeds = {
{
title = logType,
color = 10650848,
author = {
name = "Cadburry",
},
description = message,
footer = {
text = os.date('%c'),
},
}
}
})
PerformHttpRequest(webhooks[logName], function() end, 'POST', _data, { ['Content-Type'] = 'application/json' })
end
lib.callback.register('yseries:custom:sendMail', function(source, data)
local insertId, received = exports.yseries:SendMail(data, 'source', source)
return insertId and received
end)
lib.addCommand('give_pos', {
help = 'Provide POS Machine',
params = {
{
name = 'target',
type = 'playerId',
help = 'Target player\'s server id',
},
{
name = 'job',
type = 'string',
help = 'Name of the job',
}
},
restricted = 'group.admin'
}, function(source, args, raw)
if not args.target then return end
local jobName = args.job and GetJobLabel(args.job) or nil
local itemName = (args.job and 'businesspos') or 'generalpos'
AddItem(args.target, itemName, 1, { job = args.job, jobName = jobName })
end)
