local QBCore = exports['qb-core']:GetCoreObject() -- Add targets to all vending machine props CreateThread(function() Wait(2000) -- Wait for everything to load refreshTargets() end) -- Refresh all targets function refreshTargets() -- Remove old targets first for i = 1, #Config.VendingProps do exports['qb-target']:RemoveTargetModel(Config.VendingProps[i]) end -- Add new targets exports['qb-target']:AddTargetModel(Config.VendingProps, { options = { { type = "client", event = "vending:client:buyMachine", icon = "fas fa-dollar-sign", label = "Automaten kaufen ($" .. Config.VendingMachinePrice .. ")", canInteract = function(entity) return not isMachineRegistered(entity) end }, { type = "client", event = "vending:client:openBuyMenu", icon = "fas fa-shopping-cart", label = "Kaufen", canInteract = function(entity) return isMachineRegistered(entity) end }, { type = "client", event = "vending:client:openOwnerMenu", icon = "fas fa-cog", label = "Verwalten", canInteract = function(entity) return isMachineRegistered(entity) and isOwner(entity) end }, { type = "client", event = "vending:client:robberyMenu", icon = "fas fa-mask", label = "Aufbrechen", canInteract = function(entity) return isMachineRegistered(entity) and hasRobberyItem() and not isOwner(entity) end } }, distance = 2.0 }) end -- Check if machine is registered function isMachineRegistered(entity) local coords = GetEntityCoords(entity) local registered = false QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) registered = exists end, coords) -- Wait for callback (not ideal but necessary for sync check) while registered == false do Wait(10) end return registered end -- Check if player is owner function isOwner(entity) local coords = GetEntityCoords(entity) local owner = false QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner) owner = isOwner end, coords) -- Wait for callback while owner == false do Wait(10) end return owner end -- Check if player has robbery item function hasRobberyItem() local PlayerData = QBCore.Functions.GetPlayerData() for k, v in pairs(PlayerData.items) do if v.name == Config.RobberyItem and v.amount > 0 then return true end end return false end -- Buy vending machine RegisterNetEvent('vending:client:buyMachine', function(data) local entity = data.entity local coords = GetEntityCoords(entity) local model = GetEntityModel(entity) local prop = nil -- Find prop name for i = 1, #Config.VendingProps do if GetHashKey(Config.VendingProps[i]) == model then prop = Config.VendingProps[i] break end end if not prop then return end lib.registerContext({ id = 'vending_buy_confirm', title = 'Verkaufsautomat kaufen', options = { { title = 'Bestätigen', description = 'Automaten für $' .. Config.VendingMachinePrice .. ' kaufen', icon = 'fas fa-check', onSelect = function() TriggerServerEvent('vending:server:registerMachine', coords, prop) end }, { title = 'Abbrechen', description = 'Kauf abbrechen', icon = 'fas fa-times' } } }) lib.showContext('vending_buy_confirm') end) -- Open buy menu RegisterNetEvent('vending:client:openBuyMenu', function(data) local entity = data.entity local coords = GetEntityCoords(entity) QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) if #items == 0 then QBCore.Functions.Notify('Dieser Automat ist leer!', 'error') return end local options = {} for i = 1, #items do local item = items[i] if item.amount > 0 then table.insert(options, { title = QBCore.Shared.Items[item.name].label, description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount, icon = 'nui://qb-inventory/html/images/' .. item.name .. '.png', onSelect = function() TriggerServerEvent('vending:server:buyItem', coords, item.name) end }) end end lib.registerContext({ id = 'vending_buy_menu', title = 'Verkaufsautomat', options = options }) lib.showContext('vending_buy_menu') end, coords) end) -- Open owner menu RegisterNetEvent('vending:client:openOwnerMenu', function(data) local entity = data.entity local coords = GetEntityCoords(entity) 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 = 'Einnahmen auszahlen lassen', icon = 'fas fa-money-bill', onSelect = function() openWithdrawMenu(coords) end }, { title = 'Statistiken', description = 'Verkaufsstatistiken anzeigen', icon = 'fas fa-chart-bar', onSelect = function() TriggerServerEvent('vending:server:openManagement', coords) end } } }) lib.showContext('vending_owner_menu') end) -- Open price menu function openPriceMenu(coords) QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) if #items == 0 then QBCore.Functions.Notify('Keine Items im Automaten!', 'error') return end local options = {} for i = 1, #items do local item = items[i] table.insert(options, { title = QBCore.Shared.Items[item.name].label, description = 'Aktueller Preis: $' .. item.price, icon = 'nui://qb-inventory/html/images/' .. item.name .. '.png', onSelect = function() setPriceForItem(coords, item.name, item.price) end }) end lib.registerContext({ id = 'vending_price_menu', title = 'Preise festlegen', options = options }) lib.showContext('vending_price_menu') end, coords) end -- Set price for specific item function setPriceForItem(coords, itemName, currentPrice) local input = lib.inputDialog('Preis festlegen', { { type = 'number', label = 'Neuer Preis für ' .. (QBCore.Shared.Items[itemName] and QBCore.Shared.Items[itemName].label or itemName), description = 'Aktueller Preis: $' .. currentPrice, required = true, min = 1, max = 9999, default = currentPrice } }) if input and input[1] then TriggerServerEvent('vending:server:setItemPrice', coords, itemName, tonumber(input[1])) end end -- Open withdraw menu function openWithdrawMenu(coords) QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine) if not machine then return end local input = lib.inputDialog('Geld abheben', { { type = 'number', label = 'Betrag (Verfügbar: $' .. machine.money .. ')', description = 'Wie viel möchtest du abheben?', required = true, min = 1, max = machine.money } }) if input and input[1] then TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1])) end end, coords) end -- Robbery menu RegisterNetEvent('vending:client:robberyMenu', function(data) local entity = data.entity local coords = GetEntityCoords(entity) lib.registerContext({ id = 'vending_robbery_menu', title = 'Verkaufsautomat aufbrechen', options = { { title = 'Aufbrechen', description = 'Versuche den Automaten aufzubrechen', icon = 'fas fa-mask', onSelect = function() TriggerServerEvent('vending:server:startRobbery', coords) end } } }) lib.showContext('vending_robbery_menu') end) -- Start robbery minigame RegisterNetEvent('vending:client:startRobbery', function(coords) local success = false -- Progress bar if lib.progressBar({ duration = 5000, label = 'Automaten aufbrechen...', useWhileDead = false, canCancel = true, disable = { car = true, move = true, combat = true }, anim = { dict = 'missheist_jewel', clip = 'smash_case' } }) then -- Lockpicking minigame local result = lib.skillCheck({'easy', 'easy', 'medium', 'medium', 'hard'}, {'w', 'a', 's', 'd'}) if result then success = true end TriggerServerEvent('vending:server:completeRobbery', coords, success) end end) -- Police alert RegisterNetEvent('vending:client:policeAlert', function(coords, streetName) QBCore.Functions.Notify('Verkaufsautomat wird aufgebrochen: ' .. streetName, 'error', 10000) -- Add blip local blip = AddBlipForCoord(coords.x, coords.y, coords.z) SetBlipSprite(blip, 161) SetBlipScale(blip, 1.0) SetBlipColour(blip, 1) SetBlipAsShortRange(blip, false) BeginTextCommandSetBlipName("STRING") AddTextComponentString("Verkaufsautomat Aufbruch") EndTextCommandSetBlipName(blip) -- Remove blip after 5 minutes SetTimeout(300000, function() RemoveBlip(blip) end) end) -- Management menu RegisterNetEvent('vending:client:openManagement', function(machine) lib.registerContext({ id = 'vending_management', title = 'Verkaufsautomat #' .. machine.id, options = { { title = 'Guthaben: $' .. machine.money, description = 'Aktuelles Guthaben im Automaten', icon = 'fas fa-dollar-sign' }, { title = 'Inventar verwalten', description = 'Items hinzufügen oder entfernen', icon = 'fas fa-box', onSelect = function() TriggerServerEvent('vending:server:openStash', machine.coords) end }, { title = 'Preise verwalten', description = 'Verkaufspreise anpassen', icon = 'fas fa-tags', onSelect = function() openPriceMenu(machine.coords) end } } }) lib.showContext('vending_management') end) -- Refresh targets when called from server RegisterNetEvent('vending:client:refreshTargets', function() refreshTargets() end)