Jump to content

Recommended Posts

hello. there' s a bug that is present on almost all servers. (Even big online servers like Calliope have this bug!!)

 

When you move an item from a system (in my case the switchbot) you can overlap an item over a 2 or 3 cell item.

Look at the gif to understand better: https://metin2.download/video/oVR0g8341gKcCABPB1io1zhe3Z4PZHzI/.mp4

How do we fix this?

 

Ps. the bug works from a lot of systems: normal npc shop, offlineshop, switchbot, change equip, special storage and others. Basically on any system that you can drag and drop an item in inventory.

Edited by Metin2 Dev International
Core X - External 2 Internal
Link to comment
https://metin2.dev/topic/32829-bug-on-all-servers-how-to-fix-this/
Share on other sites

Yep. and I correct myself:

 

If you have sanii switchbot for example:

On the switchbot you have 5 slots. if you have an item on slot 3 in switchbot for example, and an item on slot 3 in inventory you can do this bug. it also works with 2 or 3 cell items, not just with 1 cell items, but you have to place the item on row 2.

 

In this gif, the weapon slot from change equip coresponds to slot 5 in inventory so only there you can do the bug:

https://metin2.download/video/gk74K26VZoyqVn83Jcm5mFn32xD3tJO1/.mp4

 

 

Edited by Metin2 Dev International
Core X - External 2 Internal
  • Premium

To fix the issue where a 1-cell item can overlap a 2 or 3-cell item, you need to add a check for the destination cells before moving the item. This will ensure that the destination cells are free and not occupied by another item. Here's an updated version of the MoveItem function with the necessary checks:


this is my code u can have a look  :
 

bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell, WORD count)
{
    LPITEM item = NULL;

    // NOTE : Prevent the item from being moved to the original slot.
    if (Cell.cell == DestCell.cell)
        return false;

    if (!IsValidItemPosition(Cell))
        return false;

    if (!(item = GetItem(Cell)))
        return false;

    if (item->IsExchanging())
        return false;

    if (item->GetCount() < count)
        return false;

    if (INVENTORY == Cell.window_type && Cell.cell >= INVENTORY_MAX_NUM && IS_SET(item->GetFlag(), ITEM_FLAG_IRREMOVABLE))
        return false;

    if (true == item->isLocked())
        return false;

    if (!IsValidItemPosition(DestCell))
        return false;

#ifdef __GROWTH_PET_SYSTEM__
    if (GetPetWindowType() == PET_WINDOW_ATTR_CHANGE || GetPetWindowType() == PET_WINDOW_PRIMIUM_FEEDSTUFF)
    {
        ChatPacket(CHAT_TYPE_INFO, "You cannot move items while modifying your pet's stats.");
        return false;
    }
#endif

    if (!CanHandleItem())
    {
        if (NULL != DragonSoul_RefineWindow_GetOpener())
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화창을 연 상태에서는 아이템을 옮길 수 없습니다."));
#ifdef ENABLE_AURA_SYSTEM
        if (IsAuraRefineWindowOpen())
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<아우라> 오라 창이 열려있을 때까지 항목을 이동할 수 없습니다."));
#endif
        return false;
    }

    // 기획자의 요청으로 벨트 인벤토리에는 특정 타입의 아이템만 넣을 수 있다.
    if (DestCell.window_type != DRAGON_SOUL_INVENTORY && DestCell.IsBeltInventoryPosition() && !CBeltInventoryHelper::CanMoveIntoBeltInventory(item))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 아이템은 벨트 인벤토리로 옮길 수 없습니다."));
        return false;
    }

