예제 #1
0
void WorldSession::HandleInitiateTrade(WorldPacket & recv_data)
{
	CHECK_INWORLD_RETURN;

	CHECK_PACKET_SIZE(recv_data, 8);

	uint64 guid;
	recv_data >> guid;

	uint32 TradeStatus = TRADE_STATUS_PROPOSED;

	Player* pTarget = _player->GetMapMgr()->GetPlayer((uint32)guid);
	if(pTarget == NULL || !pTarget->IsInWorld())
		TradeStatus = TRADE_STATUS_PLAYER_NOT_FOUND;
	else
	{
		// Handle possible error outcomes
		if(_player->isDead())
			TradeStatus = TRADE_STATUS_DEAD;
		else if(pTarget->isDead())
			TradeStatus = TRADE_STATUS_TARGET_DEAD;
		else if(_player->IsStunned())
			TradeStatus = TRADE_STATUS_YOU_STUNNED;
		else if(pTarget->IsStunned())
			TradeStatus = TRADE_STATUS_TARGET_STUNNED;
		else if(pTarget->mTradeTarget != 0)
			TradeStatus = TRADE_STATUS_ALREADY_TRADING;
		else if(pTarget->GetTeam() != _player->GetTeam() && GetPermissionCount() == 0)
			TradeStatus = TRADE_STATUS_WRONG_FACTION;
		else if(_player->CalcDistance(pTarget) > 10.0f)		// This needs to be checked
			TradeStatus = TRADE_STATUS_TOO_FAR_AWAY;
		set<uint32>::iterator itr = pTarget->m_ignores.find(_player->GetLowGUID());
		if(itr != pTarget->m_ignores.end())
			TradeStatus = TRADE_STATUS_PLAYER_IGNORED;
	}

	if(TradeStatus != TRADE_STATUS_PROPOSED)
	{
		_player->ResetTradeVariables();
		SendTradeStatus(TradeStatus);
	}
	else
	{
		_player->ResetTradeVariables();
		pTarget->ResetTradeVariables();

		pTarget->mTradeTarget = _player->GetLowGUID();
		_player->mTradeTarget = pTarget->GetLowGUID();

		pTarget->mTradeStatus = TradeStatus;
		_player->mTradeStatus = TradeStatus;

		WorldPacket data(SMSG_TRADE_STATUS, 12);
		data << TradeStatus;
		data << _player->GetGUID();

		if(pTarget->m_session && pTarget->m_session->GetSocket())
			pTarget->m_session->SendPacket(&data);
	}
}
예제 #2
0
void WorldSession::HandleInitiateTrade(WorldPacket & recv_data)
{
	if(!_player->IsInWorld()) return;
	CHECK_PACKET_SIZE(recv_data, 8);
	uint64 guid;
	recv_data >> guid;
	Player * pTarget = _player->GetMapMgr()->GetPlayer((uint32)guid);
	uint32 TradeStatus = TRADE_STATUS_PROPOSED;
	WorldPacket data(SMSG_TRADE_STATUS, 12);

	if(pTarget == 0)
	{
#ifdef USING_BIG_ENDIAN
		TradeStatus = swap32(uint32(TRADE_STATUS_PLAYER_NOT_FOUND));
#else
		TradeStatus = TRADE_STATUS_PLAYER_NOT_FOUND;
#endif
		OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
		return;
	}

	// Handle possible error outcomes
	if(pTarget->CalcDistance(_player) > 10.0f)		// This needs to be checked
		TradeStatus = TRADE_STATUS_TOO_FAR_AWAY;
	else if(pTarget->isDead())
		TradeStatus = TRADE_STATUS_DEAD;
	else if(pTarget->mTradeTarget != 0)
		TradeStatus = TRADE_STATUS_ALREADY_TRADING;
	else if(pTarget->GetTeam() != _player->GetTeam() && GetPermissionCount() == 0 && !sWorld.interfaction_trade)
		TradeStatus = TRADE_STATUS_WRONG_FACTION;

	data << TradeStatus;

	if(TradeStatus == TRADE_STATUS_PROPOSED)
	{
		_player->ResetTradeVariables();
		pTarget->ResetTradeVariables();

		pTarget->mTradeTarget = _player->GetLowGUID();
		_player->mTradeTarget = pTarget->GetLowGUID();

		pTarget->mTradeStatus = TradeStatus;
		_player->mTradeStatus = TradeStatus;

		data << _player->GetGUID();
	}

	pTarget->m_session->SendPacket(&data);
}
예제 #3
0
void WorldSession::HandleChannelJoin(WorldPacket & recvPacket)
{
	CHECK_INWORLD_RETURN

	CHECK_PACKET_SIZE(recvPacket, 1);
	string channelname, pass;
	uint32 dbc_id = 0;
	uint16 crap;		// crap = some sort of channel type?
	Channel* chn;

	recvPacket >> dbc_id >> crap;
	recvPacket >> channelname;
	recvPacket >> pass;

	if(sWorld.GmClientChannel.size() && !stricmp(sWorld.GmClientChannel.c_str(), channelname.c_str()) && !GetPermissionCount())
		return;

	chn = channelmgr.GetCreateChannel(channelname.c_str(), _player, dbc_id);
	if(chn == NULL)
		return;

	chn->AttemptJoin(_player, pass.c_str());
	Log.Debug("ChannelJoin", "%s", channelname.c_str());
}
예제 #4
0
void WorldSession::HandleAcceptTrade(WorldPacket & recv_data)
{
	if(!_player->IsInWorld() || _player->mTradeTarget == 0)
		return;

	uint32 TradeStatus = TRADE_STATUS_ACCEPTED;

	Player* pTarget = _player->GetTradeTarget();
	if(pTarget == NULL || !pTarget->IsInWorld())
		TradeStatus = TRADE_STATUS_PLAYER_NOT_FOUND;

	// Tell the other player we're green.
	if(pTarget->m_session && pTarget->m_session->GetSocket())
		pTarget->m_session->SendTradeStatus(TradeStatus);

	_player->mTradeStatus = TradeStatus;

	//Both sides accepted? Let's trade!
	if(_player->mTradeStatus == TRADE_STATUS_ACCEPTED && pTarget->mTradeStatus == TRADE_STATUS_ACCEPTED)
	{
		// Ready!
		uint32 ItemCount = 0;
		uint32 TargetItemCount = 0;
		Item* pItem;

		// Count items on both sides, check if bags are empty.
		for(uint32 Index = 0; Index < 6; Index++)
		{
			if(_player->mTradeItems[Index] != NULL)
			{
				pItem = _player->mTradeItems[Index];
				if( pItem != NULL && pItem->IsContainer() && TO_CONTAINER(pItem)->HasItems())
				{
					sWorld.LogCheater(this, "%s involved in bag-trick trade with %s", _player->GetName(),pTarget->GetName());
					_player->GetItemInterface()->BuildInventoryChangeError(	pItem, NULLITEM, INV_ERR_CANT_TRADE_EQUIP_BAGS);
					TradeStatus = TRADE_STATUS_CANCELLED;
					break;
				}
				else
					++ItemCount;
			}
			if(pTarget->mTradeItems[Index] != NULL)
			{
				pItem = pTarget->mTradeItems[Index];
				if( pItem != NULL && pItem->IsContainer() && TO_CONTAINER(pItem)->HasItems() )
				{
					sWorld.LogCheater(this, "%s involved in bag-trick trade with %s.", pTarget->GetName(),_player->GetName());
					pTarget->GetItemInterface()->BuildInventoryChangeError(	pItem, NULLITEM, INV_ERR_CANT_TRADE_EQUIP_BAGS);
					TradeStatus = TRADE_STATUS_CANCELLED;
					break;
				}
				else
					++TargetItemCount;
			}
		}
		//Do we have something to trade?
		if( ItemCount == 0 && TargetItemCount == 0 && _player->mTradeGold == 0 && pTarget->mTradeGold == 0 )
			TradeStatus = TRADE_STATUS_CANCELLED;
		//Do we have enough free slots on both sides?
		else if((_player->m_ItemInterface->CalculateFreeSlots(NULL) + ItemCount) < TargetItemCount || (pTarget->m_ItemInterface->CalculateFreeSlots(NULL) + TargetItemCount) < ItemCount )
			TradeStatus = TRADE_STATUS_CANCELLED;
		//Everything still ok?
		if(TradeStatus == TRADE_STATUS_ACCEPTED)
		{
			uint64 Guid;

			//Swapp 6 itemslots (7th will not trade)
			for(uint32 Index = 0; Index < 6; Index++)
			{
				Guid = _player->mTradeItems[Index] ? _player->mTradeItems[Index]->GetGUID() : 0;
				if(Guid != 0)
				{
					if( _player->mTradeItems[Index]->IsSoulbound())
						_player->GetItemInterface()->BuildInventoryChangeError(	_player->mTradeItems[Index], NULLITEM, INV_ERR_CANNOT_TRADE_THAT);
					else
					{
						//Remove from player
						pItem = _player->m_ItemInterface->SafeRemoveAndRetreiveItemByGuidRemoveStats(Guid, true);

						//and add to pTarget
						if(pItem != NULL)
						{
							pItem->SetOwner(pTarget);
							if( !pTarget->m_ItemInterface->AddItemToFreeSlot(pItem) )
							{
								pItem->DeleteMe();
								pItem = NULL;
							}
						}

						if(GetPermissionCount()>0 || pTarget->GetSession()->GetPermissionCount()>0)
							sWorld.LogGM(this, "trade item %s with %s (soulbound = %d)", _player->mTradeItems[Index]->GetProto()->Name1, pTarget->GetName());
					}
				}

				Guid = pTarget->mTradeItems[Index] ? pTarget->mTradeItems[Index]->GetGUID() : 0;
				if(Guid != 0)
				{
					if( pTarget->mTradeItems[Index]->IsSoulbound())
						pTarget->GetItemInterface()->BuildInventoryChangeError(	pTarget->mTradeItems[Index], NULLITEM, INV_ERR_CANNOT_TRADE_THAT);
					else
					{
						//Remove from pTarget
						pItem = pTarget->m_ItemInterface->SafeRemoveAndRetreiveItemByGuidRemoveStats(Guid, true);

						//and add to initiator
						if(pItem != NULL)
						{
							pItem->SetOwner(_player);
							if( !_player->m_ItemInterface->AddItemToFreeSlot(pItem) )
							{
								pItem->DeleteMe();
								pItem = NULL;
							}

						}

						if(GetPermissionCount()>0 || pTarget->GetSession()->GetPermissionCount()>0)
							sWorld.LogGM(this, "trade item %s with %s", pTarget->mTradeItems[Index]->GetProto()->Name1, _player->GetName());
					}
				}
			}


			// Trade Gold
			if(_player->mTradeGold)
			{
				pTarget->ModUnsigned32Value(PLAYER_FIELD_COINAGE, _player->mTradeGold);
				_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -(int32)_player->mTradeGold);
			}
			if(pTarget->mTradeGold)
			{
				_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, pTarget->mTradeGold);
				pTarget->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -(int32)pTarget->mTradeGold);
			}

			pTarget->SaveToDB(false);
			_player->SaveToDB(false);

			TradeStatus = TRADE_STATUS_COMPLETE;
		}

		SendTradeStatus(TradeStatus);
		if(pTarget->m_session && pTarget->m_session->GetSocket())
			pTarget->m_session->SendTradeStatus(TradeStatus);

		// Reset Trade Vars
		_player->ResetTradeVariables();
		pTarget->ResetTradeVariables();
	}
}
예제 #5
0
void WorldSession::HandleSendMail(WorldPacket& recvData)
{
    MailMessage msg;
    ObjectGuid mailbox;
    uint32_t unk1, unk2;
    uint64_t money, COD;

    std::vector< Item* > items;
    Item* pItem;

    recvData >> unk1;
    recvData >> unk2;

    recvData >> COD;
    recvData >> money;

    uint32_t bodyLength = recvData.readBits(12);
    uint32_t subjectLength = recvData.readBits(9);

    uint8_t items_count = static_cast<uint8_t>(recvData.readBits(5));              // attached items count

    if (items_count > MAIL_MAX_ITEM_SLOT)
    {
        SendMailError(MAIL_ERR_TOO_MANY_ATTACHMENTS);
        return;
    }

    mailbox[0] = recvData.readBit();

    ObjectGuid itemGUIDs[MAIL_MAX_ITEM_SLOT];

    for (uint8_t i = 0; i < items_count; ++i)
    {
        itemGUIDs[i][2] = recvData.readBit();
        itemGUIDs[i][6] = recvData.readBit();
        itemGUIDs[i][3] = recvData.readBit();
        itemGUIDs[i][7] = recvData.readBit();
        itemGUIDs[i][1] = recvData.readBit();
        itemGUIDs[i][0] = recvData.readBit();
        itemGUIDs[i][4] = recvData.readBit();
        itemGUIDs[i][5] = recvData.readBit();
    }

    mailbox[3] = recvData.readBit();
    mailbox[4] = recvData.readBit();
    uint32_t receiverLength = recvData.readBits(7);
    mailbox[2] = recvData.readBit();
    mailbox[6] = recvData.readBit();
    mailbox[1] = recvData.readBit();
    mailbox[7] = recvData.readBit();
    mailbox[5] = recvData.readBit();

    recvData.ReadByteSeq(mailbox[4]);

    for (uint8_t i = 0; i < items_count; ++i)
    {
        recvData.ReadByteSeq(itemGUIDs[i][6]);
        recvData.ReadByteSeq(itemGUIDs[i][1]);
        recvData.ReadByteSeq(itemGUIDs[i][7]);
        recvData.ReadByteSeq(itemGUIDs[i][2]);
        recvData.read_skip<uint8_t>();            // item slot in mail, not used
        recvData.ReadByteSeq(itemGUIDs[i][3]);
        recvData.ReadByteSeq(itemGUIDs[i][0]);
        recvData.ReadByteSeq(itemGUIDs[i][4]);
        recvData.ReadByteSeq(itemGUIDs[i][5]);
    }

    recvData.ReadByteSeq(mailbox[7]);
    recvData.ReadByteSeq(mailbox[3]);
    recvData.ReadByteSeq(mailbox[6]);
    recvData.ReadByteSeq(mailbox[5]);

    std::string subject = recvData.ReadString(subjectLength);
    std::string receiver = recvData.ReadString(receiverLength);

    recvData.ReadByteSeq(mailbox[2]);
    recvData.ReadByteSeq(mailbox[0]);

    std::string body = recvData.ReadString(bodyLength);

    recvData.ReadByteSeq(mailbox[1]);

    // Search for the recipient
    PlayerInfo* player_info = ObjectMgr::getSingleton().GetPlayerInfoByName(receiver.c_str());
    if (!player_info)
    {
        SendMailError(MAIL_ERR_RECIPIENT_NOT_FOUND);
        return;
    }

    for (uint8_t i = 0; i < items_count; ++i)
    {
        pItem = _player->GetItemInterface()->GetItemByGUID(itemGUIDs[i]);
        if (pItem == nullptr || pItem->isSoulbound() || pItem->hasFlags(ITEM_FLAG_CONJURED))
        {
            SendMailError(MAIL_ERR_INTERNAL_ERROR);
            return;
        }
        if (pItem->isAccountbound() && GetAccountId() != player_info->acct) // don't mail account-bound items to another account
        {
            WorldPacket data(SMSG_SEND_MAIL_RESULT, 16);
            data << uint32_t(0);
            data << uint32_t(0);
            data << uint32_t(MAIL_ERR_BAG_FULL);
            data << uint32_t(INV_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS);
            SendPacket(&data);
            return;
        }

        items.push_back(pItem);
    }

    if (receiver.empty())
        return;

    bool interfaction = false;
    if (sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION) || (HasGMPermissions() && sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM)))
    {
        interfaction = true;
    }

    // Check we're sending to the same faction (disable this for testing)
    if (player_info->team != _player->GetTeam() && !interfaction)
    {
        SendMailError(MAIL_ERR_NOT_YOUR_ALLIANCE);
        return;
    }

    // Check if we're sending mail to ourselves
    if (strcmp(player_info->name, _player->GetName()) == 0 && !GetPermissionCount())
    {
        SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF);
        return;
    }

    if (msg.stationery == MAIL_STATIONERY_GM && !HasGMPermissions())
    {
        SendMailError(MAIL_ERR_INTERNAL_ERROR);
        return;
    }

    // Instant delivery time by default.
    msg.delivery_time = (uint32_t)UNIXTIME;

    // Set up the cost
    uint32_t cost = items_count ? 30 * items_count : 30;  // price hardcoded in client

    if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_POSTAGE_COSTS) && !(GetPermissionCount() && sMailSystem.MailOption(MAIL_FLAG_NO_COST_FOR_GM)))
    {
        cost += 30;
    }

    // check that we have enough in our backpack
    if (!_player->HasGold(cost))
    {
        SendMailError(MAIL_ERR_NOT_ENOUGH_MONEY);
        return;
    }

    // Check for the item, and required item.
    if (!items.empty())
    {
        for (std::vector< Item* >::iterator itr = items.begin(); itr != items.end(); ++itr)
        {
            pItem = *itr;
            if (_player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->getGuid(), false) != pItem)
                continue;        // should never be hit.

            pItem->RemoveFromWorld();
            pItem->setOwner(NULL);
            pItem->SaveToDB(INVENTORY_SLOT_NOT_SET, 0, true, NULL);
            msg.items.push_back(pItem->getGuidLow());

            if (GetPermissionCount() > 0)
            {
                /* log the message */
                sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->getEntry(), player_info->name, money);
            }

            pItem->DeleteMe();
        }
    }

    if (money != 0 || COD != 0 || (!items.size() && player_info->acct != _player->GetSession()->GetAccountId()))
    {
        if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS))
            msg.delivery_time += 3600;  // 1hr
    }

    // take the money
    _player->ModGold(-static_cast<int32_t>(cost));

    // Fill in the rest of the info
    msg.player_guid = player_info->guid;
    msg.sender_guid = _player->getGuid();
    msg.money = static_cast<uint32_t>(money);
    msg.cod = static_cast<uint32_t>(COD);
    msg.subject = subject;
    msg.body = body;

    // 30 day expiry time for unread mail
    if (!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY))
        msg.expire_time = (uint32_t)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME);
    else
        msg.expire_time = 0;

    msg.deleted_flag = false;
    msg.message_type = 0;
    msg.checked_flag = msg.body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY;

    // Great, all our info is filled in. Now we can add it to the other players mailbox.
    sMailSystem.DeliverMessage(player_info->guid, &msg);
    // Save/Update character's gold if they've received gold that is. This prevents a rollback.
    CharacterDatabase.Execute("UPDATE characters SET gold = %u WHERE guid = %u", _player->GetGold(), _player->m_playerInfo->guid);
    // Success packet :)
    SendMailError(MAIL_OK);
}
예제 #6
0
void WorldSession::HandleInitiateTrade(WorldPacket & recv_data)
{
	if(!_player->IsInWorld()) 
	{ 
		return;
	}
#ifdef FORCED_GM_TRAINEE_MODE
	if( CanUseCommand('k') && !HasGMPermissions() )
	{
		GetPlayer()->BroadcastMessage( "You are not allowed to use this feature" );
		return;
	}
#endif
	if( sWorld.getIntRate( INTRATE_DISABLE_TRADE_FEATURE ) )
	{
		GetPlayer()->BroadcastMessage( "Trade feature is disabled right now" );
		return;
	}
//	CHECK_PACKET_SIZE(recv_data, 8);
//	uint64 guid;
//	recv_data >> guid;
	uint8 GUID_mask;
	uint8 GUID_bytes[8];
	memset( GUID_bytes, 0, sizeof( GUID_bytes ) );

	recv_data >> GUID_mask;

	if( GUID_mask & BIT_0x01 )
		recv_data >> GUID_bytes[2];
	if( GUID_mask & BIT_0x02 )
		recv_data >> GUID_bytes[1];
	if( GUID_mask & BIT_0x40 )
		recv_data >> GUID_bytes[3];
	if( GUID_mask & BIT_0x04 )
		recv_data >> GUID_bytes[0];

	uint8 GUID_bytes_obfuscated[8];
	*(uint64*)GUID_bytes_obfuscated = *(uint64*)GUID_bytes;

	GUID_un_obfuscate( GUID_bytes );
	Player * pTarget = _player->GetMapMgr()->GetPlayer( *(uint64*)GUID_bytes );
	uint32 TradeStatus = TRADE_STATUS_PROPOSED;

	if(pTarget == 0)
	{
		TradeStatus = TRADE_STATUS_PLAYER_NOT_FOUND;
		OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
		return;
	}

	// Handle possible error outcomes
	if(pTarget->CalcDistance(_player) > 10.0f)		// This needs to be checked
		TradeStatus = TRADE_STATUS_TOO_FAR_AWAY;
	else if(pTarget->IsDead())
		TradeStatus = TRADE_STATUS_DEAD;
	else if(pTarget->mTradeTarget != 0)
		TradeStatus = TRADE_STATUS_ALREADY_TRADING;
	else if(pTarget->GetTeam() != _player->GetTeam() && GetPermissionCount() == 0 && !sWorld.interfaction_trade)
		TradeStatus = TRADE_STATUS_WRONG_FACTION;

	if(TradeStatus == TRADE_STATUS_PROPOSED)
	{
		_player->ResetTradeVariables();
		pTarget->ResetTradeVariables();

		pTarget->mTradeTarget = _player->GetLowGUID();
		_player->mTradeTarget = pTarget->GetLowGUID();

		pTarget->mTradeStatus = TradeStatus;
		_player->mTradeStatus = TradeStatus;
	}
/*
13329
ME
{CLIENT} Packet: (0x4106) CMSG_INITIATE_TRADE PacketSize = 8 TimeStamp = 32130418
8A A9 79 02 00 00 00 04 
to me
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32131338
0E 69 2B 33 18 8A A9 79 02 00 00 00 04 03 00 00 00 AB 2A 00 00 90 BC 61 58 AB 01 00 00 00 00 00 00 00 -> trade proposed
to him
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32209838
80 B9 46 42 98 8A A9 79 02 00 00 00 04 90 BC 61 58 AB 2A 00 00 B3 47 A5 00 00 01 00 00 00 AB 2A 00 00 -> trade proposed
him
{CLIENT} Packet: (0x4107) CMSG_BEGIN_TRADE PacketSize = 0 TimeStamp = 32209854

to me
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32131338
01 00 00 00 00 10 BD 46 42 00 00 00 00 88 E3 29 0E 00 00 00 00 07 01 00 00 00 02 00 00 00 AB 2A 00 00 -> trade initiated
to him
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32209994
00 00 00 00 AE 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 09 01 00 00 00 02 00 00 00 00 00 00 00 -> trade initiated 
to me
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32379442
80 B9 46 42 98 10 BD 46 42 00 00 00 00 00 00 00 00 AA 2A 00 00 10 0A 6C 58 AB 08 00 00 00 00 00 00 00 ->trade complete
to him
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32456725
05 00 00 00 0A 20 B8 46 42 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 04 00 00 00 00 00 00 00 ->trade accepted
to him
{SERVER} Packet: (0x2830) SMSG_TRADE_STATUS PacketSize = 34 TimeStamp = 32460750
80 B9 46 42 98 10 BD 46 42 00 00 00 00 00 00 00 00 AA 2A 00 00 10 0A 6C 58 AB 08 00 00 00 00 00 00 00 ->trade complete

14333
/////////////////////////////////////////
E9 D7 38 03 00 00 00 01 GUID OF A
07 E2 91 03 00 00 00 01 GUID OF B
A asks B to trade
{CLIENT} Packet: (0x3863) CMSG_INITIATE_TRADE PacketSize = 6 TimeStamp = 14190240
67 90 E3 02 00 06 
server sends back to A confirmation of the received invite
{SERVER} Packet: (0xDB61) SMSG_TRADE_STATUS PacketSize = 33 TimeStamp = 14190989
5D 00 00 01 00 00 00 00 00 00 00 90 02 00 00 00 00 00 00 06 80 7F 0D 41 E3 03 00 00 00 29 B4 5E 2D 
//maybe some auto click by client on some popup
{CLIENT} Packet: (0x98CA) UNKNOWN PacketSize = 0 TimeStamp = 14191005

probably the other client accepted the trade
{SERVER} Packet: (0xDB61) SMSG_TRADE_STATUS PacketSize = 31 TimeStamp = 14191301
49 00 00 02 00 00 00 AB 2A 00 00 DB 00 09 00 00 00 0A 40 80 0D 41 0A 20 84 0D 41 2C 31 E9 00 
/////////////////////////////////////////
B asks A to trade
{SERVER} Packet: (0xDB61) SMSG_TRADE_STATUS PacketSize = 33 TimeStamp = 14208430
5D 00 2A 01 00 00 00 AB 2A 00 00 90 02 00 00 00 00 00 01 06 30 7F 0D 41 E3 07 E2 91 03 30 95 A8 4A compressed guid of the inviter
B accepts trade
{CLIENT} Packet: (0x0869) UNKNOWN PacketSize = 0 TimeStamp = 14208430

server lets B know that he received the previous packet
{SERVER} Packet: (0xDB61) SMSG_TRADE_STATUS PacketSize = 32 TimeStamp = 14208851
59 00 01 02 00 00 00 00 00 00 00 16 00 00 0A 00 00 00 DD E0 85 0D 41 BC B0 7D 0D 41 67 00 00 00 
/////////////////////////////////////////
*/
/*
we receive invite
{SERVER} Packet: (0xDB61) SMSG_TRADE_STATUS PacketSize = 33 TimeStamp = 14208430
5D 00 mask - 5 bits
2A junk
01 00 00 00 status ?
AB 2A 00 00 famous contant value or 0
90 - go2 B we are asking this guy to accept our trade
02 - go3 B we are asking this guy to accept our trade
00 00 00 00 00 00 - junk ?
06 - go0 B we are asking this guy to accept our trade
80 7F 0D 41 - magic float ? 
E3 - go1 B we are asking this guy to accept our trade
07 E2 91 03 lowguid of the other guy junk ?
30 95 A8 4A serializer ?
*/
	//right now trade initiator does not need this packet
/*	{
		sStackWorldPacket( data, SMSG_TRADE_STATUS, 44 + 10 );
		data << uint16( 0x59 ); // mask bit_2 might be go0, bit_0 might be go7
		data << uint8( 0 ); // junk
//		data << ObfuscateByte( GUID_bytes[6] );
		data << uint32( TRADE_STATUS_PROPOSED );	
		data << uint32( TRADE_ID_CONST ); //used a lot of times or 0
		data << ObfuscateByte( GUID_bytes[2] );
		data << ObfuscateByte( GUID_bytes[3] );
		data << uint8( 0 ); // junk
		data << uint32( 0x00000000 ); // highguid or junk
//		data << ObfuscateByte( GUID_bytes[7] );
		data << ObfuscateByte( GUID_bytes[0] );
		data << float( 0 ); // junk
		data << ObfuscateByte( GUID_bytes[1] );
		data << uint32( pTarget->GetLowGUID() ); // junk
		data << uint32( 0x00000000 ); // could be trade ID. Like A asks B, B refuses, A received back this number
		SendPacket( &data );
	}/**/
//	_player->SendTradeUpdate( 0 );
	//trade target does need this packet so he can auto reply with CMSG_BEGIN_TRADE
	{
		*(uint64*)GUID_bytes = _player->GetGUID();
		sStackWorldPacket( data, SMSG_TRADE_STATUS, 44 + 10 );
		data << uint16( 0x59 ); // mask bit_2 might be go0, bit_0 might be go7
		data << uint8( 0 ); // junk, can send 0 also
//		data << ObfuscateByte( GUID_bytes[6] );
		data << uint32( TRADE_STATUS_PROPOSED );	
		data << uint32( TRADE_ID_CONST ); //used a lot of times or 0, 
		data << ObfuscateByte( GUID_bytes[2] );
		data << ObfuscateByte( GUID_bytes[3] );
		data << uint8( 0 ); // junk
		data << uint32( 0x00000000 ); // highguid ? trade session counter ? junk ?
//		data << ObfuscateByte( GUID_bytes[7] );
		data << ObfuscateByte( GUID_bytes[0] );
		data << float( 0 ); // junk seems to be some float sometimes 
		data << ObfuscateByte( GUID_bytes[1] );
		data << uint32( _player->GetLowGUID() ); // lowguid ? junk ?
		data << uint32( 0 ); // could be trade ID. Like A asks B, B refuses, A received back this number. Or it could be time, global packet serializer
		pTarget->m_session->SendPacket( &data );
	}/**/
//	pTarget->SendTradeUpdate( 0 );
}
예제 #7
0
void WorldSession::HandleChannelJoin(WorldPacket& recvPacket)
{
    CHECK_INWORLD_RETURN

    CHECK_PACKET_SIZE(recvPacket, 1);
    std::string channelname, pass;
    uint32 channel_id;

    recvPacket >> channel_id;
    recvPacket.readBit();       // has voice
    recvPacket.readBit();       // zone update

    uint8 channelLength = recvPacket.readBits(8);
    uint8 passwordLength = recvPacket.readBits(8);

    channelname = recvPacket.ReadString(channelLength);
    pass = recvPacket.ReadString(passwordLength);

    if (sWorld.settings.gm.gmClientChannelName.size() && !stricmp(sWorld.settings.gm.gmClientChannelName.c_str(), channelname.c_str()) && !GetPermissionCount())
        return;

    Channel* channel = channelmgr.GetCreateChannel(channelname.c_str(), _player, channel_id);
    if (channel == nullptr)
        return;

    channel->AttemptJoin(_player, pass.c_str());
    LogDebugFlag(LF_OPCODE, "ChannelJoin %s", channelname.c_str());
}
예제 #8
0
void WorldSession::HandleSendMail(WorldPacket& recv_data)
{
    CHECK_INWORLD_RETURN

    MailMessage msg;
    uint64 gameobject;
    uint32 unk2;
    uint8 itemcount;
    uint8 itemslot;
    uint8 i;
    uint64 itemguid;
    std::vector< Item* > items;
    std::vector< Item* >::iterator itr;
    std::string recepient;
    Item* pItem;
    //uint32 err = MAIL_OK;

    recv_data >> gameobject >> recepient;
    recv_data >> msg.subject >> msg.body >> msg.stationery;
    recv_data >> unk2 >> itemcount;

    if (itemcount > MAIL_MAX_ITEM_SLOT || msg.body.find("%") != std::string::npos || msg.subject.find("%") != std::string::npos)
    {
        SendMailError(MAIL_ERR_INTERNAL_ERROR);
        return;
    }

    // Search for the recipient
    PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str());
    if (player == NULL)
    {
        SendMailError(MAIL_ERR_RECIPIENT_NOT_FOUND);
        return;
    }

    for (i = 0; i < itemcount; ++i)
    {
        recv_data >> itemslot;
        recv_data >> itemguid;

        pItem = _player->GetItemInterface()->GetItemByGUID(itemguid);
        if (pItem == NULL || pItem->IsSoulbound() || pItem->IsConjured())
        {
            SendMailError(MAIL_ERR_INTERNAL_ERROR);
            return;
        }
        if (pItem->IsAccountbound() && GetAccountId() != player->acct) // don't mail account-bound items to another account
        {
            WorldPacket data(SMSG_SEND_MAIL_RESULT, 16);
            data << uint32(0);
            data << uint32(0);
            data << uint32(MAIL_ERR_BAG_FULL);
            data << uint32(INV_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS);
            SendPacket(&data);
            return;
        }

        items.push_back(pItem);
    }

    recv_data >> msg.money;
    recv_data >> msg.cod;
    ///\todo left over: (TODO- FIX ME BURLEX!)
    // uint32
    // uint32
    // uint8

    bool interfaction = false;
    if (sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION) || (HasGMPermissions() && sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM)))
    {
        interfaction = true;
    }

    // Check we're sending to the same faction (disable this for testing)
    if (player->team != _player->GetTeam() && !interfaction)
    {
        SendMailError(MAIL_ERR_NOT_YOUR_ALLIANCE);
        return;
    }

    // Check if we're sending mail to ourselves
    if (strcmp(player->name, _player->GetName()) == 0 && !GetPermissionCount())
    {
        SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF);
        return;
    }

    if (msg.stationery == MAIL_STATIONERY_GM && !HasGMPermissions())
    {
        SendMailError(MAIL_ERR_INTERNAL_ERROR);
        return;
    }

    // Instant delivery time by default.
    msg.delivery_time = (uint32)UNIXTIME;

    // Set up the cost
    int32 cost = 0;

    // Check for attached money
    if (msg.money > 0)
        cost += msg.money;


    if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_POSTAGE_COSTS) && !(GetPermissionCount() && sMailSystem.MailOption(MAIL_FLAG_NO_COST_FOR_GM)))
    {
        cost += 30;
    }

    // check that we have enough in our backpack
    if (!_player->HasGold(cost))
    {
        SendMailError(MAIL_ERR_NOT_ENOUGH_MONEY);
        return;
    }

    // Check for the item, and required item.
    if (!items.empty())
    {
        for (itr = items.begin(); itr != items.end(); ++itr)
        {
            pItem = *itr;
            if (_player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem)
                continue;        // should never be hit.

            pItem->RemoveFromWorld();
            pItem->SetOwner(NULL);
            pItem->SaveToDB(INVENTORY_SLOT_NOT_SET, 0, true, NULL);
            msg.items.push_back(pItem->GetLowGUID());

            if (GetPermissionCount() > 0)
            {
                /* log the message */
                sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money);
            }

            pItem->DeleteMe();
        }
    }

    if (msg.money != 0 || msg.cod != 0 || (!msg.items.size() && player->acct != _player->GetSession()->GetAccountId()))
    {
        if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS))
            msg.delivery_time += 3600;  // 1hr
    }

    // take the money
    _player->ModGold(-cost);

    // Fill in the rest of the info
    msg.player_guid = player->guid;
    msg.sender_guid = _player->GetGUID();

    // 30 day expiry time for unread mail
    if (!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY))
        msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME);
    else
        msg.expire_time = 0;

    msg.deleted_flag = false;
    msg.message_type = 0;
    msg.checked_flag = msg.body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY;

    // Great, all our info is filled in. Now we can add it to the other players mailbox.
    sMailSystem.DeliverMessage(player->guid, &msg);
    // Save/Update character's gold if they've received gold that is. This prevents a rollback.
    CharacterDatabase.Execute("UPDATE characters SET gold = %u WHERE guid = %u", _player->GetGold(), _player->m_playerInfo->guid);
    // Success packet :)
    SendMailError(MAIL_OK);
}
예제 #9
0
void WorldSession::_HandleAreaTriggerOpcode(uint32 id)
{		
	sLog.outDebug("AreaTrigger: %u", id);

	WorldPacket data(80);
	AreaTrigger * pAreaTrigger = AreaTriggerStorage.LookupEntry(id);

	// Search quest log, find any exploration quests
	sQuestMgr.OnPlayerExploreArea(GetPlayer(),id);
	
	// if in BG handle is triggers
	if(GetPlayer()->m_bgInBattleground && GetPlayer()->GetCurrentBattleground() != NULL)
	{
		GetPlayer()->GetCurrentBattleground()->HandleBattlegroundAreaTrigger(GetPlayer(), id);
		return;
	}   

	if(GetPermissionCount())
	{
		sChatHandler.BlueSystemMessage(this, "[%sSystem%s] |rEntered areatrigger: %s%u.", MSG_COLOR_WHITE, MSG_COLOR_LIGHTBLUE, 
			MSG_COLOR_SUBWHITE, id);
	}

	/* if we don't have an areatrigger, create one on the stack to use for gm scripts :p */
	if(!pAreaTrigger)
	{
		AreaTrigger tmpTrigger;
		tmpTrigger.AreaTriggerID = id;

		ScriptSystem->OnActivateAreaTrigger(&tmpTrigger, _player);
		return;
	}

	/* script prerequsites */
	if(ScriptSystem->OnActivateAreaTrigger(pAreaTrigger, _player) == false)
		return;

	if(pAreaTrigger->Type == ATTYPE_BATTLEGROUND)
	{
		if(pAreaTrigger->Mapid == 489)		// hack fix
			pAreaTrigger->Mapid = 2;
		else if(pAreaTrigger->Mapid == 529)
			pAreaTrigger->Mapid = 3;
		else if(pAreaTrigger->Mapid == 30)
			pAreaTrigger->Mapid = 1;
			
		WorldPacket *pkt = sBattlegroundMgr.BuildBattlegroundListPacket(GetPlayer()->GetGUID(), _player,
			pAreaTrigger->Mapid);
		SendPacket(pkt);
		delete pkt;
		return;
	}

	bool bFailedPre = false;
	std::string failed_reason;

	if(pAreaTrigger->required_level)
	{
		if(GetPlayer()->getLevel() < pAreaTrigger->required_level)
		{
			bFailedPre = true;
			if(failed_reason.size() > 0)
				failed_reason += ", and ";
			else
				failed_reason = "You must be ";

			// mm hacky
			char lvltext[30];
			snprintf(lvltext, 30, "at least level %d", (int)pAreaTrigger->required_level);
			failed_reason += lvltext;
		}
	}
	if(bFailedPre)
	{
		failed_reason += " before you're allowed through here.";
		WorldPacket msg;
		msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
		msg << uint32(0) << failed_reason << uint8(0);
		SendPacket(&msg);
		sLog.outDebug("Player %s failed areatrigger prereq - %s", GetPlayer()->GetName(), failed_reason.c_str());
		return;
	}
	switch(pAreaTrigger->Type)
	{
	case ATTYPE_INSTANCE:
		{
			if(GetPlayer()->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
			{
				GetPlayer()->SaveEntryPoint(pAreaTrigger->Mapid);

				//death system check.
				Corpse *pCorpse = NULL;
//					CorpseData *pCorpseData = NULL;
				MapInfo *pMapinfo = NULL;

				pMapinfo = WorldMapInfoStorage.LookupEntry(pAreaTrigger->Mapid);
				if(pMapinfo && !pMapinfo->HasFlag(WMI_INSTANCE_ENABLED))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "This instance is currently unavailable." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->HasFlag(WMI_INSTANCE_XPACK_01) && !HasFlag(ACCOUNT_FLAG_XPACK_01))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_BROADCAST_MSG);
					msg << uint32(3) << "You must have The Burning Crusade Expansion to access this content." << uint8(0);
					SendPacket(&msg);
					return;
				}

                if(pMapinfo && pMapinfo->type != INSTANCE_MULTIMODE && GetPlayer()->iInstanceType == MODE_HEROIC && pMapinfo->type != INSTANCE_NULL)
                {
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "Heroic mode is not available for this instance." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->type == INSTANCE_RAID && GetPlayer()->InGroup() && GetPlayer()->GetGroup()->GetGroupType() != GROUP_TYPE_RAID)
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You need to be in a raid group to be able to enter this instance." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}
				if(pMapinfo && pMapinfo->type == INSTANCE_RAID && !GetPlayer()->InGroup())
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You need to be in a raid group to be able to enter this instance." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->required_quest && !_player->HasFinishedQuest(pMapinfo->required_quest))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You do not have the required attunement to enter this instance.";
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->required_item && !_player->GetItemInterface()->GetItemCount(pMapinfo->required_item, true))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You do not have the required attunement to enter this instance.";
					SendPacket(&msg);
					return;
				}

				if(!GetPlayer()->isAlive())
				{
					pCorpse = objmgr.GetCorpseByOwner(GetPlayer()->GetGUIDLow());
					if(pCorpse)
					{
						pMapinfo = WorldMapInfoStorage.LookupEntry(pCorpse->GetMapId());
						if(pMapinfo)
						{
                            if(GetPlayer()->InGroup())
							{
								MapMgr * groupinstance = sWorldCreator.GetInstanceByGroup(GetPlayer()->GetGroup(), GetPlayer(), pMapinfo);
								if (groupinstance)
								{
									if(groupinstance->GetPlayerCount() >= pMapinfo->playerlimit)
                                    {
                                        data.Initialize(SMSG_TRANSFER_ABORTED);
								        data << uint32(INSTANCE_ABORT_FULL);
								        _player->GetSession()->SendPacket(&data);
                                        GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
                                        GetPlayer()->ResurrectPlayer();
								        return;
                                    }

                                }
							}

                            //if its a raid instance and corpse is inside and player is not in a group, ressurect
							if(pMapinfo->type != INSTANCE_NULL && pMapinfo->type != INSTANCE_PVP  && pMapinfo->type != INSTANCE_NONRAID && pMapinfo->type != INSTANCE_MULTIMODE && GetPlayer()->GetMapId() != pCorpse->GetMapId() && pCorpse->GetMapId() == pAreaTrigger->Mapid  && !GetPlayer()->InGroup())
							{
								GetPlayer()->ResurrectPlayer();
								return;
							}
                            //if its a instance and player is trying to enter when corpse is on a diferent instance, repop back
                            else if(pMapinfo->type != INSTANCE_NULL && pMapinfo->type != INSTANCE_PVP &&  pCorpse->GetMapId() != pAreaTrigger->Mapid)
							{
								GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
								return;
							}
						}
					}
					else
					{
						GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(),GetPlayer()->GetMapId());
						return;
					}
				}
				bool result = sWorldCreator.CheckInstanceForObject(static_cast<Object*>(GetPlayer()), pMapinfo);
				if(result)
				{
					GetPlayer()->SaveEntryPoint(pAreaTrigger->Mapid);
					GetPlayer()->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
				}
			}
		}break;
	case ATTYPE_QUESTTRIGGER:
		{

		}break;
	case ATTYPE_INN:
		{
			// Inn
			if (!GetPlayer()->m_isResting) GetPlayer()->ApplyPlayerRestState(true);
		}break;
	case ATTYPE_TELEPORT:
		{
			if(GetPlayer()->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
			{
				GetPlayer()->SaveEntryPoint(pAreaTrigger->Mapid);
				GetPlayer()->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
			}
		}break;
	case ATTYPE_NULL:
		{
			MapInfo *pMapinfo = NULL;
			pMapinfo = WorldMapInfoStorage.LookupEntry(pAreaTrigger->Mapid);
			if(pMapinfo && pMapinfo->HasFlag(WMI_INSTANCE_XPACK_01) && !HasFlag(ACCOUNT_FLAG_XPACK_01))
			{
				WorldPacket msg;
				msg.Initialize(SMSG_BROADCAST_MSG);
				msg << uint32(3) << "You must have The Burning Crusade Expansion to access this content." << uint8(0);
				SendPacket(&msg);
				return;
			}
		}
	default:break;
	}
}
예제 #10
0
void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data)
{
	CHECK_INWORLD_RETURN

	CHECK_PACKET_SIZE(recv_data, 16);
	if(!_player->isAlive())
		return;

	uint64 guid;
	uint32
	text_emote,
	unk,
	namelen = 1;
	const char* name = " ";

	recv_data >> text_emote;
	recv_data >> unk;
	recv_data >> guid;
	if(m_muted && m_muted >= (uint32)UNIXTIME)
	{
		SystemMessage("Your voice is currently muted by a moderator.");
		return;
	}

	if(!GetPermissionCount() && sWorld.flood_lines)
	{
		/* flood detection, wheeee! */
		if(UNIXTIME >= floodTime)
		{
			floodLines = 0;
			floodTime = UNIXTIME + sWorld.flood_seconds;
		}

		if((++floodLines) > sWorld.flood_lines)
		{
			return;
		}
	}
	Unit* pUnit = _player->GetMapMgr()->GetUnit(guid);
	if(pUnit)
	{
		if(pUnit->IsPlayer())
		{
			name = TO< Player* >(pUnit)->GetName();
			namelen = (uint32)strlen(name) + 1;
		}
		else if(pUnit->IsPet())
		{
			name = TO< Pet* >(pUnit)->GetName().c_str();
			namelen = (uint32)strlen(name) + 1;
		}
		else
		{
			Creature* p = TO< Creature* >(pUnit);
			name = p->GetCreatureInfo()->Name;
			namelen = (uint32)strlen(name) + 1;
		}
	}

	emoteentry* em = dbcEmoteEntry.LookupEntryForced(text_emote);
	if(em)
	{
		WorldPacket data(SMSG_EMOTE, 28 + namelen);

		sHookInterface.OnEmote(_player, (EmoteType)em->textid, pUnit);
		if(pUnit)
			CALL_SCRIPT_EVENT(pUnit, OnEmote)(_player, (EmoteType)em->textid);

		switch(em->textid)
		{
			case EMOTE_STATE_SLEEP:
			case EMOTE_STATE_SIT:
			case EMOTE_STATE_KNEEL:
			case EMOTE_STATE_DANCE:
				{
					_player->SetEmoteState(em->textid);
				}
				break;
		}

		data << (uint32)em->textid;
		data << (uint64)GetPlayer()->GetGUID();
		GetPlayer()->SendMessageToSet(&data, true); //If player receives his own emote, his animation stops.

		data.Initialize(SMSG_TEXT_EMOTE);
		data << (uint64)GetPlayer()->GetGUID();
		data << (uint32)text_emote;
		data << unk;
		data << (uint32)namelen;
		if(namelen > 1)   data.append(name, namelen);
		else				data << (uint8)0x00;

		GetPlayer()->SendMessageToSet(&data, true);
#ifdef ENABLE_ACHIEVEMENTS
		_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, 0);
#endif
		sQuestMgr.OnPlayerEmote(_player, text_emote, guid);
	}
}
예제 #11
0
void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data)
{
	CHECK_INWORLD_RETURN

	CHECK_PACKET_SIZE(recv_data, 9);
	WorldPacket* data = NULL;

	uint32 type;
	int32 lang;

	const char* pMisc = NULL;
	const char* pMsg = NULL;
	recv_data >> type;
	recv_data >> lang;

	if(lang >= NUM_LANGUAGES)
		return;

	if(GetPlayer()->IsBanned())
	{
		GetPlayer()->BroadcastMessage("You cannot do that when banned.");
		return;
	}

	// Flood protection
	if(lang != -1 && !GetPermissionCount() && sWorld.flood_lines != 0)
	{
		/* flood detection, wheeee! */
		if(UNIXTIME >= floodTime)
		{
			floodLines = 0;
			floodTime = UNIXTIME + sWorld.flood_seconds;
		}

		if((++floodLines) > sWorld.flood_lines)
		{
			if(sWorld.flood_message)
				_player->BroadcastMessage("Your message has triggered serverside flood protection. You can speak again in %u seconds.", floodTime - UNIXTIME);

			return;
		}
	}

	switch(type)
	{
		case CHAT_MSG_EMOTE:
		case CHAT_MSG_SAY:
		case CHAT_MSG_YELL:
		case CHAT_MSG_WHISPER:
		case CHAT_MSG_CHANNEL:
			{
				if(m_muted && m_muted >= (uint32)UNIXTIME)
				{
					SystemMessage("Your voice is currently muted by a moderator.");
					return;
				}
			}
			break;
	}

	std::string msg, to = "", channel = "", tmp;
	msg.reserve(256);

	// Process packet
	switch(type)
	{
		case CHAT_MSG_SAY:
		case CHAT_MSG_EMOTE:
		case CHAT_MSG_PARTY:
		case CHAT_MSG_PARTY_LEADER:
		case CHAT_MSG_RAID:
		case CHAT_MSG_RAID_LEADER:
		case CHAT_MSG_RAID_WARNING:
		case CHAT_MSG_GUILD:
		case CHAT_MSG_OFFICER:
		case CHAT_MSG_YELL:
			recv_data >> msg;
			pMsg = msg.c_str();
			//g_chatFilter->ParseEscapeCodes((char*)pMsg,true);
			pMisc = 0;
			break;
		case CHAT_MSG_WHISPER:
			recv_data >> to >> msg;
			pMsg = msg.c_str();
			pMisc = to.c_str();
			break;
		case CHAT_MSG_CHANNEL:
			recv_data >> channel;
			recv_data >> msg;
			pMsg = msg.c_str();
			pMisc = channel.c_str();
			break;
		case CHAT_MSG_AFK:
		case CHAT_MSG_DND:
			break;
		case CHAT_MSG_BATTLEGROUND:
		case CHAT_MSG_BATTLEGROUND_LEADER:
			recv_data >> msg;
			pMsg = msg.c_str();
			break;
		default:
			LOG_ERROR("CHAT: unknown msg type %u, lang: %u", type, lang);
	}


	if(int(msg.find("|T")) > -1)
	{
		GetPlayer()->BroadcastMessage("Don't even THINK about doing that again");
		return;
	}

	// HookInterface OnChat event
	if(pMsg && !sHookInterface.OnChat(_player, type, lang, pMsg, pMisc))
		return;

	Channel* chn = NULL;
	// Main chat message processing
	switch(type)
	{
		case CHAT_MSG_EMOTE:
			{
				if(sWorld.interfaction_chat && lang > 0)
					lang = 0;

				if(g_chatFilter->Parse(msg))
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				if(GetPlayer()->m_modlanguage >= 0)
					data = sChatHandler.FillMessageData(CHAT_MSG_EMOTE, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
				else if(lang == 0 && sWorld.interfaction_chat)
					data = sChatHandler.FillMessageData(CHAT_MSG_EMOTE, CanUseCommand('0') ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
				else
					data = sChatHandler.FillMessageData(CHAT_MSG_EMOTE, CanUseCommand('c') ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);

				GetPlayer()->SendMessageToSet(data, true, ! sWorld.interfaction_chat);

				//sLog.outString("[emote] %s: %s", _player->GetName(), msg.c_str());
				delete data;

			}
			break;
		case CHAT_MSG_SAY:
			{
				if(sWorld.interfaction_chat && lang > 0)
					lang = 0;

				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
					break;

				if(g_chatFilter->Parse(msg))
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				if(GetPlayer()->m_modlanguage >= 0)
				{
					data = sChatHandler.FillMessageData(CHAT_MSG_SAY, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
					GetPlayer()->SendMessageToSet(data, true);
				}
				else
				{
					if(lang > 0 && LanguageSkills[lang] && ! _player->_HasSkillLine(LanguageSkills[lang]))
						return;

					if(lang == 0 && ! CanUseCommand('c') && ! sWorld.interfaction_chat)
						return;

					data = sChatHandler.FillMessageData(CHAT_MSG_SAY, lang, msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);

					GetPlayer()->SendMessageToSet(data, true);
				}
				delete data;

			}
			break;
		case CHAT_MSG_PARTY:
		case CHAT_MSG_PARTY_LEADER:
		case CHAT_MSG_RAID:
		case CHAT_MSG_RAID_LEADER:
		case CHAT_MSG_RAID_WARNING:
			{
				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
					break;

				if(sWorld.interfaction_chat && lang > 0)
					lang = 0;

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				Group* pGroup = _player->GetGroup();
				if(pGroup == NULL) break;

				if(GetPlayer()->m_modlanguage >= 0)
					data = sChatHandler.FillMessageData(type, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
				else if(lang == 0 && sWorld.interfaction_chat)
					data = sChatHandler.FillMessageData(type, (CanUseCommand('0') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
				else
					data = sChatHandler.FillMessageData(type, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
				if(type == CHAT_MSG_PARTY && pGroup->GetGroupType() == GROUP_TYPE_RAID)
				{
					// only send to that subgroup
					SubGroup* sgr = _player->GetGroup() ?
					                _player->GetGroup()->GetSubGroup(_player->GetSubGroup()) : 0;

					if(sgr)
					{
						_player->GetGroup()->Lock();
						for(GroupMembersSet::iterator itr = sgr->GetGroupMembersBegin(); itr != sgr->GetGroupMembersEnd(); ++itr)
						{
							if((*itr)->m_loggedInPlayer)
								(*itr)->m_loggedInPlayer->GetSession()->SendChatPacket(data, 1, lang, this);
						}
						_player->GetGroup()->Unlock();
					}
				}
				else
				{
					SubGroup* sgr;
					for(uint32 i = 0; i < _player->GetGroup()->GetSubGroupCount(); ++i)
					{
						sgr = _player->GetGroup()->GetSubGroup(i);
						_player->GetGroup()->Lock();
						for(GroupMembersSet::iterator itr = sgr->GetGroupMembersBegin(); itr != sgr->GetGroupMembersEnd(); ++itr)
						{
							if((*itr)->m_loggedInPlayer)
								(*itr)->m_loggedInPlayer->GetSession()->SendChatPacket(data, 1, lang, this);
						}
						_player->GetGroup()->Unlock();

					}
				}
				//sLog.outString("[party] %s: %s", _player->GetName(), msg.c_str());
				delete data;
			}
			break;
		case CHAT_MSG_GUILD:
			{
				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
				{
					break;
				}

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				if(_player->m_playerInfo->guild)
					_player->m_playerInfo->guild->GuildChat(msg.c_str(), this, lang);

			}
			break;
		case CHAT_MSG_OFFICER:
			{
				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
					break;

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				if(_player->m_playerInfo->guild)
					_player->m_playerInfo->guild->OfficerChat(msg.c_str(), this, lang);

			}
			break;
		case CHAT_MSG_YELL:
			{
				if(sWorld.interfaction_chat && lang > 0)
					lang = 0;

				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
					break;

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}
				if(lang > 0 && LanguageSkills[lang] && _player->_HasSkillLine(LanguageSkills[lang]) == false)
					return;

				if(lang == 0 && sWorld.interfaction_chat)
					data = sChatHandler.FillMessageData(CHAT_MSG_YELL, (CanUseCommand('0') && lang != -1) ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);

				else if(lang == 0 && !CanUseCommand('c'))
				{
					if(data != NULL)
						delete data;
					return;
				}

				else if(GetPlayer()->m_modlanguage >= 0)
					data = sChatHandler.FillMessageData(CHAT_MSG_YELL, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
				else
					data = sChatHandler.FillMessageData(CHAT_MSG_YELL, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);

				_player->GetMapMgr()->SendChatMessageToCellPlayers(_player, data, 2, 1, lang, this);
				delete data;
			}
			break;
		case CHAT_MSG_WHISPER:
			{
				if(lang != -1)
					lang = LANG_UNIVERSAL; //All whispers are universal
				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				PlayerCache* playercache = objmgr.GetPlayerCache(to.c_str(), false);
				if(playercache == NULL)
				{
					data = new WorldPacket(SMSG_CHAT_PLAYER_NOT_FOUND, to.length() + 1);
					*data << to;
					SendPacket(data);
					delete data;
					break;
				}

				if(_player->GetTeamInitial() != playercache->GetUInt32Value(CACHE_PLAYER_INITIALTEAM) && !sWorld.interfaction_chat && !playercache->HasFlag(CACHE_PLAYER_FLAGS, PLAYER_FLAG_GM) && !_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM))
				{
					WorldPacket response(SMSG_CHAT_PLAYER_NOT_FOUND, to.length() + 1);
					response << to;
					SendPacket(&response);
					playercache->DecRef();
					break;
				}

				// Check that the player isn't a gm with his status on
				// TODO: Game Master's on retail are able to have block whispers after they close the ticket with the current packet.
				// When a Game Master is visible to your player it says "This player is unavailable for whisper" I need to figure out how this done.
				if(!HasPermissions() && playercache->HasFlag(CACHE_PLAYER_FLAGS, PLAYER_FLAG_GM) && playercache->CountValue64(CACHE_GM_TARGETS, _player->GetGUID()) == 0)
				{
					// Build automated reply
					string Reply = "SYSTEM: This Game Master does not currently have an open ticket from you and did not receive your whisper. Please submit a new GM Ticket request if you need to speak to a GM. This is an automatic message.";
					data = sChatHandler.FillMessageData(CHAT_MSG_WHISPER_INFORM, LANG_UNIVERSAL, Reply.c_str(), playercache->GetGUID(), 4);
					SendPacket(data);
					delete data;
					playercache->DecRef();
					break;
				}

				if(playercache->CountValue64(CACHE_SOCIAL_IGNORELIST, _player->GetLowGUID()) > 0)
				{
					data = sChatHandler.FillMessageData(CHAT_MSG_IGNORED, LANG_UNIVERSAL,  msg.c_str(), playercache->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
					SendPacket(data);
					delete data;
					playercache->DecRef();
					break;
				}
				else
				{
					data = sChatHandler.FillMessageData(CHAT_MSG_WHISPER, lang,  msg.c_str(), _player->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
					playercache->SendPacket(data);
				}


				//Sent the to Users id as the channel, this should be fine as it's not used for whisper
				if(lang != -1) //DO NOT SEND if its an addon message!
				{
					data = sChatHandler.FillMessageData(CHAT_MSG_WHISPER_INFORM, LANG_UNIVERSAL, msg.c_str(), playercache->GetGUID(), playercache->HasFlag(CACHE_PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
					SendPacket(data);
					delete data;
				}

				if(playercache->HasFlag(CACHE_PLAYER_FLAGS, PLAYER_FLAG_AFK))
				{
					// Has AFK flag, autorespond.
					std::string reason;
					playercache->GetStringValue(CACHE_AFK_DND_REASON, reason);

					data = sChatHandler.FillMessageData(CHAT_MSG_AFK, LANG_UNIVERSAL, reason.c_str(), playercache->GetGUID(), _player->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
					SendPacket(data);
					delete data;
				}
				else if(playercache->HasFlag(CACHE_PLAYER_FLAGS, PLAYER_FLAG_DND))
				{
					// Has DND flag, autorespond.
					std::string reason;
					playercache->GetStringValue(CACHE_AFK_DND_REASON, reason);
					data = sChatHandler.FillMessageData(CHAT_MSG_DND, LANG_UNIVERSAL, reason.c_str(), playercache->GetGUID(), playercache->HasFlag(CACHE_PLAYER_FLAGS, PLAYER_FLAG_GM) ? 4 : 0);
					SendPacket(data);
					delete data;
				}

				playercache->DecRef();

			}
			break;
		case CHAT_MSG_CHANNEL:
			{
				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
					break;

				chn = channelmgr.GetChannel(channel.c_str(), GetPlayer());
				if(chn)
				{
					//g_chatFilter->ParseEscapeCodes((char*)pMsg, (chn->m_flags & CHANNEL_PACKET_ALLOWLINKS)>0 );
					chn->Say(GetPlayer(), msg.c_str(), NULL, false);
				}
			}
			break;
		case CHAT_MSG_AFK:
			{
				std::string reason = "";
				recv_data >> reason;

				GetPlayer()->SetAFKReason(reason);

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				/* WorldPacket *data, WorldSession* session, uint32 type, uint32 language, const char *channelName, const char *message*/
				if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_AFK))
				{
					GetPlayer()->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAG_AFK);
					if(sWorld.GetKickAFKPlayerTime())
						sEventMgr.RemoveEvents(GetPlayer(), EVENT_PLAYER_SOFT_DISCONNECT);
				}
				else
				{
					GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAG_AFK);

					if(GetPlayer()->m_bg)
						GetPlayer()->m_bg->RemovePlayer(GetPlayer(), false);

					if(sWorld.GetKickAFKPlayerTime())
						sEventMgr.AddEvent(GetPlayer(), &Player::SoftDisconnect, EVENT_PLAYER_SOFT_DISCONNECT, sWorld.GetKickAFKPlayerTime(), 1, 0);
				}
			}
			break;
		case CHAT_MSG_DND:
			{
				std::string reason;
				recv_data >> reason;
				GetPlayer()->SetAFKReason(reason);

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}

				if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAG_DND))
					GetPlayer()->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAG_DND);
				else
				{
					GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAG_DND);
				}
			}
			break;

		case CHAT_MSG_BATTLEGROUND:
		case CHAT_MSG_BATTLEGROUND_LEADER:
			{
				if(sChatHandler.ParseCommands(msg.c_str(), this) > 0)
					break;

				if(g_chatFilter->Parse(msg) == true)
				{
					SystemMessage("Your chat message was blocked by a server-side filter.");
					return;
				}
				if(_player->m_bg != NULL)
				{
					data = sChatHandler.FillMessageData(type, lang, msg.c_str(), _player->GetGUID());
					_player->m_bg->DistributePacketToTeam(data, _player->GetTeam());
					delete data;
				}
			}
			break;
	}
}
예제 #12
0
void WorldSession::HandleSendMail(WorldPacket & recv_data )
{
	MailMessage msg;
	uint64 gameobject;
	uint32 unk2;
	uint8 itemcount;
	uint8 itemslot;
	uint8 i;
	uint64 itemguid;
	vector< Item* > items;
	vector< Item* >::iterator itr;
	string recepient;
	Item * pItem;
	//uint32 err = MAIL_OK;

	recv_data >> gameobject >> recepient;
	recv_data >> msg.subject >> msg.body >> msg.stationary;
	recv_data >> unk2 >> itemcount;

	//he simply ads ' ' after each '%' to string so that vsnprintf function would not find tokens in string
	char *t=(char*)msg.subject.c_str();
	if( t[0] != 0 ) //if not an empty string
	{
		int ind=1;
		//make sure we do not have any recognizable tokens here
		while(t[ind]!=0 && ind<5000)
		{
			if(t[ind-1]=='%')
				t[ind]=' ';//just remove chars that could be interpreted
			ind++;
		}
	}
	msg.subject = t;
	t=(char*)msg.body.c_str();
	if( t[0] != 0 ) //if not an empty string
	{
		int ind=1;
		while(t[ind]!=0 && ind<5000)
		{
			if(t[ind-1]=='%')
				t[ind]=' ';//just remove chars that could be interpreted
			ind++;
		}
	}
	msg.body = t;


	if( itemcount > 12 )
	{
		//SystemMessage("Sorry, Ascent does not support sending multiple items at this time. (don't want to lose your item do you) Remove some items, and try again.");
		SendMailError(MAIL_ERR_INTERNAL_ERROR);
		return;
	}

	for( i = 0; i < itemcount; ++i )
	{
		recv_data >> itemslot;
		recv_data >> itemguid;

        pItem = _player->GetItemInterface()->GetItemByGUID( itemguid );
		if( pItem == NULL || pItem->IsSoulbound() || pItem->HasFlag( ITEM_FIELD_FLAGS, ITEM_FLAG_CONJURED ) )
		{
			SendMailError( MAIL_ERR_INTERNAL_ERROR );
			return;
		}

		items.push_back( pItem );
	}
	
	recv_data >> msg.money;
	recv_data >> msg.cod;
	// left over: (TODO- FIX ME BURLEX!)
	// uint32
	// uint32
	// uint8
	
	// Search for the recipient
	PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str());
	if( player == NULL )
	{
		SendMailError( MAIL_ERR_RECIPIENT_NOT_FOUND );
		return;
	}

	bool interfaction = false;
	if( sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION ) || (HasGMPermissions() && sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM ) ) )
	{
		interfaction = true;
	}

	// Check we're sending to the same faction (disable this for testing)
	if( player->team != _player->GetTeam() && !interfaction )
	{
		SendMailError( MAIL_ERR_NOT_YOUR_ALLIANCE );
		return;
	}

	// Check if we're sending mail to ourselves
	if( strcmp(player->name, _player->GetName()) == 0 && !GetPermissionCount())
	{
		SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF);
		return;
	}

	if( msg.stationary == 0x3d || msg.stationary == 0x3d && !HasGMPermissions())
	{
		SendMailError(MAIL_ERR_INTERNAL_ERROR);
		return;
	}

	// Instant delivery time by default.
	msg.delivery_time = (uint32)UNIXTIME;

	// Set up the cost
	int32 cost = 0;
	if( !sMailSystem.MailOption( MAIL_FLAG_DISABLE_POSTAGE_COSTS ) && !( GetPermissionCount() && sMailSystem.MailOption( MAIL_FLAG_NO_COST_FOR_GM ) ) )
	{
		cost = 30;
	}

	// Check for attached money
	if( msg.money > 0 )
		cost += msg.money;

	if( cost < 0 )
	{
		SendMailError(MAIL_ERR_INTERNAL_ERROR);
		return;
	}

	// check that we have enough in our backpack
	if( (int32)_player->GetUInt32Value( PLAYER_FIELD_COINAGE ) < cost )
	{
		SendMailError( MAIL_ERR_NOT_ENOUGH_MONEY );
		return;
	}

	// Check for the item, and required item.
	if( !items.empty( ) )
	{
		for( itr = items.begin(); itr != items.end(); ++itr )
		{
			pItem = *itr;
			if( _player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem )
				continue;		// should never be hit.

			pItem->RemoveFromWorld();
			pItem->SetOwner( NULL );
			pItem->SaveToDB( INVENTORY_SLOT_NOT_SET, 0, true, NULL );
			msg.items.push_back( pItem->GetUInt32Value(OBJECT_FIELD_GUID) );

			if( GetPermissionCount() > 0 )
			{
				/* log the message */
				sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money);
			}

			pItem->DeleteMe();
		}
	}

	if(msg.money != 0 || msg.cod != 0 || !msg.items.size() && player->acct != _player->GetSession()->GetAccountId())
	{
		if(!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS))
			msg.delivery_time += 3600;  // 1hr
	}

	// take the money
	_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -cost);

	// Fill in the rest of the info
	msg.player_guid = player->guid;
	msg.sender_guid = _player->GetGUID();
	
	// 30 day expiry time for unread mail mail
	if(!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY))
		msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME);
	else
		msg.expire_time = 0;

	msg.copy_made = false;
	msg.read_flag = false;
	msg.deleted_flag = false;
	msg.message_type = 0;

	// Great, all our info is filled in. Now we can add it to the other players mailbox.
	sMailSystem.DeliverMessage(player->guid, &msg);

	// Success packet :)
	SendMailError(MAIL_OK);
}
예제 #13
0
void WorldSession::HandleSendMail(WorldPacket & recv_data )
{
	MailMessage msg;
	uint64 gameobject;
	uint32 unk2;
	uint8 itemcount;
	uint8 itemslot;
	uint8 i;
	uint64 itemguid;
	vector< ItemPointer > items;
	vector< ItemPointer >::iterator itr;
	string recepient;
	ItemPointer pItem;
	int8 real_item_slot;

	recv_data >> gameobject >> recepient;
	// Search for the recipient
	PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str());
	if( player == NULL )
	{
		SendMailError(MAIL_ERR_RECIPIENT_NOT_FOUND);
		return;
	}
	msg.player_guid = player->guid;
	msg.sender_guid = _player->GetGUID();

	recv_data >> msg.subject >> msg.body >> msg.stationary;

	// Check attached items
	recv_data >> unk2 >> itemcount;
	for( i = 0; i < itemcount; ++i )
	{
		recv_data >> itemslot;
		recv_data >> itemguid;

        pItem = _player->GetItemInterface()->GetItemByGUID( itemguid );
		real_item_slot = _player->GetItemInterface()->GetInventorySlotByGuid( itemguid );
		if( pItem == NULL || pItem->IsSoulbound() || pItem->HasFlag( ITEM_FIELD_FLAGS, ITEM_FLAG_CONJURED ) || 
			( pItem->IsContainer() && (TO_CONTAINER( pItem ))->HasItems() ) || real_item_slot >= 0 && real_item_slot < INVENTORY_SLOT_ITEM_START )
		{
			SendMailError(MAIL_ERR_INTERNAL_ERROR);
			return;
		}
		items.push_back( pItem );
	}
	if( items.size() > 12 || msg.body.find("%") != string::npos || msg.subject.find("%") != string::npos)
	{
		SendMailError(MAIL_ERR_INTERNAL_ERROR);
		return;
	}

	recv_data >> msg.money;
	recv_data >> msg.cod;
	// left over: (TODO- FIX ME BURLEX!)
	// uint32
	// uint32
	// uint8

	// Check if we're sending mail to ourselves
	if(msg.player_guid == msg.sender_guid && !GetPermissionCount())
	{
		SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF);
		return;
	}

	// Check stationary
	if( msg.stationary == 0x3d && !HasGMPermissions())
	{
		SendMailError(MAIL_ERR_INTERNAL_ERROR);
		return;
	}

	// Set up the cost
	int32 cost = 0;
	if( !sMailSystem.MailOption( MAIL_FLAG_DISABLE_POSTAGE_COSTS ) && !( GetPermissionCount() && sMailSystem.MailOption( MAIL_FLAG_NO_COST_FOR_GM ) ) )
	{
		cost = 30;
	}
	// Check for attached money
	if( msg.money > 0 )
		cost += msg.money;
	if( cost < 0 )
	{
		SendMailError(MAIL_ERR_INTERNAL_ERROR);
		return;
	}
	// check that we have enough in our backpack
	if( (int32)_player->GetUInt32Value( PLAYER_FIELD_COINAGE ) < cost )
	{
		SendMailError( MAIL_ERR_NOT_ENOUGH_MONEY );
		return;
	}

	// Check we're sending to the same faction (disable this for testing)
	bool interfaction = (sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION ) || (HasGMPermissions() && sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM ) ));
	if(!interfaction)
	{
		if(player->team != _player->GetTeam())
		{
			SendMailError( MAIL_ERR_NOT_YOUR_ALLIANCE );
			return;
		}
	}

	msg.message_id = 0;
	msg.message_type = 0;
	msg.copy_made = false;
	msg.read_flag = false;
	msg.deleted_flag = false;
	msg.returned_flag = false;
	msg.delivery_time = (uint32)UNIXTIME;

	if(msg.money != 0 || msg.cod != 0 || !items.size() && player->acct != _player->GetSession()->GetAccountId())
	{
		if(!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS))
			msg.delivery_time += 3600;  // +1hr
	}

	msg.expire_time = 0;
	if(!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY))
	{
		msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * 30);
		if (msg.cod != 0)
		{
			msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * 3);
		}
	}

	// Sending Message
	// take the money
	_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -cost);
	// Check for the item, and required item.
	if( !items.empty( ) )
	{
		for( itr = items.begin(); itr != items.end(); ++itr )
		{
			pItem = *itr;
			if( _player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem )
				continue;		// should never be hit.

			pItem->RemoveFromWorld();
			pItem->SetOwner( NULLPLR );
			pItem->SaveToDB( INVENTORY_SLOT_NOT_SET, 0, true, NULL );
			msg.items.push_back( pItem->GetUInt32Value(OBJECT_FIELD_GUID) );
				
			if( GetPermissionCount() > 0 )
			{
				/* log the message */
				sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money);
			}

			pItem->Destructor();
		}
	}

	// Great, all our info is filled in. Now we can add it to the other players mailbox.
	sMailSystem.DeliverMessage(&msg);

	// Success packet :)
	SendMailError(MAIL_OK);
}
예제 #14
0
void WorldSession::HandleAcceptTrade(WorldPacket & recv_data) 
{
#ifdef FORCED_GM_TRAINEE_MODE
	if( CanUseCommand('k') && !HasGMPermissions() )
	{
		GetPlayer()->BroadcastMessage( "You are not allowed to use this feature" );
		return;
	}
#endif
	if( sWorld.getIntRate( INTRATE_DISABLE_TRADE_FEATURE ) )
	{
		GetPlayer()->BroadcastMessage( "Trade feature is disabled right now" );
		return;
	}
	Player * plr = _player->GetTradeTarget();
	if(_player->mTradeTarget == 0 || !plr)
	{ 
		return;
	}

	packetSMSG_TRADE_STATUS data;
	memset( &data, 0, sizeof( data ) );
	data.trade_status = TRADE_STATUS_ACCEPTED;
	OutPacket(SMSG_TRADE_STATUS,sizeof( packetSMSG_TRADE_STATUS ), &data);
	plr->m_session->OutPacket(SMSG_TRADE_STATUS,sizeof( packetSMSG_TRADE_STATUS ), &data);
	
	_player->mTradeStatus = TRADE_STATUS_ACCEPTED;	//when both have this status we can close the deal

	bool bag_hack_detected = false;
	if(plr->mTradeStatus == TRADE_STATUS_ACCEPTED)
	{
		// Ready!
		uint32 ItemCount = 0;
		uint32 TargetItemCount = 0;
		Player * pTarget = plr;

/*		// Calculate Item Count
		for(uint32 Index = 0; Index < 7; ++Index)
		{
			if(_player->mTradeItems[Index] != 0)	++ItemCount;
			if(pTarget->mTradeItems[Index] != 0)	++TargetItemCount;
		}*/
		

		// Calculate Count
		for(uint32 Index = 0; Index < TRADE_MAX_TRADABLE_ITEMS; ++Index) // cebernic: checking for MAX_TRADE_TRADABLE_ITEMS items ,untradable item check via others func.
		{
			Item * pItem;

			// safely trade checking
			pItem = _player->mTradeItems[Index];
			if( pItem )
			{
				if( ( pItem->IsContainer() && SafeContainerCast(pItem)->HasItems() )   || ( pItem->GetProto() && pItem->GetProto()->Bonding==ITEM_BIND_ON_PICKUP) )
				{
					ItemCount = 0;
					TargetItemCount = 0;
					bag_hack_detected = true;
					break;
				}
				else ++ItemCount;
			}					
			
			pItem = pTarget->mTradeItems[Index];
			if( pItem )
			{
				if( ( pItem->IsContainer() && SafeContainerCast(pItem)->HasItems() )   || ( pItem->GetProto() && pItem->GetProto()->Bonding==ITEM_BIND_ON_PICKUP) )
				{
					ItemCount = 0;
					TargetItemCount = 0;
					bag_hack_detected = true;
					break;
				}
				else 
					++TargetItemCount;
			}					

			//if(_player->mTradeItems[Index] != 0)	++ItemCount;
			//if(pTarget->mTradeItems[Index] != 0)	++TargetItemCount;
		}

		

		if( (_player->m_ItemInterface->CalculateFreeSlots(NULL) + ItemCount) < TargetItemCount ||
			(pTarget->m_ItemInterface->CalculateFreeSlots(NULL) + TargetItemCount) < ItemCount ||
			bag_hack_detected == true ||
			(ItemCount==0 && TargetItemCount==0 && !pTarget->mTradeGold && !_player->mTradeGold) )	// ceberwow added it
		{
			// Not enough slots on one end.
			data.trade_status = TRADE_STATUS_CANCELLED;
		}
		else
		{
			data.trade_status = TRADE_STATUS_COMPLETE;
			uint64 Guid;
			Item * pItem;
			
			// Remove all items from the players inventory
			for(uint32 Index = 0; Index < TRADE_MAX_TRADABLE_ITEMS; ++Index)
			{
				Guid = _player->mTradeItems[Index] ? _player->mTradeItems[Index]->GetGUID() : 0;
				if(Guid != 0)
				{
					if( _player->mTradeItems[Index]->GetProto()->Bonding == ITEM_BIND_ON_PICKUP ||
						_player->mTradeItems[Index]->GetProto()->Bonding  >=  ITEM_BIND_QUEST  )
					{
						_player->mTradeItems[Index] = NULL;
					}
					else
					{
						if(GetPermissionCount()>0)
							sGMLog.writefromsession(this, "traded item %s to %s", _player->mTradeItems[Index]->GetProto()->Name1, pTarget->GetName());
						pItem = _player->m_ItemInterface->SafeRemoveAndRetreiveItemByGuid(Guid, true);
					}
				}

				Guid = pTarget->mTradeItems[Index] ? pTarget->mTradeItems[Index]->GetGUID() : 0;
				if(Guid != 0)
				{
					if( pTarget->mTradeItems[Index]->GetProto()->Bonding == ITEM_BIND_ON_PICKUP ||  
						pTarget->mTradeItems[Index]->GetProto()->Bonding  >=  ITEM_BIND_QUEST )
					{
						pTarget->mTradeItems[Index] = NULL;
					}
					else
					{
						if(pTarget->GetSession() && pTarget->GetSession()->GetPermissionCount()>0)
							sGMLog.writefromsession(pTarget->GetSession(), "traded item %s to %s", pTarget->mTradeItems[Index]->GetProto()->Name1, _player->GetName());
						pTarget->m_ItemInterface->SafeRemoveAndRetreiveItemByGuid(Guid, true);
					}
				}
			}

			// Dump all items back into the opposite players inventory
			for(uint32 Index = 0; Index < TRADE_MAX_TRADABLE_ITEMS; ++Index)
			{
				pItem = _player->mTradeItems[Index];
				if(pItem != 0 && pTarget)
				{
					pItem->SetOwner(pTarget); // crash fixed.
					if( !pTarget->m_ItemInterface->AddItemToFreeSlot(&pItem) )
					{
						pItem->DeleteMe();
						pItem = NULL;
						_player->mTradeItems[Index] = NULL;
						continue;
					}
				}

				pItem = pTarget->mTradeItems[Index];
				if(pItem != 0 && _player)
				{
					pItem->SetOwner(_player);
					if( !_player->m_ItemInterface->AddItemToFreeSlot(&pItem) )
					{
						pItem->DeleteMe();
						pItem = NULL;
						pTarget->mTradeItems[Index] = NULL;
						continue;
					}
				}
			}

			// Trade Gold
			if(pTarget->mTradeGold && pTarget->GetGold() >= pTarget->mTradeGold )
			{
				_player->ModGold(pTarget->mTradeGold);
				pTarget->ModGold(-(int64)pTarget->mTradeGold);
				if(GetPermissionCount()>0)
					sGMLog.writefromsession(this, "traded(gave) %u gold to %s", pTarget->mTradeGold, pTarget->GetName());
			}

			if(_player->mTradeGold && _player->GetGold() >= _player->mTradeGold)
			{
				pTarget->ModGold( _player->mTradeGold);
				_player->ModGold( -(int64)_player->mTradeGold);
				if(pTarget->GetSession() && pTarget->GetSession()->GetPermissionCount()>0)
					sGMLog.writefromsession(pTarget->GetSession(), "traded(gave) %u gold to %s", _player->mTradeGold, _player->GetName());
			}

			// Close Window
			data.trade_status = TRADE_STATUS_COMPLETE;
			
		}

		OutPacket(SMSG_TRADE_STATUS,sizeof( packetSMSG_TRADE_STATUS ), &data);
		plr->m_session->OutPacket(SMSG_TRADE_STATUS,sizeof( packetSMSG_TRADE_STATUS ), &data);

		_player->mTradeStatus = TRADE_STATUS_COMPLETE;
		plr->mTradeStatus = TRADE_STATUS_COMPLETE;

		// Reset Trade Vars
		_player->ResetTradeVariables();		
		plr->ResetTradeVariables();

		//removed by zack. Hehe, just a way to spam db with saves. Not funny
		// added alternative way as item saves before 
		// Save for eachother
		//plr->SaveToDB(false);
		//_player->SaveToDB(false);
	}
}
예제 #15
0
void WorldSession::HandleAcceptTrade(WorldPacket & recv_data) 
{
	Player * plr = _player->GetTradeTarget();
	if(_player->mTradeTarget == 0 || !plr)
		return;

	uint32 TradeStatus = TRADE_STATUS_ACCEPTED;
	
	// Tell the other player we're green.
#ifdef USING_BIG_ENDIAN
	swap32(&TradeStatus);
	plr->m_session->OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
	_player->mTradeStatus = TradeStatus;
	swap32(&TradeStatus);
#else
	plr->m_session->OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
	_player->mTradeStatus = TradeStatus;
#endif

	if(plr->mTradeStatus == TRADE_STATUS_ACCEPTED)
	{
		// Ready!
		uint32 ItemCount = 0;
		uint32 TargetItemCount = 0;
		Player * pTarget = plr;

/*		// Calculate Item Count
		for(uint32 Index = 0; Index < 7; ++Index)
		{
			if(_player->mTradeItems[Index] != 0)	++ItemCount;
			if(pTarget->mTradeItems[Index] != 0)	++TargetItemCount;
		}*/
		

		// Calculate Count
		for(uint32 Index = 0; Index < 6; ++Index) // cebernic: checking for 6items ,untradable item check via others func.
		{
			Item * pItem;

			// safely trade checking
			pItem = _player->mTradeItems[Index];
			if( pItem )
			{
				if( ( pItem->IsContainer() && ((Container*)pItem)->HasItems() )   || ( pItem->GetProto() && pItem->GetProto()->Bonding==ITEM_BIND_ON_PICKUP) )
				{
					ItemCount = 0;
					TargetItemCount = 0;
					break;
				}
				else ++ItemCount;
			}					
			
			pItem = pTarget->mTradeItems[Index];
			if( pItem )
			{
				if( ( pItem->IsContainer() && ((Container*)pItem)->HasItems() )   || ( pItem->GetProto() && pItem->GetProto()->Bonding==ITEM_BIND_ON_PICKUP) )
				{
					ItemCount = 0;
					TargetItemCount = 0;
					break;
				}
				else ++TargetItemCount;
			}					

			//if(_player->mTradeItems[Index] != 0)	++ItemCount;
			//if(pTarget->mTradeItems[Index] != 0)	++TargetItemCount;
		}

		

		if( (_player->m_ItemInterface->CalculateFreeSlots(NULL) + ItemCount) < TargetItemCount ||
			(pTarget->m_ItemInterface->CalculateFreeSlots(NULL) + TargetItemCount) < ItemCount ||
			(ItemCount==0 && TargetItemCount==0 && !pTarget->mTradeGold && !_player->mTradeGold) )	// ceberwow added it
		{
			// Not enough slots on one end.
			TradeStatus = TRADE_STATUS_CANCELLED;
		}
		else
		{
			TradeStatus = TRADE_STATUS_COMPLETE;
			uint64 Guid;
			Item * pItem;
			
			// Remove all items from the players inventory
			for(uint32 Index = 0; Index < 6; ++Index)
			{
				Guid = _player->mTradeItems[Index] ? _player->mTradeItems[Index]->GetGUID() : 0;
				if(Guid != 0)
				{
					if( _player->mTradeItems[Index]->GetProto()->Bonding == ITEM_BIND_ON_PICKUP ||
						_player->mTradeItems[Index]->GetProto()->Bonding  >=  ITEM_BIND_QUEST  )
					{
						_player->mTradeItems[Index] = NULL;
					}
					else
					{
						if(GetPermissionCount()>0)
						{
							sGMLog.writefromsession(this, "traded item %s to %s", _player->mTradeItems[Index]->GetProto()->Name1, pTarget->GetName());
						}
						pItem = _player->m_ItemInterface->SafeRemoveAndRetreiveItemByGuid(Guid, true);
					}
				}

				Guid = pTarget->mTradeItems[Index] ? pTarget->mTradeItems[Index]->GetGUID() : 0;
				if(Guid != 0)
				{
					if( pTarget->mTradeItems[Index]->GetProto()->Bonding == ITEM_BIND_ON_PICKUP ||  
						pTarget->mTradeItems[Index]->GetProto()->Bonding  >=  ITEM_BIND_QUEST )
					{
						pTarget->mTradeItems[Index] = NULL;
					}
					else
					{
						pTarget->m_ItemInterface->SafeRemoveAndRetreiveItemByGuid(Guid, true);
					}
				}
			}

			// Dump all items back into the opposite players inventory
			for(uint32 Index = 0; Index < 6; ++Index)
			{
				pItem = _player->mTradeItems[Index];
				if(pItem != 0 && pTarget)
				{
					pItem->SetOwner(pTarget); // crash fixed.
					if( !pTarget->m_ItemInterface->AddItemToFreeSlot(pItem) )
						pItem->DeleteMe();
				}

				pItem = pTarget->mTradeItems[Index];
				if(pItem != 0 && _player)
				{
					pItem->SetOwner(_player);
					if( !_player->m_ItemInterface->AddItemToFreeSlot(pItem) )
						pItem->DeleteMe();
				}
			}

			// Trade Gold
			if(pTarget->mTradeGold)
			{
				_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, pTarget->mTradeGold);
				pTarget->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -(int32)pTarget->mTradeGold);
			}

			if(_player->mTradeGold)
			{
				pTarget->ModUnsigned32Value(PLAYER_FIELD_COINAGE, _player->mTradeGold);
				_player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -(int32)_player->mTradeGold);
			}

			// Close Window
			TradeStatus = TRADE_STATUS_COMPLETE;
			
		}
					
