Show
Ignore:
Timestamp:
11/19/08 13:22:41 (17 years ago)
Author:
yumileroy
Message:

[svn] -enabled instantiated battlegrounds
-enabled arena matches
-rewritten battleground queuing to support joining as group
-removed queue announcements

Original author: w12x
Date: 2008-10-05 08:48:32-05:00

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/game/BattleGroundHandler.cpp

    r2 r9  
    2727#include "ObjectAccessor.h" 
    2828#include "Object.h" 
     29#include "Chat.h" 
     30#include "Language.h" 
    2931#include "BattleGroundMgr.h" 
    3032#include "BattleGroundWS.h" 
    3133#include "BattleGround.h" 
     34#include "ArenaTeam.h" 
    3235 
    3336void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) 
     
    7679    uint32 instanceId; 
    7780    uint8 joinAsGroup; 
     81    Group * grp; 
    7882 
    7983    recv_data >> guid;                                      // battlemaster guid 
     
    8286    recv_data >> joinAsGroup;                               // join as group 
    8387 
    84     sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId); 
    85  
    86     if(bgTypeId >= MAX_BATTLEGROUND_TYPES)                  // cheating? 
    87         return; 
     88    if(bgTypeId >= MAX_BATTLEGROUND_TYPES) 
     89    { 
     90        sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); 
     91        return; 
     92    } 
     93 
     94    sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); 
     95 
     96    // can do this, since it's battleground, not arena 
     97    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0); 
    8898 
    8999    // ignore if we already in BG or BG queue 
     
    98108        return; 
    99109 
    100     // check Deserter debuff 
    101     if( !_player->CanJoinToBattleground() ) 
    102     { 
    103         WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 
    104         data << (uint32) 0xFFFFFFFE; 
    105         _player->GetSession()->SendPacket(&data); 
    106         return; 
    107     } 
    108  
    109     // check existence 
    110     BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 
    111     if(!bg) 
    112         return; 
    113  
    114     if(joinAsGroup && _player->GetGroup()) 
    115     { 
    116         Group *grp = _player->GetGroup(); 
     110    // get bg instance or bg template if instance not found 
     111    BattleGround * bg = 0; 
     112    if(instanceId) 
     113        BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); 
     114 
     115    if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) 
     116    { 
     117        sLog.outError("Battleground: no available bg / template found"); 
     118        return; 
     119    } 
     120 
     121    // check queueing conditions 
     122    if(!joinAsGroup) 
     123    { 
     124        // check Deserter debuff 
     125        if( !_player->CanJoinToBattleground() ) 
     126        { 
     127            WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 
     128            data << (uint32) 0xFFFFFFFE; 
     129            _player->GetSession()->SendPacket(&data); 
     130            return; 
     131        } 
     132        // check if already in queue 
     133        if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) 
     134            //player is already in this queue 
     135            return; 
     136        // check if has free queue slots 
     137        if(!_player->HasFreeBattleGroundQueueId()) 
     138            return; 
     139    } 
     140    else 
     141    { 
     142        grp = _player->GetGroup(); 
     143        // no group found, error 
     144        if(!grp) 
     145            return; 
     146        uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); 
     147        switch(err) 
     148        { 
     149            // TODO: add error-based feedback to players in all cases 
     150        case BG_JOIN_ERR_GROUP_TOO_MANY: 
     151            { 
     152            WorldPacket data; 
     153            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_TOO_LARGE), NULL); 
     154            SendPacket(&data); 
     155            } 
     156            return; 
     157            break; 
     158        case BG_JOIN_ERR_OFFLINE_MEMBER: 
     159            { 
     160            WorldPacket data; 
     161            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_OFFLINE_MEMBER), NULL); 
     162            SendPacket(&data); 
     163            } 
     164            return; 
     165            break; 
     166        case BG_JOIN_ERR_MIXED_FACTION: 
     167            { 
     168            WorldPacket data; 
     169            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_FACTION), NULL); 
     170            SendPacket(&data); 
     171            } 
     172            return; 
     173            break; 
     174        case BG_JOIN_ERR_MIXED_LEVELS: 
     175            { 
     176            WorldPacket data; 
     177            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_LEVELS), NULL); 
     178            SendPacket(&data); 
     179            } 
     180            return; 
     181            break; 
     182        case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE: 
     183            { 
     184            WorldPacket data; 
     185            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE), NULL); 
     186            SendPacket(&data); 
     187            } 
     188            return; 
     189            break; 
     190        case BG_JOIN_ERR_GROUP_DESERTER: 
     191            { 
     192            WorldPacket data; 
     193            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_DESERTER), NULL); 
     194            SendPacket(&data); 
     195            } 
     196            return; 
     197            break; 
     198        case BG_JOIN_ERR_ALL_QUEUES_USED: 
     199            { 
     200            WorldPacket data; 
     201            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS), NULL); 
     202            SendPacket(&data); 
     203            } 
     204            return; 
     205            break; 
     206            // all ok, can join 
     207        case BG_JOIN_ERR_OK: 
     208            break; 
     209            // these aren't possible outcomes in bgs  
     210        case BG_JOIN_ERR_GROUP_NOT_ENOUGH: 
     211        case BG_JOIN_ERR_MIXED_ARENATEAM: 
     212            return; 
     213            break; 
     214            // not the above? shouldn't happen, don't let join 
     215        default: 
     216            return; 
     217            break; 
     218        }; 
     219    } 
     220 
     221    // if we're here, then the conditions to join a bg are met. We can proceed in joining. 
     222 
     223    // _player->GetGroup() was already checked, grp is already initialized 
     224    if(joinAsGroup /* && _player->GetGroup()*/) 
     225    { 
     226        sLog.outDebug("Battleground: the following players are joining as group:"); 
     227        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); 
    117228        for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) 
    118229        { 
    119230            Player *member = itr->getSource(); 
    120             if(!member) continue; 
    121  
    122             if( !member->CanJoinToBattleground() ) 
    123             { 
    124                 WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 
    125                 data << (uint32) 0xFFFFFFFE; 
    126                 _player->GetSession()->SendPacket(&data); 
    127                 continue; 
    128             } 
    129             if (member->InBattleGroundQueueForBattleGroundType(bgTypeId)) 
    130                 //player is already in this queue 
    131                 continue; 
    132  
    133             WorldPacket data; 
    134                                                             // add to queue 
    135             uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId); 
    136             if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 
    137             { 
    138                 // fill data packet 
    139                 //member->GetSession()->SendPacket(data); 
    140                 continue; 
    141             } 
     231            if(!member) continue;   // this should never happen 
     232 
     233            uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);           // add to queue 
    142234 
    143235            // store entry point coords (same as leader entry point) 
    144236            member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); 
    145237 
     238            WorldPacket data; 
    146239                                                            // send status packet (in queue) 
    147240            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); 
     
    149242            sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); 
    150243            member->GetSession()->SendPacket(&data); 
    151             sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId); 
    152         } 
     244            sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); 
     245            sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); 
     246        } 
     247        sLog.outDebug("Battleground: group end"); 
     248        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); 
    153249    } 
    154250    else 
    155251    { 
    156         if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) 
    157             //player is already in this queue 
    158             return; 
    159         uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId); 
    160         if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 
    161         { 
    162             WorldPacket data; 
    163             // fill data packet 
    164             //SendPacket(data); 
    165             return; 
    166         } 
    167  
     252        // already checked if queueSlot is valid, now just get it 
     253        uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); 
    168254        // store entry point coords 
    169255        _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); 
     
    173259        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); 
    174260        SendPacket(&data); 
    175         sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId); 
     261 
     262        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); 
     263        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); 
     264        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); 
     265        sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); 
    176266    } 
    177267} 
     
    247337    recv_data >> bgTypeId;                                  // id from DBC 
    248338 
    249     if(bgTypeId >= MAX_BATTLEGROUND_TYPES)                  // cheating? 
    250         return; 
    251  
    252     // can't be received if player not in BG queue 
    253     if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) 
    254         return; 
     339    if(bgTypeId >= MAX_BATTLEGROUND_TYPES) 
     340    { 
     341        sLog.outError("Battleground: invalid bgtype received."); 
     342        return; 
     343    } 
    255344 
    256345    BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); 
     
    270359    sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); 
    271360 
    272     uint8 unk1; 
     361    uint8 type;                                             // arenatype if arena 
    273362    uint8 unk2;                                             // unk, can be 0x0 (may be if was invited?) and 0x1 
     363    uint32 instanceId;                                       
    274364    uint32 bgTypeId;                                        // type id from dbc 
    275365    uint16 unk;                                             // 0x1F90 constant? 
    276366    uint8 action;                                           // enter battle 0x1, leave queue 0x0 
    277367 
    278     recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action; 
    279  
    280     if(bgTypeId >= MAX_BATTLEGROUND_TYPES)                  // cheating? 
    281         return; 
    282  
    283     if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) 
    284         return; 
    285  
    286     BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 
     368    recv_data >> type >> unk2 >> bgTypeId >> unk >> action; 
     369 
     370    if(bgTypeId >= MAX_BATTLEGROUND_TYPES) 
     371    { 
     372        sLog.outError("Battleground: invalid bgtype received."); 
     373        // update battleground slots for the player to fix his UI and sent data. 
     374        // this is a HACK, I don't know why the client starts sending invalid packets in the first place. 
     375        // it usually happens with extremely high latency (if debugging / stepping in the code for example) 
     376        if(_player->InBattleGroundQueue()) 
     377        { 
     378            // update all queues, send invitation info if player is invited, queue info if queued 
     379            for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
     380            { 
     381                uint32 queue_id = _player->GetBattleGroundQueueId(i); 
     382                if(!queue_id) 
     383                    continue; 
     384                BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 
     385                // if the player is not in queue, contine 
     386                if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 
     387                    continue; 
     388 
     389                // no group information, this should never happen 
     390                if(!itrPlayerStatus->second.GroupInfo) 
     391                    continue; 
     392 
     393                BattleGround * bg = NULL; 
     394 
     395                // get possibly needed data from groupinfo 
     396                bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; 
     397                uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; 
     398                uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; 
     399                uint8 status = 0; 
     400 
     401                 
     402                if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) 
     403                { 
     404                    // not invited to bg, get template 
     405                    bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 
     406                    status = STATUS_WAIT_QUEUE; 
     407                } 
     408                else 
     409                { 
     410                    // get the bg we're invited to 
     411                    BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); 
     412                    status = STATUS_WAIT_JOIN; 
     413                } 
     414 
     415                // if bg not found, then continue 
     416                if(!bg) 
     417                    continue; 
     418 
     419                // don't invite if already in the instance 
     420                if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) 
     421                    continue; 
     422 
     423                // re - invite player with proper data 
     424                WorldPacket data; 
     425                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); 
     426                SendPacket(&data); 
     427            } 
     428        } 
     429        return; 
     430    } 
     431 
     432    uint32 bgQueueTypeId = 0; 
     433    // get the bg what we were invited to  
     434    BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; 
     435    bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); 
     436    itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 
     437 
     438    if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 
     439    { 
     440        sLog.outError("Battleground: itrplayerstatus not found."); 
     441        return; 
     442    } 
     443    instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; 
     444 
     445    // if action == 1, then instanceId is _required_ 
     446    if(!instanceId && action == 1) 
     447    { 
     448        sLog.outError("Battleground: instance not found."); 
     449        return; 
     450    } 
     451 
     452    BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); 
     453 
     454    // bg template might and must be used in case of leaving queue, when instance is not created yet 
     455    if(!bg && action == 0) 
     456        bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 
     457 
    287458    if(!bg) 
    288         return; 
    289  
    290     uint32 queueSlot = 0; 
    291     WorldPacket data; 
    292     switch(action) 
    293     { 
    294         case 1:                                             // port to battleground 
    295             // cheating? 
    296             if(!_player->IsInvitedForBattleGroundType(bgTypeId)) 
    297                 return; 
    298  
    299             // check if player is not deserter 
    300             if( !_player->CanJoinToBattleground() ) 
    301             { 
    302                 WorldPacket data2; 
    303                 data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 
    304                 data2 << (uint32) 0xFFFFFFFE; 
    305                 SendPacket(&data2); 
    306                 return; 
    307             } 
    308  
    309             // if the player is dead, resurrect him before teleport 
    310             if(!_player->isAlive()) 
    311             { 
    312                 _player->ResurrectPlayer(1.0f,false); 
    313                 _player->SpawnCorpseBones(); 
    314             } 
    315  
    316             // leave current group 
    317             _player->RemoveFromGroup(); 
    318  
    319             // packet to player about BG status 
    320             queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); 
    321             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); 
    322             _player->GetSession()->SendPacket(&data); 
    323  
    324             // remove battleground queue status from BGmgr 
    325             sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false); 
    326  
    327             // this is still needed here if battleground "jumping" shouldn't add deserter debuff 
    328             // also this required to prevent stuck at old battleground after SetBattleGroundId set to new 
    329             if (BattleGround *currentBg = _player->GetBattleGround()) 
    330                 currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); 
    331  
    332             _player->SetBattleGroundId(bg->GetTypeID()); 
    333             sBattleGroundMgr.SendToBattleGround(_player, bgTypeId); 
    334             bg->AddPlayer(_player); 
    335             break; 
    336         case 0:                                             // leave queue 
    337             queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); 
    338             _player->RemoveBattleGroundQueueId(bgTypeId);   // must be called this way, because if you move this call to queue->removeplayer, it causes bugs 
    339             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 
    340             sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true); 
    341             SendPacket(&data); 
    342             break; 
    343         default: 
    344             sLog.outError("Battleground port: unknown action %u", action); 
    345             break; 
     459    { 
     460        sLog.outError("Battleground: bg not found."); 
     461        return; 
     462    } 
     463 
     464    bgTypeId = bg->GetTypeID(); 
     465 
     466    if(_player->InBattleGroundQueue()) 
     467    { 
     468        uint32 queueSlot = 0; 
     469        uint32 team = 0; 
     470        uint32 arenatype = 0; 
     471        uint32 israted = 0; 
     472        uint32 rating = 0; 
     473        // get the team info from the queue 
     474        BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 
     475        if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end() 
     476            && pitr->second.GroupInfo ) 
     477        { 
     478            team = pitr->second.GroupInfo->Team; 
     479            arenatype = pitr->second.GroupInfo->ArenaType; 
     480            israted = pitr->second.GroupInfo->IsRated; 
     481            rating = pitr->second.GroupInfo->ArenaTeamRating; 
     482        } 
     483        else 
     484        { 
     485            sLog.outError("Battleground: Invalid player queue info!"); 
     486            return; 
     487        } 
     488        WorldPacket data; 
     489        switch(action) 
     490        { 
     491            case 1:                                     // port to battleground 
     492                if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) 
     493                    return;                                     // cheating? 
     494                // resurrect the player 
     495                if(!_player->isAlive()) 
     496                { 
     497                    _player->ResurrectPlayer(1.0f,false); 
     498                    _player->SpawnCorpseBones(); 
     499                } 
     500                // stop taxi flight at port 
     501                if(_player->isInFlight()) 
     502                { 
     503                    _player->GetMotionMaster()->MovementExpired(); 
     504                    _player->m_taxi.ClearTaxiDestinations(); 
     505                } 
     506                _player->RemoveFromGroup(); 
     507                queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); 
     508                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); 
     509                _player->GetSession()->SendPacket(&data); 
     510                // remove battleground queue status from BGmgr 
     511                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); 
     512                // this is still needed here if battleground "jumping" shouldn't add deserter debuff 
     513                // also this required to prevent stuck at old battleground after SetBattleGroundId set to new 
     514                if( BattleGround *currentBg = _player->GetBattleGround() ) 
     515                    currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); 
     516 
     517                // set the destination instance id 
     518                _player->SetBattleGroundId(bg->GetInstanceID()); 
     519                // set the destination team 
     520                _player->SetBGTeam(team); 
     521                // bg->HandleBeforeTeleportToBattleGround(_player); 
     522                sBattleGroundMgr.SendToBattleGround(_player, instanceId); 
     523                // add only in HandleMoveWorldPortAck() 
     524                // bg->AddPlayer(_player,team); 
     525                sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); 
     526                break; 
     527            case 0:                                     // leave queue 
     528                queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); 
     529                _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs 
     530                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 
     531                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); 
     532                // player left queue, we should update it, maybe now his group fits in 
     533                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating); 
     534                SendPacket(&data); 
     535                sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId); 
     536                break; 
     537            default: 
     538                sLog.outError("Battleground port: unknown action %u", action); 
     539                break; 
     540        } 
    346541    } 
    347542} 
     
    384579        if(bg) 
    385580        { 
    386             uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID()); 
     581            uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 
     582            uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); 
    387583            if((bg->GetStatus() <= STATUS_IN_PROGRESS)) 
    388584            { 
     
    392588            for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    393589            { 
    394                 uint32 queue_id = _player->GetBattleGroundQueueId(i); 
    395                 if (i == queueSlot || !queue_id) 
     590                uint32 queue_id = _player->GetBattleGroundQueueId(i);       // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong 
     591                uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); 
     592                uint8 isRated = 0; 
     593                if (i == queueSlot || !queue_id)                            // we need to get the instance ids 
    396594                    continue; 
    397                 BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id); 
     595                BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 
     596                if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 
     597                    continue; 
     598                if(itrPlayerStatus->second.GroupInfo) 
     599                { 
     600                    arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; 
     601                    isRated = itrPlayerStatus->second.GroupInfo->IsRated; 
     602                } 
     603                BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); //  try this 
    398604                if(bg2) 
    399605                { 
    400606                    //in this call is small bug, this call should be filled by player's waiting time in queue 
    401607                    //this call nulls all timers for client : 
    402                     sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); 
     608                    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); 
    403609                    SendPacket(&data); 
    404610                } 
     
    411617        for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    412618        { 
    413             if(uint32 queue_id = _player->GetBattleGroundQueueId(i)) 
    414             { 
    415                 if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id)) 
    416                 { 
    417                     sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); 
    418                     SendPacket(&data); 
    419                 } 
    420             } 
    421         } 
    422     } 
     619            uint32 queue_id = _player->GetBattleGroundQueueId(i); 
     620            if(!queue_id) 
     621                continue; 
     622            uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); 
     623            uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); 
     624            uint8 isRated = 0; 
     625            BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 
     626            BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 
     627            if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 
     628                continue; 
     629            if(itrPlayerStatus->second.GroupInfo) 
     630            { 
     631                arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; 
     632                isRated = itrPlayerStatus->second.GroupInfo->IsRated; 
     633            } 
     634            if(bg && queue_id) 
     635            { 
     636                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); 
     637                SendPacket(&data); 
     638            } 
     639        } 
     640    } 
     641/*    else              // not sure if it needed... 
     642    { 
     643        for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
     644        { 
     645            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); 
     646            SendPacket(&data); 
     647        } 
     648    }*/ 
    423649} 
    424650 
     
    479705    if(_player->InBattleGround()) 
    480706        return; 
    481  
    482     for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId) 
    483     { 
    484         if(_player->GetBattleGroundQueueId(qId) != 0) 
    485             return; 
    486     } 
    487707 
    488708    uint64 guid;                                            // arena Battlemaster guid 
     
    490710    uint8 asGroup;                                          // asGroup 
    491711    uint8 isRated;                                          // isRated 
     712    Group * grp; 
     713 
    492714    recv_data >> guid >> type >> asGroup >> isRated; 
    493715 
     
    500722 
    501723    uint8 arenatype = 0; 
     724    uint32 arenaRating = 0; 
    502725 
    503726    switch(type) 
     
    517740    } 
    518741 
    519     if(isRated && !_player->GetArenaTeamId(type))           // player not in arena team of that size 
    520     { 
    521         _player->GetSession()->SendNotInArenaTeamPacket(arenatype); 
    522         return; 
    523     } 
    524  
    525     if(asGroup && !_player->GetGroup())                     // player not in group 
    526         return; 
    527  
    528     // check existence 
    529     BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA); 
    530     if(!bg) 
    531         return; 
    532  
    533     bg->SetArenaType(arenatype); 
    534     bg->SetRated(isRated); 
    535  
    536     if(asGroup && _player->GetGroup()) 
    537     { 
    538         Group *grp = _player->GetGroup(); 
     742    //check existance 
     743    BattleGround* bg = NULL; 
     744    if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) ) 
     745    { 
     746        sLog.outError("Battleground: template bg (all arenas) not found");      
     747        return; 
     748    } 
     749 
     750    uint8 bgTypeId = bg->GetTypeID(); 
     751    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); 
     752 
     753    // check queueing conditions 
     754    if(!asGroup) 
     755    { 
     756        // check if already in queue 
     757        if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) 
     758            //player is already in this queue 
     759            return; 
     760        // check if has free queue slots 
     761        if(!_player->HasFreeBattleGroundQueueId()) 
     762            return; 
     763    } 
     764    else 
     765    { 
     766        grp = _player->GetGroup(); 
     767        // no group found, error 
     768        if(!grp) 
     769            return; 
     770        uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type); 
     771        switch(err) 
     772        { 
     773            // TODO: add error-based feedback to players in all cases 
     774        case BG_JOIN_ERR_GROUP_TOO_MANY: 
     775            { 
     776            WorldPacket data; 
     777            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_ARENA_GROUP_TOO_LARGE), NULL); 
     778            SendPacket(&data); 
     779            } 
     780            return; 
     781            break; 
     782        case BG_JOIN_ERR_GROUP_NOT_ENOUGH: 
     783            { 
     784            WorldPacket data; 
     785            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_ARENA_NOT_ENOUGH_PLAYERS), NULL); 
     786            SendPacket(&data); 
     787            } 
     788            return; 
     789            break; 
     790        case BG_JOIN_ERR_MIXED_ARENATEAM: 
     791            { 
     792            WorldPacket data; 
     793            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_ARENA_YOUR_TEAM_ONLY), NULL); 
     794            SendPacket(&data); 
     795            } 
     796            return; 
     797            break; 
     798        case BG_JOIN_ERR_OFFLINE_MEMBER: 
     799            { 
     800            WorldPacket data; 
     801            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_OFFLINE_MEMBER), NULL); 
     802            SendPacket(&data); 
     803            } 
     804            return; 
     805            break; 
     806        case BG_JOIN_ERR_MIXED_FACTION: 
     807            { 
     808            WorldPacket data; 
     809            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_FACTION), NULL); 
     810            SendPacket(&data); 
     811            } 
     812            return; 
     813            break; 
     814        case BG_JOIN_ERR_MIXED_LEVELS: 
     815            { 
     816            WorldPacket data; 
     817            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_LEVELS), NULL); 
     818            SendPacket(&data); 
     819            } 
     820            return; 
     821            break; 
     822        case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE: 
     823            { 
     824            WorldPacket data; 
     825            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE), NULL); 
     826            SendPacket(&data); 
     827            } 
     828            return; 
     829            break; 
     830        case BG_JOIN_ERR_GROUP_DESERTER: 
     831            { 
     832            WorldPacket data; 
     833            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_DESERTER), NULL); 
     834            SendPacket(&data); 
     835            } 
     836            return; 
     837            break; 
     838        case BG_JOIN_ERR_ALL_QUEUES_USED: 
     839            { 
     840            WorldPacket data; 
     841            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS), NULL); 
     842            SendPacket(&data); 
     843            } 
     844            return; 
     845            break; 
     846            // all ok, can join 
     847        case BG_JOIN_ERR_OK: 
     848            break; 
     849            // not the above? shouldn't happen, don't let join 
     850        default: 
     851            return; 
     852            break; 
     853        }; 
     854    } 
     855 
     856    uint32 ateamId = 0; 
     857 
     858    if(isRated)            
     859    { 
     860        ateamId = _player->GetArenaTeamId(type); 
     861        // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) 
     862        ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); 
     863        if(!at) 
     864        { 
     865            _player->GetSession()->SendNotInArenaTeamPacket(arenatype); 
     866            return; 
     867        } 
     868        // get the team rating for queueing 
     869        arenaRating = at->GetRating(); 
     870        // the arenateam id must match for everyone in the group 
     871        // get the personal ratings for queueing 
     872        uint32 avg_pers_rating = 0; 
     873        for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) 
     874        { 
     875            Player *member = itr->getSource(); 
     876 
     877            // calc avg personal rating 
     878            avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5); 
     879        } 
     880 
     881        if( arenatype ) 
     882            avg_pers_rating /= arenatype; 
     883 
     884        // if avg personal rating is more than 150 points below the team’s rating, the team will be queued against an opponent matching or similar to the average personal rating  
     885        if(avg_pers_rating + 150 < arenaRating) 
     886            arenaRating = avg_pers_rating; 
     887    } 
     888 
     889    if(asGroup) 
     890    { 
     891        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId); 
     892        sLog.outDebug("Battleground: arena join as group start"); 
     893        if(isRated) 
     894            sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype); 
    539895        for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) 
    540896        { 
     
    542898            if(!member) continue; 
    543899 
    544             /*if (!member->CanJoinToBattleground()) 
    545                 //player has deserter aura .. do nothing 
    546             */ 
    547  
    548             if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) 
    549                 //player is already in this queue 
    550                 continue; 
    551  
    552                                                             // add to queue 
    553             uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA); 
    554             if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 
    555             { 
    556                 WorldPacket data; 
    557                 //fill data 
    558                 //member->GetSession()->SendPacket(data); 
    559                 continue; 
    560             } 
     900            uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue 
    561901 
    562902            // store entry point coords (same as leader entry point) 
     
    565905            WorldPacket data; 
    566906            // send status packet (in queue) 
    567             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); 
     907            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); 
    568908            member->GetSession()->SendPacket(&data); 
    569             sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA); 
     909            sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); 
    570910            member->GetSession()->SendPacket(&data); 
    571             sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA); 
    572         } 
     911            sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); 
     912            sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); 
     913        } 
     914        sLog.outDebug("Battleground: arena join as group end"); 
     915        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); 
    573916    } 
    574917    else 
    575918    { 
    576         /*if (!member->CanJoinToBattleground()) 
    577             //player has deserter aura .. do nothing 
    578         */ 
    579  
    580         if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) 
    581             //player is already in this queue 
    582             return; 
    583  
    584         uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA); 
    585         if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 
    586         { 
    587             WorldPacket data; 
    588             //fill data (player is in 3 queues already) 
    589             //SendPacket(data); 
    590             return; 
    591         } 
     919        uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); 
    592920 
    593921        // store entry point coords 
     
    596924        WorldPacket data; 
    597925        // send status packet (in queue) 
    598         sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); 
     926        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); 
    599927        SendPacket(&data); 
    600         sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA); 
     928        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating); 
     929        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); 
     930        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); 
     931        sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); 
    601932    } 
    602933}