#ifdef ENABLE_SWITCHBOT
    if (Cell.IsSwitchbotPosition() && CSwitchbotManager::Instance().IsActive(GetPlayerID(), Cell.cell))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Cannot move active switchbot item."));
        return false;
    }

    if (Cell.IsSwitchbotPosition() && DestCell.IsSkillBookInventoryPosition())
    {
        if (!item->IsSkillBook())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move skill books into this inventory."));
            return false;
        }
    }

    if (Cell.IsSwitchbotPosition() && DestCell.IsUpgradeItemsInventoryPosition())
    {
        if (!item->IsUpgradeItem())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move upgrade items into this inventory."));
            return false;
        }
    }

    if (Cell.IsSwitchbotPosition() && DestCell.IsStoneInventoryPosition())
    {
        if (!item->IsStone())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move stones into this inventory."));
            return false;
        }
    }

    if (Cell.IsSwitchbotPosition() && DestCell.IsGiftBoxInventoryPosition())
    {
        if (!item->IsGiftBox())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move chests into this inventory."));
            return false;
        }
    }

    if (DestCell.IsSwitchbotPosition() && !SwitchbotHelper::IsValidItem(item))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Invalid item type for switchbot."));
        return false;
    }

    if (Cell.IsSwitchbotPosition() && DestCell.IsEquipPosition())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Cannot equip items directly from switchbot."));
        return false;
    }

    if (DestCell.IsSwitchbotPosition() && Cell.IsEquipPosition())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Cannot move equipped items to switchbot."));
        return false;
    }
#endif

#if defined(__SPECIAL_INVENTORY_SYSTEM__)
    if (DestCell.IsSkillBookInventoryPosition() && (item->IsEquipped() || Cell.IsBeltInventoryPosition()))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (DestCell.IsUpgradeItemsInventoryPosition() && (item->IsEquipped() || Cell.IsBeltInventoryPosition()))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (DestCell.IsStoneInventoryPosition() && (item->IsEquipped() || Cell.IsBeltInventoryPosition()))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (DestCell.IsGiftBoxInventoryPosition() && (item->IsEquipped() || Cell.IsBeltInventoryPosition()))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if ((Cell.IsSkillBookInventoryPosition() && !DestCell.IsSkillBookInventoryPosition() && !DestCell.IsDefaultInventoryPosition()))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (Cell.IsUpgradeItemsInventoryPosition() && !DestCell.IsUpgradeItemsInventoryPosition() && !DestCell.IsDefaultInventoryPosition())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (Cell.IsStoneInventoryPosition() && !DestCell.IsStoneInventoryPosition() && !DestCell.IsDefaultInventoryPosition())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (Cell.IsGiftBoxInventoryPosition() && !DestCell.IsGiftBoxInventoryPosition() && !DestCell.IsDefaultInventoryPosition())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't move this item into this inventory."));
        return false;
    }

    if (Cell.IsDefaultInventoryPosition() && DestCell.IsSkillBookInventoryPosition())
    {
        if (!item->IsSkillBook())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move skill books into this inventory."));
            return false;
        }
    }

    if (Cell.IsDefaultInventoryPosition() && DestCell.IsUpgradeItemsInventoryPosition())
    {
        if (!item->IsUpgradeItem())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move upgrade items into this inventory."));
            return false;
        }
    }

    if (Cell.IsDefaultInventoryPosition() && DestCell.IsStoneInventoryPosition())
    {
        if (!item->IsStone())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move stones into this inventory."));
            return false;
        }
    }

    if (Cell.IsDefaultInventoryPosition() && DestCell.IsGiftBoxInventoryPosition())
    {
        if (!item->IsGiftBox())
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only move chests into this inventory."));
            return false;
        }
    }
