[8608] implement BattleGround Alterac Valley

sql won't be included - please look at your database
providers forum

also note, that creature_loot_template id 0
is used for the loot of dead players in this bg
(after a player died and you remove insignia from him..
he not only drops money - he drops some random items too)

further work must be done in better code for adjusting right
levels to creatures - maybe using something similar like it's
done in heroic instances

also quests and creatures needs some scripts in future

thanks to:
netsky - initial start of this patch
bogie - 2nd person writing on this patch
triply, kapatejib, vladimir - code review and suggestions
arrai - for his great tool and help
and all testers / code contributers - I won't write
down a list, else I would forget most probably one ^^
This commit is contained in:
balrok 2009-10-07 11:57:28 +02:00
parent ed5130c1c1
commit 45f6a474bf
20 changed files with 1795 additions and 139 deletions

View file

@ -80,6 +80,53 @@ namespace MaNGOS
va_list* i_args;
};
class BattleGroundYellBuilder
{
public:
BattleGroundYellBuilder(uint32 language, int32 textId, Creature const* source, va_list* args = NULL)
: i_language(language), i_textId(textId), i_source(source), i_args(args) {}
void operator()(WorldPacket& data, int32 loc_idx)
{
char const* text = objmgr.GetMangosString(i_textId,loc_idx);
if(i_args)
{
// we need copy va_list before use or original va_list will corrupted
va_list ap;
va_copy(ap,*i_args);
char str [2048];
vsnprintf(str,2048,text, ap );
va_end(ap);
do_helper(data,&str[0]);
}
else
do_helper(data,text);
}
private:
void do_helper(WorldPacket& data, char const* text)
{
//copyied from BuildMonsterChat
data << (uint8)CHAT_MSG_MONSTER_YELL;
data << (uint32)i_language;
data << (uint64)i_source->GetGUID();
data << (uint32)0; //2.1.0
data << (uint32)(strlen(i_source->GetName())+1);
data << i_source->GetName();
data << (uint64)0; //Unit Target - isn't important for bgs
data << (uint32)strlen(text)+1;
data << text;
data << (uint8)0; // ChatTag - for bgs allways 0?
}
uint32 i_language;
int32 i_textId;
Creature const* i_source;
va_list* i_args;
};
class BattleGround2ChatBuilder
{
public:
@ -113,6 +160,40 @@ namespace MaNGOS
int32 i_arg1;
int32 i_arg2;
};
class BattleGround2YellBuilder
{
public:
BattleGround2YellBuilder(uint32 language, int32 textId, Creature const* source, int32 arg1, int32 arg2)
: i_language(language), i_textId(textId), i_source(source), i_arg1(arg1), i_arg2(arg2) {}
void operator()(WorldPacket& data, int32 loc_idx)
{
char const* text = objmgr.GetMangosString(i_textId,loc_idx);
char const* arg1str = i_arg1 ? objmgr.GetMangosString(i_arg1,loc_idx) : "";
char const* arg2str = i_arg2 ? objmgr.GetMangosString(i_arg2,loc_idx) : "";
char str [2048];
snprintf(str,2048,text, arg1str, arg2str );
//copyied from BuildMonsterChat
data << (uint8)CHAT_MSG_MONSTER_YELL;
data << (uint32)i_language;
data << (uint64)i_source->GetGUID();
data << (uint32)0; //2.1.0
data << (uint32)(strlen(i_source->GetName())+1);
data << i_source->GetName();
data << (uint64)0; //Unit Target - isn't important for bgs
data << (uint32)strlen(str)+1;
data << str;
data << (uint8)0; // ChatTag - for bgs allways 0?
}
private:
uint32 i_language;
int32 i_textId;
Creature const* i_source;
int32 i_arg1;
int32 i_arg2;
};
} // namespace MaNGOS
template<class Do>
@ -664,6 +745,12 @@ void BattleGround::EndBattleGround(uint32 winner)
plr->ResurrectPlayer(1.0f);
plr->SpawnCorpseBones();
}
else
{
//needed cause else in av some creatures will kill the players at the end
plr->CombatStop();
plr->getHostilRefManager().deleteReferences();
}
//this line is obsolete - team is set ALWAYS
//if(!team) team = plr->GetTeam();
@ -1381,6 +1468,13 @@ void BattleGround::OnObjectDBLoad(Creature* creature)
SpawnBGCreature(creature->GetGUID(), RESPAWN_ONE_DAY);
}
uint64 BattleGround::GetSingleCreatureGuid(uint8 event1, uint8 event2)
{
BGCreatures::const_iterator itr = m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.begin();
if (itr != m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.end())
return *itr;
return 0;
}
void BattleGround::OnObjectDBLoad(GameObject* obj)
{
@ -1525,6 +1619,16 @@ void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* sou
BroadcastWorker(bg_do);
}
void BattleGround::SendYellToAll(int32 entry, uint32 language, uint64 const& guid)
{
Creature* source = GetBgMap()->GetCreature(guid);
if(!source)
return;
MaNGOS::BattleGroundYellBuilder bg_builder(language, entry, source);
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundYellBuilder> bg_do(bg_builder);
BroadcastWorker(bg_do);
}
void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...)
{
va_list ap;
@ -1544,6 +1648,16 @@ void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* so
BroadcastWorker(bg_do);
}
void BattleGround::SendYell2ToAll(int32 entry, uint32 language, uint64 const& guid, int32 arg1, int32 arg2)
{
Creature* source = GetBgMap()->GetCreature(guid);
if(!source)
return;
MaNGOS::BattleGround2YellBuilder bg_builder(language, entry, source, arg1, arg2);
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGround2YellBuilder> bg_do(bg_builder);
BroadcastWorker(bg_do);
}
void BattleGround::EndNow()
{
RemoveFromBGFreeSlotQueue();
@ -1604,8 +1718,6 @@ void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
void BattleGround::HandleKillPlayer( Player *player, Player *killer )
{
//keep in mind that for arena this will have to be changed a bit
// add +1 deaths
UpdatePlayerScore(player, SCORE_DEATHS, 1);

View file

@ -198,10 +198,7 @@ enum ScoreType
SCORE_GRAVEYARDS_DEFENDED = 12,
SCORE_TOWERS_ASSAULTED = 13,
SCORE_TOWERS_DEFENDED = 14,
SCORE_MINES_CAPTURED = 15,
SCORE_LEADERS_KILLED = 16,
SCORE_SECONDARY_OBJECTIVES = 17
// TODO : implement them
SCORE_SECONDARY_OBJECTIVES = 15
};
enum ArenaType
@ -439,10 +436,12 @@ class BattleGround
void BlockMovement(Player *plr);
void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL);
void SendYellToAll(int32 entry, uint32 language, uint64 const& guid);
void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ... );
// specialized version with 2 string id args
void SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 strId1 = 0, int32 strId2 = 0);
void SendYell2ToAll(int32 entry, uint32 language, uint64 const& guid, int32 arg1, int32 arg2);
/* Raid Group */
Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; }
@ -473,6 +472,7 @@ class BattleGround
virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {}
// must be implemented in BG subclass if need AND call base class generic code
virtual void HandleKillPlayer(Player *player, Player *killer);
virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/) { return; };
/* Battleground events */
virtual void EventPlayerDroppedFlag(Player* /*player*/) {}
@ -505,10 +505,14 @@ class BattleGround
return false;
return m_ActiveEvents[event1] == event2;
}
uint64 GetSingleCreatureGuid(uint8 event1, uint8 event2);
void OpenDoorEvent(uint8 event1, uint8 event2 = 0);
bool IsDoor(uint8 event1, uint8 event2);
/* other things */
virtual void OnCreatureRespawn(Creature* /*creature*/) {}
void HandleTriggerBuff(uint64 const& go_guid);
// TODO: make this protected:

View file

@ -191,20 +191,17 @@ void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch(Trigger)
{
case 3948: // Arathi Basin Alliance Exit.
if (Source->GetTeam() != ALLIANCE)
Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_ALLIANCE_USE);
else
Source->LeaveBattleground();
break;
case 3949: // Arathi Basin Horde Exit.
if (Source->GetTeam() != HORDE)
Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_HORDE_USE);
else
Source->LeaveBattleground();
break;

View file

