Beispiel #1
0
        public ArenaTypes BGArenaType(BattlegroundQueueTypeId bgQueueTypeId)
        {
            switch (bgQueueTypeId)
            {
            case BattlegroundQueueTypeId.Arena2v2:
                return(ArenaTypes.Team2v2);

            case BattlegroundQueueTypeId.Arena3v3:
                return(ArenaTypes.Team3v3);

            case BattlegroundQueueTypeId.Arena5v5:
                return(ArenaTypes.Team5v5);

            default:
                return(0);
            }
        }
        public BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId)
        {
            switch (bgQueueTypeId)
            {
            case BattlegroundQueueTypeId.WS:
                return(BattlegroundTypeId.WS);

            case BattlegroundQueueTypeId.AB:
                return(BattlegroundTypeId.AB);

            case BattlegroundQueueTypeId.AV:
                return(BattlegroundTypeId.AV);

            case BattlegroundQueueTypeId.EY:
                return(BattlegroundTypeId.EY);

            case BattlegroundQueueTypeId.SA:
                return(BattlegroundTypeId.SA);

            case BattlegroundQueueTypeId.IC:
                return(BattlegroundTypeId.IC);

            case BattlegroundQueueTypeId.TP:
                return(BattlegroundTypeId.TP);

            case BattlegroundQueueTypeId.BFG:
                return(BattlegroundTypeId.BFG);

            case BattlegroundQueueTypeId.RB:
                return(BattlegroundTypeId.RB);

            case BattlegroundQueueTypeId.Arena2v2:
            case BattlegroundQueueTypeId.Arena3v3:
            case BattlegroundQueueTypeId.Arena5v5:
                return(BattlegroundTypeId.AA);

            default:
                return(0);                      // used for unknown template (it existed and do nothing)
            }
        }
        // create a new Battleground that will really be used to play
        public Battleground CreateNewBattleground(BattlegroundQueueTypeId queueId, PvpDifficultyRecord bracketEntry)
        {
            BattlegroundTypeId bgTypeId = GetRandomBG((BattlegroundTypeId)queueId.BattlemasterListId);

            // get the template BG
            Battleground bg_template = GetBattlegroundTemplate(bgTypeId);

            if (bg_template == null)
            {
                Log.outError(LogFilter.Battleground, "Battleground: CreateNewBattleground - bg template not found for {0}", bgTypeId);
                return(null);
            }

            if (bgTypeId == BattlegroundTypeId.RB || bgTypeId == BattlegroundTypeId.AA || bgTypeId == BattlegroundTypeId.RandomEpic)
            {
                return(null);
            }

            // create a copy of the BG template
            Battleground bg = bg_template.GetCopy();

            bool isRandom = bgTypeId != (BattlegroundTypeId)queueId.BattlemasterListId && !bg.IsArena();

            bg.SetQueueId(queueId);
            bg.SetBracket(bracketEntry);
            bg.SetInstanceID(Global.MapMgr.GenerateInstanceId());
            bg.SetClientInstanceID(CreateClientVisibleInstanceId((BattlegroundTypeId)queueId.BattlemasterListId, bracketEntry.GetBracketId()));
            bg.Reset();                                // reset the new bg (set status to status_wait_queue from status_none)
            bg.SetStatus(BattlegroundStatus.WaitJoin); // start the joining of the bg
            bg.SetArenaType((ArenaTypes)queueId.TeamSize);
            bg.SetRandomTypeID(bgTypeId);
            bg.SetRated(queueId.Rated);
            bg.SetRandom(isRandom);

            return(bg);
        }
