aether-framework/resources/[aether]/aether-character/client/main.lua
Jerrit Fritzsche 0440de16e5 debug: Ausgaben in der Charakterauswahl-Kette zur Fehlersuche
Temporaere [AETHER-DEBUG]-Prints in spielerBereit (core),
charakterAuswahlNoetig (character-server) und OeffneAuswahl (client),
um zu lokalisieren, wo die Auswahl bei AutoCharakter=false stoppt.
Werden nach der Diagnose wieder entfernt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:19:26 +02:00

161 lines
5.6 KiB
Lua

-- =====================================================================
-- Aether Character — Clientlogik
-- Zeigt die Charakterauswahl, verwaltet die Kamera und meldet die
-- Auswahl an den Server. Der Core uebernimmt danach das Spawnen.
-- =====================================================================
-- Ist die Auswahl gerade offen?
local auswahlOffen = false
-- Ort, an dem der Spieler waehrend der Auswahl geparkt wird
local PARKPLATZ = { x = -1037.7, y = -2737.6, z = 20.2 }
-- ---------------------------------------------------------------------
-- Auswahl oeffnen / schliessen
-- ---------------------------------------------------------------------
--- Oeffnet die Charakterauswahl mit der Liste vom Server
--- @param charaktere table Liste der Charaktere
--- @param maxSlots number Maximale Anzahl Charaktere
local function OeffneAuswahl(charaktere, maxSlots)
print(('[AETHER-DEBUG] client OeffneAuswahl: %d Charaktere')
:format(charaktere and #charaktere or -1))
auswahlOffen = true
-- Eigenen Spieler unsichtbar parken — sichtbar ist nur der Vorschau-Ped
local ped = PlayerPedId()
SetEntityVisible(ped, false, false)
FreezeEntityPosition(ped, true)
SetEntityCoordsNoOffset(ped, PARKPLATZ.x, PARKPLATZ.y, PARKPLATZ.z, false, false, false)
-- 3D-Vorschau mit dem Aussehen des ersten Charakters starten
local erstes = charaktere and charaktere[1] or nil
Vorschau.Starten(erstes and erstes.aussehen or nil, 'koerper')
print('[AETHER-DEBUG] client OeffneAuswahl: Vorschau gestartet, beende Ladebildschirm')
-- Ladebildschirm beenden, damit die Auswahl sichtbar wird
ShutdownLoadingScreen()
ShutdownLoadingScreenNui()
DoScreenFadeIn(800)
SetNuiFocus(true, true)
SendNuiMessage(json.encode({
aktion = 'oeffnen',
charaktere = charaktere,
maxSlots = maxSlots,
}))
end
--- Schliesst die Auswahl und gibt die Steuerung frei
local function SchliesseAuswahl()
if not auswahlOffen then return end
auswahlOffen = false
SendNuiMessage(json.encode({ aktion = 'schliessen' }))
SetNuiFocus(false, false)
DoScreenFadeOut(400)
Wait(400)
Vorschau.Beenden()
end
-- ---------------------------------------------------------------------
-- Ereignisse vom Server
-- ---------------------------------------------------------------------
--- Server fordert die Charakterauswahl an
RegisterNetEvent('aether:character:zeigeAuswahl', function(charaktere, maxSlots)
OeffneAuswahl(charaktere, maxSlots)
end)
--- Aktualisierte Liste nach Erstellen oder Loeschen
RegisterNetEvent('aether:character:liste', function(charaktere, maxSlots, hinweis)
SendNuiMessage(json.encode({
aktion = 'liste',
charaktere = charaktere,
maxSlots = maxSlots,
hinweis = hinweis,
}))
end)
--- Server lehnt eine Aktion ab (z. B. Slot voll, ungueltiger Name)
RegisterNetEvent('aether:character:fehler', function(text)
SendNuiMessage(json.encode({ aktion = 'fehler', text = text }))
end)
--- Charakter wurde gewaehlt: Auswahl sofort schliessen, damit der Core
--- ungestoert spawnen kann (Netz-Event kommt gleichzeitig beim Core an)
RegisterNetEvent('aether:client:spielerGeladen', function()
if auswahlOffen then
SchliesseAuswahl()
end
end)
--- Der Core hat den Ped gesetzt und gespawnt: jetzt das Aussehen anwenden.
--- Eigenes Event, damit wir nicht mit dem Modellwechsel des Cores kollidieren.
AddEventHandler('aether:client:bereit', function(daten)
if daten and daten.aussehen then
AetherAussehen.Anwenden(PlayerPedId(), daten.aussehen)
end
local ped = PlayerPedId()
FreezeEntityPosition(ped, false)
SetEntityVisible(ped, true, false)
end)
-- ---------------------------------------------------------------------
-- NUI-Callbacks (Aktionen aus der Oberflaeche)
-- ---------------------------------------------------------------------
--- Aussehen hat sich geaendert: sofort auf den Vorschau-Ped uebertragen
RegisterNUICallback('vorschau', function(daten, rueckgabe)
if daten.aussehen then
Vorschau.Anwenden(daten.aussehen)
end
if daten.modus then
Vorschau.SetzeModus(daten.modus)
end
rueckgabe({ ok = true })
end)
--- Ansicht wechseln (Gesicht / Koerper)
RegisterNUICallback('vorschauModus', function(daten, rueckgabe)
Vorschau.SetzeModus(daten.modus or 'koerper')
rueckgabe({ ok = true })
end)
--- Vorschau-Ped drehen
RegisterNUICallback('vorschauDrehen', function(daten, rueckgabe)
Vorschau.Drehen(tonumber(daten.grad) or 0.0)
rueckgabe({ ok = true })
end)
--- Spieler waehlt einen Charakter zum Spielen
RegisterNUICallback('spielen', function(daten, rueckgabe)
TriggerServerEvent('aether:character:spielen', daten.charakterId)
rueckgabe({ ok = true })
end)
--- Spieler legt einen neuen Charakter an
RegisterNUICallback('erstellen', function(daten, rueckgabe)
TriggerServerEvent('aether:character:erstellen', daten)
rueckgabe({ ok = true })
end)
--- Spieler loescht einen Charakter
RegisterNUICallback('loeschen', function(daten, rueckgabe)
TriggerServerEvent('aether:character:loeschen', daten.charakterId)
rueckgabe({ ok = true })
end)
-- ---------------------------------------------------------------------
-- Aufraeumen beim Stoppen der Ressource
-- ---------------------------------------------------------------------
AddEventHandler('onResourceStop', function(ressource)
if ressource ~= GetCurrentResourceName() then return end
SetNuiFocus(false, false)
Vorschau.Beenden()
FreezeEntityPosition(PlayerPedId(), false)
SetEntityVisible(PlayerPedId(), true, false)
end)