2025-07-29 10:26:42 +02:00
local QBCore = exports [ ' qb-core ' ] : GetCoreObject ( )
local vendingMachines = { }
local robberyInProgress = { }
-- Load vending machines from database
CreateThread ( function ( )
local result = MySQL.Sync . fetchAll ( ' SELECT * FROM vending_machines ' )
if result then
for i = 1 , # result do
local data = result [ i ]
vendingMachines [ data.id ] = {
id = data.id ,
owner = data.owner ,
coords = json.decode ( data.coords ) ,
prop = data.prop ,
money = data.money ,
items = json.decode ( data.items ) or { } ,
prices = json.decode ( data.prices ) or { } ,
managers = json.decode ( data.managers ) or { } ,
stash = ' vending_ ' .. data.id
}
end
print ( " ^2[VENDING]^7 Loaded " .. # result .. " vending machines " )
end
end )
-- Register vending machine (when player buys it)
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:registerMachine ' , function ( coords , prop )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
-- Check if there's already a machine at these coords
for id , machine in pairs ( vendingMachines ) do
2025-07-29 23:31:23 +02:00
if machine.coords and machine.coords . x and machine.coords . y and machine.coords . z then
local dist = # ( vector3 ( coords.x , coords.y , coords.z ) - vector3 ( machine.coords . x , machine.coords . y , machine.coords . z ) )
if dist < 2.0 then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Hier ist bereits ein Automat registriert! ' , ' error ' )
return
end
2025-07-29 10:26:42 +02:00
end
end
-- Check if player has enough money
if Player.PlayerData . money.cash < Config.VendingMachinePrice then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du benötigst $ ' .. Config.VendingMachinePrice .. ' um diesen Automaten zu kaufen! ' , ' error ' )
return
end
-- Remove money
Player.Functions . RemoveMoney ( ' cash ' , Config.VendingMachinePrice )
-- Create machine in database
local machineId = MySQL.insert . await ( ' INSERT INTO vending_machines (owner, coords, prop, money, items, prices, managers) VALUES (?, ?, ?, ?, ?, ?, ?) ' , {
Player.PlayerData . citizenid ,
2025-07-29 10:53:08 +02:00
json.encode ( coords ) ,
2025-07-29 10:26:42 +02:00
prop ,
0 ,
json.encode ( { } ) ,
json.encode ( { } ) ,
json.encode ( { } )
} )
-- Add to memory
vendingMachines [ machineId ] = {
id = machineId ,
owner = Player.PlayerData . citizenid ,
2025-07-29 10:53:08 +02:00
coords = coords ,
2025-07-29 10:26:42 +02:00
prop = prop ,
money = 0 ,
items = { } ,
prices = { } ,
managers = { } ,
stash = ' vending_ ' .. machineId
}
2025-07-29 10:53:08 +02:00
print ( " ^2[VENDING]^7 New vending machine registered: " .. machineId )
2025-07-29 10:26:42 +02:00
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Verkaufsautomat erfolgreich gekauft für $ ' .. Config.VendingMachinePrice .. ' ! ' , ' success ' )
TriggerClientEvent ( ' vending:client:refreshTargets ' , - 1 )
end )
-- Sell vending machine
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:sellMachine ' , function ( coords , machineId )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
if not machineId then
2025-07-29 10:53:08 +02:00
machineId = getMachineIdByCoords ( coords )
2025-07-29 10:26:42 +02:00
end
if not machineId then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Automat nicht gefunden! ' , ' error ' )
return
end
local machine = vendingMachines [ machineId ]
-- Check if player is owner
if machine.owner ~= Player.PlayerData . citizenid then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du bist nicht der Besitzer dieses Automaten! ' , ' error ' )
return
end
-- Calculate sell price
local sellPrice = math.floor ( Config.VendingMachinePrice * Config.SellBackPercentage / 100 )
-- Add money from machine to sell price
sellPrice = sellPrice + machine.money
-- Give money to player
Player.Functions . AddMoney ( ' cash ' , sellPrice )
-- Empty stash first
local stashItems = exports [ " tgiann-inventory " ] : GetSecondaryInventoryItems ( " stash " , machine.stash )
if stashItems then
for slot , item in pairs ( stashItems ) do
if item.amount > 0 then
-- Try to add to player inventory first
if Player.Functions . AddItem ( item.name , item.amount ) then
exports [ " tgiann-inventory " ] : RemoveItemFromSecondaryInventory ( " stash " , machine.stash , item.name , item.amount , slot )
TriggerClientEvent ( ' inventory:client:ItemBox ' , src , QBCore.Shared . Items [ item.name ] , ' add ' , item.amount )
else
-- If player inventory is full, create a drop
exports [ " tgiann-inventory " ] : RemoveItemFromSecondaryInventory ( " stash " , machine.stash , item.name , item.amount , slot )
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Einige Items wurden auf den Boden fallen gelassen! ' , ' info ' )
-- If you have a drop system, you can create a drop here
end
end
end
end
-- Delete from database
MySQL.Async . execute ( ' DELETE FROM vending_machines WHERE id = ? ' , { machineId } )
-- Remove from memory
vendingMachines [ machineId ] = nil
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Automat verkauft für $ ' .. sellPrice .. ' ! ' , ' success ' )
TriggerClientEvent ( ' vending:client:refreshTargets ' , - 1 )
end )
-- Check if player can manage machine
function canManageMachine ( playerId , machineId )
local Player = QBCore.Functions . GetPlayer ( playerId )
if not Player then return false end
local machine = vendingMachines [ machineId ]
if not machine then return false end
-- Check if player is owner
if machine.owner == Player.PlayerData . citizenid then
return true
end
-- Check if player is manager
if machine.managers then
for _ , manager in pairs ( machine.managers ) do
if manager == Player.PlayerData . citizenid then
return true
end
end
end
return false
end
-- Open management menu
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:openManagement ' , function ( coords )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
local machine = vendingMachines [ machineId ]
-- Check if player can manage
if not canManageMachine ( src , machineId ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast keine Berechtigung diesen Automaten zu verwalten! ' , ' error ' )
return
end
-- Add isOwner flag to distinguish between owner and manager
machine.isOwner = ( machine.owner == Player.PlayerData . citizenid )
TriggerClientEvent ( ' vending:client:openManagement ' , src , machine )
end )
-- Open stash
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:openStash ' , function ( coords )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
-- Check if player can manage
if not canManageMachine ( src , machineId ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast keine Berechtigung diesen Automaten zu verwalten! ' , ' error ' )
return
end
local machine = vendingMachines [ machineId ]
-- Öffne das Inventar mit tgiann-inventory
exports [ " tgiann-inventory " ] : OpenInventory ( src , " stash " , machine.stash , {
maxweight = Config.MaxWeight ,
slots = Config.MaxSlots ,
label = ' Vending Machine # ' .. machine.id
} )
end )
2025-07-29 23:31:23 +02:00
2025-07-29 10:26:42 +02:00
-- Set item price
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:setItemPrice ' , function ( coords , itemName , price )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
-- Check if player can manage
if not canManageMachine ( src , machineId ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast keine Berechtigung diesen Automaten zu verwalten! ' , ' error ' )
return
end
local machine = vendingMachines [ machineId ]
-- Update price
machine.prices [ itemName ] = price
MySQL.update ( ' UPDATE vending_machines SET prices = ? WHERE id = ? ' , { json.encode ( machine.prices ) , machineId } )
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Preis für ' .. ( QBCore.Shared . Items [ itemName ] and QBCore.Shared . Items [ itemName ] . label or itemName ) .. ' auf $ ' .. price .. ' gesetzt! ' , ' success ' )
end )
-- Withdraw money
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:withdrawMoney ' , function ( coords , amount )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
-- Check if player can manage
if not canManageMachine ( src , machineId ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast keine Berechtigung diesen Automaten zu verwalten! ' , ' error ' )
return
end
local machine = vendingMachines [ machineId ]
if machine.money < amount then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Nicht genug Geld im Automaten! ' , ' error ' )
return
end
-- Update machine money
machine.money = machine.money - amount
MySQL.update ( ' UPDATE vending_machines SET money = ? WHERE id = ? ' , { machine.money , machineId } )
-- Give money to player
Player.Functions . AddMoney ( ' cash ' , amount )
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast $ ' .. amount .. ' abgehoben! ' , ' success ' )
end )
-- Buy item from vending machine with quantity selection
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:buyItem ' , function ( coords , itemName , amount )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
local machine = vendingMachines [ machineId ]
local price = machine.prices [ itemName ] or Config.DefaultPrice
local totalPrice = price * amount
-- Check if player has enough money
if Player.PlayerData . money.cash < totalPrice then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast nicht genug Geld! ' , ' error ' )
return
end
-- Get stash items
local stashItems = exports [ " tgiann-inventory " ] : GetSecondaryInventoryItems ( " stash " , machine.stash )
local availableAmount = 0
if stashItems then
for slot , item in pairs ( stashItems ) do
if item.name == itemName and item.amount > 0 then
availableAmount = availableAmount + item.amount
end
end
end
if availableAmount < amount then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Nicht genug Artikel verfügbar! Verfügbar: ' .. availableAmount , ' error ' )
return
end
-- Check if player can carry the items
if not Player.Functions . AddItem ( itemName , amount ) then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du kannst nicht so viele Items tragen! ' , ' error ' )
return
end
-- Remove money from player
Player.Functions . RemoveMoney ( ' cash ' , totalPrice )
-- Add money to machine
machine.money = machine.money + totalPrice
MySQL.update ( ' UPDATE vending_machines SET money = ? WHERE id = ? ' , { machine.money , machineId } )
-- Remove items from stash
local remainingToRemove = amount
for slot , item in pairs ( stashItems ) do
if item.name == itemName and item.amount > 0 then
local removeAmount = math.min ( remainingToRemove , item.amount )
exports [ " tgiann-inventory " ] : RemoveItemFromSecondaryInventory ( " stash " , machine.stash , itemName , removeAmount , slot )
remainingToRemove = remainingToRemove - removeAmount
if remainingToRemove <= 0 then
break
end
end
end
-- Show item box
TriggerClientEvent ( ' inventory:client:ItemBox ' , src , QBCore.Shared . Items [ itemName ] , ' add ' , amount )
TriggerClientEvent ( ' QBCore:Notify ' , src , amount .. ' x ' .. ( QBCore.Shared . Items [ itemName ] and QBCore.Shared . Items [ itemName ] . label or itemName ) .. ' gekauft für $ ' .. totalPrice .. ' ! ' , ' success ' )
end )
-- Add manager to vending machine
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:addManager ' , function ( coords , targetId )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
local machine = vendingMachines [ machineId ]
-- Only owner can add managers
if machine.owner ~= Player.PlayerData . citizenid then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Nur der Besitzer kann Verwalter hinzufügen! ' , ' error ' )
return
end
-- Get target player
local Target = QBCore.Functions . GetPlayer ( tonumber ( targetId ) )
if not Target then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Spieler nicht gefunden! ' , ' error ' )
return
end
-- Check if already a manager
if machine.managers then
for _ , manager in pairs ( machine.managers ) do
if manager == Target.PlayerData . citizenid then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Diese Person ist bereits ein Verwalter! ' , ' error ' )
return
end
end
else
machine.managers = { }
end
-- Add to managers
table.insert ( machine.managers , Target.PlayerData . citizenid )
MySQL.update ( ' UPDATE vending_machines SET managers = ? WHERE id = ? ' , { json.encode ( machine.managers ) , machineId } )
TriggerClientEvent ( ' QBCore:Notify ' , src , Target.PlayerData . charinfo.firstname .. ' ' .. Target.PlayerData . charinfo.lastname .. ' als Verwalter hinzugefügt! ' , ' success ' )
TriggerClientEvent ( ' QBCore:Notify ' , Target.PlayerData . source , ' Du wurdest als Verwalter für einen Verkaufsautomaten hinzugefügt! ' , ' success ' )
end )
-- Remove manager from vending machine
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:removeManager ' , function ( coords , citizenid )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
local machine = vendingMachines [ machineId ]
-- Only owner can remove managers
if machine.owner ~= Player.PlayerData . citizenid then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Nur der Besitzer kann Verwalter entfernen! ' , ' error ' )
return
end
-- Check if manager exists
local found = false
local newManagers = { }
if machine.managers then
for _ , manager in pairs ( machine.managers ) do
if manager ~= citizenid then
table.insert ( newManagers , manager )
else
found = true
end
end
end
if not found then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Diese Person ist kein Verwalter! ' , ' error ' )
return
end
-- Update managers
machine.managers = newManagers
MySQL.update ( ' UPDATE vending_machines SET managers = ? WHERE id = ? ' , { json.encode ( machine.managers ) , machineId } )
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Verwalter entfernt! ' , ' success ' )
-- Notify the removed manager if online
local players = QBCore.Functions . GetPlayers ( )
for _ , playerId in ipairs ( players ) do
local targetPlayer = QBCore.Functions . GetPlayer ( playerId )
if targetPlayer and targetPlayer.PlayerData . citizenid == citizenid then
TriggerClientEvent ( ' QBCore:Notify ' , targetPlayer.PlayerData . source , ' Du wurdest als Verwalter eines Verkaufsautomaten entfernt! ' , ' error ' )
break
end
end
end )
2025-07-29 10:53:08 +02:00
-- Get managers list
QBCore.Functions . CreateCallback ( ' vending:server:getManagers ' , function ( source , cb , coords )
local machineId = getMachineIdByCoords ( coords )
if not machineId then
cb ( { } )
return
end
local machine = vendingMachines [ machineId ]
local managersList = { }
if machine.managers and # machine.managers > 0 then
for _ , citizenid in pairs ( machine.managers ) do
-- Try to get online player info
local found = false
local players = QBCore.Functions . GetPlayers ( )
for _ , playerId in ipairs ( players ) do
local targetPlayer = QBCore.Functions . GetPlayer ( playerId )
if targetPlayer and targetPlayer.PlayerData . citizenid == citizenid then
table.insert ( managersList , {
citizenid = citizenid ,
name = targetPlayer.PlayerData . charinfo.firstname .. ' ' .. targetPlayer.PlayerData . charinfo.lastname ,
online = true
} )
found = true
break
end
end
-- If not online, get from database
if not found then
local result = MySQL.Sync . fetchAll ( ' SELECT charinfo FROM players WHERE citizenid = ? ' , { citizenid } )
if result and result [ 1 ] then
local charinfo = json.decode ( result [ 1 ] . charinfo )
table.insert ( managersList , {
citizenid = citizenid ,
name = charinfo.firstname .. ' ' .. charinfo.lastname ,
online = false
} )
else
table.insert ( managersList , {
citizenid = citizenid ,
name = " Unbekannt " ,
online = false
} )
end
end
end
end
cb ( managersList )
end )
2025-07-29 10:26:42 +02:00
-- Start robbery
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:startRobbery ' , function ( coords )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
local machine = vendingMachines [ machineId ]
-- Check if player has required item
local hasItem = Player.Functions . GetItemByName ( Config.RobberyItem )
if not hasItem or hasItem.amount < 1 then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du benötigst einen ' .. Config.RobberyItem , ' error ' )
return
end
-- Check if already being robbed
if robberyInProgress [ machineId ] then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Dieser Automat wird bereits aufgebrochen! ' , ' error ' )
return
end
-- Check if machine has money
if machine.money < Config.MinRobberyAmount then
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Nicht genug Geld im Automaten! ' , ' error ' )
return
end
robberyInProgress [ machineId ] = true
2025-07-29 23:31:23 +02:00
-- Alert police - use a generic location name instead of street name
local locationName = " Verkaufsautomat # " .. machineId
2025-07-29 10:26:42 +02:00
2025-07-30 00:27:25 +02:00
-- Get player position for more accurate location
local playerPos = GetEntityCoords ( GetPlayerPed ( src ) )
-- Alert police with enhanced data
local alertData = {
coords = coords ,
locationName = locationName ,
machineId = machineId
}
2025-07-29 10:26:42 +02:00
local players = QBCore.Functions . GetQBPlayers ( )
for k , v in pairs ( players ) do
if v.PlayerData . job.name == ' police ' and v.PlayerData . job.onduty then
2025-07-30 00:27:25 +02:00
TriggerClientEvent ( ' vending:client:policeAlert ' , v.PlayerData . source , alertData )
2025-07-29 10:26:42 +02:00
end
end
-- Alert owner and managers
for _ , playerId in ipairs ( QBCore.Functions . GetPlayers ( ) ) do
local targetPlayer = QBCore.Functions . GetPlayer ( playerId )
if targetPlayer then
if targetPlayer.PlayerData . citizenid == machine.owner then
2025-07-29 23:31:23 +02:00
TriggerClientEvent ( ' QBCore:Notify ' , targetPlayer.PlayerData . source , ' Dein Verkaufsautomat wird gerade aufgebrochen! Standort: ' .. locationName , ' error ' , 10000 )
2025-07-29 10:26:42 +02:00
elseif machine.managers then
for _ , manager in pairs ( machine.managers ) do
if targetPlayer.PlayerData . citizenid == manager then
2025-07-29 23:31:23 +02:00
TriggerClientEvent ( ' QBCore:Notify ' , targetPlayer.PlayerData . source , ' Ein Verkaufsautomat, den du verwaltest, wird gerade aufgebrochen! Standort: ' .. locationName , ' error ' , 10000 )
2025-07-29 10:26:42 +02:00
break
end
end
end
end
end
2025-07-29 10:53:08 +02:00
TriggerClientEvent ( ' vending:client:startRobbery ' , src , coords )
2025-07-29 10:26:42 +02:00
end )
2025-07-30 00:27:25 +02:00
2025-07-29 10:26:42 +02:00
-- Complete robbery
2025-07-29 10:53:08 +02:00
RegisterNetEvent ( ' vending:server:completeRobbery ' , function ( coords , success )
2025-07-29 10:26:42 +02:00
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then return end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then return end
2025-07-29 10:26:42 +02:00
local machine = vendingMachines [ machineId ]
robberyInProgress [ machineId ] = false
if success then
local stolenAmount = math.random ( Config.MinRobberyAmount , math.min ( machine.money , Config.MaxRobberyAmount ) )
-- Remove money from machine
machine.money = machine.money - stolenAmount
MySQL.update ( ' UPDATE vending_machines SET money = ? WHERE id = ? ' , { machine.money , machineId } )
-- Give money to player
Player.Functions . AddMoney ( ' cash ' , stolenAmount )
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Du hast $ ' .. stolenAmount .. ' gestohlen! ' , ' success ' )
-- Remove robbery item with chance
if math.random ( 1 , 100 ) <= Config.RobberyItemBreakChance then
Player.Functions . RemoveItem ( Config.RobberyItem , 1 )
TriggerClientEvent ( ' inventory:client:ItemBox ' , src , QBCore.Shared . Items [ Config.RobberyItem ] , ' remove ' )
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Dein ' .. Config.RobberyItem .. ' ist kaputt gegangen! ' , ' error ' )
end
else
TriggerClientEvent ( ' QBCore:Notify ' , src , ' Aufbruch fehlgeschlagen! ' , ' error ' )
end
end )
2025-07-29 10:53:08 +02:00
-- Helper function to get machine ID by coordinates
function getMachineIdByCoords ( coords )
2025-07-29 23:31:23 +02:00
-- Ensure coords is properly formatted
local x , y , z
if coords and coords.x ~= nil and coords.y ~= nil and coords.z ~= nil then
x , y , z = coords.x , coords.y , coords.z
else
-- Handle case where coords might be a table without x,y,z properties
return nil
end
2025-07-29 10:53:08 +02:00
for id , machine in pairs ( vendingMachines ) do
2025-07-29 23:31:23 +02:00
-- Ensure machine coords are properly formatted
if machine.coords and machine.coords . x and machine.coords . y and machine.coords . z then
local dist = # ( vector3 ( x , y , z ) - vector3 ( machine.coords . x , machine.coords . y , machine.coords . z ) )
if dist < 2.0 then
return id
end
2025-07-29 10:53:08 +02:00
end
end
return nil
end
2025-07-29 10:26:42 +02:00
-- Get machine data by coordinates
2025-07-29 10:53:08 +02:00
QBCore.Functions . CreateCallback ( ' vending:server:getMachineByCoords ' , function ( source , cb , coords )
local machineId = getMachineIdByCoords ( coords )
2025-07-29 10:26:42 +02:00
if machineId then
cb ( vendingMachines [ machineId ] )
else
cb ( nil )
end
end )
-- Get stash items for vending machine menu
2025-07-29 10:53:08 +02:00
QBCore.Functions . CreateCallback ( ' vending:server:getStashItems ' , function ( source , cb , coords )
local machineId = getMachineIdByCoords ( coords )
2025-07-29 10:26:42 +02:00
if not machineId then
cb ( { } )
return
end
local machine = vendingMachines [ machineId ]
-- Get stash items using correct export
local stashItems = exports [ " tgiann-inventory " ] : GetSecondaryInventoryItems ( " stash " , machine.stash )
local items = { }
if stashItems then
for slot , item in pairs ( stashItems ) do
if item.amount > 0 then
item.price = machine.prices [ item.name ] or Config.DefaultPrice
table.insert ( items , item )
end
end
end
cb ( items )
end )
2025-07-29 10:53:08 +02:00
-- Check if player owns machine
QBCore.Functions . CreateCallback ( ' vending:server:isOwner ' , function ( source , cb , coords )
local Player = QBCore.Functions . GetPlayer ( source )
if not Player then
cb ( false )
2025-07-29 10:26:42 +02:00
return
end
2025-07-29 10:53:08 +02:00
local machineId = getMachineIdByCoords ( coords )
if not machineId then
cb ( false )
return
2025-07-29 10:26:42 +02:00
end
2025-07-29 10:53:08 +02:00
local machine = vendingMachines [ machineId ]
cb ( machine.owner == Player.PlayerData . citizenid )
2025-07-29 10:26:42 +02:00
end )
-- Check if player can manage machine
2025-07-29 10:53:08 +02:00
QBCore.Functions . CreateCallback ( ' vending:server:canManage ' , function ( source , cb , coords )
local Player = QBCore.Functions . GetPlayer ( source )
if not Player then
cb ( false )
return
end
local machineId = getMachineIdByCoords ( coords )
2025-07-29 10:26:42 +02:00
if not machineId then
cb ( false )
return
end
cb ( canManageMachine ( source , machineId ) )
end )
2025-07-29 10:53:08 +02:00
-- Check if machine exists at coords
QBCore.Functions . CreateCallback ( ' vending:server:machineExists ' , function ( source , cb , coords )
local machineId = getMachineIdByCoords ( coords )
cb ( machineId ~= nil )
end )
2025-07-29 10:26:42 +02:00
-- Get online players for manager selection
QBCore.Functions . CreateCallback ( ' vending:server:getOnlinePlayers ' , function ( source , cb )
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then
cb ( { } )
return
end
local players = { }
local onlinePlayers = QBCore.Functions . GetPlayers ( )
for _ , playerId in ipairs ( onlinePlayers ) do
local targetPlayer = QBCore.Functions . GetPlayer ( playerId )
if targetPlayer and targetPlayer.PlayerData . source ~= src then
table.insert ( players , {
id = targetPlayer.PlayerData . source ,
name = targetPlayer.PlayerData . charinfo.firstname .. ' ' .. targetPlayer.PlayerData . charinfo.lastname ,
citizenid = targetPlayer.PlayerData . citizenid
} )
end
end
cb ( players )
end )
-- Debug command
QBCore.Commands . Add ( ' vendingdebug ' , ' Debug vending machines (Admin Only) ' , { } , false , function ( source , args )
local Player = QBCore.Functions . GetPlayer ( source )
if Player.PlayerData . permission == " admin " or Player.PlayerData . permission == " god " then
local count = 0
for id , machine in pairs ( vendingMachines ) do
count = count + 1
print ( " ^2[VENDING]^7 Machine # " .. id .. " | Owner: " .. machine.owner .. " | Money: $ " .. machine.money )
end
TriggerClientEvent ( ' QBCore:Notify ' , source , count .. ' Verkaufsautomaten geladen ' , ' success ' )
else
TriggerClientEvent ( ' QBCore:Notify ' , source , ' Keine Berechtigung! ' , ' error ' )
end
end , ' admin ' )
2025-07-29 23:24:42 +02:00
-- Combined callback for faster machine status checks
QBCore.Functions . CreateCallback ( ' vending:server:getMachineStatus ' , function ( source , cb , coords )
local src = source
local Player = QBCore.Functions . GetPlayer ( src )
if not Player then
cb ( nil )
return
end
local machineId = getMachineIdByCoords ( coords )
if not machineId then
cb ( { exists = false , canManage = false } )
return
end
local machine = vendingMachines [ machineId ]
local canManage = false
-- Check if player is owner
if machine.owner == Player.PlayerData . citizenid then
canManage = true
else
-- Check if player is manager
if machine.managers then
for _ , manager in pairs ( machine.managers ) do
if manager == Player.PlayerData . citizenid then
canManage = true
break
end
end
end
end
cb ( { exists = true , canManage = canManage } )
end )