void WorldSession::HandleCancelTempItemEnchantmentOpcode(WorldPacket& recvData)
{
    IC_LOG_DEBUG("network", "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");

    uint32 eslot;

    recvData >> eslot;

    // apply only to equipped item
    if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, eslot))
        return;

    Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot);

    if (!item)
        return;

    if (!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
        return;

    GetPlayer()->ApplyEnchantment(item, TEMP_ENCHANTMENT_SLOT, false);
    item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
}
Exemple #2
0
void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data)
{
    sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");

    uint32 slot;

    recv_data >> slot;

    // apply only to equipped item
    if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot))
        return;

    Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);

    if (!item)
        return;

    if (!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
        return;

    GetPlayer()->ApplyEnchantment(item, TEMP_ENCHANTMENT_SLOT, false);
    item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
}
//this function inserts to WorldPacket auction's data
bool AuctionEntry::BuildAuctionInfo(WorldPacket & data) const {
	Item *pItem = sAuctionMgr->GetAItem(item_guidlow);
	if (!pItem) {
		sLog->outError("auction to item, that doesn't exist !!!!");
		return false;
	}
	data << uint32(Id);
	data << uint32(pItem->GetEntry());

	for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i) {
		data << uint32(pItem->GetEnchantmentId(EnchantmentSlot(i)));
		data << uint32(pItem->GetEnchantmentDuration(EnchantmentSlot(i)));
		data << uint32(pItem->GetEnchantmentCharges(EnchantmentSlot(i)));
	}

	for (uint8 i = 0; i < 2; ++i) {
		data << uint32(0);
		data << uint32(0);
		data << uint32(0);
	}

	data << int32(pItem->GetItemRandomPropertyId()); //random item property id
	data << uint32(pItem->GetItemSuffixFactor()); //SuffixFactor
	data << uint32(pItem->GetCount()); //item->count
	data << uint32(pItem->GetSpellCharges()); //item->charge FFFFFFF
	data << uint32(0); //Unknown
	data << uint64(owner); //Auction->owner
	data << uint64(startbid); //Auction->startbid (not sure if useful)
	data << uint64(bid ? GetAuctionOutBid() : 0);
	//minimal outbid
	data << uint64(buyout); //auction->buyout
	data << uint32((expire_time - time(NULL)) * IN_MILLISECONDS); //time left
	data << uint64(bidder); //auction->bidder current
	data << uint64(bid); //current bid
	return true;
}
Exemple #4
0
void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
{
    sLog.outDebug("WORLD: CMSG_SOCKET_GEMS");

    CHECK_PACKET_SIZE(recv_data,8*4);

    uint64 guids[4];
    uint32 GemEnchants[3], OldEnchants[3];
    Item *Gems[3];
    bool SocketBonusActivated, SocketBonusToBeActivated;

    for(int i = 0; i < 4; i++)
        recv_data >> guids[i];

    if(!guids[0])
        return;

    //cheat -> tried to socket same gem multiple times
    if((guids[1] && (guids[1] == guids[2] || guids[1] == guids[3])) || (guids[2] && (guids[2] == guids[3])))
        return;

    Item *itemTarget = _player->GetItemByGuid(guids[0]);
    if(!itemTarget)                                         //missing item to socket
        return;

    //this slot is excepted when applying / removing meta gem bonus
    uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT;

    for(int i = 0; i < 3; i++)
        Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL;

    GemPropertiesEntry const *GemProps[3];
    for(int i = 0; i < 3; ++i)                              //get geminfo from dbc storage
    {
        GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL;
    }

    for(int i = 0; i < 3; ++i)                              //check for hack maybe
    {
        // tried to put gem in socket where no socket exists / tried to put normal gem in meta socket
        // tried to put meta gem in normal socket
        if( GemProps[i] && ( !itemTarget->GetProto()->Socket[i].Color ||
            itemTarget->GetProto()->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META ||
            itemTarget->GetProto()->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META ) )
            return;
    }

    for(int i = 0; i < 3; ++i)                              //get new and old enchantments
    {
        GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
        OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i));
    }

    // check unique-equipped conditions
    for(int i = 0; i < 3; ++i)
    {
        if (Gems[i] && (Gems[i]->GetProto()->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED))
        {
            // for equipped item check all equipment for duplicate equipped gems
            if(itemTarget->IsEquipped())
            {
                if(GetPlayer()->GetItemOrItemWithGemEquipped(Gems[i]->GetEntry()))
                {
                    _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE, itemTarget, NULL );
                    return;
                }
            }

            // continue check for case when attempt add 2 similar unique equipped gems in one item.
            for (int j = 0; j < 3; ++j)
            {
                if ((i != j) && (Gems[j]) && (Gems[i]->GetProto()->ItemId == Gems[j]->GetProto()->ItemId))
                {
                    _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
                    return;
                }
            }
            for (int j = 0; j < 3; ++j)
            {
                if (OldEnchants[j])
                {
                    SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]);
                    if(!enchantEntry)
                        continue;

                    if ((enchantEntry->GemID == Gems[i]->GetProto()->ItemId) && (i != j))
                    {
                        _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
                        return;
                    }
                }
            }
        }
    }

    SocketBonusActivated = itemTarget->GemsFitSockets();    //save state of socketbonus
    _player->ToggleMetaGemsActive(slot, false);             //turn off all metagems (except for the target item)

    //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met

    //remove ALL enchants
    for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
        _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false);

    for(int i = 0; i < 3; ++i)
    {
        if(GemEnchants[i])
        {
            itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0);
            if(Item* guidItem = _player->GetItemByGuid(guids[i + 1]))
                _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true );
        }
    }

    for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
        _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true);

    SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
    if(SocketBonusActivated ^ SocketBonusToBeActivated)     //if there was a change...
    {
        _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false);
        itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0);
        _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true);
        //it is not displayed, client has an inbuilt system to determine if the bonus is activated
    }

    _player->ToggleMetaGemsActive(slot, true);              //turn on all metagems (except for target item)
}
void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
{
    TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData();

    ByteBuffer itemData(7*2 + 7*4 + 3*4 + 3*4 + 1);

    uint8 count = 0;
    for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
        if (view_trade->GetItem(TradeSlots(i)))
            ++count;

    WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 4*6 + 8 + 1 + 3 + count * 70);
    data << uint32(0);                                      // this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
    data << uint32(0);                                      // unk 2
    data << uint64(view_trade->GetMoney());                 // trader gold
    data << uint32(view_trade->GetSpell());                 // spell casted on lowest slot item
    data << uint32(TRADE_SLOT_COUNT);                       // trade slots count/number?, = next field in most cases
    data << uint32(0);                                      // unk 5
    data << uint8(trader_data);                             // 1 means traders data, 0 means own
    data << uint32(TRADE_SLOT_COUNT);                       // trade slots count/number?, = prev field in most cases
    data.WriteBits(count, 22);

    for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
    {
        Item* item = view_trade->GetItem(TradeSlots(i));
        if (!item)
            continue;

        ObjectGuid giftCreatorGuid = item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR);
        ObjectGuid creatorGuid = item->GetUInt64Value(ITEM_FIELD_CREATOR);

        data.WriteBit(giftCreatorGuid[7]);
        data.WriteBit(giftCreatorGuid[1]);
        bool notWrapped = data.WriteBit(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED));
        data.WriteBit(giftCreatorGuid[3]);

        if (notWrapped)
        {
            data.WriteBit(creatorGuid[7]);
            data.WriteBit(creatorGuid[1]);
            data.WriteBit(creatorGuid[4]);
            data.WriteBit(creatorGuid[6]);
            data.WriteBit(creatorGuid[2]);
            data.WriteBit(creatorGuid[3]);
            data.WriteBit(creatorGuid[5]);
            data.WriteBit(item->GetTemplate()->LockID != 0);
            data.WriteBit(creatorGuid[0]);

            itemData.WriteByteSeq(creatorGuid[1]);

            itemData << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
            for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS /*3*/; ++enchant_slot)
                itemData << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
            itemData << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));

            itemData.WriteByteSeq(creatorGuid[6]);
            itemData.WriteByteSeq(creatorGuid[2]);
            itemData.WriteByteSeq(creatorGuid[7]);
            itemData.WriteByteSeq(creatorGuid[4]);

            itemData << uint32(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT));
            itemData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
            itemData << uint32(item->GetItemRandomPropertyId());

            itemData.WriteByteSeq(creatorGuid[3]);

            itemData << uint32(0); // unk7

            itemData.WriteByteSeq(creatorGuid[0]);

            itemData << uint32(item->GetSpellCharges());
            itemData << uint32(item->GetItemSuffixFactor());

            itemData.WriteByteSeq(creatorGuid[5]);
        }

        data.WriteBit(giftCreatorGuid[6]);
        data.WriteBit(giftCreatorGuid[4]);
        data.WriteBit(giftCreatorGuid[2]);
        data.WriteBit(giftCreatorGuid[0]);
        data.WriteBit(giftCreatorGuid[5]);

        itemData.WriteByteSeq(giftCreatorGuid[6]);
        itemData.WriteByteSeq(giftCreatorGuid[1]);
        itemData.WriteByteSeq(giftCreatorGuid[7]);
        itemData.WriteByteSeq(giftCreatorGuid[4]);

        itemData << uint32(item->GetTemplate()->ItemId);

        itemData.WriteByteSeq(giftCreatorGuid[0]);

        itemData << uint32(item->GetCount());

        itemData.WriteByteSeq(giftCreatorGuid[5]);

        itemData << uint8(i);

        itemData.WriteByteSeq(giftCreatorGuid[2]);
        itemData.WriteByteSeq(giftCreatorGuid[3]);
    }

    data.FlushBits();
    data.append(itemData);

    SendPacket(&data);
}
    bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
    {
        int slot = -1;
        bool check_adjacent_slot = true;
        switch (action)
        {
        case -1: // Back
            ShowMainMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 1:
            Show1HWeaponMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 2:
            Show2HWeaponMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 3:
            ShowShieldMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 4:
            ShowHeadMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 5:
            ShowShouldersMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 6:
            ShowCloakMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 7:
            ShowChestMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 8:
            ShowBracerMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 9:
            ShowGlovesMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 10:
            ShowBeltMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 11:
            ShowLegsMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 12:
            ShowBootsMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 13:
            ShowRangedMenu(player, creature);
            break;
        case GOSSIP_ACTION_INFO_DEF + 14:
            ShowRingsMenu(player, creature);
            break;

        // 1H weapons
        case ENCHANT_WEP_BLADE_WARD:
        case ENCHANT_WEP_BLOOD_DRAINING:
        case ENCHANT_WEP_AGILITY_1H:
        case ENCHANT_WEP_SPIRIT:
        case ENCHANT_WEP_BERSERKING:
        case ENCHANT_WEP_ACCURACY:
        case ENCHANT_WEP_BLACK_MAGIC:
        case ENCHANT_WEP_BATTLEMASTER:
        case ENCHANT_WEP_ICEBREAKER:
        case ENCHANT_WEP_LIFEWARD:
        case ENCHANT_WEP_TITANGUARD:
        case ENCHANT_WEP_POTENCY:
        case ENCHANT_WEP_MONGOOSE:
        case ENCHANT_WEP_MIGHTY_SPELL_POWER:
        case ENCHANT_WEP_EXECUTIONER:
        case ENCHANT_WEP_TITANIUM_CHAIN:

        // 2H weapons
        // case ENCHANT_WEP_BERSERKING:
        // case ENCHANT_WEP_MONGOOSE:
        // case ENCHANT_WEP_EXECUTIONER:
        // case ENCHANT_WEP_TITANIUM_CHAIN:
        case ENCHANT_WEP_GREATER_SPELL_POWER:
        case ENCHANT_WEP_AGILITY_2H:
        case ENCHANT_WEP_MASSACRE:

        // Runeforging
        case ENCHANT_WEP_CINDERGLACIER:
        case ENCHANT_WEP_LICHBANE:
        case ENCHANT_WEP_RAZORICE:
        case ENCHANT_WEP_SPELLBREAKING:
        case ENCHANT_WEP_SPELLSHATTERING:
        case ENCHANT_WEP_SWORDBREAKING:
        case ENCHANT_WEP_SWORDSHATTERING:
        case ENCHANT_WEP_FALLEN_CRUSADER:
        case ENCHANT_WEP_NERUBIAN_CARAPACE:
        case ENCHANT_WEP_STONESKIN_GARGOYLE:
            slot = EQUIPMENT_SLOT_MAINHAND;
            break;

        // Shields
        case ENCHANT_SHIELD_DEFENSE:
        case ENCHANT_SHIELD_INTELLECT:
        case ENCHANT_SHIELD_RESILIENCE:
        case ENCHANT_SHIELD_TITANIUM_PLATING:
        case ENCHANT_SHIELD_MAJOR_STAMINA:
        case ENCHANT_SHIELD_TITANIUM_SPIKE:
            slot = EQUIPMENT_SLOT_OFFHAND;
            break;

        // Head
        case ENCHANT_HEAD_BLISSFUL_MENDING:
        case ENCHANT_HEAD_BURNING_MYSTERIES:
        case ENCHANT_HEAD_DOMINANCE:
        case ENCHANT_HEAD_SAVAGE_GLADIATOR:
        case ENCHANT_HEAD_STALWART_PROTECTOR:
        case ENCHANT_HEAD_TORMENT:
        case ENCHANT_HEAD_TRIUMPH:
            slot = EQUIPMENT_SLOT_HEAD;
            break;

        // Shoulders
        case ENCHANT_SHOULDER_MASTERS_AXE:
        case ENCHANT_SHOULDER_MASTERS_CRAG:
        case ENCHANT_SHOULDER_MASTERS_PINNACLE:
        case ENCHANT_SHOULDER_MASTERS_STORM:
        case ENCHANT_SHOULDER_GREATER_AXE:
        case ENCHANT_SHOULDER_GREATER_CRAG:
        case ENCHANT_SHOULDER_GREATER_GLADIATOR:
        case ENCHANT_SHOULDER_GREATER_PINNACLE:
        case ENCHANT_SHOULDER_GREATER_STORM:
        case ENCHANT_SHOULDER_DOMINANCE:
        case ENCHANT_SHOULDER_TRIUMPH:
            slot = EQUIPMENT_SLOT_SHOULDERS;
            break;

        // Cloak
        case ENCHANT_CLOAK_DARKGLOW_EMBROIDERY:
        case ENCHANT_CLOAK_SWORDGUARD_EMBROIDERY:
        case ENCHANT_CLOAK_FLEXWEAVE_UNDERLAY:
        case ENCHANT_CLOAK_LIGHTWEAVE_EMBROIDERY:
        case ENCHANT_CLOAK_SPRINGY_ARACHNOWEAVE:
        case ENCHANT_CLOAK_WISDOM:
        case ENCHANT_CLOAK_TITANWEAVE:
        case ENCHANT_CLOAK_SPELL_PIERCING:
        case ENCHANT_CLOAK_SHADOW_ARMOR:
        case ENCHANT_CLOAK_MIGHTY_ARMOR:
        case ENCHANT_CLOAK_MAJOR_AGILITY:
        case ENCHANT_CLOAK_GREATER_SPEED:
            slot = EQUIPMENT_SLOT_BACK;
            break;

        // Chest
        case ENCHANT_CHEST_EXCEPTIONAL_MANA:
        case ENCHANT_CHEST_GREATER_MANA_RESTO:
        case ENCHANT_CHEST_EXCEPTIONAL_RESILIENCE:
        case ENCHANT_CHEST_SUPER_HEALTH:
        case ENCHANT_CHEST_ALL_STATS:
            slot = EQUIPMENT_SLOT_CHEST;
            break;

        // Bracers
        case ENCHANT_BRACER_GREATER_ASSAULT:
        case ENCHANT_BRACER_EXCEPTIONAL_INTELLECT:
        case ENCHANT_BRACER_MAJOR_SPIRIT:
        case ENCHANT_BRACER_EXPERTISE:
        case ENCHANT_BRACER_GREATER_STATS:
        case ENCHANT_BRACER_SUPERIOR_SPELLPOWER:
        case ENCHANT_BRACER_MAJOR_STAMINA:
        case ENCHANT_BRACER_FUR_LINING_AP:
        case ENCHANT_BRACER_FUR_LINING_STAMINA:
        case ENCHANT_BRACER_FUR_LINING_SP:
        case ENCHANT_BRACER_ARCANE_RESIST:
        case ENCHANT_BRACER_NATURE_RESIST:
        case ENCHANT_BRACER_SHADOW_RESIST:
        case ENCHANT_BRACER_FROST_RESIST:
        case ENCHANT_BRACER_FIRE_RESIST:
        case ENCHANT_BRACER_SOCKET_BRACER:
            slot = EQUIPMENT_SLOT_WRISTS;
            break;

        // Gloves
        case ENCHANT_GLOVES_EXPERTISE:
        case ENCHANT_GLOVES_PRECISION:
        case ENCHANT_GLOVES_GREATER_ASSAULT:
        case ENCHANT_GLOVES_MAJOR_AGILITY:
        case ENCHANT_GLOVES_EXCEPTIONAL_SPELLPOWER:
        case ENCHANT_GLOVES_ARMSMAN:
        case ENCHANT_GLOVES_SOCKET_GLOVES:
        case ENCHANT_GLOVES_PYROROCKET:
        case ENCHANT_GLOVES_HYPERSPEED_ACCELERATORS:
            slot = EQUIPMENT_SLOT_HANDS;
            break;

        // Belt
        case ENCHANT_BELT_ETERNAL_BELT_BUCKLE:
        case ENCHANT_BELT_FRAG_BELT:
            slot = EQUIPMENT_SLOT_WAIST;
            break;

        // Legs
        case ENCHANT_LEGS_FROSTHIDE_ARMOR:
        case ENCHANT_LEGS_ICESCALE_ARMOR:
        case ENCHANT_LEGS_EARTHEN_ARMOR:
        case ENCHANT_LEGS_SAPPHIRE_SPELLTHREAD :
        case ENCHANT_LEGS_BRILLIANT_SPELLTHREAD:
            slot = EQUIPMENT_SLOT_LEGS;
            break;

        // Boots
        case ENCHANT_BOOTS_TUSKARRS_VITALITY:
        case ENCHANT_BOOTS_ICEWALKER:
        case ENCHANT_BOOTS_GREATER_ASSAULT:
        case ENCHANT_BOOTS_GREATER_SPIRIT:
        case ENCHANT_BOOTS_GREATER_FORTITUDE:
        case ENCHANT_BOOTS_SUPERIOR_AGILITY:
        case ENCHANT_BOOTS_NITRO_BOOSTS:
            slot = EQUIPMENT_SLOT_FEET;
            break;

        // Rings
        case ENCHANT_RING_STAMINA:
        case ENCHANT_RING_GREATER_SPELLPOWER:
        case ENCHANT_RING_ASSAULT:
            slot = EQUIPMENT_SLOT_FINGER1;
            break;

        // Ranged weapon
        case ENCHANT_RANGED_HEARTSEEKER_SCOPE:
        case ENCHANT_RANGED_SUN_SCOPE:
            slot = EQUIPMENT_SLOT_RANGED;
            break;

        // Main hand
        case GOSSIP_ACTION_INFO_DEF + 20:
            slot = EQUIPMENT_SLOT_MAINHAND;
            action = selected_enchant;
            check_adjacent_slot = false;
            break;

        // Off hand
        case GOSSIP_ACTION_INFO_DEF + 21:
            slot = EQUIPMENT_SLOT_OFFHAND;
            action = selected_enchant;
            check_adjacent_slot = false;
            break;

        default:
            player->CLOSE_GOSSIP_MENU();
            break;
        }
        if (slot > -1)
        {
            // allows for a maximum of 2 duplicates, and the
            // convenience of using enchant ids as gossip
            // userdata
            if (action < 0)
                action = -action;
            Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
            if (!item && slot == INVTYPE_RANGEDRIGHT)
                item   = player->GetItemByPos(INVENTORY_SLOT_BAG_0,
                                              INVTYPE_RANGEDRIGHT);
            if (item && check_adjacent_slot &&
                    item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT) != 0)
            {
                switch (slot)
                {
                case EQUIPMENT_SLOT_MAINHAND:
                {
                    Item* offhand = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
                    if (offhand)
                    {
                        player->PlayerTalkClass->ClearMenus();
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,
                                                item->GetTemplate()->Name1.c_str(),
                                                GOSSIP_SENDER_MAIN,
                                                GOSSIP_ACTION_INFO_DEF + 20);
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,
                                                offhand->GetTemplate()->Name1.c_str(),
                                                GOSSIP_SENDER_MAIN,
                                                GOSSIP_ACTION_INFO_DEF + 21);
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,
                                                "Back",
                                                GOSSIP_SENDER_MAIN, -1);
                        player->SEND_GOSSIP_MENU(1, creature->GetGUID());
                        selected_enchant = action;
                        return true;
                    }
                    break;
                }
                case EQUIPMENT_SLOT_FINGER1:
                {
                    Item* ring2 = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_FINGER2);
                    if (ring2)
                    {
                        player->PlayerTalkClass->ClearMenus();
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,
                                                item->GetTemplate()->Name1.c_str(),
                                                GOSSIP_SENDER_MAIN,
                                                GOSSIP_ACTION_INFO_DEF + 20);
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,
                                                ring2->GetTemplate()->Name1.c_str(),
                                                GOSSIP_SENDER_MAIN,
                                                GOSSIP_ACTION_INFO_DEF + 21);
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,
                                                "Back",
                                                GOSSIP_SENDER_MAIN, -1);
                        player->SEND_GOSSIP_MENU(1, creature->GetGUID());
                        selected_enchant = action;
                        return true;
                    }
                    break;
                }
                default:
                    break;
                }
            }
            Enchant(player, creature, item, action);
            ShowMainMenu(player, creature);
        }
        return true;
    }