@ -16,81 +16,390 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Object.h"
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundAV.h"
#include "BattleGroundMgr.h"
#include "Creature.h"
#include "GameObject.h"
#include "Language.h"
#include "WorldPacket.h"
BattleGroundAV::BattleGroundAV()
{
//TODO FIX ME!
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN;
}
BattleGroundAV::~BattleGroundAV()
{
}
void BattleGroundAV::HandleKillPlayer(Player *player, Player *killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
BattleGround::HandleKillPlayer(player, killer);
UpdateScore(GetTeamIndexByTeamId(player->GetTeam()), -1);
}
void BattleGroundAV::HandleKillUnit(Creature *creature, Player *killer)
{
sLog.outDebug("BattleGroundAV: HandleKillUnit %i", creature->GetEntry());
if (GetStatus() != STATUS_IN_PROGRESS)
return;
uint8 event1 = (sBattleGroundMgr.GetCreatureEventIndex(creature->GetDBTableGUIDLow())).event1;
if (event1 == BG_EVENT_NONE)
return;
switch(event1)
{
case BG_AV_BOSS_A:
CastSpellOnTeam(BG_AV_BOSS_KILL_QUEST_SPELL, HORDE); // this is a spell which finishes a quest where a player has to kill the boss
RewardReputationToTeam(BG_AV_FACTION_H, m_RepBoss, HORDE);
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), HORDE);
SendYellToAll(LANG_BG_AV_H_GENERAL_DEAD, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0));
EndBattleGround(HORDE);
break;
case BG_AV_BOSS_H:
CastSpellOnTeam(BG_AV_BOSS_KILL_QUEST_SPELL, ALLIANCE); // this is a spell which finishes a quest where a player has to kill the boss
RewardReputationToTeam(BG_AV_FACTION_A, m_RepBoss, ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), ALLIANCE);
SendYellToAll(LANG_BG_AV_A_GENERAL_DEAD, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0));
EndBattleGround(ALLIANCE);
break;
case BG_AV_CAPTAIN_A:
if (IsActiveEvent(BG_AV_NodeEventCaptainDead_A, 0))
return;
RewardReputationToTeam(BG_AV_FACTION_H, m_RepCaptain, HORDE);
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), HORDE);
UpdateScore(BG_TEAM_ALLIANCE, (-1) * BG_AV_RES_CAPTAIN);
// spawn destroyed aura
SpawnEvent(BG_AV_NodeEventCaptainDead_A, 0, true);
break;
case BG_AV_CAPTAIN_H:
if (IsActiveEvent(BG_AV_NodeEventCaptainDead_H, 0))
return;
RewardReputationToTeam(BG_AV_FACTION_A, m_RepCaptain, ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), ALLIANCE);
UpdateScore(BG_TEAM_HORDE, (-1) * BG_AV_RES_CAPTAIN);
// spawn destroyed aura
SpawnEvent(BG_AV_NodeEventCaptainDead_H, 0, true);
break;
case BG_AV_MINE_BOSSES_NORTH:
ChangeMineOwner(BG_AV_NORTH_MINE, GetTeamIndexByTeamId(killer->GetTeam()));
break;
case BG_AV_MINE_BOSSES_SOUTH:
ChangeMineOwner(BG_AV_SOUTH_MINE, GetTeamIndexByTeamId(killer->GetTeam()));
break;
}
}
void BattleGroundAV::HandleQuestComplete(uint32 questid, Player *player)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
uint8 team = GetTeamIndexByTeamId(player->GetTeam());
uint32 reputation = 0; // reputation for the whole team (other reputation must be done in db)
// TODO add events (including quest not available anymore, next quest availabe, go/npc de/spawning)
sLog.outError("BattleGroundAV: Quest %i completed", questid);
switch(questid)
{
case BG_AV_QUEST_A_SCRAPS1:
case BG_AV_QUEST_A_SCRAPS2:
case BG_AV_QUEST_H_SCRAPS1:
case BG_AV_QUEST_H_SCRAPS2:
m_Team_QuestStatus[team][0] += 20;
reputation = 1;
if( m_Team_QuestStatus[team][0] == 500 || m_Team_QuestStatus[team][0] == 1000 || m_Team_QuestStatus[team][0] == 1500 ) //25,50,75 turn ins
{
sLog.outDebug("BattleGroundAV: Quest %i completed starting with unit upgrading..", questid);
for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i)
if (m_Nodes[i].Owner == team && m_Nodes[i].State == POINT_CONTROLLED)
PopulateNode(i);
}
break;
case BG_AV_QUEST_A_COMMANDER1:
case BG_AV_QUEST_H_COMMANDER1:
m_Team_QuestStatus[team][1]++;
reputation = 1;
if (m_Team_QuestStatus[team][1] == 120)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
break;
case BG_AV_QUEST_A_COMMANDER2:
case BG_AV_QUEST_H_COMMANDER2:
m_Team_QuestStatus[team][2]++;
reputation = 2;
if (m_Team_QuestStatus[team][2] == 60)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
break;
case BG_AV_QUEST_A_COMMANDER3:
case BG_AV_QUEST_H_COMMANDER3:
m_Team_QuestStatus[team][3]++;
reputation = 5;
RewardReputationToTeam(team, 1, player->GetTeam());
if (m_Team_QuestStatus[team][1] == 30)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
break;
case BG_AV_QUEST_A_BOSS1:
case BG_AV_QUEST_H_BOSS1:
m_Team_QuestStatus[team][4] += 4; // there are 2 quests where you can turn in 5 or 1 item.. ( + 4 cause +1 will be done some lines below)
reputation = 4;
case BG_AV_QUEST_A_BOSS2:
case BG_AV_QUEST_H_BOSS2:
m_Team_QuestStatus[team][4]++;
reputation += 1;
if (m_Team_QuestStatus[team][4] >= 200)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
break;
case BG_AV_QUEST_A_NEAR_MINE:
case BG_AV_QUEST_H_NEAR_MINE:
m_Team_QuestStatus[team][5]++;
reputation = 2;
if (m_Team_QuestStatus[team][5] == 28)
{
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
if (m_Team_QuestStatus[team][6] == 7)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - ground assault ready", questid);
}
break;
case BG_AV_QUEST_A_OTHER_MINE:
case BG_AV_QUEST_H_OTHER_MINE:
m_Team_QuestStatus[team][6]++;
reputation = 3;
if (m_Team_QuestStatus[team][6] == 7)
{
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
if (m_Team_QuestStatus[team][5] == 20)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - ground assault ready", questid);
}
break;
case BG_AV_QUEST_A_RIDER_HIDE:
case BG_AV_QUEST_H_RIDER_HIDE:
m_Team_QuestStatus[team][7]++;
reputation = 1;
if (m_Team_QuestStatus[team][7] == 25)
{
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
if (m_Team_QuestStatus[team][8] == 25)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - rider assault ready", questid);
}
break;
case BG_AV_QUEST_A_RIDER_TAME:
case BG_AV_QUEST_H_RIDER_TAME:
m_Team_QuestStatus[team][8]++;
reputation = 1;
if (m_Team_QuestStatus[team][8] == 25)
{
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here", questid);
if (m_Team_QuestStatus[team][7] == 25)
sLog.outDebug("BattleGroundAV: Quest %i completed (need to implement some events here - rider assault ready", questid);
}
break;
default:
sLog.outDebug("BattleGroundAV: Quest %i completed but is not interesting for us", questid);
return;
break;
}
if (reputation)
RewardReputationToTeam((player->GetTeam() == ALLIANCE) ? BG_AV_FACTION_A : BG_AV_FACTION_H, reputation, player->GetTeam());
}
void BattleGroundAV::UpdateScore(BattleGroundTeamId team, int32 points )
{
// note: to remove reinforcements points must be negative, for adding reinforcements points must be positive
assert( team == BG_TEAM_ALLIANCE || team == BG_TEAM_HORDE);
m_TeamScores[team] += points; // m_TeamScores is int32 - so no problems here
if (points < 0)
{
if (m_TeamScores[team] < 1)
{
m_TeamScores[team] = 0;
// other team will win:
EndBattleGround((team == BG_TEAM_ALLIANCE)? HORDE : ALLIANCE);
}
else if (!m_IsInformedNearLose[team] && m_TeamScores[team] < BG_AV_SCORE_NEAR_LOSE)
{
SendMessageToAll((team == BG_TEAM_HORDE) ? LANG_BG_AV_H_NEAR_LOSE : LANG_BG_AV_A_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_AV_SOUND_NEAR_LOSE);
m_IsInformedNearLose[team] = true;
}
}
// must be called here, else it could display a negative value
UpdateWorldState(((team == BG_TEAM_HORDE) ? BG_AV_Horde_Score : BG_AV_Alliance_Score), m_TeamScores[team]);
}
void BattleGroundAV::OnObjectDBLoad(Creature* creature)
{
uint32 level = creature->getLevel();
if (level != 0)
level += GetMaxLevel() - 60; // maybe we can do this more generic for custom level - range.. actually it's ok
creature->SetLevel(level);
BattleGround::OnObjectDBLoad(creature);
}
void BattleGroundAV::OnCreatureRespawn(Creature* creature)
{
uint32 level = creature->getLevel();
if (level != 0)
level += GetMaxLevel() - 60; // maybe we can do this more generic for custom level - range.. actually it's ok
creature->SetLevel(level);
}
void BattleGroundAV::Update(uint32 diff)
{
BattleGround::Update(diff);
if (GetStatus() != STATUS_IN_PROGRESS)
return;
// add points from mine owning, and look if the neutral team can reclaim the mine
for(uint8 mine = 0; mine < BG_AV_MAX_MINES; mine++)
{
if (m_Mine_Owner[mine] == BG_TEAM_ALLIANCE || m_Mine_Owner[mine] == BG_TEAM_HORDE)
{
m_Mine_Timer[mine] -=diff;
if (m_Mine_Timer[mine] <= 0)
{
UpdateScore(BattleGroundTeamId(m_Mine_Owner[mine]), 1);
m_Mine_Timer[mine] = BG_AV_MINE_TICK_TIMER;
}
if (m_Mine_Reclaim_Timer[mine] > diff)
m_Mine_Reclaim_Timer[mine] -= diff;
else
ChangeMineOwner(mine, BG_AV_NEUTRAL_TEAM);
}
}
// looks for all timers of the nodes and destroy the building (for graveyards the building wont get destroyed, it goes just to the other team
for(BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
{
if (m_Nodes[i].State == POINT_ASSAULTED)
{
if (m_Nodes[i].Timer > diff)
m_Nodes[i].Timer -= diff;
else
EventPlayerDestroyedPoint(i);
}
}
}
void BattleGroundAV::StartingEventCloseDoors()
{
sLog.outDebug("BattleGroundAV: entering state STATUS_WAIT_JOIN ...");
}
void BattleGroundAV::StartingEventOpenDoors()
{
UpdateWorldState(BG_AV_SHOW_H_SCORE, 1);
UpdateWorldState(BG_AV_SHOW_A_SCORE, 1);
OpenDoorEvent(BG_EVENT_DOOR);
}
void BattleGroundAV::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
//create score and add it to map, default values are set in constructor
// create score and add it to map, default values are set in constructor
BattleGroundAVScore* sc = new BattleGroundAVScore;
m_PlayerScores[plr->GetGUID()] = sc;
}
void BattleGroundAV::RemovePlayer(Player* /*plr*/,uint64 /*guid*/)
void BattleGroundAV::EndBattleGround(uint32 winner)
{
// calculate bonuskills for both teams:
uint32 tower_survived[BG_TEAMS_COUNT] = {0, 0};
uint32 graves_owned[BG_TEAMS_COUNT] = {0, 0};
uint32 mines_owned[BG_TEAMS_COUNT] = {0, 0};
// towers all not destroyed:
for(BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i)
if (m_Nodes[i].State == POINT_CONTROLLED)
if (m_Nodes[i].TotalOwner == BG_TEAM_ALLIANCE)
++tower_survived[BG_TEAM_ALLIANCE];
for(BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i)
if (m_Nodes[i].State == POINT_CONTROLLED)
if (m_Nodes[i].TotalOwner == BG_TEAM_HORDE)
++tower_survived[BG_TEAM_HORDE];
// graves all controlled
for(BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
if (m_Nodes[i].State == POINT_CONTROLLED)
++graves_owned[m_Nodes[i].Owner];
for (uint32 i = 0; i < BG_AV_MAX_MINES; ++i)
if (m_Mine_Owner[i] != BG_AV_NEUTRAL_TEAM)
++mines_owned[m_Mine_Owner[i]];
// now we have the values give the honor/reputation to the teams:
uint32 team[BG_TEAMS_COUNT] = { ALLIANCE, HORDE };
uint32 faction[BG_TEAMS_COUNT] = { BG_AV_FACTION_A, BG_AV_FACTION_H };
for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
{
if (tower_survived[i])
{
RewardReputationToTeam(faction[i], tower_survived[i] * m_RepSurviveTower, team[i]);
RewardHonorToTeam(GetBonusHonorFromKill(tower_survived[i] * BG_AV_KILL_SURVIVING_TOWER), team[i]);
}
sLog.outDebug("BattleGroundAV: EndbattleGround: bgteam: %u towers:%u honor:%u rep:%u", i, tower_survived[i], GetBonusHonorFromKill(tower_survived[i] * BG_AV_KILL_SURVIVING_TOWER), tower_survived[i] * BG_AV_REP_SURVIVING_TOWER);
if (graves_owned[i])
RewardReputationToTeam(faction[i], graves_owned[i] * m_RepOwnedGrave, team[i]);
if (mines_owned[i])
RewardReputationToTeam(faction[i], mines_owned[i] * m_RepOwnedMine, team[i]);
// captain survived?:
if (!IsActiveEvent(BG_AV_NodeEventCaptainDead_A + GetTeamIndexByTeamId(team[i]), 0))
{
RewardReputationToTeam(faction[i], m_RepSurviveCaptain, team[i]);
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_SURVIVING_CAPTAIN), team[i]);
}
}
// both teams:
if (m_HonorMapComplete)
{
RewardHonorToTeam(m_HonorMapComplete, ALLIANCE);
RewardHonorToTeam(m_HonorMapComplete, HORDE);
}
BattleGround::EndBattleGround(winner);
}
void BattleGroundAV::RemovePlayer(Player* plr,uint64 /*guid*/)
{
}
void BattleGroundAV::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;
uint32 SpellId = 0;
switch(Trigger)
{
case 95:
case 2606:
case 2608:
if (Source->GetTeam() != ALLIANCE)
Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_ALLIANCE_USE);
else
Source->LeaveBattleground();
break;
case 2606:
if (Source->GetTeam() != HORDE)
Source->GetSession()->SendNotification(LANG_BATTLEGROUND_ONLY_HORDE_USE);
else
Source->LeaveBattleground();
break;
case 3326:
case 3327:
case 3328:
case 3329:
case 3330:
case 3331:
//Source->Unmount();
break;
default:
sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);
Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
sLog.outDebug("BattleGroundAV: WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);
// Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
break;
}
if (SpellId)
Source->CastSpell(Source, SpellId, true);
}
void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
@ -114,17 +423,419 @@ void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value
case SCORE_TOWERS_DEFENDED:
((BattleGroundAVScore*)itr->second)->TowersDefended += value;
break;
case SCORE_MINES_CAPTURED:
((BattleGroundAVScore*)itr->second)->MinesCaptured += value;
break;
case SCORE_LEADERS_KILLED:
((BattleGroundAVScore*)itr->second)->LeadersKilled += value;
break;
case SCORE_SECONDARY_OBJECTIVES:
((BattleGroundAVScore*)itr->second)->SecondaryObjectives += value;
break;
default:
BattleGround::UpdatePlayerScore(Source,type,value);
BattleGround::UpdatePlayerScore(Source, type, value);
break;
}
}
void BattleGroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
{
sLog.outDebug("BattleGroundAV: player destroyed point node %i", node);
// despawn banner
DestroyNode(node);
PopulateNode(node);
UpdateNodeWorldState(node);
uint32 owner = m_Nodes[node].Owner;
if (IsTower(node))
{
uint8 tmp = node - BG_AV_NODES_DUNBALDAR_SOUTH;
// despawn marshal (one of those guys protecting the boss)
SpawnEvent(BG_AV_MARSHAL_A_SOUTH + tmp, 0, false);
UpdateScore(BattleGroundTeamId(owner^0x1), (-1) * BG_AV_RES_TOWER);
RewardReputationToTeam((owner == BG_TEAM_ALLIANCE) ? BG_AV_FACTION_A : BG_AV_FACTION_H, m_RepTowerDestruction, owner);
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_TOWER), owner);
SendYell2ToAll(LANG_BG_AV_TOWER_TAKEN, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), GetNodeName(node), ( owner == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY : LANG_BG_AV_HORDE);
}
else
{
SendYell2ToAll(LANG_BG_AV_GRAVE_TAKEN, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0), GetNodeName(node), ( owner == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY : LANG_BG_AV_HORDE);
}
}
void BattleGroundAV::ChangeMineOwner(uint8 mine, uint32 team)
{
m_Mine_Timer[mine] = BG_AV_MINE_TICK_TIMER;
// TODO implement quest 7122
// mine=0 northmine, mine=1 southmine
// TODO changing the owner should result in setting respawntime to infinite for current creatures (they should fight the new ones), spawning new mine owners creatures and changing the chest - objects so that the current owning team can use them
assert(mine == BG_AV_NORTH_MINE || mine == BG_AV_SOUTH_MINE);
if (m_Mine_Owner[mine] == int8(team))
return;
if (team != BG_TEAM_ALLIANCE && team != BG_TEAM_HORDE)
team = BG_AV_NEUTRAL_TEAM;
m_Mine_PrevOwner[mine] = m_Mine_Owner[mine];
m_Mine_Owner[mine] = team;
SendMineWorldStates(mine);
SpawnEvent(BG_AV_MINE_EVENT + mine, team, true);
SpawnEvent(BG_AV_MINE_BOSSES + mine, team, true);
if (team == BG_TEAM_ALLIANCE || team == BG_TEAM_HORDE)
{
PlaySoundToAll((team == BG_TEAM_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_GOOD : BG_AV_SOUND_HORDE_GOOD);
m_Mine_Reclaim_Timer[mine] = BG_AV_MINE_RECLAIM_TIMER;
SendYell2ToAll(LANG_BG_AV_MINE_TAKEN , LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
(team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY : LANG_BG_AV_HORDE,
(mine == BG_AV_NORTH_MINE) ? LANG_BG_AV_MINE_NORTH : LANG_BG_AV_MINE_SOUTH);
}
}
bool BattleGroundAV::PlayerCanDoMineQuest(int32 GOId, uint32 team)
{
if (GOId == BG_AV_OBJECTID_MINE_N)
return (m_Mine_Owner[BG_AV_NORTH_MINE] == GetTeamIndexByTeamId(team));
if (GOId == BG_AV_OBJECTID_MINE_S)
return (m_Mine_Owner[BG_AV_SOUTH_MINE] == GetTeamIndexByTeamId(team));
return true; // cause it's no mine'object it is ok if this is true
}
/// will spawn and despawn creatures around a node
/// more a wrapper around spawnevent cause graveyards are special
void BattleGroundAV::PopulateNode(BG_AV_Nodes node)
{
uint32 team = m_Nodes[node].Owner;
if (IsGrave(node) && team != BG_AV_NEUTRAL_TEAM)
{
uint32 graveDefenderType;
if (m_Team_QuestStatus[team][0] < 500 )
graveDefenderType = 0;
else if (m_Team_QuestStatus[team][0] < 1000 )
graveDefenderType = 1;
else if (m_Team_QuestStatus[team][0] < 1500 )
graveDefenderType = 2;
else
graveDefenderType = 3;
if (m_Nodes[node].State == POINT_CONTROLLED) // we can spawn the current owner event
SpawnEvent(BG_AV_NODES_MAX + node, team * BG_AV_MAX_GRAVETYPES + graveDefenderType, true);
else // we despawn the event from the prevowner
SpawnEvent(BG_AV_NODES_MAX + node, m_Nodes[node].PrevOwner * BG_AV_MAX_GRAVETYPES + graveDefenderType, false);
}
SpawnEvent(node, (team * BG_AV_MAX_STATES) + m_Nodes[node].State, true);
}
/// called when using a banner
void BattleGroundAV::EventPlayerClickedOnFlag(Player *source, GameObject* target_obj)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
sLog.outDebug("BattleGroundAV: using gameobject %i", target_obj->GetEntry());
uint8 event = (sBattleGroundMgr.GetGameObjectEventIndex(target_obj->GetDBTableGUIDLow())).event1;
if (event >= BG_AV_NODES_MAX) // not a node
return;
BG_AV_Nodes node = BG_AV_Nodes(event);
switch ((sBattleGroundMgr.GetGameObjectEventIndex(target_obj->GetDBTableGUIDLow())).event2 % BG_AV_MAX_STATES)
{
case POINT_CONTROLLED:
EventPlayerAssaultsPoint(source, node);
break;
case POINT_ASSAULTED:
EventPlayerDefendsPoint(source, node);
break;
default:
break;
}
}
void BattleGroundAV::EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node)
{
assert(GetStatus() == STATUS_IN_PROGRESS);
uint32 team = GetTeamIndexByTeamId(player->GetTeam());
if (m_Nodes[node].Owner == team || m_Nodes[node].State != POINT_ASSAULTED)
return;
if( m_Nodes[node].TotalOwner == BG_AV_NEUTRAL_TEAM ) // initial snowfall capture
{
// until snowfall doesn't belong to anyone it is better handled in assault - code (best would be to have a special function
// for neutral nodes.. but doing this just for snowfall will be a bit to much i think
assert(node == BG_AV_NODES_SNOWFALL_GRAVE); // currently the only neutral grave
EventPlayerAssaultsPoint(player, node);
return;
}
sLog.outDebug("BattleGroundAV: player defends node: %i", node);
if (m_Nodes[node].PrevOwner != team)
{
sLog.outError("BattleGroundAV: player defends point which doesn't belong to his team %i", node);
return;
}
DefendNode(node, team); // set the right variables for nodeinfo
PopulateNode(node); // spawn node-creatures (defender for example)
UpdateNodeWorldState(node); // send new mapicon to the player
if (IsTower(node))
{
SendYell2ToAll( LANG_BG_AV_TOWER_DEFENDED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
GetNodeName(node),
( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE);
UpdatePlayerScore(player, SCORE_TOWERS_DEFENDED, 1);
PlaySoundToAll(BG_AV_SOUND_BOTH_TOWER_DEFEND);
}
else
{
SendYell2ToAll(LANG_BG_AV_GRAVE_DEFENDED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
GetNodeName(node),
( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE);
UpdatePlayerScore(player, SCORE_GRAVEYARDS_DEFENDED, 1);
// update the statistic for the defending player
PlaySoundToAll((team == BG_TEAM_ALLIANCE)?BG_AV_SOUND_ALLIANCE_GOOD:BG_AV_SOUND_HORDE_GOOD);
}
}
void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node)
{
// TODO implement quest 7101, 7081
uint32 team = GetTeamIndexByTeamId(player->GetTeam());
sLog.outDebug("BattleGroundAV: player assaults node %i", node);
if (m_Nodes[node].Owner == team || team == m_Nodes[node].TotalOwner)
return;
AssaultNode(node, team); // update nodeinfo variables
UpdateNodeWorldState(node); // send mapicon
PopulateNode(node);
if (IsTower(node))
{
SendYell2ToAll(LANG_BG_AV_TOWER_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
GetNodeName(node),
( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE);
UpdatePlayerScore(player, SCORE_GRAVEYARDS_ASSAULTED, 1);
}
else
{
SendYell2ToAll(LANG_BG_AV_GRAVE_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
GetNodeName(node),
( team == BG_TEAM_ALLIANCE ) ? LANG_BG_AV_ALLY:LANG_BG_AV_HORDE);
// update the statistic for the assaulting player
UpdatePlayerScore(player, SCORE_GRAVEYARDS_ASSAULTED, 1);
}
PlaySoundToAll((team == BG_TEAM_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_ASSAULTS : BG_AV_SOUND_HORDE_ASSAULTS);
}
void BattleGroundAV::FillInitialWorldStates(WorldPacket& data)
{
bool stateok;
for (uint32 i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
{
for (uint8 j = 0; j < BG_AV_MAX_STATES; j++)
{
stateok = (m_Nodes[i].State == j);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, BG_TEAM_ALLIANCE)]) << uint32((m_Nodes[i].Owner == BG_TEAM_ALLIANCE && stateok) ? 1 : 0);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, BG_TEAM_HORDE)]) << uint32((m_Nodes[i].Owner == BG_TEAM_HORDE && stateok) ? 1 : 0);
}
}
if( m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].Owner == BG_AV_NEUTRAL_TEAM ) // cause neutral teams aren't handled generic
data << uint32(AV_SNOWFALL_N) << uint32(1);
data << uint32(BG_AV_Alliance_Score) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]);
data << uint32(BG_AV_Horde_Score) << uint32(m_TeamScores[BG_TEAM_HORDE]);
if( GetStatus() == STATUS_IN_PROGRESS ) // only if game is running the teamscores are displayed
{
data << uint32(BG_AV_SHOW_A_SCORE) << uint32(1);
data << uint32(BG_AV_SHOW_H_SCORE) << uint32(1);
}
else
{
data << uint32(BG_AV_SHOW_A_SCORE) << uint32(0);
data << uint32(BG_AV_SHOW_H_SCORE) << uint32(0);
}
SendMineWorldStates(BG_AV_NORTH_MINE);
SendMineWorldStates(BG_AV_SOUTH_MINE);
}
void BattleGroundAV::UpdateNodeWorldState(BG_AV_Nodes node)
{
UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].State,m_Nodes[node].Owner)], 1);
if( m_Nodes[node].PrevOwner == BG_AV_NEUTRAL_TEAM ) // currently only snowfall is supported as neutral node
UpdateWorldState(AV_SNOWFALL_N, 0);
else
UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].PrevState,m_Nodes[node].PrevOwner)], 0);
}
void BattleGroundAV::SendMineWorldStates(uint32 mine)
{
assert(mine == BG_AV_NORTH_MINE || mine == BG_AV_SOUTH_MINE);
assert(m_Mine_PrevOwner[mine] == BG_TEAM_ALLIANCE || m_Mine_PrevOwner[mine] == BG_TEAM_HORDE || m_Mine_PrevOwner[mine] == BG_AV_NEUTRAL_TEAM);
assert(m_Mine_Owner[mine] == BG_TEAM_ALLIANCE || m_Mine_Owner[mine] == BG_TEAM_HORDE || m_Mine_Owner[mine] == BG_AV_NEUTRAL_TEAM);
UpdateWorldState(BG_AV_MineWorldStates[mine][m_Mine_Owner[mine]], 1);
if (m_Mine_Owner[mine] != m_Mine_PrevOwner[mine])
UpdateWorldState(BG_AV_MineWorldStates[mine][m_Mine_PrevOwner[mine]], 0);
}
WorldSafeLocsEntry const* BattleGroundAV::GetClosestGraveYard(Player *plr)
{
float x = plr->GetPositionX();
float y = plr->GetPositionY();
uint32 team = GetTeamIndexByTeamId(plr->GetTeam());
WorldSafeLocsEntry const* good_entry = NULL;
if (GetStatus() == STATUS_IN_PROGRESS)
{
// Is there any occupied node for this team?
float mindist = 9999999.0f;
for(uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i)
{
if (m_Nodes[i].Owner != team || m_Nodes[i].State != POINT_CONTROLLED)
continue;
WorldSafeLocsEntry const * entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[i] );
if (!entry)
continue;
float dist = (entry->x - x) * (entry->x - x) + (entry->y - y) * (entry->y - y);
if (mindist > dist)
{
mindist = dist;
good_entry = entry;
}
}
}
// If not, place ghost in the starting-cave
if (!good_entry)
good_entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[team + 7] );
return good_entry;
}
uint32 BattleGroundAV::GetNodeName(BG_AV_Nodes node)
{
switch (node)
{
case BG_AV_NODES_FIRSTAID_STATION: return LANG_BG_AV_NODE_GRAVE_STORM_AID;
case BG_AV_NODES_DUNBALDAR_SOUTH: return LANG_BG_AV_NODE_TOWER_DUN_S;
case BG_AV_NODES_DUNBALDAR_NORTH: return LANG_BG_AV_NODE_TOWER_DUN_N;
case BG_AV_NODES_STORMPIKE_GRAVE: return LANG_BG_AV_NODE_GRAVE_STORMPIKE;
case BG_AV_NODES_ICEWING_BUNKER: return LANG_BG_AV_NODE_TOWER_ICEWING;
case BG_AV_NODES_STONEHEART_GRAVE: return LANG_BG_AV_NODE_GRAVE_STONE;
case BG_AV_NODES_STONEHEART_BUNKER: return LANG_BG_AV_NODE_TOWER_STONE;
case BG_AV_NODES_SNOWFALL_GRAVE: return LANG_BG_AV_NODE_GRAVE_SNOW;
case BG_AV_NODES_ICEBLOOD_TOWER: return LANG_BG_AV_NODE_TOWER_ICE;
case BG_AV_NODES_ICEBLOOD_GRAVE: return LANG_BG_AV_NODE_GRAVE_ICE;
case BG_AV_NODES_TOWER_POINT: return LANG_BG_AV_NODE_TOWER_POINT;
case BG_AV_NODES_FROSTWOLF_GRAVE: return LANG_BG_AV_NODE_GRAVE_FROST;
case BG_AV_NODES_FROSTWOLF_ETOWER: return LANG_BG_AV_NODE_TOWER_FROST_E;
case BG_AV_NODES_FROSTWOLF_WTOWER: return LANG_BG_AV_NODE_TOWER_FROST_W;
case BG_AV_NODES_FROSTWOLF_HUT: return LANG_BG_AV_NODE_GRAVE_FROST_HUT;
default: return 0; break;
}
}
void BattleGroundAV::AssaultNode(BG_AV_Nodes node, uint32 team)
{
assert(team < 3); // alliance:0, horde:1, neutral:2
assert(m_Nodes[node].TotalOwner != team);
assert(m_Nodes[node].Owner != team);
assert(m_Nodes[node].State != POINT_ASSAULTED || !m_Nodes[node].TotalOwner ); // only assault an assaulted node if no totalowner exists
// the timer gets another time, if the previous owner was 0 == Neutral
m_Nodes[node].Timer = (m_Nodes[node].PrevOwner != BG_AV_NEUTRAL_TEAM) ? BG_AV_CAPTIME : BG_AV_SNOWFALL_FIRSTCAP;
m_Nodes[node].PrevOwner = m_Nodes[node].Owner;
m_Nodes[node].Owner = team;
m_Nodes[node].PrevState = m_Nodes[node].State;
m_Nodes[node].State = POINT_ASSAULTED;
}
void BattleGroundAV::DestroyNode(BG_AV_Nodes node)
{
assert(m_Nodes[node].State == POINT_ASSAULTED);
m_Nodes[node].TotalOwner = m_Nodes[node].Owner;
m_Nodes[node].PrevOwner = m_Nodes[node].Owner;
m_Nodes[node].PrevState = m_Nodes[node].State;
m_Nodes[node].State = POINT_CONTROLLED;
m_Nodes[node].Timer = 0;
}
void BattleGroundAV::InitNode(BG_AV_Nodes node, uint32 team, bool tower)
{
assert(team < 3); // alliance:0, horde:1, neutral:2
m_Nodes[node].TotalOwner = team;
m_Nodes[node].Owner = team;
m_Nodes[node].PrevOwner = team;
m_Nodes[node].State = POINT_CONTROLLED;
m_Nodes[node].PrevState = m_Nodes[node].State;
m_Nodes[node].State = POINT_CONTROLLED;
m_Nodes[node].Timer = 0;
m_Nodes[node].Tower = tower;
m_ActiveEvents[node] = team * BG_AV_MAX_STATES + m_Nodes[node].State;
if (IsGrave(node)) // grave-creatures are special cause of a quest
m_ActiveEvents[node + BG_AV_NODES_MAX] = team * BG_AV_MAX_GRAVETYPES;
}
void BattleGroundAV::DefendNode(BG_AV_Nodes node, uint32 team)
{
assert(team < 3); // alliance:0, horde:1, neutral:2
assert(m_Nodes[node].TotalOwner == team);
assert(m_Nodes[node].Owner != team);
assert(m_Nodes[node].State != POINT_CONTROLLED);
m_Nodes[node].PrevOwner = m_Nodes[node].Owner;
m_Nodes[node].Owner = team;
m_Nodes[node].PrevState = m_Nodes[node].State;
m_Nodes[node].State = POINT_CONTROLLED;
m_Nodes[node].Timer = 0;
}
void BattleGroundAV::Reset()
{
BattleGround::Reset();
// set the reputation and honor variables:
bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID());
m_HonorMapComplete = (isBGWeekend) ? BG_AV_KILL_MAP_COMPLETE_HOLIDAY : BG_AV_KILL_MAP_COMPLETE;
m_RepTowerDestruction = (isBGWeekend) ? BG_AV_REP_TOWER_HOLIDAY : BG_AV_REP_TOWER;
m_RepCaptain = (isBGWeekend) ? BG_AV_REP_CAPTAIN_HOLIDAY : BG_AV_REP_CAPTAIN;
m_RepBoss = (isBGWeekend) ? BG_AV_REP_BOSS_HOLIDAY : BG_AV_REP_BOSS;
m_RepOwnedGrave = (isBGWeekend) ? BG_AV_REP_OWNED_GRAVE_HOLIDAY : BG_AV_REP_OWNED_GRAVE;
m_RepSurviveCaptain = (isBGWeekend) ? BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY : BG_AV_REP_SURVIVING_CAPTAIN;
m_RepSurviveTower = (isBGWeekend) ? BG_AV_REP_SURVIVING_TOWER_HOLIDAY : BG_AV_REP_SURVIVING_TOWER;
for(uint8 i = 0; i < BG_TEAMS_COUNT; i++)
{
for(uint8 j = 0; j < 9; j++) // 9 quests getting tracked
m_Team_QuestStatus[i][j] = 0;
m_TeamScores[i] = BG_AV_SCORE_INITIAL_POINTS;
m_IsInformedNearLose[i] = false;
m_ActiveEvents[BG_AV_NodeEventCaptainDead_A + i] = BG_EVENT_NONE;
}
for(uint8 i = 0; i < BG_AV_MAX_MINES; i++)
{
m_Mine_Owner[i] = BG_AV_NEUTRAL_TEAM;
m_Mine_PrevOwner[i] = m_Mine_Owner[i];
m_ActiveEvents[BG_AV_MINE_BOSSES+ i] = BG_AV_NEUTRAL_TEAM;
m_ActiveEvents[BG_AV_MINE_EVENT + i] = BG_AV_NEUTRAL_TEAM;
m_Mine_Timer[i] = BG_AV_MINE_TICK_TIMER;
}
m_ActiveEvents[BG_AV_CAPTAIN_A] = 0;
m_ActiveEvents[BG_AV_CAPTAIN_H] = 0;
m_ActiveEvents[BG_AV_HERALD] = 0;
m_ActiveEvents[BG_AV_BOSS_A] = 0;
m_ActiveEvents[BG_AV_BOSS_H] = 0;
for(BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // towers
m_ActiveEvents[BG_AV_MARSHAL_A_SOUTH + i - BG_AV_NODES_DUNBALDAR_SOUTH] = 0;
for(BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_STONEHEART_GRAVE; ++i) // alliance graves
InitNode(i, BG_TEAM_ALLIANCE, false);
for(BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers
InitNode(i, BG_TEAM_ALLIANCE, true);
for(BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_GRAVE; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) // horde graves
InitNode(i, BG_TEAM_HORDE, false);
for(BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers
InitNode(i, BG_TEAM_HORDE, true);
InitNode(BG_AV_NODES_SNOWFALL_GRAVE, BG_AV_NEUTRAL_TEAM, false); // give snowfall neutral owner
}

View file

@ -21,17 +21,279 @@
class BattleGround;
#define BG_AV_MAX_NODE_DISTANCE 25 // distance in which players are still counted in range of a banner (for alliance towers this is calculated from the center of the tower)
#define BG_AV_BOSS_KILL_QUEST_SPELL 23658
#define BG_AV_CAPTIME 240000 // 4 minutes
#define BG_AV_SNOWFALL_FIRSTCAP 300000 // 5 minutes but i also have seen 4:05
#define BG_AV_SCORE_INITIAL_POINTS 600
#define BG_AV_SCORE_NEAR_LOSE 120
// description: KILL = bonushonor kill one kill is 21honor worth at 0
// REP reputation, RES = ressources a team will lose
#define BG_AV_KILL_BOSS 4
#define BG_AV_REP_BOSS 350
#define BG_AV_REP_BOSS_HOLIDAY 525
#define BG_AV_KILL_CAPTAIN 3
#define BG_AV_REP_CAPTAIN 125
#define BG_AV_REP_CAPTAIN_HOLIDAY 185
#define BG_AV_RES_CAPTAIN 100
#define BG_AV_KILL_TOWER 3
#define BG_AV_REP_TOWER 12
#define BG_AV_REP_TOWER_HOLIDAY 18
#define BG_AV_RES_TOWER 75
#define BG_AV_KILL_GET_COMMANDER 1 // for a safely returned wingcommander TODO implement it
// bonushonor at the end
#define BG_AV_KILL_SURVIVING_TOWER 2
#define BG_AV_REP_SURVIVING_TOWER 12
#define BG_AV_REP_SURVIVING_TOWER_HOLIDAY 18
#define BG_AV_KILL_SURVIVING_CAPTAIN 2
#define BG_AV_REP_SURVIVING_CAPTAIN 125
#define BG_AV_REP_SURVIVING_CAPTAIN_HOLIDAY 175
#define BG_AV_KILL_MAP_COMPLETE 0
#define BG_AV_KILL_MAP_COMPLETE_HOLIDAY 4
#define BG_AV_REP_OWNED_GRAVE 12
#define BG_AV_REP_OWNED_GRAVE_HOLIDAY 18
#define BG_AV_REP_OWNED_MINE 24
#define BG_AV_REP_OWNED_MINE_HOLIDAY 36
enum BG_AV_Sounds
{
BG_AV_SOUND_NEAR_LOSE = 8456, // not confirmed yet
BG_AV_SOUND_ALLIANCE_ASSAULTS = 8212, // tower,grave + enemy boss if someone tries to attack him
BG_AV_SOUND_HORDE_ASSAULTS = 8174,
BG_AV_SOUND_ALLIANCE_GOOD = 8173, // if something good happens for the team: wins(maybe only through killing the boss), captures mine or grave, destroys tower and defends grave
BG_AV_SOUND_HORDE_GOOD = 8213,
BG_AV_SOUND_BOTH_TOWER_DEFEND = 8192,
BG_AV_SOUND_ALLIANCE_CAPTAIN = 8232, // gets called when someone attacks them and at the beginning after 3min + rand(x) * 10sec (maybe buff)
BG_AV_SOUND_HORDE_CAPTAIN = 8333,
};
enum BG_AV_OTHER_VALUES
{
BG_AV_NORTH_MINE = 0,
BG_AV_SOUTH_MINE = 1,
BG_AV_MINE_TICK_TIMER = 45000,
BG_AV_MINE_RECLAIM_TIMER = 1200000, // TODO: get the right value.. this is currently 20 minutes
BG_AV_NEUTRAL_TEAM = 2, // this is the neutral owner of snowfall
BG_AV_FACTION_A = 730,
BG_AV_FACTION_H = 729,
};
#define BG_AV_MAX_MINES 2
enum BG_AV_ObjectIds
{
// mine supplies
BG_AV_OBJECTID_MINE_N = 178785,
BG_AV_OBJECTID_MINE_S = 178784,
};
enum BG_AV_Nodes
{
BG_AV_NODES_FIRSTAID_STATION = 0,
BG_AV_NODES_STORMPIKE_GRAVE = 1,
BG_AV_NODES_STONEHEART_GRAVE = 2,
BG_AV_NODES_SNOWFALL_GRAVE = 3,
BG_AV_NODES_ICEBLOOD_GRAVE = 4,
BG_AV_NODES_FROSTWOLF_GRAVE = 5,
BG_AV_NODES_FROSTWOLF_HUT = 6,
BG_AV_NODES_DUNBALDAR_SOUTH = 7,
BG_AV_NODES_DUNBALDAR_NORTH = 8,
BG_AV_NODES_ICEWING_BUNKER = 9,
BG_AV_NODES_STONEHEART_BUNKER = 10,
BG_AV_NODES_ICEBLOOD_TOWER = 11,
BG_AV_NODES_TOWER_POINT = 12,
BG_AV_NODES_FROSTWOLF_ETOWER = 13,
BG_AV_NODES_FROSTWOLF_WTOWER = 14,
BG_AV_NODES_ERROR = 255,
};
#define BG_AV_NODES_MAX 15
// for nodeevents we will use event1=node
// event2 is related to BG_AV_States
// 0 = alliance assaulted
// 1 = alliance control
// 2 = horde assaulted
// 3 = horde control
// 4 = neutral assaulted
// 5 = neutral control
// graves have special creatures - their defenders can be in 4 different states
// through some quests with armor scraps
// so i use event1=BG_AV_NODES_MAX+node (15-21)
// and event2=type
#define BG_AV_MINE_BOSSES 46 // + mineid will be exact event
#define BG_AV_MINE_BOSSES_NORTH 46
#define BG_AV_MINE_BOSSES_SOUTH 47
#define BG_AV_CAPTAIN_A 48
#define BG_AV_CAPTAIN_H 49
#define BG_AV_MINE_EVENT 50 // + mineid will be exact event
#define BG_AV_MINE_EVENT_NORTH 50
#define BG_AV_MINE_EVENT_SOUTH 51
#define BG_AV_MARSHAL_A_SOUTH 52
#define BG_AV_MARSHAL_A_NORTH 53
#define BG_AV_MARSHAL_A_ICE 54
#define BG_AV_MARSHAL_A_STONE 55
#define BG_AV_MARSHAL_H_ICE 56
#define BG_AV_MARSHAL_H_TOWER 57
#define BG_AV_MARSHAL_H_ETOWER 58
#define BG_AV_MARSHAL_H_WTOWER 59
#define BG_AV_HERALD 60
#define BG_AV_BOSS_A 61
#define BG_AV_BOSS_H 62
#define BG_AV_NodeEventCaptainDead_A 63
#define BG_AV_NodeEventCaptainDead_H 64
enum BG_AV_Graveyards
{
BG_AV_GRAVE_STORM_AID = 751,
BG_AV_GRAVE_STORM_GRAVE = 689,
BG_AV_GRAVE_STONE_GRAVE = 729,
BG_AV_GRAVE_SNOWFALL = 169,
BG_AV_GRAVE_ICE_GRAVE = 749,
BG_AV_GRAVE_FROSTWOLF = 690,
BG_AV_GRAVE_FROST_HUT = 750,
BG_AV_GRAVE_MAIN_ALLIANCE = 611,
BG_AV_GRAVE_MAIN_HORDE = 610
};
const uint32 BG_AV_GraveyardIds[9]= {
BG_AV_GRAVE_STORM_AID,
BG_AV_GRAVE_STORM_GRAVE,
BG_AV_GRAVE_STONE_GRAVE,
BG_AV_GRAVE_SNOWFALL,
BG_AV_GRAVE_ICE_GRAVE,
BG_AV_GRAVE_FROSTWOLF,
BG_AV_GRAVE_FROST_HUT,
BG_AV_GRAVE_MAIN_ALLIANCE,
BG_AV_GRAVE_MAIN_HORDE
};
enum BG_AV_States
{
POINT_ASSAULTED = 0,
POINT_CONTROLLED = 1
};
#define BG_AV_MAX_STATES 2
enum BG_AV_WorldStates
{
BG_AV_Alliance_Score = 3127,
BG_AV_Horde_Score = 3128,
BG_AV_SHOW_H_SCORE = 3133,
BG_AV_SHOW_A_SCORE = 3134,
AV_SNOWFALL_N = 1966,
};
// alliance_control horde_control neutral_control
const uint32 BG_AV_MineWorldStates[2][3] = {
{1358, 1359, 1360},
{1355, 1356, 1357}
};
// alliance_control alliance_assault h_control h_assault
const uint32 BG_AV_NodeWorldStates[BG_AV_NODES_MAX][4] = {
// Stormpike first aid station
{1326,1325,1328,1327},
// Stormpike Graveyard
{1335,1333,1336,1334},
// Stoneheart Grave
{1304,1302,1303,1301},
// Snowfall Grave
{1343,1341,1344,1342},
// Iceblood grave
{1348,1346,1349,1347},
// Frostwolf Grave
{1339,1337,1340,1338},
// Frostwolf Hut
{1331,1329,1332,1330},
// Dunbaldar South Bunker
{1375,1361,1378,1370},
// Dunbaldar North Bunker
{1374,1362,1379,1371},
// Icewing Bunker
{1376,1363,1380,1372},
// Stoneheart Bunker
{1377,1364,1381,1373},
// Iceblood Tower
{1390,1368,1395,1385},
// Tower Point
{1389,1367,1394,1384},
// Frostwolf East
{1388,1366,1393,1383},
// Frostwolf West
{1387,1365,1392,1382},
};
// through the armorscap-quest 4 different gravedefender exist
#define BG_AV_MAX_GRAVETYPES 4
enum BG_AV_QuestIds
{
BG_AV_QUEST_A_SCRAPS1 = 7223, // first quest
BG_AV_QUEST_A_SCRAPS2 = 6781, // repeatable
BG_AV_QUEST_H_SCRAPS1 = 7224,
BG_AV_QUEST_H_SCRAPS2 = 6741,
BG_AV_QUEST_A_COMMANDER1 = 6942, // soldier
BG_AV_QUEST_H_COMMANDER1 = 6825,
BG_AV_QUEST_A_COMMANDER2 = 6941, // leutnant
BG_AV_QUEST_H_COMMANDER2 = 6826,
BG_AV_QUEST_A_COMMANDER3 = 6943, // commander
BG_AV_QUEST_H_COMMANDER3 = 6827,
BG_AV_QUEST_A_BOSS1 = 7386, // 5 cristal/blood
BG_AV_QUEST_H_BOSS1 = 7385,
BG_AV_QUEST_A_BOSS2 = 6881, // 1
BG_AV_QUEST_H_BOSS2 = 6801,
BG_AV_QUEST_A_NEAR_MINE = 5892, // the mine near start location of team
BG_AV_QUEST_H_NEAR_MINE = 5893,
BG_AV_QUEST_A_OTHER_MINE = 6982, // the other mine ;)
BG_AV_QUEST_H_OTHER_MINE = 6985,
BG_AV_QUEST_A_RIDER_HIDE = 7026,
BG_AV_QUEST_H_RIDER_HIDE = 7002,
BG_AV_QUEST_A_RIDER_TAME = 7027,
BG_AV_QUEST_H_RIDER_TAME = 7001
};
struct BG_AV_NodeInfo
{
uint32 TotalOwner;
uint32 Owner;
uint32 PrevOwner;
BG_AV_States State;
BG_AV_States PrevState;
uint32 Timer;
bool Tower;
};
inline BG_AV_Nodes &operator++(BG_AV_Nodes &i)
{
return i = BG_AV_Nodes(i + 1);
}
class BattleGroundAVScore : public BattleGroundScore
{
public:
BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) {};
BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), SecondaryObjectives(0) {};
virtual ~BattleGroundAVScore() {};
uint32 GraveyardsAssaulted;
uint32 GraveyardsDefended;
uint32 TowersAssaulted;
uint32 TowersDefended;
uint32 MinesCaptured;
uint32 LeadersKilled;
uint32 SecondaryObjectives;
};
@ -46,16 +308,79 @@ class BattleGroundAV : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void OnObjectDBLoad(Creature* creature);
virtual void OnCreatureRespawn(Creature* creature);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
// world states
virtual void FillInitialWorldStates(WorldPacket& data);
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
//bool SetupBattleGround();
virtual void Reset();
/* Scorekeeping */
/*general stuff*/
void UpdateScore(BattleGroundTeamId team, int32 points);
void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
/*handle stuff*/ // these are functions which get called from extern scripts
virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj);
void HandleKillPlayer(Player* player, Player *killer);
void HandleKillUnit(Creature *creature, Player *killer);
void HandleQuestComplete(uint32 questid, Player *player);
bool PlayerCanDoMineQuest(int32 GOId,uint32 team);
void EndBattleGround(uint32 winner);
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player *plr);
private:
/* Nodes occupying */
void EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node);
void EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node);
void EventPlayerDestroyedPoint(BG_AV_Nodes node);
void AssaultNode(BG_AV_Nodes node, uint32 team);
void DestroyNode(BG_AV_Nodes node);
void InitNode(BG_AV_Nodes node, uint32 team, bool tower);
void DefendNode(BG_AV_Nodes node, uint32 team);
void PopulateNode(BG_AV_Nodes node);
uint32 GetNodeName(BG_AV_Nodes node);
const bool IsTower(BG_AV_Nodes node) { return (node == BG_AV_NODES_ERROR)? false : m_Nodes[node].Tower; }
const bool IsGrave(BG_AV_Nodes node) { return (node == BG_AV_NODES_ERROR)? false : !m_Nodes[node].Tower; }
/*mine*/
void ChangeMineOwner(uint8 mine, uint32 team);
/*worldstates*/
uint8 GetWorldStateType(uint8 state, uint32 team) const { return team * BG_AV_MAX_STATES + state; }
void SendMineWorldStates(uint32 mine);
void UpdateNodeWorldState(BG_AV_Nodes node);
/*variables */
uint32 m_Team_QuestStatus[BG_TEAMS_COUNT][9]; // [x][y] x=team y=questcounter
BG_AV_NodeInfo m_Nodes[BG_AV_NODES_MAX];
int8 m_Mine_Owner[BG_AV_MAX_MINES];
int8 m_Mine_PrevOwner[BG_AV_MAX_MINES]; // only for worldstates needed
int32 m_Mine_Timer[BG_AV_MAX_MINES];
uint32 m_Mine_Reclaim_Timer[BG_AV_MAX_MINES];
bool m_IsInformedNearLose[BG_TEAMS_COUNT];
bool m_captainAlive[BG_TEAMS_COUNT];
uint32 m_HonorMapComplete;
uint32 m_RepTowerDestruction;
uint32 m_RepCaptain;
uint32 m_RepBoss;
uint32 m_RepOwnedGrave;
uint32 m_RepOwnedMine;
uint32 m_RepSurviveCaptain;
uint32 m_RepSurviveTower;
};
#endif

