root/trunk/src/arcemu-world/BattlegroundMgr.cpp @ 3131

Revision 3131, 55.8 kB (checked in by Hypersniper, 8 months ago)

* APPLIED:
- Alterac Valley patch by Artox
- Copyrights patch by Terrorblade
- Earth shield patch by Jackpoz
- Energize patch by Arch1s
- Opcode fix by Sadikum
- Optional config fix by Psychobandit
- Various spells by Catti
- Various spells by Mesox/Ogchaos
- "Summon Myzrael" fix by this_is_junk
- "Torgos" fix by dzjhenghiz
- Worldstates patch by eggnrice
Good work community!

  • Property svn:eol-style set to native
  • Property ff set to
    *.cpp = svn:eol-style=native
    Makefile = svn:eol-style=native
    README = svn:eol-style=native
    CHANGELOG = svn:eol-style=native
    LICENSE = svn:eol-style=native
  • Property svn:keywords set to Date Author Rev
Line 
1/*
2* ArcEmu MMORPG Server
3* Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
4* Copyright (C) 2008-2010 <http://www.ArcEmu.org/>
5*
6* This program is free software: you can redistribute it and/or modify
7* it under the terms of the GNU Affero General Public License as published by
8* the Free Software Foundation, either version 3 of the License, or
9* any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14* GNU Affero General Public License for more details.
15*
16* You should have received a copy of the GNU Affero General Public License
17* along with this program.  If not, see <http://www.gnu.org/licenses/>.
18*
19*/
20
21#include "StdAfx.h"
22
23initialiseSingleton(CBattlegroundManager);
24typedef CBattleground*(*CreateBattlegroundFunc)(MapMgr* mgr,uint32 iid,uint32 group, uint32 type);
25
26const static uint32 BGMapIds[ BATTLEGROUND_NUM_TYPES ] =
27{
28        0,      // 0
29        30,     // AV
30        489,    // WSG
31        529,    // AB
32        0,      // 2v2
33        0,      // 3v3
34        0,      // 5v5
35        566,    // EOTS
36        0,
37        607,    // SOTA
38        0,
39        0,
40};
41
42const static CreateBattlegroundFunc BGCFuncs[BATTLEGROUND_NUM_TYPES] = {
43        NULL,                           // 0
44        &AlteracValley::Create,         // AV
45        &WarsongGulch::Create,          // WSG
46        &ArathiBasin::Create,           // AB
47        NULL,                           // 2v2
48        NULL,                           // 3v3
49        NULL,                           // 5v5
50        &EyeOfTheStorm::Create,         // EotS
51        NULL,
52        &StrandOfTheAncient::Create,    // SOTA
53        NULL,
54        NULL,
55};
56
57CBattlegroundManager::CBattlegroundManager()
58:EventableObject()
59{
60        int i;
61
62    // Yes we will be running from WorldRunnable
63    m_holder = sEventMgr.GetEventHolder( WORLD_INSTANCE );
64
65        sEventMgr.AddEvent(this, &CBattlegroundManager::EventQueueUpdate, EVENT_BATTLEGROUND_QUEUE_UPDATE, 15000, 0,0);
66
67        for (i= 0; i<BATTLEGROUND_NUM_TYPES; i++) {
68                m_instances[i].clear();
69                m_maxBattlegroundId[i] = 0;
70        }
71
72}
73
74CBattlegroundManager::~CBattlegroundManager()
75{
76
77}
78
79void CBattlegroundManager::HandleBattlegroundListPacket(WorldSession * m_session, uint32 BattlegroundType, uint8 from)
80{
81        if(BattlegroundType == BATTLEGROUND_ARENA_2V2 || BattlegroundType == BATTLEGROUND_ARENA_3V3 || BattlegroundType == BATTLEGROUND_ARENA_5V5)
82        {
83                WorldPacket data(SMSG_BATTLEFIELD_LIST, 18);
84                data << m_session->GetPlayer()->GetGUID() << from << uint32(6) << uint32(0xC) << uint8(0);
85                m_session->SendPacket(&data);
86                return;
87        }
88
89        if( BattlegroundType >= BATTLEGROUND_NUM_TYPES ) return; //VLack: Nasty hackers might try to abuse this packet to crash us...
90
91        uint32 Count = 0;
92        WorldPacket data(SMSG_BATTLEFIELD_LIST, 200);
93        data << m_session->GetPlayer()->GetGUID();
94        data << from;
95        data << BattlegroundType;
96        data << uint8(2);
97        data << uint32(0);      // Count
98
99        /* Append the battlegrounds */
100        m_instanceLock.Acquire();
101        for(map<uint32, CBattleground*>::iterator itr = m_instances[BattlegroundType].begin(); itr != m_instances[BattlegroundType].end(); ++itr)
102        {
103                if(itr->second->CanPlayerJoin(m_session->GetPlayer(),BattlegroundType) && !itr->second->HasEnded() )
104                {
105                        data << itr->first;
106                        ++Count;
107                }
108        }
109        m_instanceLock.Release();
110
111        *(uint32*)&data.contents()[13] = Count;
112
113    m_session->SendPacket(&data);
114}
115
116void CBattlegroundManager::HandleBattlegroundJoin(WorldSession * m_session, WorldPacket & pck)
117{
118        uint64 guid;
119        uint32 pguid = m_session->GetPlayer()->GetLowGUID();
120        uint32 lgroup = GetLevelGrouping(m_session->GetPlayer()->getLevel());
121        uint32 bgtype;
122        uint32 instance;
123
124        pck >> guid >> bgtype >> instance;
125
126
127        if(bgtype >= BATTLEGROUND_NUM_TYPES || !bgtype)
128        {
129                sCheatLog.writefromsession(m_session,"tried to crash the server by joining battleground that does not exist (0)");
130                m_session->Disconnect();
131                return;      // cheater!
132        }
133
134        /* Check the instance id */
135        if(instance)
136        {
137                /* We haven't picked the first instance. This means we've specified an instance to join. */
138                m_instanceLock.Acquire();
139                map<uint32, CBattleground*>::iterator itr = m_instances[bgtype].find(instance);
140
141                if(itr == m_instances[bgtype].end())
142                {
143                        sChatHandler.SystemMessage(m_session, m_session->LocalizedWorldSrv(51));
144                        m_instanceLock.Release();
145                        return;
146                }
147
148                m_instanceLock.Release();
149        }
150
151        /* Queue him! */
152        m_queueLock.Acquire();
153        m_queuedPlayers[bgtype][lgroup].push_back(pguid);
154        Log.Success("BattlegroundManager", "Player %u is now in battleground queue for instance %u", m_session->GetPlayer()->GetLowGUID(), (instance + 1) );
155
156        /* send the battleground status packet */
157        SendBattlefieldStatus(m_session->GetPlayer(), 1, bgtype, instance, 0, BGMapIds[bgtype],0);
158        m_session->GetPlayer()->m_bgIsQueued = true;
159        m_session->GetPlayer()->m_bgQueueInstanceId = instance;
160        m_session->GetPlayer()->m_bgQueueType = bgtype;
161
162        /* Set battleground entry point */
163        m_session->GetPlayer()->m_bgEntryPointX = m_session->GetPlayer()->GetPositionX();
164        m_session->GetPlayer()->m_bgEntryPointY = m_session->GetPlayer()->GetPositionY();
165        m_session->GetPlayer()->m_bgEntryPointZ = m_session->GetPlayer()->GetPositionZ();
166        m_session->GetPlayer()->m_bgEntryPointMap = m_session->GetPlayer()->GetMapId();
167        m_session->GetPlayer()->m_bgEntryPointInstance = m_session->GetPlayer()->GetInstanceID();
168
169        m_queueLock.Release();
170
171        /* We will get updated next few seconds =) */
172}
173
174#define IS_ARENA(x) ( (x) >= BATTLEGROUND_ARENA_2V2 && (x) <= BATTLEGROUND_ARENA_5V5 )
175
176void ErasePlayerFromList(uint32 guid, list<uint32>* l)
177{
178        for(list<uint32>::iterator itr = l->begin(); itr != l->end(); ++itr)
179        {
180                if((*itr) == guid)
181                {
182                        l->erase(itr);
183                        return;
184                }
185        }
186}
187
188uint8 GetBattlegroundCaption(BattleGroundTypes bgType)
189{
190        switch(bgType)
191        {
192        case BATTLEGROUND_ALTERAC_VALLEY:
193                return 38;
194        case BATTLEGROUND_WARSONG_GULCH:
195                return 39;
196        case BATTLEGROUND_ARATHI_BASIN:
197                return 40;
198        case BATTLEGROUND_ARENA_2V2:
199                return 41;
200        case BATTLEGROUND_ARENA_3V3:
201                return 42;
202        case BATTLEGROUND_ARENA_5V5:
203                return 43;
204        case BATTLEGROUND_EYE_OF_THE_STORM:
205                return 44;
206        case BATTLEGROUND_STRAND_OF_THE_ANCIENT:
207                return 34;
208        default:
209                return 45;
210        }
211}
212
213void CBattlegroundManager::HandleGetBattlegroundQueueCommand(WorldSession * m_session)
214{
215        std::stringstream ss;
216
217        uint32 i,j;
218        Player * plr;
219        list<uint32>::iterator it3, it4;
220
221        m_queueLock.Acquire();
222
223        bool foundSomething = false;
224
225        for(i = 0; i < BATTLEGROUND_NUM_TYPES; ++i)
226        {
227                for(j = 0; j < MAX_LEVEL_GROUP; ++j)
228                {
229                        if(!m_queuedPlayers[i][j].size())
230                                continue;
231
232                        foundSomething = true;
233
234                        ss << m_session->LocalizedWorldSrv(GetBattlegroundCaption((BattleGroundTypes)i));
235
236                        switch(j)
237                        {
238                        case 0:
239                                ss << " (<10)";
240                                break;
241                        case 1:
242                                ss << " (<20)";
243                                break;
244                        case 2:
245                                ss << " (<30)";
246                                break;
247                        case 3:
248                                ss << " (<40)";
249                                break;
250                        case 4:
251                                ss << " (<50)";
252                                break;
253                        case 5:
254                                ss << " (<60)";
255                                break;
256                        case 6:
257                                ss << " (<70)";
258                                break;
259                        case 7:
260                                ss << " (<80)";
261                                break;
262                        }
263
264                        ss << ": ";
265
266                        ss << (uint32)m_queuedPlayers[i][j].size() << " players queued";
267
268                        if(!IS_ARENA(i))
269                        {
270                                int ally = 0, horde = 0;
271
272                                for(it3 = m_queuedPlayers[i][j].begin(); it3 != m_queuedPlayers[i][j].end();)
273                                {
274                                        it4 = it3++;
275                                        plr = objmgr.GetPlayer(*it4);
276
277                                        if(!plr || GetLevelGrouping(plr->getLevel()) != j)
278                                        {
279                                                continue;
280                                        }
281
282                                        if(plr->GetTeam() == 0)
283                                                ally++;
284                                        if(plr->GetTeam() == 1)
285                                                horde++;
286                                }
287
288                                ss << " (Alliance: " << ally << " Horde: " << horde;
289                                if((int)m_queuedPlayers[i][j].size() > (ally + horde))
290                                        ss << " Unknown: " << ((int)m_queuedPlayers[i][j].size() - ally - horde);
291                                ss << ")";
292                        }
293
294                        m_session->SystemMessage( ss.str().c_str() );
295                        ss.rdbuf()->str("");
296                }
297
298                if(IS_ARENA(i))
299                {
300                        if(m_queuedGroups[i].size())
301                        {
302                                foundSomething = true;
303
304                                ss << m_session->LocalizedWorldSrv(GetBattlegroundCaption((BattleGroundTypes)i)) << " (rated): ";
305                                ss << (uint32)m_queuedGroups[i].size() << " groups queued";
306
307                                m_session->SystemMessage( ss.str().c_str() );
308                                ss.rdbuf()->str("");
309                        }
310                }
311        }
312
313        m_queueLock.Release();
314
315        if(!foundSomething)
316                m_session->SystemMessage( "There's nobody queued." );
317}
318
319void CBattlegroundManager::EventQueueUpdate()
320{
321        this->EventQueueUpdate(false);
322}
323
324uint32 CBattlegroundManager::GetArenaGroupQInfo(Group * group, int type, uint32 *avgRating)
325{
326        ArenaTeam *team;
327        ArenaTeamMember *atm;
328        Player *plr;
329        uint32 count= 0;
330        uint32 rating= 0;
331
332        if (group == NULL || group->GetLeader() == NULL) return 0;
333
334        plr = group->GetLeader()->m_loggedInPlayer;
335        if (plr == NULL) return 0;
336
337        team = plr->m_arenaTeams[type-BATTLEGROUND_ARENA_2V2];
338        if (team == NULL) return 0;
339
340        GroupMembersSet::iterator itx;
341        for(itx = group->GetSubGroup(0)->GetGroupMembersBegin(); itx != group->GetSubGroup(0)->GetGroupMembersEnd(); ++itx)
342        {
343                plr = (*itx)->m_loggedInPlayer;
344                if(plr)
345                {
346                        if (team == plr->m_arenaTeams[type-BATTLEGROUND_ARENA_2V2])
347                        {
348                                atm = team->GetMemberByGuid(plr->GetLowGUID());
349                                if (atm)
350                                {
351                                        rating+= atm->PersonalRating;
352                                        count++;
353                                }
354                        }
355                }
356        }
357
358        *avgRating = count > 0 ? rating/count : 0;
359
360        return team ? team->m_id : 0;
361}
362
363void CBattlegroundManager::AddGroupToArena(CBattleground * bg, Group * group, int nteam)
364{
365        ArenaTeam *team;
366        Player *plr;
367
368        if (group == NULL || group->GetLeader() == NULL) return;
369
370        plr = group->GetLeader()->m_loggedInPlayer;
371        if (plr == NULL) return;
372
373        team = plr->m_arenaTeams[bg->GetType()-BATTLEGROUND_ARENA_2V2];
374        if (team == NULL) return;
375
376        GroupMembersSet::iterator itx;
377        for(itx = group->GetSubGroup(0)->GetGroupMembersBegin(); itx != group->GetSubGroup(0)->GetGroupMembersEnd(); ++itx)
378        {
379                plr = (*itx)->m_loggedInPlayer;
380                if(plr && team == plr->m_arenaTeams[bg->GetType()-BATTLEGROUND_ARENA_2V2])
381                {
382                        if( bg->HasFreeSlots(nteam,bg->GetType()) )
383                        {
384                                bg->AddPlayer(plr, nteam);
385                                plr->SetTeam(nteam);
386                        }
387                }
388        }
389}
390
391int CBattlegroundManager::CreateArenaType(int type, Group * group1, Group * group2)
392{
393        Arena * ar = ((Arena*)CreateInstance(type, LEVEL_GROUP_70));
394        if (ar == NULL)
395        {
396                Log.Error("BattlegroundMgr", "%s (%u): Couldn't create Arena Instance", __FILE__, __LINE__);
397                m_queueLock.Release();
398                m_instanceLock.Release();
399                return -1;
400        }
401        ar->rated_match=true;
402
403        AddGroupToArena(ar, group1, 0);
404        AddGroupToArena(ar, group2, 1);
405
406        return 0;
407}
408
409void CBattlegroundManager::AddPlayerToBg(CBattleground * bg, deque<uint32> *playerVec, uint32 i, uint32 j)
410{
411        uint32 plrguid = *playerVec->begin();
412        playerVec->pop_front();
413        Player *plr = objmgr.GetPlayer(plrguid);
414        if(plr) {
415                if(bg->CanPlayerJoin(plr,bg->GetType()))
416                {
417                        bg->AddPlayer(plr, plr->GetTeam());
418                        ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]);
419                }
420                else
421                {
422                        // Put again the player in the queue
423                        playerVec->push_back(plrguid);
424                }
425        }
426        else
427        {
428                ErasePlayerFromList(plrguid, &m_queuedPlayers[i][j]);
429        }
430}
431
432void CBattlegroundManager::AddPlayerToBgTeam(CBattleground * bg, deque<uint32> *playerVec, uint32 i, uint32 j, int Team)
433{
434        if (bg->HasFreeSlots(Team,bg->GetType()))
435        {
436                uint32 plrguid = *playerVec->begin();
437                playerVec->pop_front();
438                Player *plr = objmgr.GetPlayer(plrguid);
439                if(plr)
440                {
441                        plr->m_bgTeam=Team;
442                        bg->AddPlayer(plr, Team);
443                }
444                ErasePlayerFromList(plrguid, &m_queuedPlayers[i][j]);
445        }
446}
447
448void CBattlegroundManager::EventQueueUpdate(bool forceStart)
449{
450        deque<uint32> tempPlayerVec[2];
451        uint32 i,j,k;
452        Player * plr;
453        CBattleground * bg;
454        list<uint32>::iterator it3, it4;
455        map<uint32, CBattleground*>::iterator iitr;
456        Arena * arena;
457        int32 team;
458        uint32 plrguid;
459        m_queueLock.Acquire();
460        m_instanceLock.Acquire();
461
462        for(i = 0; i < BATTLEGROUND_NUM_TYPES; ++i)
463        {
464                for(j = 0; j < MAX_LEVEL_GROUP; ++j)
465                {
466                        if(!m_queuedPlayers[i][j].size())
467                                continue;
468
469                        tempPlayerVec[0].clear();
470                        tempPlayerVec[1].clear();
471
472                        for(it3 = m_queuedPlayers[i][j].begin(); it3 != m_queuedPlayers[i][j].end();)
473                        {
474                                it4 = it3++;
475                                plrguid = *it4;
476                                plr = objmgr.GetPlayer(plrguid);
477
478                                if(!plr || GetLevelGrouping(plr->getLevel()) != j)
479                                {
480                                        m_queuedPlayers[i][j].erase(it4);
481                                        continue;
482                                }
483
484                                // queued to a specific instance id?
485                                if(plr->m_bgQueueInstanceId != 0)
486                                {
487                                        iitr = m_instances[i].find(plr->m_bgQueueInstanceId);
488                                        if(iitr == m_instances[i].end())
489                                        {
490                                                // queue no longer valid
491                                                plr->GetSession()->SystemMessage(plr->GetSession()->LocalizedWorldSrv(52), plr->m_bgQueueInstanceId);
492                                                plr->m_bgIsQueued = false;
493                                                plr->m_bgQueueType = 0;
494                                                plr->m_bgQueueInstanceId = 0;
495                                                m_queuedPlayers[i][j].erase(it4);
496                                        }
497
498                                        // can we join?
499                                        bg = iitr->second;
500                                        if(bg->CanPlayerJoin(plr,bg->GetType()))
501                                        {
502                                                bg->AddPlayer(plr, plr->GetTeam());
503                                                m_queuedPlayers[i][j].erase(it4);
504                                        }
505                                }
506                                else
507                                {
508                                        if(IS_ARENA(i))
509                                                tempPlayerVec[0].push_back(plrguid);
510                                        else if (!plr->HasAura(BG_DESERTER))
511                                                tempPlayerVec[plr->GetTeam()].push_back(plrguid);
512                                }
513                        }
514
515                        // try to join existing instances
516                        for(iitr = m_instances[i].begin(); iitr != m_instances[i].end(); ++iitr)
517                        {
518                                if( iitr->second->HasEnded() || iitr->second->GetLevelGroup() != j )
519                                        continue;
520
521                                if(IS_ARENA(i))
522                                {
523                                        arena = ((Arena*)iitr->second);
524                                        if(arena->Rated())
525                                                continue;
526
527                                        team = arena->GetFreeTeam();
528                                        while(team >= 0 && tempPlayerVec[0].size())
529                                        {
530                                                plrguid = *tempPlayerVec[0].begin();
531                                                tempPlayerVec[0].pop_front();
532                                                plr = objmgr.GetPlayer(plrguid);
533                                                if(plr)
534                                                {
535                                                        plr->m_bgTeam=team;
536                                                        arena->AddPlayer(plr, team);
537                                                        team = arena->GetFreeTeam();
538                                                }
539                                                ErasePlayerFromList(plrguid, &m_queuedPlayers[i][j]);
540                                        }
541                                }
542                                else
543                                {
544                                        bg = iitr->second;
545                                        int size = (int)min(tempPlayerVec[0].size(),tempPlayerVec[1].size());
546                                        for(int counter = 0; (counter < size) && (bg->IsFull() == false); counter++)
547                                        {
548                                                AddPlayerToBgTeam(bg, &tempPlayerVec[0], i, j, 0);
549                                                AddPlayerToBgTeam(bg, &tempPlayerVec[1], i, j, 1);
550                                        }
551
552                                        while (tempPlayerVec[0].size() > 0 && bg->HasFreeSlots(0, bg->GetType()))
553                                        {
554                                                AddPlayerToBgTeam(bg, &tempPlayerVec[0], i, j, 0);
555                                        }
556                                        while (tempPlayerVec[1].size() > 0 && bg->HasFreeSlots(1, bg->GetType()))
557                                        {
558                                                AddPlayerToBgTeam(bg, &tempPlayerVec[1], i, j, 1);
559                                        }
560                                }
561                        }
562
563                        if(IS_ARENA(i))
564                        {
565                                // enough players to start a round?
566                                uint32 minPlayers = BattlegroundManager.GetMinimumPlayers(i);
567                                if(!forceStart && tempPlayerVec[0].size() < minPlayers)
568                                        continue;
569
570                                if(CanCreateInstance(i,j))
571                                {
572                                        arena = ((Arena*)CreateInstance(i, j));
573                                        if ( arena == NULL )
574                                        {
575                                                Log.Error("BattlegroundMgr", "%s (%u): Couldn't create Arena Instance", __FILE__, __LINE__);
576                                                m_queueLock.Release();
577                                                m_instanceLock.Release();
578                                                return;
579                                        }
580
581                                        team = arena->GetFreeTeam();
582                                        while(!arena->IsFull() && tempPlayerVec[0].size() && team >= 0)
583                                        {
584                                                plrguid = *tempPlayerVec[0].begin();
585                                                tempPlayerVec[0].pop_front();
586                                                plr = objmgr.GetPlayer(plrguid);
587
588                                                if(plr)
589                                                {
590                                                        plr->m_bgTeam=team;
591                                                        arena->AddPlayer(plr, team);
592                                                        team = arena->GetFreeTeam();
593                                                }
594
595                                                // remove from the main queue (painful!)
596                                                ErasePlayerFromList(plrguid, &m_queuedPlayers[i][j]);
597                                        }
598                                }
599                        }
600                        else
601                        {
602                                uint32 minPlayers = BattlegroundManager.GetMinimumPlayers(i);
603                                if(forceStart || (tempPlayerVec[0].size() >= minPlayers && tempPlayerVec[1].size() >= minPlayers))
604                                {
605                                        if(CanCreateInstance(i,j))
606                                        {
607                                                bg = CreateInstance(i,j);
608                                                if ( bg == NULL )
609                                                {
610                                                        m_queueLock.Release();
611                                                        m_instanceLock.Release();
612                                                        return;
613                                                }
614
615                                                // push as many as possible in
616                                                if (forceStart)
617                                                {
618                                                        for(k = 0; k < 2; ++k)
619                                                        {
620                                                                while(tempPlayerVec[k].size() && bg->HasFreeSlots(k, bg->GetType()))
621                                                                {
622                                                                        AddPlayerToBgTeam(bg, &tempPlayerVec[k], i, j, k);
623                                                                }
624                                                        }
625                                                }
626                                                else
627                                                {
628                                                        int size = (int)min(tempPlayerVec[0].size(),tempPlayerVec[1].size());
629                                                        for(int counter = 0; (counter < size) && (bg->IsFull() == false); counter++)
630                                                        {
631                                                                AddPlayerToBgTeam(bg, &tempPlayerVec[0], i, j, 0);
632                                                                AddPlayerToBgTeam(bg, &tempPlayerVec[1], i, j, 1);
633                                                        }
634                                                }
635                                        }
636                                }
637                        }
638                }
639        }
640
641        /* Handle paired arena team joining */
642        Group * group1, *group2;
643        uint32 teamids[2] = {0,0};
644        uint32 avgRating[2] = {0,0};
645        uint32 n;
646        list<uint32>::iterator itz;
647        for(i = BATTLEGROUND_ARENA_2V2; i <= BATTLEGROUND_ARENA_5V5; ++i)
648        {
649                if(!forceStart && m_queuedGroups[i].size() < 2)      /* got enough to have an arena battle ;P */
650                {
651                        continue;
652                }
653
654                for (j= 0; j<(uint32)m_queuedGroups[i].size(); j++)
655                {
656                        group1 = group2 = NULL;
657                        n =     RandomUInt((uint32)m_queuedGroups[i].size()) - 1;
658                        for(itz = m_queuedGroups[i].begin(); itz != m_queuedGroups[i].end() && n>0; ++itz)
659                                --n;
660
661                        if(itz == m_queuedGroups[i].end())
662                                itz=m_queuedGroups[i].begin();
663
664                        if(itz == m_queuedGroups[i].end())
665                        {
666                                Log.Error("BattlegroundMgr", "Internal error at %s:%u", __FILE__, __LINE__);
667                                m_queueLock.Release();
668                                m_instanceLock.Release();
669                                return;
670                        }
671
672                        group1 = objmgr.GetGroupById(*itz);
673                        if (group1 == NULL)
674                        {
675                                continue;
676                        }
677
678                        if (forceStart && m_queuedGroups[i].size() == 1)
679                        {
680                                if (CreateArenaType(i, group1, NULL) == -1) return;
681                                m_queuedGroups[i].remove(group1->GetID());
682                                continue;
683                        }
684
685                        teamids[0] = GetArenaGroupQInfo(group1, i, &avgRating[0]);
686
687                        list<uint32> possibleGroups;
688                        for(itz = m_queuedGroups[i].begin(); itz != m_queuedGroups[i].end(); ++itz)
689                        {
690                                group2 = objmgr.GetGroupById(*itz);
691                                if (group2)
692                                {
693                                        teamids[1] = GetArenaGroupQInfo(group2, i, &avgRating[1]);
694                                        uint32 delta = abs((int32)avgRating[0] - (int32)avgRating[1]);
695                                        if (teamids[0] != teamids[1] && delta <= sWorld.ArenaQueueDiff)
696                                        {
697                                                possibleGroups.push_back(group2->GetID());
698                                        }
699                                }
700                        }
701
702                        if (possibleGroups.size() > 0)
703                        {
704                                n = RandomUInt((uint32)possibleGroups.size()) - 1;
705                                for(itz = possibleGroups.begin(); itz != possibleGroups.end() && n>0; ++itz)
706                                        --n;
707
708                                if(itz == possibleGroups.end())
709                                        itz=possibleGroups.begin();
710
711                                if(itz == possibleGroups.end())
712                                {
713                                        Log.Error("BattlegroundMgr", "Internal error at %s:%u", __FILE__, __LINE__);
714                                        m_queueLock.Release();
715                                        m_instanceLock.Release();
716                                        return;
717                                }
718
719                                group2 = objmgr.GetGroupById(*itz);
720                                if (group2)
721                                {
722                                        if (CreateArenaType(i, group1, group2) == -1) return;
723                                        m_queuedGroups[i].remove(group1->GetID());
724                                        m_queuedGroups[i].remove(group2->GetID());
725                                }
726                        }
727                }
728        }
729
730        m_queueLock.Release();
731        m_instanceLock.Release();
732}
733
734void CBattlegroundManager::RemovePlayerFromQueues(Player * plr)
735{
736        m_queueLock.Acquire();
737
738        Arcemu::Util::ARCEMU_ASSERT(   plr->m_bgQueueType < BATTLEGROUND_NUM_TYPES);
739
740        sEventMgr.RemoveEvents(plr, EVENT_BATTLEGROUND_QUEUE_UPDATE);
741
742        uint32 lgroup = GetLevelGrouping(plr->getLevel());
743        list<uint32>::iterator itr;
744
745        itr = m_queuedPlayers[plr->m_bgQueueType][lgroup].begin();
746        while(itr != m_queuedPlayers[plr->m_bgQueueType][lgroup].end())
747        {
748                if((*itr) == plr->GetLowGUID())
749                {
750                        Log.Debug("BattlegroundManager", "Removing player %u from queue instance %u type %u", plr->GetLowGUID(), plr->m_bgQueueInstanceId, plr->m_bgQueueType);
751                        m_queuedPlayers[plr->m_bgQueueType][lgroup].erase(itr);
752                        break;
753                }
754
755                ++itr;
756        }
757
758        plr->m_bgIsQueued = false;
759        plr->m_bgTeam=plr->GetTeam();
760        plr->m_pendingBattleground= 0;
761        SendBattlefieldStatus(plr,0,0,0,0,0,0);
762        m_queueLock.Release();
763
764        Group* group;
765        group = plr->GetGroup();
766        if (group) //if da niggas in a group, boot dis bitch ass' group outa da q
767        {
768                Log.Debug("BattlegroundManager", "Player %u removed whilst in a group. Removing players group %u from queue", plr->GetLowGUID(), group->GetID());
769                RemoveGroupFromQueues(group);
770        }
771}
772
773void CBattlegroundManager::RemoveGroupFromQueues(Group * grp)
774{
775        m_queueLock.Acquire();
776        for(uint32 i = BATTLEGROUND_ARENA_2V2; i < BATTLEGROUND_ARENA_5V5+1; ++i)
777        {
778                for(list<uint32>::iterator itr = m_queuedGroups[i].begin(); itr != m_queuedGroups[i].end(); )
779                {
780                        if((*itr) == grp->GetID())
781                                itr = m_queuedGroups[i].erase(itr);
782                        else
783                                ++itr;
784                }
785        }
786
787        for(GroupMembersSet::iterator itr = grp->GetSubGroup(0)->GetGroupMembersBegin(); itr != grp->GetSubGroup(0)->GetGroupMembersEnd(); ++itr)
788                if((*itr)->m_loggedInPlayer)
789                        SendBattlefieldStatus((*itr)->m_loggedInPlayer, 0, 0, 0, 0, 0, 0);
790
791        m_queueLock.Release();
792}
793
794
795bool CBattlegroundManager::CanCreateInstance(uint32 Type, uint32 LevelGroup)
796{
797        /*uint32 lc = 0;
798        for(map<uint32, CBattleground*>::iterator itr = m_instances[Type].begin(); itr != m_instances[Type].end(); ++itr)
799        {
800        if(itr->second->GetLevelGroup() == LevelGroup)
801        {
802        lc++;
803        if(lc >= MAXIMUM_BATTLEGROUNDS_PER_LEVEL_GROUP)
804        return false;
805        }
806        }*/
807
808        return true;
809}
810
811/* Returns the minimum number of players (Only valid for battlegrounds) */
812uint32 CBattlegroundManager::GetMinimumPlayers(uint32 dbcIndex)
813{
814        switch(dbcIndex)
815        {
816                case BATTLEGROUND_ALTERAC_VALLEY:
817                        return Config.MainConfig.GetIntDefault("Battleground", "AV_MIN", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
818                case BATTLEGROUND_WARSONG_GULCH:
819                        return Config.MainConfig.GetIntDefault("Battleground", "WS_MIN", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
820                case BATTLEGROUND_ARATHI_BASIN:
821                        return Config.MainConfig.GetIntDefault("Battleground", "AB_MIN", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
822                case BATTLEGROUND_EYE_OF_THE_STORM:
823                        return Config.MainConfig.GetIntDefault("Battleground", "EOS_MIN", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
824                case BATTLEGROUND_ARENA_2V2:
825                        return 2;
826                case BATTLEGROUND_ARENA_3V3:
827                        return 3;
828                case BATTLEGROUND_ARENA_5V5:
829                        return 5;
830                case BATTLEGROUND_STRAND_OF_THE_ANCIENT:
831                        return Config.MainConfig.GetIntDefault("Battleground", "SOTA_MIN", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
832                default:
833                        return dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction;
834        }
835}
836
837/* Returns the maximum number of players (Only valid for battlegrounds) */
838uint32 CBattlegroundManager::GetMaximumPlayers(uint32 dbcIndex)
839{
840        switch(dbcIndex)
841        {
842                case BATTLEGROUND_ALTERAC_VALLEY:
843                        return Config.MainConfig.GetIntDefault("Battleground", "AV_MAX", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
844                case BATTLEGROUND_WARSONG_GULCH:
845                        return Config.MainConfig.GetIntDefault("Battleground", "WS_MAX", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
846                case BATTLEGROUND_ARATHI_BASIN:
847                        return Config.MainConfig.GetIntDefault("Battleground", "AB_MAX", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
848                case BATTLEGROUND_EYE_OF_THE_STORM:
849                        return Config.MainConfig.GetIntDefault("Battleground", "EOS_MAX", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
850                case BATTLEGROUND_ARENA_2V2:
851                        return 2;
852                case BATTLEGROUND_ARENA_3V3:
853                        return 3;
854                case BATTLEGROUND_ARENA_5V5:
855                        return 5;
856                case BATTLEGROUND_STRAND_OF_THE_ANCIENT:
857                        return Config.MainConfig.GetIntDefault("Battleground", "SOTA_MAX", dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction);
858                default:
859                        return dbcBattlemasterListStore.LookupEntry(dbcIndex)->min_players_per_faction;
860        }
861}
862
863
864void CBattleground::SendWorldStates(Player * plr)
865{
866        if(!m_worldStates.size())
867                return;
868
869        uint32 bflag = 0;
870        uint32 bflag2 = 0;
871
872        switch(m_mapMgr->GetMapId())
873        {
874        case  489: bflag = 0x0CCD; bflag2 = 0x0CF9; break;
875        case  529: bflag = 0x0D1E; break;
876        case   30: bflag = 0x0A25; break;
877        case  559: bflag = 3698; break;
878        case 566: bflag = 0x0eec; bflag2 = 0; break;         // EOTS
879
880        default:      /* arenas */
881                bflag  = 0x0E76;
882                bflag2 = 0;
883                break;
884        }
885
886        WorldPacket data(SMSG_INIT_WORLD_STATES, 10 + (m_worldStates.size() * 8));
887        data << m_mapMgr->GetMapId();
888        data << bflag;
889        data << bflag2;
890        data << uint16(m_worldStates.size());
891
892        for(map<uint32, uint32>::iterator itr = m_worldStates.begin(); itr != m_worldStates.end(); ++itr)
893                data << itr->first << itr->second;
894        plr->GetSession()->SendPacket(&data);
895}
896
897CBattleground::CBattleground(MapMgr * mgr, uint32 id, uint32 levelgroup, uint32 type) : m_mapMgr(mgr), m_id(id), m_type(type), m_levelGroup(levelgroup)
898{
899        m_nextPvPUpdateTime = 0;
900        m_countdownStage = 0;
901        m_ended = false;
902        m_started = false;
903        m_winningteam = 0;
904        m_startTime = (uint32)UNIXTIME;
905        m_lastResurrect = (uint32)UNIXTIME;
906        m_invisGMs = 0;
907        sEventMgr.AddEvent(this, &CBattleground::EventResurrectPlayers, EVENT_BATTLEGROUND_QUEUE_UPDATE, 30000, 0,EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
908
909        /* create raid groups */
910        for(uint32 i = 0; i < 2; ++i)
911        {
912                m_groups[i] = new Group(true);
913                m_groups[i]->m_disbandOnNoMembers = false;
914                m_groups[i]->ExpandToRaid();
915        }
916        m_honorPerKill = HonorHandler::CalculateHonorPointsForKill(m_levelGroup * 10, m_levelGroup * 10);
917}
918
919CBattleground::~CBattleground()
920{
921        sEventMgr.RemoveEvents(this);
922        for(uint32 i = 0; i < 2; ++i)
923        {
924                PlayerInfo *inf;
925                for(uint32 j = 0; j < m_groups[i]->GetSubGroupCount(); ++j) {
926                        for(GroupMembersSet::iterator itr = m_groups[i]->GetSubGroup(j)->GetGroupMembersBegin(); itr != m_groups[i]->GetSubGroup(j)->GetGroupMembersEnd();) {
927                                inf = (*itr);
928                                ++itr;
929                                m_groups[i]->RemovePlayer(inf);
930                        }
931                }
932                delete m_groups[i];
933        }
934
935        m_resurrectMap.clear();
936        m_players[0].clear();
937        m_players[1].clear();   
938}
939
940void CBattleground::UpdatePvPData()
941{
942        if(m_type >= BATTLEGROUND_ARENA_2V2 && m_type <= BATTLEGROUND_ARENA_5V5)
943        {
944                if(!m_ended)
945                {
946                        return;
947                }
948        }
949
950        if(UNIXTIME >= m_nextPvPUpdateTime)
951        {
952                m_mainLock.Acquire();
953                WorldPacket data(10*(m_players[0].size()+m_players[1].size())+50);
954                BuildPvPUpdateDataPacket(&data);
955                DistributePacketToAll(&data);
956                m_mainLock.Release();
957
958                m_nextPvPUpdateTime = UNIXTIME + 2;
959        }
960}
961
962void CBattleground::BuildPvPUpdateDataPacket(WorldPacket * data)
963{
964        Arcemu::Util::ARCEMU_ASSERT(    data != NULL  );
965
966        data->Initialize(MSG_PVP_LOG_DATA);
967        data->reserve(10*(m_players[0].size()+m_players[1].size())+50);
968
969        BGScore * bs;
970        if(m_type >= BATTLEGROUND_ARENA_2V2 && m_type <= BATTLEGROUND_ARENA_5V5)
971        {
972                if(!m_ended)
973                {
974                        return;
975                }
976
977                *data << uint8(1);
978                //In 3.1 this should be the uint32(negative rating), uint32(positive rating), uint32(0)[<-this is the new field in 3.1], and a name if available / which is a null-terminated string, and we send an uint8(0), so we provide a zero length name string /
979                if(!Rated())
980                {
981                        *data << uint32(0) << uint32(0) << uint32(0) << uint8(0);
982                        *data << uint32(0) << uint32(0) << uint32(0) << uint8(0);
983                }
984                else
985                {
986                        /* Grab some arena teams */
987                        ArenaTeam **teams = ((Arena*)this)->GetTeams();
988
989                        if(teams[0]) {
990                                *data << uint32(0) << uint32(3000+m_deltaRating[0]) << uint32(0) << uint8(0);
991                        } else {
992                                *data << uint32(0) << uint32(0) << uint32(0) << uint8(0);
993                        }
994
995                        if(teams[1]) {
996                                *data << uint32(0) << uint32(3000+m_deltaRating[1]) << uint32(0) << uint8(0);
997                        } else {
998                                *data << uint32(0) << uint32(0) << uint32(0) << uint8(0);
999                        }
1000                }
1001
1002                *data << uint8(1);
1003                *data << uint8(m_winningteam);
1004
1005                *data << uint32((m_players[0].size() + m_players[1].size())-m_invisGMs);
1006                for(uint32 i = 0; i < 2; ++i)
1007                {
1008                        for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1009                        {
1010                                if( (*itr)->m_isGmInvisible )continue;
1011                                *data << (*itr)->GetGUID();
1012                                bs = &(*itr)->m_bgScore;
1013                                *data << bs->KillingBlows;
1014
1015                                *data << uint8((*itr)->m_bgTeam);
1016
1017                                *data << bs->DamageDone;
1018                                *data << bs->HealingDone;
1019                                *data << uint32(0);
1020                        }
1021                }
1022        }
1023        else
1024        {
1025                *data << uint8(0);
1026                if(m_ended)
1027                {
1028                        *data << uint8(1);
1029                        *data << uint8(m_winningteam ? 0 : 1);
1030                }
1031                else
1032                        *data << uint8(0);      // If the game has ended - this will be 1
1033
1034                *data << uint32((m_players[0].size() + m_players[1].size())-m_invisGMs);
1035
1036                uint32 FieldCount = GetFieldCount( GetType() );
1037                for(uint32 i = 0; i < 2; ++i)
1038                {
1039                        for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1040                        {
1041                                Arcemu::Util::ARCEMU_ASSERT(    *itr != NULL  );
1042                                if( (*itr)->m_isGmInvisible )
1043                                        continue;
1044                                *data << (*itr)->GetGUID(); // apparently there is a crash here
1045                                bs = &(*itr)->m_bgScore;
1046
1047                                *data << bs->KillingBlows;
1048                                *data << bs->HonorableKills;
1049                                *data << bs->Deaths;
1050                                *data << bs->BonusHonor;
1051                                *data << bs->DamageDone;
1052                                *data << bs->HealingDone;
1053
1054                                *data << FieldCount;
1055                                for( uint32 x = 0; x < FieldCount; ++x )
1056                                        *data << bs->MiscData[x];
1057                        }
1058                }
1059        }
1060
1061}
1062void CBattleground::AddPlayer(Player * plr, uint32 team)
1063{
1064        m_mainLock.Acquire();
1065
1066        /* This is called when the player is added, not when they port. So, they're essentially still queued, but not inside the bg yet */
1067        m_pendPlayers[team].insert(plr->GetLowGUID());
1068
1069        /* Send a packet telling them that they can enter */
1070        plr->m_pendingBattleground = this;
1071        BattlegroundManager.SendBattlefieldStatus(plr, 2, m_type, m_id, 80000, m_mapMgr->GetMapId(),Rated());      // You will be removed from the queue in 2 minutes.
1072
1073        /* Add an event to remove them in 1 minute 20 seconds time. */
1074        sEventMgr.AddEvent(plr, &Player::RemoveFromBattlegroundQueue, EVENT_BATTLEGROUND_QUEUE_UPDATE, 80000, 1,0);
1075
1076        m_mainLock.Release();
1077}
1078
1079void CBattleground::RemovePendingPlayer(Player * plr)
1080{
1081        m_mainLock.Acquire();
1082
1083        m_pendPlayers[plr->m_bgTeam].erase(plr->GetLowGUID());
1084
1085        /* send a null bg update (so they don't join) */
1086        BattlegroundManager.SendBattlefieldStatus(plr, 0, 0, 0, 0, 0,0);
1087        plr->m_pendingBattleground = 0;
1088        plr->m_bgTeam=plr->GetTeam();
1089       
1090        m_mainLock.Release();
1091}
1092
1093void CBattleground::OnPlayerPushed(Player * plr)
1094{
1095        if( plr->GetGroup() && !Rated() )
1096                plr->GetGroup()->RemovePlayer(plr->getPlayerInfo());
1097
1098        plr->ProcessPendingUpdates();
1099
1100        if( plr->GetGroup() == NULL )
1101        {
1102                if ( plr->m_isGmInvisible == false ) //do not join invisible gm's into bg groups.
1103                        m_groups[plr->m_bgTeam]->AddMember( plr->getPlayerInfo() );
1104        }
1105}
1106
1107void CBattleground::PortPlayer(Player * plr, bool skip_teleport /* = false*/)
1108{
1109        m_mainLock.Acquire();
1110        if(m_ended)
1111        {
1112                sChatHandler.SystemMessage(plr->GetSession(), plr->GetSession()->LocalizedWorldSrv(53) );
1113                BattlegroundManager.SendBattlefieldStatus(plr, 0, 0, 0, 0, 0,0);
1114                plr->m_pendingBattleground = 0;
1115                m_mainLock.Release();
1116                return;
1117        }
1118
1119        m_pendPlayers[plr->m_bgTeam].erase(plr->GetLowGUID());
1120        if(m_players[plr->m_bgTeam].find(plr) != m_players[plr->m_bgTeam].end())
1121        {
1122                m_mainLock.Release();
1123                return;
1124        }
1125
1126        plr->FullHPMP();
1127        plr->SetTeam(plr->m_bgTeam);
1128        if ( plr->m_isGmInvisible == false )
1129        {
1130                //Do not let everyone know an invisible gm has joined.
1131                WorldPacket data(SMSG_BATTLEGROUND_PLAYER_JOINED, 8);
1132                data << plr->GetGUID();
1133                DistributePacketToTeam(&data,plr->m_bgTeam);
1134        }
1135        else
1136        {
1137                m_invisGMs++;
1138        }
1139        m_players[plr->m_bgTeam].insert(plr);
1140
1141        /* remove from any auto queue remove events */
1142        sEventMgr.RemoveEvents(plr, EVENT_BATTLEGROUND_QUEUE_UPDATE);
1143
1144        if( !skip_teleport )
1145        {
1146                if( plr->IsInWorld() )
1147                        plr->RemoveFromWorld();
1148        }
1149
1150        plr->m_pendingBattleground = 0;
1151        plr->m_bg = this;
1152
1153        if(!plr->IsPvPFlagged())
1154                plr->SetPvPFlag();
1155
1156        plr->RemoveAurasByInterruptFlag( AURA_INTERRUPT_ON_PVP_ENTER );
1157
1158        /* Reset the score */
1159        memset(&plr->m_bgScore, 0, sizeof(BGScore));
1160
1161        /* send him the world states */
1162        SendWorldStates(plr);
1163
1164        /* update pvp data */
1165        UpdatePvPData();
1166
1167        /* add the player to the group */
1168        if(plr->GetGroup() && !Rated())
1169        {
1170                // remove them from their group
1171                plr->GetGroup()->RemovePlayer( plr->getPlayerInfo() );
1172        }
1173
1174        if(!m_countdownStage)
1175        {
1176                m_countdownStage = 1;
1177                sEventMgr.AddEvent(this, &CBattleground::EventCountdown, EVENT_BATTLEGROUND_COUNTDOWN, 30000, 0, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
1178                sEventMgr.ModifyEventTimeLeft(this, EVENT_BATTLEGROUND_COUNTDOWN, 10000);
1179        }
1180
1181        sEventMgr.RemoveEvents(this, EVENT_BATTLEGROUND_CLOSE);
1182
1183        if(!skip_teleport)
1184        {
1185                /* This is where we actually teleport the player to the battleground. */
1186                plr->SafeTeleport(m_mapMgr,GetStartingCoords(plr->m_bgTeam));
1187                BattlegroundManager.SendBattlefieldStatus(plr, 3, m_type, m_id, (uint32)UNIXTIME - m_startTime, m_mapMgr->GetMapId(),Rated());   // Elapsed time is the last argument
1188        }
1189        else
1190        {
1191                /* If we are not ported, call this immediatelly, otherwise its called after teleportation in Player::OnPushToWorld */
1192                OnAddPlayer( plr );
1193        }
1194
1195        m_mainLock.Release();
1196}
1197
1198CBattleground * CBattlegroundManager::CreateInstance(uint32 Type, uint32 LevelGroup)
1199{
1200        CreateBattlegroundFunc cfunc = BGCFuncs[Type];
1201        MapMgr * mgr = 0;
1202        CBattleground * bg;
1203        bool isWeekend = false;
1204        struct tm tm;
1205        uint32 iid;
1206        time_t t;
1207        int n;
1208
1209        if(Type == BATTLEGROUND_ARENA_2V2 || Type == BATTLEGROUND_ARENA_3V3 || Type == BATTLEGROUND_ARENA_5V5)
1210        {
1211                /* arenas follow a different procedure. */
1212                static const uint32 arena_map_ids[3] = { 559, 562, 572 };
1213                uint32 mapid = arena_map_ids[RandomUInt(2)];
1214                uint32 players_per_side;
1215
1216                mgr = sInstanceMgr.CreateBattlegroundInstance(mapid);
1217                if(mgr == NULL)
1218                {
1219                        Log.Error("BattlegroundManager", "Arena CreateInstance() call failed for map %u, type %u, level group %u", mapid, Type, LevelGroup);
1220                        return NULL;      // Shouldn't happen
1221                }
1222
1223                switch(Type)
1224                {
1225                case BATTLEGROUND_ARENA_2V2:
1226                        players_per_side = 2;
1227                        break;
1228
1229                case BATTLEGROUND_ARENA_3V3:
1230                        players_per_side = 3;
1231                        break;
1232
1233                case BATTLEGROUND_ARENA_5V5:
1234                        players_per_side = 5;
1235                        break;
1236                default:
1237                        players_per_side = 0;
1238                        break;
1239                }
1240
1241                iid = ++m_maxBattlegroundId[Type];
1242                bg = new Arena(mgr, iid, LevelGroup, Type, players_per_side);
1243                mgr->m_battleground = bg;
1244                Log.Success("BattlegroundManager", "Created arena battleground type %u for level group %u on map %u.", Type, LevelGroup, mapid);
1245                sEventMgr.AddEvent(bg, &CBattleground::EventCreate, EVENT_BATTLEGROUND_QUEUE_UPDATE, 1, 1,0);
1246                m_instanceLock.Acquire();
1247                m_instances[Type].insert( make_pair(iid, bg) );
1248                m_instanceLock.Release();
1249                return bg;
1250        }
1251
1252        if(cfunc == NULL)
1253        {
1254                Log.Error("BattlegroundManager", "Could not find CreateBattlegroundFunc pointer for type %u level group %u", Type, LevelGroup);
1255                return NULL;
1256        }
1257
1258        t = time(NULL);
1259#ifdef WIN32
1260//      localtime_s(&tm, &t);
1261        //zack : some luv for vs2k3 compiler
1262        tm = *localtime(&t);
1263#else
1264        localtime_r(&t, &tm);
1265#endif
1266
1267        switch (Type)
1268        {
1269                case BATTLEGROUND_WARSONG_GULCH: n = 0; break;
1270                case BATTLEGROUND_ARATHI_BASIN: n = 1; break;
1271                case BATTLEGROUND_EYE_OF_THE_STORM: n = 2; break;
1272                case BATTLEGROUND_STRAND_OF_THE_ANCIENT: n = 3; break;
1273                default: n = 0; break;
1274        }
1275        if (((tm.tm_yday / 7) % 4) == n)
1276        {
1277                /* Set weekend from Thursday night at midnight until Tuesday morning */
1278                isWeekend = tm.tm_wday >= 5 || tm.tm_wday < 2;
1279        }
1280
1281        /* Create Map Manager */
1282        mgr = sInstanceMgr.CreateBattlegroundInstance(BGMapIds[Type]);
1283        if(mgr == NULL)
1284        {
1285                Log.Error("BattlegroundManager", "CreateInstance() call failed for map %u, type %u, level group %u", BGMapIds[Type], Type, LevelGroup);
1286                return NULL;      // Shouldn't happen
1287        }
1288
1289        /* Call the create function */
1290        iid = ++m_maxBattlegroundId[Type];
1291        bg = cfunc(mgr, iid, LevelGroup, Type);
1292        bg->SetIsWeekend(isWeekend);
1293        mgr->m_battleground = bg;
1294        sEventMgr.AddEvent(bg, &CBattleground::EventCreate, EVENT_BATTLEGROUND_QUEUE_UPDATE, 1, 1,0);
1295        Log.Success("BattlegroundManager", "Created battleground type %u for level group %u.", Type, LevelGroup);
1296
1297        m_instanceLock.Acquire();
1298        m_instances[Type].insert( make_pair(iid, bg) );
1299        m_instanceLock.Release();
1300
1301        return bg;
1302}
1303
1304void CBattlegroundManager::DeleteBattleground(CBattleground * bg)
1305{
1306        try
1307        {
1308                uint32 i = bg->GetType();
1309                uint32 j = bg->GetLevelGroup();
1310                Player * plr;
1311
1312                m_instanceLock.Acquire();
1313                m_queueLock.Acquire();
1314                m_instances[i].erase(bg->GetId());
1315
1316                /* erase any queued players */
1317                list<uint32>::iterator itr = m_queuedPlayers[i][j].begin();
1318                list<uint32>::iterator it2;
1319                for(; itr != m_queuedPlayers[i][j].end();)
1320                {
1321                        it2 = itr++;
1322                        plr = objmgr.GetPlayer(*it2);
1323                        if(!plr)
1324                        {
1325                                m_queuedPlayers[i][j].erase(it2);
1326                                continue;
1327                        }
1328
1329                        if (plr && plr->m_bgQueueInstanceId == bg->GetId())
1330                        {
1331                                sChatHandler.SystemMessageToPlr(plr, plr->GetSession()->LocalizedWorldSrv(54), bg->GetId());
1332                                SendBattlefieldStatus(plr, 0, 0, 0, 0, 0,0);
1333                                plr->m_bgIsQueued = false;
1334                                m_queuedPlayers[i][j].erase(it2);
1335                        }
1336                }
1337
1338                m_queueLock.Release();
1339                m_instanceLock.Release();
1340
1341                //sLog.outDetail("Deleting battleground from queue %u, instance %u", bg->GetType(), bg->GetId());
1342                delete bg;
1343        }
1344        catch (...) // for Win32 Debug
1345        {       
1346                printf("Exception: CBattlegroundManager::DeleteBattleground\n");
1347                printStackTrace();
1348                throw;
1349        } 
1350
1351}
1352
1353GameObject * CBattleground::SpawnGameObject(uint32 entry,uint32 MapId , float x, float y, float z, float o, uint32 flags, uint32 faction, float scale)
1354{
1355        GameObject *go = m_mapMgr->CreateGameObject(entry);
1356
1357        go->CreateFromProto(entry, MapId, x, y, z, o);
1358
1359        go->SetFaction(faction);
1360        go->_setFaction();
1361        go->SetScale( scale);
1362        go->SetUInt32Value(GAMEOBJECT_FLAGS, flags);
1363        go->SetPosition(x, y, z, o);
1364        go->SetInstanceID(m_mapMgr->GetInstanceID());
1365
1366        return go;
1367}
1368
1369Creature *CBattleground::SpawnCreature(uint32 entry, float x, float y, float z, float o)
1370{
1371        CreatureProto *cp = CreatureProtoStorage.LookupEntry(entry);
1372        Creature *c = m_mapMgr->CreateCreature(entry);
1373
1374        c->Load(cp,x, y, z, o);
1375        c->PushToWorld(m_mapMgr);
1376        return c;
1377}
1378
1379void CBattleground::SendChatMessage(uint32 Type, uint64 Guid, const char * Format, ...)
1380{
1381        char msg[500];
1382        va_list ap;
1383        va_start(ap, Format);
1384        vsnprintf(msg, 500, Format, ap);
1385        va_end(ap);
1386        WorldPacket * data = sChatHandler.FillMessageData(Type, 0, msg, Guid, 0);
1387        DistributePacketToAll(data);
1388        delete data;
1389}
1390
1391void CBattleground::DistributePacketToAll(WorldPacket * packet)
1392{
1393        m_mainLock.Acquire();
1394        for(int i = 0; i < 2; ++i)
1395        {
1396     for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1397                        if( (*itr) && (*itr)->GetSession() )
1398                          (*itr)->GetSession()->SendPacket(packet);
1399        }
1400        m_mainLock.Release();
1401}
1402
1403void CBattleground::DistributePacketToTeam(WorldPacket * packet, uint32 Team)
1404{
1405        m_mainLock.Acquire();
1406        for(set<Player*>::iterator itr = m_players[Team].begin(); itr != m_players[Team].end(); ++itr)
1407                if( (*itr) && (*itr)->GetSession() )
1408                  (*itr)->GetSession()->SendPacket(packet);
1409        m_mainLock.Release();
1410}
1411
1412void CBattleground::PlaySoundToAll(uint32 Sound)
1413{
1414        WorldPacket data(SMSG_PLAY_SOUND, 4);
1415        data << Sound;
1416        DistributePacketToAll(&data);
1417}
1418
1419void CBattleground::PlaySoundToTeam(uint32 Team, uint32 Sound)
1420{
1421        WorldPacket data(SMSG_PLAY_SOUND, 4);
1422        data << Sound;
1423        DistributePacketToTeam(&data, Team);
1424}
1425
1426void CBattlegroundManager::SendBattlefieldStatus(Player * plr, uint32 Status, uint32 Type, uint32 InstanceID, uint32 Time, uint32 MapId, uint8 RatedMatch)
1427{
1428        WorldPacket data(SMSG_BATTLEFIELD_STATUS, 30);
1429        if(Status == 0)
1430                data << uint64(0) << uint32(0);
1431        else
1432        {
1433                if(Type >= BATTLEGROUND_ARENA_2V2 && Type <= BATTLEGROUND_ARENA_5V5)
1434                {
1435                        data << uint32(0);              // Queue Slot 0..2. Only the first slot is used in arcemu!
1436                        switch(Type)
1437                        {
1438                        case BATTLEGROUND_ARENA_2V2:
1439                                data << uint8(2);
1440                                break;
1441
1442                        case BATTLEGROUND_ARENA_3V3:
1443                                data << uint8(3);
1444                                break;
1445
1446                        case BATTLEGROUND_ARENA_5V5:
1447                                data << uint8(5);
1448                                break;
1449                        }
1450                        data << uint8(0xC);
1451                        data << uint32(6);
1452                        data << uint16(0x1F90);
1453                        data << uint32(11);
1454                        data << uint8(RatedMatch);      // 1 = rated match
1455                }
1456                else
1457                {
1458                        data << uint32(0);
1459                        data << uint8(0) << uint8(2);
1460                        data << Type;
1461                        data << uint16(0x1F90);
1462                        data << InstanceID;
1463                        data << uint8(0);
1464                }
1465
1466                data << Status;
1467
1468                switch(Status)
1469                {
1470                case 1:               // Waiting in queue
1471                        data << uint32(60) << uint32(0);            // Time / Elapsed time
1472                        break;
1473                case 2:               // Ready to join!
1474                        data << MapId << Time;
1475                        break;
1476                case 3:
1477                        if(Type >= BATTLEGROUND_ARENA_2V2 && Type <= BATTLEGROUND_ARENA_5V5)
1478                                data << MapId << uint32(120000) << Time << uint8(0);
1479                        else
1480                                data << MapId << uint32(120000) << Time << uint8(1);
1481                        break;
1482                }
1483        }
1484
1485        plr->GetSession()->SendPacket(&data);
1486}
1487
1488void CBattleground::RemovePlayer(Player * plr, bool logout)
1489{
1490        m_mainLock.Acquire();
1491
1492        WorldPacket data(SMSG_BATTLEGROUND_PLAYER_LEFT, 30);
1493        data << plr->GetGUID();
1494        if ( plr->m_isGmInvisible == false )
1495        {
1496                //Don't show invisible gm's leaving the game.
1497                DistributePacketToAll(&data);
1498        }
1499        else
1500        {
1501                RemoveInvisGM();
1502        }
1503
1504        // Call subclassed virtual method
1505        OnRemovePlayer(plr);
1506
1507        // Clean-up
1508        plr->m_bg = NULL;
1509        plr->FullHPMP();
1510        m_players[plr->m_bgTeam].erase(plr);
1511        memset(&plr->m_bgScore, 0, sizeof(BGScore));
1512
1513        /* are we in the group? */
1514        if(plr->GetGroup() == m_groups[plr->m_bgTeam])
1515                plr->GetGroup()->RemovePlayer( plr->getPlayerInfo() );
1516
1517        // reset team
1518        plr->ResetTeam();
1519
1520        /* revive the player if he is dead */
1521        if(!plr->isAlive())
1522        {
1523                plr->SetHealth( plr->GetMaxHealth());
1524                plr->ResurrectPlayer();
1525        }
1526
1527        /* remove buffs */
1528        plr->RemoveAura(32727); // Arena preparation
1529        plr->RemoveAura(44521); // BG preparation
1530        plr->RemoveAura(44535);
1531        plr->RemoveAura(21074);
1532
1533        /* teleport out */
1534        if(!logout)
1535        {
1536                if(!m_ended && !plr->GetSession()->HasGMPermissions())
1537                        plr->CastSpell(plr, BG_DESERTER, true);
1538
1539                if(!IS_INSTANCE(plr->m_bgEntryPointMap))
1540                {
1541                        LocationVector vec(plr->m_bgEntryPointX, plr->m_bgEntryPointY, plr->m_bgEntryPointZ, plr->m_bgEntryPointO);
1542                        plr->SafeTeleport(plr->m_bgEntryPointMap, plr->m_bgEntryPointInstance, vec);
1543                }
1544                else
1545                {
1546                        LocationVector vec(plr->GetBindPositionX(), plr->GetBindPositionY(), plr->GetBindPositionZ());
1547                        plr->SafeTeleport(plr->GetBindMapId(), 0, vec);
1548                }
1549
1550                BattlegroundManager.SendBattlefieldStatus(plr, 0, 0, 0, 0, 0,0);
1551
1552                /* send some null world states */
1553                data.Initialize(SMSG_INIT_WORLD_STATES);
1554                data << uint32(plr->GetMapId()) << uint32(0) << uint32(0);
1555                plr->GetSession()->SendPacket(&data);
1556        }
1557
1558        if(/*!m_ended && */m_players[0].size() == 0 && m_players[1].size() == 0)
1559        {
1560                /* create an inactive event */
1561                sEventMgr.RemoveEvents(this, EVENT_BATTLEGROUND_CLOSE);                  // 10mins
1562                //sEventMgr.AddEvent(this, &CBattleground::Close, EVENT_BATTLEGROUND_CLOSE, 600000, 1,0); //this is BS..appears to be           the cause if the battleground crashes.
1563                this->Close();
1564        }
1565
1566        plr->m_bgTeam = plr->GetTeam();
1567
1568        m_mainLock.Release();
1569}
1570
1571void CBattleground::SendPVPData(Player * plr)
1572{
1573        m_mainLock.Acquire();
1574
1575        WorldPacket data(10*(m_players[0].size()+m_players[1].size())+50);
1576        BuildPvPUpdateDataPacket(&data);
1577        plr->GetSession()->SendPacket(&data);
1578
1579        m_mainLock.Release();
1580}
1581
1582void CBattleground::EventCreate()
1583{
1584        OnCreate();
1585}
1586
1587int32 CBattleground::event_GetInstanceID()
1588{
1589        return m_mapMgr->GetInstanceID();
1590}
1591
1592void CBattleground::EventCountdown()
1593{
1594        if(m_countdownStage == 1)
1595        {
1596                m_countdownStage = 2;
1597
1598                m_mainLock.Acquire();
1599                for(int i = 0; i < 2; ++i)
1600                {
1601                         for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1602                                 if( (*itr) && (*itr)->GetSession() ){
1603                                                (*itr)->GetSession()->SystemMessage((*itr)->GetSession()->LocalizedWorldSrv(46),(*itr)->GetSession()->LocalizedWorldSrv(GetNameID()));
1604                                        }
1605                }
1606                m_mainLock.Release();
1607
1608                // SendChatMessage( CHAT_MSG_BG_EVENT_NEUTRAL, 0, "One minute until the battle for %s begins!", GetName() );
1609        }
1610        else if(m_countdownStage == 2)
1611        {
1612                m_countdownStage = 3;
1613
1614                m_mainLock.Acquire();
1615                for(int i = 0; i < 2; ++i)
1616                {
1617                         for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1618                                 if( (*itr) && (*itr)->GetSession() ){
1619                                                (*itr)->GetSession()->SystemMessage((*itr)->GetSession()->LocalizedWorldSrv(47),(*itr)->GetSession()->LocalizedWorldSrv(GetNameID()));
1620                                        }
1621                }
1622                m_mainLock.Release();
1623
1624                //SendChatMessage( CHAT_MSG_BG_EVENT_NEUTRAL, 0, "Thirty seconds until the battle for %s begins!", GetName() );
1625        }
1626        else if(m_countdownStage == 3)
1627        {
1628                m_countdownStage = 4;
1629
1630                m_mainLock.Acquire();
1631                for(int i = 0; i < 2; ++i)
1632                {
1633                         for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1634                                 if( (*itr) && (*itr)->GetSession() ){
1635                                                (*itr)->GetSession()->SystemMessage((*itr)->GetSession()->LocalizedWorldSrv(48),(*itr)->GetSession()->LocalizedWorldSrv(GetNameID()));
1636                                        }
1637                }
1638                m_mainLock.Release();
1639
1640                //SendChatMessage( CHAT_MSG_BG_EVENT_NEUTRAL, 0, "Fifteen seconds until the battle for %s begins!", GetName() );
1641                sEventMgr.ModifyEventTime(this, EVENT_BATTLEGROUND_COUNTDOWN, 150);
1642                sEventMgr.ModifyEventTimeLeft(this, EVENT_BATTLEGROUND_COUNTDOWN, 15000);
1643        }
1644        else
1645        {
1646                m_mainLock.Acquire();
1647                for(int i = 0; i < 2; ++i)
1648                {
1649                         for(set<Player*>::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
1650                                 if( (*itr) && (*itr)->GetSession() ){
1651                                                (*itr)->GetSession()->SystemMessage((*itr)->GetSession()->LocalizedWorldSrv(49),(*itr)->GetSession()->LocalizedWorldSrv(GetNameID()));
1652                                        }
1653                }
1654                m_mainLock.Release();
1655                //SendChatMessage( CHAT_MSG_BG_EVENT_NEUTRAL, 0, "The battle for %s has begun!", GetName() );
1656                sEventMgr.RemoveEvents(this, EVENT_BATTLEGROUND_COUNTDOWN);
1657                Start();
1658        }
1659}
1660
1661void CBattleground::Start()
1662{
1663        OnStart();
1664}
1665
1666void CBattleground::SetWorldState(uint32 Index, uint32 Value)
1667{
1668        map<uint32, uint32>::iterator itr = m_worldStates.find(Index);
1669        if(itr == m_worldStates.end())
1670                m_worldStates.insert( make_pair( Index, Value ) );
1671        else
1672                itr->second = Value;
1673
1674        WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8);
1675        data << Index << Value;
1676        DistributePacketToAll(&data);
1677}
1678
1679void CBattleground::Close()
1680{
1681        /* remove all players from the battleground */
1682        m_mainLock.Acquire();
1683        m_ended = true;
1684        for(uint32 i = 0; i < 2; ++i)
1685        {
1686                set<Player*>::iterator itr;
1687                set<uint32>::iterator it2;
1688                uint32 guid;
1689                Player * plr;
1690                for(itr = m_players[i].begin(); itr != m_players[i].end();)
1691                {
1692                        plr = *itr;
1693                        ++itr;
1694                        RemovePlayer(plr, false);
1695                }
1696
1697                for(it2 = m_pendPlayers[i].begin(); it2 != m_pendPlayers[i].end();)
1698                {
1699                        guid = *it2;
1700                        ++it2;
1701                        plr = objmgr.GetPlayer(guid);
1702
1703                        if(plr)
1704                                RemovePendingPlayer(plr);
1705                        else
1706                                m_pendPlayers[i].erase(guid);
1707                }
1708        }
1709
1710        /* call the virtual on close for cleanup etc */
1711        OnClose();
1712
1713        /* shut down the map thread. this will delete the battleground from the current context. */
1714        m_mapMgr->SetThreadState(THREADSTATE_TERMINATE);
1715
1716        m_mainLock.Release();
1717}
1718
1719Creature * CBattleground::SpawnSpiritGuide(float x, float y, float z, float o, uint32 horde)
1720{
1721        if(horde > 1)
1722                horde = 1;
1723
1724        CreatureInfo * pInfo = CreatureNameStorage.LookupEntry(13116 + horde);
1725        if(pInfo == 0)
1726        {
1727                return NULL;
1728        }
1729
1730        Creature * pCreature = m_mapMgr->CreateCreature(pInfo->Id);
1731
1732        pCreature->Create(pInfo->Name, m_mapMgr->GetMapId(), x, y, z, o);
1733
1734        pCreature->SetInstanceID(m_mapMgr->GetInstanceID());
1735        pCreature->SetEntry(  13116 + horde);
1736        pCreature->SetScale(  1.0f);
1737
1738        pCreature->SetMaxHealth( 10000);
1739        pCreature->SetMaxPower( POWER_TYPE_MANA, 4868 );
1740        pCreature->SetMaxPower( POWER_TYPE_FOCUS, 200 );
1741        pCreature->SetMaxPower( POWER_TYPE_HAPPINESS, 2000000 );
1742
1743        pCreature->SetHealth( 100000);
1744    pCreature->SetPower( POWER_TYPE_MANA, 4868 );
1745    pCreature->SetPower( POWER_TYPE_FOCUS, 200 );
1746    pCreature->SetPower( POWER_TYPE_HAPPINESS, 2000000 );
1747
1748        pCreature->setLevel(60);
1749        pCreature->SetFaction(84 - horde);
1750        pCreature->_setFaction();
1751
1752    pCreature->setRace( 0 );
1753    pCreature->setClass( 2 );
1754    pCreature->setGender( 1 );
1755    pCreature->SetPowerType( 0 );
1756
1757        pCreature->SetEquippedItem(MELEE,22802);
1758
1759        pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PLUS_MOB | UNIT_FLAG_NOT_ATTACKABLE_9 | UNIT_FLAG_UNKNOWN_10 | UNIT_FLAG_PVP); // 4928
1760
1761        pCreature->SetBaseAttackTime(MELEE,2000);
1762        pCreature->SetBaseAttackTime(OFFHAND,2000);
1763        pCreature->SetBoundingRadius(0.208f);
1764        pCreature->SetCombatReach(1.5f);
1765
1766        pCreature->SetDisplayId(13337 + horde);
1767        pCreature->SetNativeDisplayId(13337 + horde);
1768
1769        pCreature->SetChannelSpellId(  22011);
1770        pCreature->SetCastSpeedMod(1.0f);
1771
1772        pCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE);
1773        pCreature->SetUInt32Value(UNIT_FIELD_BYTES_2, 1 | (0x10 << 8));
1774
1775        pCreature->DisableAI();
1776        pCreature->PushToWorld(m_mapMgr);
1777        return pCreature;
1778}
1779
1780void CBattleground::QueuePlayerForResurrect(Player * plr, Creature * spirit_healer)
1781{
1782        m_mainLock.Acquire();
1783        map<Creature*,set<uint32> >::iterator itr = m_resurrectMap.find(spirit_healer);
1784        if(itr != m_resurrectMap.end())
1785                itr->second.insert(plr->GetLowGUID());
1786        plr->m_areaSpiritHealer_guid=spirit_healer->GetGUID();
1787        m_mainLock.Release();
1788}
1789
1790void CBattleground::RemovePlayerFromResurrect(Player * plr, Creature * spirit_healer)
1791{
1792        m_mainLock.Acquire();
1793        map<Creature*,set<uint32> >::iterator itr = m_resurrectMap.find(spirit_healer);
1794        if(itr != m_resurrectMap.end())
1795                itr->second.erase(plr->GetLowGUID());
1796        plr->m_areaSpiritHealer_guid= 0;
1797        m_mainLock.Release();
1798}
1799
1800void CBattleground::AddSpiritGuide(Creature * pCreature)
1801{
1802        m_mainLock.Acquire();
1803        map<Creature*,set<uint32> >::iterator itr = m_resurrectMap.find(pCreature);
1804        if(itr == m_resurrectMap.end())
1805        {
1806                set<uint32> ti;
1807                m_resurrectMap.insert(make_pair(pCreature,ti));
1808        }
1809        m_mainLock.Release();
1810}
1811
1812void CBattleground::RemoveSpiritGuide(Creature * pCreature)
1813{
1814        m_mainLock.Acquire();
1815        m_resurrectMap.erase(pCreature);
1816        m_mainLock.Release();
1817}
1818
1819void CBattleground::EventResurrectPlayers()
1820{
1821        m_mainLock.Acquire();
1822        Player * plr;
1823        set<uint32>::iterator itr;
1824        map<Creature*,set<uint32> >::iterator i;
1825        WorldPacket data(50);
1826        for(i = m_resurrectMap.begin(); i != m_resurrectMap.end(); ++i)
1827        {
1828                for(itr = i->second.begin(); itr != i->second.end(); ++itr)
1829                {
1830                        plr = m_mapMgr->GetPlayer(*itr);
1831                        if(plr && plr->IsDead())
1832                        {
1833                                data.Initialize(SMSG_SPELL_START);
1834                                data << plr->GetNewGUID() << plr->GetNewGUID() << uint32(RESURRECT_SPELL) << uint8(0) << uint16(0) << uint32(0) << uint16(2) << plr->GetGUID();
1835                                plr->SendMessageToSet(&data, true);
1836
1837                                data.Initialize(SMSG_SPELL_GO);
1838                                data << plr->GetNewGUID() << plr->GetNewGUID() << uint32(RESURRECT_SPELL) << uint8(0) << uint8(1) << uint8(1) << plr->GetGUID() << uint8(0) << uint16(2)
1839                                        << plr->GetGUID();
1840                                plr->SendMessageToSet(&data, true);
1841
1842                                plr->ResurrectPlayer();
1843                                plr->SetHealth( plr->GetMaxHealth());
1844                plr->SetPower( POWER_TYPE_MANA, plr->GetMaxPower( POWER_TYPE_MANA ) );
1845                                plr->SetPower( POWER_TYPE_ENERGY, plr->GetMaxPower( POWER_TYPE_ENERGY ) );
1846                                plr->CastSpell(plr, BG_REVIVE_PREPARATION, true);
1847                        }
1848                }
1849                i->second.clear();
1850        }
1851        m_lastResurrect = (uint32)UNIXTIME;
1852        m_mainLock.Release();
1853}
1854
1855void CBattlegroundManager::HandleArenaJoin(WorldSession * m_session, uint32 BattlegroundType, uint8 as_group, uint8 rated_match)
1856{
1857        uint32 pguid = m_session->GetPlayer()->GetLowGUID();
1858        uint32 lgroup = GetLevelGrouping(m_session->GetPlayer()->getLevel());
1859        if(as_group && m_session->GetPlayer()->GetGroup() == NULL)
1860                return;
1861
1862        Group * pGroup = m_session->GetPlayer()->GetGroup();
1863        if(as_group)
1864        {
1865                if(pGroup->GetSubGroupCount() != 1)
1866                {
1867                        m_session->SystemMessage(m_session->LocalizedWorldSrv(55) );
1868                        return;
1869                }
1870                if(pGroup->GetLeader() != m_session->GetPlayer()->getPlayerInfo())
1871                {
1872                        m_session->SystemMessage(m_session->LocalizedWorldSrv(56) );
1873                        return;
1874                }
1875
1876                GroupMembersSet::iterator itx;
1877                if(!rated_match)
1878                {
1879                        /* add all players normally.. bleh ;P */
1880                        pGroup->Lock();
1881                        for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx)
1882                        {
1883                                if((*itx)->m_loggedInPlayer && !(*itx)->m_loggedInPlayer->m_bgIsQueued && !(*itx)->m_loggedInPlayer->m_bg)
1884                                        HandleArenaJoin((*itx)->m_loggedInPlayer->GetSession(), BattlegroundType, 0, 0);
1885                        }
1886                        pGroup->Unlock();
1887                        return;
1888                }
1889                else
1890                {
1891                        /* make sure all players are 70 */
1892                        uint32 maxplayers;
1893                        uint32 type=BattlegroundType-BATTLEGROUND_ARENA_2V2;
1894                        switch(BattlegroundType)
1895                        {
1896                        case BATTLEGROUND_ARENA_3V3:
1897                                maxplayers=3;
1898                                break;
1899
1900                        case BATTLEGROUND_ARENA_5V5:
1901                                maxplayers=5;
1902                                break;
1903
1904                        case BATTLEGROUND_ARENA_2V2:
1905                        default:
1906                                maxplayers=2;
1907                                break;
1908                        }
1909
1910                        if(pGroup->GetLeader()->m_loggedInPlayer && pGroup->GetLeader()->m_loggedInPlayer->m_arenaTeams[type] == NULL)
1911                        {
1912                                m_session->SendNotInArenaTeamPacket(uint8(maxplayers));
1913                                return;
1914                        }
1915
1916                        pGroup->Lock();
1917                        for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx)
1918                        {
1919                                if(maxplayers== 0)
1920                                {
1921                                        m_session->SystemMessage(m_session->LocalizedWorldSrv(58));
1922                                        pGroup->Unlock();
1923                                        return;
1924                                }
1925
1926                                if( (*itx)->lastLevel < PLAYER_ARENA_MIN_LEVEL )
1927                                {
1928                                        m_session->SystemMessage(m_session->LocalizedWorldSrv(59));
1929                                        pGroup->Unlock();
1930                                        return;
1931                                }
1932
1933                                if((*itx)->m_loggedInPlayer)
1934                                {
1935                                        if((*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bgIsQueued)
1936                                        {
1937                                                m_session->SystemMessage(m_session->LocalizedWorldSrv(60));
1938                                                pGroup->Unlock();
1939                                                return;
1940                                        };
1941                                        if((*itx)->m_loggedInPlayer->m_arenaTeams[type] != pGroup->GetLeader()->m_loggedInPlayer->m_arenaTeams[type])
1942                                        {
1943                                                m_session->SystemMessage(m_session->LocalizedWorldSrv(61));
1944                                                pGroup->Unlock();
1945                                                return;
1946                                        }
1947
1948                                        --maxplayers;
1949                                }
1950                        }
1951                        WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
1952                        data << uint32(6);      // all arenas
1953
1954                        for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx)
1955                        {
1956                                if((*itx)->m_loggedInPlayer)
1957                                {
1958                                        SendBattlefieldStatus((*itx)->m_loggedInPlayer, 1, BattlegroundType, 0 , 0, 0, 1);
1959                                        (*itx)->m_loggedInPlayer->m_bgIsQueued = true;
1960                                        (*itx)->m_loggedInPlayer->m_bgQueueInstanceId = 0;
1961                                        (*itx)->m_loggedInPlayer->m_bgQueueType = BattlegroundType;
1962                                        (*itx)->m_loggedInPlayer->GetSession()->SendPacket(&data);
1963                                        (*itx)->m_loggedInPlayer->m_bgEntryPointX=(*itx)->m_loggedInPlayer->GetPositionX();
1964                                        (*itx)->m_loggedInPlayer->m_bgEntryPointY=(*itx)->m_loggedInPlayer->GetPositionY();
1965                                        (*itx)->m_loggedInPlayer->m_bgEntryPointZ=(*itx)->m_loggedInPlayer->GetPositionZ();
1966                                        (*itx)->m_loggedInPlayer->m_bgEntryPointMap=(*itx)->m_loggedInPlayer->GetMapId();
1967                                }
1968                        }
1969
1970                        pGroup->Unlock();
1971
1972                        m_queueLock.Acquire();
1973                        m_queuedGroups[BattlegroundType].push_back(pGroup->GetID());
1974                        m_queueLock.Release();
1975                        Log.Success("BattlegroundMgr", "Group %u is now in battleground queue for arena type %u", pGroup->GetID(), BattlegroundType);
1976
1977                        /* send the battleground status packet */
1978
1979                        return;
1980                }
1981        }
1982
1983
1984        /* Queue him! */
1985        m_queueLock.Acquire();
1986        m_queuedPlayers[BattlegroundType][lgroup].push_back(pguid);
1987        Log.Success("BattlegroundMgr", "Player %u is now in battleground queue for {Arena %u}", m_session->GetPlayer()->GetLowGUID(), BattlegroundType );
1988
1989        /* send the battleground status packet */
1990        SendBattlefieldStatus(m_session->GetPlayer(), 1, BattlegroundType, 0 , 0, 0,0);
1991        m_session->GetPlayer()->m_bgIsQueued = true;
1992        m_session->GetPlayer()->m_bgQueueInstanceId = 0;
1993        m_session->GetPlayer()->m_bgQueueType = BattlegroundType;
1994
1995        /* Set battleground entry point */
1996        m_session->GetPlayer()->m_bgEntryPointX = m_session->GetPlayer()->GetPositionX();
1997        m_session->GetPlayer()->m_bgEntryPointY = m_session->GetPlayer()->GetPositionY();
1998        m_session->GetPlayer()->m_bgEntryPointZ = m_session->GetPlayer()->GetPositionZ();
1999        m_session->GetPlayer()->m_bgEntryPointMap = m_session->GetPlayer()->GetMapId();
2000        m_session->GetPlayer()->m_bgEntryPointInstance = m_session->GetPlayer()->GetInstanceID();
2001
2002        m_queueLock.Release();
2003}
2004
2005bool CBattleground::CanPlayerJoin(Player * plr, uint32 type)
2006{
2007        return HasFreeSlots(plr->m_bgTeam,type)&&(GetLevelGrouping(plr->getLevel())==GetLevelGroup())&&(!plr->HasAura(BG_DESERTER));
2008}
2009
2010void CBattleground::QueueAtNearestSpiritGuide(Player *plr, Creature *old)
2011{
2012        float dd;
2013        float dist = 999999.0f;
2014        Creature *cl = NULL;
2015        set<uint32> *closest = NULL;
2016        m_lock.Acquire();
2017        map<Creature*, set<uint32> >::iterator itr = m_resurrectMap.begin();
2018        for(; itr != m_resurrectMap.end(); ++itr)
2019        {
2020                if( itr->first == old )
2021                        continue;
2022
2023                dd = plr->GetDistance2dSq(itr->first) < dist;
2024                if( dd < dist )
2025                {
2026                        cl = itr->first;
2027                        closest = &itr->second;
2028                        dist = dd;
2029                }
2030        }
2031
2032        if( closest != NULL )
2033        {
2034                closest->insert(plr->GetLowGUID());
2035                plr->m_areaSpiritHealer_guid=cl->GetGUID();
2036                plr->CastSpell(plr,2584,true);
2037        }
2038
2039        m_lock.Release();
2040}
2041
2042uint32 CBattleground::GetFreeSlots(uint32 t, uint32 type)
2043{
2044        uint32 maxPlayers = BattlegroundManager.GetMaximumPlayers(type);
2045
2046        m_mainLock.Acquire();
2047        size_t s = maxPlayers - m_players[t].size() - m_pendPlayers[t].size();
2048        m_mainLock.Release();
2049        return (uint32)s;
2050}
2051
2052bool CBattleground::HasFreeSlots(uint32 Team, uint32 type)
2053{
2054        bool res;
2055        uint32 maxPlayers = BattlegroundManager.GetMaximumPlayers(type);
2056
2057        m_mainLock.Acquire();
2058        if (type >= BATTLEGROUND_ARENA_2V2 && type <= BATTLEGROUND_ARENA_5V5)
2059        {
2060                res = ((uint32)m_players[Team].size() + m_pendPlayers[Team].size() < maxPlayers);
2061        }
2062        else
2063        {
2064                uint32 size[2];
2065                size[0] = uint32(m_players[0].size() + m_pendPlayers[0].size());
2066                size[1] = uint32(m_players[1].size() + m_pendPlayers[1].size());
2067                res = (size[Team] < maxPlayers) && (((int)size[Team] - (int)size[1-Team]) <= 0);
2068        }
2069        m_mainLock.Release();
2070        return res;
2071}
2072
Note: See TracBrowser for help on using the browser.