bool PlayerbotShamanAI::ChangeWeaponEnchants()
{
    uint32 mhEnch = 0, ohEnch = 0;

    PlayerbotAI *ai = GetAI();
    if(!ai) return false;
    Player *m_bot = GetPlayerBot();
    if(!m_bot || m_bot->isDead()) return false;


    // Choose Weapon Enchant
    if (TALENT_RESTO) { mhEnch = EARTHLIVING_WEAPON; }
    else if (TALENT_ELEMENTAL){ mhEnch = FLAMETONGUE_WEAPON; }
    else
    {
        if (WINDFURY_WEAPON)
        {
            mhEnch = WINDFURY_WEAPON;
            if (m_bot->haveOffhandWeapon())
            {
                if (LAVA_LASH) ohEnch = FLAMETONGUE_WEAPON;
                else ohEnch = WINDFURY_WEAPON;
            }
		}
    else if (FLAMETONGUE_WEAPON)
    {
        mhEnch = FLAMETONGUE_WEAPON;
        if (m_bot->haveOffhandWeapon()) ohEnch = FLAMETONGUE_WEAPON;
    }

    }

    Item* weap;
    uint32 enchant_id = 0;
    SpellEntry const *tSpell;
    bool castedsomething = false;

    if (mhEnch)
    {
        weap = m_bot->GetWeaponForAttack(BASE_ATTACK);
        if (weap)
        {
            tSpell = GetSpellStore()->LookupEntry(mhEnch);
            if (tSpell && tSpell->EffectMiscValue[0] > 0)
            {
                enchant_id = (uint32) tSpell->EffectMiscValue[0];
                if (enchant_id && weap->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) != enchant_id && sSpellItemEnchantmentStore.LookupEntry(enchant_id))
                {
                    m_bot->ApplyEnchantment(weap,TEMP_ENCHANTMENT_SLOT, false); //Remove old enchantment effect
                    weap->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, 1800 * 1000, 0); //Add for 30 mins
                    m_bot->ApplyEnchantment(weap, TEMP_ENCHANTMENT_SLOT, true); //Add new effect
                    castedsomething = true;
                }
            }
        }
    }

    if (ohEnch)
    {
        weap = m_bot->GetWeaponForAttack(OFF_ATTACK);
        if (weap)
        {
            tSpell = GetSpellStore()->LookupEntry(ohEnch);
            if (tSpell && tSpell->EffectMiscValue[0] > 0)
            {
                enchant_id = (uint32) tSpell->EffectMiscValue[0];
                if (enchant_id && weap->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) != enchant_id && sSpellItemEnchantmentStore.LookupEntry(enchant_id))
                {
                    m_bot->ApplyEnchantment(weap,TEMP_ENCHANTMENT_SLOT, false); //Remove old enchantment effect
                    weap->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, 1800 * 1000, 0); //Add for 30 mins
                    m_bot->ApplyEnchantment(weap, TEMP_ENCHANTMENT_SLOT, true); //Add new effect
                    castedsomething = true;
                }
            }
        }
    }
    return castedsomething;

}
//called when player lists his received mails
void WorldSession::HandleGetMailList(WorldPacket& recvData)
{
    ObjectGuid mailbox;

    recvData >> mailbox;

    if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
        return;

    Player* player = _player;

    //load players mails, and mailed items
    if (!player->m_mailsLoaded)
        player->_LoadMail();

    // client can't work with packets > max int16 value
    const uint32 maxPacketSize = 32767;

    uint32 mailCount = 0;
    uint32 realCount = 0;                               // true mail count (includes any skipped mail)
    time_t cur_time = time(NULL);
    ByteBuffer mailData;

    WorldPacket data(SMSG_MAIL_LIST_RESULT, 200);       // guess size
    data << uint32(0);                                  // placeholder

    size_t mailCountPos = data.bitwpos();
    data.WriteBits(0, 18);                              // placeholder

    for (PlayerMails::iterator itr = player->GetMailBegin(); itr != player->GetMailEnd(); ++itr)
    {
        Mail* mail = *itr;

        // Only first 50 mails are displayed
        if (mailCount >= 50)
        {
            realCount += 1;
            continue;
        }

        // skip deleted or not delivered (deliver delay not expired) mails
        if (mail->state == MAIL_STATE_DELETED || cur_time < mail->deliver_time)
            continue;

        // skip mail with more than MAX_MAIL_ITEMS items (should not occur)
        uint8 itemCount = mail->items.size();
        if (itemCount > MAX_MAIL_ITEMS)
        {
            realCount += 1;
            continue;
        }

        // skip mail if the packet has become too large (should not occur)
        size_t nextMailSize = 6 + 1 + 8 + itemCount * (4 + 4 + 4 + 4 + 4 + MAX_INSPECTED_ENCHANTMENT_SLOT * (4 + 4 + 4) +
            4 + 4 + 4 + 4 + 1 + 4) + mail->body.size() + mail->subject.size() + 4 + 4 + 8 + 4 + 8 + 4 + 4 + 1 + 4;

        if (data.wpos() + nextMailSize > maxPacketSize)
        {
            realCount += 1;
            continue;
        }

        data.WriteBit(mail->messageType != MAIL_NORMAL ? 1 : 0);
        data.WriteBits(mail->subject.size(), 8);
        data.WriteBits(mail->body.size(), 13);
        data.WriteBit(0);
        data.WriteBit(0);

        size_t itemCountPos = data.bitwpos();
        data.WriteBits(0, 17);                          // placeholder

        data.WriteBit(1);                               // has guid

        ObjectGuid guid = mail->messageType == MAIL_NORMAL ? MAKE_NEW_GUID(mail->sender, 0, HIGHGUID_PLAYER) : 0;
        data << guid;

        uint8 trueItemCount = 0;
        for (uint8 i = 0; i < itemCount; i++)
        {
            Item* item = player->GetMItem(mail->items[i].item_guid);
            if (!item)
                continue;

            data.WriteBit(0);

            mailData << uint32(item->GetGUIDLow());
            mailData << uint32(4);                      // unknown
            mailData << uint32(item->GetSpellCharges());
            mailData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
            mailData << uint32(0);                      // unknown

            for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; j++)
            {
                mailData << uint32(item->GetEnchantmentCharges((EnchantmentSlot)j));
                mailData << uint32(item->GetEnchantmentDuration((EnchantmentSlot)j));
                mailData << uint32(item->GetEnchantmentId((EnchantmentSlot)j));
            }

            mailData << uint32(item->GetItemSuffixFactor());
            mailData << int32(item->GetItemRandomPropertyId());
            mailData << uint32(item->GetUInt32Value(ITEM_FIELD_MAX_DURABILITY));
            mailData << uint32(item->GetCount());
            mailData << uint8(i);
            mailData << uint32(item->GetEntry());

            trueItemCount++;
        }

        data.PutBits(itemCountPos, trueItemCount, 17);

        mailData.WriteString(mail->body);
        mailData << uint32(mail->messageID);
        mailData << guid;
        mailData << uint32(mail->mailTemplateId);
        mailData << uint64(mail->COD);
        mailData.WriteString(mail->subject);
        mailData << uint32(mail->stationery);
        mailData << float(float(mail->expire_time - time(NULL)) / DAY);
        mailData << uint64(mail->money);
        mailData << uint32(mail->checked);

        if (mail->messageType != MAIL_NORMAL)
            mailData << uint32(mail->sender);

        mailData << uint8(mail->messageType);
        mailData << uint32(0);                          // unknown

        realCount++;
        mailCount++;
    }

    data.FlushBits();
    data.append(mailData);

    data.put<uint32>(0, realCount);
    data.PutBits(mailCountPos, mailCount, 18);

    SendPacket(&data);

    // recalculate m_nextMailDelivereTime and unReadMails
    _player->UpdateNextMailTimeAndUnreads();
}
WorldPacket* Mailbox::BuildMailboxListingPacket()
{
    WorldPacket* data = new WorldPacket(SMSG_MAIL_LIST_RESULT, 200);
    MessageMap::iterator itr;
    uint8 i = 0;
    uint32 realCount = 0;
    uint32 mailsCount = 0;
    uint32 t = (uint32)UNIXTIME;
    *data << uint32(0);                                      // real mail's count
    *data << uint8(0);                                       // mail's count

    for (itr = Messages.begin(); itr != Messages.end(); ++itr)
    {
        if (itr->second.expire_time && t > itr->second.expire_time)
            continue;       // expired mail -> skip it

        if ((uint32)UNIXTIME < itr->second.delivery_time)
            continue;        // undelivered

        if (mailsCount >= 50) //VLack: We could calculate message sizes instead of this, but the original code did a break at 50, so I won't fix this up if no one felt the need to do so before ;-)
        {
            realCount += 1;
            continue;
        }

        uint8 item_count = itr->second.items.size();            // max count is MAX_MAIL_ITEMS (12)

        size_t next_mail_size = 2 + 4 + 1 + (itr->second.message_type == NORMAL ? 8 : 4) + 4 * 8 + (itr->second.subject.size() + 1) + (itr->second.body.size() + 1) + 1 + item_count*(1 + 4 + 4 + MAX_INSPECTED_ENCHANTMENT_SLOT * 3 * 4 + 4 + 4 + 4 + 4 + 4 + 4 + 1);


        *data << uint16(next_mail_size);                    // Message size
        *data << uint32(itr->second.message_id);                 // Message ID
        *data << uint8(itr->second.message_type);                // Message Type

        switch (itr->second.message_type)
        {
        case NORMAL:
            *data << uint64((itr->second.sender_guid));
            break;
        case COD:
        case AUCTION:
        case ITEM:
            *data << uint32(Arcemu::Util::GUID_LOPART((itr->second.sender_guid)));
            break;
        case GAMEOBJECT:
        case CREATURE:
            *data << uint32(static_cast<uint32>((itr->second.sender_guid)));
            break;
        }

        *data << uint64(itr->second.cod);                         // COD
        *data << uint32(0);                                   // Package.dbc ID ?
        *data << uint32(itr->second.stationery);                  // stationery (Stationery.dbc)
        *data << uint64(itr->second.money);                       // Gold
        *data << uint32(itr->second.checked_flag);                     // flags
        *data << float(float((itr->second.expire_time - uint32(UNIXTIME)) / DAY)); // Time
        *data << uint32(itr->second.message_id);              // mail template (MailTemplate.dbc)
        *data << itr->second.subject;                             // Subject string - once 00, when mail type = 3, max 256
        *data << itr->second.body;                                // message? max 8000
        *data << uint8(item_count);                           // client limit is 0x10

        Item* pItem;
        std::vector<uint32>::iterator itr2;
        for (uint8 i = 0; i < item_count; ++i)
        {
            pItem = objmgr.LoadItem(itr->second.items[i]);
            // item index (0-6?)
            *data << uint8(i);
            // item guid low?
            *data << uint32((pItem ? pItem->GetLowGUID() : 0));
            // entry
            *data << uint32((pItem ? pItem->GetEntry() : 0));
            for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j)
            {
                *data << uint32((pItem ? pItem->GetEnchantmentId((EnchantmentSlot)j) : 0));
                *data << uint32((pItem ? pItem->GetEnchantmentDuration((EnchantmentSlot)j) : 0));
                *data << uint32((pItem ? pItem->GetEnchantmentCharges((EnchantmentSlot)j) : 0));
            }

            // can be negative
            *data << int32((pItem ? pItem->GetItemRandomPropertyId() : 0));
            // unk
            *data << uint32((pItem ? pItem->GetItemRandomSuffixFactor() : 0));
            // stack count
            *data << uint32((pItem ? pItem->GetStackCount() : 0));
            // charges
            *data << uint32((pItem ? pItem->GetChargesLeft() : 0));
            // durability
            *data << uint32((pItem ? pItem->GetDurabilityMax() : 0));
            // durability
            *data << uint32((pItem ? pItem->GetDurability() : 0));
            // unknown wotlk
            *data << uint8(0);
        }

        ++realCount;
        ++mailsCount;
    }

    data->put<uint32>(0, realCount);                         // this will display warning about undelivered mail to player if realCount > mailsCount
    data->put<uint8>(4, mailsCount);                        // set real send mails to client

    // do cleanup on request mail
    CleanupExpiredMessages();
    return data;
}
Exemple #10
0
//called when player lists his received mails
void WorldSession::HandleGetMail(WorldPacket & recv_data )
{
    CHECK_PACKET_SIZE(recv_data,8);

    uint64 mailbox;
    recv_data >> mailbox;

    //GameObject* obj = ObjectAccessor::GetGameObject(_player, mailbox);
    //if(!obj || !obj->IsMailBox())
    //    return;

    Player* pl = _player;

    //load players mails, and mailed items
    if(!pl->m_mailsLoaded)
        pl ->_LoadMail();

    // client can't work with packets > max int16 value
    const uint32 maxPacketSize = 32767;

    uint32 mails_count = 0;                                 // real send to client mails amount

    WorldPacket data(SMSG_MAIL_LIST_RESULT, (200));         // guess size
    data << uint8(0);                                       // mail's count
    time_t cur_time = time(NULL);

    for(PlayerMails::iterator itr = pl->GetmailBegin(); itr != pl->GetmailEnd(); ++itr)
    {
        // skip deleted or not delivered (deliver delay not expired) mails
        if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time)
            continue;

        uint8 item_count = (*itr)->items.size();            // max count is MAX_MAIL_ITEMS (12)

        size_t next_mail_size = 2+4+1+8+4*8+((*itr)->subject.size()+1)+1+item_count*(1+4+4+6*3*4+4+4+1+4+4+4);

        if(data.wpos()+next_mail_size > maxPacketSize)
            break;

        data << (uint16) 0x0040;                            // unknown 2.3.0, different values
        data << (uint32) (*itr)->messageID;                 // Message ID
        data << (uint8) (*itr)->messageType;                // Message Type

        switch((*itr)->messageType)
        {
            case MAIL_NORMAL:                               // sender guid
                data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER));
                break;
            case MAIL_CREATURE:
            case MAIL_GAMEOBJECT:
            case MAIL_AUCTION:
                data << (uint32) (*itr)->sender;            // creature/gameobject entry, auction id
                break;
            case MAIL_ITEM:                                 // item entry (?) sender = "Unknown", NYI
                break;
        }

        data << (uint32) (*itr)->COD;                       // COD
        data << (uint32) (*itr)->itemTextId;                // sure about this
        data << (uint32) 0;                                 // unknown
        data << (uint32) (*itr)->stationery;                // stationery (Stationery.dbc)
        data << (uint32) (*itr)->money;                     // Gold
        data << (uint32) 0x04;                              // unknown, 0x4 - auction, 0x10 - normal
                                                            // Time
        data << (float)  ((*itr)->expire_time-time(NULL))/DAY;
        data << (uint32) (*itr)->mailTemplateId;            // mail template (MailTemplate.dbc)
        data << (*itr)->subject;                            // Subject string - once 00, when mail type = 3

        data << (uint8) item_count;

        for(uint8 i = 0; i < item_count; ++i)
        {
            Item *item = pl->GetMItem((*itr)->items[i].item_guid);
            // item index (0-6?)
            data << (uint8)  i;
            // item guid low?
            data << (uint32) (item ? item->GetGUIDLow() : 0);
            // entry
            data << (uint32) (item ? item->GetEntry() : 0);
            for(uint8 j = 0; j < 6; ++j)
            {
                // unsure
                data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0);
                // unsure
                data << (uint32) (item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0);
                // unsure
                data << (uint32) (item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0);
            }
            // can be negative
            data << (uint32) (item ? item->GetItemRandomPropertyId() : 0);
            // unk
            data << (uint32) (item ? item->GetItemSuffixFactor() : 0);
            // stack count
            data << (uint8)  (item ? item->GetCount() : 0);
            // charges
            data << (uint32) (item ? item->GetSpellCharges() : 0);
            // durability
            data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0);
            // durability
            data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0);
        }

        mails_count += 1;
    }

    data.put<uint8>(0, mails_count);                        // set real send mails to client
    SendPacket(&data);

    // recalculate m_nextMailDelivereTime and unReadMails
    _player->UpdateNextMailTimeAndUnreads();
}
Exemple #11
0
/**
 * Handles the packet sent by the client when requesting the current mail list.
 * It will send a list of all available mails in the players mailbox to the client.
 */
