local QBCore = exports['qb-core']:GetCoreObject() local inZone = false local currentMachine = nil local PlayerData = {} local function SetupTarget() if not Config.UseQBTarget then return end -- Default 24/7 machines for modelHash, machineData in pairs(Config.DefaultMachines.Models) do exports['qb-target']:AddTargetModel(modelHash, { options = { { type = 'client', event = 'vendingmachines:client:openMenu', icon = 'fas fa-cash-register', label = 'Use Vending Machine', machineModel = modelHash, isPlayerOwned = false }, Config.EnableRobbery and { type = 'client', event = 'vendingmachines:client:startRobbery', icon = 'fas fa-lock', label = 'Rob Machine', item = Config.RobberyItem, machineModel = modelHash, isPlayerOwned = false } or nil }, distance = Config.TargetOptions.distance }) end -- Player owned machines will be added dynamically as they're loaded end local function RefreshPlayerMachines() local playerMachines = QBCore.Functions.TriggerRpc('vendingmachines:server:getPlayerMachines', PlayerData.citizenid) for _, machine in pairs(playerMachines) do exports['qb-target']:AddBoxZone('vending_' .. machine.id, json.decode(machine.location), 0.5, 0.5, { name = 'vending_' .. machine.id, heading = 0, debugPoly = false, minZ = json.decode(machine.location).z - 0.5, maxZ = json.decode(machine.location).z + 0.5 }, { options = { { type = 'client', event = 'vendingmachines:client:openMenu', icon = 'fas fa-cash-register', label = 'Use Vending Machine', machineId = machine.id, isPlayerOwned = true, machineModel = machine.model_hash }, Config.EnableRobbery and { type = 'client', event = 'vendingmachines:client:startRobbery', icon = 'fas fa-lock', label = 'Rob Machine', item = Config.RobberyItem, machineId = machine.id, isPlayerOwned = true } or nil, table.contains(Config.PlayerOwnedMachines.AllowedJobs, PlayerData.job.name) and { type = 'client', event = 'vendingmachines:client:restockMenu', icon = 'fas fa-boxes', label = 'Restock Machine', machineId = machine.id } or nil, table.contains(Config.PlayerOwnedMachines.AllowedJobs, PlayerData.job.name) and { type = 'client', event = 'vendingmachines:client:collectEarnings', icon = 'fas fa-money-bill-wave', label = 'Collect Earnings', machineId = machine.id } or nil }, distance = Config.TargetOptions.distance }) end end local function OpenVendingMenu(machineInfo) local menu = { header = 'Vending Machine', items = {} } if machineInfo.isPlayerOwned then menu.header = 'Player Vending Machine' menu.items[#menu.items + 1] = { title = 'Stock: ' .. (currentMachine and currentMachine.stock or '?'), description = 'Available items for purchase', disabled = true } else menu.header = '24/7 Vending Machine' end local items = Config.DefaultMachines.Models[machineInfo.machineModel].items for _, item in pairs(items) do menu.items[#menu.items + 1] = { title = item.label, description = 'Price: $' .. item.price, onSelect = function() local input = lib.inputDialog('Purchase Amount', { { type = 'number', label = 'Amount', min = 1, max = 10, default = 1 } }) if input and input[1] then TriggerServerEvent('vendingmachines:server:processPurchase', machineInfo.isPlayerOwned, machineInfo.isPlayerOwned and machineInfo.machineId or machineInfo.machineModel, item.name, input[1]) end end } end lib.registerContext(menu) lib.showContext('vending_menu') end local function StartRobbery(machineInfo) QBCore.Functions.TriggerCallback('vendingmachines:server:hasItem', function(hasItem) if hasItem then local success = lib.skillCheck({ 'easy', 'easy', { areaSize = 60, speedMultiplier = 1 } }, { 'w', 'a', 's', 'd' }) if success then QBCore.Functions.Progressbar('robbing_machine', 'Robbing vending machine...', Config.RobberyTime * 1000, false, true, { disableMovement = true, disableCarMovement = true, disableMouse = false, disableCombat = true, }, { animDict = 'mini@safe_cracking', anim = 'idle_base', flags = 16, }, {}, {}, function() TriggerServerEvent('vendingmachines:server:completeRobbery', machineInfo.isPlayerOwned, machineInfo.isPlayerOwned and machineInfo.machineId or nil) end, function() TriggerServerEvent('vendingmachines:server:robberyFailed', machineInfo.isPlayerOwned, machineInfo.isPlayerOwned and machineInfo.machineId or nil) end) else QBCore.Functions.Notify('Robbery failed', 'error') end else QBCore.Functions.Notify('You don\'t have the required item', 'error') end end, Config.RobberyItem) end -- Events RegisterNetEvent('vendingmachines:client:openMenu', function(data) OpenVendingMenu(data) end) RegisterNetEvent('vendingmachines:client:registerMachine', function() local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local obj = GetClosestObjectOfType(coords, 3.0, GetHashKey('prop_vend_soda_01'), false, false, false) if DoesEntityExist(obj) then local modelHash = GetEntityModel(obj) local validModel = false for _, model in pairs(Config.PlayerOwnedMachines.Models) do if model == modelHash then validModel = true break end end if not validModel then QBCore.Functions.Notify('This vending machine cannot be owned', 'error') return end local objCoords = GetEntityCoords(obj) TriggerServerEvent('vendingmachines:server:registerMachine', modelHash, objCoords) else QBCore.Functions.Notify('No vending machine nearby', 'error') end end) RegisterNetEvent('vendingmachines:client:startRobbery', function(data) StartRobbery(data) end) RegisterNetEvent('vendingmachines:client:refreshPlayerMachines', function() RefreshPlayerMachines() end) RegisterNetEvent('vendingmachines:client:restockMenu', function(data) local input = lib.inputDialog('Restock Amount', { { type = 'number', label = 'Amount', min = 1, default = 1 } }) if input and input[1] then TriggerServerEvent('vendingmachines:server:restockMachine', data.machineId) end end) RegisterNetEvent('vendingmachines:client:collectEarnings', function(data) TriggerServerEvent('vendingmachines:server:collectEarnings', data.machineId) end) -- Initialization AddEventHandler('QBCore:Client:OnPlayerLoaded', function() PlayerData = QBCore.Functions.GetPlayerData() SetupTarget() RefreshPlayerMachines() end) AddEventHandler('QBCore:Client:OnJobUpdate', function(job) PlayerData.job = job end) AddEventHandler('onResourceStart', function(resource) if GetCurrentResourceName() == resource then PlayerData = QBCore.Functions.GetPlayerData() SetupTarget() Citizen.SetTimeout(5000, function() RefreshPlayerMachines() end) end end)