Example #1
0
Item* Item::CreateItem( uint32 item, uint32 count, Player const* player )
{
    if (count < 1)
        return NULL;                                        //don't create item at zero count

    if (ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(item))
    {
        if (count > pProto->GetMaxStackSize())
            count = pProto->GetMaxStackSize();

        MANGOS_ASSERT(count != 0 && "pProto->Stackable == 0 but checked at loading already");

        Item* pItem = NewItemOrBag(pProto);
        if (pItem->Create(sObjectMgr.GenerateItemLowGuid(), item, player))
        {
            pItem->SetCount(count);
            return pItem;
        }
        else
            delete pItem;
    }
    return NULL;
}
Example #2
0
Item* Item::CreateItem( uint32 item, uint32 count, Player const* player )
{
    if ( count < 1 )
        return NULL;                                        //don't create item at zero count

    ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
    if( pProto )
    {
        if ( count > pProto->GetMaxStackSize())
            count = pProto->GetMaxStackSize();

        assert(count !=0 && "pProto->Stackable==0 but checked at loading already");

        Item *pItem = NewItemOrBag( pProto );
        if( pItem->Create(objmgr.GenerateLowGuid(HIGHGUID_ITEM), item, player) )
        {
            pItem->SetCount( count );
            return pItem;
        }
        else
            delete pItem;
    }
    return NULL;
}
Example #3
0
void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
{
    sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SELL_ITEM");
    uint64 vendorguid, itemguid;
    uint32 count;

    recvData >> vendorguid >> itemguid >> count;

    if (!itemguid)
        return;

    Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);
    if (!creature)
    {
        sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid)));
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
        return;
    }

    // remove fake death
    if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
        GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

    Item* pItem = _player->GetItemByGuid(itemguid);
    if (pItem)
    {
        // prevent sell not owner item
        if (_player->GetGUID() != pItem->GetOwnerGUID())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
            return;
        }

        // prevent sell non empty bag by drag-and-drop at vendor's item list
        if (pItem->IsNotEmptyBag())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
            return;
        }

        // prevent sell currently looted item
        if (_player->GetLootGUID() == pItem->GetGUID())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
            return;
        }

        // prevent selling item for sellprice when the item is still refundable
        // this probably happens when right clicking a refundable item, the client sends both
        // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified)
        if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
            return; // Therefore, no feedback to client

        // special case at auto sell (sell all)
        if (count == 0)
        {
            count = pItem->GetCount();
        }
        else
        {
            // prevent sell more items that exist in stack (possible only not from client)
            if (count > pItem->GetCount())
            {
                _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
                return;
            }
        }

        ItemTemplate const* pProto = pItem->GetTemplate();
        if (pProto)
        {
            if (pProto->SellPrice > 0)
            {
                if (count < pItem->GetCount())               // need split items
                {
                    Item* pNewItem = pItem->CloneItem(count, _player);
                    if (!pNewItem)
                    {
                        sLog->outError(LOG_FILTER_NETWORKIO, "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
                        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
                        return;
                    }

                    pItem->SetCount(pItem->GetCount() - count);
                    _player->ItemRemovedQuestCheck(pItem->GetEntry(), count);
                    if (_player->IsInWorld())
                        pItem->SendUpdateToPlayer(_player);
                    pItem->SetState(ITEM_CHANGED, _player);

                    _player->AddItemToBuyBackSlot(pNewItem);
                    if (_player->IsInWorld())
                        pNewItem->SendUpdateToPlayer(_player);
                }
                else
                {
                    _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
                    _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
                    pItem->RemoveFromUpdateQueueOf(_player);
                    _player->AddItemToBuyBackSlot(pItem);
                }

                uint32 money = pProto->SellPrice * count;
                _player->ModifyMoney(money);
                _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
            }
            else
                _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
            return;
        }
    }
    _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid, 0);
    return;
}
Example #4
0
void LootRoll::Finalize()
{
    sEventMgr.RemoveEvents(this);

    // this we will have to finalize with groups types.. for now
    // we'll just assume need before greed. person with highest roll
    // in need gets the item.

    uint32 highest = 0;
    int8 hightype = -1;
    uint64 player = 0;

    WorldPacket data(34);

    /*
        Player * gplr = NULL;
        for(std::map<uint64, uint32>::iterator itr = NeedRolls.begin(); itr != NeedRolls.end(); ++itr)
        {
        gplr = _mgr->GetPlayer((uint32)itr->first);
        if(gplr) break;
        }

        if(!gplr)
        {
        for(std::map<uint64, uint32>::iterator itr = GreedRolls.begin(); itr != GreedRolls.end(); ++itr)
        {
        gplr = _mgr->GetPlayer((uint32)itr->first);
        if(gplr) break;
        }
        }
        */
    for (std::map<uint32, uint32>::iterator itr = m_NeedRolls.begin(); itr != m_NeedRolls.end(); ++itr)
    {
        if (itr->second > highest)
        {
            highest = itr->second;
            player = itr->first;
            hightype = NEED;
        }
        /*
        data.Initialize(SMSG_LOOT_ROLL);
        data << _guid << _slotid << itr->first;
        data << _itemid << _itemunk1 << _itemunk2;
        data << uint8(itr->second) << uint8(NEED);
        if(gplr && gplr->GetGroup())
        gplr->GetGroup()->SendPacketToAll(&data);
        */
    }

    if (!highest)
    {
        for (std::map<uint32, uint32>::iterator itr = m_GreedRolls.begin(); itr != m_GreedRolls.end(); ++itr)
        {
            if (itr->second > highest)
            {
                highest = itr->second;
                player = itr->first;
                hightype = GREED;
            }
            /*
            data.Initialize(SMSG_LOOT_ROLL);
            data << _guid << _slotid << itr->first;
            data << _itemid << _itemunk1 << _itemunk2;
            data << uint8(itr->second) << uint8(GREED);
            if(gplr && gplr->GetGroup())
            gplr->GetGroup()->SendPacketToAll(&data);
            */
        }
    }

    Loot * pLoot = 0;
    uint32 guidtype = GET_TYPE_FROM_GUID(_guid);
    if (guidtype == HIGHGUID_TYPE_UNIT)
    {
        Creature * pc = _mgr->GetCreature(GET_LOWGUID_PART(_guid));
        if (pc) pLoot = &pc->loot;
    }
    else if (guidtype == HIGHGUID_TYPE_GAMEOBJECT)
    {
        GameObject * go = _mgr->GetGameObject(GET_LOWGUID_PART(_guid));
        if (go) pLoot = &go->loot;
    }

    if (!pLoot)
    {
        delete this;
        return;
    }

    if (_slotid >= pLoot->items.size())
    {
        delete this;
        return;
    }

    pLoot->items.at(_slotid).roll = NULL;

    uint32 itemid = pLoot->items.at(_slotid).item.itemproto->ItemId;
    uint32 amt = pLoot->items.at(_slotid).iItemsCount;
    if (!amt)
    {
        delete this;
        return;
    }

    Player * _player = (player) ? _mgr->GetPlayer((uint32)player) : 0;
    if (!player || !_player)
    {
        /* all passed */
        data.Initialize(SMSG_LOOT_ALL_PASSED);
        data << _guid << _groupcount << _itemid << _itemunk1 << _itemunk2;
        std::set<uint32>::iterator pitr = m_passRolls.begin();
        while (_player == NULL && pitr != m_passRolls.end())
            _player = _mgr->GetPlayer((*(pitr++)));

        if (_player != NULL)
        {
            if (_player->InGroup())
                _player->GetGroup()->SendPacketToAll(&data);
            else
                _player->GetSession()->SendPacket(&data);
        }

        /* item can now be looted by anyone :) */
        pLoot->items.at(_slotid).passed = true;
        delete this;
        return;
    }

    pLoot->items.at(_slotid).roll = 0;
    data.Initialize(SMSG_LOOT_ROLL_WON);
    data << _guid << _slotid << _itemid << _itemunk1 << _itemunk2;
    data << _player->GetGUID() << uint8(highest) << uint8(hightype);
    if (_player->InGroup())
        _player->GetGroup()->SendPacketToAll(&data);
    else
        _player->GetSession()->SendPacket(&data);

    ItemPrototype* it = ItemPrototypeStorage.LookupEntry(itemid);

    int8 error;
    if ((error = _player->GetItemInterface()->CanReceiveItem(it, 1)) != 0)
    {
        _player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, error);
        return;
    }

    Item * add = _player->GetItemInterface()->FindItemLessMax(itemid, amt, false);

    if (!add)
    {
        SlotResult slotresult = _player->GetItemInterface()->FindFreeInventorySlot(it);
        if (!slotresult.Result)
        {
            _player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_INVENTORY_FULL);
            return;
        }

        sLog.outDebug("AutoLootItem MISC");
        Item *item = objmgr.CreateItem(itemid, _player);

        item->SetUInt32Value(ITEM_FIELD_STACK_COUNT, amt);
        if (pLoot->items.at(_slotid).iRandomProperty != NULL)
        {
            item->SetRandomProperty(pLoot->items.at(_slotid).iRandomProperty->ID);
            item->ApplyRandomProperties(false);
        }
        else if (pLoot->items.at(_slotid).iRandomSuffix != NULL)
        {
            item->SetRandomSuffix(pLoot->items.at(_slotid).iRandomSuffix->id);
            item->ApplyRandomProperties(false);
        }


        if (_player->GetItemInterface()->SafeAddItem(item, slotresult.ContainerSlot, slotresult.Slot))
        {
            _player->GetSession()->SendItemPushResult(item, false, true, true, true, slotresult.ContainerSlot, slotresult.Slot, 1);
            sQuestMgr.OnPlayerItemPickup(_player, item);
        }
        else
            item->DeleteMe();
    }
    else
    {
        add->SetCount(add->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + amt);
        add->m_isDirty = true;
        sQuestMgr.OnPlayerItemPickup(_player, add);
        _player->GetSession()->SendItemPushResult(add, false, true, true, false, _player->GetItemInterface()->GetBagSlotByGuid(add->GetGUID()), 0xFFFFFFFF, 1);
    }

    pLoot->items.at(_slotid).iItemsCount = 0;
    // this gets sent to all looters
    data.Initialize(SMSG_LOOT_REMOVED);
    data << uint8(_slotid);
    Player * plr;
    for (LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); ++itr)
    {
        if ((plr = _player->GetMapMgr()->GetPlayer(*itr)) != 0)
            plr->GetSession()->SendPacket(&data);
    }

    /*WorldPacket idata(45);
    _player->GetSession()->BuildItemPushResult(&idata, _player->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(_slotid).iRandomProperty ? pLoot->items.at(_slotid).iRandomProperty->ID : 0);

    if(_player->InGroup())
    _player->GetGroup()->SendPacketToAll(&idata);
    else
    _player->GetSession()->SendPacket(&idata);*/

    delete this;
}
//this void creates new auction and adds auction to some auctionhouse
void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)
{
    uint64 auctioneer;
    uint32 itemsCount, etime, bid, buyout;
    recv_data >> auctioneer;
    recv_data >> itemsCount;

    uint64 itemGUIDs[MAX_AUCTION_ITEMS]; // 160 slot = 4x 36 slot bag + backpack 16 slot
    uint32 count[MAX_AUCTION_ITEMS];

    for (uint32 i = 0; i < itemsCount; ++i)
    {
        recv_data >> itemGUIDs[i];
        recv_data >> count[i];

        if (!itemGUIDs[i] || !count[i] || count[i] > 1000 )
            return;
    }

    recv_data >> bid;
    recv_data >> buyout;
    recv_data >> etime;

    if (!bid || !etime)
        return;

    Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER);
    if (!creature)
    {
        sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(auctioneer));
        return;
    }

    AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction());
    if (!auctionHouseEntry)
    {
        sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", GUID_LOPART(auctioneer));
        return;
    }

    if (itemsCount > MAX_AUCTION_ITEMS)
    {
        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
        return;
    }

    etime *= MINUTE;

    switch(etime)
    {
        case 1*MIN_AUCTION_TIME:
        case 2*MIN_AUCTION_TIME:
        case 4*MIN_AUCTION_TIME:
            break;
        default:
            return;
    }

    if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
        GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

    Item* items[MAX_AUCTION_ITEMS];

    uint32 finalCount = 0;

    for (uint32 i = 0; i < itemsCount; ++i)
    {
        Item* item = _player->GetItemByGuid(itemGUIDs[i]);

        if (!item)
        {
            SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND);
            return;
        }

        if (sAuctionMgr->GetAItem(item->GetGUIDLow()) || !item->CanBeTraded() || item->IsNotEmptyBag() || 
            item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) ||
            item->GetCount() < count[i])
        {
            SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
            return;
        }

        items[i] = item;
        finalCount += count[i];
    }

    if (!finalCount)
    {
        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
        return;
    }

    for (uint32 i = 0; i < itemsCount; ++i)
    {
        Item* item = items[i];

        if (item->GetMaxStackCount() < finalCount)
        {
            SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
            return;
        }
    }

    for (uint32 i = 0; i < itemsCount; ++i)
    {
        Item* item = items[i];

        uint32 auctionTime = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME));
        AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());

        uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount);
        if (!_player->HasEnoughMoney(deposit))
        {
            SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY);
            return;
        }

        _player->ModifyMoney(-int32(deposit));

        AuctionEntry* AH = new AuctionEntry;
        AH->Id = sObjectMgr->GenerateAuctionID();

        if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
            AH->auctioneer = 23442;
        else
            AH->auctioneer = GUID_LOPART(auctioneer);

        if (itemsCount == 1 && item->GetCount() == count[i])
        {
            if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
            {
                sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
                    GetPlayerName(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount());
            }

            AH->item_guidlow = item->GetGUIDLow();
            AH->item_template = item->GetEntry();
            AH->owner = _player->GetGUIDLow();
            AH->startbid = bid;
            AH->bidder = 0;
            AH->bid = 0;
            AH->buyout = buyout;
            AH->expire_time = time(NULL) + auctionTime;
            AH->deposit = deposit;
            AH->auctionHouseEntry = auctionHouseEntry;

            sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
            sAuctionMgr->AddAItem(item);
            auctionHouse->AddAuction(AH);

            _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);

            SQLTransaction trans = CharacterDatabase.BeginTransaction();
            item->DeleteFromInventoryDB(trans);
            item->SaveToDB(trans);
            AH->SaveToDB(trans);
            _player->SaveInventoryAndGoldToDB(trans);
            CharacterDatabase.CommitTransaction(trans);

            SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK);

            GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
            return;
        }
        else
        {
            Item* newItem = item->CloneItem(finalCount, _player);
            if (!newItem)
            {
                sLog->outError("CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry());
                SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
                return;
            }

            if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
            {
                sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
                    GetPlayerName(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount());
            }

            AH->item_guidlow = newItem->GetGUIDLow();
            AH->item_template = newItem->GetEntry();
            AH->owner = _player->GetGUIDLow();
            AH->startbid = bid;
            AH->bidder = 0;
            AH->bid = 0;
            AH->buyout = buyout;
            AH->expire_time = time(NULL) + auctionTime;
            AH->deposit = deposit;
            AH->auctionHouseEntry = auctionHouseEntry;

            sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
            sAuctionMgr->AddAItem(newItem);
            auctionHouse->AddAuction(AH);

            for (uint32 i = 0; i < itemsCount; ++i)
            {
                Item* item = items[i];

                if (item->GetCount() == count[i])
                {
                    _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);

                    SQLTransaction trans = CharacterDatabase.BeginTransaction();
                    item->DeleteFromInventoryDB(trans);
                    item->SaveToDB(trans);
                    CharacterDatabase.CommitTransaction(trans);
                }
                else
                {
                    item->SetCount(item->GetCount() - count[i]);
                    item->SetState(ITEM_CHANGED, _player);
                    _player->ItemRemovedQuestCheck(item->GetEntry(), count[i]);
                    item->SendUpdateToPlayer(_player);

                    SQLTransaction trans = CharacterDatabase.BeginTransaction();
                    item->SaveToDB(trans);
                    CharacterDatabase.CommitTransaction(trans);
                }
            }

            SQLTransaction trans = CharacterDatabase.BeginTransaction();
            AH->SaveToDB(trans);
            _player->SaveInventoryAndGoldToDB(trans);
            CharacterDatabase.CommitTransaction(trans);

            SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK);

            GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
            return;
        }
    }
}
Example #6
0
void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
{
    DEBUG_LOG(  "WORLD: Received CMSG_SELL_ITEM" );

    ObjectGuid vendorGuid;
    uint64 itemguid;
    uint32 count;

    recv_data >> vendorGuid;
    recv_data >> itemguid;
    recv_data >> count;

    if(!itemguid)
        return;

    Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
    if (!pCreature)
    {
        DEBUG_LOG("WORLD: HandleSellItemOpcode - %s not found or you can't interact with him.", vendorGuid.GetString().c_str());
        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
        return;
    }

    // remove fake death
    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

    Item *pItem = _player->GetItemByGuid( itemguid );
    if( pItem )
    {
        // prevent sell not owner item
        if(_player->GetGUID() != pItem->GetOwnerGUID())
        {
            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }

        // prevent sell non empty bag by drag-and-drop at vendor's item list
        if(pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
        {
            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }

        // prevent sell currently looted item
        if(_player->GetLootGUID() == pItem->GetGUID())
        {
            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }

        // special case at auto sell (sell all)
        if(count == 0)
        {
            count = pItem->GetCount();
        }
        else
        {
            // prevent sell more items that exist in stack (possible only not from client)
            if(count > pItem->GetCount())
            {
                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
                return;
            }
        }

        ItemPrototype const *pProto = pItem->GetProto();
        if( pProto )
        {
            if( pProto->SellPrice > 0 )
            {
                if(count < pItem->GetCount())               // need split items
                {
                    Item *pNewItem = pItem->CloneItem( count, _player );
                    if (!pNewItem)
                    {
                        sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count );
                        _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
                        return;
                    }

                    pItem->SetCount( pItem->GetCount() - count );
                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), count );
                    if( _player->IsInWorld() )
                        pItem->SendCreateUpdateToPlayer( _player );
                    pItem->SetState(ITEM_CHANGED, _player);

                    _player->AddItemToBuyBackSlot( pNewItem );
                    if( _player->IsInWorld() )
                        pNewItem->SendCreateUpdateToPlayer( _player );
                }
                else
                {
                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), pItem->GetCount());
                    _player->RemoveItem( pItem->GetBagSlot(), pItem->GetSlot(), true);
                    pItem->RemoveFromUpdateQueueOf(_player);
                    _player->AddItemToBuyBackSlot( pItem );
                }

                uint32 money = pProto->SellPrice * count;

                _player->ModifyMoney( money );
                _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
            }
            else
                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }
    }
    _player->SendSellError( SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0);
    return;
}
Example #7
0
void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
{
    CHECK_PACKET_SIZE(recv_data,8+8+1);

    sLog.outDebug(  "WORLD: Received CMSG_SELL_ITEM" );
    uint64 vendorguid, itemguid;
    uint8 _count;

    recv_data >> vendorguid >> itemguid >> _count;

    // prevent possible overflow, as mangos uses uint32 for item count
    uint32 count = _count;

    if(!itemguid)
        return;

    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
    if (!pCreature)
    {
        sLog.outDebug( "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
        return;
    }

    // remove fake death
    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

    Item *pItem = _player->GetItemByGuid( itemguid );
    if( pItem )
    {
        // prevent sell not owner item
        if(_player->GetGUID()!=pItem->GetOwnerGUID())
        {
            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }

        // prevent sell non empty bag by drag-and-drop at vendor's item list
        if(pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
        {
            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }

        // prevent sell currently looted item
        if(_player->GetLootGUID()==pItem->GetGUID())
        {
            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }

        // special case at auto sell (sell all)
        if(count==0)
        {
            count = pItem->GetCount();
        }
        else
        {
            // prevent sell more items that exist in stack (possable only not from client)
            if(count > pItem->GetCount())
            {
                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
                return;
            }
        }

        ItemPrototype const *pProto = pItem->GetProto();
        if( pProto )
        {
            if( pProto->SellPrice > 0 )
            {
                if(count < pItem->GetCount())               // need split items
                {
                    Item *pNewItem = pItem->CloneItem( count, _player );
                    if (!pNewItem)
                    {
                        sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count );
                        _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
                        return;
                    }

                    pItem->SetCount( pItem->GetCount() - count );
                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), count );
                    if( _player->IsInWorld() )
                        pItem->SendUpdateToPlayer( _player );
                    pItem->SetState(ITEM_CHANGED, _player);

                    _player->AddItemToBuyBackSlot( pNewItem );
                    if( _player->IsInWorld() )
                        pNewItem->SendUpdateToPlayer( _player );
                }
                else
                {
                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), pItem->GetCount());
                    _player->RemoveItem( pItem->GetBagSlot(), pItem->GetSlot(), true);
                    pItem->RemoveFromUpdateQueueOf(_player);
                    _player->AddItemToBuyBackSlot( pItem );
                }

                _player->ModifyMoney( pProto->SellPrice * count );
            }
            else
                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
            return;
        }
    }
    _player->SendSellError( SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0);
    return;
}
Example #8
0
static void addNewAuctions(Player *AHBplayer, AHBConfig *config)
{
	if (!AHBSeller)
		return;
	AuctionHouseObject* auctionHouse = objmgr.GetAuctionsMap(config->GetAHID());
	uint32 items = 0;
	uint32 minItems = config->GetMinItems();
	uint32 maxItems = config->GetMaxItems();
	uint32 auctions = auctionHouse->Getcount();

	if (auctions >= minItems)
	  return;
	if (auctions <= maxItems)
	{
		if ((maxItems - auctions) > ItemsPerCycle)
			items = ItemsPerCycle;
		else
			items = (maxItems - auctions);
	}
	uint32 wtgbin = config->GetPercents(AHB_WHITE_TG);
	uint32 gtgbin = config->GetPercents(AHB_GREEN_TG);
	uint32 btgbin = config->GetPercents(AHB_BLUE_TG);
	uint32 ptgbin = config->GetPercents(AHB_PURPLE_TG);
	uint32 wibin = config->GetPercents(AHB_WHITE_I);
	uint32 gibin = config->GetPercents(AHB_GREEN_I);
	uint32 bibin = config->GetPercents(AHB_BLUE_I);
	uint32 pibin = config->GetPercents(AHB_PURPLE_I);
	uint32 total = wtgbin + gtgbin + btgbin + ptgbin + wibin + gibin + bibin + pibin;

	uint32 pItems = 0;
	uint32 bItems = 0;
	uint32 gItems = 0;
	uint32 wItems = 0;
	uint32 pTGoods = 0;
	uint32 bTGoods = 0;
	uint32 gTGoods = 0;
	uint32 wTGoods = 0;
	for (AuctionHouseObject::AuctionEntryMap::iterator itr = auctionHouse->GetAuctionsBegin();itr != auctionHouse->GetAuctionsEnd();++itr)
	{
		AuctionEntry *Aentry = itr->second;
		Item *item = objmgr.GetAItem(Aentry->item_guidlow);
		if( item )
		{
			ItemPrototype const *prototype = item->GetProto();
			if( prototype )
			{
				switch (prototype->Quality)
				{
				 case 0:
					if (prototype->Class == ITEM_CLASS_TRADE_GOODS)
					   wTGoods = wTGoods + 1;
					else
					   wItems = wItems + 1;
					break;

				 case 1:
					if (prototype->Class == ITEM_CLASS_TRADE_GOODS)
					   wTGoods = wTGoods + 1;
					else
					   wItems = wItems + 1;
					break;

				 case 2:
					if (prototype->Class == ITEM_CLASS_TRADE_GOODS)
					   gTGoods = gTGoods + 1;
					else
					   gItems = gItems + 1;
					break;

				 case 3:
					if (prototype->Class == ITEM_CLASS_TRADE_GOODS)
					   bTGoods = bTGoods + 1;
					else
					   bItems = bItems + 1;
					break;

				 case 4:
					if (prototype->Class == ITEM_CLASS_TRADE_GOODS)
					   pTGoods = pTGoods + 1;
					else
					   pItems = pItems + 1;
					break;
				}
			}
		}
	}
	// only insert a few at a time, so as not to peg the processor
	for (uint32 cnt = 1;cnt <= items;cnt++)
	{
		uint32 itemID = 0;
		while (itemID == 0)
		{
			uint32 choice = urand(1, 8);
			switch (choice)
			{
			case 1:
				{
					if ((purpleItems.size() > 0) && (pItems < pibin))
					{
						itemID = purpleItems[urand(0, purpleItems.size() - 1)];
						pItems = pItems + 1;
						break;
					}
				}
			case 2:
				{
					if ((blueItems.size() > 0) && (bItems < bibin))
					{
						 itemID = blueItems[urand(0, blueItems.size() - 1)];
						 bItems = bItems + 1;
						 break;
					}
				}
			case 3:
				{
					if ((greenItems.size() > 0) && (gItems < gibin))
					{
						 itemID = greenItems[urand(0, greenItems.size() - 1)];
						 gItems = gItems + 1;
						 break;
					}
				}
			case 4:
				{
					if ((whiteItems.size() > 0) && (wItems < wibin))
					{
						 itemID = whiteItems[urand(0, whiteItems.size() - 1)];
						 wItems = wItems + 1;
						 break;
					}
				}
			case 5:
				{
					if ((purpleTradeGoods.size() > 0) && (pTGoods < ptgbin))
					{
						 itemID = purpleTradeGoods[urand(0, purpleTradeGoods.size() - 1)];
						 pTGoods = pTGoods + 1;
						 break;
					}
				}
			case 6:
				{
					if ((blueTradeGoods.size() > 0) && (bTGoods < btgbin))
					{
						 itemID = blueTradeGoods[urand(0, blueTradeGoods.size() - 1)];
						 bTGoods = bTGoods + 1;
						 break;
					}
				}
			case 7:
				{
					if ((greenTradeGoods.size() > 0) && (gTGoods < gtgbin))
					{
						 itemID = greenTradeGoods[urand(0, greenTradeGoods.size() - 1)];
						 gTGoods = gTGoods + 1;
						 break;
					}
				}
			case 8:
				{
					if ((whiteTradeGoods.size() > 0) && (wTGoods < wtgbin))
					{
						 itemID = whiteTradeGoods[urand(0, whiteTradeGoods.size() - 1)];
						 wTGoods = wTGoods + 1;
						 break;
					}
				}
			default:
				{
					break;
				}
			}
		}

		ItemPrototype const* prototype = objmgr.GetItemPrototype(itemID);
		if (prototype == NULL)
		{
		 sLog.outString("AuctionHouseBot: Huh?!?! prototype == NULL");
		 continue;
		}

		Item* item = Item::CreateItem(itemID, 1, AHBplayer);
		item->AddToUpdateQueueOf(AHBplayer);
		if (item == NULL)
		{
			sLog.outString("AuctionHouseBot: Item::CreateItem() returned NULL");
			break;
		}

		uint32 randomPropertyId = Item::GenerateItemRandomPropertyId(itemID);
		if (randomPropertyId != 0)
		 item->SetItemRandomProperties(randomPropertyId);

		uint32 buyoutPrice;
		uint32 bidPrice = 0;
		uint32 stackCount = urand(1, item->GetMaxStackCount());

		switch (SellMethod)
		{
		case 0:
			buyoutPrice  = prototype->SellPrice * item->GetCount();
			break;
		case 1:
			buyoutPrice  = prototype->BuyPrice * item->GetCount();
			break;
		default:
			buyoutPrice = 0;
			break;
		}

		switch (prototype->Quality)
		{
		 case 1:
			if (config->GetMaxStack(AHB_WHITE) != 0)
			{
			   stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(AHB_WHITE)));
			}
			buyoutPrice *= urand(config->GetMinPrice(AHB_WHITE), config->GetMaxPrice(AHB_WHITE)) * stackCount;
			buyoutPrice /= 100;
			bidPrice = buyoutPrice * urand(config->GetMinBidPrice(AHB_WHITE), config->GetMaxBidPrice(AHB_WHITE));
			bidPrice /= 100;
			break;

		 case 2:
			if (config->GetMaxStack(AHB_GREEN) != 0)
			{
			   stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(AHB_GREEN)));
			}
			buyoutPrice *= urand(config->GetMinPrice(AHB_GREEN), config->GetMaxPrice(AHB_GREEN)) * stackCount;
			buyoutPrice /= 100;
			bidPrice = buyoutPrice * urand(config->GetMinBidPrice(AHB_GREEN), config->GetMaxBidPrice(AHB_GREEN));
			bidPrice /= 100;
			break;

		 case 3:
			if (config->GetMaxStack(AHB_BLUE) != 0)
			{
			   stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(AHB_BLUE)));
			}
			buyoutPrice *= urand(config->GetMinPrice(AHB_BLUE), config->GetMaxPrice(AHB_BLUE)) * stackCount;
			buyoutPrice /= 100;
			bidPrice = buyoutPrice * urand(config->GetMinBidPrice(AHB_BLUE), config->GetMaxBidPrice(AHB_BLUE));
			bidPrice /= 100;
			break;

		 case 4:
			if (config->GetMaxStack(AHB_PURPLE) != 0)
			{
			   stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(AHB_PURPLE)));
			}
			buyoutPrice *= urand(config->GetMinPrice(AHB_PURPLE), config->GetMaxPrice(AHB_PURPLE)) * stackCount;
			buyoutPrice /= 100;
			bidPrice = buyoutPrice * urand(config->GetMinBidPrice(AHB_PURPLE), config->GetMaxBidPrice(AHB_PURPLE));
			bidPrice /= 100;
			break;
		}

		item->SetCount(stackCount);

		AuctionEntry* auctionEntry = new AuctionEntry;
		auctionEntry->Id = objmgr.GenerateAuctionID();
		auctionEntry->auctioneer = 0;
		auctionEntry->item_guidlow = item->GetGUIDLow();
		auctionEntry->item_template = item->GetEntry();
		auctionEntry->owner = AHBplayer->GetGUIDLow();
		auctionEntry->startbid = bidPrice;
		auctionEntry->buyout = buyoutPrice;
		auctionEntry->bidder = 0;
		auctionEntry->bid = 0;
		auctionEntry->deposit = 0;
		auctionEntry->location = config->GetAHID();
		auctionEntry->time = (time_t) (urand(config->GetMinTime(), config->GetMaxTime()) * 60 * 60 + time(NULL));
		item->SaveToDB();
		item->RemoveFromUpdateQueueOf(AHBplayer);
		objmgr.AddAItem(item);
		auctionHouse->AddAuction(auctionEntry);

		CharacterDatabase.PExecute("INSERT INTO `auctionhouse` (`id`,"
								 "`auctioneerguid`,`itemguid`,`item_template`,"
								 "`itemowner`,`buyoutprice`,`time`,`buyguid`,"
								 "`lastbid`,`startbid`,`deposit`,`location`) "
								 "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', "
								 "'" I64FMTD "', '%u', '%u', '%u', '%u', '%u')",
								 auctionEntry->Id,
								 auctionEntry->auctioneer,
								 auctionEntry->item_guidlow,
								 auctionEntry->item_template,
								 auctionEntry->owner,
								 auctionEntry->buyout,
								 (uint64) auctionEntry->time,
								 auctionEntry->bidder,
								 auctionEntry->bid,
								 auctionEntry->startbid,
								 auctionEntry->deposit,
								 auctionEntry->location);
	}
}
Example #9
0
void WorldSession::HandleSellItemOpcode(WorldPacket& recv_data)
{
    DEBUG_LOG("WORLD: Received opcode CMSG_SELL_ITEM");

    ObjectGuid vendorGuid;
    ObjectGuid itemGuid;
    uint8 _count;

    recv_data >> vendorGuid;
    recv_data >> itemGuid;
    recv_data >> _count;

    // prevent possible overflow, as mangos uses uint32 for item count
    uint32 count = _count;

    if (!itemGuid)
        return;

    Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
    if (!pCreature)
    {
        DEBUG_LOG("WORLD: HandleSellItemOpcode - %s not found or you can't interact with him.", vendorGuid.GetString().c_str());
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, nullptr, itemGuid, 0);
        return;
    }

    Item* pItem = _player->GetItemByGuid(itemGuid);
    if (pItem)
    {
        // prevent sell not owner item
        if (_player->GetObjectGuid() != pItem->GetOwnerGuid())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return;
        }

        // prevent sell non empty bag by drag-and-drop at vendor's item list
        if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return;
        }

        // prevent sell currently looted item
        if (_player->GetLootGuid() == pItem->GetObjectGuid())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return;
        }

        // special case at auto sell (sell all)
        if (count == 0)
        {
            count = pItem->GetCount();
        }
        else
        {
            // prevent sell more items that exist in stack (possible only not from client)
            if (count > pItem->GetCount())
            {
                _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
                return;
            }
        }

        ItemPrototype const* pProto = pItem->GetProto();
        if (pProto)
        {
            if (pProto->SellPrice > 0)
            {
                if (count < pItem->GetCount())              // need split items
                {
                    Item* pNewItem = pItem->CloneItem(count, _player);
                    if (!pNewItem)
                    {
                        sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
                        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
                        return;
                    }

                    pItem->SetCount(pItem->GetCount() - count);
                    _player->ItemRemovedQuestCheck(pItem->GetEntry(), count);
                    if (_player->IsInWorld())
                        pItem->SendCreateUpdateToPlayer(_player);
                    pItem->SetState(ITEM_CHANGED, _player);

                    _player->AddItemToBuyBackSlot(pNewItem);
                    if (_player->IsInWorld())
                        pNewItem->SendCreateUpdateToPlayer(_player);
                }
                else
                {
                    _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
                    _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
                    pItem->RemoveFromUpdateQueueOf(_player);
                    _player->AddItemToBuyBackSlot(pItem);
                }

                uint32 money = pProto->SellPrice * count;

                _player->ModifyMoney(money);
            }
            else
                _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return;
        }
    }
    _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemGuid, 0);
    return;
}
Example #10
0
void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
{
	if(!_player->IsInWorld()) return;
//	uint8 slot = 0;
	uint32 itemid = 0;
	uint32 amt = 1;
	uint8 lootSlot = 0;
	uint8 error = 0;
	SlotResult slotresult;

	Item *add;
	Loot *pLoot = NULL;

	if(_player->isCasting())
		_player->InterruptSpell();
	GameObject * pGO = NULL;
	Creature * pCreature = NULL;

	if(UINT32_LOPART(GUID_HIPART(GetPlayer()->GetLootGUID())) == HIGHGUID_UNIT)
	{
		pCreature = _player->GetMapMgr()->GetCreature((uint32)GetPlayer()->GetLootGUID());
		if (!pCreature)return;
		pLoot=&pCreature->loot;	
	}
	else if(UINT32_LOPART(GUID_HIPART(_player->GetLootGUID())) == HIGHGUID_GAMEOBJECT)
	{
		pGO = _player->GetMapMgr()->GetGameObject((uint32)GetPlayer()->GetLootGUID());
		if(!pGO)return;
		pLoot=&pGO->loot;
	}else if( (UINT32_LOPART(GUID_HIPART(_player->GetLootGUID())) == HIGHGUID_ITEM) )
	{
		Item *pItem = _player->GetItemInterface()->GetItemByGUID(_player->GetLootGUID());
		if(!pItem)
			return;
		pLoot = pItem->loot;
	}

	if(!pLoot) return;

	recv_data >> lootSlot;
	if (lootSlot >= pLoot->items.size())
	{
		sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %d)",
						GetPlayer()->GetName(), lootSlot, pLoot->items.size());
		return;
	}

	amt = pLoot->items.at(lootSlot).iItemsCount;

	if (!amt)//Test for party loot
	{  
		GetPlayer()->GetItemInterface()->BuildInventoryChangeError(NULL, NULL,INV_ERR_ALREADY_LOOTED);
		return;
	} 
	itemid = pLoot->items.at(lootSlot).item.itemid;
	ItemPrototype* it = ItemPrototypeStorage.LookupEntry(itemid);

	if((error = _player->GetItemInterface()->CanReceiveItem(it, 1)))
	{
		_player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, error);
		return;
	}

	if(pGO)
		CALL_GO_SCRIPT_EVENT(pGO, OnLootTaken)(_player, it);
	else if(pCreature)
		CALL_SCRIPT_EVENT(pCreature, OnLootTaken)(_player, it);

	add = GetPlayer()->GetItemInterface()->FindItemLessMax(itemid, amt, false);
	sHookInterface.OnLoot(_player, pCreature, 0, itemid);
	if (!add)
	{
		slotresult = GetPlayer()->GetItemInterface()->FindFreeInventorySlot(it);
		if(!slotresult.Result)
		{
			GetPlayer()->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_INVENTORY_FULL);
			return;
		}
	
		sLog.outDebug("AutoLootItem MISC");
		Item *item = objmgr.CreateItem( itemid, GetPlayer());
	   
		item->SetUInt32Value(ITEM_FIELD_STACK_COUNT,amt);
		uint32 rndprop=pLoot->items.at(lootSlot).iRandomProperty;
		if(rndprop)
			item->SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID,rndprop);
		item->ApplyRandomProperties();

		GetPlayer()->GetItemInterface()->SafeAddItem(item,slotresult.ContainerSlot, slotresult.Slot);
		
		if (it->Class == 12)		// Quest item
			sQuestMgr.OnPlayerItemPickup(GetPlayer(),item);
	}
	else 
	{	
		add->SetCount(add->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + amt);
		add->m_isDirty = true;
		if (it->Class == 12)		// Quest item
			sQuestMgr.OnPlayerItemPickup(GetPlayer(),add);
	}

	pLoot->items.at(lootSlot).iItemsCount=0;
	// this gets sent to all looters
	WorldPacket data(1);
	data.SetOpcode(SMSG_LOOT_REMOVED);
	data << lootSlot;
	Player * plr;
	for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); ++itr)
	{
		if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
			plr->GetSession()->SendPacket(&data);
	}

    WorldPacket idata;
    if(it->Class == ITEM_CLASS_QUEST)
    {
        uint32 pcount = _player->GetItemInterface()->GetItemCount(it->ItemId, true);
		BuildItemPushResult(&idata, _player->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(lootSlot).iRandomProperty,0xFF,0,0xFFFFFFFF,pcount);
    }
    else BuildItemPushResult(&idata, _player->GetGUID(), ITEM_PUSH_TYPE_LOOT, amt, itemid, pLoot->items.at(lootSlot).iRandomProperty);

	if(_player->InGroup())
		_player->GetGroup()->SendPacketToAll(&idata);
	else
		SendPacket(&idata);
}
Example #11
0
void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet)
{
    TC_LOG_DEBUG("network", "WORLD: Received CMSG_SELL_ITEM: Vendor %s, Item %s, Amount: %u",
        packet.VendorGUID.ToString().c_str(), packet.ItemGUID.ToString().c_str(), packet.Amount);

    if (packet.ItemGUID.IsEmpty())
        return;

    Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(packet.VendorGUID, UNIT_NPC_FLAG_VENDOR);
    if (!creature)
    {
        TC_LOG_DEBUG("network", "WORLD: HandleSellItemOpcode - %s not found or you can not interact with him.", packet.VendorGUID.ToString().c_str());
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, nullptr, packet.ItemGUID);
        return;
    }

    // remove fake death
    if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
        GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

    Item* pItem = _player->GetItemByGuid(packet.ItemGUID);
    if (pItem)
    {
        // prevent sell not owner item
        if (_player->GetGUID() != pItem->GetOwnerGUID())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
            return;
        }

        // prevent sell non empty bag by drag-and-drop at vendor's item list
        if (pItem->IsNotEmptyBag())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
            return;
        }

        // prevent sell currently looted item
        if (_player->GetLootGUID() == pItem->GetGUID())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
            return;
        }

        // prevent selling item for sellprice when the item is still refundable
        // this probably happens when right clicking a refundable item, the client sends both
        // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified)
        if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE))
            return; // Therefore, no feedback to client

        // special case at auto sell (sell all)
        if (packet.Amount == 0)
            packet.Amount = pItem->GetCount();
        else
        {
            // prevent sell more items that exist in stack (possible only not from client)
            if (packet.Amount > pItem->GetCount())
            {
                _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
                return;
            }
        }

        ItemTemplate const* pProto = pItem->GetTemplate();
        if (pProto)
        {
            if (pProto->GetSellPrice() > 0)
            {
                if (packet.Amount < pItem->GetCount())               // need split items
                {
                    Item* pNewItem = pItem->CloneItem(packet.Amount, _player);
                    if (!pNewItem)
                    {
                        TC_LOG_ERROR("network", "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), packet.Amount);
                        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
                        return;
                    }

                    pItem->SetCount(pItem->GetCount() - packet.Amount);
                    _player->ItemRemovedQuestCheck(pItem->GetEntry(), packet.Amount);
                    if (_player->IsInWorld())
                        pItem->SendUpdateToPlayer(_player);
                    pItem->SetState(ITEM_CHANGED, _player);

                    _player->AddItemToBuyBackSlot(pNewItem);
                    if (_player->IsInWorld())
                        pNewItem->SendUpdateToPlayer(_player);
                }
                else
                {
                    _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
                    _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
                    pItem->RemoveFromUpdateQueueOf(_player);
                    _player->AddItemToBuyBackSlot(pItem);
                }

                uint32 money = pProto->GetSellPrice() * packet.Amount;
                _player->ModifyMoney(money);
                _player->UpdateCriteria(CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
            }
            else
                _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
            return;
        }
    }
    _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, packet.ItemGUID);
    return;
}
Example #12
0
void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
{
	if(!_player->IsInWorld()) return;
	CHECK_PACKET_SIZE(recv_data, 17);
	sLog.outDetail( "WORLD: Recieved CMSG_SELL_ITEM" );
	if(!GetPlayer())
		return;

	uint64 vendorguid=0, itemguid=0;
	int8 amount=0;
	//uint8 slot = INVENTORY_NO_SLOT_AVAILABLE;
	//uint8 bagslot = INVENTORY_NO_SLOT_AVAILABLE;
	//int check = 0;

	recv_data >> vendorguid;
	recv_data >> itemguid;
	recv_data >> amount;

	if(_player->isCasting())
		_player->InterruptSpell();

	// Check if item exists
	if(!itemguid)
	{
		SendSellItem(vendorguid, itemguid, 1);
		return;
	}

	Creature *unit = _player->GetMapMgr()->GetCreature(vendorguid);
	// Check if Vendor exists
	if (unit == NULL)
	{
		SendSellItem(vendorguid, itemguid, 3);
		return;
	}

	Item* item = _player->GetItemInterface()->GetItemByGUID(itemguid);
	if(!item)
	{
		SendSellItem(vendorguid, itemguid, 1);
		return; //our player doesn't have this item
	}

	ItemPrototype *it = item->GetProto();
	if(!it)
	{
		SendSellItem(vendorguid, itemguid, 2);
		return; //our player doesn't have this item
	}

	// Check if item can be sold
	if (it->SellPrice == 0)
	{
		SendSellItem(vendorguid, itemguid, 2);
		return;
	}
	
	uint32 stackcount = item->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
	uint32 quantity = 0;

	if (amount != 0)
	{
		quantity = amount;
	}
	else
	{
		quantity = stackcount; //allitems
	}

	if(quantity > stackcount) quantity = stackcount; //make sure we don't over do it
	
	uint32 price = GetSellPriceForItem(it, quantity);

	_player->ModUInt32Value(PLAYER_FIELD_COINAGE,price);
 
	if(quantity < stackcount)
	{
		item->SetCount(stackcount - quantity);
		item->m_isDirty = true;
	}
	else
	{
		//removing the item from the char's inventory
		item = _player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(itemguid, false); //again to remove item from slot
		if(item)
		{
			_player->GetItemInterface()->AddBuyBackItem(item,(it->SellPrice) * quantity);
		}
	}

	WorldPacket data(SMSG_SELL_ITEM, 12);
	data << vendorguid << itemguid << uint8(0); 
	SendPacket( &data );

	sLog.outDetail( "WORLD: Sent SMSG_SELL_ITEM" );
}
Example #13
0
void WorldSession::HandleBuyBackOpcode( WorldPacket & recv_data )
{
	if(!_player->IsInWorld()) return;
	CHECK_PACKET_SIZE(recv_data, 8);
	WorldPacket data;
	uint64 guid;
	int32 stuff;
	Item* add ;
	bool result;
	uint8 error;

	sLog.outDetail( "WORLD: Recieved CMSG_BUYBACK_ITEM" );

	recv_data >> guid >> stuff;
	stuff -= 74;

	// prevent crashes
	if( stuff > MAX_BUYBACK_SLOT)
		return;

	//what a magical number 69???
	Item *it = _player->GetItemInterface()->GetBuyBack(stuff);
	if (it)
	{
		// Find free slot and break if inv full
		uint32 amount = it->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
		uint32 itemid = it->GetUInt32Value(OBJECT_FIELD_ENTRY);
	  
		add = _player->GetItemInterface()->FindItemLessMax(itemid,amount, false);
	 
		   uint32 FreeSlots = _player->GetItemInterface()->CalculateFreeSlots(it->GetProto());
		if ((FreeSlots == 0) && (!add))
		{
			_player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_INVENTORY_FULL);
			return;
		}
		
		// Check for gold
		int32 cost =_player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + stuff);
		if((int32)_player->GetUInt32Value(PLAYER_FIELD_COINAGE) < cost )
		{
			WorldPacket data(SMSG_BUY_FAILED, 12);
			data << uint64(guid);
			data << uint32(itemid);
			data << uint8(2); //not enough money
			SendPacket( &data );
			return;
		}
		// Check for item uniqueness
		if ((error = _player->GetItemInterface()->CanReceiveItem(it->GetProto(), amount)))
		{
			_player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, error);
			return;
		}
		_player->ModUInt32Value( PLAYER_FIELD_COINAGE , -cost);
		if (!add)
		{
			result = _player->GetItemInterface()->AddItemToFreeSlot(it);
			if(!result)
			{
				printf("HandleBuyBack: Error while adding item to free slot");
			}
		}
		else
		{
			add->SetCount(add->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + amount);
			add->m_isDirty = true;
		}

		data.Initialize( SMSG_BUY_ITEM );
		data << uint64(guid);
		data << uint32(itemid) << uint32(amount);
		SendPacket( &data );
	}
	_player->GetItemInterface()->RemoveBuyBackItem(stuff);
}
Example #14
0
void LootRoll::Finalize()
{
	if( !mLootLock.AttemptAcquire() ) // only one finalization, please. players on different maps can roll, too, so this is needed.
	{
		sEventMgr.RemoveEvents(this);
		return;
	}

	sEventMgr.RemoveEvents(this);

	// this we will have to finalize with groups types.. for now
	// we'll just assume need before greed. person with highest roll
	// in need gets the item.

	uint32 highest = 0;
	int8 hightype = -1;
	uint64 player = 0;

	WorldPacket data(34);

	for(std::map<uint32, uint32>::iterator itr = m_NeedRolls.begin(); itr != m_NeedRolls.end(); itr++)
	{
		if(itr->second > highest)
		{
			highest = itr->second;
			player = itr->first;
			hightype = NEED;
		}
	}

	if(!highest)
	{
		for(std::map<uint32, uint32>::iterator itr = m_GreedRolls.begin(); itr != m_GreedRolls.end(); itr++)
		{
			if(itr->second > highest)
			{
				highest = itr->second;
				player = itr->first;
				hightype = GREED;
			}
		}

		for(std::map<uint32, uint32>::iterator itr = m_DisenchantRolls.begin(); itr != m_DisenchantRolls.end(); itr++)
		{
			if(itr->second > highest)
			{
				highest = itr->second;
				player = itr->first;
				hightype = DISENCHANT;
			}
		}
	}


	Loot * pLoot = 0;
	uint32 guidtype = GET_TYPE_FROM_GUID(_guid);
	if( guidtype == HIGHGUID_TYPE_CREATURE )
	{
		Creature* pc = _mgr->GetCreature(GET_LOWGUID_PART(_guid));
		if(pc) pLoot = &pc->m_loot;
	}
	else if( guidtype == HIGHGUID_TYPE_GAMEOBJECT )
	{
		GameObject* go = _mgr->GetGameObject(GET_LOWGUID_PART(_guid));
		if(go) pLoot = &go->m_loot;
	}

	if(!pLoot)
	{
		delete this;
		return;
	}

	if(_slotid >= pLoot->items.size())
	{
		delete this;
		return;
	}

	pLoot->items.at(_slotid).roll = NULLROLL;

	uint32 itemid = pLoot->items.at(_slotid).item.itemproto->ItemId;
	uint32 amt = pLoot->items.at(_slotid).StackSize;
	if(!amt)
	{
		delete this;
		return;
	}

	Player* _player = (player) ? _mgr->GetPlayer((uint32)player) : NULLPLR;
	if(!player || !_player)
	{
		/* all passed */
		data.Initialize(SMSG_LOOT_ALL_PASSED);
		data << _guid << _groupcount << _itemid << _randomsuffixid << _randompropertyid;
		set<uint32>::iterator pitr = m_passRolls.begin();
		while(_player == NULL && pitr != m_passRolls.end())
		{
			_player = _mgr->GetPlayer( (*(pitr)) );
			++pitr;
		}

		if( _player != NULL )
		{
			if(_player->InGroup())
				_player->GetGroup()->SendPacketToAll(&data);
			else
				_player->GetSession()->SendPacket(&data);
		}

		/* item can now be looted by anyone :) */
		pLoot->items.at(_slotid).passed = true;
		delete this;
		return;
	}

	pLoot->items.at(_slotid).roll = 0;
	data.Initialize(SMSG_LOOT_ROLL_WON);
	data << _guid << _slotid << _itemid << _randomsuffixid << _randompropertyid;
	data << _player->GetGUID() << uint8(highest) << uint8(hightype);
	if(_player->InGroup())
		_player->GetGroup()->SendPacketToAll(&data);
	else
		_player->GetSession()->SendPacket(&data);

	if(hightype == DISENCHANT)
	{
		//generate Disenchantingloot
		Item * pItem = objmgr.CreateItem( itemid, _player);
		lootmgr.FillItemLoot(&pItem->m_loot, pItem->GetEntry(), _player->GetTeam());

		//add loot
		for(std::vector<__LootItem>::iterator iter=pItem->m_loot.items.begin();iter != pItem->m_loot.items.end();iter++)
		{
			itemid =iter->item.itemproto->ItemId;
			Item * Titem = objmgr.CreateItem( itemid, _player);
			if( Titem == NULLITEM )
				continue;
			if( !_player->GetItemInterface()->AddItemToFreeSlot(Titem) )
			{
				_player->GetSession()->SendNotification("No free slots were found in your inventory, item has been mailed.");
				sMailSystem.DeliverMessage(MAILTYPE_NORMAL, _player->GetGUID(), _player->GetGUID(), "Loot Roll", "Here is your reward.", 0, 0, itemid, 1, true);
			}
			Titem->DeleteMe();
			Titem = NULLITEM;
		}
		pItem->DeleteMe();
		pItem = NULLITEM;

		// Set a looter, doesn't matter who.
		pLoot->items.at(_slotid).has_looted.insert(_player->GetLowGUID());

		//Send "finish" packet
		data.Initialize(SMSG_LOOT_REMOVED);
		data << uint8(_slotid);
		Player* plr;
		for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); itr++)
		{
			if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
				plr->GetSession()->SendPacket(&data);
		}

		delete this;	//end here and skip the rest
		return;
	}

	ItemPrototype* it = ItemPrototypeStorage.LookupEntry(itemid);

	int8 error;
	if((error = _player->GetItemInterface()->CanReceiveItem(it, 1, NULL)))
	{
		_player->GetItemInterface()->BuildInventoryChangeError(NULLITEM, NULLITEM, error);
		return;
	}

	Item* add = _player->GetItemInterface()->FindItemLessMax(itemid, amt, false);

	if (!add)
	{
		SlotResult slotresult = _player->GetItemInterface()->FindFreeInventorySlot(it);
		if(!slotresult.Result)
		{
			_player->GetSession()->SendNotification("No free slots were found in your inventory, item has been mailed.");
			sMailSystem.DeliverMessage(MAILTYPE_NORMAL, _player->GetGUID(), _player->GetGUID(), "Loot Roll", "Here is your reward.", 0, 0, it->ItemId, 1, true);
			data.Initialize(SMSG_LOOT_REMOVED);
			data << uint8(_slotid);
			Player* plr;
			for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); itr++)
			{
				if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
					plr->GetSession()->SendPacket(&data);
			}
			delete this;
			return;
		}

		DEBUG_LOG("HandleAutostoreItem","AutoLootItem %u",itemid);
		Item* item = objmgr.CreateItem( itemid, _player);

		item->SetUInt32Value(ITEM_FIELD_STACK_COUNT,amt);
		if(pLoot->items.at(_slotid).iRandomProperty!=NULL)
		{
			item->SetRandomProperty(pLoot->items.at(_slotid).iRandomProperty->ID);
			item->ApplyRandomProperties(false);
		}
		else if(pLoot->items.at(_slotid).iRandomSuffix != NULL)
		{
			item->SetRandomSuffix(pLoot->items.at(_slotid).iRandomSuffix->id);
			item->ApplyRandomProperties(false);
		}


		if( _player->GetItemInterface()->SafeAddItem(item,slotresult.ContainerSlot, slotresult.Slot) )
		{
			_player->GetSession()->SendItemPushResult(item,false,true,true,true,slotresult.ContainerSlot,slotresult.Slot,1);
			sQuestMgr.OnPlayerItemPickup(_player,item);
		}
		else
		{
			item->DeleteMe();
			item = NULLITEM;
		}
	}
	else
	{
		add->SetCount(add->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + amt);
		add->m_isDirty = true;
		sQuestMgr.OnPlayerItemPickup(_player,add);
		_player->GetSession()->SendItemPushResult(add, false, true, true, false, _player->GetItemInterface()->GetBagSlotByGuid(add->GetGUID()), 0xFFFFFFFF, 1);
	}

	// Set a looter, doesn't matter who.
	pLoot->items.at(_slotid).has_looted.insert(_player->GetLowGUID());

	// this gets sent to all looters
	data.Initialize(SMSG_LOOT_REMOVED);
	data << uint8(_slotid);
	Player* plr;
	for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); itr++)
	{
		if((plr = _player->GetMapMgr()->GetPlayer(*itr)))
			plr->GetSession()->SendPacket(&data);
	}

	delete this;
}
Example #15
0
void WorldSession::HandleSellItemOpcode(WorldPacket& recv_data)
{
    DEBUG_LOG("WORLD: Received opcode CMSG_SELL_ITEM");

    ObjectGuid vendorGuid;
    ObjectGuid itemGuid;
    uint8 _count;

    recv_data >> vendorGuid;
    recv_data >> itemGuid;
    recv_data >> _count;

    // prevent possible overflow, as mangos uses uint32 for item count
    uint32 count = _count;

    if (!itemGuid)
        return;

    Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
    if (!pCreature)
    {
        DEBUG_LOG("WORLD: HandleSellItemOpcode - %s not found or you can't interact with him.", vendorGuid.GetString().c_str());
        _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, nullptr, itemGuid, 0);
        return;
    }

    Item* pItem = _player->GetItemByGuid(itemGuid);

    if (!pItem)
        return;

    // prevent sell not owner item
    if (_player->GetObjectGuid() != pItem->GetOwnerGuid())
    {
        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
        return;
    }

    // prevent sell non empty bag by drag-and-drop at vendor's item list
    if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
    {
        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
        return;
    }

    // prevent sell currently looted item
    if (_player->GetLootGuid() == pItem->GetObjectGuid())
    {
        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
        return;
    }

    // special case at auto sell (sell all)
    if (count == 0)
    {
        count = pItem->GetCount();
    }
    else
    {
        // prevent sell more items that exist in stack (possible only not from client)
        if (count > pItem->GetCount())
        {
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return;
        }
    }

    ItemPrototype const* pProto = pItem->GetProto();

    if (!pProto)
    {
        _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemGuid, 0);
        return;
    }

    if (pProto->SellPrice == 0)
    {
        _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
        return;
    }

    uint32 money = pProto->SellPrice * count;

    for (auto i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
    {
        auto const &spell = pProto->Spells[i];

        // if spell charges for this item are negative, it means that the item should be destroyed once the charges are consumed.
        // it also means that the value of this item is relative to how many charges are remaining.
        if (spell.SpellId != 0 && spell.SpellCharges < 0)
        {
            auto const multiplier = static_cast<float>(pItem->GetSpellCharges(i)) / spell.SpellCharges;
            money *= multiplier;
            break;
        }
    }

    if (count < pItem->GetCount())              // need split items
    {
        Item* pNewItem = pItem->CloneItem(count, _player);
        if (!pNewItem)
        {
            sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
            _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return;
        }

        pItem->SetCount(pItem->GetCount() - count);
        _player->ItemRemovedQuestCheck(pItem->GetEntry(), count);
        if (_player->IsInWorld())
            pItem->SendCreateUpdateToPlayer(_player);
        pItem->SetState(ITEM_CHANGED, _player);

        _player->AddItemToBuyBackSlot(pNewItem, money);
        if (_player->IsInWorld())
            pNewItem->SendCreateUpdateToPlayer(_player);
    }
    else
    {
        _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
        _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
        pItem->RemoveFromUpdateQueueOf(_player);
        _player->AddItemToBuyBackSlot(pItem, money);
    }

    _player->ModifyMoney(money);
}
Example #16
0
bool CPlayer::SellItemToMultiVendor(ObjectGuid itemGuid, uint8 _count)
{
    DEBUG_LOG("WORLD: SellItemToMultiVendor");

    // prevent possible overflow, as mangos uses uint32 for item count
    uint32 count = _count;

    uint32 entry;
    ObjectGuid guid;
    GetMultiVendor(entry, guid);

    if (!itemGuid)
        return false;

    Creature* pCreature = GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
    if (!pCreature)
    {
        DEBUG_LOG("WORLD: SellItemToMultiVendor - %s not found or you can't interact with him.", guid.GetString().c_str());
        SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemGuid, 0);
        return false;
    }

    // remove fake death
    if (hasUnitState(UNIT_STAT_DIED))
        RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

    Item* pItem = GetItemByGuid(itemGuid);
    if (pItem)
    {
        // prevent sell not owner item
        if (GetObjectGuid() != pItem->GetOwnerGuid())
        {
            SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return false;
        }

        // prevent sell non empty bag by drag-and-drop at vendor's item list
        if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
        {
            SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return false;
        }

        // prevent sell currently looted item
        if (GetLootGuid() == pItem->GetObjectGuid())
        {
            SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
            return false;
        }

        // special case at auto sell (sell all)
        if (count == 0)
        {
            count = pItem->GetCount();
        }
        else
        {
            // prevent sell more items that exist in stack (possible only not from client)
            if (count > pItem->GetCount())
            {
                SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
                return false;
            }
        }

        ItemPrototype const* pProto = pItem->GetProto();
        if (pProto)
        {
            if (pProto->SellPrice > 0)
            {
                if (count < pItem->GetCount())              // need split items
                {
                    Item* pNewItem = pItem->CloneItem(count, ToPlayer());
                    if (!pNewItem)
                    {
                        sLog.outError("WORLD: SellItemToMultiVendor - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
                        SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);
                        return false;
                    }

                    pItem->SetCount(pItem->GetCount() - count);
                    ItemRemovedQuestCheck(pItem->GetEntry(), count);
                    if (IsInWorld())
                        pItem->SendCreateUpdateToPlayer(ToPlayer());
                    pItem->SetState(ITEM_CHANGED, ToPlayer());

                    AddItemToBuyBackSlot(pNewItem);
                    if (IsInWorld())
                        pNewItem->SendCreateUpdateToPlayer(ToPlayer());
                }
                else
                {
                    ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
                    RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
                    pItem->RemoveFromUpdateQueueOf(ToPlayer());
                    AddItemToBuyBackSlot(pItem);
                }

                uint32 money = pProto->SellPrice * count;

                ModifyMoney(money);
            }
            else
                SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0);

            return true;
        }
    }

    SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemGuid, 0);
    return false;
}