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)
 | 
