1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-29 10:53:08 +02:00
parent e73fc734a3
commit 8110c00382
2 changed files with 497 additions and 582 deletions

View file

@ -1,108 +1,138 @@
local QBCore = exports['qb-core']:GetCoreObject() local QBCore = exports['qb-core']:GetCoreObject()
local nearbyMachines = {}
local currentMachine = nil
local showingMenu = false
-- Kontinuierlicher Check für Verkaufsautomaten -- Function to initialize targets
function InitializeTargets()
-- Remove existing targets first to avoid duplicates
exports['qb-target']:RemoveTargetModel(Config.VendingProps)
Wait(100)
-- Add targets
exports['qb-target']:AddTargetModel(Config.VendingProps, {
options = {
{
type = "client",
event = "vending:client:buyMachine",
icon = "fas fa-dollar-sign",
label = "Automaten kaufen ($" .. Config.VendingMachinePrice .. ")",
canInteract = function(entity)
return not isRegisteredMachine(entity)
end
},
{
type = "client",
event = "vending:client:openBuyMenu",
icon = "fas fa-shopping-cart",
label = "Kaufen",
canInteract = function(entity)
return isRegisteredMachine(entity)
end
},
{
type = "client",
event = "vending:client:openOwnerMenu",
icon = "fas fa-cog",
label = "Verwalten",
canInteract = function(entity)
return canManageMachine(entity)
end
},
{
type = "client",
event = "vending:client:startRobbery",
icon = "fas fa-mask",
label = "Aufbrechen",
canInteract = function(entity)
return isRegisteredMachine(entity) and not canManageMachine(entity)
end
}
},
distance = 2.0
})
print("^2[VENDING]^7 Added targets to " .. #Config.VendingProps .. " vending machine props")
end
-- Add targets to all vending machine props with multiple attempts (Option 1)
CreateThread(function() CreateThread(function()
while true do -- First attempt
local playerPed = PlayerPedId() Wait(2000)
local playerCoords = GetEntityCoords(playerPed) InitializeTargets()
local sleep = 1000
-- Reset current machine -- Second attempt after a delay
currentMachine = nil Wait(5000)
InitializeTargets()
-- Check for nearby vending machines -- Third attempt after server is fully loaded
local objects = GetGamePool('CObject') Wait(10000)
for _, obj in ipairs(objects) do InitializeTargets()
local model = GetEntityModel(obj) end)
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 -- Event-based initialization (Option 2)
currentMachine = obj RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
sleep = 0 Wait(1000)
InitializeTargets()
end)
-- Show help text RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
if not showingMenu then -- Nothing to do here, but good to have for completeness
DrawText3D(objCoords.x, objCoords.y, objCoords.z + 1.5, "[E] Verkaufsautomat") end)
if IsControlJustPressed(0, 38) then -- E key -- Listen for resource start/stop events
handleMachineInteraction(obj) AddEventHandler('onResourceStart', function(resourceName)
end if resourceName == 'qb-target' or resourceName == GetCurrentResourceName() then
end Wait(1000)
break InitializeTargets()
end
end
end
if currentMachine then break end
end
Wait(sleep)
end end
end) end)
-- 3D Text function -- Command to manually refresh targets
function DrawText3D(x, y, z, text) RegisterCommand('refreshvendingtargets', function()
local onScreen, _x, _y = World3dToScreen2d(x, y, z) InitializeTargets()
local px, py, pz = table.unpack(GetGameplayCamCoords()) QBCore.Functions.Notify('Vending machine targets refreshed', 'success')
end, false)
if onScreen then -- Check if machine is registered
SetTextScale(0.35, 0.35) function isRegisteredMachine(entity)
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)
end
end
-- Get precise coordinates for entity
function getPreciseCoords(entity)
local coords = GetEntityCoords(entity) local coords = GetEntityCoords(entity)
local heading = GetEntityHeading(entity) local isRegistered = false
local model = GetEntityModel(entity)
return {
x = coords.x,
y = coords.y,
z = coords.z,
h = heading,
model = model
}
end
-- Handle machine interaction
function handleMachineInteraction(entity)
showingMenu = true
local preciseCoords = getPreciseCoords(entity)
-- Check if machine is registered
QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists)
if exists then isRegistered = exists
-- Check if player can manage end, coords)
QBCore.Functions.TriggerCallback('vending:server:canManage', function(canManage)
if canManage then -- Wait for callback (not ideal but works for canInteract)
showOwnerMenu(entity, preciseCoords) local timeout = 0
else while isRegistered == false and timeout < 100 do
showBuyMenu(entity, preciseCoords) Wait(10)
timeout = timeout + 1
end end
end, preciseCoords)
else return isRegistered
showPurchaseMenu(entity, preciseCoords)
end
end, preciseCoords)
end end
-- Show purchase menu (buy the machine) -- Check if player can manage machine
function showPurchaseMenu(entity, preciseCoords) function canManageMachine(entity)
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
return canManage
end
-- Buy vending machine
RegisterNetEvent('vending:client:buyMachine', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
local model = GetEntityModel(entity) local model = GetEntityModel(entity)
local prop = nil local prop = nil
@ -114,67 +144,39 @@ function showPurchaseMenu(entity, preciseCoords)
end end
end end
if not prop then if not prop then return end
showingMenu = false
return
end
lib.registerContext({ lib.registerContext({
id = 'vending_purchase', id = 'vending_buy_confirm',
title = 'Verkaufsautomat', title = 'Verkaufsautomat kaufen',
options = {
{
title = 'Automaten kaufen',
description = 'Kaufe diesen Automaten für $' .. Config.VendingMachinePrice,
icon = 'fas fa-dollar-sign',
onSelect = function()
lib.registerContext({
id = 'vending_purchase_confirm',
title = 'Kauf bestätigen',
menu = 'vending_purchase',
options = { options = {
{ {
title = 'Bestätigen', title = 'Bestätigen',
description = 'Automaten für $' .. Config.VendingMachinePrice .. ' kaufen', description = 'Automaten für $' .. Config.VendingMachinePrice .. ' kaufen',
icon = 'fas fa-check', icon = 'fas fa-check',
onSelect = function() onSelect = function()
TriggerServerEvent('vending:server:registerMachine', preciseCoords, prop) TriggerServerEvent('vending:server:registerMachine', coords, prop)
showingMenu = false
end end
}, },
{ {
title = 'Abbrechen', title = 'Abbrechen',
description = 'Kauf abbrechen', description = 'Kauf abbrechen',
icon = 'fas fa-times', icon = 'fas fa-times'
onSelect = function()
showingMenu = false
end
}
}
})
lib.showContext('vending_purchase_confirm')
end
},
{
title = 'Schließen',
description = 'Menü schließen',
icon = 'fas fa-times',
onSelect = function()
showingMenu = false
end
} }
} }
}) })
lib.showContext('vending_purchase') lib.showContext('vending_buy_confirm')
end end)
-- Open buy menu with quantity selection
RegisterNetEvent('vending:client:openBuyMenu', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
-- Show buy menu (buy items from machine)
function showBuyMenu(entity, preciseCoords)
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then if #items == 0 then
QBCore.Functions.Notify('Dieser Automat ist leer!', 'error') QBCore.Functions.Notify('Dieser Automat ist leer!', 'error')
showingMenu = false
return return
end end
@ -189,58 +191,14 @@ function showBuyMenu(entity, preciseCoords)
description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount, description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount,
icon = 'fas fa-shopping-cart', icon = 'fas fa-shopping-cart',
onSelect = function() onSelect = function()
openQuantityDialog(preciseCoords, item.name, item.price, item.amount, itemLabel) openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel)
end end
}) })
end end
end end
-- Add robbery option if #options == 0 then
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
QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error') QBCore.Functions.Notify('Keine Artikel verfügbar!', 'error')
showingMenu = false
return return
end end
@ -251,15 +209,41 @@ function showBuyMenu(entity, preciseCoords)
}) })
lib.showContext('vending_buy_menu') lib.showContext('vending_buy_menu')
end, preciseCoords) end, coords)
end)
-- Open quantity dialog for buying items
function openQuantityDialog(coords, itemName, price, maxAmount, itemLabel)
local input = lib.inputDialog('Menge auswählen', {
{
type = 'number',
label = itemLabel .. ' - $' .. price .. ' pro Stück',
description = 'Wie viele möchtest du kaufen? (Max: ' .. maxAmount .. ')',
required = true,
min = 1,
max = maxAmount,
default = 1
}
})
if input and input[1] then
local amount = tonumber(input[1])
if amount > 0 and amount <= maxAmount then
TriggerServerEvent('vending:server:buyItem', coords, itemName, amount)
else
QBCore.Functions.Notify('Ungültige Menge!', 'error')
end
end
end end
-- Show owner menu -- Open owner menu
function showOwnerMenu(entity, preciseCoords) RegisterNetEvent('vending:client:openOwnerMenu', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine) QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
if not machine then if not machine then
QBCore.Functions.Notify('Automat nicht gefunden!', 'error') QBCore.Functions.Notify('Automat nicht gefunden!', 'error')
showingMenu = false
return return
end end
@ -269,8 +253,7 @@ function showOwnerMenu(entity, preciseCoords)
description = 'Items hinzufügen/entfernen', description = 'Items hinzufügen/entfernen',
icon = 'fas fa-box', icon = 'fas fa-box',
onSelect = function() onSelect = function()
TriggerServerEvent('vending:server:openStash', preciseCoords) TriggerServerEvent('vending:server:openStash', coords)
showingMenu = false
end end
}, },
{ {
@ -278,7 +261,7 @@ function showOwnerMenu(entity, preciseCoords)
description = 'Verkaufspreise für Items setzen', description = 'Verkaufspreise für Items setzen',
icon = 'fas fa-tags', icon = 'fas fa-tags',
onSelect = function() onSelect = function()
openPriceMenu(preciseCoords) openPriceMenu(coords)
end end
}, },
{ {
@ -286,7 +269,7 @@ function showOwnerMenu(entity, preciseCoords)
description = 'Verfügbar: $' .. machine.money, description = 'Verfügbar: $' .. machine.money,
icon = 'fas fa-money-bill', icon = 'fas fa-money-bill',
onSelect = function() onSelect = function()
openWithdrawMenu(preciseCoords, machine.money) openWithdrawMenu(coords, machine.money)
end end
}, },
{ {
@ -306,30 +289,21 @@ function showOwnerMenu(entity, preciseCoords)
description = 'Verwalter hinzufügen/entfernen', description = 'Verwalter hinzufügen/entfernen',
icon = 'fas fa-users-cog', icon = 'fas fa-users-cog',
onSelect = function() onSelect = function()
openManagersMenu(preciseCoords) openManagersMenu(coords)
end end
}) })
-- Add sell option only for owner -- Add sell option only for owner
table.insert(options, { table.insert(options, {
title = 'Automaten verkaufen', title = 'Automaten verkaufen',
description = 'Verkaufe den Automaten für $' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100), description = 'Verkaufe den Automaten für ' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. '$',
icon = 'fas fa-dollar-sign', icon = 'fas fa-dollar-sign',
onSelect = function() onSelect = function()
sellVendingMachine(preciseCoords, machine.id) sellVendingMachine(coords, machine.id)
end end
}) })
end end
table.insert(options, {
title = 'Schließen',
description = 'Menü schließen',
icon = 'fas fa-times',
onSelect = function()
showingMenu = false
end
})
lib.registerContext({ lib.registerContext({
id = 'vending_owner_menu', id = 'vending_owner_menu',
title = 'Verkaufsautomat Verwaltung', title = 'Verkaufsautomat Verwaltung',
@ -337,59 +311,30 @@ function showOwnerMenu(entity, preciseCoords)
}) })
lib.showContext('vending_owner_menu') lib.showContext('vending_owner_menu')
end, preciseCoords) end, coords)
end 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
-- Funktion zum Verkaufen des Automaten -- Funktion zum Verkaufen des Automaten
function sellVendingMachine(preciseCoords, machineId) function sellVendingMachine(coords, machineId)
local input = lib.inputDialog('Automaten verkaufen', { local input = lib.inputDialog('Automaten verkaufen', {
{ {
type = 'checkbox', type = 'checkbox',
label = 'Bestätigen', label = 'Bestätigen',
description = 'Du erhältst $' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. ' zurück. Diese Aktion kann nicht rückgängig gemacht werden!', description = 'Du erhältst ' .. math.floor(Config.VendingMachinePrice * Config.SellBackPercentage / 100) .. '$ zurück. Diese Aktion kann nicht rückgängig gemacht werden!',
required = true required = true
} }
}) })
if input and input[1] then if input and input[1] then
TriggerServerEvent('vending:server:sellMachine', preciseCoords, machineId) TriggerServerEvent('vending:server:sellMachine', coords, machineId)
end end
showingMenu = false
end end
-- Open price menu -- Open price menu
function openPriceMenu(preciseCoords) function openPriceMenu(coords)
QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items)
if #items == 0 then if #items == 0 then
QBCore.Functions.Notify('Keine Items im Automaten!', 'error') QBCore.Functions.Notify('Keine Items im Automaten!', 'error')
showingMenu = false
return return
end end
@ -403,32 +348,24 @@ function openPriceMenu(preciseCoords)
description = 'Aktueller Preis: $' .. item.price, description = 'Aktueller Preis: $' .. item.price,
icon = 'fas fa-tag', icon = 'fas fa-tag',
onSelect = function() onSelect = function()
setPriceForItem(preciseCoords, item.name, itemLabel) setPriceForItem(coords, item.name, itemLabel)
end end
}) })
end end
table.insert(options, {
title = 'Zurück',
description = 'Zurück zum Hauptmenü',
icon = 'fas fa-arrow-left',
onSelect = function()
showOwnerMenu(currentMachine, preciseCoords)
end
})
lib.registerContext({ lib.registerContext({
id = 'vending_price_menu', id = 'vending_price_menu',
title = 'Preise festlegen', title = 'Preise festlegen',
menu = 'vending_owner_menu',
options = options options = options
}) })
lib.showContext('vending_price_menu') lib.showContext('vending_price_menu')
end, preciseCoords) end, coords)
end end
-- Set price for specific item -- Set price for specific item
function setPriceForItem(preciseCoords, itemName, itemLabel) function setPriceForItem(coords, itemName, itemLabel)
local input = lib.inputDialog('Preis festlegen', { local input = lib.inputDialog('Preis festlegen', {
{ {
type = 'number', type = 'number',
@ -441,17 +378,14 @@ function setPriceForItem(preciseCoords, itemName, itemLabel)
}) })
if input and input[1] then if input and input[1] then
TriggerServerEvent('vending:server:setItemPrice', preciseCoords, itemName, tonumber(input[1])) TriggerServerEvent('vending:server:setItemPrice', coords, itemName, tonumber(input[1]))
end end
showingMenu = false
end end
-- Open withdraw menu -- Open withdraw menu
function openWithdrawMenu(preciseCoords, availableMoney) function openWithdrawMenu(coords, availableMoney)
if availableMoney <= 0 then if availableMoney <= 0 then
QBCore.Functions.Notify('Kein Geld im Automaten!', 'error') QBCore.Functions.Notify('Kein Geld im Automaten!', 'error')
showingMenu = false
return return
end end
@ -467,10 +401,8 @@ function openWithdrawMenu(preciseCoords, availableMoney)
}) })
if input and input[1] then if input and input[1] then
TriggerServerEvent('vending:server:withdrawMoney', preciseCoords, tonumber(input[1])) TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1]))
end end
showingMenu = false
end end
-- Open stats menu -- Open stats menu
@ -478,6 +410,7 @@ function openStatsMenu(machine)
lib.registerContext({ lib.registerContext({
id = 'vending_stats_menu', id = 'vending_stats_menu',
title = 'Verkaufsstatistiken', title = 'Verkaufsstatistiken',
menu = 'vending_owner_menu',
options = { options = {
{ {
title = 'Gesamteinnahmen', title = 'Gesamteinnahmen',
@ -493,14 +426,6 @@ function openStatsMenu(machine)
title = 'Standort', title = 'Standort',
description = 'X: ' .. math.floor(machine.coords.x) .. ' Y: ' .. math.floor(machine.coords.y), description = 'X: ' .. math.floor(machine.coords.x) .. ' Y: ' .. math.floor(machine.coords.y),
icon = 'fas fa-map-marker-alt' icon = 'fas fa-map-marker-alt'
},
{
title = 'Zurück',
description = 'Zurück zum Hauptmenü',
icon = 'fas fa-arrow-left',
onSelect = function()
showOwnerMenu(currentMachine, machine.coords)
end
} }
} }
}) })
@ -509,7 +434,8 @@ function openStatsMenu(machine)
end end
-- Open managers menu -- Open managers menu
function openManagersMenu(preciseCoords) function openManagersMenu(coords)
-- Get current managers
QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers) QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers)
local options = { local options = {
{ {
@ -517,43 +443,38 @@ function openManagersMenu(preciseCoords)
description = 'Neuen Verwalter hinzufügen', description = 'Neuen Verwalter hinzufügen',
icon = 'fas fa-user-plus', icon = 'fas fa-user-plus',
onSelect = function() onSelect = function()
openAddManagerMenu(preciseCoords) openAddManagerMenu(coords)
end end
} }
} }
-- Add existing managers with remove option
if #managers > 0 then if #managers > 0 then
for i = 1, #managers do for i = 1, #managers do
local manager = managers[i] local manager = managers[i]
table.insert(options, { table.insert(options, {
title = manager.name, title = manager.name,
description = manager.online and 'Online - Klicken zum Entfernen' or 'Offline - Klicken zum Entfernen', description = manager.online and 'Online' or 'Offline',
icon = manager.online and 'fas fa-circle text-success' or 'fas fa-circle text-danger', icon = manager.online and 'fas fa-circle text-success' or 'fas fa-circle text-danger',
onSelect = function() onSelect = function()
lib.registerContext({ lib.registerContext({
id = 'manager_confirm_remove', id = 'manager_options',
title = 'Verwalter entfernen', title = 'Verwalter: ' .. manager.name,
menu = 'managers_menu',
options = { options = {
{ {
title = 'Bestätigen', title = 'Entfernen',
description = manager.name .. ' als Verwalter entfernen', description = 'Verwalter entfernen',
icon = 'fas fa-check', icon = 'fas fa-user-minus',
onSelect = function() onSelect = function()
TriggerServerEvent('vending:server:removeManager', preciseCoords, manager.citizenid) TriggerServerEvent('vending:server:removeManager', coords, manager.citizenid)
showingMenu = false Wait(500)
end openManagersMenu(coords) -- Refresh the menu
},
{
title = 'Abbrechen',
description = 'Zurück zur Verwalterliste',
icon = 'fas fa-times',
onSelect = function()
openManagersMenu(preciseCoords)
end end
} }
} }
}) })
lib.showContext('manager_confirm_remove') lib.showContext('manager_options')
end end
}) })
end end
@ -566,31 +487,22 @@ function openManagersMenu(preciseCoords)
}) })
end end
table.insert(options, {
title = 'Zurück',
description = 'Zurück zum Hauptmenü',
icon = 'fas fa-arrow-left',
onSelect = function()
showOwnerMenu(currentMachine, preciseCoords)
end
})
lib.registerContext({ lib.registerContext({
id = 'managers_menu', id = 'managers_menu',
title = 'Verwalter verwalten', title = 'Verwalter verwalten',
menu = 'vending_owner_menu',
options = options options = options
}) })
lib.showContext('managers_menu') lib.showContext('managers_menu')
end, preciseCoords) end, coords)
end end
-- Open add manager menu -- Open add manager menu
function openAddManagerMenu(preciseCoords) function openAddManagerMenu(coords)
QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players) QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players)
if #players == 0 then if #players == 0 then
QBCore.Functions.Notify('Keine Spieler online!', 'error') QBCore.Functions.Notify('Keine Spieler online!', 'error')
showingMenu = false
return return
end end
@ -603,24 +515,17 @@ function openAddManagerMenu(preciseCoords)
description = 'ID: ' .. player.id, description = 'ID: ' .. player.id,
icon = 'fas fa-user', icon = 'fas fa-user',
onSelect = function() onSelect = function()
TriggerServerEvent('vending:server:addManager', preciseCoords, player.id) TriggerServerEvent('vending:server:addManager', coords, player.id)
showingMenu = false Wait(500)
openManagersMenu(coords) -- Refresh the menu
end end
}) })
end end
table.insert(options, {
title = 'Zurück',
description = 'Zurück zur Verwalterliste',
icon = 'fas fa-arrow-left',
onSelect = function()
openManagersMenu(preciseCoords)
end
})
lib.registerContext({ lib.registerContext({
id = 'add_manager_menu', id = 'add_manager_menu',
title = 'Verwalter hinzufügen', title = 'Verwalter hinzufügen',
menu = 'managers_menu',
options = options options = options
}) })
@ -628,8 +533,36 @@ function openAddManagerMenu(preciseCoords)
end) end)
end end
-- Robbery menu
RegisterNetEvent('vending:client:startRobbery', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
lib.registerContext({
id = 'vending_robbery_confirm',
title = 'Verkaufsautomat aufbrechen',
options = {
{
title = 'Aufbrechen',
description = 'Versuche den Automaten aufzubrechen',
icon = 'fas fa-mask',
onSelect = function()
TriggerServerEvent('vending:server:startRobbery', coords)
end
},
{
title = 'Abbrechen',
description = 'Aufbruch abbrechen',
icon = 'fas fa-times'
}
}
})
lib.showContext('vending_robbery_confirm')
end)
-- Start robbery animation and progress -- Start robbery animation and progress
RegisterNetEvent('vending:client:startRobbery', function(preciseCoords) RegisterNetEvent('vending:client:startRobbery', function(coords)
local playerPed = PlayerPedId() local playerPed = PlayerPedId()
local robberyTime = 10000 -- 10 seconds local robberyTime = 10000 -- 10 seconds
@ -656,17 +589,23 @@ RegisterNetEvent('vending:client:startRobbery', function(preciseCoords)
}) })
ClearPedTasks(playerPed) ClearPedTasks(playerPed)
TriggerServerEvent('vending:server:completeRobbery', preciseCoords, success) TriggerServerEvent('vending:server:completeRobbery', coords, success)
else else
-- Fallback without progress bar -- Fallback without progress bar
Wait(robberyTime) Wait(robberyTime)
ClearPedTasks(playerPed) ClearPedTasks(playerPed)
TriggerServerEvent('vending:server:completeRobbery', preciseCoords, true) TriggerServerEvent('vending:server:completeRobbery', coords, true)
end end
end) end)
-- Police alert -- Police alert
RegisterNetEvent('vending:client:policeAlert', function(coords, streetName) RegisterNetEvent('vending:client:policeAlert', function(coords, streetName)
local alert = {
title = "Verkaufsautomat Aufbruch",
coords = coords,
description = "Ein Verkaufsautomat wird aufgebrochen in " .. streetName
}
-- Add blip -- Add blip
local blip = AddBlipForCoord(coords.x, coords.y, coords.z) local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
SetBlipSprite(blip, 161) SetBlipSprite(blip, 161)
@ -685,17 +624,40 @@ RegisterNetEvent('vending:client:policeAlert', function(coords, streetName)
QBCore.Functions.Notify('Verkaufsautomat Aufbruch gemeldet: ' .. streetName, 'error', 8000) QBCore.Functions.Notify('Verkaufsautomat Aufbruch gemeldet: ' .. streetName, 'error', 8000)
end) end)
-- Event handlers for menu closing -- Refresh targets (called when new machine is registered)
RegisterNetEvent('vending:client:closeMenu', function() RegisterNetEvent('vending:client:refreshTargets', function()
showingMenu = false InitializeTargets()
end) end)
-- Close menu when inventory is opened -- Management menu (alternative opening method)
AddEventHandler('inventory:client:OpenInventory', function() RegisterNetEvent('vending:client:openManagement', function(machine)
showingMenu = false lib.registerContext({
id = 'vending_management',
title = 'Verkaufsautomat #' .. machine.id,
options = {
{
title = 'Inventar öffnen',
description = 'Items hinzufügen oder entfernen',
icon = 'fas fa-box',
onSelect = function()
TriggerServerEvent('vending:server:openStash', machine.coords)
end
},
{
title = 'Einnahmen: $' .. machine.money,
description = 'Geld abheben',
icon = 'fas fa-money-bill',
onSelect = function()
openWithdrawMenu(machine.coords, machine.money)
end
}
}
})
lib.showContext('vending_management')
end) end)
-- Debug commands -- Debug command to check props
RegisterCommand('checkvendingprops', function() RegisterCommand('checkvendingprops', function()
local playerPed = PlayerPedId() local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed) local playerCoords = GetEntityCoords(playerPed)
@ -714,9 +676,7 @@ RegisterCommand('checkvendingprops', function()
if dist < 30.0 then if dist < 30.0 then
foundProps = foundProps + 1 foundProps = foundProps + 1
local preciseCoords = getPreciseCoords(obj) print("Found " .. propName .. " at distance: " .. dist)
print("Found " .. propName .. " at distance: " .. dist .. " | Coords: " ..
preciseCoords.x .. ", " .. preciseCoords.y .. ", " .. preciseCoords.z)
-- Add a temporary blip -- Add a temporary blip
local blip = AddBlipForEntity(obj) local blip = AddBlipForEntity(obj)
@ -739,41 +699,18 @@ RegisterCommand('checkvendingprops', function()
QBCore.Functions.Notify('Found ' .. foundProps .. ' vending machines nearby', 'primary') QBCore.Functions.Notify('Found ' .. foundProps .. ' vending machines nearby', 'primary')
end, false) end, false)
-- Debug commands
RegisterCommand('vendingdebug', function() RegisterCommand('vendingdebug', function()
local playerPed = PlayerPedId() local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed) local coords = GetEntityCoords(playerPed)
-- Try to find the closest vending machine
local minDist = 3.0
local closestEntity = nil
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
closestEntity = obj
end
end
end
end
if closestEntity then
local preciseCoords = getPreciseCoords(closestEntity)
QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine) QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine)
if machine then if machine then
print('Machine found:', json.encode(machine)) print('Machine found:', json.encode(machine))
QBCore.Functions.Notify('Machine #' .. machine.id .. ' | Owner: ' .. machine.owner, 'primary') QBCore.Functions.Notify('Machine data logged to console', 'primary')
else else
print('No machine found at coords:', json.encode(preciseCoords)) print('No machine found at current location')
QBCore.Functions.Notify('No machine found at these coords', 'error') QBCore.Functions.Notify('No machine found here', 'error')
end
end, preciseCoords)
else
QBCore.Functions.Notify('No vending machine found nearby', 'error')
end end
end, coords)
end, false) end, false)

