Çözüldü K Envanter Size Kontrolünü devredışı bırakmak

Bu konu çözüme ulaştırılmıştır. Çözüm için konuya yazılan tüm yorumları okumayı unutmayın. Eğer konudaki yorumlar sorununuzu çözmediyse yeni bir konu açabilirsiniz.
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.

MEKA

Discord: mekaprojects
Site yetkilisi
Süper Moderatör
Premium Üye
Grafiker
Geliştirici
Yardımsever Üye
Mesaj
2.793
Çözümler
287
Beğeni
2.053
Puan
1.850
Ticaret Puanı
2
Başlık ne kadar doğru oldu bilmiyorum. Probleme geçelim
K envanterler genelde 1 slotluk itemler ile çalışıyor. Bunu 3 slota çevirdim yerden aldığımızda, üzerimizden çıkardığımızda ve kod ile çağırdığımızda k envantere geliyor fakat k envanterden normal envantere aktarıyorum bunda problem yok

Tekrar k envantere aktarmaya çalıştığımda 1 slotluk item aktarılıyor 2 ve 3 slotluk item aktarılmıyor
2 ve 3 slotluk itemlerde bu şekilde tek slot gibi algılanıyor

6c707632d379990e6222af7e36d521ea.png


C++:
        else if (Cell.IsCostumeInventoryPosition())
        {
            if (bCell < COSTUME_INVENTORY_SLOT_START)
                return false;

            if (bCell > COSTUME_INVENTORY_SLOT_END)
                return false;

            if (m_pointsInstant.bItemGrid[bCell] == (UINT)iExceptionCell)
            {
                if (bSize <= 3)
                    return true;

                int j = 1;
                BYTE bPage = bCell / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT);

                do
                {
                    UINT p = bCell + (5 * j);

                    if (p >= SPECIAL_INVENTORY_MAX_NUM)
                        return false;

                    if (p / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                        return false;

                    if (m_pointsInstant.bItemGrid[p])
                        if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
                            return false;
                } while (++j < bSize);

                return true;
            }
        }
 
Algoritmik olarak bir sorun var sanki ama direk böyle bakınca anlayamayız. Diğer kodları da incelemek gerekiyor. Yardımcı olması bakımından varsayılan envnterde boşluk kontrolü yapan kodları veriyim

C++:
bool CHARACTER::IsEmptyItemGrid(TItemPos Cell, BYTE bSize, int iExceptionCell) const
{
    switch (Cell.window_type)
    {
    case INVENTORY:
        {
            BYTE bCell = Cell.cell;
            ++iExceptionCell;

            if (Cell.IsBeltInventoryPosition())
            {
                //burayla isimiz yok
            }
            else if (bCell >= INVENTORY_MAX_NUM)
                return false;

            if (m_pointsInstant.bItemGrid[bCell])
            {
                if (m_pointsInstant.bItemGrid[bCell] == iExceptionCell)
                {
                    if (bSize == 1)
                        return true;

                    int j = 1;
                    BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);

                    do
                    {
                        BYTE p = bCell + (5 * j);

                        if (p >= INVENTORY_MAX_NUM)
                            return false;

                        if (p / (INVENTORY_MAX_NUM / 2) != bPage)
                            return false;

                        if (m_pointsInstant.bItemGrid[p])
                            if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
                                return false;
                    }
                    while (++j < bSize);

                    return true;
                }
                else
                    return false;
            }

            // 크기가 1이면 한칸을 차지하는 것이므로 그냥 리턴
            if (1 == bSize)
                return true;
            else
            {
                int j = 1;
                BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);

                do
                {
                    BYTE p = bCell + (5 * j);

                    if (p >= INVENTORY_MAX_NUM)
                        return false;

                    if (p / (INVENTORY_MAX_NUM / 2) != bPage)
                        return false;

                    if (m_pointsInstant.bItemGrid[p])
                        if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
                            return false;
                }
                while (++j < bSize);

                return true;
            }
        }
        break;

Varsayılan envanterdeki kodları kullanarak özel eklediğiniz envanterlerde kontrolleri yaptırabilirsiniz.
 