#endif

    // Check for overlapping items in destination slots
    int itemSize = item->GetSize();
    for (int i = 0; i < itemSize; ++i)
    {
        if (!IsEmptyItemGrid(DestCell + i, 1, Cell.cell))
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Target slot is occupied!"));
            return false;
        }
    }

    // 이미 착용중인 아이템을 다른 곳으로 옮기는 경우, '장책 해제' 가능한 지 확인하고 옮김
    if (Cell.IsEquipPosition())
    {
        if (!CanUnequipNow(item))
            return false;

#if defined(__WEAPON_COSTUME_SYSTEM__)
        int iWearCell = item->FindEquipCell(this);
        if (iWearCell == WEAR_WEAPON)
        {
            LPITEM pkCostumeWeapon = GetWear(WEAR_COSTUME_WEAPON);
            if (pkCostumeWeapon)
            {
                ChatPacket(CHAT_TYPE_INFO, LC_TEXT("If you want to change weapons, you must remove the weapon skin first."));
                return false;
            }
        }
#endif
    }

    if (item->IsBelt() && item->IsEquipped() && CBeltInventoryHelper::IsExistItemInBeltInventory(this))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can only discard the belt when there are no longer any items in its inventory."));
        return false;
    }

    if (DestCell.IsEquipPosition())
    {
        if (GetItem(DestCell)) // 장비일 경우 한 곳만 검사해도 된다.
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이미 장비를 착용하고 있습니다."));
            return false;
        }

        EquipItem(item, DestCell.cell - INVENTORY_MAX_NUM);
    }
    else
    {
        if (item->IsDragonSoul())
        {
            if (item->IsEquipped())
            {
                return DSManager::instance().PullOut(this, DestCell, item);
            }
            else
            {
                if (DestCell.window_type != DRAGON_SOUL_INVENTORY)
                {
                    return false;
                }

                if (!DSManager::instance().IsValidCellForThisItem(item, DestCell))
                    return false;
            }
        }
        // 용혼석이 아닌 아이템은 용혼석 인벤에 들어갈 수 없다.
        else if (DRAGON_SOUL_INVENTORY == DestCell.window_type)
            return false;

        LPITEM item2;

        if ((item2 = GetItem(DestCell)) && item != item2 && item2->IsStackable() &&
            !IS_SET(item2->GetAntiFlag(), ITEM_ANTIFLAG_STACK) &&
            item2->GetVnum() == item->GetVnum() && !item2->IsExchanging()) // 합칠 수 있는 아이템의 경우
        {
#if defined(__EXTENDED_BLEND_AFFECT__)
            if (item->IsBlendItem() && item2->IsBlendItem())
            {
                if (count == 0)
                    count = item->GetCount();

                for (int i = 0; i < 2; ++i) {
                    if (item2->GetSocket(i) != item->GetSocket(i)) {
                        return false;
                    }
                }

#if defined(ENABLE_COMMON_CHANGES)
                item2->SetSocket(2, item2->GetSocket(2) + (item->GetSocket(2) * count));
#else
                item2->SetSocket(2, item2->GetSocket(2) + item->GetSocket(2));
#endif
                item->SetCount(item->GetCount() - count);
                return true;
            }
#endif

            for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
                if (item2->GetSocket(i) != item->GetSocket(i))
                    return false;

            if (count == 0)
                count = item->GetCount();

            sys_log(0, "%s: ITEM_STACK %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell,
                DestCell.window_type, DestCell.cell, count);

            count = MIN(ITEM_MAX_COUNT - item2->GetCount(), count);

            item->SetCount(item->GetCount() - count);
            item2->SetCount(item2->GetCount() + count);
            return true;
        }

        if (!IsEmptyItemGrid(DestCell, item->GetSize(), Cell.cell))
        {
#if defined(__SWAP_ITEM_SYSTEM__)
            if (count != 0 && count != item->GetCount())
                return false;

            if (!DestCell.IsDefaultInventoryPosition() || !Cell.IsDefaultInventoryPosition())
                return false;

            LPITEM targetItem = GetItem_NEW(DestCell);
            if (targetItem && targetItem->GetVID() == item->GetVID())
                return false;

            if (targetItem)
            {
                DestCell = TItemPos(INVENTORY, targetItem->GetCell());
            }

            if (item->IsExchanging() || (targetItem && targetItem->IsExchanging()))
                return false;

            BYTE basePage = DestCell.cell / (INVENTORY_MAX_NUM / INVENTORY_PAGE_COUNT);
            std::map<WORD, LPITEM> moveItemMap;
            BYTE sizeLeft = item->GetSize();

            for (WORD i = 0; i < item->GetSize(); ++i)
            {
                WORD cellNumber = DestCell.cell + i * 5;

                BYTE cPage = cellNumber / (INVENTORY_MAX_NUM / INVENTORY_PAGE_COUNT);
                if (basePage != cPage)
                    return false;

                LPITEM mvItem = GetItem(TItemPos(INVENTORY, cellNumber));
                if (mvItem)
                {
                    if (mvItem->GetSize() > item->GetSize())
                        return false;

                    if (mvItem->IsExchanging())
                        return false;

                    moveItemMap.insert({ Cell.cell + i * 5, mvItem });
                    sizeLeft -= mvItem->GetSize();

                    if (mvItem->GetSize() > 1)
                        i += mvItem->GetSize() - 1;
                }
                else
                {
                    sizeLeft -= 1;
                }
            }

            if (sizeLeft != 0)
                return false;

            std::map<WORD, WORD> syncCells;

            syncCells.insert({ GetQuickslotPosition(QUICKSLOT_TYPE_ITEM, item->GetCell()), DestCell.cell });
            item->RemoveFromCharacter();

            for (auto it = moveItemMap.begin(); it != moveItemMap.end(); ++it)
            {
                WORD toCellNumber = it->first;
                LPITEM mvItem = it->second;

                syncCells.insert({ GetQuickslotPosition(QUICKSLOT_TYPE_ITEM, mvItem->GetCell()), toCellNumber });
                mvItem->RemoveFromCharacter();

                SetItem(TItemPos(INVENTORY, toCellNumber), mvItem);
            }

            SetItem(DestCell, item);

            for (auto& sCell : syncCells)
            {
                TQuickslot qs;
                qs.type = QUICKSLOT_TYPE_ITEM;
                qs.pos = sCell.second;

                SetQuickslot(sCell.first, qs);
            }

            return true;
#else
            return false;
#endif
        }

        if (count == 0 || count >= item->GetCount() || !item->IsStackable() || IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
        {
            sys_log(0, "%s: ITEM_MOVE %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell,
                DestCell.window_type, DestCell.cell, count);

            item->RemoveFromCharacter();
            SetItem(DestCell, item);

            if (INVENTORY == Cell.window_type && INVENTORY == DestCell.window_type)
                SyncQuickslot(QUICKSLOT_TYPE_ITEM, Cell.cell, DestCell.cell);
        }
        else if (count < item->GetCount())
        {
#ifdef ENABLE_PULSE_MANAGER
            if (!PulseManager::Instance().IncreaseClock(GetPlayerID(), ePulse::MoveItem, std::chrono::milliseconds(1000)))
            {
                ChatPacket(CHAT_TYPE_INFO, "2");
                return false;
            }
#endif
            sys_log(0, "%s: ITEM_SPLIT %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell, DestCell.window_type, DestCell.cell, count);

            item->SetCount(item->GetCount() - count);
            LPITEM item2 = ITEM_MANAGER::instance().CreateItem(item->GetVnum(), count);

            // Copy socket -- by mhh
            FN_copy_item_socket(item2, item);

            item2->AddToCharacter(this, DestCell);

            char szBuf[51 + 1];
            snprintf(szBuf, sizeof(szBuf), "%u %u %u %u ", item2->GetID(), item2->GetCount(), item->GetCount(), item->GetCount() + item2->GetCount());
            LogManager::instance().ItemLog(this, item, "ITEM_SPLIT", szBuf);
        }
    }

    return true;
}

 

───────────────────────────────────────────
— Development & Research —
Metin2 Systems • Client/Server • Reverse Engineering

Discord:  saudidos

If I helped you, consider leaving a like. ✦
───────────────────────────────────────────
 

  • Premium

I was curious if I also had this issue. Well, graphically, yes (the usableitem flag effect). Something was definitely missing (the slot check and setting the mode) :

.png

 

it stays white in the bugged cell until I trigger another overinitem though, but serverside it's all fine. Actually, it's bugged like that only when the the cell is occupied by an item with size 2 or 3.

Anyway:

		if ((item2 = GetItem(DestCell)) && item != item2 && item2->IsStackable() &&
				!IS_SET(item2->GetAntiFlag(), ITEM_ANTIFLAG_STACK) &&
				item2->GetVnum() == item->GetVnum())
		{

This should never occur if GetItem would retrieve the correct cell but, somehow, it does not, so I would start debugging from there.

 

 

 

 

  • Metin2 Dev 1
  • Premium

i had a similar issue before with the Change Look System. The problem was that any player could change the look of a WEAPON_TWO_HANDED sword to look like a one-handed sword (WEAPON_SWORD). I fixed it using the GetSize() method because, according to the item_proto.txt, the WEAPON_TWO_HANDED has a size of 3. I wrote code to check the size and ensure it matches before allowing the change.


 

   if (bPos == 1)
    {
        bool bStop = false;

        if ((pkItem->GetSize() == 3 && pkItemMaterial[0]->GetSize() == 3) ||
            (pkItem->GetSize() == 2 && pkItemMaterial[0]->GetSize() == 2) ||
            (pkItem->GetSize() == 1 && pkItemMaterial[0]->GetSize() == 1))
        {
            sys_err("Both items have size %d, allowing transmutation.", pkItem->GetSize());
        }	
        else
        {
            if (pkItem->GetType() != pkItemMaterial[0]->GetType())
            {
                sys_err("Type mismatch: %d vs %d", pkItem->GetType(), pkItemMaterial[0]->GetType());
                bStop = true;
            }
            else if (pkItem->GetSubType() != pkItemMaterial[0]->GetSubType())
            {
                sys_err("SubType mismatch: %d vs %d", pkItem->GetSubType(), pkItemMaterial[0]->GetSubType());
                bStop = true;
            }
            else if (pkItem->GetSize() != pkItemMaterial[0]->GetSize())
            {
                sys_err("Size mismatch: %d vs %d", pkItem->GetSize(), pkItemMaterial[0]->GetSize());
                bStop = true;
            }
            else if (pkItem->IsCostumeBody() && pkItemMaterial[0]->IsArmorBody())
                bStop = false;
            else if (pkItem->IsCostumeWeapon() && pkItemMaterial[0]->IsMainWeapon())
                bStop = false;
            else if (pkItem->IsArmorBody() && pkItemMaterial[0]->IsCostumeBody())
                bStop = false;
            else if (pkItem->IsMainWeapon() && pkItemMaterial[0]->IsCostumeWeapon())
                bStop = false;
            else if (pkItem->IsCostumeHair() && !pkItemMaterial[0]->IsCostumeHair())
                bStop = false;
            else
                bStop = true;
        }
        if (bStop)
        {
            sys_err("Type/subtype/size mismatch for transmutation: %d (size %d) vs %d (size %d)", pkItem->GetVnum(), pkItem->GetSize(), pkItemMaterial[0]->GetVnum(), pkItemMaterial[0]->GetSize());
            return;
        }

		if (pkItemMaterial[0]->GetOriginalVnum() == pkItem->GetOriginalVnum())
			bStop = true;
		else if (((IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_FEMALE)) && (!IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_FEMALE)))
			|| ((IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_MALE)) && (!IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_MALE))))
			bStop = true;
		else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_WARRIOR) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_WARRIOR)))
			bStop = true;
		else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_ASSASSIN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_ASSASSIN)))
			bStop = true;
		else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_SHAMAN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_SHAMAN)))
			bStop = true;
		else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_SURA) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_SURA)))
			bStop = true;
		else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_WOLFMAN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_WOLFMAN)))
			bStop = true;
		else if (IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_CHANGELOOK) || IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_CHANGELOOK))
			bStop = true;
		else if ((pkItem->IsCostume() && pkItemMaterial[0]->IsCostume()) && ((pkItem->IsCostumeWeapon()) && (pkItemMaterial[0]->IsCostumeWeapon())))
			if (pkItem->GetValue(3) != pkItemMaterial[0]->GetValue(3))
				bStop = true;

		if (bStop)
			return;
	}

