From accee02a0597bb5dec33af6a9faef9209690985e Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Mon, 28 Sep 2026 23:52:27 +0200 Subject: [PATCH] feat: Patronen per Client-Export, /tauchartikel legt die Items an CreateUseableItem feuert fuer Items aus d4rk_items nie: consume ist dort immer gesetzt (daten.lua:224), das Inventar erreicht den qbx-Rueckruf nur bei consume == nil (server.lua:623). Die Patronen tragen deshalb client_export = d4rk_divegear.patroneBenutzen und consume 0, wie d4rk_medical. /tauchartikel legt die sieben Items ueber adminItemCreate an, nur auf Zuruf; "nachziehen" stellt bei vorhandenen nur consume und Export richtig. Flasche und Maske consume 0 wie das Kleidungsitem clothing. Co-Authored-By: Claude Opus 5.5 (1M context) --- client/main.lua | 19 +++++- fxmanifest.lua | 6 +- locales/de.json | 30 +++++++++ locales/en.json | 30 +++++++++ server/artikel.lua | 149 +++++++++++++++++++++++++++++++++++++++++++++ server/main.lua | 14 ++--- 6 files changed, 236 insertions(+), 12 deletions(-) create mode 100644 server/artikel.lua diff --git a/client/main.lua b/client/main.lua index 10c1830..1bdcbe2 100644 --- a/client/main.lua +++ b/client/main.lua @@ -586,10 +586,19 @@ CreateThread(function() end) --[[ - EINE PATRONE BENUTZEN = SIE EINSETZEN (Server: CreateUseableItem je - Patrone). Nur an Land, mit Balken - wie vorher das Anlegen. + EINE PATRONE BENUTZEN = SIE EINSETZEN. Nur an Land, mit Balken - wie + vorher das Anlegen. + + UEBER EINEN CLIENT-EXPORT AM ITEM, NICHT CreateUseableItem (28.09.2026). + d4rk_items setzt consume immer (daten.lua:224, `or 1`), und d4rk_inventory + erreicht den qbx-Rueckruf nur bei consume == nil (server.lua:623) - fuer + Items aus unserer Tabelle feuerte er also nie. Die Patronen tragen + client_export = 'd4rk_divegear.patroneBenutzen' und consume = 0 (angelegt + mit /tauchartikel, server/artikel.lua); das Inventar ruft + exports.d4rk_divegear:patroneBenutzen(daten, slot) mit slot = { name, + slot, metadata } - dasselbe wie d4rk_medical `benutzen`. ]] -RegisterNetEvent('d4rk_divegear:client:patroneEinsetzen', function(slot) +local function einsetzen(slot) if IsPedSwimming(cache.ped) or cache.vehicle then lib.notify({ description = locale('error.not_standing_up'), type = 'error' }) return @@ -622,6 +631,10 @@ RegisterNetEvent('d4rk_divegear:client:patroneEinsetzen', function(slot) lib.notify({ description = locale('success.patrone_getauscht'), type = 'success' }) pruefen() +end + +exports('patroneBenutzen', function(_, slot) + einsetzen(type(slot) == 'table' and slot.slot or nil) end) lib.addKeybind({ diff --git a/fxmanifest.lua b/fxmanifest.lua index d1172fa..8f89270 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -13,7 +13,11 @@ shared_scripts { '@qbx_core/modules/lib.lua', } -server_script 'server/main.lua' +server_scripts { + 'server/main.lua', + -- /tauchartikel: die Items in d4rk_item anlegen, nur auf Zuruf (28.09.2026). + 'server/artikel.lua', +} client_scripts { -- lib.notify im Hausdesign (d4rk_lib) - VOR allen, die melden. diff --git a/locales/de.json b/locales/de.json index 1855377..b9eee54 100644 --- a/locales/de.json +++ b/locales/de.json @@ -47,5 +47,35 @@ "keybind": { "toggle_lamp": "Tauchlampe an/aus", "toggle_hud": "Tauch-HUD ein-/ausblenden" + }, + "artikel": { + "diving_tank": { + "name": "Taucherflasche", + "text": "Tauchgerät zum Anziehen. Eine Patrone benutzen, um sie einzusetzen oder zu tauschen." + }, + "diving_mask": { + "name": "Tauchmaske", + "text": "Ohne Maske kein Atmen unter Wasser." + }, + "diving_tank_small": { + "name": "Flaschenpatrone (5 Min)", + "text": "Pressluft, 300 bar, bis 45 m. Reicht für etwa 5 Minuten." + }, + "diving_tank_medium": { + "name": "Flaschenpatrone (10 Min)", + "text": "Pressluft, 300 bar, bis 45 m. Reicht für etwa 10 Minuten." + }, + "diving_tank_large": { + "name": "Flaschenpatrone (15 Min)", + "text": "Pressluft, 300 bar, bis 45 m. Reicht für etwa 15 Minuten." + }, + "diving_tank_xl": { + "name": "Flaschenpatrone (20 Min)", + "text": "Pressluft, 300 bar, bis 45 m. Reicht für etwa 20 Minuten." + }, + "diving_tank_trimix": { + "name": "Trimix-Patrone (15 Min)", + "text": "Trimix, 300 bar, bis 100 m. Reicht für etwa 15 Minuten." + } } } diff --git a/locales/en.json b/locales/en.json index 45e8216..8f85334 100644 --- a/locales/en.json +++ b/locales/en.json @@ -47,5 +47,35 @@ "keybind": { "toggle_lamp": "Toggle dive lamp", "toggle_hud": "Toggle dive HUD" + }, + "artikel": { + "diving_tank": { + "name": "Scuba tank", + "text": "Breathing apparatus to wear. Use a cartridge to insert or swap it." + }, + "diving_mask": { + "name": "Diving mask", + "text": "No mask, no breathing underwater." + }, + "diving_tank_small": { + "name": "Tank cartridge (5 min)", + "text": "Compressed air, 300 bar, down to 45 m. Lasts about 5 minutes." + }, + "diving_tank_medium": { + "name": "Tank cartridge (10 min)", + "text": "Compressed air, 300 bar, down to 45 m. Lasts about 10 minutes." + }, + "diving_tank_large": { + "name": "Tank cartridge (15 min)", + "text": "Compressed air, 300 bar, down to 45 m. Lasts about 15 minutes." + }, + "diving_tank_xl": { + "name": "Tank cartridge (20 min)", + "text": "Compressed air, 300 bar, down to 45 m. Lasts about 20 minutes." + }, + "diving_tank_trimix": { + "name": "Trimix cartridge (15 min)", + "text": "Trimix, 300 bar, down to 100 m. Lasts about 15 minutes." + } } } diff --git a/server/artikel.lua b/server/artikel.lua new file mode 100644 index 0000000..a50e961 --- /dev/null +++ b/server/artikel.lua @@ -0,0 +1,149 @@ +--[[ + d4rk_divegear - /tauchartikel: die Items in d4rk_item anlegen (28.09.2026). + + DIE ITEMS GEHOEREN d4rk_items. Angelegt wird ueber dieselben Exporte wie + der Editor im Panel (adminItemList / adminItemCreate) - dasselbe Muster + wie d4rk_medical `medartikel` (server/artikel.lua dort). + + NUR AUF ZURUF, NIE BEIM START: eine Saat bei jedem Start holte zurueck, was + der Betreiber geloescht hat (Gedaechtnis "Wiederholte Saat holt + Geloeschtes zurueck"). Vorhandene Items werden NICHT angefasst - was im + Panel gepflegt ist, gewinnt. + + NUR AN DER SERVERKONSOLE (restricted, source 0). + + Taucherflasche Kleidung (Kleiderladen, d4rk_garment -> item). Traegt + die Patrone in der Metadata. Gewicht GESETZT: Geraet + mit Atemregler ohne Patrone. + Tauchmaske Kleidung. + Patronen die fuenf aus config/shared.lua. Gewichte aus + items_for_ox_inventory.lua (dem Original). + client_export + consume = 0: siehe client/main.lua + (einsetzen) - CreateUseableItem feuert hier nie. + + consume = 0 bei ALLEN - wie das Kleidungsitem `clothing` in + d4rk_inventory/data/items.lua. Mit dem Vorgabewert 1 (d4rk_items + daten.lua:224) koennte "Benutzen" im Inventar die Flasche verbrauchen. + Am 28.09.2026 zuerst ohne angelegt (Flasche, Maske: consume 1) - deshalb + gibt es `tauchartikel nachziehen`: stellt bei VORHANDENEN Items nur + consume und den Export richtig, alles andere bleibt, wie es im Panel steht. + + stack = false bei allen: die Luft steht in der Metadata jedes Stuecks. + KEIN decay und keine durability-Schalter: metadata.durability zeigt den + Fuellstand und darf bei 0 nicht zum Loeschen fuehren (ENTSCHEIDUNGEN.md). +]] + +local shared = require 'config.shared' + +local ITEMS = 'd4rk_items' +local EXPORT = 'd4rk_divegear.patroneBenutzen' + +-- Die Schalter einer Zeile als Boolean: adminItemUpdate liest sie mit +-- `w.x and 1 or 0`, eine 0 als Zahl waere in Lua wahr (wie d4rk_medical +-- server/artikel.lua, SCHALTER). +local SCHALTER = { + 'stack', 'close_ui', 'nur_ausgabe', 'aktiv', 'cancel', + 'disable_move', 'disable_car', 'disable_combat', 'allow_armed', 'durability', +} + +local function wahr(x) return x == true or x == 1 end + +local GEWICHT = { + [shared.rigItem] = 3000, + [shared.maskItem] = 400, + diving_tank_small = 4000, + diving_tank_medium = 7000, + diving_tank_large = 10000, + diving_tank_xl = 13000, + diving_tank_trimix = 11000, +} + +local function liste() + local l = { + { name = shared.rigItem }, + { name = shared.maskItem }, + } + + for i = 1, #shared.tankNames do + l[#l + 1] = { name = shared.tankNames[i], patrone = true } + end + + return l +end + +RegisterCommand('tauchartikel', function(source, args) + if source ~= 0 then return end + + local nachziehen = args[1] == 'nachziehen' + + if GetResourceState(ITEMS) ~= 'started' then + print('^1[d4rk_divegear] tauchartikel: d4rk_items laeuft nicht - nichts angelegt.^7') + return + end + + local ok, zeilen = pcall(function() return exports[ITEMS]:adminItemList() end) + + if not ok or type(zeilen) ~= 'table' then + print('^1[d4rk_divegear] tauchartikel: adminItemList antwortet nicht - UNGUELTIG, nichts angelegt.^7') + return + end + + local da = {} + for _, z in ipairs(zeilen) do if z.name then da[z.name] = z end end + + -- GEGENPROBE: eine leere Liste hiesse "d4rk_items kennt kein einziges + -- Item" - das ist nie wahr, sondern eine kaputte Antwort. + if next(da) == nil then + print('^1[d4rk_divegear] tauchartikel: adminItemList lieferte 0 Items - UNGUELTIG, nichts angelegt.^7') + return + end + + print(('[d4rk_divegear] tauchartikel: %d Items in d4rk_item bekannt.'):format(#zeilen)) + + for _, it in ipairs(liste()) do + local sollExport = it.patrone and EXPORT or nil + local z = da[it.name] + + if z then + local istExport = (z.client_export and z.client_export ~= '') and z.client_export or nil + local passt = tonumber(z.consume) == 0 and istExport == sollExport + + if passt then + print((' %-20s vorhanden, passt'):format(it.name)) + elseif not nachziehen then + print((' %-20s ^3vorhanden, consume %s / Export %s - soll 0 / %s: tauchartikel nachziehen^7') + :format(it.name, tostring(z.consume), tostring(istExport), tostring(sollExport))) + else + local w = {} + for k, v in pairs(z) do w[k] = v end + for _, k in ipairs(SCHALTER) do w[k] = wahr(z[k]) end + w.consume = 0 + w.client_export = sollExport or '' + + local okU, erfolg, grund = pcall(function() return exports[ITEMS]:adminItemUpdate(0, z.id, w) end) + + print((' %-20s %s'):format(it.name, + (okU and erfolg == true) and '^2nachgezogen (consume 0)^7' + or ('^1FEHLER: %s^7'):format(okU and tostring(grund) or tostring(erfolg)))) + end + else + local werte = { + name = it.name, + label = locale('artikel.' .. it.name .. '.name'), + description = locale('artikel.' .. it.name .. '.text'), + weight = GEWICHT[it.name] or 1000, + stack = false, + close_ui = true, + aktiv = true, + consume = 0, + client_export = sollExport, + } + + local okC, erfolg, grund = pcall(function() return exports[ITEMS]:adminItemCreate(0, werte) end) + + print((' %-20s %s'):format(it.name, + (okC and erfolg == true) and '^2angelegt^7' + or ('^1FEHLER: %s^7'):format(okC and tostring(grund) or tostring(erfolg)))) + end + end +end, true) diff --git a/server/main.lua b/server/main.lua index c425b02..bad7222 100644 --- a/server/main.lua +++ b/server/main.lua @@ -243,15 +243,13 @@ AddEventHandler('playerDropped', function() lastSync[source] = nil end) --- Eine Patrone benutzen = sie in die getragene Flasche einsetzen (28.09.2026). --- d4rk_inventory ruft den Rueckruf mit den Itemdaten samt Slot --- (modules/bridge/qbx/server.lua: cb(source, data)). -for i = 1, #shared.tankNames do - exports.qbx_core:CreateUseableItem(shared.tankNames[i], function(source, data) - TriggerClientEvent('d4rk_divegear:client:patroneEinsetzen', source, data and data.slot) - end) -end +-- Eine Patrone benutzen = sie einsetzen: ueber den Client-Export am Item +-- (client/main.lua, patroneBenutzen). CreateUseableItem feuert fuer Items aus +-- d4rk_items nie - consume ist dort immer gesetzt (28.09.2026). +-- STILLGELEGT (Nachfuellen kommt spaeter ueber Shop/Crafting). Und ACHTUNG fuer +-- dann: CreateUseableItem feuert fuer Items aus d4rk_items nie (consume ist +-- dort immer gesetzt) - der Weg braucht einen Client-Export wie die Patronen. exports.qbx_core:CreateUseableItem(shared.fillItem, function(source) local tanks = getTankList(source)