#ifdef USING_BIG_ENDIAN
            swap32(&TradeStatus);
			OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
			plr->m_session->OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
			swap32(&TradeStatus);
#else
			OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
			plr->m_session->OutPacket(SMSG_TRADE_STATUS, 4, &TradeStatus);
#endif

			_player->mTradeStatus = TRADE_STATUS_COMPLETE;
			plr->mTradeStatus = TRADE_STATUS_COMPLETE;

			// Reset Trade Vars
			_player->ResetTradeVariables();
			pTarget->ResetTradeVariables();
			
			plr->mTradeTarget = 0;
			_player->mTradeTarget = 0;

			// Save for eachother
			plr->SaveToDB(false);
			_player->SaveToDB(false);
	}
}
예제 #16
0
void WorldSession::HandleChannelJoin(WorldPacket& recvPacket)
{
	CHECK_PACKET_SIZE(recvPacket, 1);
	string channelname,pass;
	uint32 dbc_id = 0;
	uint16 crap;		// crap = some sort of channel type?
	uint32 i;
	Channel * chn;

	recvPacket >> dbc_id >> crap;
	recvPacket >> channelname;
	recvPacket >> pass;

	if(!stricmp(channelname.c_str(), "LookingForGroup") && !sWorld.m_lfgForNonLfg)
	{
		// make sure we have lfg dungeons
		for(i = 0; i < 3; ++i)
		{
			if(_player->LfgDungeonId[i] != 0)
				break;
		}

		if(i == 3)
			return;		// don't join lfg
	}

	if( sWorld.GmClientChannel.size() && !stricmp(sWorld.GmClientChannel.c_str(), channelname.c_str()) && !GetPermissionCount())
		return;
	
	chn = channelmgr.GetCreateChannel(channelname.c_str(), _player, dbc_id);
	if(chn == NULL)
		return;

	chn->AttemptJoin(_player, pass.c_str());
	DEBUG_LOG("ChannelJoin", "%s", channelname.c_str());
}
예제 #17
0
void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
{
	CHECK_PACKET_SIZE(recv_data, 9);
	WorldPacket *data;
	if(!_player->IsInWorld())
		return;

	uint32 type;
	int32 lang;

	const char * pMisc = 0;
	const char * pMsg = 0;
	recv_data >> type;
	recv_data >> lang;

	if( lang >= NUM_LANGUAGES )
		return;

	if(GetPlayer()->IsBanned())
	{
		GetPlayer()->BroadcastMessage("You cannot do that when banned.");
		return;
	}

	if(lang != -1 && !GetPermissionCount() && sWorld.flood_lines)
	{
		/* flood detection, wheeee! */
		if(UNIXTIME >= floodTime)
		{
			floodLines = 0;
			floodTime = UNIXTIME + sWorld.flood_seconds;
		}

		if((++floodLines) > sWorld.flood_lines)
		{
			if(sWorld.flood_message)
				_player->BroadcastMessage("Your message has triggered serverside flood protection. You can speak again in %u seconds.", floodTime - UNIXTIME);

			return;
		}
	}

	std::stringstream irctext;
	irctext.rdbuf()->str("");
	std::string msg;
	msg.reserve(256);

	//arghhh STFU. I'm not giving you gold or items NOOB
	switch(type)
	{
	case CHAT_MSG_EMOTE:
	case CHAT_MSG_SAY:
	case CHAT_MSG_YELL:
	case CHAT_MSG_WHISPER:
	case CHAT_MSG_CHANNEL:
		{
			if( m_muted && m_muted >= (uint32)UNIXTIME )
			{
				SystemMessage("Your voice is currently muted by a moderator.");
				return;
			}
		}break;
	}

	switch(type)
	{
	case CHAT_MSG_EMOTE:
		{
			recv_data >> msg;

			if(GetPlayer()->m_modlanguage >=0)
				data = sChatHandler.FillMessageData( CHAT_MSG_EMOTE, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
			else	
				data = sChatHandler.FillMessageData( CHAT_MSG_EMOTE, CanUseCommand('c') ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
			GetPlayer()->SendMessageToSet( data, true ,true );

			//sLog.outString("[emote] %s: %s", _player->GetName(), msg.c_str());
			delete data;
			
			pMsg=msg.c_str();
			pMisc=0;

		}break;
	case CHAT_MSG_SAY:
		{
			recv_data >> msg;

			if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
				break;

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			if(GetPlayer()->m_modlanguage >=0)
			{
				data = sChatHandler.FillMessageData( CHAT_MSG_SAY, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
				GetPlayer()->SendMessageToSet( data, true );
			}
			else
			{
				if(lang > 0 && LanguageSkills[lang] && _player->_HasSkillLine(LanguageSkills[lang]) == false)
					return;

				if(lang==0 && !CanUseCommand('c'))
					return;

				data = sChatHandler.FillMessageData( CHAT_MSG_SAY, lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
				SendChatPacket(data, 1, lang, this);
				for(set<Player*>::iterator itr = _player->m_inRangePlayers.begin(); itr != _player->m_inRangePlayers.end(); ++itr)
				{
					(*itr)->GetSession()->SendChatPacket(data, 1, lang, this);
				}
			}

			
			//sLog.outString("[say] %s: %s", _player->GetName(), msg.c_str());
			delete data;
			pMsg=msg.c_str();
			pMisc=0;
		} break;
	case CHAT_MSG_PARTY:
	case CHAT_MSG_RAID:
	case CHAT_MSG_RAID_LEADER:
	case CHAT_MSG_RAID_WARNING:
		{
			recv_data >> msg;

			if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
				break;
			
			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			Group *pGroup = _player->GetGroup();
			if(pGroup == NULL) break;
			
			if(GetPlayer()->m_modlanguage >=0)
				data=sChatHandler.FillMessageData( type, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
			else
				data=sChatHandler.FillMessageData( type, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0);
			if(type == CHAT_MSG_PARTY && pGroup->GetGroupType() == GROUP_TYPE_RAID)
			{
				// only send to that subgroup
				SubGroup * sgr = _player->GetGroup() ?
					_player->GetGroup()->GetSubGroup(_player->GetSubGroup()) : 0;

				if(sgr)
				{
					_player->GetGroup()->Lock();
					for(GroupMembersSet::iterator itr = sgr->GetGroupMembersBegin(); itr != sgr->GetGroupMembersEnd(); ++itr)
					{
						if((*itr)->m_loggedInPlayer)
							(*itr)->m_loggedInPlayer->GetSession()->SendChatPacket(data, 1, lang, this);
					}
					_player->GetGroup()->Unlock();
				}
			}
			else
			{
				SubGroup * sgr;
				for(uint32 i = 0; i < _player->GetGroup()->GetSubGroupCount(); ++i)
				{
					sgr = _player->GetGroup()->GetSubGroup(i);
					_player->GetGroup()->Lock();
					for(GroupMembersSet::iterator itr = sgr->GetGroupMembersBegin(); itr != sgr->GetGroupMembersEnd(); ++itr)
					{
						if((*itr)->m_loggedInPlayer)
							(*itr)->m_loggedInPlayer->GetSession()->SendChatPacket(data, 1, lang, this);
					}
					_player->GetGroup()->Unlock();
				}
			}
			//sLog.outString("[party] %s: %s", _player->GetName(), msg.c_str());
			delete data;
			pMsg=msg.c_str();
			pMisc=0;
		} break;
	case CHAT_MSG_GUILD:
		{
			recv_data >> msg;
			if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
			{
				break;
			}

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			if(_player->m_playerInfo->guild)
				_player->m_playerInfo->guild->GuildChat(msg.c_str(), this, lang);

			pMsg=msg.c_str();
			pMisc=0;
		} break;
	case CHAT_MSG_OFFICER:
		{
			recv_data >> msg;

			if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
				break;

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			if(_player->m_playerInfo->guild)
				_player->m_playerInfo->guild->OfficerChat(msg.c_str(), this, lang);

			pMsg=msg.c_str();
			pMisc=0;
		} break;
	case CHAT_MSG_YELL:
		{
			recv_data >> msg;

			if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
				break;

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}
			if(lang > 0 && LanguageSkills[lang] && _player->_HasSkillLine(LanguageSkills[lang]) == false)
				return;

			if(lang==0 && !CanUseCommand('c'))
				return;

			if(GetPlayer()->m_modlanguage >=0)
				data = sChatHandler.FillMessageData( CHAT_MSG_YELL, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
			else
				data = sChatHandler.FillMessageData( CHAT_MSG_YELL, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );

			//SendPacket(data);
			//sWorld.SendZoneMessage(data, GetPlayer()->GetZoneId(), this);
			_player->GetMapMgr()->SendChatMessageToCellPlayers(_player, data, 2, 1, lang, this);
			delete data;
			//sLog.outString("[yell] %s: %s", _player->GetName(), msg.c_str());
			pMsg=msg.c_str();
			pMisc=0;
		} break;
	case CHAT_MSG_WHISPER:
		{
			std::string to = "",tmp;
			recv_data >> to >> msg;

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}
		 
			Player *player = objmgr.GetPlayer(to.c_str(), false);
			if(!player)
			{
				data = new WorldPacket(SMSG_CHAT_PLAYER_NOT_FOUND, to.length() + 1);
				*data << to;
				SendPacket(data);
				delete data;
				break;
			}

			// Check that the player isn't a gm with his status on
			if(!_player->GetSession()->GetPermissionCount() && player->bGMTagOn && player->gmTargets.count(_player) == 0)
			{
				// Send CHAT_MSG_WHISPER_INFORM packet
				WorldPacket *data2;
				data2 = sChatHandler.FillMessageData(CHAT_MSG_WHISPER_INFORM, LANG_UNIVERSAL,msg.c_str(), player->GetGUID(), 0);
				SendPacket(data2);
				delete data2; 
				// Build automated reply
				string Reply = "This Game Master does not currently have an open ticket from you and did not receive your whisper. Please submit a new GM Ticket request if you need to speak to a GM. This is an automatic message.";
				data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, LANG_UNIVERSAL, Reply.c_str(), player->GetGUID(), 4);
				SendPacket(data);
				delete data;
				break;
			}

			if(lang > 0 && LanguageSkills[lang] && _player->_HasSkillLine(LanguageSkills[lang]) == false)
				return;

			if(lang==0 && !CanUseCommand('c'))
				return;

			if( player->Social_IsIgnoring( _player->GetLowGUID() ) )
			{
				data = sChatHandler.FillMessageData( CHAT_MSG_IGNORED, LANG_UNIVERSAL,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
				SendPacket(data);
				delete data;
			}
			else
			{
				if(GetPlayer()->m_modlanguage >=0)
					data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, GetPlayer()->m_modlanguage,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
				else
					data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, ((CanUseCommand('c') || player->GetSession()->CanUseCommand('c')) && lang != -1) ? LANG_UNIVERSAL : lang,  msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );

				player->GetSession()->SendPacket(data);
				delete data;
			}

			//Sent the to Users id as the channel, this should be fine as it's not used for wisper
		  
			data = sChatHandler.FillMessageData(CHAT_MSG_WHISPER_INFORM, LANG_UNIVERSAL,msg.c_str(), player->GetGUID(), 0  );
			SendPacket(data);
			delete data;

			if(player->HasFlag(PLAYER_FLAGS, 0x02))
			{
				// Has AFK flag, autorespond.
				data = sChatHandler.FillMessageData(CHAT_MSG_AFK, LANG_UNIVERSAL,  player->m_afk_reason.c_str(),player->GetGUID(), _player->bGMTagOn ? 4 : 0);
				SendPacket(data);
				delete data;
			}
			else if(player->HasFlag(PLAYER_FLAGS, 0x04))
			{
				// Has DND flag, autorespond.
				data = sChatHandler.FillMessageData(CHAT_MSG_DND, LANG_UNIVERSAL, player->m_afk_reason.c_str(),player->GetGUID(), _player->bGMTagOn ? 4 : 0);
				SendPacket(data);
				delete data;
			}

			//sLog.outString("[whisper] %s to %s: %s", _player->GetName(), to.c_str(), msg.c_str());
			pMsg=msg.c_str();
			pMisc=to.c_str();
		} break;
	case CHAT_MSG_CHANNEL:
		{
			std::string channel = "";
			recv_data >> channel;
			recv_data >> msg;
		 
			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
				break;

			Channel *chn = channelmgr.GetChannel(channel.c_str(),GetPlayer()); 
			if(chn) 
				chn->Say(GetPlayer(),msg.c_str(), NULL, false);

			//sLog.outString("[%s] %s: %s", channel.c_str(), _player->GetName(), msg.c_str());
			pMsg=msg.c_str();
			pMisc=channel.c_str();

		} break;
	case CHAT_MSG_AFK:
		{
			std::string reason;
			recv_data >> reason;
			GetPlayer()->SetAFKReason(reason);

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			/* WorldPacket *data, WorldSession* session, uint32 type, uint32 language, const char *channelName, const char *message*/
			if(GetPlayer()->HasFlag(PLAYER_FLAGS, 0x02))
			{
				GetPlayer()->RemoveFlag(PLAYER_FLAGS, 0x02);
				if(sWorld.GetKickAFKPlayerTime())
					sEventMgr.RemoveEvents(GetPlayer(),EVENT_PLAYER_SOFT_DISCONNECT);
			}
			else
			{
				GetPlayer()->SetFlag(PLAYER_FLAGS, 0x02);
				if(sWorld.GetKickAFKPlayerTime())
					sEventMgr.AddEvent(GetPlayer(),&Player::SoftDisconnect,EVENT_PLAYER_SOFT_DISCONNECT,sWorld.GetKickAFKPlayerTime(),1,0);
			}			
		} break;
	case CHAT_MSG_DND:
		{
			std::string reason;
			recv_data >> reason;
			GetPlayer()->SetAFKReason(reason);

			if(g_chatFilter->Parse(msg) == true)
			{
				SystemMessage("Your chat message was blocked by a server-side filter.");
				return;
			}

			if(GetPlayer()->HasFlag(PLAYER_FLAGS, 0x04))
				GetPlayer()->RemoveFlag(PLAYER_FLAGS, 0x04);
			else
			{
				GetPlayer()->SetFlag(PLAYER_FLAGS, 0x04);
			}		  
		} break;
	default:
		sLog.outError("CHAT: unknown msg type %u, lang: %u", type, lang);
	}

	if(pMsg)
		sHookInterface.OnChat(_player, type, lang, pMsg, pMisc);
}
예제 #18
0
void WorldSession::HandleChannelJoin(WorldPacket& recvPacket)
{
	CHECK_PACKET_SIZE(recvPacket, 1);
	string channelname,pass;
	uint32 dbc_id = 0;
	uint16 crap;		// crap = some sort of channel type? Actually it seems that this is 2 bytes and not 1 uint16
	Channel * chn;

	recvPacket >> crap;	// seems like 00 and 01 
	recvPacket >> dbc_id;
	recvPacket >> channelname;
	recvPacket >> pass;

	if(!stricmp(channelname.c_str(), "LookingForGroup") && !sWorld.m_lfgForNonLfg)
	{
/*		// make sure we have lfg dungeons
		for(uint32 i = 0; i < MAX_LFG_QUEUE_ID; ++i)
		{
			if(_player->LfgDungeonId[i] != 0)
				break;
		}

		if(i == MAX_LFG_QUEUE_ID)
			return;		// don't join lfg
			*/

		//are we looking to any dungeons at all ?
		if( _player->LFG_dungeons.begin() == NULL )
			return;
	}

	if( sWorld.GmClientChannel.size() && !stricmp(sWorld.GmClientChannel.c_str(), channelname.c_str()) && !GetPermissionCount())
	{ 
		return;
	}
	
	chn = channelmgr.GetCreateChannel(channelname.c_str(), _player, dbc_id);
	if(chn == NULL)
	{ 
		return;
	}

	chn->AttemptJoin(_player, pass.c_str());
	Log.Debug("ChannelJoin", "%s", channelname.c_str());
}