Jump to content

How to stack automatically picked items


Recommended Posts

 

 

 

 

Hi, developers

I added an automatic pickup system

ENABLE_ AUTOMATIC_ PICK_ UP_ SYSTEM

Now I found a bug

Items entered into the inventory through the automatic pickup system cannot be automatically stacked.

Even if they are allowed to be stacked.

When I throw them on the ground, manually pick them up and enter the inventory, and they will be automatically stacked。

 

2.Pick up items, no explanation

 

Please help, thank you for everyone

 

spacer.png

In photos

The red and blue arrow logo is the same item

 

Code:

input_main.cpp

Quote

#ifdef ENABLE_AUTOMATIC_PICK_UP_SYSTEM
int CInputMain::ItemsPickup(LPCHARACTER ch, const char * c_pData, size_t uiBytes)
{
    TPacketCGItemsPickUp * p = (TPacketCGItemsPickUp *)c_pData;
    const int iExtraLen = p->count * sizeof(DWORD);
    if (uiBytes < sizeof(TPacketCGItemsPickUp) + iExtraLen)
        return -1;
    const DWORD pickupMode = ch->GetPickUPMode();
    if (IS_SET(pickupMode, AUTOMATIC_PICK_UP_ACTIVATE))
    {
        const DWORD *dwVIDS = (DWORD *)(c_pData + sizeof(TPacketCGItemsPickUp));
        for (int i = 0; i < p->count; i++)
        {
            const DWORD dwVID = *(dwVIDS + i);
            LPITEM item = ITEM_MANAGER::instance().FindByVID(dwVID);
            if (!item || !item->GetSectree() || !item->DistanceValid(ch))
                continue;
            const bool canGet = ch->CheckItemCanGet(item);
            if(canGet)
                ch->PickupItem(dwVID);
        }
        
        /*
        const DWORD *dwVIDS = (DWORD *)(c_pData + sizeof(TPacketCGItemsPickUp));
        std::map<LPITEM, LPCHARACTER> m_pickupItems; 
        for (int i = 0; i < p->count; i++)
        {
            const DWORD dwVID = *(dwVIDS + i);
            LPITEM item = ITEM_MANAGER::instance().FindByVID(dwVID);
            if (!item || !item->GetSectree() || !item->DistanceValid(ch))
                continue;
            LPCHARACTER itemOwner = ch;
            if(ch->CanGetGroundItem(item, itemOwner))
            {
                const bool canGet = itemOwner->CheckItemCanGet(item);
                if(canGet)
                    m_pickupItems.emplace(item, itemOwner);
            }
        }
        for(auto it = m_pickupItems.begin();it != m_pickupItems.end();++it)
        {
            LPITEM item = it->first;
            LPSECTREE sectree = item->GetSectree();
            if(sectree)
            {
                item->SetOwnership(NULL);
                sectree->RemoveEntity(item);
                item->Save();
            }
        }
        for(auto it = m_pickupItems.begin();it != m_pickupItems.end();++it)
            it->first->ViewCleanup();

        for(auto it = m_pickupItems.begin();it != m_pickupItems.end();++it)
        {
            LPITEM item = it->first;
            LPCHARACTER itemOwner = it->second;
            if(item->GetVnum() == 1)
            {
                itemOwner->GiveGold(item->GetCount());
                M2_DESTROY_ITEM(item);
                itemOwner->Save();
            }
            else
            {
                itemOwner->ChatPacket(CHAT_TYPE_ITEM_INFO, "304 %s", item->GetName());
                itemOwner->AutoGiveItem(item);
            }
        }
        */
    }
    return iExtraLen;
}
#endif

char_battle.cpp

 

Quote

void CHARACTER::Reward(bool bItemDrop)
{
    if (GetRaceNum() == 5001)
    {
        // @fixme194 BEGIN GetMovablePosition should not return
        PIXEL_POSITION pos = GetXYZ();
        SECTREE_MANAGER::instance().GetMovablePosition(GetMapIndex(), GetX(), GetY(), pos);
        // @fixme194 END

        LPITEM item;
        int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax);
        iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(NULL) / 100;
        iGold *= GetGoldMultipler();
        int iSplitCount = number(25, 35);

        sys_log(0, "WAEGU Dead gold %d split %d", iGold, iSplitCount);

        for (int i = 1; i <= iSplitCount; ++i)
        {
            if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold / iSplitCount)))
            {
                if (i != 0)
                {
                    pos.x = number(-7, 7) * 20;
                    pos.y = number(-7, 7) * 20;

                    pos.x += GetX();
                    pos.y += GetY();
                }

                item->AddToGround(GetMapIndex(), pos);
                item->StartDestroyEvent();
            }
        }
        return;
    }

       LPCHARACTER pkAttacker = DistributeExp();

#ifdef ENABLE_KILL_EVENT_FIX
    if (!pkAttacker && !(pkAttacker = GetMostAttacked()))
        return;
#else
    if (!pkAttacker)
        return;