void WorldSession::HandleGetMailList(WorldPacket& recv_data)
{
    ObjectGuid mailboxGuid;
    recv_data >> mailboxGuid;

    if (!CheckMailBox(mailboxGuid))
        return;

    // client can't work with packets > max int16 value
    const uint32 maxPacketSize = 32767;

    uint32 mailsCount = 0;                                  // send to client mails amount

    WorldPacket data(SMSG_MAIL_LIST_RESULT, (200));         // guess size
    data << uint8(0);                                       // mail's count
    time_t cur_time = time(nullptr);

    for (PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr)
    {
        // packet send mail count as uint8, prevent overflow
        if (mailsCount >= 254)
            break;

        // skip deleted or not delivered (deliver delay not expired) mails
        if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time)
            continue;

        uint8 item_count = (*itr)->items.size();            // max count is MAX_MAIL_ITEMS (12)

        size_t next_mail_size = 2 + 4 + 1 + 8 + 4 * 8 + ((*itr)->subject.size() + 1) + 1 + item_count * (1 + 4 + 4 + 6 * 3 * 4 + 4 + 4 + 1 + 4 + 4 + 4);

        if (data.wpos() + next_mail_size > maxPacketSize)
            break;

        data << uint16(next_mail_size);                     // Message size
        data << uint32((*itr)->messageID);                  // Message ID
        data << uint8((*itr)->messageType);                 // Message Type

        switch ((*itr)->messageType)
        {
            case MAIL_NORMAL:                               // sender guid
                data << ObjectGuid(HIGHGUID_PLAYER, (*itr)->sender);
                break;
            case MAIL_CREATURE:
            case MAIL_GAMEOBJECT:
            case MAIL_AUCTION:
                data << uint32((*itr)->sender);             // creature/gameobject entry, auction id
                break;
            case MAIL_ITEM:                                 // item entry (?) sender = "Unknown", NYI
                data << uint32(0);                          // item entry
                break;
        }

        data << uint32((*itr)->COD);                        // COD
        data << uint32((*itr)->itemTextId);                 // item text
        data << uint32(0);                                  // unknown
        data << uint32((*itr)->stationery);                 // stationery (Stationery.dbc)
        data << uint32((*itr)->money);                      // copper
        data << uint32((*itr)->checked);                    // flags
        data << float(float((*itr)->expire_time - time(nullptr)) / float(DAY));// Time
        data << uint32((*itr)->mailTemplateId);             // mail template (MailTemplate.dbc)
        data << (*itr)->subject;                            // Subject string - once 00, when mail type = 3, max 256

        data << (uint8)item_count;

        for (uint8 i = 0; i < item_count; ++i)
        {
            Item* item = _player->GetMItem((*itr)->items[i].item_guid);
            // item index (0-6?)
            data << uint8(i);
            // item guid low?
            data << uint32(item ? item->GetGUIDLow() : 0);
            // entry
            data << uint32(item ? item->GetEntry() : 0);
            for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j)
            {
                // unsure
                data << uint32(item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0);
                // unsure
                data << uint32(item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0);
                // unsure
                data << uint32(item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0);
            }
            // can be negative
            data << uint32(item ? item->GetItemRandomPropertyId() : 0);
            // unk
            data << uint32(item ? item->GetItemSuffixFactor() : 0);
            // stack count
            data << (uint8)(item ? item->GetCount() : 0);
            // charges
            data << uint32(item ? item->GetSpellCharges() : 0);
            // durability
            data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0);
            // durability
            data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0);
        }

        mailsCount += 1;
    }

    data.put<uint8>(0, mailsCount);                         // set real send mails to client
    SendPacket(data);

    // recalculate m_nextMailDelivereTime and unReadMails
    _player->UpdateNextMailTimeAndUnreads();
}
Exemple #12
0
void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
{
    DEBUG_LOG("WORLD: CMSG_SOCKET_GEMS");

    ObjectGuid itemGuid;
    ObjectGuid gemGuids[MAX_GEM_SOCKETS];

    recv_data >> itemGuid;
    if (!itemGuid.IsItem())
        return;

    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
        recv_data >> gemGuids[i];

    // cheat -> tried to socket same gem multiple times
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        ObjectGuid gemGuid = gemGuids[i];
        if (!gemGuid)
            continue;

        if (!gemGuid.IsItem())
            return;

        for (int j = i + 1; j < MAX_GEM_SOCKETS; ++j)
            if (gemGuids[j] == gemGuid)
                return;
    }

    Item* itemTarget = _player->GetItemByGuid(itemGuid);
    if (!itemTarget)                                        // missing item to socket
        return;

    ItemPrototype const* itemProto = itemTarget->GetProto();
    if (!itemProto)
        return;

    // this slot is excepted when applying / removing meta gem bonus
    uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT);

    Item* Gems[MAX_GEM_SOCKETS];
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
        Gems[i] = gemGuids[i] ? _player->GetItemByGuid(gemGuids[i]) : NULL;

    GemPropertiesEntry const* GemProps[MAX_GEM_SOCKETS];
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)               // get geminfo from dbc storage
        GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL;

    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)               // check for hack maybe
    {
        if (!GemProps[i])
            continue;

        // tried to put gem in socket where no socket exists
        if (!itemProto->Socket[i].Color)
            return;

        // tried to put normal gem in meta socket
        if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META)
            return;

        // tried to put meta gem in normal socket
        if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META)
            return;
    }

    uint32 GemEnchants[MAX_GEM_SOCKETS];
    uint32 OldEnchants[MAX_GEM_SOCKETS];
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)               // get new and old enchantments
    {
        GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
        OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + i));
    }

    // check unique-equipped conditions
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (!Gems[i])
            continue;

        // continue check for case when attempt add 2 similar unique equipped gems in one item.
        ItemPrototype const* iGemProto = Gems[i]->GetProto();

        // unique item (for new and already placed bit removed enchantments
        if (iGemProto->Flags & ITEM_FLAG_UNIQUE_EQUIPPED)
        {
            for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
            {
                if (i == j)                                 // skip self
                    continue;

                if (Gems[j])
                {
                    if (iGemProto->ItemId == Gems[j]->GetEntry())
                    {
                        _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                        return;
                    }
                }
                else if (OldEnchants[j])
                {
                    if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
                    {
                        if (iGemProto->ItemId == enchantEntry->GemID)
                        {
                            _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                            return;
                        }
                    }
                }
            }
        }

        // for equipped item check all equipment for duplicate equipped gems
        if (itemTarget->IsEquipped())
        {
            if (InventoryResult res = _player->CanEquipUniqueItem(Gems[i], slot))
            {
                _player->SendEquipError(res, itemTarget, NULL);
                return;
            }
        }
    }

    bool SocketBonusActivated = itemTarget->GemsFitSockets();    // save state of socketbonus
    _player->ToggleMetaGemsActive(slot, false);             // turn off all metagems (except for the target item)

    // if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met

    // remove ALL enchants
    for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
        _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), false);

    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (GemEnchants[i])
        {
            itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + i), GemEnchants[i], 0, 0);
            if (Item* guidItem = gemGuids[i] ? _player->GetItemByGuid(gemGuids[i]) : NULL)
                _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true);
        }
    }

    for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
        _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true);

    bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();// current socketbonus state
    if (SocketBonusActivated != SocketBonusToBeActivated)   // if there was a change...
    {
        _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false);
        itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0);
        _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true);
        // it is not displayed, client has an inbuilt system to determine if the bonus is activated
    }

    _player->ToggleMetaGemsActive(slot, true);              // turn on all metagems (except for target item)
}
Exemple #13
0
/// \todo refactoring
bool MailMessage::AddMessageDataToPacket(WorldPacket& data)
{
    uint8 i = 0;
    uint32 j;
    std::vector<uint32>::iterator itr;
    Item* pItem;

    // add stuff
    if (deleted_flag)
        return false;

    uint8 guidsize;
    if (message_type == 0)
        guidsize = 8;
    else
        guidsize = 4;

    size_t msize = 2 + 4 + 1 + guidsize + 7 * 4 + (subject.size() + 1) + (body.size() + 1) + 1 + (items.size() * (1 + 2 * 4 + 7 * (3 * 4) + 6 * 4 + 1));

    data << uint16(msize);     // message size
    data << uint32(message_id);
    data << uint8(message_type);

    switch (message_type)
    {
        case NORMAL:
            data << uint64(sender_guid);
            break;
        case COD:
        case AUCTION:
        case GAMEOBJECT:
        case ITEM:
            data << uint32(Arcemu::Util::GUID_LOPART(sender_guid));
            break;
        case CREATURE:
            data << uint32(Arcemu::Util::GET_CREATURE_ENTRY_FROM_GUID(sender_guid));
            break;
    }

    data << uint32(cod);            // cod
    data << uint32(0);
    data << uint32(stationery);
    data << uint32(money);        // money
    data << uint32(checked_flag);           // "checked" flag
    data << float((expire_time - uint32(UNIXTIME)) / 86400.0f);
    data << uint32(0);    // mail template
    data << subject;
    data << body;

    data << uint8(items.size());        // item count

    if (!items.empty())
    {
        for (itr = items.begin(); itr != items.end(); ++itr)
        {
            pItem = objmgr.LoadItem(*itr);
            if (pItem == NULL)
                continue;

            data << uint8(i++);
            data << uint32(pItem->GetLowGUID());
            data << uint32(pItem->GetEntry());

            for (j = 0; j < 7; ++j)
            {
                data << uint32(pItem->GetEnchantmentId(j));
                data << uint32(pItem->GetEnchantmentDuration(j));
                data << uint32(0);
            }

            data << uint32(pItem->GetItemRandomPropertyId());
            data << uint32(pItem->GetItemRandomSuffixFactor());
            data << uint32(pItem->GetStackCount());
            data << uint32(pItem->GetChargesLeft());
            data << uint32(pItem->GetDurabilityMax());
            data << uint32(pItem->GetDurability());
            data << uint8(0);   // unknown

            delete pItem;
        }

    }

    return true;
}
Exemple #14
0
void WorldSession::HandleSocketGems(WorldPackets::Item::SocketGems& socketGems)
{
    if (!socketGems.ItemGuid)
        return;

    //cheat -> tried to socket same gem multiple times
    if ((!socketGems.GemItem[0].IsEmpty() && (socketGems.GemItem[0] == socketGems.GemItem[1] || socketGems.GemItem[0] == socketGems.GemItem[2])) ||
        (!socketGems.GemItem[1].IsEmpty() && (socketGems.GemItem[1] == socketGems.GemItem[2])))
        return;

    Item* itemTarget = _player->GetItemByGuid(socketGems.ItemGuid);
    if (!itemTarget)                                         //missing item to socket
        return;

    ItemTemplate const* itemProto = itemTarget->GetTemplate();
    if (!itemProto)
        return;

    //this slot is excepted when applying / removing meta gem bonus
    uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT);

    Item* gems[MAX_GEM_SOCKETS];
    memset(gems, 0, sizeof(gems));
    ItemDynamicFieldGems gemData[MAX_GEM_SOCKETS];
    memset(gemData, 0, sizeof(gemData));
    GemPropertiesEntry const* gemProperties[MAX_GEM_SOCKETS];
    memset(gemProperties, 0, sizeof(gemProperties));
    ItemDynamicFieldGems const* oldGemData[MAX_GEM_SOCKETS];
    memset(oldGemData, 0, sizeof(oldGemData));
    for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (Item* gem = _player->GetItemByGuid(socketGems.GemItem[i]))
        {
            gems[i] = gem;
            gemData[i].ItemId = gem->GetEntry();
            gemData[i].Context = gem->GetUInt32Value(ITEM_FIELD_CONTEXT);
            for (std::size_t b = 0; b < gem->GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS).size() && b < 16; ++b)
                gemData[i].BonusListIDs[b] = gem->GetDynamicValue(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS, b);

            gemProperties[i] = sGemPropertiesStore.LookupEntry(gem->GetTemplate()->GetGemProperties());
        }

        oldGemData[i] = itemTarget->GetGem(i);
    }

    // Find first prismatic socket
    uint32 firstPrismatic = 0;
    while (firstPrismatic < MAX_GEM_SOCKETS && itemTarget->GetSocketColor(firstPrismatic))
        ++firstPrismatic;

    for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)                //check for hack maybe
    {
        if (!gemProperties[i])
            continue;

        // tried to put gem in socket where no socket exists (take care about prismatic sockets)
        if (!itemTarget->GetSocketColor(i))
        {
            // no prismatic socket
            if (!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT))
                return;

            if (i != firstPrismatic)
                return;
        }

        // Gem must match socket color
        if (SocketColorToGemTypeMask[itemTarget->GetSocketColor(i)] != gemProperties[i]->Type)
        {
            // unless its red, blue, yellow or prismatic
            if (!(SocketColorToGemTypeMask[itemTarget->GetSocketColor(i)] & SOCKET_COLOR_PRISMATIC) || !(gemProperties[i]->Type & SOCKET_COLOR_PRISMATIC))
                return;
        }
    }

    // check unique-equipped conditions
    for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (!gems[i])
            continue;

        // continue check for case when attempt add 2 similar unique equipped gems in one item.
        ItemTemplate const* iGemProto = gems[i]->GetTemplate();

        // unique item (for new and already placed bit removed enchantments
        if (iGemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPABLE)
        {
            for (uint32 j = 0; j < MAX_GEM_SOCKETS; ++j)
            {
                if (i == j)                                    // skip self
                    continue;

                if (gems[j])
                {
                    if (iGemProto->GetId() == gems[j]->GetEntry())
                    {
                        _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                        return;
                    }
                }
                else if (oldGemData[j])
                {
                    if (iGemProto->GetId() == oldGemData[j]->ItemId)
                    {
                        _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                        return;
                    }
                }
            }
        }

        // unique limit type item
        int32 limit_newcount = 0;
        if (iGemProto->GetItemLimitCategory())
        {
            if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->GetItemLimitCategory()))
            {
                // NOTE: limitEntry->mode is not checked because if item has limit then it is applied in equip case
                for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
                {
                    if (gems[j])
                    {
                        // new gem
                        if (iGemProto->GetItemLimitCategory() == gems[j]->GetTemplate()->GetItemLimitCategory())
                            ++limit_newcount;
                    }
                    else if (oldGemData[j])
                    {
                        // existing gem
                        if (ItemTemplate const* jProto = sObjectMgr->GetItemTemplate(oldGemData[j]->ItemId))
                            if (iGemProto->GetItemLimitCategory() == jProto->GetItemLimitCategory())
                                ++limit_newcount;
                    }
                }

                if (limit_newcount > 0 && uint32(limit_newcount) > limitEntry->Quantity)
                {
                    _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                    return;
                }
            }
        }

        // for equipped item check all equipment for duplicate equipped gems
        if (itemTarget->IsEquipped())
        {
            if (InventoryResult res = _player->CanEquipUniqueItem(gems[i], slot, std::max(limit_newcount, 0)))
            {
                _player->SendEquipError(res, itemTarget, NULL);
                return;
            }
        }
    }

    bool SocketBonusActivated = itemTarget->GemsFitSockets();    //save state of socketbonus
    _player->ToggleMetaGemsActive(slot, false);             //turn off all metagems (except for the target item)

    //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met

    //remove ALL mods - gem can change item level
    if (itemTarget->IsEquipped())
        _player->_ApplyItemMods(itemTarget, itemTarget->GetSlot(), false);

    for (uint16 i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (gems[i])
        {
            uint32 gemScalingLevel = _player->getLevel();
            if (uint32 fixedLevel = gems[i]->GetModifier(ITEM_MODIFIER_SCALING_STAT_DISTRIBUTION_FIXED_LEVEL))
                gemScalingLevel = fixedLevel;

            itemTarget->SetGem(i, &gemData[i], gemScalingLevel);

            if (gemProperties[i] && gemProperties[i]->EnchantID)
                itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + i), gemProperties[i]->EnchantID, 0, 0, _player->GetGUID());

            uint32 gemCount = 1;
            _player->DestroyItemCount(gems[i], gemCount, true);
        }
    }

    if (itemTarget->IsEquipped())
        _player->_ApplyItemMods(itemTarget, itemTarget->GetSlot(), true);

    if (Item* childItem = _player->GetChildItemByGuid(itemTarget->GetChildItem()))
    {
        if (childItem->IsEquipped())
            _player->_ApplyItemMods(childItem, childItem->GetSlot(), false);
        childItem->CopyArtifactDataFromParent(itemTarget);
        if (childItem->IsEquipped())
            _player->_ApplyItemMods(childItem, childItem->GetSlot(), true);
    }

    bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
    if (SocketBonusActivated ^ SocketBonusToBeActivated)     //if there was a change...
    {
        _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false);
        itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->GetSocketBonus() : 0), 0, 0, _player->GetGUID());
        _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true);
        //it is not displayed, client has an inbuilt system to determine if the bonus is activated
    }

    _player->ToggleMetaGemsActive(slot, true);              //turn on all metagems (except for target item)

    _player->RemoveTradeableItem(itemTarget);
    itemTarget->ClearSoulboundTradeable(_player);           // clear tradeable flag

    itemTarget->SendUpdateSockets();
}
/**
 * Handles the packet sent by the client when requesting the current mail list.
 * It will send a list of all available mails in the players mailbox to the client.
 */
