Lampen-Prop entfernt. Seit der Umstellung auf die spieleigene Scuba-Lampe war es
funktionslos: standardmaessig aus, nie verifiziert, und eine Polizei-Taschenlampe
am Kopf haette neben dem nativen Licht nur Deko gespielt. Damit fallen auch die
Debug-Befehle /divelamp und /divelampcheck weg, samt config.debug und vier
Config-Werten.
Zwoelf Upstream-Locales geloescht. Sie hatten 8 von 26 Keys - im Spiel waeren
dort rohe Key-Namen erschienen. Gepflegt werden DE und EN.
PLAN.md war ein Vorab-Plan mit Phasen und Aufwandsschaetzungen und damit
erledigt. Ersetzt durch ENTSCHEIDUNGEN.md: warum die Dinge so gebaut sind und
welche Fallstricke dahinterstecken - onCache-Timing, consume, decay,
SetMetadata, die Atemgas-Grenze, das transform-origin am Zeiger. Also das, was
beim naechsten Anfassen wirklich hilft.
README von den Abschnitten befreit, die es nicht mehr gibt. Bilder und Icons neu
erzeugt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Gleiche Bug-Klasse wie bei der Flasche, nur hatte mein Fix davor ausschliesslich
die Flasche geprueft: wer diving_gear im Tauchgang weggab, blieb ausgeruestet
und atmete weiter.
Die Besitzpruefung deckt jetzt beides ab. verifyTank heisst verifyGear und gibt
{ gear, tank } zurueck - fehlt eines von beidem, kommt die Ausruestung ab, mit
der passenden Meldung. Umsortieren im Inventar bindet weiterhin nur auf den
neuen Slot um.
Die Item-Namen stehen jetzt als gearItem/fillItem in config/shared.lua, statt
verteilt als Zeichenketten im Server-Code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bug: wer die getragene Flasche im Tauchgang weggab, konnte unbegrenzt
weiteratmen. Der Client hielt nur eine Slot-Nummer, die niemand mehr
gegenpruefte, und der Sync lief ins Leere. ox_inventory feuert clientseitig bei
jeder Inventar-Aenderung - dort wird jetzt beim Server nachgefragt. Ist die
Flasche weg, kommt die Ausruestung ab; wurde sie nur umsortiert, bindet der
Client auf den neuen Slot um, damit Aufraeumen im Inventar nichts kostet.
HUD:
- Werte aus den Uhren heraus in eine zweite Zeile: Druck, Lampe und Tiefe
liegen jetzt auf einer Linie. In der Skala kollidierte die Zahl mit
Strichen, Zeiger und rotem Bereich
- Skaliert mit der Bildschirmhoehe (entworfen auf 1080p), sonst waere das in
festen Pixeln gebaute HUD auf 1440p und 4K deutlich zu klein.
config.hudScale kommt als Geschmacksregler obendrauf
- Zustandsklassen sitzen jetzt am HUD statt an den Uhren, weil Instrument und
Wert in getrennten Grid-Zellen liegen
README-Renderings nachgezogen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Statt zweier Zahlenfelder jetzt zwei Zeigerinstrumente links und rechts vom
Luft-Ring - wie eine echte Tauchkonsole. Der Ring bleibt in der Mitte, weil die
Restzeit die Zahl ist, auf die es ankommt.
- Finimeter 0-300 bar, roter Bereich = Reserve unter reservePressure
- Tiefenmesser 0-depthDialMax, roter Bereich = Tiefengrenze des Atemgases. Der
faengt bei Pressluft bei 45 m an und bei Trimix erst bei 100 m - der
Gefahrenbereich haengt also an der getragenen Flasche. Gibt es real nicht,
hilft im Spiel aber sofort beim Einschaetzen
- Skalenzahlen bewusst weggelassen: bei 96 px kollidieren sie mit allem und
liest ohnehin niemand. Zeiger zeigt die Tendenz, die Zahl in der Uhr den Wert
- Zeiger und Wert faerben sich rot, sobald der rote Bereich erreicht ist
Beim Bauen gefunden: CSS transform-origin auf dem Zeiger wird zusaetzlich zum
rotate(winkel 50 50) im Attribut angewendet, der Drehpunkt wandert dadurch
doppelt und der Zeiger landet ausserhalb der Uhr. transform-origin ist raus.
README-Renderings auf die Konsole umgebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Die Scuba-Lampe funktioniert auch OHNE Scuba-Kleidung am Ped. Meine Annahme
aus esx_scuba, das Licht haenge am Kleidungs-Component 8, trifft hier nicht
zu - Kommentare und README entsprechend korrigiert. Die Meldung beim
Einschalten bleibt als Sicherheitsnetz fuer Ped-Models, bei denen die Native
doch nicht anschlaegt
- engineDepthLimit auf 160 m, ingame gemessen statt konservativ geschaetzt
- damagePerTick ueberall auf 0: Tiefenrausch kostet erstmal nur Sicht, Kontrolle
und Luft, kein Leben. In der letzten Stufe wieder aktivierbar
- .github entfernt: die Workflows kamen aus dem Original, liefen gegen Qbox'
Discord und GitHub-Releases und haetten auf Gitea nur ins Leere gefeuert.
Gelintet wird lokal ueber .tools/lint.mjs
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
GTA toetet selbst ab einer bestimmten Tiefe ueber den Wasserdruck - beim U-Boot
bei rund 150 m mit Implosion ab ~168 m, zu Fuss verliert man ebenfalls Leben.
Dagegen hilft kein Atemgas, das ist die Engine.
Deshalb dafuer nur eine Warnung statt eigener Effekte, konservativ auf 130 m mit
20 m Vorwarnung, beides in config.narcosis. Trimix hoert mit 100 m bewusst
darueber auf; dazwischen liegt die Zone, in der keine Ausruestung mehr hilft.
Der genaue Wert fuer Taucher zu Fuss ist nicht belegt und steht als Testpunkt in
TESTING.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Macht ein Tiefenlimit mechanisch statt zur Absprache - und oeffnet die tiefen
Spots fuer den, der die richtige Flasche dabei hat.
Der Grund fuer die realen 40-45 m ist nicht der Druck, sondern der Stickstoff in
der Pressluft: tiefer wirkt er narkotisch, ab ~56 m wird auch der Sauerstoff
giftig. Wer tiefer will, atmet Trimix, wo Helium einen Teil des Stickstoffs
ersetzt. Genau so umgesetzt:
- maxDepth und gas pro Flasche in config/shared.lua; Pressluft 45 m,
neues diving_tank_trimix 100 m
- Darunter Tiefenrausch in drei Stufen: Bildschirmeffekt, Kamerawackeln,
hoeherer Luftverbrauch, in der letzten Stufe Schaden. Schwellen, Effekte,
Staerken und Schaden komplett in config.narcosis
- Vorwarnung 5 m vor der Grenze, Tiefenanzeige im HUD wird rot und pulsiert
- Effekte werden beim Auftauchen, Ablegen, Tod und Resource-Stop aufgeraeumt
- Auswahlmenue zeigt Gas und Tiefengrenze pro Flasche
- Icon fuer die Trimix-Flasche, violett abgesetzt
Keine Dekompression - auf Wunsch bewusst weggelassen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- hudOnlyUnderwater = false: das HUD ist sichtbar sobald die Ausruestung
angelegt ist, nicht erst unter Wasser. Damit laesst sich der Flaschendruck
am Finimeter ablesen, ohne das Inventar zu oeffnen
- depthDecayEnabled = false: die angegebenen 5/10/15/20 Minuten stimmen damit
exakt und bleiben fuer Spieler berechenbar
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
GTA bringt seit v1493 eine eigene Lampe an der Tauchausruestung mit:
SetEnableScubaGearLight(ped, toggle) 0xEE2476B9EE4A094F
IsScubaGearLightEnabled(ped) 0x88274C11CF0D866D
Die sitzt an der richtigen Stelle, leuchtet in Blickrichtung und braucht weder
Prop noch Offsets noch einen Draw-Thread. Damit faellt der komplette
DrawSpotLight-Aufbau weg: Kegelwerte, Farbe, Schatten, Distanzfilter,
Lichter-Limit, die bone-relative Richtungsrechnung und das Sortieren der
Kandidaten pro Frame. client/light.lua schrumpft von ~110 auf ~55 Zeilen.
Gefunden ueber wobozkyng/esx_scuba.
- Der Flag ist ein lokaler Ped-Zustand, der Statebag bleibt also. Gesetzt wird
er per AddStateBagChangeHandler und zusaetzlich alle 500ms nachgezogen, weil
Peds beim Streaming, Respawn und Model-Wechsel neu erzeugt werden
- Die Lampe haengt an der Scuba-Kleidung (Component 8). Das Outfit wird bewusst
nicht angefasst; wer sie nicht traegt, bekommt beim Einschalten eine Meldung
statt stiller Wirkungslosigkeit
- /divelampcheck sagt, ob das aktuelle Outfit eine Lampe hat
- Prop ist jetzt optional und per Default aus
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Offset und Rotation des Lampen-Props waren hart im Code, und die Rotation
(180, 90, 0) war stumpf von der Maske uebernommen - daher stand die Lampe quer
im Gesicht. d4rk_phone haengt sein Prop mit komplett null Offset und Rotation
an, das ist der bessere Ausgangspunkt.
- lampBone, lampPropOffset, lampPropRotation in die Config; Prop und Licht
haengen jetzt am selben Bone, damit der Strahl aus der Lampe kommt
- lampProp = '' erlaubt, dann nur Licht ohne Prop
- Lichtwerte (Farbe, Reichweite, Helligkeit, Kegel) aus d4rk_phone uebernommen
statt neu geraten; lampShadows wie dort auf false
- /divelamp und /divelight stellen beides im laufenden Spiel ein und geben die
Config-Zeile zum Uebernehmen aus (config.debug)
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>