#endif

    if (pkAttacker->IsPC())
    {
        if ((GetLevel() - pkAttacker->GetLevel()) >= -10)
        {
            if (pkAttacker->GetRealAlignment() < 0)
            {
                if (pkAttacker->IsEquipUniqueItem(UNIQUE_ITEM_FASTER_ALIGNMENT_UP_BY_KILL))
                    pkAttacker->UpdateAlignment(14);
                else
                    pkAttacker->UpdateAlignment(7);
            }
            else
                pkAttacker->UpdateAlignment(2);
        }

        pkAttacker->SetQuestNPCID(GetVID());
        quest::CQuestManager::instance().Kill(pkAttacker->GetPlayerID(), GetRaceNum());
        CHARACTER_MANAGER::instance().KillLog(GetRaceNum());
#ifdef ENABLE_HUNTING_SYSTEM
        pkAttacker->UpdateHuntingMission(GetRaceNum());
#endif

        if (!number(0, 9))
        {
            if (pkAttacker->GetPoint(POINT_KILL_HP_RECOVERY))
            {
                int iHP = pkAttacker->GetMaxHP() * pkAttacker->GetPoint(POINT_KILL_HP_RECOVERY) / 100;
                pkAttacker->PointChange(POINT_HP, iHP);
                CreateFly(FLY_HP_SMALL, pkAttacker);
            }

            if (pkAttacker->GetPoint(POINT_KILL_SP_RECOVER))
            {
                int iSP = pkAttacker->GetMaxSP() * pkAttacker->GetPoint(POINT_KILL_SP_RECOVER) / 100;
                pkAttacker->PointChange(POINT_SP, iSP);
                CreateFly(FLY_SP_SMALL, pkAttacker);
            }
        }
    }
    //pu1.Pop();

    if (!bItemDrop)
        return;

    // @fixme194 BEGIN GetMovablePosition should not return
    PIXEL_POSITION pos = GetXYZ();
    SECTREE_MANAGER::instance().GetMovablePosition(GetMapIndex(), GetX(), GetY(), pos);
    // @fixme194 END

    if (test_server)
        sys_log(0, "Drop money : Attacker %s", pkAttacker->GetName());
    RewardGold(pkAttacker);

    LPITEM item;

    static std::vector<LPITEM> s_vec_item;
    s_vec_item.clear();

    if (ITEM_MANAGER::instance().CreateDropItem(this, pkAttacker, s_vec_item))
    {
        if (s_vec_item.size() == 0);
        else if (s_vec_item.size() == 1)
        {
            item = s_vec_item[0];
#ifdef ENABLE_AUTOMATIC_PICK_UP_SYSTEM
            if(pkAttacker->FindAffect(AFFECT_AUTO_PICK_UP) && IS_SET(pkAttacker->GetPickUPMode(), AUTOMATIC_PICK_UP_ACTIVATE) && pkAttacker->CheckItemCanGet(item))
            {
                pkAttacker->ChatPacket(CHAT_TYPE_ITEM_INFO, "304 %s", item->GetName());
                pkAttacker->AutoGiveItem(item);
            }
            else
#endif
            {
            item->AddToGround(GetMapIndex(), pos);

            if (CBattleArena::instance().IsBattleArenaMap(pkAttacker->GetMapIndex()) == false)
                {
#ifdef ENABLE_DICE_SYSTEM
                    if (pkAttacker->GetParty())
                    {
                        FPartyDropDiceRoll f(item, pkAttacker);
                        f.Process(this);
                    }
                    else
                        item->SetOwnership(pkAttacker);
#else
                item->SetOwnership(pkAttacker);
#endif
                }

                item->StartDestroyEvent();

                pos.x = number(-7, 7) * 20;
                pos.y = number(-7, 7) * 20;
                pos.x += GetX();
                pos.y += GetY();

                sys_log(0, "DROP_ITEM: %s %d %d from %s", item->GetName(), pos.x, pos.y, GetName());
            }
        }
        else
        {
            int iItemIdx = s_vec_item.size() - 1;

            std::priority_queue<std::pair<int, LPCHARACTER> > pq;

            int total_dam = 0;

            for (TDamageMap::iterator it = m_map_kDamage.begin(); it != m_map_kDamage.end(); ++it)
            {
                int iDamage = it->second.iTotalDamage;
                if (iDamage > 0)
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(it->first);

                    if (ch)
                    {
                        pq.push(std::make_pair(iDamage, ch));
                        total_dam += iDamage;
                    }
                }
            }

            std::vector<LPCHARACTER> v;

            while (!pq.empty() && pq.top().first * 10 >= total_dam)
            {
                v.emplace_back(pq.top().second);
                pq.pop();
            }

            if (v.empty())
            {

                while (iItemIdx >= 0)
                {
                    item = s_vec_item[iItemIdx--];

                    if (!item)
                    {
                        sys_err("item null in vector idx %d", iItemIdx + 1);
                        continue;
                    }

                    item->AddToGround(GetMapIndex(), pos);

                    //item->SetOwnership(pkAttacker);
                    item->StartDestroyEvent();

                    pos.x = number(-7, 7) * 20;
                    pos.y = number(-7, 7) * 20;
                    pos.x += GetX();
                    pos.y += GetY();

                    sys_log(0, "DROP_ITEM: %s %d %d by %s", item->GetName(), pos.x, pos.y, GetName());
                }
            }
            else
            {

                std::vector<LPCHARACTER>::iterator it = v.begin();

                while (iItemIdx >= 0)
                {
                    item = s_vec_item[iItemIdx--];

                    if (!item)
                    {
                        sys_err("item null in vector idx %d", iItemIdx + 1);
                        continue;
                    }

                    LPCHARACTER ch = *it;

                    if (ch->GetParty())
                        ch = ch->GetParty()->GetNextOwnership(ch, GetX(), GetY());
#ifdef ENABLE_AUTOMATIC_PICK_UP_SYSTEM
                    if(ch->FindAffect(AFFECT_AUTO_PICK_UP) && IS_SET(ch->GetPickUPMode(), AUTOMATIC_PICK_UP_ACTIVATE) && ch->CheckItemCanGet(item))
                    {
                        ch->ChatPacket(CHAT_TYPE_ITEM_INFO, "304 %s", item->GetName());
                        ch->AutoGiveItem(item);
                        ++it;
                        if (it == v.end())
                            it = v.begin();
                        continue;
                    }
#endif

                    item->AddToGround(GetMapIndex(), pos);
                    ++it;

                    if (it == v.end())
                        it = v.begin();
                    if (CBattleArena::instance().IsBattleArenaMap(ch->GetMapIndex()) == false)
                    {
#ifdef ENABLE_DICE_SYSTEM
                        if (ch->GetParty())
                        {
                            FPartyDropDiceRoll f(item, ch);
                            f.Process(this);
                        }
                        else
                            item->SetOwnership(ch);
#else
                        item->SetOwnership(ch);
#endif
                    }

                    item->StartDestroyEvent();

                    pos.x = number(-7, 7) * 20;
                    pos.y = number(-7, 7) * 20;
                    pos.x += GetX();
                    pos.y += GetY();

                    sys_log(0, "DROP_ITEM: %s %d %d by %s", item->GetName(), pos.x, pos.y, GetName());
                }
            }
        }
    }

    m_map_kDamage.clear();
}

 