Beispiel #4
0
        public void LogoutPlayer(bool save)
        {
            // finish pending transfers before starting the logout
            while (_player && _player.IsBeingTeleportedFar())
            {
                HandleMoveWorldportAck();
            }

            m_playerLogout = true;
            m_playerSave   = save;

            if (_player)
            {
                if (!_player.GetLootGUID().IsEmpty())
                {
                    DoLootReleaseAll();
                }

                // If the player just died before logging out, make him appear as a ghost
                //FIXME: logout must be delayed in case lost connection with client in time of combat
                if (GetPlayer().GetDeathTimer() != 0)
                {
                    _player.getHostileRefManager().deleteReferences();
                    _player.BuildPlayerRepop();
                    _player.RepopAtGraveyard();
                }
                else if (GetPlayer().HasAuraType(AuraType.SpiritOfRedemption))
                {
                    // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION
                    _player.RemoveAurasByType(AuraType.ModShapeshift);
                    _player.KillPlayer();
                    _player.BuildPlayerRepop();
                    _player.RepopAtGraveyard();
                }
                else if (GetPlayer().HasPendingBind())
                {
                    _player.RepopAtGraveyard();
                    _player.SetPendingBind(0, 0);
                }

                //drop a flag if player is carrying it
                Battleground bg = GetPlayer().GetBattleground();
                if (bg)
                {
                    bg.EventPlayerLoggedOut(GetPlayer());
                }

                // Teleport to home if the player is in an invalid instance
                if (!_player.m_InstanceValid && !_player.IsGameMaster())
                {
                    _player.TeleportTo(_player.GetHomebind());
                }

                Global.OutdoorPvPMgr.HandlePlayerLeaveZone(_player, _player.GetZoneId());

                for (uint i = 0; i < SharedConst.MaxPlayerBGQueues; ++i)
                {
                    BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(i);
                    if (bgQueueTypeId != 0)
                    {
                        _player.RemoveBattlegroundQueueId(bgQueueTypeId);
                        BattlegroundQueue queue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
                        queue.RemovePlayer(_player.GetGUID(), true);
                    }
                }

                // Repop at GraveYard or other player far teleport will prevent saving player because of not present map
                // Teleport player immediately for correct player save
                while (_player.IsBeingTeleportedFar())
                {
                    HandleMoveWorldportAck();
                }

                // If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
                Guild guild = Global.GuildMgr.GetGuildById(_player.GetGuildId());
                if (guild)
                {
                    guild.HandleMemberLogout(this);
                }

                // Remove pet
                _player.RemovePet(null, PetSaveMode.AsCurrent, true);

                // Clear whisper whitelist
                _player.ClearWhisperWhiteList();

                // empty buyback items and save the player in the database
                // some save parts only correctly work in case player present in map/player_lists (pets, etc)
                if (save)
                {
                    for (int j = InventorySlots.BuyBackStart; j < InventorySlots.BuyBackEnd; ++j)
                    {
                        int eslot = j - InventorySlots.BuyBackStart;
                        _player.SetGuidValue(PlayerFields.InvSlotHead + (j * 4), ObjectGuid.Empty);
                        _player.SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, 0);
                        _player.SetUInt32Value(PlayerFields.BuyBackTimestamp1 + eslot, 0);
                    }
                    _player.SaveToDB();
                }

                // Leave all channels before player delete...
                _player.CleanupChannels();

                // If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
                _player.UninviteFromGroup();

                // remove player from the group if he is:
                // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
                if (_player.GetGroup() && !_player.GetGroup().isRaidGroup() && m_Socket[(int)ConnectionType.Realm] != null)
                {
                    _player.RemoveFromGroup();
                }

                //! Send update to group and reset stored max enchanting level
                if (_player.GetGroup())
                {
                    _player.GetGroup().SendUpdate();
                    _player.GetGroup().ResetMaxEnchantingLevel();
                }

                //! Broadcast a logout message to the player's friends
                Global.SocialMgr.SendFriendStatus(_player, FriendsResult.Offline, _player.GetGUID(), true);
                _player.RemoveSocial();

                //! Call script hook before deletion
                Global.ScriptMgr.OnPlayerLogout(GetPlayer());

                //! Remove the player from the world
                // the player may not be in the world when logging out
                // e.g if he got disconnected during a transfer to another map
                // calls to GetMap in this case may cause crashes
                GetPlayer().CleanupsBeforeDelete();
                Log.outInfo(LogFilter.Player, "Account: {0} (IP: {1}) Logout Character:[{2}] (GUID: {3}) Level: {4}",
                            GetAccountId(), GetRemoteAddress(), _player.GetName(), _player.GetGUID().ToString(), _player.getLevel());

                Map map = GetPlayer().GetMap();
                if (map != null)
                {
                    map.RemovePlayerFromMap(GetPlayer(), true);
                }

                SetPlayer(null);

                //! Send the 'logout complete' packet to the client
                //! Client will respond by sending 3x CMSG_CANCEL_TRADE, which we currently dont handle
                LogoutComplete logoutComplete = new LogoutComplete();
                SendPacket(logoutComplete);

                //! Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline
                PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ACCOUNT_ONLINE);
                stmt.AddValue(0, GetAccountId());
                DB.Characters.Execute(stmt);
            }

            if (m_Socket[(int)ConnectionType.Instance] != null)
            {
                m_Socket[(int)ConnectionType.Instance].CloseSocket();
                m_Socket[(int)ConnectionType.Instance] = null;
            }

            m_playerLogout         = false;
            m_playerSave           = false;
            m_playerRecentlyLogout = true;
            SetLogoutStartTime(0);
        }
        void HandleBattlemasterJoin(BattlemasterJoin battlemasterJoin)
        {
            bool  isPremade = false;
            Group grp       = null;

            BattlefieldStatusFailed battlefieldStatusFailed;

            uint bgTypeId_ = (uint)(battlemasterJoin.QueueID & 0xFFFF);

            if (!CliDB.BattlemasterListStorage.ContainsKey(bgTypeId_))
            {
                Log.outError(LogFilter.Network, "Battleground: invalid bgtype ({0}) received. possible cheater? player guid {1}", bgTypeId_, GetPlayer().GetGUID().ToString());
                return;
            }

            if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, bgTypeId_, null))
            {
                GetPlayer().SendSysMessage(CypherStrings.BgDisabled);
                return;
            }
            BattlegroundTypeId bgTypeId = (BattlegroundTypeId)bgTypeId_;

            // can do this, since it's Battleground, not arena
            BattlegroundQueueTypeId bgQueueTypeId       = Global.BattlegroundMgr.BGQueueTypeId(bgTypeId, 0);
            BattlegroundQueueTypeId bgQueueTypeIdRandom = Global.BattlegroundMgr.BGQueueTypeId(BattlegroundTypeId.RB, 0);

            // ignore if player is already in BG
            if (GetPlayer().InBattleground())
            {
                return;
            }

            // get bg instance or bg template if instance not found
            Battleground bg = Global.BattlegroundMgr.GetBattlegroundTemplate(bgTypeId);

            if (!bg)
            {
                return;
            }

            // expected bracket entry
            PVPDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel(bg.GetMapId(), GetPlayer().getLevel());

            if (bracketEntry == null)
            {
                return;
            }

            GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult.None;

            // check queue conditions
            if (!battlemasterJoin.JoinAsGroup)
            {
                if (GetPlayer().isUsingLfg())
                {
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.LfgCantUseBattleground);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                // check Deserter debuff
                if (!GetPlayer().CanJoinToBattleground(bg))
                {
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.Deserters);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                if (GetPlayer().GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < SharedConst.MaxPlayerBGQueues)
                {
                    // player is already in random queue
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.InRandomBg);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                if (GetPlayer().InBattlegroundQueue() && bgTypeId == BattlegroundTypeId.RB)
                {
                    // player is already in queue, can't start random queue
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.InNonRandomBg);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                // check if already in queue
                if (GetPlayer().GetBattlegroundQueueIndex(bgQueueTypeId) < SharedConst.MaxPlayerBGQueues)
                {
                    return;  // player is already in this queue
                }
                // check if has free queue slots
                if (!GetPlayer().HasFreeBattlegroundQueueId())
                {
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.TooManyQueues);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                // check Freeze debuff
                if (_player.HasAura(9454))
                {
                    return;
                }

                BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
                GroupQueueInfo    ginfo   = bgQueue.AddGroup(GetPlayer(), null, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);

                uint avgTime   = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
                uint queueSlot = GetPlayer().AddBattlegroundQueueId(bgQueueTypeId);

                BattlefieldStatusQueued battlefieldStatusQueued;
                Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatusQueued, bg, GetPlayer(), queueSlot, ginfo.JoinTime, avgTime, ginfo.ArenaType, false);
                SendPacket(battlefieldStatusQueued);


                Log.outDebug(LogFilter.Battleground, "Battleground: player joined queue for bg queue type {0} bg type {1}: GUID {2}, NAME {3}",
                             bgQueueTypeId, bgTypeId, GetPlayer().GetGUID().ToString(), GetPlayer().GetName());
            }
            else
            {
                grp = GetPlayer().GetGroup();

                if (!grp)
                {
                    return;
                }

                if (grp.GetLeaderGUID() != GetPlayer().GetGUID())
                {
                    return;
                }

                ObjectGuid errorGuid;
                err       = grp.CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg.GetMaxPlayersPerTeam(), false, 0, out errorGuid);
                isPremade = (grp.GetMembersCount() >= bg.GetMinPlayersPerTeam());

                BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
                GroupQueueInfo    ginfo   = null;
                uint avgTime = 0;

                if (err == 0)
                {
                    Log.outDebug(LogFilter.Battleground, "Battleground: the following players are joining as group:");
                    ginfo   = bgQueue.AddGroup(GetPlayer(), grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
                    avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
                }

                for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.next())
                {
                    Player member = refe.GetSource();
                    if (!member)
                    {
                        continue;   // this should never happen
                    }
                    if (err != 0)
                    {
                        BattlefieldStatusFailed battlefieldStatus;
                        Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, 0, err, errorGuid);
                        member.SendPacket(battlefieldStatus);
                        continue;
                    }

                    // add to queue
                    uint queueSlot = member.AddBattlegroundQueueId(bgQueueTypeId);

                    BattlefieldStatusQueued battlefieldStatusQueued;
                    Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, avgTime, ginfo.ArenaType, true);
                    member.SendPacket(battlefieldStatusQueued);
                    Log.outDebug(LogFilter.Battleground, "Battleground: player joined queue for bg queue type {0} bg type {1}: GUID {2}, NAME {3}",
                                 bgQueueTypeId, bgTypeId, member.GetGUID().ToString(), member.GetName());
                }
                Log.outDebug(LogFilter.Battleground, "Battleground: group end");
            }

            Global.BattlegroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry.GetBracketId());
        }
        void HandleBattlemasterJoinArena(BattlemasterJoinArena packet)
        {
            // ignore if we already in BG or BG queue
            if (GetPlayer().InBattleground())
            {
                return;
            }

            ArenaTypes arenatype = (ArenaTypes)ArenaTeam.GetTypeBySlot(packet.TeamSizeIndex);

            //check existence
            Battleground bg = Global.BattlegroundMgr.GetBattlegroundTemplate(BattlegroundTypeId.AA);

            if (!bg)
            {
                Log.outError(LogFilter.Network, "Battleground: template bg (all arenas) not found");
                return;
            }

            if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, (uint)BattlegroundTypeId.AA, null))
            {
                GetPlayer().SendSysMessage(CypherStrings.ArenaDisabled);
                return;
            }

            BattlegroundTypeId      bgTypeId      = bg.GetTypeID();
            BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(bgTypeId, arenatype);
            PVPDifficultyRecord     bracketEntry  = Global.DB2Mgr.GetBattlegroundBracketByLevel(bg.GetMapId(), GetPlayer().getLevel());

            if (bracketEntry == null)
            {
                return;
            }

            Group grp = GetPlayer().GetGroup();

            // no group found, error
            if (!grp)
            {
                return;
            }
            if (grp.GetLeaderGUID() != GetPlayer().GetGUID())
            {
                return;
            }

            uint ateamId = GetPlayer().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 = Global.ArenaTeamMgr.GetArenaTeamById(ateamId);

            if (at == null)
            {
                GetPlayer().GetSession().SendNotInArenaTeamPacket(arenatype);
                return;
            }

            // get the team rating for queuing
            uint arenaRating      = at.GetRating();
            uint matchmakerRating = at.GetAverageMMR(grp);

            // the arenateam id must match for everyone in the group

            if (arenaRating <= 0)
            {
                arenaRating = 1;
            }

            BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);

            uint           avgTime = 0;
            GroupQueueInfo ginfo   = null;

            ObjectGuid errorGuid;
            var        err = grp.CanJoinBattlegroundQueue(bg, bgQueueTypeId, (uint)arenatype, (uint)arenatype, true, packet.TeamSizeIndex, out errorGuid);

            if (err == 0)
            {
                Log.outDebug(LogFilter.Battleground, "Battleground: arena team id {0}, leader {1} queued with matchmaker rating {2} for type {3}", GetPlayer().GetArenaTeamId(packet.TeamSizeIndex), GetPlayer().GetName(), matchmakerRating, arenatype);

                ginfo   = bgQueue.AddGroup(GetPlayer(), grp, bgTypeId, bracketEntry, arenatype, true, false, arenaRating, matchmakerRating, ateamId);
                avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
            }

            for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.next())
            {
                Player member = refe.GetSource();
                if (!member)
                {
                    continue;
                }

                if (err != 0)
                {
                    BattlefieldStatusFailed battlefieldStatus;
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, arenatype, err, errorGuid);
                    member.SendPacket(battlefieldStatus);
                    continue;
                }

                // add to queue
                uint queueSlot = member.AddBattlegroundQueueId(bgQueueTypeId);

                BattlefieldStatusQueued battlefieldStatusQueued;
                Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, avgTime, arenatype, true);
                member.SendPacket(battlefieldStatusQueued);

                Log.outDebug(LogFilter.Battleground, "Battleground: player joined queue for arena as group bg queue type {0} bg type {1}: GUID {2}, NAME {3}", bgQueueTypeId, bgTypeId, member.GetGUID().ToString(), member.GetName());
            }

            Global.BattlegroundMgr.ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry.GetBracketId());
        }
        void HandleRequestBattlefieldStatus(RequestBattlefieldStatus packet)
        {
            // we must update all queues here
            Battleground bg = null;

            for (byte i = 0; i < SharedConst.MaxPlayerBGQueues; ++i)
            {
                BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(i);
                if (bgQueueTypeId == 0)
                {
                    continue;
                }

                BattlegroundTypeId bgTypeId  = Global.BattlegroundMgr.BGTemplateId(bgQueueTypeId);
                ArenaTypes         arenaType = Global.BattlegroundMgr.BGArenaType(bgQueueTypeId);
                if (bgTypeId == GetPlayer().GetBattlegroundTypeId())
                {
                    bg = GetPlayer().GetBattleground();
                    //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
                    //so i must use bg pointer to get that information
                    if (bg && bg.GetArenaType() == arenaType)
                    {
                        BattlefieldStatusActive battlefieldStatus;
                        Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, bg, GetPlayer(), i, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), arenaType);
                        SendPacket(battlefieldStatus);
                        continue;
                    }
                }

                //we are sending update to player about queue - he can be invited there!
                //get GroupQueueInfo for queue status
                BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
                GroupQueueInfo    ginfo;
                if (!bgQueue.GetPlayerGroupInfoData(GetPlayer().GetGUID(), out ginfo))
                {
                    continue;
                }

                if (ginfo.IsInvitedToBGInstanceGUID != 0)
                {
                    bg = Global.BattlegroundMgr.GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
                    if (!bg)
                    {
                        continue;
                    }

                    BattlefieldStatusNeedConfirmation battlefieldStatus;
                    Global.BattlegroundMgr.BuildBattlegroundStatusNeedConfirmation(out battlefieldStatus, bg, GetPlayer(), i, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), Time.GetMSTimeDiff(Time.GetMSTime(), ginfo.RemoveInviteTime), arenaType);
                    SendPacket(battlefieldStatus);
                }
                else
                {
                    bg = Global.BattlegroundMgr.GetBattlegroundTemplate(bgTypeId);
                    if (!bg)
                    {
                        continue;
                    }

                    // expected bracket entry
                    PVPDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel(bg.GetMapId(), GetPlayer().getLevel());
                    if (bracketEntry == null)
                    {
                        continue;
                    }

                    uint avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
                    BattlefieldStatusQueued battlefieldStatus;
                    Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatus, bg, GetPlayer(), i, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), avgTime, arenaType, ginfo.Players.Count > 1);
                    SendPacket(battlefieldStatus);
                }
            }
        }
        void HandleBattleFieldPort(BattlefieldPort battlefieldPort)
        {
            if (!GetPlayer().InBattlegroundQueue())
            {
                Log.outDebug(LogFilter.Battleground, "CMSG_BATTLEFIELD_PORT {0} Slot: {1}, Unk: {2}, Time: {3}, AcceptedInvite: {4}. Player not in queue!",
                             GetPlayerInfo(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, battlefieldPort.AcceptedInvite);
                return;
            }

            BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(battlefieldPort.Ticket.Id);

            if (bgQueueTypeId == BattlegroundQueueTypeId.None)
            {
                Log.outDebug(LogFilter.Battleground, "CMSG_BATTLEFIELD_PORT {0} Slot: {1}, Unk: {2}, Time: {3}, AcceptedInvite: {4}. Invalid queueSlot!",
                             GetPlayerInfo(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, battlefieldPort.AcceptedInvite);
                return;
            }

            BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);

            //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue.RemovePlayer() function
            GroupQueueInfo ginfo;

            if (!bgQueue.GetPlayerGroupInfoData(GetPlayer().GetGUID(), out ginfo))
            {
                Log.outDebug(LogFilter.Battleground, "CMSG_BATTLEFIELD_PORT {0} Slot: {1}, Unk: {2}, Time: {3}, AcceptedInvite: {4}. Player not in queue (No player Group Info)!",
                             GetPlayerInfo(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, battlefieldPort.AcceptedInvite);
                return;
            }
            // if action == 1, then instanceId is required
            if (ginfo.IsInvitedToBGInstanceGUID == 0 && battlefieldPort.AcceptedInvite)
            {
                Log.outDebug(LogFilter.Battleground, "CMSG_BATTLEFIELD_PORT {0} Slot: {1}, Unk: {2}, Time: {3}, AcceptedInvite: {4}. Player is not invited to any bg!",
                             GetPlayerInfo(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, battlefieldPort.AcceptedInvite);
                return;
            }

            BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.BGTemplateId(bgQueueTypeId);
            // BGTemplateId returns Battleground_AA when it is arena queue.
            // Do instance id search as there is no AA bg instances.
            Battleground bg = Global.BattlegroundMgr.GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BattlegroundTypeId.AA ? BattlegroundTypeId.None : bgTypeId);

            if (!bg)
            {
                if (battlefieldPort.AcceptedInvite)
                {
                    Log.outDebug(LogFilter.Battleground, "CMSG_BATTLEFIELD_PORT {0} Slot: {1}, Unk: {2}, Time: {3}, AcceptedInvite: {4}. Cant find BG with id {5}!",
                                 GetPlayerInfo(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, battlefieldPort.AcceptedInvite, ginfo.IsInvitedToBGInstanceGUID);
                    return;
                }

                bg = Global.BattlegroundMgr.GetBattlegroundTemplate(bgTypeId);
                if (!bg)
                {
                    Log.outError(LogFilter.Network, "BattlegroundHandler: bg_template not found for type id {0}.", bgTypeId);
                    return;
                }
            }

            // get real bg type
            bgTypeId = bg.GetTypeID();

            // expected bracket entry
            PVPDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel(bg.GetMapId(), GetPlayer().getLevel());

            if (bracketEntry == null)
            {
                return;
            }

            //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
            if (battlefieldPort.AcceptedInvite && ginfo.ArenaType == 0)
            {
                //if player is trying to enter Battleground(not arena!) and he has deserter debuff, we must just remove him from queue
                if (!GetPlayer().CanJoinToBattleground(bg))
                {
                    // send bg command result to show nice message
                    BattlefieldStatusFailed battlefieldStatus;
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), battlefieldPort.Ticket.Id, 0, GroupJoinBattlegroundResult.Deserters);
                    SendPacket(battlefieldStatus);
                    battlefieldPort.AcceptedInvite = false;
                    Log.outDebug(LogFilter.Battleground, "Player {0} ({1}) has a deserter debuff, do not port him to Battleground!", GetPlayer().GetName(), GetPlayer().GetGUID().ToString());
                }
                //if player don't match Battlegroundmax level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
                if (GetPlayer().getLevel() > bg.GetMaxLevel())
                {
                    Log.outDebug(LogFilter.Network, "Player {0} ({1}) has level ({2}) higher than maxlevel ({3}) of Battleground({4})! Do not port him to Battleground!",
                                 GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), GetPlayer().getLevel(), bg.GetMaxLevel(), bg.GetTypeID());
                    battlefieldPort.AcceptedInvite = false;
                }
            }

            if (battlefieldPort.AcceptedInvite)
            {
                // check Freeze debuff
                if (GetPlayer().HasAura(9454))
                {
                    return;
                }

                if (!GetPlayer().IsInvitedForBattlegroundQueueType(bgQueueTypeId))
                {
                    return;                                 // cheating?
                }
                if (!GetPlayer().InBattleground())
                {
                    GetPlayer().SetBattlegroundEntryPoint();
                }

                // resurrect the player
                if (!GetPlayer().IsAlive())
                {
                    GetPlayer().ResurrectPlayer(1.0f);
                    GetPlayer().SpawnCorpseBones();
                }
                // stop taxi flight at port
                if (GetPlayer().IsInFlight())
                {
                    GetPlayer().GetMotionMaster().MovementExpired();
                    GetPlayer().CleanupAfterTaxiFlight();
                }

                BattlefieldStatusActive battlefieldStatus;
                Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, bg, GetPlayer(), battlefieldPort.Ticket.Id, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), bg.GetArenaType());
                SendPacket(battlefieldStatus);

                // remove BattlegroundQueue status from BGmgr
                bgQueue.RemovePlayer(GetPlayer().GetGUID(), false);
                // this is still needed here if Battleground"jumping" shouldn't add deserter debuff
                // also this is required to prevent stuck at old Battlegroundafter SetBattlegroundId set to new
                Battleground currentBg = GetPlayer().GetBattleground();
                if (currentBg)
                {
                    currentBg.RemovePlayerAtLeave(GetPlayer().GetGUID(), false, true);
                }

                // set the destination instance id
                GetPlayer().SetBattlegroundId(bg.GetInstanceID(), bgTypeId);
                // set the destination team
                GetPlayer().SetBGTeam(ginfo.Team);

                Global.BattlegroundMgr.SendToBattleground(GetPlayer(), ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
                Log.outDebug(LogFilter.Battleground, "Battleground: player {0} ({1}) joined battle for bg {2}, bgtype {3}, queue type {4}.", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), bg.GetInstanceID(), bg.GetTypeID(), bgQueueTypeId);
            }
            else // leave queue
            {
                // if player leaves rated arena match before match start, it is counted as he played but he lost
                if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID != 0)
                {
                    ArenaTeam at = Global.ArenaTeamMgr.GetArenaTeamById((uint)ginfo.Team);
                    if (at != null)
                    {
                        Log.outDebug(LogFilter.Battleground, "UPDATING memberLost's personal arena rating for {0} by opponents rating: {1}, because he has left queue!", GetPlayer().GetGUID().ToString(), ginfo.OpponentsTeamRating);
                        at.MemberLost(GetPlayer(), ginfo.OpponentsMatchmakerRating);
                        at.SaveToDB();
                    }
                }
                BattlefieldStatusNone battlefieldStatus = new BattlefieldStatusNone();
                battlefieldStatus.Ticket = battlefieldPort.Ticket;
                SendPacket(battlefieldStatus);

                GetPlayer().RemoveBattlegroundQueueId(bgQueueTypeId);  // must be called this way, because if you move this call to queue.removeplayer, it causes bugs
                bgQueue.RemovePlayer(GetPlayer().GetGUID(), true);
                // player left queue, we should update it - do not update Arena Queue
                if (ginfo.ArenaType == 0)
                {
                    Global.BattlegroundMgr.ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry.GetBracketId());
                }

                Log.outDebug(LogFilter.Battleground, "Battleground: player {0} ({1}) left queue for bgtype {2}, queue type {3}.", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), bg.GetTypeID(), bgQueueTypeId);
            }
        }
