Files
d4rk_divegear/README.md
T
D4rkst3randClaude Opus 5 c264872007 docs: Herkunft der Items in der README festgehalten
diving_gear und diving_fill stammen aus dem Original (Diving Gear / Diving
Tube), neu sind nur die vier Flaschen. Im Original gab es keine
Sauerstoffflasche als Item - die Luft hing an gar nichts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 00:29:55 +02:00

11 KiB
Raw Blame History

d4rk_divegear

Tauchausrüstung für QBox. Fork von qbx_divegear mit Flaschengrößen, gesyncter Lampe, Tiefen- und Druckanzeige — und Ausrüstung, die bei Animationen nicht mehr verschwindet.

HUD

Die Bilder sind maßstabsgetreue Renderings des Overlays aus denselben Werten wie nui/style.css — keine In-Game-Aufnahmen. Erzeugt mit docs/gen-hud-svg.mjs.

Normal — Luft, Tiefe, Fülldruck, Lampe an

HUD, normaler Zustand

Warnung — Restluft unter der ersten Schwelle, Tiefe über deepWarningDepth, Druck unter reservePressure

HUD, Warnstufe

Kritisch — letzte Sekunden, der Ring pulsiert

HUD, kritischer Luftstand

Das HUD erscheint nur mit angelegter Ausrüstung unter Wasser und blendet sich weich ein und aus.

Features

  • Vier Flaschengrößen — 5, 10, 15 und 20 Minuten. Die Restluft liegt in der Item-Metadata und überlebt Ablegen, Relog, Resource-Restart und Tod. Der Füllstand ist als Balken direkt im Inventar-Slot sichtbar.
  • Manometer in bar — physikalisch korrekt aus dem Restanteil abgeleitet, Reservedruck wird eingefärbt.
  • Gesyncte Tauchlampe — an der Ausrüstung, An/Aus per Taste. Andere Spieler sehen den Lichtkegel, und zwar in die Richtung, in die tatsächlich geschaut wird.
  • Tiefenanzeige und tiefenabhängiger Verbrauch — tiefer tauchen kostet mehr Luft. Abschaltbar.
  • Ausrüstung bleibt — bei Emotes, Ragdoll, Kleiderwechsel und aufräumenden Fremd-Scripts.
  • HUD ausblendbar für Unterwasser-Screenshots.
  • Serverseitige Prüfung — die Restluft kann nur sinken, und nicht schneller als physikalisch möglich.

Abhängigkeiten

qbx_core · ox_lib · ox_inventory

Installation

  1. Ordner nach resources/ und in der server.cfg starten — nach ox_inventory und qbx_core:

    ensure d4rk_divegear
    
  2. 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.

  3. Die sechs PNGs aus 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 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

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 die Luft eine Client-Variable, die an keinem Item hing — eine Sauerstoffflasche als Item gab es dort gar nicht. Für unterschiedliche Laufzeiten und persistente Restluft braucht es aber ein Item, an dem beides hängen kann.

Ein Taucher trägt damit zwei Dinge: die Ausrüstung und eine Flasche. Die Kartusche nur, wer unterwegs nachfüllen will.

Die Icons liegen als 128×128 PNG mit transparentem Hintergrund in icons/, die SVG-Quellen in icons/src/. Die Laufzeit steht als Zahl auf dem Farbband — ohne die sind die Einzelflaschen im Inventar nur noch an der Bandfarbe auseinanderzuhalten. Wer capacity ändert, sollte die Zahlen in icons/gen-icons.mjs mitziehen.

Dass alle Flaschen mit demselben Fülldruck starten, ist gewollt: in echt macht das Volumen die Laufzeit, nicht der Druck. Die große Flasche hält 300 bar einfach länger.

Metadata

Key Bedeutung
oxygen Restluft in Sekunden — die eigentliche Wahrheit
durability Füllstand in Prozent, nur für den Balken im Inventar-Slot

Kein decay = true auf den Flaschen. ox_inventory löscht Items mit decay, sobald durability 0 erreicht — die leere Flasche würde also verschwinden statt auffüllbar zu bleiben.

Bedienung

Aktion Wie
Ausrüstung an-/ausziehen diving_gear benutzen
Flasche wählen Menü beim Anlegen (entfällt bei nur einer Flasche)
Flasche auffüllen diving_fill benutzen — nicht unter Wasser, nicht bei voller Flasche
Lampe an/aus L
HUD ein-/ausblenden Eigene Taste, standardmäßig unbelegt

Beide Tasten sind vom Spieler in den FiveM-Einstellungen unter Tastenbelegung → FiveM umlegbar.

Konfiguration

config/shared.lua — Client und Server

Option Default Bedeutung
tanks 4 Flaschen name, capacity (Sekunden), pressure (bar)
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

config/client.lua

Ablauf

Option Default Bedeutung
putOnSuitTimeMs / takeOffSuitTimeMs / refillTankTimeMs 5000 Dauer der Progressbars
decayRate 1.0 Sekunden Luft pro echter Sekunde, vor dem Tiefenfaktor
warnAtSeconds {60, 30, 10} Warnschwellen, jede einmal pro Tauchgang
removeGearOnDeath true Ausrüstung beim Tod abnehmen. Die Flasche bleibt mit ihrer Restluft im Inventar
gearWatchdogIntervalMs 1000 Prüfintervall, ob die Props noch am Ped hängen
maxTimeUnderwater 50.0 Sekunden unter Wasser ohne Ausrüstung (Vanilla-Verhalten)
maxTimeUnderwaterOutOfAir 1.0 Sekunden, sobald die Flasche leer ist