View file

@ -1383,7 +1383,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
*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
*data << (uint32)((BattleGroundAVScore*)itr->second)->SecondaryObjectives; // SecondaryObjectives - free some of the Lieutnants
break;
case BATTLEGROUND_WS:
*data << (uint32)0x00000002; // count of next fields

View file

@ -366,6 +366,9 @@ void Creature::Update(uint32 diff)
else
setDeathState( JUST_ALIVED );
if (GetMap()->IsBattleGround() && ((BattleGroundMap*)GetMap())->GetBG())
((BattleGroundMap*)GetMap())->GetBG()->OnCreatureRespawn(this); // for alterac valley needed to adjust the correct level again
//Call AI respawn virtual function
i_AI->JustRespawned();

View file

@ -34,6 +34,7 @@
#include "CellImpl.h"
#include "InstanceData.h"
#include "BattleGround.h"
#include "BattleGroundAV.h"
#include "Util.h"
GameObject::GameObject() : WorldObject()
@ -744,7 +745,14 @@ bool GameObject::ActivateToQuest( Player *pTarget)const
case GAMEOBJECT_TYPE_CHEST:
{
if(LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), pTarget))
{
//look for battlegroundAV for some objects which are only activated after mine gots captured by own team
if (GetEntry() == BG_AV_OBJECTID_MINE_N || GetEntry() == BG_AV_OBJECTID_MINE_S)
if (BattleGround *bg = pTarget->GetBattleGround())
if (bg->GetTypeID() == BATTLEGROUND_AV && !(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(GetEntry(),pTarget->GetTeam())))
return false;
return true;
}
break;
}
case GAMEOBJECT_TYPE_GOOBER:

View file

@ -686,16 +686,51 @@ enum MangosStrings
LANG_DIST_ARENA_POINTS_TEAM_START = 744,
LANG_DIST_ARENA_POINTS_TEAM_END = 745,
LANG_DIST_ARENA_POINTS_END = 746,
// = 747, not used
// = 748, not used
// = 749, not used
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins."
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds."
// = 752, not used
// LANG_BG_WS_START_TWO_MINUTES = 753, - defined above
// LANG_BG_AB_START_TWO_MINUTES = 754, - defined above
// LANG_BG_EY_START_TWO_MINUTES = 755, - defined above
// Room for batleground/arena strings 756-799 not used
LANG_BATTLEGROUND_ONLY_ALLIANCE_USE = 752, // "Only The Alliance can use that portal"
LANG_BATTLEGROUND_ONLY_HORDE_USE = 753, // "Only The Horde can use that portal"
LANG_BG_AV_ALLY = 757,
LANG_BG_AV_HORDE = 758,
LANG_BG_AV_TOWER_TAKEN = 759,
LANG_BG_AV_TOWER_ASSAULTED = 760,
LANG_BG_AV_TOWER_DEFENDED = 761,
LANG_BG_AV_GRAVE_TAKEN = 762,
LANG_BG_AV_GRAVE_DEFENDED = 763,
LANG_BG_AV_GRAVE_ASSAULTED = 764,
LANG_BG_AV_MINE_TAKEN = 765,
LANG_BG_AV_MINE_NORTH = 766,
LANG_BG_AV_MINE_SOUTH = 767,
LANG_BG_AV_NODE_GRAVE_STORM_AID = 768,
LANG_BG_AV_NODE_TOWER_DUN_S = 769,
LANG_BG_AV_NODE_TOWER_DUN_N = 770,
LANG_BG_AV_NODE_GRAVE_STORMPIKE = 771,
LANG_BG_AV_NODE_TOWER_ICEWING = 772,
LANG_BG_AV_NODE_GRAVE_STONE = 773,
LANG_BG_AV_NODE_TOWER_STONE = 774,
LANG_BG_AV_NODE_GRAVE_SNOW = 775,
LANG_BG_AV_NODE_TOWER_ICE = 776,
LANG_BG_AV_NODE_GRAVE_ICE = 777,
LANG_BG_AV_NODE_TOWER_POINT = 778,
LANG_BG_AV_NODE_GRAVE_FROST = 779,
LANG_BG_AV_NODE_TOWER_FROST_E = 780,
LANG_BG_AV_NODE_TOWER_FROST_W = 781,
LANG_BG_AV_NODE_GRAVE_FROST_HUT = 782,
LANG_BG_AV_START_TWO_MINUTES = 783,
LANG_BG_AV_START_ONE_MINUTE = 784,
LANG_BG_AV_START_HALF_MINUTE = 785,
LANG_BG_AV_HAS_BEGUN = 786,
LANG_BG_AV_A_NEAR_LOSE = 787,
LANG_BG_AV_H_NEAR_LOSE = 788,
LANG_BG_AV_H_GENERAL_DEAD = 789,
LANG_BG_AV_A_GENERAL_DEAD = 790,
// Room for batleground/arena strings 790-799 not used
// in game strings
// = 800, not used

