2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
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.
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.
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
21 #include "BattleGround.h"
22 #include "BattleGroundAB.h"
25 #include "ObjectMgr.h"
26 #include "MapManager.h"
29 #include "WorldPacket.h"
31 BattleGroundAB::BattleGroundAB()
34 m_BgObjects
.resize(BG_AB_OBJECT_MAX
);
35 m_BgCreatures
.resize(BG_AB_ALL_NODES_COUNT
);
38 BattleGroundAB::~BattleGroundAB()
42 void BattleGroundAB::Update(uint32 diff
)
44 BattleGround::Update(diff
);
46 if( GetStatus() == STATUS_WAIT_JOIN
&& GetPlayersSize() )
48 ModifyStartDelayTime(diff
);
50 if( !(m_Events
& 0x01) )
54 // setup here, only when at least one player has ported to the map
55 if(!SetupBattleGround())
61 sLog
.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ...");
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
);
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
);
75 // Starting base spirit guides
76 _NodeOccupied(BG_AB_SPIRIT_ALIANCE
,ALLIANCE
);
77 _NodeOccupied(BG_AB_SPIRIT_HORDE
,HORDE
);
79 SetStartDelayTime(START_DELAY0
);
81 // After 1 minute, warning is signalled
82 else if( GetStartDelayTime() <= START_DELAY1
&& !(m_Events
& 0x04) )
85 SendMessageToAll(GetMangosString(LANG_BG_AB_ONEMINTOSTART
));
87 // After 1,5 minute, warning is signalled
88 else if( GetStartDelayTime() <= START_DELAY2
&& !(m_Events
& 0x08) )
91 SendMessageToAll(GetMangosString(LANG_BG_AB_HALFMINTOSTART
));
93 // After 2 minutes, gates OPEN ! x)
94 else if( GetStartDelayTime() < 0 && !(m_Events
& 0x10) )
97 SendMessageToAll(GetMangosString(LANG_BG_AB_STARTED
));
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
)
104 //randomly select buff to spawn
105 uint8 buff
= urand(0, 2);
106 SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES
+ buff
+ i
* 3, RESPAWN_IMMEDIATELY
);
108 DoorOpen(BG_AB_OBJECT_GATE_A
);
109 DoorOpen(BG_AB_OBJECT_GATE_H
);
111 PlaySoundToAll(SOUND_BG_START
);
112 SetStatus(STATUS_IN_PROGRESS
);
114 for(BattleGroundPlayerMap::const_iterator itr
= GetPlayers().begin(); itr
!= GetPlayers().end(); ++itr
)
115 if(Player
* plr
= objmgr
.GetPlayer(itr
->first
))
116 plr
->RemoveAurasDueToSpell(SPELL_PREPARATION
);
120 else if( GetStatus() == STATUS_IN_PROGRESS
)
122 int team_points
[2] = { 0, 0 };
124 for (int node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
126 // 3 sec delay to spawn new banner instead previous despawned one
127 if( m_BannerTimers
[node
].timer
)
129 if( m_BannerTimers
[node
].timer
> diff
)
130 m_BannerTimers
[node
].timer
-= diff
;
133 m_BannerTimers
[node
].timer
= 0;
134 _CreateBanner(node
, m_BannerTimers
[node
].type
, m_BannerTimers
[node
].teamIndex
, false);
138 // 1-minute to occupy a node from contested state
139 if( m_NodeTimers
[node
] )
141 if( m_NodeTimers
[node
] > diff
)
142 m_NodeTimers
[node
] -= diff
;
145 m_NodeTimers
[node
] = 0;
146 // Change from contested to occupied !
147 uint8 teamIndex
= m_Nodes
[node
]-1;
148 m_prevNodes
[node
] = m_Nodes
[node
];
150 // burn current contested banner
151 _DelBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
);
152 // create new occupied banner
153 _CreateBanner(node
, BG_AB_NODE_TYPE_OCCUPIED
, teamIndex
, true);
154 _SendNodeUpdate(node
);
155 _NodeOccupied(node
,(teamIndex
== 0) ? ALLIANCE
:HORDE
);
156 // Message to chatlog
158 uint8 type
= (teamIndex
== 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE
: CHAT_MSG_BG_SYSTEM_HORDE
;
159 sprintf(buf
, GetMangosString(LANG_BG_AB_NODE_TAKEN
), (teamIndex
== 0) ? GetMangosString(LANG_BG_AB_ALLY
) : GetMangosString(LANG_BG_AB_HORDE
), _GetNodeName(node
));
161 ChatHandler::FillMessageData(&data
, NULL
, type
, LANG_UNIVERSAL
, NULL
, 0, buf
, NULL
);
162 SendPacketToAll(&data
);
163 PlaySoundToAll((teamIndex
== 0) ? SOUND_NODE_CAPTURED_ALLIANCE
: SOUND_NODE_CAPTURED_HORDE
);
167 for (int team
= 0; team
< 2; ++team
)
168 if( m_Nodes
[node
] == team
+ BG_AB_NODE_TYPE_OCCUPIED
)
173 for (int team
= 0; team
< 2; ++team
)
175 int points
= team_points
[team
];
178 m_lastTick
[team
] += diff
;
179 if( m_lastTick
[team
] > BG_AB_TickIntervals
[points
] )
181 m_lastTick
[team
] -= BG_AB_TickIntervals
[points
];
182 m_TeamScores
[team
] += BG_AB_TickPoints
[points
];
183 m_HonorScoreTics
[team
] += BG_AB_TickPoints
[points
];
184 m_ReputationScoreTics
[team
] += BG_AB_TickPoints
[points
];
185 if( m_ReputationScoreTics
[team
] >= 200 )
187 (team
== BG_TEAM_ALLIANCE
) ? RewardReputationToTeam(509, 10, ALLIANCE
) : RewardReputationToTeam(510, 10, HORDE
);
188 m_ReputationScoreTics
[team
] -= 200;
190 if( m_HonorScoreTics
[team
] >= BG_HONOR_SCORE_TICKS
)
192 (team
== BG_TEAM_ALLIANCE
) ? RewardHonorToTeam(20, ALLIANCE
) : RewardHonorToTeam(20, HORDE
);
193 m_HonorScoreTics
[team
] -= BG_HONOR_SCORE_TICKS
;
195 if( !m_IsInformedNearVictory
&& m_TeamScores
[team
] > 1800 )
197 if( team
== BG_TEAM_ALLIANCE
)
198 SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY
));
200 SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY
));
201 PlaySoundToAll(SOUND_NEAR_VICTORY
);
202 m_IsInformedNearVictory
= true;
205 if( m_TeamScores
[team
] > 2000 )
206 m_TeamScores
[team
] = 2000;
207 if( team
== BG_TEAM_ALLIANCE
)
208 UpdateWorldState(BG_AB_OP_RESOURCES_ALLY
, m_TeamScores
[team
]);
209 if( team
== BG_TEAM_HORDE
)
210 UpdateWorldState(BG_AB_OP_RESOURCES_HORDE
, m_TeamScores
[team
]);
214 // Test win condition
215 if( m_TeamScores
[BG_TEAM_ALLIANCE
] >= 2000 )
216 EndBattleGround(ALLIANCE
);
217 if( m_TeamScores
[BG_TEAM_HORDE
] >= 2000 )
218 EndBattleGround(HORDE
);
222 void BattleGroundAB::AddPlayer(Player
*plr
)
224 BattleGround::AddPlayer(plr
);
225 //create score and add it to map, default values are set in the constructor
226 BattleGroundABScore
* sc
= new BattleGroundABScore
;
228 m_PlayerScores
[plr
->GetGUID()] = sc
;
231 void BattleGroundAB::RemovePlayer(Player
* /*plr*/, uint64
/*guid*/)
236 void BattleGroundAB::HandleAreaTrigger(Player
*Source
, uint32 Trigger
)
238 if( GetStatus() != STATUS_IN_PROGRESS
)
243 case 3948: // Arathi Basin Alliance Exit.
244 if( Source
->GetTeam() != ALLIANCE
)
245 Source
->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
247 Source
->LeaveBattleground();
249 case 3949: // Arathi Basin Horde Exit.
250 if( Source
->GetTeam() != HORDE
)
251 Source
->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
253 Source
->LeaveBattleground();
255 case 3866: // Stables
256 case 3869: // Gold Mine
258 case 3868: // Lumber Mill
259 case 3870: // Black Smith
264 //sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);
265 //Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
270 /* type: 0-neutral, 1-contested, 3-occupied
271 teamIndex: 0-ally, 1-horde */
272 void BattleGroundAB::_CreateBanner(uint8 node
, uint8 type
, uint8 teamIndex
, bool delay
)
274 // Just put it into the queue
277 m_BannerTimers
[node
].timer
= 2000;
278 m_BannerTimers
[node
].type
= type
;
279 m_BannerTimers
[node
].teamIndex
= teamIndex
;
283 uint8 obj
= node
*8 + type
+ teamIndex
;
285 SpawnBGObject(obj
, RESPAWN_IMMEDIATELY
);
287 // handle aura with banner
290 obj
= node
* 8 + ((type
== BG_AB_NODE_TYPE_OCCUPIED
) ? (5 + teamIndex
) : 7);
291 SpawnBGObject(obj
, RESPAWN_IMMEDIATELY
);
294 void BattleGroundAB::_DelBanner(uint8 node
, uint8 type
, uint8 teamIndex
)
296 uint8 obj
= node
*8 + type
+ teamIndex
;
297 SpawnBGObject(obj
, RESPAWN_ONE_DAY
);
299 // handle aura with banner
302 obj
= node
* 8 + ((type
== BG_AB_NODE_TYPE_OCCUPIED
) ? (5 + teamIndex
) : 7);
303 SpawnBGObject(obj
, RESPAWN_ONE_DAY
);
306 const char* BattleGroundAB::_GetNodeName(uint8 node
)
310 case BG_AB_NODE_STABLES
:
311 return GetMangosString(LANG_BG_AB_NODE_STABLES
);
312 case BG_AB_NODE_BLACKSMITH
:
313 return GetMangosString(LANG_BG_AB_NODE_BLACKSMITH
);
314 case BG_AB_NODE_FARM
:
315 return GetMangosString(LANG_BG_AB_NODE_FARM
);
316 case BG_AB_NODE_LUMBER_MILL
:
317 return GetMangosString(LANG_BG_AB_NODE_LUMBER_MILL
);
318 case BG_AB_NODE_GOLD_MINE
:
319 return GetMangosString(LANG_BG_AB_NODE_GOLD_MINE
);
326 void BattleGroundAB::FillInitialWorldStates(WorldPacket
& data
)
328 const uint8 plusArray
[] = {0, 2, 3, 0, 1};
331 for (uint8 node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
332 data
<< uint32(BG_AB_OP_NODEICONS
[node
]) << uint32((m_Nodes
[node
]==0)?1:0);
334 // Node occupied states
335 for (uint8 node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
336 for (uint8 i
= 1; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
337 data
<< uint32(BG_AB_OP_NODESTATES
[node
] + plusArray
[i
]) << uint32((m_Nodes
[node
]==i
)?1:0);
339 // How many bases each team owns
340 uint8 ally
= 0, horde
= 0;
341 for (uint8 node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
342 if( m_Nodes
[node
] == BG_AB_NODE_STATUS_ALLY_OCCUPIED
)
344 else if( m_Nodes
[node
] == BG_AB_NODE_STATUS_HORDE_OCCUPIED
)
347 data
<< uint32(BG_AB_OP_OCCUPIED_BASES_ALLY
) << uint32(ally
);
348 data
<< uint32(BG_AB_OP_OCCUPIED_BASES_HORDE
) << uint32(horde
);
351 data
<< uint32(BG_AB_OP_RESOURCES_MAX
) << uint32(BG_AB_MAX_TEAM_SCORE
);
352 data
<< uint32(BG_AB_OP_RESOURCES_WARNING
) << uint32(BG_AB_WARNING_SCORE
);
353 data
<< uint32(BG_AB_OP_RESOURCES_ALLY
) << uint32(m_TeamScores
[BG_TEAM_ALLIANCE
]);
354 data
<< uint32(BG_AB_OP_RESOURCES_HORDE
) << uint32(m_TeamScores
[BG_TEAM_HORDE
]);
357 data
<< uint32(0x745) << uint32(0x2); // 37 1861 unk
360 void BattleGroundAB::_SendNodeUpdate(uint8 node
)
362 // Send node owner state update to refresh map icons on client
363 const uint8 plusArray
[] = {0, 2, 3, 0, 1};
365 if( m_prevNodes
[node
] )
366 UpdateWorldState(BG_AB_OP_NODESTATES
[node
] + plusArray
[m_prevNodes
[node
]], 0);
368 UpdateWorldState(BG_AB_OP_NODEICONS
[node
], 0);
370 UpdateWorldState(BG_AB_OP_NODESTATES
[node
] + plusArray
[m_Nodes
[node
]], 1);
372 // How many bases each team owns
373 uint8 ally
= 0, horde
= 0;
374 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
375 if( m_Nodes
[i
] == BG_AB_NODE_STATUS_ALLY_OCCUPIED
)
377 else if( m_Nodes
[i
] == BG_AB_NODE_STATUS_HORDE_OCCUPIED
)
380 UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY
, ally
);
381 UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE
, horde
);
384 void BattleGroundAB::_NodeOccupied(uint8 node
,Team team
)
386 if( !AddSpiritGuide(node
, BG_AB_SpiritGuidePos
[node
][0], BG_AB_SpiritGuidePos
[node
][1], BG_AB_SpiritGuidePos
[node
][2], BG_AB_SpiritGuidePos
[node
][3], team
) )
387 sLog
.outError("Failed to spawn spirit guide! point: %u, team: %u,", node
, team
);
388 // SpawnBGCreature(node,RESPAWN_IMMEDIATELY);
390 uint8 capturedNodes
= 0;
391 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
393 if( m_Nodes
[node
] == GetTeamIndexByTeamId(team
) + BG_AB_NODE_TYPE_OCCUPIED
&& !m_NodeTimers
[i
])
396 if(capturedNodes
>= 5)
397 CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES
, team
);
398 if(capturedNodes
>= 4)
399 CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES
, team
);
402 void BattleGroundAB::_NodeDeOccupied(uint8 node
)
404 if( node
>= BG_AB_DYNAMIC_NODES_COUNT
)
407 // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
408 std::vector
<uint64
> ghost_list
= m_ReviveQueue
[m_BgCreatures
[node
]];
409 if( !ghost_list
.empty() )
411 WorldSafeLocsEntry
const *ClosestGrave
= NULL
;
413 for (std::vector
<uint64
>::const_iterator itr
= ghost_list
.begin(); itr
!= ghost_list
.end(); ++itr
)
415 plr
= objmgr
.GetPlayer(*itr
);
419 ClosestGrave
= GetClosestGraveYard(plr
->GetPositionX(), plr
->GetPositionY(), plr
->GetPositionZ(), plr
->GetTeam());
421 plr
->TeleportTo(GetMapId(), ClosestGrave
->x
, ClosestGrave
->y
, ClosestGrave
->z
, plr
->GetOrientation());
425 if( m_BgCreatures
[node
] )
428 // buff object isn't despawned
431 /* Invoked if a player used a banner as a gameobject */
432 void BattleGroundAB::EventPlayerClickedOnFlag(Player
*source
, GameObject
* /*target_obj*/)
434 if( GetStatus() != STATUS_IN_PROGRESS
)
437 uint8 node
= BG_AB_NODE_STABLES
;
438 GameObject
* obj
=HashMapHolder
<GameObject
>::Find(m_BgObjects
[node
*8+7]);
439 while ( (node
< BG_AB_DYNAMIC_NODES_COUNT
) && ((!obj
) || (!source
->IsWithinDistInMap(obj
,10))))
442 obj
=HashMapHolder
<GameObject
>::Find(m_BgObjects
[node
*8+BG_AB_OBJECT_AURA_CONTESTED
]);
445 if( node
== BG_AB_DYNAMIC_NODES_COUNT
)
447 // this means our player isn't close to any of banners - maybe cheater ??
451 uint8 teamIndex
= GetTeamIndexByTeamId(source
->GetTeam());
453 // Message to chatlog
455 uint8 type
= (teamIndex
== 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE
: CHAT_MSG_BG_SYSTEM_HORDE
;
457 // Check if player really could use this banner, not cheated
458 if( !(m_Nodes
[node
] == 0 || teamIndex
== m_Nodes
[node
]%2) )
461 source
->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT
);
463 // If node is neutral, change to contested
464 if( m_Nodes
[node
] == BG_AB_NODE_TYPE_NEUTRAL
)
466 UpdatePlayerScore(source
, SCORE_BASES_ASSAULTED
, 1);
467 m_prevNodes
[node
] = m_Nodes
[node
];
468 m_Nodes
[node
] = teamIndex
+ 1;
469 // burn current neutral banner
470 _DelBanner(node
, BG_AB_NODE_TYPE_NEUTRAL
, 0);
471 // create new contested banner
472 _CreateBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
, true);
473 _SendNodeUpdate(node
);
474 m_NodeTimers
[node
] = BG_AB_FLAG_CAPTURING_TIME
;
475 sprintf(buf
, GetMangosString(LANG_BG_AB_NODE_CLAIMED
), _GetNodeName(node
), (teamIndex
== 0) ? GetMangosString(LANG_BG_AB_ALLY
) : GetMangosString(LANG_BG_AB_HORDE
));
476 sound
= SOUND_NODE_CLAIMED
;
478 // If node is contested
479 else if( (m_Nodes
[node
] == BG_AB_NODE_STATUS_ALLY_CONTESTED
) || (m_Nodes
[node
] == BG_AB_NODE_STATUS_HORDE_CONTESTED
) )
481 // If last state is NOT occupied, change node to enemy-contested
482 if( m_prevNodes
[node
] < BG_AB_NODE_TYPE_OCCUPIED
)
484 UpdatePlayerScore(source
, SCORE_BASES_ASSAULTED
, 1);
485 m_prevNodes
[node
] = m_Nodes
[node
];
486 m_Nodes
[node
] = teamIndex
+ BG_AB_NODE_TYPE_CONTESTED
;
487 // burn current contested banner
488 _DelBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, !teamIndex
);
489 // create new contested banner
490 _CreateBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
, true);
491 _SendNodeUpdate(node
);
492 m_NodeTimers
[node
] = BG_AB_FLAG_CAPTURING_TIME
;
493 sprintf(buf
, GetMangosString(LANG_BG_AB_NODE_ASSAULTED
), _GetNodeName(node
));
495 // If contested, change back to occupied
498 UpdatePlayerScore(source
, SCORE_BASES_DEFENDED
, 1);
499 m_prevNodes
[node
] = m_Nodes
[node
];
500 m_Nodes
[node
] = teamIndex
+ BG_AB_NODE_TYPE_OCCUPIED
;
501 // burn current contested banner
502 _DelBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, !teamIndex
);
503 // create new occupied banner
504 _CreateBanner(node
, BG_AB_NODE_TYPE_OCCUPIED
, teamIndex
, true);
505 _SendNodeUpdate(node
);
506 m_NodeTimers
[node
] = 0;
507 _NodeOccupied(node
,(teamIndex
== 0) ? ALLIANCE
:HORDE
);
508 sprintf(buf
, GetMangosString(LANG_BG_AB_NODE_DEFENDED
), _GetNodeName(node
));
510 sound
= (teamIndex
== 0) ? SOUND_NODE_ASSAULTED_ALLIANCE
: SOUND_NODE_ASSAULTED_HORDE
;
512 // If node is occupied, change to enemy-contested
515 UpdatePlayerScore(source
, SCORE_BASES_ASSAULTED
, 1);
516 m_prevNodes
[node
] = m_Nodes
[node
];
517 m_Nodes
[node
] = teamIndex
+ BG_AB_NODE_TYPE_CONTESTED
;
518 // burn current occupied banner
519 _DelBanner(node
, BG_AB_NODE_TYPE_OCCUPIED
, !teamIndex
);
520 // create new contested banner
521 _CreateBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
, true);
522 _SendNodeUpdate(node
);
523 _NodeDeOccupied(node
);
524 m_NodeTimers
[node
] = BG_AB_FLAG_CAPTURING_TIME
;
525 sprintf(buf
, GetMangosString(LANG_BG_AB_NODE_ASSAULTED
), _GetNodeName(node
));
526 sound
= (teamIndex
== 0) ? SOUND_NODE_ASSAULTED_ALLIANCE
: SOUND_NODE_ASSAULTED_HORDE
;
529 ChatHandler::FillMessageData(&data
, source
->GetSession(), type
, LANG_UNIVERSAL
, NULL
, source
->GetGUID(), buf
, NULL
);
530 SendPacketToAll(&data
);
531 // If node is occupied again, send "X has taken the Y" msg.
532 if( m_Nodes
[node
] >= BG_AB_NODE_TYPE_OCCUPIED
)
534 sprintf(buf
, GetMangosString(LANG_BG_AB_NODE_TAKEN
), (teamIndex
== 0) ? GetMangosString(LANG_BG_AB_ALLY
) : GetMangosString(LANG_BG_AB_HORDE
), _GetNodeName(node
));
535 ChatHandler::FillMessageData(&data
, NULL
, type
, LANG_UNIVERSAL
, NULL
, 0, buf
, NULL
);
536 SendPacketToAll(&data
);
538 PlaySoundToAll(sound
);
541 bool BattleGroundAB::SetupBattleGround()
543 for (int i
= 0 ; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
545 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
)
546 || !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
)
547 || !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
)
548 || !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
)
549 || !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
)
550 || !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
)
551 || !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
)
552 || !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
)
555 sLog
.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!");
559 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
)
560 || !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
)
563 sLog
.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!");
567 for (int i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
569 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
)
570 || !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
)
571 || !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
)
573 sLog
.outErrorDb("BatteGroundAB: Failed to spawn buff object!");
579 void BattleGroundAB::ResetBGSubclass()
581 m_TeamScores
[BG_TEAM_ALLIANCE
] = 0;
582 m_TeamScores
[BG_TEAM_HORDE
] = 0;
583 m_lastTick
[BG_TEAM_ALLIANCE
] = 0;
584 m_lastTick
[BG_TEAM_HORDE
] = 0;
585 m_HonorScoreTics
[BG_TEAM_ALLIANCE
] = 0;
586 m_HonorScoreTics
[BG_TEAM_HORDE
] = 0;
587 m_ReputationScoreTics
[BG_TEAM_ALLIANCE
] = 0;
588 m_ReputationScoreTics
[BG_TEAM_HORDE
] = 0;
589 m_IsInformedNearVictory
= false;
590 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
595 m_BannerTimers
[i
].timer
= 0;
598 for (uint8 i
= 0; i
< BG_AB_ALL_NODES_COUNT
; ++i
)
603 WorldSafeLocsEntry
const* BattleGroundAB::GetClosestGraveYard(float x
, float y
, float /*z*/, uint32 team
)
605 uint8 teamIndex
= GetTeamIndexByTeamId(team
);
607 // Is there any occupied node for this team?
608 std::vector
<uint8
> nodes
;
609 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
610 if( m_Nodes
[i
] == teamIndex
+ 3 )
613 WorldSafeLocsEntry
const* good_entry
= NULL
;
614 // If so, select the closest node to place ghost on
617 float mindist
= 999999.0f
;
618 for (uint8 i
= 0; i
< nodes
.size(); ++i
)
620 WorldSafeLocsEntry
const*entry
= sWorldSafeLocsStore
.LookupEntry( BG_AB_GraveyardIds
[nodes
[i
]] );
623 float dist
= (entry
->x
- x
)*(entry
->x
- x
)+(entry
->y
- y
)*(entry
->y
- y
);
632 // If not, place ghost on starting location
634 good_entry
= sWorldSafeLocsStore
.LookupEntry( BG_AB_GraveyardIds
[teamIndex
+5] );
639 void BattleGroundAB::UpdatePlayerScore(Player
*Source
, uint32 type
, uint32 value
)
641 std::map
<uint64
, BattleGroundScore
*>::iterator itr
= m_PlayerScores
.find(Source
->GetGUID());
643 if( itr
== m_PlayerScores
.end() ) // player not found...
648 case SCORE_BASES_ASSAULTED
:
649 ((BattleGroundABScore
*)itr
->second
)->BasesAssaulted
+= value
;
651 case SCORE_BASES_DEFENDED
:
652 ((BattleGroundABScore
*)itr
->second
)->BasesDefended
+= value
;
655 BattleGround::UpdatePlayerScore(Source
,type
,value
);