you can use the same logic in the code to prevent items from overlapping.

───────────────────────────────────────────
— Development & Research —
Metin2 Systems • Client/Server • Reverse Engineering

Discord:  saudidos

If I helped you, consider leaving a like. ✦
───────────────────────────────────────────
 

2 hours ago, Intel said:

I was curious if I also had this issue. Well, graphically, yes (the usableitem flag effect). Something was definitely missing (the slot check and setting the mode) :

.png

 

it stays white in the bugged cell until I trigger another overinitem though, but serverside it's all fine. Actually, it's bugged like that only when the the cell is occupied by an item with size 2 or 3.

Anyway:

		if ((item2 = GetItem(DestCell)) && item != item2 && item2->IsStackable() &&
				!IS_SET(item2->GetAntiFlag(), ITEM_ANTIFLAG_STACK) &&
				item2->GetVnum() == item->GetVnum())
		{

This should never occur if GetItem would retrieve the correct cell but, somehow, it does not, so I would start debugging from there.

 

 

 

 

Yeah there are people who don't have this bug server side and only have the visual white slot bug on client. (it looks like you can place the item there but you actually can't)

 

But many servers like Calliope,Zarkana and basically almost every server have this bug. Even martysama source has this bug.

 

I'm curious on how this problem should be handled. Could you share the ItemMove function with us? (char_item.cpp)

  • Premium

