diff --git a/resources/[inventory]/nordi_pfand/client/main.lua b/resources/[inventory]/nordi_pfand/client/main.lua new file mode 100644 index 000000000..4e1333f11 --- /dev/null +++ b/resources/[inventory]/nordi_pfand/client/main.lua @@ -0,0 +1,175 @@ +local QBCore = exports['qb-core']:GetCoreObject() + +-- Erstelle Targets für alle Pfandautomaten +CreateThread(function() + for _, prop in pairs(Config.PfandautomatProps) do + exports['qb-target']:AddTargetModel(prop, { + options = { + { + type = "client", + event = "qb-pfandsystem:client:openPfandMenu", + icon = "fas fa-recycle", + label = "Pfand einlösen", + } + }, + distance = 2.0 + }) + end +end) + +-- Hook für Item Usage (Client-seitig) +RegisterNetEvent('tgiann-inventory:client:UseItem', function(itemName, itemData) + -- Prüfe ob das verwendete Item Pfand generiert + if Config.ConsumableItems[itemName] then + -- Informiere den Server über die Item-Nutzung + TriggerServerEvent('qb-pfandsystem:server:itemConsumed', itemName) + end +end) + +-- Öffne Pfand Menu +RegisterNetEvent('qb-pfandsystem:client:openPfandMenu', function() + QBCore.Functions.TriggerCallback('qb-pfandsystem:server:getPfandItems', function(pfandItems) + if next(pfandItems) == nil then + lib.notify({ + title = 'Pfandsystem', + description = Config.Locale['no_pfand_items'], + type = 'error' + }) + return + end + + showPfandMenu(pfandItems) + end) +end) + +-- Zeige Pfand Menu +function showPfandMenu(pfandItems) + local options = {} + + for itemName, itemData in pairs(pfandItems) do + local moneyString = string.format("€%.2f", itemData.totalWert / 100) + + table.insert(options, { + title = itemData.label, + description = string.format("Anzahl: %d | Gesamtwert: %s", itemData.count, moneyString), + icon = 'recycle', + onSelect = function() + showQuantityInput(itemName, itemData) + end + }) + end + + -- Option für alle Items + table.insert(options, { + title = "Alle Pfandartikel einlösen", + description = "Löse alle verfügbaren Pfandartikel auf einmal ein", + icon = 'coins', + onSelect = function() + redeemAllItems(pfandItems) + end + }) + + lib.registerContext({ + id = 'pfand_menu', + title = Config.Locale['pfand_menu_title'], + options = options + }) + + lib.showContext('pfand_menu') +end + +-- Zeige Mengenauswahl +function showQuantityInput(itemName, itemData) + local input = lib.inputDialog('Pfand einlösen', { + { + type = 'slider', + label = 'Anzahl (' .. itemData.label .. ')', + description = string.format('Verfügbar: %d | Pfandwert: €%.2f pro Stück', + itemData.count, itemData.pfandwert / 100), + required = true, + min = 1, + max = itemData.count, + default = itemData.count + } + }) + + if input and input[1] then + local quantity = tonumber(input[1]) + if quantity and quantity > 0 and quantity <= itemData.count then + local selectedItems = {} + selectedItems[itemName] = quantity + + -- Zeige Bestätigung + local totalValue = quantity * itemData.pfandwert + local moneyString = string.format("€%.2f", totalValue / 100) + + local confirm = lib.alertDialog({ + header = 'Pfand einlösen', + content = string.format('Möchtest du %d x %s für %s einlösen?', + quantity, itemData.label, moneyString), + centered = true, + cancel = true + }) + + if confirm == 'confirm' then + redeemPfand(selectedItems) + end + end + end +end + +-- Löse alle Items ein +function redeemAllItems(pfandItems) + local selectedItems = {} + local totalValue = 0 + local totalCount = 0 + + for itemName, itemData in pairs(pfandItems) do + selectedItems[itemName] = itemData.count + totalValue = totalValue + itemData.totalWert + totalCount = totalCount + itemData.count + end + + local moneyString = string.format("€%.2f", totalValue / 100) + + local confirm = lib.alertDialog({ + header = 'Alle Pfandartikel einlösen', + content = string.format('Möchtest du alle %d Pfandartikel für %s einlösen?', + totalCount, moneyString), + centered = true, + cancel = true + }) + + if confirm == 'confirm' then + redeemPfand(selectedItems) + end +end + +-- Sende Pfand zum Server +function redeemPfand(selectedItems) + lib.notify({ + title = 'Pfandsystem', + description = Config.Locale['processing'], + type = 'inform' + }) + + TriggerServerEvent('qb-pfandsystem:server:redeemPfand', selectedItems) +end + +-- Debug Befehle (nur wenn Debug aktiviert) +if Config.Debug then + RegisterCommand('pfandtest', function() + TriggerEvent('qb-pfandsystem:client:openPfandMenu') + end, false) + + RegisterCommand('pfandconsume', function(source, args) + if args[1] then + TriggerServerEvent('qb-pfandsystem:server:itemConsumed', args[1]) + end + end, false) +end + +-- Export für andere Scripts +exports('TriggerPfandConsumption', function(itemName) + TriggerServerEvent('qb-pfandsystem:server:itemConsumed', itemName) +end) diff --git a/resources/[inventory]/nordi_pfand/config.lua b/resources/[inventory]/nordi_pfand/config.lua new file mode 100644 index 000000000..2f93e7742 --- /dev/null +++ b/resources/[inventory]/nordi_pfand/config.lua @@ -0,0 +1,93 @@ +Config = {} + +-- Pfandautomat Props +Config.PfandautomatProps = { + 'prop_vend_soda_01', + 'prop_vend_soda_02', + 'prop_vend_water_01' +} + +-- Konsumierbare Items die Pfand generieren +Config.ConsumableItems = { + ['beer'] = { + pfandItem = 'beer_bottle', + chance = 100, -- 100% Chance Pfand zu bekommen + label = 'Bier' + }, + ['water_bottle'] = { + pfandItem = 'empty_bottle', + chance = 100, + label = 'Wasserflasche' + }, + ['cola'] = { + pfandItem = 'soda_can', + chance = 100, + label = 'Cola' + }, + ['sprite'] = { + pfandItem = 'soda_can', + chance = 100, + label = 'Sprite' + }, + ['energy_drink'] = { + pfandItem = 'energy_can', + chance = 100, + label = 'Energy Drink' + }, + ['juice'] = { + pfandItem = 'juice_bottle', + chance = 100, + label = 'Saft' + }, + ['milk'] = { + pfandItem = 'milk_bottle', + chance = 90, -- 90% Chance (manchmal geht die Flasche kaputt) + label = 'Milch' + } +} + +-- Pfand Items und ihre Werte (die leeren Behälter) +Config.PfandItems = { + ['empty_bottle'] = { + pfandwert = 25, -- Pfandwert in Cent/Credits + label = 'Leere Flasche' + }, + ['soda_can'] = { + pfandwert = 25, + label = 'Leere Dose' + }, + ['beer_bottle'] = { + pfandwert = 8, + label = 'Leere Bierflasche' + }, + ['energy_can'] = { + pfandwert = 25, + label = 'Leere Energy-Dose' + }, + ['juice_bottle'] = { + pfandwert = 25, + label = 'Leere Saftflasche' + }, + ['milk_bottle'] = { + pfandwert = 15, + label = 'Leere Milchflasche' + } +} + +-- Allgemeine Einstellungen +Config.Currency = 'cash' -- 'cash' oder 'bank' +Config.Debug = false +Config.ShowPfandNotification = true -- Zeige Benachrichtigung wenn Pfand erhalten wird + +-- Sprache +Config.Locale = { + ['pfand_menu_title'] = 'Pfandautomat', + ['pfand_menu_description'] = 'Pfandgut einlösen', + ['no_pfand_items'] = 'Du hast keine Pfandartikel bei dir!', + ['pfand_success'] = 'Du hast %s für %d Pfandartikel erhalten!', + ['pfand_error'] = 'Fehler beim Einlösen des Pfands!', + ['processing'] = 'Verarbeite Pfand...', + ['select_items'] = 'Wähle die Artikel aus, die du einlösen möchtest:', + ['pfand_received'] = 'Du hast %s erhalten!', + ['pfand_bottle_broken'] = 'Die Flasche ist beim Trinken zerbrochen!' +} diff --git a/resources/[inventory]/nordi_pfand/fxmanifest.lua b/resources/[inventory]/nordi_pfand/fxmanifest.lua new file mode 100644 index 000000000..ae1509767 --- /dev/null +++ b/resources/[inventory]/nordi_pfand/fxmanifest.lua @@ -0,0 +1,27 @@ +fx_version 'cerulean' +game 'gta5' +lua54 'yes' + +author 'YourName' +description 'Pfandsystem für QBCore' +version '1.0.0' + +shared_scripts { + '@ox_lib/init.lua', + 'config.lua' +} + +client_scripts { + 'client/main.lua' +} + +server_scripts { + 'server/main.lua' +} + +dependencies { + 'qb-core', + 'qb-target', + 'tgiann-inventory', + 'ox_lib' +} diff --git a/resources/[inventory]/nordi_pfand/server/main.lua b/resources/[inventory]/nordi_pfand/server/main.lua new file mode 100644 index 000000000..fbd04ef42 --- /dev/null +++ b/resources/[inventory]/nordi_pfand/server/main.lua @@ -0,0 +1,177 @@ +local QBCore = exports['qb-core']:GetCoreObject() + +-- Event wenn ein Item konsumiert wird +RegisterNetEvent('qb-pfandsystem:server:itemConsumed', function(itemName) + local src = source + local Player = QBCore.Functions.GetPlayer(src) + + if not Player then return end + + -- Prüfe ob das konsumierte Item Pfand generiert + if Config.ConsumableItems[itemName] then + local consumableConfig = Config.ConsumableItems[itemName] + local pfandItem = consumableConfig.pfandItem + local chance = consumableConfig.chance or 100 + + -- Würfle ob Pfand erhalten wird + local randomChance = math.random(1, 100) + + if randomChance <= chance then + -- Gebe Pfanditem + local success = exports['tgiann-inventory']:AddItem(src, pfandItem, 1) + + if success and Config.ShowPfandNotification then + local pfandLabel = Config.PfandItems[pfandItem] and Config.PfandItems[pfandItem].label or pfandItem + + TriggerClientEvent('ox_lib:notify', src, { + title = 'Pfandsystem', + description = string.format(Config.Locale['pfand_received'], pfandLabel), + type = 'success', + duration = 3000 + }) + end + + if Config.Debug then + print(string.format('[Pfandsystem] Spieler %s hat %s konsumiert und %s erhalten', + Player.PlayerData.name, itemName, pfandItem)) + end + else + -- Pfand nicht erhalten (z.B. Flasche zerbrochen) + if Config.ShowPfandNotification and chance < 100 then + TriggerClientEvent('ox_lib:notify', src, { + title = 'Pfandsystem', + description = Config.Locale['pfand_bottle_broken'], + type = 'error', + duration = 3000 + }) + end + + if Config.Debug then + print(string.format('[Pfandsystem] Spieler %s hat %s konsumiert aber kein Pfand erhalten (%d%% Chance)', + Player.PlayerData.name, itemName, chance)) + end + end + end +end) + +-- Pfand einlösen +RegisterNetEvent('qb-pfandsystem:server:redeemPfand', function(selectedItems) + local src = source + local Player = QBCore.Functions.GetPlayer(src) + + if not Player then return end + + local totalPfand = 0 + local totalItems = 0 + local itemsToRemove = {} + + -- Überprüfe ob Spieler die Items hat und berechne Gesamtpfand + for itemName, quantity in pairs(selectedItems) do + if Config.PfandItems[itemName] then + local playerItem = exports['tgiann-inventory']:GetItem(src, itemName) + + if playerItem and playerItem.count >= quantity then + local pfandWert = Config.PfandItems[itemName].pfandwert * quantity + totalPfand = totalPfand + pfandWert + totalItems = totalItems + quantity + itemsToRemove[itemName] = quantity + else + TriggerClientEvent('ox_lib:notify', src, { + title = 'Pfandsystem', + description = 'Du hast nicht genug ' .. (Config.PfandItems[itemName].label or itemName), + type = 'error' + }) + return + end + end + end + + if totalPfand <= 0 then + TriggerClientEvent('ox_lib:notify', src, { + title = 'Pfandsystem', + description = Config.Locale['no_pfand_items'], + type = 'error' + }) + return + end + + -- Entferne Items aus dem Inventar + local success = true + for itemName, quantity in pairs(itemsToRemove) do + local removed = exports['tgiann-inventory']:RemoveItem(src, itemName, quantity) + if not removed then + success = false + break + end + end + + if success then + -- Gebe Geld + if Config.Currency == 'cash' then + Player.Functions.AddMoney('cash', totalPfand) + else + Player.Functions.AddMoney('bank', totalPfand) + end + + -- Formatiere Geld für Anzeige + local moneyString = string.format("€%.2f", totalPfand / 100) + + TriggerClientEvent('ox_lib:notify', src, { + title = 'Pfandsystem', + description = string.format(Config.Locale['pfand_success'], moneyString, totalItems), + type = 'success' + }) + + if Config.Debug then + print(string.format('[Pfandsystem] Spieler %s hat %d Items für €%.2f eingelöst', + Player.PlayerData.name, totalItems, totalPfand / 100)) + end + else + TriggerClientEvent('ox_lib:notify', src, { + title = 'Pfandsystem', + description = Config.Locale['pfand_error'], + type = 'error' + }) + end +end) + +-- Hole verfügbare Pfand Items des Spielers +QBCore.Functions.CreateCallback('qb-pfandsystem:server:getPfandItems', function(source, cb) + local src = source + local pfandItems = {} + + for itemName, itemConfig in pairs(Config.PfandItems) do + local playerItem = exports['tgiann-inventory']:GetItem(src, itemName) + + if playerItem and playerItem.count > 0 then + pfandItems[itemName] = { + count = playerItem.count, + label = itemConfig.label, + pfandwert = itemConfig.pfandwert, + totalWert = itemConfig.pfandwert * playerItem.count + } + end + end + + cb(pfandItems) +end) + +-- Hook für tgiann-inventory item usage +-- Dieser Hook wird ausgelöst wenn ein Item verwendet wird +RegisterNetEvent('tgiann-inventory:server:UseItem', function(itemName, itemData) + local src = source + + -- Prüfe ob das verwendete Item in unserer Konsumierbare Items Liste ist + if Config.ConsumableItems[itemName] then + -- Warte kurz damit das originale Item erst konsumiert wird + SetTimeout(100, function() + TriggerEvent('qb-pfandsystem:server:itemConsumed', itemName) + end) + end +end) + +-- Alternative: Falls der obige Hook nicht funktioniert, kann man auch einen Export verwenden +-- Dieser Export kann von anderen Scripten aufgerufen werden +exports('ConsumePfandItem', function(source, itemName) + TriggerEvent('qb-pfandsystem:server:itemConsumed', itemName) +end) diff --git a/resources/[inventory]/nordi_trashcan/config.lua b/resources/[inventory]/nordi_trashcan/config.lua index 3f368eb68..c5e6ae74d 100644 --- a/resources/[inventory]/nordi_trashcan/config.lua +++ b/resources/[inventory]/nordi_trashcan/config.lua @@ -16,6 +16,12 @@ Config.TrashCanModels = { 'prop_cs_bin_01_skinned', 'prop_cs_bin_02', 'prop_cs_bin_03', + 'm23_2_prop_m32_dumpster_01a', + 'prop_dumpster_01a', + 'prop_dumpster_02b', + 'prop_dumpster_4b', + 'prop_dumpster_4a', + -- Add more trash can models as needed }