FiveM için komut dosyası yazmaya başlamak, çok çeşitli olasılıklar ve seyrek yayılmış dokümantasyon göz önüne alındığında biraz zor olabilir. Bu hızlı ve basit kılavuzda, Lua'da hızlı bir kaynakla nasıl başlayacağınızı göstermeye çalışacağız.

Resources

Bir kaynak, basitçe, tek tek başlatılabilen, durdurulabilen ve yeniden başlatılabilen bir dosya koleksiyonudur. Sunucu-veri klasörünüz (zaten bir sunucu kurduğunuzu varsayarsak), içinde resourceszaten birkaç kaynak bulunan bir klasöre sahip olmalıdır .

Kendi kaynaklarınız üzerinde çalışıyorsanız, muhtemelen bir resources/[local]dizin oluşturmak isteyeceksiniz - bu, sunucu-veri kökünü güncellerken Git tarafından göz ardı edilecektir. Orada, sistemi resources/[local]/mymodekullanarak bir gametype oluşturduğumuz için bir klasör oluşturacağız mapmanager.

Araçlarla Yani bir Windows geliştirme sistemini varsayarak artık böyle bir klasör olması gerekir: C:\your\path\to\cfx-server-data\resources\[local]\mymode. Bu klasörü bundan mymodesonra arayacağız .

Manifest dosyaları

Bir kaynak klasörünün (bunu mymodeyukarıda yaptığınızı biliyorsunuz ) FiveM tarafından tespit edilmesi için bir bildirime ihtiyacı olacaktır. Bu bir oyun türü olduğundan, bunun bir oyun türü mapmanagerolduğu gerçeğini öğretmek için bazı ekstra bilgilere de ihtiyacı olacaktır .

Klasörünüzde adlı bir dosya oluşturun fxmanifest.lua(bu her zaman Lua'dır, daha sonra C # / JS'de komut dosyaları yazacak olsanız bile) mymode. İçine, favori metin düzenleyicinizi kullanarak aşağıdaki metni yerleştirin:

fx_version 'cerulean'
game 'gta5'

author 'An awesome dude'
description 'An awesome, but short, description'
version '1.0.0'

resource_type 'gametype' { name = 'My awesome game type!' }

client_script 'mymode_client.lua'

Yapacağınız herhangi bir yeni kaynak muhtemelen en son oyun özelliklerini isteyecektir. Bunun fx_versioniçin var. Daha fazlasını öğrenmeye ihtiyaç duyarsanız, bu dokümantasyon sitesinde başka bir yerde okuyabilirsiniz. Bu kaynağın gta5, rdr3 veya için commonmi olduğunu belirtmek için gamedeğişkeni kullanmalısınız .

resource_typeÖte yandan, söyler mapmanagerbu, aslında, bir oyun türü olduğunu ve bu deniyor o "Benim harika oyun türü!" . Yalnızca 'bağımsız' bir eklenti kaynağı oluşturuyorsanız, muhtemelen bir resource_typesatır eklemek istemezsiniz .

Son olarak, client_scriptkomut dosyası çalışma zamanına istemcinin adlı bir komut dosyası yüklemesi gerektiğini belirtir mymode_client.lua. Bu bir JS betiği olsaydı, derdi mymode_client.jsya da C # olsaydı, muhtemelen olurdu MyModeClient.net.dll, ama şimdilik Lua'ya öğretiyoruz, o yüzden unut gitsin.

Son olarak, biz adlı bir dosya yapmalıdır mymode_client.luaiçinde mymodekaynak klasör şey.

Kaynak bildirim dosyaları hakkında daha fazla bilgi edinmek için kaynak bildirimi referansına bakın .

Kod yazma

Bu dosyaya şu içeriği koyalım:

local spawnPos = vector3(686.245, 577.950, 130.461)

AddEventHandler('onClientGameTypeStart', function()
    exports.spawnmanager:setAutoSpawnCallback(function()
        exports.spawnmanager:spawnPlayer({
            x = spawnPos.x,
            y = spawnPos.y,
            z = spawnPos.z,
            model = 'a_m_m_skater_01'
        }, function()
            TriggerEvent('chat:addMessage', {
                args = { 'Welcome to the party!~' }
            })
        end)
    end)

    exports.spawnmanager:setAutoSpawn(true)
    exports.spawnmanager:forceRespawn()
end)

