Merge commit 'origin/master' into 320

Conflicts:
	src/game/BattleGround.cpp
This commit is contained in:
tomrus88 2009-09-28 19:52:54 +04:00
commit 546f7a7fe5
47 changed files with 985 additions and 1264 deletions

View file

@ -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';
--

View file

@ -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';

View file

@ -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';

View file

@ -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')

View file

@ -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

View file

@ -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();

View file

@ -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<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
{
Creature *sh = NULL;
for(std::vector<uint64>::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<uint64>::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<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
{
for(std::vector<uint64>::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<GameObject>::Find(m_BgObjects[type]);
GameObject *obj = HashMapHolder<GameObject>::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<GameObject>::Find(m_BgObjects[type]);
GameObject *obj = HashMapHolder<GameObject>::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<GameObject>::Find(guid);
if(!obj)
return;
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
if (!map)
return;
if (respawntime == 0)
{
GameObject *obj = HashMapHolder<GameObject>::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<GameObject>::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<Creature>::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<Creature>::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<Creature>::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<Creature>::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);

View file

@ -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<uint64> BGObjects;
typedef std::vector<uint64> 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,6 +527,22 @@ 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<uint32, EventObjects> 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<uint8, uint8> 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();
@ -521,8 +556,6 @@ class BattleGround
/* Player lists, those need to be accessible by inherited classes */
BattleGroundPlayerMap m_Players;
// Spirit Guide guid + Player list GUIDS
std::map<uint64, std::vector<uint64> > 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

View file

@ -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<uint64> ghost_list = m_ReviveQueue[m_BgCreatures[node]];
if (!ghost_list.empty())
{
WorldSafeLocsEntry const *ClosestGrave = NULL;
for (std::vector<uint64>::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<GameObject>::Find(m_BgObjects[node*8+7]);
while ( (node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10))))
{
++node;
obj=HashMapHolder<GameObject>::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<uint8> 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;
}

View file

@ -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];

View file

@ -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;
}

View file

@ -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:

View file

@ -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<GameObject>::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<GameObject>::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;
}

View file

@ -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<uint64> 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;

View file

@ -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 )

View file

@ -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;
}

View file

@ -29,6 +29,8 @@ typedef std::map<uint32, BattleGround*> BattleGroundSet;
typedef std::list<BattleGround*> BGFreeSlotQueueType;
typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap;
typedef UNORDERED_MAP<uint32, BattleGroundEventIdx> CreatureBattleEventIndexesMap;
typedef UNORDERED_MAP<uint32, BattleGroundEventIdx> 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];

View file

@ -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;
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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:

View file

@ -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)

View file

@ -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;

View file

@ -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 },

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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; }

View file

@ -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

View file

@ -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

View file

@ -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())

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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 ))
{

View file

@ -109,6 +109,8 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair)
template <class T>
void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &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<T> &
obj->AddToWorld();
if(obj->isActiveObject())
map->AddToActive(obj);
if (bg)
bg->OnObjectDBLoad(obj);
++count;
}
}

View file

@ -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,

View file

@ -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<MaNGOS::GameObjectFocusCheck> checker(m_caster, goTarget, go_check);
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectFocusCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> 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);

View file

@ -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<T>::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());

View file

@ -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)

View file

@ -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

View file

@ -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;
}
}

View file

@ -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)
{

View file

@ -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)

View file

@ -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;

View file

@ -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();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8541"
#define REVISION_NR "8555"
#endif // __REVISION_NR_H__