docs: Referenz ins Wiki, README entschlankt
Die README war auf 300 Zeilen gewachsen und enthielt die komplette Config-Referenz, alle Item-Tabellen und drei Erklaerkapitel. Das gehoert ins Wiki, wo es sich navigieren laesst. Neun Wiki-Seiten angelegt: Home, Installation, Items, Bedienung, Konfiguration, Tiefe und Atemgas, Lampe, Exports, Entwicklung. Jede mit Navigationsleiste. README behaelt, was jemand in den ersten dreissig Sekunden braucht: was es ist, ein Bild, die Features, die Abhaengigkeiten, drei Installationsschritte und die Wegweiser. Von 300 auf 65 Zeilen. ENTSCHEIDUNGEN.md bleibt bewusst im Repo statt im Wiki - es erklaert, warum der Code so aussieht, und gehoert damit neben den Code und in dessen Historie. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,50 +4,19 @@ Tauchausrüstung für QBox. Fork von [qbx_divegear](https://github.com/Qbox-proj
|
||||
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`.
|
||||
|
||||
Eine Dreier-Konsole wie am echten Tauchgerät: **Finimeter** links, Restluft als
|
||||
Ring in der Mitte, **Tiefenmesser** rechts; die Werte darunter auf einer Linie.
|
||||
Das HUD ist auf 1080p entworfen und skaliert mit der Bildschirmhöhe mit, damit es
|
||||
auf 1440p und 4K nicht schrumpft.
|
||||
|
||||
**Normal** — Druck im grünen Bereich, flach getaucht, Lampe an
|
||||
|
||||

|
||||
|
||||
**Warnung** — Zeiger in der Reserve (roter Bereich ab `reservePressure`),
|
||||
Restluft unter der ersten Schwelle, Tiefe über `deepWarningDepth`
|
||||
|
||||

|
||||
|
||||
**Kritisch** — unter der Tiefengrenze des Atemgases: der Zeiger steht im roten
|
||||
Bereich des Tiefenmessers, die Uhr pulsiert, Tiefenrausch läuft
|
||||
|
||||

|
||||
|
||||
Das HUD erscheint, sobald die Ausrüstung angelegt ist — also auch an Land, damit
|
||||
sich der Flaschendruck am Finimeter ablesen lässt, ohne das Inventar zu öffnen.
|
||||
Wer es nur unter Wasser will: `hudOnlyUnderwater = true`.
|
||||

|
||||
|
||||
## 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** in Metern. Optional steigt der Luftverbrauch mit der Tiefe
|
||||
(`depthDecayEnabled`, per Default aus).
|
||||
- **Fünf Flaschen** — 5, 10, 15, 20 Minuten Pressluft plus Trimix. Die Restluft
|
||||
liegt in der Item-Metadata und überlebt Ablegen, Relog, Restart und Tod.
|
||||
- **Tauchkonsole als HUD** — Finimeter, Restluft und Tiefenmesser mit Zeigern und
|
||||
farbigen Gefahrenbereichen. Skaliert mit der Bildschirmauflösung.
|
||||
- **Gesyncte Tauchlampe** über die spieleigene Scuba-Lampe.
|
||||
- **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.
|
||||
erst ab 100 m. Macht ein Tiefenlimit mechanisch statt zur Absprache.
|
||||
- **Ausrüstung bleibt dran** — bei Emotes, Ragdoll, Kleiderwechsel und
|
||||
aufräumenden Fremd-Scripts.
|
||||
- **Serverseitige Prüfung** — die Restluft kann nur sinken, und nicht schneller
|
||||
als physikalisch möglich.
|
||||
|
||||
@@ -59,239 +28,29 @@ Wer es nur unter Wasser will: `hudOnlyUnderwater = true`.
|
||||
|
||||
## Installation
|
||||
|
||||
1. Ordner nach `resources/` und in der `server.cfg` starten — **nach**
|
||||
`ox_inventory` und `qbx_core`:
|
||||
1. `ensure d4rk_divegear` in der `server.cfg`, **nach** `ox_inventory` und `qbx_core`
|
||||
2. [`items_for_ox_inventory.lua`](items_for_ox_inventory.lua) in
|
||||
`ox_inventory/data/items.lua` einfügen
|
||||
3. Die sieben PNGs aus [`icons/`](icons) aufs Icon-CDN hochladen
|
||||
|
||||
```cfg
|
||||
ensure d4rk_divegear
|
||||
```
|
||||
Ausführlich, inklusive der beiden häufigsten Stolpersteine:
|
||||
**[Wiki → Installation](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Installation)**
|
||||
|
||||
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. Sieben Items, nichts weiter anzupassen.
|
||||
## Dokumentation
|
||||
|
||||
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`.
|
||||
Alles Weitere steht im
|
||||
**[Wiki](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki)**:
|
||||
|
||||
Es gibt bewusst **keine** fertige `items.lua` zum Ersetzen — die würde die
|
||||
restlichen Items des Servers überschreiben.
|
||||
[Items](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Items) ·
|
||||
[Bedienung](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Bedienung) ·
|
||||
[Konfiguration](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Konfiguration) ·
|
||||
[Tiefe und Atemgas](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Tiefe-und-Atemgas) ·
|
||||
[Lampe](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Lampe) ·
|
||||
[Exports](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Exports) ·
|
||||
[Entwicklung](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/wiki/Entwicklung)
|
||||
|
||||
## Items
|
||||
|
||||
| Icon | Item | Label | Laufzeit | Gas | max. Tiefe | Gewicht |
|
||||
|---|---|---|---|---|---|---|
|
||||
| <img src="icons/diving_gear.png" width="40"> | `diving_gear` | Tauchausrüstung | — | — | — | 5000 |
|
||||
| <img src="icons/diving_fill.png" width="40"> | `diving_fill` | Pressluft-Kartusche | — | — | — | 1000 |
|
||||
| <img src="icons/diving_tank_small.png" width="40"> | `diving_tank_small` | Tauchflasche (5 Min) | 300 s | Pressluft | 45 m | 4000 |
|
||||
| <img src="icons/diving_tank_medium.png" width="40"> | `diving_tank_medium` | Tauchflasche (10 Min) | 600 s | Pressluft | 45 m | 7000 |
|
||||
| <img src="icons/diving_tank_large.png" width="40"> | `diving_tank_large` | Tauchflasche (15 Min) | 900 s | Pressluft | 45 m | 10000 |
|
||||
| <img src="icons/diving_tank_xl.png" width="40"> | `diving_tank_xl` | Tauchflasche (20 Min) | 1200 s | Pressluft | 45 m | 13000 |
|
||||
| <img src="icons/diving_tank_trimix.png" width="40"> | `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
|
||||
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/`](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
|
||||
|
||||
Die Flasche wird **nicht** separat angezogen. Sie muss nur im Inventar liegen —
|
||||
beim Anlegen der Ausrüstung fragt das Script, welche angeschlossen werden soll.
|
||||
|
||||
| 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 |
|
||||
|---|---|---|
|
||||
| `gearItem` / `fillItem` | `diving_gear` / `diving_fill` | Item-Namen für Ausrüstung und Füll-Kartusche |
|
||||
| `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 |
|
||||
|
||||
### `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` | `false` | Verbrauch steigt mit der Tiefe. Aus, damit die 5/10/15/20 Minuten exakt stimmen |
|
||||
| `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 |
|
||||
|
||||
**Tiefenrausch** (`narcosis`)
|
||||
|
||||
| Option | Default | Bedeutung |
|
||||
|---|---|---|
|
||||
| `enabled` | `true` | Komplett abschaltbar |
|
||||
| `warnBeforeMeters` | `5.0` | Vorwarnung so viele Meter vor der Grenze |
|
||||
| `engineDepthLimit` | `160.0` | Tiefe, ab der **das Spiel selbst** Schluss macht — ingame gemessen, dagegen hilft keine Flasche |
|
||||
| `engineWarnBeforeMeters` | `20.0` | Vorwarnung davor |
|
||||
| `stages` | 3 Stufen | Pro Stufe: `over` (Meter unter der Grenze), `timecycle` + `strength`, `shake` + `shakeIntensity`, `drainFactor`, `damagePerTick` |
|
||||
|
||||
`damagePerTick` steht überall auf `0` — Tiefenrausch kostet also erstmal nur Sicht,
|
||||
Kontrolle und Luft, kein Leben. Wer es härter will, setzt es in der letzten Stufe
|
||||
auf z.B. `2`.
|
||||
|
||||
**HUD**
|
||||
|
||||
| Option | Default | Bedeutung |
|
||||
|---|---|---|
|
||||
| `hudEnabled` | `true` | Ohne HUD bleibt die Ausrüstung voll nutzbar |
|
||||
| `hudUpdateIntervalMs` | `250` | 4 Updates pro Sekunde |
|
||||
| `hudScale` | `1.0` | Größenfaktor obendrauf. Das HUD skaliert schon selbst mit der Bildschirmhöhe |
|
||||
| `hudOnlyUnderwater` | `false` | Auf `false` schon sichtbar, sobald die Ausrüstung an ist — Finimeter ablesen ohne Inventar |
|
||||
| `hudFollowGameHud` | `true` | Mit dem Spiel-HUD ausblenden |
|
||||
| `hudToggleKey` | `''` | Eigene Taste, leer = unbelegt |
|
||||
| `reservePressure` | `50` | Roter Bereich des Finimeters, ab hier färbt sich der Zeiger |
|
||||
| `depthDialMax` | `100.0` | Skalenende des Tiefenmessers. Tiefer schlägt der Zeiger an, die Zahl stimmt weiter |
|
||||
|
||||
**Lampe**
|
||||
|
||||
| Option | Default | Bedeutung |
|
||||
|---|---|---|
|
||||
| `lampKey` | `'l'` | Vorbelegung der Taste |
|
||||
| `lampReconcileIntervalMs` | `500` | Wie oft der Lampen-Zustand auf die Peds in der Nähe nachgezogen wird |
|
||||
|
||||
> **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
|
||||
|
||||
```lua
|
||||
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 funktioniert
|
||||
|
||||
Es wird kein Licht selbst gezeichnet. GTA bringt seit v1493 (Cayo Perico) eine
|
||||
eigene Lampe an der Tauchausrüstung mit:
|
||||
|
||||
```lua
|
||||
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.
|
||||
|
||||
Sie funktioniert **auch ohne Scuba-Kleidung** am Ped — ingame bestätigt. Der
|
||||
Hinweis in [esx_scuba](https://github.com/wobozkyng/esx_scuba), das Licht hänge am
|
||||
Kleidungs-Component, trifft hier also nicht zu. Das Outfit wird nicht angefasst.
|
||||
Sollte die Native bei einem Ped-Model doch nicht anschlagen, gibt es beim
|
||||
Einschalten eine Meldung statt stiller Wirkungslosigkeit.
|
||||
|
||||
Der Flag ist ein **lokaler** Ped-Zustand und wird nicht von selbst repliziert.
|
||||
Deshalb läuft der Zustand über einen Statebag
|
||||
(`LocalPlayer.state:set('divelight', …, true)`), und jeder Client setzt den Flag
|
||||
für die Taucher in seiner Nähe selbst — sofort per `AddStateBagChangeHandler`,
|
||||
plus ein Abgleich alle `lampReconcileIntervalMs`, weil Peds beim Streaming,
|
||||
Respawn und Model-Wechsel neu erzeugt werden und den Flag dabei verlieren.
|
||||
|
||||
## Entwicklung
|
||||
|
||||
Es gibt bewusst keine CI: die Workflows aus dem Original liefen gegen Qbox'
|
||||
Discord und GitHub-Releases, und Linting passiert lokal vor dem Commit.
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
Warum die Dinge so gebaut sind — und welche Fallstricke dahinterstecken — steht
|
||||
in [ENTSCHEIDUNGEN.md](ENTSCHEIDUNGEN.md), zusammen mit den offenen Punkten.
|
||||
Die Abnahme läuft über die
|
||||
[Issues](https://git.d4rkst3r.de/D4rkst3r/d4rk_divegear/issues?labels=test) —
|
||||
ein Issue pro Testbereich, mit `prio:`-Labels und `ungeprueft` für alles, was
|
||||
sich ohne laufendes Spiel nicht verifizieren ließ.
|
||||
|
||||
## Offene Punkte
|
||||
|
||||
Ingame getestet sind Anlegen und Ablegen, Flaschenauswahl, Luftverbrauch, HUD mit
|
||||
Tiefe und Druck sowie die Lampe. Noch offen:
|
||||
|
||||
- **Scuba-Lampe ohne passendes Outfit** — sie hängt an der Scuba-Kleidung
|
||||
(Component 8). Wer die nicht trägt, bekommt eine Meldung. Soll die Ausrüstung
|
||||
das Outfit selbst setzen, muss das noch gebaut werden (inklusive Sichern und
|
||||
Wiederherstellen der vorherigen Kleidung).
|
||||
- **`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.
|
||||
- **HUD-Position** ist nur in `nui/style.css` einstellbar, nicht in der Config.
|
||||
- **Balancing** — die Laufzeiten sind gesetzt, aber nicht am Spielgefühl geprüft.
|
||||
Warum die Dinge so gebaut sind und welche Fallstricke dahinterstecken, steht
|
||||
code-nah hier im Repo: [ENTSCHEIDUNGEN.md](ENTSCHEIDUNGEN.md).
|
||||
|
||||
## Lizenz
|
||||
|
||||
|
||||
Reference in New Issue
Block a user