128x128 PNG mit transparentem Hintergrund, aus SVG-Quellen per ImageMagick
(librsvg) erzeugt und damit reproduzierbar statt handgemalt.
- Tauchmaske, quer liegende Pressluft-Kartusche mit Manometer, drei
Einzelflaschen und die Doppelflasche fuer XL
- Laufzeit als Zahl auf dem Farbband: ohne die waren die Einzelflaschen bei
Slot-Groesse nur noch an der Bandfarbe zu unterscheiden, im 56px-Test gar
nicht mehr
- Kartusche bewusst liegend statt hochkant, damit sie sich von den Flaschen
abhebt - die erste Fassung las sich wie eine Flasche mit Download-Pfeil
- client.image faellt weg: ox_inventory laedt <imagepath>/<itemname>.png, und
die Dateien heissen genau wie die Items
gen-icons.mjs schreibt zusaetzlich ein Kontrollblatt (Schachbrett, Slot-Groesse,
klein), mit dem die Icons gegengeprueft wurden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
HUD-Layout symmetrisch: Tiefe links, Luft-Ring mittig, Druck rechts, Lampe
zentriert darunter. Umgestellt auf Grid, damit die drei Werte garantiert auf
einer Mittelachse sitzen und die Lampen-Leiste ohne Ausgleichs-Margins in einer
zweiten Zeile haengt.
README:
- Drei HUD-Renderings (normal, Warnung, kritisch) als SVG. Keine In-Game-Bilder -
hier laeuft kein GTA -, sondern massstabsgetreu aus denselben Werten wie
style.css erzeugt, per docs/gen-hud-svg.mjs reproduzierbar
- Vollstaendige Config-Referenz fuer client.lua und shared.lua
- Item-Tabelle mit Laufzeit, Fuelldruck, Gewicht, dazu die Metadata-Keys und
warum kein decay gesetzt werden darf
- Installation, Bedienung, Exports, Balancing-Hinweis
- Bekannte Unsicherheiten offen benannt
Item-Snippet mit klarem Copy-Paste-Header. Bewusst keine fertige items.lua zum
Ersetzen: die wuerde die restlichen Items des Servers mitloeschen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Druckanzeige:
- pressure * (Restluft / capacity). Bei konstantem Volumen ist der Druck
proportional zur verbliebenen Gasmenge, die lineare Abbildung stimmt also
- Fuelldruck pro Flasche in config/shared.lua, alle bei 300 bar. Dass die grosse
Flasche denselben Druck zeigt wie die kleine ist gewollt - in echt macht das
Volumen die Laufzeit, nicht der Druck
- Unter config.reservePressure (50 bar) rot: in der Tauchpraxis die Schwelle,
ab der man den Aufstieg einleitet
HUD ausblenden fuer Unterwasser-Screenshots. qbx_core hat selbst keinen
HUD-Toggle, es feuert nur hud:client:* an eine separate HUD-Resource - deshalb
drei voneinander unabhaengige Wege:
- IsHudHidden() folgen, greift bei allem was DisplayHud(false) setzt
- eigene Taste, standardmaessig unbelegt
- Export setHudVisible(bool) / isHudVisible() fuer andere Resources
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Licht ist in GTA nie synchronisiert - DrawSpotLight zeichnet nur lokal fuer den
aktuellen Frame. "Gesynct" heisst deshalb: der Zustand wird als Statebag
repliziert und jeder Client zeichnet die Lampen aller Taucher in seiner Naehe
selbst. Muster uebernommen aus d4rk_phone (Statebag, adaptives Polling,
Distanzfilter).
client/light.lua ist ein reiner Renderer ohne gemeinsamen Zustand mit main.lua -
er kommt mit dem Statebag allein aus und kennt weder Ausruestung noch Flasche.
- Richtung ueber zwei bone-relative Punkte am Kopf-Bone statt ueber
GetEntityForwardVector: beim Tauchen liegt der Ped waagerecht im Wasser, der
Entity-Forward wuerde stur horizontal leuchten. Die Offsets von
GetPedBoneCoords sind laut Native-Doku "relative to the bone's rotation",
die Differenz zweier solcher Punkte enthaelt also den Pitch
- Toggle per lib.addKeybind, Standard L, vom Spieler umlegbar
- Distanzfilter und Limit auf die naechsten N Lampen, Schatten abschaltbar
- Prop-Model wird vorher mit IsModelValid geprueft: lib.requestModel wirft bei
ungueltigen Models einen Error, der sonst die ganze Ausruestung lahmlegt
- Lampen-Status im HUD
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ersetzt die qbx.drawText2d-Anzeige (rohe Zahl plus Uhr-Emoji in der Ecke, jeden
Frame neu gezeichnet) durch ein NUI-Overlay.
- Luft als Ring mit mm:ss, Farbstufen aus config.warnAtSeconds abgeleitet,
Pulsieren im kritischen Bereich
- Tiefe in Metern ueber GetWaterHeight, geglaettet damit Wellengang die Zahl
nicht zappeln laesst; Einfaerbung ab config.deepWarningDepth
- Platz fuer den Lampen-Status, wird in Phase 5 befuellt
- Sichtbar nur mit angelegter Ausruestung unter Wasser, mit Fade
- Updates gedrosselt auf 4/s statt jeden Frame
- Kein backdrop-filter (bekannter FiveM-Bug)
Die geglaettete Tiefe speist auch den tiefenabhaengigen Verbrauch, der bisher
bei jedem Tick neu und ungeglaettet gemessen wurde.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
ox_lib feuert die onCache-Callbacks ueber Citizen.CreateThreadNow, bevor der
neue Wert in den Cache geschrieben wird (ox_lib/init.lua:188-199). cache.ped
zeigt im Callback also noch auf den alten, bereits verschwundenen Ped - die
Props waeren an genau den Ped gegangen, dessen Verschwinden der Handler
abfangen soll.
enableScuba, disableScuba, attachProp und attachGear nehmen den Ped jetzt als
Parameter (default cache.ped), der onCache-Handler reicht den Callback-Wert
durch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der 15. Parameter heisst syncRot, nicht fixedRot. useSoftPinning=false ist
laut Doku korrekt fuer eine Attachment, die sich nicht loesen soll.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Props waren soft-pinned angehaengt (useSoftPinning = true), wodurch die
Physik-Engine die Attachment bei Ragdoll und harten Anim-Uebergaengen loesen
darf. Dazu kam, dass ein Ped-Model-Wechsel und aufraeumende Fremd-Scripts
(Emotes, Handcuffs) gar nicht abgefangen wurden.
- attachProp() Helper mit harter Attachment (useSoftPinning = false)
- Watchdog-Thread prueft jede Sekunde, ob beide Props noch am aktuellen Ped
haengen, und haengt sie sonst neu an
- Scuba-Flags werden im Watchdog neu gesetzt, weil das Spiel sie bei Respawn
und Fahrzeugausstieg zuruecksetzt
- lib.onCache('ped') haengt die Props nach einem Model-Wechsel neu an
- Ausruestung wird beim Tod abgenommen (removeGearOnDeath, default true)
- removeGear() als gemeinsamer Teardown fuer Ablegen, leere Flasche und Tod
- onResourceStop raeumt Props und Scuba-Flags auf
- maxTimeUnderwater / maxTimeUnderwaterOutOfAir statt Magic Numbers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Umbauplan (PLAN.md) mit 5 Phasen: Gear-Persistenz, Sauerstoff-Logik,
Flaschengroessen, NUI-HUD (Tiefe + O2), gesyncte Taschenlampe
- fxmanifest auf D4rkst3r/Gitea umgestellt
- Qbox-spezifische CI entfernt (Discord-Webhooks, GitHub-Releases,
Issue-Projektzuordnung) - laeuft auf Gitea ins Leere bzw. gegen fremde
Endpunkte. lint.yml bleibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>