Bugs created by yourself 😄 I have switchbot and i dont have any problems with that. You have to think when adding, not add according to the tutorial like a demented person.

 

 

1 minute ago, HFWhite said:

Yeah there are people who don't have this bug server side and only have the visual white slot bug on client. (it looks like you can place the item there but you actually can't)

 

But many servers like Calliope,Zarkana and basically almost every server have this bug. Even martysama source has this bug.

 

I'm curious on how this problem should be handled. Could you share the ItemMove function with us? (char_item.cpp)

Stop talking shit about bug its included in MartySama.

  • Smile Tear 1
  • Good 1


 

58 minutes ago, TAUMP said:

Bugs created by yourself 😄 I have switchbot and i dont have any problems with that. You have to think when adding, not add according to the tutorial like a demented person.

 

 

Stop talking shit about bug its included in MartySama.

are you dumb? even martysama knows about this.

On systems like switchbot, change equip and other systems that use drag item to inventory function. 

Stop being edgy, we're not in 2016 anymore.

 

I said that not everyone has this bug. But a lot of people have this problem!

 

Edited by HFWhite
  • Lmao 3
  • Premium
Just now, HFWhite said:

are you dumb? even martysama knows about this.

On normal shop there's no bug. Only on systems like switchbot, change equip and other systems that use drag item to inventory functions.