Edited by Metin2 Dev International
Core X - External 2 Internal
Link to comment
Share on other sites

  • Replies 2
  • Created
  • Last Reply

Top Posters In This Topic

Basically in the char_item.cpp -> AutoGiveItem function don't have extend with stack item. 


Check with this, and yes write the datatype to fit with your src.

Search this:

 

void CHARACTER::AutoGiveItem(LPITEM item, bool longOwnerShip)
{
	if (NULL == item)
	{
		sys_err ("NULL point.");
		return;
	}
	if (item->GetOwner())
	{
		sys_err ("item %d 's owner exists!",item->GetID());
		return;
	}


Add under this:

 

	WORD bCount = item->GetCount();

	if (item->GetType() == ITEM_BLEND)
	{
		for (int i=0; i < INVENTORY_MAX_NUM; i++)
		{
			LPITEM inv_item = GetInventoryItem(i);

			if (inv_item == NULL)
				continue;

			if (inv_item->GetType() == ITEM_BLEND && inv_item->GetVnum() == item->GetVnum())
			{
				if (inv_item->GetSocket(0) == item->GetSocket(0) && inv_item->GetSocket(1) == item->GetSocket(1) && inv_item->GetSocket(2) == item->GetSocket(2) && inv_item->GetCount() < MAX_ITEM_STACK)
				{
					inv_item->SetCount(inv_item->GetCount() + item->GetCount());
					M2_DESTROY_ITEM(item);
					return;
				}
			}
		}
	}
	else
	{
		TItemTable * p = ITEM_MANAGER::instance().GetTable(item->GetVnum());
		if (!p)
		{
			M2_DESTROY_ITEM(item);
			return;
		}
		if (p->dwFlags & ITEM_FLAG_STACKABLE)
		{
			for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
			{
				LPITEM invItem = GetInventoryItem(i);
				if (!invItem)
					continue;

				if (invItem->GetVnum() == item->GetVnum() && FN_check_item_socket(invItem))
				{
					if (IS_SET(p->dwFlags, ITEM_FLAG_MAKECOUNT))
					{
						if (bCount < p->alValues[1])
							bCount = p->alValues[1];
					}
					const WORD bCount2 = MIN(MAX_ITEM_STACK - invItem->GetCount(), bCount);
					bCount -= bCount2;
					invItem->SetCount(invItem->GetCount() + bCount2);
					if (bCount == 0)
					{
						if (invItem->GetType() == ITEM_QUEST || invItem->GetType() == ITEM_MATERIAL)
							quest::CQuestManager::instance().PickupItem (GetPlayerID(), invItem);
						M2_DESTROY_ITEM(item);
						return;
					}
				}
			}
		}
	}

	item->SetCount(bCount);

 

Edited by SamuraiHUN
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • 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.