Index: src/game/BattleGround.h =================================================================== --- src/game/BattleGround.h (revision 5133) +++ src/game/BattleGround.h (working copy) @@ -100,6 +100,16 @@ uint32 spellid; }; +struct AlteracRewards +{ + uint8 m_CaptainsAlive[2]; + uint8 m_CaptainsKilled[2]; + uint8 m_TowersControlled[2]; + uint8 m_TowersDestroyed[2]; + uint8 m_GraveYardsControlled[2]; + uint8 m_MinesControlled[2]; +}; + #define MAX_QUEUED_PLAYERS_MAP 7 enum BattleGroundTypeId @@ -306,6 +316,7 @@ void CastSpellOnTeam(uint32 SpellID, uint32 TeamID); void RewardHonorToTeam(uint32 Honor, uint32 TeamID); void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID); + void RewardReputation(uint32 faction_id, uint32 Reputation, uint32 TeamID, Player *killer); void UpdateWorldState(uint32 Field, uint32 Value); void EndBattleGround(uint32 winner); void BlockMovement(Player *plr); @@ -339,6 +350,7 @@ virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {} // must be implemented in BG subclass if need virtual void HandleKillPlayer(Player* /*player*/, Player* /*killer*/) {} + virtual void HandleKillUnit(Unit* /*unit*/, Player* /*killer*/) {} // must be implemented in BG subclass if need virtual void HandleDropFlag(Player* /*player*/) {} @@ -372,6 +384,9 @@ std::map m_Players; std::map > m_ReviveQueue;// Spirit Guide guid + Player list GUIDS + /* Alterac Valley Rewards*/ + AlteracRewards *rew; + /* this is important variable used for invitation messages */ @@ -411,7 +426,7 @@ /* Players count by team */ uint32 m_PlayersCount[2]; - + /* Limits */ uint32 m_LevelMin; uint32 m_LevelMax; Index: src/game/BattleGroundAV.cpp =================================================================== --- src/game/BattleGroundAV.cpp (revision 5133) +++ src/game/BattleGroundAV.cpp (working copy) @@ -21,12 +21,14 @@ #include "BattleGround.h" #include "BattleGroundAV.h" #include "Creature.h" +#include "Chat.h" +#include "ObjectMgr.h" #include "MapManager.h" #include "Language.h" BattleGroundAV::BattleGroundAV() { - + rew = new AlteracRewards(); } BattleGroundAV::~BattleGroundAV() @@ -34,11 +36,267 @@ } +void BattleGroundAV::HandleKillPlayer(Player *player, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam()); + if(teamIndex==0) + AScore--; + else HScore--; + + UpdateScore(); +} +void BattleGroundAV::HandleKillUnit(Unit *unit, Player *killer) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + uint32 ressources = 0; + uint32 reputation = 0; + uint32 honor = 0; + uint16 teamIndex = 0; + if(GetTeamIndexByTeamId(killer->GetTeam()) == BG_TEAM_ALLIANCE) + teamIndex = HORDE; + else teamIndex = ALLIANCE; + //check for general/captain mobs, generals end battleground and captains decrease tickets by 100 + switch(unit->GetEntry()) + { + case 11948: + reputation = 389; + honor = 80; + EndBattleGround(HORDE); + break; + case 11946: + reputation = 389; + honor = 80; + EndBattleGround(ALLIANCE); + break; + case 11949: + reputation = 125; + honor = 60; + rew->m_CaptainsAlive[BG_TEAM_ALLIANCE]--; + rew->m_CaptainsKilled[BG_TEAM_HORDE]++; + ressources = 100; + break; + case 11947: + reputation = 125; + honor = 60; + rew->m_CaptainsAlive[BG_TEAM_HORDE]--; + rew->m_CaptainsKilled[BG_TEAM_ALLIANCE]++; + ressources = 100; + break; + default: + ressources = 0; + honor = 0; + break; + } + uint32 faction = 0; + if(teamIndex==0) + HScore -= ressources; + else AScore -= ressources; + if(killer->GetTeam() == ALLIANCE) + faction = 730; + else faction = 729; + + //RewardReputation(faction,reputation, killer->GetTeam(),killer); + UpdateScore(); +} +void BattleGroundAV::UpdateScore() +{ + uint32 TAScore = (AScore<0)?0:AScore; + uint32 THScore = (HScore<0)?0:HScore; + + UpdateWorldState(AV_Alliance_Score, TAScore); + UpdateWorldState(AV_Horde_Score, THScore); +} + +void BattleGroundAV::InitWorldStates() +{ + UpdateWorldState(AV_Alliance_Score, AScore); + UpdateWorldState(AV_Horde_Score, HScore); + UpdateWorldState(AV_SHOW_H_SCORE, 1); + UpdateWorldState(AV_SHOW_A_SCORE, 1); +} + void BattleGroundAV::Update(time_t diff) { BattleGround::Update(diff); + + if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) + { + ModifyStartDelayTime(diff); + InitWorldStates(); + + if (!(m_Events & 0x01)) + { + m_Events |= 0x01; + + sLog.outDebug("Alterac Valley: entering state STATUS_WAIT_JOIN ..."); + + // Starting doors + MapManager::Instance().GetMap(GetMapId(), m_bgobjects[BG_AV_OBJECT_GATE_A])->Add(m_bgobjects[BG_AV_OBJECT_GATE_A]); + MapManager::Instance().GetMap(GetMapId(), m_bgobjects[BG_AV_OBJECT_GATE_H])->Add(m_bgobjects[BG_AV_OBJECT_GATE_H]); + + SetStartDelayTime(START_DELAY0); + } + // After 1 minute, warning is signalled + else if (GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04)) + { + m_Events |= 0x04; + SendMessageToAll(LANG_BG_AV_ONEMINTOSTART); + } + // After 1,5 minute, warning is signalled + else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08)) + { + m_Events |= 0x08; + SendMessageToAll(LANG_BG_AV_HALFMINTOSTART); + } + // After 2 minutes, gates OPEN ! x) + else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10)) + { + m_Events |= 0x10; + SendMessageToAll(LANG_BG_AV_STARTED); + + m_bgobjects[BG_AV_OBJECT_GATE_A]->SetUInt32Value(GAMEOBJECT_FLAGS,33); + m_bgobjects[BG_AV_OBJECT_GATE_A]->SetUInt32Value(GAMEOBJECT_STATE,0); + m_bgobjects[BG_AV_OBJECT_GATE_H]->SetUInt32Value(GAMEOBJECT_FLAGS,33); + m_bgobjects[BG_AV_OBJECT_GATE_H]->SetUInt32Value(GAMEOBJECT_STATE,0); + + for(uint32 i=BG_AV_OBJECT_FIRSTAID_STATION; i<(BG_AV_OBJECT_FIRSTAID_STATION+15); i++) + { + _CreateBanner(i); + _ShowBanner(i); + if(!BG_AV_Nodes[i]._IsTower) + { + if(i<7)m_Nodes[i]=3; + else if(i>7)m_Nodes[i]=4; + else m_Nodes[i]=0; + _UpdateGYNode(i); + } + } + PlaySoundToAll(SOUND_BG_START); + SetStatus(STATUS_IN_PROGRESS); + BG_AV_Nodes[7]._WasNeutral=true; + } + } + else if(GetStatus() == STATUS_IN_PROGRESS) + { + // Test win condition + if (HScore <= 0) + EndBattleGround(ALLIANCE); + if (AScore <= 0) + EndBattleGround(HORDE); + + // Towers/Nodes + for(uint32 i=BG_AV_OBJECT_FIRSTAID_STATION; i<(BG_AV_OBJECT_FIRSTAID_STATION+15); i++) + { + if(BG_AV_Nodes[i].RespawnTimer) + if(BG_AV_Nodes[i].RespawnTimer>diff)BG_AV_Nodes[i].RespawnTimer-=diff; + else { + BG_AV_Nodes[i].RespawnTimer=0; + _ShowBanner(i); + } + if(BG_AV_Nodes[i].StateTimer) + if(BG_AV_Nodes[i].StateTimer>diff)BG_AV_Nodes[i].StateTimer-=diff; + else { + BG_AV_Nodes[i].StateTimer=0; + //_DeleteBanner(i); + UpdateWorldState(BG_AV_Nodes[i].WStates[BG_AV_Nodes[i].State],0); + BG_AV_Nodes[i].State-=2; + uint8 teamIndex = BG_AV_Nodes[i].State-1; + char buf[256]; + uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + if(BG_AV_Nodes[i]._IsTower) + { + //Node has been destoryed + sprintf(buf, LANG_BG_AV_TOWER_TAKEN, _GetNodeName(i)); + BG_AV_Nodes[i]._WasNeutral=false; + if(teamIndex == 0) + { + HScore-=BG_AV_SCORE_TOWER_LOST; + rew->m_TowersControlled[BG_TEAM_HORDE]--; + rew->m_TowersDestroyed[BG_TEAM_ALLIANCE]++; + } + else + { + rew->m_TowersControlled[BG_TEAM_ALLIANCE]--; + rew->m_TowersDestroyed[BG_TEAM_HORDE]++; + AScore-=BG_AV_SCORE_TOWER_LOST; + } + _DeleteBanner(i); + } + else + { + _DeleteBanner(i); + BG_AV_Nodes[i]._WasNeutral=false; + _CreateBanner(i); + BG_AV_Nodes[i].RespawnTimer=BG_AV_BANNER_RESPAWN_TIMER; + m_Nodes[i]=teamIndex+3; + _UpdateGYNode(i); + sprintf(buf, LANG_BG_AV_GRAVE_TAKEN, _GetNodeName(i), (teamIndex == 0) ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE); + } + UpdateWorldState(BG_AV_Nodes[i].WStates[BG_AV_Nodes[i].State],1); + WorldPacket data; + ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL); + SendPacketToAll(&data); + UpdateScore(); + } + } + } } +void BattleGroundAV::_CreateBanner(uint32 node) +{ + if(!m_bgobjects[node]) + { + m_bgobjects[node]= new GameObject(NULL); + m_bgobjects[node+BG_AV_AURA]= new GameObject(NULL); + sLog.outDebug("Alterac Valley: CREATE => node=%u id=%u state=%u",node,BG_AV_Nodes[node].GO_ids[BG_AV_Nodes[node].State],BG_AV_Nodes[node].State); + m_bgobjects[node]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AV_Nodes[node].GO_ids[BG_AV_Nodes[node].State] , GetMapId(), + BG_AV_Nodes[node].x, BG_AV_Nodes[node].y, BG_AV_Nodes[node].z, + BG_AV_Nodes[node].a, BG_AV_Nodes[node].r0, BG_AV_Nodes[node].r1, + BG_AV_Nodes[node].r2, BG_AV_Nodes[node].r3, 100, 1); + + uint32 banneraura = BG_AV_State_Auras[BG_AV_Nodes[node].State]; + if(BG_AV_Nodes[node]._IsTower)banneraura = BG_AV_State_Auras_Small[BG_AV_Nodes[node].State]; + + m_bgobjects[node+BG_AV_AURA]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), banneraura , GetMapId(), + BG_AV_Nodes[node].x, BG_AV_Nodes[node].y, BG_AV_Nodes[node].z, + BG_AV_Nodes[node].a, BG_AV_Nodes[node].r0, BG_AV_Nodes[node].r1, + BG_AV_Nodes[node].r2, BG_AV_Nodes[node].r3, 0, 0); + } + else + { + sLog.outError("Alterac Valley: Bad node => %u OBJECT IS THERE",node); + } +} +//administrator +void BattleGroundAV::_ShowBanner(uint32 node) +{ + sLog.outDebug("Alterac Valley: SHOW => node=%u",node); + MapManager::Instance().GetMap(GetMapId(), m_bgobjects[node])->Add(m_bgobjects[node]); + MapManager::Instance().GetMap(GetMapId(), m_bgobjects[node+BG_AV_AURA])->Add(m_bgobjects[node+BG_AV_AURA]); +} + +void BattleGroundAV::_DeleteBanner(uint32 node) +{ + sLog.outDebug("Alterac Valley: DELETE => node=%u",node); + m_bgobjects[node]->Delete(); + m_bgobjects[node]=NULL; + m_bgobjects[node+BG_AV_AURA]->Delete(); + m_bgobjects[node+BG_AV_AURA]=NULL; + if(BG_AV_Nodes[node]._IsTower && !BG_AV_Nodes[node]._WasNeutral) + { + m_bgobjects[node+BG_AV_FIRES]= new GameObject(NULL); + m_bgobjects[node+BG_AV_FIRES]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AB_OBJECTID_FIRE , GetMapId(), + BG_AV_Nodes[node].x, BG_AV_Nodes[node].y, BG_AV_Nodes[node].z, + BG_AV_Nodes[node].a, BG_AV_Nodes[node].r0, BG_AV_Nodes[node].r1, + BG_AV_Nodes[node].r2, BG_AV_Nodes[node].r3, 0, 0); + } +} + + void BattleGroundAV::AddPlayer(Player *plr) { BattleGround::AddPlayer(plr); @@ -50,7 +308,37 @@ void BattleGroundAV::RemovePlayer(Player *plr,uint64 guid) { + if(GetPlayersSize()==0) + { + sLog.outDebug("Alterac Valley: BG ended, objects despawning..."); + // delete everything (for times, when BG will instanced) + for(uint32 i=BG_AV_OBJECT_FIRSTAID_STATION; i<(BG_AV_OBJECT_FIRSTAID_STATION+15); i++) + if(BG_AV_Nodes[i].RespawnTimer) + { + BG_AV_Nodes[i].RespawnTimer=0; + _ShowBanner(i); //if object is created but not spawned - may generate error + } + + for(uint32 i = 0; i < BG_AV_OBJECT_MAX; i++) + if (m_bgobjects[i]) + { + m_bgobjects[i]->Delete(); + m_bgobjects[i] = NULL; + } + + for(uint32 i = 0; i<17; i++) + if(m_spiritGuides[i]) + { + m_spiritGuides[i]->CleanupsBeforeDelete(); + ObjectAccessor::Instance().AddObjectToRemoveList(m_spiritGuides[i]); + m_spiritGuides[i] = NULL; + m_Nodes[i]=0; + } + + Reset(); + SetupBattleGround(); + } } void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -63,14 +351,26 @@ switch(Trigger) { case 95: + case 2608: + if(Source->GetTeam() != ALLIANCE) + Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); + else + Source->LeaveBattleground(); + break; case 2606: - case 2608: + if(Source->GetTeam() != HORDE) + Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); + else + Source->LeaveBattleground(); + break; case 3326: case 3327: case 3328: case 3329: case 3330: case 3331: + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + //Source->Unmount(); break; default: sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); @@ -118,3 +418,272 @@ break; } } + +/* Invoked if a player used a banner as a gameobject */ +void BattleGroundAV::EventPlayerCapturedBanner(Player *source) +{ + if(GetStatus() != STATUS_IN_PROGRESS) + return; + + uint8 node = BG_AV_OBJECT_FIRSTAID_STATION; + while (node < (BG_AV_OBJECT_FIRSTAID_STATION+15)) + { + if(m_bgobjects[node]) + if((source->IsWithinDistInMap(m_bgobjects[node], 10))) // player and nodes distance + break; + ++node; + } + + if (node == (BG_AV_OBJECT_FIRSTAID_STATION+15)) + { + // this means our player isn't close to any of banners - maybe cheater ?? + return; + } + + _DeleteBanner(node); + + uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam()); + char buf[256]; + uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + + BG_AV_Nodes[node].RespawnTimer = BG_AV_BANNER_RESPAWN_TIMER; + BG_AV_Nodes[node].StateTimer=BG_AV_CAPTIME; + + UpdateWorldState(BG_AV_Nodes[node].WStates[BG_AV_Nodes[node].State],0); + + if(BG_AV_Nodes[node].State==0)BG_AV_Nodes[node].State=teamIndex+3; + else BG_AV_Nodes[node].State=5-BG_AV_Nodes[node].State; + if(BG_AV_Nodes[node]._WasNeutral)BG_AV_Nodes[node].State=teamIndex+3; + + if(BG_AV_Nodes[node]._IsTower) + { + if(BG_AV_Nodes[node].State>2) + { + UpdatePlayerScore(source,SCORE_TOWERS_ASSAULTED,1); + sprintf(buf, LANG_BG_AV_TOWER_ASSAULTED, _GetNodeName(node), (teamIndex == 0) ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE); + } + else + { + UpdatePlayerScore(source,SCORE_TOWERS_DEFENDED,1); + sprintf(buf, LANG_BG_AV_GRAVE_DEFENDED, _GetNodeName(node)); + } + } + else + { + if(BG_AV_Nodes[node]._WasNeutral) + { + sprintf(buf, LANG_BG_AV_GRAVE_ASSAULTED, _GetNodeName(node), (teamIndex == 0) ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE); + UpdatePlayerScore(source,SCORE_GRAVEYARDS_ASSAULTED,1); + } + else + { + if(BG_AV_Nodes[node].State>2) + { + UpdatePlayerScore(source,SCORE_GRAVEYARDS_ASSAULTED,1); + sprintf(buf, LANG_BG_AV_GRAVE_ASSAULTED, _GetNodeName(node), (teamIndex == 0) ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE); + m_Nodes[node]=teamIndex+1; + _UpdateGYNode(node); + } + else + { + UpdatePlayerScore(source,SCORE_GRAVEYARDS_DEFENDED,1); + sprintf(buf, LANG_BG_AV_GRAVE_DEFENDED, _GetNodeName(node)); + m_Nodes[node]=teamIndex+3; + _UpdateGYNode(node); + } + } + } + UpdateWorldState(BG_AV_Nodes[node].WStates[BG_AV_Nodes[node].State],1); + WorldPacket data; + ChatHandler::FillMessageData(&data, source->GetSession(), type, LANG_UNIVERSAL, NULL, source->GetGUID(), buf, NULL); + SendPacketToAll(&data); + UpdateScore(); + _CreateBanner(node); +} + +void BattleGroundAV::_UpdateGYNode(uint32 GYid) +{ + uint32 gystate=m_Nodes[GYid]; + sLog.outDebug("Alterac Valley: GY %u UPDATE = %u",GYid,gystate); + if(gystate>0) //to prevent double freeing + { + + if(gystate<3) + { + //changing from owned to free + sLog.outDebug("Alterac Valley: GY %u FREE",GYid); + // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard + std::vector ghost_list = m_ReviveQueue[m_spiritGuides[GYid]->GetGUID()]; + if (!ghost_list.empty()) + { + WorldSafeLocsEntry const *ClosestGrave = NULL; + Player *plr; + for (std::vector::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) + { + plr = objmgr.GetPlayer(*ghost_list.begin()); + if (!plr) + continue; + if (!ClosestGrave) + ClosestGrave = SelectGraveYard(plr); + + plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); + } + } + + m_spiritGuides[GYid]->CleanupsBeforeDelete(); + ObjectAccessor::Instance().AddObjectToRemoveList(m_spiritGuides[GYid]); + m_spiritGuides[GYid] = NULL; + m_Nodes[GYid]=0; + } + else + { + //changing from free to owned + + if (m_spiritGuides[GYid]) + return; + m_spiritGuides[GYid] = new Creature(NULL); + sLog.outDebug("Alterac Valley: GY %u NEW SG",GYid); + WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[GYid] ); + if (!m_spiritGuides[GYid]->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), entry->map_id, entry->x, entry->y, entry->z, 1, BG_AV_SpiritGuideId[gystate-3],BG_AV_SpiritGuideTeamId[gystate-3] )) + ASSERT(0); + m_spiritGuides[GYid]->setDeathState(DEAD); + m_spiritGuides[GYid]->AIM_Initialize(); + sLog.outDebug("Alterac Valley: GY %u ADD = %u",GYid,m_spiritGuides[GYid]->GetEntry()); + MapManager::Instance().GetMap(GetMapId(), m_spiritGuides[GYid])->Add(m_spiritGuides[GYid]); + m_spiritGuides[GYid]->CastSpell(m_spiritGuides[GYid], SPELL_SPIRIT_HEAL_CHANNEL, true); + sLog.outDebug("Alterac Valley: GY %u DONE",GYid); + } + } +} + +WorldSafeLocsEntry const* BattleGroundAV::SelectGraveYard(Player* player) +{ + uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam()); + + // Is there any occupied node for this team? + std::vector nodes; + for (uint8 i = 0; i < 15; ++i) + if (m_Nodes[i] == teamIndex+3) + nodes.push_back(i); + + WorldSafeLocsEntry const* good_entry = NULL; + // If so, select the closest node to place ghost on + if (!nodes.empty()) + { + float x = player->GetPositionX(); + float y = player->GetPositionY(); // let alone z coordinate... + float mindist = 999999.0f; + for (uint8 i = 0; i < nodes.size(); ++i) + { + WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[nodes[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; + } + } + nodes.clear(); + } + // If not, place ghost on starting location + if(!good_entry) + good_entry = sWorldSafeLocsStore.LookupEntry( BG_AV_GraveyardIds[teamIndex+15] ); + + return good_entry; +} + +bool BattleGroundAV::SetupBattleGround() +{ + // Initialize objects table + for (int i = 0; i < BG_AV_OBJECT_MAX; ++i) + m_bgobjects[i] = NULL; + for (int i = 0; i < 15; ++i) + m_spiritGuides[i] = NULL; + + //for (int i = BG_AV_AURA; i < BG_AV_AURA+15; ++i) + // m_bgobjects[i]= new GameObject(NULL); + AScore=BG_AV_SCORE_INITIAL_POINTS; + HScore=BG_AV_SCORE_INITIAL_POINTS; + //Alliance stats + for(uint8 i=0; i<2; i++) + { + rew->m_CaptainsAlive[i] = 2; + rew->m_CaptainsKilled[i] = 0; + rew->m_TowersControlled[i] = 8; + rew->m_TowersDestroyed[i] = 0; + rew->m_MinesControlled[i] = 0; + rew->m_GraveYardsControlled[i] = 3; + } + // Create starting objects + + // Starting gates + m_bgobjects[BG_AV_OBJECT_GATE_A] = new GameObject(NULL); + if(!m_bgobjects[BG_AV_OBJECT_GATE_A]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AV_OBJECTID_GATE_A, GetMapId(), BG_AV_DoorPositions[0][0], BG_AV_DoorPositions[0][1], BG_AV_DoorPositions[0][2], BG_AV_DoorPositions[0][3], BG_AV_DoorPositions[0][4], BG_AV_DoorPositions[0][5], BG_AV_DoorPositions[0][6], BG_AV_DoorPositions[0][7], 100, 1)) + return false; + m_bgobjects[BG_AV_OBJECT_GATE_H] = new GameObject(NULL); + if(!m_bgobjects[BG_AV_OBJECT_GATE_H]->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), BG_AV_OBJECTID_GATE_H, GetMapId(), BG_AV_DoorPositions[1][0], BG_AV_DoorPositions[1][1], BG_AV_DoorPositions[1][2], BG_AV_DoorPositions[1][3], BG_AV_DoorPositions[1][4], BG_AV_DoorPositions[1][5], BG_AV_DoorPositions[1][6], BG_AV_DoorPositions[1][7], 100, 1)) + return false; + + WorldSafeLocsEntry const *sg = NULL; + for(uint8 i=BG_AV_OBJECT_FIRSTAID_STATION; i<(BG_AV_OBJECT_FIRSTAID_STATION+15); i++) + { + //m_bgobjects[i]= new GameObject(NULL); + BG_AV_Nodes[i].RespawnTimer=0; + BG_AV_Nodes[i].State=0; + BG_AV_Nodes[i].StateTimer=0; + BG_AV_Nodes[i]._IsTower=true; + + if(BG_AV_NodePositions[i][8]==1)BG_AV_Nodes[i]._IsTower=false; + + if(i<7)BG_AV_Nodes[i].State=1; + if(i>7)BG_AV_Nodes[i].State=2; + + BG_AV_Nodes[i].x=BG_AV_NodePositions[i][0]; + BG_AV_Nodes[i].y=BG_AV_NodePositions[i][1]; + BG_AV_Nodes[i].z=BG_AV_NodePositions[i][2]; + BG_AV_Nodes[i].a=BG_AV_NodePositions[i][3]; + BG_AV_Nodes[i].r0=BG_AV_NodePositions[i][4]; + BG_AV_Nodes[i].r1=BG_AV_NodePositions[i][5]; + BG_AV_Nodes[i].r2=BG_AV_NodePositions[i][6]; + BG_AV_Nodes[i].r3=BG_AV_NodePositions[i][7]; + + for(uint8 k=0;k<5;k++) + BG_AV_Nodes[i].GO_ids[k]=BG_AV_Node_GO[i][k]; + for(uint8 k=0;k<5;k++) + BG_AV_Nodes[i].WStates[k]=BG_AV_Node_StateIcons[i][k]; + } + + return true; +} + +const char* BattleGroundAV::_GetNodeName(uint8 node) +{ + switch (node) + { + case BG_AV_OBJECT_FIRSTAID_STATION: return "Stormpike Aid Station"; + case BG_AV_OBJECT_DUNBALDAR_SHOUTH: return "The Dun Baldar South Bunker"; + case BG_AV_OBJECT_DUNBALDAR_NORTH: return "The Dun Baldar North Bunker"; + case BG_AV_OBJECT_STORMPIKE_GRAVE: return "Stormpike Graveyard"; + case BG_AV_OBJECT_ICEWING_BUNKER: return "The Icewing Bunker"; + case BG_AV_OBJECT_STONEHEART_GRAVE: return "Stonehearth Graveyard"; + case BG_AV_OBJECT_STONEHEART_BUNKER: return "The Stonehearth Bunker"; + case BG_AV_OBJECT_SNOWFALL_GRAVE: return "Snowfall Graveyard"; + case BG_AV_OBJECT_ICEBLOOD_TOWER: return "Iceblood Tower"; + case BG_AV_OBJECT_ICEBLOOD_GRAVE: return "Iceblood Graveyard"; + case BG_AV_OBJECT_TOWER_POINT: return "Tower Point"; + case BG_AV_OBJECT_FROSTWOLF_GRAVE: return "Frostwolf Graveyard"; + case BG_AV_OBJECT_FROSTWOLF_ETOWER: return "The East Frostwolf Tower"; + case BG_AV_OBJECT_FROSTWOLF_WTOWER: return "The West Frostwolf Tower"; + case BG_AV_OBJECT_FROSTWOLF_HUT: return "Frostwolf Relief Hut"; + default: + ASSERT(0); + } + return ""; +} + +void BattleGroundAV::ResetBGSubclass() +{ + AScore=BG_AV_SCORE_INITIAL_POINTS; + HScore=BG_AV_SCORE_INITIAL_POINTS; +} Index: src/game/BattleGroundAV.h =================================================================== --- src/game/BattleGroundAV.h (revision 5133) +++ src/game/BattleGroundAV.h (working copy) @@ -21,6 +21,181 @@ class BattleGround; +#define LANG_BG_AV_ALLY "Alliance" +#define LANG_BG_AV_HORDE "Horde" + +#define LANG_BG_AV_TOWER_TAKEN "%s was destroyed." +#define LANG_BG_AV_TOWER_ASSAULTED "%s is under attack! If left unchecked, the %s will destroy it!" + +#define LANG_BG_AV_GRAVE_TAKEN "The %s was taken by the %s" +#define LANG_BG_AV_GRAVE_DEFENDED "$n has defended the %s" +#define LANG_BG_AV_GRAVE_ASSAULTED "The %s is under attack! If left unchecked, the %s will control it!" +#define LANG_BG_AV_GRAVE_CLAIMED "$n claims the %s! If left unchallenged, the %s will control it!" + +#define LANG_BG_AV_ONEMINTOSTART "The Battle for Alterac Valley begins in 1 minute." +#define LANG_BG_AV_HALFMINTOSTART "The Battle for Alterac Valley begins in 30 seconds. Prepare yourselves!" +#define LANG_BG_AV_STARTED "The Battle for Alterac Valley has begun!" +#define LANG_BG_AV_A_NEAR_VICTORY "The Alliance is near victory!" +#define LANG_BG_AV_H_NEAR_VICTORY "The Horde is near victory!" + +enum BG_AV_ObjectTypes +{ + BG_AV_OBJECTID_BANNER_A = 178925, + BG_AV_OBJECTID_BANNER_H = 178943, + BG_AV_OBJECTID_BANNER_CONT_A = 178940, + BG_AV_OBJECTID_BANNER_CONT_H = 179435, + + BG_AV_OBJECTID_BANNER_A_B = 178365, + BG_AV_OBJECTID_BANNER_H_B = 178364, + BG_AV_OBJECTID_BANNER_CONT_A_B = 179286, + BG_AV_OBJECTID_BANNER_CONT_H_B = 179287, + + BG_AV_OBJECTID_BANNER_SNOWFALL_N = 180418, + + BG_AV_OBJECTID_AURA_A = 180421, + BG_AV_OBJECTID_AURA_H = 180422, + BG_AV_OBJECTID_AURA_C = 180423, + + BG_AV_OBJECTID_AURA_A_S = 180100, + BG_AV_OBJECTID_AURA_H_S = 180101, + BG_AV_OBJECTID_AURA_C_S = 180102, + + BG_AV_OBJECTID_GATE_A = 180424, + BG_AV_OBJECTID_GATE_H = 180424, + + BG_AB_OBJECTID_FIRE = 179065 +}; +const float BG_AV_NodePositions[15][9] = { + {552.585,-77.9304,51.9273,5.10115,0,0,0.557207,-0.830373,1}, + {623.184,-42.7891,42.2024,5.13256,0,0,0.544096,-0.839023,0}, + {673.021,-144.669,63.6473,0.907122,0,0,0.438169,0.898892,0}, + {668.013,-292.967,30.2909,2.76067,0,0,0.981917,0.189313,1}, + {202.515,-359.258,56.3768,5.34463,0,0,0.452241,-0.891896,0}, + {78.3916,-405.245,47.1657,1.64148,0,0,0.73165,0.68168,1}, + {-151.864,-440.838,40.3897,4.1744,0,0,0.869601,-0.493754,0}, + {-202.776,-112.4,78.4893,2.01061,0,0,0.844326,0.53583,1}, + {-572.723,-262.062,75.0087,5.44671,0,0,0.406149,-0.913807,0}, + {-611.962,-396.17,60.8351,2.53682,0,0,0.954629,0.297799,1}, + {-768.907,-363.71,90.8949,1.07991,0,0,0.514096,0.857733,0}, + {-1083.37,-340.922,55.2714,4.99119,0,0,0.601994,-0.798501,1}, + {-1297.5,-266.767,114.15,3.31044,0,0,0.996438,-0.0843258,0}, + {-1302.89,-316.92,113.867,2.01453,0,0,0.845375,0.534173,0}, + {-1403.93,-308.839,89.3659,5.24645,0,0,0.495464,-0.868629,1} +}; + +const uint32 BG_AV_State_Auras[5] = { BG_AV_OBJECTID_AURA_C,BG_AV_OBJECTID_AURA_A,BG_AV_OBJECTID_AURA_H,BG_AV_OBJECTID_AURA_C,BG_AV_OBJECTID_AURA_C }; +const uint32 BG_AV_State_Auras_Small[5] = { BG_AV_OBJECTID_AURA_C_S,BG_AV_OBJECTID_AURA_A_S,BG_AV_OBJECTID_AURA_H_S,BG_AV_OBJECTID_AURA_C_S,BG_AV_OBJECTID_AURA_C_S }; +const uint32 BG_AV_GraveyardIds[17] = { 751, 0,0, 689, 0, 729, 0, 169, 0, 749, 0, 690, 0,0, 750, 611, 610}; + +const uint32 BG_AV_Node_StateIcons[15][5] = { + {0,1325,1326,1327,1328}, + {0,1362,1371,0,1379}, + {0,1361,1370,0,1378}, + {0,1333,1334,1335,1336}, + {0,1363,1372,0,1380}, + {0,1302,1303,1304,1305}, + {0,1364,1373,0,1381}, + {1966,1341,1342,1343,1344}, + {0,1368,1385,1390,0}, + {0,1346,1347,1348,1349}, + {0,1367,1384,1389,0}, + {0,1337,1338,1339,1340}, + {0,1365,1382,1387,0}, + {0,1366,1383,1388,0}, + {0,1329,1330,1331,1332} +}; + +const uint32 BG_AV_Node_GO[15][5] = { + {0,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, + {0,BG_AV_OBJECTID_BANNER_A,0,0,BG_AV_OBJECTID_BANNER_CONT_H}, + {0,BG_AV_OBJECTID_BANNER_A,0,0,BG_AV_OBJECTID_BANNER_CONT_H}, + {0,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, + {0,BG_AV_OBJECTID_BANNER_A,0,0,BG_AV_OBJECTID_BANNER_CONT_H}, + {0,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, + {0,BG_AV_OBJECTID_BANNER_A,0,0,BG_AV_OBJECTID_BANNER_CONT_H}, + {BG_AV_OBJECTID_BANNER_SNOWFALL_N,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, + {0,0,BG_AV_OBJECTID_BANNER_H,BG_AV_OBJECTID_BANNER_CONT_A,0}, + {0,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, + {0,0,BG_AV_OBJECTID_BANNER_H,BG_AV_OBJECTID_BANNER_CONT_A,0}, + {0,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, + {0,0,BG_AV_OBJECTID_BANNER_H,BG_AV_OBJECTID_BANNER_CONT_A,0}, + {0,0,BG_AV_OBJECTID_BANNER_H,BG_AV_OBJECTID_BANNER_CONT_A,0}, + {0,BG_AV_OBJECTID_BANNER_A_B,BG_AV_OBJECTID_BANNER_H_B,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_OBJECTID_BANNER_CONT_H_B}, +}; + +enum BG_AV_ObjectType +{ + BG_AV_OBJECT_FIRSTAID_STATION = 0, + BG_AV_OBJECT_DUNBALDAR_SHOUTH = 1, + BG_AV_OBJECT_DUNBALDAR_NORTH = 2, + BG_AV_OBJECT_STORMPIKE_GRAVE = 3, + BG_AV_OBJECT_ICEWING_BUNKER = 4, + BG_AV_OBJECT_STONEHEART_GRAVE = 5, + BG_AV_OBJECT_STONEHEART_BUNKER = 6, + BG_AV_OBJECT_SNOWFALL_GRAVE = 7, + BG_AV_OBJECT_ICEBLOOD_TOWER = 8, + BG_AV_OBJECT_ICEBLOOD_GRAVE = 9, + BG_AV_OBJECT_TOWER_POINT = 10, + BG_AV_OBJECT_FROSTWOLF_GRAVE = 11, + BG_AV_OBJECT_FROSTWOLF_ETOWER = 12, + BG_AV_OBJECT_FROSTWOLF_WTOWER = 13, + BG_AV_OBJECT_FROSTWOLF_HUT = 14, + + BG_AV_OBJECT_GATE_A = 15, + BG_AV_OBJECT_GATE_H = 16, + + BG_AV_AURA = 17, + //15 aura objects + BG_AV_FIRES = 32, + //15 fires + + BG_AV_OBJECT_MAX = 47 +}; + +enum BG_AV_ScoreStates +{ + AV_Alliance_Score=3127, + AV_Horde_Score=3128, + AV_SHOW_H_SCORE=3133, + AV_SHOW_A_SCORE=3134 +}; + +#define BG_AV_CAPTIME 120000; +#define BG_AV_SNOWFALL_FIRSTCAP 180000; +#define BG_AV_SCORE_TOWER_LOST 200; //temp for 1v1 +#define BG_AV_SCORE_INITIAL_POINTS 600; +#define BG_AV_BANNER_RESPAWN_TIMER 3000; + +const float BG_AV_DoorPositions[2][8] = { + {780.487f, -493.024f, 99.9553f, 3.0976f, 0.0f, 0.0f, 0.999758f, 0.0219952f}, + {-879.096f, -547.722f, 57.3773f, 2.16454f, 0.0f, 0.0f, 0.883025f, 0.469326f} +}; + +struct BattleGroundAV_Node +{ + float x; + float y; + float z; + float a; + float r0; + float r1; + float r2; + float r3; + + bool _IsTower; + bool _WasNeutral; + + uint32 State; + uint32 GO_ids[5]; + uint32 WStates[5]; + + uint32 RespawnTimer; + uint32 StateTimer; +}; + +const uint32 BG_AV_SpiritGuideId[2] = {13116, 13117}; +const uint32 BG_AV_SpiritGuideTeamId[2] = { ALLIANCE, HORDE }; + class BattleGroundAVScore : public BattleGroundScore { public: @@ -38,7 +213,6 @@ class BattleGroundAV : public BattleGround { friend class BattleGroundMgr; - public: BattleGroundAV(); ~BattleGroundAV(); @@ -49,11 +223,35 @@ void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); - //bool SetupBattleGround(); + bool SetupBattleGround(); + virtual void ResetBGSubclass(); + /* Nodes occupying */ + void EventPlayerCapturedBanner(Player *source); + /* Scorekeeping */ void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + void HandleKillPlayer(Player* player, Player *killer); + void HandleKillUnit(Unit* unit, Player *kilelr); + WorldSafeLocsEntry const* SelectGraveYard(Player* player); + const char* _GetNodeName(uint8 node); private: + void _SetNodePosition(uint32 node,float x,float y,float z,float a,float r0,float r1,float r2,float r3); + void _SetNodeWorldStates(uint32 node,uint32 data[5]); + void _SetNodeGOids(uint32 node,uint32 data[5]); + void UpdateScore(); + void InitWorldStates(); + void _CreateBanner(uint32 node); + void _ShowBanner(uint32 node); + void _DeleteBanner(uint32 node); + void _UpdateGYNode(uint32 GYid); + + BattleGroundAV_Node BG_AV_Nodes[15]; + GameObject* m_bgobjects[BG_AV_OBJECT_MAX]; + int32 AScore; + int32 HScore; + uint8 m_Nodes[17]; + Creature* m_spiritGuides[17]; }; #endif Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 5133) +++ src/game/Player.cpp (working copy) @@ -53,6 +53,7 @@ #include "BattleGround.h" #include "BattleGroundMgr.h" #include "BattleGroundAB.h" +#include "BattleGroundAV.h" #include "ArenaTeam.h" #include "Chat.h" #include "Database/DatabaseImpl.h" @@ -3817,6 +3818,8 @@ if(bg && bg->GetTypeID() == BATTLEGROUND_AB) ClosestGrave = ((BattleGroundAB*)bg)->SelectGraveYard(this); + else if(bg && bg->GetTypeID() == BATTLEGROUND_AV) + ClosestGrave = ((BattleGroundAV*)bg)->SelectGraveYard(this); else ClosestGrave = objmgr.GetClosestGraveYard( GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam() ); Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 5133) +++ src/game/SpellEffects.cpp (working copy) @@ -2020,6 +2020,8 @@ // check if it's correct bg if(bg && bg->GetTypeID() == BATTLEGROUND_AB) ((BattleGroundAB*)bg)->EventPlayerCapturedBanner(player); + if(bg && bg->GetTypeID() == BATTLEGROUND_AV) + ((BattleGroundAV*)bg)->EventPlayerCapturedBanner(player); return; } } Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5133) +++ src/game/Unit.cpp (working copy) @@ -598,7 +598,29 @@ } } } + else if(pVictim->GetTypeId() == TYPEID_UNIT) + { + Player *killer = NULL; + if(((Player*)this)->GetTypeId()== TYPEID_PLAYER) + { + killer = ((Player*)this); + } + else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) + { + Unit *owner = GetOwner(); + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + killer = ((Player*)owner); + } + if(killer) + { + if(BattleGround *bg = killer->GetBattleGround()) + { + bg->HandleKillUnit(pVictim,killer); + } + } + } + DEBUG_LOG("DealDamage: victim just died"); DEBUG_LOG("DealDamageAttackStop");