Stop being edgy, we're not in 2016 anymore.

 

Lol, you have more information from him than me.  

HF white stupid poor idiot who owns the Romanian discord community, where he strongly supports resellers of purchased systems and resells it there for discord invites, I hope you get banned soon. 

  • Confused 1
  • Love 1


 

There is a visual bug indeed, on martysama from looking its just visually, not serversided like in your case or what i've seen on the discord. The slot appears white but it is an easy fix as @ Intel mentioned above.

Regarding overlapping or other systems that were not in the game before the source leak then that is simply your own issue to deal with, you need to check your GameType.h and the cells, i've used Sanii's paid system which i personally bought from him and never had that issue, many need to know that his systems will need adaption for various reason.

From the video your friend sent on martysama's discord its very clear that his knowledge of coding is barely anything to zero as he stole and implemented my special inventory from Prometa that i made before Chriss died. Same with some other people that have reported the same overlapping issue. You clearly need to understand that by default that bug is only visual, if it comes to the point where the items actually overlap then you done fucked up.

Edited by FrenchForeignLegion

Software Engineer @ CNH Industrial (NAFTA/EMEA)

33 minutes ago, TAUMP said:

Lol, you have more information from him than me.  

HF white stupid poor idiot who owns the Romanian discord community, where he strongly supports resellers of purchased systems and resells it there for discord invites, I hope you get banned soon. 

You don t have anything to do? We all have the same bug. How the fk 50 people can t install a switchbot, you re the best and you know everything, just stfu and do something.

  • Premium

i test it on my server it's owsap source code this bug is work 🙂

spacer.png

Edited by Metin2 Dev International
Core X - External 2 Internal
  • Scream 1

───────────────────────────────────────────
— Development & Research —
Metin2 Systems • Client/Server • Reverse Engineering

Discord:  saudidos

