Metin2 beceri.lua ile Hasar ve Performans Optimizasyonu
Metin2 sunucu yönetiminde, oyunun kalbi veritabanı (SQL) ise, sinir sistemi Lua (Quest) dosyalarıdır. Genellikle "Npc'den P yapma" işlemi basit bir script gibi görülse de, binlerce oyuncunun aynı anda yetenek kullandığı, savaştığı ve ışınlandığı bir ortamda beceri.lua dosyasının yapısı, oyunun "akıcılığını" ve "hasar tutarlılığını" (Damage Stability) doğrudan etkiler.
Bir oyuncunun "Ekranda vurdum görünüyor ama hasar işlemiyor" (Miss/Sync Loss) şikayetinin arkasında, genellikle optimize edilmemiş quest dosyalarının yarattığı mikrosaniye bazlı sunucu gecikmeleri (Quest Lag) yatar. Bu makalede, skill_proto tablosundaki matematiksel formüllerin kusursuz çalışması için beceri.lua tarafında yapılması gereken mimari optimizasyonları inceleyeceğiz.
Geleneksel Yöntemlerin Yarattığı "Hayalet Hasar" Sorunu
Eski nesil server dosyalarında (2010-2014 dönemi yaygın fileslar), yetenek yönetimi uzun if-elseif-else bloklarıyla yapılırdı.
Örneğin, klasik bir P NPC kodu şöyledir:
if pc.get_job() == 0 and pc.get_skill_group() == 1 then -- Bedensel
pc.set_skill_level(1, 59)
-- ... alt alta 6 satır
elseif pc.get_job() == 0 and pc.get_skill_group() == 2 then -- Zihinsel
-- ... alt alta 6 satır
-- ... ve diğer 8 sınıf için devam eder
Bu Yapı Neden Hasarı Bozar?
Sunucu tarafında (Server-Side), her oyuncu bu Npc'ye tıkladığında veya bir "yetenek sıfırlama" parşömeni kullandığında, işlemci bu satırları tek tek okur. Anlık 2000 oyuncunun olduğu bir sunucuda, bir lonca savaşı sırasında bu scriptin tetiklenmesi I/O darboğazı yaratır.
Bu darboğazın sonucu şudur:
Veritabanı Gecikmesi:
pc.set_skill_levelkomutu MySQL'e geç ulaşır.Senkronizasyon Hatası: Oyuncu istemcide (Client) yeteneğini P görür, ancak sunucu o anki yoğunluktan dolayı veritabanındaki seviyeyi güncelleyememiş olabilir.
Sonuç: Oyuncu "Hava Kılıcı"nı yakar, ancak sunucu bunu hala G1 seviyesinde algılar.
skill_proto'dakiszMasterBonusPolyformülü maksimum seviyeden değil, daha düşük seviyeden hesaplanır. Oyuncu düşük vurur ve oyunun "bozuk" olduğunu düşünür.
Çözüm: "Lookup Table" (Arama Tablosu) Mimarisi
Modern ve optimize bir Metin2 altyapısında, yetenek yönetimi dinamik tablolarla yapılır. Bu yöntem, işlemci yükünü %90 oranında azaltır ve hasar hesaplamalarının anlık olarak veritabanına işlenmesini garanti eder.
Matematiksel Grup Hesaplaması
Metin2'de karakter sınıfları (Job ID) 0 ile 7 arasındadır. Ancak her sınıfın iki alt grubu (Skill Group) vardır. Bu karmaşayı çözmek için if kullanmak yerine matematiksel bir indeksleme kullanmalıyız:
Formül: (Job ID * 2) + (Skill Group - 1)
Bu formül bize şu indeksleri verir:
Bedensel Savaşçı: 0
Zihinsel Savaşçı: 1
Yakın Dövüş Ninja: 2
Uzak Dövüş Ninja: 3
... ve devam eder.
Optimize Edilmiş Tam Kod Yapısı
Aşağıdaki kod bloğu, hem P verme işlemini, hem pasif yetenekleri (Kombo vb.) hem de "At Becerilerini" tek seferde, gecikmesiz işler.
quest skill_optimizer begin
state start begin
function SetPerfectSkills()
-- Karakterin meslek ve grup bilgisini al
local job = pc.get_job()
local group = pc.get_skill_group()
-- HATA KONTROLÜ: Grup seçmemiş oyuncuya skill verilirse karakter buga girer
if group == 0 then
syschat("Sistem: Önce bir eğitimciye gidip beceri grubu seçmelisiniz.")
return false
end
-- Yetenek Haritası (Skill Vnum Listesi)
local skill_map = {
[0] = {1, 2, 3, 4, 5, 6}, -- Bedensel
[1] = {16, 17, 18, 19, 20, 21}, -- Zihinsel
[2] = {31, 32, 33, 34, 35, 36}, -- Bıçakçı
[3] = {46, 47, 48, 49, 50, 51}, -- Okçu
[4] = {61, 62, 63, 64, 65, 66}, -- Büyülü Silah
[5] = {76, 77, 78, 79, 80, 81}, -- Kara Büyü
[6] = {91, 92, 93, 94, 95, 96}, -- Ejderha Gücü
[7] = {106, 107, 108, 109, 110, 111} -- İyileştirme
}
-- Matematiksel İndeksleme
local target_index = (job * 2) + (group - 1)
-- Eğer tablo içinde bu indeks varsa işlemi uygula
if skill_map[target_index] then
-- 1. Aktif Yetenekleri P Yap (Level 59)
for _, skill_vnum in ipairs(skill_map[target_index]) do
pc.set_skill_level(skill_vnum, 59)
end
-- 2. Pasif Yetenek Optimizasyonu (Kritik Öneme Sahip)
-- Kombo (122): 2 yapılmazsa DPS (Saniye başı hasar) %30 düşer.
pc.set_skill_level(122, 2)
-- Liderlik (121): P yapılmazsa grup bonusları (saldırı değeri) çalışmaz.
pc.set_skill_level(121, 40)
-- Dönüşüm (129): Boss keserken hasar maksimizasyonu için şarttır.
pc.set_skill_level(129, 40)
-- Madencilik (124) ve At Çağırma (131)
pc.set_skill_level(124, 40)
pc.set_skill_level(131, 10)
-- 3. At Yetenekleri (Asker At Kitabı varsa)
if pc.get_horse_level() == 21 then
pc.set_skill_level(137, 20) -- At Yürüyüşü
pc.set_skill_level(138, 20) -- At Güç Dalgası
pc.set_skill_level(139, 20) -- At Saldırısı
end
syschat("Sistem: Tüm yetenekler ve pasif bonuslar optimize edildi.")
return true
else
syschat("Hata: Bilinmeyen beceri grubu.")
return false
end
end
when 20094.chat."Becerileri Sıfırla ve P Yap" begin
-- Fonksiyonu çağır
skill_optimizer.SetPerfectSkills()
-- Affect Temizliği (Önemli)
-- Biyolog görevleri hariç tüm geçici etkileri temizleyip tekrar yüklemek gerekir.
-- Ancak affect.remove_all() tehlikelidir, sadece skill affectleri silinmeli.
-- Bu detay genelde C++ (Source) tarafında handle edilir.
end
end
end
Pasif Yeteneklerin "Gizli" Hasar Etkisi
Geliştiricilerin skill_proto ayarlarken gözden kaçırdığı en büyük detay Kombo (Combo) yeteneğidir.
Sorun: Eğer
beceri.luadosyanız oyuncuya Kombo yeteneğini (ID: 122) seviye 2 olarak vermezse, karakterler (özellikle Savaşçı ve Ninja) düz vuruş animasyonlarını (hit animation) tamamlayamaz veya iptal edemez (animation cancel).Hasar Kaybı: Bir Bedensel Savaşçı, Kombo 2 açıkken 10 saniyede 15 vuruş yapabiliyorsa, Kombo kapalıyken sadece 11 vuruş yapar. Bu, %20'nin üzerinde bir DPS (Saniye Başına Hasar) kaybı demektir.
Optimizasyon: Yukarıdaki kodda gördüğünüz
pc.set_skill_level(122, 2)satırı, oyuncunun potansiyel hasarının tamamını kullanabilmesini sağlayan en kritik satırdır. SQL tablosundaki hasar değerleri ne kadar yüksek olursa olsun, animasyon hızı düşükse hasar çıkmaz.
Hasar Testlerinde "Affect" (Etki) Yönetimi
Sunucunuzun hasar dengesini (PvP/PvM) ayarlarken, sürekli skill_proto düzenleyip reboot atmak yerine, Lua'nın affect sistemini bir Debug Aracı olarak kullanmalısınız.
Örneğin, "Kritik vuruş şansını %10 artırırsam oyun dengesi bozulur mu?" sorusunu test etmek için veritabanını değiştirmeyin. Lua ile oyuncuya geçici özellik verin:
-- Canlı Test Kodu
when 20095.chat."DEBUG: +10 Yarı İnsan Ver" begin
-- apply.ATTBONUS_HUMAN (Yarı İnsan)
-- Değer: 10, Süre: 60 saniye
if pc.getqf("debug_bonus") == 0 then
affect.add_collect(apply.ATTBONUS_HUMAN, 10, 60)
syschat("DEBUG: 60 saniye boyunca Yarı İnsan bonusu aktif.")
pc.setqf("debug_bonus", 1)
else
syschat("Zaten aktif bir test bonusun var.")
end
end
Bu yöntemle, skill_proto içindeki szPointPoly (Taban Hasar) ve szMasterBonusPoly (Bonus Çarpanı) değerleri arasındaki ilişkiyi, canlı sunucuda oyunculara hissettirmeden test edebilirsiniz.
Veri Bütünlüğü ve Biyolog Çakışmaları
En tehlikeli optimizasyon hatası, beceri sıfırlama (Skill Reset) sırasında yaşanır. Bazı kötü kodlanmış questler, becerileri sıfırlarken affect.remove_all_collect() komutunu kullanır.
Risk: Bu komut, oyuncunun Biyolog görevlerinden (Ork Dişi, Lanet Kitabı vb.) aldığı kalıcı özellikleri de silebilir.
Sonuç: Oyuncunun hasarı kalıcı olarak düşer (
strveyaattack_gradebonusu silinir).Doğru Yöntem: Beceri sıfırlama işlemlerinde asla toplu silme (remove_all) yapılmamalıdır. Bunun yerine sadece beceri grubu (Skill Group)
0olarak ayarlanmalı vepc.clear_skill()fonksiyonu kullanılmalıdır. Kaynak kod (Source) tarafındaClearSkillfonksiyonu sadece ilgili becerileri temizleyecek şekilde ayarlanmalıdır.
Sonuç
beceri.lua dosyası, Metin2 sunucusunun sadece bir "NPC konuşması" değil, oyunun mekanik kararlılığını sağlayan bir motor parçasıdır. Tablo tabanlı (Table-driven) yapıya geçmek, matematiksel indeksleme kullanmak ve pasif yetenekleri (Kombo gibi) zorunlu hale getirmek; sunucunuzdaki "Hasar bozuk", "Vuruyorum işlemiyor" gibi sorunları kökten çözer ve skill_proto üzerinde yaptığınız ince ayarların oyuna %100 yansımasını sağlar.

