root/trunk/src/game/BattleGroundMgr.cpp @ 2

Revision 2, 36.2 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

RevLine 
[2]1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19#include "Common.h"
20#include "Player.h"
21#include "BattleGroundMgr.h"
22#include "BattleGroundAV.h"
23#include "BattleGroundAB.h"
24#include "BattleGroundEY.h"
25#include "BattleGroundWS.h"
26#include "BattleGroundNA.h"
27#include "BattleGroundBE.h"
28#include "BattleGroundAA.h"
29#include "BattleGroundRL.h"
30#include "SharedDefines.h"
31#include "Policies/SingletonImp.h"
32#include "MapManager.h"
33#include "ObjectMgr.h"
34#include "ProgressBar.h"
35#include "World.h"
36#include "Chat.h"
37
38INSTANTIATE_SINGLETON_1( BattleGroundMgr );
39
40/*********************************************************/
41/***            BATTLEGROUND QUEUE SYSTEM              ***/
42/*********************************************************/
43
44BattleGroundQueue::BattleGroundQueue()
45{
46    //queues are empty, we don't have to call clear()
47    for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)
48    {
49        m_QueuedPlayers[i].Horde = 0;
50        m_QueuedPlayers[i].Alliance = 0;
51        //m_QueuedPlayers[i].AverageTime = 0;
52    }
53}
54
55BattleGroundQueue::~BattleGroundQueue()
56{
57    for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)
58    {
59        m_QueuedPlayers[i].clear();
60    }
61}
62
63void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId)
64{
65    uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel();
66
67    //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak
68    PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()];
69    info.InviteTime                 = 0;
70    info.IsInvitedToBGInstanceGUID  = 0;
71    info.LastInviteTime             = 0;
72    info.LastOnlineTime             = getMSTime();
73    info.Team                       = plr->GetTeam();
74
75    //add player to waiting order queue
76    m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID());
77
78    if(plr->GetTeam() == ALLIANCE)
79        ++m_QueuedPlayers[queue_id].Alliance;
80    else
81        ++m_QueuedPlayers[queue_id].Horde;
82
83    this->Update(bgTypeId, queue_id);
84
85    if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
86    {
87        BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
88        char const* bgName = bg->GetName();
89
90        uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id);
91        uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id);
92
93        // replace hardcoded max level by player max level for nice output
94        if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
95            q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL);
96
97        int8 MinPlayers = bg->GetMinPlayersPerTeam();
98
99        uint8 qHorde = m_QueuedPlayers[queue_id].Horde;
100        uint8 qAlliance = m_QueuedPlayers[queue_id].Alliance;
101
102        // Show queue status to player only (when joining queue)
103        if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
104        {
105            ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, 
106                bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde);
107        }
108        // System message
109        else
110        {
111            sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD,
112                bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde);
113        }
114    }
115}
116
117void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
118{
119    Player *plr = objmgr.GetPlayer(guid);
120
121    uint32 queue_id = 0;
122    QueuedPlayersMap::iterator itr;
123    bool IsSet = false;
124    if(!plr)
125    {                                                       //player is offline, we need to find him somewhere in queues
126        /// there is something wrong if this code is run, because we have in queue only online players!
127        sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash");
128        for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)
129        {
130            itr = m_QueuedPlayers[i].find(guid);
131            if(itr != m_QueuedPlayers[i].end())
132            {
133                queue_id = i;
134                IsSet = true;
135                break;
136            }
137        }
138    }
139    else
140    {                                                       //player is online, we have his level, so we can find exact queue from his level
141        queue_id = plr->GetBattleGroundQueueIdFromLevel();
142        itr = m_QueuedPlayers[queue_id].find(guid);
143        IsSet = true;
144    }
145
146    //all variables are set, so remove player
147    //remove player from time queue
148    m_PlayersSortedByWaitTime[queue_id].remove(guid);
149
150    if (IsSet && itr != m_QueuedPlayers[queue_id].end())
151    {
152        if (!itr->second.IsInvitedToBGInstanceGUID)
153        {
154            if(itr->second.Team == ALLIANCE)
155                --m_QueuedPlayers[queue_id].Alliance;
156            else
157                --m_QueuedPlayers[queue_id].Horde;
158        }
159        else
160        {
161            if (decreaseInvitedCount)
162            {
163                BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID);
164                if (bg)
165                    bg->DecreaseInvitedCount(itr->second.Team);
166            }
167        }
168        m_QueuedPlayers[queue_id].erase(itr);
169    }
170}
171
172/*
173this 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
174add 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
175*/
176void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id)
177{
178    if (queue_id >= MAX_BATTLEGROUND_QUEUES)
179    {
180        //this is error, that caused crashes (not in , but now it shouldn't)
181        sLog.outError("BattleGroundQueue::Update() called for non existing queue type - this can cause crash, pls report problem, if this is the last line of error log before crash");
182        return;
183    }
184
185    //if no players in queue ... do nothing
186    if (this->m_QueuedPlayers[queue_id].Alliance == 0 && this->m_QueuedPlayers[queue_id].Horde == 0)
187        return;
188
189    //battleground with free slot for player should be always the last in this queue
190    for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr)
191    {
192        // battleground is running, so if:
193        // DO NOT allow queue manager to invite new player to running arena
194        if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE)
195        {
196            //we must check both teams
197            BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!)
198            // and iterator is invalid
199
200            //check if there are some players in queue
201            if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0)
202            {
203                for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();)
204                {
205                    Player* plr = objmgr.GetPlayer(*itr2);
206                    if (!plr)
207                    {
208                        //something is wrong!, kick player from queue
209                        sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug");
210                        uint64 oldval = *itr2;
211                        itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);
212                        RemovePlayer(oldval, true);
213                        continue;
214                    }
215
216                    // player will be invited, if in bg there is a free slot for him
217                    if (bg->HasFreeSlotsForTeam(plr->GetTeam()))
218                    {
219                        // iterator to player's queue status
220                        QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2);
221
222                        // remove him from time queue
223                        itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);
224
225                        // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and pls report it)
226                        if (itrPlayerStatus == m_QueuedPlayers[queue_id].end())
227                            continue;
228
229                        // check if player is not already invited
230                        if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID)
231                        {
232                            itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID();
233                            itrPlayerStatus->second.InviteTime = getMSTime();
234                            itrPlayerStatus->second.LastInviteTime = getMSTime();
235                            if(itrPlayerStatus->second.Team == ALLIANCE)
236                                --m_QueuedPlayers[queue_id].Alliance;
237                            else
238                                --m_QueuedPlayers[queue_id].Horde;
239                            sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID());
240
241                            WorldPacket data;
242                            uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId);
243                            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);
244                            plr->GetSession()->SendPacket(&data);
245                        }
246                    }
247                    else
248                        ++itr2;
249
250                    //if battleground is FULL, then it is removed from free slot queue - not yet implemented!
251                    if (!bg->HasFreeSlots())
252                    {
253                        //if bg is full, there is no need to invite other players, so break
254                        break;
255                        //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue
256                        //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented
257                    }
258                }
259            }
260        }
261    }
262
263    /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */
264    //itr->end is the last BG - template, which is not already started!
265
266    /* here will be a most of change, when we create battlegrounds instantiated */
267    /* if (there is enough players to start new BG)
268        Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId)
269        - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template
270            (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */
271
272    /* following code is working with current Battleground system and it should be removed, when BGs will work like instances */
273    BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId);
274    if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE)
275        return;
276    if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam())
277    {
278        bg2->SetStatus(STATUS_WAIT_JOIN);
279        bg2->SetQueueType(queue_id);
280
281        for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();)
282        {
283            Player* plr = objmgr.GetPlayer(*itr2);
284            if (!plr)
285            {
286                //something is wrong!, kick player from queue
287                sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug");
288                uint64 oldval = *itr2;
289                itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);
290                RemovePlayer(oldval, true);
291                continue;
292            }
293
294            /* TODO: (i'm not sure this code will be useful:
295            here should be some condition like if (bg2->isArena() && bg2->isRated())
296            {
297                invite players from 1 certain group on each faction to play arena match
298            } else if ....and existing code
299            */
300            // player will be invited, if in bg there is a free slot for him
301            if (bg2->HasFreeSlotsForTeam(plr->GetTeam()))
302            {
303                // iterator to player's queue status
304                QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2);
305
306                // remove him from time queue
307                itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2);
308
309                // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and report it)
310                if (itrPlayerStatus == m_QueuedPlayers[queue_id].end())
311                    continue;
312
313                //check if player is not already invited
314                if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID)
315                {
316                    itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID();
317                    itrPlayerStatus->second.InviteTime = getMSTime();
318                    itrPlayerStatus->second.LastInviteTime = getMSTime();
319
320                    if(itrPlayerStatus->second.Team == ALLIANCE)
321                        --m_QueuedPlayers[queue_id].Alliance;
322                    else
323                        --m_QueuedPlayers[queue_id].Horde;
324
325                    sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID());
326
327                    WorldPacket data;
328                    uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId);
329                    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);
330                    plr->GetSession()->SendPacket(&data);
331                }
332            }
333            else
334                ++itr2;
335        }
336        bg2->StartBattleGround();
337    }
338}
339
340/*********************************************************/
341/***            BATTLEGROUND QUEUE EVENTS              ***/
342/*********************************************************/
343
344bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 p_time)
345{
346    Player* plr = objmgr.GetPlayer( m_PlayerGuid );
347
348    // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
349    if (!plr)
350        return true;
351
352    // Player can be in another BG queue and must be removed in normal way in any case
353    // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG)
354    // if (plr->GetBattleGroundId() > 0)
355    //    return true;
356
357    BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID);
358    if (!bg)
359        return true;
360
361    uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID());
362    if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)         // player is in queue
363    {
364        // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems
365        BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()];
366        BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid);
367        if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
368        {
369            WorldPacket data;
370            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0);
371            plr->GetSession()->SendPacket(&data);
372        }
373    }
374    return true;                                            //event will be deleted
375}
376
377void BGQueueInviteEvent::Abort(uint64 /*e_time*/)
378{
379    //this should not be called
380    sLog.outError("Battleground invite event ABORTED!");
381}
382
383bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
384{
385    Player* plr = objmgr.GetPlayer( m_PlayerGuid );
386    if (!plr)
387        // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
388        return true;
389
390    // Player can be in another BG queue and must be removed in normal way in any case
391    //if (plr->InBattleGround())
392    //    // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG)
393    //    return true;
394
395    BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID);
396    if (!bg)
397        return true;
398
399    uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID());
400    if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)         // player is in queue (base at player data
401    {
402        // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems
403        BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()];
404        BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid);
405        if (qItr!=qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
406        {
407            plr->RemoveBattleGroundQueueId(bg->GetTypeID());
408            sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true);
409            sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType());
410
411            WorldPacket data;
412            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
413            plr->GetSession()->SendPacket(&data);
414        }
415    }
416
417    //event will be deleted
418    return true;
419}
420
421void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
422{
423    //this should not be called
424    sLog.outError("Battleground remove event ABORTED!");
425}
426
427/*********************************************************/
428/***            BATTLEGROUND MANAGER                   ***/
429/*********************************************************/
430
431BattleGroundMgr::BattleGroundMgr()
432{
433    m_BattleGrounds.clear();
434}
435
436BattleGroundMgr::~BattleGroundMgr()
437{
438    for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr)
439        delete itr->second;
440    m_BattleGrounds.clear();
441}
442
443void BattleGroundMgr::Update(time_t diff)
444{
445    for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr)
446        itr->second->Update(diff);
447}
448
449void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2)
450{
451    // we can be in 3 queues in same time...
452    if(StatusID == 0)
453    {
454        data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3);
455        *data << uint32(QueueSlot);                         // queue id (0...2)
456        *data << uint64(0);
457        return;
458    }
459
460    data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4));
461    *data << uint32(QueueSlot);                             // queue id (0...2) - player can be in 3 queues in time
462    // uint64 in client
463    *data << uint64( uint64(bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) );
464    *data << uint32(0);                                     // unknown
465    // alliance/horde for BG and skirmish/rated for Arenas
466    *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team));
467    *data << uint32(StatusID);                              // status
468    switch(StatusID)
469    {
470        case STATUS_WAIT_QUEUE:                             // status_in_queue
471            *data << uint32(Time1);                         // average wait time, milliseconds
472            *data << uint32(Time2);                         // time in queue, updated every minute?
473            break;
474        case STATUS_WAIT_JOIN:                              // status_invite
475            *data << uint32(bg->GetMapId());                // map id
476            *data << uint32(Time1);                         // time to remove from queue, milliseconds
477            break;
478        case STATUS_IN_PROGRESS:                            // status_in_progress
479            *data << uint32(bg->GetMapId());                // map id
480            *data << uint32(Time1);                         // 0 at bg start, 120000 after bg end, time to bg auto leave, milliseconds
481            *data << uint32(Time2);                         // time from bg start, milliseconds
482            *data << uint8(0x1);                            // unk sometimes 0x0!
483            break;
484        default:
485            sLog.outError("Unknown BG status!");
486            break;
487    }
488}
489
490void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
491{
492    uint8 type = (bg->isArena() ? 1 : 0);
493                                                            // last check on 2.4.1
494    data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));
495    *data << uint8(type);                                   // seems to be type (battleground=0/arena=1)
496    if(type)                                                // arena
497    {
498        for(uint8 i = 0; i < 2; i++)
499        {
500            *data << uint32(3000+1+i);                      // rating change: showed value - 3000
501            *data << uint32(0);                             // 2.4.0, has some to do with rating change...
502            *data << uint8(0);                              // some unknown string
503        }
504    }
505
506    if(bg->GetWinner() == 2)
507    {
508        *data << uint8(0);                                  // bg in progress
509    }
510    else
511    {
512        *data << uint8(1);                                  // bg ended
513        *data << uint8(bg->GetWinner());                    // who win
514    }
515
516    *data << (int32)(bg->GetPlayerScoresSize());
517
518    for(std::map<uint64, BattleGroundScore*>::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr)
519    {
520        *data << (uint64)itr->first;
521        *data << (int32)itr->second->KillingBlows;
522        if(type)
523        {
524            // this value is team (green/gold)?
525            // that part probably wrong
526            Player *plr = objmgr.GetPlayer(itr->first);
527            if(plr)
528            {
529                if(plr->GetTeam() == HORDE)
530                    *data << uint8(0);
531                else if(plr->GetTeam() == ALLIANCE)
532                    *data << uint8(1);
533                else
534                    *data << uint8(0);
535            }
536            else
537                *data << uint8(0);
538        }
539        else
540        {
541            *data << (int32)itr->second->HonorableKills;
542            *data << (int32)itr->second->Deaths;
543            *data << (int32)itr->second->BonusHonor;        // bonus honor
544        }
545        *data << (int32)itr->second->DamageDone;            // damage done
546        *data << (int32)itr->second->HealingDone;           // healing done
547        switch(bg->GetTypeID())                             // battleground specific things
548        {
549            case BATTLEGROUND_AV:
550                *data << (uint32)0x00000005;                // count of next fields
551                *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted;  // GraveyardsAssaulted
552                *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsDefended;   // GraveyardsDefended
553                *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersAssaulted;      // TowersAssaulted
554                *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersDefended;       // TowersDefended
555                *data << (uint32)((BattleGroundAVScore*)itr->second)->MinesCaptured;        // MinesCaptured
556                break;
557            case BATTLEGROUND_WS:
558                *data << (uint32)0x00000002;                // count of next fields
559                *data << (uint32)((BattleGroundWGScore*)itr->second)->FlagCaptures;         // flag captures
560                *data << (uint32)((BattleGroundWGScore*)itr->second)->FlagReturns;          // flag returns
561                break;
562            case BATTLEGROUND_AB:
563                *data << (uint32)0x00000002;                // count of next fields
564                *data << (uint32)((BattleGroundABScore*)itr->second)->BasesAssaulted;       // bases asssulted
565                *data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended;        // bases defended
566                break;
567            case BATTLEGROUND_EY:
568                *data << (uint32)0x00000001;                 // count of next fields
569                *data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures;         // flag captures
570                break;
571            case BATTLEGROUND_NA:
572            case BATTLEGROUND_BE:
573            case BATTLEGROUND_AA:
574            case BATTLEGROUND_RL:
575                *data << (int32)0;                          // 0
576                break;
577            default:
578                sLog.outDebug("Unhandled MSG_PVP_LOG_DATA for BG id %u", bg->GetTypeID());
579                *data << (int32)0;
580                break;
581        }
582    }
583}
584
585void BattleGroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId)
586{
587    /*bgTypeId is:
588    0 - Your group has joined a battleground queue, but you are not eligible
589    1 - Your group has joined the queue for AV
590    2 - Your group has joined the queue for WS
591    3 - Your group has joined the queue for AB
592    4 - Your group has joined the queue for NA
593    5 - Your group has joined the queue for BE Arena
594    6 - Your group has joined the queue for All Arenas
595    7 - Your group has joined the queue for EotS*/
596    data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
597    *data << uint32(bgTypeId);
598}
599
600void BattleGroundMgr::BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value)
601{
602    data->Initialize(SMSG_UPDATE_WORLD_STATE, 4+4);
603    *data << uint32(field);
604    *data << uint32(value);
605}
606
607void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid)
608{
609    data->Initialize(SMSG_PLAY_SOUND, 4);
610    *data << uint32(soundid);
611}
612
613void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr)
614{
615    data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8);
616    *data << uint64(plr->GetGUID());
617}
618
619void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr)
620{
621    data->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED, 8);
622    *data << uint64(plr->GetGUID());
623}
624
625void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID)
626{
627    // set invited player counters:
628    BattleGround* bg = this->GetBattleGround(bgInstanceGUID);
629    if(!bg)
630        return;
631
632    bg->IncreaseInvitedCount(plr->GetTeam());
633    plr->SetInviteForBattleGroundType(bg->GetTypeID());
634    // create invite events:
635    //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
636    BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID);
637    plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2));
638    BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam());
639    plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
640}
641
642uint32 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)
643{
644    // Create the BG
645    BattleGround *bg = NULL;
646
647    switch(bgTypeId)
648    {
649        case BATTLEGROUND_AV: bg = new BattleGroundAV; break;
650        case BATTLEGROUND_WS: bg = new BattleGroundWS; break;
651        case BATTLEGROUND_AB: bg = new BattleGroundAB; break;
652        case BATTLEGROUND_NA: bg = new BattleGroundNA; break;
653        case BATTLEGROUND_BE: bg = new BattleGroundBE; break;
654        case BATTLEGROUND_AA: bg = new BattleGroundAA; break;
655        case BATTLEGROUND_EY: bg = new BattleGroundEY; break;
656        case BATTLEGROUND_RL: bg = new BattleGroundRL; break;
657        default:bg = new BattleGround;   break;             // placeholder for non implemented BG
658    }
659
660    bg->SetMapId(MapID);
661    bg->Reset();
662    if(!bg->SetupBattleGround())
663    {
664        delete bg;
665        return 0;
666    }
667
668    BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId);
669    //in previous method is checked if exists entry in sBattlemasterListStore, so no check needed
670    if (bl)
671    {
672        bg->SetArenaorBGType(bl->type == TYPE_ARENA);
673    }
674
675    bg->SetTypeID(bgTypeId);
676    bg->SetInstanceID(bgTypeId);                            // temporary
677    bg->SetMinPlayersPerTeam(MinPlayersPerTeam);
678    bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam);
679    bg->SetMinPlayers(MinPlayersPerTeam*2);
680    bg->SetMaxPlayers(MaxPlayersPerTeam*2);
681    bg->SetName(BattleGroundName);
682    bg->SetTeamStartLoc(ALLIANCE, Team1StartLocX, Team1StartLocY, Team1StartLocZ, Team1StartLocO);
683    bg->SetTeamStartLoc(HORDE,    Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO);
684    bg->SetLevelRange(LevelMin, LevelMax);
685    //add BaggleGround instance to FreeSlotQueue
686    bg->AddToBGFreeSlotQueue();
687
688    AddBattleGround(bg->GetInstanceID(), bg);
689    //sLog.outDetail("BattleGroundMgr: Created new battleground: %u %s (Map %u, %u players per team, Levels %u-%u)", bg_TypeID, bg->m_Name, bg->m_MapId, bg->m_MaxPlayersPerTeam, bg->m_LevelMin, bg->m_LevelMax);
690    return bg->GetInstanceID();
691}
692
693void BattleGroundMgr::CreateInitialBattleGrounds()
694{
695    float AStartLoc[4];
696    float HStartLoc[4];
697    uint32 MaxPlayersPerTeam, MinPlayersPerTeam, MinLvl, MaxLvl, start1, start2;
698    BattlemasterListEntry const *bl;
699    WorldSafeLocsEntry const *start;
700
701    uint32 count = 0;
702
703    //                                                0   1                 2                 3      4      5                6              7             8
704    QueryResult *result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam,MaxPlayersPerTeam,MinLvl,MaxLvl,AllianceStartLoc,AllianceStartO,HordeStartLoc,HordeStartO FROM battleground_template");
705
706    if(!result)
707    {
708        barGoLink bar(1);
709
710        bar.step();
711
712        sLog.outString();
713        sLog.outErrorDb(">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
714        return;
715    }
716
717    barGoLink bar(result->GetRowCount());
718
719    do
720    {
721        Field *fields = result->Fetch();
722        bar.step();
723
724        uint32 bgTypeID = fields[0].GetUInt32();
725
726        // can be overwrited by values from DB
727        bl = sBattlemasterListStore.LookupEntry(bgTypeID);
728        if(!bl)
729        {
730            sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.",bgTypeID);
731            continue;
732        }
733
734        MaxPlayersPerTeam = bl->maxplayersperteam;
735        MinPlayersPerTeam = bl->maxplayersperteam/2;
736        MinLvl = bl->minlvl;
737        MaxLvl = bl->maxlvl;
738
739        if(fields[1].GetUInt32())
740            MinPlayersPerTeam = fields[1].GetUInt32();
741
742        if(fields[2].GetUInt32())
743            MaxPlayersPerTeam = fields[2].GetUInt32();
744
745        if(fields[3].GetUInt32())
746            MinLvl = fields[3].GetUInt32();
747
748        if(fields[4].GetUInt32())
749            MaxLvl = fields[4].GetUInt32();
750
751        start1 = fields[5].GetUInt32();
752
753        start = sWorldSafeLocsStore.LookupEntry(start1);
754        if(start)
755        {
756            AStartLoc[0] = start->x;
757            AStartLoc[1] = start->y;
758            AStartLoc[2] = start->z;
759            AStartLoc[3] = fields[6].GetFloat();
760        }
761        else if(bgTypeID == BATTLEGROUND_AA)
762        {
763            AStartLoc[0] = 0;
764            AStartLoc[1] = 0;
765            AStartLoc[2] = 0;
766            AStartLoc[3] = fields[6].GetFloat();
767        }
768        else
769        {
770            sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.",bgTypeID,start1);
771            continue;
772        }
773
774        start2 = fields[7].GetUInt32();
775
776        start = sWorldSafeLocsStore.LookupEntry(start2);
777        if(start)
778        {
779            HStartLoc[0] = start->x;
780            HStartLoc[1] = start->y;
781            HStartLoc[2] = start->z;
782            HStartLoc[3] = fields[8].GetFloat();
783        }
784        else if(bgTypeID == BATTLEGROUND_AA)
785        {
786            HStartLoc[0] = 0;
787            HStartLoc[1] = 0;
788            HStartLoc[2] = 0;
789            HStartLoc[3] = fields[8].GetFloat();
790        }
791        else
792        {
793            sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.",bgTypeID,start2);
794            continue;
795        }
796
797        //sLog.outDetail("Creating battleground %s, %u-%u", bl->name[sWorld.GetDBClang()], MinLvl, MaxLvl);
798        if(!CreateBattleGround(bgTypeID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, bl->name[sWorld.GetDefaultDbcLocale()], bl->mapid[0], AStartLoc[0], AStartLoc[1], AStartLoc[2], AStartLoc[3], HStartLoc[0], HStartLoc[1], HStartLoc[2], HStartLoc[3]))
799            continue;
800
801        ++count;
802    } while (result->NextRow());
803
804    delete result;
805
806    sLog.outString();
807    sLog.outString( ">> Loaded %u battlegrounds", count );
808}
809
810void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId)
811{
812    uint32 PlayerLevel = 10;
813
814    if(plr)
815        PlayerLevel = plr->getLevel();
816
817    data->Initialize(SMSG_BATTLEFIELD_LIST);
818    *data << uint64(guid);                                  // battlemaster guid
819    *data << uint32(bgTypeId);                              // battleground id
820    if(bgTypeId == BATTLEGROUND_AA)                         // arena
821    {
822        *data << uint8(5);                                  // unk
823        *data << uint32(0);                                 // unk
824    }
825    else                                                    // battleground
826    {
827        *data << uint8(0x00);                               // unk
828
829        size_t count_pos = data->wpos();
830        uint32 count = 0;
831        *data << uint32(0x00);                              // number of bg instances
832
833        for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr)
834        {
835            if(itr->second->GetTypeID() == bgTypeId && (PlayerLevel >= itr->second->GetMinLevel()) && (PlayerLevel <= itr->second->GetMaxLevel()))
836            {
837                *data << uint32(itr->second->GetInstanceID());
838                ++count;
839            }
840        }
841        data->put<uint32>( count_pos , count);
842    }
843}
844
845void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId)
846{
847    BattleGround *bg = GetBattleGround(bgTypeId);
848    if(bg)
849    {
850        uint32 mapid = bg->GetMapId();
851        float x, y, z, O;
852        bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O);
853
854        sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O);
855        pl->TeleportTo(mapid, x, y, z, O);
856    }
857}
858
859void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid)
860{
861    WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
862    uint32 time_ = 30000 - bg->GetLastResurrectTime();      // resurrect every 30 seconds
863    if(time_ == uint32(-1))
864        time_ = 0;
865    data << guid << time_;
866    pl->GetSession()->SendPacket(&data);
867}
Note: See TracBrowser for help on using the browser.