void WorldSession::HandleGetMailList(WorldPacket& recv_data)
{
    ObjectGuid mailboxGuid;
    recv_data >> mailboxGuid;

    if (!CheckMailBox(mailboxGuid))
        return;

    // client can't work with packets > max int16 value
    const uint32 maxPacketSize = 32767;

    uint32 mailsCount = 0;                                  // send to client mails amount

    WorldPacket data(SMSG_MAIL_LIST_RESULT, (200));         // guess size
    data << uint8(0);                                       // mail's count
    time_t cur_time = time(NULL);

    for (PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr)
    {
        // packet send mail count as uint8, prevent overflow
        if (mailsCount >= 254)
            break;

        // skip deleted or not delivered (deliver delay not expired) mails
        if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time)
            continue;

        /*[-ZERO] TODO recheck this
        size_t next_mail_size = 4+1+8+((*itr)->subject.size()+1)+4*7+1+item_count*(1+4+4+6*3*4+4+4+1+4+4+4);

        if(data.wpos()+next_mail_size > maxPacketSize)
            break;
        */

        data << uint32((*itr)->messageID);                  // Message ID
        data << uint8((*itr)->messageType);                 // Message Type

        switch ((*itr)->messageType)
        {
            case MAIL_NORMAL:                               // sender guid
                data << ObjectGuid(HIGHGUID_PLAYER, (*itr)->sender);
                break;
            case MAIL_CREATURE:
            case MAIL_GAMEOBJECT:
            case MAIL_AUCTION:
                data << (uint32)(*itr)->sender;             // creature/gameobject entry, auction id
                break;
            case MAIL_ITEM:                                 // item entry (?) sender = "Unknown", NYI
                break;
        }

        data << (*itr)->subject;                            // Subject string - once 00, when mail type = 3
        data << uint32((*itr)->itemTextId);                 // sure about this
        data << uint32(0);                                  // unknown
        data << uint32((*itr)->stationery);                 // stationery (Stationery.dbc)

        // 1.12.1 can have only single item
        Item* item = (*itr)->items.size() > 0 ? _player->GetMItem((*itr)->items[0].item_guid) : NULL;
        data << uint32(item ? item->GetEntry() : 0);        // entry
        // permanent enchantment
        data << uint32(item ? item->GetEnchantmentId((EnchantmentSlot)PERM_ENCHANTMENT_SLOT) : 0);
        // can be negative
        data << uint32(item ? item->GetItemRandomPropertyId() : 0);
        // unk
        data << uint32(item ? item->GetItemSuffixFactor() : 0);
        data << uint8(item ? item->GetCount() : 0);         // stack count
        data << uint32(item ? item->GetSpellCharges() : 0); // charges
        // durability
        data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0);
        // durability
        data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0);
        data << uint32((*itr)->money);                      // copper
        data << uint32((*itr)->COD);                        // Cash on delivery
        data << uint32((*itr)->checked);                    // flags
        data << float(float((*itr)->expire_time - time(NULL)) / float(DAY));// Time
        data << uint32((*itr)->mailTemplateId);             // mail template (MailTemplate.dbc)

        mailsCount += 1;
    }

    data.put<uint8>(0, mailsCount);                         // set real send mails to client
    SendPacket(&data);

    // recalculate m_nextMailDelivereTime and unReadMails
    _player->UpdateNextMailTimeAndUnreads();
}
//called when player lists his received mails
void WorldSession::HandleGetMailList(WorldPacket & recv_data)
{
    uint64 mailbox;
    recv_data >> mailbox;

    if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
        return;

    Player* pl = _player;

    //load players mails, and mailed items
    if (!pl->m_mailsLoaded)
        pl ->_LoadMail();

    // client can't work with packets > max int16 value
    const uint32 maxPacketSize = 32767;

    uint32 mailsCount = 0;                                 // real send to client mails amount
    uint32 realCount  = 0;                                 // real mails amount

    WorldPacket data(SMSG_MAIL_LIST_RESULT, (200));
    data << uint32(0);                                      // real mail's count
    data << uint8(0);                                       // mail's count
    time_t cur_time = time(NULL);

    for (PlayerMails::iterator itr = pl->GetMailBegin(); itr != pl->GetMailEnd(); ++itr)
    {
        // packet send mail count as uint8, prevent overflow
        if (mailsCount >= 254)
        {
            realCount += 1;
            continue;
        }

        // skip deleted or not delivered (deliver delay not expired) mails
        if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time)
            continue;

        uint8 item_count = (*itr)->items.size();            // max count is MAX_MAIL_ITEMS (12)

        size_t next_mail_size = 2+4+1+((*itr)->messageType == MAIL_NORMAL ? 8 : 4)+4*8+((*itr)->subject.size()+1)+((*itr)->body.size()+1)+1+item_count*(1+4+4+7*3*4+4+4+4+4+4+4+1);

        if (data.wpos()+next_mail_size > maxPacketSize)
        {
            realCount += 1;
            continue;
        }

        data << uint16(next_mail_size);                    // Message size
        data << uint32((*itr)->messageID);                 // Message ID
        data << uint8((*itr)->messageType);                // Message Type

        switch((*itr)->messageType)
        {
            case MAIL_NORMAL:                               // sender guid
                data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER));
                break;
            case MAIL_CREATURE:
            case MAIL_GAMEOBJECT:
            case MAIL_AUCTION:
                data << uint32((*itr)->sender);              // creature/gameobject entry, auction id
                break;
            case MAIL_ITEM:                                  // item entry (?) sender = "Unknown", NYI
                data << uint32(0);                           // item entry
                break;
        }

        data << uint64((*itr)->COD);                         // COD
        data << uint32(0);                                   // probably changed in 3.3.3
        data << uint32((*itr)->stationery);                  // stationery (Stationery.dbc)
        data << uint64((*itr)->money);                       // Gold
        data << uint32((*itr)->checked);                     // flags
        data << float(((*itr)->expire_time-time(NULL))/DAY); // Time
        data << uint32((*itr)->mailTemplateId);              // mail template (MailTemplate.dbc)
        data << (*itr)->subject;                             // Subject string - once 00, when mail type = 3, max 256
        data << (*itr)->body;                                // message? max 8000
        data << uint8(item_count);                           // client limit is 0x10

        for (uint8 i = 0; i < item_count; ++i)
        {
            Item *item = pl->GetMItem((*itr)->items[i].item_guid);
            // item index (0-6?)
            data << uint8(i);
            // item guid low?
            data << uint32((item ? item->GetGUIDLow() : 0));
            // entry
            data << uint32((item ? item->GetEntry() : 0));
            for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j)
            {
                data << uint32((item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0));
                data << uint32((item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0));
                data << uint32((item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0));
            }

            for (uint8 j = 0; j < 2; ++j)
            {
                data << uint32(0);
                data << uint32(0);
                data << uint32(0);
            }

            // can be negative
            data << int32((item ? item->GetItemRandomPropertyId() : 0));
            // unk
            data << uint32((item ? item->GetItemSuffixFactor() : 0));
            // stack count
            data << uint32((item ? item->GetCount() : 0));
            // charges
            data << uint32((item ? item->GetSpellCharges() : 0));
            // durability
            data << uint32((item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0));
            // durability
            data << uint32((item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0));
            // unknown wotlk
            data << uint8(0);
        }

        realCount += 1;
        mailsCount += 1;
    }

    data.put<uint32>(0, realCount);                         // this will display warning about undelivered mail to player if realCount > mailsCount
    data.put<uint8>(4, mailsCount);                        // set real send mails to client
    SendPacket(&data);

    // recalculate m_nextMailDelivereTime and unReadMails
    _player->UpdateNextMailTimeAndUnreads();
}
Exemple #17
0
void WorldSession::SendUpdateTrade()
{
    Item *item = NULL;

    if( !_player || !_player->pTrader )
        return;

    // reset trade status
    if (_player->acceptTrade)
    {
        _player->acceptTrade = false;
        SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
    }

    if (_player->pTrader->acceptTrade)
    {
        _player->pTrader->acceptTrade = false;
        _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
    }

    WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100));    // guess size
    data << (uint8 ) 1;                                     // can be different (only seen 0 and 1)
    data << (uint32) 0;                                     // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
    data << (uint32) TRADE_SLOT_COUNT;                      // trade slots count/number?, = next field in most cases
    data << (uint32) TRADE_SLOT_COUNT;                      // trade slots count/number?, = prev field in most cases
    data << (uint32) _player->pTrader->tradeGold;           // trader gold
    data << (uint32) 0;                                     // spell casted on lowest slot item

    for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
    {
        item = (_player->pTrader->tradeItems[i] != NULL_SLOT ? _player->pTrader->GetItemByPos( _player->pTrader->tradeItems[i] ) : NULL);

        data << (uint8) i;                                  // trade slot number, if not specified, then end of packet

        if(item)
        {
            data << (uint32) item->GetProto()->ItemId;      // entry
                                                            // display id
            data << (uint32) item->GetProto()->DisplayInfoID;
                                                            // stack count
            data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
            data << (uint32) 0;                             // probably gift=1, created_by=0?
                                                            // gift creator
            data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR);
            data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT);
            for (uint8 j = 0; j < 3; ++j)
                data << (uint32) 0;                         // enchantment id (permanent/gems?)
                                                            // creator
            data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR);
            data << (uint32) item->GetSpellCharges();       // charges
            data << (uint32) item->GetItemSuffixFactor();   // SuffixFactor
                                                            // random properties id
            data << (uint32) item->GetItemRandomPropertyId();
            data << (uint32) item->GetProto()->LockID;      // lock id
                                                            // max durability
            data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
                                                            // durability
            data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY);
        }
        else
        {
            for (uint8 j = 0; j < 18; j++)
                data << uint32(0);
        }
    }
    SendPacket(&data);
}
void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
{
    sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SOCKET_GEMS");

    uint64 item_guid;
    uint64 gem_guids[MAX_GEM_SOCKETS];

    recvData >> item_guid;
    if (!item_guid)
        return;

    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
        recvData >> gem_guids[i];

    //cheat -> tried to socket same gem multiple times
    if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) ||
        (gem_guids[1] && (gem_guids[1] == gem_guids[2])))
        return;

    Item* itemTarget = _player->GetItemByGuid(item_guid);
    if (!itemTarget)                                         //missing item to socket
        return;

    ItemTemplate const* itemProto = itemTarget->GetTemplate();
    if (!itemProto)
        return;

    //this slot is excepted when applying / removing meta gem bonus
    uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT);

    Item* Gems[MAX_GEM_SOCKETS];
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
        Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL;

    GemPropertiesEntry const* GemProps[MAX_GEM_SOCKETS];
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)                //get geminfo from dbc storage
        GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetTemplate()->GemProperties) : NULL;

    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)                //check for hack maybe
    {
        if (!GemProps[i])
            continue;

        // tried to put gem in socket where no socket exists (take care about prismatic sockets)
        if (!itemProto->Socket[i].Color)
        {
            // no prismatic socket
            if (!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT))
                return;

            // not first not-colored (not normaly used) socket
            if (i != 0 && !itemProto->Socket[i-1].Color && (i+1 >= MAX_GEM_SOCKETS || itemProto->Socket[i+1].Color))
                return;

            // ok, this is first not colored socket for item with prismatic socket
        }

        // tried to put normal gem in meta socket
        if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META)
            return;

        // tried to put meta gem in normal socket
        if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META)
            return;
    }

    uint32 GemEnchants[MAX_GEM_SOCKETS];
    uint32 OldEnchants[MAX_GEM_SOCKETS];
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)                //get new and old enchantments
    {
        GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
        OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i));
    }

    // check unique-equipped conditions
    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (!Gems[i])
            continue;

        // continue check for case when attempt add 2 similar unique equipped gems in one item.
        ItemTemplate const* iGemProto = Gems[i]->GetTemplate();

        // unique item (for new and already placed bit removed enchantments
        if (iGemProto->Flags & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED)
        {
            for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
            {
                if (i == j)                                    // skip self
                    continue;

                if (Gems[j])
                {
                    if (iGemProto->ItemId == Gems[j]->GetEntry())
                    {
                        _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                        return;
                    }
                }
                else if (OldEnchants[j])
                {
                    if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
                    {
                        if (iGemProto->ItemId == enchantEntry->GemID)
                        {
                            _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                            return;
                        }
                    }
                }
            }
        }

        // unique limit type item
        int32 limit_newcount = 0;
        if (iGemProto->ItemLimitCategory)
        {
            if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory))
            {
                // NOTE: limitEntry->mode is not checked because if item has limit then it is applied in equip case
                for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
                {
                    if (Gems[j])
                    {
                        // new gem
                        if (iGemProto->ItemLimitCategory == Gems[j]->GetTemplate()->ItemLimitCategory)
                            ++limit_newcount;
                    }
                    else if (OldEnchants[j])
                    {
                        // existing gem
                        if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
                            if (ItemTemplate const* jProto = sObjectMgr->GetItemTemplate(enchantEntry->GemID))
                                if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory)
                                    ++limit_newcount;
                    }
                }

                if (limit_newcount > 0 && uint32(limit_newcount) > limitEntry->maxCount)
                {
                    _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
                    return;
                }
            }
        }

        // for equipped item check all equipment for duplicate equipped gems
        if (itemTarget->IsEquipped())
        {
            if (InventoryResult res = _player->CanEquipUniqueItem(Gems[i], slot, std::max(limit_newcount, 0)))
            {
                _player->SendEquipError(res, itemTarget, NULL);
                return;
            }
        }
    }

    bool SocketBonusActivated = itemTarget->GemsFitSockets();    //save state of socketbonus
    _player->ToggleMetaGemsActive(slot, false);             //turn off all metagems (except for the target item)

    //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met

    //remove ALL enchants
    for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
        _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), false);

    for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
    {
        if (GemEnchants[i])
        {
            itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0);
            if (Item* guidItem = _player->GetItemByGuid(gem_guids[i]))
                _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true);
        }
    }

    for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
        _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true);

    bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
    if (SocketBonusActivated ^ SocketBonusToBeActivated)     //if there was a change...
    {
        _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false);
        itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->socketBonus : 0), 0, 0);
        _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true);
        //it is not displayed, client has an inbuilt system to determine if the bonus is activated
    }

    _player->ToggleMetaGemsActive(slot, true);              //turn on all metagems (except for target item)

    _player->RemoveTradeableItem(itemTarget);
    itemTarget->ClearSoulboundTradeable(_player);           // clear tradeable flag
}
            void HandleAfterHit()
            {
                if (_stackAmount < 5)
                    return;

                Player* player = GetCaster()->ToPlayer();

                if (Unit* target = GetHitUnit())
                {

                    Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);

                    if (item == GetCastItem())
                        item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);

                    if (!item)
                        return;

                    // item combat enchantments
                    for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
                    {
                        SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot)));
                        if (!enchant)
                            continue;

                        for (uint8 s = 0; s < 3; ++s)
                        {
                            if (enchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
                                continue;

                            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(enchant->spellid[s]);
                            if (!spellInfo)
                            {
                                sLog->outError("Player::CastItemCombatSpell Enchant %i, player (Name: %s, GUID: %u) cast unknown spell %i", enchant->ID, player->GetName(), player->GetGUIDLow(), enchant->spellid[s]);
                                continue;
                            }

                            // Proc only rogue poisons
                            if (spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE || spellInfo->Dispel != DISPEL_POISON)
                                continue;

                            // Do not reproc deadly
                            if (spellInfo->SpellFamilyFlags.IsEqual(0x10000, 0x80000, 0))
                                continue;

                            if (spellInfo->IsPositive())
                                player->CastSpell(player, enchant->spellid[s], true, item);
                            else
                                player->CastSpell(target, enchant->spellid[s], true, item);
                        }
                    }
                }
            }