First Commit

For Azeroth!
This commit is contained in:
Yehonal
2016-06-26 10:39:44 +02:00
commit e8e94a0a66
3777 changed files with 1419268 additions and 0 deletions
+913
View File
@@ -0,0 +1,913 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "ArenaTeam.h"
#include "World.h"
#include "Group.h"
#include "ArenaTeamMgr.h"
#include "Player.h"
#include "WorldSession.h"
#include "Opcodes.h"
ArenaTeam::ArenaTeam()
: TeamId(0), Type(0), TeamName(), CaptainGuid(0), BackgroundColor(0), EmblemStyle(0), EmblemColor(0),
BorderStyle(0), BorderColor(0)
{
Stats.WeekGames = 0;
Stats.SeasonGames = 0;
Stats.Rank = 0;
Stats.Rating = sWorld->getIntConfig(CONFIG_ARENA_START_RATING);
Stats.WeekWins = 0;
Stats.SeasonWins = 0;
}
ArenaTeam::~ArenaTeam()
{
}
bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor)
{
// Check if captain is present
if (!ObjectAccessor::FindPlayerInOrOutOfWorld(captainGuid))
return false;
// Check if arena team name is already taken
if (sArenaTeamMgr->GetArenaTeamByName(TeamName))
return false;
// Generate new arena team id
TeamId = sArenaTeamMgr->GenerateArenaTeamId();
// Assign member variables
CaptainGuid = captainGuid;
Type = type;
TeamName = teamName;
BackgroundColor = backgroundColor;
EmblemStyle = emblemStyle;
EmblemColor = emblemColor;
BorderStyle = borderStyle;
BorderColor = borderColor;
uint32 captainLowGuid = GUID_LOPART(captainGuid);
// Save arena team to db
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM);
stmt->setUInt32(0, TeamId);
stmt->setString(1, TeamName);
stmt->setUInt32(2, captainLowGuid);
stmt->setUInt8(3, Type);
stmt->setUInt16(4, Stats.Rating);
stmt->setUInt32(5, BackgroundColor);
stmt->setUInt8(6, EmblemStyle);
stmt->setUInt32(7, EmblemColor);
stmt->setUInt8(8, BorderStyle);
stmt->setUInt32(9, BorderColor);
CharacterDatabase.Execute(stmt);
// Add captain as member
AddMember(CaptainGuid);
return true;
}
bool ArenaTeam::AddMember(uint64 playerGuid)
{
std::string playerName;
uint8 playerClass;
// Check if arena team is full (Can't have more than type * 2 players)
if (GetMembersSize() >= GetType() * 2)
return false;
// xinef: Get player name and class from player storage or global data storage
Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(playerGuid);
if (player)
{
playerClass = player->getClass();
playerName = player->GetName();
}
else
{
GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(GUID_LOPART(playerGuid));
if (!playerData)
return false;
playerName = playerData->name;
playerClass = playerData->playerClass;
}
// Check if player is already in a similar arena team
if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromStorage(GUID_LOPART(playerGuid), GetSlot()) != 0)
{
sLog->outError("Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), GUID_LOPART(playerGuid), GetType());
return false;
}
// Set player's personal rating
uint32 personalRating = 0;
if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0)
personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING);
else if (GetRating() >= 1000)
personalRating = 1000;
// xinef: zomg! sync query
// Try to get player's match maker rating from db and fall back to config setting if not found
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING);
stmt->setUInt32(0, GUID_LOPART(playerGuid));
stmt->setUInt8(1, GetSlot());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
uint16 matchMakerRating;
uint16 maxMMR;
if (result)
{
matchMakerRating = (*result)[0].GetUInt16();
uint16 Max = (*result)[1].GetUInt16();
maxMMR = std::max(Max, matchMakerRating);
}
else
{
matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING);
maxMMR = matchMakerRating;
}
// Remove all player signatures from other petitions
// This will prevent player from joining too many arena teams and corrupt arena team data integrity
Player::RemovePetitionsAndSigns(playerGuid, GetType());
// Feed data to the struct
ArenaTeamMember newMember;
//newMember.Name = playerName;
newMember.Guid = playerGuid;
newMember.Class = playerClass;
newMember.SeasonGames = 0;
newMember.WeekGames = 0;
newMember.SeasonWins = 0;
newMember.WeekWins = 0;
newMember.PersonalRating = personalRating;
newMember.MatchMakerRating = matchMakerRating;
newMember.MaxMMR = maxMMR;
Members.push_back(newMember);
sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(playerGuid), GetSlot(), GetId());
// Save player's arena team membership to db
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER);
stmt->setUInt32(0, TeamId);
stmt->setUInt32(1, GUID_LOPART(playerGuid));
CharacterDatabase.Execute(stmt);
// Inform player if online
if (player)
{
player->SetInArenaTeam(TeamId, GetSlot(), GetType());
player->SetArenaTeamIdInvited(0);
// Hide promote/remove buttons
if (CaptainGuid != playerGuid)
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
}
return true;
}
bool ArenaTeam::LoadArenaTeamFromDB(QueryResult result)
{
if (!result)
return false;
Field* fields = result->Fetch();
TeamId = fields[0].GetUInt32();
TeamName = fields[1].GetString();
CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
Type = fields[3].GetUInt8();
BackgroundColor = fields[4].GetUInt32();
EmblemStyle = fields[5].GetUInt8();
EmblemColor = fields[6].GetUInt32();
BorderStyle = fields[7].GetUInt8();
BorderColor = fields[8].GetUInt32();
Stats.Rating = fields[9].GetUInt16();
Stats.WeekGames = fields[10].GetUInt16();
Stats.WeekWins = fields[11].GetUInt16();
Stats.SeasonGames = fields[12].GetUInt16();
Stats.SeasonWins = fields[13].GetUInt16();
Stats.Rank = fields[14].GetUInt32();
return true;
}
bool ArenaTeam::LoadMembersFromDB(QueryResult result)
{
if (!result)
return false;
bool captainPresentInTeam = false;
do
{
Field* fields = result->Fetch();
// Prevent crash if db records are broken when all members in result are already processed and current team doesn't have any members
if (!fields)
break;
uint32 arenaTeamId = fields[0].GetUInt32();
// We loaded all members for this arena_team already, break cycle
if (arenaTeamId > TeamId)
break;
ArenaTeamMember newMember;
newMember.Guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
newMember.WeekGames = fields[2].GetUInt16();
newMember.WeekWins = fields[3].GetUInt16();
newMember.SeasonGames = fields[4].GetUInt16();
newMember.SeasonWins = fields[5].GetUInt16();
//newMember.Name = fields[6].GetString();
newMember.Class = fields[7].GetUInt8();
newMember.PersonalRating = fields[8].GetUInt16();
newMember.MatchMakerRating = fields[9].GetUInt16() > 0 ? fields[9].GetUInt16() : sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING);;
newMember.MaxMMR = std::max(fields[10].GetUInt16(), newMember.MatchMakerRating);
// Delete member if character information is missing
if (fields[6].GetString().empty())
{
sLog->outErrorDb("ArenaTeam %u has member with empty name - probably player %u doesn't exist, deleting him from memberlist!", arenaTeamId, GUID_LOPART(newMember.Guid));
this->DelMember(newMember.Guid, true);
continue;
}
// Check if team team has a valid captain
if (newMember.Guid == GetCaptain())
captainPresentInTeam = true;
// Put the player in the team
Members.push_back(newMember);
sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(newMember.Guid), GetSlot(), GetId());
}
while (result->NextRow());
if (Empty() || !captainPresentInTeam)
{
// Arena team is empty or captain is not in team, delete from db
;//sLog->outDebug(LOG_FILTER_BATTLEGROUND, "ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", TeamId);
return false;
}
return true;
}
void ArenaTeam::SetCaptain(uint64 guid)
{
// Disable remove/promote buttons
Player* oldCaptain = ObjectAccessor::FindPlayerInOrOutOfWorld(GetCaptain());
if (oldCaptain)
oldCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
// Set new captain
CaptainGuid = guid;
// Update database
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_CAPTAIN);
stmt->setUInt32(0, GUID_LOPART(guid));
stmt->setUInt32(1, GetId());
CharacterDatabase.Execute(stmt);
// Enable remove/promote buttons
if (Player* newCaptain = ObjectAccessor::FindPlayerInOrOutOfWorld(guid))
{
newCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 0);
/*if (oldCaptain)
{
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].",
oldCaptain->GetName().c_str(), oldCaptain->GetGUIDLow(), newCaptain->GetName().c_str(),
newCaptain->GetGUIDLow(), GetId(), GetType());
}*/
}
}
void ArenaTeam::DelMember(uint64 guid, bool cleanDb)
{
// Remove member from team
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (itr->Guid == guid)
{
Members.erase(itr);
sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(guid), GetSlot(), 0);
break;
}
// Inform player and remove arena team info from player data
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(guid))
{
player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
// delete all info regarding this team
for (uint32 i = 0; i < ARENA_TEAM_END; ++i)
player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0);
}
// Only used for single member deletion, for arena team disband we use a single query for more efficiency
if (cleanDb)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM_MEMBER);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, GUID_LOPART(guid));
CharacterDatabase.Execute(stmt);
}
}
void ArenaTeam::Disband(WorldSession* session)
{
// Remove all members from arena team
while (!Members.empty())
DelMember(Members.front().Guid, false);
// Broadcast update
if (session)
{
BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, 0, 2, session->GetPlayerName(), GetName(), "");
}
// Update database
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM);
stmt->setUInt32(0, TeamId);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM_MEMBERS);
stmt->setUInt32(0, TeamId);
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
// Remove arena team from ObjectMgr
sArenaTeamMgr->RemoveArenaTeam(TeamId);
}
void ArenaTeam::Roster(WorldSession* session)
{
Player* player = NULL;
uint8 unk308 = 0;
std::string tempName;
WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100);
data << uint32(GetId()); // team id
data << uint8(unk308); // 308 unknown value but affect packet structure
data << uint32(GetMembersSize()); // members count
data << uint32(GetType()); // arena team type?
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
player = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid);
data << uint64(itr->Guid); // guid
data << uint8((player ? 1 : 0)); // online flag
tempName = "";
sObjectMgr->GetPlayerNameByGUID(itr->Guid, tempName);
data << tempName; // member name
data << uint32((itr->Guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
data << uint8((player ? player->getLevel() : 0)); // unknown, level?
data << uint8(itr->Class); // class
data << uint32(itr->WeekGames); // played this week
data << uint32(itr->WeekWins); // wins this week
data << uint32(itr->SeasonGames); // played this season
data << uint32(itr->SeasonWins); // wins this season
data << uint32(itr->PersonalRating); // personal rating
if (unk308)
{
data << float(0.0f); // 308 unk
data << float(0.0f); // 308 unk
}
}
session->SendPacket(&data);
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
}
void ArenaTeam::Query(WorldSession* session)
{
WorldPacket data(SMSG_ARENA_TEAM_QUERY_RESPONSE, 4*7+GetName().size()+1);
data << uint32(GetId()); // team id
data << GetName(); // team name
data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
data << uint32(BackgroundColor); // background color
data << uint32(EmblemStyle); // emblem style
data << uint32(EmblemColor); // emblem color
data << uint32(BorderStyle); // border style
data << uint32(BorderColor); // border color
session->SendPacket(&data);
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
}
void ArenaTeam::SendStats(WorldSession* session)
{
WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7);
data << uint32(GetId()); // team id
data << uint32(Stats.Rating); // rating
data << uint32(Stats.WeekGames); // games this week
data << uint32(Stats.WeekWins); // wins this week
data << uint32(Stats.SeasonGames); // played this season
data << uint32(Stats.SeasonWins); // wins this season
data << uint32(Stats.Rank); // rank
session->SendPacket(&data);
}
void ArenaTeam::NotifyStatsChanged()
{
// This is called after a rated match ended
// Updates arena team stats for every member of the team (not only the ones who participated!)
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
SendStats(player->GetSession());
}
void ArenaTeam::Inspect(WorldSession* session, uint64 guid)
{
ArenaTeamMember* member = GetMember(guid);
if (!member)
return;
WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8+1+4*6);
data << uint64(guid); // player guid
data << uint8(GetSlot()); // slot (0...2)
data << uint32(GetId()); // arena team id
data << uint32(Stats.Rating); // rating
data << uint32(Stats.SeasonGames); // season played
data << uint32(Stats.SeasonWins); // season wins
data << uint32(member->SeasonGames); // played (count of all games, that the inspected member participated...)
data << uint32(member->PersonalRating); // personal rating
session->SendPacket(&data);
}
void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 type)
{
if (int32(PersonalRating) + mod < 0)
PersonalRating = 0;
else
PersonalRating += mod;
if (player)
{
player->SetArenaTeamInfoField(ArenaTeam::GetSlotByType(type), ARENA_TEAM_PERSONAL_RATING, PersonalRating);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type);
}
}
void ArenaTeamMember::ModifyMatchmakerRating(int32 mod, uint32 /*slot*/)
{
if (mod < 0)
{
// pussywizard: prevent lowering MMR too much from max achieved MMR
int32 maxAllowedDrop = (int32)sWorld->getIntConfig(CONFIG_MAX_ALLOWED_MMR_DROP);
mod = std::min<int32>(std::max<int32>(-((int32)MatchMakerRating - (int32)MaxMMR + maxAllowedDrop), mod), 0);
}
if (int32(MatchMakerRating) + mod < 0)
MatchMakerRating = 0;
else
MatchMakerRating += mod;
if (MatchMakerRating > MaxMMR)
MaxMMR = MatchMakerRating;
}
void ArenaTeam::BroadcastPacket(WorldPacket* packet)
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
player->GetSession()->SendPacket(packet);
}
void ArenaTeam::BroadcastEvent(ArenaTeamEvents event, uint64 guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3)
{
WorldPacket data(SMSG_ARENA_TEAM_EVENT, 1+1+1);
data << uint8(event);
data << uint8(strCount);
switch (strCount)
{
case 0:
break;
case 1:
data << str1;
break;
case 2:
data << str1 << str2;
break;
case 3:
data << str1 << str2 << str3;
break;
default:
sLog->outError("Unhandled strCount %u in ArenaTeam::BroadcastEvent", strCount);
return;
}
if (guid)
data << uint64(guid);
BroadcastPacket(&data);
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_EVENT");
}
void ArenaTeam::MassInviteToEvent(WorldSession* session)
{
WorldPacket data(SMSG_CALENDAR_ARENA_TEAM, (Members.size() - 1) * (4 + 8 + 1));
data << uint32(Members.size() - 1);
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid != session->GetPlayer()->GetGUID())
{
data.appendPackGUID(itr->Guid);
data << uint8(0); // unk
}
}
session->SendPacket(&data);
}
uint8 ArenaTeam::GetSlotByType(uint32 type)
{
switch (type)
{
case ARENA_TEAM_2v2: return 0;
case ARENA_TEAM_3v3: return 1;
case ARENA_TEAM_5v5: return 2;
default:
break;
}
sLog->outError("FATAL: Unknown arena team type %u for some arena team", type);
return 0xFF;
}
bool ArenaTeam::IsMember(uint64 guid) const
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (itr->Guid == guid)
return true;
return false;
}
uint32 ArenaTeam::GetPoints(uint32 memberRating)
{
// Returns how many points would be awarded with this team type with this rating
float points;
uint32 rating = memberRating + 150 < Stats.Rating ? memberRating : Stats.Rating;
if (rating <= 1500)
{
if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6)
points = (float)rating * 0.22f + 14.0f;
else
points = 344;
}
else
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
// Type penalties for teams < 5v5
if (Type == ARENA_TEAM_2v2)
points *= 0.76f;
else if (Type == ARENA_TEAM_3v3)
points *= 0.88f;
return (uint32) points;
}
uint32 ArenaTeam::GetAverageMMR(Group* group) const
{
if (!group)
return 0;
uint32 matchMakerRating = 0;
uint32 playerDivider = 0;
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
// Skip if player is not online
if (!ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
continue;
// Skip if player is not member of group
if (!group->IsMember(itr->Guid))
continue;
matchMakerRating += itr->MatchMakerRating;
++playerDivider;
}
// x/0 = crash
if (playerDivider == 0)
playerDivider = 1;
matchMakerRating /= playerDivider;
return matchMakerRating;
}
float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
{
// Returns the chance to win against a team with the given rating, used in the rating adjustment calculation
// ELO system
return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f));
}
int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float& confidence_factor*/)
{
// 'Chance' calculation - to beat the opponent
// This is a simulation. Not much info on how it really works
float chance = GetChanceAgainst(ownRating, opponentRating);
float won_mod = (won) ? 1.0f : 0.0f;
float mod = won_mod - chance;
// Work in progress:
/*
// This is a simulation, as there is not much info on how it really works
float confidence_mod = min(1.0f - fabs(mod), 0.5f);
// Apply confidence factor to the mod:
mod *= confidence_factor
// And only after that update the new confidence factor
confidence_factor -= ((confidence_factor - 1.0f) * confidence_mod) / confidence_factor;
*/
// Real rating modification
mod *= 24.0f;
return (int32)ceil(mod);
}
int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float confidence_factor*/)
{
// 'Chance' calculation - to beat the opponent
// This is a simulation. Not much info on how it really works
float chance = GetChanceAgainst(ownRating, opponentRating);
float won_mod = (won) ? 1.0f : 0.0f;
// Calculate the rating modification
float mod;
// TODO: Replace this hack with using the confidence factor (limiting the factor to 2.0f)
if (won && ownRating < 1300)
{
if (ownRating < 1000)
mod = 48.0f * (won_mod - chance);
else
mod = (24.0f + (24.0f * (1300.0f - float(ownRating)) / 300.0f)) * (won_mod - chance);
}
else
mod = 24.0f * (won_mod - chance);
return (int32)ceil(mod);
}
void ArenaTeam::FinishGame(int32 mod, const Map* bgMap)
{
// Rating can only drop to 0
if (int32(Stats.Rating) + mod < 0)
Stats.Rating = 0;
else
{
Stats.Rating += mod;
// Check if rating related achivements are met
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* member = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
if (member->FindMap() == bgMap)
member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING, Stats.Rating, Type);
}
// Update number of games played per season or week
Stats.WeekGames += 1;
Stats.SeasonGames += 1;
// Update team's rank, start with rank 1 and increase until no team with more rating was found
Stats.Rank = 1;
ArenaTeamMgr::ArenaTeamContainer::const_iterator i = sArenaTeamMgr->GetArenaTeamMapBegin();
for (; i != sArenaTeamMgr->GetArenaTeamMapEnd(); ++i)
{
if (i->second->GetType() == Type && i->second->GetStats().Rating > Stats.Rating)
++Stats.Rank;
}
}
int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap)
{
// Called when the team has won
// Change in Matchmaker rating
int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, true);
// Change in Team Rating
rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, true);
// Modify the team stats accordingly
FinishGame(rating_change, bgMap);
// Update number of wins per season and week
Stats.WeekWins += 1;
Stats.SeasonWins += 1;
// Return the rating change, used to display it on the results screen
return mod;
}
int32 ArenaTeam::LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap)
{
// Called when the team has lost
// Change in Matchmaker Rating
int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, false);
// Change in Team Rating
rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, false);
// Modify the team stats accordingly
FinishGame(rating_change, bgMap);
// return the rating change, used to display it on the results screen
return mod;
}
void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// Called for each participant of a match after losing
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == player->GetGUID())
{
// Update personal rating
int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false);
itr->ModifyPersonalRating(player, mod, GetType());
// Update matchmaker rating
itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
// Update personal played stats
itr->WeekGames +=1;
itr->SeasonGames +=1;
// update the unit fields
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->WeekGames);
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->SeasonGames);
return;
}
}
}
void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// called for each participant after winning a match
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == player->GetGUID())
{
// update personal rating
int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true);
itr->ModifyPersonalRating(player, mod, GetType());
// update matchmaker rating (pussywizard: but don't allow it to go over team rating)
if (itr->MatchMakerRating < Stats.Rating)
{
mod = std::min(MatchmakerRatingChange, Stats.Rating - itr->MatchMakerRating);
itr->ModifyMatchmakerRating(mod, GetSlot());
}
// update personal stats
itr->WeekGames +=1;
itr->SeasonGames +=1;
itr->SeasonWins += 1;
itr->WeekWins += 1;
// update unit fields
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->WeekGames);
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->SeasonGames);
return;
}
}
}
void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& playerPoints)
{
// Called after a match has ended and the stats are already modified
// Helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
// 10 played games per week is a minimum
if (Stats.WeekGames < 10)
return;
// To get points, a player has to participate in at least 30% of the matches
uint32 requiredGames = (uint32)ceil(Stats.WeekGames * 0.3f);
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
// The player participated in enough games, update his points
uint32 pointsToAdd = 0;
if (itr->WeekGames >= requiredGames)
pointsToAdd = GetPoints(itr->PersonalRating);
std::map<uint32, uint32>::iterator plr_itr = playerPoints.find(GUID_LOPART(itr->Guid));
if (plr_itr != playerPoints.end())
{
// Check if there is already more points
if (plr_itr->second < pointsToAdd)
playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
}
else
playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
}
}
void ArenaTeam::SaveToDB()
{
// Save team and member stats to db
// Called after a match has ended or when calculating arena_points
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_STATS);
stmt->setUInt16(0, Stats.Rating);
stmt->setUInt16(1, Stats.WeekGames);
stmt->setUInt16(2, Stats.WeekWins);
stmt->setUInt16(3, Stats.SeasonGames);
stmt->setUInt16(4, Stats.SeasonWins);
stmt->setUInt32(5, Stats.Rank);
stmt->setUInt32(6, GetId());
trans->Append(stmt);
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_MEMBER);
stmt->setUInt16(0, itr->PersonalRating);
stmt->setUInt16(1, itr->WeekGames);
stmt->setUInt16(2, itr->WeekWins);
stmt->setUInt16(3, itr->SeasonGames);
stmt->setUInt16(4, itr->SeasonWins);
stmt->setUInt32(5, GetId());
stmt->setUInt32(6, GUID_LOPART(itr->Guid));
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHARACTER_ARENA_STATS);
stmt->setUInt32(0, GUID_LOPART(itr->Guid));
stmt->setUInt8(1, GetSlot());
stmt->setUInt16(2, itr->MatchMakerRating);
stmt->setUInt16(3, itr->MaxMMR);
trans->Append(stmt);
}
CharacterDatabase.CommitTransaction(trans);
}
void ArenaTeam::FinishWeek()
{
// Reset team stats
Stats.WeekGames = 0;
Stats.WeekWins = 0;
// Reset member stats
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
itr->WeekGames = 0;
itr->WeekWins = 0;
}
}
bool ArenaTeam::IsFighting() const
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(itr->Guid))
if (player->GetMap()->IsBattleArena())
return true;
return false;
}
ArenaTeamMember* ArenaTeam::GetMember(const std::string& name)
{
return GetMember(sObjectMgr->GetPlayerGUIDByName(name));
}
ArenaTeamMember* ArenaTeam::GetMember(uint64 guid)
{
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (itr->Guid == guid)
return &(*itr);
return NULL;
}
+205
View File
@@ -0,0 +1,205 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SUNWELLCORE_ARENATEAM_H
#define SUNWELLCORE_ARENATEAM_H
#include "QueryResult.h"
#include "Map.h"
#include <ace/Singleton.h>
#include <list>
#include <map>
class WorldSession;
class WorldPacket;
class Player;
class Group;
enum ArenaTeamCommandTypes
{
ERR_ARENA_TEAM_CREATE_S = 0x00,
ERR_ARENA_TEAM_INVITE_SS = 0x01,
ERR_ARENA_TEAM_QUIT_S = 0x03,
ERR_ARENA_TEAM_FOUNDER_S = 0x0E
};
enum ArenaTeamCommandErrors
{
ERR_ARENA_TEAM_INTERNAL = 0x01,
ERR_ALREADY_IN_ARENA_TEAM = 0x02,
ERR_ALREADY_IN_ARENA_TEAM_S = 0x03,
ERR_INVITED_TO_ARENA_TEAM = 0x04,
ERR_ALREADY_INVITED_TO_ARENA_TEAM_S = 0x05,
ERR_ARENA_TEAM_NAME_INVALID = 0x06,
ERR_ARENA_TEAM_NAME_EXISTS_S = 0x07,
ERR_ARENA_TEAM_LEADER_LEAVE_S = 0x08,
ERR_ARENA_TEAM_PERMISSIONS = 0x08,
ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM = 0x09,
ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS = 0x0A,
ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S = 0x0B,
ERR_ARENA_TEAM_NOT_ALLIED = 0x0C,
ERR_ARENA_TEAM_IGNORING_YOU_S = 0x13,
ERR_ARENA_TEAM_TARGET_TOO_LOW_S = 0x15,
ERR_ARENA_TEAM_TARGET_TOO_HIGH_S = 0x16,
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S = 0x17,
ERR_ARENA_TEAM_NOT_FOUND = 0x1B,
ERR_ARENA_TEAMS_LOCKED = 0x1E
};
enum ArenaTeamEvents
{
ERR_ARENA_TEAM_JOIN_SS = 3, // player name + arena team name
ERR_ARENA_TEAM_LEAVE_SS = 4, // player name + arena team name
ERR_ARENA_TEAM_REMOVE_SSS = 5, // player name + arena team name + captain name
ERR_ARENA_TEAM_LEADER_IS_SS = 6, // player name + arena team name
ERR_ARENA_TEAM_LEADER_CHANGED_SSS = 7, // old captain + new captain + arena team name
ERR_ARENA_TEAM_DISBANDED_S = 8 // captain name + arena team name
};
/*
need info how to send these ones:
ERR_ARENA_TEAM_YOU_JOIN_S - client show it automatically when accept invite
ERR_ARENA_TEAM_TARGET_TOO_LOW_S
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S
ERR_ARENA_TEAM_LEVEL_TOO_LOW_I
*/
enum ArenaTeamTypes
{
ARENA_TEAM_2v2 = 2,
ARENA_TEAM_3v3 = 3,
ARENA_TEAM_5v5 = 5
};
struct ArenaTeamMember
{
uint64 Guid;
//std::string Name;
uint8 Class;
uint16 WeekGames;
uint16 WeekWins;
uint16 SeasonGames;
uint16 SeasonWins;
uint16 PersonalRating;
uint16 MatchMakerRating;
uint16 MaxMMR;
void ModifyPersonalRating(Player* player, int32 mod, uint32 type);
void ModifyMatchmakerRating(int32 mod, uint32 slot);
};
struct ArenaTeamStats
{
uint16 Rating;
uint16 WeekGames;
uint16 WeekWins;
uint16 SeasonGames;
uint16 SeasonWins;
uint32 Rank;
};
#define MAX_ARENA_SLOT 3 // 0..2 slots
class ArenaTeam
{
public:
ArenaTeam();
~ArenaTeam();
bool Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor);
void Disband(WorldSession* session);
typedef std::list<ArenaTeamMember> MemberList;
uint32 GetId() const { return TeamId; }
uint32 GetType() const { return Type; }
uint8 GetSlot() const { return GetSlotByType(GetType()); }
static uint8 GetSlotByType(uint32 type);
uint64 GetCaptain() const { return CaptainGuid; }
std::string const& GetName() const { return TeamName; }
const ArenaTeamStats& GetStats() const { return Stats; }
uint32 GetRating() const { return Stats.Rating; }
uint32 GetAverageMMR(Group* group) const;
void SetCaptain(uint64 guid);
bool AddMember(uint64 playerGuid);
// Shouldn't be uint64 ed, because than can reference guid from members on Disband
// and this method removes given record from list. So invalid reference can happen.
void DelMember(uint64 guid, bool cleanDb);
size_t GetMembersSize() const { return Members.size(); }
bool Empty() const { return Members.empty(); }
MemberList::iterator m_membersBegin() { return Members.begin(); }
MemberList::iterator m_membersEnd() { return Members.end(); }
bool IsMember(uint64 guid) const;
ArenaTeamMember* GetMember(uint64 guid);
ArenaTeamMember* GetMember(std::string const& name);
bool IsFighting() const;
bool LoadArenaTeamFromDB(QueryResult arenaTeamDataResult);
bool LoadMembersFromDB(QueryResult arenaTeamMembersResult);
void LoadStatsFromDB(uint32 ArenaTeamId);
void SaveToDB();
void BroadcastPacket(WorldPacket* packet);
void BroadcastEvent(ArenaTeamEvents event, uint64 guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3);
void NotifyStatsChanged();
void MassInviteToEvent(WorldSession* session);
void Roster(WorldSession* session);
void Query(WorldSession* session);
void SendStats(WorldSession* session);
void Inspect(WorldSession* session, uint64 guid);
uint32 GetPoints(uint32 MemberRating);
int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
int32 WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap);
void MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange);
int32 LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap);
void MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
void FinishWeek();
void FinishGame(int32 mod, const Map* bgMap);
protected:
uint32 TeamId;
uint8 Type;
std::string TeamName;
uint64 CaptainGuid;
uint32 BackgroundColor; // ARGB format
uint8 EmblemStyle; // icon id
uint32 EmblemColor; // ARGB format
uint8 BorderStyle; // border image id
uint32 BorderColor; // ARGB format
MemberList Members;
ArenaTeamStats Stats;
};
#endif
@@ -0,0 +1,195 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Define.h"
#include "ArenaTeamMgr.h"
#include "World.h"
#include "Log.h"
#include "DatabaseEnv.h"
#include "Language.h"
#include "ObjectAccessor.h"
#include "Player.h"
ArenaTeamMgr::ArenaTeamMgr()
{
NextArenaTeamId = 1;
LastArenaLogId = 0;
}
ArenaTeamMgr::~ArenaTeamMgr()
{
for (ArenaTeamContainer::iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr)
delete itr->second;
}
// Arena teams collection
ArenaTeam* ArenaTeamMgr::GetArenaTeamById(uint32 arenaTeamId) const
{
ArenaTeamContainer::const_iterator itr = ArenaTeamStore.find(arenaTeamId);
if (itr != ArenaTeamStore.end())
return itr->second;
return NULL;
}
ArenaTeam* ArenaTeamMgr::GetArenaTeamByName(const std::string& arenaTeamName) const
{
std::string search = arenaTeamName;
std::transform(search.begin(), search.end(), search.begin(), ::toupper);
for (ArenaTeamContainer::const_iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr)
{
std::string teamName = itr->second->GetName();
std::transform(teamName.begin(), teamName.end(), teamName.begin(), ::toupper);
if (search == teamName)
return itr->second;
}
return NULL;
}
ArenaTeam* ArenaTeamMgr::GetArenaTeamByCaptain(uint64 guid) const
{
for (ArenaTeamContainer::const_iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr)
if (itr->second->GetCaptain() == guid)
return itr->second;
return NULL;
}
void ArenaTeamMgr::AddArenaTeam(ArenaTeam* arenaTeam)
{
ArenaTeamStore[arenaTeam->GetId()] = arenaTeam;
}
void ArenaTeamMgr::RemoveArenaTeam(uint32 arenaTeamId)
{
ArenaTeamStore.erase(arenaTeamId);
}
uint32 ArenaTeamMgr::GenerateArenaTeamId()
{
if (NextArenaTeamId >= 0xFFFFFFFE)
{
sLog->outError("Arena team ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
return NextArenaTeamId++;
}
void ArenaTeamMgr::LoadArenaTeams()
{
uint32 oldMSTime = getMSTime();
// Clean out the trash before loading anything
CharacterDatabase.Execute("DELETE FROM arena_team_member WHERE arenaTeamId NOT IN (SELECT arenaTeamId FROM arena_team)"); // One-time query
// 0 1 2 3 4 5 6 7 8
QueryResult result = CharacterDatabase.Query("SELECT arenaTeamId, name, captainGuid, type, backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor, "
// 9 10 11 12 13 14
"rating, weekGames, weekWins, seasonGames, seasonWins, rank FROM arena_team ORDER BY arenaTeamId ASC");
if (!result)
{
sLog->outString(">> Loaded 0 arena teams. DB table `arena_team` is empty!");
sLog->outString();
return;
}
QueryResult result2 = CharacterDatabase.Query(
// 0 1 2 3 4 5 6 7 8 9 10
"SELECT arenaTeamId, atm.guid, atm.weekGames, atm.weekWins, atm.seasonGames, atm.seasonWins, c.name, class, personalRating, matchMakerRating, maxMMR FROM arena_team_member atm"
" INNER JOIN arena_team ate USING (arenaTeamId)"
" LEFT JOIN characters AS c ON atm.guid = c.guid"
" LEFT JOIN character_arena_stats AS cas ON c.guid = cas.guid AND (cas.slot = 0 AND ate.type = 2 OR cas.slot = 1 AND ate.type = 3 OR cas.slot = 2 AND ate.type = 5)"
" ORDER BY atm.arenateamid ASC");
uint32 count = 0;
do
{
ArenaTeam* newArenaTeam = new ArenaTeam;
if (!newArenaTeam->LoadArenaTeamFromDB(result) || !newArenaTeam->LoadMembersFromDB(result2))
{
newArenaTeam->Disband(NULL);
delete newArenaTeam;
continue;
}
AddArenaTeam(newArenaTeam);
++count;
}
while (result->NextRow());
sLog->outString(">> Loaded %u arena teams in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void ArenaTeamMgr::DistributeArenaPoints()
{
// Used to distribute arena points based on last week's stats
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_START);
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START);
// Temporary structure for storing maximum points to add values for all players
std::map<uint32, uint32> PlayerPoints;
// At first update all points for all team members
for (ArenaTeamContainer::iterator teamItr = GetArenaTeamMapBegin(); teamItr != GetArenaTeamMapEnd(); ++teamItr)
if (ArenaTeam* at = teamItr->second)
at->UpdateArenaPointsHelper(PlayerPoints);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt;
// Cycle that gives points to all players
for (std::map<uint32, uint32>::iterator playerItr = PlayerPoints.begin(); playerItr != PlayerPoints.end(); ++playerItr)
{
// Add points to player if online
if (Player* player = HashMapHolder<Player>::Find(playerItr->first))
player->ModifyArenaPoints(playerItr->second, &trans);
else // Update database
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ARENA_POINTS);
stmt->setUInt32(0, playerItr->second);
stmt->setUInt32(1, playerItr->first);
trans->Append(stmt);
}
}
CharacterDatabase.CommitTransaction(trans);
PlayerPoints.clear();
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END);
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
for (ArenaTeamContainer::iterator titr = GetArenaTeamMapBegin(); titr != GetArenaTeamMapEnd(); ++titr)
{
if (ArenaTeam* at = titr->second)
{
at->FinishWeek();
at->SaveToDB();
at->NotifyStatsChanged();
}
}
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_END);
}
@@ -0,0 +1,59 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENATEAMMGR_H
#define _ARENATEAMMGR_H
#include "ArenaTeam.h"
class ArenaTeamMgr
{
friend class ACE_Singleton<ArenaTeamMgr, ACE_Null_Mutex>;
ArenaTeamMgr();
~ArenaTeamMgr();
public:
typedef UNORDERED_MAP<uint32, ArenaTeam*> ArenaTeamContainer;
ArenaTeam* GetArenaTeamById(uint32 arenaTeamId) const;
ArenaTeam* GetArenaTeamByName(std::string const& arenaTeamName) const;
ArenaTeam* GetArenaTeamByCaptain(uint64 guid) const;
void LoadArenaTeams();
void AddArenaTeam(ArenaTeam* arenaTeam);
void RemoveArenaTeam(uint32 Id);
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
void DistributeArenaPoints();
uint32 GenerateArenaTeamId();
void SetNextArenaTeamId(uint32 Id) { NextArenaTeamId = Id; }
uint32 GetNextArenaLogId() { return ++LastArenaLogId; }
void SetLastArenaLogId(uint32 id) { LastArenaLogId = id; }
protected:
uint32 NextArenaTeamId;
ArenaTeamContainer ArenaTeamStore;
uint32 LastArenaLogId;
};
#define sArenaTeamMgr ACE_Singleton<ArenaTeamMgr, ACE_Null_Mutex>::instance()
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,720 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUND_H
#define __BATTLEGROUND_H
#include "Common.h"
#include "SharedDefines.h"
#include "DBCEnums.h"
#include "GameObject.h"
class Creature;
class GameObject;
class Group;
class Player;
class WorldPacket;
class BattlegroundMap;
class BattlegroundAV;
class BattlegroundWS;
class BattlegroundAB;
class BattlegroundNA;
class BattlegroundBE;
class BattlegroundEY;
class BattlegroundRL;
class BattlegroundSA;
class BattlegroundDS;
class BattlegroundRV;
class BattlegroundIC;
struct PvPDifficultyEntry;
struct WorldSafeLocsEntry;
enum BattlegroundSounds
{
SOUND_HORDE_WINS = 8454,
SOUND_ALLIANCE_WINS = 8455,
SOUND_BG_START = 3439,
SOUND_BG_START_L70ETC = 11803,
};
enum BattlegroundQuests
{
SPELL_WS_QUEST_REWARD = 43483,
SPELL_AB_QUEST_REWARD = 43484,
SPELL_AV_QUEST_REWARD = 43475,
SPELL_AV_QUEST_KILLED_BOSS = 23658,
SPELL_EY_QUEST_REWARD = 43477,
SPELL_SA_QUEST_REWARD = 61213,
SPELL_AB_QUEST_REWARD_4_BASES = 24061,
SPELL_AB_QUEST_REWARD_5_BASES = 24064
};
enum BattlegroundMarks
{
SPELL_WS_MARK_LOSER = 24950,
SPELL_WS_MARK_WINNER = 24951,
SPELL_AB_MARK_LOSER = 24952,
SPELL_AB_MARK_WINNER = 24953,
SPELL_AV_MARK_LOSER = 24954,
SPELL_AV_MARK_WINNER = 24955,
SPELL_SA_MARK_WINNER = 61160,
SPELL_SA_MARK_LOSER = 61159,
SPELL_WG_MARK_WINNER = 56902,
ITEM_AV_MARK_OF_HONOR = 20560,
ITEM_WS_MARK_OF_HONOR = 20558,
ITEM_AB_MARK_OF_HONOR = 20559,
ITEM_EY_MARK_OF_HONOR = 29024,
ITEM_SA_MARK_OF_HONOR = 42425,
ITEM_IC_MARK_OF_HONOR = 47395,
};
enum BattlegroundMarksCount
{
ITEM_WINNER_COUNT = 3,
ITEM_LOSER_COUNT = 1
};
enum BattlegroundCreatures
{
BG_CREATURE_ENTRY_A_SPIRITGUIDE = 13116, // alliance
BG_CREATURE_ENTRY_H_SPIRITGUIDE = 13117, // horde
};
enum BattlegroundSpells
{
SPELL_WAITING_FOR_RESURRECT = 2584, // Waiting to Resurrect
SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel
SPELL_SPIRIT_HEAL = 22012, // Spirit Heal
SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual
SPELL_ARENA_PREPARATION = 32727, // use this one, 32728 not correct
SPELL_ALLIANCE_GOLD_FLAG = 32724,
SPELL_ALLIANCE_GREEN_FLAG = 32725,
SPELL_HORDE_GOLD_FLAG = 35774,
SPELL_HORDE_GREEN_FLAG = 35775,
SPELL_PREPARATION = 44521, // Preparation
SPELL_SPIRIT_HEAL_MANA = 44535, // Spirit Heal
SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag
SPELL_AURA_PLAYER_INACTIVE = 43681, // Inactive
SPELL_HONORABLE_DEFENDER_25Y = 68652, // +50% honor when standing at a capture point that you control, 25yards radius (added in 3.2)
SPELL_HONORABLE_DEFENDER_60Y = 66157, // +50% honor when standing at a capture point that you control, 60yards radius (added in 3.2), probably for 40+ player battlegrounds
SPELL_THE_LAST_STANDING = 26549, // Arena achievement related
};
enum BattlegroundTimeIntervals
{
CHECK_PLAYER_POSITION_INVERVAL = 9000, // ms
RESURRECTION_INTERVAL = 30000, // ms
//REMIND_INTERVAL = 10000, // ms
INVITATION_REMIND_TIME = 20000, // ms
INVITE_ACCEPT_WAIT_TIME = 60000, // ms
TIME_TO_AUTOREMOVE = 120000, // ms
MAX_OFFLINE_TIME = 300, // secs
RESPAWN_ONE_DAY = 86400, // secs
RESPAWN_IMMEDIATELY = 0, // secs
BUFF_RESPAWN_TIME = 180, // secs
};
enum BattlegroundStartTimeIntervals
{
BG_START_DELAY_2M = 120000, // ms (2 minutes)
BG_START_DELAY_1M = 60000, // ms (1 minute)
BG_START_DELAY_30S = 30000, // ms (30 seconds)
BG_START_DELAY_15S = 15000, // ms (15 seconds) Used only in arena
BG_START_DELAY_NONE = 0, // ms
};
#define BATTLEGROUND_UPDATE_INTERVAL 1000
enum BattlegroundBuffObjects
{
BG_OBJECTID_SPEEDBUFF_ENTRY = 179871,
BG_OBJECTID_REGENBUFF_ENTRY = 179904,
BG_OBJECTID_BERSERKERBUFF_ENTRY = 179905
};
enum BattlegroundRandomRewards
{
BG_REWARD_WINNER_HONOR_FIRST = 30,
BG_REWARD_WINNER_ARENA_FIRST = 25,
BG_REWARD_WINNER_HONOR_LAST = 15,
BG_REWARD_WINNER_ARENA_LAST = 0,
BG_REWARD_LOSER_HONOR_FIRST = 5,
BG_REWARD_LOSER_HONOR_LAST = 5
};
const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY };
enum BattlegroundStatus
{
STATUS_NONE = 0, // first status, should mean bg is not instance
STATUS_WAIT_QUEUE = 1, // means bg is empty and waiting for queue
STATUS_WAIT_JOIN = 2, // this means, that BG has already started and it is waiting for more players
STATUS_IN_PROGRESS = 3, // means bg is running
STATUS_WAIT_LEAVE = 4 // means some faction has won BG and it is ending
};
enum BattlegroundTeams
{
BG_TEAMS_COUNT = 2
};
struct BattlegroundObjectInfo
{
BattlegroundObjectInfo() : object(NULL), timer(0), spellid(0) {}
GameObject *object;
int32 timer;
uint32 spellid;
};
enum ScoreType
{
SCORE_KILLING_BLOWS = 1,
SCORE_DEATHS = 2,
SCORE_HONORABLE_KILLS = 3,
SCORE_BONUS_HONOR = 4,
//EY, but in MSG_PVP_LOG_DATA opcode!
SCORE_DAMAGE_DONE = 5,
SCORE_HEALING_DONE = 6,
//WS
SCORE_FLAG_CAPTURES = 7,
SCORE_FLAG_RETURNS = 8,
//AB and IC
SCORE_BASES_ASSAULTED = 9,
SCORE_BASES_DEFENDED = 10,
//AV
SCORE_GRAVEYARDS_ASSAULTED = 11,
SCORE_GRAVEYARDS_DEFENDED = 12,
SCORE_TOWERS_ASSAULTED = 13,
SCORE_TOWERS_DEFENDED = 14,
SCORE_MINES_CAPTURED = 15,
SCORE_LEADERS_KILLED = 16,
SCORE_SECONDARY_OBJECTIVES = 17,
//SOTA
SCORE_DESTROYED_DEMOLISHER = 18,
SCORE_DESTROYED_WALL = 19,
};
enum ArenaType
{
ARENA_TYPE_2v2 = 2,
ARENA_TYPE_3v3 = 3,
ARENA_TYPE_5v5 = 5
};
enum BattlegroundType
{
TYPE_BATTLEGROUND = 3,
TYPE_ARENA = 4
};
enum BattlegroundStartingEvents
{
BG_STARTING_EVENT_NONE = 0x00,
BG_STARTING_EVENT_1 = 0x01,
BG_STARTING_EVENT_2 = 0x02,
BG_STARTING_EVENT_3 = 0x04,
BG_STARTING_EVENT_4 = 0x08
};
enum BattlegroundStartingEventsIds
{
BG_STARTING_EVENT_FIRST = 0,
BG_STARTING_EVENT_SECOND = 1,
BG_STARTING_EVENT_THIRD = 2,
BG_STARTING_EVENT_FOURTH = 3
};
#define BG_STARTING_EVENT_COUNT 4
struct BattlegroundScore
{
BattlegroundScore(Player* player) : KillingBlows(0), Deaths(0), HonorableKills(0), BonusHonor(0),
DamageDone(0), HealingDone(0), player(player)
{ }
virtual ~BattlegroundScore() { } //virtual destructor is used when deleting score from scores map
uint32 KillingBlows;
uint32 Deaths;
uint32 HonorableKills;
uint32 BonusHonor;
uint32 DamageDone;
uint32 HealingDone;
Player* player;
};
class ArenaLogEntryData
{
public:
ArenaLogEntryData() : Guid(0), ArenaTeamId(0), DamageDone(0), HealingDone(0), KillingBlows(0) {}
void Fill(const char* name, uint32 guid, uint32 acc, uint32 arenaTeamId, std::string ip)
{
Name = std::string(name);
Guid = guid;
Acc = acc;
ArenaTeamId = arenaTeamId;
IP = ip;
}
std::string Name;
uint32 Guid;
uint32 Acc;
uint32 ArenaTeamId;
std::string IP;
uint32 DamageDone;
uint32 HealingDone;
uint32 KillingBlows;
};
enum BGHonorMode
{
BG_NORMAL = 0,
BG_HOLIDAY,
BG_HONOR_MODE_NUM
};
#define BG_AWARD_ARENA_POINTS_MIN_LEVEL 71
#define ARENA_TIMELIMIT_POINTS_LOSS -16
#define ARENA_READY_MARKER_ENTRY 301337
/*
This class is used to:
1. Add player to battleground
2. Remove player from battleground
3. some certain cases, same for all battlegrounds
4. It has properties same for all battlegrounds
*/
class Battleground
{
public:
Battleground();
virtual ~Battleground();
void Update(uint32 diff);
virtual bool SetupBattleground() // must be implemented in BG subclass
{
return true;
}
virtual void Init();
virtual void StartingEventCloseDoors() { }
virtual void StartingEventOpenDoors() { }
virtual void ResetBGSubclass() { } // must be implemented in BG subclass
virtual void DestroyGate(Player* /*player*/, GameObject* /*go*/) {}
/* achievement req. */
virtual bool AllNodesConrolledByTeam(TeamId /*teamId*/) const { return false; }
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
/* Battleground */
// Get methods:
char const* GetName() const { return m_Name; }
BattlegroundTypeId GetBgTypeID() const { return m_RealTypeID; }
uint32 GetInstanceID() const { return m_InstanceID; }
BattlegroundStatus GetStatus() const { return m_Status; }
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
uint32 GetStartTime() const { return m_StartTime; }
uint32 GetEndTime() const { return m_EndTime; }
uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
uint32 GetMinLevel() const { return m_LevelMin; }
uint32 GetMaxLevel() const { return m_LevelMax; }
uint32 GetMaxPlayersPerTeam() const { return m_MaxPlayersPerTeam; }
uint32 GetMinPlayersPerTeam() const { return m_MinPlayersPerTeam; }
int32 GetStartDelayTime() const { return m_StartDelayTime; }
uint8 GetArenaType() const { return m_ArenaType; }
TeamId GetWinner() const { return m_WinnerId; }
uint32 GetScriptId() const { return ScriptId; }
uint32 GetBonusHonorFromKill(uint32 kills) const;
// Set methods:
void SetName(char const* Name) { m_Name = Name; }
void SetBgTypeID(BattlegroundTypeId TypeID) { m_RealTypeID = TypeID; }
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattlegroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
void SetStartTime(uint32 Time) { m_StartTime = Time; }
void SetEndTime(uint32 Time) { m_EndTime = Time; }
void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
void SetLevelRange(uint32 min, uint32 max) { m_LevelMin = min; m_LevelMax = max; }
void SetRated(bool state) { m_IsRated = state; }
void SetArenaType(uint8 type) { m_ArenaType = type; }
void SetArenaorBGType(bool _isArena) { m_IsArena = _isArena; }
void SetWinner(TeamId winner) { m_WinnerId = winner; }
void SetScriptId(uint32 scriptId) { ScriptId = scriptId; }
void ModifyStartDelayTime(int32 diff) { m_StartDelayTime -= diff; }
void SetStartDelayTime(int32 Time) { m_StartDelayTime = Time; }
void SetMaxPlayersPerTeam(uint32 MaxPlayers) { m_MaxPlayersPerTeam = MaxPlayers; }
void SetMinPlayersPerTeam(uint32 MinPlayers) { m_MinPlayersPerTeam = MinPlayers; }
void DecreaseInvitedCount(TeamId teamId) { ASSERT(m_BgInvitedPlayers[teamId] > 0); --m_BgInvitedPlayers[teamId]; }
void IncreaseInvitedCount(TeamId teamId) { ++m_BgInvitedPlayers[teamId]; }
uint32 GetInvitedCount(TeamId teamId) const { return m_BgInvitedPlayers[teamId]; }
bool HasFreeSlots() const;
uint32 GetFreeSlotsForTeam(TeamId teamId) const;
uint32 GetMaxFreeSlots() const;
typedef std::set<Player*> SpectatorList;
typedef std::map<uint64, uint64> ToBeTeleportedMap;
void AddSpectator(Player* p) { m_Spectators.insert(p); }
void RemoveSpectator(Player* p) { m_Spectators.erase(p); }
bool HaveSpectators() { return !m_Spectators.empty(); }
const SpectatorList& GetSpectators() const { return m_Spectators; }
void AddToBeTeleported(uint64 spectator, uint64 participant) { m_ToBeTeleported[spectator] = participant; }
void RemoveToBeTeleported(uint64 spectator) { ToBeTeleportedMap::iterator itr = m_ToBeTeleported.find(spectator); if (itr != m_ToBeTeleported.end()) m_ToBeTeleported.erase(itr); }
void SpectatorsSendPacket(WorldPacket& data);
bool isArena() const { return m_IsArena; }
bool isBattleground() const { return !m_IsArena; }
bool isRated() const { return m_IsRated; }
typedef std::map<uint64, Player*> BattlegroundPlayerMap;
BattlegroundPlayerMap const& GetPlayers() const { return m_Players; }
uint32 GetPlayersSize() const { return m_Players.size(); }
void ReadyMarkerClicked(Player* p); // pussywizard
std::set<uint32> readyMarkerClickedSet; // pussywizard
typedef std::map<uint64, BattlegroundScore*> BattlegroundScoreMap;
typedef std::map<uint64, ArenaLogEntryData> ArenaLogEntryDataMap;// pussywizard
ArenaLogEntryDataMap ArenaLogEntries; // pussywizard
BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return PlayerScores.begin(); }
BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return PlayerScores.end(); }
uint32 GetPlayerScoresSize() const { return PlayerScores.size(); }
uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); }
void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid);
void RemovePlayerFromResurrectQueue(Player* player);
/// Relocate all players in ReviveQueue to the closest graveyard
void RelocateDeadPlayers(uint64 queueIndex);
void StartBattleground();
GameObject* GetBGObject(uint32 type);
Creature* GetBGCreature(uint32 type);
// Location
void SetMapId(uint32 MapID) { m_MapId = MapID; }
uint32 GetMapId() const { return m_MapId; }
// Map pointers
void SetBgMap(BattlegroundMap* map) { m_Map = map; }
BattlegroundMap* GetBgMap() const { ASSERT(m_Map); return m_Map; }
BattlegroundMap* FindBgMap() const { return m_Map; }
void SetTeamStartLoc(TeamId teamId, float X, float Y, float Z, float O);
void GetTeamStartLoc(TeamId teamId, float &X, float &Y, float &Z, float &O) const
{
X = m_TeamStartLocX[teamId];
Y = m_TeamStartLocY[teamId];
Z = m_TeamStartLocZ[teamId];
O = m_TeamStartLocO[teamId];
}
void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; }
float GetStartMaxDist() const { return m_StartMaxDist; }
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
void SendPacketToTeam(TeamId teamId, WorldPacket* packet, Player* sender = NULL, bool self = true);
void SendPacketToAll(WorldPacket* packet);
void YellToAll(Creature* creature, const char* text, uint32 language);
template<class Do>
void BroadcastWorker(Do& _do);
void PlaySoundToAll(uint32 soundId);
void CastSpellOnTeam(uint32 spellId, TeamId teamId);
void RemoveAuraOnTeam(uint32 spellId, TeamId teamId);
void RewardHonorToTeam(uint32 honor, TeamId teamId);
void RewardReputationToTeam(uint32 factionId, uint32 reputation, TeamId teamId);
void UpdateWorldState(uint32 Field, uint32 Value);
void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player);
void EndBattleground(TeamId winnerTeamId);
void BlockMovement(Player* player);
void SendWarningToAll(int32 entry, ...);
void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL);
void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...);
// specialized version with 2 string id args
void SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 strId1 = 0, int32 strId2 = 0);
// Raid Group
Group* GetBgRaid(TeamId teamId) const { return m_BgRaids[teamId]; }
void SetBgRaid(TeamId teamId, Group* bg_raid);
virtual void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
uint32 GetPlayersCountByTeam(TeamId teamId) const { return m_PlayersCount[teamId]; }
uint32 GetAlivePlayersCountByTeam(TeamId teamId) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
void UpdatePlayersCountByTeam(TeamId teamId, bool remove)
{
if (remove)
--m_PlayersCount[teamId];
else
++m_PlayersCount[teamId];
}
// used for rated arena battles
void SetArenaTeamIdForTeam(TeamId teamId, uint32 ArenaTeamId) { m_ArenaTeamIds[teamId] = ArenaTeamId; }
uint32 GetArenaTeamIdForTeam(TeamId teamId) const { return m_ArenaTeamIds[teamId]; }
void SetArenaTeamRatingChangeForTeam(TeamId teamId, int32 RatingChange) { m_ArenaTeamRatingChanges[teamId] = RatingChange; }
int32 GetArenaTeamRatingChangeForTeam(TeamId teamId) const { return m_ArenaTeamRatingChanges[teamId]; }
void SetArenaMatchmakerRating(TeamId teamId, uint32 MMR) { m_ArenaTeamMMR[teamId] = MMR; }
uint32 GetArenaMatchmakerRating(TeamId teamId) const { return m_ArenaTeamMMR[teamId]; }
void CheckArenaAfterTimerConditions();
void CheckArenaWinConditions();
virtual void UpdateArenaWorldState();
// Triggers handle
// must be implemented in BG subclass
virtual void HandleAreaTrigger(Player* /*player*/, uint32 /*trigger*/) {}
// must be implemented in BG subclass if need AND call base class generic code
virtual void HandleKillPlayer(Player* player, Player* killer);
virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/);
// Battleground events
virtual void EventPlayerDroppedFlag(Player* /*player*/) {}
virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*gameObject*/) {}
virtual void EventPlayerDamagedGO(Player* /*player*/, GameObject* /*go*/, uint32 /*eventType*/) {}
virtual void EventPlayerUsedGO(Player* /*player*/, GameObject* /*go*/){}
// this function can be used by spell to interact with the BG map
virtual void DoAction(uint32 /*action*/, uint64 /*var*/) {}
virtual void HandlePlayerResurrect(Player* /*player*/) {}
// Death related
virtual WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
virtual void AddPlayer(Player* player); // must be implemented in BG subclass
void AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId);
void RemovePlayerAtLeave(Player* player);
// can be extended in in BG subclass
void HandleTriggerBuff(GameObject* gameObject);
void SetHoliday(bool is_holiday);
// TODO: make this protected:
typedef std::vector<uint64> BGObjects;
typedef std::vector<uint64> BGCreatures;
BGObjects BgObjects;
BGCreatures BgCreatures;
void SpawnBGObject(uint32 type, uint32 respawntime);
bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0, GOState goState = GO_STATE_READY);
Creature* AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, uint32 respawntime = 0, MotionTransport* transport = NULL);
bool DelCreature(uint32 type);
bool DelObject(uint32 type);
bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, TeamId teamId);
int32 GetObjectType(uint64 guid);
void DoorOpen(uint32 type);
void DoorClose(uint32 type);
//to be removed
const char* GetTrinityString(int32 entry);
virtual bool HandlePlayerUnderMap(Player* /*player*/) { return false; }
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
static TeamId GetOtherTeamId(TeamId teamId);
bool IsPlayerInBattleground(uint64 guid) const;
bool ToBeDeleted() const { return m_SetDeleteThis; }
//void SetDeleteThis() { m_SetDeleteThis = true; }
void RewardXPAtKill(Player* killer, Player* victim);
virtual uint64 GetFlagPickerGUID(TeamId /*teamId*/ = TEAM_NEUTRAL) const { return 0; }
virtual void SetDroppedFlagGUID(uint64 /*guid*/, TeamId /*teamId*/ = TEAM_NEUTRAL) {}
uint32 GetTeamScore(TeamId teamId) const;
virtual TeamId GetPrematureWinner();
BattlegroundAV* ToBattlegroundAV() { if (GetBgTypeID() == BATTLEGROUND_AV) return reinterpret_cast<BattlegroundAV*>(this); else return NULL; }
BattlegroundAV const* ToBattlegroundAV() const { if (GetBgTypeID() == BATTLEGROUND_AV) return reinterpret_cast<const BattlegroundAV*>(this); else return NULL; }
BattlegroundWS* ToBattlegroundWS() { if (GetBgTypeID() == BATTLEGROUND_WS) return reinterpret_cast<BattlegroundWS*>(this); else return NULL; }
BattlegroundWS const* ToBattlegroundWS() const { if (GetBgTypeID() == BATTLEGROUND_WS) return reinterpret_cast<const BattlegroundWS*>(this); else return NULL; }
BattlegroundAB* ToBattlegroundAB() { if (GetBgTypeID() == BATTLEGROUND_AB) return reinterpret_cast<BattlegroundAB*>(this); else return NULL; }
BattlegroundAB const* ToBattlegroundAB() const { if (GetBgTypeID() == BATTLEGROUND_AB) return reinterpret_cast<const BattlegroundAB*>(this); else return NULL; }
BattlegroundNA* ToBattlegroundNA() { if (GetBgTypeID() == BATTLEGROUND_NA) return reinterpret_cast<BattlegroundNA*>(this); else return NULL; }
BattlegroundNA const* ToBattlegroundNA() const { if (GetBgTypeID() == BATTLEGROUND_NA) return reinterpret_cast<const BattlegroundNA*>(this); else return NULL; }
BattlegroundBE* ToBattlegroundBE() { if (GetBgTypeID() == BATTLEGROUND_BE) return reinterpret_cast<BattlegroundBE*>(this); else return NULL; }
BattlegroundBE const* ToBattlegroundBE() const { if (GetBgTypeID() == BATTLEGROUND_BE) return reinterpret_cast<const BattlegroundBE*>(this); else return NULL; }
BattlegroundEY* ToBattlegroundEY() { if (GetBgTypeID() == BATTLEGROUND_EY) return reinterpret_cast<BattlegroundEY*>(this); else return NULL; }
BattlegroundEY const* ToBattlegroundEY() const { if (GetBgTypeID() == BATTLEGROUND_EY) return reinterpret_cast<const BattlegroundEY*>(this); else return NULL; }
BattlegroundRL* ToBattlegroundRL() { if (GetBgTypeID() == BATTLEGROUND_RL) return reinterpret_cast<BattlegroundRL*>(this); else return NULL; }
BattlegroundRL const* ToBattlegroundRL() const { if (GetBgTypeID() == BATTLEGROUND_RL) return reinterpret_cast<const BattlegroundRL*>(this); else return NULL; }
BattlegroundSA* ToBattlegroundSA() { if (GetBgTypeID() == BATTLEGROUND_SA) return reinterpret_cast<BattlegroundSA*>(this); else return NULL; }
BattlegroundSA const* ToBattlegroundSA() const { if (GetBgTypeID() == BATTLEGROUND_SA) return reinterpret_cast<const BattlegroundSA*>(this); else return NULL; }
BattlegroundDS* ToBattlegroundDS() { if (GetBgTypeID() == BATTLEGROUND_DS) return reinterpret_cast<BattlegroundDS*>(this); else return NULL; }
BattlegroundDS const* ToBattlegroundDS() const { if (GetBgTypeID() == BATTLEGROUND_DS) return reinterpret_cast<const BattlegroundDS*>(this); else return NULL; }
BattlegroundRV* ToBattlegroundRV() { if (GetBgTypeID() == BATTLEGROUND_RV) return reinterpret_cast<BattlegroundRV*>(this); else return NULL; }
BattlegroundRV const* ToBattlegroundRV() const { if (GetBgTypeID() == BATTLEGROUND_RV) return reinterpret_cast<const BattlegroundRV*>(this); else return NULL; }
BattlegroundIC* ToBattlegroundIC() { if (GetBgTypeID() == BATTLEGROUND_IC) return reinterpret_cast<BattlegroundIC*>(this); else return NULL; }
BattlegroundIC const* ToBattlegroundIC() const { if (GetBgTypeID() == BATTLEGROUND_IC) return reinterpret_cast<const BattlegroundIC*>(this); else return NULL; }
protected:
// this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends Battleground
void EndNow();
void PlayerAddedToBGCheckIfBGIsRunning(Player* player);
void _ProcessResurrect(uint32 diff);
void _ProcessProgress(uint32 diff);
void _ProcessLeave(uint32 diff);
void _ProcessJoin(uint32 diff);
void _CheckSafePositions(uint32 diff);
// Scorekeeping
BattlegroundScoreMap PlayerScores; // Player scores
// must be implemented in BG subclass
virtual void RemovePlayer(Player* /*player*/) {}
// Player lists, those need to be accessible by inherited classes
BattlegroundPlayerMap m_Players;
// Spirit Guide guid + Player list GUIDS
std::map<uint64, std::vector<uint64> > m_ReviveQueue;
// these are important variables used for starting messages
uint8 m_Events;
BattlegroundStartTimeIntervals StartDelayTimes[BG_STARTING_EVENT_COUNT];
// this must be filled in constructors!
uint32 StartMessageIds[BG_STARTING_EVENT_COUNT];
bool m_BuffChange;
BGHonorMode m_HonorMode;
int32 m_TeamScores[BG_TEAMS_COUNT];
// pussywizard:
uint32 m_UpdateTimer;
private:
// Battleground
BattlegroundTypeId m_RealTypeID;
uint32 m_InstanceID; // Battleground Instance's GUID!
BattlegroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime;
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
bool m_IsArena;
TeamId m_WinnerId;
int32 m_StartDelayTime;
bool m_IsRated; // is this battle rated?
bool m_PrematureCountDown;
uint32 m_PrematureCountDownTimer;
char const* m_Name;
/* Pre- and post-update hooks */
/**
* @brief Pre-update hook.
*
* Will be called before battleground update is started. Depending on
* the result of this call actual update body may be skipped.
*
* @param diff a time difference between two worldserver update loops in
* milliseconds.
*
* @return @c true if update must be performed, @c false otherwise.
*
* @see Update(), PostUpdateImpl().
*/
virtual bool PreUpdateImpl(uint32 /* diff */) { return true; }
/**
* @brief Post-update hook.
*
* Will be called after battleground update has passed. May be used to
* implement custom update effects in subclasses.
*
* @param diff a time difference between two worldserver update loops in
* milliseconds.
*
* @see Update(), PreUpdateImpl().
*/
virtual void PostUpdateImpl(uint32 /* diff */) { }
// Player lists
std::vector<uint64> m_ResurrectQueue; // Player GUID
std::deque<uint64> m_OfflineQueue; // Player GUID
// Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction
// Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG
// Invited players counters
uint32 m_BgInvitedPlayers[BG_TEAMS_COUNT];
// Raid Group
Group* m_BgRaids[BG_TEAMS_COUNT]; // 0 - alliance, 1 - horde
SpectatorList m_Spectators;
ToBeTeleportedMap m_ToBeTeleported;
// Players count by team
uint32 m_PlayersCount[BG_TEAMS_COUNT];
// Arena team ids by team
uint32 m_ArenaTeamIds[BG_TEAMS_COUNT];
int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT];
uint32 m_ArenaTeamMMR[BG_TEAMS_COUNT];
// Limits
uint32 m_LevelMin;
uint32 m_LevelMax;
uint32 m_MaxPlayersPerTeam;
uint32 m_MinPlayersPerTeam;
// Start location
uint32 m_MapId;
BattlegroundMap* m_Map;
float m_TeamStartLocX[BG_TEAMS_COUNT];
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
float m_TeamStartLocO[BG_TEAMS_COUNT];
float m_StartMaxDist;
uint32 ScriptId;
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,168 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDMGR_H
#define __BATTLEGROUNDMGR_H
#include "Common.h"
#include "DBCEnums.h"
#include "Battleground.h"
#include "BattlegroundQueue.h"
#include "CreatureAIImpl.h"
#include <ace/Singleton.h>
typedef std::map<uint32, Battleground*> BattlegroundContainer;
typedef UNORDERED_MAP<uint32, BattlegroundTypeId> BattleMastersMap;
#define WS_ARENA_DISTRIBUTION_TIME 20001 // Custom worldstate
struct CreateBattlegroundData
{
BattlegroundTypeId bgTypeId;
bool IsArena;
uint32 MinPlayersPerTeam;
uint32 MaxPlayersPerTeam;
uint32 LevelMin;
uint32 LevelMax;
char* BattlegroundName;
uint32 MapID;
float Team1StartLocX;
float Team1StartLocY;
float Team1StartLocZ;
float Team1StartLocO;
float Team2StartLocX;
float Team2StartLocY;
float Team2StartLocZ;
float Team2StartLocO;
float StartMaxDist;
uint32 scriptId;
};
struct GroupQueueInfo;
// pussywizard
class RandomBattlegroundSystem
{
public:
RandomBattlegroundSystem();
void Update(uint32 diff);
BattlegroundTypeId GetCurrentRandomBg() const { return m_CurrentRandomBg; }
void BattlegroundCreated(BattlegroundTypeId bgTypeId);
private:
BattlegroundTypeId m_CurrentRandomBg;
uint32 m_SwitchTimer;
std::vector<BattlegroundTypeId> m_BgOrder;
};
class BattlegroundMgr
{
friend class ACE_Singleton<BattlegroundMgr, ACE_Null_Mutex>;
private:
BattlegroundMgr();
~BattlegroundMgr();
public:
void Update(uint32 diff);
/* Packet Building */
void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player);
void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid);
void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere);
void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result);
void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value);
void BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg);
void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, TeamId teamId, bool isRated = false, BattlegroundTypeId forceBgTypeId = BATTLEGROUND_TYPE_NONE);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, uint64 guid);
/* Battlegrounds */
Battleground* GetBattleground(uint32 InstanceID);
Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId);
Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, uint32 minLevel, uint32 maxLevel, uint8 arenaType, bool isRated);
void AddBattleground(Battleground* bg);
void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
void CreateInitialBattlegrounds();
void DeleteAllBattlegrounds();
void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId);
/* Battleground queues */
BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[bgQueueTypeId]; }
void ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id);
uint32 GetPrematureFinishTime() const;
static void InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId);
void ToggleArenaTesting();
void ToggleTesting();
void SetHolidayWeekends(uint32 mask);
bool isArenaTesting() const { return m_ArenaTesting; }
bool isTesting() const { return m_Testing; }
static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType);
static BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId);
static bool IsArenaType(BattlegroundTypeId bgTypeId);
static uint8 BGArenaType(BattlegroundQueueTypeId bgQueueTypeId);
static HolidayIds BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId);
static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday);
static bool IsBGWeekend(BattlegroundTypeId bgTypeId);
PvPDifficultyEntry randomBgDifficultyEntry;
uint32 GetRatingDiscardTimer() const;
void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry();
void CheckBattleMasters();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
{
BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry);
if (itr != mBattleMastersMap.end())
return itr->second;
return BATTLEGROUND_TYPE_NONE;
}
const BattlegroundContainer& GetBattlegroundList() { return m_Battlegrounds; } // pussywizard
RandomBattlegroundSystem RandomSystem; // pussywizard
private:
bool CreateBattleground(CreateBattlegroundData& data);
uint32 GetNextClientVisibleInstanceId();
typedef std::map<BattlegroundTypeId, Battleground*> BattlegroundTemplateContainer;
BattlegroundTemplateContainer m_BattlegroundTemplates;
BattlegroundContainer m_Battlegrounds;
BattlegroundQueue m_BattlegroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES];
std::vector<uint64> m_ArenaQueueUpdateScheduler;
uint32 m_lastClientVisibleInstanceId;
uint32 m_NextPeriodicQueueUpdateTime;
time_t m_NextAutoDistributionTime;
bool m_ArenaTesting;
bool m_Testing;
BattleMastersMap mBattleMastersMap;
};
#define sBattlegroundMgr ACE_Singleton<BattlegroundMgr, ACE_Null_Mutex>::instance()
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDQUEUE_H
#define __BATTLEGROUNDQUEUE_H
#include "Common.h"
#include "DBCEnums.h"
#include "Battleground.h"
#include "EventProcessor.h"
#include <deque>
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!)
{
std::set<uint64> Players; // player guid set
TeamId teamId; // Player team (TEAM_ALLIANCE/TEAM_HORDE)
BattlegroundTypeId BgTypeId; // battleground type id
bool IsRated; // rated
uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG
uint32 ArenaTeamId; // team id if rated match
uint32 JoinTime; // time when group was added
uint32 RemoveInviteTime; // time when we will remove invite for players in group
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
uint32 ArenaTeamRating; // if rated match, inited to the rating of the team
uint32 ArenaMatchmakerRating; // if rated match, inited to the rating of the team
uint32 OpponentsTeamRating; // for rated arena matches
uint32 OpponentsMatchmakerRating; // for rated arena matches
// pussywizard: for internal use
uint8 _bracketId;
uint8 _groupType;
};
enum BattlegroundQueueGroupTypes
{
BG_QUEUE_PREMADE_ALLIANCE = 0,
BG_QUEUE_PREMADE_HORDE = 1,
BG_QUEUE_NORMAL_ALLIANCE = 2,
BG_QUEUE_NORMAL_HORDE = 3
};
#define BG_QUEUE_GROUP_TYPES_COUNT 4
class Battleground;
class BattlegroundQueue
{
public:
BattlegroundQueue();
~BattlegroundQueue();
void BattlegroundQueueUpdate(BattlegroundBracketId bracket_id, uint8 actionMask, bool isRated, uint32 arenaRatedTeamId);
void UpdateEvents(uint32 diff);
void FillPlayersToBG(const int32 aliFree, const int32 hordeFree, BattlegroundBracketId bracket_id);
void FillPlayersToBGWithSpecific(const int32 aliFree, const int32 hordeFree, BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId);
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
bool CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
GroupQueueInfo* AddGroup(Player* leader, Group* group, PvPDifficultyEntry const* bracketEntry, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 ArenaTeamId);
void RemovePlayer(uint64 guid, bool sentToBg, uint32 playerQueueSlot);
bool IsPlayerInvitedToRatedArena(uint64 pl_guid);
bool IsPlayerInvited(uint64 pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime);
bool GetPlayerGroupInfoData(uint64 guid, GroupQueueInfo* ginfo);
void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo);
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo) const;
void SetBgTypeIdAndArenaType(BattlegroundTypeId b, uint8 a) { m_bgTypeId = b; m_arenaType = ArenaType(a); } // pussywizard
void AddEvent(BasicEvent* Event, uint64 e_time);
typedef std::map<uint64, GroupQueueInfo*> QueuedPlayersMap;
QueuedPlayersMap m_QueuedPlayers;
//do NOT use deque because deque.erase() invalidates ALL iterators
typedef std::list<GroupQueueInfo*> GroupsQueueType;
/*
This two dimensional array is used to store All queued groups
First dimension specifies the bgTypeId
Second dimension specifies the player's group types -
BG_QUEUE_PREMADE_ALLIANCE is used for premade alliance groups and alliance rated arena teams
BG_QUEUE_PREMADE_HORDE is used for premade horde groups and horde rated arena teams
BG_QUEUE_NORMAL_ALLIANCE is used for normal (or small) alliance groups or non-rated arena matches
BG_QUEUE_NORMAL_HORDE is used for normal (or small) horde groups or non-rated arena matches
*/
GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_BRACKETS][BG_QUEUE_GROUP_TYPES_COUNT];
// class to select and invite groups to bg
class SelectionPool
{
public:
SelectionPool(): PlayerCount(0) {};
void Init();
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
bool KickGroup(const uint32 size);
uint32 GetPlayerCount() const {return PlayerCount;}
public:
GroupsQueueType SelectedGroups;
private:
uint32 PlayerCount;
};
//one selection pool for horde, other one for alliance
SelectionPool m_SelectionPools[BG_TEAMS_COUNT];
private:
BattlegroundTypeId m_bgTypeId;
ArenaType m_arenaType;
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
uint32 m_WaitTimeLastIndex[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS];
// Event handler
EventProcessor m_events;
};
/*
This class is used to invite player to BG again, when minute lasts from his first invitation
it is capable to solve all possibilities
*/
class BGQueueInviteEvent : public BasicEvent
{
public:
BGQueueInviteEvent(uint64 pl_guid, uint32 BgInstanceGUID, BattlegroundTypeId BgTypeId, uint8 arenaType, uint32 removeTime) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_ArenaType(arenaType), m_RemoveTime(removeTime)
{ }
virtual ~BGQueueInviteEvent() { }
virtual bool Execute(uint64 e_time, uint32 p_time);
virtual void Abort(uint64 e_time);
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
BattlegroundTypeId m_BgTypeId;
uint8 m_ArenaType;
uint32 m_RemoveTime;
};
/*
This class is used to remove player from BG queue after 1 minute 20 seconds from first invitation
We must store removeInvite time in case player left queue and joined and is invited again
We must store bgQueueTypeId, because battleground can be deleted already, when player entered it
*/
class BGQueueRemoveEvent : public BasicEvent
{
public:
BGQueueRemoveEvent(uint64 pl_guid, uint32 bgInstanceGUID, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime)
: m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_RemoveTime(removeTime), m_BgQueueTypeId(bgQueueTypeId)
{}
virtual ~BGQueueRemoveEvent() {}
virtual bool Execute(uint64 e_time, uint32 p_time);
virtual void Abort(uint64 e_time);
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
uint32 m_RemoveTime;
BattlegroundQueueTypeId m_BgQueueTypeId;
};
#endif
@@ -0,0 +1,492 @@
/*
REWRITTEN BY XINEF
*/
#include "BattlegroundAB.h"
#include "World.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
#include "Language.h"
#include "Object.h"
#include "Player.h"
#include "Util.h"
#include "WorldSession.h"
BattlegroundAB::BattlegroundAB()
{
m_BuffChange = true;
BgObjects.resize(BG_AB_OBJECT_MAX);
BgCreatures.resize(BG_AB_ALL_NODES_COUNT + BG_AB_DYNAMIC_NODES_COUNT); // xinef: +BG_AB_DYNAMIC_NODES_COUNT buff triggers
_controlledPoints[TEAM_ALLIANCE] = 0;
_controlledPoints[TEAM_HORDE] = 0;
_teamScores500Disadvantage[TEAM_ALLIANCE] = false;
_teamScores500Disadvantage[TEAM_HORDE] = false;
_honorTics = 0;
_reputationTics = 0;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN;
}
BattlegroundAB::~BattlegroundAB()
{
}
void BattlegroundAB::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
_bgEvents.Update(diff);
while (uint32 eventId =_bgEvents.ExecuteEvent())
switch (eventId)
{
case BG_AB_EVENT_UPDATE_BANNER_STABLE:
case BG_AB_EVENT_UPDATE_BANNER_FARM:
case BG_AB_EVENT_UPDATE_BANNER_BLACKSMITH:
case BG_AB_EVENT_UPDATE_BANNER_LUMBERMILL:
case BG_AB_EVENT_UPDATE_BANNER_GOLDMINE:
CreateBanner(eventId - BG_AB_EVENT_UPDATE_BANNER_STABLE, false);
break;
case BG_AB_EVENT_CAPTURE_STABLE:
case BG_AB_EVENT_CAPTURE_FARM:
case BG_AB_EVENT_CAPTURE_BLACKSMITH:
case BG_AB_EVENT_CAPTURE_LUMBERMILL:
case BG_AB_EVENT_CAPTURE_GOLDMINE:
{
uint8 node = eventId - BG_AB_EVENT_CAPTURE_STABLE;
TeamId teamId = _capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED ? TEAM_ALLIANCE : TEAM_HORDE;
DeleteBanner(node);
_capturePointInfo[node]._ownerTeamId = teamId;
_capturePointInfo[node]._state = teamId == TEAM_ALLIANCE ? BG_AB_NODE_STATE_ALLY_OCCUPIED : BG_AB_NODE_STATE_HORDE_OCCUPIED;
_capturePointInfo[node]._captured = true;
CreateBanner(node, false);
NodeOccupied(node);
SendNodeUpdate(node);
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN, teamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, NULL, teamId == TEAM_ALLIANCE ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE, LANG_BG_AB_NODE_STABLES + node);
PlaySoundToAll(teamId == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_CAPTURED_ALLIANCE : BG_AB_SOUND_NODE_CAPTURED_HORDE);
break;
}
case BG_AB_EVENT_ALLIANCE_TICK:
case BG_AB_EVENT_HORDE_TICK:
{
TeamId teamId = TeamId(eventId - BG_AB_EVENT_ALLIANCE_TICK);
uint8 controlledPoints = _controlledPoints[teamId];
if (controlledPoints == 0)
{
_bgEvents.ScheduleEvent(eventId, 3000);
break;
}
uint8 honorRewards = uint8(m_TeamScores[teamId] / _honorTics);
uint8 reputationRewards = uint8(m_TeamScores[teamId] / _reputationTics);
uint8 information = uint8(m_TeamScores[teamId] / BG_AB_WARNING_NEAR_VICTORY_SCORE);
m_TeamScores[teamId] += BG_AB_TickPoints[controlledPoints];
if (m_TeamScores[teamId] > BG_AB_MAX_TEAM_SCORE)
m_TeamScores[teamId] = BG_AB_MAX_TEAM_SCORE;
if (honorRewards < uint8(m_TeamScores[teamId] / _honorTics))
RewardHonorToTeam(GetBonusHonorFromKill(1), teamId);
if (reputationRewards < uint8(m_TeamScores[teamId] / _reputationTics))
RewardReputationToTeam(teamId == TEAM_ALLIANCE ? 509 : 510, 10, teamId);
if (information < uint8(m_TeamScores[teamId] / BG_AB_WARNING_NEAR_VICTORY_SCORE))
{
SendMessageToAll(teamId == TEAM_ALLIANCE ? LANG_BG_AB_A_NEAR_VICTORY : LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY);
}
UpdateWorldState(teamId == TEAM_ALLIANCE ? BG_AB_OP_RESOURCES_ALLY : BG_AB_OP_RESOURCES_HORDE, m_TeamScores[teamId]);
if (m_TeamScores[teamId] > m_TeamScores[GetOtherTeamId(teamId)] + 500)
_teamScores500Disadvantage[GetOtherTeamId(teamId)] = true;
if (m_TeamScores[teamId] >= BG_AB_MAX_TEAM_SCORE)
EndBattleground(teamId);
_bgEvents.ScheduleEvent(eventId, BG_AB_TickIntervals[controlledPoints]);
break;
}
}
}
}
void BattlegroundAB::StartingEventCloseDoors()
{
for (uint32 obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * BG_AB_OBJECTS_PER_NODE; ++obj)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
// Starting doors
SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
DoorClose(BG_AB_OBJECT_GATE_A);
DoorClose(BG_AB_OBJECT_GATE_H);
}
void BattlegroundAB::StartingEventOpenDoors()
{
for (uint32 banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; banner += BG_AB_OBJECTS_PER_NODE, ++i)
SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + urand(0, 2) + i * 3, RESPAWN_IMMEDIATELY);
DoorOpen(BG_AB_OBJECT_GATE_A);
DoorOpen(BG_AB_OBJECT_GATE_H);
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_AB_EVENT_START_BATTLE);
_bgEvents.ScheduleEvent(BG_AB_EVENT_ALLIANCE_TICK, 3000);
_bgEvents.ScheduleEvent(BG_AB_EVENT_HORDE_TICK, 3000);
}
void BattlegroundAB::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundABScore(player);
}
void BattlegroundAB::RemovePlayer(Player* player)
{
player->SetPhaseMask(1, false);
}
void BattlegroundAB::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 3948: // Arathi Basin Alliance Exit.
if (player->GetTeamId() != TEAM_ALLIANCE)
player->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
else
player->LeaveBattleground();
break;
case 3949: // Arathi Basin Horde Exit.
if (player->GetTeamId() != TEAM_HORDE)
player->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
else
player->LeaveBattleground();
break;
case 3866: // Stables
case 3869: // Gold Mine
case 3867: // Farm
case 3868: // Lumber Mill
case 3870: // Black Smith
case 4020: // Unk1
case 4021: // Unk2
break;
}
}
void BattlegroundAB::CreateBanner(uint8 node, bool delay)
{
// Just put it into the queue
if (delay)
{
_bgEvents.RescheduleEvent(BG_AB_EVENT_UPDATE_BANNER_STABLE+node, BG_AB_BANNER_UPDATE_TIME);
return;
}
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + _capturePointInfo[node]._state, RESPAWN_IMMEDIATELY);
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_IMMEDIATELY);
}
void BattlegroundAB::DeleteBanner(uint8 node)
{
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + _capturePointInfo[node]._state, RESPAWN_ONE_DAY);
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_ONE_DAY);
}
void BattlegroundAB::FillInitialWorldStates(WorldPacket& data)
{
for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
{
if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_NEUTRAL)
data << uint32(_capturePointInfo[node]._iconNone) << uint32(1);
for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i)
data << uint32(_capturePointInfo[node]._iconCapture + i-1) << uint32(_capturePointInfo[node]._state == i);
}
data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(_controlledPoints[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(_controlledPoints[TEAM_HORDE]);
data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE);
data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE);
data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[TEAM_HORDE]);
data << uint32(0x745) << uint32(0x2); // 37 1861 unk
}
void BattlegroundAB::SendNodeUpdate(uint8 node)
{
UpdateWorldState(_capturePointInfo[node]._iconNone, 0);
for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i)
UpdateWorldState(_capturePointInfo[node]._iconCapture + i-1, _capturePointInfo[node]._state == i);
UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, _controlledPoints[TEAM_ALLIANCE]);
UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE, _controlledPoints[TEAM_HORDE]);
}
void BattlegroundAB::NodeOccupied(uint8 node)
{
ApplyPhaseMask();
AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], _capturePointInfo[node]._ownerTeamId);
++_controlledPoints[_capturePointInfo[node]._ownerTeamId];
if (_controlledPoints[_capturePointInfo[node]._ownerTeamId] >= 5)
CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, _capturePointInfo[node]._ownerTeamId);
if (_controlledPoints[_capturePointInfo[node]._ownerTeamId] >= 4)
CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, _capturePointInfo[node]._ownerTeamId);
Creature* trigger = GetBgMap()->GetCreature(BgCreatures[BG_AB_ALL_NODES_COUNT + node]);
if (!trigger)
trigger = AddCreature(WORLD_TRIGGER, BG_AB_ALL_NODES_COUNT + node, BG_AB_NodePositions[node][0], BG_AB_NodePositions[node][1], BG_AB_NodePositions[node][2], BG_AB_NodePositions[node][3]);
if (trigger)
{
trigger->setFaction(_capturePointInfo[node]._ownerTeamId == TEAM_ALLIANCE ? 84 : 83);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false);
}
}
void BattlegroundAB::NodeDeoccupied(uint8 node)
{
--_controlledPoints[_capturePointInfo[node]._ownerTeamId];
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
RelocateDeadPlayers(BgCreatures[node]);
DelCreature(node); // Delete spirit healer
DelCreature(BG_AB_ALL_NODES_COUNT + node); // Delete aura trigger
}
void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
{
if (GetStatus() != STATUS_IN_PROGRESS || !player->IsWithinDistInMap(gameObject, 10.0f))
return;
uint8 node = BG_AB_NODE_STABLES;
for (; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
if (player->GetDistance2d(BG_AB_NodePositions[node][0], BG_AB_NodePositions[node][1]) < 10.0f)
break;
if (node == BG_AB_DYNAMIC_NODES_COUNT || _capturePointInfo[node]._ownerTeamId == player->GetTeamId() ||
(_capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED && player->GetTeamId() == TEAM_ALLIANCE) ||
(_capturePointInfo[node]._state == BG_AB_NODE_STATE_HORDE_CONTESTED && player->GetTeamId() == TEAM_HORDE))
return;
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
uint32 sound = 0;
uint32 message = 0;
uint32 message2 = 0;
DeleteBanner(node);
CreateBanner(node, true);
if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_NEUTRAL)
{
player->KilledMonsterCredit(BG_AB_QUEST_CREDIT_BASE + node, 0);
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_CONTESTED + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
sound = BG_AB_SOUND_NODE_CLAIMED;
message = LANG_BG_AB_NODE_CLAIMED;
message2 = player->GetTeamId() == TEAM_ALLIANCE ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE;
}
else if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED || _capturePointInfo[node]._state == BG_AB_NODE_STATE_HORDE_CONTESTED)
{
if (!_capturePointInfo[node]._captured)
{
player->KilledMonsterCredit(BG_AB_QUEST_CREDIT_BASE + node, 0);
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_CONTESTED + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
message = LANG_BG_AB_NODE_ASSAULTED;
}
else
{
UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1);
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_OCCUPIED + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = player->GetTeamId();
_bgEvents.CancelEvent(BG_AB_EVENT_CAPTURE_STABLE + node);
NodeOccupied(node); // after setting team owner
message = LANG_BG_AB_NODE_DEFENDED;
}
sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
}
else
{
player->KilledMonsterCredit(BG_AB_QUEST_CREDIT_BASE + node, 0);
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
NodeDeoccupied(node); // before setting team owner to neutral
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_CONTESTED + player->GetTeamId();
ApplyPhaseMask();
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
message = LANG_BG_AB_NODE_ASSAULTED;
sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
}
SendNodeUpdate(node);
PlaySoundToAll(sound);
SendMessage2ToAll(message, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, player, LANG_BG_AB_NODE_STABLES + node, message2);
}
TeamId BattlegroundAB::GetPrematureWinner()
{
if (_controlledPoints[TEAM_ALLIANCE] > _controlledPoints[TEAM_HORDE])
return TEAM_ALLIANCE;
return _controlledPoints[TEAM_HORDE] > _controlledPoints[TEAM_ALLIANCE] ? TEAM_HORDE : Battleground::GetPrematureWinner();
}
bool BattlegroundAB::SetupBattleground()
{
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_BANNER_ALLY + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_BANNER_HORDE + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_BANNER_CONT_A + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_BANNER_CONT_H + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_AURA_ALLY + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_AURA_HORDE + BG_AB_OBJECTS_PER_NODE*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);
AddObject(BG_AB_OBJECT_AURA_CONTESTED + BG_AB_OBJECTS_PER_NODE*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);
}
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);
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);
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
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);
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);
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);
}
AddSpiritGuide(BG_AB_SPIRIT_ALIANCE, BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][0], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][1], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][2], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][3], TEAM_ALLIANCE);
AddSpiritGuide(BG_AB_SPIRIT_HORDE, BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][0], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][1], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][2], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][3], TEAM_HORDE);
for (uint32 i = BG_AB_OBJECT_BANNER_NEUTRAL; i < BG_AB_OBJECT_MAX; ++i)
if (BgObjects[i] == 0)
{
sLog->outErrorDb("BatteGroundAB: Failed to spawn some object Battleground not created!");
return false;
}
for (uint32 i = BG_AB_SPIRIT_ALIANCE; i <= BG_AB_SPIRIT_HORDE; ++i)
if (BgCreatures[i] == 0)
{
sLog->outErrorDb("BatteGroundAB: Failed to spawn spirit guides Battleground not created!");
return false;
}
return true;
}
void BattlegroundAB::Init()
{
//call parent's class reset
Battleground::Init();
_bgEvents.Reset();
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID()) ? BG_AB_HONOR_TICK_WEEKEND : BG_AB_HONOR_TICK_NORMAL;
_reputationTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID()) ? BG_AB_REP_TICK_WEEKEND : BG_AB_REP_TICK_NORMAL;
_capturePointInfo[BG_AB_NODE_STABLES]._iconNone = BG_AB_OP_STABLE_ICON;
_capturePointInfo[BG_AB_NODE_FARM]._iconNone = BG_AB_OP_FARM_ICON;
_capturePointInfo[BG_AB_NODE_BLACKSMITH]._iconNone = BG_AB_OP_BLACKSMITH_ICON;
_capturePointInfo[BG_AB_NODE_LUMBER_MILL]._iconNone = BG_AB_OP_LUMBERMILL_ICON;
_capturePointInfo[BG_AB_NODE_GOLD_MINE]._iconNone = BG_AB_OP_GOLDMINE_ICON;
_capturePointInfo[BG_AB_NODE_STABLES]._iconCapture = BG_AB_OP_STABLE_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_FARM]._iconCapture = BG_AB_OP_FARM_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_BLACKSMITH]._iconCapture = BG_AB_OP_BLACKSMITH_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_LUMBER_MILL]._iconCapture = BG_AB_OP_LUMBERMILL_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_GOLD_MINE]._iconCapture = BG_AB_OP_GOLDMINE_STATE_ALIENCE;
}
void BattlegroundAB::EndBattleground(TeamId winnerTeamId)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), winnerTeamId);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_HORDE);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_ALLIANCE);
Battleground::EndBattleground(winnerTeamId);
_bgEvents.Reset();
}
WorldSafeLocsEntry const* BattlegroundAB::GetClosestGraveyard(Player* player)
{
WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[BG_AB_SPIRIT_ALIANCE + player->GetTeamId()]);
WorldSafeLocsEntry const* nearestEntry = entry;
float pX = player->GetPositionX();
float pY = player->GetPositionY();
float dist = (entry->x - pX)*(entry->x - pX)+(entry->y - pY)*(entry->y - pY);
float minDist = dist;
for (uint8 i = BG_AB_NODE_STABLES; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
if (_capturePointInfo[i]._ownerTeamId == player->GetTeamId())
{
entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[i]);
dist = (entry->x - pX)*(entry->x - pX) + (entry->y - pY)*(entry->y - pY);
if (dist < minDist)
{
minDist = dist;
nearestEntry = entry;
}
}
return nearestEntry;
}
void BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
if (itr == PlayerScores.end())
return;
switch (type)
{
case SCORE_BASES_ASSAULTED:
((BattlegroundABScore*)itr->second)->BasesAssaulted += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_ASSAULT_BASE);
break;
case SCORE_BASES_DEFENDED:
((BattlegroundABScore*)itr->second)->BasesDefended += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_DEFEND_BASE);
break;
default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
}
}
bool BattlegroundAB::AllNodesConrolledByTeam(TeamId teamId) const
{
return _controlledPoints[teamId] == BG_AB_DYNAMIC_NODES_COUNT;
}
void BattlegroundAB::ApplyPhaseMask()
{
uint32 phaseMask = 1;
for (uint32 i = BG_AB_NODE_STABLES; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
if (_capturePointInfo[i]._ownerTeamId != TEAM_NEUTRAL)
phaseMask |= 1 << (i*2+1 + _capturePointInfo[i]._ownerTeamId);
const BattlegroundPlayerMap& bgPlayerMap = GetPlayers();
for (BattlegroundPlayerMap::const_iterator itr = bgPlayerMap.begin(); itr != bgPlayerMap.end(); ++itr)
{
itr->second->SetPhaseMask(phaseMask, false);
itr->second->UpdateObjectVisibility(true, false);
}
}
@@ -0,0 +1,276 @@
/*
REWRITTEN BY XINEF
*/
#ifndef __BATTLEGROUNDAB_H
#define __BATTLEGROUNDAB_H
#include "Battleground.h"
enum BG_AB_Events
{
BG_AB_EVENT_UPDATE_BANNER_STABLE = 1,
BG_AB_EVENT_UPDATE_BANNER_FARM = 2,
BG_AB_EVENT_UPDATE_BANNER_BLACKSMITH = 3,
BG_AB_EVENT_UPDATE_BANNER_LUMBERMILL = 4,
BG_AB_EVENT_UPDATE_BANNER_GOLDMINE = 5,
BG_AB_EVENT_CAPTURE_STABLE = 6,
BG_AB_EVENT_CAPTURE_FARM = 7,
BG_AB_EVENT_CAPTURE_BLACKSMITH = 8,
BG_AB_EVENT_CAPTURE_LUMBERMILL = 9,
BG_AB_EVENT_CAPTURE_GOLDMINE = 10,
BG_AB_EVENT_ALLIANCE_TICK = 11,
BG_AB_EVENT_HORDE_TICK = 12
};
enum BG_AB_WorldStates
{
BG_AB_OP_OCCUPIED_BASES_HORDE = 1778,
BG_AB_OP_OCCUPIED_BASES_ALLY = 1779,
BG_AB_OP_RESOURCES_ALLY = 1776,
BG_AB_OP_RESOURCES_HORDE = 1777,
BG_AB_OP_RESOURCES_MAX = 1780,
BG_AB_OP_RESOURCES_WARNING = 1955,
BG_AB_OP_STABLE_ICON = 1842, //Stable map icon (NONE)
BG_AB_OP_STABLE_STATE_ALIENCE = 1767, //Stable map state (ALIENCE)
BG_AB_OP_STABLE_STATE_HORDE = 1768, //Stable map state (HORDE)
BG_AB_OP_STABLE_STATE_CON_ALI = 1769, //Stable map state (CON ALIENCE)
BG_AB_OP_STABLE_STATE_CON_HOR = 1770, //Stable map state (CON HORDE)
BG_AB_OP_FARM_ICON = 1845, //Farm map icon (NONE)
BG_AB_OP_FARM_STATE_ALIENCE = 1772, //Farm state (ALIENCE)
BG_AB_OP_FARM_STATE_HORDE = 1773, //Farm state (HORDE)
BG_AB_OP_FARM_STATE_CON_ALI = 1774, //Farm state (CON ALIENCE)
BG_AB_OP_FARM_STATE_CON_HOR = 1775, //Farm state (CON HORDE)
BG_AB_OP_BLACKSMITH_ICON = 1846, //Blacksmith map icon (NONE)
BG_AB_OP_BLACKSMITH_STATE_ALIENCE = 1782, //Blacksmith map state (ALIENCE)
BG_AB_OP_BLACKSMITH_STATE_HORDE = 1783, //Blacksmith map state (HORDE)
BG_AB_OP_BLACKSMITH_STATE_CON_ALI = 1784, //Blacksmith map state (CON ALIENCE)
BG_AB_OP_BLACKSMITH_STATE_CON_HOR = 1785, //Blacksmith map state (CON HORDE)
BG_AB_OP_LUMBERMILL_ICON = 1844, //Lumber Mill map icon (NONE)
BG_AB_OP_LUMBERMILL_STATE_ALIENCE = 1792, //Lumber Mill map state (ALIENCE)
BG_AB_OP_LUMBERMILL_STATE_HORDE = 1793, //Lumber Mill map state (HORDE)
BG_AB_OP_LUMBERMILL_STATE_CON_ALI = 1794, //Lumber Mill map state (CON ALIENCE)
BG_AB_OP_LUMBERMILL_STATE_CON_HOR = 1795, //Lumber Mill map state (CON HORDE)
BG_AB_OP_GOLDMINE_ICON = 1843, //Gold Mine map icon (NONE)
BG_AB_OP_GOLDMINE_STATE_ALIENCE = 1787, //Gold Mine map state (ALIENCE)
BG_AB_OP_GOLDMINE_STATE_HORDE = 1788, //Gold Mine map state (HORDE)
BG_AB_OP_GOLDMINE_STATE_CON_ALI = 1789, //Gold Mine map state (CON ALIENCE
BG_AB_OP_GOLDMINE_STATE_CON_HOR = 1790, //Gold Mine map state (CON HORDE)
};
enum BG_AB_ObjectIds
{
BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner
BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner
BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner
BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner
BG_AB_OBJECTID_NODE_BANNER_4 = 180091, // Gold mine banner
BG_AB_OBJECTID_BANNER_A = 180058,
BG_AB_OBJECTID_BANNER_CONT_A = 180059,
BG_AB_OBJECTID_BANNER_H = 180060,
BG_AB_OBJECTID_BANNER_CONT_H = 180061,
BG_AB_OBJECTID_AURA_A = 180100,
BG_AB_OBJECTID_AURA_H = 180101,
BG_AB_OBJECTID_AURA_C = 180102,
BG_AB_OBJECTID_GATE_A = 180255,
BG_AB_OBJECTID_GATE_H = 180256
};
enum BG_AB_ObjectType
{
BG_AB_OBJECT_BANNER_NEUTRAL = 0,
BG_AB_OBJECT_BANNER_ALLY = 1,
BG_AB_OBJECT_BANNER_HORDE = 2,
BG_AB_OBJECT_BANNER_CONT_A = 3,
BG_AB_OBJECT_BANNER_CONT_H = 4,
BG_AB_OBJECT_AURA_ALLY = 5,
BG_AB_OBJECT_AURA_HORDE = 6,
BG_AB_OBJECT_AURA_CONTESTED = 7,
BG_AB_OBJECTS_PER_NODE = 8,
BG_AB_OBJECT_GATE_A = 40,
BG_AB_OBJECT_GATE_H = 41,
BG_AB_OBJECT_SPEEDBUFF_STABLES = 42,
BG_AB_OBJECT_REGENBUFF_STABLES = 43,
BG_AB_OBJECT_BERSERKBUFF_STABLES = 44,
BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45,
BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46,
BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47,
BG_AB_OBJECT_SPEEDBUFF_FARM = 48,
BG_AB_OBJECT_REGENBUFF_FARM = 49,
BG_AB_OBJECT_BERSERKBUFF_FARM = 50,
BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51,
BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52,
BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53,
BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54,
BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55,
BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56,
BG_AB_OBJECT_MAX = 57,
};
enum BG_AB_BattlegroundNodes
{
BG_AB_NODE_STABLES = 0,
BG_AB_NODE_BLACKSMITH = 1,
BG_AB_NODE_FARM = 2,
BG_AB_NODE_LUMBER_MILL = 3,
BG_AB_NODE_GOLD_MINE = 4,
BG_AB_DYNAMIC_NODES_COUNT = 5, // dynamic nodes that can be captured
BG_AB_SPIRIT_ALIANCE = 5,
BG_AB_SPIRIT_HORDE = 6,
BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static)
};
enum BG_AB_NodeStatus
{
BG_AB_NODE_STATE_NEUTRAL = 0,
BG_AB_NODE_STATE_ALLY_OCCUPIED = 1,
BG_AB_NODE_STATE_HORDE_OCCUPIED = 2,
BG_AB_NODE_STATE_ALLY_CONTESTED = 3,
BG_AB_NODE_STATE_HORDE_CONTESTED = 4
};
enum BG_AB_Sounds
{
BG_AB_SOUND_NODE_CLAIMED = 8192,
BG_AB_SOUND_NODE_CAPTURED_ALLIANCE = 8173,
BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213,
BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212,
BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8174,
BG_AB_SOUND_NEAR_VICTORY = 8456
};
enum BG_AB_Misc
{
BG_AB_OBJECTIVE_ASSAULT_BASE = 122,
BG_AB_OBJECTIVE_DEFEND_BASE = 123,
BG_AB_EVENT_START_BATTLE = 9158, // Achievement: Let's Get This Done
BG_AB_QUEST_CREDIT_BASE = 15001,
BG_AB_HONOR_TICK_NORMAL = 260,
BG_AB_HONOR_TICK_WEEKEND = 160,
BG_AB_REP_TICK_NORMAL = 160,
BG_AB_REP_TICK_WEEKEND = 120,
BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400,
BG_AB_MAX_TEAM_SCORE = 1600,
BG_AB_FLAG_CAPTURING_TIME = 60000,
BG_AB_BANNER_UPDATE_TIME = 2000
};
const uint32 BG_AB_TickIntervals[BG_AB_DYNAMIC_NODES_COUNT+1] = {0, 12000, 9000, 6000, 3000, 1000};
const uint32 BG_AB_TickPoints[BG_AB_DYNAMIC_NODES_COUNT+1] = {0, 10, 10, 10, 10, 30};
const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899};
const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] =
{
{1185.71f, 1185.24f, -56.36f, 2.56f}, // stables
{990.75f, 1008.18f, -42.60f, 2.43f}, // blacksmith
{817.66f, 843.34f, -56.54f, 3.01f}, // farm
{807.46f, 1189.16f, 11.92f, 5.44f}, // lumber mill
{1146.62f, 816.94f, -98.49f, 6.14f} // gold mine
};
const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] =
{
{1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables
{977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith
{806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm
{856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill
{1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine
};
const float BG_AB_DoorPositions[2][8] =
{
{1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f},
{708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f}
};
const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] =
{
{1200.03f, 1171.09f, -56.47f, 5.15f}, // stables
{1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith
{833.00f, 793.00f, -57.25f, 5.27f}, // farm
{775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill
{1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine
{1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base
{714.61f, 646.15f, -10.87f, 4.34f} // horde starting base
};
struct BattlegroundABScore : public BattlegroundScore
{
BattlegroundABScore(Player* player) : BattlegroundScore(player), BasesAssaulted(0), BasesDefended(0) { }
~BattlegroundABScore() { }
uint32 BasesAssaulted;
uint32 BasesDefended;
};
class BattlegroundAB : public Battleground
{
public:
BattlegroundAB();
~BattlegroundAB();
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void EndBattleground(TeamId winnerTeamId);
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
void FillInitialWorldStates(WorldPacket& data);
void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject);
bool AllNodesConrolledByTeam(TeamId teamId) const;
bool IsTeamScores500Disadvantage(TeamId teamId) const { return _teamScores500Disadvantage[teamId]; }
TeamId GetPrematureWinner();
private:
void PostUpdateImpl(uint32 diff);
void DeleteBanner(uint8 node);
void CreateBanner(uint8 node, bool delay);
void SendNodeUpdate(uint8 node);
void NodeOccupied(uint8 node);
void NodeDeoccupied(uint8 node);
void ApplyPhaseMask();
struct CapturePointInfo
{
CapturePointInfo() : _ownerTeamId(TEAM_NEUTRAL), _iconNone(0), _iconCapture(0), _state(BG_AB_NODE_STATE_NEUTRAL), _captured(false)
{
}
uint8 _state;
uint32 _iconNone;
uint32 _iconCapture;
TeamId _ownerTeamId;
bool _captured;
};
CapturePointInfo _capturePointInfo[BG_AB_DYNAMIC_NODES_COUNT];
EventMap _bgEvents;
uint32 _honorTics;
uint32 _reputationTics;
uint8 _controlledPoints[BG_TEAMS_COUNT];
bool _teamScores500Disadvantage[BG_TEAMS_COUNT];
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,178 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundBE.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundBE::BattlegroundBE()
{
BgObjects.resize(BG_BE_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundBE::~BattlegroundBE()
{
}
void BattlegroundBE::StartingEventCloseDoors()
{
for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattlegroundBE::StartingEventOpenDoors()
{
for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
}
void BattlegroundBE::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundBE::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundBE::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundBE::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation());
return true;
}
void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 4538: // buff trigger?
//buff_guid = BgObjects[BG_BE_OBJECT_BUFF_1];
break;
case 4539: // buff trigger?
//buff_guid = BgObjects[BG_BE_OBJECT_BUFF_2];
break;
// OUTSIDE OF ARENA, TELEPORT!
case 4919:
player->NearTeleportTo(6220.90f, 318.94f, 5.1f, 5.3f);
break;
case 4921:
player->NearTeleportTo(6250.27f, 208.50f, 4.77f, 1.9f);
break;
case 4922:
player->NearTeleportTo(6214.4f, 227.12f, 4.28f, 0.8f);
break;
case 4923:
player->NearTeleportTo(6180.98f, 265.28f, 4.27f, 6.06f);
break;
case 4924:
player->NearTeleportTo(6269.0f, 295.06f, 4.46f, 3.98f);
break;
case 4944: // under arena -20
case 5039: // under arena -40
case 5040: // under arena -60
player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation());
break;
}
}
void BattlegroundBE::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0x9f3) << uint32(1); // 9
Battleground::UpdateArenaWorldState();
}
void BattlegroundBE::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundBE::SetupBattleground()
{
// gates
if (!AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_BE_OBJECT_BUFF_1, BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120)
|| !AddObject(BG_BE_OBJECT_BUFF_2, BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)
// Arena Ready Marker
|| !AddObject(BG_BE_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 6189.47f, 235.54f, 5.52f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_BE_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 6287.19f, 288.25f, 5.33f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundBE: Failed to spawn some object!");
return false;
}
return true;
}
void BattlegroundBE::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
}
@@ -0,0 +1,69 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDBE_H
#define __BATTLEGROUNDBE_H
#include "Battleground.h"
enum BattlegroundBEObjectTypes
{
BG_BE_OBJECT_DOOR_1 = 0,
BG_BE_OBJECT_DOOR_2 = 1,
BG_BE_OBJECT_DOOR_3 = 2,
BG_BE_OBJECT_DOOR_4 = 3,
BG_BE_OBJECT_BUFF_1 = 4,
BG_BE_OBJECT_BUFF_2 = 5,
BG_BE_OBJECT_READY_MARKER_1 = 6,
BG_BE_OBJECT_READY_MARKER_2 = 7,
BG_BE_OBJECT_MAX = 8
};
enum BattlegroundBEObjects
{
BG_BE_OBJECT_TYPE_DOOR_1 = 183971,
BG_BE_OBJECT_TYPE_DOOR_2 = 183973,
BG_BE_OBJECT_TYPE_DOOR_3 = 183970,
BG_BE_OBJECT_TYPE_DOOR_4 = 183972,
BG_BE_OBJECT_TYPE_BUFF_1 = 184663,
BG_BE_OBJECT_TYPE_BUFF_2 = 184664
};
class BattlegroundBE : public Battleground
{
public:
BattlegroundBE();
~BattlegroundBE();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
/* Scorekeeping */
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
};
#endif
@@ -0,0 +1,267 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundDS.h"
#include "Creature.h"
#include "GameObject.h"
#include "Language.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundDS::BattlegroundDS()
{
BgObjects.resize(BG_DS_OBJECT_MAX);
BgCreatures.resize(BG_DS_NPC_MAX);
_waterfallTimer = 0;
_waterfallStatus = 0;
_waterfallKnockbackTimer = 0;
_pipeKnockBackTimer = 0;
_pipeKnockBackCount = 0;
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundDS::~BattlegroundDS()
{
}
void BattlegroundDS::PostUpdateImpl(uint32 diff)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (getPipeKnockBackCount() < BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
{
if (getPipeKnockBackTimer() < diff)
{
for (uint32 i = BG_DS_NPC_PIPE_KNOCKBACK_1; i <= BG_DS_NPC_PIPE_KNOCKBACK_2; ++i)
if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[i]))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true);
setPipeKnockBackCount(getPipeKnockBackCount() + 1);
setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_DELAY);
}
else
setPipeKnockBackTimer(getPipeKnockBackTimer() - diff);
}
if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Repeat knockback while the waterfall still active
{
if (getWaterFallKnockbackTimer() < diff)
{
if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[BG_DS_NPC_WATERFALL_KNOCKBACK]))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_WATER_SPOUT, true);
setWaterFallKnockbackTimer(BG_DS_WATERFALL_KNOCKBACK_TIMER);
}
else
setWaterFallKnockbackTimer(getWaterFallKnockbackTimer() - diff);
}
if (getWaterFallTimer() < diff)
{
if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_OFF) // Add the water
{
DoorClose(BG_DS_OBJECT_WATER_2);
setWaterFallTimer(BG_DS_WATERFALL_WARNING_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_WARNING);
}
else if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_WARNING) // Active collision and perform knockback
{
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_READY);
setWaterFallTimer(BG_DS_WATERFALL_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_ON);
setWaterFallKnockbackTimer(BG_DS_WATERFALL_KNOCKBACK_TIMER);
}
else //if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Remove collision and water
{
// turn off collision
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_ACTIVE);
DoorOpen(BG_DS_OBJECT_WATER_2);
setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF);
}
}
else
setWaterFallTimer(getWaterFallTimer() - diff);
}
void BattlegroundDS::StartingEventCloseDoors()
{
for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattlegroundDS::StartingEventOpenDoors()
{
for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF);
setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_FIRST_DELAY);
setPipeKnockBackCount(0);
SpawnBGObject(BG_DS_OBJECT_WATER_2, RESPAWN_IMMEDIATELY);
DoorOpen(BG_DS_OBJECT_WATER_2);
// Turn off collision
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_ACTIVE);
// Remove effects of Demonic Circle Summon
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (itr->second->HasAura(48018))
itr->second->RemoveAurasDueToSpell(48018);
}
void BattlegroundDS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundDS::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundDS::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("BattlegroundDS: Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 5347:
case 5348:
// Remove effects of Demonic Circle Summon
if (player->HasAura(48018))
player->RemoveAurasDueToSpell(48018);
// Someone has get back into the pipes and the knockback has already been performed,
// so we reset the knockback count for kicking the player again into the arena.
if (getPipeKnockBackCount() >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
setPipeKnockBackCount(0);
break;
// OUTSIDE OF ARENA, TELEPORT!
case 5328:
player->NearTeleportTo(1290.44f, 744.96f, 3.16f, 1.6f);
break;
case 5329:
player->NearTeleportTo(1292.6f, 837.07f, 3.161f, 4.7f);
break;
case 5330:
player->NearTeleportTo(1250.68f, 790.86f, 3.16f, 0.0f);
break;
case 5331:
player->NearTeleportTo(1332.50f, 790.9f, 3.16f, 3.14f);
break;
case 5326: // -10
case 5343: // -40
case 5344: // -60
player->NearTeleportTo(1330.0f, 800.0f, 3.16f, player->GetOrientation());
break;
}
}
bool BattlegroundDS::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(1299.046f, 784.825f, 9.338f, 2.422f);
return true;
}
void BattlegroundDS::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(3610) << uint32(1); // 9 show
Battleground::UpdateArenaWorldState();
}
void BattlegroundDS::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundDS::SetupBattleground()
{
// gates
if (!AddObject(BG_DS_OBJECT_DOOR_1, BG_DS_OBJECT_TYPE_DOOR_1, 1350.95f, 817.2f, 20.8096f, 3.15f, 0, 0, 0.99627f, 0.0862864f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_DS_OBJECT_DOOR_2, BG_DS_OBJECT_TYPE_DOOR_2, 1232.65f, 764.913f, 20.0729f, 6.3f, 0, 0, 0.0310211f, -0.999519f, RESPAWN_IMMEDIATELY)
// water
|| !AddObject(BG_DS_OBJECT_WATER_1, BG_DS_OBJECT_TYPE_WATER_1, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120)
|| !AddObject(BG_DS_OBJECT_WATER_2, BG_DS_OBJECT_TYPE_WATER_2, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120)
// buffs
|| !AddObject(BG_DS_OBJECT_BUFF_1, BG_DS_OBJECT_TYPE_BUFF_1, 1291.7f, 813.424f, 7.11472f, 4.64562f, 0, 0, 0.730314f, -0.683111f, 120)
|| !AddObject(BG_DS_OBJECT_BUFF_2, BG_DS_OBJECT_TYPE_BUFF_2, 1291.7f, 768.911f, 7.11472f, 1.55194f, 0, 0, 0.700409f, 0.713742f, 120)
// knockback creatures
|| !AddCreature(BG_DS_NPC_TYPE_WATER_SPOUT, BG_DS_NPC_WATERFALL_KNOCKBACK, 1291.76f, 791.02f, 7.115f, 3.054326f, RESPAWN_IMMEDIATELY)
|| !AddCreature(BG_DS_NPC_TYPE_WATER_SPOUT, BG_DS_NPC_PIPE_KNOCKBACK_1, 1369.977f, 817.2882f, 16.08718f, 3.106686f, RESPAWN_IMMEDIATELY)
|| !AddCreature(BG_DS_NPC_TYPE_WATER_SPOUT, BG_DS_NPC_PIPE_KNOCKBACK_2, 1212.833f, 765.3871f, 16.09484f, 0.0f, RESPAWN_IMMEDIATELY)
// Arena Ready Marker
|| !AddObject(BG_DS_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 1229.44f, 759.35f, 17.89f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_DS_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 1352.90f, 822.77f, 17.96f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundDS: Failed to spawn some object!");
return false;
}
return true;
}
@@ -0,0 +1,122 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDDS_H
#define __BATTLEGROUNDDS_H
#include "Battleground.h"
enum BattlegroundDSObjectTypes
{
BG_DS_OBJECT_DOOR_1 = 0,
BG_DS_OBJECT_DOOR_2 = 1,
BG_DS_OBJECT_WATER_1 = 2, // Collision
BG_DS_OBJECT_WATER_2 = 3,
BG_DS_OBJECT_BUFF_1 = 4,
BG_DS_OBJECT_BUFF_2 = 5,
BG_DS_OBJECT_READY_MARKER_1 = 6,
BG_DS_OBJECT_READY_MARKER_2 = 7,
BG_DS_OBJECT_MAX = 8
};
enum BattlegroundDSObjects
{
BG_DS_OBJECT_TYPE_DOOR_1 = 192642,
BG_DS_OBJECT_TYPE_DOOR_2 = 192643,
BG_DS_OBJECT_TYPE_WATER_1 = 194395, // Collision
BG_DS_OBJECT_TYPE_WATER_2 = 191877,
BG_DS_OBJECT_TYPE_BUFF_1 = 184663,
BG_DS_OBJECT_TYPE_BUFF_2 = 184664
};
enum BattlegroundDSCreatureTypes
{
BG_DS_NPC_WATERFALL_KNOCKBACK = 0,
BG_DS_NPC_PIPE_KNOCKBACK_1 = 1,
BG_DS_NPC_PIPE_KNOCKBACK_2 = 2,
BG_DS_NPC_MAX = 3
};
enum BattlegroundDSCreatures
{
BG_DS_NPC_TYPE_WATER_SPOUT = 28567,
};
enum BattlegroundDSSpells
{
BG_DS_SPELL_FLUSH = 57405, // Visual and target selector for the starting knockback from the pipe
BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not need to be casted)
BG_DS_SPELL_WATER_SPOUT = 58873, // Knockback effect of the central waterfall
};
enum BattlegroundDSData
{ // These values are NOT blizzlike... need the correct data!
BG_DS_WATERFALL_TIMER_MIN = 30000,
BG_DS_WATERFALL_TIMER_MAX = 60000,
BG_DS_WATERFALL_WARNING_DURATION = 5000,
BG_DS_WATERFALL_DURATION = 30000,
BG_DS_WATERFALL_KNOCKBACK_TIMER = 1500,
BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000,
BG_DS_PIPE_KNOCKBACK_DELAY = 3000,
BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT = 2,
BG_DS_WATERFALL_STATUS_WARNING = 1, // Water starting to fall, but no LoS Blocking nor movement blocking
BG_DS_WATERFALL_STATUS_ON = 2, // LoS and Movement blocking active
BG_DS_WATERFALL_STATUS_OFF = 3,
};
class BattlegroundDS : public Battleground
{
public:
BattlegroundDS();
~BattlegroundDS();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
private:
uint32 _waterfallTimer;
uint8 _waterfallStatus;
uint32 _waterfallKnockbackTimer;
uint32 _pipeKnockBackTimer;
uint8 _pipeKnockBackCount;
void PostUpdateImpl(uint32 diff);
protected:
uint32 getWaterFallStatus() { return _waterfallStatus; };
void setWaterFallStatus(uint8 status) { _waterfallStatus = status; };
uint32 getWaterFallTimer() { return _waterfallTimer; };
void setWaterFallTimer(uint32 timer) { _waterfallTimer = timer; };
uint32 getWaterFallKnockbackTimer() { return _waterfallKnockbackTimer; };
void setWaterFallKnockbackTimer(uint32 timer) { _waterfallKnockbackTimer = timer; };
uint8 getPipeKnockBackCount() { return _pipeKnockBackCount; };
void setPipeKnockBackCount(uint8 count) { _pipeKnockBackCount = count; };
uint32 getPipeKnockBackTimer() { return _pipeKnockBackTimer; };
void setPipeKnockBackTimer(uint32 timer) { _pipeKnockBackTimer = timer; };
};
#endif
@@ -0,0 +1,610 @@
/*
REWRITTEN BY XINEF
*/
#include "BattlegroundEY.h"
#include "ObjectMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
#include "Language.h"
#include "Object.h"
#include "Player.h"
#include "Util.h"
#include "WorldSession.h"
BattlegroundEY::BattlegroundEY()
{
m_BuffChange = true;
BgObjects.resize(BG_EY_OBJECT_MAX);
BgCreatures.resize(BG_EY_CREATURES_MAX);
_capturePointInfo[POINT_FEL_REAVER]._areaTrigger = AT_FEL_REAVER_BUFF;
_capturePointInfo[POINT_BLOOD_ELF]._areaTrigger = AT_BLOOD_ELF_BUFF;
_capturePointInfo[POINT_DRAENEI_RUINS]._areaTrigger = AT_DRAENEI_RUINS_BUFF;
_capturePointInfo[POINT_MAGE_TOWER]._areaTrigger = AT_MAGE_TOWER_BUFF;
_honorTics = 0;
_ownedPointsCount[TEAM_ALLIANCE] = 0;
_ownedPointsCount[TEAM_HORDE] = 0;
_flagKeeperGUID = 0;
_droppedFlagGUID = 0;
_flagState = BG_EY_FLAG_STATE_ON_BASE;
_flagCapturedObject = 0;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
}
BattlegroundEY::~BattlegroundEY()
{
}
void BattlegroundEY::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
_bgEvents.Update(diff);
while (uint32 eventId = _bgEvents.ExecuteEvent())
switch (eventId)
{
case BG_EY_EVENT_ADD_POINTS:
if (_ownedPointsCount[TEAM_ALLIANCE] > 0)
AddPoints(TEAM_ALLIANCE, BG_EY_TickPoints[_ownedPointsCount[TEAM_ALLIANCE] - 1]);
if (_ownedPointsCount[TEAM_HORDE] > 0)
AddPoints(TEAM_HORDE, BG_EY_TickPoints[_ownedPointsCount[TEAM_HORDE] - 1]);
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, BG_EY_FPOINTS_TICK_TIME - (World::GetGameTimeMS() % BG_EY_FPOINTS_TICK_TIME));
break;
case BG_EY_EVENT_FLAG_ON_GROUND:
RespawnFlagAfterDrop();
break;
case BG_EY_EVENT_RESPAWN_FLAG:
RespawnFlag();
break;
case BG_EY_EVENT_CHECK_CPOINTS:
UpdatePointsState();
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, BG_EY_FPOINTS_CHECK_TIME - (World::GetGameTimeMS() % BG_EY_FPOINTS_CHECK_TIME));
break;
}
}
}
void BattlegroundEY::StartingEventCloseDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
for (uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattlegroundEY::StartingEventOpenDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY);
for (uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for (uint32 i = 0; i < EY_POINTS_MAX; ++i)
SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i*3 + urand(0, 2), RESPAWN_IMMEDIATELY);
// Achievement: Flurry
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_EY_EVENT_START_BATTLE);
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, 0);
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, 0);
}
void BattlegroundEY::AddPoints(TeamId teamId, uint32 points)
{
uint8 honorRewards = uint8(m_TeamScores[teamId] / _honorTics);
m_TeamScores[teamId] += points;
for (; honorRewards < uint8(m_TeamScores[teamId] / _honorTics); ++honorRewards)
RewardHonorToTeam(GetBonusHonorFromKill(1), teamId);
UpdateWorldState(teamId == TEAM_ALLIANCE ? EY_ALLIANCE_RESOURCES : EY_HORDE_RESOURCES, std::min<uint32>(m_TeamScores[teamId], BG_EY_MAX_TEAM_SCORE));
if (m_TeamScores[teamId] >= BG_EY_MAX_TEAM_SCORE)
EndBattleground(teamId);
}
void BattlegroundEY::UpdatePointsState()
{
std::vector<GameObject*> pointsVec;
for (uint8 point = 0; point < EY_POINTS_MAX; ++point)
{
pointsVec.push_back(GetBGObject(BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + point));
_capturePointInfo[point]._playersCount[TEAM_ALLIANCE] = 0;
_capturePointInfo[point]._playersCount[TEAM_HORDE] = 0;
}
const BattlegroundPlayerMap& bgPlayerMap = GetPlayers();
for (BattlegroundPlayerMap::const_iterator itr = bgPlayerMap.begin(); itr != bgPlayerMap.end(); ++itr)
{
UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, itr->second);
for (uint8 point = 0; point < EY_POINTS_MAX; ++point)
if (GameObject* pointObject = pointsVec[point])
if (itr->second->CanCaptureTowerPoint() && itr->second->IsWithinDistInMap(pointObject, BG_EY_POINT_RADIUS))
{
UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, itr->second);
UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, itr->second);
UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, _capturePointInfo[point]._barStatus, itr->second);
++_capturePointInfo[point]._playersCount[itr->second->GetTeamId()];
// Xinef: ugly hax... area trigger is no longer called by client...
if (pointObject->GetEntry() == BG_OBJECT_FR_TOWER_CAP_EY_ENTRY && itr->second->GetDistance2d(2043.96f, 1729.68f) < 3.0f)
HandleAreaTrigger(itr->second, AT_FEL_REAVER_POINT);
}
}
for (uint8 point = 0; point < EY_POINTS_MAX; ++point)
{
_capturePointInfo[point]._barStatus += std::max<int8>(std::min<int8>(_capturePointInfo[point]._playersCount[TEAM_ALLIANCE] - _capturePointInfo[point]._playersCount[TEAM_HORDE], BG_EY_POINT_MAX_CAPTURERS_COUNT), -BG_EY_POINT_MAX_CAPTURERS_COUNT);
_capturePointInfo[point]._barStatus = std::max<int8>(std::min<int8>(_capturePointInfo[point]._barStatus, BG_EY_PROGRESS_BAR_ALI_CONTROLLED), BG_EY_PROGRESS_BAR_HORDE_CONTROLLED);
TeamId pointOwnerTeamId = TEAM_NEUTRAL;
if (_capturePointInfo[point]._barStatus <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW)
pointOwnerTeamId = TEAM_HORDE;
else if (_capturePointInfo[point]._barStatus >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH)
pointOwnerTeamId = TEAM_ALLIANCE;
if (pointOwnerTeamId != _capturePointInfo[point]._ownerTeamId)
{
if (_capturePointInfo[point].IsUncontrolled())
EventTeamCapturedPoint(pointOwnerTeamId, point);
if (pointOwnerTeamId == TEAM_NEUTRAL && _capturePointInfo[point].IsUnderControl())
EventTeamLostPoint(pointOwnerTeamId, point);
}
}
}
void BattlegroundEY::EndBattleground(TeamId winnerTeamId)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), winnerTeamId);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_HORDE);
Battleground::EndBattleground(winnerTeamId);
}
void BattlegroundEY::UpdatePointsCount()
{
UpdateWorldState(EY_ALLIANCE_BASE, _ownedPointsCount[TEAM_ALLIANCE]);
UpdateWorldState(EY_HORDE_BASE, _ownedPointsCount[TEAM_HORDE]);
}
void BattlegroundEY::UpdatePointsIcons(uint32 point)
{
if (_capturePointInfo[point].IsUnderControl())
{
UpdateWorldState(m_PointsIconStruct[point].WorldStateControlIndex, 0);
UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceControlledIndex, _capturePointInfo[point].IsUnderControl(TEAM_ALLIANCE));
UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeControlledIndex, _capturePointInfo[point].IsUnderControl(TEAM_HORDE));
}
else
{
UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 0);
UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeControlledIndex, 0);
UpdateWorldState(m_PointsIconStruct[point].WorldStateControlIndex, 1);
}
}
void BattlegroundEY::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundEYScore(player);
}
void BattlegroundEY::RemovePlayer(Player* player)
{
if (GetFlagPickerGUID() == player->GetGUID())
EventPlayerDroppedFlag(player);
}
void BattlegroundEY::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS || !player->IsAlive())
return;
switch (trigger)
{
case AT_BLOOD_ELF_POINT:
if (_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_BLOOD_ELF);
break;
case AT_FEL_REAVER_POINT:
if (_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_FEL_REAVER);
break;
case AT_MAGE_TOWER_POINT:
if (_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_MAGE_TOWER);
break;
case AT_DRAENEI_RUINS_POINT:
if (_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_DRAENEI_RUINS);
break;
case 4512:
case 4515:
case 4517:
case 4519:
case 4530:
case 4531:
case 5866:
case AT_BLOOD_ELF_BUFF:
case AT_FEL_REAVER_BUFF:
case AT_MAGE_TOWER_BUFF:
case AT_DRAENEI_RUINS_BUFF:
break;
}
}
bool BattlegroundEY::SetupBattleground()
{
// doors
AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY);
AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY);
// banners (alliance)
AddObject(BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_FEL_REAVER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_FEL_REAVER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY);
// banners (horde)
AddObject(BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_FEL_REAVER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_FEL_REAVER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY);
// banners (natural)
AddObject(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_FEL_REAVER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_FEL_REAVER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY);
// flags
AddObject(BG_EY_OBJECT_FLAG_NETHERSTORM, BG_OBJECT_FLAG2_EY_ENTRY, 2174.782227f, 1569.054688f, 1160.361938f, -1.448624f, 0, 0, 0.662620f, -0.748956f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_FEL_REAVER, BG_OBJECT_FLAG1_EY_ENTRY, 2044.28f, 1729.68f, 1189.96f, -0.017453f, 0, 0, 0.008727f, -0.999962f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_BLOOD_ELF, BG_OBJECT_FLAG1_EY_ENTRY, 2048.83f, 1393.65f, 1194.49f, 0.20944f, 0, 0, 0.104528f, 0.994522f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_DRAENEI_RUINS, BG_OBJECT_FLAG1_EY_ENTRY, 2286.56f, 1402.36f, 1197.11f, 3.72381f, 0, 0, 0.957926f, -0.287016f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_MAGE_TOWER, BG_OBJECT_FLAG1_EY_ENTRY, 2284.48f, 1731.23f, 1189.99f, 2.89725f, 0, 0, 0.992546f, 0.121869f, RESPAWN_ONE_DAY);
// tower cap
AddObject(BG_EY_OBJECT_TOWER_CAP_FEL_REAVER, BG_OBJECT_FR_TOWER_CAP_EY_ENTRY, 2024.600708f, 1742.819580f, 1195.157715f, 2.443461f, 0, 0, 0.939693f, 0.342020f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF, BG_OBJECT_BE_TOWER_CAP_EY_ENTRY, 2050.493164f, 1372.235962f, 1194.563477f, 1.710423f, 0, 0, 0.754710f, 0.656059f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS, BG_OBJECT_DR_TOWER_CAP_EY_ENTRY, 2301.010498f, 1386.931641f, 1197.183472f, 1.570796f, 0, 0, 0.707107f, 0.707107f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER, BG_OBJECT_HU_TOWER_CAP_EY_ENTRY, 2282.121582f, 1760.006958f, 1189.707153f, 1.919862f, 0, 0, 0.819152f, 0.573576f, RESPAWN_ONE_DAY);
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(_capturePointInfo[i]._areaTrigger);
AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i * 3 + 0, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i * 3 + 1, Buff_Entries[1], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i * 3 + 2, Buff_Entries[2], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY);
}
WorldSafeLocsEntry const* sg = NULL;
sg = sWorldSafeLocsStore.LookupEntry(BG_EY_GRAVEYARD_MAIN_ALLIANCE);
AddSpiritGuide(BG_EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, TEAM_ALLIANCE);
sg = sWorldSafeLocsStore.LookupEntry(BG_EY_GRAVEYARD_MAIN_HORDE);
AddSpiritGuide(BG_EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, TEAM_HORDE);
for (uint32 i = BG_EY_OBJECT_DOOR_A; i < BG_EY_OBJECT_MAX; ++i)
if (BgObjects[i] == 0)
{
sLog->outErrorDb("BatteGroundEY: Failed to spawn some object Battleground not created!");
return false;
}
for (uint32 i = BG_EY_SPIRIT_MAIN_ALLIANCE; i <= BG_EY_SPIRIT_MAIN_HORDE; ++i)
if (BgCreatures[i] == 0)
{
sLog->outErrorDb("BatteGroundEY: Failed to spawn spirit guides Battleground not created!");
return false;
}
return true;
}
void BattlegroundEY::Init()
{
//call parent's class reset
Battleground::Init();
_bgEvents.Reset();
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID()) ? BG_EY_HONOR_TICK_WEEKEND : BG_EY_HONOR_TICK_NORMAL;
_ownedPointsCount[TEAM_ALLIANCE] = 0;
_ownedPointsCount[TEAM_HORDE] = 0;
_flagKeeperGUID = 0;
_droppedFlagGUID = 0;
_flagState = BG_EY_FLAG_STATE_ON_BASE;
_flagCapturedObject = 0;
}
void BattlegroundEY::RespawnFlag()
{
if (_flagState != BG_EY_FLAG_STATE_ON_BASE)
return;
if (_flagCapturedObject > 0)
SpawnBGObject(_flagCapturedObject, RESPAWN_ONE_DAY);
_flagCapturedObject = 0;
SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY);
SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_FLAG_RESET);
UpdateWorldState(NETHERSTORM_FLAG, 1);
}
void BattlegroundEY::RespawnFlagAfterDrop()
{
if (_flagState != BG_EY_FLAG_STATE_ON_GROUND)
return;
_flagState = BG_EY_FLAG_STATE_ON_BASE;
RespawnFlag();
if (GameObject* flag = ObjectAccessor::GetObjectInMap(GetDroppedFlagGUID(), FindBgMap(), (GameObject*)NULL))
flag->Delete();
SetDroppedFlagGUID(0);
}
void BattlegroundEY::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
Battleground::HandleKillPlayer(player, killer);
EventPlayerDroppedFlag(player);
}
void BattlegroundEY::EventPlayerDroppedFlag(Player* player)
{
if (GetFlagPickerGUID() != player->GetGUID())
return;
SetFlagPicker(0);
player->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
if (GetStatus() != STATUS_IN_PROGRESS)
return;
_flagState = BG_EY_FLAG_STATE_ON_GROUND;
_bgEvents.RescheduleEvent(BG_EY_EVENT_FLAG_ON_GROUND, BG_EY_FLAG_ON_GROUND_TIME);
player->CastSpell(player, SPELL_RECENTLY_DROPPED_FLAG, true);
player->CastSpell(player, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true);
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE);
}
void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
{
if (GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() || !player->IsWithinDistInMap(gameObject, 10.0f))
return;
_flagState = BG_EY_FLAG_STATE_ON_PLAYER;
SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_ONE_DAY);
SetFlagPicker(player->GetGUID());
SetDroppedFlagGUID(0);
player->CastSpell(player, BG_EY_NETHERSTORM_FLAG_SPELL, true);
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, NULL, player->GetName().c_str());
PlaySoundToAll(player->GetTeamId() == TEAM_ALLIANCE ? BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE : BG_EY_SOUND_FLAG_PICKED_UP_HORDE);
UpdateWorldState(NETHERSTORM_FLAG, 0);
}
void BattlegroundEY::EventTeamLostPoint(TeamId teamId, uint32 point)
{
TeamId oldTeamId = _capturePointInfo[point]._ownerTeamId;
if (oldTeamId == TEAM_ALLIANCE)
{
_ownedPointsCount[TEAM_ALLIANCE]--;
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY);
SendMessageToAll(m_LosingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE);
}
else
{
_ownedPointsCount[TEAM_HORDE]--;
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY);
SendMessageToAll(m_LosingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE);
}
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType + 2, RESPAWN_IMMEDIATELY);
_capturePointInfo[point]._ownerTeamId = TEAM_NEUTRAL;
UpdatePointsIcons(point);
UpdatePointsCount();
DelCreature(BG_EY_TRIGGER_FEL_REAVER + point);
}
void BattlegroundEY::EventTeamCapturedPoint(TeamId teamId, uint32 point)
{
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType, RESPAWN_ONE_DAY);
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType + 2, RESPAWN_ONE_DAY);
if (teamId == TEAM_ALLIANCE)
{
_ownedPointsCount[TEAM_ALLIANCE]++;
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY);
SendMessageToAll(m_CapturingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE);
}
else
{
_ownedPointsCount[TEAM_HORDE]++;
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY);
SendMessageToAll(m_CapturingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE);
}
_capturePointInfo[point]._ownerTeamId = teamId;
if (BgCreatures[point])
DelCreature(point);
WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[point].GraveYardId);
AddSpiritGuide(point, sg->x, sg->y, sg->z, 3.124139f, teamId);
UpdatePointsIcons(point);
UpdatePointsCount();
// Xinef: done this way to avoid errors in console
Creature* trigger = GetBgMap()->GetCreature(BgCreatures[BG_EY_TRIGGER_FEL_REAVER + point]);
if (!trigger)
trigger = AddCreature(WORLD_TRIGGER, BG_EY_TRIGGER_FEL_REAVER + point, BG_EY_TriggerPositions[point][0], BG_EY_TriggerPositions[point][1], BG_EY_TriggerPositions[point][2], BG_EY_TriggerPositions[point][3]);
if (trigger)
{
trigger->setFaction(teamId == TEAM_ALLIANCE ? 84 : 83);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, true);
}
}
void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType)
{
SetFlagPicker(0);
_flagState = BG_EY_FLAG_STATE_ON_BASE;
player->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY);
_bgEvents.RescheduleEvent(BG_EY_EVENT_RESPAWN_FLAG, BG_EY_FLAG_RESPAWN_TIME);
_flagCapturedObject = BgObjectType;
if (player->GetTeamId() == TEAM_ALLIANCE)
{
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE);
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE);
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1);
if (_ownedPointsCount[player->GetTeamId()] > 0)
AddPoints(player->GetTeamId(), BG_EY_FlagPoints[_ownedPointsCount[player->GetTeamId()] - 1]);
}
void BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
if (type == SCORE_FLAG_CAPTURES)
{
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
if (itr != PlayerScores.end())
((BattlegroundEYScore*)itr->second)->FlagCaptures += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_EY_OBJECTIVE_CAPTURE_FLAG);
return;
}
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
}
void BattlegroundEY::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(EY_HORDE_BASE) << uint32(_ownedPointsCount[TEAM_HORDE]);
data << uint32(EY_ALLIANCE_BASE) << uint32(_ownedPointsCount[TEAM_ALLIANCE]);
data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE));
data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE));
data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled());
data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE));
data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(MAGE_TOWER_UNCONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled());
data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE));
data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(FEL_REAVER_UNCONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUncontrolled());
data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE));
data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE));
data << uint32(BLOOD_ELF_UNCONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled());
data << uint32(NETHERSTORM_FLAG) << uint32(_flagState == BG_EY_FLAG_STATE_ON_BASE);
data << uint32(NETHERSTORM_FLAG_STATE_HORDE) << uint32(1);
data << uint32(NETHERSTORM_FLAG_STATE_ALLIANCE) << uint32(1);
data << uint32(EY_HORDE_RESOURCES) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(EY_ALLIANCE_RESOURCES) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(PROGRESS_BAR_SHOW) << uint32(0);
data << uint32(PROGRESS_BAR_PERCENT_GREY) << uint32(0);
data << uint32(PROGRESS_BAR_STATUS) << uint32(0);
}
WorldSafeLocsEntry const* BattlegroundEY::GetClosestGraveyard(Player* player)
{
WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(BG_EY_GRAVEYARD_MAIN_ALLIANCE + player->GetTeamId());
WorldSafeLocsEntry const* nearestEntry = entry;
float pX = player->GetPositionX();
float pY = player->GetPositionY();
float pZ = player->GetPositionZ();
float dist = (entry->x - pX)*(entry->x - pX) + (entry->y - pY)*(entry->y - pY) + (entry->z - pZ)*(entry->z - pZ);
float minDist = dist;
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
if (_capturePointInfo[i].IsUnderControl(player->GetTeamId()))
{
entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId);
dist = (entry->x - pX)*(entry->x - pX) + (entry->y - pY)*(entry->y - pY) + (entry->z - pZ)*(entry->z - pZ);
if (dist < minDist)
{
minDist = dist;
nearestEntry = entry;
}
}
return nearestEntry;
}
bool BattlegroundEY::AllNodesConrolledByTeam(TeamId teamId) const
{
uint32 count = 0;
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
if (_capturePointInfo[i].IsUnderControl(teamId))
++count;
return count == EY_POINTS_MAX;
}
TeamId BattlegroundEY::GetPrematureWinner()
{
if (GetTeamScore(TEAM_ALLIANCE) > GetTeamScore(TEAM_HORDE))
return TEAM_ALLIANCE;
return GetTeamScore(TEAM_HORDE) > GetTeamScore(TEAM_ALLIANCE) ? TEAM_HORDE : Battleground::GetPrematureWinner();
}
@@ -0,0 +1,397 @@
/*
REWRITTEN BY XINEF
*/
#ifndef __BATTLEGROUNDEY_H
#define __BATTLEGROUNDEY_H
#include "Language.h"
#include "Battleground.h"
enum BG_EY_Events
{
BG_EY_EVENT_ADD_POINTS = 1,
BG_EY_EVENT_FLAG_ON_GROUND = 2,
BG_EY_EVENT_RESPAWN_FLAG = 3,
BG_EY_EVENT_CHECK_CPOINTS = 4
};
enum BG_EY_Timers
{
BG_EY_FLAG_RESPAWN_TIME = 20*IN_MILLISECONDS,
BG_EY_FLAG_ON_GROUND_TIME = 10*IN_MILLISECONDS,
BG_EY_FPOINTS_CHECK_TIME = 2*IN_MILLISECONDS,
BG_EY_FPOINTS_TICK_TIME = 1*IN_MILLISECONDS
};
enum BG_EY_WorldStates
{
EY_ALLIANCE_RESOURCES = 2749,
EY_HORDE_RESOURCES = 2750,
EY_ALLIANCE_BASE = 2752,
EY_HORDE_BASE = 2753,
DRAENEI_RUINS_HORDE_CONTROL = 2733,
DRAENEI_RUINS_ALLIANCE_CONTROL = 2732,
DRAENEI_RUINS_UNCONTROL = 2731,
MAGE_TOWER_ALLIANCE_CONTROL = 2730,
MAGE_TOWER_HORDE_CONTROL = 2729,
MAGE_TOWER_UNCONTROL = 2728,
FEL_REAVER_HORDE_CONTROL = 2727,
FEL_REAVER_ALLIANCE_CONTROL = 2726,
FEL_REAVER_UNCONTROL = 2725,
BLOOD_ELF_HORDE_CONTROL = 2724,
BLOOD_ELF_ALLIANCE_CONTROL = 2723,
BLOOD_ELF_UNCONTROL = 2722,
PROGRESS_BAR_PERCENT_GREY = 2720, //100 = empty (only grey), 0 = blue|red (no grey)
PROGRESS_BAR_STATUS = 2719, //50 init!, 48 ... hordak bere .. 33 .. 0 = full 100% hordacky, 100 = full alliance
PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance
NETHERSTORM_FLAG = 2757,
//set to 2 when flag is picked up, and to 1 if it is dropped
NETHERSTORM_FLAG_STATE_ALLIANCE = 2769,
NETHERSTORM_FLAG_STATE_HORDE = 2770
};
enum BG_EY_ProgressBarConsts
{
BG_EY_POINT_MAX_CAPTURERS_COUNT = 5,
BG_EY_POINT_RADIUS = 50,
BG_EY_PROGRESS_BAR_DONT_SHOW = 0,
BG_EY_PROGRESS_BAR_SHOW = 1,
BG_EY_PROGRESS_BAR_PERCENT_GREY = 40,
BG_EY_PROGRESS_BAR_STATE_MIDDLE = 50,
BG_EY_PROGRESS_BAR_HORDE_CONTROLLED = 0,
BG_EY_PROGRESS_BAR_NEUTRAL_LOW = 30,
BG_EY_PROGRESS_BAR_NEUTRAL_HIGH = 70,
BG_EY_PROGRESS_BAR_ALI_CONTROLLED = 100
};
enum BG_EY_Sounds
{
BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212,
BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213,
BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174,
BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
BG_EY_SOUND_FLAG_RESET = 8192
};
enum BG_EY_Spells
{
BG_EY_NETHERSTORM_FLAG_SPELL = 34976,
BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991
};
enum BG_EY_ObjectEntry
{
BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door
BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door
BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic)
BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand)
BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop)
BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance)
BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde)
BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral)
BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt
BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt
BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt
BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt
};
enum BG_EY_AreaTriggers
{
AT_BLOOD_ELF_POINT = 4476,
AT_FEL_REAVER_POINT = 4514,
AT_MAGE_TOWER_POINT = 4516,
AT_DRAENEI_RUINS_POINT = 4518,
AT_BLOOD_ELF_BUFF = 4568,
AT_FEL_REAVER_BUFF = 4569,
AT_MAGE_TOWER_BUFF = 4570,
AT_DRAENEI_RUINS_BUFF = 4571
};
enum BG_EY_Graveyards
{
BG_EY_GRAVEYARD_MAIN_ALLIANCE = 1103,
BG_EY_GRAVEYARD_MAIN_HORDE = 1104,
BG_EY_GRAVEYARD_FEL_REAVER = 1105,
BG_EY_GRAVEYARD_BLOOD_ELF = 1106,
BG_EY_GRAVEYARD_DRAENEI_RUINS = 1107,
BG_EY_GRAVEYARD_MAGE_TOWER = 1108
};
enum BG_EY_Points
{
POINT_FEL_REAVER = 0,
POINT_BLOOD_ELF = 1,
POINT_DRAENEI_RUINS = 2,
POINT_MAGE_TOWER = 3,
EY_POINTS_MAX = 4
};
enum BG_EY_CreatureTypes
{
BG_EY_SPIRIT_FEL_REAVER = 0,
BG_EY_SPIRIT_BLOOD_ELF = 1,
BG_EY_SPIRIT_DRAENEI_RUINS = 2,
BG_EY_SPIRIT_MAGE_TOWER = 3,
BG_EY_SPIRIT_MAIN_ALLIANCE = 4,
BG_EY_SPIRIT_MAIN_HORDE = 5,
BG_EY_TRIGGER_FEL_REAVER = 6,
BG_EY_TRIGGER_BLOOD_ELF = 7,
BG_EY_TRIGGER_DRAENEI_RUINS = 8,
BG_EY_TRIGGER_MAGE_TOWER = 9,
BG_EY_CREATURES_MAX = 10
};
enum BG_EY_ObjectTypes
{
BG_EY_OBJECT_DOOR_A = 0,
BG_EY_OBJECT_DOOR_H = 1,
BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER = 2,
BG_EY_OBJECT_A_BANNER_FEL_REAVER_LEFT = 3,
BG_EY_OBJECT_A_BANNER_FEL_REAVER_RIGHT = 4,
BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER = 5,
BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT = 6,
BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT = 7,
BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER = 8,
BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT = 9,
BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT = 10,
BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER = 11,
BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT = 12,
BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT = 13,
BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER = 14,
BG_EY_OBJECT_H_BANNER_FEL_REAVER_LEFT = 15,
BG_EY_OBJECT_H_BANNER_FEL_REAVER_RIGHT = 16,
BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER = 17,
BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT = 18,
BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT = 19,
BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER = 20,
BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT = 21,
BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT = 22,
BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER = 23,
BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT = 24,
BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT = 25,
BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER = 26,
BG_EY_OBJECT_N_BANNER_FEL_REAVER_LEFT = 27,
BG_EY_OBJECT_N_BANNER_FEL_REAVER_RIGHT = 28,
BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER = 29,
BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT = 30,
BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT = 31,
BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER = 32,
BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT = 33,
BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT = 34,
BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER = 35,
BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT = 36,
BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT = 37,
BG_EY_OBJECT_TOWER_CAP_FEL_REAVER = 38,
BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF = 39,
BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS = 40,
BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER = 41,
BG_EY_OBJECT_FLAG_NETHERSTORM = 42,
BG_EY_OBJECT_FLAG_FEL_REAVER = 43,
BG_EY_OBJECT_FLAG_BLOOD_ELF = 44,
BG_EY_OBJECT_FLAG_DRAENEI_RUINS = 45,
BG_EY_OBJECT_FLAG_MAGE_TOWER = 46,
//buffs
BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER = 47,
BG_EY_OBJECT_REGENBUFF_FEL_REAVER = 48,
BG_EY_OBJECT_BERSERKBUFF_FEL_REAVER = 49,
BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 50,
BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 51,
BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 52,
BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 53,
BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 54,
BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 55,
BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 56,
BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 57,
BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 58,
BG_EY_OBJECT_MAX = 59
};
enum BG_EY_Score
{
BG_EY_WARNING_NEAR_VICTORY_SCORE = 1400,
BG_EY_MAX_TEAM_SCORE = 1600,
BG_EY_HONOR_TICK_WEEKEND = 160,
BG_EY_HONOR_TICK_NORMAL = 260,
BG_EY_EVENT_START_BATTLE = 13180, // Achievement: Flurry
BG_EY_OBJECTIVE_CAPTURE_FLAG = 183
};
enum BG_EY_FlagState
{
BG_EY_FLAG_STATE_ON_BASE = 1,
BG_EY_FLAG_STATE_ON_PLAYER = 2,
BG_EY_FLAG_STATE_ON_GROUND = 3
};
struct BattlegroundEYPointIconsStruct
{
BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex)
: WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex) {}
uint32 WorldStateControlIndex;
uint32 WorldStateAllianceControlledIndex;
uint32 WorldStateHordeControlledIndex;
};
const float BG_EY_TriggerPositions[EY_POINTS_MAX][4] =
{
{2044.28f, 1729.68f, 1189.96f, 0.017453f}, // FEL_REAVER center
{2048.83f, 1393.65f, 1194.49f, 0.20944f}, // BLOOD_ELF center
{2286.56f, 1402.36f, 1197.11f, 3.72381f}, // DRAENEI_RUINS center
{2284.48f, 1731.23f, 1189.99f, 2.89725f} // MAGE_TOWER center
};
struct BattlegroundEYLosingPointStruct
{
BattlegroundEYLosingPointStruct(uint32 _SpawnNeutralObjectType, uint32 _DespawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _DespawnObjectTypeHorde, uint32 _MessageIdHorde)
: SpawnNeutralObjectType(_SpawnNeutralObjectType),
DespawnObjectTypeAlliance(_DespawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance),
DespawnObjectTypeHorde(_DespawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde)
{}
uint32 SpawnNeutralObjectType;
uint32 DespawnObjectTypeAlliance;
uint32 MessageIdAlliance;
uint32 DespawnObjectTypeHorde;
uint32 MessageIdHorde;
};
struct BattlegroundEYCapturingPointStruct
{
BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId)
: DespawnNeutralObjectType(_DespawnNeutralObjectType),
SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance),
SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde),
GraveYardId(_GraveYardId)
{}
uint32 DespawnNeutralObjectType;
uint32 SpawnObjectTypeAlliance;
uint32 MessageIdAlliance;
uint32 SpawnObjectTypeHorde;
uint32 MessageIdHorde;
uint32 GraveYardId;
};
const uint32 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10};
const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500};
//constant arrays:
const BattlegroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] =
{
BattlegroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL),
BattlegroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL),
BattlegroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL),
BattlegroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL)
};
const BattlegroundEYLosingPointStruct m_LosingPointTypes[EY_POINTS_MAX] =
{
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER)
};
const BattlegroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] =
{
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, BG_EY_GRAVEYARD_FEL_REAVER),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, BG_EY_GRAVEYARD_BLOOD_ELF),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, BG_EY_GRAVEYARD_DRAENEI_RUINS),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, BG_EY_GRAVEYARD_MAGE_TOWER)
};
struct BattlegroundEYScore : public BattlegroundScore
{
BattlegroundEYScore(Player* player) : BattlegroundScore(player), FlagCaptures(0) { }
~BattlegroundEYScore() { }
uint32 FlagCaptures;
};
class BattlegroundEY : public Battleground
{
public:
BattlegroundEY();
~BattlegroundEY();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
/* BG Flags */
uint64 GetFlagPickerGUID(TeamId /*teamId*/ = TEAM_NEUTRAL) const { return _flagKeeperGUID; }
void SetFlagPicker(uint64 guid) { _flagKeeperGUID = guid; }
uint8 GetFlagState() const { return _flagState; }
void RespawnFlag();
void RespawnFlagAfterDrop();
void RemovePlayer(Player* player);
void HandleBuffUse(uint64 buff_guid);
void HandleAreaTrigger(Player* player, uint32 trigger);
void HandleKillPlayer(Player* player, Player* killer);
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
bool SetupBattleground();
void Init();
void EndBattleground(TeamId winnerTeamId);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
void FillInitialWorldStates(WorldPacket& data);
void SetDroppedFlagGUID(uint64 guid, TeamId /*teamId*/ = TEAM_NEUTRAL) { _droppedFlagGUID = guid; }
uint64 GetDroppedFlagGUID() const { return _droppedFlagGUID; }
/* Battleground Events */
void EventPlayerClickedOnFlag(Player* player, GameObject* gameObject);
void EventPlayerDroppedFlag(Player* player);
/* achievement req. */
bool AllNodesConrolledByTeam(TeamId teamId) const;
TeamId GetPrematureWinner();
private:
void PostUpdateImpl(uint32 diff);
void EventPlayerCapturedFlag(Player* Source, uint32 BgObjectType);
void EventTeamLostPoint(TeamId teamId, uint32 point);
void EventTeamCapturedPoint(TeamId teamId, uint32 point);
void UpdatePointsCount();
void UpdatePointsIcons(uint32 point);
/* Point status updating procedures */
void UpdatePointsState();
/* Scorekeeping */
void AddPoints(TeamId teamId, uint32 points);
struct CapturePointInfo
{
CapturePointInfo() : _ownerTeamId(TEAM_NEUTRAL), _barStatus(BG_EY_PROGRESS_BAR_STATE_MIDDLE), _areaTrigger(0)
{
_playersCount[TEAM_ALLIANCE] = 0;
_playersCount[TEAM_HORDE] = 0;
}
TeamId _ownerTeamId;
uint32 _areaTrigger;
int8 _barStatus;
int8 _playersCount[BG_TEAMS_COUNT];
bool IsUnderControl(TeamId teamId) const { return _ownerTeamId == teamId; }
bool IsUnderControl() const { return _ownerTeamId != TEAM_NEUTRAL; }
bool IsUncontrolled() const { return _ownerTeamId == TEAM_NEUTRAL; }
};
CapturePointInfo _capturePointInfo[EY_POINTS_MAX];
EventMap _bgEvents;
uint32 _honorTics;
uint8 _ownedPointsCount[BG_TEAMS_COUNT];
uint64 _flagKeeperGUID;
uint64 _droppedFlagGUID;
uint8 _flagState;
uint32 _flagCapturedObject;
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,151 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundNA.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundNA::BattlegroundNA()
{
BgObjects.resize(BG_NA_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundNA::~BattlegroundNA()
{
}
void BattlegroundNA::StartingEventCloseDoors()
{
for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattlegroundNA::StartingEventOpenDoors()
{
for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
}
void BattlegroundNA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundNA::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundNA::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("BattlegroundNA: Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundNA::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation());
return true;
}
void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 4536: // buff trigger?
case 4537: // buff trigger?
break;
// OUTSIDE OF ARENA, TELEPORT!
case 4917:
case 5006:
case 5008:
player->NearTeleportTo(4054.15f, 2923.7f, 13.4f, player->GetOrientation());
break;
}
}
void BattlegroundNA::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0xa11) << uint32(1); // 9
Battleground::UpdateArenaWorldState();
}
void BattlegroundNA::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundNA::SetupBattleground()
{
// gates
if (!AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941f, 2895.250000f, 13.052700f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120)
|| !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078f, 2946.350098f, 13.051300f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)
// Arena Ready Marker
|| !AddObject(BG_NA_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 4090.46f, 2875.43f, 12.16f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_NA_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 4022.82f, 2966.61f, 12.17f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundNA: Failed to spawn some object!");
return false;
}
return true;
}
@@ -0,0 +1,65 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDNA_H
#define __BATTLEGROUNDNA_H
#include "Battleground.h"
enum BattlegroundNAObjectTypes
{
BG_NA_OBJECT_DOOR_1 = 0,
BG_NA_OBJECT_DOOR_2 = 1,
BG_NA_OBJECT_DOOR_3 = 2,
BG_NA_OBJECT_DOOR_4 = 3,
BG_NA_OBJECT_BUFF_1 = 4,
BG_NA_OBJECT_BUFF_2 = 5,
BG_NA_OBJECT_READY_MARKER_1 = 6,
BG_NA_OBJECT_READY_MARKER_2 = 7,
BG_NA_OBJECT_MAX = 8
};
enum BattlegroundNAObjects
{
BG_NA_OBJECT_TYPE_DOOR_1 = 183978,
BG_NA_OBJECT_TYPE_DOOR_2 = 183980,
BG_NA_OBJECT_TYPE_DOOR_3 = 183977,
BG_NA_OBJECT_TYPE_DOOR_4 = 183979,
BG_NA_OBJECT_TYPE_BUFF_1 = 184663,
BG_NA_OBJECT_TYPE_BUFF_2 = 184664
};
class BattlegroundNA : public Battleground
{
public:
BattlegroundNA();
~BattlegroundNA();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
};
#endif
@@ -0,0 +1,175 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundRL.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundRL::BattlegroundRL()
{
BgObjects.resize(BG_RL_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundRL::~BattlegroundRL()
{
}
void BattlegroundRL::StartingEventCloseDoors()
{
for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattlegroundRL::StartingEventOpenDoors()
{
for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
}
void BattlegroundRL::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundRL::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundRL::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundRL::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation());
return true;
}
void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 4696: // buff trigger?
case 4697: // buff trigger?
break;
// OUTSIDE OF ARENA, TELEPORT!
case 4927:
case 4928:
player->NearTeleportTo(1230.77f, 1662.42f, 34.56f, 0.0f);
break;
case 4929:
case 4930:
player->NearTeleportTo(1341.16f, 1673.52f, 34.43f, 3.5f);
break;
case 4931:
player->NearTeleportTo(1294.74f, 1584.5f, 31.62f, 1.66f);
break;
case 4932:
player->NearTeleportTo(1277.5f, 1751.07f, 31.61f, 4.7f);
break;
case 4933:
player->NearTeleportTo(1269.14f, 1713.85f, 34.46f, 5.23f);
break;
case 4934:
player->NearTeleportTo(1298.14f, 1713.8f, 33.58f, 4.55f);
break;
case 4935:
player->NearTeleportTo(1306.32f, 1620.75f, 34.25f, 1.97f);
break;
case 4936:
player->NearTeleportTo(1277.97f, 1615.51f, 34.56f, 1.15f);
break;
case 4941: // under arena +10
case 5041: // under arena -10
case 5042: // under arena -30
player->NearTeleportTo(1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation());
break;
}
}
void BattlegroundRL::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0xbba) << uint32(1); // 9
Battleground::UpdateArenaWorldState();
}
void BattlegroundRL::Init()
{
//call parent's reset
Battleground::Init();
}
bool BattlegroundRL::SetupBattleground()
{
// gates
if (!AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971f, 1632.719971f, 36.730400f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120)
|| !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049f, 1699.170044f, 34.872601f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)
// Arena Ready Marker
|| !AddObject(BG_RL_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 1298.61f, 1598.59f, 31.62f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_RL_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 1273.71f, 1734.05f, 31.61f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundRL: Failed to spawn some object!");
return false;
}
return true;
}
@@ -0,0 +1,61 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDRL_H
#define __BATTLEGROUNDRL_H
#include "Battleground.h"
enum BattlegroundRLObjectTypes
{
BG_RL_OBJECT_DOOR_1 = 0,
BG_RL_OBJECT_DOOR_2 = 1,
BG_RL_OBJECT_BUFF_1 = 2,
BG_RL_OBJECT_BUFF_2 = 3,
BG_RL_OBJECT_READY_MARKER_1 = 4,
BG_RL_OBJECT_READY_MARKER_2 = 5,
BG_RL_OBJECT_MAX = 6
};
enum BattlegroundRLObjects
{
BG_RL_OBJECT_TYPE_DOOR_1 = 185918,
BG_RL_OBJECT_TYPE_DOOR_2 = 185917,
BG_RL_OBJECT_TYPE_BUFF_1 = 184663,
BG_RL_OBJECT_TYPE_BUFF_2 = 184664
};
class BattlegroundRL : public Battleground
{
public:
BattlegroundRL();
~BattlegroundRL();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void Init();
void FillInitialWorldStates(WorldPacket &d);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
};
#endif
@@ -0,0 +1,351 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Battleground.h"
#include "BattlegroundRV.h"
#include "ObjectAccessor.h"
#include "Language.h"
#include "Player.h"
#include "WorldPacket.h"
#include "GameObject.h"
#include "WorldSession.h"
#include "Pet.h"
BattlegroundRV::BattlegroundRV()
{
BgObjects.resize(BG_RV_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
CheckPlayersTimer = 0;
}
BattlegroundRV::~BattlegroundRV() { }
void BattlegroundRV::TeleportUnitToNewZ(Unit* unit, float newZ, bool casting)
{
if (!unit->IsAlive())
return;
unit->NearTeleportTo(unit->GetPositionX(), unit->GetPositionY(), newZ, unit->GetOrientation(), casting);
unit->m_positionZ = newZ;
}
void BattlegroundRV::CheckPositionForUnit(Unit* unit)
{
// get height at current pos, if something is wrong (below or high above) - teleport
if (!unit->IsFalling() && unit->IsAlive())
{
float groundZ_vmap = unit->GetMap()->GetHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, true, 50.0f);
float groundZ_dyntree = unit->GetMap()->GetDynamicMapTree().getHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, 50.0f, unit->GetPhaseMask());
if (groundZ_vmap > 28.0f && groundZ_vmap < 29.0f || groundZ_dyntree > 28.0f && groundZ_dyntree < 37.0f)
{
float groundZ = std::max<float>(groundZ_vmap, groundZ_dyntree);
if (unit->GetPositionZ() < groundZ - 0.2f || unit->GetPositionZ() > groundZ + 3.5f)
TeleportUnitToNewZ(unit, groundZ+1.0f, true);
}
}
}
void BattlegroundRV::PostUpdateImpl(uint32 diff)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (getTimer() < diff)
{
switch (getState())
{
case BG_RV_STATE_OPEN_FENCES:
for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i)
DoorOpen(i);
setTimer(BG_RV_CLOSE_FIRE_TIMER);
setState(BG_RV_STATE_CLOSE_FIRE);
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
if (Player* player = itr->second)
{
// Demonic Circle Summon
if (GameObject* gObj = player->GetGameObject(48018))
{
gObj->Relocate(gObj->GetPositionX(), gObj->GetPositionY(), 28.28f);
gObj->UpdateObjectVisibility(true);
}
if (player->GetPositionZ() < 27.0f)
TeleportUnitToNewZ(player, 28.28f, true);
for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
if (player->m_SummonSlot[i])
if (Creature* totem = GetBgMap()->GetCreature(player->m_SummonSlot[i]))
if (totem->GetPositionZ() < 28.0f)
TeleportUnitToNewZ(totem, 28.28f, true);
for (Unit::ControlSet::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr)
{
if ((*itr)->GetPositionZ() < 28.0f)
TeleportUnitToNewZ((*itr), 28.28f, true);
// Xinef: override stay position
if (CharmInfo* charmInfo = (*itr)->GetCharmInfo())
if (charmInfo->IsAtStay())
{
(*itr)->StopMovingOnCurrentPos();
charmInfo->SaveStayPosition(false);
}
}
}
// fix ground on elevators (so aoe spells can be casted there)
{
uint32 objects[2] = {BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_ELEVATOR_2};
for (uint8 i=0; i<2; ++i)
if (GameObject* go = GetBGObject(objects[i]))
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_TRANSPORT);
}
break;
case BG_RV_STATE_CLOSE_FIRE:
for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i)
DoorClose(i);
// Fire got closed after five seconds, leaves twenty seconds before toggling pillars
setTimer(BG_RV_FIRE_TO_PILLAR_TIMER);
setState(BG_RV_STATE_SWITCH_PILLARS);
break;
case BG_RV_STATE_SWITCH_PILLARS:
UpdatePillars();
setTimer(BG_RV_PILLAR_SWITCH_TIMER);
break;
}
}
else
setTimer(getTimer() - diff);
if (getState() == BG_RV_STATE_OPEN_FENCES)
return;
if (CheckPlayersTimer <= diff)
{
CheckPlayersTimer = 0;
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
CheckPositionForUnit(itr->second);
// maybe for pets and m_Controlled also, but not really necessary
}
else
CheckPlayersTimer -= diff;
}
void BattlegroundRV::StartingEventCloseDoors()
{
}
void BattlegroundRV::StartingEventOpenDoors()
{
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
itr->second->SetPhaseMask(1, true);
// Buff respawn
SpawnBGObject(BG_RV_OBJECT_BUFF_1, 90);
SpawnBGObject(BG_RV_OBJECT_BUFF_2, 90);
// Elevators
DoorOpen(BG_RV_OBJECT_ELEVATOR_1);
DoorOpen(BG_RV_OBJECT_ELEVATOR_2);
setState(BG_RV_STATE_OPEN_FENCES);
setTimer(BG_RV_FIRST_TIMER);
}
void BattlegroundRV::AddPlayer(Player* player)
{
if (GetStatus() == STATUS_WAIT_JOIN && player->GetBgTeamId() == TEAM_HORDE)
player->SetPhaseMask(2, true);
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
BattlegroundRV::UpdateArenaWorldState();
}
void BattlegroundRV::RemovePlayer(Player* player)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
if (GetStatus() == STATUS_WAIT_JOIN)
player->SetPhaseMask(1, true);
BattlegroundRV::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundRV::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
return;
Battleground::HandleKillPlayer(player, killer);
BattlegroundRV::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundRV::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(763.5f, -284, 28.276f, 2.422f);
return true;
}
void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS || getState() == BG_RV_STATE_OPEN_FENCES /*during elevator rising it's possible to jump and cause areatrigger*/)
return;
switch (trigger)
{
// fire was removed in 3.2.0
case 5473:
case 5474:
break;
// OUTSIDE OF ARENA, TELEPORT!
case 5224:
player->NearTeleportTo(765.0f, -294.0f, 28.3f, player->GetOrientation());
break;
case 5226:
player->NearTeleportTo(765.0f, -272.0f, 28.3f, player->GetOrientation());
break;
case 5447:
player->NearTeleportTo(763.5f, -284, 28.276f, 2.422f);
break;
}
}
void BattlegroundRV::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(BG_RV_WORLD_STATE) << uint32(1);
BattlegroundRV::UpdateArenaWorldState();
}
void BattlegroundRV::UpdateArenaWorldState()
{
UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(TEAM_HORDE));
}
void BattlegroundRV::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundRV::SetupBattleground()
{
// elevators
if (!AddObject(BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_TYPE_ELEVATOR_1, 763.536377f, -294.535767f, 0.505383f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_ELEVATOR_2, BG_RV_OBJECT_TYPE_ELEVATOR_2, 763.506348f, -273.873352f, 0.505383f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_RV_OBJECT_BUFF_1, BG_RV_OBJECT_TYPE_BUFF_1, 735.551819f, -284.794678f, 28.276682f, 0.034906f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_BUFF_2, BG_RV_OBJECT_TYPE_BUFF_2, 791.224487f, -284.794464f, 28.276682f, 2.600535f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// fire
|| !AddObject(BG_RV_OBJECT_FIRE_1, BG_RV_OBJECT_TYPE_FIRE_1, 743.543457f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_FIRE_2, BG_RV_OBJECT_TYPE_FIRE_2, 782.971802f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_FIREDOOR_1, BG_RV_OBJECT_TYPE_FIREDOOR_1, 743.711060f, -284.099609f, 27.542587f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_FIREDOOR_2, BG_RV_OBJECT_TYPE_FIREDOOR_2, 783.221252f, -284.133362f, 27.535686f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Gear
|| !AddObject(BG_RV_OBJECT_GEAR_1, BG_RV_OBJECT_TYPE_GEAR_1, 763.664551f, -261.872986f, 26.686588f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_GEAR_2, BG_RV_OBJECT_TYPE_GEAR_2, 763.578979f, -306.146149f, 26.665222f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Pulley
|| !AddObject(BG_RV_OBJECT_PULLEY_1, BG_RV_OBJECT_TYPE_PULLEY_1, 700.722290f, -283.990662f, 39.517582f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PULLEY_2, BG_RV_OBJECT_TYPE_PULLEY_2, 826.303833f, -283.996429f, 39.517582f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Pilars
|| !AddObject(BG_RV_OBJECT_PILAR_1, BG_RV_OBJECT_TYPE_PILAR_1, 763.632385f, -306.162384f, 25.909504f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PILAR_2, BG_RV_OBJECT_TYPE_PILAR_2, 723.644287f, -284.493256f, 24.648525f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PILAR_3, BG_RV_OBJECT_TYPE_PILAR_3, 763.611145f, -261.856750f, 25.909504f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PILAR_4, BG_RV_OBJECT_TYPE_PILAR_4, 802.211609f, -284.493256f, 24.648525f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Arena Ready Marker
|| !AddObject(BG_RV_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 769.93f, -301.04f, 2.80f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_RV_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 757.02f, -267.30f, 2.80f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
)
{
sLog->outErrorDb("BatteGroundRV: Failed to spawn some object!");
return false;
}
for (uint8 i=0; i<BG_RV_OBJECT_MAX; ++i)
if (GameObject* go = GetBGObject(i))
go->SetPhaseMask(3, true);
return true;
}
void BattlegroundRV::UpdatePillars()
{
GameObject* test = GetBgMap()->GetGameObject(BgObjects[BG_RV_OBJECT_PILAR_1]);
if (!test)
return;
if (test->GetGoState() == GO_STATE_READY)
{
for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_GEAR_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_ACTIVE);
for (uint8 i = BG_RV_OBJECT_PILAR_2; i <= BG_RV_OBJECT_PULLEY_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_READY);
}
else
{
for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_GEAR_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_READY);
for (uint8 i = BG_RV_OBJECT_PILAR_2; i <= BG_RV_OBJECT_PULLEY_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_ACTIVE);
}
}
uint32 BattlegroundRV::GetPillarIdForPos(Position* p)
{
float range = 1.75f;
if (p->GetExactDist2d(763.632385f, -306.162384f) < range)
return BG_RV_OBJECT_PILAR_1;
if (p->GetExactDist2d(723.644287f, -284.493256f) < 2.0f*range)
return BG_RV_OBJECT_PILAR_2;
if (p->GetExactDist2d(763.611145f, -261.856750f) < range)
return BG_RV_OBJECT_PILAR_3;
if (p->GetExactDist2d(802.211609f, -284.493256f) < 2.0f*range)
return BG_RV_OBJECT_PILAR_4;
return 0;
}
GameObject* BattlegroundRV::GetPillarAtPosition(Position* p)
{
uint32 pillar = GetPillarIdForPos(p);
if (!pillar)
return NULL;
return GetBgMap()->GetGameObject(BgObjects[pillar]);
}
@@ -0,0 +1,128 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDRV_H
#define __BATTLEGROUNDRV_H
#include "Battleground.h"
enum BattlegroundRVObjectTypes
{
BG_RV_OBJECT_BUFF_1,
BG_RV_OBJECT_BUFF_2,
BG_RV_OBJECT_FIRE_1,
BG_RV_OBJECT_FIRE_2,
BG_RV_OBJECT_FIREDOOR_1,
BG_RV_OBJECT_FIREDOOR_2,
BG_RV_OBJECT_PILAR_1,
BG_RV_OBJECT_PILAR_3,
BG_RV_OBJECT_GEAR_1,
BG_RV_OBJECT_GEAR_2,
BG_RV_OBJECT_PILAR_2,
BG_RV_OBJECT_PILAR_4,
BG_RV_OBJECT_PULLEY_1,
BG_RV_OBJECT_PULLEY_2,
BG_RV_OBJECT_ELEVATOR_1,
BG_RV_OBJECT_ELEVATOR_2,
BG_RV_OBJECT_READY_MARKER_1,
BG_RV_OBJECT_READY_MARKER_2,
BG_RV_OBJECT_MAX,
};
enum BattlegroundRVObjects
{
BG_RV_OBJECT_TYPE_BUFF_1 = 184663,
BG_RV_OBJECT_TYPE_BUFF_2 = 184664,
BG_RV_OBJECT_TYPE_FIRE_1 = 192704,
BG_RV_OBJECT_TYPE_FIRE_2 = 192705,
BG_RV_OBJECT_TYPE_FIREDOOR_2 = 192387,
BG_RV_OBJECT_TYPE_FIREDOOR_1 = 192388,
BG_RV_OBJECT_TYPE_PULLEY_1 = 192389,
BG_RV_OBJECT_TYPE_PULLEY_2 = 192390,
BG_RV_OBJECT_TYPE_GEAR_1 = 192393,
BG_RV_OBJECT_TYPE_GEAR_2 = 192394,
BG_RV_OBJECT_TYPE_ELEVATOR_1 = 194582,
BG_RV_OBJECT_TYPE_ELEVATOR_2 = 194586,
BG_RV_OBJECT_TYPE_PILAR_1 = 194583, // axe
BG_RV_OBJECT_TYPE_PILAR_2 = 194584, // arena
BG_RV_OBJECT_TYPE_PILAR_3 = 194585, // lightning
BG_RV_OBJECT_TYPE_PILAR_4 = 194587, // ivory
};
enum BattlegroundRVData
{
BG_RV_STATE_OPEN_FENCES,
BG_RV_STATE_SWITCH_PILLARS,
BG_RV_STATE_CLOSE_FIRE,
BG_RV_PILLAR_SWITCH_TIMER = 25000,
BG_RV_FIRE_TO_PILLAR_TIMER = 20000,
BG_RV_CLOSE_FIRE_TIMER = 5000,
BG_RV_FIRST_TIMER = 20500, // elevators rise in 20133ms
BG_RV_WORLD_STATE_A = 0xe11,
BG_RV_WORLD_STATE_H = 0xe10,
BG_RV_WORLD_STATE = 0xe1a,
};
class BattlegroundRV : public Battleground
{
public:
BattlegroundRV();
~BattlegroundRV();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void RemovePlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void UpdateArenaWorldState();
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
GameObject* GetPillarAtPosition(Position* p);
private:
uint32 Timer;
uint32 State;
uint16 CheckPlayersTimer;
void PostUpdateImpl(uint32 diff);
protected:
uint32 getTimer() { return Timer; }
void setTimer(uint32 timer) { Timer = timer; }
uint32 getState() { return State; };
void setState(uint32 state) { State = state; }
void TeleportUnitToNewZ(Unit* unit, float newZ, bool casting);
void CheckPositionForUnit(Unit* unit);
void UpdatePillars();
uint32 GetPillarIdForPos(Position* p);
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,606 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDSA_H
#define __BATTLEGROUNDSA_H
#include "Battleground.h"
struct BattlegroundSAScore : public BattlegroundScore
{
BattlegroundSAScore(Player* player) : BattlegroundScore(player), demolishers_destroyed(0), gates_destroyed(0) { }
~BattlegroundSAScore() { }
uint8 demolishers_destroyed;
uint8 gates_destroyed;
};
#define BG_SA_FLAG_AMOUNT 3
#define BG_SA_DEMOLISHER_AMOUNT 4
#define SPELL_SA_END_OF_ROUND 52459
enum BG_SA_Status
{
BG_SA_NOTSTARTED = 0,
BG_SA_WARMUP,
BG_SA_ROUND_ONE,
BG_SA_SECOND_WARMUP,
BG_SA_ROUND_TWO,
BG_SA_BONUS_ROUND
};
enum BG_SA_GateState
{
BG_SA_GATE_OK = 1,
BG_SA_GATE_DAMAGED = 2,
BG_SA_GATE_DESTROYED = 3
};
enum BG_SA_Timers
{
BG_SA_BOAT_START = 60 * IN_MILLISECONDS,
BG_SA_WARMUPLENGTH = 120 * IN_MILLISECONDS,
BG_SA_ROUNDLENGTH = 600 * IN_MILLISECONDS
};
enum BG_SA_WorldStates
{
BG_SA_TIMER_MINS = 3559,
BG_SA_TIMER_SEC_TENS = 3560,
BG_SA_TIMER_SEC_DECS = 3561,
BG_SA_ALLY_ATTACKS = 4352,
BG_SA_HORDE_ATTACKS = 4353,
BG_SA_PURPLE_GATEWS = 3614,
BG_SA_RED_GATEWS = 3617,
BG_SA_BLUE_GATEWS = 3620,
BG_SA_GREEN_GATEWS = 3623,
BG_SA_YELLOW_GATEWS = 3638,
BG_SA_ANCIENT_GATEWS = 3849,
BG_SA_LEFT_GY_ALLIANCE = 3635,
BG_SA_RIGHT_GY_ALLIANCE = 3636,
BG_SA_CENTER_GY_ALLIANCE = 3637,
BG_SA_RIGHT_ATT_TOKEN_ALL = 3627,
BG_SA_LEFT_ATT_TOKEN_ALL = 3626,
BG_SA_LEFT_ATT_TOKEN_HRD = 3629,
BG_SA_RIGHT_ATT_TOKEN_HRD = 3628,
BG_SA_HORDE_DEFENCE_TOKEN = 3631,
BG_SA_ALLIANCE_DEFENCE_TOKEN = 3630,
BG_SA_RIGHT_GY_HORDE = 3632,
BG_SA_LEFT_GY_HORDE = 3633,
BG_SA_CENTER_GY_HORDE = 3634,
BG_SA_BONUS_TIMER = 0xdf3,
BG_SA_ENABLE_TIMER = 3564,
};
enum npc
{
NPC_ANTI_PERSONNAL_CANNON = 27894,
NPC_DEMOLISHER_SA = 28781,
NPC_RIGGER_SPARKLIGHT = 29260,
NPC_GORGRIL_RIGSPARK = 29262,
};
enum BG_SA_NPCs
{
BG_SA_GUN_1 = 0,
BG_SA_GUN_2,
BG_SA_GUN_3,
BG_SA_GUN_4,
BG_SA_GUN_5,
BG_SA_GUN_6,
BG_SA_GUN_7,
BG_SA_GUN_8,
BG_SA_GUN_9,
BG_SA_GUN_10,
BG_SA_NPC_TRIGGER_1,
BG_SA_NPC_TRIGGER_2,
BG_SA_NPC_TRIGGER_3,
BG_SA_NPC_TRIGGER_4,
BG_SA_NPC_TRIGGER_5,
BG_SA_DEMOLISHER_1,
BG_SA_DEMOLISHER_2,
BG_SA_DEMOLISHER_3,
BG_SA_DEMOLISHER_4,
BG_SA_DEMOLISHER_5,
BG_SA_DEMOLISHER_6,
BG_SA_DEMOLISHER_7,
BG_SA_DEMOLISHER_8,
BG_SA_NPC_SPARKLIGHT,
BG_SA_NPC_RIGSPARK,
BG_SA_MAXNPC
};
enum BG_SA_Boat
{
BG_SA_BOAT_ONE_A = 193182,
BG_SA_BOAT_TWO_H = 193183,
BG_SA_BOAT_ONE_H = 193184,
BG_SA_BOAT_TWO_A = 193185,
};
uint32 const BG_SA_NpcEntries[BG_SA_MAXNPC] =
{
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
// Triggers
23472,
23472,
23472,
23472,
23472,
// 4 beach demolishers
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
// 4 factory demolishers
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
// Used Demolisher Salesman
NPC_RIGGER_SPARKLIGHT,
NPC_GORGRIL_RIGSPARK
};
float const BG_SA_NpcSpawnlocs[BG_SA_MAXNPC][4] =
{
// Cannons
{ 1436.429f, 110.05f, 41.407f, 5.4f },
{ 1404.9023f, 84.758f, 41.183f, 5.46f },
{ 1068.693f, -86.951f, 93.81f, 0.02f },
{ 1068.83f, -127.56f, 96.45f, 0.0912f },
{ 1422.115f, -196.433f, 42.1825f, 1.0222f },
{ 1454.887f, -220.454f, 41.956f, 0.9627f },
{ 1232.345f, -187.517f, 66.945f, 0.45f },
{ 1249.634f, -224.189f, 66.72f, 0.635f },
{ 1236.213f, 92.287f, 64.965f, 5.751f },
{ 1215.11f, 57.772f, 64.739f, 5.78f },
// Triggers
{ 1453.49f, -250.453f, 30.896f, 4.2883f},
{ 1377.05f, 97.036f, 30.8605f, 2.46539f},
{ 1186.05f, 58.8048f, 56.5491f, 2.75992f},
{ 1042.83f, -72.839f, 84.8145f, 3.58615f},
{ 1233.62f, -250.49f, 55.4036f, 3.7016f},
// Demolishers
{ 1611.597656f, -117.270073f, 8.719355f, 2.513274f},
{ 1575.562500f, -158.421875f, 5.024450f, 2.129302f},
{ 1618.047729f, 61.424641f, 7.248210f, 3.979351f},
{ 1575.103149f, 98.873344f, 2.830360f, 3.752458f},
// Demolishers 2
{ 1371.055786f, -317.071136f, 35.007359f, 1.947460f},
{ 1424.034912f, -260.195190f, 31.084425f, 2.820013f},
{ 1353.139893f, 223.745438f, 35.265411f, 4.343684f},
{ 1404.809570f, 197.027237f, 32.046032f, 3.605401f},
// Npcs
{ 1348.644165f, -298.786469f, 31.080130f, 1.710423f},
{ 1358.191040f, 195.527786f, 31.018187f, 4.171337f}
};
enum BG_SA_Objects
{
BG_SA_GREEN_GATE = 0,
BG_SA_YELLOW_GATE,
BG_SA_BLUE_GATE,
BG_SA_RED_GATE,
BG_SA_PURPLE_GATE,
BG_SA_ANCIENT_GATE,
BG_SA_TITAN_RELIC,
BG_SA_BOAT_ONE,
BG_SA_BOAT_TWO,
BG_SA_SIGIL_1,
BG_SA_SIGIL_2,
BG_SA_SIGIL_3,
BG_SA_SIGIL_4,
BG_SA_SIGIL_5,
BG_SA_CENTRAL_FLAGPOLE,
BG_SA_RIGHT_FLAGPOLE,
BG_SA_LEFT_FLAGPOLE,
BG_SA_CENTRAL_FLAG,
BG_SA_RIGHT_FLAG,
BG_SA_LEFT_FLAG,
BG_SA_PORTAL_DEFFENDER_BLUE,
BG_SA_PORTAL_DEFFENDER_GREEN,
BG_SA_PORTAL_DEFFENDER_YELLOW,
BG_SA_PORTAL_DEFFENDER_PURPLE,
BG_SA_PORTAL_DEFFENDER_RED,
BG_SA_BOMB,
BG_SA_MAXOBJ = BG_SA_BOMB+68
};
float const BG_SA_ObjSpawnlocs[BG_SA_MAXOBJ][4] =
{
{ 1411.57f, 108.163f, 28.692f, 5.441f },
{ 1055.452f, -108.1f, 82.134f, 0.034f },
{ 1431.3413f, -219.437f, 30.893f, 0.9736f },
{ 1227.667f, -212.555f, 55.372f, 0.5023f },
{ 1214.681f, 81.21f, 53.413f, 5.745f },
{ 878.555f, -108.2f, 117.845f, 0.0f },
{ 836.5f, -108.8f, 120.219f, 0.0f },
// Ships
{ 2679.696777f, -826.891235f, 3.712860f, 5.78367f}, //rot2 1 rot3 0.0002f
{ 2574.003662f, 981.261475f, 2.603424f, 0.807696f},
// Sigils
{ 1414.054f, 106.72f, 41.442f, 5.441f },
{ 1060.63f, -107.8f, 94.7f, 0.034f },
{ 1433.383f, -216.4f, 43.642f, 0.9736f },
{ 1230.75f, -210.724f, 67.611f, 0.5023f },
{ 1217.8f, 79.532f, 66.58f, 5.745f },
// Flagpoles
{ 1215.114258f, -65.711861f, 70.084267f, -3.124123f},
{1338.863892f, -153.336533f, 30.895121f, -2.530723f},
{1309.124268f, 9.410645f, 30.893402f, -1.623156f},
// Flags
{ 1215.108032f, -65.715767f, 70.084267f, -3.124123f},
{ 1338.859253f, -153.327316f, 30.895077f, -2.530723f},
{ 1309.192017f, 9.416233f, 30.893402f, 1.518436f},
// Portal
{1468.380005f, -225.798996f, 30.896200f, 0.0f}, //blue
{1394.270020f, 72.551399f, 31.054300f, 0.0f}, //green
{1065.260010f, -89.79501f, 81.073402f, 0.0f}, //yellow
{1216.069946f, 47.904301f, 54.278198f, 0.0f}, //purple
{1255.569946f, -233.548996f, 56.43699f, 0.0f}, //red
// Bombs
{1333.45f, 211.354f, 31.0538f, 5.03666f},
{1334.29f, 209.582f, 31.0532f, 1.28088f},
{1332.72f, 210.049f, 31.0532f, 1.28088f},
{1334.28f, 210.78f, 31.0538f, 3.85856f},
{1332.64f, 211.39f, 31.0532f, 1.29266f},
{1371.41f, 194.028f, 31.5107f, 0.753095f},
{1372.39f, 194.951f, 31.4679f, 0.753095f},
{1371.58f, 196.942f, 30.9349f, 1.01777f},
{1370.43f, 196.614f, 30.9349f, 0.957299f},
{1369.46f, 196.877f, 30.9351f, 2.45348f},
{1370.35f, 197.361f, 30.9349f, 1.08689f},
{1369.47f, 197.941f, 30.9349f, 0.984787f},
{1592.49f, 47.5969f, 7.52271f, 4.63218f},
{1593.91f, 47.8036f, 7.65856f, 4.63218f},
{1593.13f, 46.8106f, 7.54073f, 4.63218f},
{1589.22f, 36.3616f, 7.45975f, 4.64396f},
{1588.24f, 35.5842f, 7.55613f, 4.79564f},
{1588.14f, 36.7611f, 7.49675f, 4.79564f},
{1595.74f, 35.5278f, 7.46602f, 4.90246f},
{1596, 36.6475f, 7.47991f, 4.90246f},
{1597.03f, 36.2356f, 7.48631f, 4.90246f},
{1597.93f, 37.1214f, 7.51725f, 4.90246f},
{1598.16f, 35.888f, 7.50018f, 4.90246f},
{1579.6f, -98.0917f, 8.48478f, 1.37996f},
{1581.2f, -98.401f, 8.47483f, 1.37996f},
{1580.38f, -98.9556f, 8.4772f, 1.38781f},
{1585.68f, -104.966f, 8.88551f, 0.493246f},
{1586.15f, -106.033f, 9.10616f, 0.493246f},
{1584.88f, -105.394f, 8.82985f, 0.493246f},
{1581.87f, -100.899f, 8.46164f, 0.929142f},
{1581.48f, -99.4657f, 8.46926f, 0.929142f},
{1583.2f, -91.2291f, 8.49227f, 1.40038f},
{1581.94f, -91.0119f, 8.49977f, 1.40038f},
{1582.33f, -91.951f, 8.49353f, 1.1844f},
{1342.06f, -304.049f, 30.9532f, 5.59507f},
{1340.96f, -304.536f, 30.9458f, 1.28323f},
{1341.22f, -303.316f, 30.9413f, 0.486051f},
{1342.22f, -302.939f, 30.986f, 4.87643f},
{1382.16f, -287.466f, 32.3063f, 4.80968f},
{1381, -287.58f, 32.2805f, 4.80968f},
{1381.55f, -286.536f, 32.3929f, 2.84225f},
{1382.75f, -286.354f, 32.4099f, 1.00442f},
{1379.92f, -287.34f, 32.2872f, 3.81615f},
{1100.52f, -2.41391f, 70.2984f, 0.131054f},
{1099.35f, -2.13851f, 70.3375f, 4.4586f},
{1099.59f, -1.00329f, 70.238f, 2.49903f},
{1097.79f, 0.571316f, 70.159f, 4.00307f},
{1098.74f, -7.23252f, 70.7972f, 4.1523f},
{1098.46f, -5.91443f, 70.6715f, 4.1523f},
{1097.53f, -7.39704f, 70.7959f, 4.1523f},
{1097.32f, -6.64233f, 70.7424f, 4.1523f},
{1096.45f, -5.96664f, 70.7242f, 4.1523f},
{971.725f, 0.496763f, 86.8467f, 2.09233f},
{973.589f, 0.119518f, 86.7985f, 3.17225f},
{972.524f, 1.25333f, 86.8351f, 5.28497f},
{971.993f, 2.05668f, 86.8584f, 5.28497f},
{973.635f, 2.11805f, 86.8197f, 2.36722f},
{974.791f, 1.74679f, 86.7942f, 1.5936f},
{974.771f, 3.0445f, 86.8125f, 0.647199f},
{979.554f, 3.6037f, 86.7923f, 1.69178f},
{979.758f, 2.57519f, 86.7748f, 1.76639f},
{980.769f, 3.48904f, 86.7939f, 1.76639f},
{979.122f, 2.87109f, 86.7794f, 1.76639f},
{986.167f, 4.85363f, 86.8439f, 1.5779f},
{986.176f, 3.50367f, 86.8217f, 1.5779f},
{987.33f, 4.67389f, 86.8486f, 1.5779f},
{985.23f, 4.65898f, 86.8368f, 1.5779f},
{984.556f, 3.54097f, 86.8137f, 1.5779f},
};
/* Ships:
* 193182 - ally
* 193183 - horde
* 193184 - horde
* 193185 - ally
* Banners:
* 191308 - left one,
* 191306 - right one,
* 191310 - central,
* Ally ones, substract 1
* to get horde ones.
*/
uint32 const BG_SA_ObjEntries[BG_SA_MAXOBJ + BG_SA_FLAG_AMOUNT] =
{
190722,
190727,
190724,
190726,
190723,
192549,
192834,
0, // Boat
0, // Boat
192687,
192685,
192689,
192690,
192691,
191311,
191311,
191311,
191310,
191306,
191308,
192819,
192819,
192819,
192819,
192819,
190753
};
uint32 const BG_SA_Factions[2] =
{
1732,
1735,
};
enum BG_SA_Graveyards
{
BG_SA_BEACH_GY = 0,
BG_SA_DEFENDER_LAST_GY,
BG_SA_RIGHT_CAPTURABLE_GY,
BG_SA_LEFT_CAPTURABLE_GY,
BG_SA_CENTRAL_CAPTURABLE_GY,
BG_SA_MAX_GY
};
const uint32 BG_SA_GYEntries[BG_SA_MAX_GY] =
{
1350,
1349,
1347,
1346,
1348,
};
float const BG_SA_GYOrientation[BG_SA_MAX_GY] =
{
6.202f,
1.926f, // right capturable GY
3.917f, // left capturable GY
3.104f, // center, capturable
6.148f, // defender last GY
};
struct BG_SA_RoundScore
{
TeamId winner;
uint32 time;
};
const float SOTADefPortalDest[5][4] = {
{ 1388.94f, 103.067f, 34.49f, 5.4571f },
{ 1043.69f, -87.95f, 87.12f, 0.003f },
{ 1441.0411f, -240.974f, 35.264f, 0.949f },
{ 1228.342f, -235.234f, 60.03f, 0.4584f },
{ 1193.857f, 69.9f, 58.046f, 5.7245f },
};
/// Class for manage Strand of Ancient battleground
class BattlegroundSA : public Battleground
{
public:
BattlegroundSA();
~BattlegroundSA();
/**
* \brief Called every time for update battle data
* -Update timer
* -Round switch
*/
void PostUpdateImpl(uint32 diff);
/* inherited from BattlegroundClass */
/// Called when a player join battle
void AddPlayer(Player* player);
/// Called when battle start
void StartingEventCloseDoors();
void StartingEventOpenDoors();
/// Called for ini battleground, after that the first player be entered
bool SetupBattleground();
void Init();
/// Called for generate packet contain worldstate data
void FillInitialWorldStates(WorldPacket& data);
/// Called when a player deal damage to building (door)
void EventPlayerDamagedGO(Player* player, GameObject* go, uint32 eventType);
/// Called when a player kill a unit in bg
void HandleKillUnit(Creature* creature, Player* killer);
/// Return the nearest graveyard where player can respawn
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
/// Called when a player click on flag (graveyard flag)
void EventPlayerClickedOnFlag(Player* Source, GameObject* gameObject);
/// Called when a player use a gamobject (relic)
void EventPlayerUsedGO(Player* Source, GameObject* object);
/// Return worldstate id, according to door id
uint32 GetWorldStateFromGateID(uint32 id)
{
uint32 uws = 0;
switch (id)
{
case BG_SA_GREEN_GATE: uws = BG_SA_GREEN_GATEWS; break;
case BG_SA_YELLOW_GATE: uws = BG_SA_YELLOW_GATEWS; break;
case BG_SA_BLUE_GATE: uws = BG_SA_BLUE_GATEWS; break;
case BG_SA_RED_GATE: uws = BG_SA_RED_GATEWS; break;
case BG_SA_PURPLE_GATE: uws = BG_SA_PURPLE_GATEWS; break;
case BG_SA_ANCIENT_GATE: uws = BG_SA_ANCIENT_GATEWS; break;
}
return uws;
}
/// Called on battleground ending
void EndBattleground(TeamId winnerTeamId);
/// CAlled when a player leave battleground
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
/* Scorekeeping */
/// Update score board
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
// Teleporters
void DefendersPortalTeleport(GameObject* portal, Player* plr);
// Achievements
bool AllowDefenseOfTheAncients(Player* source);
// Achievement: Not Even a Scratch
bool notEvenAScratch(TeamId teamId) const { return _notEvenAScratch[teamId]; }
private:
/// Return gate id, relative to bg data, according to gameobject id
uint32 GetGateIDFromEntry(uint32 id)
{
uint32 i = 0;
switch(id)
{
case 190722: i = BG_SA_GREEN_GATE; break; //Green gate destroyed
case 190724: i = BG_SA_BLUE_GATE; break; //blue gate
case 190726: i = BG_SA_RED_GATE; break; //red gate
case 190723: i = BG_SA_PURPLE_GATE; break; //purple gate
case 190727: i = BG_SA_YELLOW_GATE; break; //yellow gate
case 192549: i = BG_SA_ANCIENT_GATE; break; //ancient gate
}
return i;
}
/**
* \brief Called on setup and between the two round
* -Delete all gameobject / creature
* -Respawn all gameobject / creature to have good faction
*/
bool ResetObjs();
/// Called for start ship movement
void StartShips();
/**
* \brief Called between the two round
* -Teleport all players to good location
*/
void TeleportPlayers();
void TeleportToEntrancePosition(Player* player);
/**
* \brief Called on start and between the two round
* -Update faction of all vehicle
*/
void OverrideGunFaction();
/// Set selectable or not demolisher, called on battle start, when boats arrive to dock
void DemolisherStartState(bool start);
/// Checks if a player can interact with the given object
bool CanInteractWithObject(uint32 objectId);
/// Updates interaction flags of specific objects
void UpdateObjectInteractionFlags(uint32 objectId);
void UpdateObjectInteractionFlags();
/**
* \brief Called when a gate is destroy
* -Give honor to player witch destroy it
* -Update worldstate
* -Delete gameobject in front of door (lighting object, with different colours for each door)
*/
void DestroyGate(Player* player, GameObject* go);
/// Update timer worldstate
void SendTime();
/**
* \brief Called when a graveyard is capture
* -Update spiritguide
* -Update gameobject (flag)
* -Update Worldstate
* -Send warning for announce this
* \param i : id of graveyard
* \param Source : Player who capture gy
*/
void CaptureGraveyard(BG_SA_Graveyards i, Player* Source);
/// Switch on/off timer worldstate
void ToggleTimer();
/// Respawn dead demolisher
void UpdateDemolisherSpawns();
/// Send packet to player for create boats (client part)
void SendTransportInit(Player* player);
/// Send packet to player for destroy boats (client part)
void SendTransportsRemove(Player* player);
/// Id of attacker team
TeamId Attackers;
/// Totale elapsed time of current round
uint32 TotalTime;
/// Max time of round
uint32 EndRoundTimer;
/// For know if boats has start moving or not yet
bool ShipsStarted;
/// Status of each gate (Destroy/Damage/Intact)
BG_SA_GateState GateStatus[6];
/// Statu of battle (Start or not, and what round)
BG_SA_Status Status;
/// Team witch conntrol each graveyard
TeamId GraveyardStatus[BG_SA_MAX_GY];
/// Score of each round
BG_SA_RoundScore RoundScores[2];
/// used for know we are in timer phase or not (used for worldstate update)
bool TimerEnabled;
/// 5secs before starting the 1min countdown for second round
uint32 UpdateWaitTimer;
/// for know if warning about second round start has been sent
bool SignaledRoundTwo;
/// for know if warning about second round start has been sent
bool SignaledRoundTwoHalfMin;
/// for know if second round has been init
bool InitSecondRound;
std::map<uint32/*id*/, uint32/*timer*/> DemoliserRespawnList;
// xinef:
bool _relicClicked;
// Achievement: Not Even a Scratch
bool _notEvenAScratch[BG_TEAMS_COUNT];
};
#endif
@@ -0,0 +1,551 @@
/*
REWRITTEN BY XINEF
*/
#include "BattlegroundWS.h"
#include "Creature.h"
#include "GameObject.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "BattlegroundMgr.h"
#include "Player.h"
#include "World.h"
#include "WorldPacket.h"
BattlegroundWS::BattlegroundWS()
{
BgObjects.resize(BG_WS_OBJECT_MAX);
BgCreatures.resize(BG_CREATURES_MAX_WS);
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
_flagKeepers[TEAM_ALLIANCE] = 0;
_flagKeepers[TEAM_HORDE] = 0;
_droppedFlagGUID[TEAM_ALLIANCE] = 0;
_droppedFlagGUID[TEAM_HORDE] = 0;
_flagState[TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE;
_flagState[TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
_lastFlagCaptureTeam = TEAM_NEUTRAL;
_reputationCapture = 0;
_honorWinKills = 0;
_honorEndKills = 0;
}
BattlegroundWS::~BattlegroundWS()
{
}
void BattlegroundWS::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
_bgEvents.Update(diff);
switch (_bgEvents.ExecuteEvent())
{
case BG_WS_EVENT_UPDATE_GAME_TIME:
UpdateWorldState(BG_WS_STATE_TIMER, GetMatchTime());
_bgEvents.ScheduleEvent(BG_WS_EVENT_UPDATE_GAME_TIME, ((BG_WS_TOTAL_GAME_TIME - GetStartTime()) % (MINUTE*IN_MILLISECONDS)) + 1);
break;
case BG_WS_EVENT_NO_TIME_LEFT:
if (GetTeamScore(TEAM_ALLIANCE) == GetTeamScore(TEAM_HORDE))
EndBattleground(_lastFlagCaptureTeam);
else
EndBattleground(GetTeamScore(TEAM_HORDE) > GetTeamScore(TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE);
break;
case BG_WS_EVENT_RESPAWN_BOTH_FLAGS:
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
break;
case BG_WS_EVENT_ALLIANCE_DROP_FLAG:
RespawnFlagAfterDrop(TEAM_ALLIANCE);
break;
case BG_WS_EVENT_HORDE_DROP_FLAG:
RespawnFlagAfterDrop(TEAM_HORDE);
break;
case BG_WS_EVENT_BOTH_FLAGS_KEPT10:
if (Player* player = ObjectAccessor::GetObjectInMap(GetFlagPickerGUID(TEAM_ALLIANCE), this->FindBgMap(), (Player*)NULL))
player->CastSpell(player, BG_WS_SPELL_FOCUSED_ASSAULT, true);
if (Player* player = ObjectAccessor::GetObjectInMap(GetFlagPickerGUID(TEAM_HORDE), this->FindBgMap(), (Player*)NULL))
player->CastSpell(player, BG_WS_SPELL_FOCUSED_ASSAULT, true);
break;
case BG_WS_EVENT_BOTH_FLAGS_KEPT15:
if (Player* player = ObjectAccessor::GetObjectInMap(GetFlagPickerGUID(TEAM_ALLIANCE), this->FindBgMap(), (Player*)NULL))
{
player->RemoveAurasDueToSpell(BG_WS_SPELL_FOCUSED_ASSAULT);
player->CastSpell(player, BG_WS_SPELL_BRUTAL_ASSAULT, true);
}
if (Player* player = ObjectAccessor::GetObjectInMap(GetFlagPickerGUID(TEAM_HORDE), this->FindBgMap(), (Player*)NULL))
{
player->RemoveAurasDueToSpell(BG_WS_SPELL_FOCUSED_ASSAULT);
player->CastSpell(player, BG_WS_SPELL_BRUTAL_ASSAULT, true);
}
break;
}
}
}
void BattlegroundWS::StartingEventCloseDoors()
{
for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; ++i)
{
DoorClose(i);
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattlegroundWS::StartingEventOpenDoors()
{
for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_6; ++i)
DoorOpen(i);
for (uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_4; ++i)
DoorOpen(i);
for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, WS_EVENT_START_BATTLE);
UpdateWorldState(BG_WS_STATE_TIMER_ACTIVE, 1);
_bgEvents.ScheduleEvent(BG_WS_EVENT_UPDATE_GAME_TIME, 0);
_bgEvents.ScheduleEvent(BG_WS_EVENT_NO_TIME_LEFT, BG_WS_TOTAL_GAME_TIME - 2*MINUTE*IN_MILLISECONDS); // 27 - 2 = 25 minutes
}
void BattlegroundWS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundWGScore(player);
}
void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId)
{
if (GetStatus() != STATUS_IN_PROGRESS || GetFlagState(teamId) != BG_WS_FLAG_STATE_ON_GROUND)
return;
UpdateFlagState(teamId, BG_WS_FLAG_STATE_ON_BASE);
SpawnBGObject(teamId == TEAM_ALLIANCE ? BG_WS_OBJECT_A_FLAG : BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(teamId == TEAM_ALLIANCE ? LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED : LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
if (GameObject* flag = GetBgMap()->GetGameObject(GetDroppedFlagGUID(teamId)))
flag->Delete();
SetDroppedFlagGUID(0, teamId);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras();
}
void BattlegroundWS::EventPlayerCapturedFlag(Player* player)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
RemoveAssaultAuras();
AddPoints(player->GetTeamId(), 1);
SetFlagPicker(0, GetOtherTeamId(player->GetTeamId()));
UpdateFlagState(GetOtherTeamId(player->GetTeamId()), BG_WS_FLAG_STATE_ON_BASE);
if (player->GetTeamId() == TEAM_ALLIANCE)
{
player->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE);
SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
RewardReputationToTeam(890, _reputationCapture, TEAM_ALLIANCE);
}
else
{
player->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE);
SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, player);
RewardReputationToTeam(889, _reputationCapture, TEAM_HORDE);
}
SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME);
UpdateWorldState(player->GetTeamId() == TEAM_ALLIANCE ? BG_WS_FLAG_CAPTURES_ALLIANCE : BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(player->GetTeamId()));
UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1); // +1 flag captures
_lastFlagCaptureTeam = player->GetTeamId();
RewardHonorToTeam(GetBonusHonorFromKill(2), player->GetTeamId());
if (GetTeamScore(TEAM_ALLIANCE) == BG_WS_MAX_TEAM_SCORE || GetTeamScore(TEAM_HORDE) == BG_WS_MAX_TEAM_SCORE)
{
UpdateWorldState(BG_WS_STATE_TIMER_ACTIVE, 0);
EndBattleground(GetTeamScore(TEAM_HORDE) == BG_WS_MAX_TEAM_SCORE ? TEAM_HORDE : TEAM_ALLIANCE);
}
else
_bgEvents.ScheduleEvent(BG_WS_EVENT_RESPAWN_BOTH_FLAGS, BG_WS_FLAG_RESPAWN_TIME);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
}
void BattlegroundWS::EventPlayerDroppedFlag(Player* player)
{
if (GetFlagPickerGUID(TEAM_HORDE) != player->GetGUID() && GetFlagPickerGUID(TEAM_ALLIANCE) != player->GetGUID())
return;
SetFlagPicker(0, GetOtherTeamId(player->GetTeamId()));
player->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
player->RemoveAurasDueToSpell(BG_WS_SPELL_FOCUSED_ASSAULT);
player->RemoveAurasDueToSpell(BG_WS_SPELL_BRUTAL_ASSAULT);
if (GetStatus() != STATUS_IN_PROGRESS)
return;
player->CastSpell(player, SPELL_RECENTLY_DROPPED_FLAG, true);
if (player->GetTeamId() == TEAM_ALLIANCE)
{
UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_GROUND);
player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true);
SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, player);
_bgEvents.RescheduleEvent(BG_WS_EVENT_HORDE_DROP_FLAG, BG_WS_FLAG_DROP_TIME);
}
else
{
UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_GROUND);
player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true);
SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
_bgEvents.RescheduleEvent(BG_WS_EVENT_ALLIANCE_DROP_FLAG, BG_WS_FLAG_DROP_TIME);
}
}
void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
int32 message_id = 0;
ChatMsg type = CHAT_MSG_BG_SYSTEM_NEUTRAL;
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
// Alliance Flag picked up from base
if (player->GetTeamId() == TEAM_HORDE && GetFlagState(TEAM_ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE && BgObjects[BG_WS_OBJECT_A_FLAG] == gameObject->GetGUID())
{
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY);
SetFlagPicker(player->GetGUID(), TEAM_ALLIANCE);
UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER);
player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG, true);
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED);
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_AF, CHAT_MSG_BG_SYSTEM_HORDE, player);
if (GetFlagState(TEAM_HORDE) != BG_WS_FLAG_STATE_ON_BASE)
{
_bgEvents.RescheduleEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10, BG_WS_SPELL_FORCE_TIME);
_bgEvents.RescheduleEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15, BG_WS_SPELL_BRUTAL_TIME);
}
return;
}
// Horde Flag picked up from base
if (player->GetTeamId() == TEAM_ALLIANCE && GetFlagState(TEAM_HORDE) == BG_WS_FLAG_STATE_ON_BASE && BgObjects[BG_WS_OBJECT_H_FLAG] == gameObject->GetGUID())
{
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY);
SetFlagPicker(player->GetGUID(), TEAM_HORDE);
UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_PLAYER);
player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG, true);
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED);
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
if (GetFlagState(TEAM_ALLIANCE) != BG_WS_FLAG_STATE_ON_BASE)
{
_bgEvents.RescheduleEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10, BG_WS_SPELL_FORCE_TIME);
_bgEvents.RescheduleEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15, BG_WS_SPELL_BRUTAL_TIME);
}
return;
}
// Alliance Flag on ground
if (GetFlagState(TEAM_ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && player->IsWithinDistInMap(gameObject, 10.0f) && gameObject->GetEntry() == BG_OBJECT_A_FLAG_GROUND_WS_ENTRY)
{
SetDroppedFlagGUID(0, TEAM_ALLIANCE);
if (player->GetTeamId() == TEAM_ALLIANCE)
{
UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_BASE);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY);
UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED);
SendMessageToAll(LANG_BG_WS_RETURNED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras();
return;
}
else
{
SetFlagPicker(player->GetGUID(), TEAM_ALLIANCE);
UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER);
player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG, true);
if (uint32 assaultSpellId = GetAssaultSpellId())
player->CastSpell(player, assaultSpellId, true);
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_AF, CHAT_MSG_BG_SYSTEM_HORDE, player);
return;
}
}
// Horde Flag on ground
if (GetFlagState(TEAM_HORDE) == BG_WS_FLAG_STATE_ON_GROUND && player->IsWithinDistInMap(gameObject, 10.0f) && gameObject->GetEntry() == BG_OBJECT_H_FLAG_GROUND_WS_ENTRY)
{
SetDroppedFlagGUID(0, TEAM_HORDE);
if (player->GetTeamId() == TEAM_HORDE)
{
UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_BASE);
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED);
SendMessageToAll(LANG_BG_WS_RETURNED_HF, CHAT_MSG_BG_SYSTEM_HORDE, player);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras();
return;
}
else
{
SetFlagPicker(player->GetGUID(), TEAM_HORDE);
UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_PLAYER);
player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG, true);
if (uint32 assaultSpellId = GetAssaultSpellId())
player->CastSpell(player, assaultSpellId, true);
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
return;
}
}
}
void BattlegroundWS::RemovePlayer(Player* player)
{
if (GetFlagPickerGUID(TEAM_ALLIANCE) == player->GetGUID() || GetFlagPickerGUID(TEAM_HORDE) == player->GetGUID())
EventPlayerDroppedFlag(player);
}
void BattlegroundWS::UpdateFlagState(TeamId teamId, uint32 value)
{
_flagState[teamId] = value;
UpdateWorldState(teamId == TEAM_ALLIANCE ? BG_WS_FLAG_STATE_HORDE : BG_WS_FLAG_STATE_ALLIANCE, value);
}
void BattlegroundWS::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS || !player->IsAlive())
return;
switch (trigger)
{
case 3646: // Alliance Flag spawn
if (GetFlagState(TEAM_ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE && GetFlagPickerGUID(TEAM_HORDE) == player->GetGUID())
EventPlayerCapturedFlag(player);
break;
case 3647: // Horde Flag spawn
if (GetFlagState(TEAM_HORDE) == BG_WS_FLAG_STATE_ON_BASE && GetFlagPickerGUID(TEAM_ALLIANCE) == player->GetGUID())
EventPlayerCapturedFlag(player);
break;
case 3649: // Not used
case 3688: // Not used
case 4628: // Not used
case 4629: // Not used
case 3686: // Alliance elixir of speed spawn
case 3687: // Horde elixir of speed spawn
case 3706: // Alliance elixir of regeneration spawn
case 3708: // Horde elixir of regeneration spawn
case 3707: // Alliance elixir of berserk spawn
case 3709: // Horde elixir of berserk spawn
break;
}
}
bool BattlegroundWS::SetupBattleground()
{
// flags
AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, RESPAWN_IMMEDIATELY);
// buffs
AddObject(BG_WS_OBJECT_SPEEDBUFF_1, BG_OBJECTID_SPEEDBUFF_ENTRY, 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BUFF_RESPAWN_TIME);
AddObject(BG_WS_OBJECT_SPEEDBUFF_2, BG_OBJECTID_SPEEDBUFF_ENTRY, 1005.171f, 1447.946f, 335.9032f, 1.64061f, 0, 0, 0.7313537f, 0.6819984f, BUFF_RESPAWN_TIME);
AddObject(BG_WS_OBJECT_REGENBUFF_1, BG_OBJECTID_REGENBUFF_ENTRY, 1317.506f, 1550.851f, 313.2344f, -0.2617996f, 0, 0, 0.1305263f, -0.9914448f, BUFF_RESPAWN_TIME);
AddObject(BG_WS_OBJECT_REGENBUFF_2, BG_OBJECTID_REGENBUFF_ENTRY, 1110.451f, 1353.656f, 316.5181f, -0.6806787f, 0, 0, 0.333807f, -0.9426414f, BUFF_RESPAWN_TIME);
AddObject(BG_WS_OBJECT_BERSERKBUFF_1, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1320.09f, 1378.79f, 314.7532f, 1.186824f, 0, 0, 0.5591929f, 0.8290376f, BUFF_RESPAWN_TIME);
AddObject(BG_WS_OBJECT_BERSERKBUFF_2, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1139.688f, 1560.288f, 306.8432f, -2.443461f, 0, 0, 0.9396926f, -0.3420201f, BUFF_RESPAWN_TIME);
// alliance gates
AddObject(BG_WS_OBJECT_DOOR_A_1, BG_OBJECT_DOOR_A_1_WS_ENTRY, 1503.335f, 1493.466f, 352.1888f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_A_2, BG_OBJECT_DOOR_A_2_WS_ENTRY, 1492.478f, 1457.912f, 342.9689f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_A_3, BG_OBJECT_DOOR_A_3_WS_ENTRY, 1468.503f, 1494.357f, 351.8618f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_A_4, BG_OBJECT_DOOR_A_4_WS_ENTRY, 1471.555f, 1458.778f, 362.6332f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_A_5, BG_OBJECT_DOOR_A_5_WS_ENTRY, 1492.347f, 1458.34f, 342.3712f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_A_6, BG_OBJECT_DOOR_A_6_WS_ENTRY, 1503.466f, 1493.367f, 351.7352f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY);
// horde gates
AddObject(BG_WS_OBJECT_DOOR_H_1, BG_OBJECT_DOOR_H_1_WS_ENTRY, 949.1663f, 1423.772f, 345.6241f, -0.5756807f, -0.01673368f, -0.004956111f, -0.2839723f, 0.9586737f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_H_2, BG_OBJECT_DOOR_H_2_WS_ENTRY, 953.0507f, 1459.842f, 340.6526f, -1.99662f, -0.1971825f, 0.1575096f, -0.8239487f, 0.5073641f, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_H_3, BG_OBJECT_DOOR_H_3_WS_ENTRY, 949.9523f, 1422.751f, 344.9273f, 0.0f, 0, 0, 0, 1, RESPAWN_IMMEDIATELY);
AddObject(BG_WS_OBJECT_DOOR_H_4, BG_OBJECT_DOOR_H_4_WS_ENTRY, 950.7952f, 1459.583f, 342.1523f, 0.05235988f, 0, 0, 0.02617695f, 0.9996573f, RESPAWN_IMMEDIATELY);
WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE);
AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, TEAM_ALLIANCE);
sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE);
AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, TEAM_HORDE);
for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i < BG_WS_OBJECT_MAX; ++i)
if (BgObjects[i] == 0)
{
sLog->outErrorDb("BatteGroundWS: Failed to spawn some object Battleground not created!");
return false;
}
for (uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i < BG_CREATURES_MAX_WS; ++i)
if (BgCreatures[i] == 0)
{
sLog->outErrorDb("BatteGroundWS: Failed to spawn spirit guides Battleground not created!");
return false;
}
return true;
}
void BattlegroundWS::Init()
{
//call parent's class reset
Battleground::Init();
_bgEvents.Reset();
_flagKeepers[TEAM_ALLIANCE] = 0;
_flagKeepers[TEAM_HORDE] = 0;
_droppedFlagGUID[TEAM_ALLIANCE] = 0;
_droppedFlagGUID[TEAM_HORDE] = 0;
_flagState[TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE;
_flagState[TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
_lastFlagCaptureTeam = TEAM_NEUTRAL;
if (sBattlegroundMgr->IsBGWeekend(GetBgTypeID()))
{
_reputationCapture = 45;
_honorWinKills = 3;
_honorEndKills = 4;
}
else
{
_reputationCapture = 35;
_honorWinKills = 1;
_honorEndKills = 2;
}
}
void BattlegroundWS::EndBattleground(TeamId winnerTeamId)
{
// Win reward
RewardHonorToTeam(GetBonusHonorFromKill(_honorWinKills), winnerTeamId);
// Complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(_honorEndKills), TEAM_ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(_honorEndKills), TEAM_HORDE);
Battleground::EndBattleground(winnerTeamId);
}
void BattlegroundWS::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
EventPlayerDroppedFlag(player);
Battleground::HandleKillPlayer(player, killer);
}
void BattlegroundWS::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
if (itr == PlayerScores.end())
return;
switch (type)
{
case SCORE_FLAG_CAPTURES:
((BattlegroundWGScore*)itr->second)->FlagCaptures += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG);
break;
case SCORE_FLAG_RETURNS:
((BattlegroundWGScore*)itr->second)->FlagReturns += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG);
break;
default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
}
}
WorldSafeLocsEntry const* BattlegroundWS::GetClosestGraveyard(Player* player)
{
if (GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(player->GetTeamId() == TEAM_ALLIANCE ? WS_GRAVEYARD_MAIN_ALLIANCE : WS_GRAVEYARD_MAIN_HORDE);
else
return sWorldSafeLocsStore.LookupEntry(player->GetTeamId() == TEAM_ALLIANCE ? WS_GRAVEYARD_FLAGROOM_ALLIANCE : WS_GRAVEYARD_FLAGROOM_HORDE);
}
void BattlegroundWS::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE);
data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(GetStatus() == STATUS_IN_PROGRESS);
data << uint32(BG_WS_STATE_TIMER) << uint32(GetMatchTime());
data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(GetFlagState(TEAM_HORDE));
data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(GetFlagState(TEAM_ALLIANCE));
}
TeamId BattlegroundWS::GetPrematureWinner()
{
if (GetTeamScore(TEAM_ALLIANCE) > GetTeamScore(TEAM_HORDE))
return TEAM_ALLIANCE;
return GetTeamScore(TEAM_HORDE) > GetTeamScore(TEAM_ALLIANCE) ? TEAM_HORDE : Battleground::GetPrematureWinner();
}
uint32 BattlegroundWS::GetAssaultSpellId() const
{
if ((GetFlagPickerGUID(TEAM_ALLIANCE) == 0 && GetFlagState(TEAM_ALLIANCE) != BG_WS_FLAG_STATE_ON_GROUND) ||
(GetFlagPickerGUID(TEAM_HORDE) == 0 && GetFlagState(TEAM_HORDE) != BG_WS_FLAG_STATE_ON_GROUND) ||
_bgEvents.GetNextEventTime(BG_WS_EVENT_BOTH_FLAGS_KEPT10) > 0)
return 0;
return _bgEvents.GetNextEventTime(BG_WS_EVENT_BOTH_FLAGS_KEPT15) > 0 ? BG_WS_SPELL_FOCUSED_ASSAULT : BG_WS_SPELL_BRUTAL_ASSAULT;
}
void BattlegroundWS::RemoveAssaultAuras()
{
if (Player* player = ObjectAccessor::GetObjectInMap(GetFlagPickerGUID(TEAM_ALLIANCE), this->FindBgMap(), (Player*)NULL))
{
player->RemoveAurasDueToSpell(BG_WS_SPELL_FOCUSED_ASSAULT);
player->RemoveAurasDueToSpell(BG_WS_SPELL_BRUTAL_ASSAULT);
}
if (Player* player = ObjectAccessor::GetObjectInMap(GetFlagPickerGUID(TEAM_HORDE), this->FindBgMap(), (Player*)NULL))
{
player->RemoveAurasDueToSpell(BG_WS_SPELL_FOCUSED_ASSAULT);
player->RemoveAurasDueToSpell(BG_WS_SPELL_BRUTAL_ASSAULT);
}
}
@@ -0,0 +1,205 @@
/*
REWRITTEN BY XINEF
*/
#ifndef __BATTLEGROUNDWS_H
#define __BATTLEGROUNDWS_H
#include "Battleground.h"
enum BG_WS_Events
{
BG_WS_EVENT_UPDATE_GAME_TIME = 1,
BG_WS_EVENT_NO_TIME_LEFT = 2,
BG_WS_EVENT_RESPAWN_BOTH_FLAGS = 3,
BG_WS_EVENT_ALLIANCE_DROP_FLAG = 4,
BG_WS_EVENT_HORDE_DROP_FLAG = 5,
BG_WS_EVENT_BOTH_FLAGS_KEPT10 = 6,
BG_WS_EVENT_BOTH_FLAGS_KEPT15 = 7
};
enum BG_WS_TimerOrScore
{
BG_WS_MAX_TEAM_SCORE = 3,
BG_WS_TOTAL_GAME_TIME = 27*MINUTE*IN_MILLISECONDS,
BG_WS_FLAG_RESPAWN_TIME = 23*IN_MILLISECONDS,
BG_WS_FLAG_DROP_TIME = 10*IN_MILLISECONDS,
BG_WS_SPELL_FORCE_TIME = 10*MINUTE*IN_MILLISECONDS,
BG_WS_SPELL_BRUTAL_TIME = 15*MINUTE*IN_MILLISECONDS
};
enum BG_WS_Sound
{
BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
BG_WS_SOUND_FLAG_CAPTURED_HORDE = 8213,
BG_WS_SOUND_FLAG_PLACED = 8232,
BG_WS_SOUND_FLAG_RETURNED = 8192,
BG_WS_SOUND_HORDE_FLAG_PICKED_UP = 8212,
BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP = 8174,
BG_WS_SOUND_FLAGS_RESPAWNED = 8232
};
enum BG_WS_SpellId
{
BG_WS_SPELL_WARSONG_FLAG = 23333,
BG_WS_SPELL_WARSONG_FLAG_DROPPED = 23334,
BG_WS_SPELL_WARSONG_FLAG_PICKED = 61266, // fake spell, does not exist but used as timer start event
BG_WS_SPELL_SILVERWING_FLAG = 23335,
BG_WS_SPELL_SILVERWING_FLAG_DROPPED = 23336,
BG_WS_SPELL_SILVERWING_FLAG_PICKED = 61265, // fake spell, does not exist but used as timer start event
BG_WS_SPELL_FOCUSED_ASSAULT = 46392,
BG_WS_SPELL_BRUTAL_ASSAULT = 46393
};
enum BG_WS_WorldStates
{
BG_WS_FLAG_CAPTURES_ALLIANCE = 1581,
BG_WS_FLAG_CAPTURES_HORDE = 1582,
BG_WS_FLAG_CAPTURES_MAX = 1601,
BG_WS_FLAG_STATE_HORDE = 2338,
BG_WS_FLAG_STATE_ALLIANCE = 2339,
BG_WS_STATE_TIMER = 4248,
BG_WS_STATE_TIMER_ACTIVE = 4247
};
enum BG_WS_ObjectTypes
{
BG_WS_OBJECT_DOOR_A_1 = 0,
BG_WS_OBJECT_DOOR_A_2 = 1,
BG_WS_OBJECT_DOOR_A_3 = 2,
BG_WS_OBJECT_DOOR_A_4 = 3,
BG_WS_OBJECT_DOOR_A_5 = 4,
BG_WS_OBJECT_DOOR_A_6 = 5,
BG_WS_OBJECT_DOOR_H_1 = 6,
BG_WS_OBJECT_DOOR_H_2 = 7,
BG_WS_OBJECT_DOOR_H_3 = 8,
BG_WS_OBJECT_DOOR_H_4 = 9,
BG_WS_OBJECT_A_FLAG = 10,
BG_WS_OBJECT_H_FLAG = 11,
BG_WS_OBJECT_SPEEDBUFF_1 = 12,
BG_WS_OBJECT_SPEEDBUFF_2 = 13,
BG_WS_OBJECT_REGENBUFF_1 = 14,
BG_WS_OBJECT_REGENBUFF_2 = 15,
BG_WS_OBJECT_BERSERKBUFF_1 = 16,
BG_WS_OBJECT_BERSERKBUFF_2 = 17,
BG_WS_OBJECT_MAX = 18
};
enum BG_WS_ObjectEntry
{
BG_OBJECT_DOOR_A_1_WS_ENTRY = 179918,
BG_OBJECT_DOOR_A_2_WS_ENTRY = 179919,
BG_OBJECT_DOOR_A_3_WS_ENTRY = 179920,
BG_OBJECT_DOOR_A_4_WS_ENTRY = 179921,
BG_OBJECT_DOOR_A_5_WS_ENTRY = 180322,
BG_OBJECT_DOOR_A_6_WS_ENTRY = 180322,
BG_OBJECT_DOOR_H_1_WS_ENTRY = 179916,
BG_OBJECT_DOOR_H_2_WS_ENTRY = 179917,
BG_OBJECT_DOOR_H_3_WS_ENTRY = 180322,
BG_OBJECT_DOOR_H_4_WS_ENTRY = 180322,
BG_OBJECT_A_FLAG_WS_ENTRY = 179830,
BG_OBJECT_H_FLAG_WS_ENTRY = 179831,
BG_OBJECT_A_FLAG_GROUND_WS_ENTRY = 179785,
BG_OBJECT_H_FLAG_GROUND_WS_ENTRY = 179786
};
enum BG_WS_FlagState
{
BG_WS_FLAG_STATE_ON_BASE = 1,
BG_WS_FLAG_STATE_ON_PLAYER = 2,
BG_WS_FLAG_STATE_ON_GROUND = 3
};
enum BG_WS_Graveyards
{
WS_GRAVEYARD_FLAGROOM_ALLIANCE = 769,
WS_GRAVEYARD_FLAGROOM_HORDE = 770,
WS_GRAVEYARD_MAIN_ALLIANCE = 771,
WS_GRAVEYARD_MAIN_HORDE = 772
};
enum BG_WS_CreatureTypes
{
WS_SPIRIT_MAIN_ALLIANCE = 0,
WS_SPIRIT_MAIN_HORDE = 1,
BG_CREATURES_MAX_WS = 2
};
enum BG_WS_Objectives
{
WS_OBJECTIVE_CAPTURE_FLAG = 42,
WS_OBJECTIVE_RETURN_FLAG = 44,
WS_EVENT_START_BATTLE = 8563
};
struct BattlegroundWGScore : public BattlegroundScore
{
BattlegroundWGScore(Player* player): BattlegroundScore(player), FlagCaptures(0), FlagReturns(0) { }
~BattlegroundWGScore() { }
uint32 FlagCaptures;
uint32 FlagReturns;
};
class BattlegroundWS : public Battleground
{
public:
/* Construction */
BattlegroundWS();
~BattlegroundWS();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
/* BG Flags */
uint64 GetFlagPickerGUID(TeamId teamId) const { return _flagKeepers[teamId]; }
void SetFlagPicker(uint64 guid, TeamId teamId) { _flagKeepers[teamId] = guid; }
void RespawnFlagAfterDrop(TeamId teamId);
uint8 GetFlagState(TeamId teamId) const { return _flagState[teamId]; }
/* Battleground Events */
void EventPlayerDroppedFlag(Player* player);
void EventPlayerClickedOnFlag(Player* player, GameObject* gameObject);
void EventPlayerCapturedFlag(Player* player);
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
void HandleKillPlayer(Player* player, Player* killer);
bool SetupBattleground();
void Init();
void EndBattleground(TeamId winnerTeamId);
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
void UpdateFlagState(TeamId teamId, uint32 value);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
void SetDroppedFlagGUID(uint64 guid, TeamId teamId) { _droppedFlagGUID[teamId] = guid; }
uint64 GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];}
void FillInitialWorldStates(WorldPacket& data);
/* Scorekeeping */
void AddPoints(TeamId teamId, uint32 points) { m_TeamScores[teamId] += points; }
TeamId GetPrematureWinner();
uint32 GetMatchTime() const { return 1 + (BG_WS_TOTAL_GAME_TIME - GetStartTime()) / (MINUTE*IN_MILLISECONDS); }
uint32 GetAssaultSpellId() const;
void RemoveAssaultAuras();
private:
EventMap _bgEvents;
uint64 _flagKeepers[2];
uint64 _droppedFlagGUID[2];
uint8 _flagState[2];
TeamId _lastFlagCaptureTeam;
uint32 _reputationCapture;
uint32 _honorWinKills;
uint32 _honorEndKills;
void PostUpdateImpl(uint32 diff);
};
#endif