mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 19:37:03 +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
|
|
@ -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)
|
||||
{
|
||||
winmsg = GetMangosString(LANG_BG_A_WINS);
|
||||
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)
|
||||
{
|
||||
winmsg = GetMangosString(LANG_BG_H_WINS);
|
||||
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(isArena())
|
||||
if(participant) // if the player was a match participant, remove auras, calc rating, update queue
|
||||
{
|
||||
if(!sWorld.IsFFAPvPRealm())
|
||||
plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
|
||||
}
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
WorldPacket data;
|
||||
if(SendPacket)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), 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);
|
||||
|
||||
DecreaseInvitedCount(plr->GetTeam());
|
||||
//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;
|
||||
|
||||
Group * group = plr->GetGroup();
|
||||
|
||||
// remove from raid group if exist
|
||||
if(group && group == GetBgRaid(plr->GetTeam()))
|
||||
{
|
||||
if(!group->RemoveMember(guid, 0)) // group was disbanded
|
||||
uint32 bgTypeId = GetTypeID();
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
|
||||
// if arena, remove the specific arena auras
|
||||
if(isArena())
|
||||
{
|
||||
SetBgRaid(plr->GetTeam(), NULL);
|
||||
delete group;
|
||||
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, 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(bgQueueTypeId);
|
||||
|
||||
DecreaseInvitedCount(team);
|
||||
//we should update battleground queue, but only if bg isn't ending
|
||||
if (GetQueueType() < MAX_BATTLEGROUND_QUEUES)
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType());
|
||||
|
||||
Group * group = plr->GetGroup();
|
||||
// remove from raid group if exist
|
||||
if(group && group == GetBgRaid(team))
|
||||
{
|
||||
if(!group->RemoveMember(guid, 0)) // group was disbanded
|
||||
{
|
||||
SetBgRaid(team, NULL);
|
||||
delete group;
|
||||
}
|
||||
}
|
||||
|
||||
// Let others know
|
||||
sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);
|
||||
SendPacketToTeam(team, &data, plr, false);
|
||||
}
|
||||
|
||||
// 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);
|
||||
// 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,9 +971,6 @@ 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());
|
||||
}
|
||||
|
|
@ -750,13 +978,20 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
/* This method should be called only once ... it adds pointer to queue */
|
||||
void BattleGround::AddToBGFreeSlotQueue()
|
||||
{
|
||||
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
|
||||
// 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
|
||||
// reward honor instantly
|
||||
if(Source->RewardHonor(NULL, 1, value))
|
||||
itr->second->BonusHonor += value;
|
||||
// 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue