bool OnCheck(Player* source, Unit* /*target*/) { if (!source) return false; Battleground* battleground = source->GetBattleground(); return battleground && battleground->GetBgTypeID() == BATTLEGROUND_SA && battleground->ToBattlegroundSA()->notEvenAScratch(source->GetTeamId()); }
bool OnCheck(Player* source, Unit* target) { if (!target) return false; if (Player const* player = target->ToPlayer()) { Battleground* bg = source->GetBattleground(); return bg && bg->GetBgTypeID() == BATTLEGROUND_WS && bg->ToBattlegroundWS()->GetFlagState(player->GetTeamId()) == BG_WS_FLAG_STATE_ON_BASE; } return false; }
void BattlegroundQueue::BattlegroundQueueUpdate(BattlegroundBracketId bracket_id, uint8 actionMask, bool isRated, uint32 arenaRatedTeamId) { // if no players in queue - do nothing if (m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].empty() && m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].empty()) return; Battleground* bg_template = sBattlegroundMgr->GetBattlegroundTemplate(m_bgTypeId); if (!bg_template) return; PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketById(bg_template->GetMapId(), bracket_id); if (!bracketEntry) return; // battlegrounds with free slots should be populated first using players in queue if ((actionMask & 0x01) && !BattlegroundMgr::IsArenaType(m_bgTypeId)) { const BattlegroundContainer& bgList = sBattlegroundMgr->GetBattlegroundList(); BattlegroundNeedSet bgsToCheck; // sort from most needing (most empty) to least needing using a std::set with functor for (BattlegroundContainer::const_iterator itr = bgList.begin(); itr != bgList.end(); ++itr) { Battleground* bg = itr->second; if (!BattlegroundMgr::IsArenaType(bg->GetBgTypeID()) && (bg->GetBgTypeID() == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) && bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel && bg->GetMaxLevel() >= bracketEntry->maxLevel) bgsToCheck.insert(bg); } // now iterate needing battlegrounds for (BattlegroundNeedSet::iterator itr = bgsToCheck.begin(); itr != bgsToCheck.end(); ++itr) { Battleground* bg = *itr; // call a function that fills whatever we can from normal queues FillPlayersToBG(bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id); // invite players for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr) BattlegroundMgr::InviteGroupToBG((*citr), bg, (*citr)->teamId); } } // finished iterating through battlegrounds with free slots, maybe we need to create a new bg if ((actionMask & 0x02) == 0) return; // get min and max players per team uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); if (bg_template->isArena()) { MinPlayersPerTeam = sBattlegroundMgr->isArenaTesting() ? 1 : m_arenaType; MaxPlayersPerTeam = m_arenaType; } // check if can start new premade battleground if (bg_template->isBattleground() && m_bgTypeId != BATTLEGROUND_RB) if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)) { // create new battleground Battleground* bg = sBattlegroundMgr->CreateNewBattleground(m_bgTypeId, bracketEntry->minLevel, bracketEntry->maxLevel, 0, false); if (!bg) return; // invite players for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr) BattlegroundMgr::InviteGroupToBG((*citr), bg, (*citr)->teamId); bg->StartBattleground(); // now fill the premade bg if possible (only one team for each side has been invited yet) if (bg->HasFreeSlots()) { // call a function that fills whatever we can from normal queues FillPlayersToBG(bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id); // invite players for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr) BattlegroundMgr::InviteGroupToBG((*citr), bg, (*citr)->teamId); } } // check if can start new normal battleground or non-rated arena if (!isRated) { if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam) || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam))) { BattlegroundTypeId newBgTypeId = m_bgTypeId; uint32 minLvl = bracketEntry->minLevel; uint32 maxLvl = bracketEntry->maxLevel; // for random bg use values from specific if (m_bgTypeId == BATTLEGROUND_RB) { newBgTypeId = sBattlegroundMgr->RandomSystem.GetCurrentRandomBg(); Battleground* specificTemplate = sBattlegroundMgr->GetBattlegroundTemplate(newBgTypeId); if (!specificTemplate) return; PvPDifficultyEntry const* specificBracket = GetBattlegroundBracketByLevel(specificTemplate->GetMapId(), sBattlegroundMgr->randomBgDifficultyEntry.minLevel); if (!specificBracket) return; minLvl = specificBracket->minLevel; maxLvl = specificBracket->maxLevel; sBattlegroundMgr->RandomSystem.BattlegroundCreated(newBgTypeId); } // create new battleground Battleground* bg = sBattlegroundMgr->CreateNewBattleground(newBgTypeId, minLvl, maxLvl, m_arenaType, false); if (!bg) return; // invite players for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr) BattlegroundMgr::InviteGroupToBG((*citr), bg, (*citr)->teamId); bg->StartBattleground(); } } // check if can start new rated arenas (can create many in single queue update) else if (bg_template->isArena()) { // pussywizard: everything inside this section is mine, do NOT destroy! const uint32 currMSTime = World::GetGameTimeMS(); const uint32 discardTime = sBattlegroundMgr->GetRatingDiscardTimer(); const uint32 maxDefaultRatingDifference = (MaxPlayersPerTeam > 2 ? 300 : 200); const uint32 maxCountedMMR = 2500; // we need to find 2 teams which will play next game GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT]; bool increaseItr = true; bool reverse1 = urand(0,1) ? true : false; for (uint8 ii = BG_QUEUE_PREMADE_ALLIANCE; ii <= BG_QUEUE_PREMADE_HORDE; ii++) { uint8 i = reverse1 ? (BG_QUEUE_PREMADE_HORDE-ii) : ii; for (GroupsQueueType::iterator itr = m_QueuedGroups[bracket_id][i].begin(); itr != m_QueuedGroups[bracket_id][i].end(); (increaseItr ? ++itr : itr)) { increaseItr = true; // if arenaRatedTeamId is set - look for oponents only for one team, if not - pair every possible team if (arenaRatedTeamId != 0 && arenaRatedTeamId != (*itr)->ArenaTeamId) continue; if ((*itr)->IsInvitedToBGInstanceGUID) continue; uint32 MMR1 = std::min((*itr)->ArenaMatchmakerRating, maxCountedMMR); GroupsQueueType::iterator oponentItr; uint8 oponentQueue = BG_QUEUE_GROUP_TYPES_COUNT; uint32 minOponentMMRDiff = 0xffffffff; uint8 oponentValid = 0; bool reverse2 = urand(0,1) ? true : false; for (uint8 jj = BG_QUEUE_PREMADE_ALLIANCE; jj <= BG_QUEUE_PREMADE_HORDE; jj++) { uint8 j = reverse2 ? (BG_QUEUE_PREMADE_HORDE-jj) : jj; bool brk = false; for (GroupsQueueType::iterator itr2 = m_QueuedGroups[bracket_id][j].begin(); itr2 != m_QueuedGroups[bracket_id][j].end(); ++itr2) { if ((*itr)->ArenaTeamId == (*itr2)->ArenaTeamId) continue; if ((*itr2)->IsInvitedToBGInstanceGUID) continue; uint32 MMR2 = std::min((*itr2)->ArenaMatchmakerRating, maxCountedMMR); uint32 MMRDiff = (MMR2>=MMR1 ? MMR2-MMR1 : MMR1-MMR2); uint32 maxAllowedDiff = maxDefaultRatingDifference; uint32 shorterWaitTime, longerWaitTime; if (currMSTime-(*itr)->JoinTime <= currMSTime-(*itr2)->JoinTime) { shorterWaitTime = currMSTime-(*itr)->JoinTime; longerWaitTime = currMSTime-(*itr2)->JoinTime; } else { shorterWaitTime = currMSTime-(*itr2)->JoinTime; longerWaitTime = currMSTime-(*itr)->JoinTime; } if (longerWaitTime >= discardTime) maxAllowedDiff += 150; maxAllowedDiff += shorterWaitTime/600; // increased by 100 for each minute // now check if this team is more appropriate than previous ones: if (currMSTime-(*itr)->JoinTime >= 20*MINUTE*IN_MILLISECONDS && (oponentValid < 3 || MMRDiff < minOponentMMRDiff)) // after 20 minutes of waiting, pair with closest mmr, regardless the difference { oponentValid = 3; minOponentMMRDiff = MMRDiff; oponentItr = itr2; oponentQueue = j; } else if (MMR1 >= 2000 && MMR2 >= 2000 && longerWaitTime >= 2*discardTime && (oponentValid < 2 || MMRDiff < minOponentMMRDiff)) // after 6 minutes of waiting, pair any 2000+ vs 2000+ { oponentValid = 2; minOponentMMRDiff = MMRDiff; oponentItr = itr2; oponentQueue = j; } else if (oponentValid < 2 && MMRDiff < minOponentMMRDiff) { if (!oponentValid) { minOponentMMRDiff = MMRDiff; oponentItr = itr2; oponentQueue = j; if (MMRDiff <= maxAllowedDiff) oponentValid = 1; } if ((MMR1 < 1800 || MMR2 < 1800) && MaxPlayersPerTeam == 2 && MMRDiff <= maxDefaultRatingDifference) // in 2v2 below 1800 mmr - priority for default allowed difference { minOponentMMRDiff = MMRDiff; oponentItr = itr2; oponentQueue = j; brk = true; break; } } } if (brk) break; } if (oponentQueue != BG_QUEUE_GROUP_TYPES_COUNT) { if (oponentValid) { itr_teams[i] = itr; itr_teams[i == 0 ? 1 : 0] = oponentItr; { GroupQueueInfo* aTeam = *itr_teams[TEAM_ALLIANCE]; GroupQueueInfo* hTeam = *itr_teams[TEAM_HORDE]; Battleground* arena = sBattlegroundMgr->CreateNewBattleground(m_bgTypeId, bracketEntry->minLevel, bracketEntry->maxLevel, m_arenaType, true); if (!arena) return; aTeam->OpponentsTeamRating = hTeam->ArenaTeamRating; hTeam->OpponentsTeamRating = aTeam->ArenaTeamRating; aTeam->OpponentsMatchmakerRating = hTeam->ArenaMatchmakerRating; hTeam->OpponentsMatchmakerRating = aTeam->ArenaMatchmakerRating; // now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer if (aTeam->teamId != TEAM_ALLIANCE) { aTeam->_groupType = BG_QUEUE_PREMADE_ALLIANCE; m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(aTeam); m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].erase(itr_teams[TEAM_ALLIANCE]); increaseItr = false; itr = m_QueuedGroups[bracket_id][i].begin(); } if (hTeam->teamId != TEAM_HORDE) { hTeam->_groupType = BG_QUEUE_PREMADE_HORDE; m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].push_front(hTeam); m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_teams[TEAM_HORDE]); increaseItr = false; itr = m_QueuedGroups[bracket_id][i].begin(); } arena->SetArenaMatchmakerRating(TEAM_ALLIANCE, aTeam->ArenaMatchmakerRating); arena->SetArenaMatchmakerRating(TEAM_HORDE, hTeam->ArenaMatchmakerRating); BattlegroundMgr::InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE); BattlegroundMgr::InviteGroupToBG(hTeam, arena, TEAM_HORDE); arena->StartBattleground(); } if (arenaRatedTeamId) return; else continue; } else if (arenaRatedTeamId) return; } } } } }
bool OnCheck(Player* source, Unit* /*target*/) { Battleground* bg = source->GetBattleground(); return bg && bg->GetBgTypeID() == BATTLEGROUND_IC && bg->ToBattlegroundIC()->IsResourceGlutAllowed(source->GetTeamId()); }
bool OnCheck(Player* source, Unit* /*target*/) { Battleground* bg = source->GetBattleground(); return bg && bg->GetBgTypeID() == BATTLEGROUND_AB && bg->ToBattlegroundAB()->IsTeamScores500Disadvantage(source->GetTeamId()); }
bool OnCheck(Player* source, Unit* /*target*/) { Battleground* bg = source->GetBattleground(); return bg && bg->GetBgTypeID() == BATTLEGROUND_SA && bg->ToBattlegroundSA()->AllowDefenseOfTheAncients(source); }
bool OnCheck(Player* source, Unit* /*target*/) { Battleground* bg = source->GetBattleground(); return bg && bg->GetBgTypeID() == BATTLEGROUND_AV && bg->ToBattlegroundAV()->IsAllTowersControlledAndCaptainAlive(source->GetTeamId()); }
bool OnCheck(Player* source, Unit* /*target*/) { Battleground* bg = source->GetBattleground(); return bg && bg->GetBgTypeID() == BATTLEGROUND_AV && bg->ToBattlegroundAV()->IsBothMinesControlledByTeam(source->GetTeamId()); }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recvData) { uint64 guid; uint32 bgTypeId_; uint32 instanceId; // sent to queue for particular bg from battlemaster's list, currently not used uint8 joinAsGroup; recvData >> guid; // battlemaster guid recvData >> bgTypeId_; // battleground type id (DBC id) recvData >> instanceId; // instance id, 0 if First Available selected recvData >> joinAsGroup; // join as group // entry not found if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) return; // chosen battleground type is disabled if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } // get queue typeid and random typeid to check if already queued for them BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0); BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); // safety check - bgQueueTypeId == BATTLEGROUND_QUEUE_NONE if tried to queue for arena using this function if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE) return; // get bg template Battleground* bgt = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bgt) return; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgt->GetMapId(), _player->getLevel()); if (!bracketEntry) return; // pussywizard: if trying to queue for already queued // just remove from queue and it will requeue! uint32 qSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId); if (qSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); if (bgQueue.IsPlayerInvitedToRatedArena(_player->GetGUID())) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED); SendPacket(&data); return; } bgQueue.RemovePlayer(_player->GetGUID(), false, qSlot); _player->RemoveBattlegroundQueueId(bgQueueTypeId); } // must have free queue slot if (!_player->HasFreeBattlegroundQueueId()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); SendPacket(&data); return; } // queue result (default ok) GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bgt->GetBgTypeID()); // check if player can queue: if (!joinAsGroup) { if (GetPlayer()->InBattleground()) // currently in battleground err = ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND; else if (GetPlayer()->isUsingLfg()) // using lfg system err = ERR_LFG_CANT_USE_BATTLEGROUND; else if (!_player->CanJoinToBattleground()) // has deserter debuff err = ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS; else if (_player->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeIdRandom)) // queued for random bg, so can't queue for anything else err = ERR_IN_RANDOM_BG; else if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) // already in queue, so can't queue for random err = ERR_IN_NON_RANDOM_BG; else if (_player->InBattlegroundQueueForBattlegroundQueueType(BATTLEGROUND_QUEUE_2v2) || _player->InBattlegroundQueueForBattlegroundQueueType(BATTLEGROUND_QUEUE_3v3) || _player->InBattlegroundQueueForBattlegroundQueueType(BATTLEGROUND_QUEUE_5v5)) // can't be already queued for arenas err = ERR_BATTLEGROUND_QUEUED_FOR_RATED; if (err <= 0) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); SendPacket(&data); return; } BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bracketEntry, false, false, 0, 0, 0); uint32 avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); // send status packet WorldPacket data; sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, 0, TEAM_NEUTRAL); SendPacket(&data); } // check if group can queue: else { Group* grp = _player->GetGroup(); // no group or not a leader if (!grp || grp->GetLeaderGUID() != _player->GetGUID()) return; // pussywizard: for party members - remove queues for which leader is not queued to! std::set<uint32> leaderQueueTypeIds; for (uint32 i=0; i<PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) leaderQueueTypeIds.insert((uint32)_player->GetBattlegroundQueueTypeId(i)); for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) if (Player* member = itr->GetSource()) for (uint32 i=0; i<PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) if (BattlegroundQueueTypeId mqtid = member->GetBattlegroundQueueTypeId(i)) if (leaderQueueTypeIds.count((uint32)mqtid) == 0) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(mqtid); if (bgQueue.IsPlayerInvitedToRatedArena(member->GetGUID())) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED); SendPacket(&data); return; } bgQueue.RemovePlayer(member->GetGUID(), false, i); member->RemoveBattlegroundQueueId(mqtid); } if (_player->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeIdRandom)) // queued for random bg, so can't queue for anything else err = ERR_IN_RANDOM_BG; else if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) // already in queue, so can't queue for random err = ERR_IN_NON_RANDOM_BG; else if (_player->InBattlegroundQueueForBattlegroundQueueType(BATTLEGROUND_QUEUE_2v2) || _player->InBattlegroundQueueForBattlegroundQueueType(BATTLEGROUND_QUEUE_3v3) || _player->InBattlegroundQueueForBattlegroundQueueType(BATTLEGROUND_QUEUE_5v5)) // can't be already queued for arenas err = ERR_BATTLEGROUND_QUEUED_FOR_RATED; if (err > 0) err = grp->CanJoinBattlegroundQueue(bgt, bgQueueTypeId, 0, bgt->GetMaxPlayersPerTeam(), false, 0); bool isPremade = (grp->GetMembersCount() >= bgt->GetMinPlayersPerTeam() && bgTypeId != BATTLEGROUND_RB); uint32 avgWaitTime = 0; if (err > 0) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bracketEntry, false, isPremade, 0, 0, 0); avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); } WorldPacket data; for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (err <= 0) { sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // send status packet sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, 0, TEAM_NEUTRAL); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); } } }
void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recvData) { uint64 guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated recvData >> guid >> arenaslot >> asGroup >> isRated; // can't queue for rated without a group if (isRated && !asGroup) return; // find creature by guid Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit || !unit->IsBattleMaster()) return; // get arena type uint8 arenatype = 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: return; } // get template for all arenas Battleground* bgt = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); if (!bgt) return; // arenas disabled if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, NULL)) { ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED); return; } BattlegroundTypeId bgTypeId = bgt->GetBgTypeID(); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype); // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgt->GetMapId(), _player->getLevel()); if (!bracketEntry) return; // pussywizard: if trying to queue for already queued // just remove from queue and it will requeue! uint32 qSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId); if (qSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); if (bgQueue.IsPlayerInvitedToRatedArena(_player->GetGUID())) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED); SendPacket(&data); return; } bgQueue.RemovePlayer(_player->GetGUID(), false, qSlot); _player->RemoveBattlegroundQueueId(bgQueueTypeId); } // must have free queue slot // pussywizard: allow being queued only in one arena queue, and it even cannot be together with bg queues if (_player->InBattlegroundQueue()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_CANNOT_QUEUE_FOR_RATED); SendPacket(&data); return; } // queue result (default ok) GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bgt->GetBgTypeID()); // check if player can queue: if (!asGroup) { if (GetPlayer()->InBattleground()) // currently in battleground err = ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND; else if (GetPlayer()->isUsingLfg()) // using lfg system err = ERR_LFG_CANT_USE_BATTLEGROUND; if (err <= 0) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); SendPacket(&data); return; } BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bracketEntry, false, false, 0, 0, 0); uint32 avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPacket data; sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, arenatype, TEAM_NEUTRAL); SendPacket(&data); } // check if group can queue: else { Group* grp = _player->GetGroup(); // no group or not a leader if (!grp || grp->GetLeaderGUID() != _player->GetGUID()) return; // pussywizard: for party members - remove queues for which leader is not queued to! std::set<uint32> leaderQueueTypeIds; for (uint32 i=0; i<PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) leaderQueueTypeIds.insert((uint32)_player->GetBattlegroundQueueTypeId(i)); for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) if (Player* member = itr->GetSource()) for (uint32 i=0; i<PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) if (BattlegroundQueueTypeId mqtid = member->GetBattlegroundQueueTypeId(i)) if (leaderQueueTypeIds.count((uint32)mqtid) == 0) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(mqtid); if (bgQueue.IsPlayerInvitedToRatedArena(member->GetGUID())) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED); SendPacket(&data); return; } bgQueue.RemovePlayer(member->GetGUID(), false, i); member->RemoveBattlegroundQueueId(mqtid); } uint32 ateamId = 0; uint32 arenaRating = 0; uint32 matchmakerRating = 0; // additional checks for rated arenas if (isRated) { // pussywizard: for rated matches check if season is in progress! if (!sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)) return; ateamId = _player->GetArenaTeamId(arenaslot); // check team existence ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId); if (!at) { SendNotInArenaTeamPacket(arenatype); return; } // get team rating for queueing arenaRating = at->GetRating(); matchmakerRating = at->GetAverageMMR(grp); if (arenaRating <= 0) arenaRating = 1; } err = grp->CanJoinBattlegroundQueue(bgt, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); uint32 avgWaitTime = 0; if (err > 0) { BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bracketEntry, isRated, false, arenaRating, matchmakerRating, ateamId); avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); } WorldPacket data; for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (err <= 0) { sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // send status packet sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, arenatype, TEAM_NEUTRAL, isRated); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); } // pussywizard: schedule update for rated arena if (ateamId) sBattlegroundMgr->ScheduleArenaQueueUpdate(ateamId, bgQueueTypeId, bracketEntry->GetBracketId()); } }
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) { uint8 arenaType; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 uint32 bgTypeId_; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 recvData >> arenaType >> unk2 >> bgTypeId_ >> unk >> action; // bgTypeId not valid if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) return; // player not in any queue, so can't really answer if (!_player->InBattlegroundQueue()) return; // get BattlegroundQueue for received BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenaType); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); // get group info from queue GroupQueueInfo ginfo; if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) return; // to accept, player must be invited to particular battleground id if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) return; Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID); // use template if leaving queue (instance might not be created yet) if (!bg && action == 0) bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg) return; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; // safety checks if (action == 1 && ginfo.ArenaType == 0) { // can't join with deserter, check it here right before joining to be sure if (!_player->CanJoinToBattleground()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); SendPacket(&data); action = 0; } if (_player->getLevel() > bg->GetMaxLevel()) action = 0; } // get player queue slot index for this bg (can be in up to 2 queues at the same time) uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId); WorldPacket data; switch (action) { case 1: // accept { // set entry point if not in battleground if (!_player->InBattleground()) _player->SetEntryPoint(); // resurrect the player if (!_player->IsAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } // remove player from all bg queues for (uint32 qslot = 0; qslot < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qslot) if (BattlegroundQueueTypeId q = _player->GetBattlegroundQueueTypeId(qslot)) { BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(q); queue.RemovePlayer(_player->GetGUID(), (bgQueueTypeId == q), qslot); _player->RemoveBattlegroundQueueId(q); } // send status packet sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), ginfo.teamId); SendPacket(&data); _player->SetBattlegroundId(bg->GetInstanceID(), bg->GetBgTypeID(), queueSlot, true, bgTypeId == BATTLEGROUND_RB, ginfo.teamId); sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); } break; case 0: // leave queue { bgQueue.RemovePlayer(_player->GetGUID(), false, queueSlot); _player->RemoveBattlegroundQueueId(bgQueueTypeId); } break; default: break; } }