2025-07-29 07:30:32 +02:00
local QBCore = exports [ ' qb-core ' ] : GetCoreObject ( )
2025-07-29 10:43:02 +02:00
local nearbyMachines = { }
local currentMachine = nil
local showingMenu = false
2025-07-29 07:30:32 +02:00
2025-07-29 10:43:02 +02:00
-- Kontinuierlicher Check für Verkaufsautomaten
2025-07-29 10:38:20 +02:00
CreateThread ( function ( )
while true do
local playerPed = PlayerPedId ( )
2025-07-29 10:43:02 +02:00
local playerCoords = GetEntityCoords ( playerPed )
local sleep = 1000
2025-07-29 10:38:20 +02:00
2025-07-29 10:43:02 +02:00
-- Reset current machine
currentMachine = nil
-- Check for nearby vending machines
local objects = GetGamePool ( ' CObject ' )
for _ , obj in ipairs ( objects ) do
local model = GetEntityModel ( obj )
for _ , propName in ipairs ( Config.VendingProps ) do
if model == GetHashKey ( propName ) then
local objCoords = GetEntityCoords ( obj )
local dist = # ( playerCoords - objCoords )
if dist < 2.0 then
currentMachine = obj
sleep = 0
-- Show help text
if not showingMenu then
DrawText3D ( objCoords.x , objCoords.y , objCoords.z + 1.5 , " [E] Verkaufsautomat " )
if IsControlJustPressed ( 0 , 38 ) then -- E key
handleMachineInteraction ( obj )
end
end
break
end
end
end
if currentMachine then break end
2025-07-29 10:38:20 +02:00
end
2025-07-29 10:43:02 +02:00
Wait ( sleep )
2025-07-29 10:38:20 +02:00
end
end )
2025-07-29 10:43:02 +02:00
-- 3D Text function
function DrawText3D ( x , y , z , text )
local onScreen , _x , _y = World3dToScreen2d ( x , y , z )
local px , py , pz = table.unpack ( GetGameplayCamCoords ( ) )
if onScreen then
SetTextScale ( 0.35 , 0.35 )
SetTextFont ( 4 )
SetTextProportional ( 1 )
SetTextColour ( 255 , 255 , 255 , 215 )
SetTextEntry ( " STRING " )
SetTextCentre ( 1 )
AddTextComponentString ( text )
DrawText ( _x , _y )
local factor = ( string.len ( text ) ) / 370
DrawRect ( _x , _y + 0.0125 , 0.015 + factor , 0.03 , 41 , 11 , 41 , 68 )
2025-07-29 09:48:16 +02:00
end
2025-07-29 10:43:02 +02:00
end
2025-07-29 09:48:16 +02:00
2025-07-29 10:23:04 +02:00
-- Get precise coordinates for entity
function getPreciseCoords ( entity )
local coords = GetEntityCoords ( entity )
local heading = GetEntityHeading ( entity )
local model = GetEntityModel ( entity )
return {
x = coords.x ,
y = coords.y ,
z = coords.z ,
h = heading ,
model = model
}
end
2025-07-29 10:43:02 +02:00
-- Handle machine interaction
function handleMachineInteraction ( entity )
showingMenu = true
2025-07-29 10:23:04 +02:00
local preciseCoords = getPreciseCoords ( entity )
2025-07-29 08:25:12 +02:00
2025-07-29 10:43:02 +02:00
-- Check if machine is registered
2025-07-29 08:25:12 +02:00
QBCore.Functions . TriggerCallback ( ' vending:server:machineExists ' , function ( exists )
2025-07-29 10:43:02 +02:00
if exists then
-- Check if player can manage
QBCore.Functions . TriggerCallback ( ' vending:server:canManage ' , function ( canManage )
if canManage then
showOwnerMenu ( entity , preciseCoords )
else
showBuyMenu ( entity , preciseCoords )
end
end , preciseCoords )
else
showPurchaseMenu ( entity , preciseCoords )
end
2025-07-29 10:23:04 +02:00
end , preciseCoords )
2025-07-29 08:25:12 +02:00
end
2025-07-29 10:43:02 +02:00
-- Show purchase menu (buy the machine)
function showPurchaseMenu ( entity , preciseCoords )
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:43:02 +02:00
if not prop then
showingMenu = false
return
end
2025-07-29 07:30:32 +02:00
lib.registerContext ( {
2025-07-29 10:43:02 +02:00
id = ' vending_purchase ' ,
title = ' Verkaufsautomat ' ,
2025-07-29 07:30:32 +02:00
options = {
{
2025-07-29 10:43:02 +02:00
title = ' Automaten kaufen ' ,
description = ' Kaufe diesen Automaten für $ ' .. Config.VendingMachinePrice ,
icon = ' fas fa-dollar-sign ' ,
2025-07-29 07:30:32 +02:00
onSelect = function ( )
2025-07-29 10:43:02 +02:00
lib.registerContext ( {
id = ' vending_purchase_confirm ' ,
title = ' Kauf bestätigen ' ,
menu = ' vending_purchase ' ,
options = {
{
title = ' Bestätigen ' ,
description = ' Automaten für $ ' .. Config.VendingMachinePrice .. ' kaufen ' ,
icon = ' fas fa-check ' ,
onSelect = function ( )
TriggerServerEvent ( ' vending:server:registerMachine ' , preciseCoords , prop )
showingMenu = false
end
} ,
{
title = ' Abbrechen ' ,
description = ' Kauf abbrechen ' ,
icon = ' fas fa-times ' ,
onSelect = function ( )
showingMenu = false
end
}
}
} )
lib.showContext ( ' vending_purchase_confirm ' )
2025-07-29 07:30:32 +02:00
end
} ,
{
2025-07-29 10:43:02 +02:00
title = ' Schließen ' ,
description = ' Menü schließen ' ,
icon = ' fas fa-times ' ,
onSelect = function ( )
showingMenu = false
end
2025-07-29 07:30:32 +02:00
}
}
} )
2025-07-29 10:43:02 +02:00
lib.showContext ( ' vending_purchase ' )
end
2025-07-29 07:30:32 +02:00
2025-07-29 10:43:02 +02:00
-- Show buy menu (buy items from machine)
function showBuyMenu ( entity , preciseCoords )
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 ' )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 07:30:32 +02:00
return
end
local options = { }
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 07:51:42 +02:00
title = itemLabel ,
2025-07-29 07:30:32 +02:00
description = ' Preis: $ ' .. item.price .. ' | Verfügbar: ' .. item.amount ,
2025-07-29 08:25:12 +02:00
icon = ' fas fa-shopping-cart ' ,
2025-07-29 07:30:32 +02:00
onSelect = function ( )
2025-07-29 10:23:04 +02:00
openQuantityDialog ( preciseCoords , item.name , item.price , item.amount , itemLabel )
2025-07-29 07:30:32 +02:00
end
} )
end
end
2025-07-29 10:43:02 +02:00
-- Add robbery option
table.insert ( options , {
title = ' Aufbrechen ' ,
description = ' Versuche den Automaten aufzubrechen ' ,
icon = ' fas fa-mask ' ,
onSelect = function ( )
lib.registerContext ( {
id = ' vending_robbery_confirm ' ,
title = ' Verkaufsautomat aufbrechen ' ,
menu = ' vending_buy_menu ' ,
options = {
{
title = ' Aufbrechen ' ,
description = ' Versuche den Automaten aufzubrechen (benötigt ' .. Config.RobberyItem .. ' ) ' ,
icon = ' fas fa-mask ' ,
onSelect = function ( )
TriggerServerEvent ( ' vending:server:startRobbery ' , preciseCoords )
showingMenu = false
end
} ,
{
title = ' Abbrechen ' ,
description = ' Aufbruch abbrechen ' ,
icon = ' fas fa-times ' ,
onSelect = function ( )
showingMenu = false
end
}
}
} )
lib.showContext ( ' vending_robbery_confirm ' )
end
} )
table.insert ( options , {
title = ' Schließen ' ,
description = ' Menü schließen ' ,
icon = ' fas fa-times ' ,
onSelect = function ( )
showingMenu = false
end
} )
if # options == 1 then -- Only close option
2025-07-29 08:25:12 +02:00
QBCore.Functions . Notify ( ' Keine Artikel verfügbar! ' , ' error ' )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 08:25:12 +02:00
return
end
2025-07-29 07:30:32 +02:00
lib.registerContext ( {
id = ' vending_buy_menu ' ,
title = ' Verkaufsautomat ' ,
options = options
} )
lib.showContext ( ' vending_buy_menu ' )
2025-07-29 10:23:04 +02:00
end , preciseCoords )
2025-07-29 09:02:52 +02:00
end
2025-07-29 10:43:02 +02:00
-- Show owner menu
function showOwnerMenu ( entity , preciseCoords )
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 ' )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 08:25:12 +02:00
return
end
2025-07-29 09:02:52 +02:00
local options = {
{
title = ' Inventar verwalten ' ,
description = ' Items hinzufügen/entfernen ' ,
icon = ' fas fa-box ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:openStash ' , preciseCoords )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 09:02:52 +02:00
end
} ,
{
title = ' Preise festlegen ' ,
description = ' Verkaufspreise für Items setzen ' ,
icon = ' fas fa-tags ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
openPriceMenu ( preciseCoords )
2025-07-29 09:02:52 +02:00
end
} ,
{
title = ' Geld abheben ' ,
description = ' Verfügbar: $ ' .. machine.money ,
icon = ' fas fa-money-bill ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
openWithdrawMenu ( preciseCoords , machine.money )
2025-07-29 09:02:52 +02:00
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 , {
title = ' Verwalter ' ,
description = ' Verwalter hinzufügen/entfernen ' ,
icon = ' fas fa-users-cog ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
openManagersMenu ( preciseCoords )
2025-07-29 09:02:52 +02:00
end
} )
2025-07-29 09:20:46 +02:00
-- Add sell option only for owner
table.insert ( options , {
title = ' Automaten verkaufen ' ,
2025-07-29 10:43:02 +02:00
description = ' Verkaufe den Automaten für $ ' .. math.floor ( Config.VendingMachinePrice * Config.SellBackPercentage / 100 ) ,
2025-07-29 09:20:46 +02:00
icon = ' fas fa-dollar-sign ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
sellVendingMachine ( preciseCoords , machine.id )
2025-07-29 09:20:46 +02:00
end
} )
2025-07-29 09:02:52 +02:00
end
2025-07-29 10:43:02 +02:00
table.insert ( options , {
title = ' Schließen ' ,
description = ' Menü schließen ' ,
icon = ' fas fa-times ' ,
onSelect = function ( )
showingMenu = false
end
} )
2025-07-29 08:25:12 +02:00
lib.registerContext ( {
id = ' vending_owner_menu ' ,
title = ' Verkaufsautomat Verwaltung ' ,
2025-07-29 09:02:52 +02:00
options = options
2025-07-29 08:25:12 +02:00
} )
lib.showContext ( ' vending_owner_menu ' )
2025-07-29 10:23:04 +02:00
end , preciseCoords )
2025-07-29 10:43:02 +02:00
end
-- Open quantity dialog for buying items
function openQuantityDialog ( preciseCoords , 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 ' , preciseCoords , itemName , amount )
else
QBCore.Functions . Notify ( ' Ungültige Menge! ' , ' error ' )
end
end
showingMenu = false
end
2025-07-29 08:25:12 +02:00
2025-07-29 09:20:46 +02:00
-- Funktion zum Verkaufen des Automaten
2025-07-29 10:23:04 +02:00
function sellVendingMachine ( preciseCoords , machineId )
2025-07-29 09:20:46 +02:00
local input = lib.inputDialog ( ' Automaten verkaufen ' , {
{
type = ' checkbox ' ,
label = ' Bestätigen ' ,
2025-07-29 10:43:02 +02:00
description = ' Du erhältst $ ' .. math.floor ( Config.VendingMachinePrice * Config.SellBackPercentage / 100 ) .. ' zurück. Diese Aktion kann nicht rückgängig gemacht werden! ' ,
2025-07-29 09:20:46 +02:00
required = true
}
} )
if input and input [ 1 ] then
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:sellMachine ' , preciseCoords , machineId )
2025-07-29 09:20:46 +02:00
end
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 09:20:46 +02:00
end
2025-07-29 08:25:12 +02:00
-- Open price menu
2025-07-29 10:23:04 +02:00
function openPriceMenu ( preciseCoords )
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 ' )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 08:25:12 +02:00
return
end
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 , {
title = itemLabel ,
description = ' Aktueller Preis: $ ' .. item.price ,
icon = ' fas fa-tag ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
setPriceForItem ( preciseCoords , item.name , itemLabel )
2025-07-29 08:25:12 +02:00
end
} )
end
2025-07-29 10:43:02 +02:00
table.insert ( options , {
title = ' Zurück ' ,
description = ' Zurück zum Hauptmenü ' ,
icon = ' fas fa-arrow-left ' ,
onSelect = function ( )
showOwnerMenu ( currentMachine , preciseCoords )
end
} )
2025-07-29 08:25:12 +02:00
lib.registerContext ( {
id = ' vending_price_menu ' ,
title = ' Preise festlegen ' ,
options = options
} )
lib.showContext ( ' vending_price_menu ' )
2025-07-29 10:23:04 +02:00
end , preciseCoords )
2025-07-29 08:25:12 +02:00
end
-- Set price for specific item
2025-07-29 10:23:04 +02:00
function setPriceForItem ( preciseCoords , itemName , itemLabel )
2025-07-29 08:25:12 +02:00
local input = lib.inputDialog ( ' Preis festlegen ' , {
{
type = ' number ' ,
label = ' Preis für ' .. itemLabel ,
description = ' Neuen Verkaufspreis eingeben ' ,
required = true ,
min = 1 ,
max = 10000
}
} )
if input and input [ 1 ] then
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:setItemPrice ' , preciseCoords , itemName , tonumber ( input [ 1 ] ) )
2025-07-29 08:25:12 +02:00
end
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 08:25:12 +02:00
end
-- Open withdraw menu
2025-07-29 10:23:04 +02:00
function openWithdrawMenu ( preciseCoords , availableMoney )
2025-07-29 08:25:12 +02:00
if availableMoney <= 0 then
QBCore.Functions . Notify ( ' Kein Geld im Automaten! ' , ' error ' )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 08:25:12 +02:00
return
end
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
}
} )
if input and input [ 1 ] then
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:withdrawMoney ' , preciseCoords , tonumber ( input [ 1 ] ) )
2025-07-29 08:25:12 +02:00
end
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 08:25:12 +02:00
end
-- Open stats menu
function openStatsMenu ( machine )
2025-07-29 07:30:32 +02:00
lib.registerContext ( {
2025-07-29 08:25:12 +02:00
id = ' vending_stats_menu ' ,
title = ' Verkaufsstatistiken ' ,
2025-07-29 07:30:32 +02:00
options = {
{
2025-07-29 08:25:12 +02:00
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 '
2025-07-29 10:43:02 +02:00
} ,
{
title = ' Zurück ' ,
description = ' Zurück zum Hauptmenü ' ,
icon = ' fas fa-arrow-left ' ,
onSelect = function ( )
showOwnerMenu ( currentMachine , machine.coords )
end
2025-07-29 08:25:12 +02:00
}
}
} )
lib.showContext ( ' vending_stats_menu ' )
end
2025-07-29 09:02:52 +02:00
-- Open managers menu
2025-07-29 10:23:04 +02:00
function openManagersMenu ( preciseCoords )
2025-07-29 09:02:52 +02:00
QBCore.Functions . TriggerCallback ( ' vending:server:getManagers ' , function ( managers )
local options = {
{
title = ' Verwalter hinzufügen ' ,
description = ' Neuen Verwalter hinzufügen ' ,
icon = ' fas fa-user-plus ' ,
onSelect = function ( )
2025-07-29 10:23:04 +02:00
openAddManagerMenu ( preciseCoords )
2025-07-29 09:02:52 +02:00
end
}
}
if # managers > 0 then
for i = 1 , # managers do
local manager = managers [ i ]
table.insert ( options , {
title = manager.name ,
2025-07-29 10:43:02 +02:00
description = manager.online and ' Online - Klicken zum Entfernen ' or ' Offline - Klicken zum Entfernen ' ,
2025-07-29 09:02:52 +02:00
icon = manager.online and ' fas fa-circle text-success ' or ' fas fa-circle text-danger ' ,
onSelect = function ( )
lib.registerContext ( {
2025-07-29 10:43:02 +02:00
id = ' manager_confirm_remove ' ,
title = ' Verwalter entfernen ' ,
2025-07-29 09:02:52 +02:00
options = {
{
2025-07-29 10:43:02 +02:00
title = ' Bestätigen ' ,
description = manager.name .. ' als Verwalter entfernen ' ,
icon = ' fas fa-check ' ,
2025-07-29 09:02:52 +02:00
onSelect = function ( )
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:removeManager ' , preciseCoords , manager.citizenid )
2025-07-29 10:43:02 +02:00
showingMenu = false
end
} ,
{
title = ' Abbrechen ' ,
description = ' Zurück zur Verwalterliste ' ,
icon = ' fas fa-times ' ,
onSelect = function ( )
openManagersMenu ( preciseCoords )
2025-07-29 09:02:52 +02:00
end
}
}
} )
2025-07-29 10:43:02 +02:00
lib.showContext ( ' manager_confirm_remove ' )
2025-07-29 09:02:52 +02:00
end
} )
end
else
table.insert ( options , {
title = ' Keine Verwalter ' ,
description = ' Es sind keine Verwalter vorhanden ' ,
icon = ' fas fa-info-circle ' ,
disabled = true
} )
end
2025-07-29 10:43:02 +02:00
table.insert ( options , {
title = ' Zurück ' ,
description = ' Zurück zum Hauptmenü ' ,
icon = ' fas fa-arrow-left ' ,
onSelect = function ( )
showOwnerMenu ( currentMachine , preciseCoords )
end
} )
2025-07-29 09:02:52 +02:00
lib.registerContext ( {
id = ' managers_menu ' ,
title = ' Verwalter verwalten ' ,
options = options
} )
lib.showContext ( ' managers_menu ' )
2025-07-29 10:23:04 +02:00
end , preciseCoords )
2025-07-29 09:02:52 +02:00
end
-- Open add manager menu
2025-07-29 10:23:04 +02:00
function openAddManagerMenu ( preciseCoords )
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 10:43:02 +02:00
showingMenu = false
2025-07-29 09:02:52 +02:00
return
end
local options = { }
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 ( )
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:addManager ' , preciseCoords , player.id )
2025-07-29 10:43:02 +02:00
showingMenu = false
2025-07-29 09:02:52 +02:00
end
} )
end
2025-07-29 10:43:02 +02:00
table.insert ( options , {
title = ' Zurück ' ,
description = ' Zurück zur Verwalterliste ' ,
icon = ' fas fa-arrow-left ' ,
onSelect = function ( )
openManagersMenu ( preciseCoords )
end
} )
2025-07-29 09:02:52 +02:00
lib.registerContext ( {
id = ' add_manager_menu ' ,
title = ' Verwalter hinzufügen ' ,
options = options
} )
lib.showContext ( ' add_manager_menu ' )
end )
end
2025-07-29 08:25:12 +02:00
-- Start robbery animation and progress
2025-07-29 10:23:04 +02:00
RegisterNetEvent ( ' vending:client:startRobbery ' , function ( preciseCoords )
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 )
-- 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 )
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:completeRobbery ' , preciseCoords , success )
2025-07-29 08:25:12 +02:00
else
-- Fallback without progress bar
Wait ( robberyTime )
ClearPedTasks ( playerPed )
2025-07-29 10:23:04 +02:00
TriggerServerEvent ( ' vending:server:completeRobbery ' , preciseCoords , true )
2025-07-29 08:25:12 +02:00
end
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:43:02 +02:00
-- Event handlers for menu closing
RegisterNetEvent ( ' vending:client:closeMenu ' , function ( )
showingMenu = false
end )
-- Close menu when inventory is opened
AddEventHandler ( ' inventory:client:OpenInventory ' , function ( )
showingMenu = false
2025-07-29 07:30:32 +02:00
end )
2025-07-29 10:43:02 +02:00
-- Debug commands
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:23:04 +02:00
local preciseCoords = getPreciseCoords ( obj )
print ( " Found " .. propName .. " at distance: " .. dist .. " | Coords: " ..
preciseCoords.x .. " , " .. preciseCoords.y .. " , " .. preciseCoords.z )
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 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:11:01 +02:00
-- Try to find the closest vending machine
local minDist = 3.0
2025-07-29 10:23:04 +02:00
local closestEntity = nil
2025-07-29 10:11:01 +02:00
local objects = GetGamePool ( ' CObject ' )
for _ , obj in ipairs ( objects ) do
local model = GetEntityModel ( obj )
for _ , propName in ipairs ( Config.VendingProps ) do
if model == GetHashKey ( propName ) then
local objCoords = GetEntityCoords ( obj )
local dist = # ( coords - objCoords )
if dist < minDist then
minDist = dist
2025-07-29 10:23:04 +02:00
closestEntity = obj
2025-07-29 10:11:01 +02:00
end
end
2025-07-29 09:48:16 +02:00
end
2025-07-29 10:11:01 +02:00
end
2025-07-29 10:23:04 +02:00
if closestEntity then
local preciseCoords = getPreciseCoords ( closestEntity )
QBCore.Functions . TriggerCallback ( ' vending:server:getMachineByCoords ' , function ( machine )
2025-07-29 10:11:01 +02:00
if machine then
print ( ' Machine found: ' , json.encode ( machine ) )
2025-07-29 10:23:04 +02:00
QBCore.Functions . Notify ( ' Machine # ' .. machine.id .. ' | Owner: ' .. machine.owner , ' primary ' )
2025-07-29 10:11:01 +02:00
else
2025-07-29 10:23:04 +02:00
print ( ' No machine found at coords: ' , json.encode ( preciseCoords ) )
QBCore.Functions . Notify ( ' No machine found at these coords ' , ' error ' )
2025-07-29 10:11:01 +02:00
end
2025-07-29 10:23:04 +02:00
end , preciseCoords )
2025-07-29 10:11:01 +02:00
else
QBCore.Functions . Notify ( ' No vending machine found nearby ' , ' error ' )
end
2025-07-29 09:41:19 +02:00
end , false )