If I helped you, consider leaving a like. ✦
───────────────────────────────────────────
 

7 minutes ago, saudidos said:

i test it on my server it's owsap source code this bug is work 🙂

spacer.png

Yes, it's a common bug. It's on some big online servers too. Like Calliope.

You can dupe items with this bug. We need to find a fix.

Edited by Metin2 Dev International
Core X - External 2 Internal
  • Premium
4 minutes ago, HFWhite said:

Yes, it's a common bug. It's on some big online servers too. Like Calliope.

You can dupe items with this bug. We need to find a fix.

SYSERR: Jul 25 09:24:43 :: CreateItem: ITEM_ID_DUP: 327817689 نصل العناصر الخمس+9 owner 0x52caa700
SYSERR: Jul 25 09:24:43 :: ItemLoad: cannot create item by vnum 1349 (name [DEV]AL38lAlmdbeR id 327817689)
SYSERR: Jul 25 09:26:06 :: CreateItem: ITEM_ID_DUP: 327817689 نصل العناصر الخمس+9 owner 0x52caa700
SYSERR: Jul 25 09:26:06 :: ItemLoad: cannot create item by vnum 1349 (name [DEV]AL38lAlmdbeR id 327817689)

your right this is the syserr also 🙂

───────────────────────────────────────────
— Development & Research —
Metin2 Systems • Client/Server • Reverse Engineering

Discord:  saudidos

If I helped you, consider leaving a like. ✦
───────────────────────────────────────────
 

Please stop spreading misinformation. The duplication issue is related to the systems you added, this is not a case for every server there is.

Learn to add something properly and adapt it to your source, learn to use the cells inside the game. The visual bug does exist but if there is a duplication glitch then that is an issue you have created.

Software Engineer @ CNH Industrial (NAFTA/EMEA)

  • Premium
53 minutes ago, HFWhite said:

Yeah there are people who don't have this bug server side and only have the visual white slot bug on client. (it looks like you can place the item there but you actually can't)

 

But many servers like Calliope,Zarkana and basically almost every server have this bug. Even martysama source has this bug.

 

I'm curious on how this problem should be handled. Could you share the ItemMove function with us? (char_item.cpp)

The item move is basically the same, the crucial difference is in GetItem though (well, the one I suspect the original system accounts for? I doubt sanii made a complete refactor)

 

35 minutes ago, FrenchForeignLegion said:

There is a visual bug indeed, on martysama from looking its just visually, not serversided like in your case or what i've seen on the discord. The slot appears white but it is an easy fix as @ Intel mentioned above.

Regarding overlapping or other systems that were not in the game before the source leak then that is simply your own issue to deal with, you need to check your GameType.h and the cells, i've used Sanii's paid system which i personally bought from him and never had that issue, many need to know that his systems will need adaption for various reason.

From the video your friend sent on martysama's discord its very clear that his knowledge of coding is barely anything to zero as he stole and implemented my special inventory from Prometa that i made before Chriss died. Same with some other people that have reported the same overlapping issue. You clearly need to understand that by default that bug is only visual, if it comes to the point where the items actually overlap then you done fucked up.

Ah, so with original sanii's inventory, it's handled correctly

2 minutes ago, Intel said:

The item move is basically the same, the crucial difference is in GetItem though (well, the one I suspect the original system accounts for? I doubt sanii made a complete refactor)

 

Ah, so with original sanii's inventory, it's handled correctly

Can't attach pictures but yes and no. It is handled correctly serverside which is amazing, same with clientside, but the little visual glitch is there. However you can't overlap items like those people do which is a very clear sign that they did not implement their system correctly in order to be in pace with the inventory cells.

For sanii's switchbot it would be as easy as checking if the slot is already occupied like the many other checks hes done with that switchbot.

People just claim to know what they're up to yet they do not have the knowledge to do it, funny enough, the guy that reported this got banned and someone sent me a picture of him selling a "prison system" which he "rewrote" but can't fix a simple flag in python.

Software Engineer @ CNH Industrial (NAFTA/EMEA)

  • Premium
1 minute ago, FrenchForeignLegion said:

