mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[6910] Implemented rewritten arenas. Original author w12x@getmangos.com
Many thanks also to: Balrok@github.com for long time updating. Triply@github.com for great work in rewriting process. All who I forget to name. Signed-off-by: ApoC <apoc@nymfe.net>
This commit is contained in:
parent
c51a6bc59e
commit
a5331ab517
47 changed files with 3406 additions and 924 deletions
6
sql/updates/2008_12_15_01_character_arenas.sql
Normal file
6
sql/updates/2008_12_15_01_character_arenas.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE `saved_variables` (
|
||||
`NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves';
|
||||
|
||||
ALTER TABLE `arena_team_member` ADD COLUMN `personal_rating` int(10) UNSIGNED NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `characters` ADD COLUMN `arena_pending_points` int(10) UNSIGNED NOT NULL default '0';
|
||||
26
sql/updates/2008_12_15_01_mangos_arenas.sql
Normal file
26
sql/updates/2008_12_15_01_mangos_arenas.sql
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
DELETE FROM `command` WHERE `name` = "flusharenapoints";
|
||||
INSERT INTO `command` (`name`, `security`, `help`) VALUES
|
||||
('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.');
|
||||
|
||||
DELETE FROM mangos_string WHERE entry BETWEEN 7007 AND 7023;
|
||||
|
||||
INSERT INTO mangos_string (entry, content_default) VALUES
|
||||
(7007,'Your group is too large for this battleground. Please regroup to join.'),
|
||||
(7008,'Your group is too large for this arena. Please regroup to join.'),
|
||||
(7009,'Your group has members not in your arena team. Please regroup to join.'),
|
||||
(7010,'Your group does not have enough players to join this match.'),
|
||||
(7011,'The Gold Team wins!'),
|
||||
(7012,'The Green Team wins!'),
|
||||
(7013, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.'),
|
||||
(7014, 'Your group has an offline member. Please remove him before joining.'),
|
||||
(7015, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.'),
|
||||
(7016, 'Your group has players from different battleground brakets. You can\'t join as group.'),
|
||||
(7017, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.'),
|
||||
(7018, 'Someone in your party is Deserter. You can\'t join as group.'),
|
||||
(7019, 'Someone in your party is already in three battleground queues. You cannot join as group.'),
|
||||
(7020, 'You cannot teleport to a battleground or arena map.'),
|
||||
(7021, 'You cannot summon players to a battleground or arena map.'),
|
||||
(7022, 'You must be in GM mode to teleport to a player in a battleground.'),
|
||||
(7023, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.');
|
||||
|
||||
DELETE FROM mangos_string WHERE entry = 714 OR entry = 716;
|
||||
|
|
@ -44,7 +44,7 @@ ArenaTeam::~ArenaTeam()
|
|||
|
||||
}
|
||||
|
||||
bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamName)
|
||||
bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamName)
|
||||
{
|
||||
if(!objmgr.GetPlayer(captainGuid)) // player not exist
|
||||
return false;
|
||||
|
|
@ -77,7 +77,7 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ArenaTeam::AddMember(uint64 PlayerGuid)
|
||||
bool ArenaTeam::AddMember(const uint64& PlayerGuid)
|
||||
{
|
||||
std::string plName;
|
||||
uint8 plClass;
|
||||
|
|
@ -132,39 +132,23 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid)
|
|||
newmember.personal_rating = 1500;
|
||||
members.push_back(newmember);
|
||||
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid));
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", Id, GUID_LOPART(newmember.guid), newmember.personal_rating );
|
||||
|
||||
if(pl)
|
||||
{
|
||||
pl->SetInArenaTeam(Id, GetSlot());
|
||||
pl->SetArenaTeamIdInvited(0);
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating );
|
||||
|
||||
// hide promote/remove buttons
|
||||
if(CaptainGuid != PlayerGuid)
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tokens tokens;
|
||||
if(Player::LoadValuesArrayFromDB(tokens,PlayerGuid))
|
||||
{
|
||||
Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id);
|
||||
// hide promote/remove buttons
|
||||
if(CaptainGuid != PlayerGuid)
|
||||
Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
|
||||
Player::SaveValuesArrayInDB(tokens,PlayerGuid);
|
||||
}
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
|
||||
{
|
||||
LoadStatsFromDB(ArenaTeamId);
|
||||
LoadMembersFromDB(ArenaTeamId);
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
|
||||
if(!result)
|
||||
|
|
@ -184,6 +168,22 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
|
|||
|
||||
delete result;
|
||||
|
||||
// only load here, so additional checks can be made
|
||||
LoadStatsFromDB(ArenaTeamId);
|
||||
LoadMembersFromDB(ArenaTeamId);
|
||||
|
||||
if(Empty())
|
||||
{
|
||||
// arena team is empty, delete from db
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
// return false
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -209,49 +209,37 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId)
|
|||
|
||||
void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId)
|
||||
{
|
||||
Field *fields;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
// 0 1 2 3 4 5 6 7
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class "
|
||||
"FROM arena_team_member member "
|
||||
"INNER JOIN characters chars on member.guid = chars.guid "
|
||||
"WHERE member.arenateamid = '%u'", ArenaTeamId);
|
||||
if(!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
fields = result->Fetch();
|
||||
Field *fields = result->Fetch();
|
||||
ArenaTeamMember newmember;
|
||||
newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
LoadPlayerStats(&newmember);
|
||||
newmember.games_week = fields[1].GetUInt32();
|
||||
newmember.wins_week = fields[2].GetUInt32();
|
||||
newmember.games_season = fields[3].GetUInt32();
|
||||
newmember.wins_season = fields[4].GetUInt32();
|
||||
newmember.personal_rating = fields[5].GetUInt32();
|
||||
newmember.name = fields[6].GetCppString();
|
||||
newmember.Class = fields[7].GetUInt8();
|
||||
members.push_back(newmember);
|
||||
}while( result->NextRow() );
|
||||
delete result;
|
||||
}
|
||||
|
||||
void ArenaTeam::LoadPlayerStats(ArenaTeamMember *member)
|
||||
{
|
||||
Field *fields;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT name,class FROM characters WHERE guid = '%u'", GUID_LOPART(member->guid));
|
||||
if(!result)
|
||||
return;
|
||||
fields = result->Fetch();
|
||||
member->name = fields[0].GetCppString();
|
||||
member->Class = fields[1].GetUInt8();
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
||||
void ArenaTeam::SetCaptain(uint64 guid)
|
||||
void ArenaTeam::SetCaptain(const uint64& guid)
|
||||
{
|
||||
// disable remove/promote buttons
|
||||
Player *oldcaptain = objmgr.GetPlayer(GetCaptain());
|
||||
if(oldcaptain)
|
||||
oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
else
|
||||
Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, GetCaptain());
|
||||
|
||||
// set new captain
|
||||
CaptainGuid = guid;
|
||||
|
|
@ -263,14 +251,11 @@ void ArenaTeam::SetCaptain(uint64 guid)
|
|||
Player *newcaptain = objmgr.GetPlayer(guid);
|
||||
if(newcaptain)
|
||||
newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0);
|
||||
else
|
||||
Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0, guid);
|
||||
}
|
||||
|
||||
void ArenaTeam::DelMember(uint64 guid)
|
||||
{
|
||||
MemberList::iterator itr;
|
||||
for (itr = members.begin(); itr != members.end(); itr++)
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if (itr->guid == guid)
|
||||
{
|
||||
|
|
@ -280,17 +265,19 @@ void ArenaTeam::DelMember(uint64 guid)
|
|||
}
|
||||
|
||||
Player *player = objmgr.GetPlayer(guid);
|
||||
|
||||
if(player)
|
||||
{
|
||||
player->SetInArenaTeam(0, GetSlot());
|
||||
player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
|
||||
}
|
||||
else
|
||||
// delete all info regarding this team
|
||||
for(int i = 0; i < 6; ++i)
|
||||
{
|
||||
Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid);
|
||||
player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid));
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid));
|
||||
}
|
||||
|
||||
void ArenaTeam::Disband(WorldSession *session)
|
||||
|
|
@ -300,23 +287,15 @@ void ArenaTeam::Disband(WorldSession *session)
|
|||
session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), "");
|
||||
BroadcastPacket(&data);
|
||||
|
||||
uint32 count = members.size();
|
||||
uint64 *memberGuids = new uint64[count];
|
||||
|
||||
MemberList::iterator itr;
|
||||
uint32 i=0;
|
||||
for(itr = members.begin(); itr != members.end(); itr++)
|
||||
while (!members.empty())
|
||||
{
|
||||
memberGuids[i] = itr->guid;
|
||||
++i;
|
||||
// Removing from members is done in DelMember.
|
||||
DelMember(members.front().guid);
|
||||
}
|
||||
|
||||
for(uint32 j = 0; j < count; j++)
|
||||
DelMember(memberGuids[j]);
|
||||
delete[] memberGuids;
|
||||
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
objmgr.RemoveArenaTeam(this);
|
||||
|
|
@ -334,27 +313,12 @@ void ArenaTeam::Roster(WorldSession *session)
|
|||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
pl = objmgr.GetPlayer(itr->guid);
|
||||
if(pl)
|
||||
{
|
||||
data << uint64(pl->GetGUID()); // guid
|
||||
data << uint8(1); // online flag
|
||||
data << pl->GetName(); // member name
|
||||
data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown
|
||||
data << uint8(pl->getLevel()); // unknown, probably level
|
||||
data << uint8(pl->getClass()); // class
|
||||
data << uint32(itr->games_week); // played this week
|
||||
data << uint32(itr->wins_week); // wins this week
|
||||
data << uint32(itr->games_season); // played this season
|
||||
data << uint32(itr->wins_season); // wins this season
|
||||
data << uint32(itr->personal_rating); // personal rating
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data << uint64(itr->guid); // guid
|
||||
data << uint8(0); // online flag
|
||||
data << uint8((pl ? 1 : 0)); // online flag
|
||||
data << itr->name; // member name
|
||||
data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown
|
||||
data << uint8(0); // unknown, level?
|
||||
data << uint32((itr->guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
|
||||
data << uint8((pl ? pl->getLevel() : 0)); // unknown, level?
|
||||
data << uint8(itr->Class); // class
|
||||
data << uint32(itr->games_week); // played this week
|
||||
data << uint32(itr->wins_week); // wins this week
|
||||
|
|
@ -362,7 +326,6 @@ void ArenaTeam::Roster(WorldSession *session)
|
|||
data << uint32(itr->wins_season); // wins this season
|
||||
data << uint32(itr->personal_rating); // personal rating
|
||||
}
|
||||
}
|
||||
session->SendPacket(&data);
|
||||
sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
|
||||
}
|
||||
|
|
@ -395,6 +358,18 @@ void ArenaTeam::Stats(WorldSession *session)
|
|||
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::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
Player * plr = objmgr.GetPlayer(itr->guid);
|
||||
if(plr)
|
||||
Stats(plr->GetSession());
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
|
||||
{
|
||||
ArenaTeamMember* member = GetMember(guid);
|
||||
|
|
@ -408,8 +383,8 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
|
|||
data << uint32(stats.rating); // rating
|
||||
data << uint32(stats.games_season); // season played
|
||||
data << uint32(stats.wins_season); // season wins
|
||||
data << member->games_season; // played (count of all games, that the inspected member participated...)
|
||||
data << member->personal_rating; // personal rating
|
||||
data << uint32(member->games_season); // played (count of all games, that the inspected member participated...)
|
||||
data << uint32(member->personal_rating); // personal rating
|
||||
session->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
@ -458,18 +433,6 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value)
|
|||
}
|
||||
}
|
||||
|
||||
uint8 ArenaTeam::GetSlot() const
|
||||
{
|
||||
uint8 slot = GetSlotByType(GetType());
|
||||
if(slot >= MAX_ARENA_SLOT)
|
||||
{
|
||||
sLog.outError("Unknown arena team type %u for arena team %u", uint32(GetType()), GetId());
|
||||
return 0; // better return existed slot to prevent untelated data curruption
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
void ArenaTeam::BroadcastPacket(WorldPacket *packet)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
|
|
@ -490,10 +453,11 @@ uint8 ArenaTeam::GetSlotByType( uint32 type )
|
|||
default:
|
||||
break;
|
||||
}
|
||||
sLog.outError("FATAL: Unknown arena team type %u for some arena team", type);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
bool ArenaTeam::HaveMember( uint64 guid ) const
|
||||
bool ArenaTeam::HaveMember( const uint64& guid ) const
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
if(itr->guid == guid)
|
||||
|
|
@ -502,6 +466,171 @@ bool ArenaTeam::HaveMember( uint64 guid ) const
|
|||
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)
|
||||
points = (float)rating * 0.22f + 14.0f;
|
||||
else
|
||||
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
|
||||
|
||||
// type penalties for <5v5 teams
|
||||
if(Type == ARENA_TEAM_2v2)
|
||||
points *= 0.76f;
|
||||
else if(Type == ARENA_TEAM_3v3)
|
||||
points *= 0.88f;
|
||||
|
||||
return (uint32) points;
|
||||
}
|
||||
|
||||
float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating)
|
||||
{
|
||||
// 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)enemy_rating - (float)own_rating)/400.0f));
|
||||
}
|
||||
|
||||
int32 ArenaTeam::WonAgainst(uint32 againstRating)
|
||||
{
|
||||
// called when the team has won
|
||||
//'chance' calculation - to beat the opponent
|
||||
float chance = GetChanceAgainst(stats.rating,againstRating);
|
||||
// calculate the rating modification (ELO system with k=32)
|
||||
int32 mod = (int32)floor(32.0f * (1.0f - chance));
|
||||
// modify the team stats accordingly
|
||||
stats.rating += mod;
|
||||
stats.games_week += 1;
|
||||
stats.wins_week += 1;
|
||||
stats.games_season += 1;
|
||||
stats.wins_season += 1;
|
||||
//update team's rank
|
||||
stats.rank = 1;
|
||||
ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin();
|
||||
for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i)
|
||||
{
|
||||
if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating)
|
||||
++stats.rank;
|
||||
}
|
||||
|
||||
// return the rating change, used to display it on the results screen
|
||||
return mod;
|
||||
}
|
||||
|
||||
int32 ArenaTeam::LostAgainst(uint32 againstRating)
|
||||
{
|
||||
// called when the team has lost
|
||||
//'chance' calculation - to loose to the opponent
|
||||
float chance = GetChanceAgainst(stats.rating,againstRating);
|
||||
// calculate the rating modification (ELO system with k=32)
|
||||
int32 mod = (int32)ceil(32.0f * (0.0f - chance));
|
||||
// modify the team stats accordingly
|
||||
stats.rating += mod;
|
||||
stats.games_week += 1;
|
||||
stats.games_season += 1;
|
||||
//update team's rank
|
||||
|
||||
stats.rank = 1;
|
||||
ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin();
|
||||
for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i)
|
||||
{
|
||||
if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating)
|
||||
++stats.rank;
|
||||
}
|
||||
|
||||
// return the rating change, used to display it on the results screen
|
||||
return mod;
|
||||
}
|
||||
|
||||
void ArenaTeam::MemberLost(Player * plr, uint32 againstRating)
|
||||
{
|
||||
// called for each participant of a match after losing
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == plr->GetGUID())
|
||||
{
|
||||
// update personal rating
|
||||
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
|
||||
int32 mod = (int32)ceil(32.0f * (0.0f - chance));
|
||||
itr->ModifyPersonalRating(plr, mod, GetSlot());
|
||||
// update personal played stats
|
||||
itr->games_week +=1;
|
||||
itr->games_season +=1;
|
||||
// update the unit fields
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week);
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::MemberWon(Player * plr, uint32 againstRating)
|
||||
{
|
||||
// called for each participant after winning a match
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == plr->GetGUID())
|
||||
{
|
||||
// update personal rating
|
||||
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
|
||||
int32 mod = (int32)floor(32.0f * (1.0f - chance));
|
||||
itr->ModifyPersonalRating(plr, mod, GetSlot());
|
||||
// update personal stats
|
||||
itr->games_week +=1;
|
||||
itr->games_season +=1;
|
||||
itr->wins_season += 1;
|
||||
itr->wins_week += 1;
|
||||
// update unit fields
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week);
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season);
|
||||
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.games_week < 10)
|
||||
return;
|
||||
// to get points, a player has to participate in at least 30% of the matches
|
||||
uint32 min_plays = (uint32) ceil(stats.games_week * 0.3);
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
// the player participated in enough games, update his points
|
||||
uint32 points_to_add = 0;
|
||||
if (itr->games_week >= min_plays)
|
||||
points_to_add = GetPoints(itr->personal_rating);
|
||||
// OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid);
|
||||
|
||||
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 < points_to_add)
|
||||
PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add;
|
||||
}
|
||||
else
|
||||
PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add;
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::SaveToDB()
|
||||
{
|
||||
// save team and member stats to db
|
||||
// called after a match has ended, or when calculating arena_points
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games_week, stats.games_season, stats.rank, stats.wins_week, stats.wins_season, GetId());
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, Id, itr->guid);
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::FinishWeek()
|
||||
{
|
||||
stats.games_week = 0; // played this week
|
||||
|
|
@ -519,18 +648,18 @@ arenateam fields (id from 2.3.3 client):
|
|||
1415 - 0=captain, 1=member
|
||||
1416 - played this week
|
||||
1417 - played this season
|
||||
1418 - unk
|
||||
1418 - unk - rank?
|
||||
1419 - personal arena rating
|
||||
1420 - arena team id 3v3
|
||||
1421 - 0=captain, 1=member
|
||||
1422 - played this week
|
||||
1423 - played this season
|
||||
1424 - unk
|
||||
1424 - unk - rank?
|
||||
1425 - personal arena rating
|
||||
1426 - arena team id 5v5
|
||||
1427 - 0=captain, 1=member
|
||||
1428 - played this week
|
||||
1429 - played this season
|
||||
1430 - unk
|
||||
1430 - unk - rank?
|
||||
1431 - personal arena rating
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ enum ArenaTeamCommandErrors
|
|||
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_NOT_ALLIED = 0x0C,
|
||||
ERR_ARENA_TEAM_PLAYER_TO_LOW = 0x15,
|
||||
ERR_ARENA_TEAM_FULL = 0x16
|
||||
};
|
||||
|
||||
enum ArenaTeamEvents
|
||||
|
|
@ -85,14 +87,22 @@ struct ArenaTeamMember
|
|||
{
|
||||
uint64 guid;
|
||||
std::string name;
|
||||
//uint32 unk2;
|
||||
//uint8 unk1;
|
||||
uint8 Class;
|
||||
uint32 games_week;
|
||||
uint32 wins_week;
|
||||
uint32 games_season;
|
||||
uint32 wins_season;
|
||||
uint32 personal_rating;
|
||||
|
||||
void ModifyPersonalRating(Player* plr, int32 mod, uint32 slot)
|
||||
{
|
||||
if (personal_rating + mod < 0)
|
||||
personal_rating = 0;
|
||||
else
|
||||
personal_rating += mod;
|
||||
if(plr)
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot*6) + 5, personal_rating);
|
||||
}
|
||||
};
|
||||
|
||||
struct ArenaTeamStats
|
||||
|
|
@ -113,14 +123,14 @@ class ArenaTeam
|
|||
ArenaTeam();
|
||||
~ArenaTeam();
|
||||
|
||||
bool create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName);
|
||||
bool Create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName);
|
||||
void Disband(WorldSession *session);
|
||||
|
||||
typedef std::list<ArenaTeamMember> MemberList;
|
||||
|
||||
uint32 GetId() const { return Id; }
|
||||
uint32 GetType() const { return Type; }
|
||||
uint8 GetSlot() const;
|
||||
uint8 GetSlot() const { return GetSlotByType(GetType()); }
|
||||
static uint8 GetSlotByType(uint32 type);
|
||||
const uint64& GetCaptain() const { return CaptainGuid; }
|
||||
std::string GetName() const { return Name; }
|
||||
|
|
@ -134,17 +144,22 @@ class ArenaTeam
|
|||
uint32 GetBorderColor() const { return BorderColor; }
|
||||
uint32 GetBackgroundColor() const { return BackgroundColor; }
|
||||
|
||||
void SetCaptain(uint64 guid);
|
||||
bool AddMember(uint64 PlayerGuid);
|
||||
void SetCaptain(const uint64& guid);
|
||||
bool AddMember(const uint64& PlayerGuid);
|
||||
|
||||
// Shouldn't be const 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);
|
||||
|
||||
void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor);
|
||||
|
||||
uint32 GetMembersSize() const { return members.size(); }
|
||||
MemberList::iterator membersbegin(){ return members.begin(); }
|
||||
size_t GetMembersSize() const { return members.size(); }
|
||||
bool Empty() const { return members.empty(); }
|
||||
MemberList::iterator membersBegin() { return members.begin(); }
|
||||
MemberList::iterator membersEnd() { return members.end(); }
|
||||
bool HaveMember(uint64 guid) const;
|
||||
ArenaTeamMember* GetMember(uint64 guid)
|
||||
bool HaveMember(const uint64& guid) const;
|
||||
|
||||
ArenaTeamMember* GetMember(const uint64& guid)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
if(itr->guid == guid)
|
||||
|
|
@ -152,7 +167,8 @@ class ArenaTeam
|
|||
|
||||
return NULL;
|
||||
}
|
||||
ArenaTeamMember* GetMember(std::string& name)
|
||||
|
||||
ArenaTeamMember* GetMember(const std::string& name)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
if(itr->name == name)
|
||||
|
|
@ -161,10 +177,24 @@ class ArenaTeam
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool IsFighting() const
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if (Player *p = objmgr.GetPlayer(itr->guid))
|
||||
{
|
||||
if (p->GetMap()->IsBattleArena())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadArenaTeamFromDB(uint32 ArenaTeamId);
|
||||
void LoadMembersFromDB(uint32 ArenaTeamId);
|
||||
void LoadStatsFromDB(uint32 ArenaTeamId);
|
||||
void LoadPlayerStats(ArenaTeamMember* member);
|
||||
|
||||
void SaveToDB();
|
||||
|
||||
void BroadcastPacket(WorldPacket *packet);
|
||||
|
||||
|
|
@ -173,6 +203,17 @@ class ArenaTeam
|
|||
void Stats(WorldSession *session);
|
||||
void InspectStats(WorldSession *session, uint64 guid);
|
||||
|
||||
uint32 GetPoints(uint32 MemberRating);
|
||||
float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating);
|
||||
int32 WonAgainst(uint32 againstRating);
|
||||
void MemberWon(Player * plr, uint32 againstRating);
|
||||
int32 LostAgainst(uint32 againstRating);
|
||||
void MemberLost(Player * plr, uint32 againstRating);
|
||||
|
||||
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
|
||||
|
||||
void NotifyStatsChanged();
|
||||
|
||||
void FinishWeek();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("MSG_INSPECT_ARENA_TEAMS");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8);
|
||||
|
||||
|
|
@ -54,7 +53,6 @@ void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -72,7 +70,6 @@ void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -89,7 +86,6 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
|
|
@ -110,15 +106,13 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
|||
|
||||
if(!player)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
//SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
// can't find related opcode
|
||||
SendNotification(LANG_HIS_ARENA_LEVEL_REQ_ERROR, player->GetName());
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -141,21 +135,19 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
|||
|
||||
if(player->GetArenaTeamId(arenateam->GetSlot()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(arenateam->GetMembersSize() >= arenateam->GetType() * 2)
|
||||
{
|
||||
// should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL
|
||||
// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL);
|
||||
SendNotification(LANG_YOUR_ARENA_TEAM_FULL, player->GetName());
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,arenateam->GetName(),"",ERR_ARENA_TEAM_FULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -177,23 +169,25 @@ void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/
|
|||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited());
|
||||
if(!at)
|
||||
return;
|
||||
|
||||
if(_player->GetArenaTeamIdFromDB(_player->GetGUIDLow(), at->GetType()))
|
||||
{
|
||||
// arena team not exist
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ALREADY_IN_ARENA_TEAM); // already in arena team that size
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamId(at->GetSlot()))
|
||||
{
|
||||
// already in arena team that size
|
||||
return;
|
||||
}
|
||||
|
||||
// not let enemies sign petition
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_NOT_ALLIED);// not let enemies sign petition
|
||||
return;
|
||||
}
|
||||
|
||||
if(!at->AddMember(_player->GetGUID()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_INTERNAL);// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
|
|
@ -211,7 +205,6 @@ void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data*
|
|||
void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_LEAVE");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -220,10 +213,7 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
|||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// send command result
|
||||
return;
|
||||
}
|
||||
if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1)
|
||||
{
|
||||
// check for correctness
|
||||
|
|
@ -245,13 +235,13 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
|||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), "");
|
||||
at->BroadcastPacket(&data);
|
||||
|
||||
//SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0);
|
||||
//send you are no longer member of team
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_DISBAND");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -260,16 +250,13 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
|||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (at->IsFighting())
|
||||
return;
|
||||
|
||||
at->Disband(this);
|
||||
delete at;
|
||||
|
|
@ -278,7 +265,6 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
|
|
@ -303,11 +289,14 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
|||
|
||||
ArenaTeamMember* member = at->GetMember(name);
|
||||
if(!member) // member not found
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == member->guid)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +311,6 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
|
|
@ -347,7 +335,10 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data
|
|||
|
||||
ArenaTeamMember* member = at->GetMember(name);
|
||||
if(!member) // member not found
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == member->guid) // target player already captain
|
||||
return;
|
||||
|
|
@ -360,13 +351,13 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data
|
|||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::SendArenaTeamCommandResult(uint32 unk1, const std::string& str1, const std::string& str2, uint32 unk3)
|
||||
void WorldSession::SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4);
|
||||
data << unk1;
|
||||
data << str1;
|
||||
data << str2;
|
||||
data << unk3;
|
||||
WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4);
|
||||
data << team_action;
|
||||
data << team;
|
||||
data << player;
|
||||
data << error_id;
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "Language.h"
|
||||
#include "Chat.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "World.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
|
@ -47,6 +48,8 @@ BattleGround::BattleGround()
|
|||
m_Name = "";
|
||||
m_LevelMin = 0;
|
||||
m_LevelMax = 0;
|
||||
m_InBGFreeSlotQueue = false;
|
||||
m_SetDeleteThis = false;
|
||||
|
||||
m_MaxPlayersPerTeam = 0;
|
||||
m_MaxPlayers = 0;
|
||||
|
|
@ -67,21 +70,54 @@ BattleGround::BattleGround()
|
|||
m_TeamStartLocO[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamStartLocO[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0;
|
||||
m_ArenaTeamIds[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0;
|
||||
m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_BgRaids[BG_TEAM_ALLIANCE] = NULL;
|
||||
m_BgRaids[BG_TEAM_HORDE] = NULL;
|
||||
|
||||
m_PlayersCount[BG_TEAM_ALLIANCE] = 0;
|
||||
m_PlayersCount[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_PrematureCountDown = false;
|
||||
m_PrematureCountDown = 0;
|
||||
}
|
||||
|
||||
BattleGround::~BattleGround()
|
||||
{
|
||||
// remove objects and creatures
|
||||
// (this is done automatically in mapmanager update, when the instance is reset after the reset time)
|
||||
int size = m_BgCreatures.size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
{
|
||||
DelCreature(i);
|
||||
}
|
||||
size = m_BgObjects.size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
{
|
||||
DelObject(i);
|
||||
}
|
||||
|
||||
// delete creature and go respawn times
|
||||
WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
|
||||
WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID());
|
||||
// delete instance from db
|
||||
CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID());
|
||||
// remove from battlegrounds
|
||||
sBattleGroundMgr.RemoveBattleGround(GetInstanceID());
|
||||
// unload map
|
||||
if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
|
||||
if(map->IsBattleGroundOrArena())
|
||||
((BattleGroundMap*)map)->SetUnload();
|
||||
// remove from bg free slot queue
|
||||
this->RemoveFromBGFreeSlotQueue();
|
||||
}
|
||||
|
||||
void BattleGround::Update(time_t diff)
|
||||
{
|
||||
|
||||
if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
|
||||
//BG is empty
|
||||
return;
|
||||
|
|
@ -188,6 +224,33 @@ void BattleGround::Update(time_t diff)
|
|||
m_ResurrectQueue.clear();
|
||||
}
|
||||
|
||||
// if less then minimum players are in on one side, then start premature finish timer
|
||||
if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
|
||||
{
|
||||
if(!m_PrematureCountDown)
|
||||
{
|
||||
m_PrematureCountDown = true;
|
||||
m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime();
|
||||
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
|
||||
}
|
||||
else if(m_PrematureCountDownTimer < diff)
|
||||
{
|
||||
// time's up!
|
||||
EndBattleGround(0); // noone wins
|
||||
m_PrematureCountDown = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 newtime = m_PrematureCountDownTimer - diff;
|
||||
// announce every minute
|
||||
if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000)
|
||||
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
|
||||
m_PrematureCountDownTimer = newtime;
|
||||
}
|
||||
}
|
||||
else if (m_PrematureCountDown)
|
||||
m_PrematureCountDown = false;
|
||||
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
{
|
||||
// remove all players from battleground after 2 minutes
|
||||
|
|
@ -239,7 +302,10 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *
|
|||
if(!self && sender == plr)
|
||||
continue;
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
plr->GetSession()->SendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +331,10 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
{
|
||||
sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
|
|
@ -285,7 +354,10 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
plr->CastSpell(plr, SpellID, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -302,7 +374,10 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor);
|
||||
}
|
||||
}
|
||||
|
|
@ -324,7 +399,10 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
plr->ModifyFactionReputation(factionEntry, Reputation);
|
||||
}
|
||||
}
|
||||
|
|
@ -345,30 +423,84 @@ void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player
|
|||
|
||||
void BattleGround::EndBattleGround(uint32 winner)
|
||||
{
|
||||
this->RemoveFromBGFreeSlotQueue();
|
||||
|
||||
ArenaTeam * winner_arena_team = NULL;
|
||||
ArenaTeam * loser_arena_team = NULL;
|
||||
uint32 loser_rating = 0;
|
||||
uint32 winner_rating = 0;
|
||||
WorldPacket data;
|
||||
Player *Source = NULL;
|
||||
const char *winmsg = "";
|
||||
|
||||
if(winner == ALLIANCE)
|
||||
{
|
||||
if(isBattleGround())
|
||||
winmsg = GetMangosString(LANG_BG_A_WINS);
|
||||
else
|
||||
winmsg = GetMangosString(LANG_ARENA_GOLD_WINS);
|
||||
|
||||
PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
|
||||
|
||||
SetWinner(WINNER_ALLIANCE);
|
||||
}
|
||||
else
|
||||
else if(winner == HORDE)
|
||||
{
|
||||
if(isBattleGround())
|
||||
winmsg = GetMangosString(LANG_BG_H_WINS);
|
||||
else
|
||||
winmsg = GetMangosString(LANG_ARENA_GREEN_WINS);
|
||||
|
||||
PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
|
||||
|
||||
SetWinner(WINNER_HORDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWinner(3);
|
||||
}
|
||||
|
||||
SetStatus(STATUS_WAIT_LEAVE);
|
||||
m_EndTime = 0;
|
||||
|
||||
// arena rating calculation
|
||||
if(isArena() && isRated())
|
||||
{
|
||||
if(winner == ALLIANCE)
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
}
|
||||
else if(winner == HORDE)
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
}
|
||||
if(winner_arena_team && loser_arena_team)
|
||||
{
|
||||
loser_rating = loser_arena_team->GetStats().rating;
|
||||
winner_rating = winner_arena_team->GetStats().rating;
|
||||
int32 winner_change = winner_arena_team->WonAgainst(loser_rating);
|
||||
int32 loser_change = loser_arena_team->LostAgainst(winner_rating);
|
||||
sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change);
|
||||
if(winner == ALLIANCE)
|
||||
{
|
||||
SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change);
|
||||
SetArenaTeamRatingChangeForTeam(HORDE, loser_change);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetArenaTeamRatingChangeForTeam(HORDE, winner_change);
|
||||
SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetArenaTeamRatingChangeForTeam(ALLIANCE, 0);
|
||||
SetArenaTeamRatingChangeForTeam(HORDE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
Player *plr = objmgr.GetPlayer(itr->first);
|
||||
|
|
@ -378,13 +510,29 @@ void BattleGround::EndBattleGround(uint32 winner)
|
|||
continue;
|
||||
}
|
||||
|
||||
// should remove spirit of redemption
|
||||
if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||
plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
|
||||
if(!plr->isAlive())
|
||||
{
|
||||
plr->ResurrectPlayer(1.0f);
|
||||
plr->SpawnCorpseBones();
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == winner)
|
||||
uint32 team = itr->second.Team;
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
// per player calculation
|
||||
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
|
||||
{
|
||||
if(team == winner)
|
||||
winner_arena_team->MemberWon(plr,loser_rating);
|
||||
else
|
||||
loser_arena_team->MemberLost(plr,winner_rating);
|
||||
}
|
||||
|
||||
if(team == winner)
|
||||
{
|
||||
if(!Source)
|
||||
Source = plr;
|
||||
|
|
@ -404,10 +552,28 @@ void BattleGround::EndBattleGround(uint32 winner)
|
|||
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
|
||||
{
|
||||
// update arena points only after increasing the player's match count!
|
||||
//obsolete: winner_arena_team->UpdateArenaPointsHelper();
|
||||
//obsolete: loser_arena_team->UpdateArenaPointsHelper();
|
||||
// save the stat changes
|
||||
winner_arena_team->SaveToDB();
|
||||
loser_arena_team->SaveToDB();
|
||||
// send updated arena team stats to players
|
||||
// this way all arena team members will get notified, not only the ones who participated in this match
|
||||
winner_arena_team->NotifyStatsChanged();
|
||||
loser_arena_team->NotifyStatsChanged();
|
||||
}
|
||||
|
||||
// inform invited players about the removal
|
||||
sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
|
||||
|
||||
if(Source)
|
||||
{
|
||||
ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg);
|
||||
|
|
@ -558,12 +724,16 @@ void BattleGround::BlockMovement(Player *plr)
|
|||
|
||||
void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket)
|
||||
{
|
||||
uint32 team = GetPlayerTeam(guid);
|
||||
bool participant = false;
|
||||
// Remove from lists/maps
|
||||
std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid);
|
||||
if(itr != m_Players.end())
|
||||
{
|
||||
UpdatePlayersCountByTeam(itr->second.Team, true); // -1 player
|
||||
UpdatePlayersCountByTeam(team, true); // -1 player
|
||||
m_Players.erase(itr);
|
||||
// check if the player was a participant of the match, or only entered through gm command (goname)
|
||||
participant = true;
|
||||
}
|
||||
|
||||
std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid);
|
||||
|
|
@ -577,6 +747,10 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
|
|||
|
||||
Player *plr = objmgr.GetPlayer(guid);
|
||||
|
||||
// should remove spirit of redemption
|
||||
if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||
plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
|
||||
if(plr && !plr->isAlive()) // resurrect on exit
|
||||
{
|
||||
plr->ResurrectPlayer(1.0f);
|
||||
|
|
@ -589,66 +763,106 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
|
|||
{
|
||||
plr->ClearAfkReports();
|
||||
|
||||
if(participant) // if the player was a match participant, remove auras, calc rating, update queue
|
||||
{
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
uint32 bgTypeId = GetTypeID();
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
|
||||
// if arena, remove the specific arena auras
|
||||
if(isArena())
|
||||
{
|
||||
if(!sWorld.IsFFAPvPRealm())
|
||||
plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
|
||||
plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
|
||||
bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
|
||||
|
||||
// summon old pet if there was one and there isn't a current pet
|
||||
if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber())
|
||||
{
|
||||
Pet* NewPet = new Pet;
|
||||
if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true))
|
||||
delete NewPet;
|
||||
|
||||
(plr)->SetTemporaryUnsummonedPetNumber(0);
|
||||
}
|
||||
|
||||
if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
|
||||
{
|
||||
//left a rated match while the encounter was in progress, consider as loser
|
||||
ArenaTeam * winner_arena_team = 0;
|
||||
ArenaTeam * loser_arena_team = 0;
|
||||
if(team == HORDE)
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
}
|
||||
else
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
}
|
||||
if(winner_arena_team && loser_arena_team)
|
||||
{
|
||||
loser_arena_team->MemberLost(plr,winner_arena_team->GetRating());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data;
|
||||
if(SendPacket)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
|
||||
plr->RemoveBattleGroundQueueId(m_TypeID);
|
||||
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
|
||||
|
||||
DecreaseInvitedCount(plr->GetTeam());
|
||||
DecreaseInvitedCount(team);
|
||||
//we should update battleground queue, but only if bg isn't ending
|
||||
if (GetQueueType() < MAX_BATTLEGROUND_QUEUES)
|
||||
sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType());
|
||||
|
||||
if(!plr->GetBattleGroundId())
|
||||
return;
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType());
|
||||
|
||||
Group * group = plr->GetGroup();
|
||||
|
||||
// remove from raid group if exist
|
||||
if(group && group == GetBgRaid(plr->GetTeam()))
|
||||
if(group && group == GetBgRaid(team))
|
||||
{
|
||||
if(!group->RemoveMember(guid, 0)) // group was disbanded
|
||||
{
|
||||
SetBgRaid(plr->GetTeam(), NULL);
|
||||
SetBgRaid(team, NULL);
|
||||
delete group;
|
||||
}
|
||||
}
|
||||
|
||||
// Do next only if found in battleground
|
||||
plr->SetBattleGroundId(0); // We're not in BG.
|
||||
|
||||
// Let others know
|
||||
sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);
|
||||
SendPacketToTeam(plr->GetTeam(), &data, plr, false);
|
||||
SendPacketToTeam(team, &data, plr, false);
|
||||
}
|
||||
|
||||
// Do next only if found in battleground
|
||||
plr->SetBattleGroundId(0); // We're not in BG.
|
||||
// reset destination bg team
|
||||
plr->SetBGTeam(0);
|
||||
|
||||
if(Transport)
|
||||
{
|
||||
plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO());
|
||||
//sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O);
|
||||
}
|
||||
|
||||
// Log
|
||||
sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());
|
||||
}
|
||||
|
||||
/// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist
|
||||
// we always should check if BG is in that queue before adding..
|
||||
|
||||
if(!GetPlayersSize())
|
||||
if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
|
||||
{
|
||||
Reset();
|
||||
// if no players left AND no invitees left, set this bg to delete in next update
|
||||
// direct deletion could cause crashes
|
||||
m_SetDeleteThis = true;
|
||||
// return to prevent addition to freeslotqueue
|
||||
return;
|
||||
}
|
||||
|
||||
// a player exited the battleground, so there are free slots. add to queue
|
||||
this->AddToBGFreeSlotQueue();
|
||||
}
|
||||
|
||||
// this method is called when no players remains in battleground
|
||||
|
|
@ -660,6 +874,8 @@ void BattleGround::Reset()
|
|||
SetStartTime(0);
|
||||
SetEndTime(0);
|
||||
SetLastResurrectTime(0);
|
||||
SetArenaType(0);
|
||||
SetRated(false);
|
||||
|
||||
m_Events = 0;
|
||||
|
||||
|
|
@ -668,6 +884,7 @@ void BattleGround::Reset()
|
|||
|
||||
m_InvitedAlliance = 0;
|
||||
m_InvitedHorde = 0;
|
||||
m_InBGFreeSlotQueue = false;
|
||||
|
||||
m_Players.clear();
|
||||
m_PlayerScores.clear();
|
||||
|
|
@ -704,10 +921,11 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr);
|
||||
SendPacketToTeam(team, &data, plr, false);
|
||||
|
||||
// add arena specific auras
|
||||
if(isArena())
|
||||
{
|
||||
plr->RemoveArenaSpellCooldowns();
|
||||
//plr->RemoveArenaAuras();
|
||||
plr->RemoveArenaAuras();
|
||||
plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT);
|
||||
if(team == ALLIANCE) // gold
|
||||
{
|
||||
|
|
@ -726,6 +944,19 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
|
||||
plr->DestroyConjuredItems(true);
|
||||
|
||||
Pet* pet = plr->GetPet();
|
||||
if(pet)
|
||||
{
|
||||
if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)
|
||||
{
|
||||
(plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
|
||||
(plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
|
||||
}
|
||||
(plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
|
||||
}
|
||||
else
|
||||
(plr)->SetTemporaryUnsummonedPetNumber(0);
|
||||
|
||||
if(GetStatus() == STATUS_WAIT_JOIN) // not started yet
|
||||
{
|
||||
plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true);
|
||||
|
|
@ -740,23 +971,27 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells.
|
||||
}
|
||||
|
||||
if(isArena())
|
||||
plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
|
||||
|
||||
// Log
|
||||
sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName());
|
||||
}
|
||||
|
||||
/* This method should be called only once ... it adds pointer to queue */
|
||||
void BattleGround::AddToBGFreeSlotQueue()
|
||||
{
|
||||
// make sure to add only once
|
||||
if(!m_InBGFreeSlotQueue)
|
||||
{
|
||||
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
|
||||
m_InBGFreeSlotQueue = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/
|
||||
void BattleGround::RemoveFromBGFreeSlotQueue()
|
||||
{
|
||||
/* uncomment this code when battlegrounds will work like instances
|
||||
// set to be able to re-add if needed
|
||||
m_InBGFreeSlotQueue = false;
|
||||
// uncomment this code when battlegrounds will work like instances
|
||||
for (std::deque<BattleGround*>::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr)
|
||||
{
|
||||
if ((*itr)->GetInstanceID() == m_InstanceID)
|
||||
|
|
@ -764,30 +999,69 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
|
|||
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr);
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS
|
||||
*/
|
||||
bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const
|
||||
// get the number of free slots for team
|
||||
// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group
|
||||
uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
|
||||
{
|
||||
//if BG is starting ... invite anyone:
|
||||
//if BG is starting ... invite anyone
|
||||
if (GetStatus() == STATUS_WAIT_JOIN)
|
||||
return GetInvitedCount(Team) < GetMaxPlayersPerTeam();
|
||||
return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
|
||||
//if BG is already started .. do not allow to join too much players of one faction
|
||||
uint32 otherTeam;
|
||||
uint32 otherIn;
|
||||
if (Team == ALLIANCE)
|
||||
{
|
||||
otherTeam = GetInvitedCount(HORDE);
|
||||
otherIn = GetPlayersCountByTeam(HORDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
otherTeam = GetInvitedCount(ALLIANCE);
|
||||
otherIn = GetPlayersCountByTeam(ALLIANCE);
|
||||
}
|
||||
if (GetStatus() == STATUS_IN_PROGRESS)
|
||||
return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam());
|
||||
{
|
||||
// difference based on ppl invited (not necessarily entered battle)
|
||||
// default: allow 0
|
||||
uint32 diff = 0;
|
||||
// allow join one person if the sides are equal (to fill up bg to minplayersperteam)
|
||||
if (otherTeam == GetInvitedCount(Team))
|
||||
diff = 1;
|
||||
// allow join more ppl if the other side has more players
|
||||
else if(otherTeam > GetInvitedCount(Team))
|
||||
diff = otherTeam - GetInvitedCount(Team);
|
||||
|
||||
return false;
|
||||
// difference based on max players per team (don't allow inviting more)
|
||||
uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
|
||||
|
||||
// difference based on players who already entered
|
||||
// default: allow 0
|
||||
uint32 diff3 = 0;
|
||||
// allow join one person if the sides are equal (to fill up bg minplayersperteam)
|
||||
if (otherIn == GetPlayersCountByTeam(Team))
|
||||
diff3 = 1;
|
||||
// allow join more ppl if the other side has more players
|
||||
else if (otherIn > GetPlayersCountByTeam(Team))
|
||||
diff3 = otherIn - GetPlayersCountByTeam(Team);
|
||||
// or other side has less than minPlayersPerTeam
|
||||
else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam())
|
||||
diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1;
|
||||
|
||||
// return the minimum of the 3 differences
|
||||
|
||||
// min of diff and diff 2
|
||||
diff = diff < diff2 ? diff : diff2;
|
||||
|
||||
// min of diff, diff2 and diff3
|
||||
return diff < diff3 ? diff : diff3 ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this method isn't called already, it will be useful when more battlegrounds of one type will be available */
|
||||
bool BattleGround::HasFreeSlots() const
|
||||
{
|
||||
return GetPlayersSize() < GetMaxPlayers();
|
||||
|
|
@ -813,9 +1087,13 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
|
|||
itr->second->HonorableKills += value;
|
||||
break;
|
||||
case SCORE_BONUS_HONOR: // Honor bonus
|
||||
// do not add honor in arenas
|
||||
if(isBattleGround())
|
||||
{
|
||||
// reward honor instantly
|
||||
if(Source->RewardHonor(NULL, 1, value))
|
||||
itr->second->BonusHonor += value;
|
||||
}
|
||||
break;
|
||||
//used only in EY, but in MSG_PVP_LOG_DATA opcode
|
||||
case SCORE_DAMAGE_DONE: // Damage Done
|
||||
|
|
@ -871,15 +1149,26 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
|
|||
|
||||
bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime)
|
||||
{
|
||||
GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry);
|
||||
if(!goinfo)
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
|
||||
if(!map)
|
||||
return false;
|
||||
|
||||
// must be created this way, adding to godatamap would add it to the base map of the instance
|
||||
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
|
||||
// so we must create it specific for this instance
|
||||
GameObject * go = new GameObject;
|
||||
if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
|
||||
{
|
||||
sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);
|
||||
sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry);
|
||||
delete go;
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
uint32 guid = go->GetGUIDLow();
|
||||
|
||||
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
|
||||
|
||||
// without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
|
||||
// iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed
|
||||
GameObjectData& data = objmgr.NewGOData(guid);
|
||||
|
||||
data.id = entry;
|
||||
|
|
@ -893,13 +1182,13 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
|
|||
data.rotation2 = rotation2;
|
||||
data.rotation3 = rotation3;
|
||||
data.spawntimesecs = respawnTime;
|
||||
data.spawnMask = 1;
|
||||
data.animprogress = 100;
|
||||
data.go_state = 1;
|
||||
data.spawnMask = 1;
|
||||
objmgr.AddGameobjectToGrid(guid, &data);
|
||||
|
||||
m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT);
|
||||
|
||||
*/
|
||||
// add to world, so it can be later looked up from HashMapHolder
|
||||
go->AddToWorld();
|
||||
m_BgObjects[type] = go->GetGUID();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -941,6 +1230,9 @@ void BattleGround::DoorOpen(uint32 type)
|
|||
|
||||
void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
|
||||
{
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
|
||||
if(!map)
|
||||
return;
|
||||
if( respawntime == 0 )
|
||||
{
|
||||
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
|
||||
|
|
@ -949,30 +1241,27 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
|
|||
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
|
||||
if( obj->getLootState() == GO_JUST_DEACTIVATED )
|
||||
obj->SetLootState(GO_READY);
|
||||
obj->Respawn();
|
||||
obj->SetRespawnTime(0);
|
||||
map->Add(obj);
|
||||
}
|
||||
else
|
||||
objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
|
||||
if(obj)
|
||||
{
|
||||
map->Add(obj);
|
||||
obj->SetRespawnTime(respawntime);
|
||||
obj->SetLootState(GO_JUST_DEACTIVATED);
|
||||
}
|
||||
else
|
||||
objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime);
|
||||
}
|
||||
}
|
||||
|
||||
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o)
|
||||
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime)
|
||||
{
|
||||
// note: this should normally be FindMap
|
||||
// but it's a hack to allow the battlegrounds to initialize at server startup
|
||||
Map * map = MapManager::Instance().GetMap(GetMapId(), 0);
|
||||
if(!map) return NULL;
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
|
||||
if(!map)
|
||||
return NULL;
|
||||
|
||||
Creature* pCreature = new Creature;
|
||||
if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval))
|
||||
|
|
@ -996,9 +1285,39 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
|
|||
|
||||
map->Add(pCreature);
|
||||
m_BgCreatures[type] = pCreature->GetGUID();
|
||||
|
||||
return pCreature;
|
||||
}
|
||||
/*
|
||||
void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
|
||||
{
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
|
||||
if(!map)
|
||||
return false;
|
||||
|
||||
if(respawntime == 0)
|
||||
{
|
||||
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
|
||||
if(obj)
|
||||
{
|
||||
//obj->Respawn(); // bugged
|
||||
obj->SetRespawnTime(0);
|
||||
objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);
|
||||
map->Add(obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
|
||||
if(obj)
|
||||
{
|
||||
obj->setDeathState(DEAD);
|
||||
obj->SetRespawnTime(respawntime);
|
||||
map->Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
bool BattleGround::DelCreature(uint32 type)
|
||||
{
|
||||
Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
|
||||
|
|
@ -1079,8 +1398,11 @@ void BattleGround::SendMessageToAll(int32 entry)
|
|||
|
||||
void BattleGround::EndNow()
|
||||
{
|
||||
RemoveFromBGFreeSlotQueue();
|
||||
SetStatus(STATUS_WAIT_LEAVE);
|
||||
SetEndTime(TIME_TO_AUTOREMOVE);
|
||||
// inform invited players about the removal
|
||||
sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
|
||||
}
|
||||
|
||||
// Battleground messages are localized using the dbc lang, they are not client language dependent
|
||||
|
|
@ -1158,3 +1480,28 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
|
|||
// to be able to remove insignia
|
||||
player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );
|
||||
}
|
||||
|
||||
// return the player's team based on battlegroundplayer info
|
||||
// used in same faction arena matches mainly
|
||||
uint32 BattleGround::GetPlayerTeam(uint64 guid)
|
||||
{
|
||||
std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid);
|
||||
if(itr!=m_Players.end())
|
||||
return itr->second.Team;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
|
||||
{
|
||||
int count = 0;
|
||||
for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if(itr->second.Team == Team)
|
||||
{
|
||||
Player * pl = objmgr.GetPlayer(itr->first);
|
||||
if(pl && pl->isAlive())
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#ifndef __BATTLEGROUND_H
|
||||
#define __BATTLEGROUND_H
|
||||
#define ARENA_PATCH
|
||||
|
||||
#include "Common.h"
|
||||
#include "WorldPacket.h"
|
||||
|
|
@ -83,7 +84,7 @@ enum BattleGroundTimeIntervals
|
|||
{
|
||||
RESURRECTION_INTERVAL = 30000, // ms
|
||||
REMIND_INTERVAL = 30000, // ms
|
||||
INVITE_ACCEPT_WAIT_TIME = 120000, // ms
|
||||
INVITE_ACCEPT_WAIT_TIME = 80000, // ms
|
||||
TIME_TO_AUTOREMOVE = 120000, // ms
|
||||
MAX_OFFLINE_TIME = 300000, // ms
|
||||
START_DELAY0 = 120000, // ms
|
||||
|
|
@ -143,6 +144,18 @@ enum BattleGroundTypeId
|
|||
BATTLEGROUND_RL = 8
|
||||
};
|
||||
|
||||
// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time
|
||||
enum BattleGroundQueueTypeId
|
||||
{
|
||||
BATTLEGROUND_QUEUE_AV = 1,
|
||||
BATTLEGROUND_QUEUE_WS = 2,
|
||||
BATTLEGROUND_QUEUE_AB = 3,
|
||||
BATTLEGROUND_QUEUE_EY = 4,
|
||||
BATTLEGROUND_QUEUE_2v2 = 5,
|
||||
BATTLEGROUND_QUEUE_3v3 = 6,
|
||||
BATTLEGROUND_QUEUE_5v5 = 7,
|
||||
};
|
||||
|
||||
enum ScoreType
|
||||
{
|
||||
SCORE_KILLING_BLOWS = 1,
|
||||
|
|
@ -195,6 +208,20 @@ enum BattleGroundTeamId
|
|||
BG_TEAM_HORDE = 1
|
||||
};
|
||||
|
||||
enum BattleGroundJoinError
|
||||
{
|
||||
BG_JOIN_ERR_OK = 0,
|
||||
BG_JOIN_ERR_OFFLINE_MEMBER = 1,
|
||||
BG_JOIN_ERR_GROUP_TOO_MANY = 2,
|
||||
BG_JOIN_ERR_MIXED_FACTION = 3,
|
||||
BG_JOIN_ERR_MIXED_LEVELS = 4,
|
||||
BG_JOIN_ERR_MIXED_ARENATEAM = 5,
|
||||
BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE = 6,
|
||||
BG_JOIN_ERR_GROUP_DESERTER = 7,
|
||||
BG_JOIN_ERR_ALL_QUEUES_USED = 8,
|
||||
BG_JOIN_ERR_GROUP_NOT_ENOUGH = 9
|
||||
};
|
||||
|
||||
class BattleGroundScore
|
||||
{
|
||||
public:
|
||||
|
|
@ -224,6 +251,7 @@ class BattleGround
|
|||
public:
|
||||
/* Construction */
|
||||
BattleGround();
|
||||
/*BattleGround(const BattleGround& bg);*/
|
||||
virtual ~BattleGround();
|
||||
virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version
|
||||
virtual bool SetupBattleGround() // must be implemented in BG subclass
|
||||
|
|
@ -296,6 +324,7 @@ class BattleGround
|
|||
}
|
||||
bool HasFreeSlotsForTeam(uint32 Team) const;
|
||||
bool HasFreeSlots() const;
|
||||
uint32 GetFreeSlotsForTeam(uint32 Team) const;
|
||||
|
||||
bool isArena() const { return m_IsArena; }
|
||||
bool isBattleGround() const { return !m_IsArena; }
|
||||
|
|
@ -366,6 +395,7 @@ class BattleGround
|
|||
|
||||
uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; }
|
||||
uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; }
|
||||
uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
|
||||
void UpdatePlayersCountByTeam(uint32 Team, bool remove)
|
||||
{
|
||||
if(remove)
|
||||
|
|
@ -374,6 +404,12 @@ class BattleGround
|
|||
++m_PlayersCount[GetTeamIndexByTeamId(Team)];
|
||||
}
|
||||
|
||||
// used for rated arena battles
|
||||
void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; }
|
||||
uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; }
|
||||
void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; }
|
||||
int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; }
|
||||
|
||||
/* Triggers handle */
|
||||
// must be implemented in BG subclass
|
||||
virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {}
|
||||
|
|
@ -390,6 +426,7 @@ class BattleGround
|
|||
virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; }
|
||||
|
||||
virtual void AddPlayer(Player *plr); // must be implemented in BG subclass
|
||||
|
||||
virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket);
|
||||
// can be extended in in BG subclass
|
||||
|
||||
|
|
@ -402,7 +439,8 @@ class BattleGround
|
|||
BGCreatures m_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);
|
||||
Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o);
|
||||
// void SpawnBGCreature(uint32 type, uint32 respawntime);
|
||||
Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0);
|
||||
bool DelCreature(uint32 type);
|
||||
bool DelObject(uint32 type);
|
||||
bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team);
|
||||
|
|
@ -411,6 +449,13 @@ class BattleGround
|
|||
void DoorClose(uint32 type);
|
||||
const char *GetMangosString(int32 entry);
|
||||
|
||||
virtual bool HandlePlayerUnderMap(Player * plr) {return false;}
|
||||
|
||||
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
|
||||
uint32 GetPlayerTeam(uint64 guid);
|
||||
|
||||
void SetDeleteThis() {m_SetDeleteThis = true;}
|
||||
|
||||
protected:
|
||||
//this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround
|
||||
void EndNow();
|
||||
|
|
@ -443,6 +488,8 @@ class BattleGround
|
|||
uint32 m_LastResurrectTime;
|
||||
uint32 m_Queue_type;
|
||||
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
|
||||
bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque
|
||||
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
|
||||
// this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless
|
||||
//uint8 m_BattleGroundType; // 3=BG, 4=arena
|
||||
//instead of uint8 (in previous line) is bool used
|
||||
|
|
@ -450,6 +497,8 @@ class BattleGround
|
|||
uint8 m_Winner; // 0=alliance, 1=horde, 2=none
|
||||
int32 m_StartDelayTime;
|
||||
bool m_IsRated; // is this battle rated?
|
||||
bool m_PrematureCountDown;
|
||||
uint32 m_PrematureCountDownTimer;
|
||||
char const *m_Name;
|
||||
|
||||
/* Player lists */
|
||||
|
|
@ -468,6 +517,11 @@ class BattleGround
|
|||
/* Players count by team */
|
||||
uint32 m_PlayersCount[2];
|
||||
|
||||
/* Arena team ids by team */
|
||||
uint32 m_ArenaTeamIds[2];
|
||||
|
||||
int32 m_ArenaTeamRatingChanges[2];
|
||||
|
||||
/* Limits */
|
||||
uint32 m_LevelMin;
|
||||
uint32 m_LevelMax;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,13 @@ void BattleGroundAB::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ...");
|
||||
|
||||
// despawn banners, auras and buffs
|
||||
|
|
@ -377,6 +384,7 @@ void BattleGroundAB::_NodeOccupied(uint8 node,Team team)
|
|||
{
|
||||
if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) )
|
||||
sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team);
|
||||
// SpawnBGCreature(node,RESPAWN_IMMEDIATELY);
|
||||
|
||||
uint8 capturedNodes = 0;
|
||||
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ void BattleGroundBE::Update(time_t diff)
|
|||
if (!(m_Events & 0x01))
|
||||
{
|
||||
m_Events |= 0x01;
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++)
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
|
|
@ -86,6 +92,11 @@ void BattleGroundBE::Update(time_t diff)
|
|||
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
||||
if(Player *plr = objmgr.GetPlayer(itr->first))
|
||||
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
|
||||
|
||||
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,11 +113,23 @@ void BattleGroundBE::AddPlayer(Player *plr)
|
|||
BattleGroundBEScore* sc = new BattleGroundBEScore;
|
||||
|
||||
m_PlayerScores[plr->GetGUID()] = sc;
|
||||
|
||||
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
|
||||
}
|
||||
|
||||
void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
|
||||
{
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
return;
|
||||
|
||||
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
|
||||
void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
|
||||
|
|
@ -122,15 +145,25 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
|
|||
|
||||
BattleGround::HandleKillPlayer(player,killer);
|
||||
|
||||
uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());
|
||||
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
++m_TeamKills[killer_team_index]; // add kills to killer's team
|
||||
|
||||
if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(killer->GetTeam());
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
else if(!GetAlivePlayersCountByTeam(HORDE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundBE::HandlePlayerUnderMap(Player *player)
|
||||
{
|
||||
player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
||||
|
|
@ -159,10 +192,16 @@ void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
|||
// HandleTriggerBuff(buff_guid,Source);
|
||||
}
|
||||
|
||||
void BattleGroundBE::FillInitialWorldStates(WorldPacket &data)
|
||||
{
|
||||
data << uint32(0x9f1) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7
|
||||
data << uint32(0x9f0) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8
|
||||
data << uint32(0x9f3) << uint32(1); // 9
|
||||
}
|
||||
|
||||
void BattleGroundBE::ResetBGSubclass()
|
||||
{
|
||||
m_TeamKills[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamKills[BG_TEAM_HORDE] = 0;
|
||||
|
||||
}
|
||||
|
||||
bool BattleGroundBE::SetupBattleGround()
|
||||
|
|
|
|||
|
|
@ -64,12 +64,11 @@ class BattleGroundBE : public BattleGround
|
|||
void HandleAreaTrigger(Player *Source, uint32 Trigger);
|
||||
bool SetupBattleGround();
|
||||
void ResetBGSubclass();
|
||||
virtual void FillInitialWorldStates(WorldPacket &d);
|
||||
void HandleKillPlayer(Player* player, Player *killer);
|
||||
bool HandlePlayerUnderMap(Player * plr);
|
||||
|
||||
/* Scorekeeping */
|
||||
void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
|
||||
|
||||
private:
|
||||
uint32 m_TeamKills[2]; // count of kills for each team
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,9 +54,18 @@ void BattleGroundEY::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
|
||||
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
|
||||
|
||||
// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY);
|
||||
// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY);
|
||||
for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
|
||||
SpawnBGObject(i, RESPAWN_ONE_DAY);
|
||||
|
||||
|
|
@ -572,7 +581,17 @@ void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer)
|
|||
|
||||
void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
|
||||
{
|
||||
// Drop allowed in any BG state
|
||||
if(GetStatus() != STATUS_IN_PROGRESS)
|
||||
{
|
||||
// if not running, do not cast things at the dropper player, neither send unnecessary messages
|
||||
// just take off the aura
|
||||
if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID())
|
||||
{
|
||||
SetFlagPicker(0);
|
||||
Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!IsFlagPickedup())
|
||||
return;
|
||||
|
|
@ -744,6 +763,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
|
|||
sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u",
|
||||
Point, Team, m_CapturingPointTypes[Point].GraveYardId);
|
||||
|
||||
// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY);
|
||||
|
||||
UpdatePointsIcons(Team, Point);
|
||||
UpdatePointsCount(Team);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,11 @@
|
|||
#include "MapManager.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Object.h"
|
||||
#include "Chat.h"
|
||||
#include "BattleGroundMgr.h"
|
||||
#include "BattleGroundWS.h"
|
||||
#include "BattleGround.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "Language.h"
|
||||
|
||||
void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data )
|
||||
|
|
@ -76,18 +78,25 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
uint32 bgTypeId;
|
||||
uint32 instanceId;
|
||||
uint8 joinAsGroup;
|
||||
Group * grp;
|
||||
|
||||
recv_data >> guid; // battlemaster guid
|
||||
recv_data >> bgTypeId; // battleground type id (DBC id)
|
||||
recv_data >> instanceId; // instance id, 0 if First Available selected
|
||||
recv_data >> joinAsGroup; // join as group
|
||||
|
||||
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId);
|
||||
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating?
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES)
|
||||
{
|
||||
sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow());
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore if we already in BG or BG queue
|
||||
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid);
|
||||
|
||||
// can do this, since it's battleground, not arena
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0);
|
||||
|
||||
// ignore if player is already in BG
|
||||
if(_player->InBattleGround())
|
||||
return;
|
||||
|
||||
|
|
@ -98,6 +107,20 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
if(!unit->isBattleMaster()) // it's not battlemaster
|
||||
return;
|
||||
|
||||
// get bg instance or bg template if instance not found
|
||||
BattleGround * bg = 0;
|
||||
if(instanceId)
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId);
|
||||
|
||||
if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))
|
||||
{
|
||||
sLog.outError("Battleground: no available bg / template found");
|
||||
return;
|
||||
}
|
||||
|
||||
// check queueing conditions
|
||||
if(!joinAsGroup)
|
||||
{
|
||||
// check Deserter debuff
|
||||
if( !_player->CanJoinToBattleground() )
|
||||
{
|
||||
|
|
@ -106,66 +129,60 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
_player->GetSession()->SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
|
||||
// check existence
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
|
||||
if(!bg)
|
||||
// check if already in queue
|
||||
if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
//player is already in this queue
|
||||
return;
|
||||
|
||||
if(joinAsGroup && _player->GetGroup())
|
||||
// check if has free queue slots
|
||||
if(!_player->HasFreeBattleGroundQueueId())
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Group *grp = _player->GetGroup();
|
||||
grp = _player->GetGroup();
|
||||
// no group found, error
|
||||
if(!grp)
|
||||
return;
|
||||
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
|
||||
if (err != BG_JOIN_ERR_OK)
|
||||
{
|
||||
SendBattleGroundOrArenaJoinError(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if we're here, then the conditions to join a bg are met. We can proceed in joining.
|
||||
|
||||
// _player->GetGroup() was already checked, grp is already initialized
|
||||
if(joinAsGroup /* && _player->GetGroup()*/)
|
||||
{
|
||||
sLog.outDebug("Battleground: the following players are joining as group:");
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
|
||||
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
if(!member) continue;
|
||||
if(!member) continue; // this should never happen
|
||||
|
||||
if( !member->CanJoinToBattleground() )
|
||||
{
|
||||
WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
|
||||
data << (uint32) 0xFFFFFFFE;
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
continue;
|
||||
}
|
||||
if (member->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
//player is already in this queue
|
||||
continue;
|
||||
|
||||
WorldPacket data;
|
||||
// add to queue
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
// fill data packet
|
||||
//member->GetSession()->SendPacket(data);
|
||||
continue;
|
||||
}
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue
|
||||
|
||||
// store entry point coords (same as leader entry point)
|
||||
member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
WorldPacket data;
|
||||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo);
|
||||
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
|
||||
}
|
||||
sLog.outDebug("Battleground: group end");
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
//player is already in this queue
|
||||
return;
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
WorldPacket data;
|
||||
// fill data packet
|
||||
//SendPacket(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// already checked if queueSlot is valid, now just get it
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId);
|
||||
// store entry point coords
|
||||
_player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
|
|
@ -173,7 +190,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId);
|
||||
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());
|
||||
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,12 +268,11 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data )
|
|||
uint32 bgTypeId;
|
||||
recv_data >> bgTypeId; // id from DBC
|
||||
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating?
|
||||
return;
|
||||
|
||||
// can't be received if player not in BG queue
|
||||
if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES)
|
||||
{
|
||||
sLog.outError("Battleground: invalid bgtype received.");
|
||||
return;
|
||||
}
|
||||
|
||||
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
|
||||
|
||||
|
|
@ -270,82 +290,203 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
|
|||
|
||||
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
|
||||
|
||||
uint8 unk1;
|
||||
uint8 type; // arenatype if arena
|
||||
uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
|
||||
uint32 instanceId;
|
||||
uint32 bgTypeId; // type id from dbc
|
||||
uint16 unk; // 0x1F90 constant?
|
||||
uint8 action; // enter battle 0x1, leave queue 0x0
|
||||
|
||||
recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action;
|
||||
recv_data >> type >> unk2 >> bgTypeId >> unk >> action;
|
||||
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating?
|
||||
return;
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES)
|
||||
{
|
||||
sLog.outError("Battleground: invalid bgtype received.");
|
||||
// update battleground slots for the player to fix his UI and sent data.
|
||||
// this is a HACK, I don't know why the client starts sending invalid packets in the first place.
|
||||
// it usually happens with extremely high latency (if debugging / stepping in the code for example)
|
||||
if(_player->InBattleGroundQueue())
|
||||
{
|
||||
// update all queues, send invitation info if player is invited, queue info if queued
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i);
|
||||
if(!queue_id)
|
||||
continue;
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
// if the player is not in queue, contine
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
continue;
|
||||
|
||||
if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
return;
|
||||
// no group information, this should never happen
|
||||
if(!itrPlayerStatus->second.GroupInfo)
|
||||
continue;
|
||||
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
|
||||
BattleGround * bg = NULL;
|
||||
|
||||
// get possibly needed data from groupinfo
|
||||
bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId;
|
||||
uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
|
||||
uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
|
||||
uint8 status = 0;
|
||||
|
||||
|
||||
if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
|
||||
{
|
||||
// not invited to bg, get template
|
||||
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
status = STATUS_WAIT_QUEUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the bg we're invited to
|
||||
BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID);
|
||||
status = STATUS_WAIT_JOIN;
|
||||
}
|
||||
|
||||
// if bg not found, then continue
|
||||
if(!bg)
|
||||
return;
|
||||
continue;
|
||||
|
||||
// don't invite if already in the instance
|
||||
if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID())
|
||||
continue;
|
||||
|
||||
// re - invite player with proper data
|
||||
WorldPacket data;
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 bgQueueTypeId = 0;
|
||||
// get the bg what we were invited to
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus;
|
||||
bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type);
|
||||
itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
{
|
||||
sLog.outError("Battleground: itrplayerstatus not found.");
|
||||
return;
|
||||
}
|
||||
instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;
|
||||
|
||||
// if action == 1, then instanceId is _required_
|
||||
if(!instanceId && action == 1)
|
||||
{
|
||||
sLog.outError("Battleground: instance not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId);
|
||||
|
||||
// bg template might and must be used in case of leaving queue, when instance is not created yet
|
||||
if(!bg && action == 0)
|
||||
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
|
||||
if(!bg)
|
||||
{
|
||||
sLog.outError("Battleground: bg not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
bgTypeId = bg->GetTypeID();
|
||||
|
||||
if(_player->InBattleGroundQueue())
|
||||
{
|
||||
uint32 queueSlot = 0;
|
||||
uint32 team = 0;
|
||||
uint32 arenatype = 0;
|
||||
uint32 israted = 0;
|
||||
uint32 rating = 0;
|
||||
uint32 opponentsRating = 0;
|
||||
// get the team info from the queue
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()
|
||||
&& pitr->second.GroupInfo )
|
||||
{
|
||||
team = pitr->second.GroupInfo->Team;
|
||||
arenatype = pitr->second.GroupInfo->ArenaType;
|
||||
israted = pitr->second.GroupInfo->IsRated;
|
||||
rating = pitr->second.GroupInfo->ArenaTeamRating;
|
||||
opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Battleground: Invalid player queue info!");
|
||||
return;
|
||||
}
|
||||
WorldPacket data;
|
||||
switch(action)
|
||||
{
|
||||
case 1: // port to battleground
|
||||
// cheating?
|
||||
if(!_player->IsInvitedForBattleGroundType(bgTypeId))
|
||||
return;
|
||||
|
||||
// check if player is not deserter
|
||||
if( !_player->CanJoinToBattleground() )
|
||||
{
|
||||
WorldPacket data2;
|
||||
data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
|
||||
data2 << (uint32) 0xFFFFFFFE;
|
||||
SendPacket(&data2);
|
||||
return;
|
||||
}
|
||||
|
||||
// if the player is dead, resurrect him before teleport
|
||||
if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId))
|
||||
return; // cheating?
|
||||
// resurrect the player
|
||||
if(!_player->isAlive())
|
||||
{
|
||||
_player->ResurrectPlayer(1.0f);
|
||||
_player->SpawnCorpseBones();
|
||||
}
|
||||
|
||||
// leave current group
|
||||
// stop taxi flight at port
|
||||
if(_player->isInFlight())
|
||||
{
|
||||
_player->GetMotionMaster()->MovementExpired();
|
||||
_player->m_taxi.ClearTaxiDestinations();
|
||||
}
|
||||
_player->RemoveFromGroup();
|
||||
|
||||
// packet to player about BG status
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId);
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
|
||||
// remove battleground queue status from BGmgr
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false);
|
||||
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);
|
||||
// this is still needed here if battleground "jumping" shouldn't add deserter debuff
|
||||
// also this required to prevent stuck at old battleground after SetBattleGroundId set to new
|
||||
if( BattleGround *currentBg = _player->GetBattleGround() )
|
||||
currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
|
||||
|
||||
_player->SetBattleGroundId(bg->GetTypeID());
|
||||
sBattleGroundMgr.SendToBattleGround(_player, bgTypeId);
|
||||
bg->AddPlayer(_player);
|
||||
// set the destination instance id
|
||||
_player->SetBattleGroundId(bg->GetInstanceID());
|
||||
// set the destination team
|
||||
_player->SetBGTeam(team);
|
||||
// bg->HandleBeforeTeleportToBattleGround(_player);
|
||||
sBattleGroundMgr.SendToBattleGround(_player, instanceId);
|
||||
// add only in HandleMoveWorldPortAck()
|
||||
// bg->AddPlayer(_player,team);
|
||||
sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId);
|
||||
break;
|
||||
case 0: // leave queue
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId);
|
||||
_player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
|
||||
/*
|
||||
if player leaves rated arena match before match start, it is counted as he played but he lost
|
||||
*/
|
||||
if (israted)
|
||||
{
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(team);
|
||||
if (at)
|
||||
{
|
||||
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating);
|
||||
at->MemberLost(_player, opponentsRating);
|
||||
at->SaveToDB();
|
||||
}
|
||||
}
|
||||
_player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);
|
||||
// player left queue, we should update it, maybe now his group fits in
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating);
|
||||
SendPacket(&data);
|
||||
sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Battleground port: unknown action %u", action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleBattleGroundLeaveOpcode( WorldPacket & /*recv_data*/ )
|
||||
{
|
||||
|
|
@ -384,7 +525,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
|
|||
BattleGround *bg = _player->GetBattleGround();
|
||||
if(bg)
|
||||
{
|
||||
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID());
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
|
||||
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
|
||||
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
|
||||
|
|
@ -392,15 +534,25 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
|
|||
}
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i);
|
||||
if (i == queueSlot || !queue_id)
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong
|
||||
uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id);
|
||||
uint8 isRated = 0;
|
||||
if (i == queueSlot || !queue_id) // we need to get the instance ids
|
||||
continue;
|
||||
BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id);
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
continue;
|
||||
if(itrPlayerStatus->second.GroupInfo)
|
||||
{
|
||||
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
|
||||
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
|
||||
}
|
||||
BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this
|
||||
if(bg2)
|
||||
{
|
||||
//in this call is small bug, this call should be filled by player's waiting time in queue
|
||||
//this call nulls all timers for client :
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
|
@ -411,16 +563,36 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
|
|||
// we should update all queues? .. i'm not sure if this code is correct
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
if(uint32 queue_id = _player->GetBattleGroundQueueId(i))
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i);
|
||||
if(!queue_id)
|
||||
continue;
|
||||
uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id);
|
||||
uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id);
|
||||
uint8 isRated = 0;
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
continue;
|
||||
if(itrPlayerStatus->second.GroupInfo)
|
||||
{
|
||||
if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id))
|
||||
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
|
||||
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
|
||||
}
|
||||
if(bg && queue_id)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else // not sure if it needed...
|
||||
{
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data )
|
||||
|
|
@ -480,16 +652,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
|
|||
if(_player->InBattleGround())
|
||||
return;
|
||||
|
||||
for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId)
|
||||
{
|
||||
if(_player->GetBattleGroundQueueId(qId) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid; // arena Battlemaster guid
|
||||
uint8 type; // 2v2, 3v3 or 5v5
|
||||
uint8 asGroup; // asGroup
|
||||
uint8 isRated; // isRated
|
||||
Group * grp;
|
||||
|
||||
recv_data >> guid >> type >> asGroup >> isRated;
|
||||
|
||||
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
|
||||
|
|
@ -500,6 +668,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
|
|||
return;
|
||||
|
||||
uint8 arenatype = 0;
|
||||
uint32 arenaRating = 0;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
|
|
@ -517,88 +686,118 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
|
|||
return;
|
||||
}
|
||||
|
||||
if(isRated && !_player->GetArenaTeamId(type)) // player not in arena team of that size
|
||||
//check existance
|
||||
BattleGround* bg = NULL;
|
||||
if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) )
|
||||
{
|
||||
sLog.outError("Battleground: template bg (all arenas) not found");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 bgTypeId = bg->GetTypeID();
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype);
|
||||
|
||||
// check queueing conditions
|
||||
if(!asGroup)
|
||||
{
|
||||
// check if already in queue
|
||||
if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
//player is already in this queue
|
||||
return;
|
||||
// check if has free queue slots
|
||||
if(!_player->HasFreeBattleGroundQueueId())
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
grp = _player->GetGroup();
|
||||
// no group found, error
|
||||
if(!grp)
|
||||
return;
|
||||
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type);
|
||||
if (err != BG_JOIN_ERR_OK)
|
||||
{
|
||||
SendBattleGroundOrArenaJoinError(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ateamId = 0;
|
||||
|
||||
if(isRated)
|
||||
{
|
||||
ateamId = _player->GetArenaTeamId(type);
|
||||
// check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(ateamId);
|
||||
if(!at)
|
||||
{
|
||||
_player->GetSession()->SendNotInArenaTeamPacket(arenatype);
|
||||
return;
|
||||
}
|
||||
|
||||
if(asGroup && !_player->GetGroup()) // player not in group
|
||||
return;
|
||||
|
||||
// check existence
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA);
|
||||
if(!bg)
|
||||
return;
|
||||
|
||||
bg->SetArenaType(arenatype);
|
||||
bg->SetRated(isRated);
|
||||
|
||||
if(asGroup && _player->GetGroup())
|
||||
// get the team rating for queueing
|
||||
arenaRating = at->GetRating();
|
||||
// the arenateam id must match for everyone in the group
|
||||
// get the personal ratings for queueing
|
||||
uint32 avg_pers_rating = 0;
|
||||
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Group *grp = _player->GetGroup();
|
||||
Player *member = itr->getSource();
|
||||
|
||||
// calc avg personal rating
|
||||
avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5);
|
||||
}
|
||||
|
||||
if( arenatype )
|
||||
avg_pers_rating /= arenatype;
|
||||
|
||||
// if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating
|
||||
if(avg_pers_rating + 150 < arenaRating)
|
||||
arenaRating = avg_pers_rating;
|
||||
}
|
||||
|
||||
if(asGroup)
|
||||
{
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId);
|
||||
sLog.outDebug("Battleground: arena join as group start");
|
||||
if(isRated)
|
||||
sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype);
|
||||
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
if(!member) continue;
|
||||
|
||||
/*if (!member->CanJoinToBattleground())
|
||||
//player has deserter aura .. do nothing
|
||||
*/
|
||||
|
||||
if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA))
|
||||
//player is already in this queue
|
||||
continue;
|
||||
|
||||
// add to queue
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
WorldPacket data;
|
||||
//fill data
|
||||
//member->GetSession()->SendPacket(data);
|
||||
continue;
|
||||
}
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue
|
||||
|
||||
// store entry point coords (same as leader entry point)
|
||||
member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
WorldPacket data;
|
||||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA);
|
||||
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo);
|
||||
sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
|
||||
}
|
||||
sLog.outDebug("Battleground: arena join as group end");
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*if (!member->CanJoinToBattleground())
|
||||
//player has deserter aura .. do nothing
|
||||
*/
|
||||
|
||||
if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA))
|
||||
//player is already in this queue
|
||||
return;
|
||||
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
WorldPacket data;
|
||||
//fill data (player is in 3 queues already)
|
||||
//SendPacket(data);
|
||||
return;
|
||||
}
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId);
|
||||
|
||||
// store entry point coords
|
||||
_player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
WorldPacket data;
|
||||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
|
||||
SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA);
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
|
||||
sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -620,3 +819,41 @@ void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data )
|
|||
|
||||
reportedPlayer->ReportedAfkBy(_player);
|
||||
}
|
||||
|
||||
void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err)
|
||||
{
|
||||
WorldPacket data;
|
||||
int32 msg;
|
||||
switch (err)
|
||||
{
|
||||
case BG_JOIN_ERR_OFFLINE_MEMBER:
|
||||
msg = LANG_BG_GROUP_OFFLINE_MEMBER;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_TOO_MANY:
|
||||
msg = LANG_BG_GROUP_TOO_LARGE;
|
||||
break;
|
||||
case BG_JOIN_ERR_MIXED_FACTION:
|
||||
msg = LANG_BG_GROUP_MIXED_FACTION;
|
||||
break;
|
||||
case BG_JOIN_ERR_MIXED_LEVELS:
|
||||
msg = LANG_BG_GROUP_MIXED_LEVELS;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE:
|
||||
msg = LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_DESERTER:
|
||||
msg = LANG_BG_GROUP_MEMBER_DESERTER;
|
||||
break;
|
||||
case BG_JOIN_ERR_ALL_QUEUES_USED:
|
||||
msg = LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_NOT_ENOUGH:
|
||||
case BG_JOIN_ERR_MIXED_ARENATEAM:
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(msg), NULL);
|
||||
SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -34,51 +34,99 @@ typedef std::deque<BattleGround*> BGFreeSlotQueueType;
|
|||
|
||||
#define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array
|
||||
|
||||
struct PlayerQueueInfo
|
||||
#define MAX_BATTLEGROUND_QUEUE_TYPES 8
|
||||
|
||||
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
|
||||
|
||||
struct GroupQueueInfo; // type predefinition
|
||||
struct PlayerQueueInfo // stores information for players in queue
|
||||
{
|
||||
uint32 InviteTime; // first invite time
|
||||
uint32 LastInviteTime; // last invite time
|
||||
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
|
||||
uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes
|
||||
GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo
|
||||
};
|
||||
|
||||
struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!)
|
||||
{
|
||||
std::map<uint64, PlayerQueueInfo*> Players; // player queue info map
|
||||
uint32 Team; // Player team (ALLIANCE/HORDE)
|
||||
bool IsRated;
|
||||
bool AsGroup; // uint32 GroupId;
|
||||
uint8 ArenaType;
|
||||
};
|
||||
|
||||
struct PlayersCount
|
||||
{
|
||||
uint32 Alliance;
|
||||
uint32 Horde;
|
||||
};
|
||||
|
||||
template<class _Kty, class _Ty> class bgqueue: public std::map<_Kty, _Ty>
|
||||
{
|
||||
public:
|
||||
uint32 Alliance;
|
||||
uint32 Horde;
|
||||
//bool Ready; // not used now
|
||||
//uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players)
|
||||
uint32 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 IsInvitedToBGInstanceGUID; // was invited to certain BG
|
||||
uint32 ArenaTeamRating; // if rated match, inited to the rating of the team
|
||||
uint32 OpponentsTeamRating; // for rated arena matches
|
||||
};
|
||||
|
||||
class BattleGround;
|
||||
class BattleGroundQueue
|
||||
{
|
||||
public:
|
||||
BattleGroundQueue();
|
||||
~BattleGroundQueue();
|
||||
/*
|
||||
uint32 GetType();
|
||||
void SetType(uint32 type);*/
|
||||
|
||||
void Update(uint32 bgTypeId, uint32 queue_id);
|
||||
void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0);
|
||||
|
||||
void AddPlayer(Player *plr, uint32 bgTypeId);
|
||||
GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0);
|
||||
void AddPlayer(Player *plr, GroupQueueInfo *ginfo);
|
||||
void RemovePlayer(uint64 guid, bool decreaseInvitedCount);
|
||||
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
|
||||
void BGEndedRemoveInvites(BattleGround * bg);
|
||||
|
||||
typedef bgqueue<uint64, PlayerQueueInfo> QueuedPlayersMap;
|
||||
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
|
||||
QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES];
|
||||
typedef std::list<uint64> PlayerGuidsSortedByTimeQueue;
|
||||
PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES];
|
||||
|
||||
typedef std::list<GroupQueueInfo*> QueuedGroupsList;
|
||||
QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES];
|
||||
|
||||
// class to hold pointers to the groups eligible for a specific selection pool building mode
|
||||
class EligibleGroups : public std::list<GroupQueueInfo *>
|
||||
{
|
||||
public:
|
||||
void Init(QueuedGroupsList * source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0);
|
||||
void RemoveGroup(GroupQueueInfo * ginfo);
|
||||
};
|
||||
|
||||
EligibleGroups m_EligibleGroups;
|
||||
|
||||
// class to select and invite groups to bg
|
||||
class SelectionPool
|
||||
{
|
||||
public:
|
||||
void Init();
|
||||
void AddGroup(GroupQueueInfo * group);
|
||||
GroupQueueInfo * GetMaximalGroup();
|
||||
void RemoveGroup(GroupQueueInfo * group);
|
||||
uint32 GetPlayerCount() const {return PlayerCount;}
|
||||
public:
|
||||
std::list<GroupQueueInfo *> SelectedGroups;
|
||||
private:
|
||||
uint32 PlayerCount;
|
||||
GroupQueueInfo * MaxGroup;
|
||||
};
|
||||
|
||||
enum SelectionPoolBuildMode
|
||||
{
|
||||
NORMAL_ALLIANCE,
|
||||
NORMAL_HORDE,
|
||||
ONESIDE_ALLIANCE_TEAM1,
|
||||
ONESIDE_ALLIANCE_TEAM2,
|
||||
ONESIDE_HORDE_TEAM1,
|
||||
ONESIDE_HORDE_TEAM2,
|
||||
|
||||
NUM_SELECTION_POOL_TYPES
|
||||
};
|
||||
|
||||
SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES];
|
||||
|
||||
bool BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0);
|
||||
|
||||
private:
|
||||
|
||||
bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -96,7 +144,6 @@ class BGQueueInviteEvent : public BasicEvent
|
|||
private:
|
||||
uint64 m_PlayerGuid;
|
||||
uint32 m_BgInstanceGUID;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -116,7 +163,6 @@ class BGQueueRemoveEvent : public BasicEvent
|
|||
uint32 m_PlayersTeam;
|
||||
};
|
||||
|
||||
|
||||
class BattleGroundMgr
|
||||
{
|
||||
public:
|
||||
|
|
@ -132,18 +178,18 @@ class BattleGroundMgr
|
|||
void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId);
|
||||
void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value);
|
||||
void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg);
|
||||
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2);
|
||||
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0);
|
||||
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
|
||||
|
||||
/* Player invitation */
|
||||
// called from Queue update, or from Addplayer to queue
|
||||
void InvitePlayer(Player* plr, uint32 bgInstanceGUID);
|
||||
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team);
|
||||
|
||||
/* Battlegrounds */
|
||||
BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); };
|
||||
BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); };
|
||||
|
||||
BattleGround* GetBattleGround(uint8 ID)
|
||||
BattleGround* GetBattleGround(uint32 ID)
|
||||
{
|
||||
BattleGroundSet::iterator i = m_BattleGrounds.find(ID);
|
||||
if(i != m_BattleGrounds.end())
|
||||
|
|
@ -152,9 +198,13 @@ class BattleGroundMgr
|
|||
return NULL;
|
||||
};
|
||||
|
||||
BattleGround * GetBattleGroundTemplate(uint32 bgTypeId);
|
||||
BattleGround * CreateNewBattleGround(uint32 bgTypeId);
|
||||
|
||||
uint32 CreateBattleGround(uint32 bgTypeId, 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);
|
||||
|
||||
inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; };
|
||||
void RemoveBattleGround(uint32 instanceID);
|
||||
|
||||
void CreateInitialBattleGrounds();
|
||||
|
||||
|
|
@ -162,16 +212,39 @@ class BattleGroundMgr
|
|||
|
||||
/* Battleground queues */
|
||||
//these queues are instantiated when creating BattlegroundMrg
|
||||
BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_TYPES]; // public, because we need to access them in BG handler code
|
||||
BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; // public, because we need to access them in BG handler code
|
||||
|
||||
BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES];
|
||||
|
||||
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid);
|
||||
|
||||
bool IsArenaType(uint32 bgTypeId) const;
|
||||
bool IsBattleGroundType(uint32 bgTypeId) const;
|
||||
uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const;
|
||||
uint32 BGTemplateId(uint32 bgQueueTypeId) const;
|
||||
uint8 BGArenaType(uint32 bgQueueTypeId) const;
|
||||
|
||||
uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;}
|
||||
uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;}
|
||||
|
||||
void InitAutomaticArenaPointDistribution();
|
||||
void DistributeArenaPoints();
|
||||
uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;}
|
||||
void ToggleArenaTesting();
|
||||
const bool isArenaTesting() const { return m_ArenaTesting; }
|
||||
|
||||
private:
|
||||
|
||||
/* Battlegrounds */
|
||||
BattleGroundSet m_BattleGrounds;
|
||||
uint32 m_MaxRatingDifference;
|
||||
uint32 m_RatingDiscardTimer;
|
||||
uint32 m_NextRatingDiscardUpdate;
|
||||
bool m_AutoDistributePoints;
|
||||
uint64 m_NextAutoDistributionTime;
|
||||
uint32 m_AutoDistributionTimeChecker;
|
||||
uint32 m_PrematureFinishTimer;
|
||||
bool m_ArenaTesting;
|
||||
};
|
||||
|
||||
#define sBattleGroundMgr MaNGOS::Singleton<BattleGroundMgr>::Instance()
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ void BattleGroundNA::Update(time_t diff)
|
|||
if (!(m_Events & 0x01))
|
||||
{
|
||||
m_Events |= 0x01;
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++)
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
|
|
@ -73,6 +79,9 @@ void BattleGroundNA::Update(time_t diff)
|
|||
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);
|
||||
|
||||
SendMessageToAll(LANG_ARENA_BEGUN);
|
||||
SetStatus(STATUS_IN_PROGRESS);
|
||||
SetStartDelayTime(0);
|
||||
|
|
@ -80,6 +89,11 @@ void BattleGroundNA::Update(time_t diff)
|
|||
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
||||
if(Player *plr = objmgr.GetPlayer(itr->first))
|
||||
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
|
||||
|
||||
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +110,23 @@ void BattleGroundNA::AddPlayer(Player *plr)
|
|||
BattleGroundNAScore* sc = new BattleGroundNAScore;
|
||||
|
||||
m_PlayerScores[plr->GetGUID()] = sc;
|
||||
|
||||
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
|
||||
}
|
||||
|
||||
void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
|
||||
{
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
return;
|
||||
|
||||
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
|
||||
void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
|
||||
|
|
@ -116,15 +142,25 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
|
|||
|
||||
BattleGround::HandleKillPlayer(player,killer);
|
||||
|
||||
uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());
|
||||
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
++m_TeamKills[killer_team_index]; // add kills to killer's team
|
||||
|
||||
if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(killer->GetTeam());
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
else if(!GetAlivePlayersCountByTeam(HORDE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundNA::HandlePlayerUnderMap(Player *player)
|
||||
{
|
||||
player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
||||
|
|
@ -149,19 +185,28 @@ void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
|||
// HandleTriggerBuff(buff_guid,Source);
|
||||
}
|
||||
|
||||
void BattleGroundNA::FillInitialWorldStates(WorldPacket &data)
|
||||
{
|
||||
data << uint32(0xa0f) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7
|
||||
data << uint32(0xa10) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8
|
||||
data << uint32(0xa11) << uint32(1); // 9
|
||||
}
|
||||
|
||||
void BattleGroundNA::ResetBGSubclass()
|
||||
{
|
||||
m_TeamKills[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamKills[BG_TEAM_HORDE] = 0;
|
||||
|
||||
}
|
||||
|
||||
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))
|
||||
if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY)
|
||||
// buffs
|
||||
|| !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120)
|
||||
|| !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120))
|
||||
{
|
||||
sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ enum BattleGroundNAObjectTypes
|
|||
BG_NA_OBJECT_DOOR_2 = 1,
|
||||
BG_NA_OBJECT_DOOR_3 = 2,
|
||||
BG_NA_OBJECT_DOOR_4 = 3,
|
||||
BG_NA_OBJECT_MAX = 4
|
||||
BG_NA_OBJECT_BUFF_1 = 4,
|
||||
BG_NA_OBJECT_BUFF_2 = 5,
|
||||
BG_NA_OBJECT_MAX = 6
|
||||
};
|
||||
|
||||
enum BattleGroundNAObjects
|
||||
|
|
@ -34,7 +36,9 @@ 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_DOOR_4 = 183979,
|
||||
BG_NA_OBJECT_TYPE_BUFF_1 = 184663,
|
||||
BG_NA_OBJECT_TYPE_BUFF_2 = 184664
|
||||
};
|
||||
|
||||
class BattleGroundNAScore : public BattleGroundScore
|
||||
|
|
@ -61,9 +65,8 @@ class BattleGroundNA : public BattleGround
|
|||
void HandleAreaTrigger(Player *Source, uint32 Trigger);
|
||||
bool SetupBattleGround();
|
||||
virtual void ResetBGSubclass();
|
||||
virtual void FillInitialWorldStates(WorldPacket &d);
|
||||
void HandleKillPlayer(Player* player, Player *killer);
|
||||
|
||||
private:
|
||||
uint32 m_TeamKills[2]; // count of kills for each team
|
||||
bool HandlePlayerUnderMap(Player * plr);
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -47,6 +47,13 @@ void BattleGroundRL::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
|
|
@ -73,6 +80,9 @@ void BattleGroundRL::Update(time_t diff)
|
|||
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);
|
||||
|
||||
SendMessageToAll(LANG_ARENA_BEGUN);
|
||||
SetStatus(STATUS_IN_PROGRESS);
|
||||
SetStartDelayTime(0);
|
||||
|
|
@ -80,6 +90,11 @@ void BattleGroundRL::Update(time_t diff)
|
|||
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
||||
if(Player *plr = objmgr.GetPlayer(itr->first))
|
||||
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
|
||||
|
||||
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +111,23 @@ void BattleGroundRL::AddPlayer(Player *plr)
|
|||
BattleGroundRLScore* sc = new BattleGroundRLScore;
|
||||
|
||||
m_PlayerScores[plr->GetGUID()] = sc;
|
||||
|
||||
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
|
||||
}
|
||||
|
||||
void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
|
||||
{
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
return;
|
||||
|
||||
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
|
||||
void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
|
||||
|
|
@ -116,15 +143,25 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
|
|||
|
||||
BattleGround::HandleKillPlayer(player,killer);
|
||||
|
||||
uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());
|
||||
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
++m_TeamKills[killer_team_index]; // add kills to killer's team
|
||||
|
||||
if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(killer->GetTeam());
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
else if(!GetAlivePlayersCountByTeam(HORDE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundRL::HandlePlayerUnderMap(Player *player)
|
||||
{
|
||||
player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
||||
|
|
@ -150,17 +187,26 @@ void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
|||
// HandleTriggerBuff(buff_guid,Source);
|
||||
}
|
||||
|
||||
void BattleGroundRL::FillInitialWorldStates(WorldPacket &data)
|
||||
{
|
||||
data << uint32(0xbb8) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7
|
||||
data << uint32(0xbb9) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8
|
||||
data << uint32(0xbba) << uint32(1); // 9
|
||||
}
|
||||
|
||||
void BattleGroundRL::ResetBGSubclass()
|
||||
{
|
||||
m_TeamKills[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamKills[BG_TEAM_HORDE] = 0;
|
||||
|
||||
}
|
||||
|
||||
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))
|
||||
if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY)
|
||||
// buffs
|
||||
|| !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120)
|
||||
|| !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120))
|
||||
{
|
||||
sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -24,13 +24,17 @@ enum BattleGroundRLObjectTypes
|
|||
{
|
||||
BG_RL_OBJECT_DOOR_1 = 0,
|
||||
BG_RL_OBJECT_DOOR_2 = 1,
|
||||
BG_RL_OBJECT_MAX = 2
|
||||
BG_RL_OBJECT_BUFF_1 = 2,
|
||||
BG_RL_OBJECT_BUFF_2 = 3,
|
||||
BG_RL_OBJECT_MAX = 4
|
||||
};
|
||||
|
||||
enum BattleGroundRLObjects
|
||||
{
|
||||
BG_RL_OBJECT_TYPE_DOOR_1 = 185918,
|
||||
BG_RL_OBJECT_TYPE_DOOR_2 = 185917
|
||||
BG_RL_OBJECT_TYPE_DOOR_2 = 185917,
|
||||
BG_RL_OBJECT_TYPE_BUFF_1 = 184663,
|
||||
BG_RL_OBJECT_TYPE_BUFF_2 = 184664
|
||||
};
|
||||
|
||||
class BattleGroundRLScore : public BattleGroundScore
|
||||
|
|
@ -57,9 +61,8 @@ class BattleGroundRL : public BattleGround
|
|||
void HandleAreaTrigger(Player *Source, uint32 Trigger);
|
||||
bool SetupBattleGround();
|
||||
virtual void ResetBGSubclass();
|
||||
virtual void FillInitialWorldStates(WorldPacket &d);
|
||||
void HandleKillPlayer(Player* player, Player *killer);
|
||||
|
||||
private:
|
||||
uint32 m_TeamKills[2]; // count of kills for each team
|
||||
bool HandlePlayerUnderMap(Player * plr);
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,6 +49,16 @@ void BattleGroundWS::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++)
|
||||
// SpawnBGCreature(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)
|
||||
{
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
|
@ -285,7 +295,32 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
|
|||
|
||||
void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
|
||||
{
|
||||
// Drop allowed in any BG state
|
||||
if(GetStatus() != STATUS_IN_PROGRESS)
|
||||
{
|
||||
// if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages
|
||||
// just take off the aura
|
||||
if(Source->GetTeam() == ALLIANCE)
|
||||
{
|
||||
if(!this->IsHordeFlagPickedup())
|
||||
return;
|
||||
if(GetHordeFlagPickerGUID() == Source->GetGUID())
|
||||
{
|
||||
SetHordeFlagPicker(0);
|
||||
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!this->IsAllianceFlagPickedup())
|
||||
return;
|
||||
if(GetAllianceFlagPickerGUID() == Source->GetGUID())
|
||||
{
|
||||
SetAllianceFlagPicker(0);
|
||||
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char *message = "";
|
||||
uint8 type = 0;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "PlayerDump.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "Util.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "Language.h"
|
||||
|
||||
class LoginQueryHolder : public SqlQueryHolder
|
||||
|
|
@ -59,7 +60,7 @@ bool LoginQueryHolder::Initialize()
|
|||
|
||||
// NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure.
|
||||
// !!! NOTE: including unused `zone`,`online`
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
|
|
@ -79,6 +80,7 @@ bool LoginQueryHolder::Initialize()
|
|||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid));
|
||||
// in other case still be dummy query
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -411,7 +413,7 @@ void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data )
|
|||
}
|
||||
|
||||
// is arena team captain
|
||||
if(objmgr.GetArenaTeamByCapitan(guid))
|
||||
if(objmgr.GetArenaTeamByCaptain(guid))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
||||
data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN;
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMod32Value, "", NULL },
|
||||
{ "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL },
|
||||
{ "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL },
|
||||
{ "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
|
|
@ -560,6 +561,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL },
|
||||
{ "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL },
|
||||
{ "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL },
|
||||
{ "flusharenapoints", SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
|
||||
{ "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL },
|
||||
{ "sendmessage", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL },
|
||||
{ "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL },
|
||||
|
|
|
|||
|
|
@ -415,6 +415,7 @@ class ChatHandler
|
|||
bool HandleComeToMeCommand(const char *args);
|
||||
bool HandleCombatStopCommand(const char *args);
|
||||
bool HandleSendMessageCommand(const char * args);
|
||||
bool HandleFlushArenaPointsCommand(const char *args);
|
||||
bool HandleRepairitemsCommand(const char* args);
|
||||
bool HandleWaterwalkCommand(const char* args);
|
||||
|
||||
|
|
@ -429,6 +430,7 @@ class ChatHandler
|
|||
bool HandleSaveAllCommand(const char* args);
|
||||
bool HandleGetItemState(const char * args);
|
||||
bool HandleGetLootRecipient(const char * args);
|
||||
bool HandleDebugArenaCommand(const char * args);
|
||||
|
||||
Player* getSelectedPlayer();
|
||||
Creature* getSelectedCreature();
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ uint32 GameEvent::Update() // return the next e
|
|||
{
|
||||
uint32 nextEventDelay = max_ge_check_delay; // 1 day
|
||||
uint32 calcDelay;
|
||||
for (uint16 itr = 1; itr < mGameEvent.size(); itr++)
|
||||
for (uint16 itr = 1; itr < mGameEvent.size(); ++itr)
|
||||
{
|
||||
//sLog.outErrorDb("Checking event %u",itr);
|
||||
if (CheckOneGameEvent(itr))
|
||||
|
|
|
|||
|
|
@ -1308,6 +1308,54 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
|
|||
SendUpdate();
|
||||
}
|
||||
|
||||
uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
|
||||
{
|
||||
// check for min / max count
|
||||
uint32 memberscount = GetMembersCount();
|
||||
if(memberscount < MinPlayerCount)
|
||||
return BG_JOIN_ERR_GROUP_NOT_ENOUGH;
|
||||
if(memberscount > MaxPlayerCount)
|
||||
return BG_JOIN_ERR_GROUP_TOO_MANY;
|
||||
|
||||
// get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
|
||||
Player * reference = GetFirstMember()->getSource();
|
||||
// no reference found, can't join this way
|
||||
if(!reference)
|
||||
return BG_JOIN_ERR_OFFLINE_MEMBER;
|
||||
|
||||
uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel();
|
||||
uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
|
||||
uint32 team = reference->GetTeam();
|
||||
|
||||
// check every member of the group to be able to join
|
||||
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
// offline member? don't let join
|
||||
if(!member)
|
||||
return BG_JOIN_ERR_OFFLINE_MEMBER;
|
||||
// don't allow cross-faction join as group
|
||||
if(member->GetTeam() != team)
|
||||
return BG_JOIN_ERR_MIXED_FACTION;
|
||||
// not in the same battleground level braket, don't let join
|
||||
if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId)
|
||||
return BG_JOIN_ERR_MIXED_LEVELS;
|
||||
// don't let join rated matches if the arena team id doesn't match
|
||||
if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
|
||||
return BG_JOIN_ERR_MIXED_ARENATEAM;
|
||||
// don't let join if someone from the group is already in that bg queue
|
||||
if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType))
|
||||
return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE;
|
||||
// check for deserter debuff in case not arena queue
|
||||
if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground())
|
||||
return BG_JOIN_ERR_GROUP_DESERTER;
|
||||
// check if member can join any more battleground queues
|
||||
if(!member->HasFreeBattleGroundQueueId())
|
||||
return BG_JOIN_ERR_ALL_QUEUES_USED;
|
||||
}
|
||||
return BG_JOIN_ERR_OK;
|
||||
}
|
||||
|
||||
//===================================================
|
||||
//============== Roll ===============================
|
||||
//===================================================
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ class MANGOS_DLL_SPEC Group
|
|||
void ConvertToRaid();
|
||||
|
||||
void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; }
|
||||
uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot);
|
||||
|
||||
void ChangeMembersGroup(const uint64 &guid, const uint8 &group);
|
||||
void ChangeMembersGroup(Player *player, const uint8 &group);
|
||||
|
|
|
|||
|
|
@ -641,11 +641,30 @@ enum MangosStrings
|
|||
LANG_BG_QUEUE_ANNOUNCE_SELF = 711,
|
||||
LANG_BG_QUEUE_ANNOUNCE_WORLD = 712,
|
||||
|
||||
|
||||
LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713,
|
||||
LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714,
|
||||
// LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, an opcode exists for this
|
||||
LANG_YOUR_BG_LEVEL_REQ_ERROR = 715,
|
||||
LANG_YOUR_ARENA_TEAM_FULL = 716,
|
||||
// Room for BG/ARENA 717-799 not used
|
||||
// LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this
|
||||
|
||||
LANG_BG_GROUP_TOO_LARGE = 7007, // "Your group is too large for this battleground. Please regroup to join."
|
||||
LANG_ARENA_GROUP_TOO_LARGE = 7008, // "Your group is too large for this arena. Please regroup to join."
|
||||
LANG_ARENA_YOUR_TEAM_ONLY = 7009, // "Your group has members not in your arena team. Please regroup to join."
|
||||
LANG_ARENA_NOT_ENOUGH_PLAYERS = 7010, // "Your group does not have enough players to join this match."
|
||||
LANG_ARENA_GOLD_WINS = 7011, // "The Gold Team wins!"
|
||||
LANG_ARENA_GREEN_WINS = 7012, // "The Green Team wins!"
|
||||
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 7013, // The battleground will end soon, because there aren't enough players. Get more ppl or win already!
|
||||
LANG_BG_GROUP_OFFLINE_MEMBER = 7014, // "Your group has an offline member. Please remove him before joining."
|
||||
LANG_BG_GROUP_MIXED_FACTION = 7015, // "Your group has players from the opposing faction. You can't join the battleground as a group."
|
||||
LANG_BG_GROUP_MIXED_LEVELS = 7016, // "Your group has players from different battleground brakets. You can't join as group."
|
||||
LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 7017, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group."
|
||||
LANG_BG_GROUP_MEMBER_DESERTER = 7018, // "Someone in your party is Deserter. You can't join as group."
|
||||
LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 7019, // "Someone in your party is already in three battleground queues. You cannot join as group."
|
||||
|
||||
LANG_CANNOT_TELE_TO_BG = 7020, // "You cannot teleport to a battleground or arena map."
|
||||
LANG_CANNOT_SUMMON_TO_BG = 7021, // "You cannot summon players to a battleground or arena map."
|
||||
LANG_CANNOT_GO_TO_BG_GM = 7022, // "You must be in GM mode to teleport to a player in a battleground."
|
||||
LANG_CANNOT_GO_TO_BG_FROM_BG = 7023, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first."
|
||||
|
||||
// in game strings
|
||||
// = 800, not used
|
||||
|
|
|
|||
|
|
@ -351,7 +351,14 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
|
|||
|
||||
Map* pMap = m_session->GetPlayer()->GetMap();
|
||||
|
||||
if(pMap->Instanceable())
|
||||
if(pMap->IsBattleGroundOrArena())
|
||||
{
|
||||
// cannot summon to bg
|
||||
PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,chr->GetName());
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
else if(pMap->IsDungeon())
|
||||
{
|
||||
Map* cMap = chr->GetMap();
|
||||
if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() )
|
||||
|
|
@ -435,6 +442,28 @@ bool ChatHandler::HandleGonameCommand(const char* args)
|
|||
Player *chr = objmgr.GetPlayer(name.c_str());
|
||||
if (chr)
|
||||
{
|
||||
Map* cMap = chr->GetMap();
|
||||
if(cMap->IsBattleGroundOrArena())
|
||||
{
|
||||
// only allow if gm mode is on
|
||||
if (!_player->isGameMaster())
|
||||
{
|
||||
PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName());
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
// if already in a bg, don't let port to other
|
||||
else if (_player->GetBattleGroundId())
|
||||
{
|
||||
PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName());
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
// all's well, set bg id
|
||||
// when porting out from the bg, it will be reset to 0
|
||||
_player->SetBattleGroundId(chr->GetBattleGroundId());
|
||||
}
|
||||
else if(cMap->IsDungeon())
|
||||
Map* cMap = chr->GetMap();
|
||||
if(cMap->Instanceable())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "Config/ConfigEnv.h"
|
||||
#include "Util.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "BattleGroundMgr.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "InstanceData.h"
|
||||
|
||||
|
|
@ -6479,6 +6480,12 @@ bool ChatHandler::HandleSendMessageCommand(const char* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/)
|
||||
{
|
||||
sBattleGroundMgr.DistributeArenaPoints();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleModifyGenderCommand(const char *args)
|
||||
{
|
||||
if(!*args)
|
||||
|
|
|
|||
|
|
@ -141,7 +141,17 @@ Map* MapInstanced::GetInstance(const WorldObject* obj)
|
|||
uint32 NewInstanceId = 0; // instanceId of the resulting map
|
||||
Player* player = (Player*)obj;
|
||||
|
||||
// TODO: battlegrounds and arenas
|
||||
if(IsBattleGroundOrArena())
|
||||
{
|
||||
// instantiate or find existing bg map for player
|
||||
// the instance id is set in battlegroundid
|
||||
NewInstanceId = player->GetBattleGroundId();
|
||||
assert(NewInstanceId);
|
||||
map = _FindMap(NewInstanceId);
|
||||
if(!map)
|
||||
map = CreateBattleGround(NewInstanceId);
|
||||
return map;
|
||||
}
|
||||
|
||||
InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty());
|
||||
InstanceSave *pSave = pBind ? pBind->save : NULL;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ MapManager::_GetBaseMap(uint32 id)
|
|||
Guard guard(*this);
|
||||
|
||||
const MapEntry* entry = sMapStore.LookupEntry(id);
|
||||
if (entry && entry->IsDungeon())
|
||||
if (entry && entry->Instanceable())
|
||||
{
|
||||
m = new MapInstanced(id, i_gridCleanUpDelay);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,22 +130,28 @@ void WorldSession::HandleMoveWorldportAckOpcode()
|
|||
_player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
|
||||
|
||||
// battleground state prepare
|
||||
if(_player->InBattleGround())
|
||||
// only add to bg group and object, if the player was invited (else he entered through command)
|
||||
if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId()))
|
||||
{
|
||||
BattleGround *bg = _player->GetBattleGround();
|
||||
if(bg)
|
||||
{
|
||||
bg->AddPlayer(_player);
|
||||
if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg
|
||||
{
|
||||
if(!bg->GetBgRaid(_player->GetTeam())) // first player joined
|
||||
// get the team this way, because arenas might 'override' the teams.
|
||||
uint32 team = bg->GetPlayerTeam(_player->GetGUID());
|
||||
if(!team)
|
||||
team = _player->GetTeam();
|
||||
if(!bg->GetBgRaid(team)) // first player joined
|
||||
{
|
||||
Group *group = new Group;
|
||||
bg->SetBgRaid(_player->GetTeam(), group);
|
||||
bg->SetBgRaid(team, group);
|
||||
group->Create(_player->GetGUIDLow(), _player->GetName());
|
||||
}
|
||||
else // raid already exist
|
||||
{
|
||||
bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName());
|
||||
bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -369,6 +375,14 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
if(movementInfo.z < -500.0f)
|
||||
{
|
||||
if(GetPlayer()->InBattleGround()
|
||||
&& GetPlayer()->GetBattleGround()
|
||||
&& GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player))
|
||||
{
|
||||
// do nothing, the handle already did if returned true
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this is actually called many times while falling
|
||||
// even after the player has been teleported away
|
||||
|
|
@ -386,6 +400,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
GetPlayer()->RepopAtGraveyard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -226,33 +226,43 @@ Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 ArenaTeamId) const
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 arenateamid) const
|
||||
{
|
||||
for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr)
|
||||
if ((*itr)->GetId() == ArenaTeamId)
|
||||
return *itr;
|
||||
ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid);
|
||||
if (itr != mArenaTeamMap.end())
|
||||
return itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const
|
||||
{
|
||||
for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr)
|
||||
if ((*itr)->GetName() == arenateamname)
|
||||
return *itr;
|
||||
for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
|
||||
if (itr->second->GetName() == arenateamname)
|
||||
return itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByCapitan(uint64 const& guid) const
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByCaptain(uint64 const& guid) const
|
||||
{
|
||||
for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr)
|
||||
if ((*itr)->GetCaptain() == guid)
|
||||
return *itr;
|
||||
for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
|
||||
if (itr->second->GetCaptain() == guid)
|
||||
return itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ObjectMgr::AddArenaTeam(ArenaTeam* arenaTeam)
|
||||
{
|
||||
mArenaTeamMap[arenaTeam->GetId()] = arenaTeam;
|
||||
}
|
||||
|
||||
void ObjectMgr::RemoveArenaTeam(ArenaTeam* arenaTeam)
|
||||
{
|
||||
mArenaTeamMap.erase( arenaTeam->GetId() );
|
||||
}
|
||||
|
||||
AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location )
|
||||
{
|
||||
switch ( location )
|
||||
|
|
@ -4203,7 +4213,7 @@ void ObjectMgr::AddGossipText(GossipText *pGText)
|
|||
GossipText *ObjectMgr::GetGossipText(uint32 Text_ID)
|
||||
{
|
||||
GossipTextMap::const_iterator itr;
|
||||
for (itr = mGossipText.begin(); itr != mGossipText.end(); itr++)
|
||||
for (itr = mGossipText.begin(); itr != mGossipText.end(); ++itr)
|
||||
{
|
||||
if(itr->second->Text_ID == Text_ID)
|
||||
return itr->second;
|
||||
|
|
|
|||
|
|
@ -282,11 +282,11 @@ class ObjectMgr
|
|||
|
||||
typedef std::set< Group * > GroupSet;
|
||||
typedef std::set< Guild * > GuildSet;
|
||||
typedef std::set< ArenaTeam * > ArenaTeamSet;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, ArenaTeam* > ArenaTeamMap;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, Quest*> QuestMap;
|
||||
|
||||
|
||||
typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerMap;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap;
|
||||
|
|
@ -318,11 +318,13 @@ class ObjectMgr
|
|||
void AddGuild(Guild* guild) { mGuildSet.insert( guild ); }
|
||||
void RemoveGuild(Guild* guild) { mGuildSet.erase( guild ); }
|
||||
|
||||
ArenaTeam* GetArenaTeamById(const uint32 ArenaTeamId) const;
|
||||
ArenaTeam* GetArenaTeamByName(const std::string& ArenaTeamName) const;
|
||||
ArenaTeam* GetArenaTeamByCapitan(uint64 const& guid) const;
|
||||
void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); }
|
||||
void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); }
|
||||
ArenaTeam* GetArenaTeamById(const uint32 arenateamid) const;
|
||||
ArenaTeam* GetArenaTeamByName(const std::string& arenateamname) const;
|
||||
ArenaTeam* GetArenaTeamByCaptain(uint64 const& guid) const;
|
||||
void AddArenaTeam(ArenaTeam* arenaTeam);
|
||||
void RemoveArenaTeam(ArenaTeam* arenaTeam);
|
||||
ArenaTeamMap::iterator GetArenaTeamMapBegin() { return mArenaTeamMap.begin(); }
|
||||
ArenaTeamMap::iterator GetArenaTeamMapEnd() { return mArenaTeamMap.end(); }
|
||||
|
||||
static CreatureInfo const *GetCreatureTemplate( uint32 id );
|
||||
CreatureModelInfo const *GetCreatureModelInfo( uint32 modelid );
|
||||
|
|
@ -801,7 +803,7 @@ class ObjectMgr
|
|||
|
||||
GroupSet mGroupSet;
|
||||
GuildSet mGuildSet;
|
||||
ArenaTeamSet mArenaTeamSet;
|
||||
ArenaTeamMap mArenaTeamMap;
|
||||
|
||||
ItemMap mItems;
|
||||
ItemMap mAitems;
|
||||
|
|
|
|||
|
|
@ -115,14 +115,6 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
return;
|
||||
}
|
||||
|
||||
for(uint8 i = 0; i < MAX_ARENA_SLOT; i++)
|
||||
{
|
||||
if(_player->GetArenaTeamId(i) && (i == (unk10-1)))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch(unk10)
|
||||
{
|
||||
case 1:
|
||||
|
|
@ -144,6 +136,12 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
sLog.outDebug("unknown selection at buy petition: %u", unk10);
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamId(unk10-1))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(type == 9)
|
||||
|
|
@ -153,12 +151,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(name))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(name))
|
||||
if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -171,12 +164,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(name))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(name))
|
||||
if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -216,6 +204,8 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
_player->SendNewItem(charter, 1, true, false);
|
||||
|
||||
// a petition is invalid, if both the owner and the type matches
|
||||
// we checked above, if this player is in an arenateam, so this must be
|
||||
// datacorruption
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type);
|
||||
|
||||
std::ostringstream ssInvalidPetitionGUIDs;
|
||||
|
|
@ -429,12 +419,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
|
|||
SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(newname))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(newname))
|
||||
if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -447,12 +432,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
|
|||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(newname))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(newname))
|
||||
if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -511,7 +491,13 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
|
||||
// not let enemies sign guild charter
|
||||
if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid))
|
||||
{
|
||||
if(type != 9)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
else
|
||||
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
|
||||
|
|
@ -527,10 +513,42 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
return;
|
||||
}
|
||||
|
||||
if(type != 9 && _player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
if(type != 9)
|
||||
{
|
||||
// player is too low level to join an arena team
|
||||
SendNotification(LANG_YOUR_ARENA_LEVEL_REQ_ERROR,sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
|
||||
if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 slot = ArenaTeam::GetSlotByType(type);
|
||||
if(slot >= MAX_ARENA_SLOT)
|
||||
return;
|
||||
|
||||
if(_player->GetArenaTeamId(slot))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_player->GetGuildId())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
|
||||
return;
|
||||
}
|
||||
if(_player->GetGuildIdInvited())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -619,20 +637,63 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
|
|||
|
||||
uint8 signs = 0;
|
||||
uint64 petitionguid, plguid;
|
||||
uint32 petitiontype;
|
||||
uint32 type;
|
||||
Player *player;
|
||||
recv_data >> petitiontype; // 2.0.8 - petition type?
|
||||
recv_data >> type;
|
||||
recv_data >> petitionguid; // petition guid
|
||||
recv_data >> plguid; // player guid
|
||||
sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", petitiontype, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
|
||||
sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
|
||||
|
||||
player = ObjectAccessor::FindPlayer(plguid);
|
||||
if(!player || player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
|
||||
{
|
||||
if(type != 9)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
else
|
||||
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if(type != 9)
|
||||
{
|
||||
if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
// player is too low level to join an arena team
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 slot = ArenaTeam::GetSlotByType(type);
|
||||
if(slot >= MAX_ARENA_SLOT)
|
||||
return;
|
||||
|
||||
// not let offer to enemies
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
|
||||
if(player->GetArenaTeamId(slot))
|
||||
{
|
||||
// player is already in an arena team
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(player->GetGuildId())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetGuildIdInvited())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
if(!result)
|
||||
|
|
@ -811,7 +872,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
|
|||
else // or arena team
|
||||
{
|
||||
ArenaTeam* at = new ArenaTeam;
|
||||
if(!at->create(_player->GetGUID(), type, name))
|
||||
if(!at->Create(_player->GetGUID(), type, name))
|
||||
{
|
||||
sLog.outError("PetitionsHandler: arena team create failed.");
|
||||
delete at;
|
||||
|
|
|
|||
|
|
@ -346,8 +346,8 @@ Player::Player (WorldSession *session): Unit()
|
|||
m_bgBattleGroundID = 0;
|
||||
for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++)
|
||||
{
|
||||
m_bgBattleGroundQueueID[j].bgType = 0;
|
||||
m_bgBattleGroundQueueID[j].invited = false;
|
||||
m_bgBattleGroundQueueID[j].bgQueueType = 0;
|
||||
m_bgBattleGroundQueueID[j].invitedToInstance = 0;
|
||||
}
|
||||
m_bgTeam = 0;
|
||||
|
||||
|
|
@ -1499,7 +1499,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||
MapEntry const* mEntry = sMapStore.LookupEntry(mapid);
|
||||
|
||||
// don't let enter battlegrounds without assigned battleground id (for example through areatrigger)...
|
||||
if(!InBattleGround() && mEntry->IsBattleGround() && !GetSession()->GetSecurity())
|
||||
// don't let gm level > 1 either
|
||||
if(!InBattleGround() && mEntry->IsBattleGroundOrArena())
|
||||
return false;
|
||||
|
||||
// client without expansion support
|
||||
|
|
@ -3489,6 +3490,29 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
|||
guild->DelMember(guid);
|
||||
}
|
||||
|
||||
// remove from arena teams
|
||||
uint32 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_2v2);
|
||||
if(at_id != 0)
|
||||
{
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
|
||||
if(at)
|
||||
at->DelMember(playerguid);
|
||||
}
|
||||
at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_3v3);
|
||||
if(at_id != 0)
|
||||
{
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
|
||||
if(at)
|
||||
at->DelMember(playerguid);
|
||||
}
|
||||
at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_5v5);
|
||||
if(at_id != 0)
|
||||
{
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
|
||||
if(at)
|
||||
at->DelMember(playerguid);
|
||||
}
|
||||
|
||||
// the player was uninvited already on logout so just remove from group
|
||||
QueryResult *resultGroup = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", guid);
|
||||
if(resultGroup)
|
||||
|
|
@ -7737,19 +7761,34 @@ void Player::SendInitWorldStates()
|
|||
data << uint32(0xa5f) << uint32(0x0); // 35
|
||||
break;
|
||||
case 3698: // Nagrand Arena
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_NA)
|
||||
bg->FillInitialWorldStates(data);
|
||||
else
|
||||
{
|
||||
data << uint32(0xa0f) << uint32(0x0); // 7
|
||||
data << uint32(0xa10) << uint32(0x0); // 8
|
||||
data << uint32(0xa11) << uint32(0x0); // 9
|
||||
data << uint32(0xa11) << uint32(0x0); // 9 show
|
||||
}
|
||||
break;
|
||||
case 3702: // Blade's Edge Arena
|
||||
data << uint32(0x9f0) << uint32(0x0); // 7
|
||||
data << uint32(0x9f1) << uint32(0x0); // 8
|
||||
data << uint32(0x9f3) << uint32(0x0); // 9
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_BE)
|
||||
bg->FillInitialWorldStates(data);
|
||||
else
|
||||
{
|
||||
data << uint32(0x9f0) << uint32(0x0); // 7 gold
|
||||
data << uint32(0x9f1) << uint32(0x0); // 8 green
|
||||
data << uint32(0x9f3) << uint32(0x0); // 9 show
|
||||
}
|
||||
break;
|
||||
case 3968: // Ruins of Lordaeron
|
||||
data << uint32(0xbb8) << uint32(0x0); // 7
|
||||
data << uint32(0xbb9) << uint32(0x0); // 8
|
||||
data << uint32(0xbba) << uint32(0x0); // 9
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_RL)
|
||||
bg->FillInitialWorldStates(data);
|
||||
else
|
||||
{
|
||||
data << uint32(0xbb8) << uint32(0x0); // 7 gold
|
||||
data << uint32(0xbb9) << uint32(0x0); // 8 green
|
||||
data << uint32(0xbba) << uint32(0x0); // 9 show
|
||||
}
|
||||
break;
|
||||
case 3703: // Shattrath City
|
||||
break;
|
||||
|
|
@ -13334,6 +13373,36 @@ void Player::_LoadDeclinedNames(QueryResult* result)
|
|||
delete result;
|
||||
}
|
||||
|
||||
void Player::_LoadArenaTeamInfo(QueryResult *result)
|
||||
{
|
||||
// arenateamid, played_week, played_season, personal_rating
|
||||
memset((void*)&m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1], 0, sizeof(uint32)*18);
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
uint32 arenateamid = fields[0].GetUInt32();
|
||||
uint32 played_week = fields[1].GetUInt32();
|
||||
uint32 played_season = fields[2].GetUInt32();
|
||||
uint32 personal_rating = fields[3].GetUInt32();
|
||||
|
||||
ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid);
|
||||
uint8 arenaSlot = aTeam->GetSlot();
|
||||
|
||||
m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3] = arenateamid; // TeamID
|
||||
m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 1] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1
|
||||
m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 2] = played_week; // Played Week
|
||||
m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 3] = played_season; // Played Season
|
||||
m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 4] = 0; // Unk
|
||||
m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 5] = personal_rating; // Personal Rating
|
||||
|
||||
}while (result->NextRow());
|
||||
delete result;
|
||||
}
|
||||
|
||||
bool Player::LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid)
|
||||
{
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,taxi_path FROM characters WHERE guid = '%u'",GUID_LOPART(guid));
|
||||
|
|
@ -13405,8 +13474,8 @@ float Player::GetFloatValueFromDB(uint16 index, uint64 guid)
|
|||
|
||||
bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
||||
{
|
||||
//// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32
|
||||
//QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", guid);
|
||||
//// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32 33
|
||||
//QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", guid);
|
||||
QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM);
|
||||
|
||||
if(!result)
|
||||
|
|
@ -13496,6 +13565,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
|||
|
||||
_LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP));
|
||||
|
||||
_LoadArenaTeamInfo(holder->GetResult(PLAYER_LOGIN_QUERY_LOADARENAINFO));
|
||||
|
||||
uint32 arena_currency = GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY) + fields[33].GetUInt32();
|
||||
if (arena_currency > sWorld.getConfig(CONFIG_MAX_ARENA_POINTS))
|
||||
arena_currency = sWorld.getConfig(CONFIG_MAX_ARENA_POINTS);
|
||||
|
||||
SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, arena_currency);
|
||||
|
||||
// check arena teams integrity
|
||||
for(uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
|
||||
{
|
||||
|
|
@ -14818,8 +14895,10 @@ void Player::SaveToDB()
|
|||
// first save/honor gain after midnight will also update the player's honor fields
|
||||
UpdateHonorFields();
|
||||
|
||||
// Must saved before enter into BattleGround
|
||||
if(InBattleGround())
|
||||
// players aren't saved on battleground maps
|
||||
uint32 mapid = IsBeingTeleported() ? GetTeleportDest().mapid : GetMapId();
|
||||
const MapEntry * me = sMapStore.LookupEntry(mapid);
|
||||
if(!me || me->IsBattleGroundOrArena())
|
||||
return;
|
||||
|
||||
int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0;
|
||||
|
|
@ -14857,7 +14936,7 @@ void Player::SaveToDB()
|
|||
"taximask, online, cinematic, "
|
||||
"totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, "
|
||||
"trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, "
|
||||
"death_expire_time, taxi_path) VALUES ("
|
||||
"death_expire_time, taxi_path, arena_pending_points) VALUES ("
|
||||
<< GetGUIDLow() << ", "
|
||||
<< GetSession()->GetAccountId() << ", '"
|
||||
<< sql_name << "', "
|
||||
|
|
@ -14956,7 +15035,7 @@ void Player::SaveToDB()
|
|||
|
||||
ss << ", '";
|
||||
ss << m_taxi.SaveTaxiDestinationsToString();
|
||||
ss << "' )";
|
||||
ss << "', '0' )";
|
||||
|
||||
CharacterDatabase.Execute( ss.str().c_str() );
|
||||
|
||||
|
|
@ -17619,7 +17698,8 @@ bool Player::InArena() const
|
|||
|
||||
bool Player::GetBGAccessByLevel(uint32 bgTypeId) const
|
||||
{
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
|
||||
// get a template bg instead of running one
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
if(!bg)
|
||||
return false;
|
||||
|
||||
|
|
@ -17657,6 +17737,11 @@ uint32 Player::GetBattleGroundQueueIdFromLevel() const
|
|||
return 6;
|
||||
else
|
||||
return level/10 - 1; // 20..29 -> 1, 30-39 -> 2, ...
|
||||
/*
|
||||
assert(bgTypeId < MAX_BATTLEGROUND_TYPES);
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
assert(bg);
|
||||
return (getLevel() - bg->GetMinLevel()) / 10;*/
|
||||
}
|
||||
|
||||
float Player::GetReputationPriceDiscount( Creature const* pCreature ) const
|
||||
|
|
|
|||
|
|
@ -809,9 +809,10 @@ enum PlayerLoginQueryIndex
|
|||
PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15,
|
||||
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
|
||||
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
|
||||
};
|
||||
PLAYER_LOGIN_QUERY_LOADARENAINFO = 18,
|
||||
|
||||
#define MAX_PLAYER_LOGIN_QUERY 18
|
||||
MAX_PLAYER_LOGIN_QUERY
|
||||
};
|
||||
|
||||
// Player summoning auto-decline time (in secs)
|
||||
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
|
||||
|
|
@ -1517,7 +1518,6 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot)
|
||||
{
|
||||
SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId);
|
||||
SaveDataFieldToDB(); // needed?
|
||||
}
|
||||
uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); }
|
||||
static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot);
|
||||
|
|
@ -1804,24 +1804,32 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id);
|
||||
uint32 GetBattleGroundQueueIdFromLevel() const;
|
||||
|
||||
uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; }
|
||||
uint32 GetBattleGroundQueueIndex(uint32 bgType) const
|
||||
bool InBattleGroundQueue() const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgType == bgType)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueType; }
|
||||
uint32 GetBattleGroundQueueIndex(uint32 bgQueueType) const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType)
|
||||
return i;
|
||||
return PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
bool IsInvitedForBattleGroundType(uint32 bgType) const
|
||||
bool IsInvitedForBattleGroundQueueType(uint32 bgQueueType) const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgType == bgType)
|
||||
return m_bgBattleGroundQueueID[i].invited;
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType)
|
||||
return m_bgBattleGroundQueueID[i].invitedToInstance != 0;
|
||||
return PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
bool InBattleGroundQueueForBattleGroundType(uint32 bgType) const
|
||||
bool InBattleGroundQueueForBattleGroundQueueType(uint32 bgQueueType) const
|
||||
{
|
||||
return GetBattleGroundQueueIndex(bgType) < PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
return GetBattleGroundQueueIndex(bgQueueType) < PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
|
||||
void SetBattleGroundId(uint32 val) { m_bgBattleGroundID = val; }
|
||||
|
|
@ -1829,34 +1837,47 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
if (m_bgBattleGroundQueueID[i].bgType == 0 || m_bgBattleGroundQueueID[i].bgType == val)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == 0 || m_bgBattleGroundQueueID[i].bgQueueType == val)
|
||||
{
|
||||
m_bgBattleGroundQueueID[i].bgType = val;
|
||||
m_bgBattleGroundQueueID[i].invited = false;
|
||||
m_bgBattleGroundQueueID[i].bgQueueType = val;
|
||||
m_bgBattleGroundQueueID[i].invitedToInstance = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
bool HasFreeBattleGroundQueueId()
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void RemoveBattleGroundQueueId(uint32 val)
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
if (m_bgBattleGroundQueueID[i].bgType == val)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == val)
|
||||
{
|
||||
m_bgBattleGroundQueueID[i].bgType = 0;
|
||||
m_bgBattleGroundQueueID[i].invited = false;
|
||||
m_bgBattleGroundQueueID[i].bgQueueType = 0;
|
||||
m_bgBattleGroundQueueID[i].invitedToInstance = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetInviteForBattleGroundType(uint32 bgType)
|
||||
void SetInviteForBattleGroundQueueType(uint32 bgQueueType, uint32 instanceId)
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgType == bgType)
|
||||
m_bgBattleGroundQueueID[i].invited = true;
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType)
|
||||
m_bgBattleGroundQueueID[i].invitedToInstance = instanceId;
|
||||
}
|
||||
bool IsInvitedForBattleGroundInstance(uint32 instanceId) const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; }
|
||||
float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; }
|
||||
float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; }
|
||||
|
|
@ -2053,8 +2074,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
*/
|
||||
struct BgBattleGroundQueueID_Rec
|
||||
{
|
||||
uint32 bgType;
|
||||
bool invited;
|
||||
uint32 bgQueueType;
|
||||
uint32 invitedToInstance;
|
||||
};
|
||||
BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES];
|
||||
uint32 m_bgEntryPointMap;
|
||||
|
|
@ -2099,6 +2120,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void _LoadFriendList(QueryResult *result);
|
||||
bool _LoadHomeBind(QueryResult *result);
|
||||
void _LoadDeclinedNames(QueryResult *result);
|
||||
void _LoadArenaTeamInfo(QueryResult *result);
|
||||
|
||||
/*********************************************************/
|
||||
/*** SAVE SYSTEM ***/
|
||||
|
|
|
|||
|
|
@ -2147,6 +2147,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
return;
|
||||
|
||||
// final heal
|
||||
if(m_target->IsInWorld())
|
||||
m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
|
||||
}
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2649,7 +2649,7 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype)
|
|||
return;
|
||||
}
|
||||
|
||||
if(BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgType))
|
||||
if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
|
||||
bg->SendRewardMarkByMail(player,newitemid,no_space);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -605,25 +605,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
((Creature*)pVictim)->SetLootRecipient(this);
|
||||
if (health <= damage)
|
||||
{
|
||||
// battleground things
|
||||
if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround()))
|
||||
{
|
||||
Player *killed = ((Player*)pVictim);
|
||||
Player *killer = NULL;
|
||||
if(GetTypeId() == TYPEID_PLAYER)
|
||||
killer = ((Player*)this);
|
||||
else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
|
||||
{
|
||||
Unit *owner = GetOwner();
|
||||
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
|
||||
killer = ((Player*)owner);
|
||||
}
|
||||
|
||||
if(killer)
|
||||
if(BattleGround *bg = killed->GetBattleGround())
|
||||
bg->HandleKillPlayer(killed, killer); // drop flags and etc
|
||||
}
|
||||
|
||||
DEBUG_LOG("DealDamage: victim just died");
|
||||
|
||||
// find player: owner of controlled `this` or `this` itself maybe
|
||||
|
|
@ -762,6 +743,19 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
|
||||
he->DuelComplete(DUEL_INTERUPTED);
|
||||
}
|
||||
|
||||
// battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill)
|
||||
if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->InBattleGround())
|
||||
{
|
||||
Player *killed = ((Player*)pVictim);
|
||||
if(BattleGround *bg = killed->GetBattleGround())
|
||||
if(player)
|
||||
bg->HandleKillPlayer(killed, player);
|
||||
//later we can add support for creature->player kills here i'm
|
||||
//not sure, but i guess those kills also get counted in av
|
||||
//else if(GetTypeId() == TYPEID_UNIT)
|
||||
// bg->HandleKillPlayer(killed,(Creature*)this);
|
||||
}
|
||||
}
|
||||
else // if (health <= damage)
|
||||
{
|
||||
|
|
@ -4173,6 +4167,22 @@ void Unit::RemoveAllAuras()
|
|||
}
|
||||
}
|
||||
|
||||
void Unit::RemoveArenaAuras(bool onleave)
|
||||
{
|
||||
// in join, remove positive buffs, on end, remove negative
|
||||
// used to remove positive visible auras in arenas
|
||||
for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
|
||||
{
|
||||
if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras
|
||||
&& !iter->second->IsPassive() // don't remove passive auras
|
||||
&& (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable)
|
||||
&& (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave
|
||||
RemoveAura(iter);
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::RemoveAllAurasOnDeath()
|
||||
{
|
||||
// used just after dieing to remove all visible auras
|
||||
|
|
|
|||
|
|
@ -1012,6 +1012,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
void RemoveAurasWithDispelType( DispelType type );
|
||||
|
||||
void RemoveAllAuras();
|
||||
void RemoveArenaAuras(bool onleave = false);
|
||||
void RemoveAllAurasOnDeath();
|
||||
void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime);
|
||||
|
||||
|
|
|
|||
|
|
@ -891,6 +891,12 @@ void World::LoadConfigSettings(bool reload)
|
|||
m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25);
|
||||
m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300);
|
||||
|
||||
m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0);
|
||||
m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000);
|
||||
m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false);
|
||||
m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7);
|
||||
|
||||
m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0);
|
||||
m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR);
|
||||
|
||||
m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
|
||||
|
|
@ -1292,6 +1298,7 @@ void World::SetInitialWorldSettings()
|
|||
///- Initialize Battlegrounds
|
||||
sLog.outString( "Starting BattleGround System" );
|
||||
sBattleGroundMgr.CreateInitialBattleGrounds();
|
||||
sBattleGroundMgr.InitAutomaticArenaPointDistribution();
|
||||
|
||||
//Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager
|
||||
sLog.outString( "Loading Transports..." );
|
||||
|
|
@ -2169,7 +2176,7 @@ void World::ScriptsProcess()
|
|||
void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team)
|
||||
{
|
||||
SessionMap::iterator itr;
|
||||
for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++)
|
||||
for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
|
||||
{
|
||||
if (itr->second &&
|
||||
itr->second->GetPlayer() &&
|
||||
|
|
@ -2236,11 +2243,29 @@ void World::SendWorldText(int32 string_id, ...)
|
|||
delete data_cache[i][j];
|
||||
}
|
||||
|
||||
/// Send a System Message to all players (except self if mentioned)
|
||||
void World::SendGlobalText(const char* text, WorldSession *self)
|
||||
{
|
||||
WorldPacket data;
|
||||
|
||||
// need copy to prevent corruption by strtok call in LineFromMessage original string
|
||||
char* buf = strdup(text);
|
||||
char* pos = buf;
|
||||
|
||||
while(char* line = ChatHandler::LineFromMessage(pos))
|
||||
{
|
||||
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
|
||||
SendGlobalMessage(&data, self);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/// Send a packet to all players (or players selected team) in the zone (except self if mentioned)
|
||||
void World::SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self, uint32 team)
|
||||
{
|
||||
SessionMap::iterator itr;
|
||||
for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++)
|
||||
for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
|
||||
{
|
||||
if (itr->second &&
|
||||
itr->second->GetPlayer() &&
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ enum WorldConfigs
|
|||
CONFIG_LISTEN_RANGE_SAY,
|
||||
CONFIG_LISTEN_RANGE_TEXTEMOTE,
|
||||
CONFIG_LISTEN_RANGE_YELL,
|
||||
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
|
||||
CONFIG_ARENA_RATING_DISCARD_TIMER,
|
||||
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
|
||||
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
|
||||
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
|
||||
CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
|
|
@ -396,6 +401,7 @@ class World
|
|||
void LoadConfigSettings(bool reload = false);
|
||||
|
||||
void SendWorldText(int32 string_id, ...);
|
||||
void SendGlobalText(const char* text, WorldSession *self);
|
||||
void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
|
||||
void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
|
||||
void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0);
|
||||
|
|
|
|||
|
|
@ -177,11 +177,12 @@ class MANGOS_DLL_SPEC WorldSession
|
|||
|
||||
// Guild/Arena Team
|
||||
void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult);
|
||||
void SendArenaTeamCommandResult(uint32 unk1, const std::string& str1, const std::string& str2, uint32 unk3);
|
||||
void SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id);
|
||||
void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3);
|
||||
void SendNotInArenaTeamPacket(uint8 type);
|
||||
void SendPetitionShowList( uint64 guid );
|
||||
void SendSaveGuildEmblem( uint32 msg );
|
||||
void SendBattleGroundOrArenaJoinError(uint8 err);
|
||||
|
||||
// Looking For Group
|
||||
// TRUE values set by client sending CMSG_LFG_SET_AUTOJOIN and CMSG_LFM_CLEAR_AUTOFILL before player login
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "GossipDef.h"
|
||||
#include "Language.h"
|
||||
#include "MapManager.h"
|
||||
#include "BattleGroundMgr.h"
|
||||
#include <fstream>
|
||||
#include "ObjectMgr.h"
|
||||
|
||||
|
|
@ -518,3 +519,9 @@ bool ChatHandler::HandleGetItemState(const char* args)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/)
|
||||
{
|
||||
sBattleGroundMgr.ToggleArenaTesting();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1074,6 +1074,48 @@ Death.SicknessLevel = 11
|
|||
Death.CorpseReclaimDelay.PvP = 1
|
||||
Death.CorpseReclaimDelay.PvE = 1
|
||||
|
||||
###################################################################################################################
|
||||
#
|
||||
# Rated arena matches config
|
||||
#
|
||||
# MaxRatingDifference: the maximum rating difference between two groups in rated matches
|
||||
# Default: 0 (disable, rating difference is discarded)
|
||||
#
|
||||
# RatingDiscardTimer: after the specified milliseconds has passed,
|
||||
# rating information will be discarded when selecting teams for matches
|
||||
# also initiates an update by this timer
|
||||
# Default: 60000
|
||||
#
|
||||
# AutoDistributePoints: set if arena points should be distributed automatically, or by GM command
|
||||
# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points
|
||||
# 1 (enable): arena points are distributed automatically
|
||||
#
|
||||
# AutoDistributeInterval: how often should the distribution take place
|
||||
# if automatic distribution is enabled
|
||||
# in days
|
||||
# Default: 7 (weekly)
|
||||
#
|
||||
###################################################################################################################
|
||||
|
||||
Arena.MaxRatingDifference = 0
|
||||
Arena.RatingDiscardTimer = 60000
|
||||
Arena.AutoDistributePoints = 0
|
||||
Arena.AutoDistributeInterval = 7
|
||||
|
||||
###################################################################################################################
|
||||
#
|
||||
# Battleground config
|
||||
#
|
||||
# PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side
|
||||
# in milliseconds
|
||||
# Default: 300000
|
||||
# 0 - disable
|
||||
#
|
||||
###################################################################################################################
|
||||
|
||||
BattleGround.PrematureFinishTimer = 300000
|
||||
|
||||
|
||||
###################################################################################################################
|
||||
#
|
||||
# NETWORK CONFIG
|
||||
|
|
|
|||
|
|
@ -434,9 +434,10 @@ struct MapEntry
|
|||
|
||||
// Helpers
|
||||
uint32 Expansion() const { return addon; }
|
||||
bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
|
||||
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
|
||||
|
||||
|
||||
bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
|
||||
bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID || map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
|
||||
bool IsRaid() const { return map_type == MAP_RAID; }
|
||||
bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }
|
||||
bool IsBattleArena() const { return map_type == MAP_ARENA; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "6909"
|
||||
#define REVISION_NR "6910"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue