- aether-medical: Stationen/Belegung, Intensivstation, Blutbank, Fuhrpark, Nachrichten/Aushänge, Berichte und Textbausteine (server + NUI) - aether-admin: vollständiges Server-Admin-Panel als echtes FiveM-Resource, an aether-core gekoppelt (Rechte über aether_users.admin_group), mit WebRTC-Live-Kameras (Bildschirmfreigabe) und separatem Media-Server (SFU) - Prototypen admin/ vervollständigt - SQL-Schema aether_admin.sql - Docker-Compose mit MariaDB und idempotenter Auto-Migration (schema_migrations) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
133 lines
5.8 KiB
Lua
133 lines
5.8 KiB
Lua
-- =====================================================================
|
||
-- Aether Character — Aussehen auf den GTA-Ped uebertragen
|
||
--
|
||
-- WICHTIG: Der Charakter-Ersteller arbeitet mit einer stilisierten
|
||
-- SVG-Vorschau und eigenen Werten (Paletten-Index, Slider 0–100).
|
||
-- GTA kennt diese Werte nicht — die folgenden Tabellen sind daher eine
|
||
-- *Annaeherung*. Sie sind bewusst als einfache Zuordnungstabellen
|
||
-- gebaut, damit du die Werte jederzeit nachjustieren kannst.
|
||
-- =====================================================================
|
||
|
||
AetherAussehen = {}
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- Zuordnungstabellen (Index aus dem Ersteller -> GTA-Wert)
|
||
-- ---------------------------------------------------------------------
|
||
|
||
-- Hautton-Index -> Elternteil-Haut fuer SetPedHeadBlendData (0–45)
|
||
-- Niedrige Werte = hellere Haut, hohe Werte = dunklere Haut
|
||
local HAUT_ZU_ELTERN = { [0]=0, [1]=1, [2]=2, [3]=3, [4]=4, [5]=5, [6]=6, [7]=7 }
|
||
|
||
-- Frisur-Index -> Drawable der Komponente 2 (Haare), je Geschlecht
|
||
local FRISUR = {
|
||
maennlich = { [0]=1, [1]=2, [2]=6, [3]=4, [4]=10, [5]=0 }, -- Kurz/Mittel/Undercut/Lang/Zopf/Glatze
|
||
weiblich = { [0]=1, [1]=3, [2]=12, [3]=8, [4]=9, [5]=0 },
|
||
}
|
||
|
||
-- Haarfarben-Index -> GTA-Haarfarbe (0–63)
|
||
local HAARFARBE = { [0]=0, [1]=2, [2]=5, [3]=8, [4]=10, [5]=12, [6]=6, [7]=17, [8]=18, [9]=63 }
|
||
|
||
-- Augenfarben-Index -> GTA-Augenfarbe (0–31)
|
||
local AUGENFARBE = { [0]=1, [1]=2, [2]=0, [3]=3, [4]=5, [5]=4 }
|
||
|
||
-- Bart-Index -> Overlay-Drawable (Overlay 1 = Bart); -1 bedeutet rasiert
|
||
local BART = { [0]=-1, [1]=10, [2]=2, [3]=5 }
|
||
|
||
-- Augenbrauen-Index (0/1/2) -> Overlay-Drawable (Overlay 2)
|
||
local AUGENBRAUEN = { [0]=4, [1]=1, [2]=6 }
|
||
|
||
-- Kleidungsfarben-Index -> Textur-Variante der jeweiligen Komponente
|
||
local KLEID_TEXTUR = { [0]=0, [1]=1, [2]=2, [3]=3, [4]=4, [5]=5, [6]=6, [7]=7, [8]=8, [9]=9 }
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- Hilfsfunktionen
|
||
-- ---------------------------------------------------------------------
|
||
|
||
--- Rechnet einen Slider (0–100) in einen GTA-Gesichtswert (-1.0 bis 1.0) um
|
||
--- @param wert number Sliderwert 0–100
|
||
--- @return number Gesichtswert
|
||
local function SliderZuGesicht(wert)
|
||
return ((tonumber(wert) or 50) - 50) / 50.0
|
||
end
|
||
|
||
--- Liefert den Schluessel fuer die geschlechtsabhaengigen Tabellen
|
||
--- @param geschlecht string 'männlich' | 'weiblich' | 'divers'
|
||
--- @return string
|
||
local function GeschlechtSchluessel(geschlecht)
|
||
return (geschlecht == 'weiblich') and 'weiblich' or 'maennlich'
|
||
end
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- Anwendung
|
||
-- ---------------------------------------------------------------------
|
||
|
||
--- Liefert den passenden Ped-Modellnamen zum Geschlecht
|
||
--- @param geschlecht string
|
||
--- @return string Modellname
|
||
function AetherAussehen.HoleModell(geschlecht)
|
||
if geschlecht == 'weiblich' then return 'mp_f_freemode_01' end
|
||
return 'mp_m_freemode_01'
|
||
end
|
||
|
||
--- Uebertraegt ein Aussehen-Objekt des Erstellers auf einen Ped
|
||
--- @param ped number Ped-Handle
|
||
--- @param aussehen table Aussehen aus dem Charakter-Ersteller
|
||
function AetherAussehen.Anwenden(ped, aussehen)
|
||
if not aussehen or not DoesEntityExist(ped) then return end
|
||
|
||
local schluessel = GeschlechtSchluessel(aussehen.geschlecht)
|
||
local hautEltern = HAUT_ZU_ELTERN[aussehen.skin or 1] or 1
|
||
|
||
-- Grundgesicht: Eltern und Hautton mischen
|
||
SetPedHeadBlendData(ped,
|
||
0, 0, 0, -- Gesichtsform (Vater, Mutter, Mischung)
|
||
hautEltern, hautEltern, 0,
|
||
0.5, 1.0, 0.0, -- Gewichtung Form / Haut / Drittwert
|
||
false)
|
||
|
||
-- Gesichtszuege aus den Slidern (GTA-Index -> Sliderwert)
|
||
SetPedFaceFeature(ped, 0, SliderZuGesicht(aussehen.nase)) -- Nasenbreite
|
||
SetPedFaceFeature(ped, 6, SliderZuGesicht(aussehen.lippen)) -- Lippendicke
|
||
SetPedFaceFeature(ped, 7, SliderZuGesicht(aussehen.kiefer)) -- Kieferbreite
|
||
SetPedFaceFeature(ped, 11, SliderZuGesicht(aussehen.gesichtBreite)) -- Wangenbreite
|
||
|
||
-- Haare
|
||
local frisur = (FRISUR[schluessel] or FRISUR.maennlich)[aussehen.hairStyle or 0] or 0
|
||
SetPedComponentVariation(ped, 2, frisur, 0, 0)
|
||
local haarfarbe = HAARFARBE[aussehen.hairColor or 0] or 0
|
||
SetPedHairColor(ped, haarfarbe, haarfarbe)
|
||
|
||
-- Augenfarbe (Native ohne offiziellen Namen)
|
||
local augenfarbe = AUGENFARBE[aussehen.augen or 0] or 0
|
||
Citizen.InvokeNative(0x50B56988B170AFDF, ped, augenfarbe)
|
||
|
||
-- Augenbrauen (Overlay 2)
|
||
local braue = AUGENBRAUEN[math.floor((aussehen.augenbraue or 50) / 50)] or 1
|
||
SetPedHeadOverlay(ped, 2, braue, 1.0)
|
||
SetPedHeadOverlayColor(ped, 2, 1, haarfarbe, haarfarbe)
|
||
|
||
-- Bart (Overlay 1) — nur bei nicht-weiblichen Peds sinnvoll
|
||
local bart = BART[aussehen.bart or 0] or -1
|
||
if bart >= 0 then
|
||
SetPedHeadOverlay(ped, 1, bart, 1.0)
|
||
SetPedHeadOverlayColor(ped, 1, 1, haarfarbe, haarfarbe)
|
||
else
|
||
SetPedHeadOverlay(ped, 1, 255, 0.0) -- 255 = kein Overlay
|
||
end
|
||
|
||
-- Kleidung: Farbe wird als Texturvariante der Komponente gesetzt
|
||
local oberteil = KLEID_TEXTUR[aussehen.top or 0] or 0
|
||
local hose = KLEID_TEXTUR[aussehen.hose or 0] or 0
|
||
local schuhe = KLEID_TEXTUR[aussehen.schuhe or 0] or 0
|
||
|
||
SetPedComponentVariation(ped, 11, 1, oberteil, 0) -- Oberkoerper (Jacke/Shirt)
|
||
SetPedComponentVariation(ped, 8, 1, 0, 0) -- Unterhemd
|
||
SetPedComponentVariation(ped, 3, 1, 0, 0) -- Arme
|
||
SetPedComponentVariation(ped, 4, 1, hose, 0) -- Beine
|
||
SetPedComponentVariation(ped, 6, 1, schuhe, 0) -- Schuhe
|
||
|
||
-- Koerperbau als Fettigkeits-/Muskel-Overlay (Overlay 10 = Sommersprossen frei,
|
||
-- daher nutzen wir Overlay 0 nicht; Statur ueber Gesichtszug 19 annaehern)
|
||
SetPedFaceFeature(ped, 19, SliderZuGesicht(aussehen.koerper))
|
||
end
|