1
0
Fork 0
forked from Simnation/Main
Main/resources/[inventory]/nordi_vending/client.lua

1120 lines
38 KiB
Lua
Raw Normal View History

2025-07-29 07:30:32 +02:00
local QBCore = exports['qb-core']:GetCoreObject()
2025-07-29 22:35:35 +02:00
local nearbyMachine = nil
2025-07-29 22:47:43 +02:00
local currentMachineData = nil
local isInteracting = false
2025-07-29 07:30:32 +02:00
2025-07-29 22:35:35 +02:00
-- Function to draw 3D text in the world
function DrawText3D(x, y, z, text)
2025-07-29 22:47:43 +02:00
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()
2025-07-29 22:35:35 +02:00
end
2025-07-29 09:48:16 +02:00
2025-07-29 22:47:43 +02:00
-- Function to check if machine is registered (with caching)
2025-07-29 10:53:08 +02:00
function isRegisteredMachine(entity)
2025-07-29 22:47:43 +02:00
if currentMachineData and currentMachineData.entity == entity then
return currentMachineData.isRegistered
end
2025-07-29 10:23:04 +02:00
local coords = GetEntityCoords(entity)
2025-07-29 10:53:08 +02:00
local isRegistered = false
2025-07-29 10:23:04 +02:00
2025-07-29 10:53:08 +02:00
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists)
isRegistered = exists
end, coords)
2025-07-29 22:47:43 +02:00
-- Wait for callback
2025-07-29 10:53:08 +02:00
local timeout = 0
while isRegistered == false and timeout < 100 do
Wait(10)
timeout = timeout + 1
end
2025-07-29 22:47:43 +02:00
if not currentMachineData then currentMachineData = {} end
currentMachineData.entity = entity
currentMachineData.isRegistered = isRegistered
2025-07-29 10:53:08 +02:00
return isRegistered
2025-07-29 10:23:04 +02:00
end
2025-07-29 22:47:43 +02:00
-- Check if player can manage machine (with caching)
2025-07-29 10:53:08 +02:00
function canManageMachine(entity)
2025-07-29 22:47:43 +02:00
if currentMachineData and currentMachineData.entity == entity and currentMachineData.canManage ~= nil then
return currentMachineData.canManage
end
2025-07-29 10:53:08 +02:00
local coords = GetEntityCoords(entity)
local canManage = false
2025-07-29 08:25:12 +02:00
2025-07-29 10:53:08 +02:00
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
2025-07-29 22:47:43 +02:00
if not currentMachineData then currentMachineData = {} end
currentMachineData.entity = entity
currentMachineData.canManage = canManage
2025-07-29 10:53:08 +02:00
return canManage
2025-07-29 08:25:12 +02:00
end
2025-07-29 22:35:35 +02:00
-- Main thread to detect nearby vending machines
CreateThread(function()
while true do
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
local wait = 1000
2025-07-29 22:47:43 +02:00
local foundMachine = false
2025-07-29 22:35:35 +02:00
-- 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
2025-07-29 22:47:43 +02:00
foundMachine = true
2025-07-29 22:35:35 +02:00
nearbyMachine = obj
2025-07-29 22:47:43 +02:00
-- 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")
2025-07-29 22:35:35 +02:00
2025-07-29 22:47:43 +02:00
-- 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
2025-07-29 22:35:35 +02:00
end
end
2025-07-29 22:47:43 +02:00
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
2025-07-29 22:35:35 +02:00
end
break
end
end
end
2025-07-29 22:47:43 +02:00
if foundMachine then break end
end
if not foundMachine then
nearbyMachine = nil
currentMachineData = nil
2025-07-29 22:35:35 +02:00
end
Wait(wait)
end
end)
2025-07-29 22:47:43 +02:00
-- Reset machine data when moving away
CreateThread(function()
while true do
Wait(5000)
if not nearbyMachine then
currentMachineData = nil
end
end
end)
2025-07-29 10:53:08 +02:00
-- Buy vending machine
RegisterNetEvent('vending:client:buyMachine', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
2025-07-29 07:30:32 +02:00
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
2025-07-29 10:53:08 +02:00
if not prop then return end
2025-07-29 07:30:32 +02:00
2025-07-29 22:47:43 +02:00
-- Display confirmation text
local startTime = GetGameTimer()
local textShown = true
2025-07-29 07:30:32 +02:00
2025-07-29 22:47:43 +02:00
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
2025-07-29 10:53:08 +02:00
end)
2025-07-29 07:30:32 +02:00
2025-07-29 10:53:08 +02:00
-- Open buy menu with quantity selection
RegisterNetEvent('vending:client:openBuyMenu', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
2025-07-29 07:30:32 +02:00
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then
QBCore.Functions.Notify('Dieser Automat ist leer!', 'error')
return
end
2025-07-29 22:47:43 +02:00
-- Simple item selection menu
2025-07-29 07:30:32 +02:00
local options = {}
2025-07-29 22:47:43 +02:00
local selectedItem = nil
2025-07-29 07:30:32 +02:00
for i = 1, #items do
local item = items[i]
if item.amount > 0 then
2025-07-29 07:51:42 +02:00
local itemLabel = QBCore.Shared.Items[item.name] and QBCore.Shared.Items[item.name].label or item.name
2025-07-29 07:30:32 +02:00
table.insert(options, {
2025-07-29 22:47:43 +02:00
name = item.name,
label = itemLabel,
price = item.price,
amount = item.amount
2025-07-29 07:30:32 +02:00
})
end
end
2025-07-29 10:53:08 +02:00
if #options == 0 then
2025-07-29 08:25:12 +02:00
QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error')
return
end
2025-07-29 22:47:43 +02:00
-- Display item selection
local currentIndex = 1
local menuActive = true
2025-07-29 07:30:32 +02:00
2025-07-29 22:47:43 +02:00
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
2025-07-29 10:53:08 +02:00
end, coords)
end)
-- Open owner menu
RegisterNetEvent('vending:client:openOwnerMenu', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
2025-07-29 10:23:04 +02:00
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
2025-07-29 08:25:12 +02:00
if not machine then
QBCore.Functions.Notify('Automat nicht gefunden!', 'error')
return
end
2025-07-29 22:47:43 +02:00
-- Display owner menu options
2025-07-29 09:02:52 +02:00
local options = {
2025-07-29 22:47:43 +02:00
{label = "Inventar verwalten", action = "inventory"},
{label = "Preise festlegen", action = "prices"},
{label = "Geld abheben ($" .. machine.money .. ")", action = "withdraw"},
{label = "Statistiken", action = "stats"}
2025-07-29 09:02:52 +02:00
}
-- Add manager options only for owner
if machine.isOwner then
2025-07-29 22:47:43 +02:00
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
2025-07-29 09:02:52 +02:00
end
2025-07-29 22:47:43 +02:00
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
2025-07-29 10:53:08 +02:00
sellVendingMachine(coords, machine.id)
2025-07-29 09:20:46 +02:00
end
2025-07-29 22:47:43 +02:00
elseif IsControlJustPressed(0, 177) then -- Escape key
menuActive = false
end
Wait(0)
2025-07-29 09:02:52 +02:00
end
2025-07-29 10:53:08 +02:00
end, coords)
end)
2025-07-29 08:25:12 +02:00
2025-07-29 22:35:35 +02:00
-- Function to sell the vending machine
2025-07-29 10:53:08 +02:00
function sellVendingMachine(coords, machineId)
2025-07-29 22:47:43 +02:00
-- Display confirmation text
local confirmActive = true
2025-07-29 09:20:46 +02:00
2025-07-29 22:47:43 +02:00
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)
2025-07-29 09:20:46 +02:00
end
end
2025-07-29 08:25:12 +02:00
-- Open price menu
2025-07-29 10:53:08 +02:00
function openPriceMenu(coords)
2025-07-29 08:25:12 +02:00
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then
QBCore.Functions.Notify('Keine Items im Automaten!', 'error')
return
end
2025-07-29 22:47:43 +02:00
-- Create options list
2025-07-29 08:25:12 +02:00
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, {
2025-07-29 22:47:43 +02:00
name = item.name,
label = itemLabel,
price = item.price
2025-07-29 08:25:12 +02:00
})
end
2025-07-29 22:47:43 +02:00
-- Display menu
local currentIndex = 1
local menuActive = true
2025-07-29 08:25:12 +02:00
2025-07-29 22:47:43 +02:00
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
2025-07-29 10:53:08 +02:00
end, coords)
2025-07-29 08:25:12 +02:00
end
-- Set price for specific item
2025-07-29 10:53:08 +02:00
function setPriceForItem(coords, itemName, itemLabel)
2025-07-29 22:47:43 +02:00
-- Display price input
local price = 0
local inputActive = true
local inputText = ""
2025-07-29 08:25:12 +02:00
2025-07-29 22:47:43 +02:00
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)
2025-07-29 08:25:12 +02:00
end
end
-- Open withdraw menu
2025-07-29 10:53:08 +02:00
function openWithdrawMenu(coords, availableMoney)
2025-07-29 08:25:12 +02:00
if availableMoney <= 0 then
QBCore.Functions.Notify('Kein Geld im Automaten!', 'error')
return
end
2025-07-29 22:47:43 +02:00
-- 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)
2025-07-29 08:25:12 +02:00
2025-07-29 22:47:43 +02:00
-- 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)
2025-07-29 08:25:12 +02:00
end
end
-- Open stats menu
function openStatsMenu(machine)
2025-07-29 22:47:43 +02:00
-- Display stats
local menuActive = true
2025-07-29 08:25:12 +02:00
2025-07-29 22:47:43 +02:00
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
2025-07-29 08:25:12 +02:00
end
2025-07-29 09:02:52 +02:00
-- Open managers menu
2025-07-29 10:53:08 +02:00
function openManagersMenu(coords)
-- Get current managers
2025-07-29 09:02:52 +02:00
QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers)
2025-07-29 22:47:43 +02:00
-- Create options list
2025-07-29 09:02:52 +02:00
local options = {
2025-07-29 22:47:43 +02:00
{label = "Verwalter hinzufügen", action = "add"}
2025-07-29 09:02:52 +02:00
}
2025-07-29 22:47:43 +02:00
-- Add existing managers
2025-07-29 09:02:52 +02:00
if #managers > 0 then
for i = 1, #managers do
local manager = managers[i]
table.insert(options, {
2025-07-29 22:47:43 +02:00
label = manager.name .. (manager.online and " (Online)" or " (Offline)"),
citizenid = manager.citizenid,
action = "manage"
2025-07-29 09:02:52 +02:00
})
end
else
2025-07-29 22:47:43 +02:00
table.insert(options, {label = "Keine Verwalter", action = "none"})
2025-07-29 09:02:52 +02:00
end
2025-07-29 22:47:43 +02:00
-- Display menu
local currentIndex = 1
local menuActive = true
2025-07-29 09:02:52 +02:00
2025-07-29 22:47:43 +02:00
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
2025-07-29 10:53:08 +02:00
end, coords)
2025-07-29 09:02:52 +02:00
end
2025-07-29 22:47:43 +02:00
-- 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
2025-07-29 09:02:52 +02:00
-- Open add manager menu
2025-07-29 10:53:08 +02:00
function openAddManagerMenu(coords)
2025-07-29 09:02:52 +02:00
QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players)
if #players == 0 then
QBCore.Functions.Notify('Keine Spieler online!', 'error')
2025-07-29 22:47:43 +02:00
openManagersMenu(coords) -- Go back to managers menu
2025-07-29 09:02:52 +02:00
return
end
2025-07-29 22:47:43 +02:00
-- Display player selection
local currentIndex = 1
local menuActive = true
2025-07-29 09:02:52 +02:00
2025-07-29 22:47:43 +02:00
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
2025-07-29 09:02:52 +02:00
end
2025-07-29 22:47:43 +02:00
menuText = menuText .. "\n[↑][↓] Navigieren | [ENTER] Auswählen | [ESC] Zurück"
DrawText3D(coords.x, coords.y, coords.z + 1.0, menuText)
Wait(0)
end
end)
2025-07-29 09:02:52 +02:00
2025-07-29 22:47:43 +02:00
-- 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
2025-07-29 09:02:52 +02:00
end)
end
2025-07-29 10:53:08 +02:00
-- Robbery menu
RegisterNetEvent('vending:client:startRobbery', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
2025-07-29 22:47:43 +02:00
-- 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)
2025-07-29 10:53:08 +02:00
2025-07-29 22:47:43 +02:00
-- 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
2025-07-29 10:53:08 +02:00
end)
2025-07-29 08:25:12 +02:00
-- Start robbery animation and progress
2025-07-29 10:53:08 +02:00
RegisterNetEvent('vending:client:startRobbery', function(coords)
2025-07-29 08:25:12 +02:00
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)
2025-07-29 22:47:43 +02:00
-- 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)
2025-07-29 08:25:12 +02:00
end
2025-07-29 22:47:43 +02:00
ClearPedTasks(playerPed)
TriggerServerEvent('vending:server:completeRobbery', coords, not cancelled)
2025-07-29 08:25:12 +02:00
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)
2025-07-29 10:53:08 +02:00
-- Management menu (alternative opening method)
RegisterNetEvent('vending:client:openManagement', function(machine)
2025-07-29 22:47:43 +02:00
-- 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"
2025-07-29 10:53:08 +02:00
end
2025-07-29 22:47:43 +02:00
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)
2025-07-29 10:53:08 +02:00
2025-07-29 22:47:43 +02:00
-- 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
2025-07-29 07:30:32 +02:00
end)
2025-07-29 10:53:08 +02:00
-- Debug command to check props
2025-07-29 09:39:15 +02:00
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
2025-07-29 10:53:08 +02:00
print("Found " .. propName .. " at distance: " .. dist)
2025-07-29 09:39:15 +02:00
-- Add a temporary blip
local blip = AddBlipForEntity(obj)
SetBlipSprite(blip, 1)
SetBlipColour(blip, 2)
SetBlipScale(blip, 0.8)
BeginTextCommandSetBlipName("STRING")
2025-07-29 10:23:04 +02:00
AddTextComponentString(propName)
2025-07-29 09:39:15 +02:00
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)
2025-07-29 09:41:19 +02:00
2025-07-29 10:53:08 +02:00
-- Debug commands
2025-07-29 09:48:16 +02:00
RegisterCommand('vendingdebug', function()
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
2025-07-29 09:41:19 +02:00
2025-07-29 10:53:08 +02:00
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')
2025-07-29 09:48:16 +02:00
end
2025-07-29 10:53:08 +02:00
end, coords)
2025-07-29 09:41:19 +02:00
end, false)
2025-07-29 22:47:43 +02:00
-- 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)