diff --git a/README.md b/README.md index 0c2c4b3..511abf1 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Wer es nur unter Wasser will: `hudOnlyUnderwater = true`. sehen den Lichtkegel, und zwar in die Richtung, in die tatsächlich geschaut wird. - **Tiefenanzeige** in Metern. Optional steigt der Luftverbrauch mit der Tiefe (`depthDecayEnabled`, per Default aus). +- **Tiefengrenze übers Atemgas** — mit Pressluft ab 45 m Tiefenrausch, mit Trimix + erst ab 100 m. Macht das Tiefenlimit mechanisch statt zur Absprache. - **Ausrüstung bleibt** — bei Emotes, Ragdoll, Kleiderwechsel und aufräumenden Fremd-Scripts. - **HUD ausblendbar** für Unterwasser-Screenshots. @@ -60,9 +62,9 @@ Wer es nur unter Wasser will: `hudOnlyUnderwater = true`. 2. [`items_for_ox_inventory.lua`](items_for_ox_inventory.lua) komplett markieren und in `ox_inventory/data/items.lua` innerhalb der `return { … }`-Klammer - einfügen. Sechs Items, nichts weiter anzupassen. + einfügen. Sieben Items, nichts weiter anzupassen. -3. Die sechs PNGs aus [`icons/`](icons) nach `cdn.d4rkst3r.de/items/` hochladen. +3. Die sieben PNGs aus [`icons/`](icons) nach `cdn.d4rkst3r.de/items/` hochladen. Sie heißen genau wie die Items, deshalb braucht es kein `client.image`. Es gibt bewusst **keine** fertige `items.lua` zum Ersetzen — die würde die @@ -70,14 +72,17 @@ restlichen Items des Servers überschreiben. ## Items -| Icon | Item | Label | Laufzeit | Fülldruck | Gewicht | -|---|---|---|---|---|---| -| | `diving_gear` | Tauchausrüstung | — | — | 5000 | -| | `diving_fill` | Pressluft-Kartusche | — | — | 1000 | -| | `diving_tank_small` | Tauchflasche (5 Min) | 300 s | 300 bar | 4000 | -| | `diving_tank_medium` | Tauchflasche (10 Min) | 600 s | 300 bar | 7000 | -| | `diving_tank_large` | Tauchflasche (15 Min) | 900 s | 300 bar | 10000 | -| | `diving_tank_xl` | Tauchflasche (20 Min) | 1200 s | 300 bar | 13000 | +| Icon | Item | Label | Laufzeit | Gas | max. Tiefe | Gewicht | +|---|---|---|---|---|---|---| +| | `diving_gear` | Tauchausrüstung | — | — | — | 5000 | +| | `diving_fill` | Pressluft-Kartusche | — | — | — | 1000 | +| | `diving_tank_small` | Tauchflasche (5 Min) | 300 s | Pressluft | 45 m | 4000 | +| | `diving_tank_medium` | Tauchflasche (10 Min) | 600 s | Pressluft | 45 m | 7000 | +| | `diving_tank_large` | Tauchflasche (15 Min) | 900 s | Pressluft | 45 m | 10000 | +| | `diving_tank_xl` | Tauchflasche (20 Min) | 1200 s | Pressluft | 45 m | 13000 | +| | `diving_tank_trimix` | Trimix-Flasche (15 Min) | 900 s | Trimix | 100 m | 11000 | + +Alle Flaschen starten bei 300 bar. `diving_gear` und `diving_fill` stammen aus dem Original (dort hießen sie *Diving Gear* und *Diving Tube*). Neu sind nur die vier Flaschen: im Original war @@ -130,7 +135,7 @@ FiveM* umlegbar. | Option | Default | Bedeutung | |---|---|---| -| `tanks` | 4 Flaschen | `name`, `capacity` (Sekunden), `pressure` (bar) | +| `tanks` | 5 Flaschen | `name`, `capacity` (Sekunden), `pressure` (bar), `maxDepth` (Meter), `gas` (Label fürs Menü) | | `newTanksFull` | `true` | Flaschen ohne Metadata (Shop, `AddItem`, Admin-Befehl) gelten als voll. Auf `false` muss jede neue Flasche erst mit einer Kartusche befüllt werden | | `syncIntervalSeconds` | `15` | Wie oft die Restluft an den Server gemeldet wird. Bei einem Crash gehen maximal so viele Sekunden verloren | | `maxDrainPerSecond` | `5.0` | Obergrenze der serverseitigen Prüfung | @@ -158,6 +163,14 @@ FiveM* umlegbar. | `maxDecayFactor` | `4.0` | Deckel für den Faktor | | `deepWarningDepth` | `25.0` | Ab hier wird die Tiefenanzeige eingefärbt | +**Tiefenrausch** (`narcosis`) + +| Option | Default | Bedeutung | +|---|---|---| +| `enabled` | `true` | Komplett abschaltbar | +| `warnBeforeMeters` | `5.0` | Vorwarnung so viele Meter vor der Grenze | +| `stages` | 3 Stufen | Pro Stufe: `over` (Meter unter der Grenze), `timecycle` + `strength`, `shake` + `shakeIntensity`, `drainFactor`, `damagePerTick` | + **HUD** | Option | Default | Bedeutung | @@ -200,6 +213,28 @@ ausmessen. > derselben Polizei-Taschenlampe: `prop_cs_police_torch`, `prop_police_torch`, > `prop_scn_police_torch`. Für die Beleuchtung braucht es das Prop ohnehin nicht. +## Tiefengrenze und Tiefenrausch + +Warum 40–45 m real das Limit sind, liegt nicht am Druck, sondern am **Stickstoff +in der Pressluft**: tiefer wirkt er narkotisch, und ab etwa 56 m wird auch der +Sauerstoff giftig. Wer tiefer will, atmet **Trimix** — dort ersetzt Helium einen +Teil des Stickstoffs. + +Genau so ist es hier umgesetzt: jede Flasche hat in `config/shared.lua` eine +`maxDepth`. Darunter setzt Tiefenrausch ein, in drei Stufen, je tiefer desto +heftiger — Bildschirmeffekt, Kamerawackeln, höherer Luftverbrauch, in der letzten +Stufe Schaden. Fünf Meter vorher kommt eine Warnung, und die Tiefenanzeige im HUD +wird rot und pulsiert, sobald die Grenze überschritten ist. + +Damit ist ein 45-m-Limit keine Absprache mehr, sondern spürbar — und die tiefen +Spots bleiben erreichbar, kosten aber die richtige Flasche. + +Alles daran ist in `config/client.lua` unter `narcosis` einstellbar: Schwellen, +Effekte, Stärke, Verbrauchsaufschlag, Schaden. `enabled = false` schaltet es ganz aus. + +> Die `timecycle`-Namen sind Spiel-Effekte, keine Natives. Existiert einer nicht, +> passiert einfach nichts — dann einen anderen eintragen. + ## Exports ```lua diff --git a/TESTING.md b/TESTING.md index 0504f6a..1dd1f2e 100644 --- a/TESTING.md +++ b/TESTING.md @@ -32,7 +32,7 @@ tatsächlich im Spiel lief — nicht, was „sollte gehen". - [ ] 🟡 Flasche im Inventar ansehen → `durability`-Balken zeigt den Füllstand - [ ] 🟡 Flasche einem anderen Spieler geben → Restluft geht mit - [ ] 🟡 Flasche in eine Kiste legen und wieder rausnehmen → Restluft bleibt -- [ ] 🟢 Alle vier Größen einmal durch → Laufzeiten passen ungefähr (5/10/15/20 min) +- [ ] 🟢 Alle Größen einmal durch → Laufzeiten passen (5/10/15/20 min, Trimix 15) ## 3 · Auffüllen @@ -50,13 +50,33 @@ tatsächlich im Spiel lief — nicht, was „sollte gehen". - [ ] 🔴 Untertauchen → Luft läuft, Anzeige zählt runter - [ ] 🟡 Warnungen bei 60 / 30 / 10 Sekunden → je genau **einmal** - [ ] 🔴 Flasche leer unter Wasser → Meldung, Scuba aus, Ertrinken setzt ein -- [ ] 🟡 Tief tauchen → Verbrauch steigt sichtbar schneller als an der Oberfläche +- [ ] 🟢 Mit `depthDecayEnabled = true` tief tauchen → Verbrauch steigt sichtbar. + *Per Default aus, damit die Laufzeiten exakt stimmen* - [ ] 🟢 20-Minuten-Flasche komplett leer tauchen → Laufzeit stimmt ungefähr, keine Drift durch Frame-Drops -## 5 · HUD +## 5 · Tiefengrenze und Tiefenrausch + +*Neu, komplett ungetestet. Die `timecycle`-Namen sind geraten — falls kein Effekt +kommt, in `config/client.lua` unter `narcosis.stages` einen anderen eintragen.* + +- [ ] ❓ 🟡 Mit Pressluft auf ~40 m → Vorwarnung „Du näherst dich der Grenze" +- [ ] ❓ 🔴 Unter 45 m → Bildschirmeffekt setzt ein, Tiefenanzeige rot und pulsierend +- [ ] ❓ 🟡 Unter 55 m → Effekt stärker, Kamera wackelt +- [ ] ❓ 🟡 Unter 65 m → Schaden, Luft geht spürbar schneller weg +- [ ] ❓ 🔴 Auftauchen über die Grenze → **alle** Effekte verschwinden wieder +- [ ] ❓ 🔴 Mit **Trimix** auf 60 m → kein Tiefenrausch +- [ ] ❓ 🟡 Ausrüstung ablegen während des Tiefenrauschs → Effekte weg +- [ ] ❓ 🟡 Sterben im Tiefenrausch → Effekte weg, kein Timecycle bleibt hängen +- [ ] ❓ 🟡 `ensure d4rk_divegear` im Tiefenrausch → Effekte weg +- [ ] 🟢 Auswahlmenü zeigt Gas und Tiefengrenze pro Flasche +- [ ] 🟢 `narcosis.enabled = false` → nichts davon passiert + +## 6 · HUD - [x] Erscheint unter Wasser mit Ausrüstung, Tiefe/Luft/Druck stimmen +- [ ] 🟡 An Land mit angelegter Ausrüstung → HUD ist da, Tiefe steht auf 0.0 m + (Finimeter ablesen ohne Inventar) - [ ] 🟡 Auftauchen → HUD blendet weich aus - [ ] 🟡 Ausrüstung ablegen während es sichtbar ist → HUD verschwindet - [ ] 🟢 Farbstufen: bernstein unter 60 s, rot unter 10 s mit Pulsieren @@ -67,7 +87,7 @@ tatsächlich im Spiel lief — nicht, was „sollte gehen". konnte ich nicht prüfen* - [ ] 🟢 Export `exports.d4rk_divegear:setHudVisible(false)` funktioniert -## 6 · Lampe +## 7 · Lampe - [x] Lampen-Anzeige im HUD schaltet um - [ ] ❓ 🔴 **Mit Scuba-Kleidung am Ped** (Component 8) → Lampe leuchtet @@ -78,7 +98,7 @@ tatsächlich im Spiel lief — nicht, was „sollte gehen". - [ ] 🟡 Ausrüstung ablegen mit Lampe an → Lampe geht aus, bleibt aus - [ ] 🟡 Sterben mit Lampe an → Lampe aus -## 7 · Ausrüstung bleibt dran +## 8 · Ausrüstung bleibt dran *Der ursprüngliche Bug. Jeder Punkt hier ist ein eigener Weg, wie die Props verschwinden konnten.* @@ -92,7 +112,7 @@ verschwinden konnten.* - [ ] 🟡 `ensure d4rk_divegear` während des Tauchens → keine Props als Leiche in der Welt zurück -## 8 · Zu zweit +## 9 · Zu zweit - [ ] 🔴 Beide mit Ausrüstung → jeder sieht Maske und Flasche des anderen - [ ] ❓ 🔴 **Beide mit Lampe** → jeder sieht das Licht des anderen @@ -101,14 +121,14 @@ verschwinden konnten.* wenn er sie an hat. *Dafür ist der Abgleich-Thread da* - [ ] 🟡 Einer stirbt/respawnt mit Lampe an → beim anderen geht sie aus -## 9 · Serverseitige Prüfung +## 10 · Serverseitige Prüfung - [ ] 🟢 Normal tauchen → **keine** Warnungen oder Korrekturen im Server-Log - [ ] 🟡 Tief tauchen mit hohem Verbrauch → Server schreibt keine Luft zurück. *Wenn doch: `maxDrainPerSecond` in `config/shared.lua` erhöhen* - [ ] 🟢 Flasche wegwerfen während sie getragen wird → kein Fehler im Log -## 10 · Performance +## 11 · Performance - [ ] 🟢 Längerer Tauchgang → `resmon` bleibt niedrig - [ ] 🟢 Mehrere Taucher mit Lampe gleichzeitig → keine spürbaren FPS-Einbrüche diff --git a/client/main.lua b/client/main.lua index 7a125ff..9bde106 100644 --- a/client/main.lua +++ b/client/main.lua @@ -55,13 +55,61 @@ local function getDepth() return math.max(0.0, waterZ - coords.z) end +--- Aktuell aktive Tiefenrausch-Stufe (Index in config.narcosis.stages), 0 = keine. +local narcosisStage = 0 +local narcosisWarned = false +local narcosisDamageBuffer = 0.0 + +--- Wie weit die aktuelle Tiefe unter der Grenze der getragenen Flasche liegt. +--- @return number Meter unterhalb der Grenze, negativ solange alles gut ist +local function getDepthOverLimit() + if not activeTank or not activeTank.maxDepth then return -math.huge end + + return currentDepth - activeTank.maxDepth +end + +--- Setzt Bildschirmeffekt und Kamerawackeln auf die angegebene Stufe. +--- @param stage number 0 = alles aus +local function applyNarcosisStage(stage) + if stage == narcosisStage then return end + + narcosisStage = stage + + ClearTimecycleModifier() + StopGameplayCamShaking(true) + + local data = stage > 0 and config.narcosis.stages[stage] + + if not data then return end + + if data.timecycle then + SetTimecycleModifier(data.timecycle) + SetTimecycleModifierStrength(data.strength or 1.0) + end + + if data.shake then + ShakeGameplayCam(data.shake, data.shakeIntensity or 0.5) + end +end + --- Verbrauchsfaktor. Tiefer tauchen kostet mehr Luft. --- Nutzt die geglättete Tiefe aus dem HUD-Thread, damit Wellengang den Verbrauch --- nicht im Sekundentakt springen lässt. local function getDecayFactor() - if not config.depthDecayEnabled then return 1.0 end + local factor = 1.0 - return math.min(config.maxDecayFactor, 1.0 + currentDepth / config.depthDecayReference) + if config.depthDecayEnabled then + factor = math.min(config.maxDecayFactor, 1.0 + currentDepth / config.depthDecayReference) + end + + -- Tiefenrausch: unter Stress atmet man mehr. + local stage = narcosisStage > 0 and config.narcosis.stages[narcosisStage] + + if stage then + factor = factor * (stage.drainFactor or 1.0) + end + + return factor end --- @param ped number? default cache.ped - beim Model-Wechsel muss der neue Ped explizit rein @@ -198,8 +246,11 @@ local function removeGear(outOfAir, immediateSync) currentGear.enabled = false setLamp(false) + applyNarcosisStage(0) activeTank = nil warned = {} + narcosisWarned = false + narcosisDamageBuffer = 0.0 deleteGear() disableScuba(outOfAir) @@ -220,7 +271,8 @@ local function chooseTank(tanks) options[i] = { title = tank.label, description = locale('info.tank_remaining', formatTime(tank.oxygen), - math.floor(tank.oxygen / tank.capacity * 100)), + math.floor(tank.oxygen / tank.capacity * 100), + tank.gas or '?', math.floor(tank.maxDepth or 0)), icon = 'fa-solid fa-bottle-water', onSelect = function() selection:resolve(tank) end } @@ -331,6 +383,8 @@ local function sendHudState(visible) reserve = pressure > 0 and pressure <= config.reservePressure, level = level, deep = currentDepth >= config.deepWarningDepth, + -- Grenze der getragenen Flasche überschritten: Tiefenrausch läuft. + overLimit = config.narcosis.enabled and getDepthOverLimit() >= 0, hasLamp = true, lamp = lampOn }) @@ -396,6 +450,51 @@ local function startHudThread() end) end +--- Wertet die Tiefe gegen die Grenze der getragenen Flasche aus und setzt Effekte, +--- Verbrauchsaufschlag und Schaden. Läuft auch über Wasser weiter, damit die +--- Effekte beim Auftauchen wieder verschwinden. +--- @param elapsed number Sekunden seit dem letzten Aufruf +local function updateNarcosis(elapsed) + if not config.narcosis.enabled then return end + + local over = getDepthOverLimit() + local stages = config.narcosis.stages + local stage = 0 + + for i = 1, #stages do + if over >= stages[i].over then stage = i end + end + + applyNarcosisStage(stage) + + -- Vorwarnung, solange noch Zeit zum Umkehren ist. + if activeTank and over >= -config.narcosis.warnBeforeMeters then + if not narcosisWarned then + narcosisWarned = true + exports.qbx_core:Notify(locale('info.depth_limit', math.floor(activeTank.maxDepth or 0)), 'warning') + end + else + narcosisWarned = false + end + + local data = stage > 0 and stages[stage] + + if not data or (data.damagePerTick or 0) <= 0 then + narcosisDamageBuffer = 0.0 + return + end + + -- Schaden sammeln statt jeden Tick zu runden, sonst geht bei 250 ms Takt + -- alles unter 4 Schaden pro Sekunde verloren. + narcosisDamageBuffer = narcosisDamageBuffer + data.damagePerTick * elapsed + + if narcosisDamageBuffer >= 1.0 then + local damage = math.floor(narcosisDamageBuffer) + narcosisDamageBuffer -= damage + ApplyDamageToPed(cache.ped, damage, false) + end +end + --- Zieht Luft über die tatsächlich vergangene Zeit ab statt über gezählte Ticks. --- Ein Wait(1000) läuft bei Last spürbar länger als eine Sekunde - über einen --- 20-Minuten-Tauchgang summiert sich das sichtbar auf. @@ -411,6 +510,8 @@ local function startOxygenLevelDecrementerThread() local elapsed = (now - lastTick) / 1000 lastTick = now + updateNarcosis(elapsed) + if not activeTank then goto continue end if IsPedSwimmingUnderWater(cache.ped) and activeTank.oxygen > 0 then @@ -622,6 +723,7 @@ AddEventHandler('onResourceStop', function(resource) syncTank(true) setLamp(false) + applyNarcosisStage(0) deleteGear() SendNUIMessage({ action = 'state', visible = false }) SetEnableScuba(cache.ped, false) diff --git a/config/client.lua b/config/client.lua index b4beb7e..6b99b53 100644 --- a/config/client.lua +++ b/config/client.lua @@ -59,6 +59,57 @@ return { --- Ab dieser Tiefe wird die Tiefenanzeige eingefärbt (Meter). deepWarningDepth = 25.0, + --------------------------------------------------------------------------- + -- Tiefenrausch + --------------------------------------------------------------------------- + -- Macht die Tiefengrenze mechanisch statt zur Absprache: unterhalb der + -- maxDepth der getragenen Flasche (config/shared.lua) wird es ungemütlich. + -- Mit Pressluft ab 45 m, mit Trimix erst ab 100 m - wer die tiefen Spots + -- sehen will, braucht also die richtige Flasche. + + narcosis = { + enabled = true, + + --- Wie viele Meter *vor* der Grenze schon gewarnt wird. + warnBeforeMeters = 5.0, + + --- Stufen, sobald die Grenze überschritten ist. `over` = Meter unterhalb + --- der maxDepth der Flasche. Es gilt jeweils die höchste erreichte Stufe, + --- die Reihenfolge muss also aufsteigend sein. + --- + --- timecycle Bildschirmeffekt. Namen sind Timecycle-Modifier des + --- Spiels, keine Natives - falls einer nicht existiert, + --- passiert einfach nichts. Alternativen zum Ausprobieren: + --- 'drug_flying_base', 'drug_deadman', 'REDMIST', + --- 'spectator5'. Auf nil = kein Effekt. + --- strength 0.0 bis 1.0 + --- shake Kamerawackeln, z.B. 'DRUNK_SHAKE', 'SKY_DIVING_SHAKE'. + --- Auf nil = kein Wackeln. + --- shakeIntensity Stärke des Wackelns + --- drainFactor Faktor auf den Luftverbrauch (Stress atmet mehr) + --- damagePerTick Schaden pro Sekunde. 0 = kein Schaden. + stages = { + { + over = 0.0, + timecycle = 'drug_wobbly', strength = 0.3, + shake = nil, shakeIntensity = 0.0, + drainFactor = 1.5, damagePerTick = 0 + }, + { + over = 10.0, + timecycle = 'drug_wobbly', strength = 0.7, + shake = 'DRUNK_SHAKE', shakeIntensity = 0.3, + drainFactor = 2.0, damagePerTick = 0 + }, + { + over = 20.0, + timecycle = 'drug_wobbly', strength = 1.0, + shake = 'DRUNK_SHAKE', shakeIntensity = 0.8, + drainFactor = 3.0, damagePerTick = 2 + }, + }, + }, + --- Reservedruck in bar. Darunter wird die Druckanzeige eingefärbt - in der --- Tauchpraxis die Schwelle, ab der man den Aufstieg einleitet. reservePressure = 50, diff --git a/config/shared.lua b/config/shared.lua index 21f1720..ca593be 100644 --- a/config/shared.lua +++ b/config/shared.lua @@ -3,18 +3,27 @@ local config = { --- Tauchflaschen. + --- --- capacity = Laufzeit in Sekunden bei normalem Verbrauch. --- pressure = Fülldruck in bar. Reine Anzeige: der angezeigte Druck ist --- pressure * (Restluft / capacity). Bei konstantem Volumen ist der --- Druck proportional zur verbliebenen Gasmenge, das passt also. --- Dass alle Flaschen denselben Fülldruck haben ist gewollt - in echt --- macht das Volumen die Laufzeit, nicht der Druck. + --- maxDepth = Tiefe in Metern, bis zu der das Atemgas verträglich ist. + --- Darunter setzt Tiefenrausch ein (siehe narcosis in config/client.lua). + --- Der Grund ist real der Stickstoff in der Pressluft: tiefer wirkt er + --- narkotisch, und ab ~56 m wird auch der Sauerstoff giftig. Wer tiefer + --- will, atmet Trimix - dort ersetzt Helium einen Teil des Stickstoffs. + --- gas = Nur fürs Auswahlmenü, damit man die Flaschen unterscheiden kann. + --- --- Reihenfolge = Reihenfolge im Auswahlmenü. tanks = { - { name = 'diving_tank_small', capacity = 300, pressure = 300 }, -- 5 Minuten - { name = 'diving_tank_medium', capacity = 600, pressure = 300 }, -- 10 Minuten - { name = 'diving_tank_large', capacity = 900, pressure = 300 }, -- 15 Minuten - { name = 'diving_tank_xl', capacity = 1200, pressure = 300 }, -- 20 Minuten + { name = 'diving_tank_small', capacity = 300, pressure = 300, maxDepth = 45.0, gas = 'Pressluft' }, -- 5 Minuten + { name = 'diving_tank_medium', capacity = 600, pressure = 300, maxDepth = 45.0, gas = 'Pressluft' }, -- 10 Minuten + { name = 'diving_tank_large', capacity = 900, pressure = 300, maxDepth = 45.0, gas = 'Pressluft' }, -- 15 Minuten + { name = 'diving_tank_xl', capacity = 1200, pressure = 300, maxDepth = 45.0, gas = 'Pressluft' }, -- 20 Minuten + { name = 'diving_tank_trimix', capacity = 900, pressure = 300, maxDepth = 100.0, gas = 'Trimix' }, -- 15 Minuten, tieftauglich }, --- Flaschen ohne Metadata als voll behandeln. Betrifft alles, was frisch aus diff --git a/icons/diving_fill.png b/icons/diving_fill.png index d419cdc..79c90fb 100644 Binary files a/icons/diving_fill.png and b/icons/diving_fill.png differ diff --git a/icons/diving_gear.png b/icons/diving_gear.png index 3bc5d6a..935d92f 100644 Binary files a/icons/diving_gear.png and b/icons/diving_gear.png differ diff --git a/icons/diving_tank_large.png b/icons/diving_tank_large.png index c013931..04d88a2 100644 Binary files a/icons/diving_tank_large.png and b/icons/diving_tank_large.png differ diff --git a/icons/diving_tank_medium.png b/icons/diving_tank_medium.png index c11ba02..8699cc1 100644 Binary files a/icons/diving_tank_medium.png and b/icons/diving_tank_medium.png differ diff --git a/icons/diving_tank_small.png b/icons/diving_tank_small.png index 53af1c5..25a6adc 100644 Binary files a/icons/diving_tank_small.png and b/icons/diving_tank_small.png differ diff --git a/icons/diving_tank_trimix.png b/icons/diving_tank_trimix.png new file mode 100644 index 0000000..35e96e4 Binary files /dev/null and b/icons/diving_tank_trimix.png differ diff --git a/icons/diving_tank_xl.png b/icons/diving_tank_xl.png index dfe3d2e..35a334e 100644 Binary files a/icons/diving_tank_xl.png and b/icons/diving_tank_xl.png differ diff --git a/icons/gen-icons.mjs b/icons/gen-icons.mjs index 45f699e..f9ef830 100644 --- a/icons/gen-icons.mjs +++ b/icons/gen-icons.mjs @@ -40,7 +40,8 @@ const BANDS = { small: '#4ade80', medium: '#38bdf8', large: '#fbbf24', - xl: '#f472b6' + xl: '#f472b6', + trimix: '#a78bfa' }; const defs = ` @@ -113,6 +114,17 @@ ${tank(82, 38, 38, 118, BANDS.xl)} font-size="16" font-weight="700" fill="${C.outline}">20` )); +// --- Trimix: Doppelflasche mit eigenem Farbband, deutlich abgesetzt von den +// --- Pressluft-Flaschen, weil die Verwechslung teuer waere. +writeFileSync(join(OUT, 'diving_tank_trimix.svg'), svg( + ` +${tank(46, 38, 38, 118, BANDS.trimix)} +${tank(82, 38, 38, 118, BANDS.trimix)} + + TRIMIX` +)); + // --- Tauchmaske writeFileSync(join(OUT, 'diving_gear.svg'), svg( ` @@ -145,7 +157,8 @@ writeFileSync(join(OUT, 'diving_fill.svg'), svg( // --- Kontrollblatt const NAMES = [ 'diving_gear', 'diving_fill', - 'diving_tank_small', 'diving_tank_medium', 'diving_tank_large', 'diving_tank_xl' + 'diving_tank_small', 'diving_tank_medium', 'diving_tank_large', 'diving_tank_xl', + 'diving_tank_trimix' ]; const slots = (extra = '') => diff --git a/icons/src/diving_tank_trimix.svg b/icons/src/diving_tank_trimix.svg new file mode 100644 index 0000000..39b0842 --- /dev/null +++ b/icons/src/diving_tank_trimix.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TRIMIX + diff --git a/items_for_ox_inventory.lua b/items_for_ox_inventory.lua index 0ea01e4..2deb96e 100644 --- a/items_for_ox_inventory.lua +++ b/items_for_ox_inventory.lua @@ -3,7 +3,7 @@ -- ============================================================================= -- -- Alles unten komplett markieren und innerhalb der `return {` ... `}`-Klammer --- einfügen. Sechs Items, nichts weiter anzupassen. +-- einfügen. Sieben Items, nichts weiter anzupassen. -- -- Bewusst KEINE fertige items.lua zum Ersetzen: die würde die restlichen Items -- des Servers mitlöschen. @@ -73,3 +73,11 @@ close = true, description = 'Doppelflasche, 300 bar. Reicht für etwa 20 Minuten.' }, + +['diving_tank_trimix'] = { + label = 'Trimix-Flasche (15 Min)', + weight = 11000, + stack = false, + close = true, + description = 'Helium-Sauerstoff-Stickstoff-Gemisch, 300 bar. Kein Tiefenrausch bis 100 m.' +}, diff --git a/locales/de.json b/locales/de.json index 30eaa0a..0725166 100644 --- a/locales/de.json +++ b/locales/de.json @@ -18,7 +18,8 @@ "pullout_suit": "Tauchanzug wird ausgezogen...", "filling_air": "Sauerstoff wird aufgefüllt...", "oxygen_low": "Nur noch %s Luft!", - "tank_remaining": "%s verbleibend (%d%%)" + "tank_remaining": "%s verbleibend (%d%%) · %s bis %d m", + "depth_limit": "Du näherst dich der Grenze deines Atemgases (%d m)!" }, "menu": { "choose_tank": "Tauchflasche wählen" diff --git a/locales/en.json b/locales/en.json index 44fe2af..98faa5d 100644 --- a/locales/en.json +++ b/locales/en.json @@ -18,7 +18,8 @@ "pullout_suit": "Taking off your diving suit...", "filling_air": "Filling air...", "oxygen_low": "Only %s of air left!", - "tank_remaining": "%s remaining (%d%%)" + "tank_remaining": "%s remaining (%d%%) · %s down to %d m", + "depth_limit": "You're approaching the limit of your breathing gas (%d m)!" }, "menu": { "choose_tank": "Choose an air tank" diff --git a/nui/script.js b/nui/script.js index fc7c86a..38cf095 100644 --- a/nui/script.js +++ b/nui/script.js @@ -45,6 +45,7 @@ function render(state) { hud.classList.toggle('warn', state.level === 'warn'); hud.classList.toggle('danger', state.level === 'danger'); hud.classList.toggle('deep', !!state.deep); + hud.classList.toggle('overlimit', !!state.overLimit); lamp.classList.toggle('hidden', !state.hasLamp); lamp.classList.toggle('on', !!state.lamp); diff --git a/nui/style.css b/nui/style.css index a39a3d1..d73f09b 100644 --- a/nui/style.css +++ b/nui/style.css @@ -199,6 +199,12 @@ body { #hud.deep #depth-value { color: var(--warn); } +/* Tiefengrenze des Atemgases überschritten - Tiefenrausch läuft. */ +#hud.overlimit #depth-value { + color: var(--danger); + animation: pulse 1s ease-in-out infinite; +} + /* Reservedruck: in der Tauchpraxis die Schwelle zum Aufstieg. */ #pressure.reserve .value { color: var(--danger); } diff --git a/server/main.lua b/server/main.lua index dc7c0b2..cc5a52f 100644 --- a/server/main.lua +++ b/server/main.lua @@ -82,7 +82,9 @@ local function getTankList(source) label = (exports.ox_inventory:Items(name) or {}).label or name, oxygen = readOxygen(slot, tankConfig), capacity = tankConfig.capacity, - pressure = tankConfig.pressure + pressure = tankConfig.pressure, + maxDepth = tankConfig.maxDepth, + gas = tankConfig.gas } end end