Metin2 switchbot sistemi, bir eşyanın bonuslarını (attribute) tek tek elle yenilemek yerine, istenen kombinasyon çıkana kadar otomatik olarak değiştiren bir mekanizmadır. Oyuncu bir hedef belirler — örneğin "kritik %15 ve ortalama hasar %10" — sistem de değişim eşyasını harcayıp bonusları tekrar tekrar atar, eşleşme yakalandığında durur. Bu rehberde böyle bir sistemi sunucu tarafında, Lua quest motoruyla nasıl güvenli ve dengeli kurduğunu adım adım anlatıyorum; amaç hazır kod kopyalamak değil, mantığı kavrayıp kendi sunucuna uyarlayabilmen.
Switchbot tam olarak neyi otomatikleştirir?
Metin2'de bir eşyanın bonusları attribute olarak tutulur: her satırda bir tür (kritik şansı, delici vuruş, canavarlara hasar…) ve bir değer bulunur. Oyuncu klasik yöntemde bir "bonus değiştirme" eşyası kullanır, tüm satırlar yeniden rastgele atanır, beğenmezse tekrar dener. Bu, yüzlerce tıklama gerektiren sıkıcı bir döngüdür.
Switchbot bu döngüyü server tarafına alır: oyuncu hedefini bir kez seçer, sistem her adımda bir değişim eşyası harcayıp bonusları yeniler ve sonucu hedefle karşılaştırır. Avantajları net:
- Adil ve denetlenebilir — rastgelelik ve maliyet sunucuda hesaplanır, istemciye güvenmez.
- Suistimale kapalı — eşya stoğu, deneme limiti ve cooldown tek yerden kontrol edilir.
- Loglanabilir — kim, neyi, kaç denemede değiştirdi; hepsi kayda geçer.
Bonus değişiminin temeli: change_attribute
Sistemin kalbi, bir eşyanın tüm bonus satırlarını yeniden rastgele atan motor fonksiyonudur. Çoğu source'ta bu çağrı item.change_attribute() olarak geçer ve "bonus değiştirme" eşyasının yaptığı işin aynısını quest içinden yapar. Önce işlem yapılacak eşyayı seçmen gerekir:
-- hedef esyayi VID ile sec, sonra bonuslarini yenile
item.select(item_vid)
item.change_attribute()
Yenilemeden sonra mevcut bonusları okuyup hedefle karşılaştırırız. Okuma fonksiyonunun tam adı source revizyonuna göre değişebilir (ör. item.get_attribute(i) türü, değer ikilisi döndürür); önemli olan, her satırın (tür, değer) çifti olarak elde edilebilmesidir. Mantığı buna göre kurarsan, fonksiyon adı sende farklı olsa bile sistem aynen çalışır.
Mimari: sunucu quest'i mi, istemci botu mu?
"Switchbot" adı bazen istemci tarafında çalışan, eşyaya otomatik tıklayan bir makro/bot anlamında da kullanılır. Bu yaklaşımı önermiyorum. İstemci botu paket taklidi yapar, anti-hack tarafından yakalanabilir, sunucuda denetlenemez ve oyuncular arası adaleti bozar. Doğru çözüm, sistemi tamamen sunucu tarafına almaktır:
- Tek kaynak doğruluk — bonus, maliyet ve limitler server'da; istemci sadece arayüz gösterir.
- Performans güvenliği — döngü blok etmeden, zamanlayıcıyla adım adım ilerler.
- Şeffaflık — her deneme bir eşya tüketir, ekonomiye gerçek bir maliyet bağlanır.
Bu yüzden sistemi bir quest olarak kurar, otomatik döngüyü ise server_timer ile parçalara böleriz; böylece "istenen bonus çıkana kadar" beklerken sunucu kilitlenmez.
Çekirdek döngüyü server_timer ile kurmak
Oyuncu değişim eşyasını kullandığında, hedef eşyanın VID'sini ve seçtiği hedef bonusu oyuncu flag'lerine yazar, sonra zamanlayıcıyı başlatırız. Her tetiklenişte zamanlayıcı bir deneme yapar: eşya var mı diye bakar, bir tane harcar, bonusları yeniler ve eşleşmeyi kontrol eder.
quest switchbot begin
state start begin
-- 71109: bonus degistirme tasi (ornek vnum)
when 71109.use begin
local target_vid = pc.getqf("sb_target_vid")
if target_vid == 0 then
say("Once degistirilecek esyayi sec.")
return
end
-- denemeleri sifirla ve dongu sayacini baslat
pc.setqf("sb_tries", 0)
server_timer("sb_tick", 1, get_server_timer_arg())
end
when sb_tick.server_timer begin
local change_vnum = 71109
local tries = pc.getqf("sb_tries")
-- elinde degisim esyasi var mi?
if pc.count_item(change_vnum) < 1 then
pc.notice("Degisim esyan bitti. "..tries.." deneme yapildi.")
return
end
if tries >= 200 then
pc.notice("Deneme limitine ulasildi (200).")
return
end
pc.remove_item(change_vnum, 1)
pc.setqf("sb_tries", tries + 1)
item.select(pc.getqf("sb_target_vid"))
item.change_attribute()
if sb_match_target() then
pc.notice("Hedef bonus yakalandi! Toplam "..(tries+1).." deneme.")
return
end
-- eslesme yok: kisa bekleyip tekrar dene
server_timer("sb_tick", 1, get_server_timer_arg())
end
end
end
Buradaki kilit fikir, döngüyü while ile değil zamanlayıcıyla kurmaktır. Her adım ayrı bir server_timer tetiğidir; aralarına 1 saniye koyduğumuz için yüzlerce deneme bile sunucuyu kilitlemez ve diğer oyuncular etkilenmez. Hızı dengeye göre ayarlayabilir, daha pahalı sunucularda aralığı büyütebilirsin.
Hedef bonusu eşleştirme mantığı
Sistemin beyni, "şu anki bonuslar hedefe uyuyor mu?" sorusunu yanıtlayan yardımcı fonksiyondur. Oyuncunun seçtiği hedef satırlarını flag'lerde tutar, her yenilemeden sonra eşyadaki satırları tarayıp tür eşleşiyor ve değer en az istenen kadar mı diye bakarsın:
-- ornek: APPLY_CRITICAL_PCT turunde en az %12 hedeflensin
function sb_match_target()
local want_type = pc.getqf("sb_want_type") -- apply turu
local want_value = pc.getqf("sb_want_value") -- minimum deger
-- esyadaki tum bonus satirlarini tara
for i = 0, 6 do
local atype, avalue = item.get_attribute(i)
if atype == want_type and avalue >= want_value then
return true
end
end
return false
end
Bu örnek tek bonus hedefler; iki ya da üç bonusu birden istemek için hedef listesini genişletip her birini ayrı kontrol et ve hepsi sağlanıyorsa true döndür. Apply türlerini (ör. APPLY_CRITICAL_PCT, APPLY_PENETRATE_PCT, APPLY_ATTBONUS_MONSTER) sabit isimleriyle kullanmak kodu okunur kılar. Oyuncuya hedefi seçtirmek için klasik bir NPC diyaloğu ya da basit bir select menüsü yeterlidir.
Dengeleme: maliyet, limit, cooldown ve log
Bir switchbot, sınırsız ve bedavaysa ekonomiyi anında çökertir; herkes mükemmel itemi dakikalar içinde basar. Sistemi adil tutan asıl iş, dengelemedir:
- Gerçek maliyet: her deneme bir değişim eşyası (ve istersen bir miktar yang) tüketsin. Maliyet, mükemmel sonucu "kazanılmış" hissettirecek kadar anlamlı olmalı.
- Deneme tavanı: tek seferde en fazla N deneme (örnekte 200). Tavan, sonsuz döngüyü ve sunucu yükünü engeller.
- Cooldown: bir oturum bittikten sonra kısa bir bekleme koy;
pc.setqf("sb_cd", get_global_time() + 60)ile kontrol et. - Loglama: her başarılı yakalamada oyuncu adı, eşya, hedef ve deneme sayısını veritabanına/log dosyasına yaz; suistimal ve hata ayıklama için kritiktir.
Ayrıca güvenlik kontrollerini ihmal etme: işlem boyunca hedef eşyanın hâlâ envanterde olduğunu doğrula (oyuncu satmış/atmış olabilir), +0 bir eşyada bonus yoksa kullanıcıyı uyar ve aynı anda iki switchbot oturumunun başlamasını flag ile engelle. Bu küçük kontroller, canlı sunucuda "boş eşyaya yang yatırdım" türü şikayetlerin önüne geçer.
Sık Sorulan Sorular
Switchbot bonus değerini garanti eder mi?
Hayır, garanti etmez ve etmemeli. Sistem yalnızca change_attribute'u otomatik tekrar eder; her deneme bağımsız ve rastgeledir. Switchbot sadece "elle yüzlerce kez tıklama" zahmetini kaldırır, şansı değiştirmez. Garanti istiyorsan o ayrı bir özelliktir (ör. bonus kilitleme) ve dengesi çok daha hassastır.
Bu sistem sunucuyu yorar mı?
Döngüyü while yerine server_timer ile adımlara böldüğün sürece hayır. Her deneme arasına kısa bir aralık koymak işlemi yaymaya yeter; deneme tavanı da en kötü senaryoyu sınırlar. Asıl yük, döngüyü tek karede çalıştırmaya kalkmaktan doğar — bundan kaçın.
İstemci tarafı bir switchbot daha mı kolay?
Kısa vadede evet, ama uzun vadede başını ağrıtır: anti-hack tarafından engellenebilir, denetlenemez ve oyuncular arası adaleti bozar. Sistemi sunucuda kurmak biraz daha emek ister ama güvenli, şeffaf ve sürdürülebilirdir.
Sunucun için dengeli ve sömürüye kapalı bir switchbot mu istiyorsun? Hedef seçiminden maliyet ve limitlere, loglamadan arayüze kadar sistemi baştan sona kurup test edebilirim. Projeni konuşmak için benimle iletişime geç.