774 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			774 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
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)
 | 
						|
RegisterNetEvent('vending:server:registerMachine', function(coords, prop)
 | 
						|
    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
 | 
						|
        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
 | 
						|
        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,
 | 
						|
        json.encode(coords),
 | 
						|
        prop,
 | 
						|
        0,
 | 
						|
        json.encode({}),
 | 
						|
        json.encode({}),
 | 
						|
        json.encode({})
 | 
						|
    })
 | 
						|
    
 | 
						|
    -- Add to memory
 | 
						|
    vendingMachines[machineId] = {
 | 
						|
        id = machineId,
 | 
						|
        owner = Player.PlayerData.citizenid,
 | 
						|
        coords = coords,
 | 
						|
        prop = prop,
 | 
						|
        money = 0,
 | 
						|
        items = {},
 | 
						|
        prices = {},
 | 
						|
        managers = {},
 | 
						|
        stash = 'vending_' .. machineId
 | 
						|
    }
 | 
						|
    
 | 
						|
    print("^2[VENDING]^7 New vending machine registered: " .. machineId)
 | 
						|
    TriggerClientEvent('QBCore:Notify', src, 'Verkaufsautomat erfolgreich gekauft für $' .. Config.VendingMachinePrice .. '!', 'success')
 | 
						|
    TriggerClientEvent('vending:client:refreshTargets', -1)
 | 
						|
end)
 | 
						|
 | 
						|
-- Sell vending machine
 | 
						|
RegisterNetEvent('vending:server:sellMachine', function(coords, machineId)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
    if not Player then return end
 | 
						|
    
 | 
						|
    if not machineId then
 | 
						|
        machineId = getMachineIdByCoords(coords)
 | 
						|
    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
 | 
						|
RegisterNetEvent('vending:server:openManagement', function(coords)
 | 
						|
    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]
 | 
						|
    
 | 
						|
    -- 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
 | 
						|
RegisterNetEvent('vending:server:openStash', function(coords)
 | 
						|
    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
 | 
						|
    
 | 
						|
    -- 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)
 | 
						|
 | 
						|
-- Set item price
 | 
						|
RegisterNetEvent('vending:server:setItemPrice', function(coords, itemName, price)
 | 
						|
    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
 | 
						|
    
 | 
						|
    -- 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
 | 
						|
RegisterNetEvent('vending:server:withdrawMoney', function(coords, amount)
 | 
						|
    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
 | 
						|
    
 | 
						|
    -- 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
 | 
						|
RegisterNetEvent('vending:server:buyItem', function(coords, itemName, amount)
 | 
						|
    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]
 | 
						|
    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
 | 
						|
RegisterNetEvent('vending:server:addManager', function(coords, targetId)
 | 
						|
    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]
 | 
						|
    
 | 
						|
    -- 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
 | 
						|
RegisterNetEvent('vending:server:removeManager', function(coords, citizenid)
 | 
						|
    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]
 | 
						|
    
 | 
						|
    -- 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)
 | 
						|
 | 
						|
-- 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)
 | 
						|
 | 
						|
-- Start robbery
 | 
						|
RegisterNetEvent('vending:server:startRobbery', function(coords)
 | 
						|
    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]
 | 
						|
    
 | 
						|
    -- 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 - use a generic location name instead of street name
 | 
						|
    local locationName = "Verkaufsautomat #" .. machineId
 | 
						|
    
 | 
						|
    -- 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
 | 
						|
    }
 | 
						|
    
 | 
						|
    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, alertData)
 | 
						|
        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: ' .. locationName, '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: ' .. locationName, '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)
 | 
						|
    -- 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
 | 
						|
    
 | 
						|
    for id, machine in pairs(vendingMachines) do
 | 
						|
        -- 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
 | 
						|
        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)
 | 
						|
 | 
						|
-- Check if player can manage machine
 | 
						|
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)
 | 
						|
    if not machineId then 
 | 
						|
        cb(false)
 | 
						|
        return 
 | 
						|
    end
 | 
						|
    
 | 
						|
    cb(canManageMachine(source, machineId))
 | 
						|
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
 | 
						|
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')
 | 
						|
 | 
						|
-- 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)
 |