Bu şekilde bir düzenleme yaptım bu sefer envantere sadece 1 slotlu itemleri kabul ediyor 2 ve 3 slotluk itemleri çağırdığım zaman yeterli alan yok hatası alıyorum.
C++:
        else if (Cell.IsCostumeInventoryPosition())
        {
            if (bCell < COSTUME_INVENTORY_SLOT_START)
                return false;

            if (bCell > COSTUME_INVENTORY_SLOT_END)
                return false;

            if (m_pointsInstant.bItemGrid[bCell])
            {
                if (m_pointsInstant.bItemGrid[bCell] == (UINT)iExceptionCell)
                {
                    if (bSize <= 3)
                        return true;

                    int j = 1;
                    BYTE bPage = bCell / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT);

                    do
                    {
                        UINT p = bCell + (5 * j);

                        if (p >= SPECIAL_INVENTORY_MAX_NUM)
                            return false;

                        if (p / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                            return false;

                        if (m_pointsInstant.bItemGrid[p])
                            if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
                                return false;
                    } while (++j < bSize);

                    return true;
                }
                else
                    return false;
            }
        }
 
Örnek verdiğim kodda
C++:
            if (1 == bSize)
                return true;
            else
            {

Bu ve devamındakileri de eklemeniz gerekiyor.
 
Var ya siz kralsınız ya :D problem bu muymuş cidden o kadar inceledim o kodları dediğiniz yerden sonrasını eklemek hiç aklıma gelmedi
Şimdi geldik 2 ve 3 slotlu itemlerin 1 slot gibi davranmasına görselde ne demek istediğim zaten var
:disney-is-frozen29:
 
Yerden aldığımızda veya kod ile çağırdığımızda itemler 1 slotluk gibi davranıyor fakat kendimiz iç içe koyamıyoruz o şekildeki gibi.
 
Buna benzer kodlar birkaç fonksiyona daha ekleniyordu ama hangilerinde hatırlamıyorum. Dosyaları inceleyerek ilerlemeniz gerekiyor.
char_item.cpp CHARACTER::SetItem( fonksiyonunu bi inceleyin.
 
Böyle bir düzenleme denedim fakat bir sonuç alamadım.

C++:
    case COSTUME_INVENTORY:
        {
            if (wCell >= COSTUME_INVENTORY_MAX_NUM)
            {
                sys_err("CHARACTER::SetItem: invalid item cell %d", wCell);
                return;
            }

            LPITEM pOld = m_pointsInstant.pItems[wCell];

            if (pOld)
            {
                if (wCell < COSTUME_INVENTORY_MAX_NUM)
                {
                    for (int i = 0; i < pOld->GetSize(); ++i)
                    {
                        int p = wCell + (i * 5);

                        if (p >= COSTUME_INVENTORY_MAX_NUM)
                            continue;

                        if (m_pointsInstant.pItems[p] && m_pointsInstant.pItems[p] != pOld)
                            continue;

                        m_pointsInstant.bItemGrid[p] = 0;
                    }
                }
                else
                    m_pointsInstant.bItemGrid[wCell] = 0;
            }

            if (pItem)
            {
                if (wCell < COSTUME_INVENTORY_MAX_NUM)
                {
                    for (int i = 0; i < pItem->GetSize(); ++i)
                    {
                        int p = wCell + (i * 5);

                        if (p >= COSTUME_INVENTORY_MAX_NUM)
                            continue;

                        // wCell + 1 ·Î ÇÏ´Â °ÍÀº ºó°÷À» üũÇÒ ¶§ °°Àº
                        // ¾ÆÀÌÅÛÀº ¿¹¿Üó¸®Çϱâ À§ÇÔ
                        m_pointsInstant.bItemGrid[p] = wCell + 1;
                    }
                }
                else
                    m_pointsInstant.bItemGrid[wCell] = wCell + 1;
            }

            m_pointsInstant.pItems[wCell] = pItem;
        }
 
Bu tür move işlemlerinde sıra genelde şudur. Eşyanın pos kontrolünü yap. Eşyanın taşınacağı yerin yapılan kontroldeki pos sayısı eşyanınkiyle eşitse (genelde kodlarda +1 olarak veriyorlar neden bilmiyorum) ve boşsa (IsEmpty) eşyayı taşı değilse veya bir pencere açıksa veya eşya kullanımdaysa taşıma
 
Yerden alırken de pickupitem fonksiyonuna bakın
Pickupitem fonksiyonum şu şekilde bi sorun görmüyorum birde siz inceleyin isterseniz.

C++:
                if ((item->IsSkillBook() || item->IsUpgradeItem() || item->IsStone() || item->IsGiftBox() || item->IsCostume()) && item->IsStackable() && !IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
                {
                    BYTE bCount = item->GetCount();
                    for (int i = SKILL_BOOK_INVENTORY_SLOT_START; i < COSTUME_INVENTORY_SLOT_END; ++i)
                    {
                        LPITEM item2 = GetInventoryItem(i);

                        if (!item2)
                            continue;

                        if (item2->GetVnum() == item->GetVnum())
                        {
                            int j;

                            for (j = 0; j < ITEM_SOCKET_MAX_NUM; ++j)
                                if (item2->GetSocket(j) != item->GetSocket(j))
                                    break;

                            if (j != ITEM_SOCKET_MAX_NUM)
                                continue;

                            BYTE bCount2 = MIN(200 - item2->GetCount(), bCount);
                            bCount -= bCount2;

                            item2->SetCount(item2->GetCount() + bCount2);

                            if (bCount == 0)
                            {
                                ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾ÆÀÌÅÛ È¹µæ: %s"), item2->GetName());
                                M2_DESTROY_ITEM(item);
                                // if (item2->GetType() == ITEM_QUEST)
                                quest::CQuestManager::instance().PickupItem(GetPlayerID(), item2);
                                return true;
                            }
                        }
                    }

                    item->SetCount(bCount);
                }
 
Böyle bir düzenleme denedim fakat bir sonuç alamadım.
COSTUME_INVENTORY_MAX_NUM envanter sayısını mı tutuyor yoksa cell bilgisini mi? Eğer envanter sayısını tutuyorsa çalışmaz. cell aralığında aratmanız lazım.

K envanteri için eklediğiniz şu COSTUME_INVENTORY_MAX_NUM sabitlerin bulunduğu kodları paylaşır mısınız?
 
lenght.h
C++:
    SPECIAL_INVENTORY_PAGE_SIZE = 45, // SLOT SAYISI
    SPECIAL_INVENTORY_PAGE_COUNT = 5, // SLOT SAYFASI
    SPECIAL_INVENTORY_MAX_NUM = SPECIAL_INVENTORY_PAGE_SIZE * SPECIAL_INVENTORY_PAGE_COUNT,
    // K ENVANTER MAX NUMARASI = SLOT SAYISI * SLOT SAYFASI = 225

    SKILL_BOOK_INVENTORY_MAX_NUM = SPECIAL_INVENTORY_MAX_NUM, // BK ENVANTERI = 225 SLOT
    UPGRADE_ITEMS_INVENTORY_MAX_NUM = SPECIAL_INVENTORY_MAX_NUM, // YUKSELTME ENVANTERI = 225 SLOT
    STONE_INVENTORY_MAX_NUM = SPECIAL_INVENTORY_MAX_NUM, // TAS ENVANTERI = 225 SLOT
    GIFT_BOX_INVENTORY_MAX_NUM = SPECIAL_INVENTORY_MAX_NUM, // SANDIK ENVANTERI = 225 SLOT
    COSTUME_INVENTORY_MAX_NUM = SPECIAL_INVENTORY_MAX_NUM, // KOSTUM ENVANTERI = 225 SLOT

C++:
    SKILL_BOOK_INVENTORY_SLOT_START = BELT_INVENTORY_SLOT_END,
    SKILL_BOOK_INVENTORY_SLOT_END = SKILL_BOOK_INVENTORY_SLOT_START + SKILL_BOOK_INVENTORY_MAX_NUM,

    UPGRADE_ITEMS_INVENTORY_SLOT_START = SKILL_BOOK_INVENTORY_SLOT_END,
    UPGRADE_ITEMS_INVENTORY_SLOT_END = UPGRADE_ITEMS_INVENTORY_SLOT_START + UPGRADE_ITEMS_INVENTORY_MAX_NUM,

    STONE_INVENTORY_SLOT_START = UPGRADE_ITEMS_INVENTORY_SLOT_END,
    STONE_INVENTORY_SLOT_END = STONE_INVENTORY_SLOT_START + STONE_INVENTORY_MAX_NUM,

    GIFT_BOX_INVENTORY_SLOT_START = STONE_INVENTORY_SLOT_END,
    GIFT_BOX_INVENTORY_SLOT_END = GIFT_BOX_INVENTORY_SLOT_START + GIFT_BOX_INVENTORY_MAX_NUM,

    COSTUME_INVENTORY_SLOT_START = GIFT_BOX_INVENTORY_SLOT_END,
    COSTUME_INVENTORY_SLOT_END = COSTUME_INVENTORY_SLOT_START + COSTUME_INVENTORY_MAX_NUM,
 
SetItem fonksiyonunda boşluk kontrollerini cell olarak yapar.

C++:
                if (wCell < COSTUME_INVENTORY_MAX_NUM)
                {
                    for (int i = 0; i < pItem->GetSize(); ++i)
                    {

Buradaki kodda ise COSTUME_INVENTORY_MAX_NUM kullanmışsınız. Burada wCell < 225 kontrol et demek oluyor. Yani tekrardan normal envanteri denetlemeye çalışıyor.


Kodları şu şekilde değiştirip tekrar deneyin;
C++:
    case COSTUME_INVENTORY:
        {
            if (wCell < COSTUME_INVENTORY_SLOT_START && wCell >= COSTUME_INVENTORY_SLOT_END)
            {
                sys_err("CHARACTER::SetItem: invalid costume_inventory item cell %d", wCell);
                return;
            }

            LPITEM pOld = m_pointsInstant.pItems[wCell];

            if (pOld)
            {
                if (wCell >= COSTUME_INVENTORY_SLOT_START && wCell < COSTUME_INVENTORY_SLOT_END)
                {
                    for (int i = 0; i < pOld->GetSize(); ++i)
                    {
                        int p = wCell + (i * 5);

                        if (p >= COSTUME_INVENTORY_SLOT_END)
                            continue;

                        if (m_pointsInstant.pItems[p] && m_pointsInstant.pItems[p] != pOld)
                            continue;

                        m_pointsInstant.bItemGrid[p] = 0;
                    }
                }
                else
                    m_pointsInstant.bItemGrid[wCell] = 0;
            }

            if (pItem)
            {
                if (wCell >= COSTUME_INVENTORY_SLOT_START && wCell < COSTUME_INVENTORY_SLOT_END)
                {
                    for (int i = 0; i < pItem->GetSize(); ++i)
                    {
                        int p = wCell + (i * 5);

                        if (p >= COSTUME_INVENTORY_SLOT_END)
                            continue;

                        // wCell + 1 ·Î ÇÏ´Â °ÍÀº ºó°÷À» üũÇÒ ¶§ °°Àº
                        // ¾ÆÀÌÅÛÀº ¿¹¿Üó¸®Çϱâ À§ÇÔ
                        m_pointsInstant.bItemGrid[p] = wCell + 1;
                    }
                }
                else
                    m_pointsInstant.bItemGrid[wCell] = wCell + 1;
            }

            m_pointsInstant.pItems[wCell] = pItem;
        }
 
Denedim aynı problem devam ediyor.
 
Verdiğim son kodlar doğru bu arada. Diğer envanter türlerini de aynı mantıkla ilerletin. Başka bir yerden de sorun olabilir. IsEmptyItemGrid fonksiyonunda eklediğiniz kodları verebilir misiniz? Onları da kontrol ediyim
 
Buyrun yorumlarda belirttiğiniz gibi eklemiştim :D
C++:
        else if (Cell.IsCostumeInventoryPosition())
        {
            if (bCell < COSTUME_INVENTORY_SLOT_START)
                return false;

            if (bCell > COSTUME_INVENTORY_SLOT_END)
                return false;

            if (m_pointsInstant.bItemGrid[bCell])
            {
                if (m_pointsInstant.bItemGrid[bCell] == (UINT)iExceptionCell)
                {
                    if (bSize <= 3)
                        return true;

                    int j = 1;
                    BYTE bPage = bCell / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT);

                    do
                    {
                        UINT p = bCell + (5 * j);

                        if (p >= SPECIAL_INVENTORY_MAX_NUM)
                            return false;

                        if (p / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                            return false;

                        if (m_pointsInstant.bItemGrid[p])
                            if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
                                return false;
                    } while (++j < bSize);

                    return true;
                }
                else
                    return false;
            }
            if (3 >= bSize)
                return true;
            else
            {
                int j = 1;
                BYTE bPage = bCell / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT);
                
                do
                {
                    BYTE p = bCell + (5 * j);

                    if (p >= SPECIAL_INVENTORY_MAX_NUM)
                        return false;

                    if (p / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                        return false;

                    if (m_pointsInstant.bItemGrid[p])
                        if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
                            return false;
                }
                while (++j < bSize);

                return true;
            }
        }
 
Tamam kısmen doğru gözüküyor ama bir önceki kodda olduğu gibi benzer hata mevcut. Kodları okuyarak ilerlemek gerekiyor.

Şu kodu;
C++:
                    if (bSize <= 3)
                        return true;

Değiştirin;
C++:
                    if (bSize == 1)
                        return true;

Aratın;
C++:
            if (3 >= bSize)
                return true;

Değiştirin;
C++:
            if (1 == bSize)
                return true;

Buradaki sayısal değerleri niye değiştirdiğinizi anlayamadım. #2 numaralı mesajımda zaten varsayılan envanter kodlarını paylaşmıştım. Bunları değiştirmemeliydiniz. Çünkü 1x1 boyutunda itemler için aşağıdaki slotları kontrol ettirmenize gerek yok. :)
:disney-is-frozen17::disney-is-frozen19::disney-is-frozen23::disney-is-frozen29:


İlk önce şu kısmı;
C++:
            if (bCell < COSTUME_INVENTORY_SLOT_START)
                return false;

            if (bCell > COSTUME_INVENTORY_SLOT_END)
                return false;

Şöyle değiştirelim ki satırdan tasarruf edelim ^_^
C++:
            if (bCell < COSTUME_INVENTORY_SLOT_START && bCell > COSTUME_INVENTORY_SLOT_END)
                return false;


Şimdi şuraya bakalım;
C++:
                    BYTE bPage = bCell / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT);
Burada mevcut bCell değerini 45'e bölüyoruz. Yapılan işlem şu. bCell / (225 / 5)

Bu kodun amacı sayfa kontrollerini yapmaktır. Eklenecek 1x2 ve 1x3 itemler eğer sayfa aşağısındaki slotlara sığmıyorsa hata verir. Fakat k envantere eklenen itemlerin cell değerleri çok fazla. Bu yüzden mevcut işlemde 5 sayfadan daha da yüksek değer çıkacak ve sayfaların başlangıç ve bitiş pos değerlerini de doğru hesaplamayacktır. Burada matematik işlemini şöyle değiştirmeniz lazım.
C++:
                    BYTE bPage = (bCell - COSTUME_INVENTORY_SLOT_START) / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT);

Bu yapacağımız düzenlemeler ile son slotlara 1x2 ve 1x3 itemların eklenmesini engellemek.


Devam edelim düzenlemelere. Direk olarak envanter kodunu birebir kopyalayınca gözden kaçan noktalar var tabi :):disney-is-frozen28:
C++:
                        UINT p = bCell + (5 * j);

                        if (p >= SPECIAL_INVENTORY_MAX_NUM)
                            return false;

                        if (p / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                            return false;

Burada da matematiksel olarak yanlış işlemler mevcut. Hatalı kısım tam olarak burası;
C++:
                        if (p / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                            return false;


Önceki düzenlenmesi gereken yerleri söylediğimle benzer mantık hatası oluyor. Bu yüzden kodu şöyle düzenlemelisiniz.
C++:
                        if ((p - COSTUME_INVENTORY_SLOT_START) / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                            return false;


Bu düzenlemeleri
C++:
            else
            {
                int j = 1;

sonrası içinde uygulamayı unutmayın.

Direk hazır olarak düzenleyip vermek yerine açıklayarak ilerledim :D
 
Ve mutlu son :D
Örnek bir kod gösteriyim çoğu yeri bu şekilde düzenledim
peki neden INVENTORY_AND_EQUIP_SLOT_MAX ekledik diyecek olursanız çünkü lenght.h içinde ayarladığım

INVENTORY_AND_EQUIP_SLOT_MAX = COSTUME_INVENTORY_SLOT_END,

C++:
int CHARACTER::GetEmptyInventory(BYTE size) const
{
#ifdef EK_ENVANTER_YAPMAYA_CALISIYOM
    for ( int i = 0; i < INVENTORY_AND_EQUIP_SLOT_MAX; ++i)
#else
    for ( int i = 0; i < INVENTORY_MAX_NUM; ++i)
#endif
        if (IsEmptyItemGrid(TItemPos (INVENTORY, i), size))
            return i;
    return -1;
}

Edit: case olarak INVENTORY kullandığım için böyle düzenleme yaptım başka case'ler kullanıyorsanız ona göre eklemeler yapmanız gerekiyor.
 
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.
Geri
Üst