All pastes #886797 Raw Edit

Mine

public diff v1 · immutable
#886797 ·published 2008-01-31 22:47 UTC
rendered paste body
Index: src/game/ArenaTeam.cpp===================================================================--- src/game/ArenaTeam.cpp	(revision 5116)+++ src/game/ArenaTeam.cpp	(working copy)@@ -34,7 +34,7 @@     stats.games     = 0;     stats.played    = 0;     stats.rank      = 0;-    stats.rating    = 0;+    stats.rating    = 1500;     stats.wins      = 0;     stats.wins2     = 0; }@@ -51,7 +51,7 @@     if(objmgr.GetArenaTeamByName(ArenaTeamName))            // arena team with this name already exist         return false; -    sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid));+    sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid));      CaptainGuid = captainGuid;     Name = ArenaTeamName;@@ -74,7 +74,7 @@     CharacterDatabase.PExecute("INSERT INTO `arena_team` (`arenateamid`,`name`,`captainguid`,`type`,`EmblemStyle`,`EmblemColor`,`BorderStyle`,`BorderColor`,`BackgroundColor`) "         "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')",         Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor);-    CharacterDatabase.PExecute("INSERT INTO `arena_team_stats` (`arenateamid`, `rating`, `games`, `wins`, `played`, `wins2`, `rank`) VALUES ('%u', '0', '0', '0', '0', '0', '0')", Id);+    CharacterDatabase.PExecute("INSERT INTO `arena_team_stats` (`arenateamid`, `rating`, `games`, `wins`, `played`, `wins2`, `rank`) VALUES ('%u', '1500', '0', '0', '0', '0', '0')", Id);     CharacterDatabase.CommitTransaction();      AddMember(CaptainGuid);@@ -89,8 +89,11 @@     if(!objmgr.GetPlayerNameByGUID(PlayerGuid, plName))     // player doesnt exist         return false;                                                             // player already in arenateam of that size-    if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetSlot()) != 0)+    if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0)+    {+        sLog.outError("Arena::AddMember() : player already in this sized team");         return false;+    }      // remove all player signs from another petitions     // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity@@ -118,6 +121,7 @@     newmember.played_week   = 0;     newmember.wons_season   = 0;     newmember.wons_week     = 0;+    newmember.points_to_add = 0;     members.push_back(newmember);      CharacterDatabase.PExecute("INSERT INTO `arena_team_member` (`arenateamid`,`guid`) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid));@@ -195,7 +199,7 @@ {     Field *fields; -    QueryResult *result = CharacterDatabase.PQuery("SELECT `guid`,`played_week`,`wons_week`,`played_season`,`wons_season` FROM `arena_team_member` WHERE `arenateamid` = '%u'", ArenaTeamId);+    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);     if(!result)         return; @@ -209,6 +213,7 @@         newmember.wons_week     = fields[2].GetUInt32();         newmember.played_season = fields[3].GetUInt32();         newmember.wons_season   = fields[4].GetUInt32();+        newmember.points_to_add = fields[5].GetUInt32();         members.push_back(newmember);     }while( result->NextRow() );     delete result;@@ -329,6 +334,7 @@             data << itr->wons_week;                         // wins this week             data << itr->played_season;                     // played this season             data << itr->wons_season;                       // wins this season+            data << uint32(0);                              // unknown         }         else         {@@ -342,6 +348,7 @@             data << itr->wons_week;                         // wins this week             data << itr->played_season;                     // played this season             data << itr->wons_season;                       // wins this season+            data << uint32(0);                              // unknown         }     }     session->SendPacket(&data);@@ -365,7 +372,7 @@  void ArenaTeam::Stats(WorldSession *session) {-    WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7);+    WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*9);     data << GetId();                                        // arena team id     data << stats.rating;                                   // rating     data << stats.games;                                    // games@@ -373,6 +380,19 @@     data << stats.played;                                   // played     data << stats.wins2;                                    // wins(again o_O)     data << stats.rank;                                     // rank+    uint64 guid = session->GetPlayer()->GetGUID();+    float played_percent = 0;+    for(MemberList::const_iterator itr = members.begin(); itr !=  members.end(); ++itr)+    {+        if(itr->guid == guid)+        {+            if(stats.games)+                played_percent = itr->played_week / stats.games;+            break;+        }+    }+    data << played_percent;                // played % per player+    data << played_percent;     session->SendPacket(&data); } @@ -463,6 +483,145 @@     } } +uint32 ArenaTeam::GetPoints()+{+    float points;+    if(stats.rating<=1500)+    {+        points = (float)stats.rating * 0.22f + 14.0f;+    }+    else+    {+        points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)stats.rating));+    }++    if(Type == ARENA_TEAM_2v2)+        points *= 0.76f;+    else if(Type == ARENA_TEAM_3v3)+        points *= 0.88f;++    return (uint32) points;+}++float ArenaTeam::GetChanceAgainst(uint32 rating)+{+    return 1.0f/(1.0f+exp(log(10.0f)*(float)(stats.rating - rating)/400.0f));+}++int32 ArenaTeam::WonAgainstChance(float chance)+{+    int32 mod = (int32)(32.0f * (1.0f - chance));+    stats.rating += mod;+    stats.games += 1;+    stats.wins += 1;+    stats.played += 1;+    stats.wins2 += 1;+//    SetStats(STAT_TYPE_RATING, stats.rating + mod);+//    SetStats(STAT_TYPE_GAMES, stats.games+1);+//    SetStats(STAT_TYPE_WINS, stats.wins+1);+//    SetStats(STAT_TYPE_PLAYED, stats.played+1);+//    SetStats(STAT_TYPE_WINS2, stats.wins2+1);+    uint32 higher_rank = 0;+    QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT(`arenateamid`) FROM `arena_team_stats` WHERE `rating` > '%u' AND `arenateamid` <> '%u'",stats.rating, Id);+    if(result)+    {+        higher_rank = result->Fetch()->GetUInt32();+        delete result;+    }+//    SetStats(STAT_TYPE_RATING, higher_rating + 1);+    stats.rank = higher_rank + 1;+    return mod;+}++int32 ArenaTeam::LostAgainstChance(float chance)+{+    int32 mod = (int32)(32.0f * (0.0f - chance));+    stats.rating += mod;+    stats.games += 1;+    stats.played += 1;+//    SetStats(STAT_TYPE_RATING, stats.rating + mod);+//    SetStats(STAT_TYPE_GAMES, stats.games+1);+//    SetStats(STAT_TYPE_PLAYED, stats.played+1);+    uint32 higher_rank = 0;+    QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT (`arenateamid`) FROM `arena_team_stats` WHERE `rating` > '%u' AND `arenateamid` <> '%u'",stats.rating, Id);+    if(result)+    {+        higher_rank = result->Fetch()->GetUInt32();+        delete result;+    }+//    SetStats(STAT_TYPE_RATING, higher_rating + 1);+    stats.rank = higher_rank + 1;+    return mod;+}++void ArenaTeam::MemberLost(uint64 guid)+{+    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr)+    {+        if(itr->guid == guid)+        {+            itr->played_week +=1;+            itr->played_season +=1;+            return;+        }+    }+}++void ArenaTeam::MemberWon(uint64 guid)+{+    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr)+    {+        if(itr->guid == guid)+        {+            itr->played_week +=1;+            itr->played_season +=1;+            itr->wons_season += 1;+            itr->wons_week += 1;+            return;+        }+    }+}++uint32 ArenaTeam::GetMemberPoints(uint64 guid)+{+    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr)+    {+        if(itr->guid == guid)+        {+            return itr->points_to_add;+        }+    }+    return 0;+}++void ArenaTeam::UpdateArenaPointsHelper()+{+    if(stats.games < 10)+        return;+    uint32 min_plays = stats.games * 0.3;+    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr)+    {+        if(itr->played_week >= min_plays)+        {+            itr->points_to_add = GetPoints();+            // CharacterDatabase.PExecute("UPDATE `arena_team_member` SET `points_to_add` = '%u' WHERE `arenateamid` = '%u' AND `guid` = '%u'", itr->points_to_add,Id, itr->guid);+        }+        else+        {+            itr->points_to_add = 0;+        }+    }+}++void ArenaTeam::SaveToDB()+{+    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());+    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr)+    {+        CharacterDatabase.PExecute("UPDATE `arena_team_member` SET `played_week` = '%u', `wons_week` = '%u', `played_season` = '%u', `wons_season` = '%u', `points_to_add` = '%u' WHERE `arenateamid` = '%u' AND `guid` = '%u'", itr->played_week, itr->wons_week, itr->played_season, itr->wons_season, itr->points_to_add, Id, itr->guid);+    }+}+ /* arenateam fields (id from 2.1.0 client): 1405 - arena team id 2v2Index: src/game/ArenaTeam.h===================================================================--- src/game/ArenaTeam.h	(revision 5116)+++ src/game/ArenaTeam.h	(working copy)@@ -92,6 +92,7 @@     uint32 wons_week;     uint32 played_season;     uint32 wons_season;+    uint32 points_to_add; };  struct ArenaTeamStats@@ -144,6 +145,8 @@         void LoadStatsFromDB(uint32 ArenaTeamId);         void LoadPlayerStats(ArenaTeamMember* member); +        void SaveToDB();+         void BroadcastPacket(WorldPacket *packet);          void Roster(WorldSession *session);@@ -151,6 +154,16 @@         void Stats(WorldSession *session);         void InspectStats(WorldSession *session); +        uint32 GetPoints();+        float GetChanceAgainst(uint32 rating);+        int32 WonAgainstChance(float chance);+        void MemberWon(uint64 guid);+        int32 LostAgainstChance(float chance);+        void MemberLost(uint64 guid);++        void UpdateArenaPointsHelper();+        uint32 GetMemberPoints(uint64 guid);+     protected:          uint32 Id;Index: src/game/ArenaTeamHandler.cpp===================================================================--- src/game/ArenaTeamHandler.cpp	(revision 5116)+++ src/game/ArenaTeamHandler.cpp	(working copy)@@ -141,6 +141,7 @@      if(player->GetArenaTeamId(team_slot))     {+        sLog.outDebug("ALREADY IN ARENA TEAM OF THAT SIZE!!!!! team id %u for team slot %u", player->GetArenaTeamId(team_slot), team_slot);         SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);         return;     }Index: src/game/BattleGround.cpp===================================================================--- src/game/BattleGround.cpp	(revision 5116)+++ src/game/BattleGround.cpp	(working copy)@@ -25,11 +25,13 @@ #include "Language.h"                                       // for chat messages #include "Chat.h" #include "SpellAuras.h"+#include "ArenaTeam.h" #include "World.h"  BattleGround::BattleGround() {     m_TypeID            = 0;+    m_TeamType          = 0;     m_InstanceID        = 0;     m_Status            = 0;     m_EndTime           = 0;@@ -46,6 +48,8 @@     m_Name              = "";     m_LevelMin          = 0;     m_LevelMax          = 0;+    m_InBGFreeSlotQueue = false;+    m_SetDeleteThis     = false;      m_MaxPlayersPerTeam = 0;     m_MaxPlayers        = 0;@@ -66,6 +70,12 @@     m_TeamStartLocO[BG_TEAM_ALLIANCE]   = 0;     m_TeamStartLocO[BG_TEAM_HORDE]      = 0; +    m_ArenaTeamIds[BG_TEAM_ALLIANCE]   = 0;+    m_ArenaTeamIds[BG_TEAM_HORDE]      = 0;++    m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE]   = 0;+    m_ArenaTeamRatingChanges[BG_TEAM_HORDE]      = 0;+     m_BgRaids[BG_TEAM_ALLIANCE]         = NULL;     m_BgRaids[BG_TEAM_HORDE]            = NULL; @@ -75,7 +85,28 @@  BattleGround::~BattleGround() {+    // remove objects and creatures+/*    for(BGObjects::iterator itr = m_BgObjects.begin(); itr != m_BgObjects.end(); ++itr)+    {+        if(*itr) (*itr)->RemoveFromWorld();+    } +    for(BGCreatures::iterator itr = m_BgCreatures.begin(); itr != m_BgCreatures.end(); ++itr)+    {+        if(*itr) (*itr)->RemoveFromWorld();+    }+*/+    // delete bound char instances (this should have been already deleted?)+    CharacterDatabase.PExecute("DELETE FROM `character_instance` WHERE `instance` = '%u'", GetInstanceID());+    // delete creature and go respawn times+    WorldDatabase.PExecute("DELETE FROM `creature_respawn` WHERE `instance` = '%u'",GetInstanceID());+    WorldDatabase.PExecute("DELETE FROM `gameobject_respawn` WHERE `instance` = '%u'",GetInstanceID());+    // delete instance from db+    CharacterDatabase.PExecute("DELETE FROM `instance` WHERE id = '%u'",GetInstanceID());+    // remove from battlegrounds+    sBattleGroundMgr.RemoveBattleGround(GetInstanceID());+    // remove from bg free slot queue+    this->RemoveFromBGFreeSlotQueue(); }  void BattleGround::Update(time_t diff)@@ -237,7 +268,10 @@         if(!self && sender == plr)             continue; -        if(plr->GetTeam() == TeamID)+        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());+        if(!team) team = plr->GetTeam();++        if(team == TeamID)             plr->GetSession()->SendPacket(packet);     } }@@ -263,7 +297,10 @@             continue;         } -        if(plr->GetTeam() == TeamID)+        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());+        if(!team) team = plr->GetTeam();++        if(team == TeamID)         {             sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID);             plr->GetSession()->SendPacket(&data);@@ -283,7 +320,10 @@             continue;         } -        if(plr->GetTeam() == TeamID)+        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());+        if(!team) team = plr->GetTeam();+       +        if(team == TeamID)             plr->CastSpell(plr, SpellID, true);     } }@@ -300,7 +340,10 @@             continue;         } -        if(plr->GetTeam() == TeamID)+        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());+        if(!team) team = plr->GetTeam();++        if(team == TeamID)             UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor);     } }@@ -322,7 +365,10 @@             continue;         } -        if(plr->GetTeam() == TeamID)+        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());+        if(!team) team = plr->GetTeam();++        if(team == TeamID)             plr->ModifyFactionReputation(factionEntry, Reputation);     } }@@ -336,13 +382,20 @@  void BattleGround::EndBattleGround(uint32 winner) {+    this->RemoveFromBGFreeSlotQueue();++    ArenaTeam * winner_arena_team = NULL;+    ArenaTeam * loser_arena_team = NULL;     WorldPacket data;     Player *Source = NULL;     const char *winmsg = "";      if(winner == ALLIANCE)     {-        winmsg = LANG_BG_A_WINS;+        if(isBattleGround())+            winmsg = LANG_BG_A_WINS;+        else+            winmsg = LANG_ARENA_GOLD_WINS;          PlaySoundToAll(SOUND_ALLIANCE_WINS);                // alliance wins sound @@ -350,13 +403,56 @@     }     else     {-        winmsg = LANG_BG_H_WINS;+        if(isBattleGround())+            winmsg = LANG_BG_H_WINS;+        else+            winmsg = LANG_ARENA_GREEN_WINS;          PlaySoundToAll(SOUND_HORDE_WINS);                   // horde wins sound          SetWinner(WINNER_HORDE);     } +    if(isArena() && isRated())+    {+        if(winner == ALLIANCE)+        {+            winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));+            loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));+        }+        else+        {+            winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));+            loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));+        }+        if(winner_arena_team && loser_arena_team)+        {+            uint32 loser_rating = loser_arena_team->GetStats().rating;+            uint32 winner_rating = winner_arena_team->GetStats().rating;+            float winner_chance = winner_arena_team->GetChanceAgainst(loser_rating);+            float loser_chance = loser_arena_team->GetChanceAgainst(winner_rating);+            int32 winner_change = winner_arena_team->WonAgainstChance(winner_chance);+            int32 loser_change = loser_arena_team->LostAgainstChance(loser_chance);+            if(winner == ALLIANCE)+            {+                SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change);+                SetArenaTeamRatingChangeForTeam(HORDE, loser_change);+            }+            else+            {+                SetArenaTeamRatingChangeForTeam(HORDE, winner_change);+                SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change);+            }+            winner_arena_team->UpdateArenaPointsHelper();+            loser_arena_team->UpdateArenaPointsHelper();+        }+        else+        {+            SetArenaTeamRatingChangeForTeam(ALLIANCE, 0);+            SetArenaTeamRatingChangeForTeam(HORDE, 0);+        }+    }+     SetStatus(STATUS_WAIT_LEAVE);     m_EndTime = 0; @@ -371,14 +467,35 @@             continue;         } +        // should remove spirit of redemption+        if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))+            plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);+         if(!plr->isAlive())         {             plr->ResurrectPlayer(1.0f);             plr->SpawnCorpseBones();         } -        if(plr->GetTeam() == winner)+        uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());+        if(!team) team = plr->GetTeam();++        if(isArena() && isRated() && winner_arena_team && loser_arena_team)         {+            if(team == winner)+            {+                winner_arena_team->MemberWon(itr->first);+                winner_arena_team->Stats(plr->GetSession());+            }+            else+            {+                loser_arena_team->MemberLost(itr->first);+                loser_arena_team->Stats(plr->GetSession());+            }+        }++        if(team == winner)+        {             if(!Source)                 Source = plr;             switch(GetTypeID())@@ -429,10 +546,21 @@         sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);         plr->GetSession()->SendPacket(&data); -        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());+        uint32 bgTypeId = sBattleGroundMgr.BGQueueTypeId(m_TypeID);+        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());         plr->GetSession()->SendPacket(&data);     } +    if(isArena() && isRated() && winner_arena_team && loser_arena_team)+    {+        winner_arena_team->SaveToDB();+        loser_arena_team->SaveToDB();+    }++    // inform invited players about the removal+    sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].BGEndedRemoveInvites(this);++     if(Source)     {         ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_GLOBAL, Source->GetGUID(), winmsg);@@ -449,11 +577,13 @@  void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) {+    sLog.outDebug("BG:Removing player at leave");+    uint32 team = GetPlayerTeam(guid);     // Remove from lists/maps     std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid);     if(itr != m_Players.end())     {-        UpdatePlayersCountByTeam(itr->second.Team, true);   // -1 player+        UpdatePlayersCountByTeam(team, true);   // -1 player         m_Players.erase(itr);     } @@ -468,6 +598,10 @@      Player *plr = objmgr.GetPlayer(guid); +    // should remove spirit of redemption+    if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))+        plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);+     if(plr && !plr->isAlive())                              // resurrect on exit     {         plr->ResurrectPlayer(1.0f);@@ -478,41 +612,78 @@      if(plr)     {+        if(!team) team = plr->GetTeam();++        uint32 bgTypeId = GetTypeID();         if(isArena())         {-            if(!sWorld.IsFFAPvPRealm())-                plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);+            plr->RemoveArenaAuras(true);+            plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);+            plr->RemoveAurasDueToSpell(SPELL_ALLIANCE_GOLD_FLAG);+            plr->RemoveAurasDueToSpell(SPELL_ALLIANCE_GREEN_FLAG);+            plr->RemoveAurasDueToSpell(SPELL_HORDE_GOLD_FLAG);+            plr->RemoveAurasDueToSpell(SPELL_HORDE_GREEN_FLAG);+            bgTypeId=BATTLEGROUND_AA; -            plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);+            Pet* NewPet = new Pet(plr);+            if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetOldPetNumber(), true))+                delete NewPet;++            (plr)->SetOldPetNumber(0);         }          WorldPacket data;         if(SendPacket)         {-            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);+            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgTypeId), STATUS_NONE, 0, 0);             plr->GetSession()->SendPacket(&data);         }          // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg-        plr->RemoveBattleGroundQueueId(m_TypeID);+        plr->RemoveBattleGroundQueueId(bgTypeId); -        DecreaseInvitedCount(plr->GetTeam());+        DecreaseInvitedCount(team);         //we should update battleground queue, but only if bg isn't ending         if (GetQueueType() < MAX_BATTLEGROUND_QUEUES)-            sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType());+            sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].Update(bgTypeId, GetQueueType());          if(!plr->GetBattleGroundId())             return;          Group * group = plr->GetGroup();-         // remove from raid group if exist-        if(group && group == GetBgRaid(plr->GetTeam()))+        if(group && group == GetBgRaid(team))         {+            uint32 groupSize = group->GetMembersCount();+            GroupReference * grpRef = group->GetFirstMember();+            Player * grpGuy = grpRef->getSource();+            if(grpGuy->GetGUID()==guid)+            {+                if(grpRef->hasNext()) +                {+                    grpRef = grpRef->next();+                    grpGuy = grpRef->getSource();+                }+                else if(grpRef->hasPrev())+                {+                    grpRef = (GroupReference*)grpRef->prev();+                    grpGuy = grpRef->getSource();+                }+                else+                    grpGuy = NULL;+            }             if(!group->RemoveMember(guid, 0))               // group was disbanded             {-                SetBgRaid(plr->GetTeam(), NULL);+                SetBgRaid(team, NULL);                 delete group;+                if(groupSize >= 2 && grpGuy != 0)                            // someone's still left in the bg, recreate group for him+                {+                    Group *group = new Group;+                    SetBgRaid(team, group);+                    group->ConvertToRaid();+                    group->AddMember(grpGuy->GetGUID(), grpGuy->GetName());+                    group->ChangeLeader(grpGuy->GetGUID());+                }             }         } @@ -521,11 +692,12 @@          // Let others know         sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);-        SendPacketToTeam(plr->GetTeam(), &data, plr, false);+        SendPacketToTeam(team, &data, plr, false);          if(Transport)         {             plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO(), true, false);+            //plr->SetInstanceId(plr->GetBattleGroundEntryPointInstanceId());             //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O);         } @@ -533,13 +705,32 @@         sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());     } +    // remove player from bg instance!+    CharacterDatabase.PExecute("DELETE FROM `character_instance` WHERE `guid` = '%u' AND `instance` = '%u'", guid, GetInstanceID());++    if(plr)+    {+        // remove player from bg instance!!!+        plr->m_BoundInstances.erase(GetMapId());+    }+     /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist     // we always should check if BG is in that queue before adding..      if(!GetPlayersSize())     {-        Reset();+   //     // no one left, cleanup and reinit instance+   //     Reset();+   //     if(!SetupBattleGround())+   //     {+   //         // setup failed, remove battleground.+        m_SetDeleteThis = true;+        return;+   //     }     }++    // a player exited the battleground, so there are free slots. add to queue+    this->AddToBGFreeSlotQueue(); }  // this method is called when no players remains in battleground@@ -551,6 +742,9 @@     SetStartTime(0);     SetEndTime(0);     SetLastResurrectTime(0);+    SetTeamType(BG_TEAM_TYPE_NORMAL);+    SetArenaType(0);+    SetRated(false);      m_Events = 0; @@ -559,6 +753,7 @@      m_InvitedAlliance = 0;     m_InvitedHorde = 0;+    m_InBGFreeSlotQueue = false;      m_Players.clear();     m_PlayerScores.clear();@@ -576,52 +771,64 @@      WorldPacket data;     BattleGround *bg = NULL;--    /// this code seems not correct:-    if(GetTypeID() == BATTLEGROUND_AA)-    {-        // we must select one of running arena-        uint8 arenas[3] = { BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL };-        uint8 arena_type = arenas[urand(0, 2)];--        bg = sBattleGroundMgr.GetBattleGround(arena_type);-        if(!bg)-            return;--        bg->SetStatus(STATUS_WAIT_JOIN);--        bg->SetStartTime(0);-        bg->SetLastResurrectTime(0);-    } } -void BattleGround::AddPlayer(Player *plr)+void BattleGround::AddPlayer(Player *plr, uint32 team) {+    sLog.outDebug("BGAddPlayer %u",plr->GetGUIDLow());     // score struct must be created in inherited class+    if(team==0)+        team = plr->GetTeam();      uint64 guid = plr->GetGUID();      BattleGroundPlayer bp;     bp.LastOnlineTime = 0;-    bp.Team = plr->GetTeam();+    bp.Team = team;      // Add to list/maps     m_Players[guid] = bp; -    UpdatePlayersCountByTeam(plr->GetTeam(), false);        // +1 player+    UpdatePlayersCountByTeam(team, false);        // +1 player      WorldPacket data;     sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr);-    SendPacketToTeam(plr->GetTeam(), &data, plr, false);+    SendPacketToTeam(team, &data, plr, false);      if(isArena())     {+        plr->RemoveArenaSpellCooldowns();+        plr->RemoveArenaAuras();+        if(team == ALLIANCE && plr->GetTeam() == ALLIANCE)+            plr->CastSpell(plr,SPELL_ALLIANCE_GOLD_FLAG,true);+        else if(team == HORDE && plr->GetTeam() == ALLIANCE)+            plr->CastSpell(plr,SPELL_ALLIANCE_GREEN_FLAG,true);+        else if(team == ALLIANCE && plr->GetTeam() == HORDE)+            plr->CastSpell(plr,SPELL_HORDE_GOLD_FLAG,true);+        else+            plr->CastSpell(plr,SPELL_HORDE_GREEN_FLAG,true);+        plr->DestroyConjuredItems(true);++        Pet* pet = plr->GetPet();+        if(pet)+        {+            if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)+            {+                (plr)->SetOldPetNumber(pet->GetCharmInfo()->GetPetNumber());+                (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));+            }+            (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);+        }+        else+            (plr)->SetOldPetNumber(0);+         if(GetStatus() == STATUS_WAIT_JOIN)                 // not started yet         {-            // temporary disabled-            //plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true);+            plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true);++            plr->SetHealth(plr->GetMaxHealth());+            plr->SetPower(POWER_MANA, plr->GetMaxPower(POWER_MANA));         }-        plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);     }      // Log@@ -631,13 +838,18 @@ /* This method should be called only once ... it adds pointer to queue */ void BattleGround::AddToBGFreeSlotQueue() {-    sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);+    if(!m_InBGFreeSlotQueue)+    {+        sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);+        m_InBGFreeSlotQueue = true;+    } }  /* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/ void BattleGround::RemoveFromBGFreeSlotQueue() {-    /* uncomment this code when battlegrounds will work like instances+    m_InBGFreeSlotQueue = false;+    // uncomment this code when battlegrounds will work like instances     for (std::deque<BattleGround*>::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr)     {         if ((*itr)->GetInstanceID() == m_InstanceID)@@ -645,7 +857,7 @@             sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr);             return;         }-    }*/+    } }  /*@@ -668,6 +880,30 @@     return false; } +// get the number of free slots for team+uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const+{+    //if BG is starting ... invite anyone:+    if (GetStatus() == STATUS_WAIT_JOIN)+        return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;+    //if BG is already started .. do not allow to join too much players of one faction+    uint32 otherTeam;+    if (Team == ALLIANCE)+        otherTeam = GetInvitedCount(HORDE);+    else+        otherTeam = GetInvitedCount(ALLIANCE);+    if (GetStatus() == STATUS_IN_PROGRESS)+    {+        uint32 diff = (otherTeam <= GetInvitedCount(Team)) ? 0 : otherTeam - GetInvitedCount(Team);++        uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;++        return diff < diff2 ? diff : diff2 ;+    }++    return 0;+}+ /* this method isn't called already, it will be useful when more battlegrounds of one type will be available */ bool BattleGround::HasFreeSlots() const {@@ -748,7 +984,7 @@  bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 spawntime) {-    GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry);+/*    GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry);     if(!goinfo)     {         sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);@@ -772,21 +1008,40 @@     data.spawntimesecs  = spawntime;     data.animprogress   = 100;     data.go_state       = 1;-    objmgr.AddGameobjectToGrid(guid, &data); +//    objmgr.AddGameobjectToGrid(guid, &data);+     m_BgObjects[type] = MAKE_GUID(guid, HIGHGUID_GAMEOBJECT); +/*    GameObject * go = ObjectAccessor::Instance().GetObjectInWorld(m_BgObjects[type], (GameObject*)NULL);+    go->SetInstanceId(GetInstanceID());//*/++    GameObject * go = new GameObject(NULL);+    go->SetInstanceId(GetInstanceID());+    if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, GetMapId(),x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))+    {+        sLog.outErrorDb("Cannot create gameobject template %u! BattleGround not created!", entry);+        delete go;+        return false;+    }++//    objmgr.SaveGORespawnTime(go->GetGUIDLow(),go->GetInstanceId(),spawntime);+//    MapManager::Instance().GetMap(go->GetMapId(), go)->Add(go);++    m_BgObjects[type] = go;//*/+    sLog.outDebug("GO created in bg type %u, insta %u, go entry %u",GetTypeID(), GetInstanceID(), entry);     return true; }  void BattleGround::DoorOpen(uint32 type) {-    GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);+    GameObject *obj = m_BgObjects[type];     if(obj)     {         obj->SetUInt32Value(GAMEOBJECT_FLAGS,33);         obj->SetUInt32Value(GAMEOBJECT_STATE,0);         //obj->SetLootState(GO_CLOSED);+        sLog.outDebug("BG Door opened");     }     else     {@@ -798,32 +1053,37 @@ {     if(respawntime == 0)     {-        GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);+        GameObject *obj = m_BgObjects[type];         if(obj)         {             //obj->Respawn();                               // bugged             obj->SetRespawnTime(0);-            objmgr.SaveGORespawnTime(obj->GetGUIDLow(), 0, 0);+            objmgr.SaveGORespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);+            MapManager::Instance().GetMap(obj->GetMapId(), obj)->Add(obj);+            sLog.outDebug("BG Object spawned");         }-        else-            objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0);+//        else+//            objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), GetInstanceID(), 0);     }     else     {-        GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);+        GameObject *obj = m_BgObjects[type];         if(obj)         {             obj->SetRespawnTime(respawntime);             obj->SetLootState(GO_LOOTED);+            MapManager::Instance().GetMap(obj->GetMapId(), obj)->Add(obj);+            sLog.outDebug("BG Object spawned 2");         }-        else-            objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime);+//        else+//            objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), GetInstanceID(), time(NULL) + respawntime);     } } -Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o)+Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) {     Creature* pCreature = new Creature(NULL);+    pCreature->SetInstanceId(GetInstanceID());     if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMapId(), x, y, z, o, entry, teamval))     {         sLog.outError("Can't create creature entry: %u",entry);@@ -834,17 +1094,50 @@     pCreature->AIM_Initialize();      //pCreature->SetDungeonDifficulty(0);-    MapManager::Instance().GetMap(pCreature->GetMapId(), pCreature)->Add(pCreature);-    m_BgCreatures[type] = pCreature->GetGUID();+//    objmgr.SaveCreatureRespawnTime(pCreature->GetGUIDLow(), pCreature->GetInstanceId(), respawntime);+//    MapManager::Instance().GetMap(pCreature->GetMapId(), pCreature)->Add(pCreature);+    m_BgCreatures[type] = pCreature;+    sLog.outDebug("BG Creature created in bg type %u, insta %u, go entry %u",GetTypeID(), GetInstanceID(), entry);     return  pCreature; } +void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)+{+    if(respawntime == 0)+    {+        Creature *obj = m_BgCreatures[type];+        if(obj)+        {+            //obj->Respawn();                               // bugged+            obj->SetRespawnTime(0);+            objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);+            MapManager::Instance().GetMap(obj->GetMapId(), obj)->Add(obj);+            sLog.outDebug("BG Creature spawned");+        }+       // else+       //     objmgr.SaveCreatureRespawnTime(GUID_LOPART(m_BgCreatures[type]), GetInstanceID(), 0);+    }+    else+    {+        Creature *obj = m_BgCreatures[type];+        if(obj)+        {+            obj->setDeathState(DEAD);+            obj->SetRespawnTime(respawntime);+            MapManager::Instance().GetMap(obj->GetMapId(), obj)->Add(obj);+            sLog.outDebug("BG Creature spawned 2");+        }+       // else+       //     objmgr.SaveCreatureRespawnTime(GUID_LOPART(m_BgCreatures[type]), GetInstanceID(), time(NULL) + respawntime);+    }+}+ bool BattleGround::DelCreature(uint32 type) {-    Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);+    Creature *cr = m_BgCreatures[type];     if(!cr)     {-        sLog.outError("Can't find creature guid: %u",m_BgCreatures[type]);+        sLog.outError("Can't find creature.");         return false;     }     cr->CleanupsBeforeDelete();@@ -855,10 +1148,10 @@  bool BattleGround::DelObject(uint32 type) {-    GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);+    GameObject *obj = m_BgObjects[type];     if(!obj)     {-        sLog.outError("Can't find gobject guid: %u",m_BgObjects[type]);+        sLog.outError("Can't find gobject.");         return false;     }     obj->SetRespawnTime(0);                                 // not save respawn time@@ -914,3 +1207,11 @@     SetStatus(STATUS_WAIT_LEAVE);     SetEndTime(TIME_TO_AUTOREMOVE); }++uint32 BattleGround::GetPlayerTeam(uint64 guid)+{+    std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid);+    if(itr!=m_Players.end())+        return itr->second.Team;+    return 0;+}Index: src/game/BattleGround.h===================================================================--- src/game/BattleGround.h	(revision 5116)+++ src/game/BattleGround.h	(working copy)@@ -50,7 +50,11 @@     SPELL_SPIRIT_HEAL_CHANNEL       = 22011,     SPELL_SPIRIT_HEAL               = 22012,     SPELL_RESURRECTION_VISUAL       = 24171,-    SPELL_ARENA_PREPARATION         = 32727+    SPELL_ARENA_PREPARATION         = 32727,+    SPELL_ALLIANCE_GOLD_FLAG        = 32724,+    SPELL_ALLIANCE_GREEN_FLAG       = 32725,+    SPELL_HORDE_GOLD_FLAG           = 35774,+    SPELL_HORDE_GREEN_FLAG          = 35775 };  enum BattleGroundTimeIntervals@@ -61,9 +65,9 @@     TIME_TO_AUTOREMOVE              = 120000,           // ms     MAX_OFFLINE_TIME                = 300000,           // ms     START_DELAY0                    = 120000,           // ms-    START_DELAY1                    = 60000,            // ms-    START_DELAY2                    = 30000,            // ms-    START_DELAY3                    = 15000,            // ms used only in arena+    START_DELAY1                    = 10000,            // ms+    START_DELAY2                    = 5000,            // ms+    START_DELAY3                    = 1000,            // ms used only in arena     RESPAWN_ONE_DAY                 = 86400,            // secs     RESPAWN_IMMEDIATELY             = 0,                // secs     BUFF_RESPAWN_TIME               = 180               // secs@@ -166,6 +170,13 @@     BG_TEAM_HORDE           = 1 }; +enum BattleGroundTeamType+{+    BG_TEAM_TYPE_NORMAL     = 0,    // one side is ally, other is horde+    BG_TEAM_TYPE_ALLIANCE_ONLY = 1, // both sides are alliance+    BG_TEAM_TYPE_HORDE_ONLY = 2     // both sides are horde+};+ class BattleGroundScore {     public:@@ -193,6 +204,7 @@     public:         /* Construction */         BattleGround();+        /*BattleGround(const BattleGround& bg);*/         virtual ~BattleGround();         virtual void Update(time_t diff);                   // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version         virtual bool SetupBattleGround()                    // must be implemented in BG subclass@@ -262,6 +274,7 @@         }         bool HasFreeSlotsForTeam(uint32 Team) const;         bool HasFreeSlots() const;+        uint32 GetFreeSlotsForTeam(uint32 Team) const;          bool isArena() const        { return m_IsArena; }         bool isBattleGround() const { return !m_IsArena; }@@ -334,6 +347,11 @@                 m_PlayersCount[GetTeamIndexByTeamId(Team)]++;         } +        void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[ Team == ALLIANCE ? 0 : 1] = ArenaTeamId; }+        uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[ Team == ALLIANCE ? 0 : 1]; }+        void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 ArenaTeamId) { m_ArenaTeamRatingChanges[ Team == ALLIANCE ? 0 : 1] = ArenaTeamId; }+        uint32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[ Team == ALLIANCE ? 0 : 1]; }+         /* Triggers handle */         // must be implemented in BG subclass         virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {}@@ -342,24 +360,30 @@         // must be implemented in BG subclass if need         virtual void HandleDropFlag(Player* /*player*/) {} -        virtual void AddPlayer(Player *plr);                // must be implemented in BG subclass+        virtual void AddPlayer(Player *plr, uint32 team = 0);                // must be implemented in BG subclass         virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket);                                                             // can be extended in in BG subclass          // TODO: make this protected:-        typedef std::vector<uint64> BGObjects;-        typedef std::vector<uint64> BGCreatures;+        typedef std::vector<GameObject*> BGObjects;+        typedef std::vector<Creature*> BGCreatures;         BGObjects m_BgObjects;         BGCreatures m_BgCreatures;         void SpawnBGObject(uint32 type, uint32 respawntime);+        void SpawnBGCreature(uint32 type, uint32 respawntime);         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);-        Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o);+        Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0);         bool DelCreature(uint32 type);         bool DelObject(uint32 type);         bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team);          void DoorOpen(uint32 type); +        uint32 GetPlayerTeam(uint64 guid);++        uint8 GetTeamType() const {return m_TeamType;}+        void SetTeamType(uint8 type){m_TeamType=type;}+     protected:         //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround         void EndNow();@@ -387,6 +411,9 @@         uint32 m_LastResurrectTime;         uint32 m_Queue_type;         uint8  m_ArenaType;                                 // 2=2v2, 3=3v3, 5=5v5+        uint8  m_TeamType;+        bool   m_InBGFreeSlotQueue;+        bool   m_SetDeleteThis;         // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless         //uint8  m_BattleGroundType;                        // 3=BG, 4=arena         //instead of uint8 (in previous line) is bool used@@ -412,6 +439,11 @@         /* Players count by team */         uint32 m_PlayersCount[2]; +        /* Arena team ids by team */+        uint32 m_ArenaTeamIds[2];++        int32 m_ArenaTeamRatingChanges[2];+         /* Limits */         uint32 m_LevelMin;         uint32 m_LevelMax;Index: src/game/BattleGroundAA.cpp===================================================================--- src/game/BattleGroundAA.cpp	(revision 5116)+++ src/game/BattleGroundAA.cpp	(working copy)@@ -35,9 +35,9 @@     BattleGround::Update(diff); } -void BattleGroundAA::AddPlayer(Player *plr)+void BattleGroundAA::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr,team);     //create score and add it to map, default values are set in constructor     BattleGroundAAScore* sc = new BattleGroundAAScore; Index: src/game/BattleGroundAA.h===================================================================--- src/game/BattleGroundAA.h	(revision 5116)+++ src/game/BattleGroundAA.h	(working copy)@@ -38,7 +38,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);         void RemovePlayer(Player *plr, uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);         bool SetupBattleGround();Index: src/game/BattleGroundAB.cpp===================================================================--- src/game/BattleGroundAB.cpp	(revision 5116)+++ src/game/BattleGroundAB.cpp	(working copy)@@ -237,9 +237,9 @@     } } -void BattleGroundAB::AddPlayer(Player *plr)+void BattleGroundAB::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map, default values are set in the constructor     BattleGroundABScore* sc = new BattleGroundABScore; @@ -342,6 +342,7 @@         else goId = BG_AB_OBJECTID_BANNER_H;      m_bgobjects[obj] = new GameObject(NULL);+    m_bgobjects[obj]->SetInstanceId(GetInstanceID());     m_bgobjects[obj]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), goId, GetMapId(), BG_AB_NodePositions[node][0], BG_AB_NodePositions[node][1], BG_AB_NodePositions[node][2], BG_AB_NodePositions[node][3], 0, 0, sin(BG_AB_NodePositions[node][3]/2), cos(BG_AB_NodePositions[node][3]/2), 100, 1);     MapManager::Instance().GetMap(GetMapId(), m_bgobjects[obj])->Add(m_bgobjects[obj]); @@ -463,6 +464,7 @@     if (m_spiritGuides[node])         return;     m_spiritGuides[node] = new Creature(NULL);+    m_spiritGuides[node]->SetInstanceId(GetInstanceID());     if (!m_spiritGuides[node]->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), 529, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], (node>4)?BG_AB_SpiritGuideId[node-5]:BG_AB_SpiritGuideId[m_Nodes[node]-3], (node>4)?BG_AB_SpiritGuideTeamId[node-5]:BG_AB_SpiritGuideTeamId[m_Nodes[node]-3]))         ASSERT(0);     m_spiritGuides[node]->setDeathState(DEAD);@@ -626,6 +628,7 @@     for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i)     {         m_bgobjects[banner] = new GameObject(NULL);+        m_bgobjects[banner]->SetInstanceId(GetInstanceID());         if(!m_bgobjects[banner]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_NODE_BANNER_0+i, GetMapId(), BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), 100, 1))            return false;     }@@ -634,27 +637,32 @@     for (int banner = BG_AB_OBJECT_AURA_ALLY, i = 0; i < 5; banner += 8, ++i)     {         m_bgobjects[banner] = new GameObject(NULL);+        m_bgobjects[banner]->SetInstanceId(GetInstanceID());         if(!m_bgobjects[banner]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_AURA_A, GetMapId(), BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), 0, 0))            return false;     }     for (int banner = BG_AB_OBJECT_AURA_HORDE, i = 0; i < 5; banner += 8, ++i)     {         m_bgobjects[banner] = new GameObject(NULL);+        m_bgobjects[banner]->SetInstanceId(GetInstanceID());         if(!m_bgobjects[banner]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_AURA_H, GetMapId(), BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), 0, 0))            return false;     }     for (int banner = BG_AB_OBJECT_AURA_CONTESTED, i = 0; i < 5; banner += 8, ++i)     {         m_bgobjects[banner] = new GameObject(NULL);+        m_bgobjects[banner]->SetInstanceId(GetInstanceID());         if(!m_bgobjects[banner]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_AURA_C, GetMapId(), BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), 0, 0))            return false;     }      // Starting gates     m_bgobjects[BG_AB_OBJECT_GATE_A] = new GameObject(NULL);+    m_bgobjects[BG_AB_OBJECT_GATE_A]->SetInstanceId(GetInstanceID());     if(!m_bgobjects[BG_AB_OBJECT_GATE_A]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_GATE_A, GetMapId(), BG_AB_DoorPositions[0][0], BG_AB_DoorPositions[0][1], BG_AB_DoorPositions[0][2], BG_AB_DoorPositions[0][3], BG_AB_DoorPositions[0][4], BG_AB_DoorPositions[0][5], BG_AB_DoorPositions[0][6], BG_AB_DoorPositions[0][7], 100, 1))         return false;     m_bgobjects[BG_AB_OBJECT_GATE_H] = new GameObject(NULL);+    m_bgobjects[BG_AB_OBJECT_GATE_H]->SetInstanceId(GetInstanceID());     if(!m_bgobjects[BG_AB_OBJECT_GATE_H]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_GATE_H, GetMapId(), BG_AB_DoorPositions[1][0], BG_AB_DoorPositions[1][1], BG_AB_DoorPositions[1][2], BG_AB_DoorPositions[1][3], BG_AB_DoorPositions[1][4], BG_AB_DoorPositions[1][5], BG_AB_DoorPositions[1][6], BG_AB_DoorPositions[1][7], 100, 1))         return false; @@ -755,3 +763,6 @@ }  +++Index: src/game/BattleGroundAB.h===================================================================--- src/game/BattleGroundAB.h	(revision 5116)+++ src/game/BattleGroundAB.h	(working copy)@@ -222,7 +222,7 @@         ~BattleGroundAB();          void Update(time_t diff);-        void AddPlayer(Player *plr);+        void AddPlayer(Player *plr, uint32 team = 0);         void RemovePlayer(Player *plr,uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);         virtual bool SetupBattleGround();Index: src/game/BattleGroundAV.cpp===================================================================--- src/game/BattleGroundAV.cpp	(revision 5116)+++ src/game/BattleGroundAV.cpp	(working copy)@@ -39,9 +39,9 @@     BattleGround::Update(diff); } -void BattleGroundAV::AddPlayer(Player *plr)+void BattleGroundAV::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map, default values are set in constructor     BattleGroundAVScore* sc = new BattleGroundAVScore; Index: src/game/BattleGroundAV.h===================================================================--- src/game/BattleGroundAV.h	(revision 5116)+++ src/game/BattleGroundAV.h	(working copy)@@ -45,7 +45,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);          void RemovePlayer(Player *plr,uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);Index: src/game/BattleGroundBE.cpp===================================================================--- src/game/BattleGroundBE.cpp	(revision 5116)+++ src/game/BattleGroundBE.cpp	(working copy)@@ -98,9 +98,9 @@     }*/ } -void BattleGroundBE::AddPlayer(Player *plr)+void BattleGroundBE::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map, default values are set in constructor     BattleGroundBEScore* sc = new BattleGroundBEScore; @@ -109,7 +109,13 @@  void BattleGroundBE::RemovePlayer(Player *plr, uint64 guid) {+    if(GetStatus() == STATUS_WAIT_LEAVE)+        return; +    if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))+        EndBattleGround(HORDE);+    else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))+        EndBattleGround(ALLIANCE); }  void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)@@ -123,14 +129,20 @@         return;     } -    uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());+    uint32 killer_team = GetPlayerTeam(killer->GetGUID());+    if(!killer_team) killer_team = killer->GetTeam(); +    uint32 killer_team_index = GetTeamIndexByTeamId(killer_team);+     m_TeamKills[killer_team_index]++;                       // add kills to killer's team -    if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))+    uint32 team = GetPlayerTeam(player->GetGUID());+    if(!team) team = player->GetTeam();++    if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(team))     {         // all opponents killed-        EndBattleGround(killer->GetTeam());+        EndBattleGround(killer_team);     } } @@ -141,14 +153,14 @@         return;      uint32 SpellId = 0;-    uint64 buff_guid = 0;+    GameObject* obj = 0;     switch(Trigger)     {         case 4538:                                          // buff trigger?-            buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_1];+            obj = m_BgObjects[BG_BE_OBJECT_BUFF_1];             break;         case 4539:                                          // buff trigger?-            buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_2];+            obj = m_BgObjects[BG_BE_OBJECT_BUFF_2];             break;         default:             sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);@@ -156,11 +168,8 @@             break;     } -    if(buff_guid)+    if(obj)     {-        GameObject *obj = HashMapHolder<GameObject>::Find(buff_guid);-        if(obj)-        {             if(!obj->isSpawned())                 return;                                     // buff not spawned yet             obj->SetRespawnTime(BUFF_RESPAWN_TIME);@@ -168,7 +177,6 @@             SpellId = obj->GetGOInfo()->data3;             if(SpellId)                 Source->CastSpell(Source, SpellId, true);-        }     } } Index: src/game/BattleGroundBE.h===================================================================--- src/game/BattleGroundBE.h	(revision 5116)+++ src/game/BattleGroundBE.h	(working copy)@@ -58,7 +58,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);          void RemovePlayer(Player *plr, uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);Index: src/game/BattleGroundEY.cpp===================================================================--- src/game/BattleGroundEY.cpp	(revision 5116)+++ src/game/BattleGroundEY.cpp	(working copy)@@ -39,9 +39,9 @@     BattleGround::Update(diff); } -void BattleGroundEY::AddPlayer(Player *plr)+void BattleGroundEY::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map     BattleGroundEYScore* sc = new BattleGroundEYScore; Index: src/game/BattleGroundEY.h===================================================================--- src/game/BattleGroundEY.h	(revision 5116)+++ src/game/BattleGroundEY.h	(working copy)@@ -39,7 +39,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);          void RemovePlayer(Player *plr,uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);Index: src/game/BattleGroundHandler.cpp===================================================================--- src/game/BattleGroundHandler.cpp	(revision 5116)+++ src/game/BattleGroundHandler.cpp	(working copy)@@ -26,6 +26,8 @@ #include "MapManager.h" #include "ObjectAccessor.h" #include "Object.h"+#include "Chat.h"+#include "Language.h" #include "BattleGroundMgr.h" #include "BattleGroundWS.h" #include "BattleGround.h"@@ -78,6 +80,12 @@     recv_data >> instanceId;                                // instance id, 0 if First Available selected     recv_data >> joinAsGroup;                               // join as group +    if(bgTypeId >= MAX_BATTLEGROUND_TYPES)+    {+        sLog.outError("bgport: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow());+        return;+    }+     sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid);      // ignore if we already in BG or BG queue@@ -100,19 +108,38 @@         return;     } -    // check existence-    BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);-    if(!bg)+    BattleGround * bg = 0;+    if(instanceId)+        BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId);++    if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))+    {+        sLog.outDebug("bgjoin: no available bg / template found");         return;+    }      if(joinAsGroup && _player->GetGroup())     {         Group *grp = _player->GetGroup();+        if(grp->GetMembersCount() > bg->GetMaxPlayersPerTeam())+        {+            WorldPacket data;+            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, LANG_BG_GROUP_TOO_LARGE, NULL);+            SendPacket(&data);+            return;+        }+        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddGroup(_player, 0, false);         for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())         {             Player *member = itr->getSource();             if(!member) continue; +            if( member->GetBattleGroundQueueIdFromLevel() != _player->GetBattleGroundQueueIdFromLevel() )+                continue;++            if( member->GetTeam() != _player->GetTeam() )+                continue;+             if( !member->CanJoinToBattleground() )             {                 WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);@@ -134,15 +161,16 @@             }              // store entry point coords (same as leader entry point)-            member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());+            member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetInstanceId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());                                                              // send status packet (in queue)             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);             member->GetSession()->SendPacket(&data);             sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);             member->GetSession()->SendPacket(&data);-            sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId);+            sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, ginfo);         }+        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());     }     else     {@@ -159,13 +187,16 @@         }          // store entry point coords-        _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());+        _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetInstanceId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());          WorldPacket data;                                                             // send status packet (in queue)         sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);         SendPacket(&data);-        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId);++        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddGroup(_player, 0, false);+        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, ginfo);+        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());     } } @@ -247,6 +278,12 @@     uint32 bgTypeId;     recv_data >> bgTypeId;                                  // id from DBC +    if(bgTypeId >= MAX_BATTLEGROUND_TYPES)+    {+        sLog.outError("bgport: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow());+        return;+    }+     BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);      if(!bl)@@ -265,37 +302,83 @@      uint8 unk1;     uint8 unk2;                                             // unk, can be 0x0 (may be if was invited?) and 0x1+    uint32 instanceId;                                           uint32 bgTypeId;                                        // type id from dbc     uint16 unk;                                             // 0x1F90 constant?     uint8 action;                                           // enter battle 0x1, leave queue 0x0      recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action; -    BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);+    if(bgTypeId >= MAX_BATTLEGROUND_TYPES)+    {+        sLog.outError("bgport: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow());+        return;+    }++    // get the bg what we were invited to +    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId);+    BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());+    if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())+    {+        sLog.outDebug("bgport: itrplayerstatus not found.");+        return;+    }+    instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;//*/++    if(!instanceId && action == 1)+    {+        sLog.outDebug("bgport: instance not found.");+        return;+    }++    BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId);++    if(!bg && action == 0)+        bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);++    if(!bg)+    {+        sLog.outDebug("bgport: bg not found.");+        return;+    }++    bgTypeId = bg->GetTypeID();     if(bg)     {         if(_player->InBattleGroundQueue())         {             uint32 queueSlot = 0;+            uint32 team = 0;+            uint32 arenatype = 0;+            uint32 israted = 0;+            // get the team info from the queue+            BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());+            if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()+                && pitr->second.GroupInfo )+            {+                team = pitr->second.GroupInfo->Team;+                arenatype = pitr->second.GroupInfo->ArenaType;+                israted = pitr->second.GroupInfo->IsRated;+            }             WorldPacket data;             switch(action)             {                 case 1:                                     // port to battleground-                    _player->RemoveFromGroup();-                    queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId);+                    //_player->RemoveFromGroup();+                    queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);                     sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());                     _player->GetSession()->SendPacket(&data);                     // remove battleground queue status from BGmgr-                    sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false);-                    // check if player is not deserter-                    if( !_player->CanJoinToBattleground() )+                    sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);+                    // check if player is not deserter -- check in signup, not here!+                    /*if( !_player->CanJoinToBattleground() )                     {                         WorldPacket data2;                         data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);                         data2 << (uint32) 0xFFFFFFFE;                         SendPacket(&data2);                         return;-                    }+                    }*/                     // if player is in battleground already, remove him and port him to new battleground                     if ( _player->InBattleGround() )                     {@@ -303,15 +386,16 @@                         if (currentBg)                             currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);                     }-                    _player->SetBattleGroundId(bg->GetTypeID());-                    sBattleGroundMgr.SendToBattleGround(_player, bgTypeId);-                    bg->AddPlayer(_player);+                    _player->SetBattleGroundId(bg->GetInstanceID());    // really bg type, or rather instance id?+                    // for now, it works with typeid, but should be instance id. +                    sBattleGroundMgr.SendToBattleGround(_player, instanceId, team);+                    bg->AddPlayer(_player,team);                     break;                 case 0:                                     // leave queue-                    queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId);-                    _player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs+                    queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);+                    _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs                     sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0);-                    sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true);+                    sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);                     SendPacket(&data);                     break;                 default:@@ -350,7 +434,8 @@         BattleGround *bg = _player->GetBattleGround();         if(bg)         {-            uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID());+            uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID());+            uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);             if((bg->GetStatus() <= STATUS_IN_PROGRESS))             {                 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());@@ -358,10 +443,10 @@             }             for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)             {-                uint32 queue_id = _player->GetBattleGroundQueueId(i);-                if (i == queueSlot || !queue_id)+                uint32 queue_id = _player->GetBattleGroundQueueId(i);       // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong+                if (i == queueSlot || !queue_id)                            // we need to get the instance ids                     continue;-                BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id);+                BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(queue_id); //  try this                 if(bg2)                 {                     //in this call is small bug, this call should be filled by player's waiting time in queue@@ -377,8 +462,8 @@         // we should update all queues? .. i'm not sure if this code is correct         for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)         {-            uint32 queue_id = _player->GetBattleGroundQueueId(i);-            BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id);+            uint32 queue_id = sBattleGroundMgr.BGQueueTypeId(_player->GetBattleGroundQueueId(i));+            BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(queue_id);             if(bg && queue_id)             {                 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0);@@ -453,7 +538,7 @@     recv_data.hexlike();      // ignore if we already in BG or BG queue-    if(_player->InBattleGround() || _player->InBattleGroundQueue())+    if(_player->InBattleGround())         return;      uint64 guid;                                            // arena Battlemaster guid@@ -487,23 +572,57 @@             break;     } -    if(isRated && !_player->GetArenaTeamId(type))           // player not in arena team of that size+    if(isRated)           // player not in arena team of that size     {-        _player->GetSession()->SendNotInArenaTeamPacket(arenatype);-        return;+        uint32 ateamId = _player->GetArenaTeamId(type);+        if(!ateamId)+        {+            _player->GetSession()->SendNotInArenaTeamPacket(arenatype);+            return;+        }+        Group *grp = _player->GetGroup();+        if(grp)+        {+            for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())+            {+                Player *member = itr->getSource();++                // offline member or not in team -> err+                if(!member || member->GetArenaTeamId(type) != ateamId)+                {+                    WorldPacket data;+                    ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, LANG_ARENA_YOUR_TEAM_ONLY, NULL);+                    SendPacket(&data);+                    return;+                }+            }+        }     }      if(asGroup && !_player->GetGroup())                     // player not in group         return; -    // check existence-    BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA);-    if(!bg)+    //check existance+    BattleGround* bg = NULL;+    if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) )+    {+        sLog.outDebug("arena_join template bg (all arenas) not found");              return;+    } +    uint8 bgTypeId = bg->GetTypeID();+     if(asGroup && _player->GetGroup())     {         Group *grp = _player->GetGroup();+        if(grp->GetMembersCount() > arenatype)+        {+            WorldPacket data;+            ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, LANG_ARENA_GROUP_TOO_LARGE, NULL);+            SendPacket(&data);+            return;+        }+        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddGroup(_player, arenatype, isRated);         for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())         {             Player *member = itr->getSource();@@ -513,13 +632,23 @@                 //player has deserter aura .. do nothing             */ -            if (member->GetBattleGroundQueueIndex(BATTLEGROUND_AA) < PLAYER_MAX_BATTLEGROUND_QUEUES)+            if( member->GetBattleGroundQueueIdFromLevel() != _player->GetBattleGroundQueueIdFromLevel() )+                continue;++            if( member->GetTeam() != _player->GetTeam() )+                continue;++            if (member->GetBattleGroundQueueIndex(bgTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)+            {+                sLog.outDebug("all arenas: player is already in this queue");                 //player is already in this queue                 continue;+            } -            uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA);// add to queue+            uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId);// add to queue             if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)             {+                sLog.outDebug("arena_join player max bg queues are filled. error");                 WorldPacket data;                 //fill data                 //member->GetSession()->SendPacket(data);@@ -527,16 +656,17 @@             }              // store entry point coords (same as leader entry point)-            member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());+            member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetInstanceId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());              WorldPacket data;             // send status packet (in queue)             sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);             member->GetSession()->SendPacket(&data);-            sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA);+            sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);             member->GetSession()->SendPacket(&data);-            sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA);+            sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, ginfo);         }+        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated);     }     else     {@@ -544,13 +674,17 @@             //player has deserter aura .. do nothing         */ -        if (_player->GetBattleGroundQueueIndex(BATTLEGROUND_AA) < PLAYER_MAX_BATTLEGROUND_QUEUES)+        if (_player->GetBattleGroundQueueIndex(bgTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)+        {+            sLog.outDebug("player is already in all_arenas queue");             //player is already in this queue             return;+        } -        uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA);+        uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId);         if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)         {+            sLog.outDebug("arenajoin player queues are already full");             WorldPacket data;             //fill data (player is in 3 queues already)             //SendPacket(data);@@ -558,12 +692,15 @@         }          // store entry point coords-        _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());+        _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetInstanceId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());          WorldPacket data;         // send status packet (in queue)         sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);         SendPacket(&data);-        sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA);+        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddGroup(_player,arenatype,isRated);+        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, ginfo);+        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated);+//        sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId, 0, 0, arenatype, isRated);     } }Index: src/game/BattleGroundMgr.cpp===================================================================--- src/game/BattleGroundMgr.cpp	(revision 5116)+++ src/game/BattleGroundMgr.cpp	(working copy)@@ -42,112 +42,456 @@  BattleGroundQueue::BattleGroundQueue() {+    sLog.outDebug("Creating battleground queue");     //queues are empty, we don't have to call clear()     for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)     {-        m_QueuedPlayers[i].Horde = 0;-        m_QueuedPlayers[i].Alliance = 0;+        //m_QueuedPlayers[i].Horde = 0;+        //m_QueuedPlayers[i].Alliance = 0;         //m_QueuedPlayers[i].AverageTime = 0;     } }  BattleGroundQueue::~BattleGroundQueue() {+    sLog.outDebug("Destroying battleground queue");     for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)     {         m_QueuedPlayers[i].clear();+        for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr)+        {+            delete (*itr);+        }+        m_QueuedGroups[i].clear();     } } -void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId)+void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated) {+    sLog.outDebug("initializing eligible groups for side %u, maxplayers %u, arenatype %u, rated %u",side,MaxPlayers,ArenaType,IsRated);+    clear();+    BattleGroundQueue::QueuedGroupsList::iterator itr, next;+    for(itr = source->begin(); itr!= source->end(); itr = next)+    {+        next = itr;+        ++next;+        if( (*itr)->ArenaType == ArenaType &&+            (*itr)->IsRated == IsRated &&+            (*itr)->IsInvitedToBGInstanceGUID == 0 &&+            (*itr)->Team == side &&+            (*itr)->Players.size() <= MaxPlayers )+        {+            sLog.outDebug("Found an eligible group. Inserting it.");+            // the group matches the conditions+            // insert it in order of groupsize+            uint32 size = (*itr)->Players.size();+            uint32 jointime = (*itr)->JoinTime;+            bool inserted = false;++            for(std::list<GroupQueueInfo *>::iterator elig_itr = begin(); elig_itr != end(); ++elig_itr)+            {+                // if the next one's size is smaller, then insert+                // also insert if the next one's size is equal, but it joined the queue later+                if( ((*elig_itr)->Players.size()<size) ||+                    ((*elig_itr)->Players.size() == size && (*elig_itr)->JoinTime > jointime) )+                {+                    sLog.outDebug("inserting inside list");+                    insert(elig_itr,(*itr));+                    inserted = true;+                    break;+                }+            }+            // if not inserted -> this is the smallest group -> push_back+            if(!inserted)+            {+                sLog.outDebug("inserting at end of list");+                push_back((*itr));+            }+        }+    }+}++void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo)+{+    sLog.outDebug("EligibleGroups::RemoveGroup");+    for(std::list<GroupQueueInfo *>::iterator itr = begin(); itr != end(); ++itr)+    {+        if((*itr)=ginfo)+        {+            sLog.outDebug("Group found, erase");+            erase(itr);+            return;+        }+    }+}++void BattleGroundQueue::SelectionPool::Init()+{+    sLog.outDebug("Initializing selection pool");+    SelectedGroups.clear();+    MaxGroup = 0;+    PlayerCount = 0;+}++GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup()+{+    sLog.outDebug("Getting maximal group from SelectionPool");+    if(SelectedGroups.empty())+    {+        sLog.outError("Getting max group when selection pool is empty, this should never happen.");+        MaxGroup = NULL;+        return 0;+    }+    if(MaxGroup==0 && !SelectedGroups.empty())+    {+        uint32 max_size = 0;+        for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr)+        {+            if(max_size<(*itr)->Players.size())+            {+                MaxGroup =(*itr);+                max_size = MaxGroup->Players.size();+            }+        }+    }+    return MaxGroup;+}++void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo)+{+    sLog.outDebug("Removing group from SelectionPool");+    if(MaxGroup == ginfo)+        MaxGroup = 0;+    for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr)+    {+        if((*itr)=ginfo)+        {+            SelectedGroups.erase(itr);+            PlayerCount -= ginfo->Players.size();+            return;+        }+    }+}++void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo)+{+    sLog.outDebug("Adding group to SelectionPool");+    SelectedGroups.push_back(ginfo);+    PlayerCount+=ginfo->Players.size();+    if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size())+    {+        sLog.outDebug("Setting the newly added group as MaxGroup");+        MaxGroup = ginfo;+    }+}+++GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, uint8 ArenaType, bool isRated)+{+    sLog.outDebug("Adding Group to BGQueue with leader %u",leader->GetGUIDLow());+    uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel();++    GroupQueueInfo* ginfo = new GroupQueueInfo;+    ginfo->ArenaType                 = ArenaType;+    ginfo->IsRated                   = isRated;+    ginfo->IsInvitedToBGInstanceGUID = 0;+    ginfo->JoinTime                = getMSTime();+    ginfo->Team                      = leader->GetTeam();++    ginfo->Players.clear();++    m_QueuedGroups[queue_id].push_back(ginfo);++    return ginfo;+}++void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)+{+    sLog.outDebug("Adding player %u to BGGroup in queue", plr->GetGUIDLow());     uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel();      //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak     PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()];     info.InviteTime                 = 0;-    info.IsInvitedToBGInstanceGUID  = 0;     info.LastInviteTime             = 0;     info.LastOnlineTime             = getMSTime();-    info.Team                       = plr->GetTeam();+    info.GroupInfo                  = ginfo; -    //add player to waiting order queue-    m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID());--    if(plr->GetTeam() == ALLIANCE)-        m_QueuedPlayers[queue_id].Alliance++;-    else-        m_QueuedPlayers[queue_id].Horde++;--    /* temporary BG queue status message-    std::ostringstream str;-    str << "Battleground queue invited status: horde: " << m_QueuedPlayers[queue_id].Horde << ", aliance: " << m_QueuedPlayers[queue_id].Alliance;-    plr->Say(str.str(), LANG_UNIVERSAL);*/--    this->Update(bgTypeId, queue_id);+    ginfo->Players[plr->GetGUID()]  = &info; }  void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) {+    sLog.outDebug("removing player guid %u", guid);     Player *plr = objmgr.GetPlayer(guid);      uint32 queue_id = 0;     QueuedPlayersMap::iterator itr;+    GroupQueueInfo * group;+    QueuedGroupsList::iterator group_itr;     bool IsSet = false;-    if(!plr)-    {                                                       //player is offline, we need to find him somewhere in queues-        /// there is something wrong if this code is run, because we have in queue only online players!-        sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash");+    if(plr)+    {+        sLog.outDebug("plr found");+        queue_id = plr->GetBattleGroundQueueIdFromLevel();++        itr = m_QueuedPlayers[queue_id].find(guid);+        if(itr != m_QueuedPlayers[queue_id].end())+            IsSet = true;+    }++    if(!IsSet)+    {                                                       +        // either player is offline, or he levelled up to another queue category+        // sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash");         for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)         {             itr = m_QueuedPlayers[i].find(guid);             if(itr != m_QueuedPlayers[i].end())             {+                sLog.outDebug("player itr found.");                 queue_id = i;                 IsSet = true;                 break;             }         }     }-    else-    {                                                       //player is online, we have his level, so we can find exact queue from his level-        queue_id = plr->GetBattleGroundQueueIdFromLevel();-        itr = m_QueuedPlayers[queue_id].find(guid);-        IsSet = true;++    // couldn't find the player in bg queue, return+    if(!IsSet)+    {+        sLog.outError("Battleground: couldn't find player to remove.");+        return;     } -    //all variables are set, so remove player-    //remove player from time queue-    m_PlayersSortedByWaitTime[queue_id].remove(guid);+    group = itr->second.GroupInfo; -    if (IsSet && itr != m_QueuedPlayers[queue_id].end())+    for(group_itr=m_QueuedGroups[queue_id].begin(); group_itr != m_QueuedGroups[queue_id].end(); ++group_itr)     {-        if (!itr->second.IsInvitedToBGInstanceGUID)+        if(group == (GroupQueueInfo*)(*group_itr))+            break;+    }++    // variables are set (what about leveling up when in queue????)+    // remove player from group+    // if only player there, remove group++    // remove player queue info from group queue info+    std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid);++    if(pitr != group->Players.end())+    {+        sLog.outDebug("player found, now remove");+        group->Players.erase(pitr);+    }++    if(group->Players.empty())+    {+        // player group is empty, remove group from wait queue+        // not yet implemented, probably won't ever be :(+    }++    if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end())+    {+        if (!group->IsInvitedToBGInstanceGUID)         {+/*            // do nothing for now             if(itr->second.Team == ALLIANCE)                 m_QueuedPlayers[queue_id].Alliance--;             else-                m_QueuedPlayers[queue_id].Horde--;+                m_QueuedPlayers[queue_id].Horde--;*/         }         else         {             if (decreaseInvitedCount)             {-                BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID);+                sLog.outDebug("BGQueue - decreasing invited count");+                BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID);                 if (bg)-                    bg->DecreaseInvitedCount(itr->second.Team);+                    bg->DecreaseInvitedCount(group->Team);+                // update the join queue, maybe now the player's group fits in a queue!             }         }+        // remove player queue info         m_QueuedPlayers[queue_id].erase(itr);+        // remove group queue info if needed+        if(group->Players.empty())+        {+            sLog.outDebug("BGQueue:RemovePlayer:deleting group");+            m_QueuedGroups[queue_id].erase(group_itr);+            delete group;+        }     } } +bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side)+{+    sLog.outDebug("Inviting group to bg, groupsize %u, bgtype %u, instance %u, as side %u",ginfo->Players.size(), bg->GetTypeID(), bg->GetInstanceID(), side);+    // set side if needed+    if(side)+        ginfo->Team = side;++    if(!ginfo->IsInvitedToBGInstanceGUID)+    {+        // not yet invited+        // set invitation+        ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();+        // loop through the players+        for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)+        {+            // set status+            itr->second->InviteTime = getMSTime();+            itr->second->LastInviteTime = getMSTime();++            // get the player+            Player* plr = objmgr.GetPlayer(itr->first);+            // if offline, skip him+            if(!plr)+                continue;++            // invite the player+            sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team);++            WorldPacket data;++            uint32 queueSlot = 0;+            if(bg->isArena())+                queueSlot = plr->GetBattleGroundQueueIndex(BATTLEGROUND_AA);+            else+                queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID());++            sLog.outDebug("Battleground: invite plr %u queueindex %u bgtype %u",plr->GetGUIDLow(),queueSlot,bg->GetTypeID());++            // send status packet+            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);+            plr->GetSession()->SendPacket(&data);+        }+        return true;+    }++    sLog.outDebug("Group already invited to bg, doing nothing");+    return false;+}++// this function is responsible for the selection of queued groups when trying to create new battlegrounds+bool BattleGroundQueue::BuildSelectionPool(uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers,  SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated)+{+    sLog.outDebug("Building selection pool, mode %u", mode);+    uint32 side;+    switch(mode)+    {+    case NORMAL_ALLIANCE:+    case ONESIDE_ALLIANCE_TEAM1:+    case ONESIDE_ALLIANCE_TEAM2:+        side = ALLIANCE;+        break;+    case NORMAL_HORDE:+    case ONESIDE_HORDE_TEAM1:+    case ONESIDE_HORDE_TEAM2:+        side = HORDE;+        break;+    default:+        //unknown mode, return false+        sLog.outDebug("Battleground: unknown selection pool build mode, returning...");+        return false;+        break;+    }++    // inititate the groups eligible to create the bg+    m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), side, MaxPlayers, ArenaType, isRated);+    // init the selected groups (clear)+    m_SelectionPools[mode].Init();+    while(!(m_EligibleGroups.empty()))+    {+        sLog.outDebug("m_EligibleGroups is not empty, continue building selection pool");+        // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players+        for(EligibleGroups::iterator itr= m_EligibleGroups.begin(); itr!=m_EligibleGroups.end(); ++itr)+        {+            // get the maximal not yet checked group+            GroupQueueInfo * MaxGroup = (*itr);+            // if it fits in the maxplayer size, add it+            if( (m_SelectionPools[mode].GetPlayerCount() + MaxGroup->Players.size()) <= MaxPlayers )+            {+                m_SelectionPools[mode].AddGroup(MaxGroup);+            }+        }+        if(m_SelectionPools[mode].GetPlayerCount()>=MinPlayers)+        {+            // the selection pool is set, return+            sLog.outDebug("pool build succeeded, return true");+            return true;+        }+        // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest.+        GroupQueueInfo * MaxGroup = m_SelectionPools[mode].GetMaximalGroup();+        m_EligibleGroups.RemoveGroup(MaxGroup);+        m_SelectionPools[mode].RemoveGroup(MaxGroup);+    }+    // failed to build a selection pool matching the given values+    return false;+}++void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)+{+    sLog.outDebug("BG Ended, removing invited groups");+    uint32 queue_id = bg->GetQueueType();+    uint32 bgInstanceId = bg->GetInstanceID();+    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID());+    QueuedGroupsList::iterator itr, next;+    for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next)+    {+        // must do this way, because the groupinfo will be deleted when all playerinfos are removed+        GroupQueueInfo * ginfo = (*itr);+        next = itr;+        ++next;+        // if group was invited to this bg instance, then remove all references+        if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId)+        {+            // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop+            uint32 to_remove = ginfo->Players.size();+            uint32 team = ginfo->Team;+            for(int i = 0; i < to_remove; ++i)+            {+                // always remove the first one in the group+                std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin();+                if(itr2 == ginfo->Players.end())+                {+                    sLog.outError("Empty Players in ginfo, this should never happen!");+                    return;+                }++                // get the player+                Player * plr = objmgr.GetPlayer(itr2->first);+                if(!plr)+                {+                    sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen.");+                    continue;+                }++                // get the queueslot+                uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);+                if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue+                {+                    plr->RemoveBattleGroundQueueId(bgQueueTypeId);+                    // remove player from queue, this might delete the ginfo as well! don't use that pointer after this!+                    RemovePlayer(itr2->first, true);+                    Update(bgQueueTypeId, bg->GetQueueType());+                    WorldPacket data;+                    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0);+                    plr->GetSession()->SendPacket(&data);+                }+            }+        }+    }+}+ /*-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-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+this 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+it must be called after fully adding the members of a group to ensure group joining+should be called after removeplayer functions in some cases */-void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id)+void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated) {+    sLog.outDebug("Battleground: Update with bgtype %u, queueid %u", bgTypeId, queue_id);     if (queue_id >= MAX_BATTLEGROUND_QUEUES)     {         //this is error, that caused crashes (not in , but now it shouldn't)@@ -156,158 +500,310 @@     }      //if no players in queue ... do nothing-    if (this->m_QueuedPlayers[queue_id].Alliance == 0 && this->m_QueuedPlayers[queue_id].Horde == 0)+    if (this->m_QueuedGroups[queue_id].size() == 0)         return;      //battleground with free slot for player should be always the last in this queue-    BGFreeSlotQueueType::iterator itr;-    for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr)+    BGFreeSlotQueueType::iterator itr, next;+    for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) // iterate only till .back(), not .end()!     {+        sLog.outDebug("Iterating BGFreeSlotQueue");+        next = itr;+        ++next;         // battleground is running, so if:         // DO NOT allow queue manager to invite new player to running arena         if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE)         {+            sLog.outDebug("proper bg with free slots found");             //we must check both teams             BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!)             // and iterator is invalid -            //check if there are some players in queue-            if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0)+            for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr)             {-                for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();)+                sLog.outDebug("Iterating through queued groups");+                if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size())                 {-                    Player* plr = objmgr.GetPlayer(*itr2);-                    if (!plr)-                    {-                        //something is wrong!, kick player from queue-                        sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug");-                        uint64 oldval = *itr2;-                        itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);-                        this->RemovePlayer(oldval, true);-                        continue;-                    }+                    sLog.outDebug("group fits in, inviting");+                    InviteGroupToBG((*itr),bg,(*itr)->Team);+                }+            } -                    // player will be invited, if in bg there is a free slot for him-                    if (bg->HasFreeSlotsForTeam(plr->GetTeam()))-                    {-                        // iterator to player's queue status-                        QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2);+            if (!bg->HasFreeSlots())+            {+                sLog.outDebug("bg type %u, instance %u is full, removing from free slot queue", bg->GetTypeID(), bg->GetInstanceID());+                //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue+                bg->RemoveFromBGFreeSlotQueue(); // --- do not uncomment this - not yet implemented+                //if bg is full, there is no need to invite other players, so break+//                break;+            }+        }+    } -                        // remove him from time queue-                        itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);+    // finished iterating through the bgs with free slots, maybe we need to create a new bg -                        // 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)-                        if (itrPlayerStatus == m_QueuedPlayers[queue_id].end())-                            continue;+    BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);+    if(!bg_template)+    {+        sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId);+        return;+    }+    sLog.outDebug("BG Template found"); -                        // check if player is not already invited-                        if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID)-                        {-                            itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID();-                            itrPlayerStatus->second.InviteTime = getMSTime();-                            itrPlayerStatus->second.LastInviteTime = getMSTime();-                            if(itrPlayerStatus->second.Team == ALLIANCE)-                                m_QueuedPlayers[queue_id].Alliance--;-                            else-                                m_QueuedPlayers[queue_id].Horde--;-                            sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID());+    // get the min. players per team, properly for larger arenas as well. (must have full teams for rated matches!)+    uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam();+    uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam();+    if(bg_template->isArena())+    {+        switch(arenatype)+        {+        case ARENA_TYPE_2v2:+            MaxPlayersPerTeam = 2;+            MinPlayersPerTeam = 2;+            break;+        case ARENA_TYPE_3v3:+            MaxPlayersPerTeam = 3;+            MinPlayersPerTeam = 3;+            break;+        case ARENA_TYPE_5v5:+            MaxPlayersPerTeam = 5;+            MinPlayersPerTeam = 5;+            break;+        }+    } -                            WorldPacket data;-                            uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId);-                            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);-                            plr->GetSession()->SendPacket(&data);-                        }-                    }-                    else-                        ++itr2;+    // try to build the selection pools+    bool bAllyOK = BuildSelectionPool(queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated);+    if(bAllyOK)+        sLog.outDebug("Battleground: ally pool succesfully build");+    else+        sLog.outDebug("Battleground: ally pool wasn't created");+    bool bHordeOK = BuildSelectionPool(queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated);+    if(bHordeOK)+        sLog.outDebug("Battleground: horde pool succesfully built");+    else+        sLog.outDebug("Battleground: horde pool wasn't created"); -                    //if battleground is FULL, then it is removed from free slot queue - not yet implemented!-                    if (!bg->HasFreeSlots())-                    {-                        //if bg is full, there is no need to invite other players, so break-                        break;-                        //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue-                        //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented-                    }-                }+    // if selection pools are ready, create the new bg+    if (bAllyOK && bHordeOK)+    {+        BattleGround * bg2 = 0;+        // special handling for arenas+        if(bg_template->isArena())+        {+            // Find a random arena, that can be created+            uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL};+            uint32 arena_num = urand(0,2);+            if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) &&+                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) &&+                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) )+            {+                sLog.outError("Battleground: couldn't create arena");+                return;             }++            // set the MaxPlayersPerTeam values based on arenatype+            // setting the min player values isn't needed, since we won't be using that value later on.+            switch(arenatype)+            {+            case ARENA_TYPE_2v2:+                bg2->SetMaxPlayersPerTeam(2);+                bg2->SetMaxPlayers(4);+                break;+            case ARENA_TYPE_3v3:+                bg2->SetMaxPlayersPerTeam(3);+                bg2->SetMaxPlayers(6);+                break;+            case ARENA_TYPE_5v5:+                bg2->SetMaxPlayersPerTeam(5);+                bg2->SetMaxPlayers(10);+                break;+            default:+                break;+            }         }-    }+        else+        {+            // create new battleground+            bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId);+        } -    /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */-    //itr->end is the last BG - template, which is not already started!+        if(!bg2)+        {+            sLog.outError("Battleground: couldn't create bg %u",bgTypeId);+            return;+        } -    /* here will be a most of change, when we create battlegrounds instanciated */-    /* if (there is enought players to start new BG)-        Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId)-        - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template-            (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */+        sLog.outDebug("BG Created."); -    /* folowing code is working with current Battleground system and it should be removed, when BGs will work like instances */-    BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId);-    if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE)-        return;-    if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam())-    {+        // start the joining of the bg         bg2->SetStatus(STATUS_WAIT_JOIN);         bg2->SetQueueType(queue_id);+        // initialize arena / rating info+        bg2->SetArenaType(arenatype);+        // set rating+        bg2->SetRated(isRated); -        for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();)+        std::list<GroupQueueInfo* >::iterator itr;++        // invite groups from horde selection pool+        for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr)         {-            Player* plr = objmgr.GetPlayer(*itr2);-            if (!plr)+            InviteGroupToBG((*itr),bg2,HORDE);+        }++        // invite groups from ally selection pools+        for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr)+        {+            InviteGroupToBG((*itr),bg2,ALLIANCE);+        }++        sLog.outDebug("Starting bg.");+        // start the battleground+        bg2->StartBattleGround(0);+        sLog.outDebug("BG Started.");+    }++    // there weren't enough players for a "normal" match+    // if arena, enable horde versus horde or alliance versus alliance teams here++    else if(bg_template->isArena())+    {+        bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false;+        bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false;+        bOneSideHordeTeam1 = BuildSelectionPool(queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated);+        if(bOneSideHordeTeam1)+        {+            sLog.outDebug("one side horde team1 alright");+            // one team has been selected, find out if other can be selected too+            std::list<GroupQueueInfo* >::iterator itr;+            // temporarily change the team side to enable building the next pool excluding the already selected groups+            for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr)+                (*itr)->Team=ALLIANCE;++            bOneSideHordeTeam2 = BuildSelectionPool(queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated);++            // change back the team to horde+            for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr)+                (*itr)->Team=HORDE;++            if(!bOneSideHordeTeam2)+                bOneSideHordeTeam1 = false;+            else+                sLog.outDebug("one side horde team2 alright");+        }+        if(!bOneSideHordeTeam1)+        {+            // check for one sided ally+            bOneSideAllyTeam1 = BuildSelectionPool(queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated);+            if(bOneSideAllyTeam1)             {-                //something is wrong!, kick player from queue-                sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug");-                uint64 oldval = *itr2;-                itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);-                this->RemovePlayer(oldval, true);-                continue;+                // one team has been selected, find out if other can be selected too+                std::list<GroupQueueInfo* >::iterator itr;+                // temporarily change the team side to enable building the next pool excluding the already selected groups+                for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr)+                    (*itr)->Team=HORDE;++                bOneSideAllyTeam2 = BuildSelectionPool(queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated);++                // change back the team to ally+                for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr)+                    (*itr)->Team=ALLIANCE;             } -            /* TODO: (i'm not sure this code will be useful:-            here should be some condition like if (bg2->isArena() && bg2->isRated())+            if(!bOneSideAllyTeam2)+                bOneSideAllyTeam1 = false;+        }+        // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!!+        if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) ||+            (bOneSideAllyTeam1 && bOneSideAllyTeam2) )+        {+            // create random arena+            uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL};+            uint32 arena_num = urand(0,2);+            BattleGround* bg2 = NULL;+            if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) &&+                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) &&+                !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) )             {-                invite players from 1 certain group on each faction to play arena match-            } else if ....and existing code-            */-            // player will be invited, if in bg there is a free slot for him-            if (bg2->HasFreeSlotsForTeam(plr->GetTeam()))+                sLog.outError("Could not create arena.");+                return;+            }++            sLog.outDebug("Arena created.");+            // init stats+            switch(arenatype)             {-                // iterator to player's queue status-                QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2);+            case ARENA_TYPE_2v2:+                bg2->SetMaxPlayersPerTeam(2);+                bg2->SetMaxPlayers(4);+                break;+            case ARENA_TYPE_3v3:+                bg2->SetMaxPlayersPerTeam(3);+                bg2->SetMaxPlayers(6);+                break;+            case ARENA_TYPE_5v5:+                bg2->SetMaxPlayersPerTeam(5);+                bg2->SetMaxPlayers(10);+                break;+            default:+                break;+            } -                // remove him from time queue-                itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);+            bg2->SetRated(isRated);+            // which side has enough players?+            uint32 side = 0;+            SelectionPoolBuildMode mode1, mode2;+            // find out what pools are we using+            if(bOneSideAllyTeam1 && bOneSideAllyTeam2)+            {+                side = ALLIANCE;+                mode1 = ONESIDE_ALLIANCE_TEAM1;+                mode2 = ONESIDE_ALLIANCE_TEAM2;+            }+            else+            {+                side = HORDE;+                mode1 = ONESIDE_HORDE_TEAM1;+                mode2 = ONESIDE_HORDE_TEAM2;+            }+            // assigned team of the other group+            uint32 other_side;+            if(side == ALLIANCE)+                other_side = HORDE;+            else+                other_side = ALLIANCE; -                // 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)-                if (itrPlayerStatus == m_QueuedPlayers[queue_id].end())-                    continue;+            // set the team type of the arena+            if(side == ALLIANCE)+                bg2->SetTeamType(BG_TEAM_TYPE_ALLIANCE_ONLY);+            else+                bg2->SetTeamType(BG_TEAM_TYPE_HORDE_ONLY); -                //check if player is not already invited-                if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID)-                {-                    itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID();-                    itrPlayerStatus->second.InviteTime = getMSTime();-                    itrPlayerStatus->second.LastInviteTime = getMSTime();+            // start the joining of the bg+            bg2->SetStatus(STATUS_WAIT_JOIN);+            bg2->SetQueueType(queue_id);+            // initialize arena / rating info+            bg2->SetArenaType(arenatype); -                    if(itrPlayerStatus->second.Team == ALLIANCE)-                        m_QueuedPlayers[queue_id].Alliance--;-                    else-                        m_QueuedPlayers[queue_id].Horde--;+            std::list<GroupQueueInfo* >::iterator itr; -                    sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID());+            // invite players from the first group as horde players (actually green team)+            for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr)+            {+                InviteGroupToBG((*itr),bg2,HORDE);+            } -                    WorldPacket data;-                    uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId);-                    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);-                    plr->GetSession()->SendPacket(&data);-                }+            // invite players from the second group as ally players (actually gold team)+            for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr)+            {+                InviteGroupToBG((*itr),bg2,ALLIANCE);             }-            else-                ++itr2;++            sLog.outDebug("Starting arena");+            bg2->StartBattleGround(0);+            sLog.outDebug("Arena started");         }-        bg2->StartBattleGround(0);     } } @@ -317,6 +813,7 @@  bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 p_time) {+    sLog.outDebug("Executing BGInvite event");     Player* plr = objmgr.GetPlayer( m_PlayerGuid );      // player logged off (we should do nothing, he is correctly removed from queue in another procedure)@@ -330,16 +827,17 @@     BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID);     if (bg)     {-        uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID());+        uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID());+        uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);         if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue         {             // 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-            BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()];+            BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()];             BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid);-            if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID)+            if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)             {                 WorldPacket data;-                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, BG_REMIND_INVITE_TIME, 0);+                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, BG_REMIND_INVITE_TIME, 0);                 plr->GetSession()->SendPacket(&data);             }         }@@ -355,6 +853,7 @@  bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) {+    sLog.outDebug("Executing BGRemove Event");     Player* plr = objmgr.GetPlayer( m_PlayerGuid );     if (!plr)         // player logged off (we should do nothing, he is correctly removed from queue in another procedure)@@ -366,17 +865,18 @@     BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID);     if (bg)     {-        uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID());+        uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID());+        uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);         if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue         {             // 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-            if (sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].find(m_PlayerGuid)->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID)+            if (sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].find(m_PlayerGuid)->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)             {-                plr->RemoveBattleGroundQueueId(bg->GetTypeID());-                sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true);-                sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType());+                plr->RemoveBattleGroundQueueId(bgQueueTypeId);+                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true);+                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgQueueTypeId, bg->GetQueueType());                 WorldPacket data;-                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0);+                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0);                 plr->GetSession()->SendPacket(&data);             }         }@@ -397,24 +897,46 @@  BattleGroundMgr::BattleGroundMgr() {+    sLog.outDebug("Creating BattleGroundMgr");     m_BattleGrounds.clear(); }  BattleGroundMgr::~BattleGroundMgr() {-    for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr)-        delete itr->second;+    sLog.outDebug("Destroying BattleGRoundMgr");+    BattleGroundSet::iterator itr, next;+    for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next)+    {+        next = itr;+        ++next;+        BattleGround * bg = itr->second;+        m_BattleGrounds.erase(itr);+        delete bg;+    }     m_BattleGrounds.clear(); }  void BattleGroundMgr::Update(time_t diff) {-    for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr)+    BattleGroundSet::iterator itr, next;+    for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next)+    {+        next = itr;+        ++next;         itr->second->Update(diff);+        if(itr->second->m_SetDeleteThis)+        {+            BattleGround * bg = itr->second;+            sLog.outDebug("deleting bg insta %u", bg->GetInstanceID());+            m_BattleGrounds.erase(itr);+            delete bg;+        }+    } }  void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) {+    sLog.outDebug("Building BGStatusPacket");     // we can be in 3 queues in same time...     if(StatusID == 0)     {@@ -427,7 +949,7 @@      data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4));     *data << uint32(QueueSlot);                             // queue id (0...2) - player can be in 3 queues in time-    *data << uint8(bg->GetArenaType());                     // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas+    *data << uint8(bg->GetArenaType());                     // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas    // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!!     switch(bg->GetTypeID())                                 // value depends on bg id     {         case BATTLEGROUND_AV:@@ -460,9 +982,9 @@     }      if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE))-        *data << uint32(BATTLEGROUND_AA);                   // all arenas+        *data << uint32(BATTLEGROUND_AA);                   // all arenas   I don't think so.     else-        *data << uint32(bg->GetTypeID());                   // BG id from DBC+    *data << uint32(bg->GetTypeID());                   // BG id from DBC      *data << uint16(0x1F90);                                // unk value 8080     *data << uint32(bg->GetInstanceID());                   // instance id@@ -497,6 +1019,7 @@  void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) {+    sLog.outDebug("Building PvpLogPacket");     uint8 type = (bg->isArena() ? 1 : 0);                                                             // checked on 2.1.3     data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));@@ -505,7 +1028,7 @@     {         for(uint8 i = 0; i < 2; i++)         {-            *data << uint32(3000+1+i);                      // rating change: showed value - 3000+            *data << uint32(3000+bg->m_ArenaTeamRatingChanges[i]);                      // rating change: showed value - 3000             *data << uint8(0);                              // string         }     }@@ -536,11 +1059,13 @@         {             // that part probably wrong             Player *plr = objmgr.GetPlayer(itr->first);+            uint32 team = bg->GetPlayerTeam(plr->GetGUID());+            if(!team) team = plr->GetTeam();             if(plr)             {-                if(plr->GetTeam() == HORDE)+                if(team == HORDE)                     *data << uint8(0);-                else if(plr->GetTeam() == ALLIANCE)+                else if(team == ALLIANCE)                     *data << uint8(1);                 else                     *data << uint8(0);@@ -624,20 +1149,109 @@     *data << uint64(plr->GetGUID()); } -void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID)+void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) {+    sLog.outDebug("bgmgr::inviteplayer %u to %u", plr->GetGUIDLow(), bgInstanceGUID);     // set invited player counters:     BattleGround* bg = this->GetBattleGround(bgInstanceGUID);-    bg->IncreaseInvitedCount(plr->GetTeam());+    bg->IncreaseInvitedCount(team); +    if(bg->isArena() && bg->isRated())+    {+        switch(bg->GetArenaType())+        {+        case ARENA_TYPE_2v2:+            bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0));+            break;+        case ARENA_TYPE_3v3:+            bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1));+            break;+        case ARENA_TYPE_5v5:+            bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2));+            break;+        default:+            break;+        }+    }+     // create invite events:     //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     BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID);     plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(BG_REMIND_INVITE_TIME));-    BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam());+    BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team);     plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(2*BG_REMIND_INVITE_TIME)); } +BattleGround * BattleGroundMgr::GetBattleGroundTemplate(uint32 bgTypeId)+{+    sLog.outDebug("Getting bg template for %u", bgTypeId);+    return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back();+}++BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId)+{+    sLog.outDebug("creating new bg %u", bgTypeId);+    // Create the BG+    BattleGround *bg = NULL;++    BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId);++    if(!bg_template)+    {+        sLog.outDebug("CreateNewBG - bg template not found for %u", bgTypeId);+        return 0;+    }+    +    switch(bgTypeId)+    {+        case BATTLEGROUND_AV: +            bg = new BattleGroundAV(*(BattleGroundAV*)bg_template); +            break;+        case BATTLEGROUND_WS: +            bg = new BattleGroundWS(*(BattleGroundWS*)bg_template); +            break;+        case BATTLEGROUND_AB: +            bg = new BattleGroundAB(*(BattleGroundAB*)bg_template); +            break;+        case BATTLEGROUND_NA: +            bg = new BattleGroundNA(*(BattleGroundNA*)bg_template); +            break;+        case BATTLEGROUND_BE: +            bg = new BattleGroundBE(*(BattleGroundBE*)bg_template); +            break;+        case BATTLEGROUND_AA: +            bg = new BattleGroundAA(*(BattleGroundAA*)bg_template); +            break;+        case BATTLEGROUND_EY: +            bg = new BattleGroundEY(*(BattleGroundEY*)bg_template); +            break;+        case BATTLEGROUND_RL: +            bg = new BattleGroundRL(*(BattleGroundRL*)bg_template); +            break;+        default:+            //bg = new BattleGround;   +            return 0;+            break;             // placeholder for non implemented BG+    }+    sLog.outDebug("generating instance id");+    bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id+    sLog.outDebug("id generated: %u",bg->GetInstanceID());+    bg->Reset();+    sLog.outDebug("bg reseted");+    if(!(bg->SetupBattleGround()))    // setup the battleground in its update function to ensure that a player is present in the instance. Otherwise the objects won't be spawned :(+    {+        sLog.outDebug("CreateNewBattleGround - SetupBattleGround failed for bg %u", bgTypeId);+        delete bg;+        return 0;+    }+    sLog.outDebug("bg is set up");+    bg->AddToBGFreeSlotQueue();++    AddBattleGround(bg->GetInstanceID(), bg);+    sLog.outDebug("bg added to queue and update list");+    return bg;+}+ uint32 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) {     // Create the BG@@ -657,13 +1271,19 @@     }      bg->SetMapId(MapID);++    // set unloadflag to false+    Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(MapID));+//    Map * map = MapManager::Instance().GetMap(GetMapId(), m_bgobjects[BG_AB_OBJECT_GATE_H]);+    if(map) map->SetUnloadMap(false);+     bg->Reset();-    if(!bg->SetupBattleGround())+/*    if(!bg->SetupBattleGround())      do not setup for template bgs!     {         delete bg;         return 0;     }-+*/     BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId);     //in previous method is checked if exists entry in sBattlemasterListStore, so no check needed     if (bl)@@ -672,7 +1292,8 @@     }      bg->SetTypeID(bgTypeId);-    bg->SetInstanceID(bgTypeId);                               // temporary+//    bg->SetInstanceID(bgTypeId);                               // temporary+    bg->SetInstanceID(0);                               // template bg, instance id is 0     bg->SetMinPlayersPerTeam(MinPlayersPerTeam);     bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam);     bg->SetMinPlayers(MinPlayersPerTeam*2);@@ -684,9 +1305,9 @@     //add BaggleGround instance to FreeSlotQueue     bg->AddToBGFreeSlotQueue(); -    AddBattleGround(bg->GetInstanceID(), bg);+//    AddBattleGround(bg->GetInstanceID(), bg); // do not! we're instantiating! only working ones need to be added, but not the templates!     //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);-    return bg->GetInstanceID();+    return bgTypeId; //bg->GetInstanceID(); }  void BattleGroundMgr::CreateInitialBattleGrounds()@@ -841,18 +1462,28 @@     } } -void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId)+void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId, uint32 team) {-    BattleGround *bg = GetBattleGround(bgTypeId);+    BattleGround *bg = GetBattleGround(instanceId);     if(bg)     {         uint32 mapid = bg->GetMapId();         float x, y, z, O;-        bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O);+        if(team==0)+            team = pl->GetTeam();+        bg->GetTeamStartLoc(team, x, y, z, O);          sLog.outDetail("BATTLEGROUND: Sending %s to %f, %f, %f, %f", pl->GetName(), x, y, z, O);-        pl->TeleportTo(mapid, x, y, z, O);+        // pl->SetInstanceId(instanceId); DO NOT DO THIS!!!! EVER!!!! (well, not here anyway)+        // actually, thinking a bit more, this wasn't used at all.+        pl->m_BoundInstances[mapid]=std::pair<uint32,uint32>(instanceId, pl->GetGUIDLow());+        // teleport as gm command+        pl->TeleportTo(mapid, x, y, z, O, true, true, true);     }+    else+    {+        sLog.outError("player %u trying to port to non-existent bg instance %u",pl->GetGUIDLow(), instanceId);+    } }  void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid)@@ -864,3 +1495,28 @@     data << guid << time_;     pl->GetSession()->SendPacket(&data); }++void BattleGroundMgr::RemoveBattleGround(uint32 instanceID)+{+    BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID);+    if(itr!=m_BattleGrounds.end())+        m_BattleGrounds.erase(itr);+}++bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const+{+    return ( bgTypeId == BATTLEGROUND_AA ||+        bgTypeId == BATTLEGROUND_BE ||+        bgTypeId == BATTLEGROUND_NA ||+        bgTypeId == BATTLEGROUND_RL );+}++bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const+{+    return !IsArenaType(bgTypeId);+}++uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId) const+{+    return IsArenaType(bgTypeId)?BATTLEGROUND_AA:bgTypeId;+}Index: src/game/BattleGroundMgr.h===================================================================--- src/game/BattleGroundMgr.h	(revision 5116)+++ src/game/BattleGroundMgr.h	(working copy)@@ -36,16 +36,23 @@  #define BG_REMIND_INVITE_TIME 60000                         // when this time pass, player get invitation request again +struct GroupQueueInfo; struct PlayerQueueInfo {     uint32  InviteTime;                                     // first invite time     uint32  LastInviteTime;                                 // last invite time-    uint32  IsInvitedToBGInstanceGUID;                      // was invited to certain BG     uint32  LastOnlineTime;                                 // for tracking and removing offline players from queue after 5 minutes+    GroupQueueInfo * GroupInfo;+};++struct GroupQueueInfo+{+    std::map<uint64, PlayerQueueInfo*> Players;     uint32  Team;                                           // Player team (ALLIANCE/HORDE)-    bool IsRated;-    bool AsGroup;                                           // uint32 GroupId;-    uint8 ArenaType;+    bool    IsRated;+    uint8   ArenaType;+    uint32  JoinTime;+    uint32  IsInvitedToBGInstanceGUID;                      // was invited to certain BG };  struct PlayersCount@@ -63,6 +70,7 @@         //uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players) }; +class BattleGround; class BattleGroundQueue {     public:@@ -72,15 +80,69 @@         uint32 GetType();         void SetType(uint32 type);*/ -        void Update(uint32 bgTypeId, uint32 queue_id);+        void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenateam = 0, bool isRated = false); -        void AddPlayer(Player *plr, uint32 bgTypeId);+        GroupQueueInfo * AddGroup(Player * leader, uint8 ArenaType, bool isRated);+        void AddPlayer(Player *plr, GroupQueueInfo * ginfo);         void RemovePlayer(uint64 guid, bool decreaseInvitedCount);+        void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);+        void BGEndedRemoveInvites(BattleGround * bg); -        typedef bgqueue<uint64, PlayerQueueInfo> QueuedPlayersMap;+//        uint32 GetPlayerCount(uint32 queueId, uint32 team, uint8 arenatype, bool isRated, uint32 instanceGUID = 0);++        typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;         QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES];-        typedef std::list<uint64> PlayerGuidsSortedByTimeQueue;-        PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES];++        typedef std::list<GroupQueueInfo*> QueuedGroupsList;+        QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES];++        typedef std::list<uint64> GroupIdsSortedByTimeQueue;+        GroupIdsSortedByTimeQueue m_GroupIdsSortedByWaitTime[MAX_BATTLEGROUND_QUEUES];++        class EligibleGroups : public std::list<GroupQueueInfo *>+        {+        public:+            void Init(QueuedGroupsList * source, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false);+            void RemoveGroup(GroupQueueInfo * ginfo);+        };++        EligibleGroups m_EligibleGroups;++        class SelectionPool+        {+        public:+            void Init();+            void AddGroup(GroupQueueInfo * group);+            GroupQueueInfo * GetMaximalGroup();+            void RemoveGroup(GroupQueueInfo * group);+            uint32 GetPlayerCount() const {return PlayerCount;}+        public:+            std::list<GroupQueueInfo *> SelectedGroups;+        private:+            uint32 PlayerCount;+            GroupQueueInfo * MaxGroup;+        };++        enum SelectionPoolBuildMode+        {+            NORMAL_ALLIANCE,+            NORMAL_HORDE,+            ONESIDE_ALLIANCE_TEAM1,+            ONESIDE_ALLIANCE_TEAM2,+            ONESIDE_HORDE_TEAM1,+            ONESIDE_HORDE_TEAM2,++            NUM_SELECTION_POOL_TYPES+        };++        SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES];++        bool BuildSelectionPool(uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false);++    private:++        bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side);+//        bool InvitePlayerToBG(PlayerGuidsSortedByTimeQueue::iterator &itr, Player * plr, BattleGround * bg, uint32 side); };  /*@@ -139,13 +201,13 @@          /* Player invitation */         // called from Queue update, or from Addplayer to queue-        void InvitePlayer(Player* plr, uint32 bgInstanceGUID);+        void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team);          /* Battlegrounds */         BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); };         BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; -        BattleGround* GetBattleGround(uint8 ID)+        BattleGround* GetBattleGround(uint32 ID)         {             BattleGroundSet::iterator i = m_BattleGrounds.find(ID);             if(i != m_BattleGrounds.end())@@ -154,13 +216,17 @@                 return NULL;         }; +        BattleGround * GetBattleGroundTemplate(uint32 bgTypeId);+        BattleGround * CreateNewBattleGround(uint32 bgTypeId);+         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);          inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; };+        void RemoveBattleGround(uint32 instanceID);          void CreateInitialBattleGrounds(); -        void SendToBattleGround(Player *pl, uint32 bgTypeId);+        void SendToBattleGround(Player *pl, uint32 bgTypeId, uint32 team = 0);          /* Battleground queues */         //these queues are instantiated when creating BattlegroundMrg@@ -170,6 +236,10 @@          void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); +        bool IsArenaType(uint32 bgTypeId) const;+        bool IsBattleGroundType(uint32 bgTypeId) const;+        uint32 BGQueueTypeId(uint32 bgTypeId) const;+     private:          /* Battlegrounds */Index: src/game/BattleGroundNA.cpp===================================================================--- src/game/BattleGroundNA.cpp	(revision 5116)+++ src/game/BattleGroundNA.cpp	(working copy)@@ -92,9 +92,9 @@     }*/ } -void BattleGroundNA::AddPlayer(Player *plr)+void BattleGroundNA::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map, default values are set in constructor     BattleGroundNAScore* sc = new BattleGroundNAScore; @@ -103,7 +103,13 @@  void BattleGroundNA::RemovePlayer(Player *plr, uint64 guid) {+    if(GetStatus() == STATUS_WAIT_LEAVE)+        return; +    if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))+        EndBattleGround(HORDE);+    else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))+        EndBattleGround(ALLIANCE); }  void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)@@ -117,14 +123,20 @@         return;     } -    uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());+    uint32 killer_team = GetPlayerTeam(killer->GetGUID());+    if(!killer_team) killer_team = killer->GetTeam(); +    uint32 killer_team_index = GetTeamIndexByTeamId(killer_team);+     m_TeamKills[killer_team_index]++;                       // add kills to killer's team -    if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))+    uint32 team = GetPlayerTeam(player->GetGUID());+    if(!team) team = player->GetTeam();++    if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(team))     {         // all opponents killed-        EndBattleGround(killer->GetTeam());+        EndBattleGround(killer_team);     } } Index: src/game/BattleGroundNA.h===================================================================--- src/game/BattleGroundNA.h	(revision 5116)+++ src/game/BattleGroundNA.h	(working copy)@@ -55,7 +55,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);          void RemovePlayer(Player *plr, uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);Index: src/game/BattleGroundRL.cpp===================================================================--- src/game/BattleGroundRL.cpp	(revision 5116)+++ src/game/BattleGroundRL.cpp	(working copy)@@ -93,9 +93,9 @@     }*/ } -void BattleGroundRL::AddPlayer(Player *plr)+void BattleGroundRL::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map, default values are set in constructor     BattleGroundRLScore* sc = new BattleGroundRLScore; @@ -104,7 +104,13 @@  void BattleGroundRL::RemovePlayer(Player *plr, uint64 guid) {+    if(GetStatus() == STATUS_WAIT_LEAVE)+        return; +    if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))+        EndBattleGround(HORDE);+    else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))+        EndBattleGround(ALLIANCE); }  void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)@@ -118,14 +124,20 @@         return;     } -    uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());+    uint32 killer_team = GetPlayerTeam(killer->GetGUID());+    if(!killer_team) killer_team = killer->GetTeam(); +    uint32 killer_team_index = GetTeamIndexByTeamId(killer_team);+     m_TeamKills[killer_team_index]++;                       // add kills to killer's team -    if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))+    uint32 team = GetPlayerTeam(player->GetGUID());+    if(!team) team = player->GetTeam();++    if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(team))     {         // all opponents killed-        EndBattleGround(killer->GetTeam());+        EndBattleGround(killer_team);     } } Index: src/game/BattleGroundRL.h===================================================================--- src/game/BattleGroundRL.h	(revision 5116)+++ src/game/BattleGroundRL.h	(working copy)@@ -51,7 +51,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);          void RemovePlayer(Player *plr, uint64 guid);         void HandleAreaTrigger(Player *Source, uint32 Trigger);Index: src/game/BattleGroundWS.cpp===================================================================--- src/game/BattleGroundWS.cpp	(revision 5116)+++ src/game/BattleGroundWS.cpp	(working copy)@@ -50,6 +50,9 @@         {             m_Events |= 0x01; +            for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++)+                SpawnBGCreature(i, RESPAWN_IMMEDIATELY);+             for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)                 SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -111,9 +114,9 @@     } } -void BattleGroundWS::AddPlayer(Player *plr)+void BattleGroundWS::AddPlayer(Player *plr, uint32 team) {-    BattleGround::AddPlayer(plr);+    BattleGround::AddPlayer(plr, team);     //create score and add it to map, default values are set in constructor     BattleGroundWGScore* sc = new BattleGroundWGScore; @@ -388,7 +391,7 @@         return;      uint32 SpellId = 0;-    uint64 buff_guid = 0;+    GameObject* buff_guid = 0;     switch(Trigger)     {         case 3686:                                          // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update().@@ -432,7 +435,7 @@      if(buff_guid)     {-        GameObject *obj = HashMapHolder<GameObject>::Find(buff_guid);+        GameObject *obj = buff_guid;         if(obj)         {             if(!obj->isSpawned())@@ -503,12 +506,13 @@     m_FlagState[BG_TEAM_HORDE]          = BG_WS_FLAG_STATE_ON_BASE;     m_TeamScores[BG_TEAM_ALLIANCE]      = 0;     m_TeamScores[BG_TEAM_HORDE]         = 0;-+/*  currently crashes the server, must find out the problem, till then, let the instance unloading solve this     if(m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE])         DelCreature(WS_SPIRIT_MAIN_ALLIANCE);      if(m_BgCreatures[WS_SPIRIT_MAIN_HORDE])         DelCreature(WS_SPIRIT_MAIN_HORDE);+*/ }  void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer)Index: src/game/BattleGroundWS.h===================================================================--- src/game/BattleGroundWS.h	(revision 5116)+++ src/game/BattleGroundWS.h	(working copy)@@ -97,7 +97,7 @@     BG_WS_FLAG_STATE_ON_GROUND    = 3 }; -enum BattleGroundGaveyardsWS+enum BattleGroundGraveyardsWS {     WS_GRAVEYARD_MAIN_ALLIANCE   = 771,     WS_GRAVEYARD_MAIN_HORDE      = 772@@ -122,7 +122,7 @@         void Update(time_t diff);          /* inherited from BattlegroundClass */-        virtual void AddPlayer(Player *plr);+        virtual void AddPlayer(Player *plr, uint32 team = 0);          /* BG Flags */         uint64 GetAllianceFlagPickerGUID() const    { return m_FlagKeepers[BG_TEAM_ALLIANCE]; }Index: src/game/Chat.cpp===================================================================--- src/game/Chat.cpp	(revision 5116)+++ src/game/Chat.cpp	(working copy)@@ -385,6 +385,7 @@         { "movegens",    SEC_ADMINISTRATOR, &ChatHandler::HandleMovegensCommand,         "",   NULL },         { "cast",        SEC_ADMINISTRATOR, &ChatHandler::HandleCastCommand,             "",   NULL },         { "castback",    SEC_ADMINISTRATOR, &ChatHandler::HandleCastBackCommand,         "",   NULL },+        { "flusharenapoints",    SEC_ADMINISTRATOR, &ChatHandler::HandleFlushArenaPointsCommand,         "",   NULL },          //! Development Commands         { "setvalue",    SEC_ADMINISTRATOR, &ChatHandler::HandleSetValue,                "",   NULL },Index: src/game/Chat.h===================================================================--- src/game/Chat.h	(revision 5116)+++ src/game/Chat.h	(working copy)@@ -322,6 +322,7 @@         bool HandleWritePDumpCommand(const char *args);         bool HandleCastCommand(const char *args);         bool HandleCastBackCommand(const char *args);+        bool HandleFlushArenaPointsCommand(const char *args);          //! Development Commands         bool HandleSetValue(const char* args);Index: src/game/GroupHandler.cpp===================================================================--- src/game/GroupHandler.cpp	(revision 5116)+++ src/game/GroupHandler.cpp	(working copy)@@ -26,6 +26,8 @@ #include "ObjectMgr.h" #include "Player.h" #include "Group.h"+#include "Chat.h"+#include "Language.h" #include "ObjectAccessor.h"  /* differeces from off:@@ -257,6 +259,15 @@         SendPartyResult(PARTY_OP_LEAVE, name, PARTY_RESULT_NOT_IN_YOUR_PARTY);         return;     }++    if(player && player->InBattleGround())+    {+        WorldPacket data;+        ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, LANG_BG_CANNOT_IN_BG, NULL);+        SendPacket(&data);+       +        return;+    }     /********************/      // everything's fine, do it@@ -295,7 +306,15 @@      /** error handling **/     /********************/+    if(GetPlayer() && GetPlayer()->InBattleGround())+    {+        WorldPacket data;+        ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, LANG_BG_CANNOT_IN_BG, NULL);+        SendPacket(&data); +        return;+    }+     // everything's fine, do it     SendPartyResult(PARTY_OP_LEAVE, GetPlayer()->GetName(), PARTY_RESULT_OK); Index: src/game/Language.h===================================================================--- src/game/Language.h	(revision 5116)+++ src/game/Language.h	(working copy)@@ -535,6 +535,11 @@ #define LANG_INVISIBLE_INVISIBLE         "You are now invisible." #define LANG_INVISIBLE_VISIBLE           "You are now visible." +#define LANG_BG_CANNOT_IN_BG             "You can't do that right now."+#define LANG_BG_GROUP_TOO_LARGE          "Your group is too large for this battleground. Please regroup to join."+#define LANG_ARENA_GROUP_TOO_LARGE       "Your group is too large for this arena. Please regroup to join."+#define LANG_ARENA_YOUR_TEAM_ONLY        "Your group has members not in your arena team. Please regroup to join."+ #define LANG_BG_A_WINS                   "The Alliance wins!" #define LANG_BG_H_WINS                   "The Horde wins!" #define LANG_BG_WS_ONE_MINUTE            "The battle for Warsong Gulch begins in 1 minute."@@ -568,6 +573,8 @@ #define LANG_BG_AB_A_NEAR_VICTORY        "The Alliance has gathered $1776W resources, and is near victory!" #define LANG_BG_AB_H_NEAR_VICTORY        "The Horde has gathered $1777W resources, and is near victory!" +#define LANG_ARENA_GOLD_WINS             "The Gold Team wins!"+#define LANG_ARENA_GREEN_WINS            "The Green Team wins!" #define LANG_ARENA_ONE_TOOLOW            "You must be level %u to form an arena team" #define LANG_ARENA_ONE_MINUTE            "One minute until the Arena battle begins!" #define LANG_ARENA_THIRTY_SECONDS        "Thirty seconds until the Arena battle begins!"Index: src/game/Level3.cpp===================================================================--- src/game/Level3.cpp	(revision 5116)+++ src/game/Level3.cpp	(working copy)@@ -42,6 +42,7 @@ #include "SkillExtraItems.h" #include "SystemConfig.h" #include "Config/ConfigEnv.h"+#include "ArenaTeam.h"  //reload commands bool ChatHandler::HandleReloadCommand(const char* arg)@@ -4616,3 +4617,52 @@      return true; }++bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/)+{+    sWorld.SendWorldText("Flushing Arena points based on team ratings, this may take a few minutes. Please stand by...", NULL);++    sWorld.SendWorldText("Distributing arena points to online players...", NULL);++    //TODO: Guard Player map+    HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();+    for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)+    {+        uint64 guid = itr->second->GetGUID();+        Player * pl = itr->second;+        if(!pl)+            continue;+        uint32 mod = 0;+        for(int i=0; i<3; ++i)+        {+            ArenaTeam * at = objmgr.GetArenaTeamById(pl->GetArenaTeamId(i));+            if(at && mod < at->GetMemberPoints(guid))+                mod = at->GetMemberPoints(guid);+        }+        mod += pl->GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY);+        if(mod > 5000)+            mod = 5000;++        pl->SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, mod);++        CharacterDatabase.PExecute("UPDATE `arena_team_member` SET `points_to_add` = '0' WHERE `guid` = '%u'",guid);+    }++    sWorld.SendWorldText("Finished distributing arena points to online players. Now saving... ", NULL);++    ObjectAccessor::Instance().SaveAllPlayers();++    sWorld.SendWorldText("Online players saved.", NULL);++    sWorld.SendWorldText("Distributing arena points to offline players...", NULL);++    CharacterDatabase.BeginTransaction();+    CharacterDatabase.PExecute("UPDATE `character` 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(a.`points_to_add`) FROM `arena_team_member` WHERE a.`guid` = b.`guid` GROUP BY a.`guid`) ) < '5000'), 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(a.`points_to_add`) FROM `arena_team_member` WHERE a.`guid` = b.`guid` GROUP BY a.`guid`), '5000') 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, PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY+1, PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY+1);+    CharacterDatabase.Execute("UPDATE `arena_team_member` SET `points_to_add` = '0', `played_week` = '0', `wons_week` = '0'");+    CharacterDatabase.Execute("UPDATE `arena_team_stats` SET `games` = '0', `wins` = '0'");+    CharacterDatabase.CommitTransaction();++    sWorld.SendWorldText("Finished distributing arena points to offline players.", NULL);+    sWorld.SendWorldText("Done flushing Arena points.", NULL);+    return true;+}Index: src/game/Map.cpp===================================================================--- src/game/Map.cpp	(revision 5116)+++ src/game/Map.cpp	(working copy)@@ -270,6 +270,8 @@     else         i_data = NULL; +    i_unloadmap = sWorld.getConfig(CONFIG_GRID_UNLOAD);+     i_Players.clear(); } @@ -392,7 +394,7 @@         Guard guard(*this);         if(!getNGrid(p.x_coord, p.y_coord))         {-            setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_GRID_UNLOAD)),+            setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, i_unloadmap),                 p.x_coord, p.y_coord);              // build a linkage between this map and NGridTypeIndex: src/game/Map.h===================================================================--- src/game/Map.h	(revision 5116)+++ src/game/Map.h	(working copy)@@ -148,6 +148,8 @@          bool GetUnloadFlag(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadFlag(); }         void SetUnloadFlag(const GridPair &p, bool unload) { getNGrid(p.x_coord, p.y_coord)->setUnloadFlag(unload); }+        void SetUnloadMap(bool unload){ i_unloadmap = unload; }+        bool GetUnloadMap() const { return i_unloadmap; }         void LoadGrid(const Cell& cell, bool no_unload = false);         bool UnloadGrid(const uint32 &x, const uint32 &y);         virtual void UnloadAll();@@ -206,7 +208,7 @@         bool CanEnter(Player* player) const;         const char* GetMapName() const; -        bool Instanceable() const { return(i_mapEntry && ((i_mapEntry->map_type == MAP_INSTANCE) || (i_mapEntry->map_type == MAP_RAID))); }+        bool Instanceable() const { return(i_mapEntry && ((i_mapEntry->map_type == MAP_INSTANCE) || (i_mapEntry->map_type == MAP_RAID) || (i_mapEntry->map_type == MAP_BATTLEGROUND) || (i_mapEntry->map_type == MAP_ARENA))); }         // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable         bool IsDungeon() const { return(i_mapEntry && ((i_mapEntry->map_type == MAP_INSTANCE) || (i_mapEntry->map_type == MAP_RAID))); }         bool IsRaid() const { return(i_mapEntry && (i_mapEntry->map_type == MAP_RAID)); }@@ -294,6 +296,7 @@         uint32 i_resetDelayTime;         uint32 i_InstanceId;         uint32 i_maxPlayers;+        bool i_unloadmap;         InstanceData* i_data;         std::string i_script; Index: src/game/MapInstanced.cpp===================================================================--- src/game/MapInstanced.cpp	(revision 5116)+++ src/game/MapInstanced.cpp	(working copy)@@ -44,6 +44,7 @@         {             if (i->second->GetPlayersCount() == 0)             {+                DEBUG_LOG("reseting instance in update for instance id = %u and map id = %u named %s",this->GetInstanceId(),this->GetId(),this->GetMapName());                 i->second->Reset();                 // avoid doing ++ on invalid data                 InstancedMaps::iterator i_old = i;@@ -187,7 +188,7 @@          if (!instantiator && instantiator_online)         {-            sLog.outDebug("MAPINSTANCED: Player '%s' is not in group, instantiating map for player", player->GetName());+            sLog.outDebug("MAPINSTANCED: Player '%s' is not in group, instantiating map %u for player", player->GetName(), GetId());             instantiator = player;         } @@ -230,11 +231,13 @@         // check, if we have to generate new instance         if (!instantiator_bound || (InstanceId == 0))         {+            sLog.outDebug("MAPINSTANCED: Generating new instance id");             // yes, new instance id has to be generated             InstanceId = MapManager::Instance().GenerateInstanceId();         }         else         {+            sLog.outDebug("MAPINSTANCED: Instantiator bound, finding map...");             // find map of the designated instance and verify it             map = _FindMap(InstanceId);         }@@ -242,7 +245,7 @@      // now create the instance     CreateInstance(InstanceId, map);-+    sLog.outDebug("MAPINSTANCED::GetInstance() Instance Created");     // we do need to bind instance, if the instance we use is valid, not temporary     if (player->m_InstanceValid)     {@@ -304,6 +307,7 @@             // map for the instance is present, but the instance itself is no more valid, destroy map             Guard guard(*this); +            DEBUG_LOG("reseting instance in createinstance for instance id = %u and map id = %u named %s",this->GetInstanceId(),this->GetId(),this->GetMapName());             map->Reset();             m_InstancedMaps.erase(InstanceId);             delete map;@@ -314,10 +318,12 @@     // verify, if we have the map created, and create it if needed     if (!map)     {+        sLog.outDebug("MAPINSTANCED: CreateInstance, map not found, creating it");         // map does not exist, create it         Guard guard(*this);          map = new Map(GetId(), GetGridExpiry(), InstanceId);+        map->SetUnloadMap(GetUnloadMap());         m_InstancedMaps[InstanceId] = map;     } }Index: src/game/MapManager.cpp===================================================================--- src/game/MapManager.cpp	(revision 5116)+++ src/game/MapManager.cpp	(working copy)@@ -104,7 +104,7 @@         Guard guard(*this);          const MapEntry* entry = sMapStore.LookupEntry(id);-        if (entry && ((entry->map_type == MAP_INSTANCE) || (entry->map_type == MAP_RAID)))+        if (entry && ((entry->map_type == MAP_INSTANCE) || (entry->map_type == MAP_RAID) || (entry->map_type == MAP_BATTLEGROUND) || (entry->map_type == MAP_ARENA)))         {             m = new MapInstanced(id, i_gridCleanUpDelay, 0);         }Index: src/game/MovementHandler.cpp===================================================================--- src/game/MovementHandler.cpp	(revision 5116)+++ src/game/MovementHandler.cpp	(working copy)@@ -79,17 +79,21 @@         {             if(bg->GetMapId() == _player->GetMapId())       // we teleported to bg             {-                if(!bg->GetBgRaid(_player->GetTeam()))      // first player joined+                uint32 team = bg->GetPlayerTeam(_player->GetGUID());+                if(!team)+                    team = _player->GetTeam();+                _player->RemoveFromGroup();+                if(!bg->GetBgRaid(team))      // first player joined                 {                     Group *group = new Group;-                    bg->SetBgRaid(_player->GetTeam(), group);+                    bg->SetBgRaid(team, group);                     group->ConvertToRaid();                     group->AddMember(_player->GetGUID(), _player->GetName());                     group->ChangeLeader(_player->GetGUID());                 }                 else                                        // raid already exist                 {-                    bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName());+                    bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName());                 }             }         }@@ -485,3 +489,5 @@     _player->SummonIfPossible(); } ++Index: src/game/PetitionsHandler.cpp===================================================================--- src/game/PetitionsHandler.cpp	(revision 5116)+++ src/game/PetitionsHandler.cpp	(working copy)@@ -49,9 +49,6 @@ {     CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4); -    if(_player->GetGuildId())-        return;-     sLog.outDebug("Received opcode CMSG_PETITION_BUY");     //recv_data.hexlike(); @@ -95,6 +92,9 @@     uint32 type = 0;     if(pCreature->isTabardDesigner())     {+        if(_player->GetGuildId())+            return;+         charterid = GUILD_CHARTER;         cost = GUILD_CHARTER_COST;         type = 9;@@ -188,10 +188,31 @@     charter->SetState(ITEM_CHANGED, _player);     _player->SendNewItem(charter, 1, true, false); +    // a petition is invalid, if both the owner and the type matches+    QueryResult *result = CharacterDatabase.PQuery("SELECT `petitionguid` FROM `petition` WHERE `ownerguid` = '%u'  AND `type` = '%u'", _player->GetGUIDLow(), type);++    std::ostringstream ssInvalidPetitionGUIDs;++    if (result)+    {++        do+        {+            Field *fields = result->Fetch();+			ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";+        } while (result->NextRow());++        delete result;+    }++    // delete petitions with the same guid as this one+    ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";++	sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());     CharacterDatabase.escape_string(name);     CharacterDatabase.BeginTransaction();-    CharacterDatabase.PExecute("DELETE FROM `petition` WHERE `ownerguid` = '%u' OR `petitionguid` = '%u' and `type` = '%u'", _player->GetGUIDLow(), charter->GetGUIDLow(),type);-    CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `ownerguid` = '%u' or `petitionguid` = '%u'", _player->GetGUIDLow(), charter->GetGUIDLow());+    CharacterDatabase.PExecute("DELETE FROM `petition` WHERE `petitionguid` IN ( %s )",  ssInvalidPetitionGUIDs.str().c_str());+    CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `petitionguid` IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());     CharacterDatabase.PExecute("INSERT INTO `petition` (`ownerguid`, `petitionguid`, `name`, `type`) VALUES ('%u', '%u', '%s', '%u')",         _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type);     CharacterDatabase.CommitTransaction();@@ -205,9 +226,6 @@     sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");     //recv_data.hexlike(); -    if(_player->GetGuildId())-        return;-     uint8 signs = 0;     uint64 petitionguid;     recv_data >> petitionguid;                              // petition guid@@ -215,14 +233,17 @@     // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)     uint32 petitionguid_low = GUID_LOPART(petitionguid); -    QueryResult *result = CharacterDatabase.PQuery("SELECT `petitionguid` FROM `petition` WHERE `petitionguid` = '%u'", petitionguid_low);+    QueryResult *result = CharacterDatabase.PQuery("SELECT `petitionguid`, `type` FROM `petition` WHERE `petitionguid` = '%u'", petitionguid_low);     if(!result)     {         sLog.outError("any petition on server...");         return;     }-+    Field *fields = result->Fetch();+	uint32 type = fields[1].GetUInt32();     delete result;+    if(type==9 && _player->GetGuildId())+        return;      result = CharacterDatabase.PQuery("SELECT `playerguid` FROM `petition_sign` WHERE `petitionguid` = '%u'", petitionguid_low); @@ -317,13 +338,14 @@     {         data << uint32(9);         data << uint32(9);+        data << uint32(0);     }     else     {         data << type-1;         data << type-1;+        data << type;     }-    data << uint32(0);                                      // 4     data << uint32(0);                                      // 5     data << uint32(0);                                      // 6     data << uint32(0);                                      // 7@@ -463,7 +485,7 @@      //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account     //not allow sign another player from already sign player account-    result = CharacterDatabase.PQuery("SELECT `playerguid` FROM `petition_sign` WHERE `player_account` = '%u'", GetAccountId());+    result = CharacterDatabase.PQuery("SELECT `playerguid` FROM `petition_sign` WHERE `player_account` = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));      if(result)     {@@ -638,16 +660,29 @@     }     else     {-        for(uint8 i = 0; i < 3; i++)+        uint32 type_slot;+        switch(type)         {-            if(_player->GetArenaTeamId(i))-            {+        case ARENA_TEAM_2v2:+            type_slot = 0;+            break;+        case ARENA_TEAM_3v3:+            type_slot = 1;+            break;+        case ARENA_TEAM_5v5:+            type_slot = 2;+            break;+        default:+            type_slot = 0;+            break;+        }+        if(_player->GetArenaTeamId(type_slot))+        {                 //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);                 //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD;                          // already in guild                 //_player->GetSession()->SendPacket(&data);                 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);                 return;-            }         }     } @@ -735,6 +770,7 @@         ArenaTeam* at = new ArenaTeam;         if(!at->create(_player->GetGUID(), type, name))         {+            sLog.outError("PetitionsHandler: arena team create failed.");             delete at;             delete result;             return;@@ -748,11 +784,13 @@          // register team and add captain         objmgr.AddArenaTeam(at);+        sLog.outDebug("PetitonsHandler: arena team added to objmrg");          // add members         for(uint8 i = 0; i < signs; ++i)         {             Field* fields = result->Fetch();+            sLog.outDebug("PetitionsHandler: adding arena member %u", fields[0].GetUInt64());             at->AddMember(fields[0].GetUInt64());             result->NextRow();         }@@ -820,21 +858,21 @@         data << uint32(ARENA_TEAM_CHARTER_2v2);             // charter entry         data << uint32(16161);                              // charter display id         data << uint32(ARENA_TEAM_CHARTER_2v2_COST);        // charter cost-        data << uint32(0);                                  // unknown+        data << uint32(2);                                  // unknown         data << uint32(2);                                  // required signs?         // 3v3         data << uint32(2);                                  // index         data << uint32(ARENA_TEAM_CHARTER_3v3);             // charter entry         data << uint32(16161);                              // charter display id         data << uint32(ARENA_TEAM_CHARTER_3v3_COST);        // charter cost-        data << uint32(0);                                  // unknown+        data << uint32(3);                                  // unknown         data << uint32(3);                                  // required signs?         // 5v5         data << uint32(3);                                  // index         data << uint32(ARENA_TEAM_CHARTER_5v5);             // charter entry         data << uint32(16161);                              // charter display id         data << uint32(ARENA_TEAM_CHARTER_5v5_COST);        // charter cost-        data << uint32(0);                                  // unknown+        data << uint32(5);                                  // unknown         data << uint32(5);                                  // required signs?     }     //for(uint8 i = 0; i < count; i++)Index: src/game/Player.cpp===================================================================--- src/game/Player.cpp	(revision 5116)+++ src/game/Player.cpp	(working copy)@@ -104,6 +104,9 @@     m_zoneUpdateId = 0;     m_zoneUpdateTimer = 0; +    m_areaUpdateId = 0;+    m_areaUpdateTimer = 0;+     m_dismountCost = 0;      m_nextSave = sWorld.getConfig(CONFIG_INTERVAL_SAVE);@@ -937,6 +940,20 @@             m_zoneUpdateTimer -= p_time;     } +    if (m_areaUpdateTimer > 0)+    {+        if(p_time >= m_areaUpdateTimer)+        {+            uint32 newarea = GetAreaId();+            if( m_areaUpdateId != newarea )+                UpdateArea(newarea);+            else+                m_areaUpdateTimer = ZONE_UPDATE_INTERVAL;+        }+        else+            m_areaUpdateTimer -= p_time;+    }+     if (isAlive())     {         RegenerateAll();@@ -2726,6 +2743,27 @@         removeSpell(itr->second.spell); } +void Player::RemoveArenaSpellCooldowns()+{+    SpellCooldowns::iterator itr, next;+    for(itr = m_spellCooldowns.begin();itr != m_spellCooldowns.end(); itr = next)+    {+        next = itr;+        ++next;+        SpellEntry const * entry = sSpellStore.LookupEntry(itr->first);+        if( entry && +            (entry->RecoveryTime <= 15 * 60000) &&+            (entry->CategoryRecoveryTime <= 15 * 60000))+        {+            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));+            data << uint32(itr->first);+            data << GetGUID();+            GetSession()->SendPacket(&data);+            m_spellCooldowns.erase(itr);+        }+    }+}+ void Player::RemoveAllSpellCooldown() {     if(!m_spellCooldowns.empty())@@ -5665,8 +5703,27 @@     return zone; } +void Player::UpdateArea(uint32 newArea)+{+    m_areaUpdateId    = newArea;+    m_areaUpdateTimer = ZONE_UPDATE_INTERVAL;++    AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);++    if(area && (area->flags & 0x80))+    {+        SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);+    }+    else+    {+        if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && !sWorld.IsFFAPvPRealm())+            RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);+    }+}+ void Player::UpdateZone(uint32 newZone) {+    UpdateArea(GetAreaId());     m_zoneUpdateId    = newZone;     m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL; @@ -8627,6 +8684,12 @@                 pProto->SubClass != ITEM_SUBCLASS_ARMOR_SHIELD && pProto->InventoryType != INVTYPE_RELIC)                 return EQUIP_ERR_NOT_IN_COMBAT; +            if( InBattleGround() && GetBattleGround() && GetBattleGround()->isArena() && +                (GetBattleGround()->GetStatus() == STATUS_IN_PROGRESS) &&+                (pProto->Class != ITEM_CLASS_WEAPON) && (pProto->Class != ITEM_CLASS_PROJECTILE) &&+                (pProto->SubClass != ITEM_SUBCLASS_ARMOR_SHIELD) && (pProto->InventoryType != INVTYPE_RELIC))+                return EQUIP_ERR_NOT_DURING_ARENA_MATCH;+             if(isInCombat()&& pProto->Class == ITEM_CLASS_WEAPON && m_weaponChangeTimer != 0)                 return EQUIP_ERR_CANT_DO_RIGHT_NOW;         // maybe exist better err @@ -8760,6 +8823,12 @@         pProto->SubClass != ITEM_SUBCLASS_ARMOR_SHIELD && pProto->InventoryType != INVTYPE_RELIC )         return EQUIP_ERR_NOT_IN_COMBAT; +    if( InBattleGround() && GetBattleGround() && GetBattleGround()->isArena() && +        (GetBattleGround()->GetStatus() == STATUS_IN_PROGRESS) &&+        (pProto->Class != ITEM_CLASS_WEAPON) && (pProto->Class != ITEM_CLASS_PROJECTILE) &&+        (pProto->SubClass != ITEM_SUBCLASS_ARMOR_SHIELD) && (pProto->InventoryType != INVTYPE_RELIC))+        return EQUIP_ERR_NOT_DURING_ARENA_MATCH;+     if(!swap && pItem->IsBag() && !((Bag*)pItem)->IsEmpty())         return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS; @@ -9842,6 +9911,52 @@     } } +void Player::DestroyConjuredItems( bool update )+{+    sLog.outDebug( "STORAGE: DestroyConjuredItems" );++    // in inventory+    for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)+    {+        Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );+        if( pItem && pItem->GetProto() &&+            (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && +            (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) )+            DestroyItem( INVENTORY_SLOT_BAG_0, i, update);+    }++    // in inventory bags+    for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)+    {+        Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i );+        if( pBag )+        {+            ItemPrototype const *pBagProto = pBag->GetProto();+            if( pBagProto )+            {+                for(uint32 j = 0; j < pBagProto->ContainerSlots; j++)+                {+                    Item* pItem = pBag->GetItemByPos(j);+                    if( pItem && pItem->GetProto() &&+                        (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && +                        (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) )+                        DestroyItem( i, j, update);+                }+            }+        }+    }++    // in equipment and bag list+    for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++)+    {+        Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );+        if( pItem && pItem->GetProto() &&+            (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && +            (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) )+            DestroyItem( INVENTORY_SLOT_BAG_0, i, update);+    }+}+ void Player::DestroyItemCount( Item* pItem, uint32 &count, bool update ) {     if(!pItem)@@ -14688,10 +14803,14 @@  void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type) {-    QueryResult *result = CharacterDatabase.PQuery("SELECT `ownerguid`,`petitionguid` FROM `petition_sign` WHERE `playerguid` = '%u'", GUID_LOPART(guid));+    QueryResult *result = NULL;+    if(type==10)+        result = CharacterDatabase.PQuery("SELECT `ownerguid`,`petitionguid` FROM `petition_sign` WHERE `playerguid` = '%u'", GUID_LOPART(guid));+    else+        result = CharacterDatabase.PQuery("SELECT `ownerguid`,`petitionguid` FROM `petition_sign` WHERE `playerguid` = '%u' AND `type` = '%u'", GUID_LOPART(guid), type);     if(result)     {-        do+        do    //this part effectively does nothing, since the deletion / modification only takes place _after_ the PetitionQuery. Though I don't know if the result remains intact if I execute the delete query beforehand.         {             Field *fields = result->Fetch();             uint64 ownerguid   = MAKE_GUID(fields[0].GetUInt32(), HIGHGUID_PLAYER);@@ -14706,15 +14825,23 @@          delete result; -        CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `playerguid` = '%u'", GUID_LOPART(guid));+        if(type==10)+            CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `playerguid` = '%u'", GUID_LOPART(guid));+        else+            CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `playerguid` = '%u' AND `type` = '%u'", GUID_LOPART(guid), type);     }      CharacterDatabase.BeginTransaction();     if(type == 10)+    {         CharacterDatabase.PExecute("DELETE FROM `petition` WHERE `ownerguid` = '%u'", GUID_LOPART(guid));+        CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `ownerguid` = '%u'", GUID_LOPART(guid));+    }     else+    {         CharacterDatabase.PExecute("DELETE FROM `petition` WHERE `ownerguid` = '%u' AND `type` = '%u'", GUID_LOPART(guid), type);-    CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `ownerguid` = '%u'", GUID_LOPART(guid));+        CharacterDatabase.PExecute("DELETE FROM `petition_sign` WHERE `ownerguid` = '%u' AND `type` = '%u'", GUID_LOPART(guid), type);+    }     CharacterDatabase.CommitTransaction(); } @@ -15970,7 +16097,7 @@  bool Player::GetBGAccessByLevel(uint32 bgTypeId) const {-    BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);+    BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);     if(!bg)         return false; Index: src/game/Player.h===================================================================--- src/game/Player.h	(revision 5116)+++ src/game/Player.h	(working copy)@@ -1023,6 +1023,7 @@         void DestroyItem( uint8 bag, uint8 slot, bool update );         void DestroyItemCount( uint32 item, uint32 count, bool update, bool unequip_check = false);         void DestroyItemCount( Item* item, uint32& count, bool update );+        void DestroyConjuredItems( bool update );         void DestroyZoneLimitedItem( bool update, uint32 new_zone );         void SplitItem( uint16 src, uint16 dst, uint32 count );         void SwapItem( uint16 src, uint16 dst );@@ -1332,6 +1333,7 @@         void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time);         void ProhibitSpellScholl(SpellSchools idSchool, uint32 unTimeMs );         void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); }+        void RemoveArenaSpellCooldowns();         void RemoveAllSpellCooldown();         void _LoadSpellCooldowns(QueryResult *result);         void _SaveSpellCooldowns();@@ -1362,6 +1364,7 @@         PvPInfo pvpInfo;         void UpdatePvP(bool state, bool ovrride=false);         void UpdateZone(uint32 newZone);+        void UpdateArea(uint32 newArea);         void UpdatePvPFlag(time_t currTime);          /** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/@@ -1683,9 +1686,11 @@         float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; }         float GetBattleGroundEntryPointZ() const { return m_bgEntryPointZ; }         float GetBattleGroundEntryPointO() const { return m_bgEntryPointO; }-        void SetBattleGroundEntryPoint(uint32 Map, float PosX, float PosY, float PosZ, float PosO )+        uint32 GetBattleGroundEntryPointInstanceId() const { return m_bgEntryPointInstanceId; }+        void SetBattleGroundEntryPoint(uint32 Map, uint32 InstanceId, float PosX, float PosY, float PosZ, float PosO )         {             m_bgEntryPointMap = Map;+            m_bgEntryPointInstanceId = InstanceId;             m_bgEntryPointX = PosX;             m_bgEntryPointY = PosY;             m_bgEntryPointZ = PosZ;@@ -1830,6 +1835,7 @@         */         uint32 m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES];         uint32 m_bgEntryPointMap;+        uint32 m_bgEntryPointInstanceId;         float m_bgEntryPointX;         float m_bgEntryPointY;         float m_bgEntryPointZ;@@ -1995,6 +2001,9 @@         uint32 m_zoneUpdateId;         uint32 m_zoneUpdateTimer; +        uint32 m_areaUpdateId;+        uint32 m_areaUpdateTimer;+         uint32 m_deathTimer;         time_t m_resurrectingSicknessExpire; Index: src/game/Spell.cpp===================================================================--- src/game/Spell.cpp	(revision 5116)+++ src/game/Spell.cpp	(working copy)@@ -2667,6 +2667,14 @@     if((m_spellInfo->AttributesEx3 & 0x800) != 0)         return SPELL_FAILED_ONLY_BATTLEGROUNDS; +    if( m_caster->GetTypeId() == TYPEID_PLAYER && +        ((Player*)m_caster)->InBattleGround() && +        ((Player*)m_caster)->GetBattleGround() && +        ((Player*)m_caster)->GetBattleGround()->isArena() &&+        (m_spellInfo->RecoveryTime > 15 * 60000 ||+        m_spellInfo->CategoryRecoveryTime > 15 * 60000) )+        return SPELL_FAILED_NOT_IN_ARENA;+     // zone check     uint32 zone_id = m_caster->GetAreaId(); Index: src/game/SpellHandler.cpp===================================================================--- src/game/SpellHandler.cpp	(revision 5116)+++ src/game/SpellHandler.cpp	(working copy)@@ -66,6 +66,14 @@         return;     } +    if ( pUser->InBattleGround() && pUser->GetBattleGround() && pUser->GetBattleGround()->isArena() &&+        (proto->Class == ITEM_CLASS_CONSUMABLE) && !(proto->Flags & ITEM_FLAGS_CONJURED) && !(proto->SubClass == ITEM_SUBCLASS_BANDAGE))+    {+        //send use error: not in arena+        pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL);+        return;+    }+     if (pUser->isInCombat())     {         for(int i = 0; i < 5; ++i)@@ -466,7 +474,8 @@                             if(((BattleGroundWS*)bg)->GetFlagState(ALLIANCE) != BG_WS_FLAG_STATE_ON_BASE)                                 return;                             // check if it's correct flag-                            if(((BattleGroundWS*)bg)->m_BgObjects[BG_WS_OBJECT_A_FLAG] != obj->GetGUID())+                            if(!(((BattleGroundWS*)bg)->m_BgObjects[BG_WS_OBJECT_A_FLAG]) ||+                                (((BattleGroundWS*)bg)->m_BgObjects[BG_WS_OBJECT_A_FLAG]->GetGUID() != obj->GetGUID()))                                 return;                             // check player team                             if(_player->GetTeam() == ALLIANCE)@@ -481,7 +490,8 @@                             if(((BattleGroundWS*)bg)->GetFlagState(HORDE) != BG_WS_FLAG_STATE_ON_BASE)                                 return;                             // check if it's correct flag-                            if(((BattleGroundWS*)bg)->m_BgObjects[BG_WS_OBJECT_H_FLAG] != obj->GetGUID())+                            if(!(((BattleGroundWS*)bg)->m_BgObjects[BG_WS_OBJECT_H_FLAG]) ||+                                (((BattleGroundWS*)bg)->m_BgObjects[BG_WS_OBJECT_H_FLAG]->GetGUID() != obj->GetGUID()))                                 return;                             // check player team                             if(_player->GetTeam() == HORDE)Index: src/game/Unit.cpp===================================================================--- src/game/Unit.cpp	(revision 5116)+++ src/game/Unit.cpp	(working copy)@@ -591,8 +591,11 @@                     // add +1 deaths                     bg->UpdatePlayerScore(killed, SCORE_DEATHS, 1);                     if(killer)+                    {                         // add +1 kills                         bg->UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1);+                        bg->UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1);+                    }                     // to be able to remove insignia                     killed->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );                 }@@ -3799,6 +3802,19 @@     } } +void Unit::RemoveArenaAuras(bool onleave)+{+    // in join, remove positive buffs, on end, remove negative+    // used to remove positive visible auras in arenas+    for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)+    {+        if (!iter->second->IsPassive() && (iter->second->IsPositive() ^ onleave))+            RemoveAura(iter, true);+        else+            ++iter;+    }+}+ void Unit::RemoveAllAurasOnDeath() {     // used just after dieing to remove all visible aurasIndex: src/game/Unit.h===================================================================--- src/game/Unit.h	(revision 5116)+++ src/game/Unit.h	(working copy)@@ -825,6 +825,7 @@         void RemoveAreaAurasByOthers(uint64 guid = 0);          void RemoveAllAuras();+        void RemoveArenaAuras(bool onleave = false);         void RemoveAllAurasOnDeath();         void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime);         bool SetAurDuration(uint32 spellId, uint32 effindex, uint32 duration);Index: src/game/WorldSession.cpp===================================================================--- src/game/WorldSession.cpp	(revision 5116)+++ src/game/WorldSession.cpp	(working copy)@@ -656,7 +656,7 @@         {             for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)             {-                int32 bgTypeId = _player->GetBattleGroundQueueId(i);+                int32 bgTypeId = sBattleGroundMgr.BGQueueTypeId(_player->GetBattleGroundQueueId(i));                 if (bgTypeId != 0)                 {                     _player->RemoveBattleGroundQueueId(bgTypeId);