Bu zor bir sorudur, özellikle birinci sınıf işlevler kavramına alışkın değilseniz. Global / yerel işlevleri kullanarak farklı bir şekilde de yazabilirsiniz - ama bu biraz tuhaf.

Bunu açıklamalı bir sürümle yavaş yavaş inceleyelim.

-- define a local variable called `spawnPos` with a coordinate somewhere on the map
-- Lua in FiveM (through CfxLua) supports first-class vectors, which in this case can be accessed using .x, .y and .z.
local spawnPos = vector3(686.245, 577.950, 130.461)

-- add an event handler for the (local) event called 'onClientGameTypeStart'.
-- it takes no arguments in this case (in Lua you can omit arguments), since our resource is a game type and you can only run one at once,
-- that means this will basically run when we start ourselves on the client. nice!
AddEventHandler('onClientGameTypeStart', function()
    -- set an automatic spawn callback for the spawn manager.
    -- normally, this works using hardcoded spawn points, but since this is a scripting tutorial, we'll do it this way.
    --
    -- the spawn manager will call this when the player is dead, or when forceRespawn is called.
    exports.spawnmanager:setAutoSpawnCallback(function()
        -- spawnmanager has said we should spawn, let's spawn!
        exports.spawnmanager:spawnPlayer({
            -- this argument is basically a table containing the spawn location...
            x = spawnPos.x,
            y = spawnPos.y,
            z = spawnPos.z,
            -- ... and the model to spawn as.
            model = 'a_m_m_skater_01'
        }, function()
            -- a callback to be called once the player is spawned in and the game is visible
            -- in this case, we just send a message to the local chat box.
            TriggerEvent('chat:addMessage', {
                args = { 'Welcome to the party!~' }
            })
        end)
    end)

    -- enable auto-spawn
    exports.spawnmanager:setAutoSpawn(true)

    -- and force respawn when the game type starts
    exports.spawnmanager:forceRespawn()
end)

İstemci ve sunucu komut dosyaları arasındaki farka hızlı bir şekilde değinmek: FiveM'de yapacağınız şeylerin çoğu istemci komut dosyaları kullanılarak yapılacaktır, çünkü mevcut sürümlerde sunucu komut dosyalarındaki oyun işlevselliği ile etkileşim yoktur . Sunucu komut eylemler meydana metne sahip kullanılmalıdır karşısında (istemci / sunucu olayları kullanarak) istemcileri ve böyle bir kalıcı veritabanında saklanması / yükleme şeyler gibi çeşitli eylemler için bir 'güven kaynağı' sağlamaktır.

Bir oyuncunun doğması neredeyse tamamen oyun etkileşimi olduğundan, bu müşteri tarafında olur. Katılan her oyuncunun , aralarında paylaşılan değişkenler veya bağlam olmadan bilgisayarlarında çalışan her istemci komut dosyasının yerel bir örneği olacaktır .

Bunu çalıştırıyorum

Muhtemelen bu küçük örneği çalıştırmayı umuyorsunuz - umarım zaten çalışan bir FXServer örneğiniz vardır - yoksa bunun için kılavuzu izleyin.

FXServer'ı başlattıktan sonra refresh, konsoldaki komutu yürütün . Bu fxmanifest.lua, yüklediğiniz her kaynak için her bir dosyayı yeniden okuyacaktır , çünkü muhtemelen sunucuyu yeni başlattınız, bu gerçekten gerekli değildir, ancak sunucu zaten çalışıyorsa, bu sadece yapılacak İyi Bir Fikirdir.

