2 * Copyright (C) 2005-2010 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
20 #include "BattleGround.h"
21 #include "BattleGroundAV.h"
22 #include "BattleGroundMgr.h"
24 #include "GameObject.h"
26 #include "WorldPacket.h"
28 BattleGroundAV::BattleGroundAV()
30 m_StartMessageIds
[BG_STARTING_EVENT_FIRST
] = 0;
31 m_StartMessageIds
[BG_STARTING_EVENT_SECOND
] = LANG_BG_AV_START_ONE_MINUTE
;
32 m_StartMessageIds
[BG_STARTING_EVENT_THIRD
] = LANG_BG_AV_START_HALF_MINUTE
;
33 m_StartMessageIds
[BG_STARTING_EVENT_FOURTH
] = LANG_BG_AV_HAS_BEGUN
;
36 BattleGroundAV::~BattleGroundAV()
40 void BattleGroundAV::HandleKillPlayer(Player
*player
, Player
*killer
)
42 if (GetStatus() != STATUS_IN_PROGRESS
)
45 BattleGround::HandleKillPlayer(player
, killer
);
46 UpdateScore(GetTeamIndexByTeamId(player
->GetTeam()), -1);
49 void BattleGroundAV::HandleKillUnit(Creature
*creature
, Player
*killer
)
51 sLog
.outDebug("BattleGroundAV: HandleKillUnit %i", creature
->GetEntry());
52 if (GetStatus() != STATUS_IN_PROGRESS
)
54 uint8 event1
= (sBattleGroundMgr
.GetCreatureEventIndex(creature
->GetDBTableGUIDLow())).event1
;
55 if (event1
== BG_EVENT_NONE
)
60 CastSpellOnTeam(BG_AV_BOSS_KILL_QUEST_SPELL
, HORDE
); // this is a spell which finishes a quest where a player has to kill the boss
61 RewardReputationToTeam(BG_AV_FACTION_H
, m_RepBoss
, HORDE
);
62 RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS
), HORDE
);
63 SendYellToAll(LANG_BG_AV_A_GENERAL_DEAD
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0));
64 EndBattleGround(HORDE
);
67 CastSpellOnTeam(BG_AV_BOSS_KILL_QUEST_SPELL
, ALLIANCE
); // this is a spell which finishes a quest where a player has to kill the boss
68 RewardReputationToTeam(BG_AV_FACTION_A
, m_RepBoss
, ALLIANCE
);
69 RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS
), ALLIANCE
);
70 SendYellToAll(LANG_BG_AV_H_GENERAL_DEAD
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0));
71 EndBattleGround(ALLIANCE
);
74 if (IsActiveEvent(BG_AV_NodeEventCaptainDead_A
, 0))
76 RewardReputationToTeam(BG_AV_FACTION_H
, m_RepCaptain
, HORDE
);
77 RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN
), HORDE
);
78 UpdateScore(BG_TEAM_ALLIANCE
, (-1) * BG_AV_RES_CAPTAIN
);
79 // spawn destroyed aura
80 SpawnEvent(BG_AV_NodeEventCaptainDead_A
, 0, true);
83 if (IsActiveEvent(BG_AV_NodeEventCaptainDead_H
, 0))
85 RewardReputationToTeam(BG_AV_FACTION_A
, m_RepCaptain
, ALLIANCE
);
86 RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN
), ALLIANCE
);
87 UpdateScore(BG_TEAM_HORDE
, (-1) * BG_AV_RES_CAPTAIN
);
88 // spawn destroyed aura
89 SpawnEvent(BG_AV_NodeEventCaptainDead_H
, 0, true);
91 case BG_AV_MINE_BOSSES_NORTH
:
92 ChangeMineOwner(BG_AV_NORTH_MINE
, GetTeamIndexByTeamId(killer
->GetTeam()));
94 case BG_AV_MINE_BOSSES_SOUTH
:
95 ChangeMineOwner(BG_AV_SOUTH_MINE
, GetTeamIndexByTeamId(killer
->GetTeam()));
100 void BattleGroundAV::HandleQuestComplete(uint32 questid
, Player
*player
)
102 if (GetStatus() != STATUS_IN_PROGRESS
)
104 uint8 team
= GetTeamIndexByTeamId(player
->GetTeam());
105 uint32 reputation
= 0; // reputation for the whole team (other reputation must be done in db)
106 // TODO add events (including quest not available anymore, next quest availabe, go/npc de/spawning)
107 sLog
.outError("BattleGroundAV: Quest %i completed", questid
);
110 case BG_AV_QUEST_A_SCRAPS1
:
111 case BG_AV_QUEST_A_SCRAPS2
:
112 case BG_AV_QUEST_H_SCRAPS1
:
113 case BG_AV_QUEST_H_SCRAPS2
:
114 m_Team_QuestStatus
[team
][0] += 20;
116 if( m_Team_QuestStatus
[team
][0] == 500 || m_Team_QuestStatus
[team
][0] == 1000 || m_Team_QuestStatus
[team
][0] == 1500 ) //25,50,75 turn ins
118 sLog
.outDebug("BattleGroundAV: Quest %i completed starting with unit upgrading..", questid
);
119 for (BG_AV_Nodes i
= BG_AV_NODES_FIRSTAID_STATION
; i
<= BG_AV_NODES_FROSTWOLF_HUT
; ++i
)
120 if (m_Nodes
[i
].Owner
== team
&& m_Nodes
[i
].State
== POINT_CONTROLLED
)
124 case BG_AV_QUEST_A_COMMANDER1
:
125 case BG_AV_QUEST_H_COMMANDER1
:
126 m_Team_QuestStatus
[team
][1]++;
128 if (m_Team_QuestStatus
[team
][1] == 120)
129 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
131 case BG_AV_QUEST_A_COMMANDER2
:
132 case BG_AV_QUEST_H_COMMANDER2
:
133 m_Team_QuestStatus
[team
][2]++;
135 if (m_Team_QuestStatus
[team
][2] == 60)
136 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
138 case BG_AV_QUEST_A_COMMANDER3
:
139 case BG_AV_QUEST_H_COMMANDER3
:
140 m_Team_QuestStatus
[team
][3]++;
142 RewardReputationToTeam(team
, 1, player
->GetTeam());
143 if (m_Team_QuestStatus
[team
][1] == 30)
144 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
146 case BG_AV_QUEST_A_BOSS1
:
147 case BG_AV_QUEST_H_BOSS1
:
148 m_Team_QuestStatus
[team
][4] += 4; // there are 2 quests where you can turn in 5 or 1 item.. ( + 4 cause +1 will be done some lines below)
150 case BG_AV_QUEST_A_BOSS2
:
151 case BG_AV_QUEST_H_BOSS2
:
152 m_Team_QuestStatus
[team
][4]++;
154 if (m_Team_QuestStatus
[team
][4] >= 200)
155 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
157 case BG_AV_QUEST_A_NEAR_MINE
:
158 case BG_AV_QUEST_H_NEAR_MINE
:
159 m_Team_QuestStatus
[team
][5]++;
161 if (m_Team_QuestStatus
[team
][5] == 28)
163 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
164 if (m_Team_QuestStatus
[team
][6] == 7)
165 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - ground assault ready", questid
);
168 case BG_AV_QUEST_A_OTHER_MINE
:
169 case BG_AV_QUEST_H_OTHER_MINE
:
170 m_Team_QuestStatus
[team
][6]++;
172 if (m_Team_QuestStatus
[team
][6] == 7)
174 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
175 if (m_Team_QuestStatus
[team
][5] == 20)
176 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - ground assault ready", questid
);
179 case BG_AV_QUEST_A_RIDER_HIDE
:
180 case BG_AV_QUEST_H_RIDER_HIDE
:
181 m_Team_QuestStatus
[team
][7]++;
183 if (m_Team_QuestStatus
[team
][7] == 25)
185 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
186 if (m_Team_QuestStatus
[team
][8] == 25)
187 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - rider assault ready", questid
);
190 case BG_AV_QUEST_A_RIDER_TAME
:
191 case BG_AV_QUEST_H_RIDER_TAME
:
192 m_Team_QuestStatus
[team
][8]++;
194 if (m_Team_QuestStatus
[team
][8] == 25)
196 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid
);
197 if (m_Team_QuestStatus
[team
][7] == 25)
198 sLog
.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - rider assault ready", questid
);
202 sLog
.outDebug("BattleGroundAV: Quest %i completed but is not interesting for us", questid
);
207 RewardReputationToTeam((player
->GetTeam() == ALLIANCE
) ? BG_AV_FACTION_A
: BG_AV_FACTION_H
, reputation
, player
->GetTeam());
210 void BattleGroundAV::UpdateScore(BattleGroundTeamId team
, int32 points
)
212 // note: to remove reinforcements points must be negative, for adding reinforcements points must be positive
213 assert( team
== BG_TEAM_ALLIANCE
|| team
== BG_TEAM_HORDE
);
214 m_TeamScores
[team
] += points
; // m_TeamScores is int32 - so no problems here
218 if (m_TeamScores
[team
] < 1)
220 m_TeamScores
[team
] = 0;
221 // other team will win:
222 EndBattleGround((team
== BG_TEAM_ALLIANCE
)? HORDE
: ALLIANCE
);
224 else if (!m_IsInformedNearLose
[team
] && m_TeamScores
[team
] < BG_AV_SCORE_NEAR_LOSE
)
226 SendMessageToAll((team
== BG_TEAM_HORDE
) ? LANG_BG_AV_H_NEAR_LOSE
: LANG_BG_AV_A_NEAR_LOSE
, CHAT_MSG_BG_SYSTEM_NEUTRAL
);
227 PlaySoundToAll(BG_AV_SOUND_NEAR_LOSE
);
228 m_IsInformedNearLose
[team
] = true;
231 // must be called here, else it could display a negative value
232 UpdateWorldState(((team
== BG_TEAM_HORDE
) ? BG_AV_Horde_Score
: BG_AV_Alliance_Score
), m_TeamScores
[team
]);
235 void BattleGroundAV::Update(uint32 diff
)
237 BattleGround::Update(diff
);
238 if (GetStatus() != STATUS_IN_PROGRESS
)
241 // add points from mine owning, and look if the neutral team can reclaim the mine
242 for(uint8 mine
= 0; mine
< BG_AV_MAX_MINES
; mine
++)
244 if (m_Mine_Owner
[mine
] == BG_TEAM_ALLIANCE
|| m_Mine_Owner
[mine
] == BG_TEAM_HORDE
)
246 m_Mine_Timer
[mine
] -=diff
;
247 if (m_Mine_Timer
[mine
] <= 0)
249 UpdateScore(BattleGroundTeamId(m_Mine_Owner
[mine
]), 1);
250 m_Mine_Timer
[mine
] = BG_AV_MINE_TICK_TIMER
;
253 if (m_Mine_Reclaim_Timer
[mine
] > diff
)
254 m_Mine_Reclaim_Timer
[mine
] -= diff
;
256 ChangeMineOwner(mine
, BG_AV_NEUTRAL_TEAM
);
260 // looks for all timers of the nodes and destroy the building (for graveyards the building wont get destroyed, it goes just to the other team
261 for(BG_AV_Nodes i
= BG_AV_NODES_FIRSTAID_STATION
; i
< BG_AV_NODES_MAX
; ++i
)
263 if (m_Nodes
[i
].State
== POINT_ASSAULTED
)
265 if (m_Nodes
[i
].Timer
> diff
)
266 m_Nodes
[i
].Timer
-= diff
;
268 EventPlayerDestroyedPoint(i
);
273 void BattleGroundAV::StartingEventCloseDoors()
275 sLog
.outDebug("BattleGroundAV: entering state STATUS_WAIT_JOIN ...");
278 void BattleGroundAV::StartingEventOpenDoors()
280 UpdateWorldState(BG_AV_SHOW_H_SCORE
, 1);
281 UpdateWorldState(BG_AV_SHOW_A_SCORE
, 1);
283 OpenDoorEvent(BG_EVENT_DOOR
);
286 void BattleGroundAV::AddPlayer(Player
*plr
)
288 BattleGround::AddPlayer(plr
);
289 // create score and add it to map, default values are set in constructor
290 BattleGroundAVScore
* sc
= new BattleGroundAVScore
;
291 m_PlayerScores
[plr
->GetGUID()] = sc
;
294 void BattleGroundAV::EndBattleGround(uint32 winner
)
296 // calculate bonuskills for both teams:
297 uint32 tower_survived
[BG_TEAMS_COUNT
] = {0, 0};
298 uint32 graves_owned
[BG_TEAMS_COUNT
] = {0, 0};
299 uint32 mines_owned
[BG_TEAMS_COUNT
] = {0, 0};
300 // towers all not destroyed:
301 for(BG_AV_Nodes i
= BG_AV_NODES_DUNBALDAR_SOUTH
; i
<= BG_AV_NODES_STONEHEART_BUNKER
; ++i
)
302 if (m_Nodes
[i
].State
== POINT_CONTROLLED
)
303 if (m_Nodes
[i
].TotalOwner
== BG_TEAM_ALLIANCE
)
304 ++tower_survived
[BG_TEAM_ALLIANCE
];
305 for(BG_AV_Nodes i
= BG_AV_NODES_ICEBLOOD_TOWER
; i
<= BG_AV_NODES_FROSTWOLF_WTOWER
; ++i
)
306 if (m_Nodes
[i
].State
== POINT_CONTROLLED
)
307 if (m_Nodes
[i
].TotalOwner
== BG_TEAM_HORDE
)
308 ++tower_survived
[BG_TEAM_HORDE
];
310 // graves all controlled
311 for(BG_AV_Nodes i
= BG_AV_NODES_FIRSTAID_STATION
; i
< BG_AV_NODES_MAX
; ++i
)
312 if (m_Nodes
[i
].State
== POINT_CONTROLLED
)
313 ++graves_owned
[m_Nodes
[i
].Owner
];
315 for (uint32 i
= 0; i
< BG_AV_MAX_MINES
; ++i
)
316 if (m_Mine_Owner
[i
] != BG_AV_NEUTRAL_TEAM
)
317 ++mines_owned
[m_Mine_Owner
[i
]];
319 // now we have the values give the honor/reputation to the teams:
320 uint32 team
[BG_TEAMS_COUNT
] = { ALLIANCE
, HORDE
};
321 uint32 faction
[BG_TEAMS_COUNT
] = { BG_AV_FACTION_A
, BG_AV_FACTION_H
};
322 for (uint32 i
= 0; i
< BG_TEAMS_COUNT
; i
++)
324 if (tower_survived
[i
])
326 RewardReputationToTeam(faction
[i
], tower_survived
[i
] * m_RepSurviveTower
, team
[i
]);
327 RewardHonorToTeam(GetBonusHonorFromKill(tower_survived
[i
] * BG_AV_KILL_SURVIVING_TOWER
), team
[i
]);
329 sLog
.outDebug("BattleGroundAV: EndbattleGround: bgteam: %u towers:%u honor:%u rep:%u", i
, tower_survived
[i
], GetBonusHonorFromKill(tower_survived
[i
] * BG_AV_KILL_SURVIVING_TOWER
), tower_survived
[i
] * BG_AV_REP_SURVIVING_TOWER
);
331 RewardReputationToTeam(faction
[i
], graves_owned
[i
] * m_RepOwnedGrave
, team
[i
]);
333 RewardReputationToTeam(faction
[i
], mines_owned
[i
] * m_RepOwnedMine
, team
[i
]);
334 // captain survived?:
335 if (!IsActiveEvent(BG_AV_NodeEventCaptainDead_A
+ GetTeamIndexByTeamId(team
[i
]), 0))
337 RewardReputationToTeam(faction
[i
], m_RepSurviveCaptain
, team
[i
]);
338 RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_SURVIVING_CAPTAIN
), team
[i
]);
343 if (m_HonorMapComplete
)
345 RewardHonorToTeam(m_HonorMapComplete
, ALLIANCE
);
346 RewardHonorToTeam(m_HonorMapComplete
, HORDE
);
348 BattleGround::EndBattleGround(winner
);
351 void BattleGroundAV::RemovePlayer(Player
* /*plr*/,uint64
/*guid*/)
355 void BattleGroundAV::HandleAreaTrigger(Player
*Source
, uint32 Trigger
)
357 // this is wrong way to implement these things. On official it done by gameobject spell cast.
362 if (Source
->GetTeam() != ALLIANCE
)
363 Source
->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_ALLIANCE_USE
);
365 Source
->LeaveBattleground();
368 if (Source
->GetTeam() != HORDE
)
369 Source
->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_HORDE_USE
);
371 Source
->LeaveBattleground();
382 sLog
.outDebug("BattleGroundAV: WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger
);
383 // Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
388 void BattleGroundAV::UpdatePlayerScore(Player
* Source
, uint32 type
, uint32 value
)
391 BattleGroundScoreMap::iterator itr
= m_PlayerScores
.find(Source
->GetGUID());
392 if(itr
== m_PlayerScores
.end()) // player not found...
397 case SCORE_GRAVEYARDS_ASSAULTED
:
398 ((BattleGroundAVScore
*)itr
->second
)->GraveyardsAssaulted
+= value
;
400 case SCORE_GRAVEYARDS_DEFENDED
:
401 ((BattleGroundAVScore
*)itr
->second
)->GraveyardsDefended
+= value
;
403 case SCORE_TOWERS_ASSAULTED
:
404 ((BattleGroundAVScore
*)itr
->second
)->TowersAssaulted
+= value
;
406 case SCORE_TOWERS_DEFENDED
:
407 ((BattleGroundAVScore
*)itr
->second
)->TowersDefended
+= value
;
409 case SCORE_SECONDARY_OBJECTIVES
:
410 ((BattleGroundAVScore
*)itr
->second
)->SecondaryObjectives
+= value
;
413 BattleGround::UpdatePlayerScore(Source
, type
, value
);
418 void BattleGroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node
)
421 sLog
.outDebug("BattleGroundAV: player destroyed point node %i", node
);
426 UpdateNodeWorldState(node
);
428 uint32 owner
= m_Nodes
[node
].Owner
;
431 uint8 tmp
= node
- BG_AV_NODES_DUNBALDAR_SOUTH
;
432 // despawn marshal (one of those guys protecting the boss)
433 SpawnEvent(BG_AV_MARSHAL_A_SOUTH
+ tmp
, 0, false);
435 UpdateScore(BattleGroundTeamId(owner
^0x1), (-1) * BG_AV_RES_TOWER
);
436 RewardReputationToTeam((owner
== BG_TEAM_ALLIANCE
) ? BG_AV_FACTION_A
: BG_AV_FACTION_H
, m_RepTowerDestruction
, owner
);
437 RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_TOWER
), owner
);
438 SendYell2ToAll(LANG_BG_AV_TOWER_TAKEN
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0), GetNodeName(node
), ( owner
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
: LANG_BG_HORDE
);
442 SendYell2ToAll(LANG_BG_AV_GRAVE_TAKEN
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0), GetNodeName(node
), ( owner
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
: LANG_BG_HORDE
);
446 void BattleGroundAV::ChangeMineOwner(uint8 mine
, uint32 team
)
448 m_Mine_Timer
[mine
] = BG_AV_MINE_TICK_TIMER
;
449 // TODO implement quest 7122
450 // mine=0 northmine, mine=1 southmine
451 // TODO changing the owner should result in setting respawntime to infinite for current creatures (they should fight the new ones), spawning new mine owners creatures and changing the chest - objects so that the current owning team can use them
452 assert(mine
== BG_AV_NORTH_MINE
|| mine
== BG_AV_SOUTH_MINE
);
453 if (m_Mine_Owner
[mine
] == int8(team
))
456 if (team
!= BG_TEAM_ALLIANCE
&& team
!= BG_TEAM_HORDE
)
457 team
= BG_AV_NEUTRAL_TEAM
;
459 m_Mine_PrevOwner
[mine
] = m_Mine_Owner
[mine
];
460 m_Mine_Owner
[mine
] = team
;
462 SendMineWorldStates(mine
);
464 SpawnEvent(BG_AV_MINE_EVENT
+ mine
, team
, true);
465 SpawnEvent(BG_AV_MINE_BOSSES
+ mine
, team
, true);
467 if (team
== BG_TEAM_ALLIANCE
|| team
== BG_TEAM_HORDE
)
469 PlaySoundToAll((team
== BG_TEAM_ALLIANCE
) ? BG_AV_SOUND_ALLIANCE_GOOD
: BG_AV_SOUND_HORDE_GOOD
);
470 m_Mine_Reclaim_Timer
[mine
] = BG_AV_MINE_RECLAIM_TIMER
;
471 SendYell2ToAll(LANG_BG_AV_MINE_TAKEN
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0),
472 (team
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
: LANG_BG_HORDE
,
473 (mine
== BG_AV_NORTH_MINE
) ? LANG_BG_AV_MINE_NORTH
: LANG_BG_AV_MINE_SOUTH
);
477 bool BattleGroundAV::PlayerCanDoMineQuest(int32 GOId
, uint32 team
)
479 if (GOId
== BG_AV_OBJECTID_MINE_N
)
480 return (m_Mine_Owner
[BG_AV_NORTH_MINE
] == GetTeamIndexByTeamId(team
));
481 if (GOId
== BG_AV_OBJECTID_MINE_S
)
482 return (m_Mine_Owner
[BG_AV_SOUTH_MINE
] == GetTeamIndexByTeamId(team
));
483 return true; // cause it's no mine'object it is ok if this is true
486 /// will spawn and despawn creatures around a node
487 /// more a wrapper around spawnevent cause graveyards are special
488 void BattleGroundAV::PopulateNode(BG_AV_Nodes node
)
490 uint32 team
= m_Nodes
[node
].Owner
;
491 if (IsGrave(node
) && team
!= BG_AV_NEUTRAL_TEAM
)
493 uint32 graveDefenderType
;
494 if (m_Team_QuestStatus
[team
][0] < 500 )
495 graveDefenderType
= 0;
496 else if (m_Team_QuestStatus
[team
][0] < 1000 )
497 graveDefenderType
= 1;
498 else if (m_Team_QuestStatus
[team
][0] < 1500 )
499 graveDefenderType
= 2;
501 graveDefenderType
= 3;
503 if (m_Nodes
[node
].State
== POINT_CONTROLLED
) // we can spawn the current owner event
504 SpawnEvent(BG_AV_NODES_MAX
+ node
, team
* BG_AV_MAX_GRAVETYPES
+ graveDefenderType
, true);
505 else // we despawn the event from the prevowner
506 SpawnEvent(BG_AV_NODES_MAX
+ node
, m_Nodes
[node
].PrevOwner
* BG_AV_MAX_GRAVETYPES
+ graveDefenderType
, false);
508 SpawnEvent(node
, (team
* BG_AV_MAX_STATES
) + m_Nodes
[node
].State
, true);
511 /// called when using a banner
512 void BattleGroundAV::EventPlayerClickedOnFlag(Player
*source
, GameObject
* target_obj
)
514 if (GetStatus() != STATUS_IN_PROGRESS
)
516 sLog
.outDebug("BattleGroundAV: using gameobject %i", target_obj
->GetEntry());
517 uint8 event
= (sBattleGroundMgr
.GetGameObjectEventIndex(target_obj
->GetDBTableGUIDLow())).event1
;
518 if (event
>= BG_AV_NODES_MAX
) // not a node
520 BG_AV_Nodes node
= BG_AV_Nodes(event
);
521 switch ((sBattleGroundMgr
.GetGameObjectEventIndex(target_obj
->GetDBTableGUIDLow())).event2
% BG_AV_MAX_STATES
)
523 case POINT_CONTROLLED
:
524 EventPlayerAssaultsPoint(source
, node
);
526 case POINT_ASSAULTED
:
527 EventPlayerDefendsPoint(source
, node
);
534 void BattleGroundAV::EventPlayerDefendsPoint(Player
* player
, BG_AV_Nodes node
)
536 assert(GetStatus() == STATUS_IN_PROGRESS
);
538 uint32 team
= GetTeamIndexByTeamId(player
->GetTeam());
540 if (m_Nodes
[node
].Owner
== team
|| m_Nodes
[node
].State
!= POINT_ASSAULTED
)
542 if( m_Nodes
[node
].TotalOwner
== BG_AV_NEUTRAL_TEAM
) // initial snowfall capture
544 // until snowfall doesn't belong to anyone it is better handled in assault - code (best would be to have a special function
545 // for neutral nodes.. but doing this just for snowfall will be a bit to much i think
546 assert(node
== BG_AV_NODES_SNOWFALL_GRAVE
); // currently the only neutral grave
547 EventPlayerAssaultsPoint(player
, node
);
550 sLog
.outDebug("BattleGroundAV: player defends node: %i", node
);
551 if (m_Nodes
[node
].PrevOwner
!= team
)
553 sLog
.outError("BattleGroundAV: player defends point which doesn't belong to his team %i", node
);
557 DefendNode(node
, team
); // set the right variables for nodeinfo
558 PopulateNode(node
); // spawn node-creatures (defender for example)
559 UpdateNodeWorldState(node
); // send new mapicon to the player
563 SendYell2ToAll( LANG_BG_AV_TOWER_DEFENDED
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0),
565 ( team
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
:LANG_BG_HORDE
);
566 UpdatePlayerScore(player
, SCORE_TOWERS_DEFENDED
, 1);
567 PlaySoundToAll(BG_AV_SOUND_BOTH_TOWER_DEFEND
);
571 SendYell2ToAll(LANG_BG_AV_GRAVE_DEFENDED
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0),
573 ( team
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
:LANG_BG_HORDE
);
574 UpdatePlayerScore(player
, SCORE_GRAVEYARDS_DEFENDED
, 1);
575 // update the statistic for the defending player
576 PlaySoundToAll((team
== BG_TEAM_ALLIANCE
)?BG_AV_SOUND_ALLIANCE_GOOD
:BG_AV_SOUND_HORDE_GOOD
);
580 void BattleGroundAV::EventPlayerAssaultsPoint(Player
* player
, BG_AV_Nodes node
)
582 // TODO implement quest 7101, 7081
583 uint32 team
= GetTeamIndexByTeamId(player
->GetTeam());
584 sLog
.outDebug("BattleGroundAV: player assaults node %i", node
);
585 if (m_Nodes
[node
].Owner
== team
|| team
== m_Nodes
[node
].TotalOwner
)
588 AssaultNode(node
, team
); // update nodeinfo variables
589 UpdateNodeWorldState(node
); // send mapicon
594 SendYell2ToAll(LANG_BG_AV_TOWER_ASSAULTED
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0),
596 ( team
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
:LANG_BG_HORDE
);
597 UpdatePlayerScore(player
, SCORE_TOWERS_ASSAULTED
, 1);
601 SendYell2ToAll(LANG_BG_AV_GRAVE_ASSAULTED
, LANG_UNIVERSAL
, GetSingleCreatureGuid(BG_AV_HERALD
, 0),
603 ( team
== BG_TEAM_ALLIANCE
) ? LANG_BG_ALLY
:LANG_BG_HORDE
);
604 // update the statistic for the assaulting player
605 UpdatePlayerScore(player
, SCORE_GRAVEYARDS_ASSAULTED
, 1);
608 PlaySoundToAll((team
== BG_TEAM_ALLIANCE
) ? BG_AV_SOUND_ALLIANCE_ASSAULTS
: BG_AV_SOUND_HORDE_ASSAULTS
);
611 void BattleGroundAV::FillInitialWorldStates(WorldPacket
& data
)
614 for (uint32 i
= BG_AV_NODES_FIRSTAID_STATION
; i
< BG_AV_NODES_MAX
; ++i
)
616 for (uint8 j
= 0; j
< BG_AV_MAX_STATES
; j
++)
618 stateok
= (m_Nodes
[i
].State
== j
);
619 data
<< uint32(BG_AV_NodeWorldStates
[i
][GetWorldStateType(j
, BG_TEAM_ALLIANCE
)]) << uint32((m_Nodes
[i
].Owner
== BG_TEAM_ALLIANCE
&& stateok
) ? 1 : 0);
620 data
<< uint32(BG_AV_NodeWorldStates
[i
][GetWorldStateType(j
, BG_TEAM_HORDE
)]) << uint32((m_Nodes
[i
].Owner
== BG_TEAM_HORDE
&& stateok
) ? 1 : 0);
624 if( m_Nodes
[BG_AV_NODES_SNOWFALL_GRAVE
].Owner
== BG_AV_NEUTRAL_TEAM
) // cause neutral teams aren't handled generic
625 data
<< uint32(AV_SNOWFALL_N
) << uint32(1);
627 data
<< uint32(BG_AV_Alliance_Score
) << uint32(m_TeamScores
[BG_TEAM_ALLIANCE
]);
628 data
<< uint32(BG_AV_Horde_Score
) << uint32(m_TeamScores
[BG_TEAM_HORDE
]);
629 if( GetStatus() == STATUS_IN_PROGRESS
) // only if game is running the teamscores are displayed
631 data
<< uint32(BG_AV_SHOW_A_SCORE
) << uint32(1);
632 data
<< uint32(BG_AV_SHOW_H_SCORE
) << uint32(1);
636 data
<< uint32(BG_AV_SHOW_A_SCORE
) << uint32(0);
637 data
<< uint32(BG_AV_SHOW_H_SCORE
) << uint32(0);
639 SendMineWorldStates(BG_AV_NORTH_MINE
);
640 SendMineWorldStates(BG_AV_SOUTH_MINE
);
643 void BattleGroundAV::UpdateNodeWorldState(BG_AV_Nodes node
)
645 UpdateWorldState(BG_AV_NodeWorldStates
[node
][GetWorldStateType(m_Nodes
[node
].State
,m_Nodes
[node
].Owner
)], 1);
646 if( m_Nodes
[node
].PrevOwner
== BG_AV_NEUTRAL_TEAM
) // currently only snowfall is supported as neutral node
647 UpdateWorldState(AV_SNOWFALL_N
, 0);
649 UpdateWorldState(BG_AV_NodeWorldStates
[node
][GetWorldStateType(m_Nodes
[node
].PrevState
,m_Nodes
[node
].PrevOwner
)], 0);
652 void BattleGroundAV::SendMineWorldStates(uint32 mine
)
654 assert(mine
== BG_AV_NORTH_MINE
|| mine
== BG_AV_SOUTH_MINE
);
655 assert(m_Mine_PrevOwner
[mine
] == BG_TEAM_ALLIANCE
|| m_Mine_PrevOwner
[mine
] == BG_TEAM_HORDE
|| m_Mine_PrevOwner
[mine
] == BG_AV_NEUTRAL_TEAM
);
656 assert(m_Mine_Owner
[mine
] == BG_TEAM_ALLIANCE
|| m_Mine_Owner
[mine
] == BG_TEAM_HORDE
|| m_Mine_Owner
[mine
] == BG_AV_NEUTRAL_TEAM
);
658 UpdateWorldState(BG_AV_MineWorldStates
[mine
][m_Mine_Owner
[mine
]], 1);
659 if (m_Mine_Owner
[mine
] != m_Mine_PrevOwner
[mine
])
660 UpdateWorldState(BG_AV_MineWorldStates
[mine
][m_Mine_PrevOwner
[mine
]], 0);
663 WorldSafeLocsEntry
const* BattleGroundAV::GetClosestGraveYard(Player
*plr
)
665 float x
= plr
->GetPositionX();
666 float y
= plr
->GetPositionY();
667 uint32 team
= GetTeamIndexByTeamId(plr
->GetTeam());
668 WorldSafeLocsEntry
const* good_entry
= NULL
;
669 if (GetStatus() == STATUS_IN_PROGRESS
)
671 // Is there any occupied node for this team?
672 float mindist
= 9999999.0f
;
673 for(uint8 i
= BG_AV_NODES_FIRSTAID_STATION
; i
<= BG_AV_NODES_FROSTWOLF_HUT
; ++i
)
675 if (m_Nodes
[i
].Owner
!= team
|| m_Nodes
[i
].State
!= POINT_CONTROLLED
)
677 WorldSafeLocsEntry
const * entry
= sWorldSafeLocsStore
.LookupEntry( BG_AV_GraveyardIds
[i
] );
680 float dist
= (entry
->x
- x
) * (entry
->x
- x
) + (entry
->y
- y
) * (entry
->y
- y
);
688 // If not, place ghost in the starting-cave
690 good_entry
= sWorldSafeLocsStore
.LookupEntry( BG_AV_GraveyardIds
[team
+ 7] );
695 uint32
BattleGroundAV::GetNodeName(BG_AV_Nodes node
)
699 case BG_AV_NODES_FIRSTAID_STATION
: return LANG_BG_AV_NODE_GRAVE_STORM_AID
;
700 case BG_AV_NODES_DUNBALDAR_SOUTH
: return LANG_BG_AV_NODE_TOWER_DUN_S
;
701 case BG_AV_NODES_DUNBALDAR_NORTH
: return LANG_BG_AV_NODE_TOWER_DUN_N
;
702 case BG_AV_NODES_STORMPIKE_GRAVE
: return LANG_BG_AV_NODE_GRAVE_STORMPIKE
;
703 case BG_AV_NODES_ICEWING_BUNKER
: return LANG_BG_AV_NODE_TOWER_ICEWING
;
704 case BG_AV_NODES_STONEHEART_GRAVE
: return LANG_BG_AV_NODE_GRAVE_STONE
;
705 case BG_AV_NODES_STONEHEART_BUNKER
: return LANG_BG_AV_NODE_TOWER_STONE
;
706 case BG_AV_NODES_SNOWFALL_GRAVE
: return LANG_BG_AV_NODE_GRAVE_SNOW
;
707 case BG_AV_NODES_ICEBLOOD_TOWER
: return LANG_BG_AV_NODE_TOWER_ICE
;
708 case BG_AV_NODES_ICEBLOOD_GRAVE
: return LANG_BG_AV_NODE_GRAVE_ICE
;
709 case BG_AV_NODES_TOWER_POINT
: return LANG_BG_AV_NODE_TOWER_POINT
;
710 case BG_AV_NODES_FROSTWOLF_GRAVE
: return LANG_BG_AV_NODE_GRAVE_FROST
;
711 case BG_AV_NODES_FROSTWOLF_ETOWER
: return LANG_BG_AV_NODE_TOWER_FROST_E
;
712 case BG_AV_NODES_FROSTWOLF_WTOWER
: return LANG_BG_AV_NODE_TOWER_FROST_W
;
713 case BG_AV_NODES_FROSTWOLF_HUT
: return LANG_BG_AV_NODE_GRAVE_FROST_HUT
;
714 default: return 0; break;
718 void BattleGroundAV::AssaultNode(BG_AV_Nodes node
, uint32 team
)
720 assert(team
< 3); // alliance:0, horde:1, neutral:2
721 assert(m_Nodes
[node
].TotalOwner
!= team
);
722 assert(m_Nodes
[node
].Owner
!= team
);
723 // only assault an assaulted node if no totalowner exists:
724 assert(m_Nodes
[node
].State
!= POINT_ASSAULTED
|| m_Nodes
[node
].TotalOwner
== BG_AV_NEUTRAL_TEAM
);
725 // the timer gets another time, if the previous owner was 0 == Neutral
726 m_Nodes
[node
].Timer
= (m_Nodes
[node
].PrevOwner
!= BG_AV_NEUTRAL_TEAM
) ? BG_AV_CAPTIME
: BG_AV_SNOWFALL_FIRSTCAP
;
727 m_Nodes
[node
].PrevOwner
= m_Nodes
[node
].Owner
;
728 m_Nodes
[node
].Owner
= team
;
729 m_Nodes
[node
].PrevState
= m_Nodes
[node
].State
;
730 m_Nodes
[node
].State
= POINT_ASSAULTED
;
733 void BattleGroundAV::DestroyNode(BG_AV_Nodes node
)
735 assert(m_Nodes
[node
].State
== POINT_ASSAULTED
);
737 m_Nodes
[node
].TotalOwner
= m_Nodes
[node
].Owner
;
738 m_Nodes
[node
].PrevOwner
= m_Nodes
[node
].Owner
;
739 m_Nodes
[node
].PrevState
= m_Nodes
[node
].State
;
740 m_Nodes
[node
].State
= POINT_CONTROLLED
;
741 m_Nodes
[node
].Timer
= 0;
744 void BattleGroundAV::InitNode(BG_AV_Nodes node
, uint32 team
, bool tower
)
746 assert(team
< 3); // alliance:0, horde:1, neutral:2
747 m_Nodes
[node
].TotalOwner
= team
;
748 m_Nodes
[node
].Owner
= team
;
749 m_Nodes
[node
].PrevOwner
= team
;
750 m_Nodes
[node
].State
= POINT_CONTROLLED
;
751 m_Nodes
[node
].PrevState
= m_Nodes
[node
].State
;
752 m_Nodes
[node
].State
= POINT_CONTROLLED
;
753 m_Nodes
[node
].Timer
= 0;
754 m_Nodes
[node
].Tower
= tower
;
755 m_ActiveEvents
[node
] = team
* BG_AV_MAX_STATES
+ m_Nodes
[node
].State
;
756 if (IsGrave(node
)) // grave-creatures are special cause of a quest
757 m_ActiveEvents
[node
+ BG_AV_NODES_MAX
] = team
* BG_AV_MAX_GRAVETYPES
;
760 void BattleGroundAV::DefendNode(BG_AV_Nodes node
, uint32 team
)
762 assert(team
< 3); // alliance:0, horde:1, neutral:2
763 assert(m_Nodes
[node
].TotalOwner
== team
);
764 assert(m_Nodes
[node
].Owner
!= team
);
765 assert(m_Nodes
[node
].State
!= POINT_CONTROLLED
);
766 m_Nodes
[node
].PrevOwner
= m_Nodes
[node
].Owner
;
767 m_Nodes
[node
].Owner
= team
;
768 m_Nodes
[node
].PrevState
= m_Nodes
[node
].State
;
769 m_Nodes
[node
].State
= POINT_CONTROLLED
;
770 m_Nodes
[node
].Timer
= 0;
773 void BattleGroundAV::Reset()
775 BattleGround::Reset();
776 // set the reputation and honor variables:
777 bool isBGWeekend
= sBattleGroundMgr
.IsBGWeekend(GetTypeID());
779 m_HonorMapComplete
= (isBGWeekend
) ? BG_AV_KILL_MAP_COMPLETE_HOLIDAY
: BG_AV_KILL_MAP_COMPLETE
;
780 m_RepTowerDestruction
= (isBGWeekend
) ? BG_AV_REP_TOWER_HOLIDAY
: BG_AV_REP_TOWER
;
781 m_RepCaptain
= (isBGWeekend
) ? BG_AV_REP_CAPTAIN_HOLIDAY
: BG_AV_REP_CAPTAIN
;
782 m_RepBoss
= (isBGWeekend
) ? BG_AV_REP_BOSS_HOLIDAY
: BG_AV_REP_BOSS
;
783 m_RepOwnedGrave
= (isBGWeekend
) ? BG_AV_REP_OWNED_GRAVE_HOLIDAY
: BG_AV_REP_OWNED_GRAVE
;
784 m_RepSurviveCaptain
= (isBGWeekend
) ? BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY
: BG_AV_REP_SURVIVING_CAPTAIN
;
785 m_RepSurviveTower
= (isBGWeekend
) ? BG_AV_REP_SURVIVING_TOWER_HOLIDAY
: BG_AV_REP_SURVIVING_TOWER
;
786 m_RepOwnedMine
= (isBGWeekend
) ? BG_AV_REP_OWNED_MINE_HOLIDAY
: BG_AV_REP_OWNED_MINE
;
788 for(uint8 i
= 0; i
< BG_TEAMS_COUNT
; i
++)
790 for(uint8 j
= 0; j
< 9; j
++) // 9 quests getting tracked
791 m_Team_QuestStatus
[i
][j
] = 0;
792 m_TeamScores
[i
] = BG_AV_SCORE_INITIAL_POINTS
;
793 m_IsInformedNearLose
[i
] = false;
794 m_ActiveEvents
[BG_AV_NodeEventCaptainDead_A
+ i
] = BG_EVENT_NONE
;
797 for(uint8 i
= 0; i
< BG_AV_MAX_MINES
; i
++)
799 m_Mine_Owner
[i
] = BG_AV_NEUTRAL_TEAM
;
800 m_Mine_PrevOwner
[i
] = m_Mine_Owner
[i
];
801 m_ActiveEvents
[BG_AV_MINE_BOSSES
+ i
] = BG_AV_NEUTRAL_TEAM
;
802 m_ActiveEvents
[BG_AV_MINE_EVENT
+ i
] = BG_AV_NEUTRAL_TEAM
;
803 m_Mine_Timer
[i
] = BG_AV_MINE_TICK_TIMER
;
806 m_ActiveEvents
[BG_AV_CAPTAIN_A
] = 0;
807 m_ActiveEvents
[BG_AV_CAPTAIN_H
] = 0;
808 m_ActiveEvents
[BG_AV_HERALD
] = 0;
809 m_ActiveEvents
[BG_AV_BOSS_A
] = 0;
810 m_ActiveEvents
[BG_AV_BOSS_H
] = 0;
811 for(BG_AV_Nodes i
= BG_AV_NODES_DUNBALDAR_SOUTH
; i
<= BG_AV_NODES_FROSTWOLF_WTOWER
; ++i
) // towers
812 m_ActiveEvents
[BG_AV_MARSHAL_A_SOUTH
+ i
- BG_AV_NODES_DUNBALDAR_SOUTH
] = 0;
814 for(BG_AV_Nodes i
= BG_AV_NODES_FIRSTAID_STATION
; i
<= BG_AV_NODES_STONEHEART_GRAVE
; ++i
) // alliance graves
815 InitNode(i
, BG_TEAM_ALLIANCE
, false);
816 for(BG_AV_Nodes i
= BG_AV_NODES_DUNBALDAR_SOUTH
; i
<= BG_AV_NODES_STONEHEART_BUNKER
; ++i
) // alliance towers
817 InitNode(i
, BG_TEAM_ALLIANCE
, true);
819 for(BG_AV_Nodes i
= BG_AV_NODES_ICEBLOOD_GRAVE
; i
<= BG_AV_NODES_FROSTWOLF_HUT
; ++i
) // horde graves
820 InitNode(i
, BG_TEAM_HORDE
, false);
821 for(BG_AV_Nodes i
= BG_AV_NODES_ICEBLOOD_TOWER
; i
<= BG_AV_NODES_FROSTWOLF_WTOWER
; ++i
) // horde towers
822 InitNode(i
, BG_TEAM_HORDE
, true);
824 InitNode(BG_AV_NODES_SNOWFALL_GRAVE
, BG_AV_NEUTRAL_TEAM
, false); // give snowfall neutral owner