diff --git a/resources/[inventory]/nordi_vending/client.lua b/resources/[inventory]/nordi_vending/client.lua index aecc4eea5..8bcdb8007 100644 --- a/resources/[inventory]/nordi_vending/client.lua +++ b/resources/[inventory]/nordi_vending/client.lua @@ -19,12 +19,8 @@ function DrawText3D(x, y, z, text) ClearDrawOrigin() end --- Function to check if machine is registered (with caching) +-- Function to check if machine is registered function isRegisteredMachine(entity) - if currentMachineData and currentMachineData.entity == entity then - return currentMachineData.isRegistered - end - local coords = GetEntityCoords(entity) local isRegistered = false @@ -39,19 +35,11 @@ function isRegisteredMachine(entity) timeout = timeout + 1 end - if not currentMachineData then currentMachineData = {} end - currentMachineData.entity = entity - currentMachineData.isRegistered = isRegistered - return isRegistered end --- Check if player can manage machine (with caching) +-- Check if player can manage machine function canManageMachine(entity) - if currentMachineData and currentMachineData.entity == entity and currentMachineData.canManage ~= nil then - return currentMachineData.canManage - end - local coords = GetEntityCoords(entity) local canManage = false @@ -66,10 +54,6 @@ function canManageMachine(entity) timeout = timeout + 1 end - if not currentMachineData then currentMachineData = {} end - currentMachineData.entity = entity - currentMachineData.canManage = canManage - return canManage end @@ -157,23 +141,12 @@ CreateThread(function() if not foundMachine then nearbyMachine = nil - currentMachineData = nil end Wait(wait) end end) --- Reset machine data when moving away -CreateThread(function() - while true do - Wait(5000) - if not nearbyMachine then - currentMachineData = nil - end - end -end) - -- Buy vending machine RegisterNetEvent('vending:client:buyMachine', function(data) local entity = data.entity @@ -191,32 +164,27 @@ RegisterNetEvent('vending:client:buyMachine', function(data) if not prop then return end - -- Display confirmation text - local startTime = GetGameTimer() - local textShown = true + 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' + } + } + }) - CreateThread(function() - while textShown do - local objCoords = GetEntityCoords(entity) - DrawText3D(objCoords.x, objCoords.y, objCoords.z + 1.0, "Automaten für $" .. Config.VendingMachinePrice .. " kaufen?\n[Y] Ja | [N] Nein") - Wait(0) - end - end) - - -- Wait for key press - while GetGameTimer() - startTime < 10000 and textShown do - if IsControlJustPressed(0, 246) then -- Y key - textShown = false - TriggerServerEvent('vending:server:registerMachine', coords, prop) - break - elseif IsControlJustPressed(0, 249) then -- N key - textShown = false - break - end - Wait(0) - end - - textShown = false + lib.showContext('vending_buy_confirm') end) -- Open buy menu with quantity selection @@ -230,19 +198,19 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data) return end - -- Simple item selection menu local options = {} - local selectedItem = nil for i = 1, #items do local item = items[i] if item.amount > 0 then local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name table.insert(options, { - name = item.name, - label = itemLabel, - price = item.price, - amount = item.amount + title = itemLabel, + description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount, + icon = 'fas fa-shopping-cart', + onSelect = function() + openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel) + end }) end end @@ -252,84 +220,40 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data) return end - -- Display item selection - local currentIndex = 1 - local menuActive = true + lib.registerContext({ + id = 'vending_buy_menu', + title = 'Verkaufsautomat', + options = options + }) - CreateThread(function() - while menuActive do - local objCoords = GetEntityCoords(entity) - local item = options[currentIndex] - - DrawText3D(objCoords.x, objCoords.y, objCoords.z + 1.0, - "Item: " .. item.label .. "\nPreis: $" .. item.price .. " | Verfügbar: " .. item.amount .. - "\n[←][→] Navigieren | [ENTER] Auswählen | [ESC] Abbrechen") - - Wait(0) - end - end) - - -- Handle navigation - while menuActive do - if IsControlJustPressed(0, 174) then -- Left arrow - currentIndex = currentIndex - 1 - if currentIndex < 1 then currentIndex = #options end - Wait(200) - elseif IsControlJustPressed(0, 175) then -- Right arrow - currentIndex = currentIndex + 1 - if currentIndex > #options then currentIndex = 1 end - Wait(200) - elseif IsControlJustPressed(0, 18) then -- Enter key - selectedItem = options[currentIndex] - menuActive = false - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - return - end - Wait(0) - end - - -- If item selected, ask for quantity - if selectedItem then - Wait(100) -- Small delay - - -- Display quantity selection - local quantity = 1 - local quantityMenu = true - - CreateThread(function() - while quantityMenu do - local objCoords = GetEntityCoords(entity) - DrawText3D(objCoords.x, objCoords.y, objCoords.z + 1.0, - "Item: " .. selectedItem.label .. " | Preis: $" .. (selectedItem.price * quantity) .. - "\nMenge: " .. quantity .. "/" .. selectedItem.amount .. - "\n[←][→] Ändern | [ENTER] Kaufen | [ESC] Abbrechen") - Wait(0) - end - end) - - -- Handle quantity selection - while quantityMenu do - if IsControlJustPressed(0, 174) then -- Left arrow - quantity = quantity - 1 - if quantity < 1 then quantity = 1 end - Wait(100) - elseif IsControlJustPressed(0, 175) then -- Right arrow - quantity = quantity + 1 - if quantity > selectedItem.amount then quantity = selectedItem.amount end - Wait(100) - elseif IsControlJustPressed(0, 18) then -- Enter key - quantityMenu = false - TriggerServerEvent('vending:server:buyItem', coords, selectedItem.name, quantity) - elseif IsControlJustPressed(0, 177) then -- Escape key - quantityMenu = false - end - Wait(0) - end - end + lib.showContext('vending_buy_menu') 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 @@ -341,104 +265,86 @@ RegisterNetEvent('vending:client:openOwnerMenu', function(data) return end - -- Display owner menu options local options = { - {label = "Inventar verwalten", action = "inventory"}, - {label = "Preise festlegen", action = "prices"}, - {label = "Geld abheben ($" .. machine.money .. ")", action = "withdraw"}, - {label = "Statistiken", action = "stats"} + { + 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, {label = "Verwalter", action = "managers"}) - table.insert(options, {label = "Automaten verkaufen", action = "sell"}) - end - - -- Display menu - local currentIndex = 1 - local menuActive = true - - CreateThread(function() - while menuActive do - local objCoords = GetEntityCoords(entity) - local menuText = "Verkaufsautomat Verwaltung\n" - - for i, option in ipairs(options) do - if i == currentIndex then - menuText = menuText .. "→ " .. option.label .. "\n" - else - menuText = menuText .. option.label .. "\n" - end - end - - menuText = menuText .. "\n[↑][↓] Navigieren | [ENTER] Auswählen | [ESC] Abbrechen" - - DrawText3D(objCoords.x, objCoords.y, objCoords.z + 1.0, menuText) - Wait(0) - end - end) - - -- Handle navigation - while menuActive do - if IsControlJustPressed(0, 172) then -- Up arrow - currentIndex = currentIndex - 1 - if currentIndex < 1 then currentIndex = #options end - Wait(200) - elseif IsControlJustPressed(0, 173) then -- Down arrow - currentIndex = currentIndex + 1 - if currentIndex > #options then currentIndex = 1 end - Wait(200) - elseif IsControlJustPressed(0, 18) then -- Enter key - local selectedOption = options[currentIndex].action - menuActive = false - - -- Handle selected option - if selectedOption == "inventory" then - TriggerServerEvent('vending:server:openStash', coords) - elseif selectedOption == "prices" then - openPriceMenu(coords) - elseif selectedOption == "withdraw" then - openWithdrawMenu(coords, machine.money) - elseif selectedOption == "stats" then - openStatsMenu(machine) - elseif selectedOption == "managers" then + table.insert(options, { + title = 'Verwalter', + description = 'Verwalter hinzufügen/entfernen', + icon = 'fas fa-users-cog', + onSelect = function() openManagersMenu(coords) - elseif selectedOption == "sell" then + end + }) + + -- Add sell option only for owner + table.insert(options, { + title = 'Automaten verkaufen', + description = 'Verkaufe den Automaten für ' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. '$', + icon = 'fas fa-dollar-sign', + onSelect = function() sellVendingMachine(coords, machine.id) end - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - end - Wait(0) + }) end + + lib.registerContext({ + id = 'vending_owner_menu', + title = 'Verkaufsautomat Verwaltung', + options = options + }) + + lib.showContext('vending_owner_menu') end, coords) end) -- Function to sell the vending machine function sellVendingMachine(coords, machineId) - -- Display confirmation text - local confirmActive = true + local input = lib.inputDialog('Automaten verkaufen', { + { + type = 'checkbox', + label = 'Bestätigen', + description = 'Du erhältst ' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. '$ zurück. Diese Aktion kann nicht rückgängig gemacht werden!', + required = true + } + }) - CreateThread(function() - while confirmActive do - DrawText3D(coords.x, coords.y, coords.z + 1.0, - "Automaten verkaufen für $" .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. "?\n" .. - "Diese Aktion kann nicht rückgängig gemacht werden!\n" .. - "[Y] Bestätigen | [N] Abbrechen") - Wait(0) - end - end) - - -- Wait for confirmation - while confirmActive do - if IsControlJustPressed(0, 246) then -- Y key - confirmActive = false - TriggerServerEvent('vending:server:sellMachine', coords, machineId) - elseif IsControlJustPressed(0, 249) then -- N key - confirmActive = false - end - Wait(0) + if input and input[1] then + TriggerServerEvent('vending:server:sellMachine', coords, machineId) end end @@ -450,122 +356,47 @@ function openPriceMenu(coords) return end - -- Create options list local options = {} for i = 1, #items do local item = items[i] local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name table.insert(options, { - name = item.name, - label = itemLabel, - price = item.price + title = itemLabel, + description = 'Aktueller Preis: $' .. item.price, + icon = 'fas fa-tag', + onSelect = function() + setPriceForItem(coords, item.name, itemLabel) + end }) end - -- Display menu - local currentIndex = 1 - local menuActive = true + lib.registerContext({ + id = 'vending_price_menu', + title = 'Preise festlegen', + menu = 'vending_owner_menu', + options = options + }) - CreateThread(function() - while menuActive do - local menuText = "Preise festlegen\n" - - for i, option in ipairs(options) do - if i == currentIndex then - menuText = menuText .. "→ " .. option.label .. " - $" .. option.price .. "\n" - else - menuText = menuText .. option.label .. " - $" .. option.price .. "\n" - end - end - - menuText = menuText .. "\n[↑][↓] Navigieren | [ENTER] Preis ändern | [ESC] Zurück" - - DrawText3D(coords.x, coords.y, coords.z + 1.0, menuText) - Wait(0) - end - end) - - -- Handle navigation - while menuActive do - if IsControlJustPressed(0, 172) then -- Up arrow - currentIndex = currentIndex - 1 - if currentIndex < 1 then currentIndex = #options end - Wait(200) - elseif IsControlJustPressed(0, 173) then -- Down arrow - currentIndex = currentIndex + 1 - if currentIndex > #options then currentIndex = 1 end - Wait(200) - elseif IsControlJustPressed(0, 18) then -- Enter key - local selectedItem = options[currentIndex] - menuActive = false - setPriceForItem(coords, selectedItem.name, selectedItem.label) - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - end - Wait(0) - end + lib.showContext('vending_price_menu') end, coords) end -- Set price for specific item function setPriceForItem(coords, itemName, itemLabel) - -- Display price input - local price = 0 - local inputActive = true - local inputText = "" + local input = lib.inputDialog('Preis festlegen', { + { + type = 'number', + label = 'Preis für ' .. itemLabel, + description = 'Neuen Verkaufspreis eingeben', + required = true, + min = 1, + max = 10000 + } + }) - CreateThread(function() - while inputActive do - DrawText3D(coords.x, coords.y, coords.z + 1.0, - "Preis für " .. itemLabel .. " festlegen\n" .. - "Aktueller Wert: $" .. inputText .. "_\n" .. - "Verwende Nummerntasten | [ENTER] Bestätigen | [ESC] Abbrechen") - Wait(0) - end - end) - - -- Handle input - while inputActive do - -- Number keys (0-9) - for i = 48, 57 do - if IsControlJustPressed(0, i) then - inputText = inputText .. (i - 48) - Wait(200) - end - end - - -- Numpad keys (0-9) - for i = 96, 105 do - if IsControlJustPressed(0, i) then - inputText = inputText .. (i - 96) - Wait(200) - end - end - - -- Backspace - if IsControlJustPressed(0, 194) and string.len(inputText) > 0 then - inputText = string.sub(inputText, 1, string.len(inputText) - 1) - Wait(200) - end - - -- Enter - if IsControlJustPressed(0, 18) then - inputActive = false - price = tonumber(inputText) or 0 - if price > 0 then - TriggerServerEvent('vending:server:setItemPrice', coords, itemName, price) - else - QBCore.Functions.Notify('Ungültiger Preis!', 'error') - end - end - - -- Escape - if IsControlJustPressed(0, 177) then - inputActive = false - end - - Wait(0) + if input and input[1] then + TriggerServerEvent('vending:server:setItemPrice', coords, itemName, tonumber(input[1])) end end @@ -576,248 +407,147 @@ function openWithdrawMenu(coords, availableMoney) return end - -- Display withdraw input - local inputActive = true - local inputText = "" + local input = lib.inputDialog('Geld abheben', { + { + type = 'number', + label = 'Betrag (Verfügbar: $' .. availableMoney .. ')', + description = 'Wie viel möchtest du abheben?', + required = true, + min = 1, + max = availableMoney + } + }) - CreateThread(function() - while inputActive do - DrawText3D(coords.x, coords.y, coords.z + 1.0, - "Geld abheben (Verfügbar: $" .. availableMoney .. ")\n" .. - "Betrag: $" .. inputText .. "_\n" .. - "Verwende Nummerntasten | [ENTER] Bestätigen | [ESC] Abbrechen") - Wait(0) - end - end) - - -- Handle input - while inputActive do - -- Number keys (0-9) - for i = 48, 57 do - if IsControlJustPressed(0, i) then - inputText = inputText .. (i - 48) - Wait(200) - end - end - - -- Numpad keys (0-9) - for i = 96, 105 do - if IsControlJustPressed(0, i) then - inputText = inputText .. (i - 96) - Wait(200) - end - end - - -- Backspace - if IsControlJustPressed(0, 194) and string.len(inputText) > 0 then - inputText = string.sub(inputText, 1, string.len(inputText) - 1) - Wait(200) - end - - -- Enter - if IsControlJustPressed(0, 18) then - inputActive = false - local amount = tonumber(inputText) or 0 - if amount > 0 and amount <= availableMoney then - TriggerServerEvent('vending:server:withdrawMoney', coords, amount) - else - QBCore.Functions.Notify('Ungültiger Betrag!', 'error') - end - end - - -- Escape - if IsControlJustPressed(0, 177) then - inputActive = false - end - - Wait(0) + if input and input[1] then + TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1])) end end -- Open stats menu function openStatsMenu(machine) - -- Display stats - local menuActive = true + lib.registerContext({ + id = 'vending_stats_menu', + title = 'Verkaufsstatistiken', + menu = 'vending_owner_menu', + options = { + { + title = 'Gesamteinnahmen', + description = '$' .. machine.money, + icon = 'fas fa-dollar-sign' + }, + { + title = 'Automat ID', + description = '#' .. machine.id, + icon = 'fas fa-hashtag' + }, + { + title = 'Standort', + description = 'X: ' .. math.floor(machine.coords.x) .. ' Y: ' .. math.floor(machine.coords.y), + icon = 'fas fa-map-marker-alt' + } + } + }) - CreateThread(function() - while menuActive do - DrawText3D(machine.coords.x, machine.coords.y, machine.coords.z + 1.0, - "Verkaufsstatistiken\n" .. - "Gesamteinnahmen: $" .. machine.money .. "\n" .. - "Automat ID: #" .. machine.id .. "\n" .. - "Standort: X:" .. math.floor(machine.coords.x) .. " Y:" .. math.floor(machine.coords.y) .. "\n" .. - "[ESC] Zurück") - Wait(0) - end - end) - - -- Wait for escape key - while menuActive do - if IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - end - Wait(0) - end + lib.showContext('vending_stats_menu') end -- Open managers menu function openManagersMenu(coords) -- Get current managers QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers) - -- Create options list local options = { - {label = "Verwalter hinzufügen", action = "add"} + { + title = 'Verwalter hinzufügen', + description = 'Neuen Verwalter hinzufügen', + icon = 'fas fa-user-plus', + onSelect = function() + openAddManagerMenu(coords) + end + } } - -- Add existing managers + -- Add existing managers with remove option if #managers > 0 then for i = 1, #managers do local manager = managers[i] table.insert(options, { - label = manager.name .. (manager.online and " (Online)" or " (Offline)"), - citizenid = manager.citizenid, - action = "manage" + 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, {label = "Keine Verwalter", action = "none"}) + table.insert(options, { + title = 'Keine Verwalter', + description = 'Es sind keine Verwalter vorhanden', + icon = 'fas fa-info-circle', + disabled = true + }) end - -- Display menu - local currentIndex = 1 - local menuActive = true + lib.registerContext({ + id = 'managers_menu', + title = 'Verwalter verwalten', + menu = 'vending_owner_menu', + options = options + }) - CreateThread(function() - while menuActive do - local menuText = "Verwalter verwalten\n" - - for i, option in ipairs(options) do - if i == currentIndex then - menuText = menuText .. "→ " .. option.label .. "\n" - else - menuText = menuText .. option.label .. "\n" - end - end - - menuText = menuText .. "\n[↑][↓] Navigieren | [ENTER] Auswählen | [ESC] Zurück" - - DrawText3D(coords.x, coords.y, coords.z + 1.0, menuText) - Wait(0) - end - end) - - -- Handle navigation - while menuActive do - if IsControlJustPressed(0, 172) then -- Up arrow - currentIndex = currentIndex - 1 - if currentIndex < 1 then currentIndex = #options end - Wait(200) - elseif IsControlJustPressed(0, 173) then -- Down arrow - currentIndex = currentIndex + 1 - if currentIndex > #options then currentIndex = 1 end - Wait(200) - elseif IsControlJustPressed(0, 18) then -- Enter key - local selectedOption = options[currentIndex] - - if selectedOption.action == "add" then - menuActive = false - openAddManagerMenu(coords) - elseif selectedOption.action == "manage" then - menuActive = false - openManagerOptionsMenu(coords, selectedOption.citizenid) - end - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - end - Wait(0) - end + lib.showContext('managers_menu') end, coords) end --- Open manager options menu -function openManagerOptionsMenu(coords, citizenid) - -- Display options - local menuActive = true - - CreateThread(function() - while menuActive do - DrawText3D(coords.x, coords.y, coords.z + 1.0, - "Verwalter Optionen\n" .. - "[E] Entfernen\n" .. - "[ESC] Zurück") - Wait(0) - end - end) - - -- Handle input - while menuActive do - if IsControlJustPressed(0, 38) then -- E key - menuActive = false - TriggerServerEvent('vending:server:removeManager', coords, citizenid) - Wait(500) - openManagersMenu(coords) -- Refresh the menu - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - openManagersMenu(coords) -- Go back to managers menu - end - Wait(0) - end -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') - openManagersMenu(coords) -- Go back to managers menu return end - -- Display player selection - local currentIndex = 1 - local menuActive = true + local options = {} - CreateThread(function() - while menuActive do - local menuText = "Verwalter hinzufügen\n" - - for i, player in ipairs(players) do - if i == currentIndex then - menuText = menuText .. "→ " .. player.name .. " (ID: " .. player.id .. ")\n" - else - menuText = menuText .. player.name .. " (ID: " .. player.id .. ")\n" - end + 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 - - menuText = menuText .. "\n[↑][↓] Navigieren | [ENTER] Auswählen | [ESC] Zurück" - - DrawText3D(coords.x, coords.y, coords.z + 1.0, menuText) - Wait(0) - end - end) - - -- Handle navigation - while menuActive do - if IsControlJustPressed(0, 172) then -- Up arrow - currentIndex = currentIndex - 1 - if currentIndex < 1 then currentIndex = #players end - Wait(200) - elseif IsControlJustPressed(0, 173) then -- Down arrow - currentIndex = currentIndex + 1 - if currentIndex > #players then currentIndex = 1 end - Wait(200) - elseif IsControlJustPressed(0, 18) then -- Enter key - local selectedPlayer = players[currentIndex] - menuActive = false - TriggerServerEvent('vending:server:addManager', coords, selectedPlayer.id) - Wait(500) - openManagersMenu(coords) -- Refresh the menu - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - openManagersMenu(coords) -- Go back to managers menu - end - Wait(0) + }) end + + lib.registerContext({ + id = 'add_manager_menu', + title = 'Verwalter hinzufügen', + menu = 'managers_menu', + options = options + }) + + lib.showContext('add_manager_menu') end) end @@ -826,31 +556,27 @@ RegisterNetEvent('vending:client:startRobbery', function(data) local entity = data.entity local coords = GetEntityCoords(entity) - -- Display robbery confirmation - local menuActive = true + lib.registerContext({ + id = 'vending_robbery_confirm', + title = 'Verkaufsautomat aufbrechen', + options = { + { + title = 'Aufbrechen', + description = 'Versuche den Automaten aufzubrechen', + icon = 'fas fa-mask', + onSelect = function() + TriggerServerEvent('vending:server:startRobbery', coords) + end + }, + { + title = 'Abbrechen', + description = 'Aufbruch abbrechen', + icon = 'fas fa-times' + } + } + }) - CreateThread(function() - while menuActive do - DrawText3D(coords.x, coords.y, coords.z + 1.0, - "Verkaufsautomat aufbrechen\n" .. - "[E] Aufbrechen\n" .. - "[ESC] Abbrechen") - Wait(0) - end - end) - - -- Handle input - while menuActive do - if IsControlJustPressed(0, 38) then -- E key - menuActive = false - TriggerServerEvent('vending:server:startRobbery', coords) - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - end - Wait(0) - end + lib.showContext('vending_robbery_confirm') end) -- Start robbery animation and progress @@ -866,49 +592,38 @@ RegisterNetEvent('vending:client:startRobbery', function(coords) TaskPlayAnim(playerPed, 'anim@heists@fleeca_bank@drilling', 'drill_straight_idle', 8.0, -8.0, -1, 1, 0, false, false, false) - -- Progress bar (native implementation) - local startTime = GetGameTimer() - local endTime = startTime + robberyTime - local cancelled = false - - -- Display progress bar - CreateThread(function() - while GetGameTimer() < endTime and not cancelled do - local timeLeft = endTime - GetGameTimer() - local progress = 1.0 - (timeLeft / robberyTime) - - DrawRect(0.5, 0.95, 0.2, 0.03, 0, 0, 0, 180) - DrawRect(0.5 - ((1.0 - progress) * 0.1), 0.95, 0.2 * progress, 0.03, 255, 0, 0, 180) - - SetTextScale(0.35, 0.35) - SetTextFont(4) - SetTextProportional(1) - SetTextColour(255, 255, 255, 215) - SetTextEntry("STRING") - SetTextCentre(1) - AddTextComponentString("Automat aufbrechen... " .. math.floor(progress * 100) .. "%") - DrawText(0.5, 0.94) - - -- Check for cancel - if IsControlJustPressed(0, 177) then -- Escape key - cancelled = true - end - - Wait(0) - end - end) - - -- Wait for completion - while GetGameTimer() < endTime and not cancelled do - Wait(100) + -- Progress bar + if lib.progressBar then + local success = lib.progressBar({ + duration = robberyTime, + label = 'Automat aufbrechen...', + useWhileDead = false, + canCancel = true, + disable = { + car = true, + move = true, + combat = true + } + }) + + ClearPedTasks(playerPed) + TriggerServerEvent('vending:server:completeRobbery', coords, success) + else + -- Fallback without progress bar + Wait(robberyTime) + ClearPedTasks(playerPed) + TriggerServerEvent('vending:server:completeRobbery', coords, true) end - - ClearPedTasks(playerPed) - TriggerServerEvent('vending:server:completeRobbery', coords, not cancelled) end) -- Police alert RegisterNetEvent('vending:client:policeAlert', function(coords, streetName) + local alert = { + title = "Verkaufsautomat Aufbruch", + coords = coords, + description = "Ein Verkaufsautomat wird aufgebrochen in " .. streetName + } + -- Add blip local blip = AddBlipForCoord(coords.x, coords.y, coords.z) SetBlipSprite(blip, 161) @@ -929,58 +644,30 @@ end) -- Management menu (alternative opening method) RegisterNetEvent('vending:client:openManagement', function(machine) - -- Display management menu - local options = { - {label = "Inventar öffnen", action = "inventory"}, - {label = "Geld abheben ($" .. machine.money .. ")", action = "withdraw"} - } - - local currentIndex = 1 - local menuActive = true - - CreateThread(function() - while menuActive do - local menuText = "Verkaufsautomat #" .. machine.id .. "\n" - - for i, option in ipairs(options) do - if i == currentIndex then - menuText = menuText .. "→ " .. option.label .. "\n" - else - menuText = menuText .. option.label .. "\n" + lib.registerContext({ + id = 'vending_management', + title = 'Verkaufsautomat #' .. machine.id, + options = { + { + title = 'Inventar öffnen', + description = 'Items hinzufügen oder entfernen', + icon = 'fas fa-box', + onSelect = function() + TriggerServerEvent('vending:server:openStash', machine.coords) end - end - - menuText = menuText .. "\n[↑][↓] Navigieren | [ENTER] Auswählen | [ESC] Abbrechen" - - DrawText3D(machine.coords.x, machine.coords.y, machine.coords.z + 1.0, menuText) - Wait(0) - end - end) + }, + { + title = 'Einnahmen: $' .. machine.money, + description = 'Geld abheben', + icon = 'fas fa-money-bill', + onSelect = function() + openWithdrawMenu(machine.coords, machine.money) + end + } + } + }) - -- Handle navigation - while menuActive do - if IsControlJustPressed(0, 172) then -- Up arrow - currentIndex = currentIndex - 1 - if currentIndex < 1 then currentIndex = #options end - Wait(200) - elseif IsControlJustPressed(0, 173) then -- Down arrow - currentIndex = currentIndex + 1 - if currentIndex > #options then currentIndex = 1 end - Wait(200) - elseif IsControlJustPressed(0, 18) then -- Enter key - local selectedOption = options[currentIndex].action - menuActive = false - - if selectedOption == "inventory" then - TriggerServerEvent('vending:server:openStash', machine.coords) - elseif selectedOption == "withdraw" then - openWithdrawMenu(machine.coords, machine.money) - end - elseif IsControlJustPressed(0, 177) then -- Escape key - menuActive = false - end - Wait(0) - end + lib.showContext('vending_management') end) -- Debug command to check props @@ -1041,79 +728,8 @@ RegisterCommand('vendingdebug', function() end, coords) end, false) --- Helper function to display notifications -function ShowHelpNotification(text) - BeginTextCommandDisplayHelp("STRING") - AddTextComponentSubstringPlayerName(text) - EndTextCommandDisplayHelp(0, 0, 1, -1) -end - --- Helper function to get key name -function GetKeyName(key) - local keyNames = { - [38] = "E", - [47] = "G", - [172] = "↑", - [173] = "↓", - [174] = "←", - [175] = "→", - [18] = "ENTER", - [177] = "ESC", - [246] = "Y", - [249] = "N" - } - return keyNames[key] or "KEY " .. key -end - --- Helper function to handle text input -function HandleTextInput(maxLength) - local input = "" - local inputActive = true - - while inputActive do - -- Number keys (0-9) - for i = 48, 57 do - if IsControlJustPressed(0, i) and string.len(input) < maxLength then - input = input .. (i - 48) - Wait(200) - end - end - - -- Numpad keys (0-9) - for i = 96, 105 do - if IsControlJustPressed(0, i) and string.len(input) < maxLength then - input = input .. (i - 96) - Wait(200) - end - end - - -- Backspace - if IsControlJustPressed(0, 194) and string.len(input) > 0 then - input = string.sub(input, 1, string.len(input) - 1) - Wait(200) - end - - -- Enter - if IsControlJustPressed(0, 18) then - inputActive = false - return input - end - - -- Escape - if IsControlJustPressed(0, 177) then - inputActive = false - return nil - end - - Wait(0) - end - - return nil -end - -- Event to refresh machine data when a new machine is registered RegisterNetEvent('vending:client:refreshTargets', function() -- Clear cached data currentMachineData = nil end) -