Callback Lim10Ata\Flatix\xfwidgets::gethtml is invalid (error_invalid_class).

Premium Kırdırınca Hediye Yollama

Jetain

New member
Katılım
2 Kas 2023
Mesajlar
26
Tepkime puanı
2
Puanları
1
Merhaba arkadaşlar.
v2xxx serverlar için Kaira npcsinde Premium kırdırdığınız zaman Letter hediyeleri gönderme işlemlerini anlatacağım.
Öncelikle source içerisinde user.cpp ye gidin.
user.cpp içerisinde bulunan GivePremium isimli fonksiyonda SendPremiumInfo(); isimli fonksiyonun hemen altına aşağıda vereceğim kodları yazın.

Kod:
std::string Sender = "Game XXX";

    std::string Header = "Premium Hediyeniz";
    std::string Message = "İyi Oyunlar";

    _ITEM_TABLE* pTable = nullptr;
    _ITEM_DATA pItem;
    int discPreGifts[3] = { 700002000, 508122000, 399128000 };   //   trina   || golden mattock  || 199 dc flash
    int expPreGifts[3] = { 700002000, 508121000, 399127000 };    //   trina   || golden fish     || 199 exp flash
    int warPreGifts[3] = { 700002000, 810164000, 399129000 };    //   trina   || kanat           || 199 war flash
    if (PremiumID == 10) {
        for (int i = 0; i < 3; i++)
        {
            pItem.nNum = discPreGifts[i];
            pTable = g_pMain->GetItemPtr(pItem.nNum);
            if (pTable == nullptr)
                return;
            pItem.nSerialNum = g_pMain->GenerateItemSerial();
            if (i == 2) {
                pItem.sCount = 199;
            }
            else {
                pItem.sCount = 1;
            }

            pItem.sDuration = pTable->m_sDuration;
            g_DBAgent.SendLetter(Sender, GetName(), Header, Message, 2, &pItem, 0);
        }
    }
    else if (PremiumID == 11)
    {
        for (int i = 0; i < 3; i++)
        {
            pItem.nNum = expPreGifts[i];
            pTable = g_pMain->GetItemPtr(pItem.nNum);
            if (pTable == nullptr)
                return;
            pItem.nSerialNum = g_pMain->GenerateItemSerial();
            if (i == 2) {
                pItem.sCount = 199;
            }
            else {
                pItem.sCount = 1;
            }
            pItem.sDuration = pTable->m_sDuration;
            g_DBAgent.SendLetter(Sender, GetName(), Header, Message, 2, &pItem, 0);
        }
    }
    else if (PremiumID == 12)
    {
        for (int i = 0; i < 3; i++)
        {
            pItem.nNum = warPreGifts[i];
            pTable = g_pMain->GetItemPtr(pItem.nNum);
            if (pTable == nullptr)
                return;
            pItem.nSerialNum = g_pMain->GenerateItemSerial();
            if (i == 2) {
                pItem.sCount = 199;
            }
            else {
                pItem.sCount = 1;
            }
            pItem.sDuration = pTable->m_sDuration;
            g_DBAgent.SendLetter(Sender, GetName(), Header, Message, 2, &pItem, 0);
        }
    }

şimdi bu kod bloğu içerisine ben toplamda 4 adet

Kod:
printf("%s: Type6Cancel is working 1 2 3 4\n", pSkillCaster->GetName().c_str());

şeklinde konsol çıktısı ekledim. Peki neden 4 tane ve neden buralara ekledim, Çünkü Eklenilen yerleri fonksiyon içerisindeki Return değerleri belirliyor. Bu kodu var olan kodunuzun yerine sourceye ekleyip, dosyaları build alıp oyuna girdiğinizde ve Hera scroll basıp bitmesini beklediğinizde buradaki konsol çıktıları çalışacak ve GameServer içerisinde size bilgi verecek. Ki eğer sizin dosyalarınızda sistem sorunlu olduğu için ekrana

%s: Type6Cancel is working 1 ve %s: Type6Cancel is working 2 komutları gelecek ve devamı gelmeyecektir. Bu da bize şunun bilgisini verir;

Kod:
  if (pType == nullptr)



        return;

fonksiyonumuz bu koddan ileri geçemiyor. Buradan geri dönüyor. Yani bizim

Kod:
_MAGIC_TYPE6 * pType = g_pMain->m_Magictype6Array.GetData(nSkillID);

buradaki nSkillID değeri 0 olarak(boş) geldiği için sistem hangi skili sileceğini belirleyemiyor.



Artık sorunu bulduk, gelelim çözüme;

