diff --git a/resources/[inventory]/nordi_vending/client.lua b/resources/[inventory]/nordi_vending/client.lua index f59530e91..3ea2e2a9d 100644 --- a/resources/[inventory]/nordi_vending/client.lua +++ b/resources/[inventory]/nordi_vending/client.lua @@ -11,7 +11,7 @@ CreateThread(function() event = "vending:client:buyMachine", icon = "fas fa-dollar-sign", label = "Automaten kaufen ($" .. Config.VendingMachinePrice .. ")", - canInteract = function(entity, distance, data) + canInteract = function(entity) return not isRegisteredMachine(entity) end }, @@ -20,7 +20,7 @@ CreateThread(function() event = "vending:client:openBuyMenu", icon = "fas fa-shopping-cart", label = "Kaufen", - canInteract = function(entity, distance, data) + canInteract = function(entity) return isRegisteredMachine(entity) end }, @@ -29,8 +29,8 @@ CreateThread(function() event = "vending:client:openOwnerMenu", icon = "fas fa-cog", label = "Verwalten", - canInteract = function(entity, distance, data) - return isOwnerOfMachine(entity) + canInteract = function(entity) + return canManageMachine(entity) end }, { @@ -38,8 +38,8 @@ CreateThread(function() event = "vending:client:startRobbery", icon = "fas fa-mask", label = "Aufbrechen", - canInteract = function(entity, distance, data) - return isRegisteredMachine(entity) and not isOwnerOfMachine(entity) + canInteract = function(entity) + return isRegisteredMachine(entity) and not canManageMachine(entity) end } }, @@ -66,23 +66,23 @@ function isRegisteredMachine(entity) return isRegistered end --- Check if player owns machine -function isOwnerOfMachine(entity) +-- Check if player can manage machine +function canManageMachine(entity) local coords = GetEntityCoords(entity) - local isOwner = false + local canManage = false - QBCore.Functions.TriggerCallback('vending:server:isOwner', function(owner) - isOwner = owner + QBCore.Functions.TriggerCallback('vending:server:canManage', function(result) + canManage = result end, coords) -- Wait for callback local timeout = 0 - while isOwner == false and timeout < 100 do + while canManage == false and timeout < 100 do Wait(10) timeout = timeout + 1 end - return isOwner + return canManage end -- Buy vending machine @@ -125,7 +125,7 @@ RegisterNetEvent('vending:client:buyMachine', function(data) lib.showContext('vending_buy_confirm') end) --- Open buy menu +-- Open buy menu with quantity selection RegisterNetEvent('vending:client:openBuyMenu', function(data) local entity = data.entity local coords = GetEntityCoords(entity) @@ -147,7 +147,7 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data) description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount, icon = 'fas fa-shopping-cart', onSelect = function() - TriggerServerEvent('vending:server:buyItem', coords, item.name) + openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel) end }) end @@ -168,6 +168,30 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data) end, coords) end) +-- Open quantity dialog for buying items +function openQuantityDialog(coords, itemName, price, maxAmount, itemLabel) + local input = lib.inputDialog('Menge auswählen', { + { + type = 'number', + label = itemLabel .. ' - $' .. price .. ' pro Stück', + description = 'Wie viele möchtest du kaufen? (Max: ' .. maxAmount .. ')', + required = true, + min = 1, + max = maxAmount, + default = 1 + } + }) + + if input and input[1] then + local amount = tonumber(input[1]) + if amount > 0 and amount <= maxAmount then + TriggerServerEvent('vending:server:buyItem', coords, itemName, amount) + else + QBCore.Functions.Notify('Ungültige Menge!', 'error') + end + end +end + -- Open owner menu RegisterNetEvent('vending:client:openOwnerMenu', function(data) local entity = data.entity @@ -179,43 +203,57 @@ RegisterNetEvent('vending:client:openOwnerMenu', function(data) return end + local options = { + { + title = 'Inventar verwalten', + description = 'Items hinzufügen/entfernen', + icon = 'fas fa-box', + onSelect = function() + TriggerServerEvent('vending:server:openStash', coords) + end + }, + { + title = 'Preise festlegen', + description = 'Verkaufspreise für Items setzen', + icon = 'fas fa-tags', + onSelect = function() + openPriceMenu(coords) + end + }, + { + title = 'Geld abheben', + description = 'Verfügbar: $' .. machine.money, + icon = 'fas fa-money-bill', + onSelect = function() + openWithdrawMenu(coords, machine.money) + end + }, + { + title = 'Statistiken', + description = 'Verkaufsstatistiken anzeigen', + icon = 'fas fa-chart-bar', + onSelect = function() + openStatsMenu(machine) + end + } + } + + -- Add manager options only for owner + if machine.isOwner then + table.insert(options, { + title = 'Verwalter', + description = 'Verwalter hinzufügen/entfernen', + icon = 'fas fa-users-cog', + onSelect = function() + openManagersMenu(coords) + end + }) + end + lib.registerContext({ id = 'vending_owner_menu', title = 'Verkaufsautomat Verwaltung', - options = { - { - title = 'Inventar verwalten', - description = 'Items hinzufügen/entfernen', - icon = 'fas fa-box', - onSelect = function() - TriggerServerEvent('vending:server:openStash', coords) - end - }, - { - title = 'Preise festlegen', - description = 'Verkaufspreise für Items setzen', - icon = 'fas fa-tags', - onSelect = function() - openPriceMenu(coords) - end - }, - { - title = 'Geld abheben', - description = 'Verfügbar: $' .. machine.money, - icon = 'fas fa-money-bill', - onSelect = function() - openWithdrawMenu(coords, machine.money) - end - }, - { - title = 'Statistiken', - description = 'Verkaufsstatistiken anzeigen', - icon = 'fas fa-chart-bar', - onSelect = function() - openStatsMenu(machine) - end - } - } + options = options }) lib.showContext('vending_owner_menu') @@ -325,7 +363,107 @@ function openStatsMenu(machine) lib.showContext('vending_stats_menu') end --- Start robbery +-- Open managers menu +function openManagersMenu(coords) + -- Get current managers + QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers) + local options = { + { + title = 'Verwalter hinzufügen', + description = 'Neuen Verwalter hinzufügen', + icon = 'fas fa-user-plus', + onSelect = function() + openAddManagerMenu(coords) + end + } + } + + -- Add existing managers with remove option + if #managers > 0 then + for i = 1, #managers do + local manager = managers[i] + table.insert(options, { + title = manager.name, + description = manager.online and 'Online' or 'Offline', + icon = manager.online and 'fas fa-circle text-success' or 'fas fa-circle text-danger', + onSelect = function() + lib.registerContext({ + id = 'manager_options', + title = 'Verwalter: ' .. manager.name, + menu = 'managers_menu', + options = { + { + title = 'Entfernen', + description = 'Verwalter entfernen', + icon = 'fas fa-user-minus', + onSelect = function() + TriggerServerEvent('vending:server:removeManager', coords, manager.citizenid) + Wait(500) + openManagersMenu(coords) -- Refresh the menu + end + } + } + }) + lib.showContext('manager_options') + end + }) + end + else + table.insert(options, { + title = 'Keine Verwalter', + description = 'Es sind keine Verwalter vorhanden', + icon = 'fas fa-info-circle', + disabled = true + }) + end + + lib.registerContext({ + id = 'managers_menu', + title = 'Verwalter verwalten', + menu = 'vending_owner_menu', + options = options + }) + + lib.showContext('managers_menu') + end, coords) +end + +-- Open add manager menu +function openAddManagerMenu(coords) + QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players) + if #players == 0 then + QBCore.Functions.Notify('Keine Spieler online!', 'error') + return + end + + local options = {} + + for i = 1, #players do + local player = players[i] + table.insert(options, { + title = player.name, + description = 'ID: ' .. player.id, + icon = 'fas fa-user', + onSelect = function() + TriggerServerEvent('vending:server:addManager', coords, player.id) + Wait(500) + openManagersMenu(coords) -- Refresh the menu + end + }) + end + + lib.registerContext({ + id = 'add_manager_menu', + title = 'Verwalter hinzufügen', + menu = 'managers_menu', + options = options + }) + + lib.showContext('add_manager_menu') + end) +end + +-- Robbery menu RegisterNetEvent('vending:client:startRobbery', function(data) local entity = data.entity local coords = GetEntityCoords(entity) diff --git a/resources/[inventory]/nordi_vending/server.lua b/resources/[inventory]/nordi_vending/server.lua index 7b0f703ed..dc425d6dc 100644 --- a/resources/[inventory]/nordi_vending/server.lua +++ b/resources/[inventory]/nordi_vending/server.lua @@ -16,6 +16,7 @@ CreateThread(function() money = data.money, items = json.decode(data.items) or {}, prices = json.decode(data.prices) or {}, + managers = json.decode(data.managers) or {}, stash = 'vending_' .. data.id } end @@ -48,12 +49,13 @@ RegisterNetEvent('vending:server:registerMachine', function(coords, prop) Player.Functions.RemoveMoney('cash', Config.VendingMachinePrice) -- Create machine in database - local machineId = MySQL.insert.await('INSERT INTO vending_machines (owner, coords, prop, money, items, prices) VALUES (?, ?, ?, ?, ?, ?)', { + local machineId = MySQL.insert.await('INSERT INTO vending_machines (owner, coords, prop, money, items, prices, managers) VALUES (?, ?, ?, ?, ?, ?, ?)', { Player.PlayerData.citizenid, json.encode(coords), prop, 0, json.encode({}), + json.encode({}), json.encode({}) }) @@ -66,6 +68,7 @@ RegisterNetEvent('vending:server:registerMachine', function(coords, prop) money = 0, items = {}, prices = {}, + managers = {}, stash = 'vending_' .. machineId } @@ -74,6 +77,31 @@ RegisterNetEvent('vending:server:registerMachine', function(coords, prop) TriggerClientEvent('vending:client:refreshTargets', -1) end) +-- Check if player can manage machine +function canManageMachine(playerId, machineId) + local Player = QBCore.Functions.GetPlayer(playerId) + if not Player then return false end + + local machine = vendingMachines[machineId] + if not machine then return false end + + -- Check if player is owner + if machine.owner == Player.PlayerData.citizenid then + return true + end + + -- Check if player is manager + if machine.managers then + for _, manager in pairs(machine.managers) do + if manager == Player.PlayerData.citizenid then + return true + end + end + end + + return false +end + -- Open management menu RegisterNetEvent('vending:server:openManagement', function(coords) local src = source @@ -84,15 +112,20 @@ RegisterNetEvent('vending:server:openManagement', function(coords) if not machineId then return end local machine = vendingMachines[machineId] - if machine.owner ~= Player.PlayerData.citizenid then - TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + + -- Check if player can manage + if not canManageMachine(src, machineId) then + TriggerClientEvent('QBCore:Notify', src, 'Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') return end + -- Add isOwner flag to distinguish between owner and manager + machine.isOwner = (machine.owner == Player.PlayerData.citizenid) + TriggerClientEvent('vending:client:openManagement', src, machine) end) --- Open stash (korrekt für tgiann-inventory) +-- Open stash RegisterNetEvent('vending:server:openStash', function(coords) local src = source local Player = QBCore.Functions.GetPlayer(src) @@ -101,12 +134,14 @@ RegisterNetEvent('vending:server:openStash', function(coords) local machineId = getMachineIdByCoords(coords) if not machineId then return end - local machine = vendingMachines[machineId] - if machine.owner ~= Player.PlayerData.citizenid then - TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + -- Check if player can manage + if not canManageMachine(src, machineId) then + TriggerClientEvent('QBCore:Notify', src, 'Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') return end + local machine = vendingMachines[machineId] + -- Öffne das Inventar mit tgiann-inventory exports["tgiann-inventory"]:OpenInventory(src, "stash", machine.stash, { maxweight = Config.MaxWeight, @@ -124,12 +159,14 @@ RegisterNetEvent('vending:server:setItemPrice', function(coords, itemName, price local machineId = getMachineIdByCoords(coords) if not machineId then return end - local machine = vendingMachines[machineId] - if machine.owner ~= Player.PlayerData.citizenid then - TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + -- Check if player can manage + if not canManageMachine(src, machineId) then + TriggerClientEvent('QBCore:Notify', src, 'Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') return end + local machine = vendingMachines[machineId] + -- Update price machine.prices[itemName] = price MySQL.update('UPDATE vending_machines SET prices = ? WHERE id = ?', {json.encode(machine.prices), machineId}) @@ -146,12 +183,14 @@ RegisterNetEvent('vending:server:withdrawMoney', function(coords, amount) local machineId = getMachineIdByCoords(coords) if not machineId then return end - local machine = vendingMachines[machineId] - if machine.owner ~= Player.PlayerData.citizenid then - TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + -- Check if player can manage + if not canManageMachine(src, machineId) then + TriggerClientEvent('QBCore:Notify', src, 'Du hast keine Berechtigung diesen Automaten zu verwalten!', 'error') return end + local machine = vendingMachines[machineId] + if machine.money < amount then TriggerClientEvent('QBCore:Notify', src, 'Nicht genug Geld im Automaten!', 'error') return @@ -166,8 +205,8 @@ RegisterNetEvent('vending:server:withdrawMoney', function(coords, amount) TriggerClientEvent('QBCore:Notify', src, 'Du hast $' .. amount .. ' abgehoben!', 'success') end) --- Buy item from vending machine -RegisterNetEvent('vending:server:buyItem', function(coords, itemName) +-- Buy item from vending machine with quantity selection +RegisterNetEvent('vending:server:buyItem', function(coords, itemName, amount) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return end @@ -177,44 +216,213 @@ RegisterNetEvent('vending:server:buyItem', function(coords, itemName) local machine = vendingMachines[machineId] local price = machine.prices[itemName] or Config.DefaultPrice + local totalPrice = price * amount -- Check if player has enough money - if Player.PlayerData.money.cash < price then + if Player.PlayerData.money.cash < totalPrice then TriggerClientEvent('QBCore:Notify', src, 'Du hast nicht genug Geld!', 'error') return end -- Get stash items local stashItems = exports["tgiann-inventory"]:GetSecondaryInventoryItems("stash", machine.stash) - local hasItem = false + local availableAmount = 0 if stashItems then for slot, item in pairs(stashItems) do if item.name == itemName and item.amount > 0 then - hasItem = true + availableAmount = availableAmount + item.amount + end + end + end + + if availableAmount < amount then + TriggerClientEvent('QBCore:Notify', src, 'Nicht genug Artikel verfügbar! Verfügbar: ' .. availableAmount, 'error') + return + end + + -- Check if player can carry the items + if not Player.Functions.AddItem(itemName, amount) then + TriggerClientEvent('QBCore:Notify', src, 'Du kannst nicht so viele Items tragen!', 'error') + return + end + + -- Remove money from player + Player.Functions.RemoveMoney('cash', totalPrice) + + -- Add money to machine + machine.money = machine.money + totalPrice + MySQL.update('UPDATE vending_machines SET money = ? WHERE id = ?', {machine.money, machineId}) + + -- Remove items from stash + local remainingToRemove = amount + for slot, item in pairs(stashItems) do + if item.name == itemName and item.amount > 0 then + local removeAmount = math.min(remainingToRemove, item.amount) + exports["tgiann-inventory"]:RemoveItemFromSecondaryInventory("stash", machine.stash, itemName, removeAmount, slot) + remainingToRemove = remainingToRemove - removeAmount + + if remainingToRemove <= 0 then break end end end - if not hasItem then - TriggerClientEvent('QBCore:Notify', src, 'Artikel nicht verfügbar!', 'error') + -- Show item box + TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[itemName], 'add', amount) + + TriggerClientEvent('QBCore:Notify', src, amount .. 'x ' .. (QBCore.Shared.Items[itemName] and QBCore.Shared.Items[itemName].label or itemName) .. ' gekauft für $' .. totalPrice .. '!', 'success') +end) + +-- Add manager to vending machine +RegisterNetEvent('vending:server:addManager', function(coords, targetId) + local src = source + local Player = QBCore.Functions.GetPlayer(src) + if not Player then return end + + local machineId = getMachineIdByCoords(coords) + if not machineId then return end + + local machine = vendingMachines[machineId] + + -- Only owner can add managers + if machine.owner ~= Player.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Nur der Besitzer kann Verwalter hinzufügen!', 'error') return end - -- Remove money from player - Player.Functions.RemoveMoney('cash', price) + -- Get target player + local Target = QBCore.Functions.GetPlayer(tonumber(targetId)) + if not Target then + TriggerClientEvent('QBCore:Notify', src, 'Spieler nicht gefunden!', 'error') + return + end - -- Add money to machine - machine.money = machine.money + price - MySQL.update('UPDATE vending_machines SET money = ? WHERE id = ?', {machine.money, machineId}) + -- Check if already a manager + if machine.managers then + for _, manager in pairs(machine.managers) do + if manager == Target.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Diese Person ist bereits ein Verwalter!', 'error') + return + end + end + else + machine.managers = {} + end - -- Remove item from stash and add to player - exports["tgiann-inventory"]:RemoveItemFromSecondaryInventory("stash", machine.stash, itemName, 1) - Player.Functions.AddItem(itemName, 1) - TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[itemName], 'add') + -- Add to managers + table.insert(machine.managers, Target.PlayerData.citizenid) + MySQL.update('UPDATE vending_machines SET managers = ? WHERE id = ?', {json.encode(machine.managers), machineId}) - TriggerClientEvent('QBCore:Notify', src, 'Artikel gekauft für $' .. price .. '!', 'success') + TriggerClientEvent('QBCore:Notify', src, Target.PlayerData.charinfo.firstname .. ' ' .. Target.PlayerData.charinfo.lastname .. ' als Verwalter hinzugefügt!', 'success') + TriggerClientEvent('QBCore:Notify', Target.PlayerData.source, 'Du wurdest als Verwalter für einen Verkaufsautomaten hinzugefügt!', 'success') +end) + +-- Remove manager from vending machine +RegisterNetEvent('vending:server:removeManager', function(coords, citizenid) + local src = source + local Player = QBCore.Functions.GetPlayer(src) + if not Player then return end + + local machineId = getMachineIdByCoords(coords) + if not machineId then return end + + local machine = vendingMachines[machineId] + + -- Only owner can remove managers + if machine.owner ~= Player.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Nur der Besitzer kann Verwalter entfernen!', 'error') + return + end + + -- Check if manager exists + local found = false + local newManagers = {} + + if machine.managers then + for _, manager in pairs(machine.managers) do + if manager ~= citizenid then + table.insert(newManagers, manager) + else + found = true + end + end + end + + if not found then + TriggerClientEvent('QBCore:Notify', src, 'Diese Person ist kein Verwalter!', 'error') + return + end + + -- Update managers + machine.managers = newManagers + MySQL.update('UPDATE vending_machines SET managers = ? WHERE id = ?', {json.encode(machine.managers), machineId}) + + TriggerClientEvent('QBCore:Notify', src, 'Verwalter entfernt!', 'success') + + -- Notify the removed manager if online + local players = QBCore.Functions.GetPlayers() + for _, playerId in ipairs(players) do + local targetPlayer = QBCore.Functions.GetPlayer(playerId) + if targetPlayer and targetPlayer.PlayerData.citizenid == citizenid then + TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Du wurdest als Verwalter eines Verkaufsautomaten entfernt!', 'error') + break + end + end +end) + +-- Get managers list +QBCore.Functions.CreateCallback('vending:server:getManagers', function(source, cb, coords) + local machineId = getMachineIdByCoords(coords) + if not machineId then + cb({}) + return + end + + local machine = vendingMachines[machineId] + local managersList = {} + + if machine.managers and #machine.managers > 0 then + for _, citizenid in pairs(machine.managers) do + -- Try to get online player info + local found = false + local players = QBCore.Functions.GetPlayers() + + for _, playerId in ipairs(players) do + local targetPlayer = QBCore.Functions.GetPlayer(playerId) + if targetPlayer and targetPlayer.PlayerData.citizenid == citizenid then + table.insert(managersList, { + citizenid = citizenid, + name = targetPlayer.PlayerData.charinfo.firstname .. ' ' .. targetPlayer.PlayerData.charinfo.lastname, + online = true + }) + found = true + break + end + end + + -- If not online, get from database + if not found then + local result = MySQL.Sync.fetchAll('SELECT charinfo FROM players WHERE citizenid = ?', {citizenid}) + if result and result[1] then + local charinfo = json.decode(result[1].charinfo) + table.insert(managersList, { + citizenid = citizenid, + name = charinfo.firstname .. ' ' .. charinfo.lastname, + online = false + }) + else + table.insert(managersList, { + citizenid = citizenid, + name = "Unbekannt", + online = false + }) + end + end + end + end + + cb(managersList) end) -- Start robbery @@ -260,6 +468,23 @@ RegisterNetEvent('vending:server:startRobbery', function(coords) end end + -- Alert owner and managers + for _, playerId in ipairs(QBCore.Functions.GetPlayers()) do + local targetPlayer = QBCore.Functions.GetPlayer(playerId) + if targetPlayer then + if targetPlayer.PlayerData.citizenid == machine.owner then + TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Dein Verkaufsautomat wird gerade aufgebrochen! Standort: ' .. streetName, 'error', 10000) + elseif machine.managers then + for _, manager in pairs(machine.managers) do + if targetPlayer.PlayerData.citizenid == manager then + TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Ein Verkaufsautomat, den du verwaltest, wird gerade aufgebrochen! Standort: ' .. streetName, 'error', 10000) + break + end + end + end + end + end + TriggerClientEvent('vending:client:startRobbery', src, coords) end) @@ -362,12 +587,55 @@ QBCore.Functions.CreateCallback('vending:server:isOwner', function(source, cb, c cb(machine.owner == Player.PlayerData.citizenid) end) +-- Check if player can manage machine +QBCore.Functions.CreateCallback('vending:server:canManage', function(source, cb, coords) + local Player = QBCore.Functions.GetPlayer(source) + if not Player then + cb(false) + return + end + + local machineId = getMachineIdByCoords(coords) + if not machineId then + cb(false) + return + end + + cb(canManageMachine(source, machineId)) +end) + -- Check if machine exists at coords QBCore.Functions.CreateCallback('vending:server:machineExists', function(source, cb, coords) local machineId = getMachineIdByCoords(coords) cb(machineId ~= nil) end) +-- Get online players for manager selection +QBCore.Functions.CreateCallback('vending:server:getOnlinePlayers', function(source, cb) + local src = source + local Player = QBCore.Functions.GetPlayer(src) + if not Player then + cb({}) + return + end + + local players = {} + local onlinePlayers = QBCore.Functions.GetPlayers() + + for _, playerId in ipairs(onlinePlayers) do + local targetPlayer = QBCore.Functions.GetPlayer(playerId) + if targetPlayer and targetPlayer.PlayerData.source ~= src then + table.insert(players, { + id = targetPlayer.PlayerData.source, + name = targetPlayer.PlayerData.charinfo.firstname .. ' ' .. targetPlayer.PlayerData.charinfo.lastname, + citizenid = targetPlayer.PlayerData.citizenid + }) + end + end + + cb(players) +end) + -- Debug command QBCore.Commands.Add('vendingdebug', 'Debug vending machines (Admin Only)', {}, false, function(source, args) local Player = QBCore.Functions.GetPlayer(source)