aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Metin2 NPC Diyalog: select ve confirm ile Dallanma

Metin2 npc diyalog akışı, oyuncunun bir NPC ile sohbet penceresini açtığı anda başlar ve doğru kurgulandığında küçük bir hikâye gibi hissettirir. Tek satır metin göstermek kolaydır; asıl iş, oyuncuya seçenekler sunup verdiği karara göre konuşmayı dallandırmaktır. Bu yazıda select ile çok seçenekli menüler, confirm ile evet/hayır onayları kurmayı ve bunları temiz, hatasız çalışan bir Lua quest'inde nasıl birleştireceğini adım adım anlatıyorum.

Diyaloğun temel iskeleti

Her NPC konuşması bir chat tetikleyicisiyle açılır. NPC'nin vnum'unu yazar, ona bir menü başlığı verir ve içeride say fonksiyonlarıyla metni satır satır dökersin.

quest koylu_diyalog begin
    state start begin
        when 9003.chat."Köylü ile konuş" begin
            say_title("İhtiyar Köylü")
            say("Hoş geldin gezgin.")
            say("")
            say("Buralarda işin ne?")
        end
    end
end

Burada 9003 NPC'nin vnum'u, say_title diyalog penceresinin üst başlığı, say ise gövde metnidir. Boş say("") satır arası boşluk bırakmak için kullanılır. Bu blok tek yönlüdür: oyuncu sadece okur ve "Kapat" der. Etkileşim eklemek için seçim mekanizmalarına geçmemiz gerekir.

select ile çok seçenekli menü

