fix(light): Lampen-Sitz konfigurierbar + Debug-Befehle
Lint / Lint Resource (push) Has been cancelled
Lint / Lint Resource (push) Has been cancelled
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>
This commit is contained in:
@@ -172,12 +172,14 @@ FiveM* umlegbar.
|
|||||||
| Option | Default | Bedeutung |
|
| Option | Default | Bedeutung |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `lampKey` | `'l'` | Vorbelegung |
|
| `lampKey` | `'l'` | Vorbelegung |
|
||||||
| `lampProp` | `'prop_cs_police_torch'` | Optik. Ungültiges Model → Warnung im Log, Licht funktioniert trotzdem |
|
| `lampBone` | `12844` | Bone für Prop **und** Licht — derselbe, damit der Strahl aus der Lampe kommt. `28422` = Hand statt Kopf |
|
||||||
| `lampOffset` | `vec3(0, 0.15, 0)` | Position relativ zum Kopf-Bone |
|
| `lampProp` | `'prop_cs_police_torch'` | Optik. Ungültiges Model → Warnung im Log, Licht funktioniert trotzdem. `''` = kein Prop |
|
||||||
|
| `lampPropOffset` / `lampPropRotation` | `vec3(0,0,0)` | Sitz des Props am Bone — mit `/divelamp` einstellen |
|
||||||
|
| `lampOffset` | `vec3(0,0,0)` | Ursprung des Lichtkegels, bone-relativ |
|
||||||
| `lampDirection` | `vec3(0, 1, 0)` | Richtung des Kegels, bone-relativ |
|
| `lampDirection` | `vec3(0, 1, 0)` | Richtung des Kegels, bone-relativ |
|
||||||
| `lampColour` | `{225, 245, 255}` | RGB |
|
| `lampColour` | `{255, 250, 235}` | RGB |
|
||||||
| `lampDistance` / `lampBrightness` / `lampRoundness` / `lampRadius` / `lampFalloff` | `30/6/1/14/1.5` | Form des Lichtkegels |
|
| `lampDistance` / `lampBrightness` / `lampRoundness` / `lampRadius` / `lampFalloff` | `28/3/0/16/2` | Form des Lichtkegels, Werte aus `d4rk_phone` übernommen |
|
||||||
| `lampShadows` | `true` | `false` nutzt `DrawSpotLight` statt der Schattenvariante — flacher, aber spürbar schneller |
|
| `lampShadows` | `false` | `true` nutzt `DrawSpotLightWithShadow` — sieht besser aus, kostet aber deutlich Performance |
|
||||||
| `lampDrawDistance` | `45.0` | Ab hier werden fremde Lampen nicht mehr gezeichnet |
|
| `lampDrawDistance` | `45.0` | Ab hier werden fremde Lampen nicht mehr gezeichnet |
|
||||||
| `lampMaxLights` | `4` | Gleichzeitige Lampen, die nächstgelegenen gewinnen |
|
| `lampMaxLights` | `4` | Gleichzeitige Lampen, die nächstgelegenen gewinnen |
|
||||||
|
|
||||||
@@ -185,6 +187,30 @@ FiveM* umlegbar.
|
|||||||
> `maxDecayFactor` (client) liegen. Sonst hält der Server den ehrlichen Verbrauch
|
> `maxDecayFactor` (client) liegen. Sonst hält der Server den ehrlichen Verbrauch
|
||||||
> in großer Tiefe für Cheat und schreibt Luft zurück.
|
> in großer Tiefe für Cheat und schreibt Luft zurück.
|
||||||
|
|
||||||
|
## Lampe einstellen
|
||||||
|
|
||||||
|
Wo Prop und Lichtkegel am Kopf sitzen, hängt daran, wie das Prop-Model selbst
|
||||||
|
ausgerichtet ist — das lässt sich nicht am Schreibtisch erraten. Mit
|
||||||
|
`debug = true` in `config/client.lua` gibt es zwei Befehle, die die Werte im
|
||||||
|
laufenden Spiel ändern und die fertige Config-Zeile ins Log schreiben:
|
||||||
|
|
||||||
|
```
|
||||||
|
/divelamp <x> <y> <z> <rx> <ry> <rz> Sitz des Lampen-Props
|
||||||
|
/divelight <x> <y> <z> <dx> <dy> <dz> Ursprung und Richtung des Lichtkegels
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Prop wird sofort neu angehängt, das Licht zieht ohne Verzögerung mit — kein
|
||||||
|
Resource-Restart pro Versuch. Sind die Werte gut, die ausgegebenen Zeilen in die
|
||||||
|
Config übernehmen und `debug` wieder ausschalten.
|
||||||
|
|
||||||
|
Alternativ mit einem Prop-Attach-Editor wie
|
||||||
|
[noted_propattacher](https://github.com/NotedDevelopment/noted_propattacher)
|
||||||
|
ausmessen: Prop spawnen, mit der Maus an die Stelle ziehen, Werte übernehmen.
|
||||||
|
|
||||||
|
> Im Basegame gibt es **keine** Tauchlampe. `prop_cs_police_torch` ist eine
|
||||||
|
> Polizei-Taschenlampe; Varianten davon sind `prop_police_torch` und
|
||||||
|
> `prop_scn_police_torch`. Wer eine echte Tauchlampe will, braucht ein Custom-Model.
|
||||||
|
|
||||||
## Exports
|
## Exports
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
|||||||
+2
-3
@@ -10,7 +10,6 @@ local config = require 'config.client'
|
|||||||
-- anderen Tauchers selbst zeichnet.
|
-- anderen Tauchers selbst zeichnet.
|
||||||
|
|
||||||
local STATE_KEY = 'divelight'
|
local STATE_KEY = 'divelight'
|
||||||
local HEAD_BONE = 31086 -- SKEL_Head
|
|
||||||
|
|
||||||
--- Kandidaten des aktuellen Frames. Wird wiederverwendet statt jedes Frame neu
|
--- Kandidaten des aktuellen Frames. Wird wiederverwendet statt jedes Frame neu
|
||||||
--- angelegt, damit der GC bei Dauerbetrieb nichts zu tun bekommt.
|
--- angelegt, damit der GC bei Dauerbetrieb nichts zu tun bekommt.
|
||||||
@@ -26,8 +25,8 @@ local function getLampVectors(ped)
|
|||||||
local offset = config.lampOffset
|
local offset = config.lampOffset
|
||||||
local direction = config.lampDirection
|
local direction = config.lampDirection
|
||||||
|
|
||||||
local from = GetPedBoneCoords(ped, HEAD_BONE, offset.x, offset.y, offset.z)
|
local from = GetPedBoneCoords(ped, config.lampBone, offset.x, offset.y, offset.z)
|
||||||
local ahead = GetPedBoneCoords(ped, HEAD_BONE,
|
local ahead = GetPedBoneCoords(ped, config.lampBone,
|
||||||
offset.x + direction.x,
|
offset.x + direction.x,
|
||||||
offset.y + direction.y,
|
offset.y + direction.y,
|
||||||
offset.z + direction.z)
|
offset.z + direction.z)
|
||||||
|
|||||||
+57
-4
@@ -125,10 +125,10 @@ end
|
|||||||
--- Lampen-Model einmalig prüfen. lib.requestModel wirft bei ungültigen Models einen
|
--- Lampen-Model einmalig prüfen. lib.requestModel wirft bei ungültigen Models einen
|
||||||
--- Error - ohne diese Prüfung würde ein falsch geschriebener Prop-Name die komplette
|
--- Error - ohne diese Prüfung würde ein falsch geschriebener Prop-Name die komplette
|
||||||
--- Ausrüstung unbenutzbar machen, statt nur die Optik der Lampe zu kosten.
|
--- Ausrüstung unbenutzbar machen, statt nur die Optik der Lampe zu kosten.
|
||||||
local lampModel = joaat(config.lampProp)
|
local lampModel = config.lampProp ~= '' and joaat(config.lampProp) or nil
|
||||||
local hasLampProp = IsModelValid(lampModel) or IsModelInCdimage(lampModel)
|
local hasLampProp = lampModel ~= nil and (IsModelValid(lampModel) or IsModelInCdimage(lampModel))
|
||||||
|
|
||||||
if not hasLampProp then
|
if lampModel and not hasLampProp then
|
||||||
lib.print.warn(('lampProp "%s" ist kein gültiges Model - die Lampe leuchtet, das Prop fehlt.'):format(config.lampProp))
|
lib.print.warn(('lampProp "%s" ist kein gültiges Model - die Lampe leuchtet, das Prop fehlt.'):format(config.lampProp))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ local function attachGear(ped)
|
|||||||
currentGear.mask = attachProp(ped, MASK_MODEL, MASK_BONE, vec3(0.0, 0.0, 0.0), vec3(180.0, 90.0, 0.0))
|
currentGear.mask = attachProp(ped, MASK_MODEL, MASK_BONE, vec3(0.0, 0.0, 0.0), vec3(180.0, 90.0, 0.0))
|
||||||
|
|
||||||
if hasLampProp then
|
if hasLampProp then
|
||||||
currentGear.lamp = attachProp(ped, lampModel, MASK_BONE, vec3(0.1, 0.05, 0.0), vec3(180.0, 90.0, 0.0))
|
currentGear.lamp = attachProp(ped, lampModel, config.lampBone, config.lampPropOffset, config.lampPropRotation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -536,6 +536,59 @@ lib.addKeybind({
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
--- Wo Prop und Lichtkegel am Bone sitzen, lässt sich nicht am Schreibtisch
|
||||||
|
--- erraten - das hängt daran, wie das Model selbst ausgerichtet ist. Diese Befehle
|
||||||
|
--- ändern die Werte im laufenden Spiel und geben die Zeile zum Übernehmen aus,
|
||||||
|
--- damit nicht pro Versuch die Resource neu gestartet werden muss.
|
||||||
|
---
|
||||||
|
--- lib.require cached Module, main.lua und light.lua teilen sich also dieselbe
|
||||||
|
--- config-Tabelle - das Licht zieht sofort mit.
|
||||||
|
if config.debug then
|
||||||
|
--- @return vector3?
|
||||||
|
local function readVec(args, from)
|
||||||
|
local x, y, z = tonumber(args[from]), tonumber(args[from + 1]), tonumber(args[from + 2])
|
||||||
|
|
||||||
|
if not x or not y or not z then return end
|
||||||
|
|
||||||
|
return vec3(x, y, z)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fmtVec(v)
|
||||||
|
return ('vec3(%.2f, %.2f, %.2f)'):format(v.x, v.y, v.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterCommand('divelamp', function(_, args)
|
||||||
|
local offset, rotation = readVec(args, 1), readVec(args, 4)
|
||||||
|
|
||||||
|
if not offset or not rotation then
|
||||||
|
lib.print.info('/divelamp <x> <y> <z> <rx> <ry> <rz> - Sitz des Lampen-Props')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
config.lampPropOffset, config.lampPropRotation = offset, rotation
|
||||||
|
|
||||||
|
if currentGear.enabled then
|
||||||
|
deleteGear()
|
||||||
|
attachGear()
|
||||||
|
end
|
||||||
|
|
||||||
|
lib.print.info(('lampPropOffset = %s,\nlampPropRotation = %s,'):format(fmtVec(offset), fmtVec(rotation)))
|
||||||
|
end, false)
|
||||||
|
|
||||||
|
RegisterCommand('divelight', function(_, args)
|
||||||
|
local offset, direction = readVec(args, 1), readVec(args, 4)
|
||||||
|
|
||||||
|
if not offset or not direction then
|
||||||
|
lib.print.info('/divelight <x> <y> <z> <dx> <dy> <dz> - Ursprung und Richtung des Lichtkegels')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
config.lampOffset, config.lampDirection = offset, direction
|
||||||
|
|
||||||
|
lib.print.info(('lampOffset = %s,\nlampDirection = %s,'):format(fmtVec(offset), fmtVec(direction)))
|
||||||
|
end, false)
|
||||||
|
end
|
||||||
|
|
||||||
--- Beim Model-Wechsel (Kleiderladen, Skin-Change) ist der Ped ein anderer -
|
--- Beim Model-Wechsel (Kleiderladen, Skin-Change) ist der Ped ein anderer -
|
||||||
--- alle attached Props sind weg und die Scuba-Flags gelten für den alten Ped.
|
--- alle attached Props sind weg und die Scuba-Flags gelten für den alten Ped.
|
||||||
---
|
---
|
||||||
|
|||||||
+42
-15
@@ -1,4 +1,9 @@
|
|||||||
return {
|
return {
|
||||||
|
--- Schaltet /divelamp und /divelight frei, mit denen sich Sitz und
|
||||||
|
--- Leuchtrichtung der Lampe im laufenden Spiel einstellen lassen - ohne
|
||||||
|
--- Resource-Restart pro Versuch. Auf dem Live-Server ausschalten.
|
||||||
|
debug = false,
|
||||||
|
|
||||||
putOnSuitTimeMs = 5000,
|
putOnSuitTimeMs = 5000,
|
||||||
takeOffSuitTimeMs = 5000,
|
takeOffSuitTimeMs = 5000,
|
||||||
refillTankTimeMs = 5000,
|
refillTankTimeMs = 5000,
|
||||||
@@ -61,31 +66,53 @@ return {
|
|||||||
--- Tastenbelegungen unter "FiveM" umlegen.
|
--- Tastenbelegungen unter "FiveM" umlegen.
|
||||||
lampKey = 'l',
|
lampKey = 'l',
|
||||||
|
|
||||||
--- Prop am Kopf. Rein optisch - das Licht selbst hängt nicht daran.
|
--- Bone, an dem Lampe und Licht hängen. Beides derselbe Bone, damit der
|
||||||
--- Ist das Model ungültig, wird nur das Licht gezeichnet und eine Warnung
|
--- Strahl auch sichtbar aus der Lampe kommt.
|
||||||
--- ins Log geschrieben. Alternativen: siehe forge.plebmasters.de/objects
|
--- 12844 = Kopf (wie die Maske) - Strahl folgt der Blickrichtung
|
||||||
|
--- 28422 = Hand (wie das Prop in d4rk_phone) - Handlampe, aber beim
|
||||||
|
--- Schwimmen sind die Arme seitlich ausgestreckt, der Kegel
|
||||||
|
--- wandert also mit den Schwimmzügen
|
||||||
|
lampBone = 12844,
|
||||||
|
|
||||||
|
--- Prop am Kopf. Rein optisch - das Licht hängt nicht daran, es wird nur
|
||||||
|
--- vom selben Bone aus gezeichnet. Ist das Model ungültig, leuchtet es
|
||||||
|
--- trotzdem und es gibt eine Warnung im Log.
|
||||||
|
--- Im Basegame gibt es keine Tauchlampe. Alternativen sind Varianten
|
||||||
|
--- derselben Polizei-Lampe: 'prop_police_torch', 'prop_scn_police_torch'.
|
||||||
|
--- Auf '' setzen = gar kein Prop, nur Licht.
|
||||||
lampProp = 'prop_cs_police_torch',
|
lampProp = 'prop_cs_police_torch',
|
||||||
|
|
||||||
--- Position des Lichts relativ zum Kopf-Bone (bone-relativ, nicht Weltkoordinaten).
|
--- Sitz des Props am Bone. Wie in d4rk_phone bewusst auf null: das Prop sitzt
|
||||||
lampOffset = vec3(0.0, 0.15, 0.0),
|
--- dann genau im Bone statt auf geratenen Offsets. Beim Kopf-Bone darf ein
|
||||||
|
--- kleiner Versatz nach vorne/seitlich nötig sein, damit die Lampe nicht im
|
||||||
|
--- Schädel steckt - mit /divelamp im Spiel einstellen statt hier zu raten.
|
||||||
|
lampPropOffset = vec3(0.0, 0.0, 0.0),
|
||||||
|
lampPropRotation = vec3(0.0, 0.0, 0.0),
|
||||||
|
|
||||||
|
--- Ursprung des Lichtkegels relativ zum Bone (bone-relativ, nicht Welt).
|
||||||
|
--- Sollte ungefähr dort liegen, wo das Prop sitzt.
|
||||||
|
lampOffset = vec3(0.0, 0.0, 0.0),
|
||||||
|
|
||||||
--- Richtung des Lichtkegels, ebenfalls bone-relativ. Leuchtet der Kegel in die
|
--- Richtung des Lichtkegels, ebenfalls bone-relativ. Leuchtet der Kegel in die
|
||||||
--- falsche Richtung, hier die Achse tauschen oder das Vorzeichen drehen -
|
--- falsche Richtung, hier die Achse tauschen oder das Vorzeichen drehen -
|
||||||
--- welche lokale Achse des Kopf-Bones nach vorne zeigt, hängt am Skelett.
|
--- welche lokale Achse des Kopf-Bones nach vorne zeigt, hängt am Skelett.
|
||||||
lampDirection = vec3(0.0, 1.0, 0.0),
|
lampDirection = vec3(0.0, 1.0, 0.0),
|
||||||
|
|
||||||
--- Lichtfarbe als { r, g, b }, 0-255. Leicht kühl für Unterwasser.
|
--- Lichtwerte aus d4rk_phone übernommen - dort im Betrieb erprobt, statt hier
|
||||||
lampColour = { 225, 245, 255 },
|
--- neu geraten. Leicht warmweiß wie eine echte Taschenlampe.
|
||||||
|
lampColour = { 255, 250, 235 },
|
||||||
|
|
||||||
lampDistance = 30.0, -- Reichweite in Metern
|
lampDistance = 28.0, -- Reichweite in Metern
|
||||||
lampBrightness = 6.0, -- Helligkeit
|
lampBrightness = 3.0, -- Helligkeit
|
||||||
lampRoundness = 1.0, -- Weichzeichnung des Kegelrands
|
lampRoundness = 0.0, -- Weichzeichnung des Kegelrands
|
||||||
lampRadius = 14.0, -- Öffnungswinkel
|
lampRadius = 16.0, -- Öffnungswinkel
|
||||||
lampFalloff = 1.5, -- Abfall zum Rand hin
|
lampFalloff = 2.0, -- Abfall zum Rand hin
|
||||||
|
|
||||||
--- Schatten kosten deutlich Performance. Auf false wird DrawSpotLight statt
|
--- Schatten kosten deutlich Performance. d4rk_phone nutzt bewusst das
|
||||||
--- DrawSpotLightWithShadow benutzt - sieht flacher aus, läuft aber spürbar besser.
|
--- schattenlose DrawSpotLight, deshalb hier auch der Default - unter Wasser
|
||||||
lampShadows = true,
|
--- fällt der Unterschied kaum auf, in einer Höhle mit mehreren Tauchern
|
||||||
|
--- dagegen sehr wohl.
|
||||||
|
lampShadows = false,
|
||||||
|
|
||||||
--- Ab dieser Entfernung werden fremde Lampen nicht mehr gezeichnet (Meter).
|
--- Ab dieser Entfernung werden fremde Lampen nicht mehr gezeichnet (Meter).
|
||||||
lampDrawDistance = 45.0,
|
lampDrawDistance = 45.0,
|
||||||
|
|||||||
Reference in New Issue
Block a user