aether-framework/resources/[aether]/aether-hud/client/main.lua
Jerrit Fritzsche e4b82dd685 Aether-Framework: Fachmodule, Admin-Panel und Docker-Datenbank
- 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>
2026-07-27 18:55:32 +02:00

196 lines
6.5 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- =====================================================================
-- Aether HUD — Clientlogik
-- Versorgt die Oberflaeche mit Status, Geld, Voice und Fahrzeugwerten.
-- Es wird nur gesendet, wenn sich ein Wert tatsaechlich geaendert hat.
-- =====================================================================
-- Ist der Spieler fertig geladen? (vorher kein HUD zeigen)
local istGeladen = false
-- Soll das HUD sichtbar sein? (z. B. bei offenen Menues ausblendbar)
local istSichtbar = true
-- Zuletzt gesendete Werte, um unnoetige Nachrichten zu vermeiden
local letzterStatus = {}
local letztesFahrzeug = {}
local letzteVoice = {}
-- ---------------------------------------------------------------------
-- Hilfsfunktionen
-- ---------------------------------------------------------------------
--- Schickt eine Nachricht an die Oberflaeche
--- @param nachricht table Zu sendende Daten
local function SendeAnHud(nachricht)
SendNuiMessage(json.encode(nachricht))
end
--- Prueft, ob sich mindestens ein Feld gegenueber dem Zwischenspeicher geaendert hat
--- @param neu table Neue Werte
--- @param alt table Zwischenspeicher (wird aktualisiert)
--- @return boolean true, wenn sich etwas geaendert hat
local function HatSichGeaendert(neu, alt)
local geaendert = false
for schluessel, wert in pairs(neu) do
if alt[schluessel] ~= wert then
alt[schluessel] = wert
geaendert = true
end
end
return geaendert
end
--- Rechnet die Lebensenergie (100–200) in Prozent (0–100) um.
--- GTA zaehlt Leben ab 100; darunter ist der Spieler tot.
--- @param ped number Ped-Handle
--- @return number Prozentwert 0–100
local function LebenInProzent(ped)
local leben = GetEntityHealth(ped)
if leben <= 100 then return 0 end
return Aether.Begrenze((leben - 100) / 100 * 100, 0, 100)
end
-- ---------------------------------------------------------------------
-- Ereignisse vom Core
-- ---------------------------------------------------------------------
--- Spieler ist im Spiel: HUD mit den Startwerten fuellen
AddEventHandler('aether:client:bereit', function(daten)
istGeladen = true
SendeAnHud({
aktion = 'geld',
bargeld = daten.bargeld,
konto = daten.konto,
schwarzgeld = daten.schwarzgeld,
-- Schwarzgeld nur zeigen, wenn welches vorhanden ist
schwarzgeldSichtbar = (daten.schwarzgeld or 0) > 0,
})
SendeAnHud({
aktion = 'status',
leben = LebenInProzent(PlayerPedId()),
hunger = daten.hunger,
durst = daten.durst,
ausdauer = daten.ausdauer,
})
SendeAnHud({ aktion = 'sichtbar', an = true })
end)
--- Geld hat sich geaendert
AddEventHandler('aether:client:geldGeaendert', function(geld)
SendeAnHud({
aktion = 'geld',
bargeld = geld.bargeld,
konto = geld.konto,
schwarzgeld = geld.schwarzgeld,
schwarzgeldSichtbar = (geld.schwarzgeld or 0) > 0,
})
end)
--- Hunger/Durst/Ausdauer haben sich geaendert
AddEventHandler('aether:client:zustandGeaendert', function(zustand)
SendeAnHud({
aktion = 'status',
hunger = zustand.hunger,
durst = zustand.durst,
ausdauer = zustand.ausdauer,
})
end)
-- ---------------------------------------------------------------------
-- Laufende Erfassung: Leben und Ausdauer
-- ---------------------------------------------------------------------
CreateThread(function()
while true do
Wait(500)
if istGeladen then
local ped = PlayerPedId()
-- Ausdauer aus dem Sprint-Vorrat ableiten (100 = ausgeruht)
local ausdauer = 100.0 - GetPlayerSprintStaminaRemaining(PlayerId())
local neu = {
leben = math.floor(LebenInProzent(ped)),
ausdauer = math.floor(Aether.Begrenze(ausdauer, 0, 100)),
}
if HatSichGeaendert(neu, letzterStatus) then
neu.aktion = 'status'
SendeAnHud(neu)
end
end
end
end)
-- ---------------------------------------------------------------------
-- Laufende Erfassung: Voice
-- ---------------------------------------------------------------------
CreateThread(function()
while true do
Wait(200)
if istGeladen then
-- Sprechen erkennen (funktioniert mit dem eingebauten Mumble-Voice)
local redet = NetworkIsPlayerTalking(PlayerId())
-- Reichweite aus der Mumble-Einstellung ableiten
local reichweite = MumbleGetTalkerProximity() or 0.0
local stufe = 1 -- 0 = Fluestern, 1 = Normal, 2 = Rufen
if reichweite <= 3.5 then stufe = 0
elseif reichweite >= 12.0 then stufe = 2 end
local neu = { redet = redet, voiceStufe = stufe }
if HatSichGeaendert(neu, letzteVoice) then
neu.aktion = 'voice'
SendeAnHud(neu)
end
end
end
end)
-- ---------------------------------------------------------------------
-- Laufende Erfassung: Fahrzeug
-- Im Fahrzeug haeufiger abfragen, damit der Tacho fluessig laeuft.
-- ---------------------------------------------------------------------
CreateThread(function()
while true do
local pause = 500
if istGeladen then
local daten = Fahrzeug.HoleDaten()
if daten then
pause = 100 -- fluessige Tachoanzeige
if HatSichGeaendert(daten, letztesFahrzeug) then
daten.aktion = 'fahrzeug'
SendeAnHud(daten)
end
elseif letztesFahrzeug.imFahrzeug ~= false then
-- Gerade ausgestiegen: Fahrzeuganzeige ausblenden
letztesFahrzeug = { imFahrzeug = false }
SendeAnHud({ aktion = 'fahrzeug', imFahrzeug = false, tempo = 0 })
end
end
Wait(pause)
end
end)
-- =====================================================================
-- EXPORTS — andere Module koennen das HUD aus- und einblenden
-- Beispiel: exports['aether-hud']:SetzeSichtbar(false)
-- =====================================================================
--- Blendet das HUD ein oder aus
--- @param an boolean true = sichtbar
exports('SetzeSichtbar', function(an)
istSichtbar = an and true or false
SendeAnHud({ aktion = 'sichtbar', an = istSichtbar })
end)
--- Ist das HUD gerade sichtbar?
--- @return boolean
exports('IstSichtbar', function()
return istSichtbar
end)