feat: Flaschengroessen mit echter Laufzeit und persistenter Restluft
Lint / Lint Resource (push) Has been cancelled

Der Sauerstoff war eine lokale Client-Variable: nicht persistent, an kein Item
gebunden, weg bei Relog. Dazu ergab startingOxygenLevel=100 bei decayRate=1/s
genau 100 Sekunden Tauchzeit statt Minuten.

Sauerstoff-Logik:
- Restsekunden statt Punkte, Verbrauch ueber GetGameTimer-Delta statt gezaehlter
  Wait(1000) - ein Tick laeuft unter Last laenger als eine Sekunde, was sich
  ueber einen langen Tauchgang aufsummiert
- Float-Vergleiche (oxygenLevel % 10 == 0, == 0) raus, Warnschwellen als
  config.warnAtSeconds, jede Schwelle einmal pro Tauchgang
- Verbrauch steigt mit der Tiefe (1 + tiefe/30, gedeckelt), abschaltbar
- Anzeige als mm:ss

Flaschen:
- Vier Items mit capacity in Sekunden (300/600/900/1200) in config/shared.lua
- Restluft in metadata.oxygen, Fuellstand zusaetzlich in metadata.durability,
  damit der Balken direkt im Inventar-Slot sichtbar ist
- Kein decay auf den Items: ox_inventory loescht sonst die leere Flasche
- Auswahlmenue beim Anlegen und Auffuellen (entfaellt bei nur einer Flasche)
- diving_fill fuellt bis capacity statt auf einen Fixwert, verweigert volle
  Flaschen und verbraucht sich nur bei Erfolg
- items_for_ox_inventory.lua zum Reinkopieren

Server:
- getTanks/syncTank als Callbacks, Restluft kann nur sinken und nicht schneller
  als maxDrainPerSecond pro echter Sekunde
- SetMetadata ersetzt die Metadata-Tabelle komplett, daher wird der bestehende
  Inhalt kopiert statt nur oxygen gesetzt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 23:45:11 +02:00
co-authored by Claude Opus 5
parent 58f31adfa9
commit d661152bc9
8 changed files with 469 additions and 47 deletions
+17 -6
View File
@@ -1,19 +1,30 @@
return {
startingOxygenLevel = 100,
putOnSuitTimeMs = 5000,
takeOffSuitTimeMs = 5000,
refillTankTimeMs = 5000,
decayRate = 1, -- The rate at which the oxygen level decays. Defaults to 1.
-- Intervall des Watchdogs, der prüft ob die Ausrüstung noch am Ped hängt (ms).
--- Sekunden Luft, die pro echter Sekunde verbraucht werden (vor dem Tiefenfaktor).
decayRate = 1.0,
--- Intervall des Watchdogs, der prüft ob die Ausrüstung noch am Ped hängt (ms).
gearWatchdogIntervalMs = 1000,
-- Sekunden, die der Spieler ohne Ausrüstung unter Wasser überlebt (Vanilla-Verhalten).
--- Sekunden, die der Spieler ohne Ausrüstung unter Wasser überlebt (Vanilla-Verhalten).
maxTimeUnderwater = 50.0,
-- Sekunden, sobald die Flasche leer ist. Bewusst kurz: leer tauchen soll wehtun.
--- Sekunden, sobald die Flasche leer ist. Bewusst kurz: leer tauchen soll wehtun.
maxTimeUnderwaterOutOfAir = 1.0,
-- Ausrüstung beim Tod abnehmen. Die Flasche bleibt mit ihrer Restluft im Inventar.
--- Ausrüstung beim Tod abnehmen. Die Flasche bleibt mit ihrer Restluft im Inventar.
removeGearOnDeath = true,
--- Restsekunden, bei denen gewarnt wird. Jede Schwelle löst einmal pro Tauchgang aus.
warnAtSeconds = { 60, 30, 10 },
--- Verbrauch steigt mit der Tiefe: faktor = 1 + tiefe / depthDecayReference.
--- Macht die großen Flaschen erst sinnvoll. Auf false = konstanter Verbrauch,
--- dann stimmen die 5/10/15/20 Minuten exakt.
depthDecayEnabled = true,
depthDecayReference = 30.0,
maxDecayFactor = 4.0,
}
+34
View File
@@ -0,0 +1,34 @@
-- Von Client und Server benutzt. Muss in fxmanifest unter files{} stehen,
-- damit lib.require die Datei auf beiden Seiten laden kann.
local config = {
--- Tauchflaschen. capacity = Laufzeit in Sekunden bei normalem Verbrauch.
--- Reihenfolge = Reihenfolge im Auswahlmenü.
tanks = {
{ name = 'diving_tank_small', capacity = 300 }, -- 5 Minuten
{ name = 'diving_tank_medium', capacity = 600 }, -- 10 Minuten
{ name = 'diving_tank_large', capacity = 900 }, -- 15 Minuten
{ name = 'diving_tank_xl', capacity = 1200 }, -- 20 Minuten
},
--- Wie oft der Client die Restluft an den Server meldet (Sekunden).
--- Bei einem Crash gehen maximal so viele Sekunden Luft verloren.
syncIntervalSeconds = 15,
--- Obergrenze für die serverseitige Plausibilitätsprüfung: so viele Sekunden
--- Luft kann ein Spieler höchstens pro echter Sekunde verbrauchen. Muss über
--- maxDecayFactor aus config/client.lua liegen, sonst wird ehrlichen Spielern
--- in großer Tiefe fälschlich Luft zurückgegeben.
maxDrainPerSecond = 5.0,
}
config.tankByName = {}
config.tankNames = {}
for i = 1, #config.tanks do
local tank = config.tanks[i]
config.tankByName[tank.name] = tank
config.tankNames[i] = tank.name
end
return config