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.