void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) { uint64 guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); return; } BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); // ignore if player is already in BG if (_player->InBattleGround()) return; // get bg instance or bg template if instance not found BattleGround *bg = NULL; if (instanceId) bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); if (!bracketEntry) return; // check queueing conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(0xFFFFFFFE); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: group end"); } else { GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); SendPacket(&data); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) { uint32 questId; recvPacket >> questId; if (!_player->CanShareQuest(questId)) return; TC_LOG_DEBUG("network", "WORLD: Received CMSG_PUSHQUESTTOPARTY questId = %u", questId); Quest const* quest = sObjectMgr->GetQuestTemplate(questId); if (!quest) return; Player * const sender = GetPlayer(); Group* group = sender->GetGroup(); if (!group) return; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* receiver = itr->GetSource(); if (!receiver || receiver == sender) continue; if (!receiver->SatisfyQuestStatus(quest, false)) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_HAVE_QUEST); continue; } if (receiver->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_FINISH_QUEST); continue; } if (!receiver->CanTakeQuest(quest, false)) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_CANT_TAKE_QUEST); continue; } if (!receiver->SatisfyQuestLog(false)) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_LOG_FULL); continue; } if (receiver->GetDivider() != 0) { sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_BUSY); continue; } sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_SHARING_QUEST); if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true)) { receiver->AddQuest(quest, sender); if (receiver->CanCompleteQuest(questId)) receiver->CompleteQuest(questId); } if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE)) receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true); else { receiver->SetDivider(sender->GetGUID()); receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, sender->GetGUID(), true); } } }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* loot = NULL; bool shareMoney = true; switch (GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); // do not check distance for GO if player is the owner of it (ex. fishing bobber) if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player, INTERACTION_DISTANCE)))) loot = &go->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*player, guid); if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = player->GetItemByGuid(guid)) { loot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* creature = player->GetMap()->GetCreature(guid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &creature->loot; if (creature->IsAlive()) shareMoney = false; } break; } default: return; // unlootable type } if (loot) { loot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false)) playersNear.push_back(member); } uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(goldPerPlayer); (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(goldPerPlayer); data << uint8(playersNear.size() <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(loot->gold); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(loot->gold); data << uint8(1); // "You loot..." SendPacket(&data); } loot->gold = 0; // Delete the money loot record from the DB if (loot->containerID > 0) loot->DeleteLootMoneyFromContainerItemDB(); // Delete container if empty if (loot->isLooted() && IS_ITEM_GUID(guid)) player->GetSession()->DoLootRelease(guid); } }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recv_data*/) { DEBUG_LOG("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); ObjectGuid guid = player->GetLootGuid(); if (!guid) return; Loot* pLoot = NULL; Item* pItem = NULL; switch (guid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && (pGameObject->GetOwnerGuid() == _player->GetObjectGuid() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = _player->GetMap()->GetCorpse(guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { pItem = GetPlayer()->GetItemByGuid(guid); if (!pItem || !pItem->HasGeneratedLoot()) return; pLoot = &pItem->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (!guid.IsItem() && player->GetGroup()) // item can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else player->ModifyMoney(pLoot->gold); pLoot->gold = 0; if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); } }
void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); //recv_data.hexlike(); ObjectGuid guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated Group * grp; recv_data >> guid >> arenaslot >> asGroup >> isRated; // ignore if we already in BG or BG queue if (_player->InBattleGround()) return; Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if(!unit->isBattleMaster()) // it's not battle master return; uint8 arenatype = 0; uint32 arenaRating = 0; switch(arenaslot) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); return; } // check existence BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA); if (!bg) { sLog.outError("Battleground: template bg (all arenas) not found"); return; } BattleGroundTypeId bgTypeId = bg->GetTypeID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; // check queue conditions if (!asGroup) { // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGuid() != _player->GetObjectGuid()) return; // may be Group::CanJoinBattleGroundQueue should be moved to player class... err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); } uint32 ateamId = 0; if (isRated) { ateamId = _player->GetArenaTeamId(arenaslot); // check real arena team existence only here (if it was moved to group->CanJoin .. () then we would have to get it twice) ArenaTeam * at = sObjectMgr.GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queue arenaRating = at->GetRating(); // the arena team id must match for everyone in the group // get the personal ratings for queue uint32 avg_pers_rating = 0; for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); // calc avg personal rating avg_pers_rating += member->GetArenaPersonalRating(arenaslot); } if (arenatype) avg_pers_rating /= arenatype; // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating if (avg_pers_rating + 150 < arenaRating) arenaRating = avg_pers_rating; } BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (asGroup) { uint32 avgTime; if(err > 0) { DEBUG_LOG("Battleground: arena join as group start"); if (isRated) DEBUG_LOG("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; WorldPacket data; if(err <= 0) { sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName()); } DEBUG_LOG("Battleground: arena join as group end"); } else { GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data) { uint32 type; uint32 lang; recv_data >> type; recv_data >> lang; if (type >= MAX_CHAT_MSG_TYPE) { sLog.outError("CHAT: Wrong message type received: %u", type); return; } DEBUG_LOG("CHAT: packet received. type %u, lang %u", type, lang); // prevent talking at unknown language (cheating) LanguageDesc const* langDesc = GetLanguageDescByID(lang); if (!langDesc) { SendNotification(LANG_UNKNOWN_LANGUAGE); return; } if (langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) { SendNotification(LANG_NOT_LEARNED_LANGUAGE); return; } if (lang == LANG_ADDON) { // Disabled addon channel? if (!sWorld.getConfig(CONFIG_BOOL_ADDON_CHANNEL)) return; } // LANG_ADDON should not be changed nor be affected by flood control else { // send in universal language if player in .gmon mode (ignore spell effects) if (_player->isGameMaster()) lang = LANG_UNIVERSAL; else { // send in universal language in two side iteration allowed mode if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT)) lang = LANG_UNIVERSAL; else { switch (type) { case CHAT_MSG_PARTY: case CHAT_MSG_RAID: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: // allow two side chat at group channel if two side group allowed if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) lang = LANG_UNIVERSAL; break; case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: // allow two side chat at guild channel if two side guild allowed if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GUILD)) lang = LANG_UNIVERSAL; break; } } // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) Unit::AuraList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE); if (!ModLangAuras.empty()) lang = ModLangAuras.front()->GetModifier()->m_miscvalue; } if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) { if (!_player->CanSpeak()) { std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); return; } GetPlayer()->UpdateSpeakTime(); } } switch (type) { case CHAT_MSG_SAY: case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (type == CHAT_MSG_SAY) GetPlayer()->Say(msg, lang); else if (type == CHAT_MSG_EMOTE) GetPlayer()->TextEmote(msg); else if (type == CHAT_MSG_YELL) GetPlayer()->Yell(msg, lang); } break; case CHAT_MSG_WHISPER: { std::string to, msg; recv_data >> to; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (!normalizePlayerName(to)) { SendPlayerNotFoundNotice(to); break; } Player* player = sObjectMgr.GetPlayer(to.c_str()); uint32 tSecurity = GetSecurity(); uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) { SendPlayerNotFoundNotice(to); return; } if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER) { if (GetPlayer()->GetTeam() != player->GetTeam()) { SendWrongFactionNotice(); return; } } // Playerbot mod: handle whispered command to bot if (player->GetPlayerbotAI()) { player->GetPlayerbotAI()->HandleCommand(msg, *GetPlayer()); GetPlayer()->m_speakTime = 0; GetPlayer()->m_speakCount = 0; } else GetPlayer()->Whisper(msg, lang, player->GetObjectGuid()); } break; case CHAT_MSG_PARTY: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /p Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { group = _player->GetGroup(); if (!group || group->isBGGroup()) return; } // Playerbot mod: broadcast message to bot members for(GroupReference* itr = group->GetFirstMember(); itr != NULL; itr=itr->next()) { Player* player = itr->getSource(); if (player && player->GetPlayerbotAI()) { player->GetPlayerbotAI()->HandleCommand(msg, *GetPlayer()); GetPlayer()->m_speakTime = 0; GetPlayer()->m_speakCount = 0; } } // END Playerbot mod WorldPacket data; ChatHandler::FillMessageData(&data, this, type, lang, msg.c_str()); group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetObjectGuid())); break; } case CHAT_MSG_GUILD: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (GetPlayer()->GetGuildId()) if (Guild* guild = sGuildMgr.GetGuildById(GetPlayer()->GetGuildId())) guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); break; } case CHAT_MSG_OFFICER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (GetPlayer()->GetGuildId()) if (Guild* guild = sGuildMgr.GetGuildById(GetPlayer()->GetGuildId())) guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); break; } case CHAT_MSG_RAID: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /ra Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { group = GetPlayer()->GetGroup(); if (!group || group->isBGGroup() || !group->isRaidGroup()) return; } WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_LEADER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /ra Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { group = GetPlayer()->GetGroup(); if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetObjectGuid())) return; } WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_WARNING: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; Group* group = GetPlayer()->GetGroup(); if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetObjectGuid()) || group->IsAssistant(GetPlayer()->GetObjectGuid()))) return; WorldPacket data; // in battleground, raid warning is sent only to players in battleground - code is ok ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group* group = GetPlayer()->GetGroup(); if (!group || !group->isBGGroup()) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND_LEADER: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group* group = GetPlayer()->GetGroup(); if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetObjectGuid())) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_CHANNEL: { std::string channel, msg; recv_data >> channel; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channel, _player)) chn->Say(_player->GetObjectGuid(), msg.c_str(), lang); } break; case CHAT_MSG_AFK: { std::string msg; recv_data >> msg; if (!_player->isInCombat()) { if (_player->isAFK()) // Already AFK { if (msg.empty()) _player->ToggleAFK(); // Remove AFK else _player->autoReplyMsg = msg; // Update message } else // New AFK mode { _player->autoReplyMsg = msg.empty() ? GetMangosString(LANG_PLAYER_AFK_DEFAULT) : msg; if (_player->isDND()) _player->ToggleDND(); _player->ToggleAFK(); } } break; } case CHAT_MSG_DND: { std::string msg; recv_data >> msg; if (_player->isDND()) // Already DND { if (msg.empty()) _player->ToggleDND(); // Remove DND else _player->autoReplyMsg = msg; // Update message } else // New DND mode { _player->autoReplyMsg = msg.empty() ? GetMangosString(LANG_PLAYER_DND_DEFAULT) : msg; if (_player->isAFK()) _player->ToggleAFK(); _player->ToggleDND(); } break; } default: sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); break; } }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data) { uint64 guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group* grp = NULL; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog->outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow()); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); // can do this since it's battleground BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId); // ignore if player is already in BG if (_player->InBattleground()) return; // get bg instance or bg template if instance not found Battleground* bg = NULL; if (instanceId) bg = sBattlegroundMgr->GetBattlegroundThroughClientInstance(instanceId, bgTypeId); if (!bg) bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg) return; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; // check queue conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) return; // check if has free queue slots if (!_player->HasFreeBattlegroundQueueId()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); _player->GetSession()->SendPacket(&data); return; } BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId]; GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, isPremade); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); SendPacket(&data); sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam()); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId]; GroupQueueInfo* ginfo = NULL; uint32 avgTime = 0; if (err > 0) { sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, isPremade); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; // this should never happen WorldPacket data; if (err <= 0) { sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName()); } sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: group end"); } sBattlegroundMgr->ScheduleQueueUpdate(bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recv_data*/) { DEBUG_LOG("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); ObjectGuid guid = player->GetLootGuid(); if (!guid) return; Loot* pLoot = NULL; Item* pItem = NULL; switch (guid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && (pGameObject->GetOwnerGuid() == _player->GetObjectGuid() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = _player->GetMap()->GetCorpse(guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { pItem = GetPlayer()->GetItemByGuid(guid); if (!pItem || !pItem->HasGeneratedLoot()) return; pLoot = &pItem->loot; break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (!guid.IsItem() && player->GetGroup()) // item can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) playersNear.push_back(playerGroup); } if (playersNear.size() == 0) { sLog.outError("WorldSession::HandleLootMoneyOpcode %s try aquire group loot without any group member! Cheat attempt assumed.", player->GetObjectGuid().GetString().c_str()); return; } uint64 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); if (Guild* guild = sGuildMgr.GetGuildById((*i)->GetGuildId())) if (uint32 guildGold = (*i)->GetTotalAuraModifier(SPELL_AURA_MOD_MONEY_TO_GUILD_BANK) / 100.0f * money_per_player) guild->HandleCashFlow(guildGold, *i); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4+1); data << uint32(money_per_player); data << uint8(playersNear.size() > 1 ? 0 : 1);// 0 is "you share of loot..." (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(pLoot->gold); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); if (Guild* guild = sGuildMgr.GetGuildById(player->GetGuildId())) if (uint32 guildGold = player->GetTotalAuraModifier(SPELL_AURA_MOD_MONEY_TO_GUILD_BANK) / 100.0f * pLoot->gold) guild->HandleCashFlow(guildGold, player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4+1); data << uint32(pLoot->gold); data << uint8(1); // 1 is "you loot..." player->GetSession()->SendPacket(&data); } pLoot->gold = 0; if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); } }
//Summon group of player bool ChatHandler::HandleGroupSummonCommand(const char* args) { Player* target; if (!extractPlayerTarget((char*)args, &target)) return false; // check online security if (HasLowerSecurity(target, 0)) return false; Group *grp = target->GetGroup(); std::string nameLink = GetNameLink(target); if (!grp) { PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); SetSentErrorMessage(true); return false; } Map* gmMap = m_session->GetPlayer()->GetMap(); bool to_instance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead if (to_instance && ( !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()))) // the last check is a bit excessive, but let it be, just in case { SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); SetSentErrorMessage(true); return false; } for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *pl = itr->getSource(); if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) continue; // check online security if (HasLowerSecurity(pl, 0)) return false; std::string plNameLink = GetNameLink(pl); if (pl->IsBeingTeleported() == true) { PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); SetSentErrorMessage(true); return false; } if (to_instance) { Map* plMap = pl->GetMap(); if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) { // cannot summon from instance to instance PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); SetSentErrorMessage(true); return false; } } PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); if (needReportToTarget(pl)) ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetNameLink().c_str()); // stop flight if need if (pl->isInFlight()) { pl->GetMotionMaster()->MovementExpired(); pl->CleanupAfterTaxiFlight(); } // save only in non-flight case else pl->SaveRecallPosition(); if (pl->IsMounted()) { pl->Unmount(); pl->RemoveAurasByType(SPELL_AURA_MOUNTED); } // before GM float x, y, z; m_session->GetPlayer()->GetClosePoint(x, y, z, pl->GetObjectSize()); pl->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, pl->GetOrientation()); } return true; }
void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+4+4+1); uint64 guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if(!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); return; } BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); // ignore if player is already in BG if(_player->InBattleGround()) return; Creature *unit = ObjectAccessor::GetCreature(*_player, guid); if(!unit) return; if(!unit->isBattleMaster()) // it's not battlemaster return; // get bg instance or bg template if instance not found BattleGround * bg = NULL; if(instanceId) BattleGround *bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } // check queueing conditions if(!joinAsGroup) { // check Deserter debuff if( !_player->CanJoinToBattleground() ) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << (uint32) 0xFFFFFFFE; _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if(!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if(!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: group end"); } else { // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(!ginfo->IsInvitedToBGInstanceGUID) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); }
void FocusMagic(uint32 diff) { if (!FOCUSMAGIC || me->getLevel() < 20 || fmCheckTimer > diff || GC_Timer > diff || Rand() < 50 || IsCasting()) return; if (Unit* target = FindAffectedTarget(FOCUSMAGIC, me->GetGUID(), 70, 2)) { fmCheckTimer = 30000; return; } else { Group* pGroup = master->GetGroup(); if (!pGroup) { if (master->getPowerType() == POWER_MANA && !master->HasAura(FOCUSMAGIC) && me->GetExactDist(master) < 30) target = master; } else { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->GetSource(); if (!pPlayer || pPlayer->isDead()) continue; if (me->GetMapId() != pPlayer->GetMapId()) continue; if ((pPlayer->getClass() == CLASS_MAGE || pPlayer->getClass() == CLASS_PRIEST || pPlayer->getClass() == CLASS_SHAMAN || pPlayer->getClass() == CLASS_DRUID || pPlayer->getClass() == CLASS_PALADIN || pPlayer->getClass() == CLASS_WARLOCK) && !pPlayer->HasAura(FOCUSMAGIC) && me->GetExactDist(pPlayer) < 30) { target = pPlayer; break; } } if (!target) { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->GetSource(); if (!pPlayer || !pPlayer->HaveBot()) continue; if (me->GetMapId() != pPlayer->GetMapId()) continue; for (uint8 i = 0; i != pPlayer->GetMaxNpcBots(); ++i) { Creature* cre = pPlayer->GetBotMap(i)->_Cre(); if (!cre || cre == me || cre->isDead() || cre->getPowerType() != POWER_MANA) continue; if ((cre->GetBotClass() == CLASS_MAGE || cre->GetBotClass() == CLASS_PRIEST || cre->GetBotClass() == CLASS_SHAMAN || cre->GetBotClass() == CLASS_DRUID || cre->GetBotClass() == CLASS_WARLOCK) && !cre->HasAura(FOCUSMAGIC) && me->GetExactDist(cre) < 30) { target = cre; break; } } } } } if (target && doCast(target, FOCUSMAGIC)) { GC_Timer = 500; fmCheckTimer = 30000; return; } } fmCheckTimer = 5000; }
void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+1+1+1); sLog.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); recv_data.hexlike(); // ignore if we already in BG or BG queue if(_player->InBattleGround()) return; uint64 guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated Group * grp; recv_data >> guid >> arenaslot >> asGroup >> isRated; Creature *unit = ObjectAccessor::GetCreature(*_player, guid); if(!unit) return; if(!unit->isBattleMaster()) // it's not battle master return; uint8 arenatype = 0; uint32 arenaRating = 0; switch(arenaslot) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog.outError("Unknown arena slot %u at HandleBattleGroundArenaJoin()", arenaslot); return; } //check existance BattleGround* bg = NULL; if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) ) { sLog.outError("Battleground: template bg (all arenas) not found"); return; } BattleGroundTypeId bgTypeId = bg->GetTypeID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); // check queueing conditions if(!asGroup) { // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if(!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if(!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } uint32 ateamId = 0; if(isRated) { ateamId = _player->GetArenaTeamId(arenaslot); // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); if(!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queueing arenaRating = at->GetRating(); // the arenateam id must match for everyone in the group // get the personal ratings for queueing uint32 avg_pers_rating = 0; for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); // calc avg personal rating avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaslot*6) + 5); } if( arenatype ) avg_pers_rating /= arenatype; // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating if(avg_pers_rating + 150 < arenaRating) arenaRating = avg_pers_rating; } GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); if(asGroup) { sLog.outDebug("Battleground: arena join as group start"); if(isRated) sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: arena join as group end"); if(isRated) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating); }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::BattlemasterJoin& battlemasterJoin) { bool isPremade = false; Group* grp = NULL; uint32 bgTypeId_ = battlemasterJoin.QueueID & 0xFFFF; if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { TC_LOG_ERROR("network", "Battleground: invalid bgtype (%u) received. possible cheater? %s", bgTypeId_, _player->GetGUID().ToString().c_str()); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); // can do this, since it's battleground, not arena BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0); BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); // ignore if player is already in BG if (_player->InBattleground()) return; // get bg instance or bg template if instance not found Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg) return; // expected bracket entry PvpDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE; // check queue conditions if (!battlemasterJoin.JoinAsGroup) { if (GetPlayer()->isUsingLfg()) { WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, 0, ERR_LFG_CANT_USE_BATTLEGROUND); SendPacket(battlefieldStatus.Write()); return; } // check Deserter debuff if (!_player->CanJoinToBattleground(bg)) { WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); SendPacket(battlefieldStatus.Write()); return; } if (_player->GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) { // player is already in random queue WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, 0, ERR_IN_RANDOM_BG); SendPacket(battlefieldStatus.Write()); return; } if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) { // player is already in queue, can't start random queue WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, 0, ERR_IN_NON_RANDOM_BG); SendPacket(battlefieldStatus.Write()); return; } // check if already in queue if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattlegroundQueueId()) { WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, 0, ERR_BATTLEGROUND_TOO_MANY_QUEUES); SendPacket(battlefieldStatus.Write()); return; } // check Freeze debuff if (_player->HasAura(9454)) return; BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, _player, queueSlot, ginfo->JoinTime, avgTime, ginfo->ArenaType, false); SendPacket(battlefieldStatus.Write()); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u, %s, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUID().ToString().c_str(), _player->GetName().c_str()); } else { grp = _player->GetGroup(); if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; ObjectGuid errorGuid; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0, errorGuid); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = NULL; uint32 avgTime = 0; if (!err) { TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; // this should never happen if (err) { WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, 0, err, &errorGuid); member->SendDirectMessage(battlefieldStatus.Write()); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, member, queueSlot, ginfo->JoinTime, avgTime, ginfo->ArenaType, true); member->SendDirectMessage(battlefieldStatus.Write()); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u, %s, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUID().ToString().c_str(), member->GetName().c_str()); } TC_LOG_DEBUG("bg.battleground", "Battleground: group end"); } sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandleBattlemasterJoinArena(WorldPackets::Battleground::BattlemasterJoinArena& packet) { // ignore if we already in BG or BG queue if (_player->InBattleground()) return; uint8 arenatype = ArenaTeam::GetTypeBySlot(packet.TeamSizeIndex); //check existence Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); if (!bg) { TC_LOG_ERROR("network", "Battleground: template bg (all arenas) not found"); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr)) { ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED); return; } BattlegroundTypeId bgTypeId = bg->GetTypeID(); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype); PvpDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; Group* grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; uint32 ateamId = _player->GetArenaTeamId(packet.TeamSizeIndex); // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queuing uint32 arenaRating = at->GetRating(); uint32 matchmakerRating = at->GetAverageMMR(grp); // the arenateam id must match for everyone in the group if (arenaRating <= 0) arenaRating = 1; BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); uint32 avgTime = 0; GroupQueueInfo* ginfo = nullptr; ObjectGuid errorGuid; GroupJoinBattlegroundResult err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, true, packet.TeamSizeIndex, errorGuid); if (!err) { TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(packet.TeamSizeIndex), _player->GetName().c_str(), matchmakerRating, arenatype); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, true, false, arenaRating, matchmakerRating, ateamId); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (err) { WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusFailed(&battlefieldStatus, bg, _player, 0, arenatype, err, &errorGuid); member->SendDirectMessage(battlefieldStatus.Write()); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, member, queueSlot, ginfo->JoinTime, avgTime, arenatype, true); member->SendDirectMessage(battlefieldStatus.Write()); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u, %s, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUID().ToString().c_str(), member->GetName().c_str()); } sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) { sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); Player *player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot *pLoot = NULL; switch(GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject *pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && ((pGameObject->GetOwnerGUID() == _player->GetGUID() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse *bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); if (bones && bones->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { if (Item *item = GetPlayer()->GetItemByGuid(guid)) pLoot = &item->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { if (!IS_ITEM_GUID(guid) && player->GetGroup()) //item can be looted only single player { Group *group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold)/(playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); //Offset surely incorrect, but works WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(pLoot->gold); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); } pLoot->gold = 0; pLoot->NotifyMoneyRemoved(); } }
void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty& packet) { if (!_player->CanShareQuest(packet.QuestID)) return; Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID); if (!quest) return; Player * const sender = GetPlayer(); Group* group = sender->GetGroup(); if (!group) return; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* receiver = itr->GetSource(); if (!receiver || receiver == sender) continue; if (!receiver->SatisfyQuestStatus(quest, false)) { sender->SendPushToPartyResponse(receiver, QUEST_PUSH_ONQUEST); continue; } if (receiver->GetQuestStatus(packet.QuestID) == QUEST_STATUS_COMPLETE) { sender->SendPushToPartyResponse(receiver, QUEST_PUSH_ALREADY_DONE); continue; } if (!receiver->CanTakeQuest(quest, false)) { sender->SendPushToPartyResponse(receiver, QUEST_PUSH_INVALID); continue; } if (!receiver->SatisfyQuestLog(false)) { sender->SendPushToPartyResponse(receiver, QUEST_PUSH_LOG_FULL); continue; } if (!receiver->GetDivider().IsEmpty()) { sender->SendPushToPartyResponse(receiver, QUEST_PUSH_BUSY); continue; } sender->SendPushToPartyResponse(receiver, QUEST_PUSH_SUCCESS); if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true)) receiver->AddQuestAndCheckCompletion(quest, sender); if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true); else { receiver->SetDivider(sender->GetGUID()); receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, receiver->GetGUID(), true); } } }
void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); uint64 guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated Group* grp = NULL; recv_data >> guid >> arenaslot >> asGroup >> isRated; // ignore if we already in BG or BG queue if (_player->InBattleground()) return; Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if (!unit->isBattleMaster()) // it's not battle master return; uint8 arenatype = 0; uint32 arenaRating = 0; uint32 matchmakerRating = 0; switch (arenaslot) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog->outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); return; } //check existance Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); if (!bg) { sLog->outError("Battleground: template bg (all arenas) not found"); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, NULL)) { ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED); return; } BattlegroundTypeId bgTypeId = bg->GetTypeID(); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL; if (!asGroup) { // check if already in queue if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattlegroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); } uint32 ateamId = 0; if (isRated) { ateamId = _player->GetArenaTeamId(arenaslot); // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queueing arenaRating = at->GetRating(); matchmakerRating = at->GetAverageMMR(grp); // the arenateam id must match for everyone in the group if (arenaRating <= 0) arenaRating = 1; } BattlegroundQueue &bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId]; if (asGroup) { uint32 avgTime = 0; if (err > 0) { sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: arena join as group start"); if (isRated) { sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName(), matchmakerRating, arenatype); bg->SetRated(true); } else bg->SetRated(false); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; WorldPacket data; if (err <= 0) { sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName()); } } else { GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recv_data*/) { sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* pLoot = NULL; bool shareMoney = true; switch (GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && ((pGameObject->GetOwnerGUID() == _player->GetGUID() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE)))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { pLoot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = GetPlayer()->GetItemByGuid(guid)) { pLoot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: { Creature* creature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_SKINNING); if (ok_loot && creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { pLoot = &creature->loot; if (creature->IsAlive()) shareMoney = false; } else player->SendLootError(guid, ok_loot ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL); break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->GetDistance2d(playerGroup) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else player->ModifyMoney(pLoot->gold); pLoot->gold = 0; } }
//Teleport group to given game_tele.entry static bool HandleTeleGroupCommand(ChatHandler* handler, const char* args) { if (!*args) return false; Player* target = handler->getSelectedPlayer(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); return false; } // check online security if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r GameTele const* tele = handler->extractGameTeleFromLink((char*)args); if (!tele) { handler->SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); handler->SetSentErrorMessage(true); return false; } MapEntry const* map = sMapStore.LookupEntry(tele->mapId); if (!map || map->IsBattlegroundOrArena()) { handler->SendSysMessage(LANG_CANNOT_TELE_TO_BG); handler->SetSentErrorMessage(true); return false; } std::string nameLink = handler->GetNameLink(target); Group* grp = target->GetGroup(); if (!grp) { handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || !player->GetSession()) continue; // check online security if (handler->HasLowerSecurity(player, ObjectGuid::Empty)) return false; std::string plNameLink = handler->GetNameLink(player); if (player->IsBeingTeleported()) { handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); continue; } handler->PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(), "", tele->name.c_str()); if (handler->needReportToTarget(player)) ChatHandler(player->GetSession()).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str()); // stop flight if need if (player->IsInFlight()) { player->GetMotionMaster()->MovementExpired(); player->CleanupAfterTaxiFlight(); } // save only in non-flight case else player->SaveRecallPosition(); player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); } return true; }
void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); uint8 arenaslot; // 2v2, 3v3 or 5v5 recvData >> arenaslot; // ignore if we already in BG or BG queue if (_player->InBattleground()) return; uint32 arenaRating = 0; uint32 matchmakerRating = 0; uint8 arenatype = ArenaTeam::GetTypeBySlot(arenaslot); if (!arenatype) { TC_LOG_ERROR("network", "Unknown arena type %u at HandleBattlemasterJoinArena()", arenatype); return; } //check existance Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); if (!bg) { TC_LOG_ERROR("network", "Battleground: template bg (all arenas) not found"); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, NULL)) { ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED); return; } BattlegroundTypeId bgTypeId = bg->GetTypeID(); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE; Group* grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; uint32 ateamId = _player->GetArenaTeamId(arenaslot); // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queueing arenaRating = at->GetRating(); matchmakerRating = at->GetAverageMMR(grp); // the arenateam id must match for everyone in the group if (arenaRating <= 0) arenaRating = 1; BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); uint32 avgTime = 0; GroupQueueInfo* ginfo = NULL; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, true, arenaslot); if (!err) { TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName().c_str(), matchmakerRating, arenatype); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, true, false, arenaRating, matchmakerRating, ateamId); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (err) { WorldPacket data; sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // add joined time data member->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, member, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, arenatype); member->GetSession()->SendPacket(&data); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str()); } sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* pProp) { if (!pProp) return; uint64 guid = GetPlayer()->GetGUID(); LfgProposalPlayerMap::const_iterator itPlayer = pProp->players.find(guid); if (itPlayer == pProp->players.end()) // Player MUST be in the proposal return; LfgProposalPlayer* ppPlayer = itPlayer->second; uint32 pLowGroupGuid = ppPlayer->groupLowGuid; uint32 dLowGuid = pProp->groupLowGuid; uint32 dungeonId = pProp->dungeonId; bool isSameDungeon = false; bool isContinue = false; Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; uint32 completedEncounters = 0; if (grp) { uint64 gguid = grp->GetGUID(); isContinue = grp->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue; } sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), pProp->state); WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + pProp->players.size() * (4 + 1 + 1 + 1 + 1 +1)); if (!isContinue) // Only show proposal dungeon if it's continue { LfgDungeonSet playerDungeons = sLFGMgr->GetSelectedDungeons(guid); if (playerDungeons.size() == 1) dungeonId = (*playerDungeons.begin()); } if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) { dungeonId = dungeon->Entry(); // Select a player inside to be get completed encounters from if (grp) { for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* groupMember = itr->getSource(); if (groupMember && groupMember->GetMapId() == uint32(dungeon->map)) { if (InstanceScript* instance = groupMember->GetInstanceScript()) completedEncounters = instance->GetCompletedEncounterMask(); break; } } } } ObjectGuid playerGUID = guid; ObjectGuid InstanceSaveGUID = MAKE_NEW_GUID(dungeonId, 0, HIGHGUID_INSTANCE_SAVE); data << uint32(0); data << uint32(dungeonId); data << uint32(completedEncounters); data << uint32(0x03); data << uint32(proposalId); data << uint32(getMSTime()); data << uint8(pProp->state); data.WriteBit(playerGUID[4]); data.WriteBit(isSameDungeon); data.WriteBit(playerGUID[2]); data.WriteBit(playerGUID[0]); data.WriteBits(pProp->players.size(), 21); for (itPlayer = pProp->players.begin(); itPlayer != pProp->players.end(); ++itPlayer) { bool inDungeon = false; bool inSameGroup = false; if (itPlayer->second->groupLowGuid) { inDungeon = itPlayer->second->groupLowGuid == dLowGuid; inSameGroup = itPlayer->second->groupLowGuid == pLowGroupGuid; } data.WriteBit(itPlayer->first == guid); // Self player data.WriteBit(itPlayer->second->accept != LFG_ANSWER_PENDING); // Answered data.WriteBit(inDungeon); // In dungeon (silent) data.WriteBit(inSameGroup); // Same Group than player data.WriteBit(itPlayer->second->accept == LFG_ANSWER_AGREE); // Accepted } data.WriteBit(playerGUID[5]); data.WriteBit(InstanceSaveGUID[7]); data.WriteBit(InstanceSaveGUID[4]); data.WriteBit(playerGUID[1]); data.WriteBit(InstanceSaveGUID[6]); data.WriteBit(InstanceSaveGUID[0]); data.WriteBit(InstanceSaveGUID[1]); data.WriteBit(playerGUID[6]); data.WriteBit(playerGUID[3]); data.WriteBit(InstanceSaveGUID[3]); data.WriteBit(InstanceSaveGUID[2]); data.WriteBit(isContinue); data.WriteBit(playerGUID[7]); data.WriteBit(InstanceSaveGUID[5]); data.FlushBits(); data.WriteByteSeq(InstanceSaveGUID[3]); data.WriteByteSeq(InstanceSaveGUID[0]); data.WriteByteSeq(playerGUID[2]); data.WriteByteSeq(playerGUID[3]); data.WriteByteSeq(playerGUID[1]); data.WriteByteSeq(playerGUID[4]); data.WriteByteSeq(InstanceSaveGUID[6]); data.WriteByteSeq(InstanceSaveGUID[4]); data.WriteByteSeq(InstanceSaveGUID[1]); data.WriteByteSeq(InstanceSaveGUID[5]); data.WriteByteSeq(playerGUID[6]); for (itPlayer = pProp->players.begin(); itPlayer != pProp->players.end(); ++itPlayer) data << uint32(itPlayer->second->role); data.WriteByteSeq(InstanceSaveGUID[2]); data.WriteByteSeq(playerGUID[7]); data.WriteByteSeq(playerGUID[0]); data.WriteByteSeq(InstanceSaveGUID[7]); data.WriteByteSeq(playerGUID[5]); SendPacket(&data); }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) { uint32 bgTypeId_; uint32 instanceId; bool asGroup; bool isPremade = false; Group* grp; ObjectGuid guid; recvData >> instanceId; // Instance Id guid[2] = recvData.ReadBit(); guid[0] = recvData.ReadBit(); guid[3] = recvData.ReadBit(); guid[1] = recvData.ReadBit(); guid[5] = recvData.ReadBit(); asGroup = recvData.ReadBit(); // As Group guid[4] = recvData.ReadBit(); guid[6] = recvData.ReadBit(); guid[7] = recvData.ReadBit(); recvData.ReadByteSeq(guid[2]); recvData.ReadByteSeq(guid[6]); recvData.ReadByteSeq(guid[4]); recvData.ReadByteSeq(guid[3]); recvData.ReadByteSeq(guid[7]); recvData.ReadByteSeq(guid[0]); recvData.ReadByteSeq(guid[5]); recvData.ReadByteSeq(guid[1]); //extract from guid bgTypeId_ = GUID_LOPART(uint64(guid)); if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { TC_LOG_ERROR("network", "Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow()); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); //TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID:"UI64FMTD" TypeId:%u)", guid, bgTypeId_); // can do this, since it's battleground, not arena BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0); BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); // ignore if player is already in BG if (_player->InBattleground()) return; // get bg instance or bg template if instance not found Battleground* bg = NULL; if (instanceId) bg = sBattlegroundMgr->GetBattlegroundThroughClientInstance(instanceId, bgTypeId); if (!bg) bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg && !sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId)) { TC_LOG_ERROR("network", "Battleground: no available bg / template found"); return; } // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE; // check queue conditions if (!asGroup) { if (GetPlayer()->isUsingLfg()) { WorldPacket data; sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_LFG_CANT_USE_BATTLEGROUND); GetPlayer()->GetSession()->SendPacket(&data); return; } // check Deserter debuff if (!_player->CanJoinToBattleground(bg)) { WorldPacket data; sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data); return; } if (_player->GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) { // player is already in random queue WorldPacket data; sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) { // player is already in queue, can't start random queue WorldPacket data; sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_NON_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattlegroundQueueId()) { WorldPacket data; sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_BATTLEGROUND_TOO_MANY_QUEUES); _player->GetSession()->SendPacket(&data); return; } BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); // add joined time data _player->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, ginfo->ArenaType); SendPacket(&data); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str()); } else { grp = _player->GetGroup(); if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = NULL; uint32 avgTime = 0; if (!err) { TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; // this should never happen WorldPacket data; if (err) { sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // add joined time data member->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, member, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, ginfo->ArenaType); member->GetSession()->SendPacket(&data); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str()); } TC_LOG_DEBUG("bg.battleground", "Battleground: group end"); } sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recv_data) { ObjectGuid guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group* grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow()); return; } BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); DEBUG_LOG("WORLD: Received opcode CMSG_BATTLEMASTER_JOIN from %s", guid.GetString().c_str()); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, ARENA_TYPE_NONE); // ignore if player is already in BG if (_player->InBattleGround()) return; Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if (!unit->isBattleMaster()) // it's not battlemaster return; // get bg instance or bg template if instance not found BattleGround* bg = NULL; if (instanceId) bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } BattleGroundBracketId bgBracketId = _player->GetBattleGroundBracketIdFromLevel(bgTypeId); // check queue conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(0xFFFFFFFE); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH) && (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup) { DEBUG_LOG("Battleground: the following players are joining as group:"); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bgBracketId, ARENA_TYPE_NONE, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player); // send status packet (in queue) WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->arenaType, TEAM_NONE); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName(), member->GetBGTeam()); } DEBUG_LOG("Battleground: group end"); } else { GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bgBracketId, ARENA_TYPE_NONE, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->arenaType, TEAM_NONE); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(0, ARENA_TYPE_NONE, bgQueueTypeId, bgTypeId, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); }
void WorldSession::SendLfgRoleCheckUpdate() { if (!sWorld.getConfig(CONFIG_BOOL_LFG_ENABLE)) { DEBUG_LOG("SendLfgRoleCheckUpdate %u failed - Dungeon finder disabled", GetPlayer()->GetObjectGuid().GetCounter()); return; } Group* group = GetPlayer()->GetGroup(); if (!group) return; LFGDungeonSet const* dungeons = group->GetLFGState()->GetDungeons(); if (!dungeons) return; DEBUG_LOG("SMSG_LFG_ROLE_CHECK_UPDATE %u, dugeons size " SIZEFMTD, GetPlayer()->GetObjectGuid().GetCounter(), dungeons->size()); WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons->size() * 4 + 1 + group->GetMembersCount() * (8 + 1 + 4 + 1)); data << uint32(group->GetLFGState()->GetRoleCheckState()); // Check result data << uint8(group->GetLFGState()->GetRoleCheckState() == LFG_ROLECHECK_INITIALITING); data << uint8(dungeons->size()); // Number of dungeons if (dungeons->size()) { for (LFGDungeonSet::const_iterator itr = dungeons->begin(); itr != dungeons->end(); ++itr) { data << uint32(*itr ? (*itr)->Entry() : 0); // Dungeon Entry } } data << uint8(group->GetMembersCount()); // Players in group if (group->GetMembersCount()) { // Leader info MUST be sent 1st :S ObjectGuid leaderguid = group->GetLeaderGuid(); Player* leader = sObjectMgr.GetPlayer(leaderguid); LFGRoleMask roles = LFG_ROLE_MASK_NONE; uint8 leaderLevel = 1; if (leader) { roles = leader->GetLFGState()->GetRoles(); leaderLevel = leader->getLevel(); } data << leaderguid; // Guid data << uint8(roles != LFG_ROLE_MASK_NONE); // Ready data << uint32(roles); // Roles data << uint8(leaderLevel); // Level for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { if (Player* member = itr->getSource()) { ObjectGuid guid = member->GetObjectGuid(); if (guid == leaderguid) continue; roles = member->GetLFGState()->GetRoles(); data << guid; // Guid data << uint8(roles != LFG_ROLE_MASK_NONE); // Ready data << uint32(roles); // Roles data << uint8(member->getLevel()); // Level } } } SendPacket(&data); }
void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) { ObjectGuid guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); return; } BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); DEBUG_LOG( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from %s", guid.GetString().c_str()); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); BattleGroundQueueTypeId bgQueueTypeIdRandom = BattleGroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); // ignore if player is already in BG if (_player->InBattleGround()) return; uint32 mapid = _player->GetMapId(); if(mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571) { SendNotification("You cannot join from here"); return; } // get bg instance or bg template if instance not found BattleGround *bg = NULL; if (instanceId) bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; // check queue conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data; sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data); return; } if (_player->GetBattleGroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) { //player is already in random queue WorldPacket data; sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } if(_player->InBattleGroundQueue() && bgTypeId == BATTLEGROUND_RB) { //player is already in queue, can't start random queue WorldPacket data; sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) { WorldPacket data; sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); _player->GetSession()->SendPacket(&data); return; } } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGuid() != _player->GetObjectGuid()) return; err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH) && (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup) { GroupQueueInfo * ginfo; uint32 avgTime; if(err > 0) { DEBUG_LOG("Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; // this should never happen uint32 mapid = member->GetMapId(); if(mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571) continue; WorldPacket data; if(err <= 0) { sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } DEBUG_LOG("Battleground: group end"); } else { GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
void WorldSession::SendLfgUpdateList(uint32 dungeonID) { if (!sWorld.getConfig(CONFIG_BOOL_LFR_ENABLE)) { DEBUG_LOG("SendLfgUpdateList %u failed - Raid finder disabled", GetPlayer()->GetObjectGuid().GetCounter()); return; } DEBUG_LOG("SMSG_LFG_SEARCH_RESULTS %u dungeonentry: %u ", GetPlayer()->GetObjectGuid().GetCounter(), dungeonID); LFGDungeonEntry const* dungeon = sLFGMgr.GetDungeon(dungeonID); if (!dungeon) return; Team team = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP) ? TEAM_NONE : GetPlayer()->GetTeam(); LFGQueueSet groups = sLFGMgr.GetDungeonGroupQueue(dungeon, team); LFGQueueSet players = sLFGMgr.GetDungeonPlayerQueue(dungeon, team); uint32 groupCount = groups.size(); uint32 groupSize = 4+4; for (LFGQueueSet::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) { Group* group = sObjectMgr.GetGroup(*itr); if (!group) continue; Player* leader = sObjectMgr.GetPlayer(group->GetLeaderGuid()); if (!leader) continue; leader->GetLFGState()->AddFlags(LFG_MEMBER_FLAG_CHARINFO | LFG_MEMBER_FLAG_COMMENT | LFG_MEMBER_FLAG_GROUPLEADER | LFG_MEMBER_FLAG_GROUPGUID | LFG_MEMBER_FLAG_ROLES | LFG_MEMBER_FLAG_AREA | LFG_MEMBER_FLAG_STATUS | LFG_MEMBER_FLAG_BIND); uint32 flags = leader->GetLFGState()->GetFlags(); if (flags & LFG_MEMBER_FLAG_COMMENT) groupSize += leader->GetLFGState()->GetComment().size()+1; if (flags & LFG_MEMBER_FLAG_ROLES) groupSize +=3; if (flags & LFG_MEMBER_FLAG_BIND) groupSize += (8+4); players.insert(*itr); for (GroupReference *itr2 = group->GetFirstMember(); itr2 != NULL; itr2 = itr2->next()) { Player* player = itr2->getSource(); if (!player || player == leader) continue; player->GetLFGState()->AddFlags(LFG_MEMBER_FLAG_GROUPLEADER | LFG_MEMBER_FLAG_GROUPGUID | LFG_MEMBER_FLAG_STATUS); player->GetLFGState()->RemoveFlags(LFG_MEMBER_FLAG_CHARINFO | LFG_MEMBER_FLAG_COMMENT | LFG_MEMBER_FLAG_ROLES | LFG_MEMBER_FLAG_AREA | LFG_MEMBER_FLAG_BIND); players.insert(player->GetObjectGuid()); } } uint32 playerCount = players.size(); uint32 playerSize = 4+4; uint32 guidsSize = 0; LFGQueueSet playersUpdated; playersUpdated.clear(); for(LFGQueueSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (!player || !player->IsInWorld()) continue; uint32 flags = player->GetLFGState()->GetFlags(); playerSize += (8+4); if (flags & LFG_MEMBER_FLAG_CHARINFO) playerSize += (1+1+1+3+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4); if (flags & LFG_MEMBER_FLAG_COMMENT) playerSize += player->GetLFGState()->GetComment().size()+1; // comment if (flags & LFG_MEMBER_FLAG_GROUPLEADER) playerSize += 1; if (flags & LFG_MEMBER_FLAG_GROUPGUID) playerSize += 8; if (flags & LFG_MEMBER_FLAG_ROLES) playerSize += 1; if (flags & LFG_MEMBER_FLAG_AREA) playerSize += 4; if (flags & LFG_MEMBER_FLAG_STATUS) playerSize += 1; if (flags & LFG_MEMBER_FLAG_BIND) playerSize += (8+4); if (flags & LFG_MEMBER_FLAG_UPDATE) { player->GetLFGState()->RemoveFlags(LFG_MEMBER_FLAG_UPDATE); playersUpdated.insert(player->GetObjectGuid()); guidsSize += 8; } } WorldPacket data(SMSG_LFG_SEARCH_RESULTS, 4 + 4 + 1 + groupSize + playerSize + guidsSize); data << uint32(dungeon->type); // type data << uint32(dungeon->Entry()); // entry from LFGDungeons.dbc if (!playersUpdated.empty()) { data << uint8(playersUpdated.size()); for (LFGQueueSet::const_iterator itr = playersUpdated.begin(); itr != playersUpdated.end(); ++itr) { data << *itr; // player guid } } else data << uint8(0); if (!groups.empty()) { data << uint32(groupCount); // groups count data << uint32(groupCount); // groups count2 for (LFGQueueSet::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) { Group* group = sObjectMgr.GetGroup(*itr); if (!group) continue; Player* leader = sObjectMgr.GetPlayer(group->GetLeaderGuid()); uint32 flags = leader->GetLFGState()->GetFlags(); data << group->GetObjectGuid(); data << flags; if (flags & LFG_MEMBER_FLAG_COMMENT) { data << leader->GetLFGState()->GetComment().c_str(); } if (flags & LFG_MEMBER_FLAG_ROLES) { for (int i = 0; i < 3; ++i) { // need implement function for roles count calculation. or not need? data << uint8(0); } } if (flags & LFG_MEMBER_FLAG_BIND) { ObjectGuid instanceGuid; uint32 encounters = 0; if (InstancePlayerBind* bind = leader->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) { instanceGuid = state->GetInstanceGuid(); encounters = state->GetCompletedEncountersMask(); } } data << instanceGuid; data << encounters; } } } else { data << uint32(0); data << uint32(0); // groups count2 } if (!players.empty()) { data << uint32(playerCount); // players count data << uint32(playerCount); // players count 2 for(LFGQueueSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (!player || !player->IsInWorld()) continue; uint32 flags = player->GetLFGState()->GetFlags(); data << *itr; // guid data << flags; // flags if (flags & LFG_MEMBER_FLAG_CHARINFO) // charinfo { data << uint8(player->getLevel()); data << uint8(player->getClass()); data << uint8(player->getRace()); for(int i = 0; i < 3; ++i) data << uint8(player->GetTalentsCount(i)); // spent talents count in specific tab data << uint32(player->GetArmor()); // armor data << uint32(player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SPELL)); // spd data << uint32(player->SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_SPELL)); // heal data << uint32(player->GetRatingBonusValue(CR_CRIT_MELEE)); // crit rating melee data << uint32(player->GetRatingBonusValue(CR_CRIT_RANGED)); // crit rating ranged data << uint32(player->GetRatingBonusValue(CR_CRIT_SPELL)); // crit rating spell data << float(player->GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER)*5); // mp5 data << float(player->GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER)*5); // unk data << uint32(player->GetTotalAttackPowerValue(BASE_ATTACK)); // attack power data << uint32(player->GetTotalStatValue(STAT_AGILITY)); // agility data << uint32(player->GetMaxHealth()); // health data << uint32(player->GetMaxPower(player->getPowerType())); // power data << uint32(player->GetFreeTalentPoints()); // free talent points (TOM_RUS) data << float(0); // unk data << uint32(player->GetRatingBonusValue(CR_DEFENSE_SKILL)); // defence rating data << uint32(player->GetRatingBonusValue(CR_DODGE)); // dodge rating data << uint32(player->GetRatingBonusValue(CR_BLOCK)); // block rating data << uint32(player->GetRatingBonusValue(CR_PARRY)); // parry rating data << uint32(player->GetRatingBonusValue(CR_HASTE_MELEE)); // crit rating data << uint32(player->GetRatingBonusValue(CR_EXPERTISE)); // expertize } if (flags & LFG_MEMBER_FLAG_COMMENT) data << player->GetLFGState()->GetComment().c_str(); // comment if (flags & LFG_MEMBER_FLAG_GROUPLEADER) // Group leader flag { bool isLeader = false; if (Group* group = player->GetGroup()) if (player->GetObjectGuid() == group->GetLeaderGuid()) isLeader = true; data << uint8(isLeader); } if (flags & LFG_MEMBER_FLAG_GROUPGUID) // Group guid { ObjectGuid groupGuid = ObjectGuid(); if (Group* group = player->GetGroup()) groupGuid = group->GetObjectGuid(); data << groupGuid; } if (flags & LFG_MEMBER_FLAG_ROLES) // rolesMask data << uint8(player->GetLFGState()->GetRoles()); if (flags & LFG_MEMBER_FLAG_AREA) // Area data << uint32(player->GetAreaId()); if (flags & LFG_MEMBER_FLAG_STATUS) // status data << uint8(0); if (flags & LFG_MEMBER_FLAG_BIND) { ObjectGuid instanceGuid; uint32 encounters = 0; if (InstancePlayerBind* bind = player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) { instanceGuid = state->GetInstanceGuid(); encounters = state->GetCompletedEncountersMask(); } } data << instanceGuid; data << encounters; } } } else { data << uint32(0); // players count data << uint32(0); // unk } SendPacket(&data); }
void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* pProp) { if (!pProp) return; uint64 guid = GetPlayer()->GetGUID(); LfgProposalPlayerMap::const_iterator itPlayer = pProp->players.find(guid); if (itPlayer == pProp->players.end()) // Player MUST be in the proposal return; LfgProposalPlayer* ppPlayer = itPlayer->second; uint32 pLowGroupGuid = ppPlayer->groupLowGuid; uint32 dLowGuid = pProp->groupLowGuid; uint32 dungeonId = pProp->dungeonId; bool isSameDungeon = false; bool isContinue = false; Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; uint32 completedEncounters = 0; if (grp) { uint64 gguid = grp->GetGUID(); isContinue = grp->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue; } sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), pProp->state); WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + pProp->players.size() * (4 + 1 + 1 + 1 + 1 +1)); if (!isContinue) // Only show proposal dungeon if it's continue { LfgDungeonSet playerDungeons = sLFGMgr->GetSelectedDungeons(guid); if (playerDungeons.size() == 1) dungeonId = (*playerDungeons.begin()); } if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) { dungeonId = dungeon->Entry(); // Select a player inside to be get completed encounters from if (grp) { for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* groupMember = itr->getSource(); if (groupMember && groupMember->GetMapId() == uint32(dungeon->map)) { if (InstanceScript* instance = groupMember->GetInstanceScript()) completedEncounters = instance->GetCompletedEncounterMask(); break; } } } } data << uint32(dungeonId); // Dungeon data << uint8(pProp->state); // Result state data << uint32(proposalId); // Internal Proposal ID data << uint32(completedEncounters); // Bosses killed data << uint8(isSameDungeon); // Silent (show client window) data << uint8(pProp->players.size()); // Group size for (itPlayer = pProp->players.begin(); itPlayer != pProp->players.end(); ++itPlayer) { ppPlayer = itPlayer->second; data << uint32(ppPlayer->role); // Role data << uint8(itPlayer->first == guid); // Self player if (!ppPlayer->groupLowGuid) // Player not it a group { data << uint8(0); // Not in dungeon data << uint8(0); // Not same group } else { data << uint8(ppPlayer->groupLowGuid == dLowGuid); // In dungeon (silent) data << uint8(ppPlayer->groupLowGuid == pLowGroupGuid); // Same Group than player } data << uint8(ppPlayer->accept != LFG_ANSWER_PENDING); // Answered data << uint8(ppPlayer->accept == LFG_ANSWER_AGREE); // Accepted } SendPacket(&data); }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data) { uint8 joinAsGroup; uint32 bgTypeId_; uint32 unk, unk2; bool isPremade = false; Group * grp = NULL; recv_data >> joinAsGroup; // join as group (join as group = 0x80, else 0x0) recv_data >> unk; // unk recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> unk2; // unk if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog->outError( "Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow()); return; } if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); // can do this, since it's battleground, not arena BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId( bgTypeId, 0); BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); // ignore if player is already in BG if (_player->InBattleground()) return; // get bg template Battleground *bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg) return; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel( bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; // check queue conditions if (!joinAsGroup) { if (GetPlayer()->isUsingLfg()) { // player is using dungeon finder or raid finder WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_LFG_CANT_USE_BATTLEGROUND); GetPlayer()->GetSession()->SendPacket(&data); return; } // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data); return; } if (_player->GetBattlegroundQueueIndex( bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) { //player is already in random queue WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) { //player is already in queue, can't start random queue WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattlegroundQueueIndex( bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattlegroundQueueId()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); _player->GetSession()->SendPacket(&data); return; } BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId]; GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); SendPacket(&data); sLog->outDebug( LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId]; GroupQueueInfo * ginfo = NULL; uint32 avgTime = 0; if (err > 0) { sLog->outDebug( LOG_FILTER_BATTLEGROUND, "Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if (!member) continue; // this should never happen WorldPacket data; if (err <= 0) { sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); sLog->outDebug( LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName()); } sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: group end"); } sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
// Summon group of player static bool HandleGroupSummonCommand(ChatHandler* handler, char const* args) { Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; // check online security if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; Group* group = target->GetGroup(); std::string nameLink = handler->GetNameLink(target); if (!group) { handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } Player* gmPlayer = handler->GetSession()->GetPlayer(); Group* gmGroup = gmPlayer->GetGroup(); Map* gmMap = gmPlayer->GetMap(); bool toInstance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead if (toInstance && ( !gmGroup || group->GetLeaderGUID() != gmPlayer->GetGUID() || gmGroup->GetLeaderGUID() != gmPlayer->GetGUID())) // the last check is a bit excessive, but let it be, just in case { handler->SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); handler->SetSentErrorMessage(true); return false; } for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == gmPlayer || !player->GetSession()) continue; // check online security if (handler->HasLowerSecurity(player, ObjectGuid::Empty)) return false; std::string plNameLink = handler->GetNameLink(player); if (player->IsBeingTeleported()) { handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } if (toInstance) { Map* playerMap = player->GetMap(); if (playerMap->Instanceable() && playerMap->GetInstanceId() != gmMap->GetInstanceId()) { // cannot summon from instance to instance handler->PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } } handler->PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); if (handler->needReportToTarget(player)) ChatHandler(player->GetSession()).PSendSysMessage(LANG_SUMMONED_BY, handler->GetNameLink().c_str()); // stop flight if need if (player->IsInFlight()) { player->GetMotionMaster()->MovementExpired(); player->CleanupAfterTaxiFlight(); } // save only in non-flight case else player->SaveRecallPosition(); // before GM float x, y, z; gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize()); player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); } return true; }
void WorldSession::HandleQuestPushToParty(WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket,4); uint32 quest; recvPacket >> quest; sLog.outDebug( "WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", quest ); Quest const *pQuest = objmgr.GetQuestTemplate(quest); if( pQuest ) { if( _player->GetGroup() ) { Group *pGroup = _player->GetGroup(); if( pGroup ) { for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *pPlayer = itr->getSource(); if (!pPlayer || pPlayer == _player) // skip self continue; _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); if( !pPlayer->SatisfyQuestStatus( pQuest, false ) ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_HAVE_QUEST ); continue; } if( pPlayer->GetQuestStatus( quest ) == QUEST_STATUS_COMPLETE ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_FINISH_QUEST ); continue; } if( !pPlayer->CanTakeQuest( pQuest, false ) ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_CANT_TAKE_QUEST ); continue; } if( !pPlayer->SatisfyQuestLog( false ) ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_LOG_FULL ); continue; } if( pPlayer->GetDivider() != 0 ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_BUSY ); continue; } pPlayer->PlayerTalkClass->SendQuestGiverQuestDetails( pQuest, _player->GetGUID(), true ); pPlayer->SetDivider( _player->GetGUID() ); } } } } }