Beispiel #9
0
 public bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId)
 {
     return(GetBattlegroundQueueIndex(bgQueueTypeId) < SharedConst.MaxPlayerBGQueues);
 }
 public void BuildBattlegroundStatusFailed(out BattlefieldStatusFailed battlefieldStatus, BattlegroundQueueTypeId queueId, Player pPlayer, uint ticketId, GroupJoinBattlegroundResult result, ObjectGuid errorGuid = default)
 {
     battlefieldStatus = new BattlefieldStatusFailed();
     battlefieldStatus.Ticket.RequesterGuid = pPlayer.GetGUID();
     battlefieldStatus.Ticket.Id            = ticketId;
     battlefieldStatus.Ticket.Type          = RideType.Battlegrounds;
     battlefieldStatus.Ticket.Time          = (int)pPlayer.GetBattlegroundQueueJoinTime(queueId);
     battlefieldStatus.QueueID = queueId.GetPacked();
     battlefieldStatus.Reason  = (int)result;
     if (!errorGuid.IsEmpty() && (result == GroupJoinBattlegroundResult.NotInBattleground || result == GroupJoinBattlegroundResult.JoinTimedOut))
     {
         battlefieldStatus.ClientID = errorGuid;
     }
 }
        public void ScheduleQueueUpdate(uint arenaMatchmakerRating, ArenaTypes arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
        {
            //we will use only 1 number created of bgTypeId and bracket_id
            ulong scheduleId = ((ulong)arenaMatchmakerRating << 32) | ((uint)arenaType << 24) | ((uint)bgQueueTypeId << 16) | ((uint)bgTypeId << 8) | (uint)bracket_id;

            if (!m_QueueUpdateScheduler.Contains(scheduleId))
            {
                m_QueueUpdateScheduler.Add(scheduleId);
            }
        }
 public void AddToBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, Battleground bg)
 {
     m_BGFreeSlotQueue.Add(bgTypeId, bg);
 }
 public List <Battleground> GetBGFreeSlotQueueStore(BattlegroundQueueTypeId bgTypeId)
 {
     return(m_BGFreeSlotQueue[bgTypeId]);
 }
        public bool IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId)
        {
            BattlemasterListRecord battlemasterList = CliDB.BattlemasterListStorage.LookupByKey(bgQueueTypeId.BattlemasterListId);

            if (battlemasterList == null)
            {
                return(false);
            }

            switch ((BattlegroundQueueIdType)bgQueueTypeId.BgType)
            {
            case BattlegroundQueueIdType.Battleground:
                if (battlemasterList.InstanceType != (int)MapTypes.Battleground)
                {
                    return(false);
                }
                if (bgQueueTypeId.TeamSize != 0)
                {
                    return(false);
                }
                break;

            case BattlegroundQueueIdType.Arena:
                if (battlemasterList.InstanceType != (int)MapTypes.Arena)
                {
                    return(false);
                }
                if (!bgQueueTypeId.Rated)
                {
                    return(false);
                }
                if (bgQueueTypeId.TeamSize == 0)
                {
                    return(false);
                }
                break;

            case BattlegroundQueueIdType.Wargame:
                if (bgQueueTypeId.Rated)
                {
                    return(false);
                }
                break;

            case BattlegroundQueueIdType.ArenaSkirmish:
                if (battlemasterList.InstanceType != (int)MapTypes.Arena)
                {
                    return(false);
                }
                if (bgQueueTypeId.Rated)
                {
                    return(false);
                }
                if (bgQueueTypeId.TeamSize != 0)
                {
                    return(false);
                }
                break;

            default:
                return(false);
            }

            return(true);
        }
        public void Update(uint diff)
        {
            m_UpdateTimer += diff;
            if (m_UpdateTimer > 1000)
            {
                foreach (var data in bgDataStore.Values)
                {
                    var bgs = data.m_Battlegrounds;

                    // first one is template and should not be deleted
                    foreach (var pair in bgs.ToList())
                    {
                        Battleground bg = pair.Value;
                        bg.Update(m_UpdateTimer);

                        if (bg.ToBeDeleted())
                        {
                            bgs.Remove(pair.Key);
                            var clients = data.m_ClientBattlegroundIds[(int)bg.GetBracketId()];
                            if (!clients.Empty())
                            {
                                clients.Remove(bg.GetClientInstanceID());
                            }

                            bg.Dispose();
                        }
                    }
                }

                m_UpdateTimer = 0;
            }
            // update events timer
            foreach (var pair in m_BattlegroundQueues)
            {
                pair.Value.UpdateEvents(diff);
            }

            // update scheduled queues
            if (!m_QueueUpdateScheduler.Empty())
            {
                List <ScheduledQueueUpdate> scheduled = new();
                Extensions.Swap(ref scheduled, ref m_QueueUpdateScheduler);

                for (byte i = 0; i < scheduled.Count; i++)
                {
                    uint arenaMMRating = scheduled[i].ArenaMatchmakerRating;
                    BattlegroundQueueTypeId bgQueueTypeId = scheduled[i].QueueId;
                    BattlegroundBracketId   bracket_id    = scheduled[i].BracketId;
                    GetBattlegroundQueue(bgQueueTypeId).BattlegroundQueueUpdate(diff, bracket_id, arenaMMRating);
                }
            }

            // if rating difference counts, maybe force-update queues
            if (WorldConfig.GetIntValue(WorldCfg.ArenaMaxRatingDifference) != 0 && WorldConfig.GetIntValue(WorldCfg.ArenaRatedUpdateTimer) != 0)
            {
                // it's time to force update
                if (m_NextRatedArenaUpdate < diff)
                {
                    // forced update for rated arenas (scan all, but skipped non rated)
                    Log.outDebug(LogFilter.Arena, "BattlegroundMgr: UPDATING ARENA QUEUES");
                    foreach (ArenaTypes teamSize in new[] { ArenaTypes.Team2v2, ArenaTypes.Team3v3, ArenaTypes.Team5v5 })
                    {
                        BattlegroundQueueTypeId ratedArenaQueueId = BGQueueTypeId((ushort)BattlegroundTypeId.AA, BattlegroundQueueIdType.Arena, true, teamSize);
                        for (var bracket = BattlegroundBracketId.First; bracket < BattlegroundBracketId.Max; ++bracket)
                        {
                            GetBattlegroundQueue(ratedArenaQueueId).BattlegroundQueueUpdate(diff, bracket, 0);
                        }
                    }

                    m_NextRatedArenaUpdate = WorldConfig.GetUIntValue(WorldCfg.ArenaRatedUpdateTimer);
                }
                else
                {
                    m_NextRatedArenaUpdate -= diff;
                }
            }
        }
        public void Update(uint diff)
        {
            m_UpdateTimer += diff;
            if (m_UpdateTimer > 1000)
            {
                foreach (var data in bgDataStore.Values)
                {
                    var bgs = data.m_Battlegrounds;

                    // first one is template and should not be deleted
                    foreach (var pair in bgs.ToList())
                    {
                        Battleground bg = pair.Value;
                        bg.Update(m_UpdateTimer);

                        if (bg.ToBeDeleted())
                        {
                            bgs.Remove(pair.Key);
                            var clients = data.m_ClientBattlegroundIds[(int)bg.GetBracketId()];
                            if (!clients.Empty())
                            {
                                clients.Remove(bg.GetClientInstanceID());
                            }

                            bg.Dispose();
                        }
                    }
                }

                m_UpdateTimer = 0;
            }
            // update events timer
            for (var qtype = BattlegroundQueueTypeId.None; qtype < BattlegroundQueueTypeId.Max; ++qtype)
            {
                m_BattlegroundQueues[(int)qtype].UpdateEvents(diff);
            }

            // update scheduled queues
            if (!m_QueueUpdateScheduler.Empty())
            {
                List <ulong> scheduled = new List <ulong>();
                Extensions.Swap(ref scheduled, ref m_QueueUpdateScheduler);

                for (byte i = 0; i < scheduled.Count; i++)
                {
                    uint arenaMMRating = (uint)(scheduled[i] >> 32);
                    byte arenaType     = (byte)(scheduled[i] >> 24 & 255);
                    BattlegroundQueueTypeId bgQueueTypeId = (BattlegroundQueueTypeId)(scheduled[i] >> 16 & 255);
                    BattlegroundTypeId      bgTypeId      = (BattlegroundTypeId)((scheduled[i] >> 8) & 255);
                    BattlegroundBracketId   bracket_id    = (BattlegroundBracketId)(scheduled[i] & 255);
                    m_BattlegroundQueues[(int)bgQueueTypeId].BattlegroundQueueUpdate(diff, bgTypeId, bracket_id, arenaType, arenaMMRating > 0, arenaMMRating);
                }
            }

            // if rating difference counts, maybe force-update queues
            if (WorldConfig.GetIntValue(WorldCfg.ArenaMaxRatingDifference) != 0 && WorldConfig.GetIntValue(WorldCfg.ArenaRatedUpdateTimer) != 0)
            {
                // it's time to force update
                if (m_NextRatedArenaUpdate < diff)
                {
                    // forced update for rated arenas (scan all, but skipped non rated)
                    Log.outDebug(LogFilter.Arena, "BattlegroundMgr: UPDATING ARENA QUEUES");
                    for (var qtype = BattlegroundQueueTypeId.Arena2v2; qtype <= BattlegroundQueueTypeId.Arena5v5; ++qtype)
                    {
                        for (int bracket = (int)BattlegroundBracketId.First; bracket < (int)BattlegroundBracketId.Max; ++bracket)
                        {
                            m_BattlegroundQueues[(int)qtype].BattlegroundQueueUpdate(diff,
                                                                                     BattlegroundTypeId.AA, (BattlegroundBracketId)bracket,
                                                                                     (byte)BGArenaType(qtype), true, 0);
                        }
                    }

                    m_NextRatedArenaUpdate = WorldConfig.GetUIntValue(WorldCfg.ArenaRatedUpdateTimer);
                }
                else
                {
                    m_NextRatedArenaUpdate -= diff;
                }
            }
        }
 void BuildBattlegroundStatusHeader(BattlefieldStatusHeader header, Battleground bg, Player player, uint ticketId, uint joinTime, BattlegroundQueueTypeId queueId, ArenaTypes arenaType)
 {
     header.Ticket = new RideTicket();
     header.Ticket.RequesterGuid = player.GetGUID();
     header.Ticket.Id            = ticketId;
     header.Ticket.Type          = RideType.Battlegrounds;
     header.Ticket.Time          = (int)joinTime;
     header.QueueID.Add(queueId.GetPacked());
     header.RangeMin        = (byte)bg.GetMinLevel();
     header.RangeMax        = (byte)bg.GetMaxLevel();
     header.TeamSize        = (byte)(bg.IsArena() ? arenaType : 0);
     header.InstanceID      = bg.GetClientInstanceID();
     header.RegisteredMatch = bg.IsRated();
     header.TournamentRules = false;
 }
 public ScheduledQueueUpdate(uint arenaMatchmakerRating, BattlegroundQueueTypeId queueId, BattlegroundBracketId bracketId)
 {
     ArenaMatchmakerRating = arenaMatchmakerRating;
     QueueId   = queueId;
     BracketId = bracketId;
 }
 public void BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatus, Battleground bg, Player player, uint ticketId, uint joinTime, BattlegroundQueueTypeId queueId, uint avgWaitTime, ArenaTypes arenaType, bool asGroup)
 {
     battlefieldStatus = new BattlefieldStatusQueued();
     BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, queueId, arenaType);
     battlefieldStatus.AverageWaitTime        = avgWaitTime;
     battlefieldStatus.AsGroup                = asGroup;
     battlefieldStatus.SuspendedQueue         = false;
     battlefieldStatus.EligibleForMatchmaking = true;
     battlefieldStatus.WaitTime               = Time.GetMSTimeDiffToNow(joinTime);
 }
 public BattlegroundQueue GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId)
 {
     return(m_BattlegroundQueues[(int)bgQueueTypeId]);
 }
