Çö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
Süper Moderatör
Grafiker
Geliştirici
Yardımsever Üye
Mesaj
2.849
Çözümler
297
Beğeni
2.130
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++:
Genişlet Daralt Kopyala
        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++:
Genişlet Daralt Kopyala
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++:
Genişlet Daralt Kopyala
        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++:
Genişlet Daralt Kopyala
            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++:
Genişlet Daralt Kopyala
    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++:
Genişlet Daralt Kopyala
                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++:
Genişlet Daralt Kopyala
    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++:
Genişlet Daralt Kopyala
    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++:
Genişlet Daralt Kopyala
                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++:
Genişlet Daralt Kopyala
    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++:
Genişlet Daralt Kopyala
        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++:
Genişlet Daralt Kopyala
                    if (bSize <= 3)
                        return true;

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

Aratın;
C++:
Genişlet Daralt Kopyala
            if (3 >= bSize)
                return true;

Değiştirin;
C++:
Genişlet Daralt Kopyala
            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++:
Genişlet Daralt Kopyala
            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++:
Genişlet Daralt Kopyala
            if (bCell < COSTUME_INVENTORY_SLOT_START && bCell > COSTUME_INVENTORY_SLOT_END)
                return false;


Şimdi şuraya bakalım;
C++:
Genişlet Daralt Kopyala
                    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++:
Genişlet Daralt Kopyala
                    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++:
Genişlet Daralt Kopyala
                        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++:
Genişlet Daralt Kopyala
                        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++:
Genişlet Daralt Kopyala
                        if ((p - COSTUME_INVENTORY_SLOT_START) / (SPECIAL_INVENTORY_MAX_NUM / SPECIAL_INVENTORY_PAGE_COUNT) != bPage)
                            return false;


Bu düzenlemeleri
C++:
Genişlet Daralt Kopyala
            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++:
Genişlet Daralt Kopyala
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ı.
Üst