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"
24 #include "ObjectMgr.h"
27 #include "WorldPacket.h"
29 BattleGroundAB::BattleGroundAB()
32 m_BgObjects
.resize(BG_AB_OBJECT_MAX
);
33 m_BgCreatures
.resize(BG_AB_ALL_NODES_COUNT
);
35 m_StartMessageIds
[BG_STARTING_EVENT_FIRST
] = LANG_BG_AB_START_TWO_MINUTES
;
36 m_StartMessageIds
[BG_STARTING_EVENT_SECOND
] = LANG_BG_AB_START_ONE_MINUTE
;
37 m_StartMessageIds
[BG_STARTING_EVENT_THIRD
] = LANG_BG_AB_START_HALF_MINUTE
;
38 m_StartMessageIds
[BG_STARTING_EVENT_FOURTH
] = LANG_BG_AB_HAS_BEGUN
;
41 BattleGroundAB::~BattleGroundAB()
45 void BattleGroundAB::Update(uint32 diff
)
47 BattleGround::Update(diff
);
49 if (GetStatus() == STATUS_IN_PROGRESS
)
51 int team_points
[BG_TEAMS_COUNT
] = { 0, 0 };
53 for (int node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
55 // 3 sec delay to spawn new banner instead previous despawned one
56 if (m_BannerTimers
[node
].timer
)
58 if (m_BannerTimers
[node
].timer
> diff
)
59 m_BannerTimers
[node
].timer
-= diff
;
62 m_BannerTimers
[node
].timer
= 0;
63 _CreateBanner(node
, m_BannerTimers
[node
].type
, m_BannerTimers
[node
].teamIndex
, false);
67 // 1-minute to occupy a node from contested state
68 if (m_NodeTimers
[node
])
70 if (m_NodeTimers
[node
] > diff
)
71 m_NodeTimers
[node
] -= diff
;
74 m_NodeTimers
[node
] = 0;
75 // Change from contested to occupied !
76 uint8 teamIndex
= m_Nodes
[node
]-1;
77 m_prevNodes
[node
] = m_Nodes
[node
];
79 // burn current contested banner
80 _DelBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
);
81 // create new occupied banner
82 _CreateBanner(node
, BG_AB_NODE_TYPE_OCCUPIED
, teamIndex
, true);
83 _SendNodeUpdate(node
);
84 _NodeOccupied(node
,(teamIndex
== 0) ? ALLIANCE
:HORDE
);
89 // FIXME: team and node names not localized
90 SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN
,CHAT_MSG_BG_SYSTEM_ALLIANCE
,NULL
,LANG_BG_AB_ALLY
,_GetNodeNameId(node
));
91 PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE
);
95 // FIXME: team and node names not localized
96 SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN
,CHAT_MSG_BG_SYSTEM_HORDE
,NULL
,LANG_BG_AB_HORDE
,_GetNodeNameId(node
));
97 PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE
);
102 for (int team
= 0; team
< BG_TEAMS_COUNT
; ++team
)
103 if (m_Nodes
[node
] == team
+ BG_AB_NODE_TYPE_OCCUPIED
)
108 for (int team
= 0; team
< BG_TEAMS_COUNT
; ++team
)
110 int points
= team_points
[team
];
113 m_lastTick
[team
] += diff
;
114 if (m_lastTick
[team
] > BG_AB_TickIntervals
[points
])
116 m_lastTick
[team
] -= BG_AB_TickIntervals
[points
];
117 m_TeamScores
[team
] += BG_AB_TickPoints
[points
];
118 m_HonorScoreTics
[team
] += BG_AB_TickPoints
[points
];
119 m_ReputationScoreTics
[team
] += BG_AB_TickPoints
[points
];
120 if (m_ReputationScoreTics
[team
] >= m_ReputationTics
)
122 (team
== BG_TEAM_ALLIANCE
) ? RewardReputationToTeam(509, 10, ALLIANCE
) : RewardReputationToTeam(510, 10, HORDE
);
123 m_ReputationScoreTics
[team
] -= m_ReputationTics
;
125 if (m_HonorScoreTics
[team
] >= m_HonorTics
)
127 RewardHonorToTeam(GetBonusHonorFromKill(1), (team
== BG_TEAM_ALLIANCE
) ? ALLIANCE
: HORDE
);
128 m_HonorScoreTics
[team
] -= m_HonorTics
;
130 if (!m_IsInformedNearVictory
&& m_TeamScores
[team
] > BG_AB_WARNING_NEAR_VICTORY_SCORE
)
132 if (team
== BG_TEAM_ALLIANCE
)
133 SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY
, CHAT_MSG_BG_SYSTEM_NEUTRAL
);
135 SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY
, CHAT_MSG_BG_SYSTEM_NEUTRAL
);
136 PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY
);
137 m_IsInformedNearVictory
= true;
140 if (m_TeamScores
[team
] > BG_AB_MAX_TEAM_SCORE
)
141 m_TeamScores
[team
] = BG_AB_MAX_TEAM_SCORE
;
142 if (team
== BG_TEAM_ALLIANCE
)
143 UpdateWorldState(BG_AB_OP_RESOURCES_ALLY
, m_TeamScores
[team
]);
144 if (team
== BG_TEAM_HORDE
)
145 UpdateWorldState(BG_AB_OP_RESOURCES_HORDE
, m_TeamScores
[team
]);
149 // achievements flags
150 if (m_TeamScores
[BG_TEAM_ALLIANCE
] > m_TeamScores
[BG_TEAM_HORDE
])
152 if (m_TeamScores
[BG_TEAM_ALLIANCE
] - m_TeamScores
[BG_TEAM_HORDE
] >= 500)
153 m_TeamScores500disadvantage
[BG_TEAM_HORDE
] = true;
157 if (m_TeamScores
[BG_TEAM_HORDE
] - m_TeamScores
[BG_TEAM_ALLIANCE
] >= 500)
158 m_TeamScores500disadvantage
[BG_TEAM_ALLIANCE
] = true;
161 // Test win condition
162 if (m_TeamScores
[BG_TEAM_ALLIANCE
] >= BG_AB_MAX_TEAM_SCORE
)
163 EndBattleGround(ALLIANCE
);
164 if (m_TeamScores
[BG_TEAM_HORDE
] >= BG_AB_MAX_TEAM_SCORE
)
165 EndBattleGround(HORDE
);
169 void BattleGroundAB::StartingEventCloseDoors()
171 // despawn banners, auras and buffs
172 for (int obj
= BG_AB_OBJECT_BANNER_NEUTRAL
; obj
< BG_AB_DYNAMIC_NODES_COUNT
* 8; ++obj
)
173 SpawnBGObject(obj
, RESPAWN_ONE_DAY
);
174 for (int i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
* 3; ++i
)
175 SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES
+ i
, RESPAWN_ONE_DAY
);
178 DoorClose(BG_AB_OBJECT_GATE_A
);
179 DoorClose(BG_AB_OBJECT_GATE_H
);
180 SpawnBGObject(BG_AB_OBJECT_GATE_A
, RESPAWN_IMMEDIATELY
);
181 SpawnBGObject(BG_AB_OBJECT_GATE_H
, RESPAWN_IMMEDIATELY
);
183 // Starting base spirit guides
184 _NodeOccupied(BG_AB_SPIRIT_ALIANCE
,ALLIANCE
);
185 _NodeOccupied(BG_AB_SPIRIT_HORDE
,HORDE
);
188 void BattleGroundAB::StartingEventOpenDoors()
190 // spawn neutral banners
191 for (int banner
= BG_AB_OBJECT_BANNER_NEUTRAL
, i
= 0; i
< 5; banner
+= 8, ++i
)
192 SpawnBGObject(banner
, RESPAWN_IMMEDIATELY
);
193 for (int i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
195 //randomly select buff to spawn
196 uint8 buff
= urand(0, 2);
197 SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES
+ buff
+ i
* 3, RESPAWN_IMMEDIATELY
);
199 DoorOpen(BG_AB_OBJECT_GATE_A
);
200 DoorOpen(BG_AB_OBJECT_GATE_H
);
203 void BattleGroundAB::AddPlayer(Player
*plr
)
205 BattleGround::AddPlayer(plr
);
206 //create score and add it to map, default values are set in the constructor
207 BattleGroundABScore
* sc
= new BattleGroundABScore
;
209 m_PlayerScores
[plr
->GetGUID()] = sc
;
212 void BattleGroundAB::RemovePlayer(Player
* /*plr*/, uint64
/*guid*/)
217 void BattleGroundAB::HandleAreaTrigger(Player
*Source
, uint32 Trigger
)
219 if (GetStatus() != STATUS_IN_PROGRESS
)
224 case 3948: // Arathi Basin Alliance Exit.
225 if (Source
->GetTeam() != ALLIANCE
)
226 Source
->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
228 Source
->LeaveBattleground();
230 case 3949: // Arathi Basin Horde Exit.
231 if (Source
->GetTeam() != HORDE
)
232 Source
->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
234 Source
->LeaveBattleground();
236 case 3866: // Stables
237 case 3869: // Gold Mine
239 case 3868: // Lumber Mill
240 case 3870: // Black Smith
245 //sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);
246 //Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
251 /* type: 0-neutral, 1-contested, 3-occupied
252 teamIndex: 0-ally, 1-horde */
253 void BattleGroundAB::_CreateBanner(uint8 node
, uint8 type
, uint8 teamIndex
, bool delay
)
255 // Just put it into the queue
258 m_BannerTimers
[node
].timer
= 2000;
259 m_BannerTimers
[node
].type
= type
;
260 m_BannerTimers
[node
].teamIndex
= teamIndex
;
264 uint8 obj
= node
*8 + type
+ teamIndex
;
266 SpawnBGObject(obj
, RESPAWN_IMMEDIATELY
);
268 // handle aura with banner
271 obj
= node
* 8 + ((type
== BG_AB_NODE_TYPE_OCCUPIED
) ? (5 + teamIndex
) : 7);
272 SpawnBGObject(obj
, RESPAWN_IMMEDIATELY
);
275 void BattleGroundAB::_DelBanner(uint8 node
, uint8 type
, uint8 teamIndex
)
277 uint8 obj
= node
*8 + type
+ teamIndex
;
278 SpawnBGObject(obj
, RESPAWN_ONE_DAY
);
280 // handle aura with banner
283 obj
= node
* 8 + ((type
== BG_AB_NODE_TYPE_OCCUPIED
) ? (5 + teamIndex
) : 7);
284 SpawnBGObject(obj
, RESPAWN_ONE_DAY
);
287 int32
BattleGroundAB::_GetNodeNameId(uint8 node
)
291 case BG_AB_NODE_STABLES
: return LANG_BG_AB_NODE_STABLES
;
292 case BG_AB_NODE_BLACKSMITH
: return LANG_BG_AB_NODE_BLACKSMITH
;
293 case BG_AB_NODE_FARM
: return LANG_BG_AB_NODE_FARM
;
294 case BG_AB_NODE_LUMBER_MILL
:return LANG_BG_AB_NODE_LUMBER_MILL
;
295 case BG_AB_NODE_GOLD_MINE
: return LANG_BG_AB_NODE_GOLD_MINE
;
302 void BattleGroundAB::FillInitialWorldStates(WorldPacket
& data
)
304 const uint8 plusArray
[] = {0, 2, 3, 0, 1};
307 for (uint8 node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
308 data
<< uint32(BG_AB_OP_NODEICONS
[node
]) << uint32((m_Nodes
[node
]==0)?1:0);
310 // Node occupied states
311 for (uint8 node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
312 for (uint8 i
= 1; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
313 data
<< uint32(BG_AB_OP_NODESTATES
[node
] + plusArray
[i
]) << uint32((m_Nodes
[node
]==i
)?1:0);
315 // How many bases each team owns
316 uint8 ally
= 0, horde
= 0;
317 for (uint8 node
= 0; node
< BG_AB_DYNAMIC_NODES_COUNT
; ++node
)
318 if (m_Nodes
[node
] == BG_AB_NODE_STATUS_ALLY_OCCUPIED
)
320 else if (m_Nodes
[node
] == BG_AB_NODE_STATUS_HORDE_OCCUPIED
)
323 data
<< uint32(BG_AB_OP_OCCUPIED_BASES_ALLY
) << uint32(ally
);
324 data
<< uint32(BG_AB_OP_OCCUPIED_BASES_HORDE
) << uint32(horde
);
327 data
<< uint32(BG_AB_OP_RESOURCES_MAX
) << uint32(BG_AB_MAX_TEAM_SCORE
);
328 data
<< uint32(BG_AB_OP_RESOURCES_WARNING
) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE
);
329 data
<< uint32(BG_AB_OP_RESOURCES_ALLY
) << uint32(m_TeamScores
[BG_TEAM_ALLIANCE
]);
330 data
<< uint32(BG_AB_OP_RESOURCES_HORDE
) << uint32(m_TeamScores
[BG_TEAM_HORDE
]);
333 data
<< uint32(0x745) << uint32(0x2); // 37 1861 unk
336 void BattleGroundAB::_SendNodeUpdate(uint8 node
)
338 // Send node owner state update to refresh map icons on client
339 const uint8 plusArray
[] = {0, 2, 3, 0, 1};
341 if (m_prevNodes
[node
])
342 UpdateWorldState(BG_AB_OP_NODESTATES
[node
] + plusArray
[m_prevNodes
[node
]], 0);
344 UpdateWorldState(BG_AB_OP_NODEICONS
[node
], 0);
346 UpdateWorldState(BG_AB_OP_NODESTATES
[node
] + plusArray
[m_Nodes
[node
]], 1);
348 // How many bases each team owns
349 uint8 ally
= 0, horde
= 0;
350 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
351 if (m_Nodes
[i
] == BG_AB_NODE_STATUS_ALLY_OCCUPIED
)
353 else if (m_Nodes
[i
] == BG_AB_NODE_STATUS_HORDE_OCCUPIED
)
356 UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY
, ally
);
357 UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE
, horde
);
360 void BattleGroundAB::_NodeOccupied(uint8 node
,Team team
)
362 if (!AddSpiritGuide(node
, BG_AB_SpiritGuidePos
[node
][0], BG_AB_SpiritGuidePos
[node
][1], BG_AB_SpiritGuidePos
[node
][2], BG_AB_SpiritGuidePos
[node
][3], team
))
363 sLog
.outError("Failed to spawn spirit guide! point: %u, team: %u,", node
, team
);
364 // SpawnBGCreature(node,RESPAWN_IMMEDIATELY);
366 uint8 capturedNodes
= 0;
367 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
369 if (m_Nodes
[node
] == GetTeamIndexByTeamId(team
) + BG_AB_NODE_TYPE_OCCUPIED
&& !m_NodeTimers
[i
])
372 if (capturedNodes
>= 5)
373 CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES
, team
);
374 if (capturedNodes
>= 4)
375 CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES
, team
);
378 void BattleGroundAB::_NodeDeOccupied(uint8 node
)
380 if (node
>= BG_AB_DYNAMIC_NODES_COUNT
)
383 // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
384 std::vector
<uint64
> ghost_list
= m_ReviveQueue
[m_BgCreatures
[node
]];
385 if (!ghost_list
.empty())
387 WorldSafeLocsEntry
const *ClosestGrave
= NULL
;
388 for (std::vector
<uint64
>::const_iterator itr
= ghost_list
.begin(); itr
!= ghost_list
.end(); ++itr
)
390 Player
* plr
= objmgr
.GetPlayer(*itr
);
394 if (!ClosestGrave
) // cache
395 ClosestGrave
= GetClosestGraveYard(plr
);
398 plr
->TeleportTo(GetMapId(), ClosestGrave
->x
, ClosestGrave
->y
, ClosestGrave
->z
, plr
->GetOrientation());
402 if (m_BgCreatures
[node
])
405 // buff object isn't despawned
408 /* Invoked if a player used a banner as a gameobject */
409 void BattleGroundAB::EventPlayerClickedOnFlag(Player
*source
, GameObject
* /*target_obj*/)
411 if (GetStatus() != STATUS_IN_PROGRESS
)
414 uint8 node
= BG_AB_NODE_STABLES
;
415 GameObject
* obj
=HashMapHolder
<GameObject
>::Find(m_BgObjects
[node
*8+7]);
416 while ( (node
< BG_AB_DYNAMIC_NODES_COUNT
) && ((!obj
) || (!source
->IsWithinDistInMap(obj
,10))))
419 obj
=HashMapHolder
<GameObject
>::Find(m_BgObjects
[node
*8+BG_AB_OBJECT_AURA_CONTESTED
]);
422 if (node
== BG_AB_DYNAMIC_NODES_COUNT
)
424 // this means our player isn't close to any of banners - maybe cheater ??
428 BattleGroundTeamId teamIndex
= GetTeamIndexByTeamId(source
->GetTeam());
430 // Check if player really could use this banner, not cheated
431 if (!(m_Nodes
[node
] == 0 || teamIndex
== m_Nodes
[node
]%2))
434 source
->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT
);
436 // If node is neutral, change to contested
437 if (m_Nodes
[node
] == BG_AB_NODE_TYPE_NEUTRAL
)
439 UpdatePlayerScore(source
, SCORE_BASES_ASSAULTED
, 1);
440 m_prevNodes
[node
] = m_Nodes
[node
];
441 m_Nodes
[node
] = teamIndex
+ 1;
442 // burn current neutral banner
443 _DelBanner(node
, BG_AB_NODE_TYPE_NEUTRAL
, 0);
444 // create new contested banner
445 _CreateBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
, true);
446 _SendNodeUpdate(node
);
447 m_NodeTimers
[node
] = BG_AB_FLAG_CAPTURING_TIME
;
449 // FIXME: team and node names not localized
451 SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED
,CHAT_MSG_BG_SYSTEM_ALLIANCE
, source
, _GetNodeNameId(node
), LANG_BG_AB_ALLY
);
453 SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED
,CHAT_MSG_BG_SYSTEM_HORDE
, source
, _GetNodeNameId(node
), LANG_BG_AB_HORDE
);
455 sound
= BG_AB_SOUND_NODE_CLAIMED
;
457 // If node is contested
458 else if ((m_Nodes
[node
] == BG_AB_NODE_STATUS_ALLY_CONTESTED
) || (m_Nodes
[node
] == BG_AB_NODE_STATUS_HORDE_CONTESTED
))
460 // If last state is NOT occupied, change node to enemy-contested
461 if (m_prevNodes
[node
] < BG_AB_NODE_TYPE_OCCUPIED
)
463 UpdatePlayerScore(source
, SCORE_BASES_ASSAULTED
, 1);
464 m_prevNodes
[node
] = m_Nodes
[node
];
465 m_Nodes
[node
] = teamIndex
+ BG_AB_NODE_TYPE_CONTESTED
;
466 // burn current contested banner
467 _DelBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, !teamIndex
);
468 // create new contested banner
469 _CreateBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
, true);
470 _SendNodeUpdate(node
);
471 m_NodeTimers
[node
] = BG_AB_FLAG_CAPTURING_TIME
;
473 // FIXME: node names not localized
474 if (teamIndex
== BG_TEAM_ALLIANCE
)
475 SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED
,CHAT_MSG_BG_SYSTEM_ALLIANCE
, source
, _GetNodeNameId(node
));
477 SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED
,CHAT_MSG_BG_SYSTEM_HORDE
, source
, _GetNodeNameId(node
));
479 // If contested, change back to occupied
482 UpdatePlayerScore(source
, SCORE_BASES_DEFENDED
, 1);
483 m_prevNodes
[node
] = m_Nodes
[node
];
484 m_Nodes
[node
] = teamIndex
+ BG_AB_NODE_TYPE_OCCUPIED
;
485 // burn current contested banner
486 _DelBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, !teamIndex
);
487 // create new occupied banner
488 _CreateBanner(node
, BG_AB_NODE_TYPE_OCCUPIED
, teamIndex
, true);
489 _SendNodeUpdate(node
);
490 m_NodeTimers
[node
] = 0;
491 _NodeOccupied(node
,(teamIndex
== BG_TEAM_ALLIANCE
) ? ALLIANCE
:HORDE
);
493 // FIXME: node names not localized
494 if (teamIndex
== BG_TEAM_ALLIANCE
)
495 SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED
,CHAT_MSG_BG_SYSTEM_ALLIANCE
, source
, _GetNodeNameId(node
));
497 SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED
,CHAT_MSG_BG_SYSTEM_HORDE
, source
, _GetNodeNameId(node
));
499 sound
= (teamIndex
== BG_TEAM_ALLIANCE
) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE
: BG_AB_SOUND_NODE_ASSAULTED_HORDE
;
501 // If node is occupied, change to enemy-contested
504 UpdatePlayerScore(source
, SCORE_BASES_ASSAULTED
, 1);
505 m_prevNodes
[node
] = m_Nodes
[node
];
506 m_Nodes
[node
] = teamIndex
+ BG_AB_NODE_TYPE_CONTESTED
;
507 // burn current occupied banner
508 _DelBanner(node
, BG_AB_NODE_TYPE_OCCUPIED
, !teamIndex
);
509 // create new contested banner
510 _CreateBanner(node
, BG_AB_NODE_TYPE_CONTESTED
, teamIndex
, true);
511 _SendNodeUpdate(node
);
512 _NodeDeOccupied(node
);
513 m_NodeTimers
[node
] = BG_AB_FLAG_CAPTURING_TIME
;
515 // FIXME: node names not localized
516 if (teamIndex
== BG_TEAM_ALLIANCE
)
517 SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED
,CHAT_MSG_BG_SYSTEM_ALLIANCE
, source
, _GetNodeNameId(node
));
519 SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED
,CHAT_MSG_BG_SYSTEM_HORDE
, source
, _GetNodeNameId(node
));
521 sound
= (teamIndex
== BG_TEAM_ALLIANCE
) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE
: BG_AB_SOUND_NODE_ASSAULTED_HORDE
;
524 // If node is occupied again, send "X has taken the Y" msg.
525 if (m_Nodes
[node
] >= BG_AB_NODE_TYPE_OCCUPIED
)
527 // FIXME: team and node names not localized
528 if (teamIndex
== BG_TEAM_ALLIANCE
)
529 SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN
,CHAT_MSG_BG_SYSTEM_ALLIANCE
, NULL
, LANG_BG_AB_ALLY
, _GetNodeNameId(node
));
531 SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN
,CHAT_MSG_BG_SYSTEM_HORDE
, NULL
, LANG_BG_AB_HORDE
, _GetNodeNameId(node
));
533 PlaySoundToAll(sound
);
536 bool BattleGroundAB::SetupBattleGround()
538 for (int i
= 0 ; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
540 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
)
541 || !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
)
542 || !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
)
543 || !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
)
544 || !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
)
545 || !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
)
546 || !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
)
547 || !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
)
550 sLog
.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!");
554 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
)
555 || !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
)
558 sLog
.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!");
562 for (int i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
564 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
)
565 || !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
)
566 || !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
)
568 sLog
.outErrorDb("BatteGroundAB: Failed to spawn buff object!");
574 void BattleGroundAB::Reset()
576 //call parent's class reset
577 BattleGround::Reset();
579 m_TeamScores
[BG_TEAM_ALLIANCE
] = 0;
580 m_TeamScores
[BG_TEAM_HORDE
] = 0;
581 m_lastTick
[BG_TEAM_ALLIANCE
] = 0;
582 m_lastTick
[BG_TEAM_HORDE
] = 0;
583 m_HonorScoreTics
[BG_TEAM_ALLIANCE
] = 0;
584 m_HonorScoreTics
[BG_TEAM_HORDE
] = 0;
585 m_ReputationScoreTics
[BG_TEAM_ALLIANCE
] = 0;
586 m_ReputationScoreTics
[BG_TEAM_HORDE
] = 0;
587 m_IsInformedNearVictory
= false;
588 bool isBGWeekend
= false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call!
589 m_HonorTics
= (isBGWeekend
) ? BG_AB_ABBGWeekendHonorTicks
: BG_AB_NotABBGWeekendHonorTicks
;
590 m_ReputationTics
= (isBGWeekend
) ? BG_AB_ABBGWeekendReputationTicks
: BG_AB_NotABBGWeekendReputationTicks
;
591 m_TeamScores500disadvantage
[BG_TEAM_ALLIANCE
] = false;
592 m_TeamScores500disadvantage
[BG_TEAM_HORDE
] = false;
594 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
599 m_BannerTimers
[i
].timer
= 0;
602 for (uint8 i
= 0; i
< BG_AB_ALL_NODES_COUNT
; ++i
)
603 if (m_BgCreatures
[i
])
607 void BattleGroundAB::EndBattleGround(uint32 winner
)
610 if (winner
== ALLIANCE
)
611 RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE
);
613 RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE
);
614 //complete map_end rewards (even if no team wins)
615 RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE
);
616 RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE
);
618 BattleGround::EndBattleGround(winner
);
621 WorldSafeLocsEntry
const* BattleGroundAB::GetClosestGraveYard(Player
* player
)
623 BattleGroundTeamId teamIndex
= GetTeamIndexByTeamId(player
->GetTeam());
625 // Is there any occupied node for this team?
626 std::vector
<uint8
> nodes
;
627 for (uint8 i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
628 if (m_Nodes
[i
] == teamIndex
+ 3)
631 WorldSafeLocsEntry
const* good_entry
= NULL
;
632 // If so, select the closest node to place ghost on
635 float plr_x
= player
->GetPositionX();
636 float plr_y
= player
->GetPositionY();
638 float mindist
= 999999.0f
;
639 for (uint8 i
= 0; i
< nodes
.size(); ++i
)
641 WorldSafeLocsEntry
const*entry
= sWorldSafeLocsStore
.LookupEntry( BG_AB_GraveyardIds
[nodes
[i
]] );
644 float dist
= (entry
->x
- plr_x
)*(entry
->x
- plr_x
)+(entry
->y
- plr_y
)*(entry
->y
- plr_y
);
653 // If not, place ghost on starting location
655 good_entry
= sWorldSafeLocsStore
.LookupEntry( BG_AB_GraveyardIds
[teamIndex
+5] );
660 void BattleGroundAB::UpdatePlayerScore(Player
*Source
, uint32 type
, uint32 value
)
662 BattleGroundScoreMap::iterator itr
= m_PlayerScores
.find(Source
->GetGUID());
663 if( itr
== m_PlayerScores
.end() ) // player not found...
668 case SCORE_BASES_ASSAULTED
:
669 ((BattleGroundABScore
*)itr
->second
)->BasesAssaulted
+= value
;
671 case SCORE_BASES_DEFENDED
:
672 ((BattleGroundABScore
*)itr
->second
)->BasesDefended
+= value
;
675 BattleGround::UpdatePlayerScore(Source
,type
,value
);
680 bool BattleGroundAB::IsAllNodesConrolledByTeam(uint32 team
) const
683 for(int i
= 0; i
< BG_AB_DYNAMIC_NODES_COUNT
; ++i
)
684 if (team
== ALLIANCE
&& m_Nodes
[i
] == BG_AB_NODE_STATUS_ALLY_OCCUPIED
||
685 team
== HORDE
&& m_Nodes
[i
] == BG_AB_NODE_STATUS_HORDE_OCCUPIED
)
688 return count
== BG_AB_DYNAMIC_NODES_COUNT
;