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

Metin2 Acce Sistemi: Aksesuar Soketleme ve Absorbe

Metin2 acce sistemi, eski sunucularda olmayan ama yeni nesil P-server'larda neredeyse standart hâle gelen bir kostüm aksesuar mekaniğidir. Mantığı basittir: sırta takılan bir aksesuar kostümünün (acce) içine normal bir item'ı "soketlersin", acce de o item'ın bonuslarının bir yüzdesini absorbe edip karaktere uygular. Bu rehberde mekaniği sıfırdan, hem sunucu hem client tarafıyla nasıl eklediğimi anlatıyorum.

Acce sistemi tam olarak ne yapar?

Klasik kostüm sistemi sadece görseli değiştirir; acce bir adım öteye gider. Oyuncu, görünümü değiştiren bir aksesuar takar, ardından bu aksesuarın içine güçlü bir zırh, silah ya da başka bir item koyar. Acce o item'ı tüketmez; onun bonus özelliklerinin (örneğin canavarlara zarar, HP, kritik şansı) belirli bir yüzdesini "emer" ve oyuncuya ekstra stat olarak verir. Yani oyuncu hem istediği görünümü korur hem de gizli bir bonus kaynağı kazanır. Bu, sunucuna hem koleksiyon hem de güç ilerlemesi katan güzel bir sistemdir.

Item proto: acce kostümünü tanımlamak

Her şey item proto'da başlar. Acce item'ları normal kostüm gibi ITEM_COSTUME tipindedir, ama alt tipi (subtype) COSTUME_ACCE olmalıdır. Item editöründe ya da item_proto tablosunda:

  • Type: COSTUME
  • SubType: ACCE
  • WearFlags: aksesuarın takılacağı kuşam slotuna uygun bir flag (genellikle ayrı bir WEAR_COSTUME_ACCE slotu).

Bu alt tip, sunucunun "bu item bir acce, içine başka item alabilir" diye anlamasını sağlar. Görsel için ayrıca .gr2 modeli ve ikonu hazırlaman gerekir, ama mekanik tamamen alt tipe ve soketlere dayanır.

Soketler: absorbe edilen item'ı saklamak

Metin2'de her item'ın birkaç socket alanı vardır (normalde metin taşı/elmas için kullanılır). Acce'de bu soketleri, içine konan item'ın bilgisini saklamak için yeniden kullanırız. En temiz yaklaşım, hangi soketin ne tuttuğunu sabitlerle tanımlamaktır:

// item.h — acce'nin soketleri neyi tutacak?
enum EAcceSocket
{
    ACCE_ABSORBED_VNUM_SLOT = 0,  // absorbe edilen item'in vnum'u
    ACCE_ABSORB_PCT_SLOT    = 1,  // absorbe yuzdesi (orn. 50 = %50)
};

Böylece oyuncu acce penceresinde bir item'ı absorbe ettiğinde, sunucu o item'ın vnum'unu socket0'a, hesaplanan absorbe yüzdesini socket1'e yazar. Soketler item'la birlikte veritabanına kaydedildiği için bu bilgi sunucu yeniden başlasa bile kaybolmaz — acce sisteminin kalıcı olmasını sağlayan tam olarak budur.

Absorbe bonuslarını oyuncuya uygulamak

Asıl iş, acce takılı olduğunda absorbe edilen item'ın bonuslarını hesaplayıp karaktere eklemektir. Acce'nin soketinden absorbe edilen vnum'u okuyup o item'ın proto'sundaki apply bonuslarını yüzdeyle çarparız:

// char_item.cpp — acce takilinca/cikinca bonuslari uygula
void CHARACTER::__ApplyAcceAbsorb(LPITEM pAcce, bool bAdd)
{
    if (!pAcce || pAcce->GetSubType() != COSTUME_ACCE)
        return;

    DWORD dwVnum = pAcce->GetSocket(ACCE_ABSORBED_VNUM_SLOT);
    int   iPct   = pAcce->GetSocket(ACCE_ABSORB_PCT_SLOT);
    if (dwVnum == 0 || iPct <= 0)
        return;

    TItemTable * pProto = ITEM_MANAGER::instance().GetTable(dwVnum);
    if (!pProto)
        return;

    for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
    {
        BYTE bType  = pProto->aApplies[i].bType;
        long lValue = pProto->aApplies[i].lValue;
        if (bType == APPLY_NONE || lValue == 0)
            continue;

        long lAbsorbed = (lValue * iPct) / 100;
        ApplyPoint(bType, bAdd ? lAbsorbed : -lAbsorbed);
    }
}