select, oyuncuya bir buton listesi gösterir ve seçtiği seçeneğin sıra numarasını (1'den başlar) döner. Dönen değeri bir değişkene alıp if / elseif ile dallandırırsın.

when 9003.chat."Köylü ile konuş" begin
    say_title("İhtiyar Köylü")
    say("Sana nasıl yardımcı olabilirim?")
    say("")
    local secim = select("Görev ver", "Eşya al", "Hikâyeni anlat", "Vazgeç")

    if secim == 1 then
        say("O zaman dinle: ormandaki kurtları temizle.")
    elseif secim == 2 then
        say("Maalesef satacak bir şeyim kalmadı.")
    elseif secim == 3 then
        say("Yıllar önce bu köy bambaşkaydı...")
    else
        say("Yolun açık olsun.")
    end
end

Dikkat edilecek noktalar: select en fazla pratik olarak 6-7 seçenek için rahattır, daha fazlası diyalog penceresine sığmaz. Son seçeneği her zaman bir "Vazgeç" çıkışı yapmak iyi bir alışkanlıktır; oyuncu menüde sıkışıp kalmaz. Dönen değeri mutlaka local bir değişkende sakla, çünkü ikinci bir select çağırırsan önceki değer kaybolur.

confirm ile evet/hayır onayı

Geri döndürülemez bir işlem (eşya silme, ışınlanma, yang harcama) yapmadan önce oyuncudan onay almak istersin. confirm("metin") tam da bunun içindir: oyuncuya bir "Evet / Hayır" penceresi açar ve onayladıysa true, reddettiyse false döner.

when 9003.chat."Şehre ışınlan" begin
    say_title("İhtiyar Köylü")
    say("Seni şehre göndereyim mi?")
    say("Bu 50.000 yang tutar.")
    say("")

    if confirm("Şehre ışınlanmak istiyor musun?") then
        if pc.get_money() >= 50000 then
            pc.change_money(-50000)
            pc.warp(469000, 964000)
        else
            say("Yeterli yangın yok.")
        end
    else
        say("Belki başka zaman.")
    end
end

confirm bir if koşulu içinde doğrudan kullanılabilir çünkü doğrudan boolean döner. Bazı sürümlerde varsayılan butonlar yerine kendi metnini koymak için confirm_with_button("soru", "Evet metni", "Hayır metni") da bulunur; ancak bunun varlığı kaynağına bağlı olduğundan, taşınabilir kalmak istiyorsan standart confirm ile devam et.

select ve confirm'i birlikte zincirlemek

Asıl güç, ikisini iç içe kullandığında ortaya çıkar. Oyuncu önce bir select menüsünden seçer, ardından kritik adımda confirm ile son kararını verir. Aşağıda bir ödül sandığı NPC'si örneği var:

when 9003.chat."Ödül sandığı" begin
    say_title("Gizemli Sandık")
    say("İçinden bir ödül seç, ama dikkatli ol.")
    say("Seçtikten sonra geri dönüş yok.")
    say("")
    local odul = select("Kılıç", "Zırh", "Yang", "Daha sonra")

    if odul == 4 then
        say("Sandık kapandı.")
        return
    end

    if not confirm("Seçiminden emin misin?") then
        say("Sandığın başında bir an düşündün.")
        return
    end

    if odul == 1 then
        pc.give_item2(11209, 1)
        say("Keskin bir kılıç kazandın!")
    elseif odul == 2 then
        pc.give_item2(11949, 1)
        say("Sağlam bir zırh kazandın!")
    elseif odul == 3 then
        pc.change_money(500000)
        say("500.000 yang kazandın!")
    end
end

Burada üç teknik birlikte çalışıyor: select dallanmayı belirliyor, erken return ile "vazgeç" durumunu temiz şekilde kapatıyoruz ve confirm ile geri döndürülemez ödülü vermeden önce son bir güvenlik kapısı koyuyoruz. return kullanmak, kodu derin if yuvalarından kurtarıp okunaklı tutar.

Metni dinamik hale getirmek

Sabit metinler hızla sıkıcılaşır. Oyuncunun adını, seviyesini veya envanterindeki eşya sayısını metne katmak için say içinde string birleştirme kullan. Lua'da metin birleştirme operatörü iki noktadır (..).

when 9003.chat."Selam ver" begin
    say_title("İhtiyar Köylü")
    say("Merhaba "..pc.get_name()..", seni görmek güzel.")
    say("Seviyen "..pc.get_level().." olmuş, hızlı ilerlemişsin.")
end

Bu sayede aynı diyalog her oyuncuya kişisel hissettirir. Sayısal değerleri (pc.get_level()) metne katarken Lua otomatik dönüştürme yapar, ayrıca tostring() çağırmana gerek kalmaz.

Sık yapılan hatalar ve ipuçları

  • select sonucunu kontrol etmeyi unutmak: oyuncu pencereyi ESC ile kapatabilir; her seçenek için bir dal ve bir de "vazgeç" çıkışı tanımla.
  • confirm'i sıradan if gibi yazıp parantezi unutmak: confirm(...) mutlaka bir metin argümanı ister, boş bırakma.
  • Çok uzun say zincirleri: 4-5 satırdan sonra oyuncuya wait() ile "Devam" düğmesi göster; aksi halde metin penceresi taşar.
  • Türkçe karakterler: quest dosyalarını sunucunun beklediği kodlamada (genelde UTF-8 veya ilgili locale) kaydet; yanlış kodlama diyalogda bozuk karakter olarak görünür.
  • Değişiklik sonrası quest'i derleyip yeniden yüklemeyi unutma; aksi halde game core eski metni göstermeye devam eder.

Sık Sorulan Sorular

select kaç seçeneğe kadar destekler?

Teknik bir sert sınır olmasa da diyalog penceresine pratikte 6-7 seçenek rahat sığar. Daha fazlasına ihtiyacın varsa seçenekleri kategorilere böl: ilk menüde grupları göster, seçilen gruba göre ikinci bir select aç. Bu hem daha temiz görünür hem de okunabilir kalır.

confirm penceresinin butonlarındaki metni değiştirebilir miyim?

Standart confirm sabit "Evet/Hayır" butonları kullanır. Bazı kaynaklarda butona kendi metnini koyabilen genişletilmiş bir sürüm bulunur, ama bu sürüme bağlıdır. Taşınabilirlik istiyorsan asıl soruyu say ile net yazıp confirm'i basit tutmak en güvenli yoldur.

select sonucunu doğrudan if içinde kullanabilir miyim?

Kullanabilirsin ama önerilmez. select menüyü gösterip değeri döner; aynı çağrıyı iki if dalında tekrarlarsan menü iki kez açılır. Bunun yerine sonucu bir local değişkene al, sonra o değişkeni karşılaştır.

NPC diyaloglarında takıldın mı? Sunucun için dallanan görev zincirleri, çok adımlı diyalog sistemleri veya menü kurgusu konusunda yardıma ihtiyacın varsa benimle iletişime geç — birlikte kuralım.

Bu kategorideki tüm yazılar →

Devamı için