Jump to content

Recommended Posts

  • Bronze

Here you got some bugfixes from me.


Stack Potts etc directly in Belt Inventory, before putting them to Inventory

Spoiler

char_item.cpp:


search:

if (item->IsStackable() && !IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
{
    BYTE bCount = item->GetCount();

add after:
    for (WORD i = BELT_INVENTORY_SLOT_START; i < BELT_INVENTORY_SLOT_END; ++i)
        {
            LPITEM item2 = pc->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);

Stack items you drop for Other guys in your party:

Spoiler

 

char_item.cpp:

search:
LPCHARACTER owner = funcFindOwnership.owner;

            int iEmptyCell;

add after:
//FIX_DROP_PARTY
            if (owner)
            {
                if (item->IsStackable() && !IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
                {
                    BYTE bCount = item->GetCount();
                    for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
                    {
                        LPITEM item2 = owner->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)
                            {
                                owner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾ÆÀÌÅÛ È¹µæ: %s ´ÔÀ¸·ÎºÎÅÍ %s"), GetName(), item2->GetName());
                                ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾ÆÀÌÅÛ Àü´Þ: %s ´Ô¿¡°Ô %s"), owner->GetName(), item2->GetName());
                                M2_DESTROY_ITEM(item);
                                if (item2->GetType() == ITEM_QUEST)
                                    quest::CQuestManager::instance().PickupItem(owner->GetPlayerID(), item2);
                                return true;
                            }
                        }
                    }
                    item->SetCount(bCount);

                }

            }
            //END FIX_DROP_PARTY

 



Fix for the Drops Pet makes if they kill an Monster

 

Spoiler

 

service.h:
    add:
        #define __FIX_PET_ATTACK


char.h:
    search:
        #ifdef __PET_SYSTEM__
            private:
                bool m_bIsPet;
            public:
                void SetPet() { m_bIsPet = true; }
                bool IsPet() { return m_bIsPet; }
        #endif
    add below:
        #ifdef __FIX_PET_ATTACK
            private:
                LPCHARACTER m_Owner;
            public:
                void SetOwner(LPCHARACTER owner) { m_Owner = owner; }
                LPCHARACTER GetOwner() { return m_Owner; }
        #endif
char.cpp:
    search:
        #ifdef PET_SYSTEM
         m_petSystem = 0;
         m_bIsPet = false;
        #endif
    add below:
        #ifdef __FIX_PET_ATTACK
        m_Owner = NULL;
        #endif
PetSystem.cpp:
    in:
        DWORD CPetActor::Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar)
    search:
        if (0 != m_pkChar)
        {
            m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
            m_dwVID = m_pkChar->GetVID();

            return m_dwVID;
        }
    replace it with:
        if (0 != m_pkChar)
        {
        #ifdef __FIX_PET_ATTACK
                m_pkChar->SetOwner(m_pkOwner);
                m_pkChar->SetPet();
        #endif
            m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
            m_dwVID = m_pkChar->GetVID();

            return m_dwVID;
        }
        

    search:
        m_pkChar->SetEmpire(m_pkOwner->GetEmpire());
    add below:
        #ifdef __FIX_PET_ATTACK
                m_pkChar->SetOwner(m_pkOwner);
        #endif

item.cpp:
    in:
        void CItem::SetOwnership(LPCHARACTER ch, int iSec)


    add at the beginning of the function:
        #ifdef __FIX_PET_ATTACK
            if(ch)
            {
                if (ch->IsPet())
                {
                    LPCHARACTER owner = ch->GetOwner();
                    if(owner)
                        ch = owner;
                }
            }
        #endif

 


Pets run towards your dropped items and pick them up for you:

 

 

Spoiler

 

service.h:
        add:
                #define __PET_PICKUP
PetSystem.h:
        search:
                void            SetSummonItem (LPITEM pItem);
        add below:
                #ifdef __PET_PICKUP
                        void            PickUpItems(int range);
                        void            BringItem();
                        void            SetPickup(bool is_pickup) { m_is_pickup = is_pickup; }
                        bool            IsPickup(){ return m_is_pickup; }
                        void            SetPickupItem(LPITEM item) { m_pickup_item = item; }
                        LPITEM            GetPickupItem(){ return m_pickup_item; }
                #endif
        search:
            LPCHARACTER        m_pkOwner;
        add below:
            #ifdef __PET_PICKUP
            bool            m_is_pickup;
            LPITEM            m_pickup_item;
            #endif


char.h:
        search:
                bool            PickupItem(DWORD vid);
        add below:
                #ifdef __PET_PICKUP
                        bool            PickupItemByPet(DWORD vid);
                        
                #endif


char_item.cpp:
        search:
            bool CHARACTER::PickupItem(DWORD dwVID)

        add above:
            #ifdef __PET_PICKUP
            bool CHARACTER::PickupItemByPet(DWORD dwVID)
            {
                LPITEM item = ITEM_MANAGER::instance().FindByVID(dwVID);
                if (IsObserverMode())
                    return false;
                if (!item || !item->GetSectree())
                    return false;
                if (item->IsOwnership(this))
                {
                    if (item->GetType() == ITEM_ELK)
                    {
                        GiveGold(item->GetCount());
                        item->RemoveFromGround();

                        M2_DESTROY_ITEM(item);
                        Save();
                    }
                    else
                    {
                        if (item->IsStackable() && !IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
                        {
                            BYTE bCount = item->GetCount();

                            for (int i = 0; i < INVENTORY_MAX_NUM; ++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);
                        }

                        int iEmptyCell;
                        if (item->IsDragonSoul())
                        {
                            if ((iEmptyCell = GetEmptyDragonSoulInventory(item)) == -1)
                            {
                                sys_log(0, "No empty ds inventory pid %u size %ud itemid %u", GetPlayerID(), item->GetSize(), item->GetID());
                                ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ÒÁöÇÏ°í ÀÖ´Â ¾ÆÀÌÅÛÀÌ ³Ê¹« ¸¹½À´Ï´Ù."));
                                return false;
                            }
                        }
                        else
                        {
                            if ((iEmptyCell = GetEmptyInventory(item->GetSize())) == -1)
                            {
                                sys_log(0, "No empty inventory pid %u size %ud itemid %u", GetPlayerID(), item->GetSize(), item->GetID());
                                ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ÒÁöÇÏ°í ÀÖ´Â ¾ÆÀÌÅÛÀÌ ³Ê¹« ¸¹½À´Ï´Ù."));
                                return false;
                            }
                        }

                        item->RemoveFromGround();

                        if (item->IsDragonSoul())
                            item->AddToCharacter(this, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyCell));
                        else
                            item->AddToCharacter(this, TItemPos(INVENTORY, iEmptyCell));

                        char szHint[32 + 1];
                        snprintf(szHint, sizeof(szHint), "%s %u %u", item->GetName(), item->GetCount(), item->GetOriginalVnum());
                        LogManager::instance().ItemLog(this, item, "GET", szHint);
                        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾ÆÀÌÅÛ È¹µæ: %s"), item->GetName());

                        if (item->GetType() == ITEM_QUEST)
                            quest::CQuestManager::instance().PickupItem(GetPlayerID(), item);
                    }
                    //Motion(MOTION_PICKUP);
                    return true;
                }

                return false;
            }
            #endif
PetSystem.cpp:
        search:
                bool CPetActor::Follow(float fMinDistance)
        add above:
                #ifdef __PET_PICKUP
                struct PetPickUpItemStruct
                {
                    CPetActor * pet;
                    int range;
                    PetPickUpItemStruct(CPetActor * p, int r){

                        pet = p;
                        range = r;
                    }
                    void operator()(LPENTITY pEnt)
                    {
                        if (!pet->GetOwner() || !pet->GetCharacter())
                            return;
                        if (pet->IsPickup())
                            return;
                        if (pEnt->IsType(ENTITY_ITEM) == true)
                        {
                            
                            LPITEM item = (LPITEM)pEnt;
                            LPCHARACTER player = pet->GetOwner();
                            if (!item->GetSectree() || !item->IsOwnership(player))
                                return;

                            int iDist = DISTANCE_APPROX(item->GetX() - player->GetX(), player->GetY() - player->GetY());

                            if (iDist > range)
                                return;
                            pet->SetPickup(true);
                            pet->SetPickupItem(item);
                        }

                    }
                };
                void CPetActor::PickUpItems(int range){
                    if (IsPickup())
                        return;
                    long map = m_pkChar->GetMapIndex();
                    PIXEL_POSITION m = m_pkChar->GetXYZ();
                    LPSECTREE tree = SECTREE_MANAGER::instance().Get(map, m.x, m.y);
                    if (!tree)
                    {
                        sys_err("cannot find sectree by %dx%d", m.x, m.y);
                        return;
                    }
                    PetPickUpItemStruct f(this, range);
                    tree->ForEachAround(f);
                }

                void CPetActor::BringItem(){
                    if (!IsPickup())
                        return;
                    LPITEM item = GetPickupItem();
                    if (!m_pkOwner || !m_pkChar || !item || !item->GetSectree())
                        return;
                    
                    float fMinDistance = 20.0;
                    float fPetX = m_pkChar->GetX();
                    float fPetY = m_pkChar->GetY();

                    float itemX = item->GetX();
                    float itemY = item->GetY();

                    float fDist = DISTANCE_SQRT(itemX - fPetX, itemY - fPetY);
                    if (fDist <= 250.0)
                    {
                        SetPickup(false);
                        m_pkOwner->PickupItemByPet(item->GetVID());
                        SetPickupItem(NULL);
                        m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0, 0);
                        return;
                    }
                    m_pkChar->SetRotationToXY(itemX, itemY);
                    float fx, fy;

                    float fDistToGo = fDist - fMinDistance;
                    GetDeltaByDegree(m_pkChar->GetRotation(), fDistToGo, &fx, &fy);

                    if (!m_pkChar->Goto((int)(fPetX + fx + 0.5f), (int)(fPetY + fy + 0.5f)))
                        return;

                    m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0, 0);
                }
                #endif

    search:
        if (this->IsSummoned() && HasOption(EPetOption_Followable))

    add above:
            #ifdef __PET_PICKUP
                if (this->IsSummoned()){
                    this->BringItem();
                    this->PickUpItems(900); // 900 = RANGE
                }    
            #endif
    search:
        this->SetSummonItem(NULL);
    add below:
        #ifdef __PET_PICKUP
                this->SetPickupItem(NULL);
                this->SetPickup(false);
        #endif

    search:
        m_dwSummonItemVID = 0;
        m_dwSummonItemVnum = 0;
    add below:
        #ifdef __PET_PICKUP
                this->SetPickupItem(NULL);
                this->SetPickup(false);
        #endif

 

 

 

 

 

  • Love 16
Link to comment
Share on other sites

Hey, very useful and nice things. Thanks :)

Few notes, regarding to pet pickup system:

Spoiler

Sometimes pet get "stuck" between owner and item.
In order to fix I suggest to change in 'bool CPetActor::Update(DWORD deltaTime)'

This:
if (this->IsSummoned() && HasOption(EPetOption_Followable))
        bResult = bResult && this->_UpdateFollowAI();

To:
if (this->IsSummoned() && HasOption(EPetOption_Followable) && !IsPickup() && !GetPickupItem())
        bResult = bResult && this->_UpdateFollowAI();

 

And one more:
When pet want to bring item which already taken by someone else (other player or pet) it also get "stuck" on position where item was.
I've fixed it with changing next in 'void CPetActor::BringItem()'

This:
if (!m_pkOwner || !m_pkChar || !item || !item->GetSectree())
        return;

To:
if (!m_pkOwner || !m_pkChar || !item || !item->GetSectree())
    {
        this->SetPickupItem(NULL);
        this->SetPickup(false);
        return;
    }

 

Edited by wezt
  • Love 2
Link to comment
Share on other sites

  • Bronze

Im

38 minutes ago, ImBacK said:

im pet pickup system there is bug pet stuck in some time and not taking item 

in pickup pet i have some stuck with iteSuztHNtMbH.gif

                            if (!item->GetSectree() || !item->IsOwnership(player))
                                return;

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

2 hours ago, ImBacK said:
3 hours ago, metin2team said:

this means that if you don't own the item the pet won't get it unless you have your char's name on it.

so , if i want et pickup item without name and with name remove this  !item->IsOwnership(player)  ?

bool CItem::IsOwnership(LPCHARACTER ch)
{
    if (!m_pkOwnershipEvent)
        return true; //return true if item doesn't has ownership at all (item without name)

    return m_dwOwnershipPID == ch->GetPlayerID() ? true : false; //return true if item has ownership and it's belong to current player.
}

So you don't have to remove "!item->IsOwnership(player)" in order to "teach" your pet to pick up items "without names" ;)

 

@Micha aka xCPx, I've found one more little bug in "pet pickup system" >> When two or more pets want to bring same item one of them disappears.
Fix in the spoiler:

Spoiler

In order to fix I suggest add 'bool m_isFreeForPet;' to item class.

How to:

1. In item.h

1.1 Find:

bool        m_isLocked;

Add below

bool        m_isFreeForPet;

1.2 Find:

bool        isLocked() const { return m_isLocked; }

Add below:

        void        SetFreeForPet(bool f) {m_isFreeForPet = f;}
        bool        isFreeForPet() const {return m_isFreeForPet; }

2. In item.cpp

Find:

CItem::CItem(DWORD dwVnum)
    : m_dwVnum(dwVnum), m_bWindow(0), m_dwID(0), m_bEquipped(false), m_dwVID(0), m_wCell(0), m_dwCount(0), m_lFlag(0), m_dwLastOwnerPID(0),
    m_bExchanging(false), m_pkDestroyEvent(NULL), m_pkUniqueExpireEvent(NULL), m_pkTimerBasedOnWearExpireEvent(NULL), m_pkRealTimeExpireEvent(NULL),
    m_pkExpireEvent(NULL), 
       m_pkAccessorySocketExpireEvent(NULL), m_pkOwnershipEvent(NULL), m_dwOwnershipPID(0), m_bSkipSave(false), m_isLocked(false),
    m_dwMaskVnum(0), m_dwSIGVnum (0)

Add to the end 'm_isFreeForPet(true)', will be something like this:

CItem::CItem(DWORD dwVnum)
    : m_dwVnum(dwVnum), m_bWindow(0), m_dwID(0), m_bEquipped(false), m_dwVID(0), m_wCell(0), m_dwCount(0), m_lFlag(0), m_dwLastOwnerPID(0),
    m_bExchanging(false), m_pkDestroyEvent(NULL), m_pkUniqueExpireEvent(NULL), m_pkTimerBasedOnWearExpireEvent(NULL), m_pkRealTimeExpireEvent(NULL),
    m_pkExpireEvent(NULL), 
       m_pkAccessorySocketExpireEvent(NULL), m_pkOwnershipEvent(NULL), m_dwOwnershipPID(0), m_bSkipSave(false), m_isLocked(false),
    m_dwMaskVnum(0), m_dwSIGVnum (0), m_isFreeForPet(true)

 

3. In PetSystem.cpp change "struct PetPickUpItemStruct"

struct PetPickUpItemStruct
{
    CPetActor * pet;
    int range;

    PetPickUpItemStruct(CPetActor * p, int r)
    {
        pet = p;
        range = r;
    }

    void operator()(LPENTITY pEnt)
    {
        if (!pet->GetOwner() || !pet->GetCharacter())
            return;
        if (pet->IsPickup())
            return;
        if (pEnt->IsType(ENTITY_ITEM) == true)
        {
            LPITEM item = (LPITEM)pEnt;
            LPCHARACTER player = pet->GetOwner();
            if (!item || !item->GetSectree() || !item->IsOwnership(player))
                return;

            int iDist = DISTANCE_APPROX(item->GetX() - player->GetX(), player->GetY() - player->GetY());

            if (iDist > range)
                return;

            if(item && item->isFreeForPet())
            {
                item->SetFreeForPet(false);
                pet->SetPickup(true);
                pet->SetPickupItem(item);
            }
        }

    }
};

4. In char_item.cpp -> "bool CHARACTER::PickupItemByPet(DWORD dwVID)"

Find this:

            if (item->GetType() == ITEM_QUEST)
                quest::CQuestManager::instance().PickupItem(GetPlayerID(), item);

Add below:

item->SetFreeForPet(true);

 

That's all.
P.s: Let me know if you have better solution for this bug or if I'm wrong in something.

 

Regards

Link to comment
Share on other sites

  • 1 month later...
  • 1 year later...
  • 11 months later...

So if I did something like this in questlua_pc.cpp->int pc_give_or_drop_item(lua_State* L)

LogManager::instance().QuestRewardLog(pPC->GetCurrentQuestName().c_str(), ch->GetPlayerID(), ch->GetLevel(), dwVnum, icount);

if (dwVnum->IsStackable() && !IS_SET(dwVnum->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
{
	BYTE bCount = dwVnum->GetCount();
	for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
    {
    	LPITEM item2 = ch->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) != dwVnum->GetSocket(j))
                	break;

		if (j != ITEM_SOCKET_MAX_NUM)
        	continue;

        BYTE bCount2 = std::min(200 - item2->GetCount(), bCount);
        bCount -= bCount2;

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

        if (bCount == 0)
        {
        	LPITEM item = ch->AutoGiveItem(dwVnum, icount);
        }
    }
}

would that work or I'm missing something?

  • Sad 1
Link to comment
Share on other sites

Ok guys so now I need help.

I changed this:

bool CHARACTER::PickupItemByPet(DWORD dwVID)
{
	LPITEM item = ITEM_MANAGER::instance().FindByVID(dwVID);
  
    if (IsObserverMode())
    	return false;
  
    if (!item || !item->GetSectree())
    	return false;

into this:

bool CHARACTER::PickupItemByPet(DWORD dwVID)
{
	LPITEM item = ITEM_MANAGER::instance().FindByVID(dwVID);
	int iEmptyCell;
	
	if (IsObserverMode())
		return false;
	
	if (!item || !item->GetSectree() || (iEmptyCell = GetEmptyDragonSoulInventory(item)) == -1)
		return false;

What I tried to do was to return false when the inventory is full. But then my server broke into pieces (Segmentation fault!) and now I'm stuck. Can someone help please?

EDIT: Nevermind, I saw the function again and I can see that there is a check down below, just wanted to save the pet's time from walking to the item, since it won't pick it up anw... Great guide!

Link to comment
Share on other sites

On 5/12/2016 at 10:03 AM, ImBacK said:

im pet pickup system there is bug pet stuck in some time and not taking item 

in pickup pet i have some stuck with iteSuztHNtMbH.gif

Strange thing, I wanted this happen, but my source was already setup like:

bool CItem::IsOwnership(LPCHARACTER ch)
{
    if (!m_pkOwnershipEvent)
        return true;

    return m_dwOwnershipPID == ch->GetPlayerID() ? true : false;
}

So I decided to make a little fix just for the pet, without changing the function to the rest of the calls. If it happens you want the same thing do this:

// @item.h - Change this like:
bool		IsOwnership(LPCHARACTER ch, bool strict = false);

// @item.cpp - Chnage the structure like this:
bool CItem::IsOwnership(LPCHARACTER ch, bool strict)
{
	if (!m_pkOwnershipEvent)
		return !strict;

	return m_dwOwnershipPID == ch->GetPlayerID() ? true : false;
}

Now, each time you call item->IsOwnership(ch/player/etc...)  you will get the same result you know (item->IsOwnership(ch, false) works as well), but when you call item->IsOwnership(ch, true) the bool will return true only if the item has the character's name on it.

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

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.