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

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

[svn] * Proper SVN structure

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