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

Revision 44, 27.9 kB (checked in by yumileroy, 17 years ago)

[svn] * Merge Temp dev SVN with Assembla.
* Changes include:

  • Implementation of w12x's Outdoor PvP and Game Event Systems.
  • Temporary removal of IRC Chat Bot (until infinite loop when disabled is fixed).
  • All mangos -> trinity (to convert your mangos_string table, please run mangos_string_to_trinity_string.sql).
  • Improved Config cleanup.
  • And many more changes.

Original author: Seline
Date: 2008-10-14 11:57:03-05:00

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