size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Language language, ObjectGuid senderGUID, ObjectGuid receiverGUID, std::string const& message, uint8 chatTag, std::string const& senderName /*= ""*/, std::string const& receiverName /*= ""*/, uint32 achievementId /*= 0*/, bool gmMessage /*= false*/, std::string const& channelName /*= ""*/) { size_t receiverGUIDPos = 0; data.Initialize(!gmMessage ? SMSG_MESSAGECHAT : SMSG_GM_MESSAGECHAT); data << uint8(chatType); data << int32(language); data << uint64(senderGUID); data << uint32(0); // some flags switch (chatType) { case CHAT_MSG_MONSTER_SAY: case CHAT_MSG_MONSTER_PARTY: case CHAT_MSG_MONSTER_YELL: case CHAT_MSG_MONSTER_WHISPER: case CHAT_MSG_MONSTER_EMOTE: case CHAT_MSG_RAID_BOSS_EMOTE: case CHAT_MSG_RAID_BOSS_WHISPER: case CHAT_MSG_BATTLENET: data << uint32(senderName.length() + 1); data << senderName; receiverGUIDPos = data.wpos(); data << uint64(receiverGUID); if (receiverGUID && !receiverGUID.IsPlayer() && !receiverGUID.IsPet()) { data << uint32(receiverName.length() + 1); data << receiverName; } break; case CHAT_MSG_WHISPER_FOREIGN: data << uint32(senderName.length() + 1); data << senderName; receiverGUIDPos = data.wpos(); data << uint64(receiverGUID); break; case CHAT_MSG_BG_SYSTEM_NEUTRAL: case CHAT_MSG_BG_SYSTEM_ALLIANCE: case CHAT_MSG_BG_SYSTEM_HORDE: receiverGUIDPos = data.wpos(); data << uint64(receiverGUID); if (receiverGUID && !receiverGUID.IsPlayer()) { data << uint32(receiverName.length() + 1); data << receiverName; } break; case CHAT_MSG_ACHIEVEMENT: case CHAT_MSG_GUILD_ACHIEVEMENT: receiverGUIDPos = data.wpos(); data << uint64(receiverGUID); break; default: if (gmMessage) { data << uint32(senderName.length() + 1); data << senderName; } if (chatType == CHAT_MSG_CHANNEL) { ASSERT(channelName.length() > 0); data << channelName; } receiverGUIDPos = data.wpos(); data << uint64(receiverGUID); break; } data << uint32(message.length() + 1); data << message; data << uint8(chatTag); if (chatType == CHAT_MSG_ACHIEVEMENT || chatType == CHAT_MSG_GUILD_ACHIEVEMENT) data << uint32(achievementId); return receiverGUIDPos; }
void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) { ObjectGuid guid; uint32 questId; uint32 startCheat; recvData >> guid >> questId >> startCheat; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST %s, quest = %u, startCheat = %u", guid.ToString().c_str(), questId, startCheat); Object* object; if (!guid.IsPlayer()) object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); else object = ObjectAccessor::FindPlayer(guid); #define CLOSE_GOSSIP_CLEAR_DIVIDER() \ do { \ _player->PlayerTalkClass->SendCloseGossip(); \ _player->SetDivider(ObjectGuid::Empty); \ } while (0) // no or incorrect quest giver if (!object) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Player* playerQuestObject = object->ToPlayer()) { if ((_player->GetDivider() && _player->GetDivider() != guid) || !playerQuestObject->CanShareQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (!_player->IsInSameRaidWith(playerQuestObject)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } else { if (!object->hasQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { // prevent cheating if (!GetPlayer()->CanTakeQuest(quest, true)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (!_player->GetDivider().IsEmpty()) { Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); if (player) { player->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); _player->SetDivider(ObjectGuid::Empty); } } if (_player->CanAddQuest(quest, true)) { _player->AddQuestAndCheckCompletion(quest, object); if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) { if (Group* group = _player->GetGroup()) { for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == _player) // not self continue; if (player->CanTakeQuest(quest, true)) { player->SetDivider(_player->GetGUID()); // need confirmation that any gossip window will close player->PlayerTalkClass->SendCloseGossip(); _player->SendQuestConfirmAccept(quest, player); } } } } _player->PlayerTalkClass->SendCloseGossip(); if (quest->GetSrcSpell() > 0) _player->CastSpell(_player, quest->GetSrcSpell(), true); return; } } CLOSE_GOSSIP_CLEAR_DIVIDER(); #undef CLOSE_GOSSIP_CLEAR_DIVIDER }