Can't attach pictures but yes and no. It is handled correctly serverside which is amazing, same with clientside, but the little visual glitch is there. However you can't overlap items like those people do which is a very clear sign that they did not implement their system correctly in order to be in pace with the inventory cells.

For sanii's switchbot it would be as easy as checking if the slot is already occupied like the many other checks hes done with that switchbot.

People just claim to know what they're up to yet they do not have the knowledge to do it, funny enough, the guy that reported this got banned and someone sent me a picture of him selling a "prison system" which he "rewrote" but can't fix a simple flag in python.

Yeah, I meant serverside, which is what really counts here ^^

I also have that visual bug and that first time not triggering kinda bothers me, but eh, as long as items don't overlap

  • Honorable Member

If you have this bug server-side, then you must use IsEmptyItemGrid inside CHARACTER::MoveItem.

GetItem returns nullptr in the 2nd/3rd vertical slot, that's why it fails.

By default, many systems only check the grids client-side.

Edited by martysama0134
15 minutes ago, Zedu said:

Indeed, however the issue is created by their own additions. This does not happen or work with mainline/any other source thats clean. They obviously have to check for each system in place that the actual cell size does not match the dest cell grid size.

Usually for the ones using sanii's switchbot they would have to look for if (Cell.IsSwitchbotPosition() && CSwitcbotManager::Instance().IsActive inside char_item.cpp and under that whole function to check what i said above.

  • Metin2 Dev 1

Software Engineer @ CNH Industrial (NAFTA/EMEA)

  • Active+ Member

not a single fucking relevant or useful answer,

just bunch of kids being toxic & flexing their non existent programing muscles..

[Untested btw i wrote it like in 5 min]

in bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell, ItemCountType count)

Spoiler
no need marty can fix it with IsEmptyItemGrid

 

you can do way better than this or have it in a seprate func ofc, this is just a simple example

gl...

Edited by CONTROL

I don’t know — I think.

 

Discord

 

  • Honorable Member
16 minutes ago, CONTROL said:

not a single fucking relevant or useful answer,

just bunch of kids flexing their non existent programing muscles..

[Untested btw i wrote it like in 5 min]

in bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell, ItemCountType count)

  Hide contents
	if (Cell.IsSwitchbotPosition() && INVENTORY == DestCell.window_type)
	{
		// start backward check
		if (!GetItem(DestCell))
		{
			const uint8_t linesPerPage = 5;
			const uint8_t itemMaxSize = 3;
			uint8_t maxRounds = 1;
			int wCell = DestCell.cell;
			for (uint8_t i = 0; i <= itemMaxSize; i++)
			{
				wCell -= linesPerPage;
				if (wCell < 0) {
					break;
				}

				if (maxRounds == itemMaxSize) {
					break;
				}
				maxRounds ++;
				
#ifdef ENABLE_GRID_MEMORY_FIX
				LPITEM item = m_pointsInstant.playerSlots->pItems[wCell];
#else
				LPITEM item =  m_pointsInstant.pItems[wCell];
#endif
				if (item) 
				{
					if (item->GetSize() >= maxRounds) {
						return false;
					}
				}
			}
		}
	}

 

you can do way better than this or have it in a seprate func ofc, this is just a simple example

gl...

>bunch of kids

>not using IsEmptyItemGrid

>recreating IsEmptyItemGrid code but uglier

 

  • Flame 1
  • Active+ Member
On 7/25/2024 at 5:14 PM, martysama0134 said:

>bunch of kids

>not using IsEmptyItemGrid

>recreating IsEmptyItemGrid code but uglier

 

1- you're typing in english because it's the only language you know , im typing in english because it's the only language you know  , we're not the same .. english teacher

2- [Untested btw i wrote it like in 5 min]

3- get a life

On 7/25/2024 at 5:14 PM, martysama0134 said:

>bunch of kids

>not using IsEmptyItemGrid

>recreating IsEmptyItemGrid code but uglier

 

you were right the IsEmptyItemGrid really did came through after all 

.png

  • Lmao 1

I don’t know — I think.

 

Discord

 

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.