-- ===================================================================== -- Aether Core — Spielerobjekt -- Kapselt die Daten eines eingeloggten Charakters samt Methoden. -- ===================================================================== Aether = Aether or {} -- Alle aktiven Spieler, indiziert nach Server-ID Aether.Spieler = {} -- Methodentabelle (Vorlage fuer jedes Spielerobjekt) local SpielerMethoden = {} SpielerMethoden.__index = SpielerMethoden -- --------------------------------------------------------------------- -- Erzeugung -- --------------------------------------------------------------------- --- Erzeugt ein Spielerobjekt aus einem Charakter-Datensatz --- @param quelle number Server-ID des Spielers --- @param lizenz string Rockstar-Lizenz --- @param charakter table Datensatz aus aether_characters --- @return table Spielerobjekt function Aether.ErzeugeSpieler(quelle, lizenz, charakter) -- Gespeicherte Position einlesen (oder Standard-Spawn nutzen) local position = Config.SpawnPunkt if charakter.position then local erfolg, entschluesselt = pcall(json.decode, charakter.position) if erfolg and entschluesselt then position = entschluesselt end end -- Aussehen einlesen (JSON aus dem Charakter-Ersteller) local aussehen = nil if charakter.appearance then local erfolg, entschluesselt = pcall(json.decode, charakter.appearance) if erfolg then aussehen = entschluesselt end end local spieler = setmetatable({}, SpielerMethoden) spieler.quelle = quelle spieler.lizenz = lizenz spieler.charakterId = charakter.id -- Identitaet spieler.vorname = charakter.firstname spieler.nachname = charakter.lastname spieler.geburtstag = charakter.dob spieler.geschlecht = charakter.gender spieler.herkunft = charakter.nationality spieler.aussehen = aussehen -- Geld spieler.bargeld = charakter.cash spieler.konto = charakter.bank spieler.schwarzgeld = charakter.dirty_money spieler.iban = charakter.iban -- Arbeit und Zugehoerigkeit spieler.job = charakter.job spieler.jobRang = charakter.job_grade spieler.fraktion = charakter.faction spieler.fraktionRang= charakter.faction_rank -- Zustand spieler.leben = charakter.health spieler.hunger = charakter.hunger spieler.durst = charakter.thirst spieler.ausdauer = charakter.stamina spieler.istTot = charakter.is_dead == 1 spieler.position = position spieler.spielzeit = charakter.playtime or 0 Aether.Spieler[quelle] = spieler return spieler end -- --------------------------------------------------------------------- -- Geld -- --------------------------------------------------------------------- --- Liefert den Kontostand einer Geldart --- @param art string 'bargeld' | 'konto' | 'schwarzgeld' --- @return number function SpielerMethoden:HoleGeld(art) return self[art] or 0 end --- Fuegt Geld hinzu und meldet die Aenderung an den Client --- @param art string 'bargeld' | 'konto' | 'schwarzgeld' --- @param betrag number Positiver Betrag --- @param grund string|nil Verwendungszweck fuer die Transaktionsliste --- @return boolean Erfolg function SpielerMethoden:FuegeGeldHinzu(art, betrag, grund) if betrag <= 0 then return false end self[art] = (self[art] or 0) + betrag -- Kontobewegungen zusaetzlich protokollieren if art == 'konto' then Aether.DB.SchreibeTransaktion(self.charakterId, 'deposit', betrag, self.konto, grund) end self:SendeGeld() return true end --- Zieht Geld ab, sofern gedeckt --- @param art string 'bargeld' | 'konto' | 'schwarzgeld' --- @param betrag number Positiver Betrag --- @param grund string|nil Verwendungszweck --- @return boolean Erfolg (false = nicht genug Geld) function SpielerMethoden:EntferneGeld(art, betrag, grund) if betrag <= 0 then return false end if (self[art] or 0) < betrag then return false end -- Deckungspruefung self[art] = self[art] - betrag if art == 'konto' then Aether.DB.SchreibeTransaktion(self.charakterId, 'withdraw', -betrag, self.konto, grund) end self:SendeGeld() return true end --- Schickt die aktuellen Geldwerte an den Client (fuer HUD und Handy) function SpielerMethoden:SendeGeld() TriggerClientEvent('aether:client:geldAktualisiert', self.quelle, { bargeld = self.bargeld, konto = self.konto, schwarzgeld = self.schwarzgeld, }) end -- --------------------------------------------------------------------- -- Zustand -- --------------------------------------------------------------------- --- Setzt einen Zustandswert (Hunger/Durst/Ausdauer) und begrenzt ihn auf 0–100 --- @param art string 'hunger' | 'durst' | 'ausdauer' --- @param wert number Neuer Wert function SpielerMethoden:SetzeZustand(art, wert) self[art] = Aether.Begrenze(wert, 0, 100) TriggerClientEvent('aether:client:zustandAktualisiert', self.quelle, { hunger = self.hunger, durst = self.durst, ausdauer = self.ausdauer, }) end -- --------------------------------------------------------------------- -- Daten fuer den Client -- --------------------------------------------------------------------- --- Baut das Datenpaket, das der Client zum Spielen braucht --- @return table function SpielerMethoden:HoleDaten() return { charakterId = self.charakterId, vorname = self.vorname, nachname = self.nachname, geburtstag = self.geburtstag, geschlecht = self.geschlecht, aussehen = self.aussehen, bargeld = self.bargeld, konto = self.konto, schwarzgeld = self.schwarzgeld, iban = self.iban, job = self.job, jobRang = self.jobRang, fraktion = self.fraktion, fraktionRang= self.fraktionRang, leben = self.leben, hunger = self.hunger, durst = self.durst, ausdauer = self.ausdauer, istTot = self.istTot, position = self.position, } end -- --------------------------------------------------------------------- -- Speichern -- --------------------------------------------------------------------- --- Schreibt den aktuellen Stand des Spielers in die Datenbank function SpielerMethoden:Speichere() Aether.DB.SpeichereCharakter(self.charakterId, { cash = self.bargeld, bank = self.konto, dirty_money = self.schwarzgeld, job = self.job, job_grade = self.jobRang, faction = self.fraktion, faction_rank = self.fraktionRang, health = self.leben, hunger = math.floor(self.hunger), thirst = math.floor(self.durst), stamina = math.floor(self.ausdauer), position = self.position, is_dead = self.istTot, playtime = self.spielzeit, }) end