local QBCore = exports['qb-core']:GetCoreObject() -- if not LoadResourceFile("Renewed-Banking", 'web/public/build/bundle.js') then -- error('Unable to load UI. Build Renewed-Banking or download the latest release.\n ^https://github.com/Renewed-Scripts/Renewed-Banking/releases/latest/download/Renewed-Banking.rar^0\n If you are using a custom build of the UI, please make sure the resource name is Renewed-Banking (you may not rename the resource).') -- end local cachedAccounts = {} local cachedPlayers = {} CreateThread(function() MySQL.query('SELECT * FROM bank_accounts_new', {}, function(accounts) for _,v in pairs (accounts) do local job = v.id v.auth = json.decode(v.auth) cachedAccounts[job] = { -- cachedAccounts[#cachedAccounts+1] id = job, type = Lang:t("ui.org"), name = QBCore.Shared.Jobs[job] and QBCore.Shared.Jobs[job].label or QBCore.Shared.Gangs[job] and QBCore.Shared.Gangs[job].label or job, frozen = v.isFrozen == 1, amount = v.amount, transactions = json.decode(v.transactions), auth = {}, creator = v.creator } if #v.auth >= 1 then for k=1, #v.auth do cachedAccounts[job].auth[v.auth[k]] = true end end end end) end) local function getTimeElapsed(seconds) local retData local minutes = math.floor(seconds / 60) local hours = math.floor(minutes / 60) local days = math.floor(hours / 24) local weeks = math.floor(days / 7) if weeks ~= 0 and weeks > 1 then retData = Lang:t("time.weeks",{time=weeks}) elseif weeks ~= 0 and weeks == 1 then retData = Lang:t("time.aweek") elseif days ~= 0 and days > 1 then retData = Lang:t("time.days",{time=days}) elseif days ~= 0 and days == 1 then retData = Lang:t("time.aday") elseif hours ~= 0 and hours > 1 then retData = Lang:t("time.hours",{time=hours}) elseif hours ~= 0 and hours == 1 then retData = Lang:t("time.ahour") elseif minutes ~= 0 and minutes > 1 then retData = Lang:t("time.mins",{time=minutes}) elseif minutes ~= 0 and minutes == 1 then retData = Lang:t("time.amin") else retData = Lang:t("time.secs") end return retData end local function updatePlayerAccount(cid) MySQL.query('SELECT * FROM player_transactions WHERE id = @id ', {['@id'] = cid}, function(account) local query = '%' .. cid .. '%' MySQL.query("SELECT * FROM bank_accounts_new WHERE auth LIKE ? ", {query}, function(shared) cachedPlayers[cid] = { isFrozen = 0, transactions = #account > 0 and json.decode(account[1].transactions) or {}, accounts = {} } if #shared >= 1 then for k=1, #shared do cachedPlayers[cid].accounts[#cachedPlayers[cid].accounts+1] = shared[k].id end end end) end) end local function getBankData(source) local Player = QBCore.Functions.GetPlayer(source) local bankData = {} local time = os.time() local cid = Player.PlayerData.citizenid if not cachedPlayers[cid] then updatePlayerAccount(cid) end bankData[#bankData+1] = { id = cid, type = Lang:t("ui.personal"), name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname), frozen = cachedPlayers[cid].isFrozen, amount = Player.PlayerData.money.bank, cash = Player.PlayerData.money.cash, transactions = json.decode(json.encode(cachedPlayers[cid].transactions)), } for k=1, #bankData[1].transactions do bankData[1].transactions[k].time = getTimeElapsed(time-bankData[1].transactions[k].time) end if config.renewedMultiJob then local jobs = exports['qb-phone']:getJobs(cid) for k,v in pairs(jobs) do if cachedAccounts[k] then local job = json.decode(json.encode(cachedAccounts[k])) if job and QBCore.Shared.Jobs[k].grades[tostring(v.grade)].bankAuth then for i=1, #job.transactions do job.transactions[i].time = getTimeElapsed(time-job.transactions[i].time) end bankData[#bankData+1] = job end end end else local job = json.decode(json.encode(cachedAccounts[Player.PlayerData.job.name])) if job and QBCore.Shared.Jobs[Player.PlayerData.job.name].grades[tostring(Player.PlayerData.job.grade.level)].bankAuth then for k=1, #job.transactions do job.transactions[k].time = getTimeElapsed(time-job.transactions[k].time) end bankData[#bankData+1] = job end end local gang = json.decode(json.encode(cachedAccounts[Player.PlayerData.gang.name])) if gang and QBCore.Shared.Gangs[Player.PlayerData.gang.name].grades[tostring(Player.PlayerData.gang.grade.level)].bankAuth then for k=1, #gang.transactions do gang.transactions[k].time = getTimeElapsed(time-gang.transactions[k].time) end bankData[#bankData+1] = gang end local sharedAccounts = cachedPlayers[cid].accounts for k=1, #sharedAccounts do local sAccount = json.decode(json.encode(cachedAccounts[sharedAccounts[k]])) for i=1, #sAccount.transactions do sAccount.transactions[i].time = getTimeElapsed(time-sAccount.transactions[i].time) end bankData[#bankData+1] = sAccount end return bankData end QBCore.Functions.CreateCallback("renewed-banking:server:initalizeBanking", function(source, cb) local bankData = getBankData(source) cb(bankData) end) RegisterNetEvent('QBCore:Server:OnPlayerLoaded', function() local Player = QBCore.Functions.GetPlayer(source) local cid = Player.PlayerData.citizenid updatePlayerAccount(cid) end) -- Events AddEventHandler('onResourceStart', function(resourceName) if resourceName == GetCurrentResourceName() then for _, v in pairs(QBCore.Functions.GetPlayers()) do local Player = QBCore.Functions.GetPlayer(v) if Player then local cid = Player.PlayerData.citizenid updatePlayerAccount(cid) end end end end) local function genTransactionID() local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' return string.gsub(template, '[xy]', function (c) local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb) return string.format('%x', v) end) end local function handleTransaction(account, title, amount, message, issuer, receiver, type, transID) local transaction = { trans_id = transID or genTransactionID(), title = title, amount = amount, trans_type = type, receiver = receiver, message = message, issuer = issuer, time = os.time() } if cachedAccounts[account] then table.insert(cachedAccounts[account].transactions, 1, transaction) MySQL.query("INSERT INTO bank_accounts_new (id, transactions) VALUES (:id, :transactions) ON DUPLICATE KEY UPDATE transactions = :transactions",{ ['id'] = account, ['transactions'] = json.encode(cachedAccounts[account].transactions) }) elseif cachedPlayers[account] then table.insert(cachedPlayers[account].transactions, 1, transaction) MySQL.query("INSERT INTO player_transactions (id, transactions) VALUES (:id, :transactions) ON DUPLICATE KEY UPDATE transactions = :transactions",{ ['id'] = account, ['transactions'] = json.encode(cachedPlayers[account].transactions) }) else print(Lang:t("logs.invalid_account",{account=account})) end return transaction end exports("handleTransaction", handleTransaction) local function getAccountMoney(account) if not cachedAccounts[account] then Lang:t("logs.invalid_account",{account=account}) return false end return cachedAccounts[account].amount end exports('getAccountMoney', getAccountMoney) local function updateBalance(account) MySQL.query("UPDATE bank_accounts_new SET amount = ? WHERE id = ?",{ cachedAccounts[account].amount, account }) end local function addAccountMoney(account, amount) if not cachedAccounts[account] then Lang:t("logs.invalid_account",{account=account}) return false end cachedAccounts[account].amount += amount updateBalance(account) return true end exports('addAccountMoney', addAccountMoney) QBCore.Functions.CreateCallback("Renewed-Banking:server:deposit", function(source, cb, data) local Player = QBCore.Functions.GetPlayer(source) local amount = tonumber(data.amount) if not amount or amount < 1 then QBCore.Functions.Notify(source, Lang:t("notify.invalid_amount",{type="deposit"}), 'error', 5000) cb(false) return end local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) if not data.comment or data.comment == "" then data.comment = Lang:t("notify.comp_transaction",{name = name, type="deposited", amount = amount}) end if Player.Functions.RemoveMoney('cash', amount, data.comment) then if cachedAccounts[data.fromAccount] then addAccountMoney(data.fromAccount, amount) else Player.Functions.AddMoney('bank', amount, data.comment) end handleTransaction(data.fromAccount,Lang:t("ui.personal_acc") .. data.fromAccount, amount, data.comment, name, data.fromAccount, "deposit") local bankData = getBankData(source) cb(bankData) else TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.not_enough_money")) cb(false) end end) local function removeAccountMoney(account, amount) if not cachedAccounts[account] then print(Lang:t("logs.invalid_account",{account=account})) return false end if cachedAccounts[account].amount < amount then print(Lang:t("logs.broke_account",{account=account, amount=amount})) return false end cachedAccounts[account].amount -= amount updateBalance(account) return true end exports('removeAccountMoney', removeAccountMoney) QBCore.Functions.CreateCallback("Renewed-Banking:server:withdraw", function(source, cb, data) local Player = QBCore.Functions.GetPlayer(source) local amount = tonumber(data.amount) if not amount or amount < 1 then QBCore.Functions.Notify(source, Lang:t("notify.invalid_amount",{type="withdraw"}), 'error', 5000) cb(false) return end local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) if not data.comment or data.comment == "" then data.comment = Lang:t("notify.comp_transaction",{name = name, type="withdrawed", amount = amount}) end local canWithdraw if cachedAccounts[data.fromAccount] then canWithdraw = removeAccountMoney(data.fromAccount, amount) else canWithdraw = Player.PlayerData.money.bank >= amount and Player.Functions.RemoveMoney('bank', amount, data.comment) or false end if canWithdraw then Player.Functions.AddMoney('cash', amount, data.comment) handleTransaction(data.fromAccount,Lang:t("ui.personal_acc") .. data.fromAccount, amount, data.comment, data.fromAccount, name, "withdraw") local bankData = getBankData(source) cb(bankData) else TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.not_enough_money")) cb(false) end end) local function getPlayerData(source, id) local Player = QBCore.Functions.GetPlayer(tonumber(id)) if not Player then Player = QBCore.Functions.GetPlayerByCitizenId(id) end if not Player then Player = QBCore.Functions.GetOfflinePlayerByCitizenId(id) if Player and not cachedPlayers[Player.PlayerData.citizenid] then local pushingP = promise.new() MySQL.query('SELECT * FROM player_transactions WHERE id = @id ', {['@id'] = id}, function(account) local resolve = account[1] and json.decode(account[1].transactions) or {} pushingP:resolve(resolve) end) local offlineTrans = Citizen.Await(pushingP) cachedPlayers[id] = {transactions = offlineTrans} end end if not Player then local msg = ("Cannot Find Account(%s)"):format(id) print(Lang:t("logs.invalid_account",{account=id})) if source then QBCore.Functions.Notify(source, msg, 'error', 5000) end end return Player end QBCore.Functions.CreateCallback("Renewed-Banking:server:transfer", function(source, cb, data) local Player = QBCore.Functions.GetPlayer(source) local amount = tonumber(data.amount) if not amount or amount < 1 then QBCore.Functions.Notify(source, Lang:t("notify.invalid_amount",{type="transfer"}), 'error', 5000) cb(false) return end if cachedAccounts[data.fromAccount] then if not data.comment or data.comment == "" then data.comment = Lang:t("notify.comp_transaction",{name = data.fromAccount, type="transfered", amount = amount}) end if cachedAccounts[data.stateid] then local canTransfer = removeAccountMoney(data.fromAccount, amount) if canTransfer then addAccountMoney(data.stateid, amount) local title = ("%s / %s"):format(cachedAccounts[data.fromAccount].name, data.fromAccount) local transaction = handleTransaction(data.fromAccount, title, amount, data.comment, cachedAccounts[data.fromAccount].name, cachedAccounts[data.stateid].name, "withdraw") handleTransaction(data.stateid, title, amount, data.comment, cachedAccounts[data.fromAccount].name, cachedAccounts[data.stateid].name, "deposit", transaction.trans_id) else TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.not_enough_money")) cb(false) return end else local Player2 = getPlayerData(source, data.stateid) if not Player2 then TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.fail_transfer")) cb(false) return end local canTransfer = removeAccountMoney(data.fromAccount, amount) if canTransfer then Player2.Functions.AddMoney('bank', amount, data.comment) local name = ("%s %s"):format(Player2.PlayerData.charinfo.firstname, Player2.PlayerData.charinfo.lastname) local transaction = handleTransaction(data.fromAccount, ("%s / %s"):format(cachedAccounts[data.fromAccount].name, data.fromAccount), amount, data.comment, cachedAccounts[data.fromAccount].name, name, "withdraw") handleTransaction(data.stateid, ("%s / %s"):format(cachedAccounts[data.fromAccount].name, data.fromAccount), amount, data.comment, cachedAccounts[data.fromAccount].name, name, "deposit", transaction.trans_id) else TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.not_enough_money")) cb(false) return end end else local name = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) if not data.comment or data.comment == "" then data.comment = Lang:t("notify.comp_transaction",{name = data.fromAccount, type="transfered", amount = amount}) end if cachedAccounts[data.stateid] then if Player.PlayerData.money.bank >= amount and Player.Functions.RemoveMoney('bank', amount, data.comment) then addAccountMoney(data.stateid, amount) local transaction = handleTransaction(data.fromAccount, Lang:t("ui.personal_acc") .. data.fromAccount, amount, data.comment, name, cachedAccounts[data.stateid].name, "withdraw") handleTransaction(data.stateid, Lang:t("ui.personal_acc") .. data.fromAccount, amount, data.comment, name, cachedAccounts[data.stateid].name, "deposit", transaction.trans_id) else TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.not_enough_money")) cb(false) return end else local Player2 = getPlayerData(source, data.stateid) if not Player2 then TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.fail_transfer")) cb(false) return end if Player.PlayerData.money.bank >= amount and Player.Functions.RemoveMoney('bank', amount, data.comment) then Player2.Functions.AddMoney('bank', amount, data.comment) local name2 = ("%s %s"):format(Player2.PlayerData.charinfo.firstname, Player2.PlayerData.charinfo.lastname) local transaction = handleTransaction(data.fromAccount, Lang:t("ui.personal_acc") .. data.fromAccount, amount, data.comment, name, name2, "withdraw") handleTransaction(data.stateid, Lang:t("ui.personal_acc") .. data.fromAccount, amount, data.comment, name, name2, "deposit", transaction.trans_id) else TriggerClientEvent('Renewed-Banking:client:sendNotification', source, Lang:t("notify.not_enough_money")) cb(false) return end end end local bankData = getBankData(source) cb(bankData) end) RegisterNetEvent('Renewed-Banking:server:createNewAccount', function(accountid) local Player = QBCore.Functions.GetPlayer(source) if cachedAccounts[accountid] then QBCore.Functions.Notify(source, Lang:t("notify.account_taken"), "error") return end cachedAccounts[accountid] = { id = accountid, type = Lang:t("ui.org"), name = accountid, frozen = 0, amount = 0, transactions = {}, auth = { [Player.PlayerData.citizenid] = true }, creator = Player.PlayerData.citizenid } cachedPlayers[Player.PlayerData.citizenid].accounts[#cachedPlayers[Player.PlayerData.citizenid].accounts+1] = accountid MySQL.query("INSERT INTO bank_accounts_new (id, amount, transactions, auth, isFrozen, creator) VALUES (:id, :amount, :transactions, :auth, :isFrozen, :creator) ",{ ['id'] = accountid, ['amount'] = cachedAccounts[accountid].amount, ['transactions'] = json.encode(cachedAccounts[accountid].transactions), ['auth'] = json.encode({Player.PlayerData.citizenid}), ['isFrozen'] = cachedAccounts[accountid].frozen, ['creator'] = Player.PlayerData.citizenid }) end) RegisterNetEvent("Renewed-Banking:server:getPlayerAccounts", function() local Player = QBCore.Functions.GetPlayer(source) local accounts = cachedPlayers[Player.PlayerData.citizenid].accounts local data = {} if #accounts >= 1 then for k=1, #accounts do if cachedAccounts[accounts[k]].creator == Player.PlayerData.citizenid then data[#data+1] = accounts[k] end end end TriggerClientEvent("Renewed-Banking:client:accountsMenu", source, data) end) RegisterNetEvent("Renewed-Banking:server:viewMemberManagement", function(data) local Player = QBCore.Functions.GetPlayer(source) local account = data.account local retData = { account = account, members = {} } for k,_ in pairs(cachedAccounts[account].auth) do local Player2 = getPlayerData(source, k) if Player.PlayerData.citizenid ~= Player2.PlayerData.citizenid then local charInfo = Player2.PlayerData.charinfo retData.members[k] = ("%s %s"):format(charInfo.firstname, charInfo.lastname) end end TriggerClientEvent("Renewed-Banking:client:viewMemberManagement", Player.PlayerData.source, retData) end) RegisterNetEvent('Renewed-Banking:server:addAccountMember', function(account, member) local Player = QBCore.Functions.GetPlayer(source) if Player.PlayerData.citizenid ~= cachedAccounts[account].creator then print(Lang:t("logs.illegal_action", {name=GetPlayerName(source)})) return end local Player2 = getPlayerData(source, member) if not Player2 then return end local targetCID = Player2.PlayerData.citizenid if not Player2.Offline and cachedPlayers[targetCID] then cachedPlayers[targetCID].accounts[#cachedPlayers[targetCID].accounts+1] = account end local auth = {} for k in pairs(cachedAccounts[account].auth) do auth[#auth+1] = k end auth[#auth+1] = targetCID cachedAccounts[account].auth[targetCID] = true MySQL.update('UPDATE bank_accounts_new SET auth = ? WHERE id = ?',{json.encode(auth), account}) end) RegisterNetEvent('Renewed-Banking:server:removeAccountMember', function(data) local Player = QBCore.Functions.GetPlayer(source) if Player.PlayerData.citizenid ~= cachedAccounts[data.account].creator then print(Lang:t("logs.illegal_action", {name=GetPlayerName(source)})) return end local Player2 = getPlayerData(source, data.cid) if not Player2 then return end local targetCID = Player2.PlayerData.citizenid local tmp = {} for k in pairs(cachedAccounts[data.account].auth) do if targetCID ~= k then tmp[#tmp+1] = k end end if not Player2.Offline and cachedPlayers[targetCID] then local newAccount = {} if #cachedPlayers[targetCID].accounts >= 1 then for k=1, #cachedPlayers[targetCID].accounts do if cachedPlayers[targetCID].accounts[k] ~= data.account then newAccount[#newAccount+1] = cachedPlayers[targetCID].accounts[k] end end end cachedPlayers[targetCID].accounts = newAccount end cachedAccounts[data.account].auth[targetCID] = nil MySQL.update('UPDATE bank_accounts_new SET auth = ? WHERE id = ?',{json.encode(tmp), data.account}) end) local split = QBCore.Shared.SplitStr local function updateAccountName(account, newName, src) if not split then split = QBCore.Shared.SplitStr end if not account or not newName then return false end if not cachedAccounts[account] then local getTranslation = Lang:t("logs.invalid_account",{account=account}) print(getTranslation) if src then QBCore.Functions.Notify(src, split(getTranslation, '0')[2], 'error', 5000) end return false end if cachedAccounts[newName] then local getTranslation = Lang:t("logs.existing_account",{account=account}) print(getTranslation) if src then QBCore.Functions.Notify(src, split(getTranslation, '0')[2], 'error', 5000) end return false end if src then local Player = QBCore.Functions.GetPlayer(src) if Player.PlayerData.citizenid ~= cachedAccounts[account].creator then local getTranslation = Lang:t("logs.illegal_action", {name=GetPlayerName(src)}) print(getTranslation) QBCore.Functions.Notify(src, split(getTranslation, '0')[2], 'error', 5000) return false end end cachedAccounts[newName] = json.decode(json.encode(cachedAccounts[account])) cachedAccounts[newName].id = newName cachedAccounts[newName].name = newName cachedAccounts[account] = nil for _, v in pairs(QBCore.Functions.GetPlayers()) do local Player2 = QBCore.Functions.GetPlayer(v) if Player2 then local cid = Player2.PlayerData.citizenid if #cachedPlayers[cid].accounts >= 1 then for k=1, #cachedPlayers[cid].accounts do if cachedPlayers[cid].accounts[k] == account then table.remove(cachedPlayers[cid].accounts, k) cachedPlayers[cid].accounts[#cachedPlayers[cid].accounts+1] = newName end end end end end MySQL.update('UPDATE bank_accounts_new SET id = ? WHERE id = ?',{newName, account}) return true end RegisterNetEvent('Renewed-Banking:server:changeAccountName', function(account, newName) updateAccountName(account, newName, source) end) exports("changeAccountName", updateAccountName)-- Should only use this on very secure backends to avoid anyone using this as this is a server side ONLY export -- local function addAccountMember(account, member) if not account or not member then return end if not cachedAccounts[account] then print(Lang:t("logs.invalid_account",{account=account})) return end local Player2 = getPlayerData(false, member) if not Player2 then return end local targetCID = Player2.PlayerData.citizenid if not Player2.Offline and cachedPlayers[targetCID] then cachedPlayers[targetCID].accounts[#cachedPlayers[targetCID].accounts+1] = account end local auth = {} for k, _ in pairs(cachedAccounts[account].auth) do auth[#auth+1] = k end auth[#auth+1] = targetCID cachedAccounts[account].auth[targetCID] = true MySQL.update('UPDATE bank_accounts_new SET auth = ? WHERE id = ?',{json.encode(auth), account}) end exports("addAccountMember", addAccountMember) local function removeAccountMember(account, member) local Player2 = getPlayerData(false, member) if not Player2 then return end if not cachedAccounts[account] then print(Lang:t("logs.invalid_account",{account=account})) return end local targetCID = Player2.PlayerData.citizenid local tmp = {} for k in pairs(cachedAccounts[account].auth) do if targetCID ~= k then tmp[#tmp+1] = k end end if not Player2.Offline and cachedPlayers[targetCID] then local newAccount = {} if #cachedPlayers[targetCID].accounts >= 1 then for k=1, #cachedPlayers[targetCID].accounts do if cachedPlayers[targetCID].accounts[k] ~= account then newAccount[#newAccount+1] = cachedPlayers[targetCID].accounts[k] end end end cachedPlayers[targetCID].accounts = newAccount end cachedAccounts[account].auth[targetCID] = nil MySQL.update('UPDATE bank_accounts_new SET auth = ? WHERE id = ?',{json.encode(tmp), account}) end exports("removeAccountMember", removeAccountMember) exports("getAccountTransactions", function(account) if cachedAccounts[account] then return cachedAccounts[account].transactions elseif cachedPlayers[account] then return cachedPlayers[account].transactions end print(Lang:t("logs.invalid_account",{account=account})) return false end) QBCore.Commands.Add('givecash', Lang:t('menu.givecash'), {{name = 'id', help = 'Player ID'}, {name = 'amount', help = 'Amount'}}, true, function(source, args) local src = source local id = tonumber(args[1]) local amount = math.ceil(tonumber(args[2])) local Player = QBCore.Functions.GetPlayer(src) if not Player then return end if not id or not amount then QBCore.Functions.Notify(src, Lang:t('menu.givecash'), 'error', 5000) return end local iPlayer = QBCore.Functions.GetPlayer(id) if not iPlayer then QBCore.Functions.Notify(src, Lang:t('notify.unknown_player', {id=id}), 'error', 5000) return end if Player.PlayerData.metadata["isdead"] then QBCore.Functions.Notify(src, Lang:t('notify.dead'), 'error', 5000) return end local distance = Player.PlayerData.metadata["inlaststand"] and 3.0 or 10.0 if #(GetEntityCoords(GetPlayerPed(src)) - GetEntityCoords(GetPlayerPed(id))) > distance then QBCore.Functions.Notify(src, Lang:t('notify.too_far_away'), 'error', 5000) return end if amount < 0 then QBCore.Functions.Notify(src, Lang:t('notify.invalid_amount', {type="give"}), 'error', 5000) return end if Player.Functions.RemoveMoney('cash', amount) then if iPlayer.Functions.AddMoney('cash', amount) then local nameA = ("%s %s"):format(Player.PlayerData.charinfo.firstname, Player.PlayerData.charinfo.lastname) local nameB = ("%s %s"):format(iPlayer.PlayerData.charinfo.firstname, iPlayer.PlayerData.charinfo.lastname) QBCore.Functions.Notify(src, Lang:t('notify.give_cash',{id = nameB, cash = tostring(amount)}), 'success', 5000) QBCore.Functions.Notify(id, Lang:t('notify.received_cash',{id = nameA, cash = tostring(amount)}), 'success', 5000) else -- Return player cash Player.Functions.AddMoney('cash', amount) end else QBCore.Functions.Notify(id, Lang:t('notify.not_enough_money'), 'error', 5000) end end)