Core/BG: When starting a battleground teleport the player to start location if it goes outside of the allowed "waiting" area (for example, getting out of the "bubble" in EotS)

Allowed waiting area is calculated as the distance specified in database (battleground_template.StartMaxDist) and the battleground start point for each team
A distance of 0 is ignored (not used in SotA nor arenas)

The values in DB might need some tweaks, open a pull request if you calculate better ones

Closes #180

Initial patch and idea by Rat

Also added validation (DBError log) to some fields in battleground_template table
This commit is contained in:
Nay
2012-04-13 20:51:07 +01:00
parent b9c50a8b6e
commit a28742bffe
6 changed files with 77 additions and 28 deletions
@@ -0,0 +1,7 @@
ALTER TABLE `battleground_template` ADD `StartMaxDist` float NOT NULL DEFAULT 0 AFTER `HordeStartO`;
UPDATE `battleground_template` SET `StartMaxDist`=200 WHERE `id`=30; -- IC
UPDATE `battleground_template` SET `StartMaxDist`=100 WHERE `id`=1; -- AV
UPDATE `battleground_template` SET `StartMaxDist`=75 WHERE `id` IN (2,3,7); -- WSG, AB, EotS
UPDATE `battleground_template` SET `MinLvl`=1 WHERE `id`=32;
+34 -3
View File
@@ -144,6 +144,7 @@ Battleground::Battleground()
m_Winner = 2;
m_StartTime = 0;
m_ResetStatTimer = 0;
m_ValidStartPositionTimer = 0;
m_Events = 0;
m_IsRated = false;
m_BuffChange = false;
@@ -177,6 +178,8 @@ Battleground::Battleground()
m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0;
m_ArenaTeamIds[BG_TEAM_HORDE] = 0;
m_StartMaxDist = 0.0f;
m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0;
m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0;
@@ -291,6 +294,7 @@ void Battleground::Update(uint32 diff)
// Update start time and reset stats timer
m_StartTime += diff;
m_ResetStatTimer += diff;
m_ValidStartPositionTimer += diff;
PostUpdateImpl(diff);
}
@@ -453,19 +457,19 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// First start warning - 2 or 1 minute
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// After 1 minute or 30 seconds, warning is signalled
// After 1 minute or 30 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
{
m_Events |= BG_STARTING_EVENT_2;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// After 30 or 15 seconds, warning is signalled
// After 30 or 15 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
{
m_Events |= BG_STARTING_EVENT_3;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// Delay expired (atfer 2 or 1 minute)
// Delay expired (after 2 or 1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
{
m_Events |= BG_STARTING_EVENT_4;
@@ -526,6 +530,33 @@ inline void Battleground::_ProcessJoin(uint32 diff)
sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
}
// Find if the player left our start zone; if so, teleport it back
if (m_ValidStartPositionTimer > 1000)
{
m_ValidStartPositionTimer = 0;
float maxDist = GetStartMaxDist();
if (maxDist > 0.0f)
{
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
{
if (Player *plr = ObjectAccessor::FindPlayer(itr->first))
{
float x, y, z, o;
uint32 team = plr->GetBGTeam();
GetTeamStartLoc(team, x, y, z, o);
float dist = plr->GetDistance(x, y, z);
if (dist >= maxDist)
{
sLog->outError("BATTLEGROUND: Sending %s back to start location (possible exploit)", plr->GetName());
plr->TeleportTo(GetMapId(), x, y, z, o);
}
}
}
}
}
}
inline void Battleground::_ProcessLeave(uint32 diff)
@@ -443,6 +443,8 @@ class Battleground
Z = m_TeamStartLocZ[idx];
O = m_TeamStartLocO[idx];
}
void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; }
float GetStartMaxDist() const { return m_StartMaxDist; }
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
@@ -617,6 +619,7 @@ class Battleground
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime;
BattlegroundBracketId m_BracketId;
@@ -698,6 +701,7 @@ class Battleground
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
float m_TeamStartLocO[BG_TEAMS_COUNT];
float m_StartMaxDist;
uint32 ScriptId;
};
#endif
@@ -660,6 +660,7 @@ uint32 BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data)
bg->SetName(data.BattlegroundName);
bg->SetTeamStartLoc(ALLIANCE, data.Team1StartLocX, data.Team1StartLocY, data.Team1StartLocZ, data.Team1StartLocO);
bg->SetTeamStartLoc(HORDE, data.Team2StartLocX, data.Team2StartLocY, data.Team2StartLocZ, data.Team2StartLocO);
bg->SetStartMaxDist(data.StartMaxDist);
bg->SetLevelRange(data.LevelMin, data.LevelMax);
bg->SetScriptId(data.scriptId);
@@ -677,8 +678,8 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
uint8 selectionWeight;
BattlemasterListEntry const* bl;
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, Weight, ScriptName FROM battleground_template");
// 0 1 2 3 4 5 6 7 8 9 10 11
QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
if (!result)
{
@@ -712,17 +713,20 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
data.MaxPlayersPerTeam = fields[2].GetUInt16();
data.LevelMin = fields[3].GetUInt8();
data.LevelMax = fields[4].GetUInt8();
//check values from DB
if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
// check values from DB
if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
{
data.MinPlayersPerTeam = 0; // by default now expected strong full bg requirement
data.MaxPlayersPerTeam = 40;
sLog->outErrorDb("Table `battleground_template` for id %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)",
data.bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam);
continue;
}
if (data.LevelMin == 0 || data.LevelMax == 0 || data.LevelMin > data.LevelMax)
{
//TO-DO: FIX ME
data.LevelMin = 0;//bl->minlvl;
data.LevelMax = 80;//bl->maxlvl;
sLog->outErrorDb("Table `battleground_template` for id %u has bad values for LevelMin (%u) and LevelMax(%u)",
data.bgTypeId, data.LevelMin, data.LevelMax);
continue;
}
startId = fields[5].GetUInt32();
@@ -767,8 +771,10 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
continue;
}
selectionWeight = fields[9].GetUInt8();
data.scriptId = sObjectMgr->GetScriptId(fields[10].GetCString());
data.StartMaxDist = fields[9].GetFloat();
selectionWeight = fields[10].GetUInt8();
data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()];
data.MapID = bl->mapid[0];
@@ -50,6 +50,7 @@ struct CreateBattlegroundData
float Team2StartLocY;
float Team2StartLocZ;
float Team2StartLocO;
float StartMaxDist;
uint32 scriptId;
};
+14 -14
View File
@@ -3294,20 +3294,20 @@ enum BanReturn
// indexes of BattlemasterList.dbc
enum BattlegroundTypeId
{
BATTLEGROUND_TYPE_NONE = 0,
BATTLEGROUND_AV = 1,
BATTLEGROUND_WS = 2,
BATTLEGROUND_AB = 3,
BATTLEGROUND_NA = 4,
BATTLEGROUND_BE = 5,
BATTLEGROUND_AA = 6,
BATTLEGROUND_EY = 7,
BATTLEGROUND_RL = 8,
BATTLEGROUND_SA = 9,
BATTLEGROUND_DS = 10,
BATTLEGROUND_RV = 11,
BATTLEGROUND_IC = 30,
BATTLEGROUND_RB = 32
BATTLEGROUND_TYPE_NONE = 0, // None
BATTLEGROUND_AV = 1, // Alterac Valley
BATTLEGROUND_WS = 2, // Warsong Gulch
BATTLEGROUND_AB = 3, // Arathi Basin
BATTLEGROUND_NA = 4, // Nagrand Arena
BATTLEGROUND_BE = 5, // Blade's Edge Arena
BATTLEGROUND_AA = 6, // All Arenas
BATTLEGROUND_EY = 7, // Eye of the Storm
BATTLEGROUND_RL = 8, // Ruins of Lordaernon
BATTLEGROUND_SA = 9, // Strand of the Ancients
BATTLEGROUND_DS = 10, // Dalaran Sewers
BATTLEGROUND_RV = 11, // Ring of Valor
BATTLEGROUND_IC = 30, // Isle of Conquest
BATTLEGROUND_RB = 32 // Random Battleground
};
#define MAX_BATTLEGROUND_TYPE_ID 33