diff --git a/sql/mangos.sql b/sql/mangos.sql index f6bf658d6..9071133cc 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8521_01_mangos_spell_proc_event` bit(1) default NULL + `required_8549_03_mangos_battleground_events` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- diff --git a/sql/updates/8548_01_mangos_creature_battleground.sql b/sql/updates/8548_01_mangos_creature_battleground.sql new file mode 100644 index 000000000..8f9e880e6 --- /dev/null +++ b/sql/updates/8548_01_mangos_creature_battleground.sql @@ -0,0 +1,10 @@ +ALTER TABLE db_version CHANGE COLUMN required_8521_01_mangos_spell_proc_event required_8548_01_mangos_creature_battleground bit; + +DROP TABLE IF EXISTS `creature_battleground`; +CREATE TABLE `creature_battleground` ( + `guid` int(10) unsigned NOT NULL COMMENT 'Creature\'s GUID', + `event1` tinyint(3) unsigned NOT NULL COMMENT 'main event', + `event2` tinyint(3) unsigned NOT NULL COMMENT 'sub event', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Creature battleground indexing system'; + diff --git a/sql/updates/8548_02_mangos_gameobject_battleground.sql b/sql/updates/8548_02_mangos_gameobject_battleground.sql new file mode 100644 index 000000000..a8dbd8e40 --- /dev/null +++ b/sql/updates/8548_02_mangos_gameobject_battleground.sql @@ -0,0 +1,10 @@ +ALTER TABLE db_version CHANGE COLUMN required_8548_01_mangos_creature_battleground required_8548_02_mangos_gameobject_battleground bit; + +DROP TABLE IF EXISTS `gameobject_battleground`; +CREATE TABLE `gameobject_battleground` ( + `guid` int(10) unsigned NOT NULL COMMENT 'GameObject\'s GUID', + `event1` tinyint(3) unsigned NOT NULL COMMENT 'main event', + `event2` tinyint(3) unsigned NOT NULL COMMENT 'sub event', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='GameObject battleground indexing system'; + diff --git a/sql/updates/8549_03_mangos_battleground_events.sql b/sql/updates/8549_03_mangos_battleground_events.sql new file mode 100644 index 000000000..63bedd54d --- /dev/null +++ b/sql/updates/8549_03_mangos_battleground_events.sql @@ -0,0 +1,92 @@ +ALTER TABLE db_version CHANGE COLUMN required_8548_02_mangos_gameobject_battleground required_8549_03_mangos_battleground_events bit; + +DROP TABLE IF EXISTS `battleground_events`; +CREATE TABLE `battleground_events` ( + `map` smallint(5) NOT NULL, + `event1` tinyint(3) unsigned NOT NULL, + `event2` tinyint(3) unsigned NOT NULL, + `description` varchar(255) NOT NULL, + PRIMARY KEY (`map`,`event1`,`event2`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +SET @WS_MAP = 489; +SET @AB_MAP = 529; +SET @EY_MAP = 566; +SET @NA_MAP = 559; +SET @BE_MAP = 562; +SET @RL_MAP = 572; + +INSERT INTO battleground_events (map, event1, event2, description) VALUES + (@WS_MAP, 0, 0, 'Alliance Flag'), + (@WS_MAP, 1, 0, 'Horde Flag'), + (@WS_MAP, 2, 0, 'Spirit Guides'), + (@WS_MAP, 254, 0, 'Doors'), + +-- arathi + (@AB_MAP, 0, 0, 'Stables - neutral'), + (@AB_MAP, 0, 1, 'Stables - alliance contested'), + (@AB_MAP, 0, 2, 'Stables - horde contested'), + (@AB_MAP, 0, 3, 'Stables - alliance owned'), + (@AB_MAP, 0, 4, 'Stables - horde owned'), + + (@AB_MAP, 1, 0, 'Blacksmith - neutral'), + (@AB_MAP, 1, 1, 'Blacksmith - alliance contested'), + (@AB_MAP, 1, 2, 'Blacksmith - horde contested'), + (@AB_MAP, 1, 3, 'Blacksmith - alliance owned'), + (@AB_MAP, 1, 4, 'Blacksmith - horde owned'), + + (@AB_MAP, 2, 0, 'Farm - neutral'), + (@AB_MAP, 2, 1, 'Farm - alliance contested'), + (@AB_MAP, 2, 2, 'Farm - horde contested'), + (@AB_MAP, 2, 3, 'Farm - alliance owned'), + (@AB_MAP, 2, 4, 'Farm - horde owned'), + + (@AB_MAP, 3, 0, 'Lumber Mill - neutral'), + (@AB_MAP, 3, 1, 'Lumber Mill - alliance contested'), + (@AB_MAP, 3, 2, 'Lumber Mill - horde contested'), + (@AB_MAP, 3, 3, 'Lumber Mill - alliance owned'), + (@AB_MAP, 3, 4, 'Lumber Mill - horde owned'), + + (@AB_MAP, 4, 0, 'Gold Mine - neutral'), + (@AB_MAP, 4, 1, 'Gold Mine - alliance contested'), + (@AB_MAP, 4, 2, 'Gold Mine - horde contested'), + (@AB_MAP, 4, 3, 'Gold Mine - alliance owned'), + (@AB_MAP, 4, 4, 'Gold Mine - horde owned'), + + (@AB_MAP, 254, 0, 'doors'), +-- eye of the storm + (@EY_MAP, 0, 0, 'Fel Reaver - alliance'), + (@EY_MAP, 0, 1, 'Fel Reaver - horde'), + (@EY_MAP, 0, 2, 'Fel Reaver - neutral'), + + (@EY_MAP, 1, 0, 'Blood Elf - alliance'), + (@EY_MAP, 1, 1, 'Blood Elf - horde'), + (@EY_MAP, 1, 2, 'Blood Elf - neutral'), + + (@EY_MAP, 2, 0, 'Draenei Ruins - alliance'), + (@EY_MAP, 2, 1, 'Draenei Ruins - horde'), + (@EY_MAP, 2, 2, 'Draenei Ruins - neutral'), + + (@EY_MAP, 3, 0, 'Mage Tower - alliance'), + (@EY_MAP, 3, 1, 'Mage Tower - horde'), + (@EY_MAP, 3, 2, 'Mage Tower - neutral'), + + (@EY_MAP, 4, 0, 'capture flag - Fel Reaver'), + (@EY_MAP, 4, 1, 'capture flag - Blood Elf'), + (@EY_MAP, 4, 2, 'capture flag - Draenei Ruins'), + (@EY_MAP, 4, 3, 'capture flag - Mage Tower'), + (@EY_MAP, 4, 4, 'capture flag - center'), + + (@EY_MAP, 254, 0, 'doors'), + +-- arenas + (@NA_MAP, 253, 0, 'buffs'), + (@NA_MAP, 254, 0, 'doors'), + + (@RL_MAP, 253, 0, 'buffs'), + (@RL_MAP, 254, 0, 'doors'), + + (@BE_MAP, 253, 0, 'buffs'), + (@BE_MAP, 254, 0, 'doors') diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index cd09ce4a8..5387117fa 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -113,6 +113,9 @@ pkgdata_DATA = \ 8511_01_mangos_spell_proc_event.sql \ 8514_01_mangos_spell_bonus_data.sql \ 8521_01_mangos_spell_proc_event.sql \ + 8548_01_mangos_creature_battleground.sql \ + 8548_02_mangos_gameobject_battleground.sql \ + 8549_03_mangos_battleground_events.sql \ README ## Additional files to include when running 'make dist' @@ -206,4 +209,7 @@ EXTRA_DIST = \ 8511_01_mangos_spell_proc_event.sql \ 8514_01_mangos_spell_bonus_data.sql \ 8521_01_mangos_spell_proc_event.sql \ + 8548_01_mangos_creature_battleground.sql \ + 8548_02_mangos_gameobject_battleground.sql \ + 8549_03_mangos_battleground_events.sql \ README diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index ed8a05963..15dbc47fd 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -307,7 +307,7 @@ void AuctionHouseMgr::LoadAuctionItems() if(!proto) { - sLog.outError( "ObjectMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid,item_template); + sLog.outError( "AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid,item_template); continue; } @@ -416,7 +416,7 @@ void AuctionHouseMgr::LoadAuctions() } // check if sold item exists for guid - // and item_template in fact (GetAItem will fail if problematic in result check in ObjectMgr::LoadAuctionItems) + // and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) if ( !GetAItem( aItem->item_guidlow ) ) { aItem->DeleteFromDB(); diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 4d6113fab..0667c5cea 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -130,7 +130,6 @@ BattleGround::BattleGround() m_Status = STATUS_NONE; m_ClientInstanceID = 0; m_EndTime = 0; - m_LastResurrectTime = 0; m_QueueId = QUEUE_ID_MAX_LEVEL_19; m_InvitedAlliance = 0; m_InvitedHorde = 0; @@ -199,11 +198,8 @@ BattleGround::~BattleGround() { // remove objects and creatures // (this is done automatically in mapmanager update, when the instance is reset after the reset time) - int size = m_BgCreatures.size(); - for(int i = 0; i < size; ++i) - DelCreature(i); - size = m_BgObjects.size(); + int size = m_BgObjects.size(); for(int i = 0; i < size; ++i) DelObject(i); @@ -263,62 +259,6 @@ void BattleGround::Update(uint32 diff) } } - /*********************************************************/ - /*** BATTLEGROUND RESSURECTION SYSTEM ***/ - /*********************************************************/ - - //this should be handled by spell system - m_LastResurrectTime += diff; - if (m_LastResurrectTime >= RESURRECTION_INTERVAL) - { - if (GetReviveQueueSize()) - { - for(std::map >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) - { - Creature *sh = NULL; - for(std::vector::const_iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2) - { - Player *plr = objmgr.GetPlayer(*itr2); - if (!plr) - continue; - - if (!sh && plr->IsInWorld()) - { - sh = plr->GetMap()->GetCreature(itr->first); - // only for visual effect - if (sh) - // Spirit Heal, effect 117 - sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true); - } - - // Resurrection visual - plr->CastSpell(plr, SPELL_RESURRECTION_VISUAL, true); - m_ResurrectQueue.push_back(*itr2); - } - (itr->second).clear(); - } - - m_ReviveQueue.clear(); - m_LastResurrectTime = 0; - } - else - // queue is clear and time passed, just update last resurrection time - m_LastResurrectTime = 0; - } - else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC - { - for(std::vector::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr) - { - Player *plr = objmgr.GetPlayer(*itr); - if (!plr) - continue; - plr->ResurrectPlayer(1.0f); - plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true); - ObjectAccessor::Instance().ConvertCorpseForPlayer(*itr); - } - m_ResurrectQueue.clear(); - } - /*********************************************************/ /*** BATTLEGROUND BALLANCE SYSTEM ***/ /*********************************************************/ @@ -360,10 +300,24 @@ void BattleGround::Update(uint32 diff) } m_PrematureCountDownTimer = newtime; } + } else if (m_PrematureCountDown) m_PrematureCountDown = false; + /*********************************************************/ + /*** ARENA BUFF OBJECT SPAWNING ***/ + /*********************************************************/ + if (isArena() && !m_ArenaBuffSpawned) + { + // 60 seconds after start the buffobjects in arena should get spawned + if (m_StartTime > uint32(m_StartDelayTimes[BG_STARTING_EVENT_FIRST] + ARENA_SPAWN_BUFF_OBJECTS)) + { + SpawnEvent(ARENA_BUFF_EVENT, 0, true); + m_ArenaBuffSpawned = true; + } + } + /*********************************************************/ /*** BATTLEGROUND STARTING SYSTEM ***/ /*********************************************************/ @@ -961,8 +915,6 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac m_PlayerScores.erase(itr2); } - RemovePlayerFromResurrectQueue(guid); - Player *plr = objmgr.GetPlayer(guid); // should remove spirit of redemption @@ -1077,12 +1029,19 @@ void BattleGround::Reset() SetStatus(STATUS_WAIT_QUEUE); SetStartTime(0); SetEndTime(0); - SetLastResurrectTime(0); SetArenaType(0); SetRated(false); m_Events = 0; + // door-event2 is always 0 + m_ActiveEvents[BG_EVENT_DOOR] = 0; + if (isArena()) + { + m_ActiveEvents[ARENA_BUFF_EVENT] = BG_EVENT_NONE; + m_ArenaBuffSpawned = false; + } + if (m_InvitedAlliance > 0 || m_InvitedHorde > 0) sLog.outError("BattleGround system: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance, m_InvitedHorde); @@ -1100,7 +1059,6 @@ void BattleGround::Reset() void BattleGround::StartBattleGround() { SetStartTime(0); - SetLastResurrectTime(0); // add BG to free slot queue AddToBGFreeSlotQueue(); @@ -1332,39 +1290,6 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) } } -void BattleGround::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid) -{ - m_ReviveQueue[npc_guid].push_back(player_guid); - - Player *plr = objmgr.GetPlayer(player_guid); - if (!plr) - return; - - plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true); -} - -void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid) -{ - for(std::map >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) - { - for(std::vector::iterator itr2 =(itr->second).begin(); itr2 != (itr->second).end(); ++itr2) - { - if (*itr2 == player_guid) - { - (itr->second).erase(itr2); - - Player *plr = objmgr.GetPlayer(player_guid); - if (!plr) - return; - - plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT); - - return; - } - } - } -} - bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime) { Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); @@ -1413,9 +1338,9 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float //some doors aren't despawned so we cannot handle their closing in gameobject::update() //it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code -void BattleGround::DoorClose(uint32 type) +void BattleGround::DoorClose(uint64 const& guid) { - GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + GameObject *obj = HashMapHolder::Find(guid); if (obj) { //if doors are open, close it @@ -1432,9 +1357,9 @@ void BattleGround::DoorClose(uint32 type) } } -void BattleGround::DoorOpen(uint32 type) +void BattleGround::DoorOpen(uint64 const& guid) { - GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); + GameObject *obj = HashMapHolder::Find(guid); if (obj) { //change state to be sure they will be opened @@ -1447,112 +1372,136 @@ void BattleGround::DoorOpen(uint32 type) } } -void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) +void BattleGround::OnObjectDBLoad(Creature* creature) { + const BattleGroundEventIdx eventId = sBattleGroundMgr.GetCreatureEventIndex(creature->GetDBTableGUIDLow()); + if (eventId.event1 == BG_EVENT_NONE) + return; + m_EventObjects[MAKE_PAIR32(eventId.event1, eventId.event2)].creatures.push_back(creature->GetGUID()); + if (!IsActiveEvent(eventId.event1, eventId.event2)) + SpawnBGCreature(creature->GetGUID(), RESPAWN_ONE_DAY); +} + + +void BattleGround::OnObjectDBLoad(GameObject* obj) +{ + const BattleGroundEventIdx eventId = sBattleGroundMgr.GetGameObjectEventIndex(obj->GetDBTableGUIDLow()); + if (eventId.event1 == BG_EVENT_NONE) + return; + m_EventObjects[MAKE_PAIR32(eventId.event1, eventId.event2)].gameobjects.push_back(obj->GetGUID()); + if (!IsActiveEvent(eventId.event1, eventId.event2)) + { + SpawnBGObject(obj->GetGUID(), RESPAWN_ONE_DAY); + } + else + { + // it's possible, that doors aren't spawned anymore (wsg) + if (GetStatus() >= STATUS_IN_PROGRESS && IsDoor(eventId.event1, eventId.event2)) + DoorOpen(obj->GetGUID()); + } +} + +bool BattleGround::IsDoor(uint8 event1, uint8 event2) +{ + if (event1 == BG_EVENT_DOOR) + { + if (event2 > 0) + { + sLog.outError("BattleGround too high event2 for event1:%i", event1); + return false; + } + return true; + } + return false; +} + +void BattleGround::OpenDoorEvent(uint8 event1, uint8 event2 /*=0*/) +{ + if (!IsDoor(event1, event2)) + { + sLog.outError("BattleGround:OpenDoorEvent this is no door event1:%u event2:%u", event1, event2); + return; + } + if (!IsActiveEvent(event1, event2)) // maybe already despawned (eye) + { + sLog.outError("BattleGround:OpenDoorEvent this event isn't active event1:%u event2:%u", event1, event2); + return; + } + BGObjects::const_iterator itr = m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.begin(); + for(; itr != m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.end(); ++itr) + DoorOpen(*itr); +} + +void BattleGround::SpawnEvent(uint8 event1, uint8 event2, bool spawn) +{ + // stop if we want to spawn something which was already spawned + // or despawn something which was already despawned + if (event2 == BG_EVENT_NONE || (spawn && m_ActiveEvents[event1] == event2) + || (!spawn && m_ActiveEvents[event1] != event2)) + return; + + if (spawn) + { + // if event gets spawned, the current active event mus get despawned + SpawnEvent(event1, m_ActiveEvents[event1], false); + m_ActiveEvents[event1] = event2; // set this event to active + } + else + m_ActiveEvents[event1] = BG_EVENT_NONE; // no event active if event2 gets despawned + + BGCreatures::const_iterator itr = m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.begin(); + for(; itr != m_EventObjects[MAKE_PAIR32(event1, event2)].creatures.end(); ++itr) + SpawnBGCreature(*itr, (spawn) ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + BGObjects::const_iterator itr2 = m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.begin(); + for(; itr2 != m_EventObjects[MAKE_PAIR32(event1, event2)].gameobjects.end(); ++itr2) + SpawnBGObject(*itr2, (spawn) ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); +} + +void BattleGround::SpawnBGObject(uint64 const& guid, uint32 respawntime) +{ + GameObject *obj = HashMapHolder::Find(guid); + if(!obj) + return; Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); if (!map) return; if (respawntime == 0) { - GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); - if (obj) - { - //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again - if (obj->getLootState() == GO_JUST_DEACTIVATED) - obj->SetLootState(GO_READY); - obj->SetRespawnTime(0); - map->Add(obj); - } + //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again + if (obj->getLootState() == GO_JUST_DEACTIVATED) + obj->SetLootState(GO_READY); + obj->SetRespawnTime(0); + map->Add(obj); } else { - GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); - if (obj) - { - map->Add(obj); - obj->SetRespawnTime(respawntime); - obj->SetLootState(GO_JUST_DEACTIVATED); - } + map->Add(obj); + obj->SetRespawnTime(respawntime); + obj->SetLootState(GO_JUST_DEACTIVATED); } } -Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) +void BattleGround::SpawnBGCreature(uint64 const& guid, uint32 respawntime) { + Creature* obj = HashMapHolder::Find(guid); + if (!obj) + return; Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); if (!map) - return NULL; - - Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, teamval)) - { - sLog.outError("Can't create creature entry: %u",entry); - delete pCreature; - return NULL; - } - - pCreature->Relocate(x, y, z, o); - - if (!pCreature->IsPositionValid()) - { - sLog.outError("Creature (guidlow %d, entry %d) not added to battleground. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); - delete pCreature; - return NULL; - } - - pCreature->AIM_Initialize(); - - //pCreature->SetDungeonDifficulty(0); - - map->Add(pCreature); - m_BgCreatures[type] = pCreature->GetGUID(); - - return pCreature; -} -/* -void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime) -{ - Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId()); - if (!map) - return false; - + return; if (respawntime == 0) { - Creature *obj = HashMapHolder::Find(m_BgCreatures[type]); - if (obj) - { - //obj->Respawn(); // bugged - obj->SetRespawnTime(0); - objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0); - map->Add(obj); - } + obj->Respawn(); + map->Add(obj); } else { - Creature *obj = HashMapHolder::Find(m_BgCreatures[type]); - if (obj) - { - obj->setDeathState(DEAD); - obj->SetRespawnTime(respawntime); - map->Add(obj); - } + map->Add(obj); + obj->setDeathState(JUST_DIED); + obj->SetRespawnDelay(respawntime); + obj->RemoveCorpse(); } } -*/ -bool BattleGround::DelCreature(uint32 type) -{ - if (!m_BgCreatures[type]) - return true; - - Creature *cr = HashMapHolder::Find(m_BgCreatures[type]); - if (!cr) - { - sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type])); - return false; - } - cr->AddObjectToRemoveList(); - m_BgCreatures[type] = 0; - return true; -} bool BattleGround::DelObject(uint32 type) { @@ -1571,38 +1520,6 @@ bool BattleGround::DelObject(uint32 type) return true; } -bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team) -{ - uint32 entry = 0; - - if (team == ALLIANCE) - entry = 13116; - else - entry = 13117; - - Creature* pCreature = AddCreature(entry,type,team,x,y,z,o); - if (!pCreature) - { - sLog.outError("Can't create Spirit guide. BattleGround not created!"); - EndNow(); - return false; - } - - pCreature->setDeathState(DEAD); - - pCreature->SetChannelObjectGUID(pCreature->GetGUID()); - // aura - pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL); - // casting visual effect - pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL); - // correct cast speed - pCreature->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); - - //pCreature->CastSpell(pCreature, SPELL_SPIRIT_HEAL_CHANNEL, true); - - return true; -} - void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* source) { MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source); @@ -1663,17 +1580,19 @@ void BattleGround::HandleTriggerBuff(uint64 const& go_guid) if (m_BuffChange && entry != Buff_Entries[buff]) { //despawn current buff - SpawnBGObject(index, RESPAWN_ONE_DAY); + SpawnBGObject(m_BgObjects[index], RESPAWN_ONE_DAY); //set index for new one for (uint8 currBuffTypeIndex = 0; currBuffTypeIndex < 3; ++currBuffTypeIndex) + { if (entry == Buff_Entries[currBuffTypeIndex]) { index -= currBuffTypeIndex; index += buff; } + } } - SpawnBGObject(index, BUFF_RESPAWN_TIME); + SpawnBGObject(m_BgObjects[index], BUFF_RESPAWN_TIME); } void BattleGround::HandleKillPlayer( Player *player, Player *killer ) @@ -1716,11 +1635,6 @@ uint32 BattleGround::GetPlayerTeam(uint64 guid) return 0; } -uint32 BattleGround::GetOtherTeam(uint32 teamId) -{ - return (teamId) ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0; -} - bool BattleGround::IsPlayerInBattleGround(uint64 guid) { BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid); diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 8d81d13b8..fa26e69bd 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -22,6 +22,15 @@ #include "Common.h" #include "SharedDefines.h" +// magic event-numbers +#define BG_EVENT_NONE 255 +// those generic events should get a high event id +#define BG_EVENT_DOOR 254 +// only arena event +// cause this buff apears 90sec after start in every bg i implement it here +#define ARENA_BUFF_EVENT 252 + + class Creature; class GameObject; class Group; @@ -30,6 +39,12 @@ class WorldPacket; struct WorldSafeLocsEntry; +struct BattleGroundEventIdx +{ + uint8 event1; + uint8 event2; +}; + enum BattleGroundSounds { SOUND_HORDE_WINS = 8454, @@ -67,17 +82,12 @@ enum BattleGroundMarksCount enum BattleGroundSpells { - SPELL_WAITING_FOR_RESURRECT = 2584, // Waiting to Resurrect - SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel - SPELL_SPIRIT_HEAL = 22012, // Spirit Heal - SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual SPELL_ARENA_PREPARATION = 32727, // use this one, 32728 not correct SPELL_ALLIANCE_GOLD_FLAG = 32724, SPELL_ALLIANCE_GREEN_FLAG = 32725, SPELL_HORDE_GOLD_FLAG = 35774, SPELL_HORDE_GREEN_FLAG = 35775, SPELL_PREPARATION = 44521, // Preparation - SPELL_SPIRIT_HEAL_MANA = 44535, // Spirit Heal SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag SPELL_AURA_PLAYER_INACTIVE = 43681 // Inactive }; @@ -93,6 +103,7 @@ enum BattleGroundTimeIntervals RESPAWN_ONE_DAY = 86400, // secs RESPAWN_IMMEDIATELY = 0, // secs BUFF_RESPAWN_TIME = 180, // secs + ARENA_SPAWN_BUFF_OBJECTS = 90000, // ms - 90sec after start }; enum BattleGroundStartTimeIntervals @@ -306,7 +317,6 @@ class BattleGround uint32 GetClientInstanceID() const { return m_ClientInstanceID; } uint32 GetStartTime() const { return m_StartTime; } uint32 GetEndTime() const { return m_EndTime; } - uint32 GetLastResurrectTime() const { return m_LastResurrectTime; } uint32 GetMaxPlayers() const { return m_MaxPlayers; } uint32 GetMinPlayers() const { return m_MinPlayers; } @@ -337,7 +347,6 @@ class BattleGround void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; } void SetStartTime(uint32 Time) { m_StartTime = Time; } void SetEndTime(uint32 Time) { m_EndTime = Time; } - void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; } void SetMaxPlayers(uint32 MaxPlayers) { m_MaxPlayers = MaxPlayers; } void SetMinPlayers(uint32 MinPlayers) { m_MinPlayers = MinPlayers; } void SetLevelRange(uint32 min, uint32 max) { m_LevelMin = min; m_LevelMax = max; } @@ -380,11 +389,6 @@ class BattleGround BattleGroundScoreMap::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } uint32 GetPlayerScoresSize() const { return m_PlayerScores.size(); } - uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } - - void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid); - void RemovePlayerFromResurrectQueue(uint64 player_guid); - void StartBattleGround(); /* Location */ @@ -478,29 +482,44 @@ class BattleGround virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); // can be extended in in BG subclass + /* event related */ + // generic implementation in BattleGround-class + // called when a creature gets added to map (NOTE: only triggered if + // a player activates the cell of the creature) + virtual void OnObjectDBLoad(Creature* /*creature*/); + virtual void OnObjectDBLoad(GameObject* /*obj*/); + // (de-)spawns creatures and gameobjects from an event + void SpawnEvent(uint8 event1, uint8 event2, bool spawn); + bool IsActiveEvent(uint8 event1, uint8 event2) + { + if (m_ActiveEvents.find(event1) == m_ActiveEvents.end()) + return false; + return m_ActiveEvents[event1] == event2; + } + void OpenDoorEvent(uint8 event1, uint8 event2 = 0); + bool IsDoor(uint8 event1, uint8 event2); + + /* other things */ void HandleTriggerBuff(uint64 const& go_guid); // TODO: make this protected: typedef std::vector BGObjects; typedef std::vector BGCreatures; + // TODO drop m_BGObjects BGObjects m_BgObjects; - BGCreatures m_BgCreatures; - void SpawnBGObject(uint32 type, uint32 respawntime); + void SpawnBGObject(uint64 const& guid, uint32 respawntime); bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); -// void SpawnBGCreature(uint32 type, uint32 respawntime); - Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0); - bool DelCreature(uint32 type); + void SpawnBGCreature(uint64 const& guid, uint32 respawntime); bool DelObject(uint32 type); - bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team); - void DoorOpen(uint32 type); - void DoorClose(uint32 type); + void DoorOpen(uint64 const& guid); + void DoorClose(uint64 const& guid); virtual bool HandlePlayerUnderMap(Player * /*plr*/) { return false; } // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player uint32 GetPlayerTeam(uint64 guid); - uint32 GetOtherTeam(uint32 teamId); + uint32 GetOtherTeam(uint32 teamId){ return (teamId) ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0; } bool IsPlayerInBattleGround(uint64 guid); void SetDeleteThis() {m_SetDeleteThis = true;} @@ -508,21 +527,35 @@ class BattleGround /* virtual score-array - get's used in bg-subclasses */ int32 m_TeamScores[BG_TEAMS_COUNT]; + struct EventObjects + { + BGObjects gameobjects; + BGCreatures creatures; + }; + + // cause we create it dynamicly i use a map - to avoid resizing when + // using vector - also it contains 2*events concatenated with PAIR32 + // this is needed to avoid overhead of a 2dimensional std::map + std::map m_EventObjects; + // this must be filled first in BattleGroundXY::Reset().. else + // creatures will get added wrong + // door-events are automaticly added - but _ALL_ other must be in this vector + std::map m_ActiveEvents; + + protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); void PlayerAddedToBGCheckIfBGIsRunning(Player* plr); /* Scorekeeping */ - + BattleGroundScoreMap m_PlayerScores; // Player scores // must be implemented in BG subclass virtual void RemovePlayer(Player * /*player*/, uint64 /*guid*/) {} /* Player lists, those need to be accessible by inherited classes */ BattleGroundPlayerMap m_Players; - // Spirit Guide guid + Player list GUIDS - std::map > m_ReviveQueue; /* these are important variables used for starting messages @@ -541,8 +574,8 @@ class BattleGround BattleGroundStatus m_Status; uint32 m_ClientInstanceID; //the instance-id which is sent to the client and without any other internal use uint32 m_StartTime; + bool m_ArenaBuffSpawned; // to cache if arenabuff event is started (cause bool is faster than checking IsActiveEvent) int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself - uint32 m_LastResurrectTime; BGQueueIdBasedOnLevel m_QueueId; uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 8737b9395..ea10e3dee 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -21,7 +21,8 @@ #include "BattleGround.h" #include "BattleGroundAB.h" #include "Creature.h" -#include "ObjectMgr.h" +#include "GameObject.h" +#include "BattleGroundMgr.h" #include "Language.h" #include "Util.h" #include "WorldPacket.h" @@ -30,7 +31,6 @@ BattleGroundAB::BattleGroundAB() { m_BuffChange = true; m_BgObjects.resize(BG_AB_OBJECT_MAX); - m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT); m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES; m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE; @@ -50,7 +50,7 @@ void BattleGroundAB::Update(uint32 diff) { int team_points[BG_TEAMS_COUNT] = { 0, 0 }; - for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + for (int node = 0; node < BG_AB_NODES_MAX; ++node) { // 3 sec delay to spawn new banner instead previous despawned one if (m_BannerTimers[node].timer) @@ -76,8 +76,6 @@ void BattleGroundAB::Update(uint32 diff) uint8 teamIndex = m_Nodes[node]-1; m_prevNodes[node] = m_Nodes[node]; m_Nodes[node] += 2; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex); // create new occupied banner _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); _SendNodeUpdate(node); @@ -86,13 +84,11 @@ void BattleGroundAB::Update(uint32 diff) if (teamIndex == 0) { - // FIXME: team and node names not localized SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node)); PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); } else { - // FIXME: team and node names not localized SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node)); PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); } @@ -163,36 +159,20 @@ void BattleGroundAB::Update(uint32 diff) void BattleGroundAB::StartingEventCloseDoors() { - // despawn banners, auras and buffs - for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) - SpawnBGObject(obj, RESPAWN_ONE_DAY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); - - // Starting doors - DoorClose(BG_AB_OBJECT_GATE_A); - DoorClose(BG_AB_OBJECT_GATE_H); - SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); - - // Starting base spirit guides - _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE); - _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE); + // despawn buffs + for (int i = 0; i < BG_AB_NODES_MAX * 3; ++i) + SpawnBGObject(m_BgObjects[BG_AB_OBJECT_SPEEDBUFF_STABLES + i], RESPAWN_ONE_DAY); } void BattleGroundAB::StartingEventOpenDoors() { - // spawn neutral banners - for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) - SpawnBGObject(banner, RESPAWN_IMMEDIATELY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (int i = 0; i < BG_AB_NODES_MAX; ++i) { //randomly select buff to spawn uint8 buff = urand(0, 2); - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_BgObjects[BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3], RESPAWN_IMMEDIATELY); } - DoorOpen(BG_AB_OBJECT_GATE_A); - DoorOpen(BG_AB_OBJECT_GATE_H); + OpenDoorEvent(BG_EVENT_DOOR); } void BattleGroundAB::AddPlayer(Player *plr) @@ -256,27 +236,12 @@ void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool return; } - uint8 obj = node*8 + type + teamIndex; + // cause the node-type is in the generic form + // please see in the headerfile for the ids + if (type != BG_AB_NODE_TYPE_NEUTRAL) + type += teamIndex; - SpawnBGObject(obj, RESPAWN_IMMEDIATELY); - - // handle aura with banner - if (!type) - return; - obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, RESPAWN_IMMEDIATELY); -} - -void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) -{ - uint8 obj = node*8 + type + teamIndex; - SpawnBGObject(obj, RESPAWN_ONE_DAY); - - // handle aura with banner - if (!type) - return; - obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, RESPAWN_ONE_DAY); + SpawnEvent(node, type, true); // will automaticly despawn other events } int32 BattleGroundAB::_GetNodeNameId(uint8 node) @@ -299,17 +264,17 @@ void BattleGroundAB::FillInitialWorldStates(WorldPacket& data) const uint8 plusArray[] = {0, 2, 3, 0, 1}; // Node icons - for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + for (uint8 node = 0; node < BG_AB_NODES_MAX; ++node) data << uint32(BG_AB_OP_NODEICONS[node]) << uint32((m_Nodes[node]==0)?1:0); // Node occupied states - for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) - for (uint8 i = 1; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (uint8 node = 0; node < BG_AB_NODES_MAX; ++node) + for (uint8 i = 1; i < BG_AB_NODES_MAX; ++i) data << uint32(BG_AB_OP_NODESTATES[node] + plusArray[i]) << uint32((m_Nodes[node]==i)?1:0); // How many bases each team owns uint8 ally = 0, horde = 0; - for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + for (uint8 node = 0; node < BG_AB_NODES_MAX; ++node) if (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) ++ally; else if (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) @@ -342,7 +307,7 @@ void BattleGroundAB::_SendNodeUpdate(uint8 node) // How many bases each team owns uint8 ally = 0, horde = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (uint8 i = 0; i < BG_AB_NODES_MAX; ++i) if (m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) ++ally; else if (m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) @@ -354,12 +319,8 @@ void BattleGroundAB::_SendNodeUpdate(uint8 node) void BattleGroundAB::_NodeOccupied(uint8 node,Team team) { - if (!AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team)) - sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team); -// SpawnBGCreature(node,RESPAWN_IMMEDIATELY); - uint8 capturedNodes = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (uint8 i = 0; i < BG_AB_NODES_MAX; ++i) { if (m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i]) ++capturedNodes; @@ -370,78 +331,39 @@ void BattleGroundAB::_NodeOccupied(uint8 node,Team team) CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team); } -void BattleGroundAB::_NodeDeOccupied(uint8 node) -{ - if (node >= BG_AB_DYNAMIC_NODES_COUNT) - return; - - // 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_BgCreatures[node]]; - if (!ghost_list.empty()) - { - WorldSafeLocsEntry const *ClosestGrave = NULL; - for (std::vector::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) - { - Player* plr = objmgr.GetPlayer(*itr); - if (!plr) - continue; - - if (!ClosestGrave) // cache - ClosestGrave = GetClosestGraveYard(plr); - - if (ClosestGrave) - plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); - } - } - - if (m_BgCreatures[node]) - DelCreature(node); - - // buff object isn't despawned -} - /* Invoked if a player used a banner as a gameobject */ -void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/) +void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* target_obj) { if (GetStatus() != STATUS_IN_PROGRESS) return; - uint8 node = BG_AB_NODE_STABLES; - GameObject* obj=HashMapHolder::Find(m_BgObjects[node*8+7]); - while ( (node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10)))) - { - ++node; - obj=HashMapHolder::Find(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); - } - - if (node == BG_AB_DYNAMIC_NODES_COUNT) - { - // this means our player isn't close to any of banners - maybe cheater ?? + uint8 event = (sBattleGroundMgr.GetGameObjectEventIndex(target_obj->GetDBTableGUIDLow())).event1; + if (event >= BG_AB_NODES_MAX) // not a node return; - } + BG_AB_Nodes node = BG_AB_Nodes(event); BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(source->GetTeam()); // Check if player really could use this banner, not cheated - if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2)) + if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node] % 2)) return; source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); uint32 sound = 0; + + // TODO in the following code we should restructure a bit to avoid + // duplication (or maybe write functions?) // If node is neutral, change to contested if (m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL) { UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); m_prevNodes[node] = m_Nodes[node]; m_Nodes[node] = teamIndex + 1; - // burn current neutral banner - _DelBanner(node, BG_AB_NODE_TYPE_NEUTRAL, 0); // create new contested banner _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - // FIXME: team and node names not localized if (teamIndex == 0) SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY); else @@ -458,14 +380,11 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); m_prevNodes[node] = m_Nodes[node]; m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); // create new contested banner _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - // FIXME: node names not localized if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else @@ -477,15 +396,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ UpdatePlayerScore(source, SCORE_BASES_DEFENDED, 1); m_prevNodes[node] = m_Nodes[node]; m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_OCCUPIED; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); // create new occupied banner _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = 0; _NodeOccupied(node,(teamIndex == BG_TEAM_ALLIANCE) ? ALLIANCE:HORDE); - // FIXME: node names not localized if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else @@ -499,15 +415,11 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); m_prevNodes[node] = m_Nodes[node]; m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; - // burn current occupied banner - _DelBanner(node, BG_AB_NODE_TYPE_OCCUPIED, !teamIndex); // create new contested banner _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); _SendNodeUpdate(node); - _NodeDeOccupied(node); m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - // FIXME: node names not localized if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else @@ -519,7 +431,6 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ // If node is occupied again, send "X has taken the Y" msg. if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED) { - // FIXME: team and node names not localized if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node)); else @@ -530,31 +441,8 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ bool BattleGroundAB::SetupBattleGround() { - for (int i = 0 ; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - if (!AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i,BG_AB_OBJECTID_BANNER_CONT_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i,BG_AB_OBJECTID_BANNER_CONT_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i,BG_AB_OBJECTID_BANNER_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_HORDE + 8*i,BG_AB_OBJECTID_BANNER_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_ALLY + 8*i,BG_AB_OBJECTID_AURA_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_HORDE + 8*i,BG_AB_OBJECTID_AURA_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_CONTESTED + 8*i,BG_AB_OBJECTID_AURA_C,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - ) - { - sLog.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!"); - return false; - } - } - if (!AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY) - || !AddObject(BG_AB_OBJECT_GATE_H,BG_AB_OBJECTID_GATE_H,BG_AB_DoorPositions[1][0],BG_AB_DoorPositions[1][1],BG_AB_DoorPositions[1][2],BG_AB_DoorPositions[1][3],BG_AB_DoorPositions[1][4],BG_AB_DoorPositions[1][5],BG_AB_DoorPositions[1][6],BG_AB_DoorPositions[1][7],RESPAWN_IMMEDIATELY) - ) - { - sLog.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!"); - return false; - } //buffs - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (int i = 0; i < BG_AB_NODES_MAX; ++i) { if (!AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) @@ -571,32 +459,31 @@ void BattleGroundAB::Reset() //call parent's class reset BattleGround::Reset(); - m_TeamScores[BG_TEAM_ALLIANCE] = 0; - m_TeamScores[BG_TEAM_HORDE] = 0; - m_lastTick[BG_TEAM_ALLIANCE] = 0; - m_lastTick[BG_TEAM_HORDE] = 0; - m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; - m_HonorScoreTics[BG_TEAM_HORDE] = 0; - m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; - m_ReputationScoreTics[BG_TEAM_HORDE] = 0; + for (uint8 i = 0; i <= BG_TEAMS_COUNT; ++i) + { + m_TeamScores[i] = 0; + m_lastTick[i] = 0; + m_HonorScoreTics[i] = 0; + m_ReputationScoreTics[i] = 0; + m_TeamScores500Disadvantage[i] = false; + } + m_IsInformedNearVictory = false; - bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; - m_TeamScores500Disadvantage[BG_TEAM_ALLIANCE] = false; - m_TeamScores500Disadvantage[BG_TEAM_HORDE] = false; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (uint8 i = 0; i < BG_AB_NODES_MAX; ++i) { m_Nodes[i] = 0; m_prevNodes[i] = 0; m_NodeTimers[i] = 0; m_BannerTimers[i].timer = 0; + + // all nodes owned by neutral team at beginning + m_ActiveEvents[i] = BG_AB_NODE_TYPE_NEUTRAL; } - for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT; ++i) - if (m_BgCreatures[i]) - DelCreature(i); } void BattleGroundAB::EndBattleGround(uint32 winner) @@ -619,7 +506,7 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) // Is there any occupied node for this team? std::vector nodes; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (uint8 i = 0; i < BG_AB_NODES_MAX; ++i) if (m_Nodes[i] == teamIndex + 3) nodes.push_back(i); @@ -675,10 +562,10 @@ void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value bool BattleGroundAB::IsAllNodesConrolledByTeam(uint32 team) const { uint32 count = 0; - for(int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + for (int i = 0; i < BG_AB_NODES_MAX; ++i) if ((team == ALLIANCE && m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) || (team == HORDE && m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED)) ++count; - return count == BG_AB_DYNAMIC_NODES_COUNT; + return count == BG_AB_NODES_MAX; } diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 30471f1ee..fdaa74c2b 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -62,64 +62,32 @@ const uint32 BG_AB_OP_NODESTATES[5] = {1767, 1782, 1772, 1792, 1787}; const uint32 BG_AB_OP_NODEICONS[5] = {1842, 1846, 1845, 1844, 1843}; -/* Note: code uses that these IDs follow each other */ -enum BG_AB_NodeObjectId -{ - BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner - BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner - BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner - BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner - BG_AB_OBJECTID_NODE_BANNER_4 = 180091 // Gold mine banner -}; - enum BG_AB_ObjectType { - // for all 5 node points 8*5=40 objects - BG_AB_OBJECT_BANNER_NEUTRAL = 0, - BG_AB_OBJECT_BANNER_CONT_A = 1, - BG_AB_OBJECT_BANNER_CONT_H = 2, - BG_AB_OBJECT_BANNER_ALLY = 3, - BG_AB_OBJECT_BANNER_HORDE = 4, - BG_AB_OBJECT_AURA_ALLY = 5, - BG_AB_OBJECT_AURA_HORDE = 6, - BG_AB_OBJECT_AURA_CONTESTED = 7, - //gates - BG_AB_OBJECT_GATE_A = 40, - BG_AB_OBJECT_GATE_H = 41, + // TODO drop them (pool-system should be used for this) //buffs - BG_AB_OBJECT_SPEEDBUFF_STABLES = 42, - BG_AB_OBJECT_REGENBUFF_STABLES = 43, - BG_AB_OBJECT_BERSERKBUFF_STABLES = 44, - BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45, - BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46, - BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47, - BG_AB_OBJECT_SPEEDBUFF_FARM = 48, - BG_AB_OBJECT_REGENBUFF_FARM = 49, - BG_AB_OBJECT_BERSERKBUFF_FARM = 50, - BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51, - BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52, - BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53, - BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54, - BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55, - BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56, - BG_AB_OBJECT_MAX = 57, + BG_AB_OBJECT_SPEEDBUFF_STABLES = 1, + BG_AB_OBJECT_REGENBUFF_STABLES = 2, + BG_AB_OBJECT_BERSERKBUFF_STABLES = 3, + BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 4, + BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 5, + BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 6, + BG_AB_OBJECT_SPEEDBUFF_FARM = 7, + BG_AB_OBJECT_REGENBUFF_FARM = 8, + BG_AB_OBJECT_BERSERKBUFF_FARM = 9, + BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 10, + BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 11, + BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 12, + BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 13, + BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 14, + BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 15, + BG_AB_OBJECT_MAX = 16, }; -/* Object id templates from DB */ -enum BG_AB_ObjectTypes -{ - BG_AB_OBJECTID_BANNER_A = 180058, - BG_AB_OBJECTID_BANNER_CONT_A = 180059, - BG_AB_OBJECTID_BANNER_H = 180060, - BG_AB_OBJECTID_BANNER_CONT_H = 180061, - BG_AB_OBJECTID_AURA_A = 180100, - BG_AB_OBJECTID_AURA_H = 180101, - BG_AB_OBJECTID_AURA_C = 180102, - - BG_AB_OBJECTID_GATE_A = 180255, - BG_AB_OBJECTID_GATE_H = 180256 -}; +/* node events */ +// node-events are just event1=BG_AB_Nodes, event2=BG_AB_NodeStatus +// so we don't need to define the constants here :) enum BG_AB_Timers { @@ -133,22 +101,18 @@ enum BG_AB_Score }; /* do NOT change the order, else wrong behaviour */ -enum BG_AB_BattleGroundNodes +enum BG_AB_Nodes { BG_AB_NODE_STABLES = 0, BG_AB_NODE_BLACKSMITH = 1, BG_AB_NODE_FARM = 2, BG_AB_NODE_LUMBER_MILL = 3, BG_AB_NODE_GOLD_MINE = 4, - - BG_AB_DYNAMIC_NODES_COUNT = 5, // dynamic nodes that can be captured - - BG_AB_SPIRIT_ALIANCE = 5, - BG_AB_SPIRIT_HORDE = 6, - - BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static) + BG_AB_NODES_ERROR = 255 }; +#define BG_AB_NODES_MAX 5 + enum BG_AB_NodeStatus { BG_AB_NODE_TYPE_NEUTRAL = 0, @@ -175,30 +139,15 @@ enum BG_AB_Sounds #define BG_AB_NotABBGWeekendReputationTicks 200 #define BG_AB_ABBGWeekendReputationTicks 150 -// x, y, z, o -const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { - {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables - {977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith - {806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm - {856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill - {1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine -}; - -// x, y, z, o, rot0, rot1, rot2, rot3 -const float BG_AB_DoorPositions[2][8] = { - {1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f}, - {708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f} -}; - // Tick intervals and given points: case 0,1,2,3,4,5 captured nodes const uint32 BG_AB_TickIntervals[6] = {0, 12000, 9000, 6000, 3000, 1000}; const uint32 BG_AB_TickPoints[6] = {0, 10, 10, 10, 10, 30}; // WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location -const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899}; +const uint32 BG_AB_GraveyardIds[7] = {895, 894, 893, 897, 896, 898, 899}; // x, y, z, o -const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { +const float BG_AB_BuffPositions[BG_AB_NODES_MAX][4] = { {1185.71f, 1185.24f, -56.36f, 2.56f}, // stables {990.75f, 1008.18f, -42.60f, 2.43f}, // blacksmith {817.66f, 843.34f, -56.54f, 3.01f}, // farm @@ -206,17 +155,6 @@ const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { {1146.62f, 816.94f, -98.49f, 6.14f} // gold mine }; -// x, y, z, o -const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] = { - {1200.03f, 1171.09f, -56.47f, 5.15f}, // stables - {1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith - {833.00f, 793.00f, -57.25f, 5.27f}, // farm - {775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill - {1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine - {1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base - {714.61f, 646.15f, -10.87f, 4.34f} // horde starting base -}; - struct BG_AB_BannerTimer { uint32 timer; @@ -272,7 +210,6 @@ class BattleGroundAB : public BattleGround /* Creature spawning/despawning */ // TODO: working, scripted peons spawning void _NodeOccupied(uint8 node,Team team); - void _NodeDeOccupied(uint8 node); int32 _GetNodeNameId(uint8 node); @@ -282,10 +219,10 @@ class BattleGroundAB : public BattleGround 2: horde contested 3: ally occupied 4: horde occupied */ - uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; - uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; - BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; + uint8 m_Nodes[BG_AB_NODES_MAX]; + uint8 m_prevNodes[BG_AB_NODES_MAX]; // used for performant wordlstate-updating + BG_AB_BannerTimer m_BannerTimers[BG_AB_NODES_MAX]; + uint32 m_NodeTimers[BG_AB_NODES_MAX]; uint32 m_lastTick[BG_TEAMS_COUNT]; uint32 m_HonorScoreTics[BG_TEAMS_COUNT]; uint32 m_ReputationScoreTics[BG_TEAMS_COUNT]; diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index e15e360ba..fddc8bc45 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -26,8 +26,6 @@ BattleGroundBE::BattleGroundBE() { - m_BgObjects.resize(BG_BE_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; @@ -56,20 +54,11 @@ void BattleGroundBE::Update(uint32 diff) void BattleGroundBE::StartingEventCloseDoors() { - for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - - for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); } void BattleGroundBE::StartingEventOpenDoors() { - for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); + OpenDoorEvent(BG_EVENT_DOOR); } void BattleGroundBE::AddPlayer(Player *plr) @@ -161,19 +150,6 @@ void BattleGroundBE::Reset() bool BattleGroundBE::SetupBattleGround() { - // gates - if (!AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_BE_OBJECT_BUFF_1, BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120) - || !AddObject(BG_BE_OBJECT_BUFF_2, BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)) - { - sLog.outErrorDb("BatteGroundBE: Failed to spawn some object!"); - return false; - } - return true; } diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h index 0fea026e5..bbc130503 100644 --- a/src/game/BattleGroundBE.h +++ b/src/game/BattleGroundBE.h @@ -20,27 +20,6 @@ class BattleGround; -enum BattleGroundBEObjectTypes -{ - BG_BE_OBJECT_DOOR_1 = 0, - BG_BE_OBJECT_DOOR_2 = 1, - BG_BE_OBJECT_DOOR_3 = 2, - BG_BE_OBJECT_DOOR_4 = 3, - BG_BE_OBJECT_BUFF_1 = 4, - BG_BE_OBJECT_BUFF_2 = 5, - BG_BE_OBJECT_MAX = 6 -}; - -enum BattleGroundBEObjects -{ - BG_BE_OBJECT_TYPE_DOOR_1 = 183971, - BG_BE_OBJECT_TYPE_DOOR_2 = 183973, - BG_BE_OBJECT_TYPE_DOOR_3 = 183970, - BG_BE_OBJECT_TYPE_DOOR_4 = 183972, - BG_BE_OBJECT_TYPE_BUFF_1 = 184663, - BG_BE_OBJECT_TYPE_BUFF_2 = 184664 -}; - class BattleGroundBEScore : public BattleGroundScore { public: diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 824a8dd99..d9855e150 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -22,6 +22,7 @@ #include "BattleGroundEY.h" #include "Creature.h" #include "ObjectMgr.h" +#include "BattleGroundMgr.h" #include "Language.h" #include "WorldPacket.h" #include "Util.h" @@ -30,7 +31,7 @@ BattleGroundEY::BattleGroundEY() { m_BuffChange = true; m_BgObjects.resize(BG_EY_OBJECT_MAX); - m_BgCreatures.resize(BG_EY_CREATURES_MAX); + m_Points_Trigger[FEL_REALVER] = TR_FEL_REALVER_BUFF; m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF; m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF; @@ -94,25 +95,18 @@ void BattleGroundEY::Update(uint32 diff) void BattleGroundEY::StartingEventCloseDoors() { - SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); - - for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); } void BattleGroundEY::StartingEventOpenDoors() { - SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY); - SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY); + // eye-doors are despawned, not opened + SpawnEvent(BG_EVENT_DOOR, 0, false); - for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - for(uint32 i = 0; i < EY_POINTS_MAX; ++i) + for(uint32 i = 0; i < BG_EY_NODES_MAX; ++i) { //randomly spawn buff uint8 buff = urand(0, 2); - SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_BgObjects[BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3], RESPAWN_IMMEDIATELY); } } @@ -131,37 +125,33 @@ void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) void BattleGroundEY::CheckSomeoneJoinedPoint() { - GameObject *obj = NULL; - for (uint8 i = 0; i < EY_POINTS_MAX; ++i) + for (uint8 i = 0; i < BG_EY_NODES_MAX; ++i) { - obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); - if (obj) + uint8 j = 0; + while (j < m_PlayersNearPoint[BG_EY_NODES_MAX].size()) { - uint8 j = 0; - while (j < m_PlayersNearPoint[EY_POINTS_MAX].size()) + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[BG_EY_NODES_MAX][j]); + if (!plr) { - Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[EY_POINTS_MAX][j]); - if (!plr) - { - sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[EY_POINTS_MAX][j])); - ++j; - continue; - } - if (plr->CanCaptureTowerPoint() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) - { - //player joined point! - //show progress bar - UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, plr); - UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], plr); - UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, plr); - //add player to point - m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[EY_POINTS_MAX][j]); - //remove player from "free space" - m_PlayersNearPoint[EY_POINTS_MAX].erase(m_PlayersNearPoint[EY_POINTS_MAX].begin() + j); - } - else - ++j; + sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[BG_EY_NODES_MAX][j])); + ++j; + continue; } + if (plr->CanCaptureTowerPoint() && + plr->IsWithinDist3d(BG_EY_NodePositions[i][0], BG_EY_NodePositions[i][1], BG_EY_NodePositions[i][2], BG_EY_POINT_RADIUS)) + { + //player joined point! + //show progress bar + UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, plr); + UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], plr); + UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, plr); + //add player to point + m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[BG_EY_NODES_MAX][j]); + //remove player from "free space" + m_PlayersNearPoint[BG_EY_NODES_MAX].erase(m_PlayersNearPoint[BG_EY_NODES_MAX].begin() + j); + } + else + ++j; } } } @@ -169,40 +159,36 @@ void BattleGroundEY::CheckSomeoneJoinedPoint() void BattleGroundEY::CheckSomeoneLeftPoint() { //reset current point counts - for (uint8 i = 0; i < 2*EY_POINTS_MAX; ++i) + for (uint8 i = 0; i < 2*BG_EY_NODES_MAX; ++i) m_CurrentPointPlayersCount[i] = 0; - GameObject *obj = NULL; - for(uint8 i = 0; i < EY_POINTS_MAX; ++i) + for(uint8 i = 0; i < BG_EY_NODES_MAX; ++i) { - obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); - if (obj) + uint8 j = 0; + while (j < m_PlayersNearPoint[i].size()) { - uint8 j = 0; - while (j < m_PlayersNearPoint[i].size()) + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[i][j]); + if (!plr) { - Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[i][j]); - if (!plr) - { - sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j])); - //move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug - m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); - m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); - ++j; - continue; - } - if (!plr->CanCaptureTowerPoint() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) - //move player out of point (add him to players that are out of points - { - m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); - m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); - UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, plr); - } - else - { - //player is neat flag, so update count: - m_CurrentPointPlayersCount[2 * i + GetTeamIndexByTeamId(plr->GetTeam())]++; - ++j; - } + sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j])); + //move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug + m_PlayersNearPoint[BG_EY_NODES_MAX].push_back(m_PlayersNearPoint[i][j]); + m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); + ++j; + continue; + } + if (!plr->CanCaptureTowerPoint() || + !plr->IsWithinDist3d(BG_EY_NodePositions[i][0], BG_EY_NodePositions[i][1], BG_EY_NodePositions[i][2], BG_EY_POINT_RADIUS)) + //move player out of point (add him to players that are out of points + { + m_PlayersNearPoint[BG_EY_NODES_MAX].push_back(m_PlayersNearPoint[i][j]); + m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); + UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, plr); + } + else + { + //player is neat flag, so update count: + m_CurrentPointPlayersCount[2 * i + GetTeamIndexByTeamId(plr->GetTeam())]++; + ++j; } } } @@ -210,7 +196,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint() void BattleGroundEY::UpdatePointStatuses() { - for(uint8 point = 0; point < EY_POINTS_MAX; ++point) + for(uint8 point = 0; point < BG_EY_NODES_MAX; ++point) { if (m_PlayersNearPoint[point].empty()) continue; @@ -308,19 +294,19 @@ void BattleGroundEY::UpdatePointsIcons(uint32 Team, uint32 Point) //we MUST firstly send 0, after that we can send 1!!! if (m_PointState[Point] == EY_POINT_UNDER_CONTROL) { - UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 0); + UpdateWorldState(PointsIconStruct[Point].WorldStateControlIndex, 0); if (Team == ALLIANCE) - UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 1); + UpdateWorldState(PointsIconStruct[Point].WorldStateAllianceControlledIndex, 1); else - UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 1); + UpdateWorldState(PointsIconStruct[Point].WorldStateHordeControlledIndex, 1); } else { if (Team == ALLIANCE) - UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 0); + UpdateWorldState(PointsIconStruct[Point].WorldStateAllianceControlledIndex, 0); else - UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 0); - UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 1); + UpdateWorldState(PointsIconStruct[Point].WorldStateHordeControlledIndex, 0); + UpdateWorldState(PointsIconStruct[Point].WorldStateControlIndex, 1); } } @@ -330,7 +316,7 @@ void BattleGroundEY::AddPlayer(Player *plr) //create score and add it to map BattleGroundEYScore* sc = new BattleGroundEYScore; - m_PlayersNearPoint[EY_POINTS_MAX].push_back(plr->GetGUID()); + m_PlayersNearPoint[BG_EY_NODES_MAX].push_back(plr->GetGUID()); m_PlayerScores[plr->GetGUID()] = sc; } @@ -338,7 +324,7 @@ void BattleGroundEY::AddPlayer(Player *plr) void BattleGroundEY::RemovePlayer(Player *plr, uint64 guid) { // sometimes flag aura not removed :( - for (int j = EY_POINTS_MAX; j >= 0; --j) + for (int j = BG_EY_NODES_MAX; j >= 0; --j) { for(size_t i = 0; i < m_PlayersNearPoint[j].size(); ++i) if (m_PlayersNearPoint[j][i] == guid) @@ -372,22 +358,22 @@ void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger) case TR_BLOOD_ELF_POINT: if (m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == Source->GetTeam()) if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_BLOOD_ELF); + EventPlayerCapturedFlag(Source, BG_EY_NODE_BLOOD_ELF); break; case TR_FEL_REALVER_POINT: if (m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[FEL_REALVER] == Source->GetTeam()) if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_FEL_REALVER); + EventPlayerCapturedFlag(Source, BG_EY_NODE_FEL_REALVER); break; case TR_MAGE_TOWER_POINT: if (m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[MAGE_TOWER] == Source->GetTeam()) if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_MAGE_TOWER); + EventPlayerCapturedFlag(Source, BG_EY_NODE_MAGE_TOWER); break; case TR_DRAENEI_RUINS_POINT: if (m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[DRAENEI_RUINS] == Source->GetTeam()) if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_DRAENEI_RUINS); + EventPlayerCapturedFlag(Source, BG_EY_NODE_DRAENEI_RUINS); break; case 4512: case 4515: @@ -409,67 +395,8 @@ void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger) bool BattleGroundEY::SetupBattleGround() { - // doors - if (!AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY) - // banners (alliance) - || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) - // banners (horde) - || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) - // banners (natural) - || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) - // flags - || !AddObject(BG_EY_OBJECT_FLAG_NETHERSTORM, BG_OBJECT_FLAG2_EY_ENTRY, 2174.782227f, 1569.054688f, 1160.361938f, -1.448624f, 0, 0, 0.662620f, -0.748956f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_FEL_REALVER, BG_OBJECT_FLAG1_EY_ENTRY, 2044.28f, 1729.68f, 1189.96f, -0.017453f, 0, 0, 0.008727f, -0.999962f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_BLOOD_ELF, BG_OBJECT_FLAG1_EY_ENTRY, 2048.83f, 1393.65f, 1194.49f, 0.20944f, 0, 0, 0.104528f, 0.994522f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_DRAENEI_RUINS, BG_OBJECT_FLAG1_EY_ENTRY, 2286.56f, 1402.36f, 1197.11f, 3.72381f, 0, 0, 0.957926f, -0.287016f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_MAGE_TOWER, BG_OBJECT_FLAG1_EY_ENTRY, 2284.48f, 1731.23f, 1189.99f, 2.89725f, 0, 0, 0.992546f, 0.121869f, RESPAWN_ONE_DAY) - // tower cap - || !AddObject(BG_EY_OBJECT_TOWER_CAP_FEL_REALVER, BG_OBJECT_FR_TOWER_CAP_EY_ENTRY, 2024.600708f, 1742.819580f, 1195.157715f, 2.443461f, 0, 0, 0.939693f, 0.342020f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF, BG_OBJECT_BE_TOWER_CAP_EY_ENTRY, 2050.493164f, 1372.235962f, 1194.563477f, 1.710423f, 0, 0, 0.754710f, 0.656059f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS, BG_OBJECT_DR_TOWER_CAP_EY_ENTRY, 2301.010498f, 1386.931641f, 1197.183472f, 1.570796f, 0, 0, 0.707107f, 0.707107f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER, BG_OBJECT_HU_TOWER_CAP_EY_ENTRY, 2282.121582f, 1760.006958f, 1189.707153f, 1.919862f, 0, 0, 0.819152f, 0.573576f, RESPAWN_ONE_DAY) - ) - { - sLog.outErrorDb("BatteGroundEY: Failed to spawn some object BattleGround not created!"); - return false; - } - //buffs - for (int i = 0; i < EY_POINTS_MAX; ++i) + for (int i = 0; i < BG_EY_NODES_MAX; ++i) { AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(m_Points_Trigger[i]); if (!at) @@ -484,21 +411,6 @@ bool BattleGroundEY::SetupBattleGround() sLog.outError("BattleGroundEY: Cannot spawn buff"); } - WorldSafeLocsEntry const *sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE); - if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) - { - sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); - return false; - } - - sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_HORDE); - if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) - { - sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); - return false; - } - return true; } @@ -514,34 +426,34 @@ void BattleGroundEY::Reset() m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; m_HonorScoreTics[BG_TEAM_HORDE] = 0; m_FlagState = BG_EY_FLAG_STATE_ON_BASE; - m_FlagCapturedBgObjectType = 0; m_FlagKeeper = 0; m_DroppedFlagGUID = 0; m_PointAddingTimer = 0; m_TowerCapCheckTimer = 0; - bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; - for(uint8 i = 0; i < EY_POINTS_MAX; ++i) + for(uint8 i = 0; i < BG_EY_NODES_MAX; ++i) { m_PointOwnedByTeam[i] = EY_POINT_NO_OWNER; m_PointState[i] = EY_POINT_STATE_UNCONTROLLED; m_PointBarStatus[i] = BG_EY_PROGRESS_BAR_STATE_MIDDLE; m_PlayersNearPoint[i].clear(); m_PlayersNearPoint[i].reserve(15); //tip size + m_ActiveEvents[i] = BG_EYE_NEUTRAL_TEAM; // neutral team owns every node } + // the flag in the middle is spawned at beginning + m_ActiveEvents[BG_EY_EVENT_CAPTURE_FLAG] = BG_EY_EVENT2_FLAG_CENTER; + m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].clear(); m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].reserve(30); } void BattleGroundEY::RespawnFlag(bool send_message) { - if (m_FlagCapturedBgObjectType > 0) - SpawnBGObject(m_FlagCapturedBgObjectType, RESPAWN_ONE_DAY); - - m_FlagCapturedBgObjectType = 0; m_FlagState = BG_EY_FLAG_STATE_ON_BASE; - SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY); + // will despawn captured flags at the node and spawn in center + SpawnEvent(BG_EY_EVENT_CAPTURE_FLAG, BG_EY_EVENT2_FLAG_CENTER, true); if (send_message) { @@ -630,7 +542,9 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target UpdateWorldState(NETHERSTORM_FLAG, 0); m_FlagState = BG_EY_FLAG_STATE_ON_PLAYER; - SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_ONE_DAY); + // despawn center-flag + SpawnEvent(BG_EY_EVENT_CAPTURE_FLAG, BG_EY_EVENT2_FLAG_CENTER, false); + SetFlagPicker(Source->GetGUID()); //get flag aura on player Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true); @@ -647,40 +561,30 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) if (GetStatus() != STATUS_IN_PROGRESS) return; - //Natural point + // neutral node uint32 Team = m_PointOwnedByTeam[Point]; if (!Team) return; if (Team == ALLIANCE) - { m_TeamPointsCount[BG_TEAM_ALLIANCE]--; - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); - } else - { m_TeamPointsCount[BG_TEAM_HORDE]--; - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); - } - - SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 1, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 2, RESPAWN_IMMEDIATELY); - - //buff isn't despawned + // it's important to set the OwnedBy before despawning spiritguides, else + // player won't get teleported away m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER; m_PointState[Point] = EY_POINT_NO_OWNER; + SpawnEvent(Point, BG_EYE_NEUTRAL_TEAM, true); // will despawn alliance/horde + + //buff isn't despawned + if (Team == ALLIANCE) - SendMessageToAll(m_LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + SendMessageToAll(LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); else - SendMessageToAll(m_LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); + SendMessageToAll(LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); @@ -693,24 +597,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) uint32 Team = Source->GetTeam(); - SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); - SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY); - SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 2, RESPAWN_ONE_DAY); - - if (Team == ALLIANCE) - { - m_TeamPointsCount[BG_TEAM_ALLIANCE]++; - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); - } - else - { - m_TeamPointsCount[BG_TEAM_HORDE]++; - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); - } + m_TeamPointsCount[GetTeamIndexByTeamId(Team)]++; + SpawnEvent(Point, GetTeamIndexByTeamId(Team), true); //buff isn't respawned @@ -718,26 +606,15 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) m_PointState[Point] = EY_POINT_UNDER_CONTROL; if (Team == ALLIANCE) - SendMessageToAll(m_CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + SendMessageToAll(CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); else - SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); - - if (m_BgCreatures[Point]) - DelCreature(Point); - - WorldSafeLocsEntry const *sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId); - if (!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team)) - sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", - Point, Team, m_CapturingPointTypes[Point].GraveYardId); - -// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY); + SendMessageToAll(CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); } -void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType) +void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, BG_EY_Nodes node) { if (GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() != Source->GetGUID()) return; @@ -753,10 +630,9 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType else PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); - SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY); + SpawnEvent(BG_EY_EVENT_CAPTURE_FLAG, node, true); m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; - m_FlagCapturedBgObjectType = BgObjectType; uint8 team_id = 0; if (Source->GetTeam() == ALLIANCE) @@ -875,13 +751,13 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player) distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); nearestDistance = distance; - for(uint8 i = 0; i < EY_POINTS_MAX; ++i) + for(uint8 i = 0; i < BG_EY_NODES_MAX; ++i) { if (m_PointOwnedByTeam[i]==player->GetTeam() && m_PointState[i]==EY_POINT_UNDER_CONTROL) { - entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId); + entry = sWorldSafeLocsStore.LookupEntry(CapturingPointTypes[i].GraveYardId); if (!entry) - sLog.outError("BattleGroundEY: Not found graveyard: %u",m_CapturingPointTypes[i].GraveYardId); + sLog.outError("BattleGroundEY: Not found graveyard: %u",CapturingPointTypes[i].GraveYardId); else { distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); @@ -900,9 +776,9 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player) bool BattleGroundEY::IsAllNodesConrolledByTeam(uint32 team) const { uint32 count = 0; - for(int i = 0; i < EY_POINTS_MAX; ++i) + for(int i = 0; i < BG_EY_NODES_MAX; ++i) if (m_PointOwnedByTeam[i] == team && m_PointState[i] == EY_POINT_UNDER_CONTROL) ++count; - return count == EY_POINTS_MAX; + return count == BG_EY_NODES_MAX; } diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index af9a189ff..d0bd7e75a 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -83,22 +83,6 @@ enum BG_EY_Spells BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991 }; -enum EYBattleGroundObjectEntry -{ - BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door - BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door - BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic) - BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand) - BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop) - BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance) - BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde) - BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral) - BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt - BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt - BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt - BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt -}; - enum EYBattleGroundPointsTrigger { TR_BLOOD_ELF_POINT = 4476, @@ -121,6 +105,7 @@ enum EYBattleGroundGaveyards EY_GRAVEYARD_MAGE_TOWER = 1108 }; +// deprecated enum EYBattleGroundPoints { FEL_REALVER = 0, @@ -129,84 +114,49 @@ enum EYBattleGroundPoints MAGE_TOWER = 3, EY_PLAYERS_OUT_OF_POINTS = 4, - EY_POINTS_MAX = 4 }; -enum EYBattleGroundCreaturesTypes +enum BG_EY_Nodes { - EY_SPIRIT_FEL_REALVER = 0, - EY_SPIRIT_BLOOD_ELF = 1, - EY_SPIRIT_DRAENEI_RUINS = 2, - EY_SPIRIT_MAGE_TOWER = 3, - EY_SPIRIT_MAIN_ALLIANCE = 4, - EY_SPIRIT_MAIN_HORDE = 5, + BG_EY_NODE_FEL_REALVER = 0, + BG_EY_NODE_BLOOD_ELF = 1, + BG_EY_NODE_DRAENEI_RUINS = 2, + BG_EY_NODE_MAGE_TOWER = 3, + BG_EY_NODES_ERROR = 255 +}; +#define BG_EY_NODES_MAX 4 - BG_EY_CREATURES_MAX = 6 +// node-events work like this: event1:nodeid, event2:state (0alliance,1horde,2neutral) +#define BG_EYE_NEUTRAL_TEAM 2 +#define BG_EY_EVENT_CAPTURE_FLAG 4 // event1=4, event2=nodeid or 4 for the default center spawn + #define BG_EY_EVENT2_FLAG_CENTER 4 // maximum node is 3 so 4 for center is ok + // all other event2 are just nodeids, i won't define something here + +// x, y, z +// used to check, when player is in range of a node +const float BG_EY_NodePositions[BG_EY_NODES_MAX][4] = { + {2024.600708f, 1742.819580f, 1195.157715f}, // FEL_REALVER + {2050.493164f, 1372.235962f, 1194.563477f}, // BLOOD_ELF + {2301.010498f, 1386.931641f, 1197.183472f}, // DRAENEI_RUINS + {2282.121582f, 1760.006958f, 1189.707153f} // MAGE_TOWER }; enum EYBattleGroundObjectTypes { - BG_EY_OBJECT_DOOR_A = 0, - BG_EY_OBJECT_DOOR_H = 1, - BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER = 2, - BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT = 3, - BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT = 4, - BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER = 5, - BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT = 6, - BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT = 7, - BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER = 8, - BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT = 9, - BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT = 10, - BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER = 11, - BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT = 12, - BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT = 13, - BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER = 14, - BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT = 15, - BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT = 16, - BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER = 17, - BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT = 18, - BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT = 19, - BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER = 20, - BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT = 21, - BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT = 22, - BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER = 23, - BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT = 24, - BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT = 25, - BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER = 26, - BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT = 27, - BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT = 28, - BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER = 29, - BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT = 30, - BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT = 31, - BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER = 32, - BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT = 33, - BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT = 34, - BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER = 35, - BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT = 36, - BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT = 37, - BG_EY_OBJECT_TOWER_CAP_FEL_REALVER = 38, - BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF = 39, - BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS = 40, - BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER = 41, - BG_EY_OBJECT_FLAG_NETHERSTORM = 42, - BG_EY_OBJECT_FLAG_FEL_REALVER = 43, - BG_EY_OBJECT_FLAG_BLOOD_ELF = 44, - BG_EY_OBJECT_FLAG_DRAENEI_RUINS = 45, - BG_EY_OBJECT_FLAG_MAGE_TOWER = 46, //buffs - BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER = 47, - BG_EY_OBJECT_REGENBUFF_FEL_REALVER = 48, - BG_EY_OBJECT_BERSERKBUFF_FEL_REALVER = 49, - BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 50, - BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 51, - BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 52, - BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 53, - BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 54, - BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 55, - BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 56, - BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 57, - BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 58, - BG_EY_OBJECT_MAX = 59 + BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER = 1, + BG_EY_OBJECT_REGENBUFF_FEL_REALVER = 2, + BG_EY_OBJECT_BERSERKBUFF_FEL_REALVER = 3, + BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 4, + BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 5, + BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 6, + BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 7, + BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 8, + BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 9, + BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 10, + BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 11, + BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 12, + BG_EY_OBJECT_MAX = 13 }; #define BG_EY_NotEYWeekendHonorTicks 330 @@ -244,60 +194,48 @@ struct BattleGroundEYPointIconsStruct struct BattleGroundEYLoosingPointStruct { - BattleGroundEYLoosingPointStruct(uint32 _SpawnNeutralObjectType, uint32 _DespawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _DespawnObjectTypeHorde, uint32 _MessageIdHorde) - : SpawnNeutralObjectType(_SpawnNeutralObjectType), - DespawnObjectTypeAlliance(_DespawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), - DespawnObjectTypeHorde(_DespawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde) + BattleGroundEYLoosingPointStruct(uint32 _MessageIdAlliance, uint32 _MessageIdHorde) + : MessageIdAlliance(_MessageIdAlliance), MessageIdHorde(_MessageIdHorde) {} - uint32 SpawnNeutralObjectType; - uint32 DespawnObjectTypeAlliance; uint32 MessageIdAlliance; - uint32 DespawnObjectTypeHorde; uint32 MessageIdHorde; }; struct BattleGroundEYCapturingPointStruct { - BattleGroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId) - : DespawnNeutralObjectType(_DespawnNeutralObjectType), - SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), - SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde), - GraveYardId(_GraveYardId) + BattleGroundEYCapturingPointStruct(uint32 _MessageIdAlliance, uint32 _MessageIdHorde, uint32 _GraveYardId) + : MessageIdAlliance(_MessageIdAlliance), MessageIdHorde(_MessageIdHorde), GraveYardId(_GraveYardId) {} - - uint32 DespawnNeutralObjectType; - uint32 SpawnObjectTypeAlliance; uint32 MessageIdAlliance; - uint32 SpawnObjectTypeHorde; uint32 MessageIdHorde; uint32 GraveYardId; }; -const uint8 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10}; -const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500}; +const uint8 BG_EY_TickPoints[BG_EY_NODES_MAX] = {1, 2, 5, 10}; +const uint32 BG_EY_FlagPoints[BG_EY_NODES_MAX] = {75, 85, 100, 500}; //constant arrays: -const BattleGroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] = +const BattleGroundEYPointIconsStruct PointsIconStruct[BG_EY_NODES_MAX] = { BattleGroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL), BattleGroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL), BattleGroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL), BattleGroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL) }; -const BattleGroundEYLoosingPointStruct m_LoosingPointTypes[EY_POINTS_MAX] = +const BattleGroundEYLoosingPointStruct LoosingPointTypes[BG_EY_NODES_MAX] = { - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS), - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER), - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS), - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER) + BattleGroundEYLoosingPointStruct(LANG_BG_EY_HAS_LOST_A_F_RUINS, LANG_BG_EY_HAS_LOST_H_F_RUINS), + BattleGroundEYLoosingPointStruct(LANG_BG_EY_HAS_LOST_A_B_TOWER, LANG_BG_EY_HAS_LOST_H_B_TOWER), + BattleGroundEYLoosingPointStruct(LANG_BG_EY_HAS_LOST_A_D_RUINS, LANG_BG_EY_HAS_LOST_H_D_RUINS), + BattleGroundEYLoosingPointStruct(LANG_BG_EY_HAS_LOST_A_M_TOWER, LANG_BG_EY_HAS_LOST_H_M_TOWER) }; -const BattleGroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] = +const BattleGroundEYCapturingPointStruct CapturingPointTypes[BG_EY_NODES_MAX] = { - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, EY_GRAVEYARD_FEL_REALVER), - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, EY_GRAVEYARD_BLOOD_ELF), - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, EY_GRAVEYARD_DRAENEI_RUINS), - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, EY_GRAVEYARD_MAGE_TOWER) + BattleGroundEYCapturingPointStruct(LANG_BG_EY_HAS_TAKEN_A_F_RUINS, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, EY_GRAVEYARD_FEL_REALVER), + BattleGroundEYCapturingPointStruct(LANG_BG_EY_HAS_TAKEN_A_B_TOWER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, EY_GRAVEYARD_BLOOD_ELF), + BattleGroundEYCapturingPointStruct(LANG_BG_EY_HAS_TAKEN_A_D_RUINS, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, EY_GRAVEYARD_DRAENEI_RUINS), + BattleGroundEYCapturingPointStruct(LANG_BG_EY_HAS_TAKEN_A_M_TOWER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, EY_GRAVEYARD_MAGE_TOWER) }; class BattleGroundEYScore : public BattleGroundScore @@ -350,8 +288,9 @@ class BattleGroundEY : public BattleGround /* achievement req. */ bool IsAllNodesConrolledByTeam(uint32 team) const; + private: - void EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType); + void EventPlayerCapturedFlag(Player *Source, BG_EY_Nodes node); void EventTeamCapturedPoint(Player *Source, uint32 Point); void EventTeamLostPoint(Player *Source, uint32 Point); void UpdatePointsCount(uint32 Team); @@ -372,21 +311,20 @@ class BattleGroundEY : public BattleGround uint32 m_HonorScoreTics[2]; uint32 m_TeamPointsCount[2]; - uint32 m_Points_Trigger[EY_POINTS_MAX]; + uint32 m_Points_Trigger[BG_EY_NODES_MAX]; uint64 m_FlagKeeper; // keepers guid uint64 m_DroppedFlagGUID; - uint32 m_FlagCapturedBgObjectType; // type that should be despawned when flag is captured uint8 m_FlagState; // for checking flag state int32 m_FlagsTimer; int32 m_TowerCapCheckTimer; - uint32 m_PointOwnedByTeam[EY_POINTS_MAX]; - uint8 m_PointState[EY_POINTS_MAX]; - int32 m_PointBarStatus[EY_POINTS_MAX]; + uint32 m_PointOwnedByTeam[BG_EY_NODES_MAX]; + uint8 m_PointState[BG_EY_NODES_MAX]; + int32 m_PointBarStatus[BG_EY_NODES_MAX]; typedef std::vector PlayersNearPointType; - PlayersNearPointType m_PlayersNearPoint[EY_POINTS_MAX + 1]; - uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; + PlayersNearPointType m_PlayersNearPoint[BG_EY_NODES_MAX + 1]; + uint8 m_CurrentPointPlayersCount[2*BG_EY_NODES_MAX]; int32 m_PointAddingTimer; uint32 m_HonorTics; diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 865988746..21be23200 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -31,6 +31,7 @@ #include "BattleGround.h" #include "ArenaTeam.h" #include "Language.h" +#include "ScriptCalls.h" void WorldSession::HandleBattlemasterHelloOpcode( WorldPacket & recv_data ) { @@ -586,7 +587,7 @@ void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) if(!unit->isSpiritService()) // it's not spirit service return; - sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid); + unit->SendAreaSpiritHealerQueryOpcode(GetPlayer()); } void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) @@ -607,7 +608,7 @@ void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) if(!unit->isSpiritService()) // it's not spirit service return; - bg->AddPlayerToResurrectQueue(guid, _player->GetGUID()); + Script->GossipHello(GetPlayer(), unit); } void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 1dccbafa0..b63abd1b9 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -42,7 +42,7 @@ #include "ArenaTeam.h" #include "World.h" #include "WorldPacket.h" -#include "ProgressBar.h" +#include "GameEventMgr.h" #include "Policies/SingletonImp.h" @@ -1902,16 +1902,6 @@ void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId, BattleGr } } -void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid) -{ - WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); - uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds - if (time_ == uint32(-1)) - time_ = 0; - data << guid << time_; - pl->GetSession()->SendPacket(&data); -} - bool BattleGroundMgr::IsArenaType(BattleGroundTypeId bgTypeId) { return ( bgTypeId == BATTLEGROUND_AA || @@ -2100,3 +2090,128 @@ void BattleGroundMgr::LoadBattleMastersEntry() sLog.outString( ">> Loaded %u battlemaster entries", count ); } +bool BattleGroundMgr::IsBGWeekend(BattleGroundTypeId bgTypeId) +{ + switch (bgTypeId) + { + case BATTLEGROUND_AV: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_AV); + case BATTLEGROUND_EY: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_EY); + case BATTLEGROUND_WS: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_WS); + case BATTLEGROUND_SA: + return IsHolidayActive(HOLIDAY_CALL_TO_ARMS_SA); + default: + return false; + } +} + +void BattleGroundMgr::LoadBattleEventIndexes() +{ + BattleGroundEventIdx events; + events.event1 = BG_EVENT_NONE; + events.event2 = BG_EVENT_NONE; + m_GameObjectBattleEventIndexMap.clear(); // need for reload case + m_GameObjectBattleEventIndexMap[-1] = events; + m_CreatureBattleEventIndexMap.clear(); // need for reload case + m_CreatureBattleEventIndexMap[-1] = events; + + uint32 count = 0; + + QueryResult *result = + // 0 1 2 3 4 5 6 + WorldDatabase.PQuery( "SELECT data.typ, data.guid1, data.ev1 ev1, data.ev2 ev2, data.map m, data.guid2, description.map, " + // 7 8 9 + "description.event1, description.event2, description.description " + "FROM " + "(SELECT 1 typ, a.guid guid1, a.event1 ev1, a.event2 ev2, b.map map, b.guid guid2 " + "FROM gameobject_battleground a " + "LEFT OUTER JOIN gameobject b ON a.guid = b.guid " + "UNION " + "SELECT 2 typ, a.guid guid1, a.event1 ev1, a.event2 ev2, b.map map, b.guid guid2 " + "FROM creature_battleground a " + "LEFT OUTER JOIN creature b ON a.guid = b.guid " + ") data " + "RIGHT OUTER JOIN battleground_events description ON data.map = description.map " + "AND data.ev1 = description.event1 AND data.ev2 = description.event2 " + // full outer join doesn't work in mysql :-/ so just UNION-select the same again and add a left outer join + "UNION " + "SELECT data.typ, data.guid1, data.ev1, data.ev2, data.map, data.guid2, description.map, " + "description.event1, description.event2, description.description " + "FROM " + "(SELECT 1 typ, a.guid guid1, a.event1 ev1, a.event2 ev2, b.map map, b.guid guid2 " + "FROM gameobject_battleground a " + "LEFT OUTER JOIN gameobject b ON a.guid = b.guid " + "UNION " + "SELECT 2 typ, a.guid guid1, a.event1 ev1, a.event2 ev2, b.map map, b.guid guid2 " + "FROM creature_battleground a " + "LEFT OUTER JOIN creature b ON a.guid = b.guid " + ") data " + "LEFT OUTER JOIN battleground_events description ON data.map = description.map " + "AND data.ev1 = description.event1 AND data.ev2 = description.event2 " + "ORDER BY m, ev1, ev2" ); + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + } + barGoLink bar( result->GetRowCount() ); + do + { + bar.step(); + Field *fields = result->Fetch(); + if (fields[2].GetUInt8() == BG_EVENT_NONE || fields[3].GetUInt8() == BG_EVENT_NONE) + continue; // we don't need to add those to the eventmap + + bool gameobject = (fields[0].GetUInt8() == 1); + uint32 dbTableGuidLow = fields[1].GetUInt32(); + events.event1 = fields[2].GetUInt8(); + events.event2 = fields[3].GetUInt8(); + uint32 map = fields[4].GetUInt32(); + + uint32 desc_map = fields[6].GetUInt32(); + uint8 desc_event1 = fields[7].GetUInt8(); + uint8 desc_event2 = fields[8].GetUInt8(); + const char *description = fields[9].GetString(); + + // checking for NULL - through right outer join this will mean following: + if (fields[5].GetUInt32() != dbTableGuidLow) + { + sLog.outErrorDb("BattleGroundEvent: %s with nonexistant guid %u for event: map:%u, event1:%u, event2:%u (\"%s\")", + (gameobject) ? "gameobject" : "creature", dbTableGuidLow, map, events.event1, events.event2, description); + continue; + } + + // checking for NULL - through full outer join this can mean 2 things: + if (desc_map != map) + { + // there is an event missing + if (dbTableGuidLow == 0) + { + sLog.outErrorDb("BattleGroundEvent: missing db-data for map:%u, event1:%u, event2:%u (\"%s\")", desc_map, desc_event1, desc_event2, description); + continue; + } + // we have an event which shouldn't exist + else + { + sLog.outErrorDb("BattleGroundEvent: %s with guid %u is registered, for a nonexistant event: map:%u, event1:%u, event2:%u", + (gameobject) ? "gameobject" : "creature", dbTableGuidLow, map, events.event1, events.event2); + continue; + } + } + + if (gameobject) + m_GameObjectBattleEventIndexMap[dbTableGuidLow] = events; + else + m_CreatureBattleEventIndexMap[dbTableGuidLow] = events; + + ++count; + + } while( result->NextRow() ); + sLog.outString(); + sLog.outString( ">> Loaded %u battleground eventindexes", count); + if (count == 0) + return; + delete result; +} diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 7044a4de2..45199d8b6 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -29,6 +29,8 @@ typedef std::map BattleGroundSet; typedef std::list BGFreeSlotQueueType; typedef UNORDERED_MAP BattleMastersMap; +typedef UNORDERED_MAP CreatureBattleEventIndexesMap; +typedef UNORDERED_MAP GameObjectBattleEventIndexesMap; #define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day #define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10 @@ -191,7 +193,6 @@ class BattleGroundMgr void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); - void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); /* Battlegrounds */ BattleGround* GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId); @@ -236,6 +237,22 @@ class BattleGroundMgr return BATTLEGROUND_WS; } + void LoadBattleEventIndexes(); + const BattleGroundEventIdx GetCreatureEventIndex(uint32 dbTableGuidLow) const + { + CreatureBattleEventIndexesMap::const_iterator itr = m_CreatureBattleEventIndexMap.find(dbTableGuidLow); + if(itr != m_CreatureBattleEventIndexMap.end()) + return itr->second; + return m_CreatureBattleEventIndexMap.find(-1)->second; + } + const BattleGroundEventIdx GetGameObjectEventIndex(uint32 dbTableGuidLow) const + { + GameObjectBattleEventIndexesMap::const_iterator itr = m_GameObjectBattleEventIndexMap.find(dbTableGuidLow); + if(itr != m_GameObjectBattleEventIndexMap.end()) + return itr->second; + return m_GameObjectBattleEventIndexMap.find(-1)->second; + } + bool isArenaTesting() const { return m_ArenaTesting; } bool isTesting() const { return m_Testing; } @@ -244,8 +261,12 @@ class BattleGroundMgr static BattleGroundQueueTypeId BGQueueTypeId(BattleGroundTypeId bgTypeId, uint8 arenaType); static BattleGroundTypeId BGTemplateId(BattleGroundQueueTypeId bgQueueTypeId); static uint8 BGArenaType(BattleGroundQueueTypeId bgQueueTypeId); + + static bool IsBGWeekend(BattleGroundTypeId bgTypeId); private: BattleMastersMap mBattleMastersMap; + CreatureBattleEventIndexesMap m_CreatureBattleEventIndexMap; + GameObjectBattleEventIndexesMap m_GameObjectBattleEventIndexMap; /* Battlegrounds */ BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID]; diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index bc8738202..ba7e18f97 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -26,8 +26,6 @@ BattleGroundNA::BattleGroundNA() { - m_BgObjects.resize(BG_NA_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; @@ -56,17 +54,11 @@ void BattleGroundNA::Update(uint32 diff) void BattleGroundNA::StartingEventCloseDoors() { - for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); } void BattleGroundNA::StartingEventOpenDoors() { - for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); + OpenDoorEvent(BG_EVENT_DOOR); } void BattleGroundNA::AddPlayer(Player *plr) @@ -154,19 +146,6 @@ void BattleGroundNA::Reset() bool BattleGroundNA::SetupBattleGround() { - // gates - if (!AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) - || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) - { - sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); - return false; - } - return true; } diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h index 1d35b839e..f22a21de0 100644 --- a/src/game/BattleGroundNA.h +++ b/src/game/BattleGroundNA.h @@ -20,27 +20,6 @@ class BattleGround; -enum BattleGroundNAObjectTypes -{ - BG_NA_OBJECT_DOOR_1 = 0, - BG_NA_OBJECT_DOOR_2 = 1, - BG_NA_OBJECT_DOOR_3 = 2, - BG_NA_OBJECT_DOOR_4 = 3, - BG_NA_OBJECT_BUFF_1 = 4, - BG_NA_OBJECT_BUFF_2 = 5, - BG_NA_OBJECT_MAX = 6 -}; - -enum BattleGroundNAObjects -{ - BG_NA_OBJECT_TYPE_DOOR_1 = 183978, - BG_NA_OBJECT_TYPE_DOOR_2 = 183980, - BG_NA_OBJECT_TYPE_DOOR_3 = 183977, - BG_NA_OBJECT_TYPE_DOOR_4 = 183979, - BG_NA_OBJECT_TYPE_BUFF_1 = 184663, - BG_NA_OBJECT_TYPE_BUFF_2 = 184664 -}; - class BattleGroundNAScore : public BattleGroundScore { public: diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index d79db75b1..009e0e945 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -26,8 +26,6 @@ BattleGroundRL::BattleGroundRL() { - m_BgObjects.resize(BG_RL_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; @@ -56,17 +54,11 @@ void BattleGroundRL::Update(uint32 diff) void BattleGroundRL::StartingEventCloseDoors() { - for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); } void BattleGroundRL::StartingEventOpenDoors() { - for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); + OpenDoorEvent(BG_EVENT_DOOR); } void BattleGroundRL::AddPlayer(Player *plr) @@ -155,17 +147,6 @@ void BattleGroundRL::Reset() bool BattleGroundRL::SetupBattleGround() { - // gates - if (!AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) - || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) - { - sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); - return false; - } - return true; } diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h index dd0dfd2af..197fa3e19 100644 --- a/src/game/BattleGroundRL.h +++ b/src/game/BattleGroundRL.h @@ -20,23 +20,6 @@ class BattleGround; -enum BattleGroundRLObjectTypes -{ - BG_RL_OBJECT_DOOR_1 = 0, - BG_RL_OBJECT_DOOR_2 = 1, - BG_RL_OBJECT_BUFF_1 = 2, - BG_RL_OBJECT_BUFF_2 = 3, - BG_RL_OBJECT_MAX = 4 -}; - -enum BattleGroundRLObjects -{ - BG_RL_OBJECT_TYPE_DOOR_1 = 185918, - BG_RL_OBJECT_TYPE_DOOR_2 = 185917, - BG_RL_OBJECT_TYPE_BUFF_1 = 184663, - BG_RL_OBJECT_TYPE_BUFF_2 = 184664 -}; - class BattleGroundRLScore : public BattleGroundScore { public: diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 312735654..0816d689a 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -23,14 +23,12 @@ #include "Creature.h" #include "GameObject.h" #include "ObjectMgr.h" +#include "BattleGroundMgr.h" #include "WorldPacket.h" #include "Language.h" BattleGroundWS::BattleGroundWS() { - m_BgObjects.resize(BG_WS_OBJECT_MAX); - m_BgCreatures.resize(BG_CREATURES_MAX_WS); - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; @@ -92,29 +90,16 @@ void BattleGroundWS::Update(uint32 diff) void BattleGroundWS::StartingEventCloseDoors() { - for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; ++i) - { - DoorClose(i); - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - } - for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); } void BattleGroundWS::StartingEventOpenDoors() { - for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; ++i) - DoorOpen(i); - for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; ++i) - DoorOpen(i); + OpenDoorEvent(BG_EVENT_DOOR); - SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY); + // TODO implement timer to despawn doors after a short while - for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); + SpawnEvent(WS_EVENT_FLAG_A, 0, true); + SpawnEvent(WS_EVENT_FLAG_H, 0, true); } void BattleGroundWS::AddPlayer(Player *plr) @@ -132,18 +117,20 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) { sLog.outDebug("Respawn Alliance flag"); m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + SpawnEvent(WS_EVENT_FLAG_A, 0, true); } else { sLog.outDebug("Respawn Horde flag"); m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + SpawnEvent(WS_EVENT_FLAG_H, 0, true); } if (captured) { //when map_update will be allowed for battlegrounds this code will be useless - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + SpawnEvent(WS_EVENT_FLAG_A, 0, true); + SpawnEvent(WS_EVENT_FLAG_H, 0, true); SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... } @@ -154,17 +141,11 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) if (GetStatus() != STATUS_IN_PROGRESS) return; - RespawnFlag(team,false); + RespawnFlag(team, false); if (team == ALLIANCE) - { - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); - } else - { - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); - } PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); @@ -216,8 +197,9 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) //for flag capture is reward 2 honorable kills RewardHonorToTeam(GetBonusHonorFromKill(2), Source->GetTeam()); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); + // despawn flags + SpawnEvent(WS_EVENT_FLAG_A, 0, false); + SpawnEvent(WS_EVENT_FLAG_H, 0, false); if (Source->GetTeam() == ALLIANCE) SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); @@ -336,14 +318,16 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target int32 message_id = 0; ChatMsg type; + uint8 event = (sBattleGroundMgr.GetGameObjectEventIndex(target_obj->GetDBTableGUIDLow())).event1; + //alliance flag picked up from base if(Source->GetTeam() == HORDE && GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE - && m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) + && event == WS_EVENT_FLAG_A) { message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); + SpawnEvent(WS_EVENT_FLAG_A, 0, false); SetAllianceFlagPicker(Source->GetGUID()); m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; //update world state to show correct flag carrier @@ -354,12 +338,12 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target //horde flag picked up from base if (Source->GetTeam() == ALLIANCE && GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE - && m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) + && event == WS_EVENT_FLAG_H) { message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); + SpawnEvent(WS_EVENT_FLAG_H, 0, false); SetHordeFlagPicker(Source->GetGUID()); m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; //update world state to show correct flag carrier @@ -377,7 +361,6 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target type = CHAT_MSG_BG_SYSTEM_ALLIANCE; UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN); RespawnFlag(ALLIANCE, false); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); } @@ -386,7 +369,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); + SpawnEvent(WS_EVENT_FLAG_A, 0, false); SetAllianceFlagPicker(Source->GetGUID()); Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; @@ -406,7 +389,6 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target type = CHAT_MSG_BG_SYSTEM_HORDE; UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN); RespawnFlag(HORDE, false); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); } @@ -415,7 +397,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); + SpawnEvent(WS_EVENT_FLAG_H, 0, false); SetHordeFlagPicker(Source->GetGUID()); Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; @@ -531,50 +513,6 @@ void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger) bool BattleGroundWS::SetupBattleGround() { - // flags - if (!AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, BG_WS_FLAG_RESPAWN_TIME/1000) - || !AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, BG_WS_FLAG_RESPAWN_TIME/1000) - // buffs - || !AddObject(BG_WS_OBJECT_SPEEDBUFF_1, BG_OBJECTID_SPEEDBUFF_ENTRY, 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_SPEEDBUFF_2, BG_OBJECTID_SPEEDBUFF_ENTRY, 1005.171f, 1447.946f, 335.9032f, 1.64061f, 0, 0, 0.7313537f, 0.6819984f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_REGENBUFF_1, BG_OBJECTID_REGENBUFF_ENTRY, 1317.506f, 1550.851f, 313.2344f, -0.2617996f, 0, 0, 0.1305263f, -0.9914448f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_REGENBUFF_2, BG_OBJECTID_REGENBUFF_ENTRY, 1110.451f, 1353.656f, 316.5181f, -0.6806787f, 0, 0, 0.333807f, -0.9426414f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_BERSERKBUFF_1, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1320.09f, 1378.79f, 314.7532f, 1.186824f, 0, 0, 0.5591929f, 0.8290376f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_BERSERKBUFF_2, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1139.688f, 1560.288f, 306.8432f, -2.443461f, 0, 0, 0.9396926f, -0.3420201f, BUFF_RESPAWN_TIME) - // alliance gates - || !AddObject(BG_WS_OBJECT_DOOR_A_1, BG_OBJECT_DOOR_A_1_WS_ENTRY, 1503.335f, 1493.466f, 352.1888f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_2, BG_OBJECT_DOOR_A_2_WS_ENTRY, 1492.478f, 1457.912f, 342.9689f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_3, BG_OBJECT_DOOR_A_3_WS_ENTRY, 1468.503f, 1494.357f, 351.8618f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_4, BG_OBJECT_DOOR_A_4_WS_ENTRY, 1471.555f, 1458.778f, 362.6332f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_5, BG_OBJECT_DOOR_A_5_WS_ENTRY, 1492.347f, 1458.34f, 342.3712f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_6, BG_OBJECT_DOOR_A_6_WS_ENTRY, 1503.466f, 1493.367f, 351.7352f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) - // horde gates - || !AddObject(BG_WS_OBJECT_DOOR_H_1, BG_OBJECT_DOOR_H_1_WS_ENTRY, 949.1663f, 1423.772f, 345.6241f, -0.5756807f, -0.01673368f, -0.004956111f, -0.2839723f, 0.9586737f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_H_2, BG_OBJECT_DOOR_H_2_WS_ENTRY, 953.0507f, 1459.842f, 340.6526f, -1.99662f, -0.1971825f, 0.1575096f, -0.8239487f, 0.5073641f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_H_3, BG_OBJECT_DOOR_H_3_WS_ENTRY, 949.9523f, 1422.751f, 344.9273f, 0.0f, 0, 0, 0, 1, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_H_4, BG_OBJECT_DOOR_H_4_WS_ENTRY, 950.7952f, 1459.583f, 342.1523f, 0.05235988f, 0, 0, 0.02617695f, 0.9996573f, RESPAWN_IMMEDIATELY) - ) - { - sLog.outErrorDb("BatteGroundWS: Failed to spawn some object BattleGround not created!"); - return false; - } - - WorldSafeLocsEntry const *sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); - if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) - { - sLog.outErrorDb("BatteGroundWS: Failed to spawn Alliance spirit guide! BattleGround not created!"); - return false; - } - - sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); - if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) - { - sLog.outErrorDb("BatteGroundWS: Failed to spawn Horde spirit guide! BattleGround not created!"); - return false; - } - - sLog.outDebug("BatteGroundWS: BG objects and spirit guides spawned"); - return true; } @@ -583,25 +521,23 @@ void BattleGroundWS::Reset() //call parent's class reset BattleGround::Reset(); - m_FlagKeepers[BG_TEAM_ALLIANCE] = 0; - m_FlagKeepers[BG_TEAM_HORDE] = 0; - m_DroppedFlagGUID[BG_TEAM_ALLIANCE] = 0; - m_DroppedFlagGUID[BG_TEAM_HORDE] = 0; - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; - m_TeamScores[BG_TEAM_ALLIANCE] = 0; - m_TeamScores[BG_TEAM_HORDE] = 0; - bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! + // spiritguides and flags not spawned at beginning + m_ActiveEvents[WS_EVENT_SPIRITGUIDES_SPAWN] = BG_EVENT_NONE; + m_ActiveEvents[WS_EVENT_FLAG_A] = BG_EVENT_NONE; + m_ActiveEvents[WS_EVENT_FLAG_H] = BG_EVENT_NONE; + + for(uint32 i = 0; i < BG_TEAMS_COUNT; ++i) + { + m_DroppedFlagGUID[i] = 0; + m_FlagKeepers[i] = 0; + m_FlagState[i] = BG_WS_FLAG_STATE_ON_BASE; + m_TeamScores[i] = 0; + } + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); m_ReputationCapture = (isBGWeekend) ? 45 : 35; m_HonorWinKills = (isBGWeekend) ? 3 : 1; m_HonorEndKills = (isBGWeekend) ? 4 : 2; - /* Spirit nodes is static at this BG and then not required deleting at BG reset. - if (m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) - DelCreature(WS_SPIRIT_MAIN_ALLIANCE); - if (m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) - DelCreature(WS_SPIRIT_MAIN_HORDE); - */ } void BattleGroundWS::EndBattleGround(uint32 winner) diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index bc393bd70..93df2bc0a 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -56,45 +56,6 @@ enum BG_WS_WorldStates BG_WS_FLAG_STATE_ALLIANCE = 2339 }; -enum BG_WS_ObjectTypes -{ - BG_WS_OBJECT_DOOR_A_1 = 0, - BG_WS_OBJECT_DOOR_A_2 = 1, - BG_WS_OBJECT_DOOR_A_3 = 2, - BG_WS_OBJECT_DOOR_A_4 = 3, - BG_WS_OBJECT_DOOR_A_5 = 4, - BG_WS_OBJECT_DOOR_A_6 = 5, - BG_WS_OBJECT_DOOR_H_1 = 6, - BG_WS_OBJECT_DOOR_H_2 = 7, - BG_WS_OBJECT_DOOR_H_3 = 8, - BG_WS_OBJECT_DOOR_H_4 = 9, - BG_WS_OBJECT_A_FLAG = 10, - BG_WS_OBJECT_H_FLAG = 11, - BG_WS_OBJECT_SPEEDBUFF_1 = 12, - BG_WS_OBJECT_SPEEDBUFF_2 = 13, - BG_WS_OBJECT_REGENBUFF_1 = 14, - BG_WS_OBJECT_REGENBUFF_2 = 15, - BG_WS_OBJECT_BERSERKBUFF_1 = 16, - BG_WS_OBJECT_BERSERKBUFF_2 = 17, - BG_WS_OBJECT_MAX = 18 -}; - -enum BG_WS_ObjectEntry -{ - BG_OBJECT_DOOR_A_1_WS_ENTRY = 179918, - BG_OBJECT_DOOR_A_2_WS_ENTRY = 179919, - BG_OBJECT_DOOR_A_3_WS_ENTRY = 179920, - BG_OBJECT_DOOR_A_4_WS_ENTRY = 179921, - BG_OBJECT_DOOR_A_5_WS_ENTRY = 180322, - BG_OBJECT_DOOR_A_6_WS_ENTRY = 180322, - BG_OBJECT_DOOR_H_1_WS_ENTRY = 179916, - BG_OBJECT_DOOR_H_2_WS_ENTRY = 179917, - BG_OBJECT_DOOR_H_3_WS_ENTRY = 180322, - BG_OBJECT_DOOR_H_4_WS_ENTRY = 180322, - BG_OBJECT_A_FLAG_WS_ENTRY = 179830, - BG_OBJECT_H_FLAG_WS_ENTRY = 179831 -}; - enum BG_WS_FlagState { BG_WS_FLAG_STATE_ON_BASE = 0, @@ -111,14 +72,6 @@ enum BG_WS_Graveyards WS_GRAVEYARD_MAIN_HORDE = 772 }; -enum BG_WS_CreatureTypes -{ - WS_SPIRIT_MAIN_ALLIANCE = 0, - WS_SPIRIT_MAIN_HORDE = 1, - - BG_CREATURES_MAX_WS = 2 -}; - class BattleGroundWGScore : public BattleGroundScore { public: @@ -128,6 +81,15 @@ class BattleGroundWGScore : public BattleGroundScore uint32 FlagReturns; }; + +enum BG_WS_Events +{ + WS_EVENT_FLAG_A = 0, + WS_EVENT_FLAG_H = 1, + // spiritguides will spawn (same moment, like WS_EVENT_DOOR_OPEN) + WS_EVENT_SPIRITGUIDES_SPAWN = 2 +}; + class BattleGroundWS : public BattleGround { friend class BattleGroundMgr; @@ -180,11 +142,12 @@ class BattleGroundWS : public BattleGround void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } private: - uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde - uint64 m_DroppedFlagGUID[2]; - uint8 m_FlagState[2]; // for checking flag state - int32 m_FlagsTimer[2]; - int32 m_FlagsDropTimer[2]; + uint64 m_FlagKeepers[BG_TEAMS_COUNT]; + + uint64 m_DroppedFlagGUID[BG_TEAMS_COUNT]; + uint8 m_FlagState[BG_TEAMS_COUNT]; + int32 m_FlagsTimer[BG_TEAMS_COUNT]; + int32 m_FlagsDropTimer[BG_TEAMS_COUNT]; uint32 m_ReputationCapture; uint32 m_HonorWinKills; diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 03d48b58f..c024989ff 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -405,6 +405,7 @@ ChatCommand * ChatHandler::getCommandTable() { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL }, { "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL }, { "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL }, + { "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL }, { "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand,"",NULL }, { "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL }, { "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL }, @@ -418,6 +419,7 @@ ChatCommand * ChatHandler::getCommandTable() { "gameobject_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL }, { "gameobject_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL }, { "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL }, + { "gameobject_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL }, { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 9ee748292..f5e2c2a38 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -327,6 +327,7 @@ class ChatHandler bool HandleReloadEventAISummonsCommand(const char* args); bool HandleReloadEventAIScriptsCommand(const char* args); bool HandleReloadCommandCommand(const char* args); + bool HandleReloadBattleEventCommand(const char* args); bool HandleReloadCreatureQuestRelationsCommand(const char* args); bool HandleReloadCreatureQuestInvRelationsCommand(const char* args); bool HandleReloadDbScriptStringCommand(const char* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 00ce44097..0df39018f 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -37,6 +37,7 @@ #include "WaypointMovementGenerator.h" #include "InstanceData.h" #include "BattleGroundMgr.h" +#include "Spell.h" #include "Util.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -160,7 +161,11 @@ void Creature::RemoveCorpse() setDeathState(DEAD); ObjectAccessor::UpdateObjectVisibility(this); loot.clear(); - m_respawnTime = time(NULL) + m_respawnDelay; + uint32 respawnDelay = m_respawnDelay; + if (AI()) + AI()->CorpseRemoved(respawnDelay); + + m_respawnTime = time(NULL) + respawnDelay; float x,y,z,o; GetRespawnCoord(x, y, z, &o); @@ -327,6 +332,15 @@ void Creature::Update(uint32 diff) break; case DEAD: { + if (isSpiritService()) + { + Unit::Update( diff ); + // do not allow the AI to be changed during update + m_AI_locked = true; + i_AI->UpdateAI(diff); + m_AI_locked = false; + break; // they don't should respawn + } if( m_respawnTime <= time(NULL) ) { DEBUG_LOG("Respawning..."); @@ -1450,6 +1464,7 @@ void Creature::DeleteFromDB() WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id = '%u'", m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM creature_battleground WHERE guid = '%u'", m_DBTableGuid); WorldDatabase.CommitTransaction(); } @@ -1528,12 +1543,15 @@ void Creature::setDeathState(DeathState s) { SetHealth(GetMaxHealth()); SetLootRecipient(NULL); - Unit::setDeathState(ALIVE); CreatureInfo const *cinfo = GetCreatureInfo(); SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); AddMonsterMoveFlag(MONSTER_MOVE_WALK); SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); + if (!isSpiritService()) + Unit::setDeathState(ALIVE); + else + Unit::setDeathState(DEAD); clearUnitState(UNIT_STAT_ALL_STATE); i_motionMaster.Clear(); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); @@ -2308,3 +2326,13 @@ void Creature::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transi //float orientation = (float)atan2((double)dy, (double)dx); SendMonsterMove(x, y, z, 0, GetMonsterMoveFlags(), transitTime, player); } + +void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl) +{ + uint32 next_resurrect = 0; + if (Spell* pcurSpell = GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + next_resurrect = pcurSpell->GetCastedTime(); + WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 8 + 4); + data << GetGUID() << next_resurrect; + pl->SendDirectMessage(&data); +} diff --git a/src/game/Creature.h b/src/game/Creature.h index b6f1d676c..1e2f01076 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -684,6 +684,8 @@ class MANGOS_DLL_SPEC Creature : public Unit bool isActiveObject() const { return m_isActiveObject || HasAuraType(SPELL_AURA_BIND_SIGHT) || HasAuraType(SPELL_AURA_FAR_SIGHT); } void SetActiveObjectState(bool on); + void SendAreaSpiritHealerQueryOpcode(Player *pl); + protected: bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 778c2c6d1..a9857eb2a 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -109,6 +109,9 @@ class MANGOS_DLL_SPEC CreatureAI // Is unit visible for MoveInLineOfSight virtual bool IsVisible(Unit *) const { return false; } + // called when the corpse of this creature gets removed + virtual void CorpseRemoved(uint32 & /*respawnDelay*/) {} + // Called when victim entered water and creature can not enter water virtual bool canReachByRangeAttack(Unit*) { return false; } diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index d88193726..995940ebf 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -641,6 +641,7 @@ void GameObject::DeleteFromDB() objmgr.DeleteGOData(m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM game_event_gameobject WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM gameobject_battleground WHERE guid = '%u'", m_DBTableGuid); } GameObjectInfo const *GameObject::GetGOInfo() const diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 8d2433ce3..151b4e0c3 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -44,8 +44,7 @@ inline void MaNGOS::ObjectUpdater::Visit(CreatureMapType &m) { for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - if(!iter->getSource()->isSpiritService()) - iter->getSource()->Update(i_timeDiff); + iter->getSource()->Update(i_timeDiff); } inline void diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index e37c82ba3..e13609401 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -70,6 +70,7 @@ bool ChatHandler::HandleReloadAllCommand(const char*) HandleReloadReservedNameCommand(""); HandleReloadMangosStringCommand(""); HandleReloadGameTeleCommand(""); + HandleReloadBattleEventCommand(""); return true; } @@ -594,6 +595,14 @@ bool ChatHandler::HandleReloadItemRequiredTragetCommand(const char*) return true; } +bool ChatHandler::HandleReloadBattleEventCommand(const char*) +{ + sLog.outString( "Re-Loading BattleGround Eventindexes..." ); + sBattleGroundMgr.LoadBattleEventIndexes(); + SendGlobalSysMessage("DB table `gameobject_battleground` and `creature_battleground` reloaded."); + return true; +} + bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg) { if(sWorld.IsScriptScheduled()) diff --git a/src/game/Map.h b/src/game/Map.h index 1227e4277..d4a01bc62 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -43,6 +43,7 @@ class Group; class InstanceSave; struct ScriptInfo; struct ScriptAction; +class BattleGround; typedef ACE_RW_Thread_Mutex GridRWLock; @@ -585,6 +586,10 @@ class MANGOS_DLL_SPEC BattleGroundMap : public Map void UnloadAll(bool pForce); virtual void InitVisibilityDistance(); + BattleGround* GetBG() { return m_bg; } + void SetBG(BattleGround* bg) { m_bg = bg; } + private: + BattleGround* m_bg; }; /*inline diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 4fc4155a5..4105bba80 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -135,7 +135,7 @@ Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player) ASSERT(NewInstanceId); map = _FindMap(NewInstanceId); if(!map) - map = CreateBattleGround(NewInstanceId); + map = CreateBattleGroundMap(NewInstanceId, player->GetBattleGround()); } else { @@ -208,15 +208,16 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, return map; } -BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId) +BattleGroundMap* MapInstanced::CreateBattleGroundMap(uint32 InstanceId, BattleGround* bg) { // load/create a map Guard guard(*this); - sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); + sLog.outDebug("MapInstanced::CreateBattleGroundMap: instance:%d for map:%d and bgType:%d created.", InstanceId, GetId(), bg->GetTypeID()); BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this); ASSERT(map->IsBattleGroundOrArena()); + map->SetBG(bg); m_InstancedMaps[InstanceId] = map; return map; diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index efb48b274..5e8183bac 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -62,7 +62,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map private: InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty); - BattleGroundMap* CreateBattleGround(uint32 InstanceId); + BattleGroundMap* CreateBattleGroundMap(uint32 InstanceId, BattleGround* bg); InstancedMaps m_InstancedMaps; diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index fd15a1d4e..8bb0be9b9 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -32,8 +32,6 @@ #include "ObjectAccessor.h" #include "Creature.h" #include "Pet.h" -#include "BattleGroundMgr.h" -#include "BattleGround.h" #include "Guild.h" void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data ) @@ -274,17 +272,8 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) unit->StopMoving(); } - // If spiritguide, no need for gossip menu, just put player into resurrect queue if (unit->isSpiritGuide()) - { - BattleGround *bg = _player->GetBattleGround(); - if(bg) - { - bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID()); - sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID()); - return; - } - } + unit->SendAreaSpiritHealerQueryOpcode(_player); if(!Script->GossipHello( _player, unit )) { diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index 896c0726d..89f3fcfea 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -109,6 +109,8 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair) template void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager &m, uint32 &count, Map* map) { + BattleGround* bg = map->IsBattleGroundOrArena() ? ((BattleGroundMap*)map)->GetBG() : NULL; + for(CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) { T* obj = new T; @@ -127,9 +129,10 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager & obj->AddToWorld(); if(obj->isActiveObject()) map->AddToActive(obj); + if (bg) + bg->OnObjectDBLoad(obj); ++count; - } } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 03427d1f0..c19e29d8f 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -329,7 +329,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { #define SPELL_ATTR_EX3_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required #define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground -#define SPELL_ATTR_EX3_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX3_CAST_ON_DEAD 0x00001000 // 12 target is a dead player (not every spell has this flag) #define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag #define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag @@ -1036,6 +1036,7 @@ enum Targets TARGET_AREAEFFECT_PARTY = 37, TARGET_SCRIPT = 38, TARGET_SELF_FISHING = 39, + TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT= 40, TARGET_TOTEM_EARTH = 41, TARGET_TOTEM_WATER = 42, TARGET_TOTEM_AIR = 43, @@ -1048,12 +1049,18 @@ enum Targets TARGET_DYNAMIC_OBJECT_RIGHT_SIDE = 50, TARGET_AREAEFFECT_CUSTOM_2 = 52, TARGET_CURRENT_ENEMY_COORDINATES = 53, // set unit coordinates as dest, only 16 target B imlemented + TARGET_LARGE_FRONTAL_CONE = 54, TARGET_ALL_RAID_AROUND_CASTER = 56, TARGET_SINGLE_FRIEND_2 = 57, + TARGET_NARROW_FRONTAL_CONE = 60, TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, TARGET_DUELVSPLAYER_COORDINATES = 63, - TARGET_BEHIND_VICTIM = 65, // uses in teleport behind spells, caster/target dependent from spell effect - TARGET_RANDOM_NEARBY_LOC = 72, // uses in teleport onto nearby locations + TARGET_INFRONT_OF_VICTIM = 64, + TARGET_BEHIND_VICTIM = 65, // used in teleport behind spells, caster/target dependent from spell effect + TARGET_RIGHT_FROM_VICTIM = 66, + TARGET_LEFT_FROM_VICTIM = 67, + TARGET_RANDOM_NEARBY_LOC = 72, // used in teleport onto nearby locations + TARGET_RANDOM_CIRCUMFERENCE_POINT = 73, TARGET_DYNAMIC_OBJECT_COORDINATES = 76, TARGET_SINGLE_ENEMY = 77, TARGET_POINT_AT_NORTH = 78, // 78-85 possible _COORDINATES at radius with pi/4 step around target in unknown order, N? @@ -1893,7 +1900,7 @@ enum HolidayIds HOLIDAY_NOBLEGARDEN = 181, HOLIDAY_CHILDRENS_WEEK = 201, HOLIDAY_CALL_TO_ARMS_AV = 283, - HOLIDAY_CALL_TO_ARMS_WG = 284, + HOLIDAY_CALL_TO_ARMS_WS = 284, HOLIDAY_CALL_TO_ARMS_AB = 285, HOLIDAY_FISHING_EXTRAVAGANZA = 301, HOLIDAY_HARVEST_FESTIVAL = 321, @@ -1901,7 +1908,7 @@ enum HolidayIds HOLIDAY_LUNAR_FESTIVAL = 327, HOLIDAY_LOVE_IS_IN_THE_AIR = 335, HOLIDAY_FIRE_FESTIVAL = 341, - HOLIDAY_CALL_TO_ARMS_ES = 353, + HOLIDAY_CALL_TO_ARMS_EY = 353, HOLIDAY_BREWFEST = 372, HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374, HOLIDAY_DARKMOON_FAIRE_THUNDER = 375, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 25214ad14..7cd115731 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -498,10 +498,13 @@ void Spell::FillTargetMap() if(m_spellInfo->Effect[i] == 0) continue; - // targets for TARGET_SCRIPT_COORDINATES (A) and TARGET_SCRIPT filled in Spell::CheckCast call + // targets for TARGET_SCRIPT_COORDINATES (A) and TARGET_SCRIPT + // and TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT (A) if no RequiresSpellFocus set + // filled in Spell::CheckCast call if( m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT_COORDINATES || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT || - m_spellInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[i] != TARGET_SELF ) + (m_spellInfo->EffectImplicitTargetA[i] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT && !m_spellInfo->RequiresSpellFocus) || + (m_spellInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[i] != TARGET_SELF) ) continue; // TODO: find a way so this is not needed? @@ -1217,7 +1220,7 @@ bool Spell::IsAliveUnitPresentInTargetList() { Unit *unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); - if (unit && unit->isAlive()) + if (unit && (unit->isAlive() ^ IsDeathOnlySpell(m_spellInfo))) needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target } } @@ -1289,14 +1292,16 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) else radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - if(m_originalCaster) - if(Player* modOwner = m_originalCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); - uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[effIndex]; + if(m_originalCaster) + { if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + { + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); + } + } // Get spell max affected targets uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; @@ -1323,10 +1328,39 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) switch(targetMode) { - case TARGET_RANDOM_NEARBY_LOC: + case TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT: { - float dest_x = m_caster->GetPositionX() + irand(-radius, radius); - float dest_y = m_caster->GetPositionY() + irand(-radius, radius); + if(m_spellInfo->RequiresSpellFocus) + { + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + GameObject* goTarget = NULL; + MaNGOS::GameObjectFocusCheck go_check(m_caster, m_spellInfo->RequiresSpellFocus); + MaNGOS::GameObjectSearcher checker(m_caster, goTarget, go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + CellLock cell_lock(cell, p); + Map& map = *m_caster->GetMap(); + cell_lock->Visit(cell_lock, object_checker, map, *m_caster, map.GetVisibilityDistance()); + + if(goTarget) + AddGOTarget(goTarget, effIndex); + } + else if(m_targets.getGOTarget()) + AddGOTarget(m_targets.getGOTarget(), effIndex); + + break; + } + case TARGET_RANDOM_NEARBY_LOC: + radius *= sqrt(rand_norm()); // Get a random point in circle. Use sqrt(rand) to correct distribution when converting polar to Cartesian coordinates. + // no 'break' expected since we use code in case TARGET_RANDOM_CIRCUMFERENCE_POINT!!! + case TARGET_RANDOM_CIRCUMFERENCE_POINT: + { + float angle = 2.0 * M_PI * rand_norm(); + float dest_x = m_caster->GetPositionX() + cos(angle) * radius; + float dest_y = m_caster->GetPositionY() + sin(angle) * radius; float dest_z = m_caster->GetMap()->GetHeight(dest_x, dest_y, MAX_HEIGHT); m_targets.setDestination(dest_x, dest_y, dest_z); @@ -1335,8 +1369,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) } case TARGET_RANDOM_NEARBY_DEST: { - float dest_x = m_targets.m_destX + irand(-radius, radius); - float dest_y = m_targets.m_destY + irand(-radius, radius); + radius *= sqrt(rand_norm()); // Get a random point in circle. Use sqrt(rand) to correct distribution when converting polar to Cartesian coordinates. + float angle = 2.0 * M_PI * rand_norm(); + float dest_x = m_targets.m_destX + cos(angle) * radius; + float dest_y = m_targets.m_destY + sin(angle) * radius; float dest_z = m_caster->GetMap()->GetHeight(dest_x, dest_y, MAX_HEIGHT); m_targets.setDestination(dest_x, dest_y, dest_z); @@ -1350,7 +1386,6 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) break; } - case TARGET_TOTEM_EARTH: case TARGET_TOTEM_WATER: case TARGET_TOTEM_AIR: @@ -1753,6 +1788,12 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius,inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); break; } + case TARGET_LARGE_FRONTAL_CONE: + FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_90, SPELL_TARGETS_AOE_DAMAGE); + break; + case TARGET_NARROW_FRONTAL_CONE: + FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_15, SPELL_TARGETS_AOE_DAMAGE); + break; case TARGET_IN_FRONT_OF_CASTER_30: FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_30, SPELL_TARGETS_AOE_DAMAGE); break; @@ -1993,7 +2034,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id ); break; } + case TARGET_INFRONT_OF_VICTIM: case TARGET_BEHIND_VICTIM: + case TARGET_RIGHT_FROM_VICTIM: + case TARGET_LEFT_FROM_VICTIM: { Unit *pTarget = NULL; @@ -2008,8 +2052,19 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if(pTarget) { + float angle = 0.0f; + float dist = (radius && targetMode != TARGET_BEHIND_VICTIM) ? radius : CONTACT_DISTANCE; + + switch(targetMode) + { + case TARGET_INFRONT_OF_VICTIM: break; + case TARGET_BEHIND_VICTIM: angle = M_PI; break; + case TARGET_RIGHT_FROM_VICTIM: angle = -M_PI/2; break; + case TARGET_LEFT_FROM_VICTIM: angle = M_PI/2; break; + } + float _target_x, _target_y, _target_z; - pTarget->GetClosePoint(_target_x, _target_y, _target_z, m_caster->GetObjectSize(), CONTACT_DISTANCE, M_PI); + pTarget->GetClosePoint(_target_x, _target_y, _target_z, pTarget->GetObjectSize(), dist, angle); if(pTarget->IsWithinLOS(_target_x, _target_y, _target_z)) { TagUnitMap.push_back(m_caster); @@ -2250,7 +2305,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) break; } default: - sLog.outError( "SPELL: Unknown implicit target (%u) for spell ID %u", targetMode, m_spellInfo->Id ); + //sLog.outError( "SPELL: Unknown implicit target (%u) for spell ID %u", targetMode, m_spellInfo->Id ); break; } @@ -3836,6 +3891,9 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_NOT_READY; } + if (IsDeathOnlySpell(m_spellInfo) && m_caster->isAlive()) + return SPELL_FAILED_TARGET_NOT_DEAD; + // only allow triggered spells if at an ended battleground if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER) if(BattleGround * bg = ((Player*)m_caster)->GetBattleGround()) @@ -4061,27 +4119,12 @@ SpellCastResult Spell::CheckCast(bool strict) if (non_caster_target && (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET) && target->isInCombat()) return SPELL_FAILED_TARGET_AFFECTING_COMBAT; } - - // Spell casted only on battleground - if ((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_BATTLEGROUND) && m_caster->GetTypeId() == TYPEID_PLAYER) - if(!((Player*)m_caster)->InBattleGround()) - return SPELL_FAILED_ONLY_BATTLEGROUNDS; - - // do not allow spells to be cast in arenas - // - with greater than 15 min CD without SPELL_ATTR_EX4_USABLE_IN_ARENA flag - // - with SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA flag - if ((m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) || - GetSpellRecoveryTime(m_spellInfo) > 15 * MINUTE * IN_MILISECONDS && !(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA)) - if(MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId())) - if(mapEntry->IsBattleArena()) - return SPELL_FAILED_NOT_IN_ARENA; - // zone check uint32 zone, area; m_caster->GetZoneAndAreaId(zone, area); SpellCastResult locRes= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area, - m_caster->GetTypeId() == TYPEID_PLAYER ? ((Player*)m_caster) : NULL); + m_caster->GetCharmerOrOwnerPlayerOrPlayerItself()); if (locRes != SPELL_CAST_OK) return locRes; @@ -4111,8 +4154,10 @@ SpellCastResult Spell::CheckCast(bool strict) if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF || m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES || + m_spellInfo->EffectImplicitTargetA[j] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT ) { + SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(m_spellInfo->Id); if(bounds.first==bounds.second) sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id); diff --git a/src/game/Spell.h b/src/game/Spell.h index 473ca8c51..bda3a1871 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -84,7 +84,9 @@ enum SpellCastFlags enum SpellNotifyPushType { PUSH_IN_FRONT, + PUSH_IN_FRONT_90, PUSH_IN_FRONT_30, + PUSH_IN_FRONT_15, PUSH_IN_BACK, PUSH_SELF_CENTER, PUSH_DEST_CENTER, @@ -407,6 +409,7 @@ class Spell SpellCastTargets m_targets; int32 GetCastTime() const { return m_casttime; } + uint32 GetCastedTime() { return m_timer; } bool IsAutoRepeat() const { return m_autoRepeat; } void SetAutoRepeat(bool rep) { m_autoRepeat = rep; } void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; } @@ -656,37 +659,35 @@ namespace MaNGOS for(typename GridRefManager::iterator itr = m.begin(); itr != m.end(); ++itr) { - if( !itr->getSource()->isAlive() || (itr->getSource()->GetTypeId() == TYPEID_PLAYER && ((Player*)itr->getSource())->isInFlight())) - continue; - - // mostly phase check - if(!itr->getSource()->IsInMap(i_originalCaster)) + // there are still more spells which can be casted on dead, but + // they are no AOE and don't have such a nice SPELL_ATTR flag + if ( !itr->getSource()->isTargetableForAttack(i_spell.m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_CAST_ON_DEAD) + // mostly phase check + || !itr->getSource()->IsInMap(i_originalCaster)) continue; switch (i_TargetType) { case SPELL_TARGETS_HOSTILE: - if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsHostileTo( itr->getSource() )) + if (!i_originalCaster->IsHostileTo( itr->getSource() )) continue; break; case SPELL_TARGETS_NOT_FRIENDLY: - if (!itr->getSource()->isTargetableForAttack() || i_originalCaster->IsFriendlyTo( itr->getSource() )) + if (i_originalCaster->IsFriendlyTo( itr->getSource() )) continue; break; case SPELL_TARGETS_NOT_HOSTILE: - if (!itr->getSource()->isTargetableForAttack() || i_originalCaster->IsHostileTo( itr->getSource() )) + if (i_originalCaster->IsHostileTo( itr->getSource() )) continue; break; case SPELL_TARGETS_FRIENDLY: - if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsFriendlyTo( itr->getSource() )) + if (!i_originalCaster->IsFriendlyTo( itr->getSource() )) continue; break; case SPELL_TARGETS_AOE_DAMAGE: { if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem()) continue; - if(!itr->getSource()->isTargetableForAttack()) - continue; Unit* check = i_originalCaster->GetCharmerOrOwnerOrSelf(); @@ -711,10 +712,18 @@ namespace MaNGOS if(i_spell.GetCaster()->isInFrontInMap((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) i_data->push_back(itr->getSource()); break; + case PUSH_IN_FRONT_90: + if(i_spell.GetCaster()->isInFrontInMap((Unit*)(itr->getSource()), i_radius, M_PI/2 )) + i_data->push_back(itr->getSource()); + break; case PUSH_IN_FRONT_30: if(i_spell.GetCaster()->isInFrontInMap((Unit*)(itr->getSource()), i_radius, M_PI/6 )) i_data->push_back(itr->getSource()); break; + case PUSH_IN_FRONT_15: + if(i_spell.GetCaster()->isInFrontInMap((Unit*)(itr->getSource()), i_radius, M_PI/12 )) + i_data->push_back(itr->getSource()); + break; case PUSH_IN_BACK: if(i_spell.GetCaster()->isInBackInMap((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) i_data->push_back(itr->getSource()); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index df294eeec..f12885b80 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2281,14 +2281,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) switch(GetId()) { - case 2584: // Waiting to Resurrect - { - // Waiting to resurrect spell cancel, we must remove player from resurrect queue - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); - return; - } case 36730: // Flame Strike { m_target->CastSpell(m_target, 36731, true, NULL, this); @@ -6279,7 +6271,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) void Aura::PeriodicTick() { - if(!m_target->isAlive()) + if (!m_target->isAlive() ^ IsDeathOnlySpell(GetSpellProto())) return; switch(m_modifier.m_auraname) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 82328934b..b2fe11dc9 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2423,8 +2423,8 @@ void Spell::EffectApplyAura(uint32 i) return; // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if( !unitTarget->isAlive() && !IsDeathPersistentSpell(m_spellInfo) && - (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) + if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) && + (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) return; Unit* caster = m_originalCaster ? m_originalCaster : m_caster; @@ -6803,25 +6803,20 @@ void Spell::EffectSummonDemon(uint32 i) } } -/* There is currently no need for this effect. We handle it in BattleGround.cpp - If we would handle the resurrection here, the spiritguide would instantly disappear as the - player revives, and so we wouldn't see the spirit heal visual effect on the npc. - This is why we use a half sec delay between the visual effect and the resurrection itself */ void Spell::EffectSpiritHeal(uint32 /*i*/) { - /* - if(!unitTarget || unitTarget->isAlive()) + // TODO player can't see the heal-animation - he should respawn some ticks later + if (!unitTarget || unitTarget->isAlive()) return; - if(unitTarget->GetTypeId() != TYPEID_PLAYER) + if (unitTarget->GetTypeId() != TYPEID_PLAYER) return; - if(!unitTarget->IsInWorld()) + if (!unitTarget->IsInWorld()) + return; + if (m_spellInfo->Id == 22012 && !unitTarget->HasAura(2584)) return; - //m_spellInfo->EffectBasePoints[i]; == 99 (percent?) - //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA)); ((Player*)unitTarget)->ResurrectPlayer(1.0f); ((Player*)unitTarget)->SpawnCorpseBones(); - */ } // remove insignia spell effect diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7bc2f8613..051404404 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2125,7 +2125,9 @@ void SpellMgr::LoadSpellScriptTarget() if( spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT || spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT || spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES || - spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES ) + spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES || + spellProto->EffectImplicitTargetA[i]==TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT || + spellProto->EffectImplicitTargetB[i]==TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT ) { targetfound = true; break; @@ -2133,7 +2135,7 @@ void SpellMgr::LoadSpellScriptTarget() } if(!targetfound) { - sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId,targetEntry); + sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46) or TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT (40).",spellId,targetEntry); continue; } @@ -2801,6 +2803,20 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell } // bg spell checks + + // do not allow spells to be cast in arenas + // - with SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA flag + // - with greater than 15 min CD + if ((spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) || + (GetSpellRecoveryTime(spellInfo) > 15 * MINUTE * IN_MILISECONDS && !(spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA))) + if (!player || !player->InArena()) + return SPELL_FAILED_NOT_IN_ARENA; + + // Spell casted only on battleground + if ((spellInfo->AttributesEx3 & SPELL_ATTR_EX3_BATTLEGROUND)) + if (!player || !player->InBattleGround()) + return SPELL_FAILED_ONLY_BATTLEGROUNDS; + switch(spellInfo->Id) { case 23333: // Warsong Flag @@ -2809,59 +2825,45 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell case 34976: // Netherstorm Flag return map_id == 566 && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; case 2584: // Waiting to Resurrect + case 42792: // Recently Dropped Flag + case 43681: // Inactive + { + return player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_ONLY_BATTLEGROUNDS; + } case 22011: // Spirit Heal Channel case 22012: // Spirit Heal case 24171: // Resurrection Impact Visual - case 42792: // Recently Dropped Flag - case 43681: // Inactive case 44535: // Spirit Heal (mana) { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if (!mapEntry) return SPELL_FAILED_INCORRECT_AREA; - - return mapEntry->IsBattleGround() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; + return mapEntry->IsBattleGround()? SPELL_CAST_OK : SPELL_FAILED_ONLY_BATTLEGROUNDS; } case 44521: // Preparation { if (!player) return SPELL_FAILED_REQUIRES_AREA; - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if (!mapEntry) - return SPELL_FAILED_INCORRECT_AREA; - - if (!mapEntry->IsBattleGround()) - return SPELL_FAILED_REQUIRES_AREA; - BattleGround* bg = player->GetBattleGround(); - return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; + return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_ONLY_BATTLEGROUNDS; } case 32724: // Gold Team (Alliance) case 32725: // Green Team (Alliance) case 35774: // Gold Team (Horde) case 35775: // Green Team (Horde) { - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if (!mapEntry) - return SPELL_FAILED_INCORRECT_AREA; - - return mapEntry->IsBattleArena() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; + return player && player->InArena() ? SPELL_CAST_OK : SPELL_FAILED_ONLY_IN_ARENA; } case 32727: // Arena Preparation { if (!player) return SPELL_FAILED_REQUIRES_AREA; - - MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if (!mapEntry) - return SPELL_FAILED_INCORRECT_AREA; - - if (!mapEntry->IsBattleArena()) + if (!player->InArena()) return SPELL_FAILED_REQUIRES_AREA; BattleGround* bg = player->GetBattleGround(); - return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; + return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_ONLY_IN_ARENA; } } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 45bc53d41..236a7f833 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -198,6 +198,12 @@ inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA); } +inline bool IsDeathOnlySpell(SpellEntry const *spellInfo) +{ + return spellInfo->AttributesEx & SPELL_ATTR_EX3_CAST_ON_DEAD + || spellInfo->Id == 2584 + || spellInfo->Id == 22011; +} inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 4f869e503..5161df21a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3403,7 +3403,7 @@ bool Unit::AddAura(Aura *Aur) // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && - Aur->GetId() != 2584 && // Waiting to Resurrect (not have death persistence flag) + !IsDeathOnlySpell(aurSpellInfo) && (GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) { delete Aur; @@ -9416,7 +9416,7 @@ void Unit::ClearInCombat() ((Player*)this)->UpdatePotionCooldown(); } -bool Unit::isTargetableForAttack() const +bool Unit::isTargetableForAttack(bool inverseAlive /*=false*/) const { if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster()) return false; @@ -9428,7 +9428,10 @@ bool Unit::isTargetableForAttack() const if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) return false; - return IsInWorld() && isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; + if (!(isAlive() ^ inverseAlive)) + return false; + + return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; } int32 Unit::ModifyHealth(int32 dVal) diff --git a/src/game/Unit.h b/src/game/Unit.h index 87b51eb7c..f3f20e233 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1110,7 +1110,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage); - bool isTargetableForAttack() const; + bool isTargetableForAttack(bool inversAlive = false) const; virtual bool IsInWater() const; virtual bool IsUnderWater() const; bool isInAccessablePlaceFor(Creature const* c) const; diff --git a/src/game/World.cpp b/src/game/World.cpp index 4ebd61694..b3260ddf4 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1382,6 +1382,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading BattleMasters..." ); sBattleGroundMgr.LoadBattleMastersEntry(); + sLog.outString( "Loading BattleGround event indexes..." ); + sBattleGroundMgr.LoadBattleEventIndexes(); + sLog.outString( "Loading GameTeleports..." ); objmgr.LoadGameTele(); @@ -2183,4 +2186,4 @@ void World::LoadDBVersion() if(m_CreatureEventAIVersion.empty()) m_CreatureEventAIVersion = "Unknown creature EventAI."; -} \ No newline at end of file +} diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b49806524..18b0ced5f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8541" + #define REVISION_NR "8555" #endif // __REVISION_NR_H__