Changeset 9 for trunk

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

Location:
trunk
Files:
1 added
39 modified

Legend:

Unmodified
Added
Removed
  • trunk/sql/mangos.sql

    r6 r9  
    199199('debug standstate',2,'Syntax: .debug standstate #emoteid\r\n\r\nChange the emote of your character while standing to #emoteid.'), 
    200200('debug update',3,'Syntax: .debug update #field #value\r\n\r\nUpdate the field #field of the selected character or creature with value #value.\r\n\r\nIf no #value is provided, display the content of field #field.'), 
     201('debug arena',3,'Syntax: .debug arena\r\n\r\n Toggles arena 1v1 or normal mode.'), 
    201202('delticket',2,'Syntax: .delticket all\r\n        .delticket #num\r\n        .delticket $character_name\r\n\rall to dalete all tickets at server, $character_name to delete ticket of this character, #num to delete ticket #num.'), 
    202203('demorph',2,'Syntax: .demorph\r\n\r\nDemorph the selected player.'), 
     
    209210('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'), 
    210211('explorecheat',3,'Syntax: .explorecheat #flag\r\n\r\nReveal  or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\n\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), 
     212('flusharenapoints',3,'Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'), 
    211213('gm',1,'Syntax: .gm on/off\r\n\r\nEnable or Disable GM MODE'), 
    212214('gm fly',3,'Syntax: .gm fly on/off\r\nEnable/disable gm fly mode.'), 
     
    13641366/*!40000 ALTER TABLE `instance_template` DISABLE KEYS */; 
    13651367INSERT INTO `instance_template` VALUES 
     1368(30,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 
    13661369(33,0,22,30,10,7200,NULL,NULL,NULL,NULL,''), 
    13671370(34,0,24,32,10,7200,NULL,NULL,NULL,NULL,''), 
     
    13871390(429,0,55,60,5,7200,NULL,NULL,NULL,NULL,''), 
    13881391(469,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), 
     1392(489,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 
    13891393(509,0,60,0,20,259200,NULL,NULL,NULL,NULL,''), 
     1394(529,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 
    13901395(531,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), 
    1391 (533,0,60,0,40,604800,NULL,NULL,NULL,NULL,''); 
     1396(533,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), 
     1397(559,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 
     1398(562,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 
     1399(566,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 
     1400(572,0,10,0,50,0,NULL,NULL,NULL,NULL,''); 
    13921401/*!40000 ALTER TABLE `instance_template` ENABLE KEYS */; 
    13931402UNLOCK TABLES; 
     
    25672576(709,'Do not Disturb',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
    25682577(710,'Away from Keyboard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
    2569 (711,'Queue status for %s (Lvl: %u to %u)\nQueued alliances: %u (Need at least %u more)\nQueued hordes: %u (Need at least %u more)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
    2570 (712,'|cffff0000[BG Queue Announcer]:|r %s -- [%u-%u] A: %u (Need: %u), H: %u (Needs %u)|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); 
     2578(711,'Your group is too large for this battleground. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2579(712,'Your group is too large for this arena. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2580(713,'Your group has members not in your arena team. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2581(714,'Your group does not have enough players to join this match.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2582(715,'The Gold Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2583(716,'The Green Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2584(717, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2585(718, 'Your group has an offline member. Please remove him before joining.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2586(719, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2587(720, 'Your group has players from different battleground brakets. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2588(721, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2589(722, 'Someone in your party is Deserter. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2590(723, 'Someone in your party is already in three battleground queues. You cannot join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2591(724, 'You cannot teleport to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2592(725, 'You cannot summon players to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2593(726, 'You must be in GM mode to teleport to a player in a battleground.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2594(727, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 
     2595(728, 'Arena testing turned %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); 
    25712596/*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; 
    25722597UNLOCK TABLES; 
  • trunk/src/game/ArenaTeam.cpp

    r2 r9  
    5252        return false; 
    5353 
    54     sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid)); 
     54    sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid)); 
    5555 
    5656    CaptainGuid = captainGuid; 
     
    139139        pl->SetInArenaTeam(Id, GetSlot()); 
    140140        pl->SetArenaTeamIdInvited(0); 
    141     } 
    142     else 
    143     { 
    144         Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id, PlayerGuid); 
     141        // personal rating 
     142        pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 5, 1500); 
    145143    } 
    146144 
     
    150148        if(pl) 
    151149            pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); 
    152         else 
    153             Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, PlayerGuid); 
    154     } 
     150    } 
     151 
     152    // setuint32valueindb is asynch, can't be used here 
     153    Tokens tokens; 
     154    if(!Player::LoadValuesArrayFromDB(tokens,PlayerGuid)) 
     155        return false; 
     156 
     157    // arena team id 
     158    uint16 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6); 
     159    char buf[11]; 
     160    snprintf(buf,11,"%u",Id); 
     161    tokens[index] = buf; 
     162    // pers rating 
     163    index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 5; 
     164    buf[11]; 
     165    snprintf(buf,11,"%u",1500); 
     166    tokens[index] = buf; 
     167    // hide promote/remove buttons 
     168    if(CaptainGuid != PlayerGuid) 
     169    { 
     170        index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6); 
     171        buf[11]; 
     172        snprintf(buf,11,"%u",1); 
     173        tokens[index] = buf; 
     174    } 
     175 
     176    Player::SaveValuesArrayInDB(tokens,PlayerGuid); 
     177 
    155178    return true; 
    156179} 
     
    158181bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) 
    159182{ 
    160     LoadStatsFromDB(ArenaTeamId); 
    161     LoadMembersFromDB(ArenaTeamId); 
    162  
    163     //                                                      0          1    2           3    4               5           6           7           8 
    164183    QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); 
    165184 
     
    181200    delete result; 
    182201 
     202    // only load here, so additional checks can be made 
     203    LoadStatsFromDB(ArenaTeamId); 
     204    LoadMembersFromDB(ArenaTeamId); 
     205 
     206    if(!GetMembersSize()) 
     207    { 
     208        // arena team is empty, delete from db 
     209        CharacterDatabase.BeginTransaction(); 
     210        CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); 
     211        CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 
     212        CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); 
     213        CharacterDatabase.CommitTransaction(); 
     214        // return false 
     215        return false; 
     216    } 
     217 
    183218    return true; 
    184219} 
     
    208243    Field *fields; 
    209244 
    210     QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 
     245    QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season,points_to_add FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 
    211246    if(!result) 
    212247        return; 
     
    217252        ArenaTeamMember newmember; 
    218253        newmember.guid          = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); 
     254        // check if this member is in this arenateam 
     255        // based on character data field 
     256        if(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6),newmember.guid) != ArenaTeamId) 
     257        { 
     258            // the player's registered arena team for this slot isn't this team, so delete member info from here 
     259            CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u' AND arenateamid = '%u'",fields[0].GetUInt32(), ArenaTeamId); 
     260            continue; 
     261        } 
    219262        LoadPlayerStats(&newmember); 
    220263        newmember.played_week   = fields[1].GetUInt32(); 
     
    277320 
    278321    Player *player = objmgr.GetPlayer(guid); 
     322    // this will be ugly. because of the asynchronous sql handling, we have to set all the fields of the player at once, and save them at once, or else the save will only modify the last field. 
     323    // rip off of setuint32valueindb 
    279324    if(player) 
    280325    { 
    281326        player->SetInArenaTeam(0, GetSlot()); 
    282327        player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0); 
    283     } 
    284     else 
    285     { 
    286         Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid); 
    287     } 
    288  
    289     CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid)); 
     328        // delete all info regarding this team 
     329        for(int i = 0; i < 6; ++i) 
     330        { 
     331            player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0); 
     332        } 
     333    } 
     334 
     335    // we have to do it this way, setuint32valueindb is asynch, unsafe to use multiple times in a row on the same player 
     336    Tokens tokens; 
     337    if(!Player::LoadValuesArrayFromDB(tokens,guid)) 
     338        return; 
     339 
     340    for(int i = 0; i < 6; ++i) 
     341    { 
     342        uint16 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i; 
     343        char buf[11]; 
     344        snprintf(buf,11,"%u",0); 
     345        tokens[index] = buf; 
     346    } 
     347 
     348    Player::SaveValuesArrayInDB(tokens,guid); 
     349 
     350    // only delete from this arena team! 
     351    CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid)); 
    290352} 
    291353 
     
    314376    CharacterDatabase.BeginTransaction(); 
    315377    CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); 
     378    CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); 
    316379    CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); 
    317380    CharacterDatabase.CommitTransaction(); 
     
    343406            data << uint32(itr->played_season);             // played this season 
    344407            data << uint32(itr->wons_season);               // wins this season 
    345             data << uint32(0);                              // personal rating? 
     408            data << uint32(pl->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5));                              // personal rating? 
    346409        } 
    347410        else 
     
    357420            data << uint32(itr->played_season);             // played this season 
    358421            data << uint32(itr->wons_season);               // wins this season 
    359             data << uint32(0);                              // personal rating? 
     422            data << uint32(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5, itr->guid));                              // personal rating? 
    360423        } 
    361424    } 
     
    392455} 
    393456 
     457void ArenaTeam::NotifyStatsChanged() 
     458{ 
     459    // this is called after a rated match ended 
     460    // updates arena team stats for every member of the team (not only the ones who participated!) 
     461    for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 
     462    { 
     463        Player * plr=objmgr.GetPlayer(itr->guid); 
     464        if(plr) 
     465            Stats(plr->GetSession()); 
     466    } 
     467} 
     468 
    394469void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) 
    395470{ 
     
    399474    data << uint32(GetId());                                // arena team id 
    400475    data << uint32(stats.rating);                           // rating 
    401     data << uint32(stats.games);                            // games 
    402     data << uint32(stats.wins);                             // wins 
    403     data << uint32(stats.played);                           // played (count of all games, that played...) 
    404     data << uint32(0);                                      // 2.3.3 personal rating? 
     476    data << uint32(stats.played);                           // season played 
     477    data << uint32(stats.wins2);                            // season wins 
     478    uint32 participated = 0; 
     479    for(MemberList::iterator itr = members.begin(); itr!= members.end(); ++itr) 
     480    { 
     481        if(itr->guid == guid) 
     482        { 
     483            participated = itr->played_season; 
     484            break; 
     485        } 
     486    } 
     487    data << uint32(participated);                            // played (count of all games, that the inspected member participated...) 
     488    data << uint32(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5, guid));                                       // unk, 2.3.3 (personal rating?) 
     489 
    405490    session->SendPacket(&data); 
    406491} 
     
    495580} 
    496581 
     582uint32 ArenaTeam::GetPoints(uint32 MemberRating) 
     583{ 
     584    // returns how many points would be awarded with this team type with this rating 
     585    float points; 
     586 
     587    uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating; 
     588 
     589    if(rating<=1500) 
     590    { 
     591        points = (float)rating * 0.22f + 14.0f; 
     592    } 
     593    else 
     594    { 
     595        points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating)); 
     596    } 
     597 
     598    // type penalties for <5v5 teams 
     599    if(Type == ARENA_TEAM_2v2) 
     600        points *= 0.76f; 
     601    else if(Type == ARENA_TEAM_3v3) 
     602        points *= 0.88f; 
     603 
     604    return (uint32) points; 
     605} 
     606 
     607float ArenaTeam::GetChanceAgainst(uint32 rating) 
     608{ 
     609    // returns the chance to win against a team with the given rating, used in the rating adjustment calculation 
     610    // ELO system 
     611    return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)rating - (float)stats.rating)/400.0f)); 
     612} 
     613 
     614int32 ArenaTeam::WonAgainstChance(float chance) 
     615{ 
     616    // called when the team has won, and had 'chance' calculated chance to beat the opponent 
     617    // calculate the rating modification (ELO system with k=32) 
     618    int32 mod = (int32)floor(32.0f * (1.0f - chance)); 
     619    // modify the team stats accordingly 
     620    stats.rating += mod; 
     621    stats.games += 1; 
     622    stats.wins += 1; 
     623    stats.played += 1; 
     624    stats.wins2 += 1; 
     625/*  this should be done in .flusharenapoints; not a breaker though. 
     626    uint32 higher_rank = 0; 
     627    QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT(arenateamid) FROM arena_team_stats WHERE rating > '%u' AND arenateamid <> '%u'",stats.rating, Id); 
     628    if(result) 
     629    { 
     630        higher_rank = result->Fetch()->GetUInt32(); 
     631        delete result; 
     632    } 
     633    stats.rank = higher_rank + 1;*/ 
     634    // return the rating change, used to display it on the results screen 
     635    return mod; 
     636} 
     637 
     638int32 ArenaTeam::LostAgainstChance(float chance) 
     639{ 
     640    // called when the team has lost, and had 'chance' calculated chance to beat the opponent 
     641    // calculate the rating modification (ELO system with k=32) 
     642    int32 mod = (int32)ceil(32.0f * (0.0f - chance)); 
     643    // modify the team stats accordingly 
     644    stats.rating += mod; 
     645    stats.games += 1; 
     646    stats.played += 1; 
     647/*    uint32 higher_rank = 0; 
     648    QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT (arenateamid) FROM arena_team_stats WHERE rating > '%u' AND arenateamid <> '%u'",stats.rating, Id); 
     649    if(result) 
     650    { 
     651        higher_rank = result->Fetch()->GetUInt32(); 
     652        delete result; 
     653    } 
     654    stats.rank = higher_rank + 1;*/ 
     655    // return the rating adjustment for display 
     656    return mod; 
     657} 
     658 
     659void ArenaTeam::MemberLost(Player * plr, uint32 againstrating) 
     660{ 
     661    // called for each participant of a match after losing 
     662    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     663    { 
     664        if(itr->guid == plr->GetGUID()) 
     665        { 
     666            // update personal rating 
     667            int32 personalrating = plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5); 
     668            float chance = 1.0f/(1.0f+exp(log(10.0f)*(float)((float)againstrating - (float)personalrating)/400.0f)); 
     669            int32 mod = (int32)ceil(32.0f * (0.0f - chance)); 
     670            personalrating += mod; 
     671            if(personalrating < 0) 
     672                personalrating = 0; 
     673            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, personalrating); 
     674            // update personal played stats 
     675            itr->played_week +=1; 
     676            itr->played_season +=1; 
     677            // update the unit fields 
     678            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->played_week); 
     679            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->played_season); 
     680            return; 
     681        } 
     682    } 
     683} 
     684 
     685void ArenaTeam::MemberWon(Player * plr, uint32 againstrating) 
     686{ 
     687    // called for each participant after winning a match 
     688    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     689    { 
     690        if(itr->guid == plr->GetGUID()) 
     691        { 
     692            // update personal rating 
     693            int32 personalrating = plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5); 
     694            float chance = 1.0f/(1.0f+exp(log(10.0f)*(float)((float)againstrating - (float)personalrating)/400.0f)); 
     695            int32 mod = (int32)floor(32.0f * (1.0f - chance)); 
     696            personalrating += mod; 
     697            if(personalrating < 0) 
     698                personalrating = 0; 
     699            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, personalrating); 
     700            // update personal stats 
     701            itr->played_week +=1; 
     702            itr->played_season +=1; 
     703            itr->wons_season += 1; 
     704            itr->wons_week += 1; 
     705            // update unit fields 
     706            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->played_week); 
     707            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->played_season); 
     708            return; 
     709        } 
     710    } 
     711} 
     712 
     713void ArenaTeam::UpdateArenaPointsHelper() 
     714{ 
     715    // called after a match has ended and the stats are already modified 
     716    // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons) 
     717    // 10 played games per week is a minimum 
     718    if(stats.games < 10) 
     719        return; 
     720    // to get points, a player has to participate in at least 30% of the matches 
     721    uint32 min_plays = ceil(stats.games * 0.3); 
     722    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     723    { 
     724        // the player participated in enough games, update his points 
     725        if(itr->played_week >= min_plays) 
     726        { 
     727            // do it separately for online and offline players 
     728            // online players might have modified personal rating in MemberLost/MemberWon, that's not already saved to DB because of asynch queries 
     729            // offline player cant have a personal rating not matching the db 
     730            Player * plr = objmgr.GetPlayer(itr->guid); 
     731            uint32 points_to_add = 0; 
     732            if(plr) 
     733                points_to_add = GetPoints(plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5)); 
     734            else 
     735                points_to_add = GetPoints(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5,itr->guid)); 
     736            // it's enough to set the points in memory, the saving is done in separate function 
     737            CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid); 
     738        } 
     739        // the player failed to participate in enough games, so no points for him 
     740        else 
     741        { 
     742            CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", 0, Id, itr->guid); 
     743        } 
     744    } 
     745} 
     746 
     747void ArenaTeam::SaveToDB() 
     748{ 
     749    // save team and member stats to db 
     750    // called after a match has ended 
     751    CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games, stats.played, stats.rank, stats.wins, stats.wins2, GetId()); 
     752    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     753    { 
     754        CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->played_week, itr->wons_week, itr->played_season, itr->wons_season, Id, itr->guid); 
     755    } 
     756} 
     757 
     758void ArenaTeam::FinishWeek() 
     759{ 
     760    stats.games = 0; // played this week 
     761    stats.wins = 0; // wins this week 
     762    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     763    { 
     764        itr->played_week = 0; 
     765        itr->wons_week = 0; 
     766    } 
     767} 
     768 
    497769/* 
    498770arenateam fields (id from 2.3.3 client): 
    4997711414 - arena team id 2v2 
    5007721415 - 0=captain, 1=member 
    501 1416 - played this season 
    502 1417 - played this week 
     7731416 - played this week 
     7741417 - played this season 
    5037751418 - unk 
    504 1419 - unk 
     7761419 - personal arena rating 
    5057771420 - arena team id 3v3 
    5067781421 - 0=captain, 1=member 
    507 1422 - played this season 
    508 1423 - played this week 
     7791422 - played this week 
     7801423 - played this season 
    5097811424 - unk 
    510 1425 - unk 
     7821425 - personal arena rating 
    5117831426 - arena team id 5v5 
    5127841427 - 0=captain, 1=member 
    513 1428 - played this season 
    514 1429 - played this week 
     7851428 - played this week 
     7861429 - played this season 
    5157871430 - unk 
    516 1431 - unk 
     7881431 - personal arena rating 
    517789*/ 
  • trunk/src/game/ArenaTeam.h

    r2 r9  
    150150        void LoadPlayerStats(ArenaTeamMember* member); 
    151151 
     152        void SaveToDB(); 
     153 
    152154        void BroadcastPacket(WorldPacket *packet); 
    153155 
     
    156158        void Stats(WorldSession *session); 
    157159        void InspectStats(WorldSession *session, uint64 guid); 
     160 
     161        uint32 GetPoints(uint32 MemberRating); 
     162        float GetChanceAgainst(uint32 rating); 
     163        int32 WonAgainstChance(float chance); 
     164        void MemberWon(Player * plr, uint32 againstrating); 
     165        int32 LostAgainstChance(float chance); 
     166        void MemberLost(Player * plr, uint32 againstrating); 
     167 
     168        void UpdateArenaPointsHelper(); 
     169 
     170        void FinishWeek(); 
     171 
     172        void NotifyStatsChanged(); 
    158173 
    159174    protected: 
  • trunk/src/game/BattleGround.cpp

    r2 r9  
    2525#include "Chat.h" 
    2626#include "SpellAuras.h" 
     27#include "ArenaTeam.h" 
    2728#include "World.h" 
    2829#include "Util.h" 
     
    4849    m_LevelMin          = 0; 
    4950    m_LevelMax          = 0; 
     51    m_InBGFreeSlotQueue = false; 
     52    m_SetDeleteThis     = false; 
    5053 
    5154    m_MaxPlayersPerTeam = 0; 
     
    6871    m_TeamStartLocO[BG_TEAM_HORDE]      = 0; 
    6972 
     73    m_ArenaTeamIds[BG_TEAM_ALLIANCE]   = 0; 
     74    m_ArenaTeamIds[BG_TEAM_HORDE]      = 0; 
     75 
     76    m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE]   = 0; 
     77    m_ArenaTeamRatingChanges[BG_TEAM_HORDE]      = 0; 
     78 
    7079    m_BgRaids[BG_TEAM_ALLIANCE]         = NULL; 
    7180    m_BgRaids[BG_TEAM_HORDE]            = NULL; 
     
    7382    m_PlayersCount[BG_TEAM_ALLIANCE]    = 0; 
    7483    m_PlayersCount[BG_TEAM_HORDE]       = 0; 
     84 
     85    m_PrematureCountDown = false; 
     86    m_PrematureCountDown = 0; 
    7587} 
    7688 
    7789BattleGround::~BattleGround() 
    7890{ 
    79  
     91    // remove objects and creatures 
     92    // (this is done automatically in mapmanager update, when the instance is reset after the reset time)     
     93    int size = m_BgCreatures.size(); 
     94    for(int i = 0; i < size; ++i) 
     95    { 
     96        DelCreature(i); 
     97    } 
     98    size = m_BgObjects.size(); 
     99    for(int i = 0; i < size; ++i) 
     100    { 
     101        DelObject(i); 
     102    } 
     103 
     104    // delete creature and go respawn times 
     105    WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID()); 
     106    WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID()); 
     107    // delete instance from db 
     108    CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID()); 
     109    // remove from battlegrounds 
     110    sBattleGroundMgr.RemoveBattleGround(GetInstanceID()); 
     111    // unload map 
     112    if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID())) 
     113        if(map->IsBattleGroundOrArena()) 
     114            ((BattleGroundMap*)map)->SetUnload(); 
     115    // remove from bg free slot queue 
     116    this->RemoveFromBGFreeSlotQueue(); 
    80117} 
    81118 
    82119void BattleGround::Update(time_t diff) 
    83120{ 
    84  
    85121    if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) 
    86122        //BG is empty 
     
    189225    } 
    190226 
     227    // if less then minimum players are in on one side, then start premature finish timer 
     228    if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam())) 
     229    { 
     230        if(!m_PrematureCountDown) 
     231        { 
     232            m_PrematureCountDown = true; 
     233            m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime(); 
     234            SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); 
     235        } 
     236        else if(m_PrematureCountDownTimer < diff) 
     237        { 
     238            // time's up! 
     239            EndBattleGround(0); // noone wins 
     240            m_PrematureCountDown = false; 
     241        }  
     242        else  
     243        { 
     244            uint32 newtime = m_PrematureCountDownTimer - diff; 
     245            // announce every minute 
     246            if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000) 
     247                SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); 
     248            m_PrematureCountDownTimer = newtime; 
     249        } 
     250    } 
     251    else if (m_PrematureCountDown) 
     252        m_PrematureCountDown = false; 
     253 
    191254    if(GetStatus() == STATUS_WAIT_LEAVE) 
    192255    { 
     
    240303            continue; 
    241304 
    242         if(plr->GetTeam() == TeamID) 
     305        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 
     306 
     307        if(team == TeamID) 
    243308            plr->GetSession()->SendPacket(packet); 
    244309    } 
     
    266331        } 
    267332 
    268         if(plr->GetTeam() == TeamID) 
     333        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 
     334 
     335        if(team == TeamID) 
    269336        { 
    270337            sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID); 
     
    286353        } 
    287354 
    288         if(plr->GetTeam() == TeamID) 
     355        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 
     356        
     357        if(team == TeamID) 
    289358            plr->CastSpell(plr, SpellID, true); 
    290359    } 
     
    303372        } 
    304373 
    305         if(plr->GetTeam() == TeamID) 
     374        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 
     375 
     376        if(team == TeamID) 
    306377            UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor); 
    307378    } 
     
    325396        } 
    326397 
    327         if(plr->GetTeam() == TeamID) 
     398        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 
     399 
     400        if(team == TeamID) 
    328401            plr->ModifyFactionReputation(factionEntry, Reputation); 
    329402    } 
     
    346419void BattleGround::EndBattleGround(uint32 winner) 
    347420{ 
     421    // battleground finished, remove from the running bg's list 
     422    this->RemoveFromBGFreeSlotQueue(); 
     423 
     424    ArenaTeam * winner_arena_team = NULL; 
     425    ArenaTeam * loser_arena_team = NULL; 
     426    uint32 loser_rating = 0; 
     427    uint32 winner_rating = 0; 
    348428    WorldPacket data; 
    349429    Player *Source = NULL; 
     
    352432    if(winner == ALLIANCE) 
    353433    { 
    354         winmsg = GetMangosString(LANG_BG_A_WINS); 
     434        if(isBattleGround()) 
     435            winmsg = GetMangosString(LANG_BG_A_WINS); 
     436        else 
     437            winmsg = GetMangosString(LANG_ARENA_GOLD_WINS); 
    355438 
    356439        PlaySoundToAll(SOUND_ALLIANCE_WINS);                // alliance wins sound 
     
    358441        SetWinner(WINNER_ALLIANCE); 
    359442    } 
     443    else if(winner == HORDE) 
     444    { 
     445        if(isBattleGround()) 
     446            winmsg = GetMangosString(LANG_BG_H_WINS); 
     447        else 
     448            winmsg = GetMangosString(LANG_ARENA_GREEN_WINS); 
     449 
     450        PlaySoundToAll(SOUND_HORDE_WINS);                   // horde wins sound 
     451 
     452        SetWinner(WINNER_HORDE); 
     453    } 
    360454    else 
    361455    { 
    362         winmsg = GetMangosString(LANG_BG_H_WINS); 
    363  
    364         PlaySoundToAll(SOUND_HORDE_WINS);                   // horde wins sound 
    365  
    366         SetWinner(WINNER_HORDE); 
     456        SetWinner(3); 
    367457    } 
    368458 
     
    370460    m_EndTime = 0; 
    371461 
     462    // arena rating calculation 
     463    if(isArena() && isRated()) 
     464    { 
     465        if(winner == ALLIANCE) 
     466        { 
     467            winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 
     468            loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 
     469        } 
     470        else if(winner == HORDE) 
     471        { 
     472            winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 
     473            loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 
     474        } 
     475        if(winner_arena_team && loser_arena_team) 
     476        { 
     477            loser_rating = loser_arena_team->GetStats().rating; 
     478            winner_rating = winner_arena_team->GetStats().rating; 
     479            float winner_chance = winner_arena_team->GetChanceAgainst(loser_rating); 
     480            float loser_chance = loser_arena_team->GetChanceAgainst(winner_rating); 
     481            int32 winner_change = winner_arena_team->WonAgainstChance(winner_chance); 
     482            int32 loser_change = loser_arena_team->LostAgainstChance(loser_chance); 
     483            sLog.outDebug("--- %u ; %u ; %d ; %d ; %u ; %u ---",winner_rating,loser_rating,winner_chance,loser_chance,winner_change,loser_change); 
     484            if(winner == ALLIANCE) 
     485            { 
     486                SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change); 
     487                SetArenaTeamRatingChangeForTeam(HORDE, loser_change); 
     488            } 
     489            else 
     490            { 
     491                SetArenaTeamRatingChangeForTeam(HORDE, winner_change); 
     492                SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change); 
     493            } 
     494        } 
     495        else 
     496        { 
     497            SetArenaTeamRatingChangeForTeam(ALLIANCE, 0); 
     498            SetArenaTeamRatingChangeForTeam(HORDE, 0); 
     499        } 
     500    } 
     501 
    372502    for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) 
    373503    { 
     
    379509        } 
    380510 
     511        // should remove spirit of redemption 
     512        if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) 
     513            plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); 
     514 
    381515        if(!plr->isAlive()) 
    382516        { 
     
    385519        } 
    386520 
    387         if(plr->GetTeam() == winner) 
     521        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 
     522        if(!team) team = plr->GetTeam(); 
     523 
     524        // per player calculation 
     525        if(isArena() && isRated() && winner_arena_team && loser_arena_team) 
     526        { 
     527            if(team == winner) 
     528                winner_arena_team->MemberWon(plr,loser_rating); 
     529            else 
     530                loser_arena_team->MemberLost(plr,winner_rating); 
     531        } 
     532 
     533        if(team == winner) 
    388534        { 
    389535            if(!Source) 
     
    405551        plr->GetSession()->SendPacket(&data); 
    406552 
    407         sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); 
     553        uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); 
     554        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); 
    408555        plr->GetSession()->SendPacket(&data); 
    409556    } 
     557 
     558    if(isArena() && isRated() && winner_arena_team && loser_arena_team) 
     559    { 
     560        // update arena points only after increasing the player's match count! 
     561        winner_arena_team->UpdateArenaPointsHelper(); 
     562        loser_arena_team->UpdateArenaPointsHelper(); 
     563        // save the stat changes 
     564        winner_arena_team->SaveToDB(); 
     565        loser_arena_team->SaveToDB(); 
     566        // send updated arena team stats to players 
     567        // this way all arena team members will get notified, not only the ones who participated in this match 
     568        winner_arena_team->NotifyStatsChanged(); 
     569        loser_arena_team->NotifyStatsChanged(); 
     570    } 
     571 
     572    // inform invited players about the removal 
     573    sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); 
    410574 
    411575    if(Source) 
     
    559723void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) 
    560724{ 
     725    uint32 team = GetPlayerTeam(guid); 
     726    bool participant = false; 
    561727    // Remove from lists/maps 
    562728    std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid); 
    563729    if(itr != m_Players.end()) 
    564730    { 
    565         UpdatePlayersCountByTeam(itr->second.Team, true);   // -1 player 
     731        UpdatePlayersCountByTeam(team, true);   // -1 player 
    566732        m_Players.erase(itr); 
     733        // check if the player was a participant of the match, or only entered through gm command (goname) 
     734        participant = true; 
    567735    } 
    568736 
     
    578746    Player *plr = objmgr.GetPlayer(guid); 
    579747 
     748    // should remove spirit of redemption 
     749    if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) 
     750        plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); 
     751 
    580752    if(plr && !plr->isAlive())                              // resurrect on exit 
    581753    { 
     
    590762        plr->ClearAfkReports(); 
    591763 
    592         if(isArena()) 
    593         { 
    594             if(!sWorld.IsFFAPvPRealm()) 
    595                 plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); 
    596         } 
    597  
    598         WorldPacket data; 
    599         if(SendPacket) 
    600         { 
    601             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); 
    602             plr->GetSession()->SendPacket(&data); 
    603         } 
    604  
    605         // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg 
    606         plr->RemoveBattleGroundQueueId(m_TypeID); 
    607  
    608         DecreaseInvitedCount(plr->GetTeam()); 
    609         //we should update battleground queue, but only if bg isn't ending 
    610         if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) 
    611             sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType()); 
    612  
    613         if(!plr->GetBattleGroundId()) 
    614             return; 
    615  
    616         Group * group = plr->GetGroup(); 
    617  
    618         // remove from raid group if exist 
    619         if(group && group == GetBgRaid(plr->GetTeam())) 
    620         { 
    621             if(!group->RemoveMember(guid, 0))               // group was disbanded 
     764        if(participant) // if the player was a match participant, remove auras, calc rating, update queue 
     765        { 
     766            if(!team) team = plr->GetTeam(); 
     767 
     768            uint32 bgTypeId = GetTypeID(); 
     769            uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); 
     770            // if arena, remove the specific arena auras 
     771            if(isArena()) 
    622772            { 
    623                 SetBgRaid(plr->GetTeam(), NULL); 
    624                 delete group; 
     773                plr->RemoveArenaAuras(true);    // removes debuffs / dots etc., we don't want the player to die after porting out 
     774                bgTypeId=BATTLEGROUND_AA;       // set the bg type to all arenas (it will be used for queue refreshing) 
     775 
     776                // summon old pet if there was one and there isn't a current pet 
     777                if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber()) 
     778                { 
     779                    Pet* NewPet = new Pet; 
     780                    if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true)) 
     781                        delete NewPet; 
     782 
     783                    (plr)->SetTemporaryUnsummonedPetNumber(0); 
     784                } 
     785 
     786                if(isRated() && GetStatus() == STATUS_IN_PROGRESS) 
     787                { 
     788                    //left a rated match while the encounter was in progress, consider as loser 
     789                    ArenaTeam * winner_arena_team = 0; 
     790                    ArenaTeam * loser_arena_team = 0; 
     791                    if(team == HORDE) 
     792                    { 
     793                        winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 
     794                        loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 
     795                    } 
     796                    else 
     797                    { 
     798                        winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 
     799                        loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 
     800                    } 
     801                    if(winner_arena_team && loser_arena_team) 
     802                    { 
     803                        loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); 
     804                    } 
     805                } 
    625806            } 
     807 
     808            WorldPacket data; 
     809            if(SendPacket) 
     810            { 
     811                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); 
     812                plr->GetSession()->SendPacket(&data); 
     813            } 
     814 
     815            // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg 
     816            plr->RemoveBattleGroundQueueId(bgQueueTypeId); 
     817 
     818            DecreaseInvitedCount(team); 
     819            //we should update battleground queue, but only if bg isn't ending 
     820            if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) 
     821                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType()); 
     822 
     823            Group * group = plr->GetGroup(); 
     824            // remove from raid group if exist 
     825            if(group && group == GetBgRaid(team)) 
     826            { 
     827                if(!group->RemoveMember(guid, 0))               // group was disbanded 
     828                { 
     829                    SetBgRaid(team, NULL); 
     830                    delete group; 
     831                } 
     832            } 
     833 
     834            // Let others know 
     835            sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); 
     836            SendPacketToTeam(team, &data, plr, false); 
    626837        } 
    627838 
    628839        // Do next only if found in battleground 
    629840        plr->SetBattleGroundId(0);                          // We're not in BG. 
    630  
    631         // Let others know 
    632         sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); 
    633         SendPacketToTeam(plr->GetTeam(), &data, plr, false); 
     841        // reset destination bg team 
     842        plr->SetBGTeam(0); 
    634843 
    635844        if(Transport) 
    636845        { 
    637846            plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); 
    638             //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); 
    639847        } 
    640848 
     
    643851    } 
    644852 
    645     /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist 
    646     // we always should check if BG is in that queue before adding.. 
    647  
    648     if(!GetPlayersSize()) 
    649     { 
    650         Reset(); 
    651     } 
     853    if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE)) 
     854    { 
     855        // if no players left AND no invitees left, set this bg to delete in next update 
     856        // direct deletion could cause crashes 
     857        m_SetDeleteThis = true; 
     858        // return to prevent addition to freeslotqueue 
     859        return; 
     860    } 
     861 
     862    // a player exited the battleground, so there are free slots. add to queue 
     863    this->AddToBGFreeSlotQueue(); 
    652864} 
    653865 
     
    661873    SetEndTime(0); 
    662874    SetLastResurrectTime(0); 
     875    SetArenaType(0); 
     876    SetRated(false); 
    663877 
    664878    m_Events = 0; 
     
    669883    m_InvitedAlliance = 0; 
    670884    m_InvitedHorde = 0; 
     885    m_InBGFreeSlotQueue = false; 
    671886 
    672887    m_Players.clear(); 
    673888    m_PlayerScores.clear(); 
    674889 
    675     // reset BGSubclass 
     890    // reset BGSubclass (this cleans up creatures and gos as well) 
    676891    this->ResetBGSubclass(); 
    677892} 
     
    699914    m_Players[guid] = bp; 
    700915 
    701     UpdatePlayersCountByTeam(team, false);                  // +1 player 
     916    UpdatePlayersCountByTeam(team, false);        // +1 player 
    702917 
    703918    WorldPacket data; 
     
    705920    SendPacketToTeam(team, &data, plr, false); 
    706921 
     922    // add arena specific auras 
    707923    if(isArena()) 
    708924    { 
     925        // remove auras first, only then reset spell cooldowns 
     926        // this is to prevent bugging amp. curse, combustion, etc. like spells 
     927        plr->RemoveArenaAuras(); 
    709928        plr->RemoveArenaSpellCooldowns(); 
    710         //plr->RemoveArenaAuras(); 
    711929        plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT); 
    712930        if(team == ALLIANCE && plr->GetTeam() == ALLIANCE) 
     
    720938        plr->DestroyConjuredItems(true); 
    721939 
     940        Pet* pet = plr->GetPet(); 
     941        if(pet) 
     942        { 
     943            if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET) 
     944            { 
     945                (plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber()); 
     946                (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); 
     947            } 
     948            (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); 
     949        } 
     950 
    722951        if(GetStatus() == STATUS_WAIT_JOIN)                 // not started yet 
    723952        { 
     
    734963    } 
    735964 
    736     if(isArena()) 
    737         plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); 
    738  
    739965    // Log 
    740966    sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName()); 
     
    744970void BattleGround::AddToBGFreeSlotQueue() 
    745971{ 
    746     sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); 
     972    // make sure to add only once 
     973    if(!m_InBGFreeSlotQueue) 
     974    { 
     975        sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); 
     976        m_InBGFreeSlotQueue = true; 
     977    } 
    747978} 
    748979 
     
    750981void BattleGround::RemoveFromBGFreeSlotQueue() 
    751982{ 
    752     /* uncomment this code when battlegrounds will work like instances 
     983    // set to be able to re-add if needed 
     984    m_InBGFreeSlotQueue = false; 
     985    // uncomment this code when battlegrounds will work like instances 
    753986    for (std::deque<BattleGround*>::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) 
    754987    { 
     
    758991            return; 
    759992        } 
    760     }*/ 
    761 } 
    762  
    763 /* 
    764 this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS 
    765 */ 
    766 bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const 
     993    } 
     994} 
     995 
     996// get the number of free slots for team 
     997// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group 
     998uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const 
    767999{ 
    7681000    //if BG is starting ... invite anyone: 
    7691001    if (GetStatus() == STATUS_WAIT_JOIN) 
    770         return GetInvitedCount(Team) < GetMaxPlayersPerTeam(); 
     1002        return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; 
    7711003    //if BG is already started .. do not allow to join too much players of one faction 
    7721004    uint32 otherTeam; 
     1005    uint32 otherIn; 
    7731006    if (Team == ALLIANCE) 
     1007    { 
    7741008        otherTeam = GetInvitedCount(HORDE); 
     1009        otherIn = GetPlayersCountByTeam(HORDE); 
     1010    } 
    7751011    else 
     1012    { 
    7761013        otherTeam = GetInvitedCount(ALLIANCE); 
     1014        otherIn = GetPlayersCountByTeam(ALLIANCE); 
     1015    } 
    7771016    if (GetStatus() == STATUS_IN_PROGRESS) 
    778         return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam()); 
    779  
    780     return false; 
    781 } 
    782  
    783 /* this method isn't called already, it will be useful when more battlegrounds of one type will be available */ 
     1017    { 
     1018        // difference based on ppl invited (not necessarily entered battle) 
     1019        // default: allow 0 
     1020        uint32 diff = 0; 
     1021        // allow join one person if the sides are equal (to fill up bg to minplayersperteam) 
     1022        if (otherTeam == GetInvitedCount(Team))  
     1023            diff = 1; 
     1024        // allow join more ppl if the other side has more players 
     1025        else if(otherTeam > GetInvitedCount(Team)) 
     1026            diff = otherTeam - GetInvitedCount(Team); 
     1027 
     1028        // difference based on max players per team (don't allow inviting more) 
     1029        uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; 
     1030 
     1031        // difference based on players who already entered 
     1032        // default: allow 0 
     1033        uint32 diff3 = 0; 
     1034        // allow join one person if the sides are equal (to fill up bg minplayersperteam) 
     1035        if (otherIn == GetPlayersCountByTeam(Team)) 
     1036            diff3 = 1; 
     1037        // allow join more ppl if the other side has more players 
     1038        else if (otherIn > GetPlayersCountByTeam(Team)) 
     1039            diff3 = otherIn - GetPlayersCountByTeam(Team); 
     1040 
     1041        // return the minimum of the 3 differences 
     1042 
     1043        // min of diff and diff 2 
     1044        diff = diff < diff2 ? diff : diff2; 
     1045 
     1046        // min of diff, diff2 and diff3 
     1047        return diff < diff3 ? diff : diff3 ; 
     1048    } 
     1049 
     1050    return 0; 
     1051} 
     1052 
    7841053bool BattleGround::HasFreeSlots() const 
    7851054{ 
     
    8071076            break; 
    8081077        case SCORE_BONUS_HONOR:                             // Honor bonus 
    809             // reward honor instantly 
    810             if(Source->RewardHonor(NULL, 1, value)) 
    811                 itr->second->BonusHonor += value; 
     1078            // do not add honor in arenas 
     1079            if(isBattleGround()) 
     1080            { 
     1081                // reward honor instantly 
     1082                if(Source->RewardHonor(NULL, 1, value)) 
     1083                    itr->second->BonusHonor += value; 
     1084            } 
    8121085            break; 
    8131086            //used only in EY, but in MSG_PVP_LOG_DATA opcode 
     
    8651138bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime) 
    8661139{ 
    867     GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); 
    868     if(!goinfo) 
     1140    Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); 
     1141    if(!map) 
     1142        return false; 
     1143 
     1144    // must be created this way, adding to godatamap would add it to the base map of the instance 
     1145    // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created 
     1146    // so we must create it specific for this instance 
     1147    GameObject * go = new GameObject; 
     1148    if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) 
    8691149    { 
    8701150        sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); 
     1151        sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); 
     1152        delete go; 
    8711153        return false; 
    8721154    } 
    873  
    874     uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); 
    875  
     1155/* 
     1156    uint32 guid = go->GetGUIDLow(); 
     1157 
     1158    // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata 
     1159    // iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed 
    8761160    GameObjectData& data = objmgr.NewGOData(guid); 
    8771161 
     
    8871171    data.rotation3      = rotation3; 
    8881172    data.spawntimesecs  = respawnTime; 
     1173    data.spawnMask      = 1; 
    8891174    data.animprogress   = 100; 
    8901175    data.go_state       = 1; 
    891     data.spawnMask      = 1; 
    892     objmgr.AddGameobjectToGrid(guid, &data); 
    893  
    894     m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT); 
    895  
     1176*/ 
     1177    // add to world, so it can be later looked up from HashMapHolder 
     1178    go->AddToWorld(); 
     1179    m_BgObjects[type] = go->GetGUID(); 
    8961180    return true; 
    8971181} 
     
    9351219void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) 
    9361220{ 
     1221    Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); 
     1222    if(!map) 
     1223        return; 
    9371224    if( respawntime == 0 ) 
    9381225    { 
     
    9431230            if( obj->getLootState() == GO_JUST_DEACTIVATED ) 
    9441231                obj->SetLootState(GO_READY); 
    945             obj->Respawn(); 
    946         } 
    947         else 
    948             objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0); 
     1232            obj->SetRespawnTime(0); 
     1233            map->Add(obj); 
     1234        } 
    9491235    } 
    9501236    else 
     
    9531239        if(obj) 
    9541240        { 
     1241            map->Add(obj); 
    9551242            obj->SetRespawnTime(respawntime); 
    9561243            obj->SetLootState(GO_JUST_DEACTIVATED); 
    9571244        } 
    958         else 
    959             objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime); 
    960     } 
    961 } 
    962  
    963 Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o) 
    964 { 
    965     // note: this should normally be FindMap 
    966     // but it's a hack to allow the battlegrounds to initialize at server startup 
    967     Map * map = MapManager::Instance().GetMap(GetMapId(), 0); 
    968     if(!map) return NULL; 
     1245    } 
     1246} 
     1247 
     1248Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) 
     1249{ 
     1250    Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); 
     1251    if(!map) 
     1252        return NULL; 
    9691253 
    9701254    Creature* pCreature = new Creature; 
     
    9901274    map->Add(pCreature); 
    9911275    m_BgCreatures[type] = pCreature->GetGUID(); 
     1276 
    9921277    return  pCreature; 
    9931278} 
     
    10731358void BattleGround::EndNow() 
    10741359{ 
     1360    RemoveFromBGFreeSlotQueue(); 
    10751361    SetStatus(STATUS_WAIT_LEAVE); 
    10761362    SetEndTime(TIME_TO_AUTOREMOVE); 
     1363    // inform invited players about the removal 
     1364    sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); 
    10771365} 
    10781366 
     
    11521440    player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE ); 
    11531441} 
     1442 
     1443// return the player's team based on battlegroundplayer info 
     1444// used in same faction arena matches mainly 
     1445uint32 BattleGround::GetPlayerTeam(uint64 guid) 
     1446{ 
     1447    std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid); 
     1448    if(itr!=m_Players.end()) 
     1449        return itr->second.Team; 
     1450    return 0; 
     1451} 
     1452 
     1453uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const 
     1454{ 
     1455    int count = 0; 
     1456    for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) 
     1457    { 
     1458        if(itr->second.Team == Team) 
     1459        { 
     1460            Player * pl = objmgr.GetPlayer(itr->first); 
     1461            if(pl && pl->isAlive()) 
     1462                ++count; 
     1463        } 
     1464    } 
     1465    return count; 
     1466} 
  • trunk/src/game/BattleGround.h

    r2 r9  
    142142    BATTLEGROUND_EY     = 7, 
    143143    BATTLEGROUND_RL     = 8 
     144}; 
     145 
     146// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time 
     147enum BattleGroundQueueTypeId 
     148{ 
     149    BATTLEGROUND_QUEUE_AV     = 1, 
     150    BATTLEGROUND_QUEUE_WS     = 2, 
     151    BATTLEGROUND_QUEUE_AB     = 3, 
     152    BATTLEGROUND_QUEUE_EY     = 4, 
     153    BATTLEGROUND_QUEUE_2v2     = 5, 
     154    BATTLEGROUND_QUEUE_3v3     = 6, 
     155    BATTLEGROUND_QUEUE_5v5     = 7, 
    144156}; 
    145157 
     
    196208}; 
    197209 
     210enum BattleGroundJoinError 
     211{ 
     212    BG_JOIN_ERR_OK = 0, 
     213    BG_JOIN_ERR_OFFLINE_MEMBER = 1, 
     214    BG_JOIN_ERR_GROUP_TOO_MANY = 2, 
     215    BG_JOIN_ERR_MIXED_FACTION = 3, 
     216    BG_JOIN_ERR_MIXED_LEVELS = 4, 
     217    BG_JOIN_ERR_MIXED_ARENATEAM = 5, 
     218    BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE = 6, 
     219    BG_JOIN_ERR_GROUP_DESERTER = 7, 
     220    BG_JOIN_ERR_ALL_QUEUES_USED = 8, 
     221    BG_JOIN_ERR_GROUP_NOT_ENOUGH = 9 
     222}; 
     223 
    198224class BattleGroundScore 
    199225{ 
     
    297323        bool HasFreeSlotsForTeam(uint32 Team) const; 
    298324        bool HasFreeSlots() const; 
     325        uint32 GetFreeSlotsForTeam(uint32 Team) const; 
    299326 
    300327        bool isArena() const        { return m_IsArena; } 
     
    367394        uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } 
    368395        uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; } 
     396        uint32 GetAlivePlayersCountByTeam(uint32 Team) const;   // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases 
    369397        void UpdatePlayersCountByTeam(uint32 Team, bool remove) 
    370398        { 
     
    375403        } 
    376404 
     405        // used for rated arena battles 
     406        void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; } 
     407        uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } 
     408        void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; } 
     409        int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } 
     410 
    377411        /* Triggers handle */ 
    378412        // must be implemented in BG subclass 
     
    391425 
    392426        virtual void AddPlayer(Player *plr);                // must be implemented in BG subclass 
     427 
    393428        virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); 
    394429                                                            // can be extended in in BG subclass 
     
    403438        void SpawnBGObject(uint32 type, uint32 respawntime); 
    404439        bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); 
    405         Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o); 
     440//        void SpawnBGCreature(uint32 type, uint32 respawntime); 
     441        Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0); 
    406442        bool DelCreature(uint32 type); 
    407443        bool DelObject(uint32 type); 
     
    411447        void DoorClose(uint32 type); 
    412448        const char *GetMangosString(int32 entry); 
     449 
     450        virtual bool HandlePlayerUnderMap(Player * plr) {return false;} 
     451 
     452        // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player 
     453        uint32 GetPlayerTeam(uint64 guid); 
     454 
     455        void SetDeleteThis() {m_SetDeleteThis = true;} 
    413456 
    414457    protected: 
     
    444487        uint32 m_Queue_type; 
    445488        uint8  m_ArenaType;                                 // 2=2v2, 3=3v3, 5=5v5 
     489        bool   m_InBGFreeSlotQueue;                         // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque 
     490        bool   m_SetDeleteThis;                             // used for safe deletion of the bg after end / all players leave 
    446491        // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless 
    447492        //uint8  m_BattleGroundType;                        // 3=BG, 4=arena 
     
    451496        int32  m_StartDelayTime; 
    452497        bool   m_IsRated;                                   // is this battle rated? 
     498        bool   m_PrematureCountDown; 
     499        uint32 m_PrematureCountDownTimer; 
    453500        char const *m_Name; 
    454501 
     
    468515        /* Players count by team */ 
    469516        uint32 m_PlayersCount[2]; 
     517 
     518        /* Arena team ids by team */ 
     519        uint32 m_ArenaTeamIds[2]; 
     520 
     521        int32 m_ArenaTeamRatingChanges[2]; 
    470522 
    471523        /* Limits */ 
  • trunk/src/game/BattleGroundAB.cpp

    r2 r9  
    5050        { 
    5151            m_Events |= 0x01; 
     52 
     53            // setup here, only when at least one player has ported to the map 
     54            if(!SetupBattleGround()) 
     55            { 
     56                EndNow(); 
     57                return; 
     58            } 
    5259 
    5360            sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ..."); 
  • trunk/src/game/BattleGroundBE.cpp

    r2 r9  
    4848        { 
    4949            m_Events |= 0x01; 
     50            // setup here, only when at least one player has ported to the map 
     51            if(!SetupBattleGround()) 
     52            { 
     53                EndNow(); 
     54                return; 
     55            } 
    5056            for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) 
    5157                SpawnBGObject(i, RESPAWN_IMMEDIATELY); 
     
    8793                if(Player *plr = objmgr.GetPlayer(itr->first)) 
    8894                    plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); 
     95 
     96            if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 
     97                EndBattleGround(HORDE); 
     98            else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) 
     99                EndBattleGround(ALLIANCE); 
    89100        } 
    90101    } 
     
    103114 
    104115    m_PlayerScores[plr->GetGUID()] = sc; 
     116 
     117    UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); 
     118    UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); 
    105119} 
    106120 
    107121void BattleGroundBE::RemovePlayer(Player *plr, uint64 guid) 
    108122{ 
    109  
     123    if(GetStatus() == STATUS_WAIT_LEAVE) 
     124        return; 
     125 
     126    UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); 
     127    UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); 
     128 
     129    if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 
     130        EndBattleGround(HORDE); 
     131    else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) 
     132        EndBattleGround(ALLIANCE); 
    110133} 
    111134 
     
    121144    } 
    122145 
    123     BattleGround::HandleKillPlayer(player, killer); 
    124  
    125     uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); 
    126  
    127     ++m_TeamKills[killer_team_index];                       // add kills to killer's team 
    128  
    129     if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) 
     146    BattleGround::HandleKillPlayer(player,killer); 
     147 
     148    UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); 
     149    UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); 
     150 
     151    if(!GetAlivePlayersCountByTeam(ALLIANCE)) 
    130152    { 
    131153        // all opponents killed 
    132         EndBattleGround(killer->GetTeam()); 
    133     } 
     154        EndBattleGround(HORDE); 
     155    } 
     156    else if(!GetAlivePlayersCountByTeam(HORDE)) 
     157    { 
     158        // all opponents killed 
     159        EndBattleGround(ALLIANCE); 
     160    } 
     161} 
     162 
     163bool BattleGroundBE::HandlePlayerUnderMap(Player *player) 
     164{ 
     165    player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false); 
     166    return true; 
    134167} 
    135168 
     
    160193} 
    161194 
     195void BattleGroundBE::FillInitialWorldStates(WorldPacket &data) 
     196{ 
     197    data << uint32(0x9f1) << uint32(GetAlivePlayersCountByTeam(ALLIANCE));           // 7 
     198    data << uint32(0x9f0) << uint32(GetAlivePlayersCountByTeam(HORDE));           // 8 
     199    data << uint32(0x9f3) << uint32(1);           // 9 
     200} 
     201 
    162202void BattleGroundBE::ResetBGSubclass() 
    163203{ 
    164     m_TeamKills[BG_TEAM_ALLIANCE] = 0; 
    165     m_TeamKills[BG_TEAM_HORDE]    = 0; 
     204 
    166205} 
    167206 
  • trunk/src/game/BattleGroundBE.h

    r2 r9  
    6565        bool SetupBattleGround(); 
    6666        void ResetBGSubclass(); 
     67        virtual void FillInitialWorldStates(WorldPacket &d); 
    6768        void HandleKillPlayer(Player* player, Player *killer); 
     69        bool HandlePlayerUnderMap(Player * plr); 
    6870 
    6971        /* Scorekeeping */ 
    7072        void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); 
    71  
    72     private: 
    73         uint32 m_TeamKills[2];                              // count of kills for each team 
    7473}; 
    7574#endif 
  • trunk/src/game/BattleGroundEY.cpp

    r2 r9  
    5454        { 
    5555            m_Events |= 0x01; 
     56 
     57            // setup here, only when at least one player has ported to the map 
     58            if(!SetupBattleGround()) 
     59            { 
     60                EndNow(); 
     61                return; 
     62            } 
    5663 
    5764            SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); 
     
    573580void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) 
    574581{ 
    575     // Drop allowed in any BG state 
     582    if(GetStatus() != STATUS_IN_PROGRESS) 
     583    { 
     584        // if not running, do not cast things at the dropper player, neither send unnecessary messages 
     585        // just take off the aura 
     586        if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID()) 
     587        { 
     588            SetFlagPicker(0); 
     589            Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); 
     590        } 
     591        return; 
     592    } 
    576593 
    577594    if(!IsFlagPickedup()) 
  • 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} 
  • trunk/src/game/BattleGroundMgr.cpp

    r2 r9  
    3131#include "Policies/SingletonImp.h" 
    3232#include "MapManager.h" 
     33#include "Map.h" 
     34#include "MapInstanced.h" 
    3335#include "ObjectMgr.h" 
    3436#include "ProgressBar.h" 
    3537#include "World.h" 
     38#include "ArenaTeam.h" 
    3639#include "Chat.h" 
    3740 
     
    4548{ 
    4649    //queues are empty, we don't have to call clear() 
     50/*    for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 
     51    { 
     52        //m_QueuedPlayers[i].Horde = 0; 
     53        //m_QueuedPlayers[i].Alliance = 0; 
     54        //m_QueuedPlayers[i].AverageTime = 0; 
     55    }*/ 
     56} 
     57 
     58BattleGroundQueue::~BattleGroundQueue() 
     59{ 
    4760    for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 
    4861    { 
    49         m_QueuedPlayers[i].Horde = 0; 
    50         m_QueuedPlayers[i].Alliance = 0; 
    51         //m_QueuedPlayers[i].AverageTime = 0; 
    52     } 
    53 } 
    54  
    55 BattleGroundQueue::~BattleGroundQueue() 
    56 { 
    57     for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 
    58     { 
    5962        m_QueuedPlayers[i].clear(); 
    60     } 
    61 } 
    62  
    63 void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) 
     63        for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr) 
     64        { 
     65            delete (*itr); 
     66        } 
     67        m_QueuedGroups[i].clear(); 
     68    } 
     69} 
     70 
     71// initialize eligible groups from the given source matching the given specifications 
     72void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) 
     73{ 
     74    // clear from prev initialization 
     75    clear(); 
     76    BattleGroundQueue::QueuedGroupsList::iterator itr, next; 
     77    // iterate through the source 
     78    for(itr = source->begin(); itr!= source->end(); itr = next) 
     79    { 
     80        next = itr; 
     81        ++next; 
     82        if( (*itr)->BgTypeId == BgTypeId &&     // bg type must match 
     83            (*itr)->ArenaType == ArenaType &&   // arena type must match 
     84            (*itr)->IsRated == IsRated &&       // israted must match 
     85            (*itr)->IsInvitedToBGInstanceGUID == 0 && // leave out already invited groups 
     86            (*itr)->Team == side &&             // match side 
     87            (*itr)->Players.size() <= MaxPlayers &&   // the group must fit in the bg 
     88            ( !excludeTeam || (*itr)->ArenaTeamId != excludeTeam ) && // if excludeTeam is specified, leave out those arena team ids 
     89            ( !IsRated || (*itr)->Players.size() == MaxPlayers ) &&   // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen) 
     90            (  (*itr)->JoinTime <= DisregardTime              // pass if disregard time is greater than join time 
     91               || (*itr)->ArenaTeamRating == 0                 // pass if no rating info 
     92               || ( (*itr)->ArenaTeamRating >= MinRating       // pass if matches the rating range 
     93                     && (*itr)->ArenaTeamRating <= MaxRating ) ) )    
     94        { 
     95            // the group matches the conditions 
     96            // insert it in order of groupsize, and join time 
     97            uint32 size = (*itr)->Players.size(); 
     98            uint32 jointime = (*itr)->JoinTime; 
     99            bool inserted = false; 
     100 
     101            for(std::list<GroupQueueInfo *>::iterator elig_itr = begin(); elig_itr != end(); ++elig_itr) 
     102            { 
     103                // if the next one's size is smaller, then insert 
     104                // also insert if the next one's size is equal, but it joined the queue later 
     105                if( ((*elig_itr)->Players.size()<size) || 
     106                    ((*elig_itr)->Players.size() == size && (*elig_itr)->JoinTime > jointime) ) 
     107                { 
     108                    insert(elig_itr,(*itr)); 
     109                    inserted = true; 
     110                    break; 
     111                } 
     112            } 
     113            // if not inserted -> this is the smallest group -> push_back 
     114            if(!inserted) 
     115            { 
     116                push_back((*itr)); 
     117            } 
     118        } 
     119    } 
     120} 
     121 
     122// remove group from eligible groups 
     123// used when building selection pools 
     124void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo) 
     125{ 
     126    for(std::list<GroupQueueInfo *>::iterator itr = begin(); itr != end(); ++itr) 
     127    { 
     128        if((*itr)==ginfo) 
     129        { 
     130            erase(itr); 
     131            return; 
     132        } 
     133    } 
     134} 
     135 
     136// selection pool initialization, used to clean up from prev selection 
     137void BattleGroundQueue::SelectionPool::Init() 
     138{ 
     139    SelectedGroups.clear(); 
     140    MaxGroup = 0; 
     141    PlayerCount = 0; 
     142} 
     143 
     144// get the maximal group from the selection pool 
     145// used when building the pool, and have to remove the largest 
     146GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup() 
     147{ 
     148    if(SelectedGroups.empty()) 
     149    { 
     150        sLog.outError("Getting max group when selection pool is empty, this should never happen."); 
     151        MaxGroup = NULL; 
     152        return 0; 
     153    } 
     154    // actually select the max group if it's not set 
     155    if(MaxGroup==0 && !SelectedGroups.empty()) 
     156    { 
     157        uint32 max_size = 0; 
     158        for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) 
     159        { 
     160            if(max_size<(*itr)->Players.size()) 
     161            { 
     162                MaxGroup =(*itr); 
     163                max_size = MaxGroup->Players.size(); 
     164            } 
     165        } 
     166    } 
     167    return MaxGroup; 
     168} 
     169 
     170// remove group info from selection pool 
     171// used when building selection pools and have to remove maximal group 
     172void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo) 
     173{ 
     174    // uninitiate max group info if needed 
     175    if(MaxGroup == ginfo) 
     176        MaxGroup = 0; 
     177    // find what to remove 
     178    for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) 
     179    { 
     180        if((*itr)==ginfo) 
     181        { 
     182            SelectedGroups.erase(itr); 
     183            // decrease selected players count 
     184            PlayerCount -= ginfo->Players.size(); 
     185            return; 
     186        } 
     187    } 
     188} 
     189 
     190// add group to selection 
     191// used when building selection pools 
     192void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo) 
     193{ 
     194    SelectedGroups.push_back(ginfo); 
     195    // increase selected players count 
     196    PlayerCount+=ginfo->Players.size(); 
     197    if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size()) 
     198    { 
     199        // update max group info if needed 
     200        MaxGroup = ginfo; 
     201    } 
     202} 
     203 
     204// add group to bg queue with the given leader and bg specifications 
     205GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid) 
     206{ 
     207    uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(); 
     208 
     209    // create new ginfo 
     210    // cannot use the method like in addplayer, because that could modify an in-queue group's stats 
     211    // (e.g. leader leaving queue then joining as individual again) 
     212    GroupQueueInfo* ginfo = new GroupQueueInfo; 
     213    ginfo->BgTypeId                  = BgTypeId; 
     214    ginfo->ArenaType                 = ArenaType; 
     215    ginfo->ArenaTeamId               = arenateamid; 
     216    ginfo->IsRated                   = isRated; 
     217    ginfo->IsInvitedToBGInstanceGUID = 0;                       // maybe this should be modifiable by function arguments to enable selection of running instances? 
     218    ginfo->JoinTime                  = getMSTime(); 
     219    ginfo->Team                      = leader->GetTeam(); 
     220 
     221    if(sBattleGroundMgr.GetMaxRatingDifference())               // if max difference is set, then store rating info for queue 
     222        ginfo->ArenaTeamRating       = arenaRating; 
     223    else 
     224        ginfo->ArenaTeamRating       = 0;                       // don't if it doesn't matter 
     225 
     226    ginfo->Players.clear(); 
     227 
     228    m_QueuedGroups[queue_id].push_back(ginfo); 
     229 
     230    // return ginfo, because it is needed to add players to this group info 
     231    return ginfo; 
     232} 
     233 
     234void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) 
    64235{ 
    65236    uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); 
     
    68239    PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; 
    69240    info.InviteTime                 = 0; 
    70     info.IsInvitedToBGInstanceGUID  = 0; 
    71241    info.LastInviteTime             = 0; 
    72242    info.LastOnlineTime             = getMSTime(); 
    73     info.Team                       = plr->GetTeam(); 
    74  
    75     //add player to waiting order queue 
    76     m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID()); 
    77  
    78     if(plr->GetTeam() == ALLIANCE) 
    79         ++m_QueuedPlayers[queue_id].Alliance; 
    80     else 
    81         ++m_QueuedPlayers[queue_id].Horde; 
    82  
    83     this->Update(bgTypeId, queue_id); 
    84  
    85     if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) 
    86     { 
    87         BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 
    88         char const* bgName = bg->GetName(); 
    89  
    90         uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id); 
    91         uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id); 
    92  
    93         // replace hardcoded max level by player max level for nice output 
    94         if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) 
    95             q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); 
    96  
    97         int8 MinPlayers = bg->GetMinPlayersPerTeam(); 
    98  
    99         uint8 qHorde = m_QueuedPlayers[queue_id].Horde; 
    100         uint8 qAlliance = m_QueuedPlayers[queue_id].Alliance; 
    101  
    102         // Show queue status to player only (when joining queue) 
    103         if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) 
    104         { 
    105             ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF,  
    106                 bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde); 
    107         } 
    108         // System message 
    109         else 
    110         { 
    111             sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, 
    112                 bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde); 
    113         } 
    114     } 
     243    info.GroupInfo                  = ginfo; 
     244 
     245    // add the pinfo to ginfo's list 
     246    ginfo->Players[plr->GetGUID()]  = &info; 
    115247} 
    116248 
     
    121253    uint32 queue_id = 0; 
    122254    QueuedPlayersMap::iterator itr; 
     255    GroupQueueInfo * group; 
     256    QueuedGroupsList::iterator group_itr; 
    123257    bool IsSet = false; 
    124     if(!plr) 
    125     {                                                       //player is offline, we need to find him somewhere in queues 
    126         /// there is something wrong if this code is run, because we have in queue only online players! 
    127         sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); 
     258    if(plr) 
     259    { 
     260        queue_id = plr->GetBattleGroundQueueIdFromLevel(); 
     261 
     262        itr = m_QueuedPlayers[queue_id].find(guid); 
     263        if(itr != m_QueuedPlayers[queue_id].end()) 
     264            IsSet = true; 
     265    } 
     266 
     267    if(!IsSet) 
     268    {                                                        
     269        // either player is offline, or he levelled up to another queue category 
     270        // sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); 
    128271        for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 
    129272        { 
     
    137280        } 
    138281    } 
    139     else 
    140     {                                                       //player is online, we have his level, so we can find exact queue from his level 
    141         queue_id = plr->GetBattleGroundQueueIdFromLevel(); 
    142         itr = m_QueuedPlayers[queue_id].find(guid); 
    143         IsSet = true; 
    144     } 
    145  
    146     //all variables are set, so remove player 
    147     //remove player from time queue 
    148     m_PlayersSortedByWaitTime[queue_id].remove(guid); 
    149  
    150     if (IsSet && itr != m_QueuedPlayers[queue_id].end()) 
    151     { 
    152         if (!itr->second.IsInvitedToBGInstanceGUID) 
    153         { 
    154             if(itr->second.Team == ALLIANCE) 
    155                 --m_QueuedPlayers[queue_id].Alliance; 
    156             else 
    157                 --m_QueuedPlayers[queue_id].Horde; 
    158         } 
    159         else 
    160         { 
    161             if (decreaseInvitedCount) 
    162             { 
    163                 BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID); 
     282 
     283    // couldn't find the player in bg queue, return 
     284    if(!IsSet) 
     285    { 
     286        sLog.outError("Battleground: couldn't find player to remove."); 
     287        return; 
     288    } 
     289 
     290    group = itr->second.GroupInfo; 
     291 
     292    for(group_itr=m_QueuedGroups[queue_id].begin(); group_itr != m_QueuedGroups[queue_id].end(); ++group_itr) 
     293    { 
     294        if(group == (GroupQueueInfo*)(*group_itr)) 
     295            break; 
     296    } 
     297 
     298    // variables are set (what about leveling up when in queue????) 
     299    // remove player from group 
     300    // if only player there, remove group 
     301 
     302    // remove player queue info from group queue info 
     303    std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid); 
     304 
     305    if(pitr != group->Players.end()) 
     306        group->Players.erase(pitr); 
     307 
     308    // check for iterator correctness 
     309    if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end()) 
     310    { 
     311        // used when player left the queue, NOT used when porting to bg 
     312        if (decreaseInvitedCount) 
     313        { 
     314            // if invited to bg, and should decrease invited count, then do it 
     315            if(group->IsInvitedToBGInstanceGUID) 
     316            { 
     317                BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); 
    164318                if (bg) 
    165                     bg->DecreaseInvitedCount(itr->second.Team); 
    166             } 
    167         } 
     319                    bg->DecreaseInvitedCount(group->Team); 
     320                if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE)) 
     321                { 
     322                    // no more players on battleground, set delete it 
     323                    bg->SetDeleteThis(); 
     324                } 
     325            } 
     326            // update the join queue, maybe now the player's group fits in a queue! 
     327            // not yet implemented (should store bgTypeId in group queue info?) 
     328        } 
     329        // remove player queue info 
    168330        m_QueuedPlayers[queue_id].erase(itr); 
     331        // remove group queue info if needed 
     332        if(group->Players.empty()) 
     333        { 
     334            m_QueuedGroups[queue_id].erase(group_itr); 
     335            delete group; 
     336        } 
     337        // NEEDS TESTING! 
     338        // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too 
     339        // don't remove recursively if already invited to bg! 
     340        else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount && group->IsRated) 
     341        { 
     342            // remove next player, this is recursive 
     343            // first send removal information 
     344            if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) 
     345            { 
     346                BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); 
     347                uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId,group->ArenaType); 
     348                uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); 
     349                plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs 
     350                WorldPacket data; 
     351                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 
     352                plr2->GetSession()->SendPacket(&data); 
     353            } 
     354            // then actually delete, this may delete the group as well! 
     355            RemovePlayer(group->Players.begin()->first,decreaseInvitedCount); 
     356        } 
     357    } 
     358} 
     359 
     360bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) 
     361{ 
     362    // set side if needed 
     363    if(side) 
     364        ginfo->Team = side; 
     365 
     366    if(!ginfo->IsInvitedToBGInstanceGUID) 
     367    { 
     368        // not yet invited 
     369        // set invitation 
     370        ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); 
     371        uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 
     372        // loop through the players 
     373        for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) 
     374        { 
     375            // set status 
     376            itr->second->InviteTime = getMSTime(); 
     377            itr->second->LastInviteTime = getMSTime(); 
     378 
     379            // get the player 
     380            Player* plr = objmgr.GetPlayer(itr->first); 
     381            // if offline, skip him 
     382            if(!plr) 
     383                continue; 
     384 
     385            // invite the player 
     386            sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team); 
     387 
     388            WorldPacket data; 
     389 
     390            uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 
     391 
     392            sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); 
     393 
     394            // send status packet 
     395            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); 
     396            plr->GetSession()->SendPacket(&data); 
     397        } 
     398        return true; 
     399    } 
     400 
     401    return false; 
     402} 
     403 
     404// this function is responsible for the selection of queued groups when trying to create new battlegrounds 
     405bool BattleGroundQueue::BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers,  SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) 
     406{ 
     407    uint32 side; 
     408    switch(mode) 
     409    { 
     410    case NORMAL_ALLIANCE: 
     411    case ONESIDE_ALLIANCE_TEAM1: 
     412    case ONESIDE_ALLIANCE_TEAM2: 
     413        side = ALLIANCE; 
     414        break; 
     415    case NORMAL_HORDE: 
     416    case ONESIDE_HORDE_TEAM1: 
     417    case ONESIDE_HORDE_TEAM2: 
     418        side = HORDE; 
     419        break; 
     420    default: 
     421        //unknown mode, return false 
     422        sLog.outDebug("Battleground: unknown selection pool build mode, returning..."); 
     423        return false; 
     424        break; 
     425    } 
     426 
     427    // inititate the groups eligible to create the bg 
     428    m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), bgTypeId, side, MaxPlayers, ArenaType, isRated, MinRating, MaxRating, DisregardTime, excludeTeam); 
     429    // init the selected groups (clear) 
     430    m_SelectionPools[mode].Init(); 
     431    while(!(m_EligibleGroups.empty())) 
     432    { 
     433        sLog.outDebug("m_EligibleGroups is not empty, continue building selection pool"); 
     434        // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players 
     435        for(EligibleGroups::iterator itr= m_EligibleGroups.begin(); itr!=m_EligibleGroups.end(); ++itr) 
     436        { 
     437            // get the maximal not yet checked group 
     438            GroupQueueInfo * MaxGroup = (*itr); 
     439            // if it fits in the maxplayer size, add it 
     440            if( (m_SelectionPools[mode].GetPlayerCount() + MaxGroup->Players.size()) <= MaxPlayers ) 
     441            { 
     442                m_SelectionPools[mode].AddGroup(MaxGroup); 
     443            } 
     444        } 
     445        if(m_SelectionPools[mode].GetPlayerCount()>=MinPlayers) 
     446        { 
     447            // the selection pool is set, return 
     448            sLog.outDebug("pool build succeeded, return true"); 
     449            return true; 
     450        } 
     451        // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest. 
     452        GroupQueueInfo * MaxGroup = m_SelectionPools[mode].GetMaximalGroup(); 
     453        m_EligibleGroups.RemoveGroup(MaxGroup); 
     454        m_SelectionPools[mode].RemoveGroup(MaxGroup); 
     455    } 
     456    // failed to build a selection pool matching the given values 
     457    return false; 
     458} 
     459 
     460// used to remove the Enter Battle window if the battle has already, but someone still has it 
     461// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event 
     462void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) 
     463{ 
     464    uint32 queue_id = bg->GetQueueType(); 
     465    uint32 bgInstanceId = bg->GetInstanceID(); 
     466    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 
     467    QueuedGroupsList::iterator itr, next; 
     468    for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) 
     469    { 
     470        // must do this way, because the groupinfo will be deleted when all playerinfos are removed 
     471        GroupQueueInfo * ginfo = (*itr); 
     472        next = itr; 
     473        ++next; 
     474        // if group was invited to this bg instance, then remove all references 
     475        if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId) 
     476        { 
     477            // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop 
     478            uint32 to_remove = ginfo->Players.size(); 
     479            uint32 team = ginfo->Team; 
     480            for(int i = 0; i < to_remove; ++i) 
     481            { 
     482                // always remove the first one in the group 
     483                std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin(); 
     484                if(itr2 == ginfo->Players.end()) 
     485                { 
     486                    sLog.outError("Empty Players in ginfo, this should never happen!"); 
     487                    return; 
     488                } 
     489 
     490                // get the player 
     491                Player * plr = objmgr.GetPlayer(itr2->first); 
     492                if(!plr) 
     493                { 
     494                    sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen."); 
     495                    continue; 
     496                } 
     497 
     498                // get the queueslot 
     499                uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 
     500                if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 
     501                { 
     502                    plr->RemoveBattleGroundQueueId(bgQueueTypeId); 
     503                    // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! 
     504                    RemovePlayer(itr2->first, true); 
     505                    // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups 
     506                    // but updateing the queue can't hurt 
     507                    Update(bgQueueTypeId, bg->GetQueueType()); 
     508                    // send info to client 
     509                    WorldPacket data; 
     510                    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); 
     511                    plr->GetSession()->SendPacket(&data); 
     512                } 
     513            } 
     514        } 
    169515    } 
    170516} 
    171517 
    172518/* 
    173 this method is called when player is inserted, or removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue 
    174 add method calls this by itself, the remove method could works in other way, so you have to call this method from other code after calling remove method 
     519this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue 
     520it must be called after fully adding the members of a group to ensure group joining 
     521should be called after removeplayer functions in some cases 
    175522*/ 
    176 void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) 
     523void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) 
    177524{ 
    178525    if (queue_id >= MAX_BATTLEGROUND_QUEUES) 
     
    184531 
    185532    //if no players in queue ... do nothing 
    186     if (this->m_QueuedPlayers[queue_id].Alliance == 0 && this->m_QueuedPlayers[queue_id].Horde == 0) 
     533    if (this->m_QueuedGroups[queue_id].size() == 0) 
    187534        return; 
    188535 
     536    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); 
     537 
    189538    //battleground with free slot for player should be always the last in this queue 
    190     for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr) 
    191     { 
     539    BGFreeSlotQueueType::iterator itr, next; 
     540    for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) 
     541    { 
     542        next = itr; 
     543        ++next; 
    192544        // battleground is running, so if: 
    193545        // DO NOT allow queue manager to invite new player to running arena 
    194         if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) 
     546        if ((*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) 
    195547        { 
    196548            //we must check both teams 
     
    198550            // and iterator is invalid 
    199551 
    200             //check if there are some players in queue 
    201             if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0) 
    202             { 
    203                 for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) 
     552            for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr) 
     553            { 
     554                // did the group join for this bg type? 
     555                if((*itr)->BgTypeId != bgTypeId) 
     556                    continue; 
     557                // if so, check if fits in 
     558                if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size()) 
    204559                { 
    205                     Player* plr = objmgr.GetPlayer(*itr2); 
    206                     if (!plr) 
    207                     { 
    208                         //something is wrong!, kick player from queue 
    209                         sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); 
    210                         uint64 oldval = *itr2; 
    211                         itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); 
    212                         RemovePlayer(oldval, true); 
    213                         continue; 
    214                     } 
    215  
    216                     // player will be invited, if in bg there is a free slot for him 
    217                     if (bg->HasFreeSlotsForTeam(plr->GetTeam())) 
    218                     { 
    219                         // iterator to player's queue status 
    220                         QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); 
    221  
    222                         // remove him from time queue 
    223                         itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); 
    224  
    225                         // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and pls report it) 
    226                         if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) 
    227                             continue; 
    228  
    229                         // check if player is not already invited 
    230                         if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) 
    231                         { 
    232                             itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID(); 
    233                             itrPlayerStatus->second.InviteTime = getMSTime(); 
    234                             itrPlayerStatus->second.LastInviteTime = getMSTime(); 
    235                             if(itrPlayerStatus->second.Team == ALLIANCE) 
    236                                 --m_QueuedPlayers[queue_id].Alliance; 
    237                             else 
    238                                 --m_QueuedPlayers[queue_id].Horde; 
    239                             sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID()); 
    240  
    241                             WorldPacket data; 
    242                             uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); 
    243                             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); 
    244                             plr->GetSession()->SendPacket(&data); 
    245                         } 
    246                     } 
    247                     else 
    248                         ++itr2; 
    249  
    250                     //if battleground is FULL, then it is removed from free slot queue - not yet implemented! 
    251                     if (!bg->HasFreeSlots()) 
    252                     { 
    253                         //if bg is full, there is no need to invite other players, so break 
    254                         break; 
    255                         //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue 
    256                         //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented 
    257                     } 
     560                    // if group fits in, invite it 
     561                    InviteGroupToBG((*itr),bg,(*itr)->Team); 
    258562                } 
    259563            } 
    260         } 
    261     } 
    262  
    263     /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */ 
    264     //itr->end is the last BG - template, which is not already started! 
    265  
    266     /* here will be a most of change, when we create battlegrounds instantiated */ 
    267     /* if (there is enough players to start new BG) 
    268         Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId) 
    269         - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template 
    270             (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */ 
    271  
    272     /* following code is working with current Battleground system and it should be removed, when BGs will work like instances */ 
    273     BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId); 
    274     if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE) 
     564 
     565            if (!bg->HasFreeSlots()) 
     566            { 
     567                //remove BG from BGFreeSlotQueue 
     568                bg->RemoveFromBGFreeSlotQueue(); 
     569            } 
     570        } 
     571    } 
     572 
     573    // finished iterating through the bgs with free slots, maybe we need to create a new bg 
     574 
     575    BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 
     576    if(!bg_template) 
     577    { 
     578        sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId); 
    275579        return; 
    276     if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam()) 
    277     { 
     580    } 
     581 
     582    // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!) 
     583    uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); 
     584    uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); 
     585    if(bg_template->isArena()) 
     586    { 
     587        if(sBattleGroundMgr.isArenaTesting()) 
     588        { 
     589            MaxPlayersPerTeam = 1; 
     590            MinPlayersPerTeam = 1; 
     591        } 
     592        else 
     593        { 
     594            switch(arenatype) 
     595            { 
     596            case ARENA_TYPE_2v2: 
     597                MaxPlayersPerTeam = 2; 
     598                MinPlayersPerTeam = 2; 
     599                break; 
     600            case ARENA_TYPE_3v3: 
     601                MaxPlayersPerTeam = 3; 
     602                MinPlayersPerTeam = 3; 
     603                break; 
     604            case ARENA_TYPE_5v5: 
     605                MaxPlayersPerTeam = 5; 
     606                MinPlayersPerTeam = 5; 
     607                break; 
     608            } 
     609        } 
     610    } 
     611 
     612    // found out the minimum and maximum ratings the newly added team should battle against 
     613    // arenaRating is the rating of the latest joined team 
     614    uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference(); 
     615    // if no rating is specified, set maxrating to 0 
     616    uint32 arenaMaxRating = (arenaRating == 0)? 0 : arenaRating + sBattleGroundMgr.GetMaxRatingDifference(); 
     617    uint32 discardTime = 0; 
     618    // if max rating difference is set and the time past since server startup is greater than the rating discard time 
     619    // (after what time the ratings aren't taken into account when making teams) then  
     620    // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account 
     621    // else leave the discard time on 0, this way all ratings will be discarded 
     622    if(sBattleGroundMgr.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr.GetRatingDiscardTimer()) 
     623        discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer(); 
     624 
     625    // try to build the selection pools 
     626    bool bAllyOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 
     627    if(bAllyOK) 
     628        sLog.outDebug("Battleground: ally pool succesfully build"); 
     629    else 
     630        sLog.outDebug("Battleground: ally pool wasn't created"); 
     631    bool bHordeOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 
     632    if(bHordeOK) 
     633        sLog.outDebug("Battleground: horde pool succesfully built"); 
     634    else 
     635        sLog.outDebug("Battleground: horde pool wasn't created"); 
     636 
     637    // if selection pools are ready, create the new bg 
     638    if (bAllyOK && bHordeOK) 
     639    { 
     640        BattleGround * bg2 = 0; 
     641        // special handling for arenas 
     642        if(bg_template->isArena()) 
     643        { 
     644            // Find a random arena, that can be created 
     645            uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; 
     646            uint32 arena_num = urand(0,2); 
     647            if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && 
     648                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && 
     649                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) 
     650            { 
     651                sLog.outError("Battleground: couldn't create arena"); 
     652                return; 
     653            } 
     654 
     655            // set the MaxPlayersPerTeam values based on arenatype 
     656            // setting the min player values isn't needed, since we won't be using that value later on. 
     657            if(sBattleGroundMgr.isArenaTesting()) 
     658            { 
     659                bg2->SetMaxPlayersPerTeam(1); 
     660                bg2->SetMaxPlayers(2); 
     661            } 
     662            else 
     663            { 
     664                switch(arenatype) 
     665                { 
     666                case ARENA_TYPE_2v2: 
     667                    bg2->SetMaxPlayersPerTeam(2); 
     668                    bg2->SetMaxPlayers(4); 
     669                    break; 
     670                case ARENA_TYPE_3v3: 
     671                    bg2->SetMaxPlayersPerTeam(3); 
     672                    bg2->SetMaxPlayers(6); 
     673                    break; 
     674                case ARENA_TYPE_5v5: 
     675                    bg2->SetMaxPlayersPerTeam(5); 
     676                    bg2->SetMaxPlayers(10); 
     677                    break; 
     678                default: 
     679                    break; 
     680                } 
     681            } 
     682        } 
     683        else 
     684        { 
     685            // create new battleground 
     686            bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId); 
     687        } 
     688 
     689        if(!bg2) 
     690        { 
     691            sLog.outError("Battleground: couldn't create bg %u",bgTypeId); 
     692            return; 
     693        } 
     694 
     695        // start the joining of the bg 
    278696        bg2->SetStatus(STATUS_WAIT_JOIN); 
    279697        bg2->SetQueueType(queue_id); 
    280  
    281         for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) 
    282         { 
    283             Player* plr = objmgr.GetPlayer(*itr2); 
    284             if (!plr) 
    285             { 
    286                 //something is wrong!, kick player from queue 
    287                 sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); 
    288                 uint64 oldval = *itr2; 
    289                 itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); 
    290                 RemovePlayer(oldval, true); 
    291                 continue; 
    292             } 
    293  
    294             /* TODO: (i'm not sure this code will be useful: 
    295             here should be some condition like if (bg2->isArena() && bg2->isRated()) 
    296             { 
    297                 invite players from 1 certain group on each faction to play arena match 
    298             } else if ....and existing code 
    299             */ 
    300             // player will be invited, if in bg there is a free slot for him 
    301             if (bg2->HasFreeSlotsForTeam(plr->GetTeam())) 
    302             { 
    303                 // iterator to player's queue status 
    304                 QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); 
    305  
    306                 // remove him from time queue 
    307                 itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); 
    308  
    309                 // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and report it) 
    310                 if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) 
    311                     continue; 
    312  
    313                 //check if player is not already invited 
    314                 if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) 
     698        // initialize arena / rating info 
     699        bg2->SetArenaType(arenatype); 
     700        // set rating 
     701        bg2->SetRated(isRated); 
     702 
     703        std::list<GroupQueueInfo* >::iterator itr; 
     704 
     705        // invite groups from horde selection pool 
     706        for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr) 
     707        { 
     708            InviteGroupToBG((*itr),bg2,HORDE); 
     709        } 
     710 
     711        // invite groups from ally selection pools 
     712        for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr) 
     713        { 
     714            InviteGroupToBG((*itr),bg2,ALLIANCE); 
     715        } 
     716 
     717        // start the battleground 
     718        bg2->StartBattleGround(); 
     719    } 
     720 
     721    // there weren't enough players for a "normal" match 
     722    // if arena, enable horde versus horde or alliance versus alliance teams here 
     723 
     724    else if(bg_template->isArena()) 
     725    { 
     726        bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false; 
     727        bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false; 
     728        bOneSideHordeTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 
     729        if(bOneSideHordeTeam1) 
     730        { 
     731            // one team has been selected, find out if other can be selected too 
     732            std::list<GroupQueueInfo* >::iterator itr; 
     733            // temporarily change the team side to enable building the next pool excluding the already selected groups 
     734            for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) 
     735                (*itr)->Team=ALLIANCE; 
     736 
     737            bOneSideHordeTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime, (*(m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); 
     738 
     739            // change back the team to horde 
     740            for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) 
     741                (*itr)->Team=HORDE; 
     742 
     743            if(!bOneSideHordeTeam2) 
     744                bOneSideHordeTeam1 = false; 
     745        } 
     746        if(!bOneSideHordeTeam1) 
     747        { 
     748            // check for one sided ally 
     749            bOneSideAllyTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 
     750            if(bOneSideAllyTeam1) 
     751            { 
     752                // one team has been selected, find out if other can be selected too 
     753                std::list<GroupQueueInfo* >::iterator itr; 
     754                // temporarily change the team side to enable building the next pool excluding the already selected groups 
     755                for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) 
     756                    (*itr)->Team=HORDE; 
     757 
     758                bOneSideAllyTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime,(*(m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); 
     759 
     760                // change back the team to ally 
     761                for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) 
     762                    (*itr)->Team=ALLIANCE; 
     763            } 
     764 
     765            if(!bOneSideAllyTeam2) 
     766                bOneSideAllyTeam1 = false; 
     767        } 
     768        // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!! 
     769        if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) || 
     770            (bOneSideAllyTeam1 && bOneSideAllyTeam2) ) 
     771        { 
     772            // which side has enough players? 
     773            uint32 side = 0; 
     774            SelectionPoolBuildMode mode1, mode2; 
     775            // find out what pools are we using 
     776            if(bOneSideAllyTeam1 && bOneSideAllyTeam2) 
     777            { 
     778                side = ALLIANCE; 
     779                mode1 = ONESIDE_ALLIANCE_TEAM1; 
     780                mode2 = ONESIDE_ALLIANCE_TEAM2; 
     781            } 
     782            else 
     783            { 
     784                side = HORDE; 
     785                mode1 = ONESIDE_HORDE_TEAM1; 
     786                mode2 = ONESIDE_HORDE_TEAM2; 
     787            } 
     788 
     789            // create random arena 
     790            uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; 
     791            uint32 arena_num = urand(0,2); 
     792            BattleGround* bg2 = NULL; 
     793            if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && 
     794                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && 
     795                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) 
     796            { 
     797                sLog.outError("Could not create arena."); 
     798                return; 
     799            } 
     800 
     801            sLog.outDebug("Battleground: One-faction arena created."); 
     802            // init stats 
     803            if(sBattleGroundMgr.isArenaTesting()) 
     804            { 
     805                bg2->SetMaxPlayersPerTeam(1); 
     806                bg2->SetMaxPlayers(2); 
     807            } 
     808            else 
     809            { 
     810                switch(arenatype) 
    315811                { 
    316                     itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID(); 
    317                     itrPlayerStatus->second.InviteTime = getMSTime(); 
    318                     itrPlayerStatus->second.LastInviteTime = getMSTime(); 
    319  
    320                     if(itrPlayerStatus->second.Team == ALLIANCE) 
    321                         --m_QueuedPlayers[queue_id].Alliance; 
    322                     else 
    323                         --m_QueuedPlayers[queue_id].Horde; 
    324  
    325                     sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID()); 
    326  
    327                     WorldPacket data; 
    328                     uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); 
    329                     sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); 
    330                     plr->GetSession()->SendPacket(&data); 
     812                case ARENA_TYPE_2v2: 
     813                    bg2->SetMaxPlayersPerTeam(2); 
     814                    bg2->SetMaxPlayers(4); 
     815                    break; 
     816                case ARENA_TYPE_3v3: 
     817                    bg2->SetMaxPlayersPerTeam(3); 
     818                    bg2->SetMaxPlayers(6); 
     819                    break; 
     820                case ARENA_TYPE_5v5: 
     821                    bg2->SetMaxPlayersPerTeam(5); 
     822                    bg2->SetMaxPlayers(10); 
     823                    break; 
     824                default: 
     825                    break; 
    331826                } 
    332827            } 
     828 
     829            bg2->SetRated(isRated); 
     830 
     831            // assigned team of the other group 
     832            uint32 other_side; 
     833            if(side == ALLIANCE) 
     834                other_side = HORDE; 
    333835            else 
    334                 ++itr2; 
    335         } 
    336         bg2->StartBattleGround(); 
     836                other_side = ALLIANCE; 
     837 
     838            // start the joining of the bg 
     839            bg2->SetStatus(STATUS_WAIT_JOIN); 
     840            bg2->SetQueueType(queue_id); 
     841            // initialize arena / rating info 
     842            bg2->SetArenaType(arenatype); 
     843 
     844            std::list<GroupQueueInfo* >::iterator itr; 
     845 
     846            // invite players from the first group as horde players (actually green team) 
     847            for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr) 
     848            { 
     849                InviteGroupToBG((*itr),bg2,HORDE); 
     850            } 
     851 
     852            // invite players from the second group as ally players (actually gold team) 
     853            for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr) 
     854            { 
     855                InviteGroupToBG((*itr),bg2,ALLIANCE); 
     856            } 
     857 
     858            bg2->StartBattleGround(); 
     859        } 
    337860    } 
    338861} 
     
    362885    if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)         // player is in queue 
    363886    { 
    364         // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems 
    365         BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; 
    366         BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); 
    367         if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) 
    368         { 
    369             WorldPacket data; 
    370             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); 
    371             plr->GetSession()->SendPacket(&data); 
     887        uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 
     888        uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 
     889        if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 
     890        { 
     891            // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems 
     892            BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; 
     893            BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); 
     894            if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) 
     895            { 
     896                WorldPacket data; 
     897                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); 
     898                plr->GetSession()->SendPacket(&data); 
     899            } 
    372900        } 
    373901    } 
     
    397925        return true; 
    398926 
    399     uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); 
    400     if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)         // player is in queue (base at player data 
     927    sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); 
     928 
     929    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 
     930    uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 
     931    if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 
    401932    { 
    402933        // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems 
    403         BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; 
    404         BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); 
    405         if (qItr!=qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) 
    406         { 
    407             plr->RemoveBattleGroundQueueId(bg->GetTypeID()); 
    408             sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true); 
    409             sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType()); 
    410  
     934        BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].find(m_PlayerGuid); 
     935        if (qMapItr != sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) 
     936        { 
     937            plr->RemoveBattleGroundQueueId(bgQueueTypeId); 
     938            sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); 
     939            sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgQueueTypeId, bg->GetQueueType()); 
    411940            WorldPacket data; 
    412             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 
     941            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); 
    413942            plr->GetSession()->SendPacket(&data); 
    414943        } 
    415944    } 
     945    else 
     946        sLog.outDebug("Battleground: Player was already removed from queue"); 
    416947 
    417948    //event will be deleted 
     
    432963{ 
    433964    m_BattleGrounds.clear(); 
     965    m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS); 
     966    m_MaxRatingDifference = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); 
     967    m_RatingDiscardTimer = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); 
     968    m_PrematureFinishTimer = sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); 
     969    m_NextRatingDiscardUpdate = m_RatingDiscardTimer; 
     970    m_AutoDistributionTimeChecker = 0; 
     971    m_ArenaTesting = false; 
    434972} 
    435973 
    436974BattleGroundMgr::~BattleGroundMgr() 
    437975{ 
    438     for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) 
    439         delete itr->second; 
     976    BattleGroundSet::iterator itr, next; 
     977    for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) 
     978    { 
     979        next = itr; 
     980        ++next; 
     981        BattleGround * bg = itr->second; 
     982        m_BattleGrounds.erase(itr); 
     983        delete bg; 
     984    } 
    440985    m_BattleGrounds.clear(); 
    441986} 
    442987 
     988// used to update running battlegrounds, and delete finished ones 
    443989void BattleGroundMgr::Update(time_t diff) 
    444990{ 
    445     for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) 
     991    BattleGroundSet::iterator itr, next; 
     992    for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) 
     993    { 
     994        next = itr; 
     995        ++next; 
    446996        itr->second->Update(diff); 
    447 } 
    448  
    449 void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) 
     997        // use the SetDeleteThis variable 
     998        // direct deletion caused crashes 
     999        if(itr->second->m_SetDeleteThis) 
     1000        { 
     1001            BattleGround * bg = itr->second; 
     1002            m_BattleGrounds.erase(itr); 
     1003            delete bg; 
     1004        } 
     1005    } 
     1006    // if rating difference counts, maybe force-update queues 
     1007    if(m_MaxRatingDifference) 
     1008    { 
     1009        // it's time to force update 
     1010        if(m_NextRatingDiscardUpdate < diff) 
     1011        { 
     1012            // forced update for level 70 rated arenas 
     1013            m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0); 
     1014            m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0); 
     1015            m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0); 
     1016            m_NextRatingDiscardUpdate = m_RatingDiscardTimer; 
     1017        }  
     1018        else  
     1019            m_NextRatingDiscardUpdate -= diff; 
     1020    } 
     1021    if(m_AutoDistributePoints) 
     1022    { 
     1023        if(m_AutoDistributionTimeChecker < diff) 
     1024        { 
     1025            if(time(NULL) > m_NextAutoDistributionTime) 
     1026            { 
     1027                DistributeArenaPoints(); 
     1028                m_NextAutoDistributionTime = time(NULL) + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); 
     1029                CharacterDatabase.PExecute("UPDATE saved_variables SET NextArenaPointDistributionTime = FROM_UNIXTIME('"I64FMTD"')",(uint64)m_NextAutoDistributionTime); 
     1030            } 
     1031            m_AutoDistributionTimeChecker = 600000; // check 10 minutes 
     1032        } 
     1033        else 
     1034            m_AutoDistributionTimeChecker -= diff; 
     1035    } 
     1036} 
     1037 
     1038void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted) 
    4501039{ 
    4511040    // we can be in 3 queues in same time... 
     
    4611050    *data << uint32(QueueSlot);                             // queue id (0...2) - player can be in 3 queues in time 
    4621051    // uint64 in client 
    463     *data << uint64( uint64(bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); 
     1052    *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); 
    4641053    *data << uint32(0);                                     // unknown 
    4651054    // alliance/horde for BG and skirmish/rated for Arenas 
    466     *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team)); 
     1055    *data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team)); 
     1056/*    *data << uint8(arenatype ? arenatype : bg->GetArenaType());                     // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas    // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! 
     1057    switch(bg->GetTypeID())                                 // value depends on bg id 
     1058    { 
     1059        case BATTLEGROUND_AV: 
     1060            *data << uint8(1); 
     1061            break; 
     1062        case BATTLEGROUND_WS: 
     1063            *data << uint8(2); 
     1064            break; 
     1065        case BATTLEGROUND_AB: 
     1066            *data << uint8(3); 
     1067            break; 
     1068        case BATTLEGROUND_NA: 
     1069            *data << uint8(4); 
     1070            break; 
     1071        case BATTLEGROUND_BE: 
     1072            *data << uint8(5); 
     1073            break; 
     1074        case BATTLEGROUND_AA: 
     1075            *data << uint8(6); 
     1076            break; 
     1077        case BATTLEGROUND_EY: 
     1078            *data << uint8(7); 
     1079            break; 
     1080        case BATTLEGROUND_RL: 
     1081            *data << uint8(8); 
     1082            break; 
     1083        default:                                            // unknown 
     1084            *data << uint8(0); 
     1085            break; 
     1086    } 
     1087 
     1088    if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE)) 
     1089        *data << uint32(BATTLEGROUND_AA);                   // all arenas   I don't think so. 
     1090    else 
     1091    *data << uint32(bg->GetTypeID());                   // BG id from DBC 
     1092 
     1093    *data << uint16(0x1F90);                                // unk value 8080 
     1094    *data << uint32(bg->GetInstanceID());                   // instance id 
     1095 
     1096    if(bg->isBattleGround()) 
     1097        *data << uint8(bg->GetTeamIndexByTeamId(team));     // team 
     1098    else 
     1099        *data << uint8(israted?israted:bg->isRated());                      // is rated battle 
     1100*/ 
    4671101    *data << uint32(StatusID);                              // status 
    4681102    switch(StatusID) 
     
    4941128    data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); 
    4951129    *data << uint8(type);                                   // seems to be type (battleground=0/arena=1) 
     1130 
    4961131    if(type)                                                // arena 
    4971132    { 
    498         for(uint8 i = 0; i < 2; i++) 
    499         { 
    500             *data << uint32(3000+1+i);                      // rating change: showed value - 3000 
    501             *data << uint32(0);                             // 2.4.0, has some to do with rating change... 
    502             *data << uint8(0);                              // some unknown string 
     1133        // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H 
     1134        for(int i = 1; i >= 0; --i) 
     1135        { 
     1136            *data << uint32(3000-bg->m_ArenaTeamRatingChanges[i]);                      // rating change: showed value - 3000 
     1137            *data << uint32(3999);  // huge thanks for TOM_RUS for this! 
     1138            sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]); 
     1139        } 
     1140        for(int i = 1; i >= 0; --i) 
     1141        { 
     1142            uint32 at_id = bg->m_ArenaTeamIds[i]; 
     1143            ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 
     1144            if(at) 
     1145                *data << at->GetName(); 
     1146            else//*/ 
     1147                *data << (uint8)0; 
    5031148        } 
    5041149    } 
     
    5201165        *data << (uint64)itr->first; 
    5211166        *data << (int32)itr->second->KillingBlows; 
    522         if(type) 
    523         { 
    524             // this value is team (green/gold)? 
     1167        Player *plr = objmgr.GetPlayer(itr->first); 
     1168        uint32 team = bg->GetPlayerTeam(itr->first); 
     1169        if(!team && plr) team = plr->GetTeam(); 
     1170        if(type == 0) 
     1171        { 
     1172            *data << (int32)itr->second->HonorableKills; 
     1173            *data << (int32)itr->second->Deaths; 
     1174            *data << (int32)(itr->second->BonusHonor); 
     1175        } 
     1176        else 
     1177        { 
    5251178            // that part probably wrong 
    526             Player *plr = objmgr.GetPlayer(itr->first); 
    5271179            if(plr) 
    5281180            { 
    529                 if(plr->GetTeam() == HORDE) 
     1181                if(team == HORDE) 
    5301182                    *data << uint8(0); 
    531                 else if(plr->GetTeam() == ALLIANCE) 
     1183                else if(team == ALLIANCE) 
     1184                { 
    5321185                    *data << uint8(1); 
     1186                } 
    5331187                else 
    5341188                    *data << uint8(0); 
     
    5371191                *data << uint8(0); 
    5381192        } 
    539         else 
    540         { 
    541             *data << (int32)itr->second->HonorableKills; 
    542             *data << (int32)itr->second->Deaths; 
    543             *data << (int32)itr->second->BonusHonor;        // bonus honor 
    544         } 
    545         *data << (int32)itr->second->DamageDone;            // damage done 
    546         *data << (int32)itr->second->HealingDone;           // healing done 
    547         switch(bg->GetTypeID())                             // battleground specific things 
     1193        *data << (int32)itr->second->DamageDone;             // damage done 
     1194        *data << (int32)itr->second->HealingDone;            // healing done 
     1195        switch(bg->GetTypeID())                              // battleground specific things 
    5481196        { 
    5491197            case BATTLEGROUND_AV: 
     
    6231271} 
    6241272 
    625 void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID) 
     1273void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) 
    6261274{ 
    6271275    // set invited player counters: 
     
    6291277    if(!bg) 
    6301278        return; 
    631  
    632     bg->IncreaseInvitedCount(plr->GetTeam()); 
    633     plr->SetInviteForBattleGroundType(bg->GetTypeID()); 
     1279    bg->IncreaseInvitedCount(team); 
     1280     
     1281    plr->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg->GetTypeID(),bg->GetArenaType()), bgInstanceGUID); 
     1282 
     1283    // set the arena teams for rated matches 
     1284    if(bg->isArena() && bg->isRated()) 
     1285    { 
     1286        switch(bg->GetArenaType()) 
     1287        { 
     1288        case ARENA_TYPE_2v2: 
     1289            bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0)); 
     1290            break; 
     1291        case ARENA_TYPE_3v3: 
     1292            bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1)); 
     1293            break; 
     1294        case ARENA_TYPE_5v5: 
     1295            bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2)); 
     1296            break; 
     1297        default: 
     1298            break; 
     1299        } 
     1300    } 
     1301 
    6341302    // create invite events: 
    6351303    //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events 
    6361304    BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); 
    6371305    plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); 
    638     BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam()); 
     1306    BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team); 
    6391307    plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); 
    6401308} 
    6411309 
     1310BattleGround * BattleGroundMgr::GetBattleGroundTemplate(uint32 bgTypeId) 
     1311{ 
     1312    return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back(); 
     1313} 
     1314 
     1315// create a new battleground that will really be used to play 
     1316BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId) 
     1317{ 
     1318    BattleGround *bg = NULL; 
     1319 
     1320    // get the template BG 
     1321    BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId); 
     1322 
     1323    if(!bg_template) 
     1324    { 
     1325        sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId); 
     1326        return 0; 
     1327    } 
     1328     
     1329    // create a copy of the BG template 
     1330    switch(bgTypeId) 
     1331    { 
     1332        case BATTLEGROUND_AV:  
     1333            bg = new BattleGroundAV(*(BattleGroundAV*)bg_template);  
     1334            break; 
     1335        case BATTLEGROUND_WS:  
     1336            bg = new BattleGroundWS(*(BattleGroundWS*)bg_template);  
     1337            break; 
     1338        case BATTLEGROUND_AB:  
     1339            bg = new BattleGroundAB(*(BattleGroundAB*)bg_template);  
     1340            break; 
     1341        case BATTLEGROUND_NA:  
     1342            bg = new BattleGroundNA(*(BattleGroundNA*)bg_template);  
     1343            break; 
     1344        case BATTLEGROUND_BE:  
     1345            bg = new BattleGroundBE(*(BattleGroundBE*)bg_template);  
     1346            break; 
     1347        case BATTLEGROUND_AA:  
     1348            bg = new BattleGroundAA(*(BattleGroundAA*)bg_template);  
     1349            break; 
     1350        case BATTLEGROUND_EY:  
     1351            bg = new BattleGroundEY(*(BattleGroundEY*)bg_template);  
     1352            break; 
     1353        case BATTLEGROUND_RL:  
     1354            bg = new BattleGroundRL(*(BattleGroundRL*)bg_template);  
     1355            break; 
     1356        default: 
     1357            //bg = new BattleGround;    
     1358            return 0; 
     1359            break;             // placeholder for non implemented BG 
     1360    } 
     1361 
     1362    // generate a new instance id 
     1363    bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id 
     1364 
     1365    // reset the new bg (set status to status_wait_queue from status_none) 
     1366    bg->Reset(); 
     1367 
     1368    /*   will be setup in BG::Update() when the first player is ported in 
     1369    if(!(bg->SetupBattleGround())) 
     1370    { 
     1371        sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId); 
     1372        delete bg; 
     1373        return 0; 
     1374    } 
     1375    */ 
     1376 
     1377    // add BG to free slot queue 
     1378    bg->AddToBGFreeSlotQueue(); 
     1379 
     1380    // add bg to update list 
     1381    AddBattleGround(bg->GetInstanceID(), bg); 
     1382 
     1383    return bg; 
     1384} 
     1385 
     1386// used to create the BG templates 
    6421387uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO) 
    6431388{ 
     
    6591404 
    6601405    bg->SetMapId(MapID); 
     1406 
    6611407    bg->Reset(); 
    662     if(!bg->SetupBattleGround()) 
    663     { 
    664         delete bg; 
    665         return 0; 
    666     } 
    6671408 
    6681409    BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId); 
     
    6741415 
    6751416    bg->SetTypeID(bgTypeId); 
    676     bg->SetInstanceID(bgTypeId);                            // temporary 
     1417    bg->SetInstanceID(0);                               // template bg, instance id is 0 
    6771418    bg->SetMinPlayersPerTeam(MinPlayersPerTeam); 
    6781419    bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam); 
     
    6831424    bg->SetTeamStartLoc(HORDE,    Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); 
    6841425    bg->SetLevelRange(LevelMin, LevelMax); 
    685     //add BaggleGround instance to FreeSlotQueue 
     1426 
     1427    //add BattleGround instance to FreeSlotQueue (.back() will return the template!) 
    6861428    bg->AddToBGFreeSlotQueue(); 
    6871429 
    688     AddBattleGround(bg->GetInstanceID(), bg); 
    689     //sLog.outDetail("BattleGroundMgr: Created new battleground: %u %s (Map %u, %u players per team, Levels %u-%u)", bg_TypeID, bg->m_Name, bg->m_MapId, bg->m_MaxPlayersPerTeam, bg->m_LevelMin, bg->m_LevelMax); 
    690     return bg->GetInstanceID(); 
     1430    // do NOT add to update list, since this is a template battleground! 
     1431 
     1432    // return some not-null value, bgTypeId is good enough for me 
     1433    return bgTypeId;  
    6911434} 
    6921435 
     
    8081551} 
    8091552 
     1553void BattleGroundMgr::InitAutomaticArenaPointDistribution() 
     1554{ 
     1555    if(m_AutoDistributePoints) 
     1556    { 
     1557        sLog.outDebug("Initializing Automatic Arena Point Distribution"); 
     1558        QueryResult * result = CharacterDatabase.Query("SELECT UNIX_TIMESTAMP(NextArenaPointDistributionTime) FROM saved_variables"); 
     1559        if(!result) 
     1560        { 
     1561            sLog.outDebug("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now.");  
     1562            m_NextAutoDistributionTime = time(NULL) + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); 
     1563            CharacterDatabase.PExecute("INSERT INTO saved_variables (NextArenaPointDistributionTime) VALUES ( FROM_UNIXTIME('"I64FMTD"') )",(uint64)m_NextAutoDistributionTime); 
     1564        } 
     1565        else 
     1566        { 
     1567            m_NextAutoDistributionTime = (*result)[0].GetUInt64(); 
     1568            delete result; 
     1569        } 
     1570        sLog.outDebug("Automatic Arena Point Distribution initialized."); 
     1571    } 
     1572} 
     1573 
     1574void BattleGroundMgr::DistributeArenaPoints() 
     1575{ 
     1576    // used to distribute arena points based on last week's stats 
     1577 
     1578    CharacterDatabase.BeginTransaction(); 
     1579    // direct execute, because of the later GetUInt32ValueFromDB() calls 
     1580                                                                                                                                        // 1                                                                                               2                                                          3                                                 4                                                                                                                                      5                                                                              6                                                         7                                                 8                                                                                                                                  9                                                                                    10                                                 1                           2                              3                        4                                        5                                      6                        7                              8                       9                                             10 
     1581    CharacterDatabase.DirectPExecute("UPDATE characters b, arena_team_member a SET b.data = CONCAT( SUBSTRING_INDEX(b.data, ' ', '%u'),' ', CAST( IF ( ((CAST( SUBSTRING( b.data FROM (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) + 2) FOR (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - 1) ) AS UNSIGNED) + (SELECT MAX(c.points_to_add) FROM arena_team_member c WHERE c.guid = b.guid GROUP BY c.guid) ) < '%u'), CAST(SUBSTRING(b.data FROM (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) + 2) FOR (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - 1) ) AS UNSIGNED) + (SELECT MAX(d.points_to_add) FROM arena_team_member d WHERE d.guid = b.guid GROUP BY d.guid), '%u') AS CHAR),' ',SUBSTRING(b.data FROM (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) + 2))) WHERE b.guid = a.guid",PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY+1, PLAYER_FIELD_ARENA_CURRENCY, sWorld.getConfig(CONFIG_MAX_ARENA_POINTS),PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY+1, PLAYER_FIELD_ARENA_CURRENCY, sWorld.getConfig(CONFIG_MAX_ARENA_POINTS), PLAYER_FIELD_ARENA_CURRENCY+1); 
     1582    for(int i=0; i<3; ++i) 
     1583    { 
     1584        // reset weekly played matches 
     1585        uint32 position = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * i + 2; 
     1586        CharacterDatabase.DirectPExecute("UPDATE characters SET data = CONCAT( SUBSTRING_INDEX(data,' ','%u'),' ','0',' ',SUBSTRING(data FROM (CHAR_LENGTH(SUBSTRING_INDEX(data,' ','%u')) + 2)))",position, position + 1); 
     1587    } 
     1588    CharacterDatabase.DirectExecute("UPDATE arena_team_member SET points_to_add = '0', played_week = '0', wons_week = '0'"); 
     1589    CharacterDatabase.DirectExecute("UPDATE arena_team_stats SET games = '0', wins = '0'"); 
     1590    CharacterDatabase.CommitTransaction(); 
     1591 
     1592    QueryResult *result = CharacterDatabase.PQuery("SELECT guid, data FROM characters WHERE online = '1'"); 
     1593    if( result ) 
     1594    { 
     1595        do 
     1596        { 
     1597            Field *fields = result->Fetch(); 
     1598 
     1599            uint32 guid = fields[0].GetUInt32(); 
     1600            if(Player * pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER))) 
     1601            { 
     1602                Tokens data = StrSplit(fields[1].GetCppString(), " "); 
     1603                // update arena currency 
     1604                pl->SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_ARENA_CURRENCY)); 
     1605                // reset played this week count for all teams 
     1606                for(int i= 0; i < 3; ++i) 
     1607                    pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * i + 2, 0); 
     1608            } 
     1609 
     1610        } while (result->NextRow()); 
     1611 
     1612        delete result; 
     1613    } 
     1614 
     1615    for(ObjectMgr::ArenaTeamSet::iterator titr = objmgr.GetArenaTeamSetBegin(); titr != objmgr.GetArenaTeamSetEnd(); ++titr) 
     1616    { 
     1617        if(ArenaTeam * at = (*titr)) 
     1618        { 
     1619            at->FinishWeek();   // set played this week etc values to 0 in memory, too 
     1620            // at->SaveToDB(); // no need, the modified values are already saved above 
     1621            at->NotifyStatsChanged();  // notify the players of the changes 
     1622        } 
     1623    } 
     1624} 
     1625 
    8101626void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) 
    8111627{ 
     
    8431659} 
    8441660 
    845 void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId) 
    846 { 
    847     BattleGround *bg = GetBattleGround(bgTypeId); 
     1661void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) 
     1662{ 
     1663    BattleGround *bg = GetBattleGround(instanceId); 
    8481664    if(bg) 
    8491665    { 
    8501666        uint32 mapid = bg->GetMapId(); 
    8511667        float x, y, z, O; 
    852         bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O); 
     1668        uint32 team = pl->GetBGTeam(); 
     1669        if(team==0) 
     1670            team = pl->GetTeam(); 
     1671        bg->GetTeamStartLoc(team, x, y, z, O); 
    8531672 
    8541673        sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O); 
    8551674        pl->TeleportTo(mapid, x, y, z, O); 
     1675    } 
     1676    else 
     1677    { 
     1678        sLog.outError("player %u trying to port to non-existent bg instance %u",pl->GetGUIDLow(), instanceId); 
    8561679    } 
    8571680} 
     
    8661689    pl->GetSession()->SendPacket(&data); 
    8671690} 
     1691 
     1692void BattleGroundMgr::RemoveBattleGround(uint32 instanceID) 
     1693{ 
     1694    BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID); 
     1695    if(itr!=m_BattleGrounds.end()) 
     1696        m_BattleGrounds.erase(itr); 
     1697} 
     1698 
     1699bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const 
     1700{ 
     1701    return ( bgTypeId == BATTLEGROUND_AA || 
     1702        bgTypeId == BATTLEGROUND_BE || 
     1703        bgTypeId == BATTLEGROUND_NA || 
     1704        bgTypeId == BATTLEGROUND_RL ); 
     1705} 
     1706 
     1707bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const 
     1708{ 
     1709    return !IsArenaType(bgTypeId); 
     1710} 
     1711 
     1712uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const 
     1713{ 
     1714    switch(bgTypeId) 
     1715    { 
     1716    case BATTLEGROUND_WS: 
     1717        return BATTLEGROUND_QUEUE_WS; 
     1718    case BATTLEGROUND_AB: 
     1719        return BATTLEGROUND_QUEUE_AB; 
     1720    case BATTLEGROUND_AV: 
     1721        return BATTLEGROUND_QUEUE_AV; 
     1722    case BATTLEGROUND_EY: 
     1723        return BATTLEGROUND_QUEUE_EY; 
     1724    case BATTLEGROUND_AA: 
     1725    case BATTLEGROUND_NA: 
     1726    case BATTLEGROUND_RL: 
     1727    case BATTLEGROUND_BE: 
     1728        switch(arenaType) 
     1729        { 
     1730        case ARENA_TYPE_2v2: 
     1731            return BATTLEGROUND_QUEUE_2v2; 
     1732        case ARENA_TYPE_3v3: 
     1733            return BATTLEGROUND_QUEUE_3v3; 
     1734        case ARENA_TYPE_5v5: 
     1735            return BATTLEGROUND_QUEUE_5v5; 
     1736        default: 
     1737            return 0; 
     1738        } 
     1739    default: 
     1740        return 0; 
     1741    } 
     1742} 
     1743 
     1744uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const 
     1745{ 
     1746    switch(bgQueueTypeId) 
     1747    { 
     1748    case BATTLEGROUND_QUEUE_WS: 
     1749        return BATTLEGROUND_WS; 
     1750    case BATTLEGROUND_QUEUE_AB: 
     1751        return BATTLEGROUND_AB; 
     1752    case BATTLEGROUND_QUEUE_AV: 
     1753        return BATTLEGROUND_AV; 
     1754    case BATTLEGROUND_QUEUE_EY: 
     1755        return BATTLEGROUND_EY; 
     1756    case BATTLEGROUND_QUEUE_2v2: 
     1757    case BATTLEGROUND_QUEUE_3v3: 
     1758    case BATTLEGROUND_QUEUE_5v5: 
     1759        return BATTLEGROUND_AA; 
     1760    default: 
     1761        return 0; 
     1762    } 
     1763} 
     1764 
     1765uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const 
     1766{ 
     1767    switch(bgQueueTypeId) 
     1768    { 
     1769    case BATTLEGROUND_QUEUE_2v2: 
     1770        return ARENA_TYPE_2v2; 
     1771    case BATTLEGROUND_QUEUE_3v3: 
     1772        return ARENA_TYPE_3v3; 
     1773    case BATTLEGROUND_QUEUE_5v5: 
     1774        return ARENA_TYPE_5v5; 
     1775    default: 
     1776        return 0; 
     1777    } 
     1778} 
     1779 
     1780void BattleGroundMgr::ToggleArenaTesting() 
     1781{ 
     1782    m_ArenaTesting = !m_ArenaTesting; 
     1783    sWorld.SendWorldText(LANG_ARENA_TESTING, m_ArenaTesting ? "on" : "off"); 
     1784} 
  • trunk/src/game/BattleGroundMgr.h

    r2 r9  
    3535#define MAX_BATTLEGROUND_TYPES 9                            // each BG type will be in array 
    3636 
    37 struct PlayerQueueInfo 
     37#define MAX_BATTLEGROUND_QUEUE_TYPES 8 
     38 
     39#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY    86400     // seconds in a day 
     40 
     41struct GroupQueueInfo;                                      // type predefinition 
     42struct PlayerQueueInfo                                      // stores information for players in queue 
    3843{ 
    3944    uint32  InviteTime;                                     // first invite time 
    4045    uint32  LastInviteTime;                                 // last invite time 
     46    uint32  LastOnlineTime;                                 // for tracking and removing offline players from queue after 5 minutes 
     47    GroupQueueInfo * GroupInfo;                             // pointer to the associated groupqueueinfo 
     48}; 
     49 
     50struct GroupQueueInfo                                       // stores information about the group in queue (also used when joined as solo!) 
     51{ 
     52    std::map<uint64, PlayerQueueInfo*> Players;             // player queue info map 
     53    uint32  Team;                                           // Player team (ALLIANCE/HORDE) 
     54    bool    IsRated;                                        // rated 
     55    uint32  BgTypeId;                                       // battleground type id 
     56    uint8   ArenaType;                                      // 2v2, 3v3, 5v5 or 0 when BG 
     57    uint32  ArenaTeamId;                                    // team id if rated match 
     58    uint32  JoinTime;                                       // time when group was added 
    4159    uint32  IsInvitedToBGInstanceGUID;                      // was invited to certain BG 
    42     uint32  LastOnlineTime;                                 // for tracking and removing offline players from queue after 5 minutes 
    43     uint32  Team;                                           // Player team (ALLIANCE/HORDE) 
    44     bool IsRated; 
    45     bool AsGroup;                                           // uint32 GroupId; 
    46     uint8 ArenaType; 
    47 }; 
    48  
    49 struct PlayersCount 
    50 { 
    51     uint32 Alliance; 
    52     uint32 Horde; 
    53 }; 
    54  
    55 template<class _Kty, class _Ty> class bgqueue: public std::map<_Kty, _Ty> 
    56 { 
    57     public: 
    58         uint32 Alliance; 
    59         uint32 Horde; 
    60         //bool   Ready; // not used now 
    61         //uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players) 
    62 }; 
    63  
     60    uint32  ArenaTeamRating;                                // if rated match, inited to the rating of the team 
     61}; 
     62 
     63class BattleGround; 
    6464class BattleGroundQueue 
    6565{ 
     
    6767        BattleGroundQueue(); 
    6868        ~BattleGroundQueue(); 
    69 /* 
    70         uint32 GetType(); 
    71         void SetType(uint32 type);*/ 
    72  
    73         void Update(uint32 bgTypeId, uint32 queue_id); 
    74  
    75         void AddPlayer(Player *plr, uint32 bgTypeId); 
     69 
     70        void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); 
     71 
     72        GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); 
     73        void AddPlayer(Player *plr, GroupQueueInfo * ginfo); 
    7674        void RemovePlayer(uint64 guid, bool decreaseInvitedCount); 
    77  
    78         typedef bgqueue<uint64, PlayerQueueInfo> QueuedPlayersMap; 
     75        void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); 
     76        void BGEndedRemoveInvites(BattleGround * bg); 
     77 
     78        typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap; 
    7979        QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; 
    80         typedef std::list<uint64> PlayerGuidsSortedByTimeQueue; 
    81         PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES]; 
     80 
     81        typedef std::list<GroupQueueInfo*> QueuedGroupsList; 
     82        QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES]; 
     83 
     84        // class to hold pointers to the groups eligible for a specific selection pool building mode 
     85        class EligibleGroups : public std::list<GroupQueueInfo *> 
     86        { 
     87        public: 
     88            void Init(QueuedGroupsList * source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); 
     89            void RemoveGroup(GroupQueueInfo * ginfo); 
     90        }; 
     91 
     92        EligibleGroups m_EligibleGroups; 
     93 
     94        // class to select and invite groups to bg 
     95        class SelectionPool 
     96        { 
     97        public: 
     98            void Init(); 
     99            void AddGroup(GroupQueueInfo * group); 
     100            GroupQueueInfo * GetMaximalGroup(); 
     101            void RemoveGroup(GroupQueueInfo * group); 
     102            uint32 GetPlayerCount() const {return PlayerCount;} 
     103        public: 
     104            std::list<GroupQueueInfo *> SelectedGroups; 
     105        private: 
     106            uint32 PlayerCount; 
     107            GroupQueueInfo * MaxGroup; 
     108        }; 
     109 
     110        enum SelectionPoolBuildMode 
     111        { 
     112            NORMAL_ALLIANCE, 
     113            NORMAL_HORDE, 
     114            ONESIDE_ALLIANCE_TEAM1, 
     115            ONESIDE_ALLIANCE_TEAM2, 
     116            ONESIDE_HORDE_TEAM1, 
     117            ONESIDE_HORDE_TEAM2, 
     118 
     119            NUM_SELECTION_POOL_TYPES 
     120        }; 
     121 
     122        SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES]; 
     123 
     124        bool BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); 
     125 
     126    private: 
     127 
     128        bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); 
    82129}; 
    83130 
     
    97144        uint64 m_PlayerGuid; 
    98145        uint32 m_BgInstanceGUID; 
    99  
    100146}; 
    101147 
     
    116162        uint32 m_PlayersTeam; 
    117163}; 
    118  
    119164 
    120165class BattleGroundMgr 
     
    133178        void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); 
    134179        void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); 
    135         void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2); 
     180        void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); 
    136181        void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); 
    137182 
    138183        /* Player invitation */ 
    139184        // called from Queue update, or from Addplayer to queue 
    140         void InvitePlayer(Player* plr, uint32 bgInstanceGUID); 
     185        void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); 
    141186 
    142187        /* Battlegrounds */ 
     
    144189        BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; 
    145190 
    146         BattleGround* GetBattleGround(uint8 ID) 
     191        BattleGround* GetBattleGround(uint32 ID) 
    147192        { 
    148193            BattleGroundSet::iterator i = m_BattleGrounds.find(ID); 
     
    153198        }; 
    154199 
     200        BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); 
     201        BattleGround * CreateNewBattleGround(uint32 bgTypeId); 
     202 
    155203        uint32 CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); 
    156204 
    157205        inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; 
     206        void RemoveBattleGround(uint32 instanceID); 
    158207 
    159208        void CreateInitialBattleGrounds(); 
     
    163212        /* Battleground queues */ 
    164213        //these queues are instantiated when creating BattlegroundMrg 
    165         BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_TYPES]; // public, because we need to access them in BG handler code 
     214        BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; // public, because we need to access them in BG handler code 
    166215 
    167216        BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; 
    168217 
    169218        void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); 
     219 
     220        bool IsArenaType(uint32 bgTypeId) const; 
     221        bool IsBattleGroundType(uint32 bgTypeId) const; 
     222        uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const; 
     223        uint32 BGTemplateId(uint32 bgQueueTypeId) const; 
     224        uint8 BGArenaType(uint32 bgQueueTypeId) const; 
     225 
     226        uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;} 
     227        uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;} 
     228 
     229        void InitAutomaticArenaPointDistribution(); 
     230        void DistributeArenaPoints(); 
     231        uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;} 
     232        void ToggleArenaTesting(); 
     233        const bool isArenaTesting() const { return m_ArenaTesting; } 
    170234 
    171235    private: 
     
    173237        /* Battlegrounds */ 
    174238        BattleGroundSet m_BattleGrounds; 
     239        uint32 m_MaxRatingDifference; 
     240        uint32 m_RatingDiscardTimer; 
     241        uint32 m_NextRatingDiscardUpdate; 
     242        bool   m_AutoDistributePoints; 
     243        uint64 m_NextAutoDistributionTime; 
     244        uint32 m_AutoDistributionTimeChecker; 
     245        uint32 m_PrematureFinishTimer; 
     246        bool   m_ArenaTesting; 
    175247}; 
    176248 
  • trunk/src/game/BattleGroundNA.cpp

    r2 r9  
    4848        { 
    4949            m_Events |= 0x01; 
     50            // setup here, only when at least one player has ported to the map 
     51            if(!SetupBattleGround()) 
     52            { 
     53                EndNow(); 
     54                return; 
     55            } 
    5056            for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) 
    5157                SpawnBGObject(i, RESPAWN_IMMEDIATELY); 
     
    7379            for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) 
    7480                DoorOpen(i); 
     81 
     82            for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++) 
     83                SpawnBGObject(i, 60); 
    7584 
    7685            SendMessageToAll(LANG_ARENA_BEGUN); 
     
    8190                if(Player *plr = objmgr.GetPlayer(itr->first)) 
    8291                    plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); 
     92 
     93            if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 
     94                EndBattleGround(HORDE); 
     95            else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) 
     96                EndBattleGround(ALLIANCE); 
    8397        } 
    8498    } 
     
    97111 
    98112    m_PlayerScores[plr->GetGUID()] = sc; 
     113 
     114    UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); 
     115    UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); 
    99116} 
    100117 
    101118void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) 
    102119{ 
    103  
     120    if(GetStatus() == STATUS_WAIT_LEAVE) 
     121        return; 
     122 
     123    UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); 
     124    UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); 
     125 
     126    if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 
     127        EndBattleGround(HORDE); 
     128    else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) 
     129        EndBattleGround(ALLIANCE); 
    104130} 
    105131 
     
    115141    } 
    116142 
    117     BattleGround::HandleKillPlayer(player, killer); 
    118  
    119     uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); 
    120  
    121     ++m_TeamKills[killer_team_index];                       // add kills to killer's team 
    122  
    123     if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) 
     143    BattleGround::HandleKillPlayer(player,killer); 
     144 
     145    UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); 
     146    UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); 
     147 
     148    if(!GetAlivePlayersCountByTeam(ALLIANCE)) 
    124149    { 
    125150        // all opponents killed 
    126         EndBattleGround(killer->GetTeam()); 
    127     } 
     151        EndBattleGround(HORDE); 
     152    } 
     153    else if(!GetAlivePlayersCountByTeam(HORDE)) 
     154    { 
     155        // all opponents killed 
     156        EndBattleGround(ALLIANCE); 
     157    } 
     158} 
     159 
     160bool BattleGroundNA::HandlePlayerUnderMap(Player *player) 
     161{ 
     162    player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false); 
     163    return true; 
    128164} 
    129165 
     
    150186} 
    151187 
     188void BattleGroundNA::FillInitialWorldStates(WorldPacket &data) 
     189{ 
     190    data << uint32(0xa0f) << uint32(GetAlivePlayersCountByTeam(ALLIANCE));           // 7 
     191    data << uint32(0xa10) << uint32(GetAlivePlayersCountByTeam(HORDE));           // 8 
     192    data << uint32(0xa11) << uint32(1);           // 9 
     193} 
     194 
    152195void BattleGroundNA::ResetBGSubclass() 
    153196{ 
    154     m_TeamKills[BG_TEAM_ALLIANCE] = 0; 
    155     m_TeamKills[BG_TEAM_HORDE]    = 0; 
     197 
    156198} 
    157199 
     
    159201{ 
    160202    // gates 
    161     if(    !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) 
    162         || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY) 
    163         || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) 
    164         || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)) 
     203    if(    !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) 
     204        || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) 
     205        || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) 
     206        || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) 
     207    // buffs 
     208        || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) 
     209        || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) 
    165210    { 
    166211        sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); 
  • trunk/src/game/BattleGroundNA.h

    r2 r9  
    2727    BG_NA_OBJECT_DOOR_3         = 2, 
    2828    BG_NA_OBJECT_DOOR_4         = 3, 
    29     BG_NA_OBJECT_MAX            = 4 
     29    BG_NA_OBJECT_BUFF_1         = 4, 
     30    BG_NA_OBJECT_BUFF_2         = 5, 
     31    BG_NA_OBJECT_MAX            = 6 
    3032}; 
    3133 
     
    3537    BG_NA_OBJECT_TYPE_DOOR_2    = 183980, 
    3638    BG_NA_OBJECT_TYPE_DOOR_3    = 183977, 
    37     BG_NA_OBJECT_TYPE_DOOR_4    = 183979 
     39    BG_NA_OBJECT_TYPE_DOOR_4    = 183979, 
     40    BG_NA_OBJECT_TYPE_BUFF_1    = 184663, 
     41    BG_NA_OBJECT_TYPE_BUFF_2    = 184664 
    3842}; 
    3943 
     
    6266        bool SetupBattleGround(); 
    6367        virtual void ResetBGSubclass(); 
     68        virtual void FillInitialWorldStates(WorldPacket &d); 
    6469        void HandleKillPlayer(Player* player, Player *killer); 
    65  
    66     private: 
    67         uint32 m_TeamKills[2];                              // count of kills for each team 
     70        bool HandlePlayerUnderMap(Player * plr); 
    6871}; 
    6972#endif 
  • trunk/src/game/BattleGroundRL.cpp

    r2 r9  
    4848            m_Events |= 0x01; 
    4949 
     50            // setup here, only when at least one player has ported to the map 
     51            if(!SetupBattleGround()) 
     52            { 
     53                EndNow(); 
     54                return; 
     55            } 
     56 
    5057            for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) 
    5158                SpawnBGObject(i, RESPAWN_IMMEDIATELY); 
     
    7380            for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) 
    7481                DoorOpen(i); 
     82 
     83            for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++) 
     84                SpawnBGObject(i, 60); 
    7585 
    7686            SendMessageToAll(LANG_ARENA_BEGUN); 
     
    8191                if(Player *plr = objmgr.GetPlayer(itr->first)) 
    8292                    plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); 
     93 
     94            if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 
     95                EndBattleGround(HORDE); 
     96            else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) 
     97                EndBattleGround(ALLIANCE); 
    8398        } 
    8499    } 
     
    97112 
    98113    m_PlayerScores[plr->GetGUID()] = sc; 
     114 
     115    UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); 
     116    UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); 
    99117} 
    100118 
    101119void BattleGroundRL::RemovePlayer(Player *plr, uint64 guid) 
    102120{ 
    103  
     121    if(GetStatus() == STATUS_WAIT_LEAVE) 
     122        return; 
     123 
     124    UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); 
     125    UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); 
     126 
     127    if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 
     128        EndBattleGround(HORDE); 
     129    else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) 
     130        EndBattleGround(ALLIANCE); 
    104131} 
    105132 
     
    115142    } 
    116143 
    117     BattleGround::HandleKillPlayer(player, killer); 
    118  
    119     uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); 
    120  
    121     ++m_TeamKills[killer_team_index];                       // add kills to killer's team 
    122  
    123     if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) 
     144    BattleGround::HandleKillPlayer(player,killer); 
     145 
     146    UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); 
     147    UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); 
     148 
     149    if(!GetAlivePlayersCountByTeam(ALLIANCE)) 
    124150    { 
    125151        // all opponents killed 
    126         EndBattleGround(killer->GetTeam()); 
    127     } 
     152        EndBattleGround(HORDE); 
     153    } 
     154    else if(!GetAlivePlayersCountByTeam(HORDE)) 
     155    { 
     156        // all opponents killed 
     157        EndBattleGround(ALLIANCE); 
     158    } 
     159} 
     160 
     161bool BattleGroundRL::HandlePlayerUnderMap(Player *player) 
     162{ 
     163    player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false); 
     164    return true; 
    128165} 
    129166 
     
    151188} 
    152189 
     190void BattleGroundRL::FillInitialWorldStates(WorldPacket &data) 
     191{ 
     192    data << uint32(0xbb8) << uint32(GetAlivePlayersCountByTeam(ALLIANCE));           // 7 
     193    data << uint32(0xbb9) << uint32(GetAlivePlayersCountByTeam(HORDE));           // 8 
     194    data << uint32(0xbba) << uint32(1);           // 9 
     195} 
     196 
    153197void BattleGroundRL::ResetBGSubclass() 
    154198{ 
    155     m_TeamKills[BG_TEAM_ALLIANCE] = 0; 
    156     m_TeamKills[BG_TEAM_HORDE]    = 0; 
     199 
    157200} 
    158201 
     
    160203{ 
    161204    // gates 
    162     if(    !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY) 
    163         || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)) 
     205    if(    !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) 
     206        || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) 
     207    // buffs 
     208        || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) 
     209        || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) 
    164210    { 
    165211        sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); 
  • trunk/src/game/BattleGroundRL.h

    r2 r9  
    2525    BG_RL_OBJECT_DOOR_1         = 0, 
    2626    BG_RL_OBJECT_DOOR_2         = 1, 
    27     BG_RL_OBJECT_MAX            = 2 
     27    BG_RL_OBJECT_BUFF_1         = 2, 
     28    BG_RL_OBJECT_BUFF_2         = 3, 
     29    BG_RL_OBJECT_MAX            = 4 
    2830}; 
    2931 
     
    3133{ 
    3234    BG_RL_OBJECT_TYPE_DOOR_1    = 185918, 
    33     BG_RL_OBJECT_TYPE_DOOR_2    = 185917 
     35    BG_RL_OBJECT_TYPE_DOOR_2    = 185917, 
     36    BG_RL_OBJECT_TYPE_BUFF_1    = 184663, 
     37    BG_RL_OBJECT_TYPE_BUFF_2    = 184664 
    3438}; 
    3539 
     
    5862        bool SetupBattleGround(); 
    5963        virtual void ResetBGSubclass(); 
     64        virtual void FillInitialWorldStates(WorldPacket &d); 
    6065        void HandleKillPlayer(Player* player, Player *killer); 
    61  
    62     private: 
    63         uint32 m_TeamKills[2];                              // count of kills for each team 
     66        bool HandlePlayerUnderMap(Player * plr); 
    6467}; 
    6568#endif 
  • trunk/src/game/BattleGroundWS.cpp

    r2 r9  
    5050            m_Events |= 0x01; 
    5151 
     52            // setup here, only when at least one player has ported to the map 
     53            if(!SetupBattleGround()) 
     54            { 
     55                EndNow(); 
     56                return; 
     57            } 
     58 
    5259            for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) 
    5360            { 
     
    286293void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) 
    287294{ 
    288     // Drop allowed in any BG state 
     295    if(GetStatus() != STATUS_IN_PROGRESS) 
     296    { 
     297        // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages 
     298        // just take off the aura 
     299        if(Source->GetTeam() == ALLIANCE) 
     300        { 
     301            if(!this->IsHordeFlagPickedup()) 
     302                return; 
     303            if(GetHordeFlagPickerGUID() == Source->GetGUID()) 
     304            { 
     305                SetHordeFlagPicker(0); 
     306                Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); 
     307            } 
     308        } 
     309        else 
     310        { 
     311            if(!this->IsAllianceFlagPickedup()) 
     312                return; 
     313            if(GetAllianceFlagPickerGUID() == Source->GetGUID()) 
     314            { 
     315                SetAllianceFlagPicker(0); 
     316                Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); 
     317            } 
     318        } 
     319        return; 
     320    } 
    289321 
    290322    const char *message = ""; 
  • trunk/src/game/Chat.cpp

    r6 r9  
    164164        { "anim",           SEC_GAMEMASTER,     &ChatHandler::HandleAnimCommand,                "", NULL }, 
    165165        { "lootrecipient",  SEC_GAMEMASTER,     &ChatHandler::HandleGetLootRecipient,           "", NULL }, 
     166        { "arena",          SEC_ADMINISTRATOR,  &ChatHandler::HandleDebugArenaCommand,          "", NULL }, 
    166167        { NULL,             0,                  NULL,                                           "", NULL } 
    167168    }; 
     
    512513        { "damage",         SEC_ADMINISTRATOR,  &ChatHandler::HandleDamageCommand,              "", NULL }, 
    513514        { "combatstop",     SEC_GAMEMASTER,     &ChatHandler::HandleCombatStopCommand,          "", NULL }, 
     515        { "flusharenapoints",    SEC_ADMINISTRATOR, &ChatHandler::HandleFlushArenaPointsCommand,         "",   NULL }, 
    514516 
    515517        { NULL,             0,                  NULL,                                           "", NULL } 
  • trunk/src/game/Chat.h

    r6 r9  
    381381        bool HandleComeToMeCommand(const char *args); 
    382382        bool HandleCombatStopCommand(const char *args); 
     383        bool HandleFlushArenaPointsCommand(const char *args); 
    383384 
    384385        //! Development Commands 
     
    393394        bool HandleGetItemState(const char * args); 
    394395        bool HandleGetLootRecipient(const char * args); 
     396        bool HandleDebugArenaCommand(const char * args); 
    395397 
    396398        Player*   getSelectedPlayer(); 
  • trunk/src/game/Group.cpp

    r2 r9  
    12451245} 
    12461246 
     1247uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) 
     1248{ 
     1249    // check for min / max count 
     1250    uint32 memberscount = GetMembersCount(); 
     1251    if(memberscount < MinPlayerCount) 
     1252        return BG_JOIN_ERR_GROUP_NOT_ENOUGH; 
     1253    if(memberscount > MaxPlayerCount) 
     1254        return BG_JOIN_ERR_GROUP_TOO_MANY; 
     1255 
     1256    // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) 
     1257    Player * reference = GetFirstMember()->getSource(); 
     1258    // no reference found, can't join this way 
     1259    if(!reference) 
     1260        return BG_JOIN_ERR_OFFLINE_MEMBER; 
     1261 
     1262    uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel(); 
     1263    uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); 
     1264    uint32 team = reference->GetTeam(); 
     1265 
     1266    // check every member of the group to be able to join 
     1267    for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) 
     1268    { 
     1269        Player *member = itr->getSource(); 
     1270        // offline member? don't let join 
     1271        if(!member) 
     1272            return BG_JOIN_ERR_OFFLINE_MEMBER; 
     1273        // don't allow cross-faction join as group 
     1274        if(member->GetTeam() != team) 
     1275            return BG_JOIN_ERR_MIXED_FACTION; 
     1276        // not in the same battleground level braket, don't let join 
     1277        if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId) 
     1278            return BG_JOIN_ERR_MIXED_LEVELS; 
     1279        // don't let join rated matches if the arena team id doesn't match 
     1280        if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) 
     1281            return BG_JOIN_ERR_MIXED_ARENATEAM; 
     1282        // don't let join if someone from the group is already in that bg queue 
     1283        if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType)) 
     1284            return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE; 
     1285        // check for deserter debuff in case not arena queue 
     1286        if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground()) 
     1287            return BG_JOIN_ERR_GROUP_DESERTER; 
     1288        // check if member can join any more battleground queues 
     1289        if(!member->HasFreeBattleGroundQueueId()) 
     1290            return BG_JOIN_ERR_ALL_QUEUES_USED; 
     1291    } 
     1292    return BG_JOIN_ERR_OK; 
     1293} 
     1294 
    12471295//=================================================== 
    12481296//============== Roll =============================== 
  • trunk/src/game/Group.h

    r2 r9  
    233233        } 
    234234        void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } 
     235        uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); 
    235236 
    236237        void ChangeMembersGroup(const uint64 &guid, const uint8 &group); 
  • trunk/src/game/Language.h

    r6 r9  
    608608    LANG_PLAYER_AFK_DEFAULT             = 710, 
    609609 
    610     LANG_BG_QUEUE_ANNOUNCE_SELF         = 711, 
    611     LANG_BG_QUEUE_ANNOUNCE_WORLD        = 712, 
     610    LANG_BG_GROUP_TOO_LARGE             = 711, 
     611    LANG_ARENA_GROUP_TOO_LARGE          = 712, 
     612    LANG_ARENA_YOUR_TEAM_ONLY           = 713, 
     613    LANG_ARENA_NOT_ENOUGH_PLAYERS       = 714, 
     614    LANG_ARENA_GOLD_WINS                = 715, 
     615    LANG_ARENA_GREEN_WINS               = 716, 
     616    LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 717, 
     617    LANG_BG_GROUP_OFFLINE_MEMBER        = 718, 
     618    LANG_BG_GROUP_MIXED_FACTION         = 719, 
     619    LANG_BG_GROUP_MIXED_LEVELS          = 720, 
     620    LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 721, 
     621    LANG_BG_GROUP_MEMBER_DESERTER       = 722, 
     622    LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 723, 
     623 
     624    LANG_CANNOT_TELE_TO_BG              = 724, 
     625    LANG_CANNOT_SUMMON_TO_BG            = 725, 
     626    LANG_CANNOT_GO_TO_BG_GM             = 726, 
     627    LANG_CANNOT_GO_TO_BG_FROM_BG        = 727, 
     628 
     629    LANG_ARENA_TESTING                  = 728 
     630 
    612631}; 
    613632#endif 
  • trunk/src/game/Level1.cpp

    r6 r9  
    316316        Map* pMap = MapManager::Instance().GetMap(m_session->GetPlayer()->GetMapId(),m_session->GetPlayer()); 
    317317 
    318         if(pMap->Instanceable()) 
     318        if(pMap->IsBattleGroundOrArena()) 
     319        { 
     320            // cannot summon to bg 
     321            SendSysMessage(LANG_CANNOT_SUMMON_TO_BG); 
     322            SetSentErrorMessage(true); 
     323            return false; 
     324        } 
     325        else if(pMap->IsDungeon()) 
    319326        { 
    320327            Map* cMap = MapManager::Instance().GetMap(chr->GetMapId(),chr); 
     
    402409    { 
    403410        Map* cMap = MapManager::Instance().GetMap(chr->GetMapId(),chr); 
    404         if(cMap->Instanceable()) 
     411        if(cMap->IsBattleGroundOrArena()) 
     412        { 
     413            // only allow if gm mode is on 
     414            if (!_player->isGameMaster()) 
     415            { 
     416                SendSysMessage(LANG_CANNOT_GO_TO_BG_GM); 
     417                SetSentErrorMessage(true); 
     418                return false; 
     419            } 
     420            // if already in a bg, don't let port to other 
     421            else if (_player->GetBattleGroundId()) 
     422            { 
     423                SendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG); 
     424                SetSentErrorMessage(true); 
     425                return false; 
     426            } 
     427            // all's well, set bg id 
     428            // when porting out from the bg, it will be reset to 0 
     429            _player->SetBattleGroundId(chr->GetBattleGroundId()); 
     430        } 
     431        else if(cMap->IsDungeon()) 
    405432        { 
    406433            Map* pMap = MapManager::Instance().GetMap(_player->GetMapId(),_player); 
     
    15861613    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r 
    15871614    GameTele const* tele = extractGameTeleFromLink((char*)args); 
    1588  
    15891615    if (!tele) 
    15901616    { 
    15911617        SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); 
     1618        SetSentErrorMessage(true); 
     1619        return false; 
     1620    } 
     1621 
     1622    MapEntry const * me = sMapStore.LookupEntry(tele->mapId); 
     1623    if(!me || me->IsBattleGroundOrArena()) 
     1624    { 
     1625        SendSysMessage(LANG_CANNOT_TELE_TO_BG); 
    15921626        SetSentErrorMessage(true); 
    15931627        return false; 
     
    18661900    } 
    18671901 
     1902    MapEntry const * me = sMapStore.LookupEntry(tele->mapId); 
     1903    if(!me || me->IsBattleGroundOrArena()) 
     1904    { 
     1905        SendSysMessage(LANG_CANNOT_TELE_TO_BG); 
     1906        SetSentErrorMessage(true); 
     1907        return false; 
     1908    } 
     1909 
    18681910    Player *chr = objmgr.GetPlayer(name.c_str()); 
    18691911    if (chr) 
     
    19281970    } 
    19291971 
     1972    MapEntry const * me = sMapStore.LookupEntry(tele->mapId); 
     1973    if(!me || me->IsBattleGroundOrArena()) 
     1974    { 
     1975        SendSysMessage(LANG_CANNOT_TELE_TO_BG); 
     1976        SetSentErrorMessage(true); 
     1977        return false; 
     1978    } 
    19301979    Group *grp = player->GetGroup(); 
    19311980    if(!grp) 
  • trunk/src/game/Level3.cpp

    r6 r9  
    4747#include "Util.h" 
    4848#include "ItemEnchantmentMgr.h" 
     49#include "BattleGroundMgr.h" 
    4950#include "InstanceSaveMgr.h" 
    5051#include "InstanceData.h" 
     
    54585459    return true; 
    54595460} 
     5461 
     5462bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) 
     5463{ 
     5464    sBattleGroundMgr.DistributeArenaPoints(); 
     5465    return true; 
     5466} 
  • trunk/src/game/MapInstanced.cpp

    r2 r9  
    142142            Player* player = (Player*)obj; 
    143143 
    144             // TODO: battlegrounds and arenas 
     144            if(IsBattleGroundOrArena()) 
     145            { 
     146                // instantiate or find existing bg map for player 
     147                // the instance id is set in battlegroundid 
     148                NewInstanceId = player->GetBattleGroundId(); 
     149                assert(NewInstanceId); 
     150                map = _FindMap(NewInstanceId); 
     151                if(!map) 
     152                    map = CreateBattleGround(NewInstanceId); 
     153                return map; 
     154            } 
    145155 
    146156            InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); 
  • trunk/src/game/MapManager.cpp

    r2 r9  
    108108 
    109109        const MapEntry* entry = sMapStore.LookupEntry(id); 
    110         if (entry && entry->IsDungeon()) 
     110        if (entry && entry->Instanceable()) 
    111111        { 
    112112            m = new MapInstanced(id, i_gridCleanUpDelay, 0); 
  • trunk/src/game/MiscHandler.cpp

    r2 r9  
    847847        return; 
    848848 
     849    if (BattleGround * bg = _player->GetBattleGround()) 
     850        if(bg->isArena()) 
     851            return; 
     852 
    849853    // body not released yet 
    850854    if(!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) 
  • trunk/src/game/MovementHandler.cpp

    r2 r9  
    131131 
    132132    // battleground state preper 
    133     if(_player->InBattleGround()) 
     133    // only add to bg group and object, if the player was invited (else he entered through command) 
     134    if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) 
    134135    { 
    135136        BattleGround *bg = _player->GetBattleGround(); 
    136137        if(bg) 
    137138        { 
     139            bg->AddPlayer(_player); 
    138140            if(bg->GetMapId() == _player->GetMapId())       // we teleported to bg 
    139141            { 
    140                 if(!bg->GetBgRaid(_player->GetTeam()))      // first player joined 
     142                // get the team this way, because arenas might 'override' the teams. 
     143                uint32 team = bg->GetPlayerTeam(_player->GetGUID()); 
     144                if(!team) 
     145                    team = _player->GetTeam(); 
     146                if(!bg->GetBgRaid(team))      // first player joined 
    141147                { 
    142148                    Group *group = new Group; 
    143                     bg->SetBgRaid(_player->GetTeam(), group); 
     149                    bg->SetBgRaid(team, group); 
    144150                    group->Create(_player->GetGUIDLow(), _player->GetName()); 
    145151                } 
    146152                else                                        // raid already exist 
    147153                { 
    148                     bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName()); 
     154                    bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName()); 
    149155                } 
    150156            } 
     
    366372    if(movementInfo.z < -500.0f) 
    367373    { 
    368         // NOTE: this is actually called many times while falling 
    369         // even after the player has been teleported away 
    370         // TODO: discard movement packets after the player is rooted 
    371         if(GetPlayer()->isAlive()) 
    372         { 
    373             GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); 
    374             // change the death state to CORPSE to prevent the death timer from 
    375             // starting in the next player update 
    376             GetPlayer()->KillPlayer(); 
    377             GetPlayer()->BuildPlayerRepop(); 
    378         } 
    379  
    380         // cancel the death timer here if started 
    381         GetPlayer()->RepopAtGraveyard(); 
     374        if(GetPlayer()->InBattleGround()  
     375            && GetPlayer()->GetBattleGround()  
     376            && GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player)) 
     377        { 
     378            // do nothing, the handle already did if returned true 
     379        } 
     380        else 
     381        { 
     382            // NOTE: this is actually called many times while falling 
     383            // even after the player has been teleported away 
     384            // TODO: discard movement packets after the player is rooted 
     385            if(GetPlayer()->isAlive()) 
     386            { 
     387                GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); 
     388                // change the death state to CORPSE to prevent the death timer from 
     389                // starting in the next player update 
     390                GetPlayer()->KillPlayer(); 
     391                GetPlayer()->BuildPlayerRepop(); 
     392            } 
     393 
     394            // cancel the death timer here if started 
     395            GetPlayer()->RepopAtGraveyard(); 
     396        } 
    382397    } 
    383398} 
  • trunk/src/game/ObjectMgr.h

    r6 r9  
    311311        void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); } 
    312312        void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); } 
     313        ArenaTeamSet::iterator GetArenaTeamSetBegin() { return mArenaTeamSet.begin(); } 
     314        ArenaTeamSet::iterator GetArenaTeamSetEnd() { return mArenaTeamSet.end(); } 
    313315 
    314316        static CreatureInfo const *GetCreatureTemplate( uint32 id ); 
  • trunk/src/game/Player.cpp

    r6 r9  
    347347    for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++) 
    348348    { 
    349         m_bgBattleGroundQueueID[j].bgType  = 0; 
    350         m_bgBattleGroundQueueID[j].invited = false; 
     349        m_bgBattleGroundQueueID[j].bgQueueType  = 0; 
     350        m_bgBattleGroundQueueID[j].invitedToInstance = 0; 
    351351    } 
    352352    m_bgTeam = 0; 
     
    14401440 
    14411441    // don't let enter battlegrounds without assigned battleground id (for example through areatrigger)... 
    1442     if(!InBattleGround() && mEntry->IsBattleGround() && !GetSession()->GetSecurity()) 
     1442    // don't let gm level > 1 either 
     1443    if(!InBattleGround() && mEntry->IsBattleGroundOrArena()) 
    14431444        return false; 
    14441445 
     
    34533454        if(guild) 
    34543455            guild->DelMember(guid); 
     3456    } 
     3457 
     3458    // remove from arena teams 
     3459    uint32 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_2v2); 
     3460    if(at_id != 0) 
     3461    { 
     3462        ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 
     3463        if(at) 
     3464            at->DelMember(playerguid); 
     3465    } 
     3466    at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_3v3); 
     3467    if(at_id != 0) 
     3468    { 
     3469        ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 
     3470        if(at) 
     3471            at->DelMember(playerguid); 
     3472    } 
     3473    at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_5v5); 
     3474    if(at_id != 0) 
     3475    { 
     3476        ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 
     3477        if(at) 
     3478            at->DelMember(playerguid); 
    34553479    } 
    34563480 
     
    58845908    UpdateHonorFields(); 
    58855909 
     5910    // do not reward honor in arenas, but return true to enable onkill spellproc 
     5911    if(InBattleGround() && GetBattleGround() && GetBattleGround()->isArena()) 
     5912        return true; 
     5913 
    58865914    if(honor <= 0) 
    58875915    { 
     
    60476075uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) 
    60486076{ 
    6049     // need fix it! 
    60506077    QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid FROM arena_team_member WHERE guid='%u'", GUID_LOPART(guid)); 
    60516078    if(result) 
    60526079    { 
    6053         // init id to 0, check the arena type before assigning a value to id 
    6054         uint32 id = 0; 
     6080        bool found = false; 
     6081        // init id to find the type of the arenateam 
     6082        uint32 id = (*result)[0].GetUInt32(); 
    60556083        do 
    60566084        { 
     
    60636091                { 
    60646092                    // if the type matches, we've found the id 
    6065                     id = (*result)[0].GetUInt32(); 
     6093                    found = true; 
    60666094                    break; 
    60676095                } 
     
    60696097        } while(result->NextRow()); 
    60706098        delete result; 
    6071         return id; 
     6099        if(found) return id; 
    60726100    } 
    60736101    // no arenateam for the specified guid, return 0 
     
    77107738            break; 
    77117739        case 3698:                                          // Nagrand Arena 
    7712             data << uint32(0xa0f) << uint32(0x0);           // 7 
    7713             data << uint32(0xa10) << uint32(0x0);           // 8 
    7714             data << uint32(0xa11) << uint32(0x0);           // 9 
     7740            if (bg && bg->GetTypeID() == BATTLEGROUND_NA) 
     7741                bg->FillInitialWorldStates(data); 
     7742            else 
     7743            { 
     7744                data << uint32(0xa0f) << uint32(0x0);           // 7 
     7745                data << uint32(0xa10) << uint32(0x0);           // 8 
     7746                data << uint32(0xa11) << uint32(0x0);           // 9 show 
     7747            } 
    77157748            break; 
    77167749        case 3702:                                          // Blade's Edge Arena 
    7717             data << uint32(0x9f0) << uint32(0x0);           // 7 
    7718             data << uint32(0x9f1) << uint32(0x0);           // 8 
    7719             data << uint32(0x9f3) << uint32(0x0);           // 9 
     7750            if (bg && bg->GetTypeID() == BATTLEGROUND_BE) 
     7751                bg->FillInitialWorldStates(data); 
     7752            else 
     7753            { 
     7754                data << uint32(0x9f0) << uint32(0x0);           // 7 gold 
     7755                data << uint32(0x9f1) << uint32(0x0);           // 8 green 
     7756                data << uint32(0x9f3) << uint32(0x0);           // 9 show 
     7757            } 
    77207758            break; 
    77217759        case 3968:                                          // Ruins of Lordaeron 
    7722             data << uint32(0xbb8) << uint32(0x0);           // 7 
    7723             data << uint32(0xbb9) << uint32(0x0);           // 8 
    7724             data << uint32(0xbba) << uint32(0x0);           // 9 
     7760            if (bg && bg->GetTypeID() == BATTLEGROUND_RL) 
     7761                bg->FillInitialWorldStates(data); 
     7762            else 
     7763            { 
     7764                data << uint32(0xbb8) << uint32(0x0);           // 7 gold  
     7765                data << uint32(0xbb9) << uint32(0x0);           // 8 green 
     7766                data << uint32(0xbba) << uint32(0x0);           // 9 show 
     7767            } 
    77257768            break; 
    77267769        case 3703:                                          // Shattrath City 
     
    1471114754    UpdateHonorFields(); 
    1471214755 
    14713     // Must saved before enter into BattleGround 
    14714     if(InBattleGround()) 
     14756    // players aren't saved on battleground maps 
     14757    uint32 mapid = IsBeingTeleported() ? GetTeleportDest().mapid : GetMapId(); 
     14758    const MapEntry * me = sMapStore.LookupEntry(mapid); 
     14759    if(!me || me->IsBattleGroundOrArena()) 
    1471514760        return; 
    1471614761 
     
    1746117506bool Player::GetBGAccessByLevel(uint32 bgTypeId) const 
    1746217507{ 
    17463     BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 
     17508    // get a template bg instead of running one 
     17509    BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 
    1746417510    if(!bg) 
    1746517511        return false; 
  • trunk/src/game/Player.h

    r6 r9  
    18031803        uint32 GetBattleGroundQueueIdFromLevel() const; 
    18041804 
    1805         uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; } 
    1806         uint32 GetBattleGroundQueueIndex(uint32 bgType) const 
     1805        bool InBattleGroundQueue() const          
     1806            {     
     1807                for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)    
     1808                if (m_bgBattleGroundQueueID[i].bgQueueType != 0)          
     1809                        return true;      
     1810                return false;     
     1811            } 
     1812 
     1813        uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueType; } 
     1814        uint32 GetBattleGroundQueueIndex(uint32 bgQueueType) const 
    18071815        { 
    18081816            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    1809                 if (m_bgBattleGroundQueueID[i].bgType == bgType) 
     1817                if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) 
    18101818                    return i; 
    18111819            return PLAYER_MAX_BATTLEGROUND_QUEUES; 
    18121820        } 
    1813         bool IsInvitedForBattleGroundType(uint32 bgType) const 
     1821        bool IsInvitedForBattleGroundQueueType(uint32 bgQueueType) const 
    18141822        { 
    18151823            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    1816                 if (m_bgBattleGroundQueueID[i].bgType == bgType) 
    1817                     return m_bgBattleGroundQueueID[i].invited; 
     1824                if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) 
     1825                    return m_bgBattleGroundQueueID[i].invitedToInstance != 0; 
    18181826            return PLAYER_MAX_BATTLEGROUND_QUEUES; 
    18191827        } 
    1820         bool InBattleGroundQueueForBattleGroundType(uint32 bgType) const 
    1821         { 
    1822             return GetBattleGroundQueueIndex(bgType) < PLAYER_MAX_BATTLEGROUND_QUEUES; 
     1828        bool InBattleGroundQueueForBattleGroundQueueType(uint32 bgQueueType) const 
     1829        { 
     1830            return GetBattleGroundQueueIndex(bgQueueType) < PLAYER_MAX_BATTLEGROUND_QUEUES; 
    18231831        } 
    18241832 
     
    18281836            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    18291837            { 
    1830                 if (m_bgBattleGroundQueueID[i].bgType == 0 || m_bgBattleGroundQueueID[i].bgType == val) 
     1838                if (m_bgBattleGroundQueueID[i].bgQueueType == 0 || m_bgBattleGroundQueueID[i].bgQueueType == val) 
    18311839                { 
    1832                     m_bgBattleGroundQueueID[i].bgType = val; 
    1833                     m_bgBattleGroundQueueID[i].invited = false; 
     1840                    m_bgBattleGroundQueueID[i].bgQueueType = val; 
     1841                    m_bgBattleGroundQueueID[i].invitedToInstance = 0; 
    18341842                    return i; 
    18351843                } 
     
    18371845            return PLAYER_MAX_BATTLEGROUND_QUEUES; 
    18381846        } 
     1847        bool HasFreeBattleGroundQueueId() 
     1848        { 
     1849            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
     1850                if (m_bgBattleGroundQueueID[i].bgQueueType == 0) 
     1851                    return true; 
     1852            return false; 
     1853        } 
    18391854        void RemoveBattleGroundQueueId(uint32 val) 
    18401855        { 
    18411856            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    18421857            { 
    1843                 if (m_bgBattleGroundQueueID[i].bgType == val) 
     1858                if (m_bgBattleGroundQueueID[i].bgQueueType == val) 
    18441859                { 
    1845                     m_bgBattleGroundQueueID[i].bgType = 0; 
    1846                     m_bgBattleGroundQueueID[i].invited = false; 
     1860                    m_bgBattleGroundQueueID[i].bgQueueType = 0; 
     1861                    m_bgBattleGroundQueueID[i].invitedToInstance = 0; 
    18471862                    return; 
    18481863                } 
    18491864            } 
    18501865        } 
    1851         void SetInviteForBattleGroundType(uint32 bgType) 
     1866        void SetInviteForBattleGroundQueueType(uint32 bgQueueType, uint32 instanceId) 
    18521867        { 
    18531868            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
    1854                 if (m_bgBattleGroundQueueID[i].bgType == bgType) 
    1855                     m_bgBattleGroundQueueID[i].invited = true; 
    1856         } 
    1857  
     1869                if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) 
     1870                    m_bgBattleGroundQueueID[i].invitedToInstance = instanceId; 
     1871        } 
     1872        bool IsInvitedForBattleGroundInstance(uint32 instanceId) const 
     1873        { 
     1874            for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 
     1875                if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId) 
     1876                    return true; 
     1877            return false; 
     1878        } 
    18581879        uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } 
    18591880        float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } 
     
    20352056        struct BgBattleGroundQueueID_Rec 
    20362057        { 
    2037             uint32 bgType; 
    2038             bool   invited; 
     2058            uint32 bgQueueType; 
     2059            uint32 invitedToInstance; 
    20392060        }; 
    20402061        BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; 
     
    20502071        uint32 m_contestedPvPTimer; 
    20512072 
    2052         uint32 m_bgTeam;                                    // what side the player will be added to 
     2073        uint32 m_bgTeam;    // what side the player will be added to 
    20532074 
    20542075        /*********************************************************/ 
  • trunk/src/game/SpellEffects.cpp

    r6 r9  
    25192519        } 
    25202520 
    2521         if(BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgType)) 
     2521        if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType)) 
    25222522            bg->SendRewardMarkByMail(player,newitemid,no_space); 
    25232523    } 
  • trunk/src/game/Unit.cpp

    r6 r9  
    594594    if (health <= damage) 
    595595    { 
    596         // battleground things 
    597         if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround())) 
    598         { 
    599             Player *killed = ((Player*)pVictim); 
    600             Player *killer = NULL; 
    601             if(GetTypeId() == TYPEID_PLAYER) 
    602                 killer = ((Player*)this); 
    603             else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) 
    604             { 
    605                 Unit *owner = GetOwner(); 
    606                 if(owner && owner->GetTypeId() == TYPEID_PLAYER) 
    607                     killer = ((Player*)owner); 
    608             } 
    609  
    610             if(killer) 
    611                 if(BattleGround *bg = killed->GetBattleGround()) 
    612                     bg->HandleKillPlayer(killed, killer);   // drop flags and etc 
    613         } 
    614  
    615596        DEBUG_LOG("DealDamage: victim just died"); 
    616597 
     
    750731 
    751732            he->DuelComplete(DUEL_INTERUPTED); 
     733        } 
     734 
     735        // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill) 
     736        if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround())) 
     737        { 
     738            Player *killed = ((Player*)pVictim); 
     739            Player *killer = NULL; 
     740            if(GetTypeId() == TYPEID_PLAYER) 
     741                killer = ((Player*)this); 
     742            else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) 
     743            { 
     744                Unit *owner = GetOwner(); 
     745                if(owner && owner->GetTypeId() == TYPEID_PLAYER) 
     746                    killer = ((Player*)owner); 
     747            } 
     748 
     749            if(killer) 
     750                if(BattleGround *bg = killed->GetBattleGround()) 
     751                    bg->HandleKillPlayer(killed, killer);   // drop flags and etc 
    752752        } 
    753753    } 
     
    41414141        AuraMap::iterator iter = m_Auras.begin(); 
    41424142        RemoveAura(iter); 
     4143    } 
     4144} 
     4145 
     4146void Unit::RemoveArenaAuras(bool onleave) 
     4147{ 
     4148    // in join, remove positive buffs, on end, remove negative 
     4149    // used to remove positive visible auras in arenas 
     4150    for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) 
     4151    { 
     4152        if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras 
     4153            && !iter->second->IsPassive()                               // don't remove passive auras 
     4154            && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8))   // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) 
     4155            && (iter->second->IsPositive() ^ onleave))                   // remove positive buffs on enter, negative buffs on leave 
     4156            RemoveAura(iter); 
     4157        else 
     4158            ++iter; 
    41434159    } 
    41444160} 
  • trunk/src/game/Unit.h

    r6 r9  
    10041004 
    10051005        void RemoveAllAuras(); 
     1006        void RemoveArenaAuras(bool onleave = false); 
    10061007        void RemoveAllAurasOnDeath(); 
    10071008        void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); 
  • trunk/src/game/World.cpp

    r6 r9  
    630630 
    631631    m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER]              = sConfig.GetBoolDefault("Battleground.CastDeserter", true); 
    632     m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE]     = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", true); 
    633     m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false); 
    634632 
    635633    m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true); 
     
    770768    m_configs[CONFIG_LISTEN_RANGE_YELL]      = sConfig.GetIntDefault("ListenRange.Yell", 300); 
    771769 
     770 
     771    m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0); 
     772    m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000); 
     773    m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); 
     774    m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7); 
     775 
     776    m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0); 
    772777 
    773778    m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); 
     
    11571162    sLog.outString( "Starting BattleGround System" ); 
    11581163    sBattleGroundMgr.CreateInitialBattleGrounds(); 
     1164    sBattleGroundMgr.InitAutomaticArenaPointDistribution(); 
    11591165 
    11601166    //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager 
  • trunk/src/game/World.h

    r6 r9  
    102102    CONFIG_INSTANCE_IGNORE_RAID, 
    103103    CONFIG_BATTLEGROUND_CAST_DESERTER, 
    104     CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, 
    105     CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY, 
    106104    CONFIG_INSTANCE_RESET_TIME_HOUR, 
    107105    CONFIG_INSTANCE_UNLOAD_DELAY, 
     
    160158    CONFIG_LISTEN_RANGE_TEXTEMOTE, 
    161159    CONFIG_LISTEN_RANGE_YELL, 
     160    CONFIG_ARENA_MAX_RATING_DIFFERENCE, 
     161    CONFIG_ARENA_RATING_DISCARD_TIMER, 
     162    CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, 
     163    CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, 
     164    CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, 
    162165    CONFIG_VALUE_COUNT 
    163166}; 
  • trunk/src/game/debugcmds.cpp

    r2 r9  
    3131#include "Language.h" 
    3232#include "MapManager.h" 
     33#include "BattleGroundMgr.h" 
    3334 
    3435bool ChatHandler::HandleDebugInArcCommand(const char* /*args*/) 
     
    513514    return true; 
    514515} 
     516 
     517bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) 
     518{ 
     519    sBattleGroundMgr.ToggleArenaTesting(); 
     520    return true; 
     521} 
  • trunk/src/shared/Database/DBCStructure.h

    r6 r9  
    472472    // Helpers 
    473473    bool IsExpansionMap() const { return addon != 0; } 
    474     bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; } 
    475     // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable 
     474 
     475 
    476476    bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; } 
     477    bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID || map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; } 
    477478    bool IsRaid() const { return map_type == MAP_RAID; } 
    478479    bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; } 
  • trunk/src/trinitycore/trinitycore.conf.dist

    r2 r9  
    438438#                 0 (false) 
    439439# 
    440 #    Battleground.QueueAnnouncer.Enable 
    441 #        Enable queue announcer posting to chat 
    442 #        Default: 1 (true) 
    443 #                 0 (false) 
    444 # 
    445 #    Battleground.QueueAnnouncer.PlayerOnly 
    446 #        Enable queue announcer posting to chat 
    447 #        Default: 0 (false) 
    448 #                 1 (true) 
    449 # 
    450440#    CastUnstuck 
    451441#        Allow cast or not Unstuck spell at .start or client Help option use 
     
    538528ActivateWeather = 1 
    539529Battleground.CastDeserter = 1 
    540 Battleground.QueueAnnouncer.Enable = 1 
    541 Battleground.QueueAnnouncer.PlayerOnly = 0 
    542530CastUnstuck = 1 
    543531Instance.IgnoreLevel = 0 
     
    10261014Ra.MinLevel = 3 
    10271015Ra.Secure = 1 
     1016 
     1017################################################################################################################### 
     1018# 
     1019# Rated arena matches config 
     1020# 
     1021# MaxRatingDifference: the maximum rating difference between two groups in rated matches 
     1022#             Default: 0 (disable, rating difference is discarded)   
     1023# 
     1024# RatingDiscardTimer: after the specified milliseconds has passed,  
     1025#                     rating information will be discarded when selecting teams for matches 
     1026#                     also initiates an update by this timer 
     1027#             Default: 60000 
     1028# 
     1029# AutoDistributePoints: set if arena points should be distributed automatically, or by GM command 
     1030#             Default: 0 (disable) (recommended): use gm command or sql query to distribute the points 
     1031#                      1 (enable): arena points are distributed automatically 
     1032# 
     1033# AutoDistributeInterval: how often should the distribution take place  
     1034#                         if automatic distribution is enabled 
     1035#                         in days 
     1036#             Default: 7 (weekly) 
     1037# 
     1038################################################################################################################### 
     1039 
     1040Arena.MaxRatingDifference = 0 
     1041Arena.RatingDiscardTimer = 60000 
     1042Arena.AutoDistributePoints = 0 
     1043Arena.AutoDistributeInterval = 7 
     1044 
     1045################################################################################################################### 
     1046# 
     1047# Battleground config 
     1048# 
     1049# PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side 
     1050#                       in milliseconds, 0 - disabled 
     1051#              Default: 0  
     1052# 
     1053################################################################################################################### 
     1054 
     1055BattleGround.PrematureFinishTimer = 0