All pastes #878136 Raw Edit

Someone

public diff v1 · immutable
#878136 ·published 2008-01-29 12:55 UTC
rendered paste body
Index: src/game/ArenaTeam.cpp===================================================================--- src/game/ArenaTeam.cpp	(revision 5103)+++ src/game/ArenaTeam.cpp	(working copy)@@ -329,6 +329,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 +343,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);Index: src/game/BattleGround.cpp===================================================================--- src/game/BattleGround.cpp	(revision 5103)+++ src/game/BattleGround.cpp	(working copy)@@ -30,6 +30,7 @@ BattleGround::BattleGround() {     m_TypeID            = 0;+    m_TeamType          = 0;     m_InstanceID        = 0;     m_Status            = 0;     m_EndTime           = 0;@@ -46,6 +47,8 @@     m_Name              = "";     m_LevelMin          = 0;     m_LevelMax          = 0;+    m_InBGFreeSlotQueue = false;+    m_SetDeleteThis     = false;      m_MaxPlayersPerTeam = 0;     m_MaxPlayers        = 0;@@ -75,7 +78,17 @@  BattleGround::~BattleGround() {-+    // 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 +250,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 +279,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 +302,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 +322,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 +347,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 +364,18 @@  void BattleGround::EndBattleGround(uint32 winner) {+    this->RemoveFromBGFreeSlotQueue();+     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,7 +383,10 @@     }     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 @@ -371,13 +407,20 @@             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(team == winner)         {             if(!Source)                 Source = plr;@@ -429,7 +472,8 @@         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);     } @@ -449,11 +493,12 @@  void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) {+    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 +513,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 +527,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 +607,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 +620,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 +657,9 @@     SetStartTime(0);     SetEndTime(0);     SetLastResurrectTime(0);+    SetTeamType(BG_TEAM_TYPE_NORMAL);+    SetArenaType(0);+    SetRated(false);      m_Events = 0; @@ -559,6 +668,7 @@      m_InvitedAlliance = 0;     m_InvitedHorde = 0;+    m_InBGFreeSlotQueue = false;      m_Players.clear();     m_PlayerScores.clear();@@ -576,52 +686,63 @@      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) {     // 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 +752,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 +771,7 @@             sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr);             return;         }-    }*/+    } }  /*@@ -668,6 +794,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 +898,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,16 +922,33 @@     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;//*/     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);@@ -798,32 +965,35 @@ {     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);         }-        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);         }-        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 +1004,47 @@     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;     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);+        }+       // 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);+        }+       // 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 +1055,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 +1114,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 5103)+++ 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@@ -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; }@@ -342,24 +355,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 +406,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 usedIndex: src/game/BattleGroundAA.cpp===================================================================--- src/game/BattleGroundAA.cpp	(revision 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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);+                    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 5103)+++ src/game/BattleGroundMgr.cpp	(working copy)@@ -45,8 +45,8 @@     //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;     } }@@ -56,98 +56,360 @@     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) {+    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 )+        {+            // 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) )+                {+                    insert(elig_itr,(*itr));+                    inserted = true;+                    break;+                }+            }+            // if not inserted -> this is the smallest group -> push_back+            if(!inserted)+            {+                push_back((*itr));+            }+        }+    }+}++void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo)+{+    for(std::list<GroupQueueInfo *>::iterator itr = begin(); itr != end(); ++itr)+    {+        if((*itr)=ginfo)+        {+            erase(itr);+            return;+        }+    }+}++void BattleGroundQueue::SelectionPool::Init()+{+    SelectedGroups.clear();+    MaxGroup = 0;+    PlayerCount = 0;+}++GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup()+{+    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)+{+    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)+{+    SelectedGroups.push_back(ginfo);+    PlayerCount+=ginfo->Players.size();+    if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size())+        MaxGroup = ginfo;+}+++GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, uint8 ArenaType, bool isRated)+{+    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)+{     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);+                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())+        {+            m_QueuedGroups[queue_id].erase(group_itr);+            delete group;+        }     } } +bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 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)+{+    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()))+    {+        // 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;+}+ /*-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,13 +418,15 @@     }      //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()!     {+        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)@@ -171,143 +435,275 @@             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();)-                {-                    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;-                    }+                if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size())+                    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())+            {+                //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+            }+        }+    } -                        // 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;+    } -                        // 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) */--    /* 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);+        }++        // start the battleground+        bg2->StartBattleGround(0);+    }++    // 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])) )+                return;++            // init stats+            switch(arenatype)             {-                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()))+            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;+            }++            bg2->SetRated(isRated);+            // which side has enough players?+            uint32 side = 0;+            SelectionPoolBuildMode mode1, mode2;+            // find out what pools are we using+            if(bOneSideAllyTeam1 && bOneSideAllyTeam2)             {-                // iterator to player's queue status-                QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2);+                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; -                // remove him from time queue-                itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);+            // 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); -                // 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;+            // start the joining of the bg+            bg2->SetStatus(STATUS_WAIT_JOIN);+            bg2->SetQueueType(queue_id);+            // initialize arena / rating info+            bg2->SetArenaType(arenatype); -                //check if player is not already invited-                if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID)-                {-                    itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID();-                    itrPlayerStatus->second.InviteTime = getMSTime();-                    itrPlayerStatus->second.LastInviteTime = getMSTime();+            std::list<GroupQueueInfo* >::iterator itr; -                    if(itrPlayerStatus->second.Team == ALLIANCE)-                        m_QueuedPlayers[queue_id].Alliance--;-                    else-                        m_QueuedPlayers[queue_id].Horde--;+            // 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);+            } -                    sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID());+            // 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);+            } -                    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);-                }-            }-            else-                ++itr2;+            bg2->StartBattleGround(0);         }-        bg2->StartBattleGround(0);     } } @@ -330,16 +726,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);             }         }@@ -366,17 +763,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);             }         }@@ -402,15 +800,33 @@  BattleGroundMgr::~BattleGroundMgr() {-    for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr)-        delete itr->second;+    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;+            m_BattleGrounds.erase(itr);+            delete bg;+        }+    } }  void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2)@@ -427,7 +843,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 +876,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@@ -536,11 +952,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 +1042,88 @@     *data << uint64(plr->GetGUID()); } -void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID)+void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) {     // set invited player counters:     BattleGround* bg = this->GetBattleGround(bgInstanceGUID);-    bg->IncreaseInvitedCount(plr->GetTeam());+    bg->IncreaseInvitedCount(team);      // 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)+{+    return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back();+}++BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 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+    }+    +    bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id++    bg->Reset();+    +    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;+    }++    bg->AddToBGFreeSlotQueue();++    AddBattleGround(bg->GetInstanceID(), bg);++    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 +1143,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 +1164,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 +1177,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,16 +1334,20 @@     } } -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->SetInstanceId(instanceId);+        pl->m_BoundInstances[mapid]=std::pair<uint32,uint32>(instanceId, pl->GetGUIDLow());         pl->TeleportTo(mapid, x, y, z, O);     } }@@ -864,3 +1361,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 5103)+++ 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,68 @@         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); -        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 +200,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 +215,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 +235,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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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 5103)+++ 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/GroupHandler.cpp===================================================================--- src/game/GroupHandler.cpp	(revision 5103)+++ 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 5103)+++ src/game/Language.h	(working copy)@@ -534,6 +534,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."@@ -567,6 +572,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/Map.cpp===================================================================--- src/game/Map.cpp	(revision 5103)+++ 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 5103)+++ 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 5103)+++ 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;@@ -304,6 +305,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;@@ -318,6 +320,7 @@         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 5103)+++ 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 5103)+++ src/game/MovementHandler.cpp	(working copy)@@ -79,17 +79,20 @@         {             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();+                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 +488,5 @@     _player->SummonIfPossible(); } ++Index: src/game/Player.cpp===================================================================--- src/game/Player.cpp	(revision 5103)+++ 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())@@ -5634,8 +5672,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; @@ -8596,6 +8653,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 @@ -8729,6 +8792,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; @@ -9811,6 +9880,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)@@ -15939,7 +16054,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 5103)+++ 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 5103)+++ src/game/Spell.cpp	(working copy)@@ -2660,6 +2660,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 5103)+++ 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 5103)+++ 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 5103)+++ src/game/Unit.h	(working copy)@@ -824,6 +824,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 5103)+++ src/game/WorldSession.cpp	(working copy)@@ -648,7 +648,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);Index: win/VC80/mangosd.vcproj===================================================================--- win/VC80/mangosd.vcproj	(revision 5103)+++ win/VC80/mangosd.vcproj	(working copy)@@ -1,4 +1,4 @@-<?xml version="1.0" encoding="Windows-1252"?>+<?xml version="1.0" encoding="windows-1250"?> <VisualStudioProject 	ProjectType="Visual C++" 	Version="8,00"