Ejemplo n.º 1
0
        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());
        }
Ejemplo n.º 2
0
        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;
                }
            }
        }
    }
}
Ejemplo n.º 4
0
 bool OnCheck(Player* source, Unit* /*target*/)
 {
     Battleground* bg = source->GetBattleground();
     return bg && bg->GetBgTypeID() == BATTLEGROUND_IC && bg->ToBattlegroundIC()->IsResourceGlutAllowed(source->GetTeamId());
 }
Ejemplo n.º 5
0
 bool OnCheck(Player* source, Unit* /*target*/)
 {
     Battleground* bg = source->GetBattleground();
     return bg && bg->GetBgTypeID() == BATTLEGROUND_AB && bg->ToBattlegroundAB()->IsTeamScores500Disadvantage(source->GetTeamId());
 }
Ejemplo n.º 6
0
 bool OnCheck(Player* source, Unit* /*target*/)
 {
     Battleground* bg = source->GetBattleground();
     return bg && bg->GetBgTypeID() == BATTLEGROUND_SA && bg->ToBattlegroundSA()->AllowDefenseOfTheAncients(source);
 }
Ejemplo n.º 7
0
 bool OnCheck(Player* source, Unit* /*target*/)
 {
     Battleground* bg = source->GetBattleground();
     return bg && bg->GetBgTypeID() == BATTLEGROUND_AV && bg->ToBattlegroundAV()->IsAllTowersControlledAndCaptainAlive(source->GetTeamId());
 }
Ejemplo n.º 8
0
 bool OnCheck(Player* source, Unit* /*target*/)
 {
     Battleground* bg = source->GetBattleground();
     return bg && bg->GetBgTypeID() == BATTLEGROUND_AV && bg->ToBattlegroundAV()->IsBothMinesControlledByTeam(source->GetTeamId());
 }
Ejemplo n.º 9
0
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);
        }
    }
}
Ejemplo n.º 10
0
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());
    }
}
Ejemplo n.º 11
0
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;
    }
}