mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-18 11:25:42 +00:00
1130 lines
40 KiB
C++
1130 lines
40 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-GPL2
|
|
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
|
*/
|
|
|
|
#include "BattlegroundSA.h"
|
|
#include "Language.h"
|
|
#include "Player.h"
|
|
#include "GameObject.h"
|
|
#include "ObjectMgr.h"
|
|
#include "WorldPacket.h"
|
|
#include "WorldSession.h"
|
|
#include "GameGraveyard.h"
|
|
|
|
BattlegroundSA::BattlegroundSA()
|
|
{
|
|
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES;
|
|
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_SA_START_ONE_MINUTE;
|
|
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_SA_START_HALF_MINUTE;
|
|
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_SA_HAS_BEGUN;
|
|
BgObjects.resize(BG_SA_MAXOBJ);
|
|
BgCreatures.resize(BG_SA_MAXNPC + BG_SA_MAX_GY);
|
|
TimerEnabled = false;
|
|
UpdateWaitTimer = 0;
|
|
SignaledRoundTwo = false;
|
|
SignaledRoundTwoHalfMin = false;
|
|
InitSecondRound = false;
|
|
Attackers = TEAM_ALLIANCE;
|
|
TotalTime = 0;
|
|
EndRoundTimer = 0;
|
|
ShipsStarted = false;
|
|
Status = BG_SA_NOTSTARTED;
|
|
|
|
for (uint8 i = 0; i < 6; i++)
|
|
GateStatus[i] = BG_SA_GATE_OK;
|
|
|
|
for (uint8 i = 0; i < 2; i++)
|
|
{
|
|
RoundScores[i].winner = TEAM_ALLIANCE;
|
|
RoundScores[i].time = 0;
|
|
}
|
|
|
|
//! This is here to prevent an uninitialised variable warning
|
|
//! The warning only occurs when SetUpBattleGround fails though.
|
|
//! In the future this function should be called BEFORE sending initial worldstates.
|
|
memset(&GraveyardStatus, 0, sizeof(GraveyardStatus));
|
|
}
|
|
|
|
BattlegroundSA::~BattlegroundSA()
|
|
{
|
|
}
|
|
|
|
void BattlegroundSA::Init()
|
|
{
|
|
Battleground::Init();
|
|
|
|
TotalTime = 0;
|
|
Attackers = ((urand(0, 1)) ? TEAM_ALLIANCE : TEAM_HORDE);
|
|
for (uint8 i = 0; i <= 5; i++)
|
|
GateStatus[i] = BG_SA_GATE_OK;
|
|
ShipsStarted = false;
|
|
_notEvenAScratch[TEAM_ALLIANCE] = true;
|
|
_notEvenAScratch[TEAM_HORDE] = true;
|
|
Status = BG_SA_WARMUP;
|
|
_relicClicked = false;
|
|
}
|
|
|
|
bool BattlegroundSA::SetupBattleground()
|
|
{
|
|
return ResetObjs();
|
|
}
|
|
|
|
bool BattlegroundSA::ResetObjs()
|
|
{
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
SendTransportsRemove(itr->second);
|
|
|
|
uint32 atF = BG_SA_Factions[Attackers];
|
|
uint32 defF = BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE];
|
|
|
|
for (uint8 i = 0; i < BG_SA_MAXOBJ; i++)
|
|
DelObject(i);
|
|
|
|
for (uint8 i = 0; i < BG_SA_MAXNPC; i++)
|
|
DelCreature(i);
|
|
|
|
for (uint8 i = BG_SA_MAXNPC; i < BG_SA_MAXNPC + BG_SA_MAX_GY; i++)
|
|
DelCreature(i);
|
|
|
|
for (uint8 i = 0; i < 6; ++i)
|
|
GateStatus[i] = BG_SA_GATE_OK;
|
|
|
|
for (uint8 i = 0; i < BG_SA_BOAT_ONE; i++)
|
|
{
|
|
if (!AddObject(i, BG_SA_ObjEntries[i], BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1], BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3], 0, 0, 0, 0, RESPAWN_ONE_DAY))
|
|
return false;
|
|
}
|
|
|
|
for (uint8 i = BG_SA_BOAT_ONE; i < BG_SA_SIGIL_1; i++)
|
|
{
|
|
uint32 boatid = 0;
|
|
switch (i)
|
|
{
|
|
case BG_SA_BOAT_ONE:
|
|
boatid = Attackers ? BG_SA_BOAT_ONE_H : BG_SA_BOAT_ONE_A;
|
|
break;
|
|
case BG_SA_BOAT_TWO:
|
|
boatid = Attackers ? BG_SA_BOAT_TWO_H : BG_SA_BOAT_TWO_A;
|
|
break;
|
|
}
|
|
if (!AddObject(i, boatid, BG_SA_ObjSpawnlocs[i][0],
|
|
BG_SA_ObjSpawnlocs[i][1],
|
|
BG_SA_ObjSpawnlocs[i][2] + (Attackers ? -3.750f : 0),
|
|
BG_SA_ObjSpawnlocs[i][3], 0, 0, 0, 0, RESPAWN_ONE_DAY))
|
|
return false;
|
|
}
|
|
|
|
for (uint8 i = BG_SA_SIGIL_1; i < BG_SA_CENTRAL_FLAG; i++)
|
|
{
|
|
if (!AddObject(i, BG_SA_ObjEntries[i],
|
|
BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1],
|
|
BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3],
|
|
0, 0, 0, 0, RESPAWN_ONE_DAY))
|
|
return false;
|
|
}
|
|
|
|
// MAD props for Kiper for discovering those values - 4 hours of his work.
|
|
GetBGObject(BG_SA_BOAT_ONE)->SetTransportPathRotation(0.0f, 0.0f, 1.0f, 0.0002f);
|
|
GetBGObject(BG_SA_BOAT_TWO)->SetTransportPathRotation(0.0f, 0.0f, 1.0f, 0.00001f);
|
|
SpawnBGObject(BG_SA_BOAT_ONE, RESPAWN_IMMEDIATELY);
|
|
SpawnBGObject(BG_SA_BOAT_TWO, RESPAWN_IMMEDIATELY);
|
|
|
|
//Cannons and demolishers - NPCs are spawned
|
|
//By capturing GYs.
|
|
for (uint8 i = 0; i < BG_SA_DEMOLISHER_5; i++)
|
|
{
|
|
if (!AddCreature(BG_SA_NpcEntries[i], i,
|
|
BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1],
|
|
BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3], 600))
|
|
return false;
|
|
}
|
|
|
|
OverrideGunFaction();
|
|
DemolisherStartState(true);
|
|
|
|
for (uint8 i = BG_SA_GREEN_GATE; i <= BG_SA_TITAN_RELIC; i++)
|
|
{
|
|
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
|
if (GameObject* go = GetBGObject(i))
|
|
{
|
|
go->setActive(true);
|
|
go->SetUInt32Value(GAMEOBJECT_FACTION, defF);
|
|
go->SetDestructibleBuildingModifyState(false);
|
|
}
|
|
}
|
|
|
|
GetBGObject(BG_SA_TITAN_RELIC)->SetUInt32Value(GAMEOBJECT_FACTION, atF);
|
|
GetBGObject(BG_SA_TITAN_RELIC)->Refresh();
|
|
|
|
TotalTime = 0;
|
|
ShipsStarted = false;
|
|
|
|
//Graveyards!
|
|
for (uint8 i = 0; i < BG_SA_MAX_GY; i++)
|
|
{
|
|
GraveyardStruct const* sg = nullptr;
|
|
sg = sGraveyard->GetGraveyard(BG_SA_GYEntries[i]);
|
|
|
|
if (!sg)
|
|
{
|
|
sLog->outError("SOTA: Can't find GY entry %u", BG_SA_GYEntries[i]);
|
|
return false;
|
|
}
|
|
|
|
if (i == BG_SA_BEACH_GY)
|
|
{
|
|
GraveyardStatus[i] = Attackers;
|
|
AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], Attackers);
|
|
}
|
|
else
|
|
{
|
|
GraveyardStatus[i] = GetOtherTeamId(Attackers);
|
|
if (!AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], GetOtherTeamId(Attackers)))
|
|
sLog->outError("SOTA: couldn't spawn GY: %u", i);
|
|
}
|
|
}
|
|
|
|
//GY capture points
|
|
for (uint8 i = BG_SA_CENTRAL_FLAG; i < BG_SA_PORTAL_DEFFENDER_BLUE; i++)
|
|
{
|
|
AddObject(i, (BG_SA_ObjEntries[i] - (Attackers == TEAM_ALLIANCE ? 1 : 0)),
|
|
BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1],
|
|
BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3],
|
|
0, 0, 0, 0, RESPAWN_ONE_DAY);
|
|
GetBGObject(i)->SetUInt32Value(GAMEOBJECT_FACTION, atF);
|
|
}
|
|
|
|
for (uint8 i = BG_SA_PORTAL_DEFFENDER_BLUE; i < BG_SA_BOMB; i++)
|
|
{
|
|
AddObject(i, BG_SA_ObjEntries[i],
|
|
BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1],
|
|
BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3],
|
|
0, 0, 0, 0, RESPAWN_ONE_DAY);
|
|
GetBGObject(i)->SetUInt32Value(GAMEOBJECT_FACTION, defF);
|
|
}
|
|
|
|
UpdateObjectInteractionFlags();
|
|
|
|
for (uint8 i = BG_SA_BOMB; i < BG_SA_MAXOBJ; i++)
|
|
{
|
|
AddObject(i, BG_SA_ObjEntries[BG_SA_BOMB],
|
|
BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1],
|
|
BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3],
|
|
0, 0, 0, 0, RESPAWN_ONE_DAY);
|
|
GetBGObject(i)->SetUInt32Value(GAMEOBJECT_FACTION, atF);
|
|
}
|
|
|
|
//Player may enter BEFORE we set up bG - lets update his worldstates anyway...
|
|
UpdateWorldState(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
|
|
UpdateWorldState(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
|
|
UpdateWorldState(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
|
|
|
|
UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
|
|
UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
|
|
UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
|
|
|
|
if (Attackers == TEAM_ALLIANCE)
|
|
{
|
|
UpdateWorldState(BG_SA_ALLY_ATTACKS, 1);
|
|
UpdateWorldState(BG_SA_HORDE_ATTACKS, 0);
|
|
|
|
UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, 1);
|
|
UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, 1);
|
|
UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, 0);
|
|
UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, 0);
|
|
|
|
UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN, 1);
|
|
UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN, 0);
|
|
}
|
|
else
|
|
{
|
|
UpdateWorldState(BG_SA_HORDE_ATTACKS, 1);
|
|
UpdateWorldState(BG_SA_ALLY_ATTACKS, 0);
|
|
|
|
UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, 0);
|
|
UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, 0);
|
|
UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, 1);
|
|
UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, 1);
|
|
|
|
UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN, 0);
|
|
UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN, 1);
|
|
}
|
|
|
|
UpdateWorldState(BG_SA_PURPLE_GATEWS, 1);
|
|
UpdateWorldState(BG_SA_RED_GATEWS, 1);
|
|
UpdateWorldState(BG_SA_BLUE_GATEWS, 1);
|
|
UpdateWorldState(BG_SA_GREEN_GATEWS, 1);
|
|
UpdateWorldState(BG_SA_YELLOW_GATEWS, 1);
|
|
UpdateWorldState(BG_SA_ANCIENT_GATEWS, 1);
|
|
|
|
for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++)
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
SendTransportInit(itr->second);
|
|
|
|
// set status manually so preparation is cast correctly in 2nd round too
|
|
SetStatus(STATUS_WAIT_JOIN);
|
|
|
|
TeleportPlayers();
|
|
return true;
|
|
}
|
|
|
|
void BattlegroundSA::StartShips()
|
|
{
|
|
if (ShipsStarted)
|
|
return;
|
|
|
|
DoorOpen(BG_SA_BOAT_ONE);
|
|
DoorOpen(BG_SA_BOAT_TWO);
|
|
|
|
for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++)
|
|
{
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
{
|
|
UpdateData data;
|
|
WorldPacket pkt;
|
|
GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, itr->second);
|
|
data.BuildPacket(&pkt);
|
|
itr->second->GetSession()->SendPacket(&pkt);
|
|
}
|
|
}
|
|
ShipsStarted = true;
|
|
}
|
|
|
|
void BattlegroundSA::PostUpdateImpl(uint32 diff)
|
|
{
|
|
if (InitSecondRound)
|
|
{
|
|
if (UpdateWaitTimer < diff)
|
|
{
|
|
if (!SignaledRoundTwo)
|
|
{
|
|
SignaledRoundTwo = true;
|
|
InitSecondRound = false;
|
|
SendMessageToAll(LANG_BG_SA_ROUND_TWO_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UpdateWaitTimer -= diff;
|
|
return;
|
|
}
|
|
}
|
|
TotalTime += diff;
|
|
|
|
if (Status == BG_SA_WARMUP)
|
|
{
|
|
EndRoundTimer = BG_SA_ROUNDLENGTH;
|
|
if (TotalTime >= BG_SA_WARMUPLENGTH)
|
|
{
|
|
TotalTime = 0;
|
|
ToggleTimer();
|
|
DemolisherStartState(false);
|
|
Status = BG_SA_ROUND_ONE;
|
|
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
|
|
}
|
|
if (TotalTime >= BG_SA_BOAT_START)
|
|
StartShips();
|
|
return;
|
|
}
|
|
else if (Status == BG_SA_SECOND_WARMUP)
|
|
{
|
|
if (RoundScores[0].time < BG_SA_ROUNDLENGTH)
|
|
EndRoundTimer = RoundScores[0].time;
|
|
else
|
|
EndRoundTimer = BG_SA_ROUNDLENGTH;
|
|
|
|
if (TotalTime >= 60000)
|
|
{
|
|
SendWarningToAll(LANG_BG_SA_HAS_BEGUN);
|
|
TotalTime = 0;
|
|
ToggleTimer();
|
|
DemolisherStartState(false);
|
|
Status = BG_SA_ROUND_TWO;
|
|
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
|
|
|
|
// status was set to STATUS_WAIT_JOIN manually for Preparation, set it back now
|
|
SetStatus(STATUS_IN_PROGRESS);
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
itr->second->RemoveAurasDueToSpell(SPELL_PREPARATION);
|
|
}
|
|
if (TotalTime >= 30000)
|
|
{
|
|
if (!SignaledRoundTwoHalfMin)
|
|
{
|
|
SignaledRoundTwoHalfMin = true;
|
|
SendMessageToAll(LANG_BG_SA_ROUND_TWO_START_HALF_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
|
}
|
|
}
|
|
StartShips();
|
|
return;
|
|
}
|
|
else if (GetStatus() == STATUS_IN_PROGRESS)
|
|
{
|
|
if (Status == BG_SA_ROUND_ONE)
|
|
{
|
|
if (TotalTime >= BG_SA_ROUNDLENGTH || _relicClicked)
|
|
{
|
|
if (_relicClicked)
|
|
{
|
|
RoundScores[0].winner = Attackers;
|
|
RoundScores[0].time = TotalTime;
|
|
//Achievement Storm the Beach (1310)
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
if (itr->second->GetTeamId() == Attackers)
|
|
itr->second->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
|
|
}
|
|
else
|
|
{
|
|
// cast this before Attackers variable is switched
|
|
// cast this spell only upon timer end, no other ability for defenders to win :)
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
itr->second->CastSpell(itr->second, SPELL_SA_END_OF_ROUND, true);
|
|
|
|
RoundScores[0].winner = Attackers;
|
|
RoundScores[0].time = BG_SA_ROUNDLENGTH;
|
|
}
|
|
|
|
_relicClicked = false;
|
|
Attackers = (Attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE;
|
|
Status = BG_SA_SECOND_WARMUP;
|
|
TotalTime = 0;
|
|
ToggleTimer();
|
|
SendWarningToAll(LANG_BG_SA_ROUND_ONE_END);
|
|
UpdateWaitTimer = 5000;
|
|
SignaledRoundTwo = false;
|
|
SignaledRoundTwoHalfMin = false;
|
|
InitSecondRound = true;
|
|
ResetObjs();
|
|
|
|
return;
|
|
}
|
|
}
|
|
else if (Status == BG_SA_ROUND_TWO)
|
|
{
|
|
if (TotalTime >= EndRoundTimer)
|
|
{
|
|
// cast this spell only upon timer end, no other ability for defenders to win :)
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
itr->second->CastSpell(itr->second, SPELL_SA_END_OF_ROUND, true);
|
|
|
|
RoundScores[1].time = BG_SA_ROUNDLENGTH;
|
|
RoundScores[1].winner = GetOtherTeamId(Attackers);
|
|
|
|
if (RoundScores[0].time == RoundScores[1].time)
|
|
EndBattleground(TEAM_NEUTRAL);
|
|
else if (RoundScores[0].time < RoundScores[1].time)
|
|
EndBattleground(RoundScores[0].winner);
|
|
else
|
|
EndBattleground(RoundScores[1].winner);
|
|
return;
|
|
}
|
|
}
|
|
if (Status == BG_SA_ROUND_ONE || Status == BG_SA_ROUND_TWO)
|
|
{
|
|
SendTime();
|
|
UpdateDemolisherSpawns();
|
|
}
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::StartingEventCloseDoors()
|
|
{
|
|
}
|
|
|
|
void BattlegroundSA::StartingEventOpenDoors()
|
|
{
|
|
}
|
|
|
|
void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
|
|
{
|
|
uint32 ally_attacks = uint32(Attackers == TEAM_ALLIANCE ? 1 : 0);
|
|
uint32 horde_attacks = uint32(Attackers == TEAM_HORDE ? 1 : 0);
|
|
|
|
data << uint32(BG_SA_ANCIENT_GATEWS) << uint32(GateStatus[BG_SA_ANCIENT_GATE]);
|
|
data << uint32(BG_SA_YELLOW_GATEWS) << uint32(GateStatus[BG_SA_YELLOW_GATE]);
|
|
data << uint32(BG_SA_GREEN_GATEWS) << uint32(GateStatus[BG_SA_GREEN_GATE]);
|
|
data << uint32(BG_SA_BLUE_GATEWS) << uint32(GateStatus[BG_SA_BLUE_GATE]);
|
|
data << uint32(BG_SA_RED_GATEWS) << uint32(GateStatus[BG_SA_RED_GATE]);
|
|
data << uint32(BG_SA_PURPLE_GATEWS) << uint32(GateStatus[BG_SA_PURPLE_GATE]);
|
|
|
|
data << uint32(BG_SA_BONUS_TIMER) << uint32(0);
|
|
|
|
data << uint32(BG_SA_HORDE_ATTACKS) << horde_attacks;
|
|
data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks;
|
|
|
|
//Time will be sent on first update...
|
|
data << uint32(BG_SA_ENABLE_TIMER) << ((TimerEnabled) ? uint32(1) : uint32(0));
|
|
data << uint32(BG_SA_TIMER_MINS) << uint32(0);
|
|
data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0);
|
|
data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0);
|
|
|
|
data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
|
|
data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
|
|
data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
|
|
|
|
data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
|
|
data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
|
|
data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
|
|
|
|
data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks;
|
|
data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks;
|
|
|
|
data << uint32(BG_SA_LEFT_ATT_TOKEN_HRD) << horde_attacks;
|
|
data << uint32(BG_SA_RIGHT_ATT_TOKEN_HRD) << horde_attacks;
|
|
data << uint32(BG_SA_RIGHT_ATT_TOKEN_ALL) << ally_attacks;
|
|
data << uint32(BG_SA_LEFT_ATT_TOKEN_ALL) << ally_attacks;
|
|
}
|
|
|
|
void BattlegroundSA::AddPlayer(Player* player)
|
|
{
|
|
Battleground::AddPlayer(player);
|
|
//create score and add it to map, default values are set in constructor
|
|
BattlegroundSAScore* sc = new BattlegroundSAScore(player);
|
|
|
|
SendTransportInit(player);
|
|
PlayerScores[player->GetGUID()] = sc;
|
|
TeleportToEntrancePosition(player);
|
|
}
|
|
|
|
void BattlegroundSA::RemovePlayer(Player* /*player*/)
|
|
{
|
|
}
|
|
|
|
void BattlegroundSA::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/)
|
|
{
|
|
// this is wrong way to implement these things. On official it done by gameobject spell cast.
|
|
if (GetStatus() != STATUS_IN_PROGRESS)
|
|
return;
|
|
}
|
|
|
|
void BattlegroundSA::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
|
|
{
|
|
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
|
|
if (itr == PlayerScores.end())
|
|
return;
|
|
|
|
if (type == SCORE_DESTROYED_DEMOLISHER)
|
|
((BattlegroundSAScore*)itr->second)->demolishers_destroyed += value;
|
|
else if (type == SCORE_DESTROYED_WALL)
|
|
((BattlegroundSAScore*)itr->second)->gates_destroyed += value;
|
|
else
|
|
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
|
|
}
|
|
|
|
void BattlegroundSA::TeleportPlayers()
|
|
{
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
{
|
|
if (Player* player = itr->second)
|
|
{
|
|
// should remove spirit of redemption
|
|
if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
|
player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
|
|
|
|
if (!player->IsAlive())
|
|
{
|
|
player->ResurrectPlayer(1.0f);
|
|
player->SpawnCorpseBones();
|
|
}
|
|
|
|
if (Status == BG_SA_SECOND_WARMUP)
|
|
{
|
|
player->CastSpell(player, SPELL_PREPARATION, true);
|
|
player->GetMotionMaster()->MovementExpired();
|
|
}
|
|
|
|
player->ResetAllPowers();
|
|
player->CombatStopWithPets(true);
|
|
|
|
TeleportToEntrancePosition(player);
|
|
|
|
// xinef: one more time, just to be sure
|
|
if (Status == BG_SA_SECOND_WARMUP)
|
|
player->GetMotionMaster()->Clear(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::TeleportToEntrancePosition(Player* player)
|
|
{
|
|
if (player->GetTeamId() != Attackers)
|
|
{
|
|
player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
|
|
}
|
|
else
|
|
{
|
|
if (!ShipsStarted)
|
|
{
|
|
player->CastSpell(player, 12438, true);//Without this player falls before boat loads...
|
|
if (urand(0, 1))
|
|
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
|
|
else
|
|
player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
|
|
}
|
|
else
|
|
player->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::DefendersPortalTeleport(GameObject* portal, Player* plr)
|
|
{
|
|
if (plr->GetTeamId() == Attackers)
|
|
return;
|
|
|
|
uint32 portal_num = 0;
|
|
//get it via X
|
|
switch( (uint32)portal->GetPositionX() )
|
|
{
|
|
case 1394:
|
|
portal_num = 0;
|
|
break;
|
|
case 1065:
|
|
portal_num = 1;
|
|
break;
|
|
case 1468:
|
|
portal_num = 2;
|
|
break;
|
|
case 1255:
|
|
portal_num = 3;
|
|
break;
|
|
case 1216:
|
|
portal_num = 4;
|
|
break;
|
|
}
|
|
|
|
plr->TeleportTo( plr->GetMapId(), SOTADefPortalDest[portal_num][0], SOTADefPortalDest[portal_num][1], SOTADefPortalDest[portal_num][2], SOTADefPortalDest[portal_num][3], TELE_TO_SPELL );
|
|
}
|
|
|
|
void BattlegroundSA::EventPlayerDamagedGO(Player* /*player*/, GameObject* go, uint32 eventType)
|
|
{
|
|
if (!go || !go->GetGOInfo())
|
|
return;
|
|
|
|
if (eventType == go->GetGOInfo()->building.damagedEvent)
|
|
{
|
|
uint32 i = GetGateIDFromEntry(go->GetEntry());
|
|
GateStatus[i] = BG_SA_GATE_DAMAGED;
|
|
uint32 uws = GetWorldStateFromGateID(i);
|
|
if (uws)
|
|
UpdateWorldState(uws, GateStatus[i]);
|
|
}
|
|
|
|
if (eventType == go->GetGOInfo()->building.destroyedEvent)
|
|
{
|
|
if (go->GetGOInfo()->building.destroyedEvent == 19837)
|
|
SendWarningToAll(LANG_BG_SA_CHAMBER_BREACHED);
|
|
else
|
|
SendWarningToAll(LANG_BG_SA_WAS_DESTROYED, go->GetGOInfo()->name.c_str());
|
|
|
|
uint32 i = GetGateIDFromEntry(go->GetEntry());
|
|
switch (i)
|
|
{
|
|
case BG_SA_BLUE_GATE:
|
|
case BG_SA_GREEN_GATE:
|
|
{
|
|
GameObject* go = nullptr;
|
|
if ((go = GetBGObject(BG_SA_RED_GATE)))
|
|
go->SetDestructibleBuildingModifyState(true);
|
|
if ((go = GetBGObject(BG_SA_PURPLE_GATE)))
|
|
go->SetDestructibleBuildingModifyState(true);
|
|
break;
|
|
}
|
|
case BG_SA_RED_GATE:
|
|
case BG_SA_PURPLE_GATE:
|
|
if (GameObject* go = GetBGObject(BG_SA_YELLOW_GATE))
|
|
go->SetDestructibleBuildingModifyState(true);
|
|
break;
|
|
case BG_SA_YELLOW_GATE:
|
|
if (GameObject* go = GetBGObject(BG_SA_ANCIENT_GATE))
|
|
go->SetDestructibleBuildingModifyState(true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eventType == go->GetGOInfo()->building.damageEvent)
|
|
SendWarningToAll(LANG_BG_SA_IS_UNDER_ATTACK, go->GetGOInfo()->name.c_str());
|
|
}
|
|
|
|
void BattlegroundSA::HandleKillUnit(Creature* creature, Player* killer)
|
|
{
|
|
if (creature->GetEntry() == NPC_DEMOLISHER_SA)
|
|
{
|
|
UpdatePlayerScore(killer, SCORE_DESTROYED_DEMOLISHER, 1);
|
|
_notEvenAScratch[Attackers] = false;
|
|
creature->SetVisible(false);
|
|
}
|
|
}
|
|
|
|
/*
|
|
You may ask what the fuck does it do?
|
|
Prevents owner overwriting guns faction with own.
|
|
*/
|
|
void BattlegroundSA::OverrideGunFaction()
|
|
{
|
|
if (!BgCreatures[0])
|
|
return;
|
|
|
|
for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10; i++)
|
|
{
|
|
if (Creature* gun = GetBGCreature(i))
|
|
gun->setFaction(BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE]);
|
|
}
|
|
|
|
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
|
|
{
|
|
if (Creature* dem = GetBGCreature(i))
|
|
dem->setFaction(BG_SA_Factions[Attackers]);
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::DemolisherStartState(bool start)
|
|
{
|
|
if (!BgCreatures[0])
|
|
return;
|
|
|
|
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
|
|
if (Creature* dem = GetBGCreature(i))
|
|
{
|
|
if (start)
|
|
dem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
|
else
|
|
dem->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
|
}
|
|
|
|
for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10; i++)
|
|
if (Creature* gun = GetBGCreature(i))
|
|
{
|
|
if (start)
|
|
gun->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
|
else
|
|
gun->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
|
}
|
|
|
|
// xinef: enable first gates damaging at start
|
|
if (!start)
|
|
{
|
|
if (GameObject* go = GetBGObject(BG_SA_GREEN_GATE))
|
|
go->SetDestructibleBuildingModifyState(true);
|
|
if (GameObject* go = GetBGObject(BG_SA_BLUE_GATE))
|
|
go->SetDestructibleBuildingModifyState(true);
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::DestroyGate(Player* player, GameObject* go)
|
|
{
|
|
uint32 i = GetGateIDFromEntry(go->GetEntry());
|
|
if (!GateStatus[i])
|
|
return;
|
|
|
|
if (GameObject* g = GetBGObject(i))
|
|
{
|
|
if (g->GetGOValue()->Building.Health == 0)
|
|
{
|
|
GateStatus[i] = BG_SA_GATE_DESTROYED;
|
|
if (uint32 uws = GetWorldStateFromGateID(i))
|
|
UpdateWorldState(uws, GateStatus[i]);
|
|
|
|
bool rewardHonor = true;
|
|
switch (i)
|
|
{
|
|
case BG_SA_GREEN_GATE:
|
|
if (GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)
|
|
rewardHonor = false;
|
|
break;
|
|
case BG_SA_BLUE_GATE:
|
|
if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED)
|
|
rewardHonor = false;
|
|
break;
|
|
case BG_SA_RED_GATE:
|
|
if (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED)
|
|
rewardHonor = false;
|
|
break;
|
|
case BG_SA_PURPLE_GATE:
|
|
if (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED)
|
|
rewardHonor = false;
|
|
break;
|
|
}
|
|
|
|
UpdateObjectInteractionFlags();
|
|
|
|
if (i < 5)
|
|
DelObject(i + 9);
|
|
|
|
if (player)
|
|
{
|
|
UpdatePlayerScore(player, SCORE_DESTROYED_WALL, 1);
|
|
if (rewardHonor)
|
|
UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GraveyardStruct const* BattlegroundSA::GetClosestGraveyard(Player* player)
|
|
{
|
|
GraveyardStruct const* closest = nullptr;
|
|
float mindist = 999999.0f;
|
|
float x, y;
|
|
|
|
player->GetPosition(x, y);
|
|
|
|
for (uint8 i = BG_SA_BEACH_GY; i < BG_SA_MAX_GY; i++)
|
|
{
|
|
if (GraveyardStatus[i] != player->GetTeamId())
|
|
continue;
|
|
|
|
GraveyardStruct const* ret = sGraveyard->GetGraveyard(BG_SA_GYEntries[i]);
|
|
|
|
// if on beach
|
|
if (i == BG_SA_BEACH_GY)
|
|
{
|
|
if (x > 1400)
|
|
return ret;
|
|
continue;
|
|
}
|
|
|
|
float dist = sqrt(pow(ret->x - x, 2) * pow(ret->y - y, 2));
|
|
if (dist < mindist)
|
|
{
|
|
mindist = dist;
|
|
closest = ret;
|
|
}
|
|
}
|
|
if (!closest && GraveyardStatus[BG_SA_BEACH_GY] == player->GetTeamId())
|
|
return sGraveyard->GetGraveyard(BG_SA_GYEntries[BG_SA_BEACH_GY]);
|
|
|
|
return closest;
|
|
}
|
|
|
|
void BattlegroundSA::SendTime()
|
|
{
|
|
uint32 end_of_round = (EndRoundTimer - TotalTime);
|
|
UpdateWorldState(BG_SA_TIMER_MINS, end_of_round / 60000);
|
|
UpdateWorldState(BG_SA_TIMER_SEC_TENS, (end_of_round % 60000) / 10000);
|
|
UpdateWorldState(BG_SA_TIMER_SEC_DECS, ((end_of_round % 60000) % 10000) / 1000);
|
|
}
|
|
|
|
bool BattlegroundSA::CanInteractWithObject(uint32 objectId)
|
|
{
|
|
switch (objectId)
|
|
{
|
|
case BG_SA_TITAN_RELIC:
|
|
if (GateStatus[BG_SA_ANCIENT_GATE] != BG_SA_GATE_DESTROYED || GateStatus[BG_SA_YELLOW_GATE] != BG_SA_GATE_DESTROYED)
|
|
{
|
|
return false;
|
|
}
|
|
[[fallthrough]];
|
|
case BG_SA_CENTRAL_FLAG:
|
|
if (GateStatus[BG_SA_RED_GATE] != BG_SA_GATE_DESTROYED && GateStatus[BG_SA_PURPLE_GATE] != BG_SA_GATE_DESTROYED)
|
|
{
|
|
return false;
|
|
}
|
|
[[fallthrough]];
|
|
case BG_SA_LEFT_FLAG:
|
|
case BG_SA_RIGHT_FLAG:
|
|
if (GateStatus[BG_SA_GREEN_GATE] != BG_SA_GATE_DESTROYED && GateStatus[BG_SA_BLUE_GATE] != BG_SA_GATE_DESTROYED)
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
default:
|
|
ABORT();
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void BattlegroundSA::UpdateObjectInteractionFlags(uint32 objectId)
|
|
{
|
|
if (GameObject* go = GetBGObject(objectId))
|
|
{
|
|
if (CanInteractWithObject(objectId))
|
|
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE | GO_FLAG_INTERACT_COND | GO_FLAG_IN_USE);
|
|
else
|
|
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::UpdateObjectInteractionFlags()
|
|
{
|
|
for (uint8 i = BG_SA_CENTRAL_FLAG; i <= BG_SA_LEFT_FLAG; ++i)
|
|
UpdateObjectInteractionFlags(i);
|
|
UpdateObjectInteractionFlags(BG_SA_TITAN_RELIC);
|
|
}
|
|
|
|
void BattlegroundSA::EventPlayerClickedOnFlag(Player* Source, GameObject* gameObject)
|
|
{
|
|
switch (gameObject->GetEntry())
|
|
{
|
|
case 191307:
|
|
case 191308:
|
|
if (CanInteractWithObject(BG_SA_LEFT_FLAG))
|
|
CaptureGraveyard(BG_SA_LEFT_CAPTURABLE_GY, Source);
|
|
break;
|
|
case 191305:
|
|
case 191306:
|
|
if (CanInteractWithObject(BG_SA_RIGHT_FLAG))
|
|
CaptureGraveyard(BG_SA_RIGHT_CAPTURABLE_GY, Source);
|
|
break;
|
|
case 191310:
|
|
case 191309:
|
|
if (CanInteractWithObject(BG_SA_CENTRAL_FLAG))
|
|
CaptureGraveyard(BG_SA_CENTRAL_CAPTURABLE_GY, Source);
|
|
break;
|
|
default:
|
|
return;
|
|
};
|
|
}
|
|
|
|
void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
|
|
{
|
|
if (GraveyardStatus[i] == Attackers || Source->GetTeamId() != Attackers)
|
|
return;
|
|
|
|
GraveyardStatus[i] = Source->GetTeamId();
|
|
// Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
|
|
std::vector<uint64> ghost_list = m_ReviveQueue[BgCreatures[BG_SA_MAXNPC + i]];
|
|
if (!ghost_list.empty())
|
|
{
|
|
GraveyardStruct const* ClosestGrave = nullptr;
|
|
for (std::vector<uint64>::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
|
|
{
|
|
Player* player = ObjectAccessor::FindPlayer(*itr);
|
|
if (!player)
|
|
continue;
|
|
|
|
if (!ClosestGrave) // cache
|
|
ClosestGrave = GetClosestGraveyard(player);
|
|
|
|
if (ClosestGrave)
|
|
player->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, player->GetOrientation());
|
|
}
|
|
// xinef: clear resurrect queue for this creature
|
|
m_ReviveQueue[BgCreatures[BG_SA_MAXNPC + i]].clear();
|
|
}
|
|
|
|
DelCreature(BG_SA_MAXNPC + i);
|
|
|
|
GraveyardStruct const* sg = sGraveyard->GetGraveyard(BG_SA_GYEntries[i]);
|
|
if (!sg)
|
|
{
|
|
sLog->outError("BattlegroundSA::CaptureGraveyard: non-existant GY entry: %u", BG_SA_GYEntries[i]);
|
|
return;
|
|
}
|
|
|
|
AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], GraveyardStatus[i]);
|
|
uint32 npc = 0;
|
|
uint32 flag = 0;
|
|
|
|
switch(i)
|
|
{
|
|
case BG_SA_LEFT_CAPTURABLE_GY:
|
|
flag = BG_SA_LEFT_FLAG;
|
|
DelObject(flag);
|
|
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
|
|
BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1],
|
|
BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY);
|
|
|
|
npc = BG_SA_NPC_RIGSPARK;
|
|
AddCreature(BG_SA_NpcEntries[npc], npc, Attackers,
|
|
BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1],
|
|
BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]);
|
|
|
|
for (uint8 j = BG_SA_DEMOLISHER_7; j <= BG_SA_DEMOLISHER_8; j++)
|
|
{
|
|
AddCreature(BG_SA_NpcEntries[j], j,
|
|
BG_SA_NpcSpawnlocs[j][0], BG_SA_NpcSpawnlocs[j][1],
|
|
BG_SA_NpcSpawnlocs[j][2], BG_SA_NpcSpawnlocs[j][3], 600);
|
|
|
|
if (Creature* dem = GetBGCreature(j))
|
|
dem->setFaction(BG_SA_Factions[Attackers]);
|
|
}
|
|
|
|
UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0));
|
|
UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1));
|
|
if (Source->GetTeamId() == TEAM_ALLIANCE)
|
|
SendWarningToAll(LANG_BG_SA_A_GY_WEST);
|
|
else
|
|
SendWarningToAll(LANG_BG_SA_H_GY_WEST);
|
|
break;
|
|
case BG_SA_RIGHT_CAPTURABLE_GY:
|
|
flag = BG_SA_RIGHT_FLAG;
|
|
DelObject(flag);
|
|
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
|
|
BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1],
|
|
BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY);
|
|
|
|
npc = BG_SA_NPC_SPARKLIGHT;
|
|
AddCreature(BG_SA_NpcEntries[npc], npc,
|
|
BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1],
|
|
BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]);
|
|
|
|
for (uint8 j = BG_SA_DEMOLISHER_5; j <= BG_SA_DEMOLISHER_6; j++)
|
|
{
|
|
AddCreature(BG_SA_NpcEntries[j], j, BG_SA_NpcSpawnlocs[j][0], BG_SA_NpcSpawnlocs[j][1],
|
|
BG_SA_NpcSpawnlocs[j][2], BG_SA_NpcSpawnlocs[j][3], 600);
|
|
|
|
if (Creature* dem = GetBGCreature(j))
|
|
dem->setFaction(BG_SA_Factions[Attackers]);
|
|
}
|
|
|
|
UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0));
|
|
UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1));
|
|
if (Source->GetTeamId() == TEAM_ALLIANCE)
|
|
SendWarningToAll(LANG_BG_SA_A_GY_EAST);
|
|
else
|
|
SendWarningToAll(LANG_BG_SA_H_GY_EAST);
|
|
break;
|
|
case BG_SA_CENTRAL_CAPTURABLE_GY:
|
|
flag = BG_SA_CENTRAL_FLAG;
|
|
DelObject(flag);
|
|
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
|
|
BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1],
|
|
BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY);
|
|
|
|
UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0));
|
|
UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1));
|
|
if (Source->GetTeamId() == TEAM_ALLIANCE)
|
|
SendWarningToAll(LANG_BG_SA_A_GY_SOUTH);
|
|
else
|
|
SendWarningToAll(LANG_BG_SA_H_GY_SOUTH);
|
|
break;
|
|
default:
|
|
ABORT();
|
|
break;
|
|
};
|
|
}
|
|
|
|
void BattlegroundSA::EventPlayerUsedGO(Player* Source, GameObject* object)
|
|
{
|
|
if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] && CanInteractWithObject(BG_SA_TITAN_RELIC))
|
|
{
|
|
if (Source->GetTeamId() == Attackers)
|
|
{
|
|
if (Source->GetTeamId() == TEAM_ALLIANCE)
|
|
SendMessageToAll(LANG_BG_SA_ALLIANCE_CAPTURED_RELIC, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
|
else SendMessageToAll(LANG_BG_SA_HORDE_CAPTURED_RELIC, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
|
|
|
if (Status == BG_SA_ROUND_ONE)
|
|
{
|
|
_relicClicked = true;
|
|
}
|
|
else if (Status == BG_SA_ROUND_TWO)
|
|
{
|
|
RoundScores[1].winner = Attackers;
|
|
RoundScores[1].time = TotalTime;
|
|
ToggleTimer();
|
|
//Achievement Storm the Beach (1310)
|
|
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
|
if (itr->second->GetTeamId() == Attackers && RoundScores[1].winner == Attackers)
|
|
itr->second->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
|
|
|
|
if (RoundScores[0].time == RoundScores[1].time)
|
|
EndBattleground(TEAM_NEUTRAL);
|
|
else if (RoundScores[0].time < RoundScores[1].time)
|
|
EndBattleground(RoundScores[0].winner);
|
|
else
|
|
EndBattleground(RoundScores[1].winner);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::ToggleTimer()
|
|
{
|
|
TimerEnabled = !TimerEnabled;
|
|
UpdateWorldState(BG_SA_ENABLE_TIMER, (TimerEnabled) ? 1 : 0);
|
|
}
|
|
|
|
void BattlegroundSA::EndBattleground(TeamId winnerTeamId)
|
|
{
|
|
//honor reward for winning
|
|
RewardHonorToTeam(GetBonusHonorFromKill(1), winnerTeamId);
|
|
|
|
//complete map_end rewards (even if no team wins)
|
|
RewardHonorToTeam(GetBonusHonorFromKill(2), TEAM_ALLIANCE);
|
|
RewardHonorToTeam(GetBonusHonorFromKill(2), TEAM_HORDE);
|
|
|
|
Battleground::EndBattleground(winnerTeamId);
|
|
}
|
|
|
|
void BattlegroundSA::UpdateDemolisherSpawns()
|
|
{
|
|
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_8; i++)
|
|
{
|
|
if (BgCreatures[i])
|
|
{
|
|
if (Creature* Demolisher = GetBGCreature(i))
|
|
{
|
|
if (Demolisher->isDead())
|
|
{
|
|
// Demolisher is not in list
|
|
if (DemoliserRespawnList.find(i) == DemoliserRespawnList.end())
|
|
{
|
|
DemoliserRespawnList[i] = World::GetGameTimeMS() + 30000;
|
|
}
|
|
else
|
|
{
|
|
if (DemoliserRespawnList[i] < World::GetGameTimeMS())
|
|
{
|
|
Demolisher->Relocate(BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1],
|
|
BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3]);
|
|
|
|
Demolisher->SetVisible(true);
|
|
Demolisher->Respawn();
|
|
DemoliserRespawnList.erase(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::SendTransportInit(Player* player)
|
|
{
|
|
if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO])
|
|
{
|
|
UpdateData transData;
|
|
if (BgObjects[BG_SA_BOAT_ONE])
|
|
GetBGObject(BG_SA_BOAT_ONE)->BuildCreateUpdateBlockForPlayer(&transData, player);
|
|
if (BgObjects[BG_SA_BOAT_TWO])
|
|
GetBGObject(BG_SA_BOAT_TWO)->BuildCreateUpdateBlockForPlayer(&transData, player);
|
|
WorldPacket packet;
|
|
transData.BuildPacket(&packet);
|
|
player->GetSession()->SendPacket(&packet);
|
|
}
|
|
}
|
|
|
|
void BattlegroundSA::SendTransportsRemove(Player* player)
|
|
{
|
|
if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO])
|
|
{
|
|
UpdateData transData;
|
|
if (BgObjects[BG_SA_BOAT_ONE])
|
|
GetBGObject(BG_SA_BOAT_ONE)->BuildOutOfRangeUpdateBlock(&transData);
|
|
if (BgObjects[BG_SA_BOAT_TWO])
|
|
GetBGObject(BG_SA_BOAT_TWO)->BuildOutOfRangeUpdateBlock(&transData);
|
|
WorldPacket packet;
|
|
transData.BuildPacket(&packet);
|
|
player->GetSession()->SendPacket(&packet);
|
|
}
|
|
}
|
|
|
|
bool BattlegroundSA::AllowDefenseOfTheAncients(Player* source)
|
|
{
|
|
if (source->GetTeamId() == Attackers)
|
|
return false;
|
|
|
|
for (uint8 i = 0; i <= 5; i++)
|
|
{
|
|
if (GateStatus[i] == BG_SA_GATE_DESTROYED)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|