Son olarak, start mymodekonsolda çalıştırın ve localhostgeliştirici modunda FiveM istemcisinin kullanışlı düğmesini kullanarak sunucunuza bağlanın (veya localhostdoğrudan bağlantı sekmesine girin veya varsayılan bağlantı noktasını kullandıysanız, FiveM'nin kurulu olduğu bilgisayardaki bu kullanışlı bağlantıya tıklayın) ).

Oyun yüklendikten sonra, kendinizi bir yerde doğarken görmelisiniz - umarım büyük bir sahnede!

Oyunu çalışır durumda tutun (ve belki oyun seçeneklerinde onu kenarlıksız veya pencereli moda ayarlayın) ve Alt-Tab kod düzenleyicinize geri dönün - yapacak daha çok işimiz var!

Kaynakları yeniden başlatma

Kaynağınızı yinelemek için oyununuzu ve sunucunuzu kapatıp her ikisini de yeniden başlatmak aptalca. Elbette kaynağınızı da yeniden başlatabilirsiniz .

Farklı bir yumurtlama noktası deneyelim.

Yerine spawnPoshat (birincisi) mymode/mymode_client.luaaşağıdaki ile:

local spawnPos = vector3(-275.522, 6635.835, 7.425)

Ardından, sunucu konsolunuzda sihirli komutu yürütün restart mymode. Sohbet kutunuzda belirtilen 'Partiye hoş geldiniz! ~' İfadesini (tekrar) görmeli ve sahne yerine bir iskele üzerinde son bulmalısınız.

Bunun üzerine genişleyen

Muhtemelen daha fazlasını yapmak isteyeceksiniz. Bunun için, yerli halkla hiçbir ilgisi olmayan ve aslında 'oyun tanımlı komut dosyası işlevleri' için bir R * etiketi olan yerlileri nasıl çağıracağınızı öğrenmeniz gerekecek . Yerlileri doğru şekilde aramakla ilgili pek çok karmaşıklık var - tam bir referans için, bunun için özel bölüme bakın - ancak şimdilik basit başlayacağız.

Aptalca bir şekilde 'tekrar bu kinaye', bir araba ortaya çıkaracak bir komut vereceğiz. Yerel olarak. Çünkü sunucu başlarken kimse umursamıyor.

Sayfanızın altına mymode_client.luaşu kodu ekleyin:

RegisterCommand('car', function(source, args)
    -- TODO: make a vehicle! fun!
    TriggerEvent('chat:addMessage', {
        args = { 'I wish I could spawn this ' .. (args[1] or 'adder') .. ' but my owner was too lazy. :(' }
    })
end, false)

Zaten başlayarak, bir işleve çağrı görüyoruz. Bu işlevi tanımlamadık. Evet, biz (FiveM ekibinde olduğu gibi) yaptık, ama bu harika yazılmış bir rehber harikası boyunca size, okuyucuya rehberlik ederken değil. Bu, başka bir yerden gelmesi gerektiği anlamına gelir!

Ve tahmin et ne oldu, aslında REGISTER_COMMAND ! Bu bağlantıya tıkladığınızda bu yerel için belgelere yönlendirileceksiniz. Biraz şuna benziyor:

// 0x5fa79b0f
// RegisterCommand
void REGISTER_COMMAND(char* commandName, func handler, BOOL restricted);

Biz esas olarak ikinci satırdaki isme ( RegisterCommandyukarıdaki Lua kodunda kullanıldığı gibi) ve argümanlara önem vereceğiz .

Gördüğünüz gibi, ilk argüman komut adıdır . İkinci bağımsız değişken, komut işleyicisi olan bir işlevdir ve üçüncü bağımsız değişken, kısıtlı bir komut olup olmayacağını belirten bir mantıksaldır .

İşlevin kendisi source, yalnızca sunucuda çalışıyorsanız gerçekten önemli olan bir bağımsız değişken alır (bu, komutu giren oyuncunun istemci kimliği, sahip olunması gerçekten yararlı bir şey olacaktır) ve bir dizi argsbunlar temelde varoluşu veya varoluşu /car zentornoyapmak gibi komuttan sonra girdiğiniz şeylerdir .args{ 'zentorno' }/car zentorno unused{ 'zentorno', 'unused' }

Sohbet kutusuna bir mesajın nasıl yazdırılacağını zaten bildiğimiz için, aracın adını konsola yazdırarak bir araç yaratmış gibi yapacağız.

Kaynağı yeniden başlatalım ve ne olacağını görelim. Çalıştırın restart mymode, ardından istemci sohbet kutusuna (varsayılan T) yazın /car zentorno. Sohbet kutusunun bunu uygulayamayacak kadar tembel olduğunuzdan şikayet ettiğini göreceksiniz. Onlara kesinlikle tembel olmadığınızı göstereceğiz ve bunu şimdi uygulayacağız.

Bir araba çıkma yeri uygulama

Bu çok fazla standart kod ve biz bunu doğru şekilde yapmak isteyeceğiz çünkü pek çok insan bu örneği kopyalayacak, bu yüzden biraz bunaltıcı görünebilir.

Temel olarak yapacağımız şey:

  1. Geçilen modelin geçerli olup olmadığını kontrol edin. Bu isimde bir araç yokken bir 'patates' yaratmaya çalışmak hiç eğlenceli değil.
  2. Modeli yükleyin. Kullandığınız her modeli açıkça yönetmeniz gerekir, bunlar orijinal olarak R * tarafından tanımlanan kurallardır.
  3. Modelin yüklenmesini bekleyin. Evet, oyun eşzamansız olarak çalışmaya devam edecek.
  4. Oynatıcının yüklendikten sonra nerede olduğunu bulun.
  5. Aracı yaratın! Harika, sonunda yaratıcı olacaksın.
  6. Oynatıcıyı araca koyun.
  7. Temizleyin, çünkü biz düzenli insanlarız ve.

Haydi gidelim!

Biraz önce yapıştırdığınız biti bununla değiştirin ve endişelenmeyin, siz iki kez 'tembel' demeden önce açıklayacağız:

RegisterCommand('car', function(source, args)
    -- account for the argument not being passed
    local vehicleName = args[1] or 'adder'

    -- check if the vehicle actually exists
    if not IsModelInCdimage(vehicleName) or not IsModelAVehicle(vehicleName) then
        TriggerEvent('chat:addMessage', {
            args = { 'It might have been a good thing that you tried to spawn a ' .. vehicleName .. '. Who even wants their spawning to actually ^*succeed?' }
        })

        return
    end

    -- load the model
    RequestModel(vehicleName)

    -- wait for the model to load
    while not HasModelLoaded(vehicleName) do
        Wait(500) -- often you'll also see Citizen.Wait
    end

    -- get the player's position
    local playerPed = PlayerPedId() -- get the local player ped
    local pos = GetEntityCoords(playerPed) -- get the position of the local player ped

    -- create the vehicle
    local vehicle = CreateVehicle(vehicleName, pos.x, pos.y, pos.z, GetEntityHeading(playerPed), true, false)

    -- set the player ped into the vehicle's driver seat
    SetPedIntoVehicle(playerPed, vehicle, -1)

    -- give the vehicle back to the game (this'll make the game decide when to despawn the vehicle)
    SetEntityAsNoLongerNeeded(vehicle)

    -- release the model
    SetModelAsNoLongerNeeded(vehicleName)

    -- tell the player
    TriggerEvent('chat:addMessage', {
		args = { 'Woohoo! Enjoy your new ^*' .. vehicleName .. '!' }
	})
end, false)

Bu, çok sayıda yerli kullanır. Birkaçını birbirine bağlayıp zor kısımları açıklayacağız.

Adım 1: Doğrulama

Araç adını kontrol etmekle başladık. Eğer öyleyse nil(yani, mevcut değilse), varsayılan olarak adder. Her iki durumda da bir değişkende saklanır.

Ardından IS_MODEL_IN_CDIMAGE kullanarak aracın CD görüntüsünde olup olmadığını kontrol ederiz . Bu temelde 'bu oyuna kayıtlı mı' anlamına gelir. IS_MODEL_A_VEHICLE kullanan bir araç olup olmadığını da kontrol ediyoruz . Kontrollerden biri başarısız olursa, oyuncuya söyler ve komuttan geri döneriz.

Adım 2: Modeli yükleme

Şimdi, gerçek araç modelini yüklemek için REQUEST_MODEL'i çağırıyoruz . Bu yerel bir Hashargüman alır , ancak Lua'da sadece bir dizeyi de iletebilirsiniz ve bu bir karmaya dönüştürülür. Sık sık insanların GetHashKeyGET_HASH_KEY ) kullandığını görürsünüz , ancak eğer yerel, a alıyor olarak belirtilmişseHash , aslında buna ihtiyacınız yoktur.

3. Adım: Modelin yüklenmesi bekleniyor

Yüklemenin başarılı olup olmadığını kontrol etmek için HAS_MODEL_LOADED çağrılarını döngüye alıyoruz . Bu bir döngü olduğundan ve işbirliği içinde çoklu görev yaptığımız için, oyuna da çalışması için zaman vermeniz gerekecek - aksi takdirde yükleme asla bitmeyecek ve oyun maalesef donacaktır. Yani ne Waitçağrı içindir - bu belli bir milisaniye kadar bekler, sonra senaryo içine doğru geri döner.

Model yüklendikten sonra devam edeceğiz.

4. Adım: Oyuncunun pozisyonunu almak

Oyuncuların fiziksel enkarnasyonları, ped"yaya" nın kısaltması olan kendileriyle tanımlanır . Bu bir GTA terimidir ve genellikle 'yaşayan ve bacakları olan her şey' anlamına gelir. Oyuncunun pedini yerel (temelde bu komutu kim çalıştırıyorsa) almak için PLAYER_PED_ID kullanıyoruz .

Ped'e sahip olduktan ve onu bir değişkene kaydettikten sonra, GET_ENTITY_COORDS kullanarak ped oyuncunun konumunu alırız . Ped bir varlık olduğu için (aynı şey araçlar ve diğer birkaç şey için de geçerlidir), bu kişi konumlarını almak için kullanılır. Bu yerli, yine, bir döner Vector3şekline benzer, spawnPosdaha önce tanımlandı.

Adım 5: Aracın oluşturulması

Bir araç yaratmak için CREATE_VEHICLE kullanıyoruz . Bu arada, GET_ENTITY_HEADING kullanarak oyuncunun yönünü almak için gizlice bir çağrı yaptık , bu da arabanın oyuncuyla aynı yöne bakmasını sağlıyor.

true, falseVarlık oluşturma yerlileri bir kongre bir ağ nesnesi (ile araç yaratmaktır true), ancak bunu bir misyon nesne yapmaz ( false). Genellikle ilkini istersiniz veya başka hiç kimse aracı görmez - ve tam bir R * görev senaryosu yazmadığınız için ikincisini istemezsiniz.

Adım 6: Oynatıcıyı araca yerleştirme

Şu anda bir pedimiz ve bir aracımız olduğu için, ped'i araca yerleştirmek için SET_PED_INTO_VEHICLE kullanabiliriz . Belgelerin dediği gibi, -1aracın sürücü koltuğu.

7. Adım: Temizleme

Oyun, kendi peşinizi temizlemenizden hoşlanıyor ve bu senaryoda artık araç veya modelle hiçbir şey yapmadığımız için oyunun yönetmesine izin vereceğiz. Bu, SET_ENTITY_AS_NO_LONGER_NEEDED ve SET_MODEL_AS_NO_LONGER_NEEDED için kullandığımız şeydir .

Son olarak, oyuncuya yeni aracının keyfini çıkarmasını söyleriz.

Bunu çalıştırıyorum

Sunucu konsolunuzda refresh; restart mymode(evet, noktaları noktalı virgüllerle bölebilirsiniz) ve /car voltic2oyun istemcisinde deneyin (şimdiye kadar yeniden doğmaktan gerçekten sıkılmış olmalı). Artık kendi Rocket Volticinize sahip olacaksınız!

Sunucu komut dosyaları

Muhtemelen sunucuyla etkileşime giren komut dosyaları da yazmak isteyeceksiniz. Bu bölüm hala yazılacak. :-(


Fivem Oyun Sunucunuzu kurmadan önce bir fivem oyun sunucusuna sahip olmanız gerektiğini unutmayın. Fivem Oyun Sunucusu paketlerimizi incelemek için tıklayın.