1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-29 09:02:52 +02:00
parent 179f7c0d12
commit c688255b8a
2 changed files with 486 additions and 80 deletions

View file

@ -11,7 +11,7 @@ CreateThread(function()
event = "vending:client:buyMachine",
icon = "fas fa-dollar-sign",
label = "Automaten kaufen ($" .. Config.VendingMachinePrice .. ")",
canInteract = function(entity, distance, data)
canInteract = function(entity)
return not isRegisteredMachine(entity)
end
},
@ -20,7 +20,7 @@ CreateThread(function()
event = "vending:client:openBuyMenu",
icon = "fas fa-shopping-cart",
label = "Kaufen",
canInteract = function(entity, distance, data)
canInteract = function(entity)
return isRegisteredMachine(entity)
end
},
@ -29,8 +29,8 @@ CreateThread(function()
event = "vending:client:openOwnerMenu",
icon = "fas fa-cog",
label = "Verwalten",
canInteract = function(entity, distance, data)
return isOwnerOfMachine(entity)
canInteract = function(entity)
return canManageMachine(entity)
end
},
{
@ -38,8 +38,8 @@ CreateThread(function()
event = "vending:client:startRobbery",
icon = "fas fa-mask",
label = "Aufbrechen",
canInteract = function(entity, distance, data)
return isRegisteredMachine(entity) and not isOwnerOfMachine(entity)
canInteract = function(entity)
return isRegisteredMachine(entity) and not canManageMachine(entity)
end
}
},
@ -66,23 +66,23 @@ function isRegisteredMachine(entity)
return isRegistered
end
-- Check if player owns machine
function isOwnerOfMachine(entity)
-- Check if player can manage machine
function canManageMachine(entity)
local coords = GetEntityCoords(entity)
local isOwner = false
local canManage = false
QBCore.Functions.TriggerCallback('vending:server:isOwner', function(owner)
isOwner = owner
QBCore.Functions.TriggerCallback('vending:server:canManage', function(result)
canManage = result
end, coords)
-- Wait for callback
local timeout = 0
while isOwner == false and timeout < 100 do
while canManage == false and timeout < 100 do
Wait(10)
timeout = timeout + 1
end
return isOwner
return canManage
end
-- Buy vending machine
@ -125,7 +125,7 @@ RegisterNetEvent('vending:client:buyMachine', function(data)
lib.showContext('vending_buy_confirm')
end)
-- Open buy menu
-- Open buy menu with quantity selection
RegisterNetEvent('vending:client:openBuyMenu', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)
@ -147,7 +147,7 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data)
description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount,
icon = 'fas fa-shopping-cart',
onSelect = function()
TriggerServerEvent('vending:server:buyItem', coords, item.name)
openQuantityDialog(coords, item.name, item.price, item.amount, itemLabel)
end
})
end
@ -168,6 +168,30 @@ RegisterNetEvent('vending:client:openBuyMenu', function(data)
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
-- Open owner menu
RegisterNetEvent('vending:client:openOwnerMenu', function(data)
local entity = data.entity
@ -179,43 +203,57 @@ RegisterNetEvent('vending:client:openOwnerMenu', function(data)
return
end
local options = {
{
title = 'Inventar verwalten',
description = 'Items hinzufügen/entfernen',
icon = 'fas fa-box',
onSelect = function()
TriggerServerEvent('vending:server:openStash', coords)
end
},
{
title = 'Preise festlegen',
description = 'Verkaufspreise für Items setzen',
icon = 'fas fa-tags',
onSelect = function()
openPriceMenu(coords)
end
},
{
title = 'Geld abheben',
description = 'Verfügbar: $' .. machine.money,
icon = 'fas fa-money-bill',
onSelect = function()
openWithdrawMenu(coords, machine.money)
end
},
{
title = 'Statistiken',
description = 'Verkaufsstatistiken anzeigen',
icon = 'fas fa-chart-bar',
onSelect = function()
openStatsMenu(machine)
end
}
}
-- Add manager options only for owner
if machine.isOwner then
table.insert(options, {
title = 'Verwalter',
description = 'Verwalter hinzufügen/entfernen',
icon = 'fas fa-users-cog',
onSelect = function()
openManagersMenu(coords)
end
})
end
lib.registerContext({
id = 'vending_owner_menu',
title = 'Verkaufsautomat Verwaltung',
options = {
{
title = 'Inventar verwalten',
description = 'Items hinzufügen/entfernen',
icon = 'fas fa-box',
onSelect = function()
TriggerServerEvent('vending:server:openStash', coords)
end
},
{
title = 'Preise festlegen',
description = 'Verkaufspreise für Items setzen',
icon = 'fas fa-tags',
onSelect = function()
openPriceMenu(coords)
end
},
{
title = 'Geld abheben',
description = 'Verfügbar: $' .. machine.money,
icon = 'fas fa-money-bill',
onSelect = function()
openWithdrawMenu(coords, machine.money)
end
},
{
title = 'Statistiken',
description = 'Verkaufsstatistiken anzeigen',
icon = 'fas fa-chart-bar',
onSelect = function()
openStatsMenu(machine)
end
}
}
options = options
})
lib.showContext('vending_owner_menu')
@ -325,7 +363,107 @@ function openStatsMenu(machine)
lib.showContext('vending_stats_menu')
end
-- Start robbery
-- Open managers menu
function openManagersMenu(coords)
-- Get current managers
QBCore.Functions.TriggerCallback('vending:server:getManagers', function(managers)
local options = {
{
title = 'Verwalter hinzufügen',
description = 'Neuen Verwalter hinzufügen',
icon = 'fas fa-user-plus',
onSelect = function()
openAddManagerMenu(coords)
end
}
}
-- Add existing managers with remove option
if #managers > 0 then
for i = 1, #managers do
local manager = managers[i]
table.insert(options, {
title = manager.name,
description = manager.online and 'Online' or 'Offline',
icon = manager.online and 'fas fa-circle text-success' or 'fas fa-circle text-danger',
onSelect = function()
lib.registerContext({
id = 'manager_options',
title = 'Verwalter: ' .. manager.name,
menu = 'managers_menu',
options = {
{
title = 'Entfernen',
description = 'Verwalter entfernen',
icon = 'fas fa-user-minus',
onSelect = function()
TriggerServerEvent('vending:server:removeManager', coords, manager.citizenid)
Wait(500)
openManagersMenu(coords) -- Refresh the menu
end
}
}
})
lib.showContext('manager_options')
end
})
end
else
table.insert(options, {
title = 'Keine Verwalter',
description = 'Es sind keine Verwalter vorhanden',
icon = 'fas fa-info-circle',
disabled = true
})
end
lib.registerContext({
id = 'managers_menu',
title = 'Verwalter verwalten',
menu = 'vending_owner_menu',
options = options
})
lib.showContext('managers_menu')
end, coords)
end
-- Open add manager menu
function openAddManagerMenu(coords)
QBCore.Functions.TriggerCallback('vending:server:getOnlinePlayers', function(players)
if #players == 0 then
QBCore.Functions.Notify('Keine Spieler online!', 'error')
return
end
local options = {}
for i = 1, #players do
local player = players[i]
table.insert(options, {
title = player.name,
description = 'ID: ' .. player.id,
icon = 'fas fa-user',
onSelect = function()
TriggerServerEvent('vending:server:addManager', coords, player.id)
Wait(500)
openManagersMenu(coords) -- Refresh the menu
end
})
end
lib.registerContext({
id = 'add_manager_menu',
title = 'Verwalter hinzufügen',
menu = 'managers_menu',
options = options
})
lib.showContext('add_manager_menu')
end)
end
-- Robbery menu
RegisterNetEvent('vending:client:startRobbery', function(data)
local entity = data.entity
local coords = GetEntityCoords(entity)

View file

@ -16,6 +16,7 @@ CreateThread(function()
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
@ -48,12 +49,13 @@ RegisterNetEvent('vending:server:registerMachine', function(coords, prop)
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) VALUES (?, ?, ?, ?, ?, ?)', {
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({})
})
@ -66,6 +68,7 @@ RegisterNetEvent('vending:server:registerMachine', function(coords, prop)
money = 0,
items = {},
prices = {},
managers = {},
stash = 'vending_' .. machineId
}
@ -74,6 +77,31 @@ RegisterNetEvent('vending:server:registerMachine', function(coords, prop)
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
@ -84,15 +112,20 @@ RegisterNetEvent('vending:server:openManagement', function(coords)
if not machineId then return end
local machine = vendingMachines[machineId]
if machine.owner ~= Player.PlayerData.citizenid then
TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error')
-- 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 (korrekt für tgiann-inventory)
-- Open stash
RegisterNetEvent('vending:server:openStash', function(coords)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
@ -101,12 +134,14 @@ RegisterNetEvent('vending:server:openStash', function(coords)
local machineId = getMachineIdByCoords(coords)
if not machineId then return end
local machine = vendingMachines[machineId]
if machine.owner ~= Player.PlayerData.citizenid then
TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error')
-- 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,
@ -124,12 +159,14 @@ RegisterNetEvent('vending:server:setItemPrice', function(coords, itemName, price
local machineId = getMachineIdByCoords(coords)
if not machineId then return end
local machine = vendingMachines[machineId]
if machine.owner ~= Player.PlayerData.citizenid then
TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error')
-- 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})
@ -146,12 +183,14 @@ RegisterNetEvent('vending:server:withdrawMoney', function(coords, amount)
local machineId = getMachineIdByCoords(coords)
if not machineId then return end
local machine = vendingMachines[machineId]
if machine.owner ~= Player.PlayerData.citizenid then
TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error')
-- 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
@ -166,8 +205,8 @@ RegisterNetEvent('vending:server:withdrawMoney', function(coords, amount)
TriggerClientEvent('QBCore:Notify', src, 'Du hast $' .. amount .. ' abgehoben!', 'success')
end)
-- Buy item from vending machine
RegisterNetEvent('vending:server:buyItem', function(coords, itemName)
-- 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
@ -177,44 +216,213 @@ RegisterNetEvent('vending:server:buyItem', function(coords, itemName)
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 < price then
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 hasItem = false
local availableAmount = 0
if stashItems then
for slot, item in pairs(stashItems) do
if item.name == itemName and item.amount > 0 then
hasItem = true
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
if not hasItem then
TriggerClientEvent('QBCore:Notify', src, 'Artikel nicht verfügbar!', 'error')
-- 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
-- Remove money from player
Player.Functions.RemoveMoney('cash', price)
-- Get target player
local Target = QBCore.Functions.GetPlayer(tonumber(targetId))
if not Target then
TriggerClientEvent('QBCore:Notify', src, 'Spieler nicht gefunden!', 'error')
return
end
-- Add money to machine
machine.money = machine.money + price
MySQL.update('UPDATE vending_machines SET money = ? WHERE id = ?', {machine.money, machineId})
-- 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
-- Remove item from stash and add to player
exports["tgiann-inventory"]:RemoveItemFromSecondaryInventory("stash", machine.stash, itemName, 1)
Player.Functions.AddItem(itemName, 1)
TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[itemName], 'add')
-- 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, 'Artikel gekauft für $' .. price .. '!', 'success')
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
@ -260,6 +468,23 @@ RegisterNetEvent('vending:server:startRobbery', function(coords)
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)
@ -362,12 +587,55 @@ QBCore.Functions.CreateCallback('vending:server:isOwner', function(source, cb, c
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)