(Belki daha yetkin arkadaşlarımız, çok daha sağlıklı çözümler üretebilir, varsa ekstra çözümler method olarak konu altına yolunu yazarsanız farklı geliştirmeler yapılabilir.)



Bizim buradaki değeri fonksiyona manuel olarak tanımlamamız gerekiyor.

Dolayısı ile fonksiyon başlığını MagicInstance.h içerisinde

Kod:
void Type6Cancel(bool bForceRemoval = false, uint32 iSkillID = 0);

bu şekilde değiştirirsek fonksiyonu gönderen kod bloklarından direkt olarak iSkillID bilgisini çekebiliriz.

Bu şekilde sadece başlığı değiştirirsek sonuç değişmeyeceği için fonksiyonumuzun içinde de ufak bir güncelleme yapıyoruz. Fonksiyonun son hali aşağıdaki gibi olmalı.

Kod:
void MagicInstance::Type6Cancel(bool bForceRemoval /* = false*/, uint32 iSkillID/* = 0*/)

{

    // NPCs cannot transform.

    if (pSkillCaster == nullptr

        || !pSkillCaster->isPlayer()

        || (!bForceRemoval && !TO_USER(pSkillCaster)->isTransformed()))

        return;



    CUser * pUser = TO_USER(pSkillCaster);

    // 13.06.2023 eklemesi ts süre bitme sorunu

    _MAGIC_TYPE6* pType = g_pMain->m_Magictype6Array.GetData(iSkillID);

    _MAGIC_TYPE6* pType2 = g_pMain->m_Magictype6Array.GetData(nSkillID);



    if (pType == nullptr && pType2 == nullptr) // nSkillID null sonradan eklendi sc sildirme vs. için

        return;

    // 13.06.2023 eklemesi ts süre bitme sorunu end



    if (pUser->isSiegeTransformation())

        pUser->m_bRegeneType = REGENE_NORMAL;



    Packet result(WIZ_MAGIC_PROCESS, uint8(MagicOpcode::MAGIC_CANCEL_TRANSFORMATION));

    // TODO: Reset stat changes, recalculate stats.

    pUser->m_transformationType = Unit::TransformationType::TransformationNone;

    pUser->m_sTransformHpchange = false;

    pUser->m_sTransformMpchange = false;



    pUser->Send(&result);

    pUser->SetUserAbility();

    pUser->RemoveSavedMagic(pUser->m_bAbnormalType);

    pUser->StateChangeServerDirect(3, ABNORMAL_NORMAL);



}

peki biz burada ekstradan ne yaptık. Manuel olarak gelen iSkillID değerini de Magic6 datası içerisinde kontrol ettirip hem bizim manuel çektiğimiz iSkillID hem de zaten fonksiyonda bulunan nSkillID değerlerinin ikisinin de aynı anda boş olduğu şartlarda fonksiyon çalışmasın diğer şartlarda çalışsın diye bir düzenleme yaptık.



Bu şekilde düzenlememizi yaptıktan sonra son aşamaya geliyoruz. Bu fonksiyonu nerden gönderiyor source onu bulacağız.

En basit şekilde source içerisinde Type6Cancel( şeklinde arama yaptığımızda karşımıza birçok Type6Cancel(true) ve bir tane de Type6Cancel(false) şekilde yer gelecek. True olan yerler zorla silme işlemi demek yani ya biz fare ile tıklayıp sildik ya da Sundriesten alınan Transformation gibi yaratıklara ölünce kendisi silindi.



O zaman bizi ilgilendiren süresi bitince kendiliğinden silinen False değerinin olduğu yer. Yani CMagicProcess::CheckExpiredType6Skills( fonksiyonu.

Bu fonksiyon içerisinde çok ufak bir ekleme ile sorunu halletmiş olacağız. Bu düzenleme de şu şekilde;

Kod:
 instance.Type6Cancel(false);

yukarıdaki kodu silip yerine

Kod:
instance.Type6Cancel(false, TO_USER(pTarget)->m_sTransformSkillID);// 13.06.2023 eklemesi ts süre bitme sorunu end

kodunu yazıyoruz. Bu kod ile artık bu fonksiyon nSkillID değerini manuel olarak diğer fonksiyona aktarmış oluyor.


Eminim ki bu yazıyı okumayıp direk kodları alarak yoluna devam edecek birçok kişi olacaktır. Ama bir kişi de olsa burada yazılanlardan bir şeyler kaparak kendisi de buna benzer yollar ile sorunları çözme gayesini kendisine amaç edinirse ne mutlu bana.
 
Üst