[TUTORIAL]|- FIVEM - Schreibe deinen ersten GameMode in LUA !-|
Exclusive FiveM Scripts
In diesem Tutorial wir euch erklärt, wie ihr das Scripting auf FiveM mit LUA beginnen könnt.
Ressourcen
Sind eine Sammlung von Dateien, die einzeln gestartet, gestoppt und neu gestartet werden können.
Wenn du an deinem eigenen GameMode arbeitest, hast du wahrscheinlich ein Ressourcen- / [lokales] Verzeichnis erstellt - dieser wird von Git beim Aktualisieren des Serverdatenstamms ignoriert. Dort erstellen wir einen Ordner resources / [local] / GameMode, da wir mit dem Mapmanager-System einen Spieltyp erstellen. Das bedeutet, dass wir jetzt einen Ordner wie diesen haben müssen, vorausgesetzt ein Windows-Entwicklungssystem: C: \ Ihr \ Pfad \ zu \ cfx-Serverdaten \ Ressourcen \ [lokal] \ gamemode.
Für einen Ressourcenordner muss ein Manifest von FiveM erkannt werden. Da es sich um einen Spieltyp handelt, sind einige zusätzliche Informationen erforderlich, um Mapmanager darüber zu informieren, dass es sich um einen Spieltyp handelt. Erstelle in deinem GameMode-Ordner eine Datei mit dem Namen fxmanifest.lua (dies ist immer Lua, auch wenn du später Skripte in C # / JS schreibst).
Fügen den folgenden Text mit Ihrem bevorzugten Texteditor ein:
- Jeder neue Ressource den du erstellst, wird wahrscheinlich die neuesten Spielversion benötigen.
- Der resource_type teilt dem Mapmanager mit, das dies tatsächlich ein Spieltyp ist und das er "Mein großartiger Spieltyp!" Heißt.
- Mit client_script lädt der Client das Skript mit dem Namen mymode_client.lual. Wenn dies ein JS-Skript wäre, würde es mymode_client.js heißen, oder bei C #, wäre es MyModeClient.net.dll .
Nun sollten wir eine Datei namens gamemode_client.lua im Ressourcenordner GameMode erstellen.
Jetzt fügen wir in unsere Datei folgendes ein..
Nun gehen wir es Stück für Stück durch...
-- Definiere eine lokale Variable namens `spawnPos` mit einer Koordinate irgendwo auf der Karte!
--Lua in FiveM (über CfxLua) unterstützt erstklassige Vektoren, auf die in diesem Fall mit .x, .y und .z zugegriffen werden kann.
local spawnPos = vector3(686.245, 577.950, 130.461)
-- Fügt einen Ereignishandler für das (lokale) Ereignis mit dem Namen 'onClientGameTypeStart' hinzu'.
-- In diesem Fall sind keine Argumente erforderlich (in Lua kannst du Argumente weglassen), da unsere Ressource ein Spieltyp ist und du nur eines gleichzeitig ausführen kannst.
-- Das bedeutet, dass dies grundsätzlich ausgeführt wird, wenn wir uns auf dem Client befinden.
AddEventHandler('onClientGameTypeStart', function() -- Setze einen automatischen Spawn-Rückruf für den Spawn-Manager. -- Normalerweise funktioniert dies mit fest codierten Spawnpunkten. Da es sich jedoch um ein Skript-Tutorial handelt, werden wir dies auf diese Weise tun. -- -- Der Spawn-Manager ruft dies auf, wenn der Spieler tot ist oder wenn forceRespawn aufgerufen wird. exports.spawnmanager:setAutoSpawnCallback(function() -- spawnmanager hat gesagt, wir sollten spawnen! exports.spawnmanager:spawnPlayer({ -- Dieses Argument ist im Grunde eine Tabelle, die den Spawn-Speicherort enthält ... x = spawnPos.x, y = spawnPos.y, z = spawnPos.z, -- ...und das Modell, als das laichen soll. model = 'a_m_m_skater_01' }, function() -- Ein callback, der aufgerufen wird, sobald der Spieler erschienen ist und das Spiel sichtbar ist -- In diesem Fall senden wir einfach eine Nachricht an die lokale Chatbox. TriggerEvent('chat:addMessage', { args = { 'Willkommen auf dem Server ;)~' } }) end) end)
-- Auto-Spawn aktivieren exports.spawnmanager:setAutoSpawn(true)
-- und Respawn erzwingen, wenn der Spieltyp startet exports.spawnmanager:forceRespawn()
end)
Das meiste, was wir in FiveM tun, wird mit Client-Skripten ausgeführt, da in aktuellen Versionen keine Interaktion mit der Spielfunktionalität in Serverskripten besteht. Serverskripte sollten verwendet werden, damit skriptübergreifende Aktionen zwischen Clients ausgeführt werden (mithilfe von Client / Server-Ereignissen) und um eine Vertrauensquelle für verschiedene Aktionen bereitzustellen, z. B. das Speichern / Laden von Objekten in einer persistenten Datenbank.
Jeder Spieler, der beigetreten ist, hat eine lokale Instanz jedes Client-Skripts auf seinem PC, ohne gemeinsame Variablen oder Kontext zwischen ihnen.
Die Ausführung
Führe nach dem Starten von FXServer den Aktualisierungsbefehl in der Konsole aus. Dadurch wird jede einzelne Datei fxmanifest.lua für jede von dir installierte Ressource erneut gelesen, da du den Server wahrscheinlich gerade erst gestartet hast. Dies ist nicht unbedingt erforderlich. Wenn der Server jedoch bereits ausgeführt wurde, ist dies nur eine gute Idee.
Jetzt kannst du deinen GameMode in der Konsole ausführen und stelle im Entwicklermodus über die praktischen lokalen Hosts des FünfM-Clients eine Verbindung zu einem bestimmten Server her (oder gebe einfachen Localhost auf die direkte Direktverbindung ein, oder KLICKE, wenn du den Standardport verwendest.
Halten das Spiel am Laufen (und stelle in den Spieloptionen möglicherweise auf den randlosen oder Fenstermodus ein) und drücke Alt-Tab wieder in deinenCode-Editor.
Ressourcen(GameMode)
Es ist albern, das Spiel und den Server zu schließen und beide neu zu starten. Natürlich können wir unsere Ressource(GameMode) auch neu starten, versuchen wir es einen anderen Spawnpunkt. Ersetze die spawnPos-Zeile (die erste) in GameMode/ GameMode_client.lua durch Folgendes:
local spawnPos = vector3(-275.522, 6635.835, 7.425)
Führe dann in der Serverkonsole den Befehl restart GameMode aus.
Fügen Sie am Ende Ihrer GameMode_client.lua diesen Code hinzu:
RegisterCommand('car', function(source, args) -- TODO: make a vehicle! fun! TriggerEvent('chat:addMessage', { args = { 'Test Test :O ' .. (args[1] or 'adder') .. ' Auto :O Test Test Test :(' } })
end, false)
Klicke auf folgendes KLICK, um zur Dokumentation für dieses native System zu gelangen. Beispiel:
// 0x5fa79b0f
// RegisterCommand
void REGISTER_COMMAND(char* commandName, func handler, BOOL restricted);
Wir werden uns hauptsächlich um den Namen in der zweiten Zeile (RegisterCommand, wie er im obigen Lua-Code verwendet wird) und die Argumente kümmern.
Das erste Argument ist der Befehlsname. Das zweite Argument ist eine Funktion, die der Befehlshandler ist, und das dritte Argument ist ein Boolescher Wert, der angibt, ob es sich um einen eingeschränkten Befehl handeln soll oder nicht.
Die Funktion selbst erhält ein Argument, das die Quelle ist, was nur dann wirklich wichtig ist, wenn sie auf dem Server ausgeführt werden (es ist die Client-ID des Players, der den Befehl eingegeben hat, eine wirklich nützliche Sache) und ein Array von Argumenten, die im
Grunde das sind, was Sie nach dem Befehl eingeben, wie / car zentorno, wodurch Argumente am Ende {'zentorno'} oder / car zentorno unbenutzt sind {'zentorno', 'unbenutzt'}.
Da wir bereits wissen, wie eine Nachricht in die Chat-Box gedruckt wird, geben wir nur vor, ein Fahrzeug zu erzeugen, indem wir den Namen des Fahrzeugs auf die Konsole drucken.
Lass uns die Ressource neu starten und sehen, was passiert. Führe restart GameMode aus und geben dann im Client-Chat-Feld (Standard-T) / car zentorno ein. Du wirst sehen, dass sich die Chat-Box beschwert, nun müssen wir Ihn tatsächlich implementieren.
Implementierung eines Auto-Spawners
Wir werden wir Folgendes tun:
- Wir überprüfen ob das übergebene Modell gültig ist. Es macht keinen Spaß zu versuchen, eine „Kartoffel“ hervorzubringen, wenn es kein Fahrzeug mit diesem Namen gibt.
- Lade das Modell. Du musst jedes Modell, das du verwendest, explizit verwalten. Dies sind die Regeln, die ursprünglich von R * definiert wurden.
- Warten bis das Modell geladen ist. Ja, das Spiel läuft asynchron weiter.
- Finde heraus, wo sich der Player befindet, sobald er geladen ist.
- Erstelle das Fahrzeug
- Setze den Spieler in das Fahrzeug.
Ersetzen die gerade eingefügte Funktion durch diese:
RegisterCommand('car', function(source, args) -- konto für das Argument nicht übergeben local vehicleName = args[1] or 'adder'
-- Überprüfen ob das Fahrzeug tatsächlich vorhanden ist if not IsModelInCdimage(vehicleName) or not IsModelAVehicle(vehicleName) then TriggerEvent('chat:addMessage', { args = { ' ' .. vehicleName .. } })
return end
-- load the model RequestModel(vehicleName)
-- Warte bis das Modell geladen ist HasModelLoaded(vehicleName) warte(500) end
-- Hole die Position des Spielers local playerPed = PlayerPedId() -- position des peds holen local pos = GetEntityCoords(playerPed)
-- Erstelle das Fahrzeug local vehicle = CreateVehicle(vehicleName, pos.x, pos.y, pos.z, GetEntityHeading(playerPed), true, false)
-- Setze den Spiler Ped auf den Fahrersitz des Fahrzeugs SetPedIntoVehicle(playerPed, vehicle, -1)
-- Gib das Fahrzeug zurück zum Spiel (dadurch entscheidet das Spiel, wann das Fahrzeug den Server verlassen soll SetEntityAsNoLongerNeeded(vehicle)
-- Fahrzeugmodel freigeben SetModelAsNoLongerNeeded(vehicleName)
-- Sag das dem Spieler TriggerEvent('chat:addMessage', {
args = { 'Dein neues Fahrzeug ^*' .. vehicleName .. '!' }
})
end, false)
Wir begannen mit der Überprüfung des Fahrzeugnamens. Wenn es Null ist (dh nicht vorhanden ist), verwenden wir standardmäßig den Addierer. In jedem Fall wird es in einer Variablen gespeichert.
Anschließend prüfen wir mit IS_MODEL_IN_CDIMAGE, ob sich das Fahrzeug im CD-Image befindet. Dies bedeutet im Grunde, dass dies beim Spiel registriert ist. Wir prüfen auch, ob es sich um ein Fahrzeug handelt, das IS_MODEL_A_VEHICLE verwendet. Wenn eine der Prüfungen fehlschlägt, teilen wir dies dem Spieler mit und kehren vom Befehl zurück.
Wir rufen REQUEST_MODEL auf, um das tatsächliche Fahrzeugmodell zu laden. Dieser Native verwendet ein Hash-Argument, aber in Lua können wir auch einfach einen String übergeben, der in einen Hash konvertiert wird. Wir werden oft sehen, dass Leute GetHashKey (GET_HASH_KEY) verwenden, aber wenn der Native als Hash angegeben wird, brauchen wir dies eigentlich nicht.
Wir führen einen Schleifenaufrufe an HAS_MODEL_LOADED durch, um zu überprüfen, ob das Laden erfolgreich war. Da dies eine Schleife ist und wir kooperativ Multitasking betreiben, müssen wir dem Spiel auch Zeit zum Ausführen geben - andernfalls wird das Laden nie beendet und das Spiel friert leider ein. Dafür ist der Wait-Aufruf gedacht - er wartet auf die angegebene Anzahl von Millisekunden und kehrt dann direkt zum Skript zurück.
Die Inkarnationen der Spieler werden durch ihren Ped identifiziert, was für "Fußgänger" steht. Dies ist ein GTA-Begriff und bedeutet normalerweise „alles, was lebt und Beine hat“. Wir verwenden PLAYER_PED_ID, um den Ped des lokalen Spielers (im Grunde derjenige, der diesen Befehl ausführt) abzurufen.
Nachdem wir den ped haben und in einer Variablen gespeichert haben, erhalten wir die Position des Spieler-ped mithilfe von GET_ENTITY_COORDS. Da ein Ped eine Einheit ist (dasselbe gilt für Fahrzeuge und einige andere Dinge), wird dieser Eingeborene verwendet, um seine Position zu ermitteln. Dieser native gibt wiederum einen Vector3 zurück, ähnlich wie der spawnPos zuvor definiert wurde.
Wir verwenden CREATE_VEHICLE, um ein Fahrzeug zu erstellen. In der Zwischenzeit haben wir einen Anruf getätigt, um mithilfe von GET_ENTITY_HEADING den Kurs des Spielers zu ermitteln, wodurch das Auto in die gleiche Richtung wie der Spieler spawnt. Das Richtig, Falsch ist eine Konvention bei Entitätserstellungs-Eingeborenen, um das Fahrzeug mit einem Netzwerkobjekt (wahr) zu erstellen, es jedoch nicht zu einem Missionsobjekt zu machen (falsch). Normalerweise möchten Sie das erstere, oder niemand anderes wird das Fahrzeug sehen - und du möchtest das letztere nicht, da wir kein vollständiges R * -Missionsskript schreiben.
Da wir jetzt einen Spieler und ein Fahrzeug haben, können wir SET_PED_INTO_VEHICLE verwenden, um den Spieler im Fahrzeug zu platzieren. Wie die Dokumentation zufällig sagt, ist -1 der Fahrersitz des Fahrzeugs.
Dafür verwenden wir SET_ENTITY_AS_NO_LONGER_NEEDED und SET_MODEL_AS_NO_LONGER_NEEDED.
Quelle: KLICK