Bu fonksiyonu, karakterin statlarını yeniden hesapladığı yerde — yani ComputePoints() içinde kuşam item'ları işlenirken — çağırmalısın:

// char.cpp — ComputePoints() icinde kusam islenirken
LPITEM pAcce = GetWear(WEAR_COSTUME_ACCE);
if (pAcce)
    __ApplyAcceAbsorb(pAcce, true);

ComputePoints() statları sıfırdan kurduğu için burada her zaman true ile ekleriz; oyuncu acce'yi çıkardığında bir sonraki yeniden hesaplama bonusu otomatik olarak siler. bAdd parametresi ise canlı olarak (tüm statları yeniden hesaplamadan) sökme için kullanışlıdır.

Acce penceresi: paket akışı ve client

Oyuncunun item'ı acce'ye sürükleyebilmesi için bir arayüz penceresi gerekir. Bu, client'ta uiacce.py (Python root dosyası) ile çizilir ve sunucuyla özel paketler üzerinden konuşur. Tipik akış şudur:

  • Oyuncu acce'ye sağ tıklar → client HEADER_CG_ACCE_REFINE_OPEN gönderir, sunucu pencereyi açar.
  • Oyuncu acce item'ını ve absorbe edilecek item'ı slotlara koyar.
  • "Birleştir" butonuna basınca client HEADER_CG_ACCE_REFINE gönderir; sunucu absorbe yüzdesini hesaplar, soketleri yazar ve sonucu HEADER_GC_ACCE_REFINE_RESULT ile geri bildirir.

Bu paket başlıklarını hem client hem sunucuda packet.h içinde aynı numarayla tanımlamak zorundasın — uyuşmazlık olursa client anında "crash" verir. Ayrıca pencere metinleri için locale_game.txt'e gerekli satırları eklemeyi unutma.

Absorbe oranları ve sık yapılan hatalar

Absorbe yüzdesini nasıl belirleyeceğin tamamen senin denge tercihine bağlıdır. İki yaygın yöntem var: sabit bir oran (örneğin her zaman %50), ya da item'ın seviyesine/grade'ine göre bir tablodan okunan değişken oran. Değişken oran daha dengeli sonuç verir çünkü çok güçlü item'ları absorbe etmeyi otomatik olarak sınırlayabilirsin. İşte sık karşılaşılan hatalar:

  • Soketler kaydedilmiyor: absorbe işleminden sonra SetSocket() çağrısının ardından item'ı veritabanına yazdırdığından emin ol; yoksa restart'ta bonus uçar.
  • Çift bonus: __ApplyAcceAbsorb'u hem ComputePoints'ta hem de equip anında ayrıca çağırırsan bonus iki katına çıkar. Tek bir yerden yönet.
  • Yanlış kuşam slotu: acce için ayrı bir WEAR slotu tanımlamazsan normal kostümle çakışır.
  • Paket numarası uyuşmazlığı: client ve sunucu header'ları farklıysa pencere açılmaz ya da crash olur.

Sık Sorulan Sorular

Acce'ye konan item kaybolur mu?

Klasik mekanikte evet — absorbe edilen item tüketilir ve geriye sadece bonusu kalır. Bazı sunucular item'ı geri çıkarılabilir yapar; bu durumda soketlerde item'ın özelliklerini de saklaman ve "çıkar" işleminde geri vermen gerekir.

Acce bonusu kuşanılan item'ın seviye sınırından etkilenir mi?

Hayır. Acce'nin kendi LimitType alanları (örneğin seviye sınırı) geçerlidir; absorbe edilen item'ın seviye şartı doğrudan uygulanmaz. Dengeyi acce'nin kendi sınırlarıyla ayarlamalısın.

Bu sistem mevcut bir source'a sonradan eklenebilir mi?

Evet. Acce sistemi tamamen modülerdir: yeni bir alt tip, birkaç fonksiyon, paket başlıkları ve bir client penceresi. Mevcut quest, item veya kostüm sistemlerine dokunmadan eklenebilir.

Sunucuna eksiksiz bir acce sistemi mi istiyorsun? Proto'dan client penceresine, absorbe dengesinden veritabanı kaydına kadar tüm zinciri kurabilirim — benimle iletişime geç.

Bu kategorideki tüm yazılar →

Devamı için