root/trunk/src/game/BattleGroundAB.cpp @ 34

Revision 34, 27.8 kB (checked in by yumileroy, 17 years ago)

[svn] * Removing useless data accidentally committed.
* Applying ImpConfig? patch.
* Note: QUEUE_FOR_GM currently disabled as it's not compatible with the ACE patch. Anyone care to rewrite it?
* Note2: This is untested - I may have done some mistakes here and there. Will try to compile now.

Original author: XTZGZoReX
Date: 2008-10-10 13:37:21-05:00

Line 
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 "Object.h"
20#include "Player.h"
21#include "BattleGround.h"
22#include "BattleGroundAB.h"
23#include "Creature.h"
24#include "Chat.h"
25#include "ObjectMgr.h"
26#include "MapManager.h"
27#include "Language.h"
28#include "World.h"
29#include "Util.h"
30
31BattleGroundAB::BattleGroundAB()
32{
33    m_BuffChange = true;
34    m_BgObjects.resize(BG_AB_OBJECT_MAX);
35    m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT);
36}
37
38BattleGroundAB::~BattleGroundAB()
39{
40}
41
42void BattleGroundAB::Update(time_t diff)
43{
44    BattleGround::Update(diff);
45
46    if( GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize() )
47    {
48        ModifyStartDelayTime(diff);
49
50        if( !(m_Events & 0x01) )
51        {
52            m_Events |= 0x01;
53
54            // setup here, only when at least one player has ported to the map
55            if(!SetupBattleGround())
56            {
57                EndNow();
58                return;
59            }
60
61            sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ...");
62
63            // despawn banners, auras and buffs
64            for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj)
65                SpawnBGObject(obj, RESPAWN_ONE_DAY);
66            for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
67                SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
68
69            // Starting doors
70            SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
71            SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
72            DoorClose(BG_AB_OBJECT_GATE_A);
73            DoorClose(BG_AB_OBJECT_GATE_H);
74
75            // Starting base spirit guides
76            _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE);
77            _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE);
78
79            SetStartDelayTime(START_DELAY0);
80        }
81        // After 1 minute, warning is signalled
82        else if( GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04) )
83        {
84            m_Events |= 0x04;
85            SendMessageToAll(GetMangosString(LANG_BG_AB_ONEMINTOSTART));
86        }
87        // After 1,5 minute, warning is signalled
88        else if( GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08) )
89        {
90            m_Events |= 0x08;
91            SendMessageToAll(GetMangosString(LANG_BG_AB_HALFMINTOSTART));
92        }
93        // After 2 minutes, gates OPEN ! x)
94        else if( GetStartDelayTime() < 0 && !(m_Events & 0x10) )
95        {
96            m_Events |= 0x10;
97            SendMessageToAll(GetMangosString(LANG_BG_AB_STARTED));
98
99            // spawn neutral banners
100            for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i)
101                SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
102            for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
103            {
104                //randomly select buff to spawn
105                uint8 buff = urand(0, 2);
106                SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY);
107            }
108            DoorOpen(BG_AB_OBJECT_GATE_A);
109            DoorOpen(BG_AB_OBJECT_GATE_H);
110
111            if(sWorld.getConfig(CONFIG_BG_START_MUSIC))
112                        {
113                                PlaySoundToAll(SOUND_BG_START);
114                                PlaySoundToAll(SOUND_BG_START_L70ETC); //MUSIC
115                        }
116                        else
117                                PlaySoundToAll(SOUND_BG_START);
118            SetStatus(STATUS_IN_PROGRESS);
119
120            for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
121                if(Player* plr = objmgr.GetPlayer(itr->first))
122                    plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
123        }
124
125    }
126    else if( GetStatus() == STATUS_IN_PROGRESS )
127    {
128        int team_points[2] = { 0, 0 };
129
130        for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
131        {
132            // 3 sec delay to spawn new banner instead previous despawned one
133            if( m_BannerTimers[node].timer )
134            {
135                if( m_BannerTimers[node].timer > diff )
136                    m_BannerTimers[node].timer -= diff;
137                else
138                {
139                    m_BannerTimers[node].timer = 0;
140                    _CreateBanner(node, m_BannerTimers[node].type, m_BannerTimers[node].teamIndex, false);
141                }
142            }
143
144            // 1-minute to occupy a node from contested state
145            if( m_NodeTimers[node] )
146            {
147                if( m_NodeTimers[node] > diff )
148                    m_NodeTimers[node] -= diff;
149                else
150                {
151                    m_NodeTimers[node] = 0;
152                    // Change from contested to occupied !
153                    uint8 teamIndex = m_Nodes[node]-1;
154                    m_prevNodes[node] = m_Nodes[node];
155                    m_Nodes[node] += 2;
156                    // burn current contested banner
157                    _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex);
158                    // create new occupied banner
159                    _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true);
160                    _SendNodeUpdate(node);
161                    _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
162                    // Message to chatlog
163                    char buf[256];
164                    uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
165                    sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node));
166                    WorldPacket data;
167                    ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL);
168                    SendPacketToAll(&data);
169                    PlaySoundToAll((teamIndex == 0) ? SOUND_NODE_CAPTURED_ALLIANCE : SOUND_NODE_CAPTURED_HORDE);
170                }
171            }
172
173            for (int team = 0; team < 2; ++team)
174                if( m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED )
175                    ++team_points[team];
176        }
177
178        // Accumulate points
179        for (int team = 0; team < 2; ++team)
180        {
181            int points = team_points[team];
182            if( !points )
183                continue;
184            m_lastTick[team] += diff;
185            if( m_lastTick[team] > BG_AB_TickIntervals[points] )
186            {
187                m_lastTick[team] -= BG_AB_TickIntervals[points];
188                m_TeamScores[team] += BG_AB_TickPoints[points];
189                m_HonorScoreTics[team] += BG_AB_TickPoints[points];
190                m_ReputationScoreTics[team] += BG_AB_TickPoints[points];
191                if( m_ReputationScoreTics[team] >= 200 )
192                {
193                    (team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
194                    m_ReputationScoreTics[team] -= 200;
195                }
196                if( m_HonorScoreTics[team] >= BG_HONOR_SCORE_TICKS )
197                {
198                    (team == BG_TEAM_ALLIANCE) ? RewardHonorToTeam(20, ALLIANCE) : RewardHonorToTeam(20, HORDE);
199                    m_HonorScoreTics[team] -= BG_HONOR_SCORE_TICKS;
200                }
201                if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 )
202                {
203                    if( team == BG_TEAM_ALLIANCE )
204                        SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY));
205                    else
206                        SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY));
207                    PlaySoundToAll(SOUND_NEAR_VICTORY);
208                    m_IsInformedNearVictory = true;
209                }
210
211                if( m_TeamScores[team] > 2000 )
212                    m_TeamScores[team] = 2000;
213                if( team == BG_TEAM_ALLIANCE )
214                    UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]);
215                if( team == BG_TEAM_HORDE )
216                    UpdateWorldState(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[team]);
217            }
218        }
219
220        // Test win condition
221        if( m_TeamScores[BG_TEAM_ALLIANCE] >= 2000 )
222            EndBattleGround(ALLIANCE);
223        if( m_TeamScores[BG_TEAM_HORDE] >= 2000 )
224            EndBattleGround(HORDE);
225    }
226}
227
228void BattleGroundAB::AddPlayer(Player *plr)
229{
230    BattleGround::AddPlayer(plr);
231    //create score and add it to map, default values are set in the constructor
232    BattleGroundABScore* sc = new BattleGroundABScore;
233
234    m_PlayerScores[plr->GetGUID()] = sc;
235}
236
237void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
238{
239
240}
241
242void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger)
243{
244    if( GetStatus() != STATUS_IN_PROGRESS )
245        return;
246
247    switch(Trigger)
248    {
249        case 3948:                                          // Arathi Basin Alliance Exit.
250            if( Source->GetTeam() != ALLIANCE )
251                Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
252            else
253                Source->LeaveBattleground();
254            break;
255        case 3949:                                          // Arathi Basin Horde Exit.
256            if( Source->GetTeam() != HORDE )
257                Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
258            else
259                Source->LeaveBattleground();
260            break;
261        case 3866:                                          // Stables
262        case 3869:                                          // Gold Mine
263        case 3867:                                          // Farm
264        case 3868:                                          // Lumber Mill
265        case 3870:                                          // Black Smith
266        case 4020:                                          // Unk1
267        case 4021:                                          // Unk2
268            //break;
269        default:
270            //sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);
271            //Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
272            break;
273    }
274}
275
276/*  type: 0-neutral, 1-contested, 3-occupied
277    teamIndex: 0-ally, 1-horde                        */
278void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay)
279{
280    // Just put it into the queue
281    if( delay )
282    {
283        m_BannerTimers[node].timer = 2000;
284        m_BannerTimers[node].type = type;
285        m_BannerTimers[node].teamIndex = teamIndex;
286        return;
287    }
288
289    uint8 obj = node*8 + type + teamIndex;
290
291    SpawnBGObject(obj, RESPAWN_IMMEDIATELY);
292
293    // handle aura with banner
294    if( !type )
295        return;
296    obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7);
297    SpawnBGObject(obj, RESPAWN_IMMEDIATELY);
298}
299
300void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex)
301{
302    uint8 obj = node*8 + type + teamIndex;
303    SpawnBGObject(obj, RESPAWN_ONE_DAY);
304
305    // handle aura with banner
306    if( !type )
307        return;
308    obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7);
309    SpawnBGObject(obj, RESPAWN_ONE_DAY);
310}
311
312const char* BattleGroundAB::_GetNodeName(uint8 node)
313{
314    switch (node)
315    {
316        case BG_AB_NODE_STABLES:
317            return GetMangosString(LANG_BG_AB_NODE_STABLES);
318        case BG_AB_NODE_BLACKSMITH:
319            return GetMangosString(LANG_BG_AB_NODE_BLACKSMITH);
320        case BG_AB_NODE_FARM:
321            return GetMangosString(LANG_BG_AB_NODE_FARM);
322        case BG_AB_NODE_LUMBER_MILL:
323            return GetMangosString(LANG_BG_AB_NODE_LUMBER_MILL);
324        case BG_AB_NODE_GOLD_MINE:
325            return GetMangosString(LANG_BG_AB_NODE_GOLD_MINE);
326        default:
327            ASSERT(0);
328    }
329    return "";
330}
331
332void BattleGroundAB::FillInitialWorldStates(WorldPacket& data)
333{
334    const uint8 plusArray[] = {0, 2, 3, 0, 1};
335
336    // Node icons
337    for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
338        data << uint32(BG_AB_OP_NODEICONS[node]) << uint32((m_Nodes[node]==0)?1:0);
339
340    // Node occupied states
341    for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
342        for (uint8 i = 1; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
343            data << uint32(BG_AB_OP_NODESTATES[node] + plusArray[i]) << uint32((m_Nodes[node]==i)?1:0);
344
345    // How many bases each team owns
346    uint8 ally = 0, horde = 0;
347    for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
348        if( m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED )
349            ++ally;
350        else if( m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED )
351            ++horde;
352
353    data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY)  << uint32(ally);
354    data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(horde);
355
356    // Team scores
357    data << uint32(BG_AB_OP_RESOURCES_MAX)      << uint32(BG_AB_MAX_TEAM_SCORE);
358    data << uint32(BG_AB_OP_RESOURCES_WARNING)  << uint32(BG_AB_WARNING_SCORE);
359    data << uint32(BG_AB_OP_RESOURCES_ALLY)     << uint32(m_TeamScores[BG_TEAM_ALLIANCE]);
360    data << uint32(BG_AB_OP_RESOURCES_HORDE)    << uint32(m_TeamScores[BG_TEAM_HORDE]);
361
362    // other unknown
363    data << uint32(0x745) << uint32(0x2);           // 37 1861 unk
364}
365
366void BattleGroundAB::_SendNodeUpdate(uint8 node)
367{
368    // Send node owner state update to refresh map icons on client
369    const uint8 plusArray[] = {0, 2, 3, 0, 1};
370
371    if( m_prevNodes[node] )
372        UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_prevNodes[node]], 0);
373    else
374        UpdateWorldState(BG_AB_OP_NODEICONS[node], 0);
375
376    UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_Nodes[node]], 1);
377
378    // How many bases each team owns
379    uint8 ally = 0, horde = 0;
380    for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
381        if( m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED )
382            ++ally;
383        else if( m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED )
384            ++horde;
385
386    UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, ally);
387    UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE, horde);
388}
389
390void BattleGroundAB::_NodeOccupied(uint8 node,Team team)
391{
392   if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) )
393        sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team);
394
395    uint8 capturedNodes = 0;
396    for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
397    {
398        if( m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i])
399            ++capturedNodes;
400    }
401    if(capturedNodes >= 5)
402        CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, team);
403    if(capturedNodes >= 4)
404        CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team);
405}
406
407void BattleGroundAB::_NodeDeOccupied(uint8 node)
408{
409    if( node >= BG_AB_DYNAMIC_NODES_COUNT)
410        return;
411
412    // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
413    std::vector<uint64> ghost_list = m_ReviveQueue[m_BgCreatures[node]];
414    if( !ghost_list.empty() )
415    {
416        WorldSafeLocsEntry const *ClosestGrave = NULL;
417        Player *plr;
418        for (std::vector<uint64>::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
419        {
420            plr = objmgr.GetPlayer(*ghost_list.begin());
421            if( !plr )
422                continue;
423            if( !ClosestGrave )
424                ClosestGrave = GetClosestGraveYard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetTeam());
425
426            plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation());
427        }
428    }
429
430     if( m_BgCreatures[node] )
431        DelCreature(node);
432
433    // buff object isn't despawned
434}
435
436/* Invoked if a player used a banner as a gameobject */
437void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/)
438{
439    if( GetStatus() != STATUS_IN_PROGRESS )
440        return;
441
442    uint8 node = BG_AB_NODE_STABLES;
443    GameObject* obj=HashMapHolder<GameObject>::Find(m_BgObjects[node*8+7]);
444    while ( (node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10))))
445    {
446        ++node;
447        obj=HashMapHolder<GameObject>::Find(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]);
448    }
449
450    if( node == BG_AB_DYNAMIC_NODES_COUNT)
451    {
452        // this means our player isn't close to any of banners - maybe cheater ??
453        return;
454    }
455
456    uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam());
457
458    // Message to chatlog
459    char buf[256];
460    uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
461
462    // Check if player really could use this banner, not cheated
463    if( !(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2) )
464        return;
465
466    source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
467    uint32 sound = 0;
468    // If node is neutral, change to contested
469    if( m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL )
470    {
471        UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1);
472        m_prevNodes[node] = m_Nodes[node];
473        m_Nodes[node] = teamIndex + 1;
474        // burn current neutral banner
475        _DelBanner(node, BG_AB_NODE_TYPE_NEUTRAL, 0);
476        // create new contested banner
477        _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true);
478        _SendNodeUpdate(node);
479        m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
480        sprintf(buf, GetMangosString(LANG_BG_AB_NODE_CLAIMED), _GetNodeName(node), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE));
481        sound = SOUND_NODE_CLAIMED;
482    }
483    // If node is contested
484    else if( (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED) )
485    {
486        // If last state is NOT occupied, change node to enemy-contested
487        if( m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED )
488        {
489            UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1);
490            m_prevNodes[node] = m_Nodes[node];
491            m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED;
492            // burn current contested banner
493            _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex);
494            // create new contested banner
495            _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true);
496            _SendNodeUpdate(node);
497            m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
498            sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node));
499        }
500        // If contested, change back to occupied
501        else
502        {
503            UpdatePlayerScore(source, SCORE_BASES_DEFENDED, 1);
504            m_prevNodes[node] = m_Nodes[node];
505            m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_OCCUPIED;
506            // burn current contested banner
507            _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex);
508            // create new occupied banner
509            _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true);
510            _SendNodeUpdate(node);
511            m_NodeTimers[node] = 0;
512            _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
513            sprintf(buf, GetMangosString(LANG_BG_AB_NODE_DEFENDED), _GetNodeName(node));
514        }
515        sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE;
516    }
517    // If node is occupied, change to enemy-contested
518    else
519    {
520        UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1);
521        m_prevNodes[node] = m_Nodes[node];
522        m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED;
523        // burn current occupied banner
524        _DelBanner(node, BG_AB_NODE_TYPE_OCCUPIED, !teamIndex);
525        // create new contested banner
526        _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true);
527        _SendNodeUpdate(node);
528        _NodeDeOccupied(node);
529        m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
530        sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node));
531        sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE;
532    }
533    WorldPacket data;
534    ChatHandler::FillMessageData(&data, source->GetSession(), type, LANG_UNIVERSAL, NULL, source->GetGUID(), buf, NULL);
535    SendPacketToAll(&data);
536    // If node is occupied again, send "X has taken the Y" msg.
537    if( m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED )
538    {
539        sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node));
540        ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL);
541        SendPacketToAll(&data);
542    }
543    PlaySoundToAll(sound);
544}
545
546bool BattleGroundAB::SetupBattleGround()
547{
548    for (int i = 0 ; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
549    {
550        if(    !AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
551            || !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i,BG_AB_OBJECTID_BANNER_CONT_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
552            || !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i,BG_AB_OBJECTID_BANNER_CONT_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
553            || !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i,BG_AB_OBJECTID_BANNER_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
554            || !AddObject(BG_AB_OBJECT_BANNER_HORDE + 8*i,BG_AB_OBJECTID_BANNER_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
555            || !AddObject(BG_AB_OBJECT_AURA_ALLY + 8*i,BG_AB_OBJECTID_AURA_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
556            || !AddObject(BG_AB_OBJECT_AURA_HORDE + 8*i,BG_AB_OBJECTID_AURA_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
557            || !AddObject(BG_AB_OBJECT_AURA_CONTESTED + 8*i,BG_AB_OBJECTID_AURA_C,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
558        )
559        {
560            sLog.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!");
561            return false;
562        }
563    }
564    if(    !AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY)
565        || !AddObject(BG_AB_OBJECT_GATE_H,BG_AB_OBJECTID_GATE_H,BG_AB_DoorPositions[1][0],BG_AB_DoorPositions[1][1],BG_AB_DoorPositions[1][2],BG_AB_DoorPositions[1][3],BG_AB_DoorPositions[1][4],BG_AB_DoorPositions[1][5],BG_AB_DoorPositions[1][6],BG_AB_DoorPositions[1][7],RESPAWN_IMMEDIATELY)
566        )
567    {
568        sLog.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!");
569        return false;
570    }
571    //buffs
572    for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
573    {
574        if(    !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
575            || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
576            || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
577            )
578            sLog.outErrorDb("BatteGroundAB: Failed to spawn buff object!");
579    }
580
581    return true;
582}
583
584void BattleGroundAB::ResetBGSubclass()
585{
586    m_TeamScores[BG_TEAM_ALLIANCE]          = 0;
587    m_TeamScores[BG_TEAM_HORDE]             = 0;
588    m_lastTick[BG_TEAM_ALLIANCE]            = 0;
589    m_lastTick[BG_TEAM_HORDE]               = 0;
590    m_HonorScoreTics[BG_TEAM_ALLIANCE]      = 0;
591    m_HonorScoreTics[BG_TEAM_HORDE]         = 0;
592    m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0;
593    m_ReputationScoreTics[BG_TEAM_HORDE]    = 0;
594    m_IsInformedNearVictory                 = false;
595    for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
596    {
597        m_Nodes[i] = 0;
598        m_prevNodes[i] = 0;
599        m_NodeTimers[i] = 0;
600        m_BannerTimers[i].timer = 0;
601    }
602
603    for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT; ++i)
604        if(m_BgCreatures[i])
605            DelCreature(i);
606}
607
608WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(float x, float y, float /*z*/, uint32 team)
609{
610    uint8 teamIndex = GetTeamIndexByTeamId(team);
611
612    // Is there any occupied node for this team?
613    std::vector<uint8> nodes;
614    for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
615        if( m_Nodes[i] == teamIndex + 3 )
616            nodes.push_back(i);
617
618    WorldSafeLocsEntry const* good_entry = NULL;
619    // If so, select the closest node to place ghost on
620    if( !nodes.empty() )
621    {
622        float mindist = 999999.0f;
623        for (uint8 i = 0; i < nodes.size(); ++i)
624        {
625            WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[nodes[i]] );
626            if( !entry )
627                continue;
628            float dist = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y);
629            if( mindist > dist )
630            {
631                mindist = dist;
632                good_entry = entry;
633            }
634        }
635        nodes.clear();
636    }
637    // If not, place ghost on starting location
638    if( !good_entry )
639        good_entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[teamIndex+5] );
640
641    return good_entry;
642}
643
644void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
645{
646    std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
647
648    if( itr == m_PlayerScores.end() )                         // player not found...
649        return;
650
651    switch(type)
652    {
653        case SCORE_BASES_ASSAULTED:
654            ((BattleGroundABScore*)itr->second)->BasesAssaulted += value;
655            break;
656        case SCORE_BASES_DEFENDED:
657            ((BattleGroundABScore*)itr->second)->BasesDefended += value;
658            break;
659        default:
660            BattleGround::UpdatePlayerScore(Source,type,value);
661            break;
662    }
663}
Note: See TracBrowser for help on using the browser.