Metin2 Hakkında Yapay Zeka ile Oluşturulmuş Genel Rehber

maxbro

[GM]MaxBro
MT Üye
Mesaj
614
Çözümler
21
Beğeni
501
Puan
829
Ticaret Puanı
0
Merhaba arkadaşlar, geçenlerde ücretli bir yapay zeka ile tüm metin2 dosyalarını client pack source herşeyi tek tek dahil analiz ettirdim ve böyle bir rehber hazırladı. Tek mesaja sığmadığı için birkaç mesaj şeklinde alt kısma ekleyeceğim. İşe yarayıp yaramadığına siz değerli forum üyeleri karar verecektir.


# Metin2 Geliştirici Kılavuzu: Kaynak Kod Analizi

# Metin2 Geliştirici Kılavuzu: Kaynak Kod Analizi ve Sistem Mimarisi

Bu proje, Metin2 oyununun hem sunucu (Server) hem de istemci (Client) tarafındaki kaynak kodlarını (Source Code) detaylı bir şekilde analiz eden, teknik bir eğitim rehberidir. Bir kitap formatında hazırlanan bu dökümantasyon, 7 cilt ve 40 bölümden oluşmaktadır.

## 🟢 Cilt 1: Temeller ve Altyapı
* **Bölüm 1:** [Giriş ve Teknolojiler](volume1_altyapi/bolum1_giris.md) - Metin2 Source nedir?
* **Bölüm 2:** [Dizin Yapısı](volume1_altyapi/bolum2_dizin_yapisi.md) - Klasör ve dosya hiyerarşisi.
* **Bölüm 3:** [Ağ ve Paket Yapısı](volume1_altyapi/bolum3_network.md) - Sunucu-Client iletişimi.
* **Bölüm 4:** [Girdi İşleme ve Chat](volume1_altyapi/bolum4_input.md) - Klavye verileri ve sohbet sistemi.
* **Bölüm 5:** [Bağlantı Tanımlayıcıları (DESC)](volume1_altyapi/bolum5_baglanti_tanimlayicilari.md) - Güvenlik ve el sıkışma.

## 🟠 Cilt 2: Karakter ve Varlık Sistemi
* **Bölüm 1:** [CHARACTER Sınıfı](volume2_karakter/bolum1_char_sinifi.md) - Oyuncu ve varlık nesnesi.
* **Bölüm 2:** [Savaş Mekanikleri](volume2_karakter/bolum2_savas_mekanikleri.md) - Hasar hesaplama ve savunma.
* **Bölüm 3:** [Eşya Sistemi](volume2_karakter/bolum3_item_sistemi.md) - Item nesnesi ve düşme mantığı.
* **Bölüm 4:** [Beceri Sistemi](volume2_karakter/bolum4_beceri_sistemi.md) - Skill ilerlemesi ve alan hasarı.
* **Bölüm 5:** [Affect Sistemi](volume2_karakter/bolum5_affect_sistemi.md) - Buff ve debuff yönetimi.
* **Bölüm 6:** [CHARACTER_MANAGER](volume2_karakter/bolum6_char_manager.md) - Varlık takibi ve spawn.
* **Bölüm 7:** [Savaş ve Ölüm](volume2_karakter/bolum7_savas_yonetimi.md) - Stun, ölüm ve EXP kaybı.
* **Bölüm 8:** [At ve Binek Sistemi](volume2_karakter/bolum8_at_sistemi.md) - Binicilik mekanikleri.
* **Bölüm 9:** [MobManager](volume2_karakter/bolum9_mob_manager.md) - Canavar veri yapıları ve gruplar.

## 🔵 Cilt 3: Dünya ve Harita Dinamikleri
* **Bölüm 1:** [Zindan Sistemi](volume3_dunya/bolum1_zindan_sistemi.md) - Private Map ve kopyalama.
* **Bölüm 2:** [Yapay Zeka (AI)](volume3_dunya/bolum2_yapay_zeka.md) - Canavar agresifliği ve kaçış.
* **Bölüm 3:** [Regen Sistemi](volume3_dunya/bolum3_regen_sistemi.md) - Harita popülasyonu ve doğum.
* **Bölüm 4:** [Harita Koordinatları](volume3_dunya/bolum4_harita_sistemi.md) - Sectree ve global konumlar.
* **Bölüm 5:** [Zindan Yönetimi](volume3_dunya/bolum5_zindan_yonetimi.md) - CDungeon ve yaşam döngüsü.

## 🟡 Cilt 4: Sosyal ve Ekonomik Sistemler
* **Bölüm 1:** [Lonca Sistemi](volume4_ekonomi/bolum1_lonca_sistemi.md) - Üyelik, rütbe ve online takibi.
* **Bölüm 2:** [Ticaret ve Güvenlik](volume4_ekonomi/bolum2_ticaret_sistemi.md) - Eşya takası ve anti-dupe.
* **Bölüm 3:** [Privilege Oranları](volume4_ekonomi/bolum3_oran_yonetimi.md) - DROP ve EXP bonusları.
* **Bölüm 4:** [Çevrimdışı Pazar](volume4_ekonomi/bolum4_offline_shop.md) - Offline Shop mimarisi.
* **Bölüm 5:** [Market (Shop) Sistemi](volume4_ekonomi/bolum5_market_sistemi.md) - NPC market ve para akışı.

## 🔴 Cilt 5: Görev (Quest) ve Etkinlik Motoru
* **Bölüm 1:** [Quest Motoru ve Lua](volume5_quest/bolum1_quest_motoru.md) - C++ ve Lua entegrasyonu.
* **Bölüm 2:** [PC Lua Köprüsü](volume5_quest/bolum2_quest_lua_pc.md) - Oyuncu yetkileri ve güvenliği.
* **Bölüm 3:** [Zindan Lua Köprüsü](volume5_quest/bolum3_quest_lua_dungeon.md) - Zindan otomasyonu.
* **Bölüm 4:** [Lonca Lua Köprüsü](volume5_quest/bolum4_quest_lua_guild.md) - Lonca savaşları ve liderlik.

## 🟣 Cilt 6: İstemci (Client) Mimarisi
* **Bölüm 1:** [Grafik Döngüsü](volume6_client/bolum1_client_mimarisi.md) - Update ve Render döngüsü.
* **Bölüm 2:** [InstanceBase](volume6_client/bolum2_instance_base.md) - Görsel modeller ve zırh kaplama.
* **Bölüm 3:** [Network Stream](volume6_client/bolum3_network_stream.md) - İstemci paket dağıtımı.
* **Bölüm 4:** [Yerdeki Eşyalar](volume6_client/bolum4_yerdeki_esyalar.md) - Ground Items ve fizik.
* **Bölüm 5:** [Efekt Sistemi](volume6_client/bolum5_efekt_sistemi.md) - Görsel efektler ve PVP işaretleri.
* **Bölüm 6:** [Oyuncu Mantığı](volume6_client/bolum6_oyuncu_mantigi.md) - Otomatik saldırı ve statüler.
* **Bölüm 7:** [Sohbet Sistemi](volume6_client/bolum7_sohbet_sistemi.md) - Chat scrolling ve filtreleme.

## 🟤 Cilt 7: Veri Yönetimi ve MySQL
* **Bölüm 1:** [Database Yönetimi](volume7_database/bolum1_db_yonetimi.md) - ClientManager ve SQL köprüsü.
* **Bölüm 2:** [Cache Mekanizması](volume7_database/bolum2_cache_mekanizmasi.md) - Performanslı veri saklama.
* **Bölüm 3:** [Proto Okuma](volume7_database/bolum3_proto_okuma.md) - Veri dönüştürme ve proto yazımı.
* **Bölüm 4:** [Giriş İşlemleri](volume7_database/bolum4_giris_islemleri.md) - Login ve karakter seçimi.
* **Bölüm 5:** [Hediye Sistemi](volume7_database/bolum5_hediye_sistemi.md) - ItemAward ve Nesne Market.

---
**Not:** Bu kılavuz Metin2 kaynak kodlarını anlamak isteyen geliştiriciler için hazırlanmıştır. Ticari amaç gütmez.




Metin2Source (Kaynak Kodları), oyunun beynini oluşturan, geliştiriciler tarafından yazılmış ham C++, Python ve Lua dosyalarının bütünüdür. Bu kaynak kodlarına sahip olmak, oyunun her türlü kuralını değiştirebilmek, yeni sistemler eklemek ve hataları kökten çözebilmek anlamına gelir.

## 1.1. Metin2'nin Teknolojik Mirası

Metin2, 2000'li yılların başındaki teknoloji standartlarına göre inşa edilmiştir. Temel bileşenleri şunlardır:

* **Sunucu Tarafı (Server Side):** Tamamen **C++** diliyle yazılmıştır. Nesne yönelimli programlama (OOP) mantığıyla karakterler, eşyalar ve haritalar yönetilir. Veritabanı olarak **MySQL** kullanılır, ancak sunucu hızı için özel bir önbellekleme (Caching) sistemi geliştirilmiştir.
* **İstemci Tarafı (Client Side):** Sunucu ile aynı teknolojide, C++ üzerinde çalışan **EterEngine** motorunu kullanır. Karayüz (UI) ve görev ekranları gibi esnek olması gereken kısımlar **Python** diliyle yazılmış ve C++ ile köprülenmiştir.
* **Görev Sistemi (Quest Engine):** Oyun içi hikayeler ve etkinlik tetikleyicileri için **Lua** dili kullanılır. Lua, C++'ın hızı ile Python'ın esnekliği arasında bir köprü görevi görür.

## 1.2. Neden Source Kodlarına İhtiyaç Duyulur?

Metin2 gibi devasa bir oyunu "Binary" (Yani sadece çalıştırılabilir dosyalarla) yönetmek çok kısıtlıdır. Source kodları şu imkanları sunar:
1. **Güvenlik:** Oyunun paket yapılarını (Network packets) değiştirerek hilelerin önüne geçmek.
2. **Optimizasyon:** Sunucu işlemci ve RAM kullanımını iyileştirerek daha fazla oyuncuyu aynı anda barındırmak.
3. **Modernizasyon:** Oyuna HD doku desteği, yeni simyalar, kuşak sistemleri veya güncel dillerdeki eklentileri entegre etmek.

## 1.3. Geliştirme Ortamı (Compiler)

Metin2 Source dosyalarını derlemek (Compile) için kullanılan standart araçlar:
* **Sunucu:** FreeBSD işletim sistemi üzerinde **gcc** (GNU Compiler Collection).
* **İstemci:** Windows üzerinde **Microsoft Visual Studio**.
* **Veritabanı:** MySQL Server ve yönetim için genellikle **Navicat**.

## 1.4. Bu Kitabın Amacı

Bu rehber, Metin2'nin "Kara Kutusunu" açmayı amaçlar. Kodların arasında kaybolmak yerine, hangi dosyanın hangi amaçla yazıldığını, bir fonksiyonun neden orada olduğunu ve sistemlerin birbirine nasıl bağlandığını adım adım açıklayacağız.

---
**Önemli Uyarı:** Kod üzerinde yapacağınız en küçük bir noktalı virgül (;) hatası, sunucunun açılmamasına veya oyuna girerken aniden kapanmalara yol açabilir. Bu yüzden her zaman değişiklik öncesi bir yedek (Backup) bulundurmak, profesyonel Metin2 geliştiriciliğinin ilk kuralıdır.

Metin2 geliştiriciliğine yeni başlayanların en çok zorlandığı konu, binlerce dosya arasından doğru olanı bulmaktır. Bu bölüm, standart bir Metin2 source projesinin klasör yapısını ve hangi dosyanın nerede bulunduğunu haritasını çıkarır.

## 2.1. Sunucu Source Yapısı (Server/Src)

Sunucu kodları genellikle üç ana klasöre ayrılır:

1. **game:** Oyunun kalbi burasıdır. Savaşlar, ticaret, hareketler, skiller ve tüm oyun mekanikleri burada yazılıdır.
* `src/`: Tüm `.cpp` ve `.h` dosyaları burada toplanır.
* `config.cpp`: Sunucunun `CONFIG` dosyasından okuduğu ayarların (IP, Port, Oranlar) tanımlandığı yerdir.
2. **db:** Veritabanı ile oyun sunucusu arasındaki köprüdür.
* `src/ClientManager.cpp`: MySQL'den veri çekme ve gönderme işlemlerini yönetir.
* `src/ProtoReader.cpp`: `item_proto` ve `mob_proto` dosyalarının okunmasını sağlar.
3. **common:** Hem `game` hem de `db` sunucusunun ortak kullandığı rehber dosyalarıdır.
* `tables.h`: Paketlerin (Packets) ve veritabanı tablolarının yapısını tanımlar.
* `service.h`: Oyununuzun özelliklerini (Örn: `ENABLE_GUILD_DRAGONLAIR`) açıp kapatabileceğiniz anahtarlar buradadır.

## 2.2. İstemci Source Yapısı (Client)

İstemci tarafı, görselleştirme ve kullanıcı arayüzü ile ilgilenir:

1. **UserInterface:** Oyunun başlatıcı (Launcher) ve ana motor kısmıdır.
* `PythonNetworkStream.cpp`: Sunucudan gelen paketlerin Python arayüzüne aktarıldığı merkezdir.
* `InstanceBase.cpp`: 3D modellerin (Zırh, Silah, Saç) karakter üzerinde nasıl duracağını yönetir.
2. **EterLib / EterGrn:** Oyunun grafik motoru (Render) kütüphaneleridir.
3. **SpeedTree:** Haritadaki ağaçların ve bitkilerin rüzgar animasyonlarını yöneten sistemdir.

## 2.3. Python ve Pack Yapısı (Client/Root)

C++ kodları derlendikten sonra, oyunun görsel arayüzü `pack` dosyaları içindeki `.py` dosyalarıyla şekillenir:

* **root.eix/epk:** Oyunun tüm Python mantığı buradadır.
* `game.py`: Oyun penceresindeki klavye/fare tıklamalarını yönetir.
* `uiInventory.py`: Envanter penceresinin tasarımı ve butonlarıdır.
* **locale_tr.eix/epk:** Oyunun dil dosyaları ve eşya isimleri (`item_proto`) burada saklanır.
* **uiscript.eix/epk:** Pencerelerin tasarımları (Butonların yerleri, resim yolları) burada tanımlanır.

## 2.4. Ek Dosyalar ve Araçlar

* **Extern:** C++ projelerinin ihtiyaç duyduğu harici kütüphaneler (Cryptopp, Boost, LZO, Lua).
* **Tools:** DumpProto (Veritabanı dosyalarını kapatmak için) gibi geliştirici araçları.

---
**Geliştirici Notu:** Bir sistem ekleyeceğiniz zaman işe her zaman `common/tables.h` dosyasından başlayın. Önce verinin nasıl saklanacağını belirlemek (Structure), kodun geri kalanını yazarken size rehberlik edecektir. Ayrıca, sunucu tarafında yaptığınız bir paket değişikliğini (`packet.h`), client tarafındaki `packet.h` dosyasına da birebir uygulamayı unutmayın. Aksi takdirde sunucu ve client farklı dillerde konuşmaya başlayacak ve bağlantı kopacaktır.

Metin2 Sunucusu (Game) ile İstemcisi (Client) arasındaki tüm iletişim, **Packet (Paket)** adı verilen yapılandırılmış veri blokları üzerinden yürütülür. Bu bölüm, `packet.h` dosyasını temel alarak Metin2'nin "sinir sistemini" her detayıyla analiz eder.

## 3.1. Paket Protokolü Nedir?

Bir paket, sunucuya gönderilen veya sunucudan gelen küçük bir veri paketidir. Her paketin bir **Header (Başlık)** değeri vardır. Bu başlık, paketin ne tür bir işlem olduğunu (hareket, sohbet, envanter güncelleme vb.) belirtir.

Metin2'de 3 ana paket türü vardır:
1. **CG (Client to Game):** Oyuncunun bilgisayarından sunucuya giden emirler.
2. **GC (Game to Client):** Sunucudan oyuncunun ekranına giden güncellemeler.
3. **GG (Game to Game):** Sunucular (CH1, CH2 vb.) arasındaki iç konuşmalar (P2P).

## 3.2. `packet.h` dosyasının Anatomisi

İncelediğimiz `packet.h` dosyasında paketlerin başlıkları `enum` olarak tanımlanmıştır. İşte bazı kritik başlıklar ve anlamları:

### GC (Game to Client) Önemli Başlıklar:
* `HEADER_GC_CHAT (4)`: Sohbet satırlarını istemciye gönderir.
* `HEADER_GC_LOGIN_SUCCESS (6)`: Giriş başarılı olduğunda karakter bilgilerini yollar.
* `HEADER_GC_CHARACTER_UPDATE (19)`: Bir karakterin ekipmanı veya tipi değiştiğinde çevredekilere haber verir.
* `HEADER_GC_ITEM_SET (21)`: Envanterdeki bir slotun içeriğini günceller.
* `HEADER_GC_OFFLINE_SHOP (47)`: (Eklenti) Çevrimdışı pazar verilerini yönetir.

### 3.3. Paketlerin Hafızadaki Yapısı (`#pragma pack(1)`)

Metin2'de paketler `struct` yapıları kullanılarak tanımlanır. En önemli kural şudur: **Paketler arasında boşluk (padding) olmamalıdır.** Bu yüzden `#pragma pack(1)` komutu kullanılır. Bu, işlemcinin veri yapılarını hız için boşluklarla hizalamasını engeller ve verinin "olduğu gibi" internet üzerinden gönderilmesini sağlar.

#### Örnek Analiz: `TPacketGGLogin`
Bu paket, bir oyuncu bir kanala (CH) girdiğinde diğer kanallara "Bu oyuncu buraya girdi" bilgisi verir.

```cpp
typedef struct SPacketGGLogin
{
BYTE bHeader; // Paketin kimliği (HEADER_GG_LOGIN)
char szName[CHARACTER_NAME_MAX_LEN + 1]; // Karakter adı
DWORD dwPID; // Karakterin benzersiz Player ID'si
BYTE bEmpire; // İmparatorluk ID (1: Kırmızı, 2: Sarı, 3: Mavi)
long lMapIndex; // Hangi haritada olduğu
BYTE bChannel; // Hangi kanalda (CH) olduğu
} TPacketGGLogin;
```

Bu paket internet hattında şöyle görünür (basitleştirilmiş):
`[HEADER][MEHMET][P_ID][EMPIRE][MAP][CH]`

## 3.4. Dinamik Boyutlu Paketler

Sabit boyutlu paketler (yukarıdaki gibi) işlenmesi kolaydır. Ancak sohbet mesajları veya lonca isimleri gibi veriler değişken boyutludur. Bu durumda:
1. Önce bir başlık gönderilir.
2. Başlığın hemen ardından verinin uzunluğu (`long lSize`) gönderilir.
3. Son olarak gerçek veri bloğu gönderilir.

**Örnek:** `TPacketGGNotice` (Duyuru paketi)
```cpp
typedef struct SPacketGGNotice
{
BYTE bHeader;
long lSize; // Gelecek olan duyuru metninin karakter sayısı
} TPacketGGNotice;
```

## 3.5. Ağ Akışı ve Input İşleme (Input Main)

Sunucu taraflı `input_main.cpp` dosyası, istemciden gelen paketleri bir `switch-case` döngüsünde karşılar:

1. Paketi oku.
2. Header'a bak (Örn: `HEADER_CG_MOVE`).
3. O başlığa ait fonksiyonu çağır (`AnalyzeMove`).
4. Gelen verileri doğrula (Hız hilesi var mı? Duvar içinden mi geçiyor?).
5. Eğer güvenliyse işlemi onayla.

## Özet ve Dikkat Edilmesi Gerekenler
* Bir paketin boyutunu değiştirdiğinizde, hem **Server Source** hem de **Client Source** tarafında aynı değişikliği yapmalısınız. Aksi takdirde sunucu ile istemci arasındaki "senkronizasyon" bozulur ve oyuncular oyuna girer girmez hata alıp kapanır (**Core/Crash**).
* Paketlerdeki veri türleri (`BYTE`, `WORD`, `DWORD`) boyutları optimize etmek için çok önemlidir. Gereksiz yere `long` kullanmak ağ trafiğini şişirir.

---
*Bu bölüm, Metin2'nin iletişim temelini atmaktadır. Sonraki bölümlerde bu paketlerin `input_main.cpp` içerisinde nasıl işlendiğini daha derin inceleyeceğiz.*

Bir oyuncu tıkladığında veya bir şey yazdığında, bu bilgi sunucuya bir paket olarak ulaşır. Sunucu tarafında bu paketleri karşılayan ve işleyen ana birim `CInputMain` sınıfıdır (`input_main.cpp`). Bu bölüm, oyuncu emirlerinin nasıl denetlendiğini ve filtrelendiğini inceler.

## 4.1. `input_main.cpp`'nin Rolü

Sunucu ağdan bir paket aldığında (Örn: `HEADER_CG_WHISPER`), bu paketi `input_main.cpp` içerisindeki ilgili fonksiyona yönlendirir. Burası oyunun **"Gümrük Kapısı"**dır. Her emir burada şu denetimlerden geçer:
* **Hız Sınırı (Rate Limit):** Oyuncu bu işlemi çok mu hızlı yapıyor? (Flood engelleme)
* **Yetki Kontrolü:** Oyuncunun bu işlemi yapmaya yetkisi var mı?
* **Mesafe Kontrolü:** Oyuncu çok uzaktaki bir NPC ile mi konuşmaya çalışıyor?

## 4.2. Sohbet ve Fısıltı Sistemi (`Whisper`)

