From b086fbe4dbd675091e4a25c6122950c9d8359ac9 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Tue, 29 Jul 2025 07:30:32 +0200 Subject: [PATCH] ed --- ...ty_glasbootle.png => empty_glasbottle.png} | Bin resources/[inventory]/nordi_pfand/config.lua | 2 +- .../[inventory]/nordi_vending/client.lua | 412 ++++++++++++++++++ .../[inventory]/nordi_vending/config.lua | 27 ++ .../[inventory]/nordi_vending/fxmanifest.lua | 30 ++ .../[inventory]/nordi_vending/server.lua | 369 ++++++++++++++++ .../[inventory]/pickle_consumables/config.lua | 70 ++- .../tgiann-inventory/items/items.lua | 4 +- 8 files changed, 887 insertions(+), 27 deletions(-) rename resources/[inventory]/inventory_images/images/{empty_glasbootle.png => empty_glasbottle.png} (100%) create mode 100644 resources/[inventory]/nordi_vending/client.lua create mode 100644 resources/[inventory]/nordi_vending/config.lua create mode 100644 resources/[inventory]/nordi_vending/fxmanifest.lua create mode 100644 resources/[inventory]/nordi_vending/server.lua diff --git a/resources/[inventory]/inventory_images/images/empty_glasbootle.png b/resources/[inventory]/inventory_images/images/empty_glasbottle.png similarity index 100% rename from resources/[inventory]/inventory_images/images/empty_glasbootle.png rename to resources/[inventory]/inventory_images/images/empty_glasbottle.png diff --git a/resources/[inventory]/nordi_pfand/config.lua b/resources/[inventory]/nordi_pfand/config.lua index 8518efd54..9c60da18e 100644 --- a/resources/[inventory]/nordi_pfand/config.lua +++ b/resources/[inventory]/nordi_pfand/config.lua @@ -11,7 +11,7 @@ Config.PfandDelay = 1500 -- Consumable items that generate deposits Config.ConsumableItems = { ['beer'] = { - pfandItem = 'empty_glasbootle', + pfandItem = 'empty_glasbottle', label = 'Bier' }, ['water_bottle'] = { diff --git a/resources/[inventory]/nordi_vending/client.lua b/resources/[inventory]/nordi_vending/client.lua new file mode 100644 index 000000000..610f6bfd0 --- /dev/null +++ b/resources/[inventory]/nordi_vending/client.lua @@ -0,0 +1,412 @@ +local QBCore = exports['qb-core']:GetCoreObject() + +-- Add targets to all vending machine props +CreateThread(function() + Wait(2000) -- Wait for everything to load + refreshTargets() +end) + +-- Refresh all targets +function refreshTargets() + -- Remove old targets first + for i = 1, #Config.VendingProps do + exports['qb-target']:RemoveTargetModel(Config.VendingProps[i]) + end + + -- Add new targets + exports['qb-target']:AddTargetModel(Config.VendingProps, { + options = { + { + type = "client", + event = "vending:client:buyMachine", + icon = "fas fa-dollar-sign", + label = "Automaten kaufen ($" .. Config.VendingMachinePrice .. ")", + canInteract = function(entity) + return not isMachineRegistered(entity) + end + }, + { + type = "client", + event = "vending:client:openBuyMenu", + icon = "fas fa-shopping-cart", + label = "Kaufen", + canInteract = function(entity) + return isMachineRegistered(entity) + end + }, + { + type = "client", + event = "vending:client:openOwnerMenu", + icon = "fas fa-cog", + label = "Verwalten", + canInteract = function(entity) + return isMachineRegistered(entity) and isOwner(entity) + end + }, + { + type = "client", + event = "vending:client:robberyMenu", + icon = "fas fa-mask", + label = "Aufbrechen", + canInteract = function(entity) + return isMachineRegistered(entity) and hasRobberyItem() and not isOwner(entity) + end + } + }, + distance = 2.0 + }) +end + +-- Check if machine is registered +function isMachineRegistered(entity) + local coords = GetEntityCoords(entity) + local registered = false + + QBCore.Functions.TriggerCallback('vending:server:machineExists', function(exists) + registered = exists + end, coords) + + -- Wait for callback (not ideal but necessary for sync check) + while registered == false do + Wait(10) + end + + return registered +end + +-- Check if player is owner +function isOwner(entity) + local coords = GetEntityCoords(entity) + local owner = false + + QBCore.Functions.TriggerCallback('vending:server:isOwner', function(isOwner) + owner = isOwner + end, coords) + + -- Wait for callback + while owner == false do + Wait(10) + end + + return owner +end + +-- Check if player has robbery item +function hasRobberyItem() + local PlayerData = QBCore.Functions.GetPlayerData() + for k, v in pairs(PlayerData.items) do + if v.name == Config.RobberyItem and v.amount > 0 then + return true + end + end + return false +end + +-- Buy vending machine +RegisterNetEvent('vending:client:buyMachine', function(data) + local entity = data.entity + local coords = GetEntityCoords(entity) + local model = GetEntityModel(entity) + local prop = nil + + -- Find prop name + for i = 1, #Config.VendingProps do + if GetHashKey(Config.VendingProps[i]) == model then + prop = Config.VendingProps[i] + break + end + end + + if not prop then return end + + lib.registerContext({ + id = 'vending_buy_confirm', + title = 'Verkaufsautomat kaufen', + options = { + { + title = 'Bestätigen', + description = 'Automaten für $' .. Config.VendingMachinePrice .. ' kaufen', + icon = 'fas fa-check', + onSelect = function() + TriggerServerEvent('vending:server:registerMachine', coords, prop) + end + }, + { + title = 'Abbrechen', + description = 'Kauf abbrechen', + icon = 'fas fa-times' + } + } + }) + + lib.showContext('vending_buy_confirm') +end) + +-- Open buy menu +RegisterNetEvent('vending:client:openBuyMenu', function(data) + local entity = data.entity + local coords = GetEntityCoords(entity) + + QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) + if #items == 0 then + QBCore.Functions.Notify('Dieser Automat ist leer!', 'error') + return + end + + local options = {} + + for i = 1, #items do + local item = items[i] + if item.amount > 0 then + table.insert(options, { + title = QBCore.Shared.Items[item.name].label, + description = 'Preis: $' .. item.price .. ' | Verfügbar: ' .. item.amount, + icon = 'nui://qb-inventory/html/images/' .. item.name .. '.png', + onSelect = function() + TriggerServerEvent('vending:server:buyItem', coords, item.name) + end + }) + end + end + + lib.registerContext({ + id = 'vending_buy_menu', + title = 'Verkaufsautomat', + options = options + }) + + lib.showContext('vending_buy_menu') + end, coords) +end) + +-- Open owner menu +RegisterNetEvent('vending:client:openOwnerMenu', function(data) + local entity = data.entity + local coords = GetEntityCoords(entity) + + 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 = 'Einnahmen auszahlen lassen', + icon = 'fas fa-money-bill', + onSelect = function() + openWithdrawMenu(coords) + end + }, + { + title = 'Statistiken', + description = 'Verkaufsstatistiken anzeigen', + icon = 'fas fa-chart-bar', + onSelect = function() + TriggerServerEvent('vending:server:openManagement', coords) + end + } + } + }) + + lib.showContext('vending_owner_menu') +end) + +-- Open price menu +function openPriceMenu(coords) + QBCore.Functions.TriggerCallback('vending:server:getStashItems', function(items) + if #items == 0 then + QBCore.Functions.Notify('Keine Items im Automaten!', 'error') + return + end + + local options = {} + + for i = 1, #items do + local item = items[i] + table.insert(options, { + title = QBCore.Shared.Items[item.name].label, + description = 'Aktueller Preis: $' .. item.price, + icon = 'nui://qb-inventory/html/images/' .. item.name .. '.png', + onSelect = function() + setPriceForItem(coords, item.name, item.price) + end + }) + end + + lib.registerContext({ + id = 'vending_price_menu', + title = 'Preise festlegen', + options = options + }) + + lib.showContext('vending_price_menu') + end, coords) +end + +-- Set price for specific item +function setPriceForItem(coords, itemName, currentPrice) + local input = lib.inputDialog('Preis festlegen', { + { + type = 'number', + label = 'Neuer Preis für ' .. (QBCore.Shared.Items[itemName] and QBCore.Shared.Items[itemName].label or itemName), + description = 'Aktueller Preis: $' .. currentPrice, + required = true, + min = 1, + max = 9999, + default = currentPrice + } + }) + + if input and input[1] then + TriggerServerEvent('vending:server:setItemPrice', coords, itemName, tonumber(input[1])) + end +end + +-- Open withdraw menu +function openWithdrawMenu(coords) + QBCore.Functions.TriggerCallback('vending:server:getMachineByCoords', function(machine) + if not machine then return end + + local input = lib.inputDialog('Geld abheben', { + { + type = 'number', + label = 'Betrag (Verfügbar: $' .. machine.money .. ')', + description = 'Wie viel möchtest du abheben?', + required = true, + min = 1, + max = machine.money + } + }) + + if input and input[1] then + TriggerServerEvent('vending:server:withdrawMoney', coords, tonumber(input[1])) + end + end, coords) +end + +-- Robbery menu +RegisterNetEvent('vending:client:robberyMenu', function(data) + local entity = data.entity + local coords = GetEntityCoords(entity) + + lib.registerContext({ + id = 'vending_robbery_menu', + title = 'Verkaufsautomat aufbrechen', + options = { + { + title = 'Aufbrechen', + description = 'Versuche den Automaten aufzubrechen', + icon = 'fas fa-mask', + onSelect = function() + TriggerServerEvent('vending:server:startRobbery', coords) + end + } + } + }) + + lib.showContext('vending_robbery_menu') +end) + +-- Start robbery minigame +RegisterNetEvent('vending:client:startRobbery', function(coords) + local success = false + + -- Progress bar + if lib.progressBar({ + duration = 5000, + label = 'Automaten aufbrechen...', + useWhileDead = false, + canCancel = true, + disable = { + car = true, + move = true, + combat = true + }, + anim = { + dict = 'missheist_jewel', + clip = 'smash_case' + } + }) then + -- Lockpicking minigame + local result = lib.skillCheck({'easy', 'easy', 'medium', 'medium', 'hard'}, {'w', 'a', 's', 'd'}) + + if result then + success = true + end + + TriggerServerEvent('vending:server:completeRobbery', coords, success) + end +end) + +-- Police alert +RegisterNetEvent('vending:client:policeAlert', function(coords, streetName) + QBCore.Functions.Notify('Verkaufsautomat wird aufgebrochen: ' .. streetName, 'error', 10000) + + -- Add blip + local blip = AddBlipForCoord(coords.x, coords.y, coords.z) + SetBlipSprite(blip, 161) + SetBlipScale(blip, 1.0) + SetBlipColour(blip, 1) + SetBlipAsShortRange(blip, false) + BeginTextCommandSetBlipName("STRING") + AddTextComponentString("Verkaufsautomat Aufbruch") + EndTextCommandSetBlipName(blip) + + -- Remove blip after 5 minutes + SetTimeout(300000, function() + RemoveBlip(blip) + end) +end) + +-- Management menu +RegisterNetEvent('vending:client:openManagement', function(machine) + lib.registerContext({ + id = 'vending_management', + title = 'Verkaufsautomat #' .. machine.id, + options = { + { + title = 'Guthaben: $' .. machine.money, + description = 'Aktuelles Guthaben im Automaten', + icon = 'fas fa-dollar-sign' + }, + { + title = 'Inventar verwalten', + description = 'Items hinzufügen oder entfernen', + icon = 'fas fa-box', + onSelect = function() + TriggerServerEvent('vending:server:openStash', machine.coords) + end + }, + { + title = 'Preise verwalten', + description = 'Verkaufspreise anpassen', + icon = 'fas fa-tags', + onSelect = function() + openPriceMenu(machine.coords) + end + } + } + }) + + lib.showContext('vending_management') +end) + +-- Refresh targets when called from server +RegisterNetEvent('vending:client:refreshTargets', function() + refreshTargets() +end) diff --git a/resources/[inventory]/nordi_vending/config.lua b/resources/[inventory]/nordi_vending/config.lua new file mode 100644 index 000000000..83f15855e --- /dev/null +++ b/resources/[inventory]/nordi_vending/config.lua @@ -0,0 +1,27 @@ +Config = {} + +-- Vending Machine Settings +Config.VendingProps = { + 'prop_vend_coffe_01', + 'prop_vend_soda_01', + 'prop_vend_soda_02', + 'prop_vend_water_01' +} + +-- Purchase Settings +Config.VendingMachinePrice = 5000 -- Price to buy/register a vending machine + +-- Items +Config.RobberyItem = 'crowbar' -- Item needed to rob vending machines + +-- Inventory Settings +Config.MaxWeight = 50000 -- Maximum weight for vending machine stash +Config.MaxSlots = 20 -- Maximum slots for vending machine stash + +-- Pricing +Config.DefaultPrice = 5 -- Default price if owner hasn't set a price + +-- Robbery Settings +Config.MinRobberyAmount = 50 -- Minimum money in machine to rob +Config.MaxRobberyAmount = 500 -- Maximum money that can be stolen +Config.RobberyItemBreakChance = 25 -- Chance (%) that robbery item breaks diff --git a/resources/[inventory]/nordi_vending/fxmanifest.lua b/resources/[inventory]/nordi_vending/fxmanifest.lua new file mode 100644 index 000000000..706c332fd --- /dev/null +++ b/resources/[inventory]/nordi_vending/fxmanifest.lua @@ -0,0 +1,30 @@ +fx_version 'cerulean' +game 'gta5' + +author 'YourName' +description 'Advanced Vending Machine System with Manual Placement' +version '1.0.0' + +shared_scripts { + '@ox_lib/init.lua', + 'config.lua' +} + +client_scripts { + 'client.lua' +} + +server_scripts { + '@oxmysql/lib/MySQL.lua', + 'server.lua' +} + +dependencies { + 'qb-core', + 'qb-target', + 'ox_lib', + 'tgiann-inventory', + 'oxmysql' +} + +lua54 'yes' diff --git a/resources/[inventory]/nordi_vending/server.lua b/resources/[inventory]/nordi_vending/server.lua new file mode 100644 index 000000000..ad39eba7f --- /dev/null +++ b/resources/[inventory]/nordi_vending/server.lua @@ -0,0 +1,369 @@ +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 {}, + stash = 'vending_' .. data.id + } + + -- Create stash for this vending machine + exports['tgiann-inventory']:CreateStash({ + stashId = 'vending_' .. data.id, + stashName = 'Vending Machine #' .. data.id, + maxWeight = Config.MaxWeight, + maxSlots = Config.MaxSlots, + stashCoords = vendingMachines[data.id].coords + }) + end + 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 + 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 + + -- 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) VALUES (?, ?, ?, ?, ?, ?)', { + Player.PlayerData.citizenid, + json.encode(coords), + prop, + 0, + json.encode({}), + json.encode({}) + }) + + -- Add to memory + vendingMachines[machineId] = { + id = machineId, + owner = Player.PlayerData.citizenid, + coords = coords, + prop = prop, + money = 0, + items = {}, + prices = {}, + stash = 'vending_' .. machineId + } + + -- Create stash + exports['tgiann-inventory']:CreateStash({ + stashId = 'vending_' .. machineId, + stashName = 'Vending Machine #' .. machineId, + maxWeight = Config.MaxWeight, + maxSlots = Config.MaxSlots, + stashCoords = coords + }) + + TriggerClientEvent('QBCore:Notify', src, 'Verkaufsautomat erfolgreich gekauft für $' .. Config.VendingMachinePrice .. '!', 'success') + TriggerClientEvent('vending:client:refreshTargets', -1) +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] + if machine.owner ~= Player.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + return + end + + 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 + + local machine = vendingMachines[machineId] + if machine.owner ~= Player.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + return + end + + exports['tgiann-inventory']:OpenStash(src, machine.stash) +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 + + local machine = vendingMachines[machineId] + if machine.owner ~= Player.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + return + end + + -- 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 + + local machine = vendingMachines[machineId] + if machine.owner ~= Player.PlayerData.citizenid then + TriggerClientEvent('QBCore:Notify', src, 'Das ist nicht dein Verkaufsautomat!', 'error') + return + end + + 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 +RegisterNetEvent('vending:server:buyItem', function(coords, itemName) + 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 + + -- Check if player has enough money + if Player.PlayerData.money.cash < price then + TriggerClientEvent('QBCore:Notify', src, 'Du hast nicht genug Geld!', 'error') + return + end + + -- Check if item is available in stash + local stashItems = exports['tgiann-inventory']:GetStashItems(machine.stash) + local hasItem = false + + for i = 1, #stashItems do + if stashItems[i].name == itemName and stashItems[i].amount > 0 then + hasItem = true + break + end + end + + if not hasItem then + TriggerClientEvent('QBCore:Notify', src, 'Artikel nicht verfügbar!', 'error') + return + end + + -- Remove money from player + Player.Functions.RemoveMoney('cash', price) + + -- Add money to machine + machine.money = machine.money + price + MySQL.update('UPDATE vending_machines SET money = ? WHERE id = ?', {machine.money, machineId}) + + -- Remove item from stash and give to player + exports['tgiann-inventory']:RemoveItemFromStash(machine.stash, itemName, 1) + exports['tgiann-inventory']:AddItem(src, itemName, 1) + + TriggerClientEvent('QBCore:Notify', src, 'Artikel gekauft für $' .. price .. '!', 'success') +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 = exports['tgiann-inventory']:GetItemByName(src, Config.RobberyItem) + if not hasItem or hasItem.amount < 1 then + TriggerClientEvent('QBCore:Notify', src, 'Du benötigst einen ' .. Config.RobberyItem, 'error') + return + end + + -- Check if already being robbed + if robberyInProgress[machineId] then + TriggerClientEvent('QBCore:Notify', src, 'Dieser Automat wird bereits aufgebrochen!', 'error') + return + end + + -- Check if machine has money + if machine.money < Config.MinRobberyAmount then + TriggerClientEvent('QBCore:Notify', src, 'Nicht genug Geld im Automaten!', 'error') + return + end + + robberyInProgress[machineId] = true + + -- Alert police + local streetHash = GetStreetNameAtCoord(coords.x, coords.y, coords.z) + local streetName = GetStreetNameFromHashKey(streetHash) + + local players = QBCore.Functions.GetQBPlayers() + for k, v in pairs(players) do + if v.PlayerData.job.name == 'police' and v.PlayerData.job.onduty then + TriggerClientEvent('vending:client:policeAlert', v.PlayerData.source, coords, streetName) + end + end + + 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 + exports['tgiann-inventory']:RemoveItem(src, Config.RobberyItem, 1) + TriggerClientEvent('QBCore:Notify', src, 'Dein ' .. Config.RobberyItem .. ' ist kaputt gegangen!', 'error') + end + else + TriggerClientEvent('QBCore:Notify', src, 'Aufbruch fehlgeschlagen!', 'error') + end +end) + +-- Helper function to get machine ID by coordinates +function getMachineIdByCoords(coords) + for id, machine in pairs(vendingMachines) do + local dist = #(vector3(coords.x, coords.y, coords.z) - vector3(machine.coords.x, machine.coords.y, machine.coords.z)) + if dist < 2.0 then + return id + end + end + return nil +end + +-- Get machine data by coordinates +QBCore.Functions.CreateCallback('vending:server:getMachineByCoords', function(source, cb, coords) + local machineId = getMachineIdByCoords(coords) + if machineId then + cb(vendingMachines[machineId]) + else + cb(nil) + end +end) + +-- Get stash items for vending machine menu +QBCore.Functions.CreateCallback('vending:server:getStashItems', function(source, cb, coords) + local machineId = getMachineIdByCoords(coords) + if not machineId then + cb({}) + return + end + + local machine = vendingMachines[machineId] + local items = exports['tgiann-inventory']:GetStashItems(machine.stash) + + -- Add prices to items + for i = 1, #items do + items[i].price = machine.prices[items[i].name] or Config.DefaultPrice + 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 machine exists at coords +QBCore.Functions.CreateCallback('vending:server:machineExists', function(source, cb, coords) + local machineId = getMachineIdByCoords(coords) + cb(machineId ~= nil) +end) diff --git a/resources/[inventory]/pickle_consumables/config.lua b/resources/[inventory]/pickle_consumables/config.lua index d4f0ed18d..e7c05e649 100644 --- a/resources/[inventory]/pickle_consumables/config.lua +++ b/resources/[inventory]/pickle_consumables/config.lua @@ -1589,7 +1589,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_glasbottle" -- This is the item that will be returned after all uses }, ["spazi"] = { uses = 2, @@ -1603,7 +1604,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["spazi_limo"] = { uses = 2, @@ -1617,7 +1619,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["ecola_dose"] = { uses = 1, @@ -1631,7 +1634,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["sprunk_dose"] = { uses = 1, @@ -1645,7 +1649,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["slushi"] = { uses = 2, @@ -1687,7 +1692,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["sprunk_zero_dose"] = { uses = 1, @@ -1701,7 +1707,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["sprunk_dose"] = { uses = 1, @@ -1715,7 +1722,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["orange_o_tang_zero_dose"] = { uses = 1, @@ -1729,7 +1737,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["orange_o_tang_dose"] = { uses = 1, @@ -1743,7 +1752,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["ecola_zero_flasche"] = { uses = 2, @@ -1757,7 +1767,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_bottle" -- This is the item that will be returned after all uses }, ["ecola_flasche"] = { uses = 2, @@ -1771,7 +1782,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_bottle" -- This is the item that will be returned after all uses }, ["sprunk_flasche"] = { uses = 2, @@ -1785,7 +1797,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_bottle" -- This is the item that will be returned after all uses }, ["sprunk_zero_flasche"] = { uses = 2, @@ -1799,7 +1812,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_bottle" -- This is the item that will be returned after all uses }, ["orange_o_tang_zero_flasche"] = { uses = 2, @@ -1813,7 +1827,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_bottle" -- This is the item that will be returned after all uses }, ["orange_o_tang_flasche"] = { uses = 2, @@ -1827,7 +1842,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_bottle" -- This is the item that will be returned after all uses }, ["water_bottle"] = { uses = 2, @@ -1855,8 +1871,9 @@ Config.Items = { stress = 0, armor = 0, alcohol = 0, - stamina = 0, - } + stamina = 10, + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["munky_juice"] = { uses = 1, @@ -1884,7 +1901,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["campers_fuel"] = { uses = 1, @@ -1897,8 +1915,9 @@ Config.Items = { stress = 0, armor = 0, alcohol = 0, - stamina = 0, - } + stamina = 10, + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["kakao"] = { uses = 1, @@ -2013,7 +2032,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_can" -- This is the item that will be returned after all uses }, ["kayas_rotwein"] = { uses = 2, @@ -2042,7 +2062,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_glasbottle" -- This is the item that will be returned after all uses }, ["cerveza_barracho"] = { uses = 2, @@ -2057,7 +2078,8 @@ Config.Items = { armor = 0, alcohol = 0, stamina = 0, - } + }, + return_item = "empty_glasbottle" -- This is the item that will be returned after all uses }, ["kadis_rostbite"] = { uses = 2, diff --git a/resources/[inventory]/tgiann-inventory/items/items.lua b/resources/[inventory]/tgiann-inventory/items/items.lua index 33a952a9c..f03e624e1 100644 --- a/resources/[inventory]/tgiann-inventory/items/items.lua +++ b/resources/[inventory]/tgiann-inventory/items/items.lua @@ -10805,7 +10805,7 @@ itemsData = { image = 'empty_can.png', name = 'empty_can', }, - empty_glasbootle = { + empty_glasbottle = { shouldClose = true, type = 'item', description = '', @@ -10814,6 +10814,6 @@ itemsData = { unique = true, useable = true, image = 'empty_glasbootle.png', - name = 'empty_glasbootle', + name = 'empty_glasbottle', }, }