Lint / Lint Resource (push) Has been cancelled
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>
223 lines
9.0 KiB
Markdown
223 lines
9.0 KiB
Markdown
# d4rk_divegear
|
|
|
|
Tauchausrüstung für QBox. Fork von [qbx_divegear](https://github.com/Qbox-project/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
|
|
|
|

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

|
|
|
|
**Kritisch** — letzte Sekunden, der Ring pulsiert
|
|
|
|

|
|
|
|
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`](https://github.com/Qbox-project/qbx_core) ·
|
|
[`ox_lib`](https://github.com/overextended/ox_lib) ·
|
|
[`ox_inventory`](https://github.com/overextended/ox_inventory)
|
|
|
|
## Installation
|
|
|
|
1. Ordner nach `resources/` und in der `server.cfg` starten — **nach**
|
|
`ox_inventory` und `qbx_core`:
|
|
|
|
```cfg
|
|
ensure d4rk_divegear
|
|
```
|
|
|
|
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. Sechs Items, nichts weiter anzupassen.
|
|
|
|
3. Icons nach `cdn.d4rkst3r.de/items/` legen: `diving_gear.png`,
|
|
`diving_fill.png`, `diving_tank_small.png`, `diving_tank_medium.png`,
|
|
`diving_tank_large.png`, `diving_tank_xl.png`.
|
|
|
|
Es gibt bewusst **keine** fertige `items.lua` zum Ersetzen — die würde die
|
|
restlichen Items des Servers überschreiben.
|
|
|
|
## Items
|
|
|
|
| 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 |
|
|
|
|
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
|
|
|
|
```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 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
|
|
|
|
```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
|
|
```
|
|
|
|
Der Umbau ist in [PLAN.md](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](https://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`.
|