View file

@ -24,46 +24,16 @@ CreateThread(function()
end end
end) end)
-- Helper function to get machine ID by precise coordinates
function getMachineIdByCoords(preciseCoords)
-- First try to find an exact match
for id, machine in pairs(vendingMachines) do
if machine.coords.x == preciseCoords.x and
machine.coords.y == preciseCoords.y and
machine.coords.z == preciseCoords.z and
machine.coords.model == preciseCoords.model then
return id
end
end
-- If no exact match, try with a small tolerance
local closestId = nil
local closestDist = 0.1 -- Very small tolerance
for id, machine in pairs(vendingMachines) do
if machine.coords.model == preciseCoords.model then
local dist = #(vector3(preciseCoords.x, preciseCoords.y, preciseCoords.z) - vector3(machine.coords.x, machine.coords.y, machine.coords.z))
if dist < closestDist then
closestDist = dist
closestId = id
end
end
end
return closestId
end
-- Register vending machine (when player buys it) -- Register vending machine (when player buys it)
RegisterNetEvent('vending:server:registerMachine', function(preciseCoords, prop) RegisterNetEvent('vending:server:registerMachine', function(coords, prop)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
-- Check if there's already a machine at these coords -- Check if there's already a machine at these coords
for id, machine in pairs(vendingMachines) do for id, machine in pairs(vendingMachines) do
if machine.coords.x == preciseCoords.x and local dist = #(vector3(coords.x, coords.y, coords.z) - vector3(machine.coords.x, machine.coords.y, machine.coords.z))
machine.coords.y == preciseCoords.y and if dist < 2.0 then
machine.coords.z == preciseCoords.z then
TriggerClientEvent('QBCore:Notify', src, 'Hier ist bereits ein Automat registriert!', 'error') TriggerClientEvent('QBCore:Notify', src, 'Hier ist bereits ein Automat registriert!', 'error')
return return
end end
@ -81,7 +51,7 @@ RegisterNetEvent('vending:server:registerMachine', function(preciseCoords, prop)
-- Create machine in database -- Create machine in database
local machineId = MySQL.insert.await('INSERT INTO vending_machines (owner, coords, prop, money, items, prices, managers) VALUES (?, ?, ?, ?, ?, ?, ?)', { local machineId = MySQL.insert.await('INSERT INTO vending_machines (owner, coords, prop, money, items, prices, managers) VALUES (?, ?, ?, ?, ?, ?, ?)', {
Player.PlayerData.citizenid, Player.PlayerData.citizenid,
json.encode(preciseCoords), json.encode(coords),
prop, prop,
0, 0,
json.encode({}), json.encode({}),
@ -93,7 +63,7 @@ RegisterNetEvent('vending:server:registerMachine', function(preciseCoords, prop)
vendingMachines[machineId] = { vendingMachines[machineId] = {
id = machineId, id = machineId,
owner = Player.PlayerData.citizenid, owner = Player.PlayerData.citizenid,
coords = preciseCoords, coords = coords,
prop = prop, prop = prop,
money = 0, money = 0,
items = {}, items = {},
@ -102,19 +72,19 @@ RegisterNetEvent('vending:server:registerMachine', function(preciseCoords, prop)
stash = 'vending_' .. machineId stash = 'vending_' .. machineId
} }
print("^2[VENDING]^7 New vending machine registered: #" .. machineId) print("^2[VENDING]^7 New vending machine registered: " .. machineId)
TriggerClientEvent('QBCore:Notify', src, 'Verkaufsautomat erfolgreich gekauft für $' .. Config.VendingMachinePrice .. '!', 'success') TriggerClientEvent('QBCore:Notify', src, 'Verkaufsautomat erfolgreich gekauft für $' .. Config.VendingMachinePrice .. '!', 'success')
TriggerClientEvent('vending:client:refreshTargets', -1) TriggerClientEvent('vending:client:refreshTargets', -1)
end) end)
-- Sell vending machine -- Sell vending machine
RegisterNetEvent('vending:server:sellMachine', function(preciseCoords, machineId) RegisterNetEvent('vending:server:sellMachine', function(coords, machineId)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
if not machineId then if not machineId then
machineId = getMachineIdByCoords(preciseCoords) machineId = getMachineIdByCoords(coords)
end end
if not machineId then if not machineId then
@ -194,16 +164,13 @@ function canManageMachine(playerId, machineId)
end end
-- Open management menu -- Open management menu
RegisterNetEvent('vending:server:openManagement', function(preciseCoords) RegisterNetEvent('vending:server:openManagement', function(coords)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
local machine = vendingMachines[machineId] local machine = vendingMachines[machineId]
@ -220,16 +187,13 @@ RegisterNetEvent('vending:server:openManagement', function(preciseCoords)
end) end)
-- Open stash -- Open stash
RegisterNetEvent('vending:server:openStash', function(preciseCoords) RegisterNetEvent('vending:server:openStash', function(coords)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
-- Check if player can manage -- Check if player can manage
if not canManageMachine(src, machineId) then if not canManageMachine(src, machineId) then
@ -246,18 +210,14 @@ RegisterNetEvent('vending:server:openStash', function(preciseCoords)
label = 'Vending Machine #' .. machine.id label = 'Vending Machine #' .. machine.id
}) })
end) end)
-- Set item price -- Set item price
RegisterNetEvent('vending:server:setItemPrice', function(preciseCoords, itemName, price) RegisterNetEvent('vending:server:setItemPrice', function(coords, itemName, price)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
-- Check if player can manage -- Check if player can manage
if not canManageMachine(src, machineId) then if not canManageMachine(src, machineId) then
@ -275,16 +235,13 @@ RegisterNetEvent('vending:server:setItemPrice', function(preciseCoords, itemName
end) end)
-- Withdraw money -- Withdraw money
RegisterNetEvent('vending:server:withdrawMoney', function(preciseCoords, amount) RegisterNetEvent('vending:server:withdrawMoney', function(coords, amount)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
-- Check if player can manage -- Check if player can manage
if not canManageMachine(src, machineId) then if not canManageMachine(src, machineId) then
@ -309,16 +266,13 @@ RegisterNetEvent('vending:server:withdrawMoney', function(preciseCoords, amount)
end) end)
-- Buy item from vending machine with quantity selection -- Buy item from vending machine with quantity selection
RegisterNetEvent('vending:server:buyItem', function(preciseCoords, itemName, amount) RegisterNetEvent('vending:server:buyItem', function(coords, itemName, amount)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
local machine = vendingMachines[machineId] local machine = vendingMachines[machineId]
local price = machine.prices[itemName] or Config.DefaultPrice local price = machine.prices[itemName] or Config.DefaultPrice
@ -381,16 +335,13 @@ RegisterNetEvent('vending:server:buyItem', function(preciseCoords, itemName, amo
end) end)
-- Add manager to vending machine -- Add manager to vending machine
RegisterNetEvent('vending:server:addManager', function(preciseCoords, targetId) RegisterNetEvent('vending:server:addManager', function(coords, targetId)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
local machine = vendingMachines[machineId] local machine = vendingMachines[machineId]
@ -428,16 +379,13 @@ RegisterNetEvent('vending:server:addManager', function(preciseCoords, targetId)
end) end)
-- Remove manager from vending machine -- Remove manager from vending machine
RegisterNetEvent('vending:server:removeManager', function(preciseCoords, citizenid) RegisterNetEvent('vending:server:removeManager', function(coords, citizenid)
local src = source local src = source
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then return end
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
local machine = vendingMachines[machineId] local machine = vendingMachines[machineId]
@ -483,148 +431,9 @@ RegisterNetEvent('vending:server:removeManager', function(preciseCoords, citizen
end end
end) end)
-- Start robbery
RegisterNetEvent('vending:server:startRobbery', function(preciseCoords)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords)
if not machineId then
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
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
-- Alert police
local streetHash = GetStreetNameAtCoord(machine.coords.x, machine.coords.y, machine.coords.z)
local streetName = GetStreetNameFromHashKey(streetHash)
local players = QBCore.Functions.GetQBPlayers()
for k, v in pairs(players) do
if v.PlayerData.job.name == 'police' and v.PlayerData.job.onduty then
TriggerClientEvent('vending:client:policeAlert', v.PlayerData.source, machine.coords, streetName)
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
TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Dein Verkaufsautomat wird gerade aufgebrochen! Standort: ' .. streetName, 'error', 10000)
elseif machine.managers then
for _, manager in pairs(machine.managers) do
if targetPlayer.PlayerData.citizenid == manager then
TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Ein Verkaufsautomat, den du verwaltest, wird gerade aufgebrochen! Standort: ' .. streetName, 'error', 10000)
break
end
end
end
end
end
TriggerClientEvent('vending:client:startRobbery', src, preciseCoords)
end)
-- Complete robbery
RegisterNetEvent('vending:server:completeRobbery', function(preciseCoords, success)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local machineId = getMachineIdByCoords(preciseCoords)
if not machineId then
TriggerClientEvent('QBCore:Notify', src, 'Automat nicht gefunden!', 'error')
return
end
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)
-- Get machine data by coordinates
QBCore.Functions.CreateCallback('vending:server:getMachineByCoords', function(source, cb, preciseCoords)
local machineId = getMachineIdByCoords(preciseCoords)
if machineId then
cb(vendingMachines[machineId])
else
cb(nil)
end
end)
-- Get stash items for vending machine menu
QBCore.Functions.CreateCallback('vending:server:getStashItems', function(source, cb, preciseCoords)
local machineId = getMachineIdByCoords(preciseCoords)
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)
-- Get managers list -- Get managers list
QBCore.Functions.CreateCallback('vending:server:getManagers', function(source, cb, preciseCoords) QBCore.Functions.CreateCallback('vending:server:getManagers', function(source, cb, coords)
local machineId = getMachineIdByCoords(preciseCoords) local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then
cb({}) cb({})
return return
@ -676,15 +485,177 @@ QBCore.Functions.CreateCallback('vending:server:getManagers', function(source, c
cb(managersList) cb(managersList)
end) end)
-- Check if machine exists -- Start robbery
QBCore.Functions.CreateCallback('vending:server:machineExists', function(source, cb, preciseCoords) RegisterNetEvent('vending:server:startRobbery', function(coords)
local machineId = getMachineIdByCoords(preciseCoords) local src = source
cb(machineId ~= nil) local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local machineId = getMachineIdByCoords(coords)
if not machineId then return end
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
-- Alert police
local streetHash = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
local streetName = GetStreetNameFromHashKey(streetHash)
local players = QBCore.Functions.GetQBPlayers()
for k, v in pairs(players) do
if v.PlayerData.job.name == 'police' and v.PlayerData.job.onduty then
TriggerClientEvent('vending:client:policeAlert', v.PlayerData.source, coords, streetName)
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
TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Dein Verkaufsautomat wird gerade aufgebrochen! Standort: ' .. streetName, 'error', 10000)
elseif machine.managers then
for _, manager in pairs(machine.managers) do
if targetPlayer.PlayerData.citizenid == manager then
TriggerClientEvent('QBCore:Notify', targetPlayer.PlayerData.source, 'Ein Verkaufsautomat, den du verwaltest, wird gerade aufgebrochen! Standort: ' .. streetName, 'error', 10000)
break
end
end
end
end
end
TriggerClientEvent('vending:client:startRobbery', src, coords)
end)
-- Complete robbery
RegisterNetEvent('vending:server:completeRobbery', function(coords, success)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local machineId = getMachineIdByCoords(coords)
if not machineId then return end
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)
-- Helper function to get machine ID by coordinates
function getMachineIdByCoords(coords)
for id, machine in pairs(vendingMachines) do
local dist = #(vector3(coords.x, coords.y, coords.z) - vector3(machine.coords.x, machine.coords.y, machine.coords.z))
if dist < 2.0 then
return id
end
end
return nil
end
-- Get machine data by coordinates
QBCore.Functions.CreateCallback('vending:server:getMachineByCoords', function(source, cb, coords)
local machineId = getMachineIdByCoords(coords)
if machineId then
cb(vendingMachines[machineId])
else
cb(nil)
end
end)
-- Get stash items for vending machine menu
QBCore.Functions.CreateCallback('vending:server:getStashItems', function(source, cb, coords)
local machineId = getMachineIdByCoords(coords)
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)
-- 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)
return
end
local machineId = getMachineIdByCoords(coords)
if not machineId then
cb(false)
return
end
local machine = vendingMachines[machineId]
cb(machine.owner == Player.PlayerData.citizenid)
end) end)
-- Check if player can manage machine -- Check if player can manage machine
QBCore.Functions.CreateCallback('vending:server:canManage', function(source, cb, preciseCoords) QBCore.Functions.CreateCallback('vending:server:canManage', function(source, cb, coords)
local machineId = getMachineIdByCoords(preciseCoords) local Player = QBCore.Functions.GetPlayer(source)
if not Player then
cb(false)
return
end
local machineId = getMachineIdByCoords(coords)
if not machineId then if not machineId then
cb(false) cb(false)
return return
@ -693,6 +664,12 @@ QBCore.Functions.CreateCallback('vending:server:canManage', function(source, cb,
cb(canManageMachine(source, machineId)) cb(canManageMachine(source, machineId))
end) end)
-- Check if machine exists at coords
QBCore.Functions.CreateCallback('vending:server:machineExists', function(source, cb, coords)
local machineId = getMachineIdByCoords(coords)
cb(machineId ~= nil)
end)
-- Get online players for manager selection -- Get online players for manager selection
QBCore.Functions.CreateCallback('vending:server:getOnlinePlayers', function(source, cb) QBCore.Functions.CreateCallback('vending:server:getOnlinePlayers', function(source, cb)
local src = source local src = source
@ -735,3 +712,4 @@ QBCore.Commands.Add('vendingdebug', 'Debug vending machines (Admin Only)', {}, f
end end
end, 'admin') end, 'admin')