Beispiel #21
0
        void HandleBattlemasterJoin(BattlemasterJoin battlemasterJoin)
        {
            bool isPremade = false;

            if (battlemasterJoin.QueueIDs.Empty())
            {
                Log.outError(LogFilter.Network, $"Battleground: no bgtype received. possible cheater? {_player.GetGUID()}");
                return;
            }

            BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId.FromPacked(battlemasterJoin.QueueIDs[0]);

            if (!Global.BattlegroundMgr.IsValidQueueId(bgQueueTypeId))
            {
                Log.outError(LogFilter.Network, $"Battleground: invalid bg queue {bgQueueTypeId} received. possible cheater? {_player.GetGUID()}");
                return;
            }

            BattlemasterListRecord battlemasterListEntry = CliDB.BattlemasterListStorage.LookupByKey(bgQueueTypeId.BattlemasterListId);

            if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, bgQueueTypeId.BattlemasterListId, null) || battlemasterListEntry.Flags.HasAnyFlag(BattlemasterListFlags.Disabled))
            {
                GetPlayer().SendSysMessage(CypherStrings.BgDisabled);
                return;
            }

            BattlegroundTypeId bgTypeId = (BattlegroundTypeId)bgQueueTypeId.BattlemasterListId;

            // ignore if player is already in BG
            if (GetPlayer().InBattleground())
            {
                return;
            }

            // get bg instance or bg template if instance not found
            Battleground bg = Global.BattlegroundMgr.GetBattlegroundTemplate(bgTypeId);

            if (!bg)
            {
                return;
            }

            // expected bracket entry
            PvpDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel(bg.GetMapId(), GetPlayer().GetLevel());

            if (bracketEntry == null)
            {
                return;
            }

            GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult.None;

            Group grp = _player.GetGroup();

            BattlefieldStatusFailed battlefieldStatusFailed;

            // check queue conditions
            if (grp == null)
            {
                if (GetPlayer().IsUsingLfg())
                {
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.LfgCantUseBattleground);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                // check Deserter debuff
                if (!GetPlayer().CanJoinToBattleground(bg))
                {
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.Deserters);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                bool isInRandomBgQueue = _player.InBattlegroundQueueForBattlegroundQueueType(Global.BattlegroundMgr.BGQueueTypeId((ushort)BattlegroundTypeId.RB, BattlegroundQueueIdType.Battleground, false, 0)) ||
                                         _player.InBattlegroundQueueForBattlegroundQueueType(Global.BattlegroundMgr.BGQueueTypeId((ushort)BattlegroundTypeId.RandomEpic, BattlegroundQueueIdType.Battleground, false, 0));
                if (bgTypeId != BattlegroundTypeId.RB && bgTypeId != BattlegroundTypeId.RandomEpic && isInRandomBgQueue)
                {
                    // player is already in random queue
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.InRandomBg);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                if (_player.InBattlegroundQueue() && !isInRandomBgQueue && (bgTypeId == BattlegroundTypeId.RB || bgTypeId == BattlegroundTypeId.RandomEpic))
                {
                    // player is already in queue, can't start random queue
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.InNonRandomBg);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                // check if already in queue
                if (GetPlayer().GetBattlegroundQueueIndex(bgQueueTypeId) < SharedConst.MaxPlayerBGQueues)
                {
                    return;  // player is already in this queue
                }
                // check if has free queue slots
                if (!GetPlayer().HasFreeBattlegroundQueueId())
                {
                    Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.TooManyQueues);
                    SendPacket(battlefieldStatusFailed);
                    return;
                }

                // check Freeze debuff
                if (_player.HasAura(9454))
                {
                    return;
                }

                BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
                GroupQueueInfo    ginfo   = bgQueue.AddGroup(GetPlayer(), null, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);

                uint avgTime   = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
                uint queueSlot = GetPlayer().AddBattlegroundQueueId(bgQueueTypeId);

                Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatusQueued, bg, GetPlayer(), queueSlot, ginfo.JoinTime, bgQueueTypeId, avgTime, ginfo.ArenaType, false);
                SendPacket(battlefieldStatusQueued);

                Log.outDebug(LogFilter.Battleground, $"Battleground: player joined queue for bg queue {bgQueueTypeId}, {_player.GetGUID()}, NAME {_player.GetName()}");
            }
            else
            {
                if (grp.GetLeaderGUID() != GetPlayer().GetGUID())
                {
                    return;
                }

                ObjectGuid errorGuid;
                err       = grp.CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg.GetMaxPlayersPerTeam(), false, 0, out errorGuid);
                isPremade = (grp.GetMembersCount() >= bg.GetMinPlayersPerTeam());

                BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
                GroupQueueInfo    ginfo   = null;
                uint avgTime = 0;

                if (err == 0)
                {
                    Log.outDebug(LogFilter.Battleground, "Battleground: the following players are joining as group:");
                    ginfo   = bgQueue.AddGroup(GetPlayer(), grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
                    avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
                }

                for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.Next())
                {
                    Player member = refe.GetSource();
                    if (!member)
                    {
                        continue;   // this should never happen
                    }
                    if (err != 0)
                    {
                        BattlefieldStatusFailed battlefieldStatus;
                        Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, err, errorGuid);
                        member.SendPacket(battlefieldStatus);
                        continue;
                    }

                    // add to queue
                    uint queueSlot = member.AddBattlegroundQueueId(bgQueueTypeId);

                    Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, bgQueueTypeId, avgTime, ginfo.ArenaType, true);
                    member.SendPacket(battlefieldStatusQueued);
                    Log.outDebug(LogFilter.Battleground, $"Battleground: player joined queue for bg queue {bgQueueTypeId}, {member.GetGUID()}, NAME {member.GetName()}");
                }
                Log.outDebug(LogFilter.Battleground, "Battleground: group end");
            }

            Global.BattlegroundMgr.ScheduleQueueUpdate(0, bgQueueTypeId, bracketEntry.GetBracketId());
        }