View file

@ -65,6 +65,16 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
loot = &pItem->loot;
}
else if (IS_CORPSE_GUID(lguid))
{
Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid);
if (!bones)
{
player->SendLootRelease(lguid);
return;
}
loot = &bones->loot;
}
else
{
Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid);

View file

@ -782,9 +782,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
{
BattleGround* bg = GetPlayer()->GetBattleGround();
if(bg)
if(bg->GetStatus() == STATUS_IN_PROGRESS)
bg->HandleAreaTrigger(GetPlayer(), Trigger_ID);
bg->HandleAreaTrigger(GetPlayer(), Trigger_ID);
return;
}

View file

@ -51,6 +51,7 @@
#include "Transports.h"
#include "Weather.h"
#include "BattleGround.h"
#include "BattleGroundAV.h"
#include "BattleGroundMgr.h"
#include "ArenaTeam.h"
#include "Chat.h"
@ -7410,6 +7411,14 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (go->getLootState() == GO_READY)
{
uint32 lootid = go->GetGOInfo()->GetLootId();
if ((go->GetEntry() == BG_AV_OBJECTID_MINE_N || go->GetEntry() == BG_AV_OBJECTID_MINE_S))
if (BattleGround *bg = GetBattleGround())
if (bg->GetTypeID() == BATTLEGROUND_AV)
if (!(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(go->GetEntry(), GetTeam())))
{
SendLootRelease(guid);
return;
}
if (lootid)
{
@ -7476,6 +7485,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
bones->lootForBody = true;
uint32 pLevel = bones->loot.gold;
bones->loot.clear();
if (GetBattleGround()->GetTypeID() == BATTLEGROUND_AV)
loot->FillLoot(0, LootTemplates_Creature, this, false);
// It may need a better formula
// Now it works like this: lvl10: ~6copper, lvl70: ~9silver
bones->loot.gold = (uint32)( urand(50, 150) * 0.016f * pow( ((float)pLevel)/5.76f, 2.5f) * sWorld.getRate(RATE_DROP_MONEY) );
@ -7759,81 +7770,86 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
case 2257:
break;
case 2597: // AV
data << uint32(0x7ae) << uint32(0x1); // 7
data << uint32(0x532) << uint32(0x1); // 8
data << uint32(0x531) << uint32(0x0); // 9
data << uint32(0x52e) << uint32(0x0); // 10
data << uint32(0x571) << uint32(0x0); // 11
data << uint32(0x570) << uint32(0x0); // 12
data << uint32(0x567) << uint32(0x1); // 13
data << uint32(0x566) << uint32(0x1); // 14
data << uint32(0x550) << uint32(0x1); // 15
data << uint32(0x544) << uint32(0x0); // 16
data << uint32(0x536) << uint32(0x0); // 17
data << uint32(0x535) << uint32(0x1); // 18
data << uint32(0x518) << uint32(0x0); // 19
data << uint32(0x517) << uint32(0x0); // 20
data << uint32(0x574) << uint32(0x0); // 21
data << uint32(0x573) << uint32(0x0); // 22
data << uint32(0x572) << uint32(0x0); // 23
data << uint32(0x56f) << uint32(0x0); // 24
data << uint32(0x56e) << uint32(0x0); // 25
data << uint32(0x56d) << uint32(0x0); // 26
data << uint32(0x56c) << uint32(0x0); // 27
data << uint32(0x56b) << uint32(0x0); // 28
data << uint32(0x56a) << uint32(0x1); // 29
data << uint32(0x569) << uint32(0x1); // 30
data << uint32(0x568) << uint32(0x1); // 13
data << uint32(0x565) << uint32(0x0); // 32
data << uint32(0x564) << uint32(0x0); // 33
data << uint32(0x563) << uint32(0x0); // 34
data << uint32(0x562) << uint32(0x0); // 35
data << uint32(0x561) << uint32(0x0); // 36
data << uint32(0x560) << uint32(0x0); // 37
data << uint32(0x55f) << uint32(0x0); // 38
data << uint32(0x55e) << uint32(0x0); // 39
data << uint32(0x55d) << uint32(0x0); // 40
data << uint32(0x3c6) << uint32(0x4); // 41
data << uint32(0x3c4) << uint32(0x6); // 42
data << uint32(0x3c2) << uint32(0x4); // 43
data << uint32(0x516) << uint32(0x1); // 44
data << uint32(0x515) << uint32(0x0); // 45
data << uint32(0x3b6) << uint32(0x6); // 46
data << uint32(0x55c) << uint32(0x0); // 47
data << uint32(0x55b) << uint32(0x0); // 48
data << uint32(0x55a) << uint32(0x0); // 49
data << uint32(0x559) << uint32(0x0); // 50
data << uint32(0x558) << uint32(0x0); // 51
data << uint32(0x557) << uint32(0x0); // 52
data << uint32(0x556) << uint32(0x0); // 53
data << uint32(0x555) << uint32(0x0); // 54
data << uint32(0x554) << uint32(0x1); // 55
data << uint32(0x553) << uint32(0x1); // 56
data << uint32(0x552) << uint32(0x1); // 57
data << uint32(0x551) << uint32(0x1); // 58
data << uint32(0x54f) << uint32(0x0); // 59
data << uint32(0x54e) << uint32(0x0); // 60
data << uint32(0x54d) << uint32(0x1); // 61
data << uint32(0x54c) << uint32(0x0); // 62
data << uint32(0x54b) << uint32(0x0); // 63
data << uint32(0x545) << uint32(0x0); // 64
data << uint32(0x543) << uint32(0x1); // 65
data << uint32(0x542) << uint32(0x0); // 66
data << uint32(0x540) << uint32(0x0); // 67
data << uint32(0x53f) << uint32(0x0); // 68
data << uint32(0x53e) << uint32(0x0); // 69
data << uint32(0x53d) << uint32(0x0); // 70
data << uint32(0x53c) << uint32(0x0); // 71
data << uint32(0x53b) << uint32(0x0); // 72
data << uint32(0x53a) << uint32(0x1); // 73
data << uint32(0x539) << uint32(0x0); // 74
data << uint32(0x538) << uint32(0x0); // 75
data << uint32(0x537) << uint32(0x0); // 76
data << uint32(0x534) << uint32(0x0); // 77
data << uint32(0x533) << uint32(0x0); // 78
data << uint32(0x530) << uint32(0x0); // 79
data << uint32(0x52f) << uint32(0x0); // 80
data << uint32(0x52d) << uint32(0x1); // 81
if (bg && bg->GetTypeID() == BATTLEGROUND_AV)
bg->FillInitialWorldStates(data);
else
{
data << uint32(0x7ae) << uint32(0x1); // 7 snowfall n
data << uint32(0x532) << uint32(0x1); // 8 frostwolfhut hc
data << uint32(0x531) << uint32(0x0); // 9 frostwolfhut ac
data << uint32(0x52e) << uint32(0x0); // 10 stormpike firstaid a_a
data << uint32(0x571) << uint32(0x0); // 11 east frostwolf tower horde assaulted -unused
data << uint32(0x570) << uint32(0x0); // 12 west frostwolf tower horde assaulted - unused
data << uint32(0x567) << uint32(0x1); // 13 frostwolfe c
data << uint32(0x566) << uint32(0x1); // 14 frostwolfw c
data << uint32(0x550) << uint32(0x1); // 15 irondeep (N) ally
data << uint32(0x544) << uint32(0x0); // 16 ice grave a_a
data << uint32(0x536) << uint32(0x0); // 17 stormpike grave h_c
data << uint32(0x535) << uint32(0x1); // 18 stormpike grave a_c
data << uint32(0x518) << uint32(0x0); // 19 stoneheart grave a_a
data << uint32(0x517) << uint32(0x0); // 20 stoneheart grave h_a
data << uint32(0x574) << uint32(0x0); // 21 1396 unk
data << uint32(0x573) << uint32(0x0); // 22 iceblood tower horde assaulted -unused
data << uint32(0x572) << uint32(0x0); // 23 towerpoint horde assaulted - unused
data << uint32(0x56f) << uint32(0x0); // 24 1391 unk
data << uint32(0x56e) << uint32(0x0); // 25 iceblood a
data << uint32(0x56d) << uint32(0x0); // 26 towerp a
data << uint32(0x56c) << uint32(0x0); // 27 frostwolfe a
data << uint32(0x56b) << uint32(0x0); // 28 froswolfw a
data << uint32(0x56a) << uint32(0x1); // 29 1386 unk
data << uint32(0x569) << uint32(0x1); // 30 iceblood c
data << uint32(0x568) << uint32(0x1); // 31 towerp c
data << uint32(0x565) << uint32(0x0); // 32 stoneh tower a
data << uint32(0x564) << uint32(0x0); // 33 icewing tower a
data << uint32(0x563) << uint32(0x0); // 34 dunn a
data << uint32(0x562) << uint32(0x0); // 35 duns a
data << uint32(0x561) << uint32(0x0); // 36 stoneheart bunker alliance assaulted - unused
data << uint32(0x560) << uint32(0x0); // 37 icewing bunker alliance assaulted - unused
data << uint32(0x55f) << uint32(0x0); // 38 dunbaldar south alliance assaulted - unused
data << uint32(0x55e) << uint32(0x0); // 39 dunbaldar north alliance assaulted - unused
data << uint32(0x55d) << uint32(0x0); // 40 stone tower d
data << uint32(0x3c6) << uint32(0x0); // 41 966 unk
data << uint32(0x3c4) << uint32(0x0); // 42 964 unk
data << uint32(0x3c2) << uint32(0x0); // 43 962 unk
data << uint32(0x516) << uint32(0x1); // 44 stoneheart grave a_c
data << uint32(0x515) << uint32(0x0); // 45 stonheart grave h_c
data << uint32(0x3b6) << uint32(0x0); // 46 950 unk
data << uint32(0x55c) << uint32(0x0); // 47 icewing tower d
data << uint32(0x55b) << uint32(0x0); // 48 dunn d
data << uint32(0x55a) << uint32(0x0); // 49 duns d
data << uint32(0x559) << uint32(0x0); // 50 1369 unk
data << uint32(0x558) << uint32(0x0); // 51 iceblood d
data << uint32(0x557) << uint32(0x0); // 52 towerp d
data << uint32(0x556) << uint32(0x0); // 53 frostwolfe d
data << uint32(0x555) << uint32(0x0); // 54 frostwolfw d
data << uint32(0x554) << uint32(0x1); // 55 stoneh tower c
data << uint32(0x553) << uint32(0x1); // 56 icewing tower c
data << uint32(0x552) << uint32(0x1); // 57 dunn c
data << uint32(0x551) << uint32(0x1); // 58 duns c
data << uint32(0x54f) << uint32(0x0); // 59 irondeep (N) horde
data << uint32(0x54e) << uint32(0x0); // 60 irondeep (N) ally
data << uint32(0x54d) << uint32(0x1); // 61 mine (S) neutral
data << uint32(0x54c) << uint32(0x0); // 62 mine (S) horde
data << uint32(0x54b) << uint32(0x0); // 63 mine (S) ally
data << uint32(0x545) << uint32(0x0); // 64 iceblood h_a
data << uint32(0x543) << uint32(0x1); // 65 iceblod h_c
data << uint32(0x542) << uint32(0x0); // 66 iceblood a_c
data << uint32(0x540) << uint32(0x0); // 67 snowfall h_a
data << uint32(0x53f) << uint32(0x0); // 68 snowfall a_a
data << uint32(0x53e) << uint32(0x0); // 69 snowfall h_c
data << uint32(0x53d) << uint32(0x0); // 70 snowfall a_c
data << uint32(0x53c) << uint32(0x0); // 71 frostwolf g h_a
data << uint32(0x53b) << uint32(0x0); // 72 frostwolf g a_a
data << uint32(0x53a) << uint32(0x1); // 73 frostwolf g h_c
data << uint32(0x539) << uint32(0x0); // 74 frostwolf g a_c
data << uint32(0x538) << uint32(0x0); // 75 stormpike grave h_a
data << uint32(0x537) << uint32(0x0); // 76 stormpike grave a_a
data << uint32(0x534) << uint32(0x0); // 77 frostwolf hut h_a
data << uint32(0x533) << uint32(0x0); // 78 frostwolf hut a_a
data << uint32(0x530) << uint32(0x0); // 79 stormpike first aid h_a
data << uint32(0x52f) << uint32(0x0); // 80 stormpike first aid h_c
data << uint32(0x52d) << uint32(0x1); // 81 stormpike first aid a_c
}
break;
case 3277: // WS
if (bg && bg->GetTypeID() == BATTLEGROUND_WS)
@ -12645,6 +12661,10 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
RemoveTimedQuest(quest_id);
if (BattleGround* bg = GetBattleGround())
if (bg->GetTypeID() == BATTLEGROUND_AV)
((BattleGroundAV*)bg)->HandleQuestComplete(pQuest->GetQuestId(), this);
if (pQuest->GetRewChoiceItemsCount() > 0)
{
if (uint32 itemId = pQuest->RewChoiceItemId[reward])
@ -13751,7 +13771,8 @@ bool Player::HasQuestForItem( uint32 itemid ) const
continue;
// hide quest if player is in raid-group and quest is no raid quest
if(GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID)
if (GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID
&& !InBattleGround())
continue;
// There should be no mixed ReqItem/ReqSource drop

View file

@ -3044,7 +3044,7 @@ void Spell::EffectOpenLock(uint32 effIndex)
if (BattleGround *bg = player->GetBattleGround())
{
// check if it's correct bg
if (bg && bg->GetTypeID() == BATTLEGROUND_AB)
if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
bg->EventPlayerClickedOnFlag(player, gameObjTarget);
return;
}

View file

@ -718,10 +718,12 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(BattleGround *bg = killed->GetBattleGround())
if(player)
bg->HandleKillPlayer(killed, player);
//later we can add support for creature->player kills here i'm
//not sure, but i guess those kills also get counted in av
//else if(GetTypeId() == TYPEID_UNIT)
// bg->HandleKillPlayer(killed,(Creature*)this);
}
else if(pVictim->GetTypeId() == TYPEID_UNIT)
{
if (player)
if (BattleGround *bg = player->GetBattleGround())
bg->HandleKillUnit((Creature*)pVictim, player);
}
}
else // if (health <= damage)

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8607"
#define REVISION_NR "8608"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8596_01_characters_bugreport"
#define REVISION_DB_MANGOS "required_8607_02_mangos_command"
#define REVISION_DB_MANGOS "required_8608_02_mangos_battleground_events"
#define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters"
#endif // __REVISION_SQL_H__