Main/resources/[inventory]/nordi_vending/client.lua
2025-07-29 22:47:43 +02:00

1119 lines
38 KiB
Lua

local QBCore = exports['qb-core']:GetCoreObject()
local nearbyMachine = nil
local currentMachineData = nil
local isInteracting = false
-- Function to draw 3D text in the world
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry("STRING")
SetTextCentre(1)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = (string.len(text)) / 370
DrawRect(0.0, 0.0+0.0125, 0.017+ factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
-- Function to check if machine is registered (with caching)
function isRegisteredMachine(entity)
if currentMachineData and currentMachineData.entity == entity then
return currentMachineData.isRegistered
end
local coords = GetEntityCoords(entity)
local isRegistered = false
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists)
isRegistered = exists
end, coords)
-- Wait for callback
local timeout = 0
while isRegistered == false and timeout < 100 do
Wait(10)
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)
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
QBCore.Functions.TriggerCallback('vending:server:canManage', function(result)
canManage = result
end, coords)
-- Wait for callback
local timeout = 0
while canManage == false and timeout < 100 do
Wait(10)
timeout = timeout + 1
end
if not currentMachineData then currentMachineData = {} end
currentMachineData.entity = entity
currentMachineData.canManage = canManage
return canManage
end
-- Main thread to detect nearby vending machines
CreateThread(function()
while true do
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
local wait = 1000
local foundMachine = false
-- Check for nearby vending machines
for _, propName in ipairs(Config.VendingProps) do
local hash = GetHashKey(propName)
local objects = GetGamePool('CObject')
for _, obj in ipairs(objects) do
if GetEntityModel(obj) == hash then
local objCoords = GetEntityCoords(obj)
local dist = #(playerCoords - objCoords)
if dist < 2.0 then
wait = 0
foundMachine = true
nearbyMachine = obj
-- Only check status if not already interacting
if not isInteracting then
local z = objCoords.z + 1.0
local registered = isRegisteredMachine(obj)
if registered then
local canManage = canManageMachine(obj)
if canManage then
DrawText3D(objCoords.x, objCoords.y, z, "[E] Kaufen | [G] Verwalten")
-- Handle key presses for management
if IsControlJustPressed(0, 38) then -- E key
isInteracting = true
TriggerEvent('vending:client:openBuyMenu', {entity = obj})
Wait(500) -- Prevent multiple triggers
isInteracting = false
elseif IsControlJustPressed(0, 47) then -- G key
isInteracting = true
TriggerEvent('vending:client:openOwnerMenu', {entity = obj})
Wait(500) -- Prevent multiple triggers
isInteracting = false
end
else
DrawText3D(objCoords.x, objCoords.y, z, "[E] Kaufen | [G] Aufbrechen")
-- Handle key presses for buying/robbery
if IsControlJustPressed(0, 38) then -- E key
isInteracting = true
TriggerEvent('vending:client:openBuyMenu', {entity = obj})
Wait(500) -- Prevent multiple triggers
isInteracting = false
elseif IsControlJustPressed(0, 47) then -- G key
isInteracting = true
TriggerEvent('vending:client:startRobbery', {entity = obj})
Wait(500) -- Prevent multiple triggers
isInteracting = false
end
end
else
DrawText3D(objCoords.x, objCoords.y, z, "[E] Automaten kaufen ($" .. Config.VendingMachinePrice .. ")")
-- Handle key press for buying machine
if IsControlJustPressed(0, 38) then -- E key
isInteracting = true
TriggerEvent('vending:client:buyMachine', {entity = obj})
Wait(500) -- Prevent multiple triggers
isInteracting = false
end
end
end
break
end
end
end
if foundMachine then break end
end
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
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
-- Display confirmation text
local startTime = GetGameTimer()
local textShown = true
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
end)
-- Open buy menu with quantity selection
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
-- 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
})
end
end
if #options == 0 then
QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error')
return
end
-- Display item selection
local currentIndex = 1
local menuActive = true
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
end, coords)
end)
-- Open owner menu
RegisterNetEvent('vending:client:openOwnerMenu', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
if not machine then
QBCore.Functions.Notify('Automat nicht gefunden!', 'error')
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"}
}
-- 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
openManagersMenu(coords)
elseif selectedOption == "sell" then
sellVendingMachine(coords, machine.id)
end
elseif IsControlJustPressed(0, 177) then -- Escape key
menuActive = false
end
Wait(0)
end
end, coords)
end)
-- Function to sell the vending machine
function sellVendingMachine(coords, machineId)
-- Display confirmation text
local confirmActive = 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)
end
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
-- 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
})
end
-- Display menu
local currentIndex = 1
local menuActive = true
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
end, coords)
end
-- Set price for specific item
function setPriceForItem(coords, itemName, itemLabel)
-- Display price input
local price = 0
local inputActive = true
local inputText = ""
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)
end
end
-- Open withdraw menu
function openWithdrawMenu(coords, availableMoney)
if availableMoney <= 0 then
QBCore.Functions.Notify('Kein Geld im Automaten!', 'error')
return
end
-- Display withdraw input
local inputActive = true
local inputText = ""
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)
end
end
-- Open stats menu
function openStatsMenu(machine)
-- Display stats
local menuActive = true
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
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"}
}
-- Add existing managers
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"
})
end
else
table.insert(options, {label = "Keine Verwalter", action = "none"})
end
-- Display menu
local currentIndex = 1
local menuActive = true
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
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
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
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
end)
end
-- Robbery menu
RegisterNetEvent('vending:client:startRobbery', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
-- Display robbery confirmation
local menuActive = true
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
end)
-- Start robbery animation and progress
RegisterNetEvent('vending:client:startRobbery', function(coords)
local playerPed = PlayerPedId()
local robberyTime = 10000 -- 10 seconds
-- Animation
RequestAnimDict('anim@heists@fleeca_bank@drilling')
while not HasAnimDictLoaded('anim@heists@fleeca_bank@drilling') do
Wait(100)
end
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)
end
ClearPedTasks(playerPed)
TriggerServerEvent('vending:server:completeRobbery', coords, not cancelled)
end)
-- Police alert
RegisterNetEvent('vending:client:policeAlert', function(coords, streetName)
-- Add blip
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
SetBlipSprite(blip, 161)
SetBlipColour(blip, 1)
SetBlipScale(blip, 1.0)
SetBlipAsShortRange(blip, false)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Verkaufsautomat Aufbruch")
EndTextCommandSetBlipName(blip)
-- Remove blip after 5 minutes
SetTimeout(300000, function()
RemoveBlip(blip)
end)
QBCore.Functions.Notify('Verkaufsautomat Aufbruch gemeldet: ' .. streetName, 'error', 8000)
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"
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)
-- 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
end)
-- Debug command to check props
RegisterCommand('checkvendingprops', function()
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
local foundProps = 0
for _, propName in ipairs(Config.VendingProps) do
local hash = GetHashKey(propName)
local objects = GetGamePool('CObject')
print("Checking for prop: " .. propName .. " (Hash: " .. hash .. ")")
for _, obj in ipairs(objects) do
if GetEntityModel(obj) == hash then
local objCoords = GetEntityCoords(obj)
local dist = #(playerCoords - objCoords)
if dist < 30.0 then
foundProps = foundProps + 1
print("Found " .. propName .. " at distance: " .. dist)
-- Add a temporary blip
local blip = AddBlipForEntity(obj)
SetBlipSprite(blip, 1)
SetBlipColour(blip, 2)
SetBlipScale(blip, 0.8)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString(propName)
EndTextCommandSetBlipName(blip)
-- Remove blip after 10 seconds
SetTimeout(10000, function()
RemoveBlip(blip)
end)
end
end
end
end
QBCore.Functions.Notify('Found ' .. foundProps .. ' vending machines nearby', 'primary')
end, false)
-- Debug commands
RegisterCommand('vendingdebug', function()
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
if machine then
print('Machine found:', json.encode(machine))
QBCore.Functions.Notify('Machine data logged to console', 'primary')
else
print('No machine found at current location')
QBCore.Functions.Notify('No machine found here', 'error')
end
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)