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 @@
+
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