Files
TCPlayerbotCore/src/server/game/Battlegrounds/BattlegroundMgr.cpp
T

1192 lines
46 KiB
C++
Raw Normal View History

2008-10-02 16:23:55 -05:00
/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2010-01-16 20:19:18 +03:00
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
2008-10-02 16:23:55 -05:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -05:00
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "Common.h"
2009-06-04 21:41:07 +02:00
#include "ObjectMgr.h"
#include "World.h"
2010-06-08 13:05:47 -06:00
#include "WorldPacket.h"
2009-10-17 15:51:44 -07:00
2009-06-04 21:41:07 +02:00
#include "ArenaTeam.h"
2010-08-08 04:37:24 +02:00
#include "BattlegroundMgr.h"
#include "BattlegroundAV.h"
#include "BattlegroundAB.h"
#include "BattlegroundEY.h"
#include "BattlegroundWS.h"
#include "BattlegroundNA.h"
#include "BattlegroundBE.h"
#include "BattlegroundAA.h"
#include "BattlegroundRL.h"
#include "BattlegroundSA.h"
#include "BattlegroundDS.h"
#include "BattlegroundRV.h"
#include "BattlegroundIC.h"
#include "BattlegroundRB.h"
2009-06-04 21:41:07 +02:00
#include "Chat.h"
2008-10-05 08:48:32 -05:00
#include "Map.h"
#include "MapInstanced.h"
2009-06-04 21:41:07 +02:00
#include "MapManager.h"
#include "Player.h"
#include "GameEventMgr.h"
2010-06-08 13:05:47 -06:00
#include "ProgressBar.h"
#include "SharedDefines.h"
#include "Formulas.h"
#include "DisableMgr.h"
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/*********************************************************/
/*** BATTLEGROUND MANAGER ***/
/*********************************************************/
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundMgr::BattlegroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false)
2008-10-02 16:23:55 -05:00
{
2009-10-17 16:20:24 -07:00
for (uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++)
2010-08-08 04:37:24 +02:00
m_Battlegrounds[i].clear();
m_NextRatingDiscardUpdate = sWorld.getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
m_Testing=false;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundMgr::~BattlegroundMgr()
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
DeleteAllBattlegrounds();
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::DeleteAllBattlegrounds()
{
2009-11-20 19:11:28 -08:00
for (uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; ++i)
2008-10-05 08:48:32 -05:00
{
2010-08-08 04:37:24 +02:00
for (BattlegroundSet::iterator itr = m_Battlegrounds[i].begin(); itr != m_Battlegrounds[i].end();)
{
2010-08-08 04:37:24 +02:00
Battleground * bg = itr->second;
m_Battlegrounds[i].erase(itr++);
if (!m_ClientBattlegroundIds[i][bg->GetBracketId()].empty())
m_ClientBattlegroundIds[i][bg->GetBracketId()].erase(bg->GetClientInstanceID());
delete bg;
}
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
// destroy template battlegrounds that listed only in queues (other already terminated)
2009-10-17 16:20:24 -07:00
for (uint32 bgTypeId = 0; bgTypeId < MAX_BATTLEGROUND_TYPE_ID; ++bgTypeId)
{
2010-08-08 04:37:24 +02:00
// ~Battleground call unregistring BG from queue
2010-04-07 19:13:19 +02:00
while (!BGFreeSlotQueue[bgTypeId].empty())
delete BGFreeSlotQueue[bgTypeId].front();
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// used to update running battlegrounds, and delete finished ones
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::Update(uint32 diff)
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundSet::iterator itr, next;
2009-11-20 19:11:28 -08:00
for (uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; ++i)
2008-10-05 08:48:32 -05:00
{
2010-08-08 04:37:24 +02:00
itr = m_Battlegrounds[i].begin();
// skip updating battleground template
2010-08-08 04:37:24 +02:00
if (itr != m_Battlegrounds[i].end())
++itr;
2010-08-08 04:37:24 +02:00
for (; itr != m_Battlegrounds[i].end(); itr = next)
2008-10-05 08:48:32 -05:00
{
next = itr;
++next;
itr->second->Update(diff);
// use the SetDeleteThis variable
// direct deletion caused crashes
if (itr->second->m_SetDeleteThis)
{
2010-08-08 04:37:24 +02:00
Battleground * bg = itr->second;
m_Battlegrounds[i].erase(itr);
if (!m_ClientBattlegroundIds[i][bg->GetBracketId()].empty())
m_ClientBattlegroundIds[i][bg->GetBracketId()].erase(bg->GetClientInstanceID());
delete bg;
}
2008-10-05 08:48:32 -05:00
}
}
2009-10-17 15:51:44 -07:00
// update scheduled queues
if (!m_QueueUpdateScheduler.empty())
{
std::vector<uint64> scheduled;
{
//copy vector and clear the other
scheduled = std::vector<uint64>(m_QueueUpdateScheduler);
m_QueueUpdateScheduler.clear();
//release lock
}
for (uint8 i = 0; i < scheduled.size(); i++)
{
uint32 arenaRating = scheduled[i] >> 32;
uint8 arenaType = scheduled[i] >> 24 & 255;
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId(scheduled[i] >> 16 & 255);
BattlegroundTypeId bgTypeId = BattlegroundTypeId((scheduled[i] >> 8) & 255);
BattlegroundBracketId bracket_id = BattlegroundBracketId(scheduled[i] & 255);
m_BattlegroundQueues[bgQueueTypeId].Update(bgTypeId, bracket_id, arenaType, arenaRating > 0, arenaRating);
}
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// if rating difference counts, maybe force-update queues
if (sWorld.getIntConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER))
2008-10-05 08:48:32 -05:00
{
// it's time to force update
if (m_NextRatingDiscardUpdate < diff)
2008-10-05 08:48:32 -05:00
{
// forced update for rated arenas (scan all, but skipped non rated)
2010-08-08 04:37:24 +02:00
sLog.outDebug("BattlegroundMgr: UPDATING ARENA QUEUES");
2010-04-07 19:12:44 +02:00
for (int qtype = BATTLEGROUND_QUEUE_2v2; qtype <= BATTLEGROUND_QUEUE_5v5; ++qtype)
for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket)
2010-08-08 04:37:24 +02:00
m_BattlegroundQueues[qtype].Update(
BATTLEGROUND_AA, BattlegroundBracketId(bracket),
BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId(qtype)), true, 0);
m_NextRatingDiscardUpdate = sWorld.getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
}
else
2008-10-05 08:48:32 -05:00
m_NextRatingDiscardUpdate -= diff;
}
if (sWorld.getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
2008-10-05 08:48:32 -05:00
{
if (m_AutoDistributionTimeChecker < diff)
2008-10-05 08:48:32 -05:00
{
2010-04-07 19:14:10 +02:00
if (time(NULL) > m_NextAutoDistributionTime)
2008-10-05 08:48:32 -05:00
{
DistributeArenaPoints();
m_NextAutoDistributionTime = m_NextAutoDistributionTime + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getIntConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS);
2010-03-26 16:48:33 +01:00
sWorld.setWorldState(WS_ARENA_DISTRIBUTION_TIME, uint64(m_NextAutoDistributionTime));
2008-10-05 08:48:32 -05:00
}
m_AutoDistributionTimeChecker = 600000; // check 10 minutes
}
else
m_AutoDistributionTimeChecker -= diff;
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket *data, Battleground *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype, uint8 uiFrame)
2008-10-02 16:23:55 -05:00
{
2010-02-14 19:13:14 -07:00
// we can be in 2 queues in same time...
2009-10-17 15:51:44 -07:00
if (StatusID == 0 || !bg)
2008-10-02 16:23:55 -05:00
{
2010-02-14 19:13:14 -07:00
data->Initialize(SMSG_BATTLEFIELD_STATUS, 4+8);
*data << uint32(QueueSlot); // queue id (0...1)
2008-10-02 16:23:55 -05:00
*data << uint64(0);
return;
}
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+8+1+1+4+1+4+4+4));
*data << uint32(QueueSlot); // queue id (0...1) - player can be in 2 queues in time
// The following segment is read as uint64 in client but can be appended as their original type.
*data << uint8(arenatype);
2010-08-08 04:37:24 +02:00
sLog.outDebug("BattlegroundMgr::BuildBattlegroundStatusPacket: arenatype = %u for bg instanceID %u, TypeID %u.", arenatype, bg->GetClientInstanceID(), bg->GetTypeID());
*data << uint8(bg->isArena() ? 0xC : 0x2);
*data << uint32(bg->GetTypeID());
*data << uint16(0x1F90);
// End of uint64 segment, decomposed this way for simplicity
*data << uint8(0); // 3.3.0, some level, only saw 80...
*data << uint8(0); // 3.3.0, some level, only saw 80...
*data << uint32(bg->GetClientInstanceID());
2008-10-02 16:23:55 -05:00
// alliance/horde for BG and skirmish/rated for Arenas
// following displays the minimap-icon 0 = faction icon 1 = arenaicon
*data << uint8(bg->isRated()); // 1 for rated match, 0 for bg or non rated match
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
*data << uint32(StatusID); // status
switch(StatusID)
{
case STATUS_WAIT_QUEUE: // status_in_queue
*data << uint32(Time1); // average wait time, milliseconds
*data << uint32(Time2); // time in queue, updated every minute!, milliseconds
2008-10-02 16:23:55 -05:00
break;
case STATUS_WAIT_JOIN: // status_invite
*data << uint32(bg->GetMapId()); // map id
*data << uint64(0); // 3.3.5, unknown
2008-10-02 16:23:55 -05:00
*data << uint32(Time1); // time to remove from queue, milliseconds
break;
case STATUS_IN_PROGRESS: // status_in_progress
*data << uint32(bg->GetMapId()); // map id
*data << uint64(0); // 3.3.5, unknown
*data << uint32(Time1); // time to bg auto leave, 0 at bg start, 120000 after bg end, milliseconds
2008-10-02 16:23:55 -05:00
*data << uint32(Time2); // time from bg start, milliseconds
*data << uint8(uiFrame);
2008-10-02 16:23:55 -05:00
break;
default:
sLog.outError("Unknown BG status!");
break;
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket *data, Battleground *bg)
2008-10-02 16:23:55 -05:00
{
uint8 type = (bg->isArena() ? 1 : 0);
// last check on 3.0.3
data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));
*data << uint8(type); // type (battleground=0/arena=1)
2010-04-07 19:14:10 +02:00
if (type) // arena
2008-10-02 16:23:55 -05:00
{
// it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H
for (int i = 1; i >= 0; --i)
2008-10-05 08:48:32 -05:00
{
uint32 pointsLost = bg->m_ArenaTeamRatingChanges[i] < 0 ? abs(bg->m_ArenaTeamRatingChanges[i]) : 0;
uint32 pointsGained = bg->m_ArenaTeamRatingChanges[i] > 0 ? bg->m_ArenaTeamRatingChanges[i] : 0;
*data << uint32(pointsLost); // Rating Lost
*data << uint32(pointsGained); // Rating gained
*data << uint32(0); // Matchmaking Value
sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]);
2008-10-05 08:48:32 -05:00
}
for (int i = 1; i >= 0; --i)
2008-10-02 16:23:55 -05:00
{
uint32 at_id = bg->m_ArenaTeamIds[i];
2010-08-08 05:25:45 +02:00
ArenaTeam * at = sObjectMgr.GetArenaTeamById(at_id);
if (at)
*data << at->GetName();
else
*data << (uint8)0;
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
if (bg->GetStatus() != STATUS_WAIT_LEAVE)
2008-10-02 16:23:55 -05:00
{
*data << uint8(0); // bg not ended
2008-10-02 16:23:55 -05:00
}
else
{
*data << uint8(1); // bg ended
*data << uint8(bg->GetWinner()); // who win
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
*data << (int32)(bg->GetPlayerScoresSize());
2010-08-08 04:37:24 +02:00
for (Battleground::BattlegroundScoreMap::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr)
2008-10-02 16:23:55 -05:00
{
*data << (uint64)itr->first;
*data << (int32)itr->second->KillingBlows;
if (type == 0)
2008-10-05 08:48:32 -05:00
{
*data << (int32)itr->second->HonorableKills;
*data << (int32)itr->second->Deaths;
*data << (int32)(itr->second->BonusHonor);
2008-10-05 08:48:32 -05:00
}
else
2008-10-02 16:23:55 -05:00
{
2010-08-08 05:25:45 +02:00
Player *plr = sObjectMgr.GetPlayer(itr->first);
uint32 team = bg->GetPlayerTeam(itr->first);
if (!team && plr)
2010-01-27 13:40:01 +01:00
team = plr->GetBGTeam();
*data << uint8(team == ALLIANCE ? 1 : 0); // green or yellow
2008-10-02 16:23:55 -05:00
}
*data << (int32)itr->second->DamageDone; // damage done
*data << (int32)itr->second->HealingDone; // healing done
switch(bg->GetTypeID(true)) // battleground specific things
2008-10-02 16:23:55 -05:00
{
case BATTLEGROUND_RB:
switch(bg->GetMapId())
{
case 489:
*data << (uint32)0x00000002; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundWGScore*)itr->second)->FlagCaptures; // flag captures
*data << (uint32)((BattlegroundWGScore*)itr->second)->FlagReturns; // flag returns
break;
case 566:
*data << (uint32)0x00000001; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundEYScore*)itr->second)->FlagCaptures; // flag captures
break;
case 529:
*data << (uint32)0x00000002; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundABScore*)itr->second)->BasesAssaulted; // bases asssulted
*data << (uint32)((BattlegroundABScore*)itr->second)->BasesDefended; // bases defended
break;
case 30:
*data << (uint32)0x00000005; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted; // GraveyardsAssaulted
*data << (uint32)((BattlegroundAVScore*)itr->second)->GraveyardsDefended; // GraveyardsDefended
*data << (uint32)((BattlegroundAVScore*)itr->second)->TowersAssaulted; // TowersAssaulted
*data << (uint32)((BattlegroundAVScore*)itr->second)->TowersDefended; // TowersDefended
*data << (uint32)((BattlegroundAVScore*)itr->second)->MinesCaptured; // MinesCaptured
break;
case 607:
*data << uint32(2);
2010-08-08 04:37:24 +02:00
*data << uint32(((BattlegroundSAScore*)itr->second)->demolishers_destroyed);
*data << uint32(((BattlegroundSAScore*)itr->second)->gates_destroyed);
break;
default:
*data << (int32)0; // 0
break;
}
2008-10-02 16:23:55 -05:00
case BATTLEGROUND_AV:
*data << (uint32)0x00000005; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted; // GraveyardsAssaulted
*data << (uint32)((BattlegroundAVScore*)itr->second)->GraveyardsDefended; // GraveyardsDefended
*data << (uint32)((BattlegroundAVScore*)itr->second)->TowersAssaulted; // TowersAssaulted
*data << (uint32)((BattlegroundAVScore*)itr->second)->TowersDefended; // TowersDefended
*data << (uint32)((BattlegroundAVScore*)itr->second)->MinesCaptured; // MinesCaptured
2008-10-02 16:23:55 -05:00
break;
case BATTLEGROUND_WS:
*data << (uint32)0x00000002; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundWGScore*)itr->second)->FlagCaptures; // flag captures
*data << (uint32)((BattlegroundWGScore*)itr->second)->FlagReturns; // flag returns
2008-10-02 16:23:55 -05:00
break;
case BATTLEGROUND_AB:
*data << (uint32)0x00000002; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundABScore*)itr->second)->BasesAssaulted; // bases asssulted
*data << (uint32)((BattlegroundABScore*)itr->second)->BasesDefended; // bases defended
2008-10-02 16:23:55 -05:00
break;
case BATTLEGROUND_EY:
*data << (uint32)0x00000001; // count of next fields
2010-08-08 04:37:24 +02:00
*data << (uint32)((BattlegroundEYScore*)itr->second)->FlagCaptures; // flag captures
2008-10-02 16:23:55 -05:00
break;
case BATTLEGROUND_NA:
case BATTLEGROUND_BE:
case BATTLEGROUND_AA:
case BATTLEGROUND_RL:
2010-02-14 19:13:14 -07:00
case BATTLEGROUND_SA:
*data << uint32(2);
2010-08-08 04:37:24 +02:00
*data << uint32(((BattlegroundSAScore*)itr->second)->demolishers_destroyed);
*data << uint32(((BattlegroundSAScore*)itr->second)->gates_destroyed);
break;
case BATTLEGROUND_DS: // wotlk
case BATTLEGROUND_RV: // wotlk
2009-12-17 10:43:12 +01:00
case BATTLEGROUND_IC: // wotlk
*data << (int32)0; // 0
2008-10-02 16:23:55 -05:00
break;
default:
sLog.outDebug("Unhandled MSG_PVP_LOG_DATA for BG id %u", bg->GetTypeID());
*data << (int32)0;
2008-10-02 16:23:55 -05:00
break;
}
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket *data, GroupJoinBattlegroundResult result)
2008-10-02 16:23:55 -05:00
{
data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
*data << int32(result);
if (result == ERR_BATTLEGROUND_JOIN_TIMED_OUT || result == ERR_BATTLEGROUND_JOIN_FAILED)
*data << uint64(0); // player guid
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value)
2008-10-02 16:23:55 -05:00
{
data->Initialize(SMSG_UPDATE_WORLD_STATE, 4+4);
*data << uint32(field);
*data << uint32(value);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid)
2008-10-02 16:23:55 -05:00
{
data->Initialize(SMSG_PLAY_SOUND, 4);
*data << uint32(soundid);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildPlayerLeftBattlegroundPacket(WorldPacket *data, const uint64& guid)
2008-10-02 16:23:55 -05:00
{
data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8);
*data << uint64(guid);
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildPlayerJoinedBattlegroundPacket(WorldPacket *data, Player *plr)
2008-10-02 16:23:55 -05:00
{
data->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED, 8);
*data << uint64(plr->GetGUID());
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground * BattlegroundMgr::GetBattlegroundThroughClientInstance(uint32 instanceId, BattlegroundTypeId bgTypeId)
{
2010-08-08 04:37:24 +02:00
//cause at HandleBattlegroundJoinOpcode the clients sends the instanceid he gets from
//SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id
2010-08-08 04:37:24 +02:00
Battleground* bg = GetBattlegroundTemplate(bgTypeId);
if (!bg)
return NULL;
2009-10-17 15:51:44 -07:00
if (bg->isArena())
2010-08-08 04:37:24 +02:00
return GetBattleground(instanceId, bgTypeId);
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for (BattlegroundSet::iterator itr = m_Battlegrounds[bgTypeId].begin(); itr != m_Battlegrounds[bgTypeId].end(); ++itr)
{
if (itr->second->GetClientInstanceID() == instanceId)
return itr->second;
}
return NULL;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground * BattlegroundMgr::GetBattleground(uint32 InstanceID, BattlegroundTypeId bgTypeId)
{
2009-08-01 00:20:32 +02:00
if (!InstanceID)
return NULL;
//search if needed
2010-08-08 04:37:24 +02:00
BattlegroundSet::iterator itr;
if (bgTypeId == BATTLEGROUND_TYPE_NONE)
{
2009-10-17 16:20:24 -07:00
for (uint32 i = BATTLEGROUND_AV; i < MAX_BATTLEGROUND_TYPE_ID; i++)
{
2010-08-08 04:37:24 +02:00
itr = m_Battlegrounds[i].find(InstanceID);
if (itr != m_Battlegrounds[i].end())
return itr->second;
}
return NULL;
}
2010-08-08 04:37:24 +02:00
itr = m_Battlegrounds[bgTypeId].find(InstanceID);
return ((itr != m_Battlegrounds[bgTypeId].end()) ? itr->second : NULL);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground * BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgTypeId)
2008-10-05 08:48:32 -05:00
{
//map is sorted and we can be sure that lowest instance id has only BG template
2010-08-08 04:37:24 +02:00
return m_Battlegrounds[bgTypeId].empty() ? NULL : m_Battlegrounds[bgTypeId].begin()->second;
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{
if (IsArenaType(bgTypeId))
return 0; //arenas don't have client-instanceids
2009-10-17 15:51:44 -07:00
// we create here an instanceid, which is just for
// displaying this to the client and without any other use..
// the client-instanceIds are unique for each battleground-type
// the instance-id just needs to be as low as possible, beginning with 1
// the following works, because std::set is default ordered with "<"
// the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable
uint32 lastId = 0;
2010-08-08 04:37:24 +02:00
for (std::set<uint32>::iterator itr = m_ClientBattlegroundIds[bgTypeId][bracket_id].begin(); itr != m_ClientBattlegroundIds[bgTypeId][bracket_id].end();)
{
2010-04-07 22:59:46 +02:00
if ((++lastId) != *itr) //if there is a gap between the ids, we will break..
break;
lastId = *itr;
}
2010-08-08 04:37:24 +02:00
m_ClientBattlegroundIds[bgTypeId][bracket_id].insert(lastId + 1);
return lastId + 1;
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// create a new battleground that will really be used to play
2010-08-08 04:37:24 +02:00
Battleground * BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated)
2008-10-05 08:48:32 -05:00
{
// get the template BG
2010-08-08 04:37:24 +02:00
Battleground *bg_template = GetBattlegroundTemplate(bgTypeId);
BattlegroundSelectionWeightMap *selectionWeights = NULL;
2010-05-31 20:53:43 +02:00
if (!bg_template)
2008-10-05 08:48:32 -05:00
{
2010-08-08 04:37:24 +02:00
sLog.outError("Battleground: CreateNewBattleground - bg template not found for %u", bgTypeId);
return NULL;
2008-10-05 08:48:32 -05:00
}
2010-05-31 20:53:43 +02:00
bool isRandom = false;
2009-10-17 15:51:44 -07:00
if (bg_template->isArena())
selectionWeights = &m_ArenaSelectionWeights;
2010-05-31 20:53:43 +02:00
else if (bgTypeId == BATTLEGROUND_RB)
{
selectionWeights = &m_BGSelectionWeights;
2010-05-31 20:53:43 +02:00
isRandom = true;
}
2009-10-17 15:51:44 -07:00
if (selectionWeights)
{
if (!selectionWeights->size())
2010-05-31 20:53:43 +02:00
return NULL;
uint32 Weight = 0;
uint32 selectedWeight = 0;
bgTypeId = BATTLEGROUND_TYPE_NONE;
// Get sum of all weights
2010-08-08 04:37:24 +02:00
for (BattlegroundSelectionWeightMap::const_iterator it = selectionWeights->begin(); it != selectionWeights->end(); ++it)
Weight += it->second;
if (!Weight)
return NULL;
// Select a random value
2010-08-03 14:39:18 -03:00
selectedWeight = urand(0, Weight-1);
// Select the correct bg (if we have in DB A(10), B(20), C(10), D(15) --> [0---A---9|10---B---29|30---C---39|40---D---54])
Weight = 0;
2010-08-08 04:37:24 +02:00
for (BattlegroundSelectionWeightMap::const_iterator it = selectionWeights->begin(); it != selectionWeights->end(); ++it)
{
Weight += it->second;
if (selectedWeight < Weight)
{
bgTypeId = it->first;
break;
}
}
2010-08-08 04:37:24 +02:00
bg_template = GetBattlegroundTemplate(bgTypeId);
if (!bg_template)
{
2010-08-08 04:37:24 +02:00
sLog.outError("Battleground: CreateNewBattleground - bg template not found for %u", bgTypeId);
return NULL;
}
}
2010-08-08 04:37:24 +02:00
Battleground *bg = NULL;
2008-10-05 08:48:32 -05:00
// create a copy of the BG template
switch(bgTypeId)
{
case BATTLEGROUND_AV:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundAV(*(BattlegroundAV*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_WS:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundWS(*(BattlegroundWS*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_AB:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundAB(*(BattlegroundAB*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_NA:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundNA(*(BattlegroundNA*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_BE:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundBE(*(BattlegroundBE*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_AA:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundAA(*(BattlegroundAA*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_EY:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundEY(*(BattlegroundEY*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_RL:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundRL(*(BattlegroundRL*)bg_template);
2008-10-05 08:48:32 -05:00
break;
case BATTLEGROUND_SA:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundSA(*(BattlegroundSA*)bg_template);
break;
case BATTLEGROUND_DS:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundDS(*(BattlegroundDS*)bg_template);
break;
case BATTLEGROUND_RV:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundRV(*(BattlegroundRV*)bg_template);
break;
2009-12-17 10:43:12 +01:00
case BATTLEGROUND_IC:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundIC(*(BattlegroundIC*)bg_template);
2009-12-17 10:43:12 +01:00
break;
case BATTLEGROUND_RB:
2010-08-08 04:37:24 +02:00
bg = new BattlegroundRB(*(BattlegroundRB*)bg_template);
2009-12-17 10:43:12 +01:00
break;
2008-10-05 08:48:32 -05:00
default:
//error, but it is handled few lines above
2008-10-05 08:48:32 -05:00
return 0;
}
2009-10-17 15:51:44 -07:00
// set battelground difficulty before initialization
bg->SetBracket(bracketEntry);
2008-10-05 08:48:32 -05:00
// generate a new instance id
bg->SetInstanceID(sMapMgr.GenerateInstanceId()); // set instance id
bg->SetClientInstanceID(CreateClientVisibleInstanceId(isRandom ? BATTLEGROUND_RB : bgTypeId, bracketEntry->GetBracketId()));
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// reset the new bg (set status to status_wait_queue from status_none)
bg->Reset();
2009-10-17 15:51:44 -07:00
// start the joining of the bg
bg->SetStatus(STATUS_WAIT_JOIN);
bg->SetArenaType(arenaType);
bg->SetRated(isRated);
bg->SetRandom(isRandom);
bg->SetTypeID(isRandom ? BATTLEGROUND_RB : bgTypeId);
bg->SetRandomTypeID(bgTypeId);
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
return bg;
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// used to create the BG templates
2010-08-08 04:37:24 +02:00
uint32 BattlegroundMgr::CreateBattleground(BattlegroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattlegroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO, uint32 scriptId)
2008-10-02 16:23:55 -05:00
{
// Create the BG
2010-08-08 04:37:24 +02:00
Battleground *bg = NULL;
2008-10-02 16:23:55 -05:00
switch(bgTypeId)
{
2010-08-08 04:37:24 +02:00
case BATTLEGROUND_AV: bg = new BattlegroundAV; break;
case BATTLEGROUND_WS: bg = new BattlegroundWS; break;
case BATTLEGROUND_AB: bg = new BattlegroundAB; break;
case BATTLEGROUND_NA: bg = new BattlegroundNA; break;
case BATTLEGROUND_BE: bg = new BattlegroundBE; break;
case BATTLEGROUND_AA: bg = new BattlegroundAA; break;
case BATTLEGROUND_EY: bg = new BattlegroundEY; break;
case BATTLEGROUND_RL: bg = new BattlegroundRL; break;
case BATTLEGROUND_SA: bg = new BattlegroundSA; break;
case BATTLEGROUND_DS: bg = new BattlegroundDS; break;
case BATTLEGROUND_RV: bg = new BattlegroundRV; break;
case BATTLEGROUND_IC: bg = new BattlegroundIC; break;
case BATTLEGROUND_RB: bg = new BattlegroundRB; break;
2009-12-17 10:43:12 +01:00
default:
2010-08-08 04:37:24 +02:00
bg = new Battleground;
2009-12-17 10:43:12 +01:00
break;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
bg->SetMapId(MapID);
bg->SetTypeID(bgTypeId);
bg->SetInstanceID(0);
bg->SetArenaorBGType(IsArena);
2008-10-02 16:23:55 -05:00
bg->SetMinPlayersPerTeam(MinPlayersPerTeam);
bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam);
bg->SetMinPlayers(MinPlayersPerTeam * 2);
bg->SetMaxPlayers(MaxPlayersPerTeam * 2);
2010-08-08 04:37:24 +02:00
bg->SetName(BattlegroundName);
2008-10-02 16:23:55 -05:00
bg->SetTeamStartLoc(ALLIANCE, Team1StartLocX, Team1StartLocY, Team1StartLocZ, Team1StartLocO);
bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO);
bg->SetLevelRange(LevelMin, LevelMax);
bg->SetScriptId(scriptId);
2009-10-17 15:51:44 -07:00
// add bg to update list
2010-08-08 04:37:24 +02:00
AddBattleground(bg->GetInstanceID(), bg->GetTypeID(), bg);
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// return some not-null value, bgTypeId is good enough for me
return bgTypeId;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::CreateInitialBattlegrounds()
2008-10-02 16:23:55 -05:00
{
float AStartLoc[4];
float HStartLoc[4];
uint32 MaxPlayersPerTeam, MinPlayersPerTeam, MinLvl, MaxLvl, start1, start2;
uint8 selectionWeight;
2008-10-02 16:23:55 -05:00
BattlemasterListEntry const *bl;
WorldSafeLocsEntry const *start;
bool IsArena;
uint32 scriptId = 0;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint32 count = 0;
2009-10-17 15:51:44 -07:00
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam,MaxPlayersPerTeam,MinLvl,MaxLvl,AllianceStartLoc,AllianceStartO,HordeStartLoc,HordeStartO,Weight,ScriptName FROM battleground_template");
2009-10-17 15:51:44 -07:00
if (!result)
2008-10-02 16:23:55 -05:00
{
barGoLink bar(1);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
bar.step();
2009-10-17 15:51:44 -07:00
sLog.outString();
2008-10-02 16:23:55 -05:00
sLog.outErrorDb(">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
return;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
barGoLink bar(result->GetRowCount());
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
do
{
Field *fields = result->Fetch();
bar.step();
2009-10-17 15:51:44 -07:00
uint32 bgTypeID_ = fields[0].GetUInt32();
if (sDisableMgr.IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeID_, NULL))
continue;
2009-10-17 15:51:44 -07:00
// can be overwrite by values from DB
bl = sBattlemasterListStore.LookupEntry(bgTypeID_);
if (!bl)
2008-10-02 16:23:55 -05:00
{
sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.", bgTypeID_);
2008-10-02 16:23:55 -05:00
continue;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundTypeId bgTypeID = BattlegroundTypeId(bgTypeID_);
2009-10-17 15:51:44 -07:00
IsArena = (bl->type == TYPE_ARENA);
MinPlayersPerTeam = fields[1].GetUInt32();
MaxPlayersPerTeam = fields[2].GetUInt32();
MinLvl = fields[3].GetUInt32();
MaxLvl = fields[4].GetUInt32();
//check values from DB
if (MaxPlayersPerTeam == 0 || MinPlayersPerTeam == 0 || MinPlayersPerTeam > MaxPlayersPerTeam)
{
MinPlayersPerTeam = 0; // by default now expected strong full bg requirement
MaxPlayersPerTeam = 40;
}
if (MinLvl == 0 || MaxLvl == 0 || MinLvl > MaxLvl)
{
2010-02-14 19:13:14 -07:00
//TO-DO: FIX ME
MinLvl = 0;//bl->minlvl;
MaxLvl = 80;//bl->maxlvl;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
start1 = fields[5].GetUInt32();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
start = sWorldSafeLocsStore.LookupEntry(start1);
if (start)
2008-10-02 16:23:55 -05:00
{
AStartLoc[0] = start->x;
AStartLoc[1] = start->y;
AStartLoc[2] = start->z;
AStartLoc[3] = fields[6].GetFloat();
}
else if (bgTypeID == BATTLEGROUND_AA || bgTypeID == BATTLEGROUND_RB)
2008-10-02 16:23:55 -05:00
{
AStartLoc[0] = 0;
AStartLoc[1] = 0;
AStartLoc[2] = 0;
AStartLoc[3] = fields[6].GetFloat();
}
else
{
sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", bgTypeID, start1);
2008-10-02 16:23:55 -05:00
continue;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
start2 = fields[7].GetUInt32();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
start = sWorldSafeLocsStore.LookupEntry(start2);
if (start)
2008-10-02 16:23:55 -05:00
{
HStartLoc[0] = start->x;
HStartLoc[1] = start->y;
HStartLoc[2] = start->z;
HStartLoc[3] = fields[8].GetFloat();
}
else if (bgTypeID == BATTLEGROUND_AA || bgTypeID == BATTLEGROUND_RB)
2008-10-02 16:23:55 -05:00
{
HStartLoc[0] = 0;
HStartLoc[1] = 0;
HStartLoc[2] = 0;
HStartLoc[3] = fields[8].GetFloat();
}
else
{
sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", bgTypeID, start2);
2008-10-02 16:23:55 -05:00
continue;
}
2009-10-17 15:51:44 -07:00
selectionWeight = fields[9].GetUInt8();
2010-08-08 05:25:45 +02:00
scriptId = sObjectMgr.GetScriptId(fields[10].GetString());
2008-10-02 16:23:55 -05:00
//sLog.outDetail("Creating battleground %s, %u-%u", bl->name[sWorld.GetDBClang()], MinLvl, MaxLvl);
2010-08-08 04:37:24 +02:00
if (!CreateBattleground(bgTypeID, IsArena, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, bl->name[sWorld.GetDefaultDbcLocale()], bl->mapid[0], AStartLoc[0], AStartLoc[1], AStartLoc[2], AStartLoc[3], HStartLoc[0], HStartLoc[1], HStartLoc[2], HStartLoc[3], scriptId))
2008-10-02 16:23:55 -05:00
continue;
2009-10-17 15:51:44 -07:00
2010-05-31 20:53:43 +02:00
if (IsArena)
{
if (bgTypeID != BATTLEGROUND_AA)
m_ArenaSelectionWeights[bgTypeID] = selectionWeight;
2010-05-31 20:53:43 +02:00
}
else if (bgTypeID != BATTLEGROUND_RB)
m_BGSelectionWeights[bgTypeID] = selectionWeight;
2008-10-02 16:23:55 -05:00
++count;
} while (result->NextRow());
2009-10-17 15:51:44 -07:00
sLog.outString();
2010-04-07 22:59:46 +02:00
sLog.outString(">> Loaded %u battlegrounds", count);
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::InitAutomaticArenaPointDistribution()
2008-10-05 08:48:32 -05:00
{
if (!sWorld.getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
return;
2010-04-07 18:09:10 +02:00
2010-08-23 07:51:19 +02:00
time_t wstime = time_t(sWorld.getWorldState(WS_ARENA_DISTRIBUTION_TIME));
time_t curtime = time(NULL);
sLog.outDebug("Initializing Automatic Arena Point Distribution");
if (wstime < curtime)
{
m_NextAutoDistributionTime = curtime; // reset will be called in the next update
sLog.outDebug("Battleground: Next arena point distribution time in the past, reseting it now.");
2008-10-05 08:48:32 -05:00
}
else
2010-08-23 07:51:19 +02:00
m_NextAutoDistributionTime = wstime;
sLog.outDebug("Automatic Arena Point Distribution initialized.");
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::DistributeArenaPoints()
2008-10-05 08:48:32 -05:00
{
// used to distribute arena points based on last week's stats
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_START);
2009-10-17 15:51:44 -07:00
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START);
2009-10-17 15:51:44 -07:00
//temporary structure for storing maximum points to add values for all players
std::map<uint32, uint32> PlayerPoints;
2009-10-17 15:51:44 -07:00
//at first update all points for all team members
2010-08-08 05:25:45 +02:00
for (ObjectMgr::ArenaTeamMap::iterator team_itr = sObjectMgr.GetArenaTeamMapBegin(); team_itr != sObjectMgr.GetArenaTeamMapEnd(); ++team_itr)
if (ArenaTeam * at = team_itr->second)
at->UpdateArenaPointsHelper(PlayerPoints);
2009-10-17 15:51:44 -07:00
//cycle that gives points to all players
for (std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr)
{
//update to database
CharacterDatabase.PExecute("UPDATE characters SET arenaPoints = arenaPoints + '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first);
//add points to player if online
2010-08-08 05:25:45 +02:00
Player* pl = sObjectMgr.GetPlayer(plr_itr->first);
if (pl)
pl->ModifyArenaPoints(plr_itr->second);
}
2009-10-17 15:51:44 -07:00
PlayerPoints.clear();
2009-10-17 15:51:44 -07:00
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END);
2009-10-17 15:51:44 -07:00
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
2010-08-08 05:25:45 +02:00
for (ObjectMgr::ArenaTeamMap::iterator titr = sObjectMgr.GetArenaTeamMapBegin(); titr != sObjectMgr.GetArenaTeamMapEnd(); ++titr)
2008-10-05 08:48:32 -05:00
{
if (ArenaTeam * at = titr->second)
2008-10-05 08:48:32 -05:00
{
at->FinishWeek(); // set played this week etc values to 0 in memory, too
at->SaveToDB(); // save changes
at->NotifyStatsChanged(); // notify the players of the changes
2008-10-05 08:48:32 -05:00
}
}
2009-10-17 15:51:44 -07:00
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
2009-10-17 15:51:44 -07:00
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_END);
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket *data, const uint64& guid, Player* plr, BattlegroundTypeId bgTypeId, uint8 fromWhere)
2008-10-02 16:23:55 -05:00
{
if (!plr)
return;
2009-10-17 15:51:44 -07:00
uint32 win_kills = plr->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST;
uint32 win_arena = plr->GetRandomWinner() ? BG_REWARD_WINNER_ARENA_LAST : BG_REWARD_WINNER_ARENA_FIRST;
uint32 loos_kills = plr->GetRandomWinner() ? BG_REWARD_LOOSER_HONOR_LAST : BG_REWARD_LOOSER_HONOR_FIRST;
win_kills = Trinity::Honor::hk_honor_at_level(plr->getLevel(), win_kills);
loos_kills = Trinity::Honor::hk_honor_at_level(plr->getLevel(), loos_kills);
2008-10-02 16:23:55 -05:00
data->Initialize(SMSG_BATTLEFIELD_LIST);
*data << uint64(guid); // battlemaster guid
2009-06-11 00:45:59 -05:00
*data << uint8(fromWhere); // from where you joined
2008-10-02 16:23:55 -05:00
*data << uint32(bgTypeId); // battleground id
2010-04-11 11:13:08 +04:00
*data << uint8(0); // unk
2010-04-11 20:20:38 +02:00
*data << uint8(0); // unk
2010-04-11 11:13:08 +04:00
// Rewards
*data << uint8(plr->GetRandomWinner()); // 3.3.3 hasWin
*data << uint32(win_kills); // 3.3.3 winHonor
*data << uint32(win_arena); // 3.3.3 winArena
*data << uint32(loos_kills); // 3.3.3 lossHonor
uint8 isRandom = bgTypeId == BATTLEGROUND_RB;
2010-04-11 20:20:38 +02:00
*data << uint8(isRandom); // 3.3.3 isRandom
if (isRandom)
{
// Rewards (random)
*data << uint8(plr->GetRandomWinner()); // 3.3.3 hasWin_Random
*data << uint32(win_kills); // 3.3.3 winHonor_Random
*data << uint32(win_arena); // 3.3.3 winArena_Random
*data << uint32(loos_kills); // 3.3.3 lossHonor_Random
2010-04-11 11:13:08 +04:00
}
2010-04-11 20:20:38 +02:00
2010-04-07 19:14:10 +02:00
if (bgTypeId == BATTLEGROUND_AA) // arena
2008-10-02 16:23:55 -05:00
{
2009-06-11 00:45:59 -05:00
*data << uint32(0); // unk (count?)
2008-10-02 16:23:55 -05:00
}
else // battleground
{
size_t count_pos = data->wpos();
uint32 count = 0;
2010-02-14 19:13:14 -07:00
*data << uint32(0); // number of bg instances
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
if (Battleground* bgTemplate = sBattlegroundMgr.GetBattlegroundTemplate(bgTypeId))
2008-10-02 16:23:55 -05:00
{
// expected bracket entry
2010-04-07 19:14:10 +02:00
if (PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgTemplate->GetMapId(),plr->getLevel()))
{
2010-08-08 04:37:24 +02:00
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
for (std::set<uint32>::iterator itr = m_ClientBattlegroundIds[bgTypeId][bracketId].begin(); itr != m_ClientBattlegroundIds[bgTypeId][bracketId].end();++itr)
{
*data << uint32(*itr);
++count;
}
2010-04-07 22:59:46 +02:00
data->put<uint32>(count_pos , count);
}
2008-10-02 16:23:55 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::SendToBattleground(Player *pl, uint32 instanceId, BattlegroundTypeId bgTypeId)
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
Battleground *bg = GetBattleground(instanceId, bgTypeId);
if (bg)
2008-10-02 16:23:55 -05:00
{
uint32 mapid = bg->GetMapId();
float x, y, z, O;
2008-10-05 08:48:32 -05:00
uint32 team = pl->GetBGTeam();
2010-04-07 23:25:02 +02:00
if (team == 0)
2008-10-05 08:48:32 -05:00
team = pl->GetTeam();
bg->GetTeamStartLoc(team, x, y, z, O);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O);
pl->TeleportTo(mapid, x, y, z, O);
}
2008-10-05 08:48:32 -05:00
else
{
sLog.outError("player %u trying to port to non-existent bg instance %u",pl->GetGUIDLow(), instanceId);
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, Battleground *bg, const uint64& guid)
2008-10-02 16:23:55 -05:00
{
WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds
if (time_ == uint32(-1))
2008-10-02 16:23:55 -05:00
time_ = 0;
data << guid << time_;
pl->GetSession()->SendPacket(&data);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool BattlegroundMgr::IsArenaType(BattlegroundTypeId bgTypeId)
2008-10-05 08:48:32 -05:00
{
2010-04-07 22:59:46 +02:00
return (bgTypeId == BATTLEGROUND_AA ||
2008-10-05 08:48:32 -05:00
bgTypeId == BATTLEGROUND_BE ||
bgTypeId == BATTLEGROUND_NA ||
2009-11-27 02:03:50 +01:00
bgTypeId == BATTLEGROUND_DS ||
bgTypeId == BATTLEGROUND_RV ||
2009-12-17 10:43:12 +01:00
bgTypeId == BATTLEGROUND_RL ||
2010-04-07 22:59:46 +02:00
bgTypeId == BATTLEGROUND_DS);
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType)
2008-10-05 08:48:32 -05:00
{
switch(bgTypeId)
{
2009-01-18 19:01:41 -06:00
case BATTLEGROUND_WS:
return BATTLEGROUND_QUEUE_WS;
case BATTLEGROUND_AB:
return BATTLEGROUND_QUEUE_AB;
case BATTLEGROUND_AV:
return BATTLEGROUND_QUEUE_AV;
case BATTLEGROUND_EY:
return BATTLEGROUND_QUEUE_EY;
case BATTLEGROUND_SA:
return BATTLEGROUND_QUEUE_SA;
2009-12-17 10:43:12 +01:00
case BATTLEGROUND_IC:
return BATTLEGROUND_QUEUE_IC;
case BATTLEGROUND_RB:
return BATTLEGROUND_QUEUE_RB;
2009-01-18 19:01:41 -06:00
case BATTLEGROUND_AA:
case BATTLEGROUND_NA:
case BATTLEGROUND_RL:
case BATTLEGROUND_BE:
case BATTLEGROUND_DS:
case BATTLEGROUND_RV:
switch(arenaType)
{
case ARENA_TYPE_2v2:
return BATTLEGROUND_QUEUE_2v2;
case ARENA_TYPE_3v3:
return BATTLEGROUND_QUEUE_3v3;
case ARENA_TYPE_5v5:
return BATTLEGROUND_QUEUE_5v5;
default:
return BATTLEGROUND_QUEUE_NONE;
2009-01-18 19:01:41 -06:00
}
2008-10-05 08:48:32 -05:00
default:
return BATTLEGROUND_QUEUE_NONE;
2008-10-05 08:48:32 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId)
2008-10-05 08:48:32 -05:00
{
switch(bgQueueTypeId)
{
2009-01-18 19:01:41 -06:00
case BATTLEGROUND_QUEUE_WS:
return BATTLEGROUND_WS;
case BATTLEGROUND_QUEUE_AB:
return BATTLEGROUND_AB;
case BATTLEGROUND_QUEUE_AV:
return BATTLEGROUND_AV;
case BATTLEGROUND_QUEUE_EY:
return BATTLEGROUND_EY;
case BATTLEGROUND_QUEUE_SA:
return BATTLEGROUND_SA;
2009-12-17 10:43:12 +01:00
case BATTLEGROUND_QUEUE_IC:
return BATTLEGROUND_IC;
case BATTLEGROUND_QUEUE_RB:
return BATTLEGROUND_RB;
2009-01-18 19:01:41 -06:00
case BATTLEGROUND_QUEUE_2v2:
case BATTLEGROUND_QUEUE_3v3:
case BATTLEGROUND_QUEUE_5v5:
return BATTLEGROUND_AA;
default:
2010-08-08 04:37:24 +02:00
return BattlegroundTypeId(0); // used for unknown template (it existed and do nothing)
2008-10-05 08:48:32 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint8 BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId bgQueueTypeId)
2008-10-05 08:48:32 -05:00
{
switch(bgQueueTypeId)
{
2009-01-18 19:01:41 -06:00
case BATTLEGROUND_QUEUE_2v2:
return ARENA_TYPE_2v2;
case BATTLEGROUND_QUEUE_3v3:
return ARENA_TYPE_3v3;
case BATTLEGROUND_QUEUE_5v5:
return ARENA_TYPE_5v5;
default:
return 0;
2008-10-05 08:48:32 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::ToggleTesting()
{
m_Testing = !m_Testing;
if (m_Testing)
sWorld.SendWorldText(LANG_DEBUG_BG_ON);
else
sWorld.SendWorldText(LANG_DEBUG_BG_OFF);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::ToggleArenaTesting()
2008-10-05 08:48:32 -05:00
{
m_ArenaTesting = !m_ArenaTesting;
if (m_ArenaTesting)
sWorld.SendWorldText(LANG_DEBUG_ARENA_ON);
else
sWorld.SendWorldText(LANG_DEBUG_ARENA_OFF);
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::SetHolidayWeekends(uint32 mask)
{
2009-10-17 16:20:24 -07:00
for (uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID; ++bgtype)
{
2010-08-08 04:37:24 +02:00
if (Battleground * bg = GetBattlegroundTemplate(BattlegroundTypeId(bgtype)))
{
bg->SetHoliday(mask & (1 << bgtype));
}
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::ScheduleQueueUpdate(uint32 arenaRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{
//This method must be atomic, TODO add mutex
//we will use only 1 number created of bgTypeId and bracket_id
uint64 schedule_id = ((uint64)arenaRating << 32) | (arenaType << 24) | (bgQueueTypeId << 16) | (bgTypeId << 8) | bracket_id;
bool found = false;
for (uint8 i = 0; i < m_QueueUpdateScheduler.size(); i++)
{
if (m_QueueUpdateScheduler[i] == schedule_id)
{
found = true;
break;
}
}
if (!found)
m_QueueUpdateScheduler.push_back(schedule_id);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 BattlegroundMgr::GetMaxRatingDifference() const
{
// this is for stupid people who can't use brain and set max rating difference to 0
uint32 diff = sWorld.getIntConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE);
if (diff == 0)
diff = 5000;
return diff;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 BattlegroundMgr::GetRatingDiscardTimer() const
{
return sWorld.getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 BattlegroundMgr::GetPrematureFinishTime() const
{
return sWorld.getIntConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER);
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::LoadBattleMastersEntry()
{
mBattleMastersMap.clear(); // need for reload case
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,bg_template FROM battlemaster_entry");
2009-10-17 15:51:44 -07:00
uint32 count = 0;
2009-10-17 15:51:44 -07:00
if (!result)
{
2010-04-07 22:59:46 +02:00
barGoLink bar(1);
bar.step();
2009-10-17 15:51:44 -07:00
sLog.outString();
2010-04-07 22:59:46 +02:00
sLog.outString(">> Loaded 0 battlemaster entries - table is empty!");
return;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
barGoLink bar(result->GetRowCount());
2009-10-17 15:51:44 -07:00
do
{
++count;
bar.step();
2009-10-17 15:51:44 -07:00
Field *fields = result->Fetch();
2009-10-17 15:51:44 -07:00
uint32 entry = fields[0].GetUInt32();
uint32 bgTypeId = fields[1].GetUInt32();
if (!sBattlemasterListStore.LookupEntry(bgTypeId))
{
sLog.outErrorDb("Table `battlemaster_entry` contain entry %u for not existed battleground type %u, ignored.",entry,bgTypeId);
continue;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
mBattleMastersMap[entry] = BattlegroundTypeId(bgTypeId);
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
} while (result->NextRow());
2009-10-17 15:51:44 -07:00
sLog.outString();
2010-04-07 22:59:46 +02:00
sLog.outString(">> Loaded %u battlemaster entries", count);
2009-02-18 22:39:00 +01:00
}
2010-08-08 04:37:24 +02:00
HolidayIds BattlegroundMgr::BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId)
{
switch (bgTypeId)
{
case BATTLEGROUND_AV: return HOLIDAY_CALL_TO_ARMS_AV;
case BATTLEGROUND_EY: return HOLIDAY_CALL_TO_ARMS_EY;
case BATTLEGROUND_WS: return HOLIDAY_CALL_TO_ARMS_WS;
case BATTLEGROUND_SA: return HOLIDAY_CALL_TO_ARMS_SA;
case BATTLEGROUND_AB: return HOLIDAY_CALL_TO_ARMS_AB;
default: return HOLIDAY_NONE;
}
}
2009-12-17 10:43:12 +01:00
2010-08-08 04:37:24 +02:00
BattlegroundTypeId BattlegroundMgr::WeekendHolidayIdToBGType(HolidayIds holiday)
{
switch (holiday)
{
case HOLIDAY_CALL_TO_ARMS_AV: return BATTLEGROUND_AV;
case HOLIDAY_CALL_TO_ARMS_EY: return BATTLEGROUND_EY;
case HOLIDAY_CALL_TO_ARMS_WS: return BATTLEGROUND_WS;
case HOLIDAY_CALL_TO_ARMS_SA: return BATTLEGROUND_SA;
case HOLIDAY_CALL_TO_ARMS_AB: return BATTLEGROUND_AB;
default: return BATTLEGROUND_TYPE_NONE;
}
}
2010-08-08 04:37:24 +02:00
bool BattlegroundMgr::IsBGWeekend(BattlegroundTypeId bgTypeId)
{
return IsHolidayActive(BGTypeToWeekendHolidayId(bgTypeId));
}
2010-08-08 04:37:24 +02:00
void BattlegroundMgr::DoCompleteAchievement(uint32 achievement, Player * player)
2009-12-17 10:43:12 +01:00
{
AchievementEntry const* AE = GetAchievementStore()->LookupEntry(achievement);
2010-04-07 19:14:10 +02:00
if (!player)
{
//Map::PlayerList const &PlayerList = this->GetPlayers();
//GroupsQueueType::iterator group = SelectedGroups.begin();
//if (!PlayerList.isEmpty())
//for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
// for (GroupsQueueType::iterator itr = group; itr != SelectedGroups.end(); ++itr)
// if (Player *pPlayer = itr->getSource())
// pPlayer->CompletedAchievement(AE);
}
else
{
player->CompletedAchievement(AE);
}
2009-12-17 10:43:12 +01:00
}