Fısıltı paketi işlenirken (`CInputMain::Whisper`) sunucu şu adımları izler:
1. **Engelleme Kontrolü:** Alıcı veya gönderici birbirini engellemiş mi? (`IsBlockMode`)
2. **Mesafe/Durum Kontrolü:** Karakter o an sohbet edebilir durumda mı? (Susturulmuş mu? `AFFECT_BLOCK_CHAT`)
3. **Hedef Bulma:** Alıcı aynı kanaldaysa (`FindPC`), farklı kanaldaysa (`P2P_MANAGER`) bulunur.
4. **İmparatorluk Filtresi:** Eğer imparatorluk dilleri konuşulmuyorsa, rakip imparatorluğun yazıları anlamsız karakterler olarak görünür.

## 4.3. Spam Engelleme Sistemi (`SpamBlockCheck`)

Metin2, sunucuyu yoran ve oyuncuları rahatsız eden mesaj saldırılarını (Chat Spam) otomatik olarak engeller.
* **Spam Puanı:** Her mesajın içeriğine göre bir puanı vardır.
* **Anlık Ceza:** Eğer bir IP adresi belirli bir puanı (`g_uiSpamBlockScore`) aşarsa, `block_chat_by_ip_event` tetiklenir ve o IP belirli bir süre susturulur.

## 4.4. Metin Etiketleri (Text Tags) ve Renkli Yazılar

Metin2'de gördüğünüz renkli isimler veya eşya linkleri (`|Hitem:Vnum|h[İsim]|h`) özel etiketlerdir. Sunucu bu etiketleri `GetTextTag` fonksiyonu ile analiz eder:

* `|cffff0000`: Yazının rengini değiştirir (RGB).
* `|Hitem...|h`: Eşya üzerine tıklandığında özelliklerini gösteren bir **Hyperlink** oluşturur.
* **Cam Küre (Prism) Kontrolü:** Bağırma kanalında eşya yansıtmak bazen "Cam Küre" eşyası gerektirir. Sunucu bunu `ProcessTextTag` içinde kontrol eder ve gerekirse eşyayı envanterden siler.

## 4.5. P2P (Sunucular Arası) İletişim

Eğer fısıltı attığınız kişi farklı bir CH'de ise, mesaj doğrudan ona gidemez. `P2P_MANAGER` devreye girer:
1. Sunucu, mesajı diğer sunuculara (CH2, CH3, CH4) bir **P2P Paketi** olarak yayınlar.
2. Hedef oyuncunun bulunduğu sunucu mesajı alır ve oyuncuya iletir.
3. Bu sayede Metin2'de kanallar arası "Kesintisiz İletişim" sağlanır.

---
**Geliştirici Notu:** Eğer bir sistem eklediyseniz ve çalışmıyorsa (Örn: Bir butona basıyorsunuz ama tepki yok), ilk bakmanız gereken yer `input_main.cpp`'de o butonun gönderdiği paket başlığının (Header) tanımlı olup olmadığıdır.

Metin2 sunucusuna bağlanan her bir istemci (Client), sunucu tarafında bir `DESC` (Descriptor - Tanımlayıcı) nesnesi ile temsil edilir. Bu nesne, ağ bağlantısının düşük seviyeli yönetiminden, paketlerin şifrelenmesine kadar tüm temel hattı korur. `desc.cpp` dosyası, bu iletişimin güvenli limanıdır.

## 5.1. Bağlantı Kurulumu ve El Sıkışma (Handshake)

Yeni bir bağlantı geldiğinde `Setup` fonksiyonu tetiklenir:
* **IP ve Port Kaydı:** İstemcinin adresi (`m_stHost`) ve kapısı (`m_wPort`) kaydedilir.
* **Bellek Hazırlığı:** Gelen (`Input`) ve giden (`Output`) veriler için tampon bölgeler (Buffers) oluşturulur.
* **Handshake:** Sunucu ve istemci, paket alışverişine başlamadan önce birbirlerini doğrularlar. Bu süreçte paylaşılan gizli bir anahtar (`_handshake`) kullanılır.

## 5.2. Veri Okuma ve Şifre Çözme (`ProcessInput`)

Soketten gelen ham veriler doğrudan işlenemez. Önce şifrelerinin çözülmesi (Decryption) gerekir:
* **TEA Şifrelemesi:** Eski nesil serverlarda `TEA_Decrypt` fonksiyonu kullanılır. Veriler 8 baytlık bloklar halinde çözülür.
* **Gelişmiş Şifreleme:** Modern sistemlerde (`_IMPROVED_PACKET_ENCRYPTION_`) daha karmaşık `cipher` yapıları kullanılır.
* **İşlemciye Sevk:** Şifresi çözülen veri, o anki faza (Login, Game vb.) ait `InputProcessor` sınıfına gönderilerek anlamlandırılır.

## 5.3. Paket Gönderme ve Sıralama (`Packet`)

Sunucu bir paket göndermek istediğinde veriyi doğrudan sokete yazmaz, önce `Packet` fonksiyonuna gönderir:
* **Tamponlama (Buffering):** Eğer gönderilecek veri çok küçükse, işlemci yükünü azaltmak için `m_lpBufferedOutputBuffer` içinde biriktirilir ve tek bir hamlede gönderilir.
* **Şifreleme (Encryption):** Veri istemciye gitmeden hemen önce sunucunun şifreleme anahtarı (`m_adwEncryptionKey`) ile mühürlenir.
* **Büyük Paketler:** Eğer bir lonca logosu veya uzun bir liste gönderiliyorsa, `LargePacket` fonksiyonu ile bellek alanı dinamik olarak genişletilir.

## 5.4. Bağlantı Sağlık Kontrolü: PING ve PONG

Oyuncunun bağlantısının kopup kopmadığını anlamak için her `ping_event_second_cycle` (Genellikle 10 saniye) süresinde bir kontrol yapılır:
* **PING:** Sunucu istemciye bir "Ping" paketi gönderir.
* **PONG:** İstemci bu pakete "Pong" ile cevap vermelidir.
* **Zaman Aşımı:** Eğer belirli bir süre içinde cevap gelmezse, `DESC` nesnesi `PHASE_CLOSE` durumuna alınır ve bağlantı koparılır (Oyuncunun "Karakter Atması").

## 5.5. Röle (Relay) Sistemi

Bazı durumlarda bir paket doğrudan dışarıya değil, başka bir sunucuya (Örn: P2P üzerinden diğer kanallara) iletilmelidir. `HEADER_GG_RELAY` başlığı kullanılan bu sistemde, `m_stRelayName` yardımıyla paketler sunucular arası tünellerden geçer.

---
**Geliştirici Notu:** `desc.cpp` içerisindeki "testtesttesttest" olarak görünen varsayılan şifreleme anahtarları, oyunun güvenliği için en zayıf halkadır. Profesyonel bir sunucuda bu anahtarlar hem sunucu hem de istemci tarafında benzersiz ve karmaşık dizilerle değiştirilmelidir. Aksi takdirde, paket dinleme yazılımları (Sniffers) ile oyuncuların verilerini çalmak çok kolaydır.
 
Metin2 sunucu kaynak kodlarının kalbi `CHARACTER` sınıfıdır. Oyundaki her bir varlık (oyuncu, NPC, slot/monster, evcil hayvan) aslında bir `CHARACTER` nesnesidir. Bir varlığın dünyada "var olması" demek, bu sınıfın bir örneğinin (instance) bellekte oluşması demektir.

## 1.1. Nesne Yaşam Döngüsü: Create, Initialize ve Destroy

Bir karakter (örneğin bir oyuncu veya canavar) oyuna dahil olduğunda şu sıra izlenir:
1. **Constructor (`CHARACTER::CHARACTER`)**: Boş bir karakter nesnesi oluşturulur. Karakterin "durumları" (Idle, Move, Battle) atanır.
2. **Initialize (`CHARACTER::Initialize`)**: Sınıfın yüzlerce değişkeni (HP, SP, Seviye, At hızı, Lonca bilgisi vb.) sıfırlanır veya varsayılan değerlere getirilir.
3. **Create (`CHARACTER::Create`)**: Karakterin ağ üzerindeki benzersiz kimliği olan **VID** (Virtual ID) atanır. Eğer bir oyuncuysa adı (`m_stName`) kaydedilir.

### Kod Analizi: `Initialize()` Neden Bu Kadar Kalabalık?
`char.cpp` dosyasındaki `Initialize` fonksiyonuna baktığınızda, Metin2'nin ne kadar karmaşık bir sistem olduğunu görebilirsiniz. İşte bazı kritik atamalar:

* **Zamanlayıcılar (Events):** `m_pkDeadEvent`, `m_pkSaveEvent`, `m_pkRecoveryEvent`. Karakterin canının dolması veya belli bir süre sonra ölmesi gibi "zamanlı" işler bu işaretçiler (pointers) üzerinden yönetilir.
* **Sosyal Nesneler:** `m_pkShop` (Oyuncunun baktığı dükkan), `m_pkExchange` (Ticaret penceresi), `m_pkParty` (Grup bilgisi).
* **Puanlar (Points):** `m_points` ve `m_pointsInstant`. Statüler, efsunlar ve anlık değerler burada tutulur.

## 1.2. VID (Virtual ID) ve PID (Player ID) Farkı

Yeni başlayanların en çok karıştırdığı konulardan biri budur:
* **VID:** Karakterin o anki oyun oturumundaki "geçici" numarasıdır. Bir canavar öldüğünde VID'i serbest kalır ve yeni doğan birine verilebilir.
* **PID:** Sadece oyunculara (PC) özeldir ve veritabanındaki kalıcı kimlik numarasıdır.

## 1.3. Karakter Durum Makinesi (State Machine)

Metin2 karakterleri bir **State Machine** mimarisiyle çalışır. `char.cpp`'de şu durumlar tanımlıdır:
* `m_stateIdle`: Karakter bekliyor. (Yapay zeka canavarlar için: "Etrafı kolla")
* `m_stateMove`: Karakter hareket ediyor.
* `m_stateBattle`: Karakter savaş halinde.

Karakterin bir durumdan diğerine geçmesi `GotoState()` fonksiyonu ile yapılır. Örneğin, bir slota vurduğunuzda slot `Idle` durumundan `Battle` durumuna geçer.

## 1.4. Kodun Derinlikleri: Seviye Kontrolü (Örnek)

Aşağıdaki fonksiyon, projenizdeki `char.cpp` dosyasından alınmış harika bir "hard-coded" kural örneğidir:

```cpp
bool CAN_ENTER_ZONE(const LPCHARACTER& ch, int map_index)
{
switch (map_index)
{
case 301: case 302: case 303: case 304:
if (ch->GetLevel() < 90)
return false;
}
return true;
}
```
Bu basit kod parçası, 301-304 kodlu haritalara (Beta haritalar) girmek için 90 seviye sınırı koyar. Eğer yeni bir harita ekleyip seviye sınırı koymak isterseniz, düzenlemeniz gereken yer tam burasıdır.

## 1.5. Yoketme ve Temizlik (`Destroy`)

Bir karakter oyundan çıktığında veya bir canavar yok olduğunda `Destroy()` çağrılır. Bu fonksiyon bir "temizlikçi" gibi çalışır:
* Açık dükkanları kapatır.
* Ticaret (Exchange) varsa iptal eder.
* At ve Binek gibi ek varlıkları (HorseSummon) kaldırır.
* Bellekte sızıntı (Memory Leak) olmaması için tüm `Event`'leri iptal eder.

---
*Bu bölüm, Metin2'nin temel varlık yapısını ele almıştır. Bir sonraki bölümde bu karakterlerin nasıl "savaşçıya" dönüştüğünü (`Battle.cpp`) ve hasar hesaplamalarının nasıl yapıldığını inceleyeceğiz.*

Metin2'nin en çok merak edilen ve oyun dengesini (Oyun Sonu/PvP) doğrudan etkileyen kısmı hasar hesaplama sistemidir. Bu sistem `battle.cpp` dosyası içerisinde yönetilir. Bu bölümde, bir karaktere vurduğunuzda arka planda dönen matematiksel fırtınayı inceleyeceğiz.

## 2.1. Temel Hasar Yapısı: Yakın Dövüş (Melee Damage)

Yakın dövüş hasarı (`CalcMeleeDamage`), saldırganın silahı, seviyesi ve çeşitli bonusları ile kurbanın savunması arasındaki farka dayanır.

### Hasar Hesaplama Adımları:
1. **Silah Hasarı:** Silahın `value3` (min) ve `value4` (max) değerleri aralığında rastgele bir sayı seçilir ve 2 ile çarpılır.
2. **Saldırı Değeri (Attack Grade):** Karakterin statülerinden (STR, DEX vb.) gelen saldırı değeri eklenir.
3. **Seviye Katsayısı:** `iAtk = SaldırıDeğeri + Hasar - (Seviye * 2)`. Seviyenin etkisi burada önce çıkarılır, hesaplama yapıldıktan sonra tekrar eklenir.
4. **AR (Attack Rating) Çarpanı:** Karakterin isabet oranına göre hasar belli bir katsayı (`fAR`) ile çarpılır.

## 2.2. Bonusların Uygulanması (`CalcAttBonus`)

Hasar hesaplandıktan sonra, kurbanın türüne göre ek bonuslar devreye girer. Bu, "Ölümsüzlere Karşı Güçlü" veya "Yarı İnsanlara Karşı Güçlü" gibi efsunların çalıştığı yerdir.

### Kod Analizi: Irk Bonusları
Sunucu, kurbanın `RaceFlag` değerine bakarak hasarı % oranında artırır:

```cpp
if (pkVictim->IsRaceFlag(RACE_FLAG_ANIMAL))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ANIMAL)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_UNDEAD))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_UNDEAD)) / 100;
// ... (Şeytan, Orklar, Mistikler vb. devam eder)
```

### Karakter Sınıfı (Job) Bonusları ve Savunmaları
PvP dengesini sağlayan en önemli kısım burasıdır. Eğer kurban bir oyuncuysa (PC), saldırganın o sınıfa özel "Güç" ve kurbanın o sınıfa özel "Savunma" değerleri işlenir:

```cpp
switch (pkVictim->GetJob())
{
case JOB_WARRIOR:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_WARRIOR)) / 100;
break;
}
```

## 2.3. Savunma Düştükten Sonraki Sonuç

Tüm efsunlar ve bonuslar eklendikten sonra kurbanın savunma değeri (`POINT_DEF_GRADE`) hesaplanır ve saldırı değerinden çıkarılır:

**Final Hasarı = MAX(0, ToplamSaldırı - ToplamSavunma)**

## 2.4. Özel Durumlar: Kritik ve Delici Vuruşlar

* **Kritik Vuruş:** Eğer vuruş kritikse, en sonda hesaplanan final hasarı **2 ile çarpılır**.
* **Delici Vuruş:** Eğer vuruş deliciyse, kurbanın savunması (iDef) **0 kabul edilir** ve saldırganın delici vuruş bonusu kadar ek hasar eklenir.

## 2.5. Dönüşüm (Polymorph) Hasarı

Dönüşüm küresi kullanıldığında hasar sistemi değişir:
1. Karakterin kendi statülerinden gelen saldırı değeri büyük oranda devre dışı kalır.
2. Dönüşülen yaratığın (Mob) DNA'sındaki hasar değerleri (`dwDamageRange`) baz alınır.
3. "Dönüşüm Gücü" (`GetPolymorphPower`) hasarı çarpan olarak etkiler.

---
**Geliştirici Notu:** Eğer oyununuzda Sura veya Savaşçıların çok fazla vurduğunu düşünüyorsanız, `battle.cpp` içindeki bu çarpanları (örneğin `/ 100` yerine `/ 110`) değiştirerek global bir dengeleme yapabilirsiniz. Ancak bu, oyundaki tüm eşya dengelerini değiştireceği için çok dikkatli yapılmalıdır.

Metin2'de eşyalar sadece birer görüntüden ibaret değildir; her biri sunucu tarafında karmaşık birer veri yapısıdır (`CItem`). Bu bölümde, eşyaların nasıl oluşturulduğunu, nasıl yere düştüğünü ve sandıkların nasıl açıldığını inceleyeceğiz.

## 3.1. Eşya Veri Yapısı (`item.h` ve `item.cpp`)

Her eşya örneği (instance) bellekte şu temel bilgileri tutar:
* **Vnum:** Eşyanın `item_proto`daki kimlik numarası (Örn: 10).
* **ID:** O anki eşyanın dünyadaki benzersiz seri numarası.
* **Attributes (Efsunlar):** `attrtype0` (Efsun kodu) ve `attrvalue` (Değeri).
* **Sockets (Taşlar):** Silah/Zırhlardaki taş yuvaları.
* **Window & Pos:** Eşyanın nerede olduğu (Envanter, Depo, Giyili).

## 3.2. Eşya Yöneticisi (`ITEM_MANAGER`)

Sistemin beyni `ITEM_MANAGER` sınıfıdır. Temel görevleri şunlardır:
1. **Tabloları Okumak:** `item_proto` dosyasını belleğe yükler.
2. **Eşya Oluşturmak:** `ITEM_MANAGER::instance().CreateItem(vnum, count)` çağrıldığında yeni bir eşya nesnesi üretir.
3. **Drop (Düşürme) Kontrolü:** Ölen bir canavardan ne düşeceğine karar verir.

## 3.3. Sandık Açma ve Özel Droplar (`special_item_group.txt`)

Bazı eşyalar (Örn: Azrail Sandığı, Altın Define Sandığı) sağ tıklandığında içinden başka eşyalar çıkar. Sunucu bunu `item_manager_read_tables.cpp` dosyasındaki mantıkla yürütür.

### Kod Analizi: Sandık İçeriği
Sistem, `special_item_group.txt` içindeki grupları okur. Bir grup şu tiplerde olabilir:
* **Normal:** Rastgele bir eşya düşer.
* **PCT:** Belirlenen şansa (%) göre eşya düşer.
* **Special:** Özel efektler veya görev tetikleyicileri içerir.

```cpp
if (stType == "pct") {
type = CSpecialItemGroup::PCT;
} else if (stType == "quest") {
type = CSpecialItemGroup::QUEST;
}
```

## 3.4. Canavar Dropları (`mob_drop_item.txt`)

Bir canavar öldüğünde `ITEM_MANAGER::CreateDropItem` fonksiyonu çalışır. Drop sistemi üç katmanlıdır:
1. **Common Drop:** Seviyeye göre (genellikle 10 seviye altı/üstü) düşen genel eşyalar.
2. **Etc Drop:** `etc_drop_item.txt` içindeki nadir eşyalar.
3. **Group Drop:** Canavara özel olarak tanımlanmış (`mob_drop_item.txt`) eşya listesi.

### Geliştirici İpucu: Drop Şansını Artırmak
Eğer bir eşyanın düşme oranını kod bazında etkilemek isterseniz, `ITEM_MANAGER::ReadEtcDropItemFile` içerisindeki şu satıra bakmalısınız:
`m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);`
Buradaki `10000.0f` katsayısı, float (`0.01` gibi) değerlerin tam sayıya (integer) dönüştürülmesini sağlar. Oran hesaplamalarında hassasiyeti belirler.

## 3.5. Efsunların Atanması

Yeni bir eşya oluşturulduğunda (`CreateItem`), eğer eşya efsun alabilir bir türdeyse (Zırh, Kılıç vb.), `ITEM::AlterToMagicItem()` fonksiyonu çağrılır. Bu fonksiyon:
1. Rastgele kaç efsun geleceğini belirler (Genellikle 1-5 arası).
2. `item_attr` tablosundaki efsun oranlarını (Probability) kullanarak rastgele efsunları ve değerlerini seçer.

---
**Önemli Bilgi:** Metin2'de bir eşyayı sildiğinizde aslında o eşya bellekten hemen silinmez. "Silinme kuyruğuna" (M2_DELETE) eklenir. Bu, oyunun çökmemesi ve veritabanı senkronizasyonu için alınan bir güvenlik önlemidir.

Metin2'de beceriler (Skills), karakterin gücünü belirleyen en dinamik unsurlardan biridir. Bu sistem `char_skill.cpp` dosyasında yönetilir. Bir becerinin nasıl öğrenildiği, nasıl Master (M1) veya Grand Master (G1) olduğu ve bekleme sürelerinin (Cooltime) kod seviyesindeki işleyişi bu bölümde incelenir.

## 4.1. Beceri Seviyeleri ve Master Türleri

Metin2'de beceriler 4 ana aşamadan oluşur. Kod tarafında bu aşamalar `ComputeSkillMasterType` fonksiyonu ile belirlenir:

* **Normal (1-19):** `SKILL_NORMAL`
* **Master (M1-M10):** `SKILL_MASTER` (Beceri puanı 17-20 arasına ulaştığında tetiklenir)
* **Grand Master (G1-G10):** `SKILL_GRAND_MASTER` (30. seviyeye ulaşıldığında)
* **Perfect Master (P):** `SKILL_PERFECT_MASTER` (40. seviyeye ulaşıldığında)

## 4.2. Beceri Kitabı Okuma Mantığı (`LearnSkillByBook`)

Bir Master beceriyi geliştirmek için "Beceri Kitabı" okuduğunuzda arka planda şu kontroller yapılır:

1. **Zaman Kontrolü:** `GetSkillNextReadTime`. Eğer son okuma üzerinden 24 saat geçmediyse (veya Kötü Ruh Kovma Kağıdı kullanılmadıysa) okuma başarısız olur.
2. **EXP Maliyeti:** Master seviyesindeki bir beceriyi geliştirmek 20.000 EXP (`need_exp`) gerektirir.
3. **Şans Çarpanı:** `bProb` (Kitabın geçme şansı). Eğer "Münzevi Tavsiyesi" (`AFFECT_SKILL_BOOK_BONUS`) etkisindeyse bu şans %50 artar:
```cpp
if (FindAffect(AFFECT_SKILL_BOOK_BONUS)) {
bProb += bProb / 2;
}
```

## 4.3. Grand Master Gelişimi (`LearnGrandMasterSkill`)

G1 seviyesinden sonra "Ruh Taşı" ile yapılan geliştirmeler daha risklidir ve `LearnGrandMasterSkill` fonksiyonu ile yönetilir:
* **Derece Puanı (Alignment):** Ruh taşı okumak derece puanı tüketir. Kodda bu durum `idx` (9 aşamalı zorluk) üzerinden hesaplanır.
* **Başarı Sayacı:** Ruh taşı her okunduğunda gizli bir sayaç (`training_grandmaster_skill`) artar. Bu sayaç belirli bir alt sınıra (`iMinReadCount`) ulaşana kadar başarı şansı oldukça düşüktür.
* **Sonuç:** Başarı durumunda `SkillLevelUp` çağrılır, başarısızlıkta ise oyuncuya o meşhur "Başaramadın!" mesajları yollanır.

## 4.4. Beceri Sınırları ve Kısıtlamalar (`IsLearnableSkill`)

Hangi karakterin hangi beceriyi öğrenebileceği katı kurallara bağlıdır:
* **Sınıf Kontrolü:** Savaşçı becerileri sadece Savaşçılar (`JOB_WARRIOR`) tarafından öğrenilebilir.
* **Grup Kontrolü:** Oyuncunun bir beceri grubu (Hava kılıcı vs Zihinsel) seçmiş olması gerekir.
* **Özel Beceriler:** Örneğin, Assassin (Ninja) sınıfı olmayan bir karakterin "Okçu" binek becerilerini öğrenmesi kod bazında engellenmiştir:
```cpp
if (dwSkillVnum == SKILL_HORSE_WILDATTACK_RANGE && GetJob() != JOB_ASSASSIN)
return false;
```

## 4.5. Alan Hasarı ve Hedefleme (AoE)

Becerilerin kaç kişiye vuracağı `CSkillProto` verilerinden okunur. Beceri kullanıldığında:
1. Saldırganın etrafındaki veya hedefindeki karakterler bir listeye (Vector) alınır.
2. Her bir hedefe tek tek `battle.cpp` kuralları çerçevesinde hasar uygulanır.
3. Hasar hesaplanırken becerinin o anki seviyesi (M1, G1, P) çarpan olarak kullanılır.

---
**Geliştirici Notu:** Eğer bir becerinin (Örn: Hava Kılıcı) saniyesini veya bekleme süresini (Cooltime) değiştirmek isterseniz, bu değişiklikleri hem sunucu tarafındaki `skill_proto` dosyasından hem de istemci tarafındaki `PythonSkill.cpp` alt yapısından eşzamanlı yapmalısınız. Aksi takdirde istemcide beceri dolmuş görünse bile sunucu "Henüz hazır değil" diyerek kullanımı reddedecektir.

Metin2'de karakterlerin üzerindeki şebnemler, potlar, beceri buffları (Hava Kılıcı, Kutsama) ve zehir gibi tüm süreli etkiler "Affect" (Etki) sistemi ile yönetilir. Bu sistem `char_affect.cpp` dosyasında tanımlanır. Bu bölüm, bu etkilerin nasıl hesaplandığını, zamanının nasıl azaldığını ve veritabanına nasıl kaydedildiğini analiz eder.

## 5.1. Affect Yapısı ve Bileşenleri

Her bir etki (`CAffect`), karakter üzerinde şu bilgileri taşır:
* **dwType:** Etkinin türü (Örn: `SKILL_GEOMKYUNG` - Hava Kılıcı).
* **bApplyOn:** Etkinin hangi statüye etki edeceği (Örn: `POINT_ATT_SPEED` - Saldırı Hızı).
* **lApplyValue:** Statüye ne kadar ekleneceği (Örn: +50).
* **lDuration:** Etkinin ne kadar süreceği (Saniye cinsinden).

## 5.2. Affect Döngüsü (`affect_event` ve `ProcessAffect`)

Etkiler pasif duran veriler değildir. Karakter oyunda olduğu sürece her saniye `affect_event` çalışır:
1. **Süre Azaltma:** `ProcessAffect` fonksiyonu içindeki `pkAff->lDuration--` satırı ile her saniye etkinin süresi 1 azalır.
2. **Otomatik İptal:** Eğer süre 0'a ulaşırsa, `it = m_list_pkAffect.erase(it)` ile etki listeden silinir ve karakterin statüleri eski haline getirilir (`ComputeAffect(pkAff, false)`).
3. **Otomatik Yenileme:** HP ve SP potlarının otomatik kullanımı (`AutoRecoveryItemProcess`) bu döngü içinde kontrol edilir.

## 5.3. Özel Koşullu Etkiler

Bazı etkiler sadece süreye değil, özel durumlara bağlıdır:
* **Lonca Becerileri:** Eğer oyuncu lonca savaşında değilse veya loncadan çıktıysa, üzerindeki ejderha yardımı gibi lonca kutsamaları anında silinir.
* **Silah Bağımlılığı:** Bazı beceriler (Hava Kılıcı gibi) sadece silah takılıyken etkilidir. Eğer silah çıkarılırsa etki düşer:
```cpp
if (!GetWear(WEAR_WEAPON)) {
if (IsAffectFlag(AFF_GEOMGYEONG)) RemoveAffect(SKILL_GEOMKYUNG);
}
```
* **Premium Üyelikler:** Işınlanma yüzüğü, tecrübe yüzüğü gibi premium etkiler, sunucunun global zamanına (`GetPremiumRemainSeconds`) göre kontrol edilir ve süre bittiğinde silinir.

## 5.4. Veri Güvenliği ve Kayıt (`SaveAffect`)

Oyuncu oyundan çıktığında üzerindeki etkilerin kaybolmaması gerekir (Örn: 10 dakikalık şebnem bastıysa geri girdiğinde devam etmelidir).
* **SaveAffect:** Oyuncunun etkileri `db` sunucusuna `HEADER_GD_ADD_AFFECT` paketiyle gönderilir ve MySQL'deki `affect` tablosuna yazılır.
* **Yükleme (`LoadAffect`):** Oyuncu tekrar girdiğinde bu bilgiler MySQL'den okunur. Ancak burada bir **Trick (Hile)** vardır: Etkiler karakter tamamen oyuna girdikten (`PHASE_GAME`) sonra yüklenmelidir. Eğer karakter hala yükleme ekranındaysa, sistem bir `load_affect_login_event` (Zamanlayıcı) oluşturarak karakterin oyuna tam girmesini bekler.

## 5.5. Affect Flags (Görsel İşaretler)

Bazı etkiler karakterin üzerinde görsel bir değişiklik yapar (Parlama, isim rengi değişimi vb.). Bu durum `m_afAffectFlag` (Bitset) ile kontrol edilir. Örneğin, zehirlenen bir karakterin isminin ve modelinin yeşile dönmesi bu flag üzerinden sağlanır.

---
**Geliştirici Notu:** "Affect Bug" olarak bilinen, süresi biten etkilerin silinmemesi sorunu genellikle `ProcessAffect` döngüsündeki bir performans dar boğazından veya `event_cancel` fonksiyonunun yanlış çağrılmasından kaynaklanır. Sizin dosyanızdaki `if (--pkAff->lDuration <= 0)` kontrolü, her saniye garantili bir düşüş sağladığı için bu sistem oldukça stabildir.