Tiefe

Option Default Bedeutung
depthDecayEnabled true Verbrauch steigt mit der Tiefe
depthDecayReference 30.0 Faktor 1 + tiefe / referenz
maxDecayFactor 4.0 Deckel für den Faktor
deepWarningDepth 25.0 Ab hier wird die Tiefenanzeige eingefärbt

HUD

Option Default Bedeutung
hudEnabled true Ohne HUD bleibt die Ausrüstung voll nutzbar
hudUpdateIntervalMs 250 4 Updates pro Sekunde
hudFollowGameHud true Mit dem Spiel-HUD ausblenden
hudToggleKey '' Eigene Taste, leer = unbelegt
reservePressure 50 Ab hier wird die Druckanzeige rot

Lampe

Option Default Bedeutung
lampKey 'l' Vorbelegung
lampProp 'prop_cs_police_torch' Optik. Ungültiges Model → Warnung im Log, Licht funktioniert trotzdem
lampOffset vec3(0, 0.15, 0) Position relativ zum Kopf-Bone
lampDirection vec3(0, 1, 0) Richtung des Kegels, bone-relativ
lampColour {225, 245, 255} RGB
lampDistance / lampBrightness / lampRoundness / lampRadius / lampFalloff 30/6/1/14/1.5 Form des Lichtkegels
lampShadows true false nutzt DrawSpotLight statt der Schattenvariante — flacher, aber spürbar schneller
lampDrawDistance 45.0 Ab hier werden fremde Lampen nicht mehr gezeichnet
lampMaxLights 4 Gleichzeitige Lampen, die nächstgelegenen gewinnen

Beim Balancing beachten: maxDrainPerSecond (shared) muss über maxDecayFactor (client) liegen. Sonst hält der Server den ehrlichen Verbrauch in großer Tiefe für Cheat und schreibt Luft zurück.

Exports

exports.d4rk_divegear:setHudVisible(false)      -- HUD ausblenden
local shown = exports.d4rk_divegear:isHudVisible()

Gedacht für HUD- und Screenshot-Resources. Zusätzlich folgt das HUD automatisch IsHudHidden(), greift also bei allem was DisplayHud(false) setzt, ohne dass etwas angebunden werden muss.

Wie die Lampe synchron wird

Licht ist in GTA nie synchronisiert — DrawSpotLight zeichnet nur lokal für den aktuellen Frame. Der Lampenzustand wird deshalb als Statebag repliziert (LocalPlayer.state:set('divelight', …, true)), und jeder Client zeichnet die Lampen aller Taucher in seiner Nähe selbst.

Die Richtung kommt aus zwei bone-relativen Punkten am Kopf-Bone, nicht aus GetEntityForwardVector: beim Tauchen liegt der Ped waagerecht im Wasser, der Entity-Forward würde stur horizontal leuchten. Die Offsets von GetPedBoneCoords sind laut Native-Doku "relative to the bone's rotation", die Differenz zweier solcher Punkte enthält also den Pitch.

Entwicklung

node ../.tools/lint.mjs             # Lua-Lint, CfxLua-tauglich
node ../.tools/nui-preview.mjs nui  # HUD im Browser anschauen
node docs/gen-hud-svg.mjs docs      # Renderings für diese README neu bauen

# Item-Icons neu bauen (SVG -> PNG, braucht ImageMagick mit librsvg)
node icons/gen-icons.mjs
for f in icons/src/*.svg; do
  magick -background none "$f" -resize 128x128 "icons/$(basename "$f" .svg).png"
done

gen-icons.mjs schreibt außerdem icons/_check.html — alle Icons auf Schachbrett, in Slot-Größe und klein, zum Gegenschauen nach Änderungen.

librsvg 2.40 wirft beim Rendern der Zahlen ein Invalid UTF-8 string passed to pango_layout_set_text(). Das ist harmlos und passiert bei jedem <text>-Element, auch im minimalsten Testfall — die Zahlen kommen korrekt raus.

Der Umbau ist in PLAN.md dokumentiert, inklusive der offenen Punkte.

Bekannte Unsicherheiten

Bisher nicht im Spiel getestet — geprüft sind Lua-Syntax und Globals, die Locale-JSONs und das HUD im Browser.

  • lampProp — der Prop-Name ist ungeprüft. Falls falsch: Warnung im Log, das Licht funktioniert weiter, nur ohne sichtbares Prop. Ersatz finden: forge.plebmasters.de/objects
  • lampDirection — welche lokale Achse des Kopf-Bones nach vorne zeigt, hängt am Skelett. Leuchtet der Kegel falsch herum: Achse tauschen oder Vorzeichen drehen.
  • IsHudHidden() — ob die Native auf DisplayHud(false) anspringt, ist ungetestet. Falls nicht, greifen Taste und Export weiterhin.
  • Nach einem Relog muss die Ausrüstung neu angelegt werden. Die Restluft geht dabei nicht verloren, die liegt auf der Flasche.

Lizenz

GPL-3.0, wie das Original. Die Upstream-Historie ist erhalten und liegt auf dem Remote upstream.