Metin2 dünyasındaki tüm canlıların (oyuncular, canavarlar ve NPC'ler) orkestra şefi `CHARACTER_MANAGER` sınıfıdır. Bu sınıf, varlıkların yaratılması, yok edilmesi ve dünya üzerindeki konumlarının orkestrasyonunu yapar. `char_manager.cpp` dosyası, bu yönetim sisteminin beynidir.

## 6.1. Varlık Takibi ve Arama (Find)

Sunucu, binlerce karakter arasından birini çok hızlı bulmak zorundadır. `CHARACTER_MANAGER`, karakterleri üç farklı yöntemle indeksler ve arar:

1. **VID (Virtual ID) ile Arama:** `Find` fonksiyonu, karakterin anlık oturumu boyunca geçerli olan sanal ID üzerinden arama yapar. Bu ID her karakter yaratıldığında artan bir sayıdır.
2. **PID (Player ID) ile Arama:** `FindByPID`, sadece oyuncular için geçerli olan ve veritabanındaki `id` sütununa karşılık gelen kalıcı kimlik üzerinden arama yapar. Ticaret ve fısıltı gibi işlemlerde bu kullanılır.
3. **İsim ile Arama:** `FindPC`, oyuncu adıyla (büyük/küçük harf duyarsız - `str_lower`) arama yapar.

```cpp
LPCHARACTER found = it->second;
if (found != NULL && dwPID != found->GetPlayerID()) {
sys_err("[CHARACTER_MANAGER::FindByPID] %u != %u", dwPID, found->GetPlayerID());
}
```
*Geliştirici Notu:* Kodda görülen bu "Sanity Check" (Mantık Kontrolü), bellek hataları nedeniyle yanlış karakterin bulunmasını engelleyen kritik bir güvenlik önlemidir.

## 6.2. Canavar Doğurma (Spawn) Mekanikleri

Canavarlar haritaya gelişigüzel bırakılmaz. `SpawnMob` ve `SpawnMobRandomPosition` fonksiyonları şu kuralları uygular:

* **Attribute Kontrolü:** Bir yaratık asla bir duvarın içine (`ATTR_BLOCK`) veya bir objenin üzerine (`ATTR_OBJECT`) doğamaz. Kod, harita üzerindeki `Sectree` verisini tarayarak geçerli bir nokta bulana kadar (deneme limiti 2000'dir) konum arar.
* **Etkinlik Kontrolü:** Bazı canavarlar sadece belirli etkinlikler (`japan_regen`, `newyear_mob`) aktifse doğabilir. Eğer ilgili `EventFlag` kapalıysa, doğuş işlemi iptal edilir.
* **İmparatorluk Ataması:** Eğer bir NPC'nin imparatorluğu yoksa, doğduğu haritanın ait olduğu imparatorluğa otomatik olarak atanır.

## 6.3. Alan (Range) Bazlı Doğum

`SpawnMobRange` fonksiyonu, canavarların belirli bir koordinat aralığında (`sx, sy` to `ex, ey`) dağılmasını sağlar.
* **Z-Section:** Haritanın yüksekliği (Z koordinatı) genellikle zemin seviyesine (`GetHeight`) göre otomatik ayarlanır.
* **Rotation (Yön):** Canavarlar haritaya rastgele yönlere bakarak doğarlar, bu da doğal bir görünüm sağlar.

## 6.4. Grup Doğumları (SpawnGroup)

Metin2'de canavarlar genellikle tek tek değil, gruplar (`group.txt`) halinde dolaşırlar. `SpawnGroup` fonksiyonu, bir grup liderini ve ona bağlı korumaları aynı koordinatlarda, birbirine yakın şekilde yaratır.

---
**Geliştirici Notu:** `CHARACTER_MANAGER` içindeki en tehlikeli işlemler karakter silme (`M2_DESTROY_CHARACTER`) süreçleridir. Eğer bir karakter tam olarak silinmeden bellekte kalırsa "Zombie Character" oluşur ve bu durum sunucunun zamanla şişip çökmesine neden olur. Modern source dosyalarında bu sızıntıları önlemek için `SMART_PTR` kullanımına benzer akıllı bir havuz (`DynamicPool`) yapısı bulunur.

Metin2'nin savaş döngüsü sadece karakterlerin birbirine vurmasından ibaret değildir. Hasarın uygulanması, karakterin bayılması (Stun), ölümü ve ölüm sonrası cezaların (EXP kaybı) yönetimi `char_battle.cpp` dosyası içerisinde koordine edilir.

## 7.1. Saldırı Mekanizması (`Attack`)

Bir karakter saldırı başlattığında `Attack` fonksiyonu şu süzgeçlerden geçer:
* **Güvenli Alan Kontrolü:** Eğer kurban bir pazar (`MyShop`) veya bir NPC ise saldırı iptal edilir.
* **Harita Kontrolü:** Kale savaşı (`Castle Map`) gibi özel haritalarda ırkların birbirine vuruş yetkileri denetlenir.
* **Savaş Türü Dağıtımı:** Karakterin tipine (`BATTLE_TYPE`) göre saldırı dallanır:
* `MELEE`: Yakın dövüş hasarı hesaplanır.
* `RANGE`: Hedef belirlenir (`FlyTarget`) ve ok/kurşun gibi bir mermi fırlatılır (`Shoot`).
* `MAGIC`: Büyülü saldırı mekanizması devreye girer.

## 7.2. Bayılma Sistemi (`Stun`)

Oyundaki en sinir bozucu ama kritik mekanizmalardan biri sersemlemedir.
* **İşlem Kısıtlaması:** Karakter Stun yediğinde `INSTANT_FLAG_STUN` bayrağı aktif olur. Bu durumda hareket edemez, saldırı yapamaz ve pazar açamaz (`CloseMyShop`).
* **İyileşme Durması:** Stun yiyen karakterin doğal HP/SP yenilenmesi (`RecoveryEvent`) durdurulur.
* **Zamanlayıcı:** 3 saniyelik bir `StunEvent` oluşturulur. Süre bittiğinde baygınlık durumu kalkar veya karakter hala saldırı altındaysa `Dead` fonksiyonuna yönlendirilebilir.

## 7.3. Ölüm ve Yeniden Doğuş (`Dead` ve `dead_event`)

Karakterin canı %0'a ulaştığında ölüm süreci başlar:
1. **Zamanlayıcı:** 3 dakikalık bir `dead_event` başlar (Yeniden başla butonunun süresi).
2. **Yeniden Başlama Seçenekleri:**
* **Burada Başla:** Eğer oyuncu "Burada Başla" derse, karakter canlanır ama 3 saniye Stun (Baygınlık) ve hayalet moduyla başlar.
* **Şehirde Başla:** Eğer `dead_event` süresi biterse veya oyuncu şehirde başla derse, karakter kendi krallığının başlangıç koordinatlarına (`GetRecallPositionByEmpire`) ışınlanır.
3. **Hayati Değerler:** Canlanan karakter tam canla değil, genellikle yarı canla (`GetMaxHP / 2`) oyuna döner.

## 7.4. Ölüm Cezası ve EXP Kaybı (`DeathPenalty`)

Metin2'deki meydan okuma unsurlarından biri öldüğünüzde tecrübe puanı (EXP) kaybetmenizdir.
* **Sınır:** 10. seviyenin altındaki karakterler koruma altındadır, EXP kaybetmezler.
* **Şans Faktörü:** Her ölümde EXP kaybetme zorunluluğu yoktur (`number(0, 2)` ile %33 şansla yırtabilirsiniz).
* **Hesaplama:** Kaybedilen EXP, bir sonraki seviye için gereken puanın belirli bir yüzdesidir (`aiExpLossPercents`).
* **Azaltıcılar:** Eğer karakterde "Tanrıça Gözyaşı" (`TEARDROP_OF_GODNESS`) varsa EXP kaybı yarı yarıya azalır.

## 7.5. Canavar Dirilme Mekanizması

Bazı özel canavarların "Dirilme" yeteneği vardır. Eğer ölen canavar bir Boss veya özel koruma ise:
```cpp
if (ch->IsRevive() == false && ch->HasReviverInParty() == true) {
ch->SetHP(ch->GetMaxHP());
ch->SetRevive(true);
}
```
Bu kod sayesinde canavar bir kez öldükten sonra "yalan söyleyerek" (Revive) ful canla tekrar ayağa kalkıp oyuncuya saldırmaya devam eder.

---
**Geliştirici Notu:** `char_battle.cpp` içerisindeki `HACK: Too long skill using term` logu, oyun içi bekleme sürelerini (Cooltime) hile ile kaldıran oyuncuları tespit etmek için kullanılır. Eğer bir oyuncu skili olması gerekenden çok daha hızlı kullandıysa, sunucu bunu "Hack" olarak işaretler ve işlemi iptal eder.

Metin2'nin en ikonik özelliklerinden biri olan at ve binek sistemi, `char_horse.cpp` dosyası tarafından yönetilir. Bu sistem, atın çağrılmasından (Summon), üzerine binilmesine (Riding) ve atın sağlığının/açlığının takibine kadar geniş bir yelpazeyi kapsar.

## 8.1. At Çağırma Mekanizması (`HorseSummon`)

Bir oyuncu atını çağırdığında (`HorseSummon(true)`), arka planda şu işlemler gerçekleşir:
* **Mesafe Hesaplama:** Eğer at "uzaktan" çağrılıyorsa (`bFromFar`), karakterin 20-25 metre uzağında doğar ve karakterin yanına doğru koşmaya başlar. Eğer normal çağrılıyorsa hemen dibinde belirir.
* **İsimlendirme:** Atın ismi öncelikle `CHorseNameManager` üzerinden kontrol edilir. Eğer oyuncu atına özel bir isim verdiyse o isim, yoksa "OyuncuAdı'nın Atı" şeklinde bir isim atanır.
* **Sağlık Kontrolü:** Eğer atın canı 0 ise, at "ölü" pozisyonunda (`POS_DEAD`) doğar ve oyuncunun onu canlandırması (Bitki kullanımı) gerekir.

## 8.2. Binicilik ve Kısıtlamalar (`StartRiding`)

Ata binmek her zaman mümkün değildir. Kod seviyesindeki engeller şunlardır:
* **Dönüşüm:** Eğer oyuncu bir dönüşüm küresi (`Polymorph`) kullanmışsa ata binemez.
* **Özel Zırhlar:** Bazı zırhlar (Örn: Gelinlik/Damatlık - Vnum `11901-11904`) ile ata binmek engellenmiştir.
* **Harita Engeli:** Düello arenaları (`Arena Map`) gibi bazı haritalarda binicilik tamamen devre dışıdır.
* **At Durumu:** Atın seviyesi 0 ise, açlıktan enerjisi bittiyse veya canı yoksa `StartRiding` fonksiyonu başarısız olur.

## 8.3. İnebilme ve Atı Gönderme (`StopRiding`)

Attan inildiğinde:
* **Warp Senkronizasyonu:** Oyuncunun koordinatları binek üzerinden normal zemine çekilir.
* **Statü Silinme:** At üzerindeyken gelen statü bonusları (`POINT_ST, DX, HT, IQ`) sıfırlanır.
* **Atın Akıbeti:** At ya tamamen yok edilir (`M2_DESTROY_CHARACTER`) ya da oyuncunun arkasında beklemeye devam eder.

## 8.4. At Becerileri Kullanım Hakları (`CanUseHorseSkill`)

At üzerindeyken beceri kullanabilmek için (Örn: At Üzerinde Saldırı) şu şartlar aranır:
* **At Seviyesi:** Atın derecesi (`Horse Grade`) 3 (Asker At) olmalıdır.
* **Binek İstisnaları:** Bazı özel binekler (Örn: Siyah At, Fırtına Kaplanı) at seviyesine bakılmaksızın beceri kullanımına izin verecek şekilde kodlanmıştır (`CMobVnumHelper::IsRamadanBlackHorse`).

## 8.5. At Bilgilerinin Arayüze Gönderilmesi (`SendHorseInfo`)

Atın açlık ve sağlık durumu istemciye (Client) 4 kademeli (`Grade`) bir sistemle gönderilir:
1. **Grade 3:** %70 - %100 arası (Sağlıklı/Tok).
2. **Grade 2:** %30 - %70 arası.
3. **Grade 1:** %0 - %30 arası.
4. **Grade 0:** %0 (Aç veya Ölü).
Bu derecelendirme, Python tarafında at simgesinin renginin değişmesini (Yeşil, Sarı, Kırmızı) sağlar.

---
**Geliştirici Notu:** Atın hızını değiştirmek isterseniz, `char_horse.cpp` yerine `CHorseRider` sınıfının temel değerlerine bakmalısınız. Ancak hızı sadece sunucuda artırmak yetmez; istemci (Client) tarafındaki `InstanceBase` üzerinde de benzer bir hız artışı yapılmalıdır, aksi takdirde karakter at üzerindeyken "sekme" (Rubberbanding) yapacaktır.

Oyun sunucusu açılırken, `db` sunucusundan gelen ham canavar verilerini (`mob_proto`) anlamlı nesnelere dönüştüren ve canavar gruplarını yöneten birim `CMobManager`'dır. `mob_manager.cpp` dosyası, sunucunun canavarları hafızada nasıl organize ettiğini belirler.

## 9.1. Mob Proto'nun RAM'e Yüklenmesi (`Initialize`)

Sunucu açılışında `Initialize` fonksiyonu, veritabanından gelen tüm canavar tablosunu tarar:
* **Vnum ve İsim İndeksleme:** Canavarlar hem Vnum (`m_map_pkMobByVnum`) hem de isim (`m_map_pkMobByName`) üzerinden iki farklı `map` yapısında saklanır. Bu, canavarların adıyla veya koduyla çok hızlı bulunmasını sağlar.
* **İstatistik Kaydı:** Her canavarın Level, HP, Defans ve EXP gibi değerleri `TMobTable` yapısından bellek nesnesine (`CMob`) kopyalanır.
* **NPC Kaydı:** Eğer canavarın tipi `CHAR_TYPE_NPC` ise, bu canavar otomatik olarak `QuestManager`'a kaydedilir. Böylece üzerindeki questlerin (Tıklandığında açılan pencereler) çalışması sağlanır.

## 9.2. Canavar Grupları (`LoadGroup`)

Metin2'de canavarlar genellikle `group.txt` içerisinde tanımlanan timler halinde hareket ederler:
* **Lider sistemi:** Her grubun bir lideri (`leader`) ve bu lider öldüğünde veya saldırdığında ona eşlik eden üyeleri vardır.
* **Grup Hashleme:** Gruplar Vnum değerlerine göre `m_map_pkMobGroup` içerisinde tutulur. `SpawnGroup` çağrıldığında sunucu bu listeden ilgili grubu bulup tüm üyelerini aynı anda haritaya yerleştirir.

## 9.3. Grup Grupları (`LoadGroupGroup`)

Bazı haritalarda (Örn: Örümcek Zindanı), belirli bir bölgede hangi canavar grubunun doğacağı rastgele belirlenir. Bu, `group_group.txt` dosyasıyla yönetilir:
* **Olasılık Dağıtımı:** Bir `GroupGroup` içerisinde birden fazla grup Vnum'u bulunur. Sunucu, bu liste içerisinden birini rastgele seçerek doğumu gerçekleştirir.
* **Çeşitlilik:** Bu sayede aynı koordinatta bazen "3 Pençeli Örümcek", bazen de "2 Örümcek + 1 Göz" grubu doğabilir.

## 9.4. Regen Sayacı ve İstatistik (`IncRegenCount`)

`CMobManager`, sunucu performansını optimize etmek veya harita yoğunluğunu analiz etmek için bir "Doğum Sayacı" tutar:
* **Günlük Tahmin:** `IncRegenCount` fonksiyonu, bir canavarın 24 saat içerisinde (`86400 / iTime`) o haritada yaklaşık kaç kez doğacağını hesaplar.
* **Raporlama:** `DumpRegenCount` fonksiyonu ile bu veriler bir dosyaya yazdırılabilir. Eğer bir haritada canavar sayısı aşırı fazlaysa (Lag nedeni), bu rapor üzerinden optimizasyon yapılır.

## 9.5. Proto Yeniden Bağlama (`RebindMobProto`)

Sunucu çalışırken GM komutuyla veya bir etkinlik nedeniyle `mob_proto` güncellenirse, haritadaki mevcut canavarların da bu değişikliklerden etkilenmesi gerekir. `RebindMobProto` fonksiyonu, haritadaki canlıları tek tek gezerek (PC'ler hariç) verilerini güncel proto ile senkronize eder.

---
**Geliştirici Notu:** `Initialize` fonksiyonundaki `thecore_shutdown()` çağrılarına dikkat edin. Eğer `group.txt` veya `group_group.txt` dosyalarınızda bir sözdizimi (Syntax) hatası varsa veya dosya eksikse, sunucu açılış işlemini anında durdurur. Sunucunuz açılmıyorsa "syserr" dosyasındaki "cannot load group.txt" hatasını aramalısınız.



Metin2'de zindanlar (Örn: Şeytan Kulesi, Ejderha Odası, Örümcek Barones), her grubun veya oyuncunun kendine özel bir "harita kopyasında" oynamasını sağlayan sistemlerdir. Bu bölüm, `dungeon.cpp` ve `dungeon_manager.cpp` dosyalarını baz alarak bu "izole dünya" mantığını açıklar.

## 3.1. Private Map (Özel Harita) Nedir?

Normal bir haritada (Örn: 1. Köy) tüm oyuncular aynı dünyadadır. Ancak bir zindana girdiğinizde, sunucu o haritanın **sadece sizin için** bir kopyasını oluşturur.
* **Original Map Index:** Haritanın temel kodu (Örn: 66 - Şeytan Kulesi).
* **Private Map Index:** Sunucu tarafından o an üretilen benzersiz kopya numarası (Örn: 660001).

## 3.2. Zindan Yaşam Döngüsü

### 1. Zindanın Oluşturulması (`CDungeonManager::Create`)
Zindan bir NPC veya görev aracılığıyla tetiklendiğinde `Create` fonksiyonu çalışır:
1. `SECTREE_MANAGER` haritanın bellekteki bir kopyasını oluşturur.
2. Zindana benzersiz bir `id` atanır.
3. Zindan nesnesi (`LPDUNGEON`) belleğe yerleşir.

### 2. Oyuncu Girişi (`CDungeon::Join`)
Oyuncu zindana girdiğinde `Join` veya `JoinParty` çağrılır. Bu fonksiyon, oyuncuyu veya tüm grubunu (Party) yeni oluşturulan `m_lMapIndex` (Özel Harita) koordinatlarına ışınlar (`WarpSet`).

### 3. Zindanın Boşalması ve Silinme (`DecMember`)
Zindanlar sunucu kaynaklarını (RAM) korumak için içeride kimse kalmadığında kendi kendini yok eder:
* Her oyuncu çıktığında `DecMember` çağrılır.
* Eğer zindandaki oyuncu sayısı 0 olursa, 10 saniyelik bir `deadEvent` (Zamanlayıcı) oluşturulur.
* 10 saniye içinde kimse girmezse `CDungeonManager::Destroy` tetiklenir ve harita kopyası bellekten silinir.

## 3.3. Benzersiz Canavarlar (Unique Mobs)

Zindanların en büyük özelliği, zindan içindeki boss veya özel canavarlara C++ kodlarından doğrudan müdahale edilebilmesidir.
* **Unique Set:** `UniqueSetMaxHP` gibi fonksiyonlar, sadece o zindan kopyasındaki belirli bir canavarın özelliklerini değiştirmeyi sağlar.
* Örneğin: "X canavarı öldüğünde Y kapısı açılsın" gibi bir mantık, canavarın zindan içindeki `Unique` kimliği üzerinden yürütülür.

## 3.4. Grup (Party) Hakimiyeti

Zindanlar genellikle grup çalışması içindir. `JoinParty` fonksiyonu, grubun her bir üyesini `ForEachOnlineMember` döngüsüyle zindana çeker. Grup lideri zindandan çıksa bile, zindan nesnesi grup üyelerinden biri içeride olduğu sürece yaşamaya devam eder.

## 3.5. Zindan Bayrakları (Dungeon Flags)

Zindan içindeki aşamaları (Örn: "2. kattasınız", "Anahtarı buldunuz") takip etmek için `SetFlag` ve `GetFlag` fonksiyonları kullanılır. Bu veriler sadece o zindan kopyasına hastır. Bir gruptakinin anahtarı bulması, diğer gruptakilerin zindanını etkilemez.

---
**Geliştirici Notu:** Zindan kodlarında yapılan en büyük hata, zindanı yok etmeyi (Destroy) unutmaktır. Eğer bir zindanda `DecMember` mantığı hatalıysa, oyuncular çıktıktan sonra bile haritalar RAM'de kalmaya devam eder ve sunucu bir süre sonra "Out of Memory" hatasıyla çökebilir. Sizin projenizdeki `deadEvent` mekanizması bu sızıntıyı önleyen en sağlıklı yöntemdir.

Metin2'de canavarların ve nesnelerin nasıl kendi başlarına hareket ettikleri, ne zaman saldıracakları ve canları azaldığında ne yapacakları `char_state.cpp` dosyasında tanımlanan **State Machine (Durum Makinesi)** ile yönetilir. Bu bölüm, oyunun yapay zekasının "karar verme" süreçlerini analiz eder.

## 2.1. Metin Taşlarının Yapay Zekası (`__StateIdle_Stone`)

En ilgi çekici yapay zeka örneklerinden biri Metin Taşlarıdır. Bir "taş" olmasına rağmen, aslında arka planda çok aktif bir durum takip sistemi çalışır.

### Kod Analizi: Can Azaldıkça Canavar Doğurma
Metin taşları, canları (`HP`) düştükçe çevrelerine canavar grupları (Spawn Group) çağırırlar. Kodda bu durum `m_pointsInstant.m_dwMaxSP` değeri ile işaretlenir (Taşın aslında SP'si yoktur, sadece kaçıncı aşamada olduğunu takip etmek için bu değişkeni kullanır):

```cpp
if (iPercent <= 10 && GetMaxSP() < 10) {
SetMaxSP(10);
CHARACTER_MANAGER::instance().SpawnGroup(dwVnum, GetMapIndex(), ...);
}
```
* **Aşamalılık:** Taş %90, %80 ... %10 can değerlerine her ulaştığında bir kez canavar doğurur.
* **Doğrulama:** `GetMaxSP() < 10` kontrolü, aynı aşamanın tekrar tekrar tetiklenmesini (Bug) engeller.

## 2.2. Korkak Canavarlar ve Kaçma Mantığı (`CowardEscape`)

Bazı canavarların `AIFLAG_COWARD` (Korkak) bayrağı vardır. Bu canavarlar oyuncuya vurmak yerine ondan kaçmayı tercih eder.
1. **Yön Seçimi:** Canavar rastgele bir açı (`SetRotation`) seçer.
2. **Mesafe Hesaplama:** 5 metreden 50 metreye (`500` - `5000`) kadar bir kaçış mesafesi belirler.
3. **Yol Kontrolü:** `SECTREE_MANAGER::instance().IsMovablePosition` ile kaçacağı yönde bir engel (Duvar, Dağ) olup olmadığını kontrol eder.
4. **Hareket:** Eğer yol temizse, canavar o noktaya ışınlanmak yerine gerçekten "koşarak" gider (`Goto`).

## 2.3. Saldırganlık Türleri ve AI Bayrakları (AIFLAGS)

Canavarların davranışlarını belirleyen çeşitli bayraklar vardır:
* `AIFLAG_BERSERK`: Canı azaldığında daha hızlı saldırır.
* `AIFLAG_STONESKIN`: Fiziksel savunması anlık olarak artar.
* `AIFLAG_REVIVE`: Öldüğünde bir kez uyanma (Dirilme) şansı vardır.
* `AIFLAG_ATTACKMOB`: Bazı agresif moblar sadece oyunculara değil, diğer canavarlara da saldırabilir.

## 2.4. İmparatorluk Koruması (`NoAttack`)

Bazı NPC'lerin veya özel yaratıkların belirli imparatorluklara saldırmaması sağlanabilir:
* `AIFLAG_NOATTACKSHINSU`: Kırmızı krallığa saldırmaz.
* `AIFLAG_NOATTACKCHUNJO`: Sarı krallığa saldırmaz.
* `AIFLAG_NOATTACKJINNO`: Mavi krallığa saldırmaz.

## 2.5. Bekleme Durumu (`StateIdle`)

Bir canavar kimseyle savaşmıyorsa `StateIdle` durumundadır.
1. **PC ise:** Hiçbir şey yapma (Hareket kontrolü oyuncudadır).
2. **NPC ise:** Sabit dur veya varsa önceden tanımlı "Patrol" (Devriye) yolunda yürü.
3. **Monster ise:** Etrafındaki oyuncuları ("Agro Range") tara. Eğer bir oyuncu menzile girerse `StateBattle` durumuna geç ve saldırmaya başla.

---
**Geliştirici Notu:** Eğer bir mobun (Örn: Bir Bosun) canı bittiğinde çok fazla canavar doğurduğunu veya hiç doğurmadığını düşünüyorsanız, `char_state.cpp` içerisindeki `iPercent` kontrollerini ve `SpawnGroup` fonksiyonlarındaki koordinat sapmalarını (`GetX() - 1000`) düzenleyerek bu dengeyi sağlayabilirsiniz.

Metin2 haritalarının "canlı" kalmasını sağlayan, canavarların ve NPC'lerin belirli aralıklarla haritaya doğmasını yöneten sistem `regen.cpp` içerisinde tanımlanır. Bu sistem, harita dosyalarında bulunan `regen.txt`, `npc.txt` ve `boss.txt` gibi dosyaların nasıl işlendiğini ve yaratıkların hangi mantıkla haritaya yerleştirildiğini belirler.

## 3.1. Regen Türleri ve Parametreleri

Sunucu bir haritayı yüklediğinde `regen_do` fonksiyonu çalışır ve şu yaratık türlerini belleğe alır:

* **m (Mob):** Tek bir canavar doğumu.
* **g (Group):** `group.txt` içerisinde tanımlı bir grubun (Örn: 3 Yabani Köpek) doğumu.
* **r (Group Group):** `group_group.txt` içerisindeki birden fazla gruptan birinin rastgele seçilip doğurulması.
* **s (Anywhere):** Haritanın herhangi bir uygun (engelsiz) noktasına rastgele doğum.

## 3.2. Zamanlama ve Geri Sayım (`regen_time`)

Canavarlar öldükten sonra ne zaman tekrar doğacaklarını belirleyen `time` parametresi, C++ tarafında akıllıca parse edilir. Kodda `h` (saat), `m` (dakika) ve `s` (saniye) takıları algılanarak toplam saniyeye dönüştürülür:
```cpp
case 'h': regen->time += tmpTime * 3600; break;
case 'm': regen->time += tmpTime * 60; break;
case 's': regen->time += tmpTime; break;
```
Eğer `regen.txt` içerisinde süre olarak `10m` yazılmışsa, sunucu o yaratık öldükten tam 600 saniye sonra tekrar doğum tetiklemesi yapar.

## 3.3. Doğum Alanı Hesaplama (SX, SY, EX, EY)

Yaratıkların doğacağı alanlar birer dikdörtgen bölge olarak tanımlanır.
* **SX, SY:** Başlangıç koordinatları.
* **EX, EY:** Bitiş koordinatları.
Metin2 harita koordinatları `x100` çarpanı ile çalışır. Kod, dosyadan okuduğu koordinatları sunucunun içsel koordinat sistemine çevirir (`regen->sx *= 100`). Eğer `SX=EX` ve `SY=EY` ise, yaratık her zaman tam olarak o noktada doğar (Sabit NPC mantığı).

## 3.4. Zindan Doğuşları ve Event Sistemi

Zindanlardaki (`Dungeon`) doğumlar normal haritalardan farklıdır. Bir zindanda `dungeon_regen_event` kullanılır.
* **İzole Zaman:** Her zindan kopyasının kendi doğum zamanlayıcısı vardır.
* **Otomatik Silinme:** Zindan yok edildiğinde, o zindana bağlı tüm `regen` eventleri de `event_cancel` ile temizlenir. Bu sayede sunucu hafızası korunur.

## 3.5. Regen Exceptions (Doğum İstisnaları)

Bazı bölgelerde canavar doğması istenmez (Örn: Köy içi güvenli alanlar). `is_regen_exception` fonksiyonu, bir koordinatın "yasaklı bölge" (`regen_exception_list`) içerisinde olup olmadığını kontrol eder. Eğer yaratık o alana düşerse doğum iptal edilir.

---
**Geliştirici Notu:** `regen.txt` dosyalarınızda bir yaratığın süresini `0` (sıfır) yaparsanız, o yaratık öldüğü anın bir saniye sonrasında tekrar doğar. Ancak bu durum, çok sayıda yaratığın olduğu haritalarda sunucuya anlık yük bindirebilir. Performans için "Boss" ve "Metin Taşı" gibi yoğun işlem gerektiren nesnelerin sürelerini en az birkaç dakika tutmak her zaman daha sağlıklıdır.

Metin2'nin dünyası, birbirine bağlı onlarca haritadan ve bu haritaları yöneten karmaşık bir koordinat sisteminden oluşur. Sistemin kalbinde `SECTREE_MANAGER` (Dünya ve Bölge Yöneticisi) ve `CMapLocation` (Harita Konum Takibi) sınıfları yer alır. Bu bölüm, sunucunun haritaları nasıl yüklediğini ve oyuncuları doğru noktaya nasıl ışınladığını analiz eder.

## 4.1. Harita Koordinat Yapısı: BasePosition ve Local

Metin2 haritaları iki farklı koordinat sistemiyle çalışır:
* **Küresel (Global) Koordinat:** Tüm oyun dünyasındaki benzersiz konumdur (Örn: `BaseX + LocalX`).
* **Yerel (Local) Koordinat:** Haritadaki 0,0 noktasına göre olan konumdur.
`Setting.txt` dosyası içerisindeki `BasePosition` (Örn: 969600, 225600), o haritanın dünyadaki başlangıç noktasını belirler. Sunucu, oyuncu hareketlerini her zaman bu "Global" sayılar üzerinden takip eder.

## 4.2. Sectree: Haritayı Bölgelere Ayırmak

Devasa bir haritanın (Örn: Sürgün Mağarası) her hareketini tek seferde işlemek imkansızdır. `SECTREE_MANAGER`, haritaları `128x128` (veya `64x64`) birimlik küçük karelere (`SECTREE`) böler:
* **Entity Takibi:** Oyuncular, canavarlar ve eşyalar bulundukları `Sectree` içerisine kaydedilir.
* **Verimlilik:** Sunucu, size paket gönderirken tüm haritayı değil, sadece bulunduğunuz `Sectree` ve komşu 8 karedeki olayları tarar. Bu, işlemci yükünü muazzam ölçüde azaltır.

## 4.3. Harita Özellikleri: Server Attr (`LoadAttribute`)

Haritanın neresinde yürünebileceği (`ATTR_BLOCK`), neresinde balık tutulabileceği (`ATTR_WATER`) ve neresinin güvenli alan (`ATTR_BANPK`) olduğu `server_attr` dosyasında saklanır.
* **LZO Sıkıştırma:** Bu veri çok büyük olduğu için `LZOManager` ile sıkıştırılmış olarak diskte tutulur.
* **Belleğe Yükleme:** Sunucu açılırken bu dosyayı decompress eder (açar) ve her bir hücre (`CELL`) için hangi özelliklerin aktif olduğunu RAM'e yansıtır.

## 4.4. Sunucular Arası Işınlanma (Warp) ve Portlar

Metin2'de her harita aynı sunucu (Core/Process) üzerinde olmayabilir. Örneğin, CH1 bir sunucuda, CH2 başka bir sunucuda veya Şeytan Kulesi farklı bir portta çalışabilir.
* **CMapLocation:** Bu sınıf, hangi Harita ID'sinin hangi IP adresinde ve hangi Portta çalıştığını tutan bir haritadır (`m_map_address`).
* **Warp İşlemi:** Oyuncu bir portala girdiğinde, `CMapLocation::Get` çağrılarak kule haritasının adresi alınır. İstemciye (Client) "Şu IP ve Porta bağlan" talimatı gönderilir.

## 4.5. Şehirde Başla Mantığı (`GetRecallPositionByEmpire`)

Ölen bir oyuncu "Şehirde Başla" dediğinde sistem `TMapRegion` listesine bakar:
1. Oyuncunun bulunduğu harita indexini bulur.
2. `bEmpireSpawnDifferent` bayrağına bakar. Eğer haritada her krallık için farklı başlangıç noktası varsa (Örn: 1. Köy), oyuncuyu kendi krallığının (`posEmpire[empire]`) koordinatına yollar.
3. Eğer ortak bir alan ise (Örn: Çöl), varsayılan `posSpawn` noktasına ışınlar.

---
**Geliştirici Notu:** "Map Index Mismatch" veya "Haritaya girerken oyundan atma" hataları genellikle `Setting.txt` içerisindeki harita boyutuyla `server_attr` dosyasının boyutunun uyuşmamasından kaynaklanır. `BuildSectreeFromSetting` fonksiyonu bu boyutu hesaplarken bir hata bulursa sunucu `FATAL ERROR` vererek açılışı durdurur. Bu durumda `server_attr` dosyasını harita editörüyle tekrar kaydetmek tek çözümdür.

Metin2'nin zindan sistemi, binlerce oyuncuyu ayrı kopyalarda (Instances) ağırlayabilen muazzam bir mimariye sahiptir. Bu sistemin yönetimi `Dungeon.cpp` dosyası içerisindeki `CDungeon` ve `CDungeonManager` sınıfları aracılığıyla yapılır. Bu bölüm, zindanların nasıl yaratıldığını, oyuncuların nasıl bağlandığını ve zindanların nasıl kendi kendini yok ettiğini analiz eder.

## 5.1. Zindanların Doğuşu: Private Map

Her yeni zindan girişi, aslında temel bir haritanın (Örn: Şeytan Kulesi) bellekteki sanal bir kopyasıdır:
* **CreatePrivateMap:** `DungeonManager`, bir zindan isteği geldiğinde `SECTREE_MANAGER` üzerinden benzersiz bir `MapIndex` oluşturur.
* **İzole Dünya:** Bu yeni index, sadece o zindana giren oyuncu veya grup için geçerlidir. Dışarıdaki kimse bu haritaya giremez.

## 5.2. Oyuncu ve Grup Bağlantısı (`Join` ve `JoinParty`)

Bir zindana karakterlerin dahil edilmesi iki şekilde olur:
* **Bireysel Katılım (`Join`):** Tek bir oyuncu zindana ışınlanır.
* **Grup Katılımı (`JoinParty`):** Tüm grup üyeleri aynı zindan hattına (`m_lMapIndex`) yönlendirilir.
* **Warp Senkronizasyonu:** `FWarpToDungeon` yapısı kullanılarak, tüm oyuncuların eski konumları kaydedilir (`SaveExitLocation`) ve zindandaki başlangıç noktalarına toplu halde ışınlanırlar.

## 5.3. Üye Takibi ve Kendi Kendini Yok Etme (Auto-Destroy)

Sunucu kaynaklarını korumak için, içinde kimse kalmayan zindanların silinmesi hayati önem taşır:
* **Sayaçlar (`IncMember` / `DecMember`):** Zindana giren her karakter sayacı artırır, çıkan her karakter azaltır.
* **Dead Event:** Zindandaki son oyuncu da ayrıldığında (`m_set_pkCharacter.empty()`), 10 saniyelik bir `dungeon_dead_event` zamanlayıcısı başlar.
* **Temizlik:** Eğer bu 10 saniye içinde kimse geri gelmezse, `CDungeonManager::Destroy` fonksiyonu çağrılır; harita bellekten silinir ve zindana bağlı tüm canavarlar yok edilir.

## 5.4. Toplu Taşıma: Jump ve Warp Mekanikleri

Zindan içindeki aşamalarda (Örn: Kattan kata geçiş) tüm grubu hareket ettirmek için özel fonksiyonlar kullanılır:
* **JumpAll:** Belirli bir bölgedeki tüm oyuncuları hedef bir koordinata (`x, y`) "zıplatır".
* **WarpAll:** Oyuncuların yükleme ekranı görmesini sağlayarak (Harita geçişi gibi) koordinat değiştirir.
* **Sanal Koordinat:** Koordinat değerleri sunucuda her zaman 100 çarpanıyla işlenir (`x *= 100`), bu da milimetrik hassasiyet sağlar.

## 5.5. Unique (Benzersiz) Boss Yönetimi

Zindanlarda bazen "Anahtarı düşüren boss" veya "Kilit taşı" gibi özel nesneler bulunur. `CDungeon`, bu nesneleri bir `UniqueMobMap` içerisinde saklar:
* **Özel Komutlar:** Lua üzerinden bu bossların canı (`UniqueSetHP`) veya defansı (`UniqueSetDefGrade`) karakter bazlı değil, zindan bazlı olarak dinamik olarak değiştirilebilir.
* **Takip:** Eğer bu benzersiz yaratık ölürse, zindan motoru otomatik olarak bir sonraki "Quest" tetiğini (Örn: Kapıyı aç) çalıştırır.

---
**Geliştirici Notu:** Zindan kodundaki en ünlü hata "Dungeon Crash" veya "Nightmare" olarak işaretlenen (`@warme011 the begin of the nightmare`) kısımlardır. Bu, genellikle bir grubun (Party) zindan içindeyken dağılmasıyla (Disband) oluşur. Eğer grup dağılırsa, `DecPartyMember` fonksiyonu sahipsiz (NULL) bir grup nesnesine erişmeye çalışabilir. Modern source dosyalarında bu durum `if (pParty)` kontrolleriyle sıkıca denetlenir.
 
Metin2'nin en önemli sosyal yapısı olan Lonca sistemi, oyuncuların bir bayrak altında toplanmasını, birlikte savaşmasını ve toprak sahibi olmasını sağlar. Bu sistem `guild.cpp` ve `guild_manager.cpp` dosyalarında yönetilir. Bu bölüm, lonca üyeliğinden P2P (Sunucular Arası) iletişime kadar lonca altyapısını analiz eder.

## 4.1. Lonca Üyelik Yönetimi

Bir loncaya üye eklendiğinde (`CGuild::AddMember`), sunucu sadece RAM'deki listeyi güncellemekle kalmaz, aynı zamanda veritabanına (`db`) kalıcı bir kayıt paketi gönderir:
* `HEADER_GD_GUILD_ADD_MEMBER`: Veritabanına "Bu oyuncu bu loncaya katıldı" bilgisini yollar.
* `Link`: Oyuncunun `CHARACTER` nesnesi ile `CGuild` nesnesi birbirine bağlanır.

## 4.2. P2P Online Takibi (Kanallar Arası Üye Takibi)

Metin2'de lonca üyeleri farklı kanallarda (CH1, CH2 vb.) olabilir. Ancak lonca penceresinde herkesin online durumunu görmelisiniz. Bunu sağlayan mekanizma **P2P (Peer-to-Peer)** iletişimidir:

* **P2PLoginMember:** Eğer bir üye başka bir kanalda oyuna girerse, loncanın bulunduğu sunucuya "Bu üye online oldu" (P2P) bilgisi gelir.
* **m_memberP2POnline:** Diğer kanallarda online olan üyeler bu listede tutulur.
* **Görsel Güncelleme:** Bir üye online olduğunda, o loncadaki **tüm online oyunculara** `SendLoginPacket` gönderilir. Böylece lonca listesindeki isim kararmış halden parlak hale geçer.

## 4.3. Rutbe ve Yetki Sistemi (`SendAllGradePacket`)

Her loncanın 15 farklı rütbesi (Grade) olabilir. Lonca lideri bu rütbelerin yetkilerini (Savaş açma, üye alma, duyuru yapma) değiştirebilir.
* Rütbe bilgileri `m_data.grade_array` dizisinde saklanır.
* Bir oyuncu oyuna girdiğinde, lonca sistemi ona tüm rütbe listesini (`SendAllGradePacket`) ve kendi yetkilerini gönderir.

## 4.4. Lonca Seviyesi ve EXP Bağışı (`dwOffer`)

Oyuncular loncalarına EXP bağışlayarak lonca seviyesini artırabilirler.
* **offer_exp:** Oyuncunun o ana kadar loncaya ne kadar EXP bağışladığını tutan değişkendir.
* Lonca seviyesi arttıkça; üye kapasitesi artar ve lonca becerileri (Skill) için puan kazanılır.

## 4.5. Üye Çıkarma ve Ayrılma

Üye çıkarma işlemi (`RequestRemoveMember`) güvenlik kontrollerine tabidir:
1. **Lider Kontrolü:** Lonca lideri kendini kovamaz.
2. **DB İletişimi:** Kovulma isteği önce `db` sunucusuna gider. DB onay verirse tüm kanallardaki lonca listesinden o üye silinir.
3. **Temizlik:** Oyuncu online ise `ch->SetGuild(NULL)` yapılarak karakterin lonca bağı koparılır.

---
**Geliştirici Notu:** Lonca sisteminde karşılaşılan yaygın hatalardan biri "Hayalet Üye" (Lonca listesinde görünen ama aslında loncada olmayan) sorunudur. Bu genellikle `P2PLoginMember` veya `Unlink` fonksiyonlarındaki senkronizasyon hatasından kaynaklanır. Sizin dosyanızdaki `CGuildManager::instance().Unlink(pid)` çağrısı, üye silindiğinde tüm sistemdeki bağları kopardığı için bu hatayı önlemektedir.

Metin2'de oyuncular arası ticaret, en karmaşık kontrol mekanizmalarına sahip sistemlerden biridir. Sadece iki oyuncu arasında eşya değiş tokuşu gibi görünse de, arka planda onlarca "Dupe" (Eşya Kopyalama) ve "Exploit" (Açık) önleyici kontrol çalışır. Bu kontroller `exchange.cpp` dosyasında tanımlanan **CExchange** sınıfı tarafından yönetilir.

## 2.1. Ticaretin Temeli: Karşılıklı Nesneler

Bir ticaret başladığında, sistem iki adet `CExchange` nesnesi oluşturur.
* **m_pOwner:** Ticareti başlatan/yapan oyuncu.
* **m_pCompany:** Ticaret yaptığı karşı oyuncu.
Bu iki nesne birbirine bağlanarak (`SetCompany`) veri alışverişini sağlar.

## 2.2. Eşya Ekleme ve Güvenlik Filtreleri (`AddItem`)

Bir oyuncu ticaret penceresine bir eşya koyduğunda `AddItem` fonksiyonu şu kontrolleri yapar:

1. **Ekipman Kontrolü:** Giyili olan (Armor, Weapon vb.) eşyalar doğrudan ticaret penceresine konulamaz. Önce çıkarılmalıdır.
2. **Anti-Flag Kontrolü:** Eğer eşyada `ITEM_ANTIFLAG_GIVE` (Ticaret yapılamaz) bayrağı varsa işlem reddedilir.
3. **Kilitli Eşya Kontrolü:** Karakter kilit sistemi (Item Lock) ile kilitlenmiş eşyalar ticarete konu olamaz.
4. **Zaten Ticarette mi? (`IsExchanging`):** Bir eşya aynı anda iki farklı işleme (Örn: Hem ticaret penceresi hem depo) konu olamaz. Bu, eşya kopyalama açıklarının en büyük engelidir.

## 2.3. Kabul (Accept) ve Durum Sıfırlama

Ticaret penceresine yeni bir eşya eklendiğinde veya çıkarıldığında, her iki tarafın daha önce bastığı "Kabul" butonları sistem tarafından otomatik olarak iptal edilir:
```cpp
Accept(false);
GetCompany()->Accept(false);
```
Bu, "Dolandırıcılık Önleme" mekanizmasıdır. Siz tam kabul edecekken karşı tarafın eşyayı değiştirmesini veya kaldırmasını engeller.

## 2.4. Envanter Boşluk Kontrolü (`CheckSpace`)

Ticaretin son aşamasında (ikinci kabuller yapıldığında) sistem, eşyaların karşı tarafın envanterine sığıp sığmayacağını hesaplar.
* **Grid Sistemi:** Metin2 envanteri 5x9'luk (veya daha geniş) bir ızgara (Grid) sistemidir.
* **Akıllı Hesaplama:** `Sectree` benzeri bir mantıkla `s_grid1`, `s_grid2` gibi sanal kopyalar oluşturulur. Gelen eşyaların boyutları (1x1, 1x2, 1x3) bu sanal ızgaraya yerleştirilir. Eğer bir eşya bile dışarıda kalırsa, "Envanterinizde yer yok" hatası verilir ve ticaret iptal edilir.
* **Simya ve Özel Envanter:** Eğer gelen eşya bir Ejderha Taşı (Dragon Soul) ise, oyuncunun simya görevini yapıp yapmadığı ve simya envanterindeki özel boşluklar kontrol edilir.

## 2.5. Ticaretin Sonuçlanması (`Done`)

Her iki taraf da kabul ettiğinde, eşyalar sahiplerinden silinir (`item->Remove`) ve karşı tarafa eklenir. Bu işlem sırasında her iki oyuncunun da CPU ve bellek üzerinde "Atomatic" bir işlemde olduğu işaretlenir. Eğer bu aşamada bağlantı koparsa, işlem veritabanı loglarına kaydedilir (`trade_log`).

---
**Geliştirici Notu:** Ticaret sistemindeki en kritik açıklar genellikle "Ghost Item" (Hayalet Eşya) vakalarıdır. Bu, oyuncunun eşyayı ticarete koyup aynı karede yere atması veya depoya koymasıyla oluşur. Modlanmış source dosyalarında `exchange.cpp` içerisindeki `item->IsExchanging()` kontrolü bu yüzden hayati önem taşır; eşya ticarete girdiği an "meşgul" (Busy) olarak işaretlenmelidir.

Metin2'de sunucu genelinde veya krallıklara özel olarak uygulanan "EXP Artışı", "Eşya Düşürme Şansı" ve "Altın Kazanma Oranı" gibi bonuslar `Privilege` (Ayrıcalık) sistemiyle yönetilir. `priv_manager.cpp` dosyası, bu oranların nasıl ayarlandığını, süresini ve karakterlere nasıl yansıtıldığını kontrol eder.

## 3.1. Privilege Seviyeleri

Metin2'de oran artışları hiyerarşik bir yapıdadır. Bir oyuncunun toplam bonusu hesaplanırken şu üç seviyeye bakılır:

1. **Karakter Bazlı (`Character Priv`):** Sadece belirli bir oyuncuya verilen özel bonus (Örn: Bir çekiliş ödülü).
2. **Lonca Bazlı (`Guild Priv`):** Bir loncanın üyelerine özel olarak sağlanan bonus (Örn: Lonca arazisi avantajları).
3. **İmparatorluk Bazlı (`Empire Priv`):** Tüm krallığa veya tüm sunucuya (`Empire = 0`) uygulanan genel bonus.

## 3.2. Oranların Hesaplanması (`GetPriv`)

Bir canavar öldürüldüğünde veya bir kutu açıldığında sunucu `CPrivManager::GetPriv` fonksiyonunu çağırır.
* **En Yüksek Değer Kuralı:** Sistem, farklı seviyelerden gelen aynı türdeki bonusları toplamaz. Bunun yerine, oyuncunun sahip olduğu en yüksek değeri seçer (`MAX(val_ch, val_empire, val_guild)`).
* **Negatif Oranlar:** Nadir durumlarda oranlar düşürülebilir (Ceza olarak). Ancak oyuncuda "Kötü Şans Koruyucusu" (`UNIQUE_ITEM_NO_BAD_LUCK_EFFECT`) eşyası varsa bu negatif etkiler görmezden gelinir.

## 3.3. Oran İstekleri ve Veritabanı Senkronizasyonu

Bir GM `/priv` komutu kullandığında, bu istek doğrudan sunucuda aktif olmaz:
1. **Request:** Önce `db` sunucusuna bir istek (`HEADER_GD_REQUEST_EMPIRE_PRIV`) gönderilir.
2. **Kayıt:** `db` sunucusu bu oranı MySQL'e kaydeder.
3. **Dağıtım:** Ardından bu bilgi tüm çekirdeklere (Cores) dağıtılır (`GiveEmpirePriv`). Bu sayede sunucu kapansa bile aktif oranlar MySQL'den tekrar yüklenir.

## 3.4. Duyuru ve Bildirim Sistemi

Bir krallığa bonus verildiğinde sunucu otomatik olarak tüm oyunculara bir duyuru (`SendNotice`) geçer:
```cpp
snprintf(buf, sizeof(buf), LC_TEXT("%s krallığına %s %d%% artırıldı!"),
GetEmpireName(empire), GetPrivName(type), value);
```
Bu, krallıklar arası rekabeti ve topluluk heyecanını canlı tutan bir otomasyondur.

## 3.5. Süre Kısıtlamaları ve Temizlik

Privilege oranları sonsuza kadar sürmez.
* **Maksimum Değer:** Güvenlik gereği oranlar genellikle %1000 (10 kat) ile sınırlandırılmıştır (`MINMAX(0, value, 1000)`).
* **Maksimum Süre:** Bir oran en fazla 7 gün (`60*60*24*7` saniye) olarak ayarlanabilir.
* **Bitiş Zamanı:** `end_time_sec` değeri ile sistem her saniye kontrol yapar ve zamanı geçen oranları `RemoveEmpirePriv` ile listeden siler.

---
**Geliştirici Notu:** Eğer sunucunuzda "Oranlar açık ama düşen eşya sayısı değişmiyor" gibi bir sorun yaşıyorsanız, `item_manager.cpp` içerisindeki `GetPrivByIndex` çağrılarını kontrol etmelisiniz. Bazı modlarda bu kısımlar yanlışlıkla silinmiş olabilir. Ayrıca, etkinlik oranlarını %100'ün üzerinde çok yüksek değerlere ayarlamak, piyasadaki eşya değerlerini aniden düşürebileceği için dikkatli kullanılmalıdır.

Metin2'nin modern sürümlerinde en çok kullanılan eklentilerden biri olan **Çevrimdışı Pazar (Offline Shop)**, oyuncuların oyundan çıksalar bile dükkanlarının açık kalmasını sağlayan karmaşık bir sistemdir. Bu bölüm, `offline_shop.cpp` dosyasındaki mantığı ve veritabanı senkronizasyonunu analiz eder.

## 4.1. Sistemin Temel Mantığı

Standart bir pazar (Standard Shop), oyuncu oyundan çıktığında yok olur çünkü pazar verileri oyuncunun `CHARACTER` nesnesine bağlıdır. Çevrimdışı pazar ise:
1. Pazar verilerini (Eşyalar, Fiyatlar, Konum) veritabanındaki özel tablolarda (`offline_shop_item`) tutar.
2. Oyuncu çıksa bile, harita üzerinde "Sahipsiz" bir NPC (`CHAR_TYPE_NPC`) oluşturur.
3. Satış yapıldığında parayı oyuncunun veritabanı kaydına (`money2` veya `bank`) ekler.

## 4.2. Satın Alma Süreci (`COfflineShop::Buy`)

Bir oyuncu çevrimdışı pazardan bir eşya aldığında şu adımlar izlenir:

### 1. Para Kontrolü
```cpp
if (ch->GetGold() < (long long) dwPrice) {
return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
}
```
Önce alıcının parası kontrol edilir.

### 2. Eşya Oluşturma ve Özellik Aktarımı
Eşya veritabanından okunur ve alıcının envanterinde yeni bir nesne olarak oluşturulur. Orijinal eşyadaki taşlar (Sockets) ve efsunlar (Attributes) tek tek yeni eşyaya kopyalanır:
```cpp
pItem->SetAttributes(aAttr);
for (BYTE i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
pItem->SetSocket(i, alSockets);
```

### 3. Veritabanı Güncelleme (Paranın Sahibe İletilmesi)
Bu sistemin en kritik noktası, pazar sahibi online olmasa bile parasının hesabına geçmesidir:
```cpp
DBManager::instance().DirectQuery("UPDATE player.player SET money2 = money2 + %lld WHERE id = %u",
dwPrice, ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
```
Buradaki `DirectQuery`, değişikliğin anında MySQL'e yazılmasını sağlar.

## 4.3. Pazarın Kapatılması ve Eşyaların İadesi

Eğer pazardaki son eşya satılırsa veya pazar süresi dolarsa `Destroy()` fonksiyonu çağrılır:
* Pazar NPC'si haritadan silinir.
* Eğer içinde eşya kaldıysa, bu eşyalar "Pazar Deposu"na (Safebox) veya oyuncunun envanterine (eğer online ise) gönderilir.

## 4.4. Yayın (Broadcast) Sistemi

Pazardaki bir eşya satıldığında, o an pazara bakan tüm diğer oyuncuların ekranında o slotun boşalması gerekir. Bunu `BroadcastUpdateItem` fonksiyonu yapar:
* Bir paket hazırlanır (`HEADER_GC_OFFLINE_SHOP`).
* Pazara bağlı tüm oyunculara (`Broadcast`) bu bilgi gönderilir.
* İstemci (Client) paketi alır almaz arayüzdeki eşyayı siler.

## 4.5. Performans ve Güvenlik (Exploit) Önlemleri

Çevrimdışı pazarlar sunucuyu yorabilir. Bu yüzden projenizde şu önlemler alınmıştır:
* **Arama Sınırı:** `ch->SetQuestFlag("search.searchlast", get_global_time() + 2);` oyuncuların çok sık arama yaparak SQL'i yormasını engeller.
* **Duplicate Fix:** Bir eşya satılırken, veritabanından `vnum = 0` yapılarak o slotun "artık boş olduğu" işaretlenir. Bu, aynı eşyanın iki kez satılması hatasını (Bug) önler.

---
**Geliştirici Notu:** Çevrimdışı pazar sisteminde bir değişiklik yaptığınızda (Örn: Yeni bir eşya türü eklemek), hem `game` içindeki C++ dosyalarını, hem de `db` (database) içindeki sorguları güncellemeniz gerekir. Ayrıca Client tarafındaki Python pencerelerinin de yeni veri paketlerini tanıması şarttır.


Metin2'nin temel ekonomik döngüsü NPC marketleri ve oyuncu pazarları üzerine kuruludur. Bu sistemin yönetimi `shop_manager.cpp` içerisindeki `CShopManager` sınıfı tarafından yürütülür. Bu bölüm, eşya alışverişi, fiyatlandırma ve pazar güvenliği mekanizmalarını analiz eder.

## 5.1. Market Türleri: NPC ve PC (Pazar)

Sistem iki tür marketi birbirinden ayırır:
* **NPC Marketleri:** Sabit NPC'lerin (Zırhçı, Silahçı vb.) sunduğu, `shop_proto` veritabanından veya `shop_table_ex.txt` dosyasından okunan marketlerdir.
* **PC Marketleri (Pazar):** Oyuncuların "Pazar Kurma" paketiyle açtıkları geçici marketlerdir. Bu marketler anlık olarak `m_map_pkShopByPC` haritasında saklanır.

## 5.2. Satın Alma Döngüsü (`Buy`)

Bir oyuncu marketten eşya satın aldığında şu kontroller yapılır:
1. **Mesafe Kontrolü:** Oyuncu ile market sahibi (NPC veya Oyuncu) arasındaki fiziksel mesafe kontrol edilir. Eğer mesafe 20 metreden (`2000` birim) fazlaysa işlem engellenir.
2. **Hile Koruması:** `ch->SetMyShopTime()` ile işlem kaydedilir. Bu, çok hızlı peş peşe satın alma yaparak "Hız Hilesi" ile eşya boşaltılmasını engelleyen bir "Cooldown" mekanizmasıdır.
3. **Bakiye ve Stok:** Oyuncunun parası (`Gold`) kontrol edilir ve eşya envanterine eklenirken marketten eksiltilir.

## 5.3. Eşya Satma ve Fiyat Hesaplama (`Sell`)

Eşyalarınızı NPC'lere satarken sunucu şu adımları izler:
* **Yasaklı Eşyalar:** Eğer eşyada `ITEM_ANTIFLAG_SELL` bayrağı varsa veya eşya o an "Kilitli" (`isLocked`) ise satılamaz.
* **Fiyatlandırma:** Eşyanın `shop_buy_price` değeri baz alınır. Bazı eşyalar (Örn: Değerli taşlar) 1 altın (`ITEM_FLAG_COUNT_PER_1GOLD`) karşılığında toplu olarak satılacak şekilde ayarlanabilir.
* **Para Sınırı (Overflow):** Metin2'de bir karakterin taşıyabileceği maksimum altın (`2.000.000.000`) sınırlıdır. Eğer satış sonrası bu miktar aşılacaksa, sunucu hatayı önlemek için işlemi reddeder.

## 5.4. Gelişmiş Market Yapılandırması (`ShopTableEx`)

Modern Metin2 sürümlerinde `shop_proto` yerine daha esnek olan `shop_table_ex.txt` kullanılır:
* **Coin Type (Para Türü):** Sadece altın değil, "İkincil Para" (`SecondaryCoin` - Ejderha Markası vb.) ile de satış yapılabilir.
* **Grid (Izgara) Yerleşimi:** Market penceresi 5x9'luk bir ızgaradır. `ShopTableEx`, eşyaları boyutlarına göre bu ızgaradaki boşluklara (`FindBlank`) otomatik olarak yerleştirir.
* **Sıralama (`Sort`):** Eşyalar isimlerine göre A-Z (`Asc`) veya Z-A (`Desc`) şeklinde otomatik sıralanabilir.

## 5.5. Pazar Kapatma ve Güvenlik

Bir oyuncu pazarını kapattığında veya dükkandan ayrıldığında `StopShopping` veya `DestroyPCShop` tetiklenir:
* **Misafir Temizliği:** O an o dükkan penceresini açık tutan diğer oyunculara "Pazar Kapatıldı" mesajı gider ve pencereleri otomatik kapanır.
* **Bellek Yönetimi:** `M2_DELETE(pkShop)` ile pazar nesnesi RAM'den silinir, böylece sunucu üzerinde gereksiz nesne birikimi engellenir.

---
**Geliştirici Notu:** Market sistemindeki en büyük risk "Dükkan Açıkken Eşya Kopyalama" (Dupe) açıklarındır. `shop_manager.cpp` içerisindeki `ch->SetMyShopTime()` ve `item->IsExchanging()` kontrolleri bu yüzden hayati önem taşır. Eğer bir oyuncu eşyayı hem markete koyup hem de aynı anda ticaret penceresine sürmeye çalışırsa, bu kontroller sayesinde sunucu işlemi fark eder ve bağlantıyı keser.





Metin2'nin en esnek kısmı **Quest** sistemidir. Bu sistem, oyunun ana döngüsünü bozmadan yeni senaryolar, görevler ve etkinlikler eklemeyi sağlar. Sistem, C++ ile yazılmış bir motor (`QuestManager`) ve bu motorun üzerinde çalışan **Lua** betik dilinden oluşur.

## 5.1. QuestManager'ın Görevi

`questmanager.cpp`, Lua sanal makinesini (VM) yöneten bir orkestra şefidir. Temel görevleri şunlardır:
1. **Lua Entegrasyonu:** Lua scriptlerini belleğe yükler ve çalıştırır.
2. **Tetikleyiciler (Events):** Oyunda bir olay olduğunda (Örn: Canavar öldürme, seviye atlama, NPC'ye tıklama), ilgili Lua fonksiyonunu çağırır.
3. **Durum Yönetimi (State):** Bir oyuncunun o an hangi görevde hangi aşamada olduğunu takip eder.

## 5.2. Tetikleme Mekanizması: Bir Görev Nasıl Başlar?

Bir görev, `questmanager.cpp` içindeki olay dinleyicileri (Event Listeners) sayesinde tetiklenir.

### Örnek: `Kill` Tetikleyicisi
```cpp
void CQuestManager::Kill(unsigned int pc, unsigned int npc)
{
if ((pPC = GetPC(pc)))
{
// Ölen canavarın vnum'una göre Lua'daki "when VNUM.kill" bloğunu çalıştırır
m_mapNPC[npc].OnKill(*pPC);
// Genel kill dinleyicilerini çalıştırır
m_mapNPC[QUEST_NO_NPC].OnKill(*pPC);
}
}
```
Bir oyuncu bir canavarı öldürdüğünde, sunucu `CHARACTER::Dead` içerisinden `QuestManager::Kill` fonksiyonunu çağırır. Bu fonksiyon da Lua tarafına "Hey, birisi şu kodlu canavarı öldürdü, yapman gereken bir şey var mı?" diye sorar.

## 5.3. Lua ve C++ Arasındaki Veri Alışverişi

Lua'dan C++ fonksiyonlarını çağırmak için `questlua_*.cpp` dosyaları kullanılır. Örneğin:
* Lua'da `pc.give_item2(10)` yazdığınızda;
* C++ tarafında `questlua_pc.cpp` içindeki `pc_give_item2` fonksiyonu çalışır.
* Bu fonksiyon Lua yığınından (Stack) 10 sayısını okur ve `CHARACTER::AutoGiveItem` fonksiyonunu çağırır.

## 5.4. Suspend (Askıya Alma) Durumları

Quest ekranında bir seçim yapmanız istendiğinde (Örn: "Evet/Hayır"), Lua betiği o noktada durur (**Suspended**).
* `SUSPEND_STATE_SELECT`: Oyuncu bir menüden seçim yapana kadar bekler.
* `SUSPEND_STATE_INPUT`: Oyuncunun bir metin veya sayı girmesini bekler.
* `SUSPEND_STATE_CONFIRM`: Bir onay kutusuna (Pencere) basılmasını bekler.

Oyuncu seçim yaptığında sunucuya bir paket gelir, `CQuestManager::Select` çalışır ve durdurulan Lua betiği kaldığı yerden devam eder.

## 5.5. Sunucu Zamanlayıcıları (Server Timers)

Bazı görevler oyuncudan bağımsız olarak çalışır (Örn: "30 dakika sonra bu zindandaki herkesi dışarı at").
* **Timer:** Tek bir oyuncuya özel geri sayım.
* **Server Timer:** Tüm sunucuyu veya bir haritayı etkileyen global geri sayım.
* Bu zamanlayıcılar `event_create` sistemiyle C++ çekirdeğinde (TheCore) çalıştırılır.

---
**Geliştirici Notu:** Lua dosyalarınızda bir hata (Syntax Error) yaptığınızda, sunucu açılırken `syserr` dosyasına bunu yazar. Eğer `quest_list` dosyasında olup da çalışmayan bir göreviniz varsa, `questmanager.cpp` içindeki `LuaError` çıktılarını incelemelisiniz.

Metin2 Quest sistemi, Lua betikleri üzerinden oyuncuya müdahale etmeyi sağlar. Ancak Lua'nın kendisi oyuncunun envanterini göremez veya onu ışınlayamaz. Bu işlemleri gerçekleştirmek için Lua fonksiyonlarının C++ karşılıkları olan "Wrapper" fonksiyonlarına ihtiyaç duyar. `questlua_pc.cpp` dosyası, `pc` (Player Character) nesnesi için bu köprüyü kuran ana dosyadır.

## 2.1. Lua'dan C++'a Veri Akışı

Bir quest içerisinde `pc.give_gold(100)` yazdığınızda süreç şöyle işler:
1. **Lua Yığını (Stack):** Lua motoru `100` değerini bir yığına (Stack) koyar ve C++ tarafındaki `pc_give_gold` fonksiyonunu çağırır.
2. **Veri Okuma:** C++ tarafında `lua_tonumber(L, 1)` komutu ile yığındaki ilk değer okunur.
3. **İşlem:** Okunan değer, `CHARACTER::PointChange` fonksiyonuna gönderilerek oyuncunun parası artırılır.

## 2.2. Güvenlik ve Hile Koruması (`IsHack`)

Quest fonksiyonları çalışırken sadece oyuncunun isteğini yerine getirmez, aynı zamanda işlemin güvenli olup olmadığını da denetler:

* **Warp (Işınlanma) Engeli:** Eğer oyuncu hileli (`IsHack`) olarak işaretlendiyse ışınlanma reddedilir.
* **İşlem Kısıtlamaları:** Oyuncu ticaret (`Exchange`), pazar (`MyShop`) veya depo (`Safebox`) penceresi açıkken quest aracılığıyla ışınlanamaz. Bu, eşya kopyalama (dupe) açıklarını önleyen en temel kuraldır.
* **Süre Kısıtlaması:** Ticaret yaptıktan hemen sonra ışınlanmak bazen engellenmiştir (`GetExchangeTime`).

## 2.3. Envanter Kontrolü (`pc.enough_inventory`)

Questler aracılığıyla oyuncuya eşya verilmeden önce yer olup olmadığı mutlaka kontrol edilmelidir.
```cpp
bool bEnoughInventoryForItem = ch->GetEmptyInventory(pTable->bSize) != -1;
lua_pushboolean(L, bEnoughInventoryForItem);
```
Eğer modern bir source (Özel Depo/Special Storage) kullanılıyorsa, eşyanın türüne göre (Yükseltme eşyası, Beceri kitabı, Taş) ilgili özel envanterdeki boşluklar da bu fonksiyon üzerinden denetlenir.

## 2.4. Lonca İşlemleri ve Savaş Durumu

Lua üzerinden lonca kapatma veya üyeyi çıkarma gibi kritik işlemler yapılabilir.
* **Lonca Kapatma (`pc.destroy_guild`):** Eğer lonca o an bir savaş içerisindeyse (`UnderAnyWar`), lonca kapatma işlemi reddedilir. Bu, savaş arenalarında loncayı kapatarak puan kaybetmeyi veya rakipten kaçmayı engelleyen bir kuraldır.

## 2.5. Eşya Verme Mekanizması (`pc.give_item`)

`pc.give_item` veya `pc.give_item2`, oyuncuya eşya kazandıran en sık kullanılan quest fonksiyonudur.
* **Vnum ve Ad:** Fonksiyon hem eşya kodunu (Vnum) hem de eşya adını (isimle eşleşme) kabul eder.
* **Loglama:** Quest ile verilen değerli eşyalar ve paralar, veritabanına özel bir `quest_log` veya `money_log` olarak kaydedilir. Bu sayede bir quest açığı ile sınırsız para basan oyuncular kolayca tespit edilebilir.

---
**Geliştirici Notu:** Kendi Quest fonksiyonunuzu yazmak isterseniz, bu dosyadaki fonksiyon yapısını (örneğin `int pc_my_function(lua_State* L)`) klonlayıp, dosyanın sonundaki `RegisterPCFunctionTable` listesine eklemeniz gerekir. Unutmayın, Lua tarafına tek bir değer döndürecekseniz `return 1;`, hiç değer döndürmeyecekseniz `return 0;` yazmalısınız.

Metin2'deki zindanların (Örn: Şeytan Kulesi, Mavi Ejderha Odası) tüm mantığı Lua üzerinden yönetilir. `questlua_dungeon.cpp` dosyası, Lua tarafındaki `dungeon` nesnesinin C++ zindan motoru (`Dungeon.cpp`) ile nasıl konuştuğunu belirleyen fonksiyonları içerir.

## 3.1. Zindan Yaratma ve Işınlama (`dungeon.new_jump`)

Bir oyuncu zindana girmek istediğinde (Örn: Gardiyan ile konuşurken), Lua tarafında şu fonksiyonlar tetiklenir:
* **dungeon.new_jump:** Tek bir oyuncu için yeni ve izole bir zindan haritası (Private Map) oluşturur.
* **dungeon.new_jump_party:** Tüm grubun (`Party`) aynı zindan kopyasına ışınlanmasını sağlar. Eğer oyuncunun bir grubu yoksa `ch->GetParty() == NULL` kontrolü ile işlem iptal edilir.
* **İzole Map Index:** Zindanlar, varsayılan harita indexinin üzerine binlik çarpanlar eklenerek oluşturulan sanal indexler üzerinden çalışır. Bu sayede 100 farklı grup aynı kulede birbirini görmeden savaşabilir.

## 3.2. Mob ve Regen Yönetimi

Zindandaki canavarların ne zaman ve nerede doğacağı Lua tarafından dikte edilir:
* **dungeon.regen_file:** Belirlenen bir `regen.txt` dosyasını zindana yükleyerek canavarları tek seferde doğurur.
* **dungeon.check_eliminated:** Zindandaki tüm canavarların ölüp ölmediğini kontrol eder. Özellikle "Tüm slotları temizle" görevlerinde bir sonraki aşamaya geçmek için kullanılır.
* **dungeon.clear_regen:** Zindandaki mevcut doğum döngüsünü durdurur.

## 3.3. Bayraklar (Flags): Zindan Hafızası

Zindanlar, içlerindeki aşamaları takip etmek için kendi hafızalarına (Flag) sahiptir:
* **dungeon.setf / dungeon.getf:** Zindana özel değişkenler saklar. Örneğin, "door_opened = 1" bayrağı ile kapının açıldığı bilgisi zindan silinene kadar RAM'de tutulur.
* **Süreklilik:** Bu bayraklar oyuncu bazlı değil, zindan kopyası bazlıdır. Yani gruptaki herkes aynı bayrak değerini görür.

## 3.4. Otomatik Tahliye Mekanizmaları (`Warp At Eliminate`)

Zindan bittiğinde veya süre dolduğunda oyuncuların dışarı atılması gerekir:
* **dungeon.set_exit_all_at_eliminate:** Belirli bir süre sonra (Örn: 60 saniye) herkesin zindandan otomatik ışınlanmasını sağlar.
* **dungeon.set_warp_at_eliminate:** Canavarlar bittiğinde oyuncuların hangi koordinata (`X, Y`) ve hangi haritaya ışınlanacağını programlar.

## 3.5. Zindan Bilgileri ve İstatistikler

Lua motoru, zindanın o anki durumu hakkında C++'tan canlı bilgi alabilir:
* **dungeon.get_kill_mob_count:** Zindan başladığından beri kaç yaratık öldürüldüğünü döndürür.
* **dungeon.is_use_potion:** Zindanda pot kullanımının yasak olup olmadığını (Modern zindanlar için bir kısıtlama) denetler.

---
**Geliştirici Notu:** Zindan questlerinde karşılaşılan en büyük hata, `dungeon.new_jump` yapmadan önce `dungeon` fonksiyonlarını çağırmaya çalışmaktır. Unutmayın, bir `dungeon` nesnesi sadece "Zindan Haritası" içerisindeyken (`ch->GetDungeon()`) anlam ifade eder. Eğer oyuncu normal bir haritadaysa bu fonksiyonlar `sys_err("no dungeon !!!")` hatası döndürecektir.

Metin2'de lonca savaşları, lonca sıralamaları ve liderlik değişimleri gibi işlemler `questlua_guild.cpp` dosyası üzerinden Quest sistemine bağlanır. Bu dosya, `guild` nesnesi aracılığıyla lonca verilerine erişimi sağlar.

## 4.1. Lonca Savaşı Entegrasyonu (`war_enter`)

Bir lonca savaşı başladığında oyuncuların savaş alanına girmesini sağlayan Quest fonksiyonları şunlardır:
* **guild.war_enter:** Oyuncunun loncasının bir savaşta olup olmadığını kontrol eder ve eğer uygunsa onu savaş haritasına ışınlar.
* **guild.get_any_war:** Loncanın aktif olarak herhangi bir savaşta (Bölge savaşı veya Klasik savaş) olup olmadığını döndürür.
* **guild.get_warp_war_list:** Mevcut tüm aktif lonca savaşlarını bir liste (Table) olarak döndürür. Bu, "Savaş Sorumlusu" NPC'sinde aktif savaşları izlemek için kullanılır.

## 4.2. Bahis Sistemi (`war_bet`)

Metin2'nin köklü özelliklerinden biri olan lonca savaşlarına bahis oynama sistemi burada yönetilir:
* **guild.war_bet:** Oyuncunun belirli bir miktar altınla (`dwGold`) bir savaşa bahis yatırmasını sağlar. Bu veri doğrudan `db` sunucusuna (`HEADER_GD_GUILD_WAR_BET`) gönderilerek kaydedilir.
* **guild.is_bet:** Oyuncunun halihazırda o savaşa bahis yapıp yapmadığını denetler.

## 4.3. Sıralama ve Derece Sistemleri

`guild` kütüphanesi, loncaların başarısını ölçen verileri çekebilir:
* **guild.get_rank:** Loncanın sunucu genelindeki sıralamasını döndürür.
* **guild.get_ladder_point:** Loncanın kazandığı savaş puanlarını (Basamak puanı) verir.
* **guild.level:** Loncanın mevcut seviyesini döndürür.

## 4.4. Lonca Liderliği Devri (`change_master`)

Lonca başkanının görevini başka bir üyeye devretmesi işlemi Quest üzerinden güvenli bir şekilde yapılabilir:
* **Liderlik Kontrolü:** Sadece mevcut lonca başkanı bu fonksiyonu tetikleyebilir.
* **Limitli Devir (`change_master_with_limit`):** Bu fonksiyon, devir işlemini belirli şartlara bağlar:
* **Seviye Sınırı:** Yeni liderin minimum bir seviyede olması gerekir.
* **Zaman Sınırı (Cooldown):** Yeni liderin daha önce başka bir lonca liderliğini bırakıp bırakmadığı (`be_other_leader` flagı) kontrol edilir.

## 4.5. Lonca Üye Bilgileri

* **guild.get_member_count:** Loncanın anlık toplam üye sayısını döndürür. Bu, lonca geliştirme görevlerinde veya savaş gereksinimlerinde kullanılır.
* **guild.get_name:** Belirli bir Lonca ID'sine karşılık gelen ismi döndürür.

---
**Geliştirici Notu:** Lonca sistemindeki Quest fonksiyonlarını kullanırken oyuncunun bir loncada olup olmadığını her zaman `pc.hasguild()` ile kontrol etmeniz önerilir. Oyuncu loncasızken `guild` fonksiyonlarını çağırmak çoğu zaman `0` veya boş değer döndürür, ancak bazı durumlarda mantık hatalarına yol açabilir. Özellikle liderlik devri (`change_master`) işlemlerinde `pNewMaster` nesnesinin o an online olup olmadığı `CHARACTER_MANAGER::instance().FindPC` ile kontrol edilir; bu yüzden devir işlemi sırasında her iki oyuncu da oyunda olmalıdır.
 
Metin2 İstemcisi, Windows üzerinde çalışan yüksek performanslı bir oyun yazılımıdır. Oyunun "kalbi" ve ana üretim merkezi `PythonApplication.cpp` dosyasıdır. Bu dosya, her saniye defalarca çalışan ve ekranın çizilmesini sağlayan ana döngüyü (Main Loop) yönetir.

## 6.1. Oyunun Kalp Atışı: `Process()`

İstemci çalışmaya başladığında sonsuz bir döngüye girer. Bu döngünün her bir adımına `Frame` (Kare) denir. `CPythonApplication::Process()` fonksiyonu her karede şu 3 ana işi yapar:

1. **Girdi İşleme (Input):** Fare ve klavye hareketlerini okur.
2. **Güncelleme (Update):** Karakterlerin hareketlerini, efektlerin gelişimini ve ağ trafiğini hesaplar.
3. **Çizim (Render):** Tüm hesaplanan verileri ekrana bir resim olarak çizer.

## 6.2. Güncelleme Döngüsü (`UpdateGame`)

Bu fonksiyon, ekran çizilmeden hemen önce oyun dünyasındaki her şeyi günceller:
* **Player Update:** Sizin karakterinizin o karedeki yeni konumu hesaplanır.
* **Character Manager Update:** Çevrenizdeki diğer oyuncuların ve canavarların animasyonları ilerletilir.
* **Background Update:** Bulunduğunuz haritanın kaplamaları (Terrain), gökyüzü ve uzaklık ayarları güncellenir.
* **Network Stream Process:** Sunucudan gelen yeni paketler okunur ve "X oyuncusu vurdu", "Y eşyası düştü" gibi emirler anında işlenir.

## 6.3. Render Aşaması: Ekrana Çizim Sanatı (`RenderGame`)

Metin2'nin grafik motoru (EterEngine), verileri ekrana belli bir hiyerarşiyle çizer. Bu sırayı bozmak, ağaçların karakterlerin önünde görünmesi veya gökyüzünün oyunun üstüne binmesi gibi hatalara yol açar.

**Render Sırası:**
1. **Sky (Gökyüzü):** En arka plana gökyüzü çizilir.
2. **Background (Zemin):** Yerler, dağlar ve denizler çizilir.
3. **Characters (Karakterler):** Oyuncular ve NPC'ler yerleştirilir.
4. **Effects (Efektler):** Beceri (Skill) efektleri ve parlamalar karakterlerin üzerine eklenir.
5. **Items (Yerdeki Eşyalar):** Yerdeki 3D eşya modelleri çizilir.
6. **UI (Arayüz):** En son olarak envanter, sohbet pencereleri ve isimler (TextTail) her şeyin üstüne çizilir.

## 6.4. Performans ve FPS Kontrolü

Metin2 motoru, bilgisayarı gereksiz yormamak için "Frame Skipping" (Kare Atlatma) mekanizması kullanır:
* Eğer bilgisayar çok hızlıysa ve FPS limiti varsa, motor bir sonraki kareyi çizmek için milisaniye cinsinden bekler (`ELTimer_SetFrameMSec`).
* Analiz ettiğimiz kodda, `perf_game_render.txt` dosyasına her bir modülün (Zemin, Karakter, Efekt) ne kadar sürede çizildiği loglanır. Eğer oyununuz donuyorsa (FPS Drop), bu log dosyası hangi modülün yavaş olduğunu gösterir.

## 6.5. FOV (Görüş Açısı) ve Kamera

İstemci tarafındaki en önemli ayarlardan biri **FOV (Field of View)**'dur. `PythonApplication.cpp` içerisinde FOV seviyesi şu kodla ayarlanır:
```cpp
#ifdef ENABLE_FOV_OPTION
float fFOV = m_pySystem.GetFOVLevel();
m_pyGraphic.SetPerspective(fFOV, fAspect, 100.0, fFarClip);
#else
m_pyGraphic.SetPerspective(30.0f, fAspect, 100.0, fFarClip);
#endif
```
Standart Metin2'de bu değer sabittir (`30.0f`). Modern source dosyalarında (sizin dosyanızda olduğu gibi) oyuncuya bu açıyı değiştirme (Geniş Ekran) imkanı sunulur.

---
**Geliştirici Notu:** Oyununuza yeni bir görsel sistem (Örn: Render Target veya Gelişmiş Işıklandırma) eklediğinizde, bu sistemi mutlaka `RenderGame` fonksiyonu içerisindeki doğru yere (Efektlerden sonra, UI'dan önce gibi) eklemelisiniz.

Metin2 dünyasında ekranınızda gördüğünüz her karakter, her at ve her canavar birer `CInstanceBase` nesnesidir. Bu sınıf, sunucudaki `CHARACTER` sınıfının istemci tarafındaki (görsel) karşılığıdır. Modellerin yüklenmesi, zırhların giyilmesi ve binicilik sistemleri burada yönetilir.

## 2.1. InstanceBase Nedir?

Bir oyuncu yanınıza geldiğinde, sunucu size onun bilgilerini paket olarak gönderir. İstemci bu paketi alınca `CInstanceBase` sınıfından bir nesne üretir. Bu nesne:
* Hangi 3D modelin (`Granny`) yükleneceğini bilir.
* Zırhın parlayıp parlamayacağını (`Specular`) hesaplar.
* Atın veya bineğin o anki seviyesini ve yeteneklerini tutar.

## 2.2. Zırhların Görselleşmesi (`__ArmorVnumToShape`)

Oyunda bir zırh giydiğinizde, istemci bu zırhın Vnum (kod) değerine bakarak hangi dış görünüşü (`Shape`) kullanacağını bulur.

### Kod Analizi: `item_proto` Değerlerinin Kullanımı
```cpp
bool __ArmorVnumToShape(int iVnum, DWORD* pdwShape) {
CItemData* pItemData;
if (!CItemManager::Instance().GetItemDataPointer(iVnum, &pItemData))
return false;

// item_proto'daki 3. değer (value3) zırhın görünüm ID'sidir (ShapeIndex).
*pdwShape = pItemData->GetValue(3);
return true;
}
```
Buradaki mantık şöyledir: Sunucu "11299" (Mavi Çelik Zırh) giyildiğini söyler. İstemci bu koda ait `item_proto` verisine bakar, `value3` değerindeki (Örn: 20) şekil ID'sini alır ve karakterin üzerine 20 numaralı `MSM` (Model Script) dosyasındaki kaplamayı giydirir.

## 2.3. Binek ve At Sistemi (`SHORSE`)

`InstanceBase` içerisinde atlar ve binekler için özel bir alt yapı (`SHORSE`) bulunur. Bu yapı, atın seviyesine göre karakterin yeteneklerini kısıtlar veya artırır:

* **Saldırı Kontrolü (`CanAttack`):** Eğer atın seviyesi 1'den küçükse (Acemi At), karakter at üzerindeyken vuramaz.
* **Yetenek Kontrolü (`CanUseSkill`):** Atlı yeteneklerini kullanabilmek için at seviyesinin en az 3 (Asker At) olması gerekir.
* **Görsel Bağlantılar (`__AttachHorseSaddle`):** Atın üzerine eyer (Saddle) eklenmesi veya çıkarılması `AttachModelInstance` fonksiyonu ile yapılır.

## 2.4. Görünmezlik ve GM Belirtileri

* **Görünmezlik (`IsInvisibility`):** Eğer bir karakterde `AFFECT_INVISIBILITY` (Görünmezlik) varsa, motor bu nesneyi çizmez (`IsMovieMode`). Ancak GM'ler için özel bir kontrol (`__MainCanSeeHiddenThing`) yapılarak görünmez oyuncuları görmeleri sağlanır.
* **GM Logosu (`IsGameMaster`):** Eğer karakterde sarı GM logosu (`AFFECT_YMIR`) varsa, `IsGameMaster` fonksiyonu `true` döner.

## 2.5. Çizim Önceliği (`LessRenderOrder`)

Ekranda çok sayıda karakter olduğunda (Örn: Pazar Alanı), ekran kartının hangisini önce çizeceği performans için kritiktir.
1. **Alpha (Saydamlık):** Saydam olan karakterler (Örn: Ölüp canlananlar) en son çizilir.
2. **LOD (Level of Detail):** Uzaktaki karakterlerin daha az detaylı modelleri çizilir (`GetLODLevel`).
3. **Hizalama:** Ekranın merkezine yakın olanlar önceliklidir.

---
**Geliştirici Notu:** Oyununuza yeni bir binek eklediğinizde, bu bineğin kodunu `CInstanceBase::SHORSE::GetLevel` içerisindeki `switch-case` yapısına eklemelisiniz. Aksi takdirde oyuncu binek üzerindeyken "Z" tuşuyla canavarlara vuramaz.

Metin2 istemcisi, sunucudan gelen ham verileri (`Packet`) bir grafik şölenine dönüştürmek zorundadır. Bu dönüşümün başladığı yer `PythonNetworkStream.cpp` dosyasıdır. Bu dosya, ağ soketi ile oyunun görselleri arasındaki "Tercüman"dır.

## 3.1. Ağ Akışı (Network Stream) Nasıl Çalışır?

Sunucudan bir veri paketi geldiğinde `CPythonNetworkStream::Process()` fonksiyonu tetiklenir:
1. Soketten paket başlığı (Header) okunur.
2. `CheckPacket` fonksiyonu ile bu başlığın geçerli olduğu doğrulanır.
3. Başlığa ait veri yapısı (Struct) belleğe kopyalanır.
4. İlgili "Phase" (Faz) fonksiyonu çağrılarak veri oyunun diğer parçalarına (Envanter, Karakter Yöneticisi vb.) dağıtılır.

## 3.2. Faz (Phase) Sistemi: Login'den Game'e Geçiş

Metin2'de iletişim, bulunduğunuz duruma göre farklı "Fazlar" üzerinden yürütülür. `PythonNetworkStream.cpp` bu fazları yöneten dosyadır:

* **Login Phase (`PythonNetworkStreamPhaseLogin.cpp`):** Kullanıcı adı ve şifre doğrulama paketlerini işler.
* **Select Phase (`PythonNetworkStreamPhaseSelect.cpp`):** Karakter seçimi ekranındaki karakter bilgilerini (`dwID`, `byJob`, `byLevel`) doldurur.
* **Loading Phase (`PythonNetworkStreamPhaseLoading.cpp`):** Harita yüklenirken sunucu ile senkronizasyonu sağlar.
* **Game Phase (`PythonNetworkStreamPhaseGame.cpp`):** Oyun içi tüm hareketler, ticaret ve savaş paketlerini işlediği ana katmandır.

## 3.3. Paket Haritalama (Header Map)

İstemcinin hangi paket numarasının kaç bayt olduğunu bilmesi gerekir. Bu bilgi `CNetworkPacketHeaderMap` içerisinde saklanır:

```cpp
Set(HEADER_GC_CHAT, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCChat), DYNAMIC_SIZE_PACKET));
Set(HEADER_GC_ITEM_SET, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCItemSet), STATIC_SIZE_PACKET));
```
* **STATIC_SIZE:** Paketin boyutu her zaman sabittir (Örn: Seviye atlama).
* **DYNAMIC_SIZE:** Paketin boyutu veriye göre değişir (Örn: Sohbet mesajı veya Pazar içeriği).

## 3.4. Karakter Bilgilerinin Dağıtımı

Karakter seçim ekranında bir karaktere tıkladığınızda `GetAccountCharacterSlotData` fonksiyonu çalışır. Bu fonksiyon, sunucudan gelen ham verileri (IP adresi, Port numarası, Karakter adı) Python tarafına (UI) gönderir:

```cpp
case ACCOUNT_CHARACTER_SLOT_NAME:
return rkSimplePlayerInfo.szName;
case ACCOUNT_CHARACTER_SLOT_LEVEL:
return rkSimplePlayerInfo.byLevel;
```

## 3.5. Marka ve Sembol Yönetimi (Guild Mark)

Lonca logoları (`Guild Mark`) sunucudan parça parça indirilir. `__DownloadMark` ve `UploadMark` fonksiyonları bu dosya akışını yönetir. Logolar indirildikten sonra `GuildMarkManager` üzerinden belleğe aktarılır ve `InstanceBase` tarafından karakterlerin başında gösterilir.

---
**Geliştirici Notu:** Eğer sunucuya yeni bir sistem eklediyseniz (Örn: Hızlı Ekipman) ve paketi sunucudan göndermenize rağmen istemci hiçbir şey yapmıyorsa, ilk kontrol etmeniz gereken yer `PythonNetworkStream.cpp` içerisindeki `CMainPacketHeaderMap` tanımı ve paketi karşılayacak olan `Recv[Sistemİsmi]Packet` fonksiyonudur.

Metin2'de bir canavar öldüğünde veya bir oyuncu eşya attığında, o eşyanın yerde 3D bir model olarak görünmesi, parlaması ve isminin yazılması `PythonItem.cpp` dosyasında yönetilir. Bu bölüm, yerdeki eşyaların fiziksel davranışlarını ve ses efektlerini analiz eder.

## 4.1. Eşya Oluşturma ve Fiziksel Konum (`CreateItem`)

Yerde bir eşya belirdiğinde sunucudan bir "Eşya Oluştur" paketi gelir. İstemci bu paketi alınca `CreateItem` fonksiyonunu çalıştırır:
* **Yükseklik Ayarı:** Eşya her zaman zeminin (`CPythonBackground`) bir miktar üzerinde (`+10.0f`) oluşturulur.
* **BDrop Bayrağı:** Eğer eşya bir "Düşme" (`bDrop`) efektiyle geliyorsa, yerden sekme ve animasyon süreci başlatılır.

## 4.2. Gelişmiş Eşya İsimleri ve Dönüşüm Küreleri

Normal eşyalar için `pItemData->GetName()` yeterlidir. Ancak bazı özel durumlarda (Örn: Dönüşüm Küreleri), eşyanın ismi dinamik olarak oluşturulur:
```cpp
case CItemData::ITEM_TYPE_POLYMORPH: {
const char* c_szTmp;
CPythonNonPlayer::Instance().GetName(alSockets[0], &c_szTmp);
len += snprintf(szItemName, sizeof(szItemName), "%s", c_szTmp);
}
```
Burada, eşyanın ismi `item_proto`dan değil, o eşyanın `socket0` (Yuva 0) değerine kayıtlı olan canavarın isminden alınır. Bu sayede "Dönüşüm Küresi" yerine "Yabani Köpek Dönüşüm Küresi" yazar.

## 4.3. Yere Düşme Animasyonu ve "Saplanma" Mantığı

Metin2'nin en estetik grafik detaylarından biri, ok ve kılıç gibi eşyaların yere saplanmasıdır.
* **Saplanma (`bStabGround`):** Eğer düşen eşya bir kılıç (`WEAPON_SWORD`) veya ok (`WEAPON_ARROW`) ise, `bStabGround` bayrağı devreye girebilir (Orijinal kodda bu kısım özelleştirilebilir).
* **Dönme ve Yatış:** Eşya yere düştüğünde, onun en büyük boyutu (`BoundBox`) hesaplanır. Eğer eşya "ince ve uzun" ise, yere paralel yatacak şekilde rastgele bir Quaternion (Rotasyon) atanır. Bu, eşyaların her zaman aynı yöne bakmasını engeller ve doğal bir görünüm verir.

## 4.4. Ses ve Efekt Entegrasyonu

Eşyaların hem düşerken hem de yerden alınırken çıkardıkları sesler türlerine göre değişir (`__GetDropSoundType`):
* **Zırhlar:** Metalik bir `ARMOR` sesi.
* **Takılar:** Daha hafif bir `ACCESSORY` sesi.
* **İksirler:** `POTION` sesi.
* **Işınlanma:** `PORTAL` sesi.
Ayrıca her düşen eşyanın altında parlayan bir efekt (`m_dwDropItemEffectID`) oluşturulur.

## 4.5. TextTail: İsim Etiketleri

Yerdeki eşyanın üzerine mause ile gelindiğinde veya `Alt` tuşuna basıldığında görünen isimler `CPythonTextTail` üzerinden çizilir. Bu isim etiketi, 3D dünyadaki eşya modelinin tepesine (`v3EndPosition`) bağlanır. Eğer eşya sahibi tarafından henüz alınabilir değilse, isim etiketi rengi buna göre değişir.

---
**Geliştirici Notu:** Eğer yerdeki bir eşyanın (Örn: Bir etkinlik eşyası) daha belirgin görünmesini istiyorsanız, `CreateItem` fonksiyonunda `rem.CreateEffect` çağrısını o eşyaya özel bir efekt ID'si ile değiştirebilirsiniz. Bu, eşyanın yerde bir ışık sütunu gibi görünmesini sağlayacaktır.

Metin2'nin atmosferini oluşturan parlamalar, hasar sayıları, seviye atlama efektleri ve PVP işaretleri `InstanceBaseEffect.cpp` dosyasında yönetilir. Bu dosya, `EffectManager` (Efekt Yöneticisi) ile karakter modelleri arasındaki görsel bağı kuran ana unsurdur.

## 5.1. Hasar Sayılarının Oluşturulması (`ProcessDamage`)

Ekranda uçuşan hasar sayıları aslında her bir rakamın (`0.dds` - `9.dds`) yan yana dizilmesidir.
* **Dinamik Doku Karıştırma:** Kod, aldığı hasar değerini (Örn: 1540) basamaklarına ayırır ve her basamak için uygun `.dds` dosyasını `textures` listesine ekler.
* **Billboard Teknolojisi:** Hasar sayıları her zaman kameraya bakacak şekilde (`InverseViewMatrix`) ayarlanır. Bu sayede karakter dönse bile hasar sayılarını düz bir şekilde okuyabilirsiniz.
* **Renkler:** Hasarın türüne göre (Kritik, Delici, Normal) farklı doku yolları (`target_`, `selfdamage_`) kullanılır.

## 5.2. Seviye Atlama ve Statü Efektleri

Bazı etkiler doğrudan `InstanceBase` nesnesine "yapıştırılır" (`AttachEffect`):
* **Level Up:** Karakter seviye atladığında gökten inen altın ışık sütunu.
* **Skill Up:** Bir beceri seviyesi arttığında karakterin altında oluşan parlama.
* **Dış Görünüş Efektleri:** Seviye atlayan bir metin taşından duman çıkması (`AttachSmokeEffect`) bu sistemin bir parçasıdır.

## 2.3. Lonca (İmparatorluk) ve PVP İşaretleri

Karakterlerin kimliğini belirleyen görsel unsurlar otomatik olarak ekrana yansıtılır:
* **İmparatorluk Efekti:** Düşman imparatorluktan bir oyuncuyla karşılaştığınızda (eğer görünmez değilse) başının üzerinde imparatorluk rengine göre bir efekt oluşturulur.
* **Hedefleme (`Target`):** Bir oyuncuyu veya canavarı seçtiğinizde ayaklarının altında oluşan daire efekti (`EFFECT_SELECT`).
* **PVP Key Sistemi:** İki oyuncu arasındaki PVP bağını (Düello, Serbest vb.) takip etmek için benzersiz bir anahtar (`__GetPVPKey`) oluşturulur. Bu anahtar, her iki karakterin VID numaralarının hashlenmesiyle elde edilir.

## 5.4. Şeffaflık ve Kaybolma Animasyonu (`UpdateDeleting`)

Bir karakter öldüğünde veya kapsama alanından çıktığında aniden yok olmaz.
* **Blend Mode:** Karakter "Şeffaf Çizim Modu"na alınır.
* **Alpha Azalması:** Karakterin görünürlüğü (`Alpha`) saniyede 1.5 birim hızla azaltılır. Alpha 0'a ulaştığında karakter bellekten tamamen silinir.

## 5.5. Efekt Konteynırı (Effect Container)

Bir karakterin üzerinde aynı anda onlarca efekt (Zehir, Bufflar, Parlamalı Zırhlar) olabilir.
* **Mükerrer Engelleme:** `__EffectContainer_AttachEffect` fonksiyonu, aynı efektin (`dwEftKey`) karakter üzerine birden fazla kez eklenmesini (Stacking) engeller. Eğer efekt zaten varsa, yeni bir tane oluşturulmaz.
* **Toplu Temizlik:** Karakter silindiğinde veya öldüğünde konteynır boşaltılır ve tüm bağlı efektler (`DetachEffect`) durdurulur.

---
**Geliştirici Notu:** Oyununuzdaki hasar sayılarının fontunu veya boyutunu değiştirmek isterseniz, `d:/ymir work/effect/affect/damagevalue/` klasöründeki `.dds` dosyalarını düzenlemeli ve `ProcessDamage` fonksiyonu içerisindeki `FONT_WIDTH` değerini yeni harf genişliğinize göre güncellemelisiniz.

İstemci tarafında sizin karakterinizi temsil eden, envanterden statülere, otomatik saldırıdan dayanıklılık (Stamina) kontrolüne kadar her şeyi yöneten sınıf `CPythonPlayer`'dır. Bu dosya, grafiksel karakter modeli (`InstanceBase`) ile Python tabanlı arayüz (UI) arasındaki veri aktarım merkezidir.

## 6.1. Oyuncu Statüleri ve Güç Hesaplaması

Sunucudaki statüleriniz (Güç, Zeka, Çeviklik) istemciye ulaştığında `CPythonPlayer` bu değerleri kullanarak görsel saldırı değerlerinizi (`Attack Value`) hesaplar.
* **Irk Bazlı Bonuslar:** Karakterinizin sınıfına göre ana saldırı statüsü değişir. Savaşçılar için `STR` (Güç), Şamanlar için `IQ` (Zeka), Ninjalar için `DX` (Çeviklik) baz alınır.
* **Saldırı Formülü:** `__GetTotalAtk` fonksiyonu, silah gücü, seviye bonusu ve isabet oranını (`HitRate`) harmanlayarak karakter penceresinde gördüğünüz sayıları üretir.
* **İsabet ve Savuşturma:** `__GetHitRate` ve `__GetEvadeRate` fonksiyonları, rakiplerinize ne kadar ıskalayacağınızı veya size gelen darbelerden ne kadar kaçınacağınızı (Miss) belirleyen istemci tarafındaki tahmin mekanizmalarıdır.

## 6.2. Otomatik Saldırı ve Hedef Takibi (`__Update_AutoAttack`)

Metin2'nin "Otomatik Av" veya "Space tuşuyla vurma" mantığı bu fonksiyon ile yönetilir:
1. **Hedef Kontrolü:** Eğer bir hedef seçiliyse (`m_dwAutoAttackTargetVID`) ve hedef ölmemişse saldırı başlar.
2. **Kısıtlamalar:** Karakter baygınsa (`Sleep`) veya binicilik seviyesi yetersizse (`CanAttackHorseLevel`) otomatik saldırı durdurulur.
3. **Charge Skills:** Eğer karakter o an bir hareket becerisi (Örn: Hamle) kullanıyorsa düz vuruşlar askıya alınır.

## 6.3. Dayanıklılık (Stamina) ve Koşma Kontrolü

Oyunda koşarken azalan sarı bar (Stamina) `PythonPlayer` tarafından saniye bazlı hesaplanır:
```cpp
float fElapsedTime = CTimer::Instance().GetElapsedSecond();
m_fCurrentStamina -= (fElapsedTime * m_fConsumeStaminaPerSec);
SetStatus(POINT_STAMINA, DWORD(m_fCurrentStamina));
```
* **UI Senkronizasyonu:** Dayanıklılık her değiştiğinde Python tarafındaki `RefreshStamina` fonksiyonu çağrılarak arayüzdeki barın güncellenmesi sağlanır.

## 6.4. Otomatik Eşya Toplama (`Auto Pickup`)

Modern Metin2 source dosyalarında bulunan otomatik toplama özelliği burada tetiklenir:
* **Zamanlama:** 500 milisaniyede bir (`s_dwNextTCPAutoPickTime`) çevre taraması yapılır.
* **Uzaklık Filtresi:** `PickCloseItem` fonksiyonu, karakterin çevresindeki en yakın eşyaları tespit ederek sunucuya "Bunu al" paketleri gönderir.

## 6.5. Lonca Arazisi Bildirimleri (`NotifyGuildAreaEvent`)

Haritada gezerken bir lonca arazisine girdiğinizi veya çıktığınızı ekranın ortasındaki yazıdan anlarsınız.
* **Konum Analizi:** Oyuncunun koordinatları `PythonMiniMap::Instance().GetGuildAreaID` üzerinden kontrol edilir.
* **Python Köprüsü:** Eğer oyuncu bir araziye girerse, Python tarafındaki `BINARY_Guild_EnterGuildArea` fonksiyonu tetiklenerek gerekli UI mesajları bastırılır.

---
**Geliştirici Notu:** Karakter penceresindeki (C tuşu) saldırı değerlerinin yanlış hesaplandığını düşünüyorsanız, `CPythonPlayer.cpp` içerisindeki `__GetTotalAtk` formülünü incelemelisiniz. Genellikle "Silah Kostümü" veya "Yeni Efsunlar" gibi sistemler eklendiğinde bu formülün güncellenmesi unutulur ve oyuncu aslında 500 vururken karakter penceresinde 300 görebilir.

Metin2'nin iletişim kalbi olan sohbet (Chat) sistemi, istemci tarafında `CPythonChat` sınıfı tarafından yönetilir. Bu sistem sadece oyuncuların karşılıklı konuşmalarını değil, aynı zamanda sistem duyurularını, eşya bilgilerini ve oyun içi komut çıktılarını da işler. `PythonChat.cpp` dosyası, bu metinlerin ekranda nasıl belireceğini ve kaydırılacağını (Scrolling) kontrol eder.

## 7.1. Sohbet Modları ve Filtreleme

Metin2 sohbet penceresi farklı sekmelerden ve modlardan oluşur:
* **BOARD_STATE_VIEW:** Normal oyun anında, mesajların belirli bir süre sonra silindiği (Fade out) otomatik mod.
* **BOARD_STATE_LOG:** Geçmişe dönük tüm mesajların görülebildiği günlük modu.
* **BOARD_STATE_EDIT:** Sohbet satırının aktif olduğu ve yazı yazılabildiği mod.
`CPythonChat`, oyuncunun seçtiği filtrelere göre (Örn: Sadece Bağırma veya Sadece Grup) mesajları `ArrangeShowingChat` fonksiyonu ile anlık olarak süzgeçten geçirir.

## 7.2. Mesaj Ekleme ve Bellek Yönetimi (`AppendChat`)

Yeni bir mesaj geldiğinde şu süreçler işletilir:
1. **Font Seçimi:** Mesajın yazılacağı varsayılan yazı tipi (`DefaultFont`) ayarlanır.
2. **Renk Atama:** Mesajın tipine göre (`iType`) renk belirlenir. Örneğin, "Bağırma" mesajları yeşil, "Sistem" mesajları sarı, "PM" mesajları ise pembe (Mor) renkte boyanır.
3. **Deque Hafızası:** Mesajlar `m_ChatLineDeque` adında bir kuyrukta saklanır. Bellek şişmesini önlemek için `CHAT_LINE_MAX_NUM` (Genellikle 500 satır) sınırı aşıldığında en eski mesajlar otomatik olarak silinir.

## 7.3. Animasyon ve Kaydırma (Scrolling)

Sohbet penceresindeki metinlerin hareketleri matematiksel olarak hesaplanır:
* **Fading (Solma):** `UpdateViewMode` içerisinde, mesajın ekrana geliş süresine göre şeffaflığı (`Alpha`) azaltılır. Eski mesajlar yavaşça silinerek ekranın temiz kalması sağlanır.
* **Kaydırma:** Oyuncu fare tekerleğiyle sohbeti kaydırdığında, `m_fEndPos` (0.0 ile 1.0 arası bir değer) güncellenir ve `ArrangeShowingChat` buna göre kuyruğun farklı bir bölgesini ekrana yansıtır.

## 7.4. Gecikmeli Mesajlar (`AppendChatWithDelay`)

Bazı bildirimlerin hemen değil, belirli bir süre sonra çıkması gerekebilir.
* **Wait List:** Gecikmeli mesajlar `m_WaitChatList` içerisine eklenir. `Update` fonksiyonu her karede (Frame) bu listeyi kontrol eder; zamanı gelen mesajlar normal sohbet kuyruğuna aktarılır.

## 7.5. Grafiksel Metin Örnekleri (GraphicTextInstance)

Her sohbet satırı aslında bir `CGraphicTextInstance` nesnesidir:
* **Performans:** Metinler her karede yeniden oluşturulmaz. Sadece konumları güncellenir ve `Render` fonksiyonu ile ekran kartına (GPU) gönderilir.
* **Hizalama:** Mesajların pencere içindeki `x` ve `y` koordinatları `SetPosition` ve `SetStep` (Satır aralığı) fonksiyonlarıyla milimetrik olarak ayarlanır.

---
**Geliştirici Notu:** "Chat Log Dolduğunda Oyunun Kasması" sorunu genellikle `ArrangeShowingChat` fonksiyonunun her mesaj geldiğinde tüm kuyruğu tekrar taramasından kaynaklanır. Eğer çok fazla spam mesaj geliyorsa, `CHAT_LINE_MAX_NUM` değerini düşürmek veya `Deque` yerine daha performanslı bir veri yapısı kullanmak client performansını artıracaktır. Ayrıca, sohbet renklerini değiştirmek isterseniz `GetChatColor` fonksiyonundaki `switch-case` yapısına yeni renk kodları ekleyebilirsiniz.



Metin2'de `db` adlı sunucu bileşeni, oyun dünyası ile MySQL veritabanı arasında devasa bir köprü vazifesi görür. Bu köprünün bekçisi ise `ClientManager.cpp` dosyasıdır. Bu dosya, verilerin kaybolmamasını ve sunucunun SQL'e aşırı yüklenmemesini sağlayan **Cache (Önbellek)** mekanizmasını yönetir.

## 7.1. Sistemin Mimarisi: DB <=> Game

Metin2'de `game` sunucusu (oyuncuların gezdiği yer) asla doğrudan MySQL'e SQL sorgusu atmaz.
1. **Game Sunucusu:** "Şu oyuncunun 100 altını oldu" der ve bu bilgiyi bir paketle `db` sunucusuna gönderir.
2. **DB Sunucusu (`ClientManager`):** Bu bilgiyi alır, bir süre hafızasında (Cache) tutar.
3. **Kalıcı Kayıt:** Belirli aralıklarla (flush) veya oyuncu çıktığında hafızadaki bilgiyi MySQL'e `UPDATE` sorgusuyla yazar.

## 7.2. Boot Süreci: Tabloların Hafızaya Alınması

`db` sunucusu ilk açıldığında `ClientManager::Initialize` çalışır ve tüm statik oyun tablolarını MySQL'den okuyup RAM'e yükler:
* `TMobTable`: Tüm canavarların özelliklerini.
* `TItemTable`: Tüm eşyaların özelliklerini (`item_proto`).
* `TRefineTable`: Artı basma şemalarını.
* `TSkillTable`: Beceri hasarlarını ve gereksinimlerini.

Daha sonra bu veriler, `game` sunucuları açıldığında onlara toplu paketler (`peer->Encode`) halinde gönderilir. Bu sayede `game` sunucusu çok hızlı bir şekilde ayağa kalkar.

## 7.3. Önemli Fonksiyon: `QUERY_QUEST_SAVE` (Görev Kaydı)

Görev verileri (Quest Flags) çok sık değişir. `ClientManager` bu verileri optimize etmek için `REPLACE INTO` veya `DELETE` sorgularını kullanır:
```cpp
snprintf(szQuery, sizeof(szQuery),
"REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(%d, '%s', '%s', %ld)",
GetTablePostfix(), pTable->dwPID, pTable->szName, pTable->szState, pTable->lValue);
```
Eğer görev değeri 0 ise, veritabanını şişirmemek için o satırı siler (`DELETE`). Eğer sıfırdan farklıysa, `REPLACE` komutu ile üzerine yazar.

## 7.4. Depo (Safebox) Güvenliği ve Şifre Kontrolü

Depo açma işlemi en hassas veri işlemlerinden biridir. `QUERY_SAFEBOX_LOAD` fonksiyonu şu süreci yönetir:
1. Oyuncunun girdiği şifreyi (`szPassword`) alır.
2. MySQL'den o oyuncunun gerçek depo şifresini çeker.
3. Karşılaştırma yapar. Eğer şifre `"000000"` (varsayılan) ise veya MySQL'deki ile eşleşiyorsa verileri `game` sunucusuna yollar.
4. Eğer yanlışsa `HEADER_DG_SAFEBOX_WRONG_PASSWORD` paketiyle işlemi iptal eder.

## 7.5. ID Range Manager: Benzersiz Eşya Seri Numaraları

Metin2'de her eşyanın dünyada tek olan bir seri numarası (Item ID) vardır.
* Bir eşya oluşturulurken `db` sunucusu `GetRange()` fonksiyonunu kullanarak bir sayı aralığı (örneğin 100.000 ile 110.000 arası) tahsis eder.
* Bu numara aralığı dolduğunda `db`den yeni bir aralık istenir.
* Bu sistem, birden fazla kanal (CH) varken aynı seri numaralı iki eşyanın (Duplicate) oluşmasını engeller.

---
**Geliştirici Notu:** Eğer veritabanında yaptığınız bir değişiklik oyunda anında görünmüyorsa (Örn: Bir oyuncunun parasını MySQL'den değiştirdiniz ama oyunda hala eski parası görünüyor), bunun sebebi `db` sunucusunun o veriyi hafızasında (**Cache**) tutuyor olmasıdır. Bu tür manuel değişikliklerin etkili olması için oyuncunun oyundan çıkmış olması veya sunucunun yeniden başlatılması gerekir.

Metin2'nin yüksek oyun hızı ve binlerce anlık oyuncu işlemi (eşya alma, düşürme, statü verme), veritabanının (MySQL) tek başına altından kalkamayacağı bir yük oluşturur. `db` sunucusu bu yükü hafifletmek için `Cache.cpp` dosyasında tanımlanan **Sınıf Tabanlı Önbellek** sistemini kullanır.

## 2.1. Önbellek (Cache) Nedir ve Neden Gerekli?

Bir oyuncu yerden bir kılıç aldığında, sunucu her seferinde MySQL'e "INSERT INTO..." sorgusu gönderseydi, binlerce oyuncu aynı anda işlem yaptığında veritabanı kitlenirdi. `Cache` sistemi bu işlemi şu şekilde yürütür:
1. **RAM'de Tutma:** İşlem önce sunucunun RAM'indeki bir nesneye (`TPlayerItem`) yazılır.
2. **Bayrak Koyma:** Bu nesnenin üzerindeki `m_bNeedQuery` bayrağı "true" yapılır. (Yani: "Bu veri değişti, SQL'den farklı!")
3. **Flush (Yazma):** Belirlenen bir süre sonra (Örn: `g_iItemCacheFlushSeconds`) bu veri topluca veritabanına kaydedilir.

## 2.2. Eşya Önbelleği (`CItemCache`)

Eşyaların kaydı (`REPLACE INTO`) en çok işlem gören kısımdır. `CItemCache::OnFlush` fonksiyonu, bir eşyanın taşlarını, efsunlarını ve konumunu tek bir devasa sorgu ile günceller:

```cpp
snprintf(szItemQuery, sizeof(szItemQuery), "REPLACE INTO item%s (%s) VALUES(%s)",
GetTablePostfix(), szColumns, szValues);
```
* **Optimizasyon:** Eğer eşyanın taşları veya efsunları değişmemişse (`isSocket`, `isAttr`), sorguya bu sütunlar dahil edilmez. Bu, SQL trafiğini %40'a kadar azaltır.
* **Silinme:** Bir eşya silindiğinde (`m_data.vnum == 0`), Cache sistemi bunu fark eder ve MySQL'e kalıcı bir `DELETE` sorgusu gönderir.

## 2.3. Oyuncu Önbelleği (`CPlayerTableCache`)

Oyuncunun seviyesi, parası ve konumu (`x, y`) bu önbellekte tutulur. Oyuncu her adım attığında MySQL güncellenmez; ancak oyuncu zindana girdiğinde veya oyundan çıktığında `OnFlush` çağrılarak tüm ilerleme kalıcı hale gelir.

## 2.4. Mağaza Fiyat Listesi Önbelleği (`CItemPriceListTableCache`)

Pazar kurulumunda fiyat listelerinin (`myshop_pricelist`) yönetimi de Cache üzerinden yürütülür. Bir oyuncu dükkanındaki fiyatları güncellediğinde:
1. **UpdateList:** Önce eski fiyatlar silinir ve yeni fiyatlar RAM'deki listeye eklenir. `m_bNeedQuery` bayrağı kaldırılır.
2. **Ölü Veri Temizliği:** Kullanılmayan veya silinen eşya fiyatları listeden temizlenir (`nDeletedNum`).

## 2.5. Flush Zamanlaması (Zaman Azaltma)

Sunucu belleğini korumak için her Cache nesnesinin bir "Sona Erme Süresi" (`m_expireTime`) vardır. Genellikle bu süre 30 dakikadır (`1800` saniye).
* Eğer sunucu ani bir şekilde kapanırsa (Elektrik kesintisi vb.), son Flush işleminden bu yana yapılan tüm değişiklikler (kaydedilmemiş eşyalar, kazanılan paralar) kaybolur. Bu olaya Metin2 camiasında **"Rollback" (Geri Sarma)** denir.

---
**Geliştirici Notu:** "Rollback" sorununu azaltmak için `g_iItemCacheFlushSeconds` değerini düşürebilirsiniz (Örn: 300 saniye - 5 dakika). Ancak bu, MySQL sunucunuz üzerindeki yükü artıracaktır. İdeal dengeyi sunucunuzun performansına göre ayarlamalısınız.

Metin2 sunucusu açılırken, eşya (`item_proto`) ve canavar (`mob_proto`) bilgilerini MySQL veritabanından okuyup bellek hızında işlenebilecek özel bir yapıya çevirmek zorundadır. Bu kritik süreci `ProtoReader.cpp` dosyası yönetir. Bu bölüm, veritabanındaki "yazıların" (Enum/String) sunucu için nasıl "sayılara" (Integer/Bitmask) dönüştürüldüğünü analiz eder.

## 3.1. Neden ProtoReader?

MySQL'de veriler insanlar tarafından okunabilir formatta tutulur (Örn: `ITEM_SWORD`, `APPLY_STR`). Ancak bir savaş anında C++ kodunun bu yazıları tek tek karşılaştırması çok yavaştır. `ProtoReader`, bu yazıları sunucu ilk açıldığında bir kez okur ve onları C++ sabitlerine (Enum) çevirir.

## 3.2. Bitmask Hesaplama: Anti-Flag ve Flag Sistemi

Metin2'de bir eşyanın aynı anda "Savaşçı giyemez", "Atılamaz" ve "Satılamaz" gibi birden fazla özelliği olabilir. Bu özellikler `get_Item_AntiFlag_Value` gibi fonksiyonlarla birleştirilir:
* **Split Mantığı:** Yazılar `|` (Pipe) işareti ile ayrılır (Örn: `ANTI_WARRIOR|ANTI_GIVE|ANTI_SELL`).
* **Üs Hesaplama:** Her özellik bir bit değerine (`2^i`) karşılık gelir. Tüm bu değerler toplanarak tek bir sayı elde edilir.
* **Sonuç:** Sunucu sadece bu tek sayıya bakarak eşyanın tüm yasaklarını (Anti-Flag) anında kontrol edebilir.

## 3.3. Bonus ve Statü Dönüşümleri (`ApplyType`)

Eşyaların üzerindeki efsunlar (`APPLY_MAX_HP`, `APPLY_CRITICAL_PCT` vb.) `get_Item_ApplyType_Value` fonksiyonu ile sayılara dökülür.
* **Dizi Eşleşmesi:** Dosya içerisinde devasa bir `arApplyType` dizisi bulunur.
* **Trim & Compare:** Veritabanından gelen yazıdaki boşluklar temizlenir (`trim`) ve dizi içerisindeki index numarası döndürülür.
* **Örnek:** Eğer efsun `APPLY_STR` ise, bu dizi içerisinde 5. sırada olduğu için C++ tarafında değeri `5` olur.

## 3.4. Canavar Rütbeleri ve Tipleri (`Mob Proto`)

Canavarların güç seviyeleri (`Rank`) ve türleri (`Type`) de benzer şekilde işlenir:
* **Rank:** `PAWN` (Normal), `S_PAWN` (Güçlü), `KNIGHT` (Elit), `BOSS` (Patron).
* **Battle Type:** `MELEE` (Yakın dövüş), `RANGE` (Uzak dövüş), `MAGIC` (Büyülü).
Bu dönüşümler sayesinde sunucu, bir canavarın saldırı menzilini veya agresiflik durumunu en hızlı şekilde belirler.

## 3.5. Proto Yazımı ve Senkronizasyon

`db` sunucusu bu okuma ve dönüştürme işlemini tamamladıktan sonra:
1. **RAM'e Yükleme:** Verileri `TItemTable` ve `TMobTable` yapılarına doldurur.
2. **Binary Proto:** Genellikle bu verileri `item_proto` ve `mob_proto` adında binary dosyalara yazar.
3. **İstemci Senkronizasyonu:** Bu ikili dosyalar istemci (Client) tarafına da kopyalanmalıdır. Eğer sunucudaki proto ile istemcideki proto eşleşmezse, oyuncular eşya isimlerini yanlış görebilir veya oyundan atılabilirler (Syserr: `Itemproto mismatch`).

---
**Geliştirici Notu:** Eğer oyununuza yeni bir efsun (Örn: `APPLY_ELEMENT_RESIST`) eklemek isterseniz, bu efsunu mutlaka `ProtoReader.cpp` içerisindeki `arApplyType` dizisine eklemelisiniz. Aksi takdirde sunucu bu efsunu veritabanından okurken hata verecek veya görmezden gelecektir.

Metin2'de bir oyuncu kullanıcı adı ve şifresini girdiğinde, sunucu bu bilgileri doğrulamak ve karakter bilgilerini çekmek için `db` sunucusundaki `ClientManagerLogin.cpp` dosyasını kullanır. Bu bölüm, giriş sürecinin veritabanı aşamasını analiz eder.

## 4.1. Hesap Doğrulama (`RESULT_LOGIN`)

Oyuncu giriş yapmak istediğinde `db` sunucusu önce `account` tablosuna bir sorgu gönderir.
* **Şifre Kontrolü:** Sorgu sonucunda veritabanındaki şifre (`passwd`) ile kullanıcının girdiği şifre karşılaştırılır. Eğer uyuşmazsa `HEADER_DG_LOGIN_WRONG_PASSWD` paketi döndürülür.
* **Durum Kontrolü:** Hesabın banlı olup olmadığı (`status` sütunu) bu aşamada denetlenir.

## 4.2. Karakter Verilerinin Çekilmesi

Şifre doğruysa, sistem hemen ikinci bir sorgu ile o hesaba bağlı tüm karakterleri (`player` tablosu) çeker:
* **JOIN Sorgusu:** `SELECT id, name, job, level... FROM player WHERE account_id=...`
* **Basit Veri Yapısı:** Karakter seçim ekranında ağır veriler (Envanter, Beceriler vb.) çekilmez. Sadece karakterin 3D modeli için gerekli olan `job` (Sınıf), `part_main` (Zırh), `part_hair` (Saç) ve temel statüler çekilir.

## 4.3. Önbellek (Cache) Senkronizasyonu

Metin2'nin giriş sistemi çok zekidir. Eğer bir karakterin verileri zaten `db` sunucusunun önbelleğinde (`CPlayerTableCache`) varsa, veritabanına sorgu göndermek yerine doğrudan RAM'deki güncel veriyi kullanır:
```cpp
CPlayerTableCache * pc = CClientManager::instance().GetPlayerCache(player_id);
TPlayerTable * pt = pc ? pc->Get(false) : NULL;
if (pt) {
// RAM'den oku
} else {
// Veritabanından satırı oku
}
```
Bu sayede, oyuncu karakter değiştirirken henüz veritabanına kaydedilmemiş olan (Örn: Son 1 dakikada kazandığı seviye) bilgileri bile karakter ekranında doğru bir şekilde görür.

## 4.4. Çift Giriş Koruması (`InsertLogonAccount`)

Aynı hesabın iki farklı kanaldan veya sunucudan girmesini engellemek için `InsertLogonAccount` fonksiyonu kullanılır.
* **Dinamik Liste:** Başarıyla giriş yapan her hesap "Online" listesine eklenir.
* **Hata:** Eğer hesap zaten listedeyse `HEADER_DG_LOGIN_ALREADY` paketi gönderilir ve "Hesabınız şu an bağlı" uyarısı çıkar.

## 4.5. Güvenli Çıkış (Logout) ve Temizlik

Oyuncu oyundan çıktığında `QUERY_LOGOUT` tetiklenir:
1. **Online Silme:** Hesap aktif giriş listesinden temizlenir.
2. **Veri Hazırlığı:** Eğer oyuncu "Karakter Değiştir" dediyse, karakterin son koordinatları ve oyun süresi (`playtime`) hızlıca güncellenir.
3. **Hata Önleme:** Eğer çıkış anında bir hata oluşursa, verilerin yanlış kaydedilmemesi için `DeleteLogonAccount` çağrılır.

---
**Geliştirici Notu:** Giriş sistemindeki en yaygın sorunlardan biri `PLAYER_PER_ACCOUNT` (Hesap başına karakter sayısı) limitidir. Orijinal Metin2'de bu limit 4 iken, bazı sunucularda 5'e çıkarılmıştır. Bu değişikliği yaparken hem `common/tables.h` içerisindeki bu sabiti hem de `ClientManagerLogin.cpp` içerisindeki döngü sınırlarını eşzamanlı güncellemelisiniz. Aksi takdirde, 5. karakteriniz karakter seçim ekranında görünse bile oyuna girmek istediğinizde sunucu hata verebilir.

Metin2'de oyunculara dış kaynaklardan (Nesne Market, site ödülleri, telafi hediyeleri) eşya gönderildiğinde kullanılan sistem `ItemAward` (Eşya Ödülü) sistemidir. `db` sunucusu içerisindeki `ItemAwardManager.cpp` dosyası, bu ödüllerin veritabanından çekilmesini ve oyuncu oyuna girdiğinde ona teslim edilmesini koordine eder.

## 5.1. Ödüllerin Veritabanından Çekilmesi (`RequestLoad`)

Sunucu açıldığında veya periyodik aralıklarla `item_award` tablosuna bir sorgu gönderilir:
* **Filtreleme:** Sadece henüz alınmamış (`taken_time IS NULL`) ve yeni eklenen (`id > g_dwLastCachedItemAwardID`) ödüller çekilir.
* **Hafıza Kaydı:** Çekilen ödüllerin Vnum (Eşya Kodu), Count (Adet) ve Efsun (Socket) bilgileri `TItemAward` yapısı ile RAM'e yüklenir.

## 5.2. Login Bazlı İndeksleme

Sunucu performansını artırmak için ödüller kullanıcı adlarına (`szLogin`) göre gruplandırılır:
```cpp
std::set<TItemAward *> & kSet = m_map_kSetAwardByLogin[kData->szLogin];
kSet.insert(kData);
```
Bu sayede oyuncu oyuna girdiğinde, sunucu binlerce ödül arasından sadece o oyuncuya ait olanları `GetByLogin` fonksiyonuyla milisaniyeler içinde bulabilir.

## 5.3. Nesne Market ve GIFT Bildirimleri (`GIFT`)

Eğer bir ödülün "Neden" (`why`) sütununda "GIFT" yazıyorsa, bu bir hediye bildirimini tetikler:
* **ForwardPacket:** Sunucu, oyuncunun ekranında "Yeni bir hediyeniz var!" veya "Nesne market deponuzda eşya sizi bekliyor" uyarısı çıkması için istemciye özel bir sinyal (`HEADER_DG_ITEMAWARD_INFORMER`) gönderir.

## 5.4. Ödül Teslimatı ve Alındı İşareti (`Taken`)

Oyuncu nesne market deposunu açıp eşyayı envanterine aldığında süreç şöyle tamamlanır:
1. **Envanter Kaydı:** Eşya karakterin çantasına veya mallsuna eklenir.
2. **Veritabanı Güncelleme:** `Taken` fonksiyonu tetiklenerek `UPDATE item_award SET taken_time=NOW()...` sorgusu gönderilir.
3. **Tekrar Engelleme:** `taken_time` sütunu dolduğu için oyuncu aynı ödülü ikinci kez alamaz. `taken_time IS NULL` kontrolü bu güvenliğin temelidir.

## 5.5. Socket ve Efsun Desteği

`item_award` sistemi sadece düz eşyalar için değildir:
* **Soketler:** `socket0, socket1, socket2` değerleri sayesinde taşlı veya süreli eşyalar gönderilebilir.
* **Mall Bayrağı:** `bMall` değeri eşyanın normal depoya mı yoksa "Nesne Market Deposu"na mı gideceğini belirler.

---
**Geliştirici Notu:** `item_award` sisteminde bazen eşyaların gelmemesi sorunu yaşanabilir. Bunun en büyük sebebi veritabanındaki `login` sütununun büyük-küçük harf duyarlılığıdır. `ItemAwardManager` ödülü çekerken `trim_and_lower` fonksiyonuyla kullanıcı adını küçük harfe çevirir. Eğer veritabanına ödülü ekleyen PHP/Web scripti kullanıcı adını büyük harflerle ekliyorsa eşleşme sağlanamayabilir. Bu yüzden her iki tarafın da (Web ve DB) aynı yazım kuralını (Case sensitivity) kullandığından emin olunmalıdır.
 
Geri
Üst