Merge branch 'master' into 320

This commit is contained in:
VladimirMangos 2009-10-02 19:09:06 +04:00
commit 59befa2e0e
42 changed files with 816 additions and 567 deletions

View file

@ -875,6 +875,13 @@ int main(int argc, char *argv[])
} }
} }
if (local && do_sql)
{
printf("Options -l/--local and -s/--sql can't be used in same time currently.\n");
printf("FAILED\n");
return 1;
}
DO( find_path() ); DO( find_path() );
if(!local) if(!local)
{ {

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_8549_03_mangos_battleground_events` bit(1) default NULL `required_8573_01_mangos_mangos_string` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -178,6 +178,87 @@ LOCK TABLES `areatrigger_teleport` WRITE;
/*!40000 ALTER TABLE `areatrigger_teleport` ENABLE KEYS */; /*!40000 ALTER TABLE `areatrigger_teleport` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `battleground_events`
--
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;
--
-- Dumping data for table `battleground_events`
--
LOCK TABLES `battleground_events` WRITE;
/*!40000 ALTER TABLE `battleground_events` DISABLE KEYS */;
INSERT INTO battleground_events (map, event1, event2, description) VALUES
-- WS
(489, 0, 0, 'Alliance Flag'),
(489, 1, 0, 'Horde Flag'),
(489, 2, 0, 'Spirit Guides'),
(489, 254, 0, 'Doors'),
-- AB
(529, 0, 0, 'Stables - neutral'),
(529, 0, 1, 'Stables - alliance contested'),
(529, 0, 2, 'Stables - horde contested'),
(529, 0, 3, 'Stables - alliance owned'),
(529, 0, 4, 'Stables - horde owned'),
(529, 1, 0, 'Blacksmith - neutral'),
(529, 1, 1, 'Blacksmith - alliance contested'),
(529, 1, 2, 'Blacksmith - horde contested'),
(529, 1, 3, 'Blacksmith - alliance owned'),
(529, 1, 4, 'Blacksmith - horde owned'),
(529, 2, 0, 'Farm - neutral'),
(529, 2, 1, 'Farm - alliance contested'),
(529, 2, 2, 'Farm - horde contested'),
(529, 2, 3, 'Farm - alliance owned'),
(529, 2, 4, 'Farm - horde owned'),
(529, 3, 0, 'Lumber Mill - neutral'),
(529, 3, 1, 'Lumber Mill - alliance contested'),
(529, 3, 2, 'Lumber Mill - horde contested'),
(529, 3, 3, 'Lumber Mill - alliance owned'),
(529, 3, 4, 'Lumber Mill - horde owned'),
(529, 4, 0, 'Gold Mine - neutral'),
(529, 4, 1, 'Gold Mine - alliance contested'),
(529, 4, 2, 'Gold Mine - horde contested'),
(529, 4, 3, 'Gold Mine - alliance owned'),
(529, 4, 4, 'Gold Mine - horde owned'),
(529, 254, 0, 'doors'),
-- EY
(566, 0, 0, 'Fel Reaver - alliance'),
(566, 0, 1, 'Fel Reaver - horde'),
(566, 0, 2, 'Fel Reaver - neutral'),
(566, 1, 0, 'Blood Elf - alliance'),
(566, 1, 1, 'Blood Elf - horde'),
(566, 1, 2, 'Blood Elf - neutral'),
(566, 2, 0, 'Draenei Ruins - alliance'),
(566, 2, 1, 'Draenei Ruins - horde'),
(566, 2, 2, 'Draenei Ruins - neutral'),
(566, 3, 0, 'Mage Tower - alliance'),
(566, 3, 1, 'Mage Tower - horde'),
(566, 3, 2, 'Mage Tower - neutral'),
(566, 4, 0, 'capture flag - Fel Reaver'),
(566, 4, 1, 'capture flag - Blood Elf'),
(566, 4, 2, 'capture flag - Draenei Ruins'),
(566, 4, 3, 'capture flag - Mage Tower'),
(566, 4, 4, 'capture flag - center'),
(566, 254, 0, 'doors'),
-- arenas
(559, 253, 0, 'buffs'),
(559, 254, 0, 'doors'),
(572, 253, 0, 'buffs'),
(572, 254, 0, 'doors'),
(562, 253, 0, 'buffs'),
(562, 254, 0, 'doors');
/*!40000 ALTER TABLE `battleground_events` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `battleground_template` -- Table structure for table `battleground_template`
-- --
@ -583,6 +664,27 @@ LOCK TABLES `creature_addon` WRITE;
/*!40000 ALTER TABLE `creature_addon` ENABLE KEYS */; /*!40000 ALTER TABLE `creature_addon` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `creature_battleground`
--
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';
--
-- Dumping data for table `creature_battleground`
--
LOCK TABLES `creature_battleground` WRITE;
/*!40000 ALTER TABLE `creature_battleground` DISABLE KEYS */;
/*!40000 ALTER TABLE `creature_battleground` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `creature_equip_template` -- Table structure for table `creature_equip_template`
-- --
@ -1422,6 +1524,27 @@ LOCK TABLES `gameobject` WRITE;
/*!40000 ALTER TABLE `gameobject` ENABLE KEYS */; /*!40000 ALTER TABLE `gameobject` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `gameobject_battleground`
--
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';
--
-- Dumping data for table `gameobject_battleground`
--
LOCK TABLES `gameobject_battleground` WRITE;
/*!40000 ALTER TABLE `gameobject_battleground` DISABLE KEYS */;
/*!40000 ALTER TABLE `gameobject_battleground` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `gameobject_involvedrelation` -- Table structure for table `gameobject_involvedrelation`
-- --
@ -2893,8 +3016,6 @@ INSERT INTO `mangos_string` VALUES
(570,'The uint32 value of %u in %u is: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (570,'The uint32 value of %u in %u is: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(571,'Get %u float Value:[OPCODE]:%u [VALUE]:%f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (571,'Get %u float Value:[OPCODE]:%u [VALUE]:%f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(572,'The float of %u value in %u is: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (572,'The float of %u value in %u is: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(573,'.Set32Bit:[OPCODE]:%u [VALUE]:%u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(574,'You set Bit of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(575,'.Mod32Value:[OPCODE]:%u [VALUE]:%i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (575,'.Mod32Value:[OPCODE]:%u [VALUE]:%i',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(576,'You modified the value of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (576,'You modified the value of Field:%u to Value: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(577,'You are now invisible.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (577,'You are now invisible.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),

View file

@ -89,4 +89,4 @@ INSERT INTO battleground_events (map, event1, event2, description) VALUES
(@RL_MAP, 254, 0, 'doors'), (@RL_MAP, 254, 0, 'doors'),
(@BE_MAP, 253, 0, 'buffs'), (@BE_MAP, 253, 0, 'buffs'),
(@BE_MAP, 254, 0, 'doors') (@BE_MAP, 254, 0, 'doors');

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_8549_03_mangos_battleground_events required_8573_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN(573,574);

View file

@ -116,6 +116,7 @@ pkgdata_DATA = \
8548_01_mangos_creature_battleground.sql \ 8548_01_mangos_creature_battleground.sql \
8548_02_mangos_gameobject_battleground.sql \ 8548_02_mangos_gameobject_battleground.sql \
8549_03_mangos_battleground_events.sql \ 8549_03_mangos_battleground_events.sql \
8573_01_mangos_mangos_string.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -212,4 +213,5 @@ EXTRA_DIST = \
8548_01_mangos_creature_battleground.sql \ 8548_01_mangos_creature_battleground.sql \
8548_02_mangos_gameobject_battleground.sql \ 8548_02_mangos_gameobject_battleground.sql \
8549_03_mangos_battleground_events.sql \ 8549_03_mangos_battleground_events.sql \
8573_01_mangos_mangos_string.sql \
README README

View file

@ -161,90 +161,90 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
return true; return true;
} }
bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) bool ArenaTeam::LoadArenaTeamFromDB(QueryResult *arenaTeamDataResult)
{ {
QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); if(!arenaTeamDataResult)
if(!result)
return false; return false;
Field *fields = result->Fetch(); Field *fields = arenaTeamDataResult->Fetch();
m_TeamId = fields[0].GetUInt32(); m_TeamId = fields[0].GetUInt32();
m_Name = fields[1].GetCppString(); m_Name = fields[1].GetCppString();
m_CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER); m_CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
m_Type = fields[3].GetUInt32(); m_Type = fields[3].GetUInt32();
m_BackgroundColor = fields[4].GetUInt32(); m_BackgroundColor = fields[4].GetUInt32();
m_EmblemStyle = fields[5].GetUInt32(); m_EmblemStyle = fields[5].GetUInt32();
m_EmblemColor = fields[6].GetUInt32(); m_EmblemColor = fields[6].GetUInt32();
m_BorderStyle = fields[7].GetUInt32(); m_BorderStyle = fields[7].GetUInt32();
m_BorderColor = fields[8].GetUInt32(); m_BorderColor = fields[8].GetUInt32();
//load team stats
delete result; m_stats.rating = fields[9].GetUInt32();
m_stats.games_week = fields[10].GetUInt32();
// only load here, so additional checks can be made m_stats.wins_week = fields[11].GetUInt32();
LoadStatsFromDB(ArenaTeamId); m_stats.games_season = fields[12].GetUInt32();
LoadMembersFromDB(ArenaTeamId); m_stats.wins_season = fields[13].GetUInt32();
m_stats.rank = fields[14].GetUInt32();
if(Empty())
{
// arena team is empty, delete from db
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId);
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId);
CharacterDatabase.CommitTransaction();
return false;
}
return true; return true;
} }
void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId) bool ArenaTeam::LoadMembersFromDB(QueryResult *arenaTeamMembersResult)
{ {
// 0 1 2 3 4 5 if(!arenaTeamMembersResult)
QueryResult *result = CharacterDatabase.PQuery("SELECT rating,games,wins,played,wins2,rank FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); return false;
if(!result) bool captainPresentInTeam = false;
return;
Field *fields = result->Fetch();
m_stats.rating = fields[0].GetUInt32();
m_stats.games_week = fields[1].GetUInt32();
m_stats.wins_week = fields[2].GetUInt32();
m_stats.games_season = fields[3].GetUInt32();
m_stats.wins_season = fields[4].GetUInt32();
m_stats.rank = fields[5].GetUInt32();
delete result;
}
void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId)
{
// 0 1 2 3 4 5 6 7
QueryResult *result = CharacterDatabase.PQuery("SELECT member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class "
"FROM arena_team_member member "
"INNER JOIN characters chars on member.guid = chars.guid "
"WHERE member.arenateamid = '%u'", ArenaTeamId);
if(!result)
return;
do do
{ {
Field *fields = result->Fetch(); Field *fields = arenaTeamMembersResult->Fetch();
//prevent crash if db records are broken, when all members in result are already processed and current team hasn't got any members
if (!fields)
break;
uint32 arenaTeamId = fields[0].GetUInt32();
if (arenaTeamId < m_TeamId)
{
//there is in table arena_team_member record which doesn't have arenateamid in arena_team table, report error
sLog.outErrorDb("ArenaTeam %u does not exist but it has record in arena_team_member table, deleting it!", arenaTeamId);
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", arenaTeamId);
continue;
}
if (arenaTeamId > m_TeamId)
//we loaded all members for this arena_team already, break cycle
break;
ArenaTeamMember newmember; ArenaTeamMember newmember;
newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); newmember.guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
newmember.games_week = fields[1].GetUInt32(); newmember.games_week = fields[2].GetUInt32();
newmember.wins_week = fields[2].GetUInt32(); newmember.wins_week = fields[3].GetUInt32();
newmember.games_season = fields[3].GetUInt32(); newmember.games_season = fields[4].GetUInt32();
newmember.wins_season = fields[4].GetUInt32(); newmember.wins_season = fields[5].GetUInt32();
newmember.personal_rating = fields[5].GetUInt32(); newmember.personal_rating = fields[6].GetUInt32();
newmember.name = fields[6].GetCppString(); newmember.name = fields[7].GetCppString();
newmember.Class = fields[7].GetUInt8(); newmember.Class = fields[8].GetUInt8();
//check if member exists in characters table
if (newmember.name.empty())
{
sLog.outErrorDb("ArenaTeam %u has member with empty name - probably player %u doesn't exist, deleting him from memberlist!", arenaTeamId, GUID_LOPART(newmember.guid));
this->DelMember(newmember.guid);
continue;
}
if (newmember.guid == GetCaptain())
captainPresentInTeam = true;
m_members.push_back(newmember); m_members.push_back(newmember);
}while( result->NextRow() ); }while (arenaTeamMembersResult->NextRow());
delete result;
if(Empty() || !captainPresentInTeam)
{
// arena team is empty or captain is not in team, delete from db
sLog.outErrorDb("ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", m_TeamId);
return false;
}
return true;
} }
void ArenaTeam::SetCaptain(const uint64& guid) void ArenaTeam::SetCaptain(const uint64& guid)
@ -291,9 +291,12 @@ void ArenaTeam::DelMember(uint64 guid)
void ArenaTeam::Disband(WorldSession *session) void ArenaTeam::Disband(WorldSession *session)
{ {
// event // event
WorldPacket data; if (session)
session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), ""); {
BroadcastPacket(&data); WorldPacket data;
session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), "");
BroadcastPacket(&data);
}
while (!m_members.empty()) while (!m_members.empty())
{ {

View file

@ -179,8 +179,8 @@ class ArenaTeam
bool IsFighting() const; bool IsFighting() const;
bool LoadArenaTeamFromDB(uint32 ArenaTeamId); bool LoadArenaTeamFromDB(QueryResult *arenaTeamDataResult);
void LoadMembersFromDB(uint32 ArenaTeamId); bool LoadMembersFromDB(QueryResult *arenaTeamMembersResult);
void LoadStatsFromDB(uint32 ArenaTeamId); void LoadStatsFromDB(uint32 ArenaTeamId);
void SaveToDB(); void SaveToDB();

View file

@ -152,6 +152,7 @@ BattleGround::BattleGround()
m_MinPlayers = 0; m_MinPlayers = 0;
m_MapId = 0; m_MapId = 0;
m_Map = NULL;
m_TeamStartLocX[BG_TEAM_ALLIANCE] = 0; m_TeamStartLocX[BG_TEAM_ALLIANCE] = 0;
m_TeamStartLocX[BG_TEAM_HORDE] = 0; m_TeamStartLocX[BG_TEAM_HORDE] = 0;
@ -214,10 +215,12 @@ BattleGround::~BattleGround()
} }
sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID()); sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID());
// unload map // unload map
if (Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID())) // map can be null at bg destruction
if (map->IsBattleGroundOrArena()) if (m_Map)
((BattleGroundMap*)map)->SetUnload(); m_Map->SetUnload();
// remove from bg free slot queue // remove from bg free slot queue
this->RemoveFromBGFreeSlotQueue(); this->RemoveFromBGFreeSlotQueue();
@ -1292,15 +1295,11 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
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) 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());
if (!map)
return false;
// must be created this way, adding to godatamap would add it to the base map of the instance // must be created this way, adding to godatamap would add it to the base map of the instance
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// so we must create it specific for this instance // so we must create it specific for this instance
GameObject * go = new GameObject; GameObject * go = new GameObject;
if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map, if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, GetBgMap(),
PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,GO_STATE_READY)) PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,GO_STATE_READY))
{ {
sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);
@ -1340,7 +1339,7 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
//it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code //it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
void BattleGround::DoorClose(uint64 const& guid) void BattleGround::DoorClose(uint64 const& guid)
{ {
GameObject *obj = HashMapHolder<GameObject>::Find(guid); GameObject *obj = GetBgMap()->GetGameObject(guid);
if (obj) if (obj)
{ {
//if doors are open, close it //if doors are open, close it
@ -1359,7 +1358,7 @@ void BattleGround::DoorClose(uint64 const& guid)
void BattleGround::DoorOpen(uint64 const& guid) void BattleGround::DoorOpen(uint64 const& guid)
{ {
GameObject *obj = HashMapHolder<GameObject>::Find(guid); GameObject *obj = GetBgMap()->GetGameObject(guid);
if (obj) if (obj)
{ {
//change state to be sure they will be opened //change state to be sure they will be opened
@ -1459,12 +1458,11 @@ void BattleGround::SpawnEvent(uint8 event1, uint8 event2, bool spawn)
void BattleGround::SpawnBGObject(uint64 const& guid, uint32 respawntime) void BattleGround::SpawnBGObject(uint64 const& guid, uint32 respawntime)
{ {
GameObject *obj = HashMapHolder<GameObject>::Find(guid); Map* map = GetBgMap();
GameObject *obj = map->GetGameObject(guid);
if(!obj) if(!obj)
return; return;
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
if (!map)
return;
if (respawntime == 0) if (respawntime == 0)
{ {
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
@ -1483,12 +1481,11 @@ void BattleGround::SpawnBGObject(uint64 const& guid, uint32 respawntime)
void BattleGround::SpawnBGCreature(uint64 const& guid, uint32 respawntime) void BattleGround::SpawnBGCreature(uint64 const& guid, uint32 respawntime)
{ {
Creature* obj = HashMapHolder<Creature>::Find(guid); Map* map = GetBgMap();
Creature* obj = map->GetCreature(guid);
if (!obj) if (!obj)
return; return;
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
if (!map)
return;
if (respawntime == 0) if (respawntime == 0)
{ {
obj->Respawn(); obj->Respawn();
@ -1508,12 +1505,13 @@ bool BattleGround::DelObject(uint32 type)
if (!m_BgObjects[type]) if (!m_BgObjects[type])
return true; return true;
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]); GameObject *obj = GetBgMap()->GetGameObject(m_BgObjects[type]);
if (!obj) if (!obj)
{ {
sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type])); sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type]));
return false; return false;
} }
obj->SetRespawnTime(0); // not save respawn time obj->SetRespawnTime(0); // not save respawn time
obj->Delete(); obj->Delete();
m_BgObjects[type] = 0; m_BgObjects[type] = 0;
@ -1560,11 +1558,20 @@ buffs are in their positions when battleground starts
*/ */
void BattleGround::HandleTriggerBuff(uint64 const& go_guid) void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
{ {
GameObject *obj = HashMapHolder<GameObject>::Find(go_guid); GameObject *obj = GetBgMap()->GetGameObject(go_guid);
if (!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned()) if (!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
return; return;
//change buff type, when buff is used: // static buffs are already handled just by database and don't need
// battleground code
if (!m_BuffChange)
{
obj->SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
return;
}
// change buff type, when buff is used:
// TODO this can be done when poolsystem works for instances
int32 index = m_BgObjects.size() - 1; int32 index = m_BgObjects.size() - 1;
while (index >= 0 && m_BgObjects[index] != go_guid) while (index >= 0 && m_BgObjects[index] != go_guid)
index--; index--;

View file

@ -36,6 +36,7 @@ class GameObject;
class Group; class Group;
class Player; class Player;
class WorldPacket; class WorldPacket;
class BattleGroundMap;
struct WorldSafeLocsEntry; struct WorldSafeLocsEntry;
@ -395,6 +396,14 @@ class BattleGround
void SetMapId(uint32 MapID) { m_MapId = MapID; } void SetMapId(uint32 MapID) { m_MapId = MapID; }
uint32 GetMapId() const { return m_MapId; } uint32 GetMapId() const { return m_MapId; }
/* Map pointers */
void SetBgMap(BattleGroundMap* map) { m_Map = map; }
BattleGroundMap* GetBgMap()
{
ASSERT(m_Map);
return m_Map;
}
void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O); void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O);
void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const
{ {
@ -619,6 +628,7 @@ class BattleGround
/* Start location */ /* Start location */
uint32 m_MapId; uint32 m_MapId;
BattleGroundMap* m_Map;
float m_TeamStartLocX[BG_TEAMS_COUNT]; float m_TeamStartLocX[BG_TEAMS_COUNT];
float m_TeamStartLocY[BG_TEAMS_COUNT]; float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT]; float m_TeamStartLocZ[BG_TEAMS_COUNT];

View file

@ -469,7 +469,7 @@ void BattleGroundAB::Reset()
} }
m_IsInformedNearVictory = false; m_IsInformedNearVictory = false;
bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); bool isBGWeekend = BattleGroundMgr::IsBGWeekend(GetTypeID());
m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks;
m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks;

View file

@ -430,7 +430,7 @@ void BattleGroundEY::Reset()
m_DroppedFlagGUID = 0; m_DroppedFlagGUID = 0;
m_PointAddingTimer = 0; m_PointAddingTimer = 0;
m_TowerCapCheckTimer = 0; m_TowerCapCheckTimer = 0;
bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); bool isBGWeekend = BattleGroundMgr::IsBGWeekend(GetTypeID());
m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks;
for(uint8 i = 0; i < BG_EY_NODES_MAX; ++i) for(uint8 i = 0; i < BG_EY_NODES_MAX; ++i)
@ -468,7 +468,7 @@ void BattleGroundEY::RespawnFlagAfterDrop()
{ {
RespawnFlag(true); RespawnFlag(true);
GameObject *obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID()); GameObject *obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID());
if (obj) if (obj)
obj->Delete(); obj->Delete();
else else

View file

@ -23,7 +23,6 @@
#include "Player.h" #include "Player.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "WorldSession.h" #include "WorldSession.h"
#include "ObjectAccessor.h"
#include "Object.h" #include "Object.h"
#include "Chat.h" #include "Chat.h"
#include "BattleGroundMgr.h" #include "BattleGroundMgr.h"

View file

@ -21,6 +21,7 @@
#include "Common.h" #include "Common.h"
#include "Policies/Singleton.h" #include "Policies/Singleton.h"
#include "Utilities/EventProcessor.h"
#include "BattleGround.h" #include "BattleGround.h"
typedef std::map<uint32, BattleGround*> BattleGroundSet; typedef std::map<uint32, BattleGround*> BattleGroundSet;

View file

@ -98,6 +98,7 @@ void BattleGroundWS::StartingEventOpenDoors()
// TODO implement timer to despawn doors after a short while // TODO implement timer to despawn doors after a short while
SpawnEvent(WS_EVENT_SPIRITGUIDES_SPAWN, 0, true);
SpawnEvent(WS_EVENT_FLAG_A, 0, true); SpawnEvent(WS_EVENT_FLAG_A, 0, true);
SpawnEvent(WS_EVENT_FLAG_H, 0, true); SpawnEvent(WS_EVENT_FLAG_H, 0, true);
} }
@ -149,7 +150,7 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
GameObject *obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID(team)); GameObject *obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID(team));
if (obj) if (obj)
obj->Delete(); obj->Delete();
else else
@ -533,7 +534,7 @@ void BattleGroundWS::Reset()
m_FlagState[i] = BG_WS_FLAG_STATE_ON_BASE; m_FlagState[i] = BG_WS_FLAG_STATE_ON_BASE;
m_TeamScores[i] = 0; m_TeamScores[i] = 0;
} }
bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); bool isBGWeekend = BattleGroundMgr::IsBGWeekend(GetTypeID());
m_ReputationCapture = (isBGWeekend) ? 45 : 35; m_ReputationCapture = (isBGWeekend) ? 45 : 35;
m_HonorWinKills = (isBGWeekend) ? 3 : 1; m_HonorWinKills = (isBGWeekend) ? 3 : 1;
m_HonorEndKills = (isBGWeekend) ? 4 : 2; m_HonorEndKills = (isBGWeekend) ? 4 : 2;

View file

@ -492,7 +492,6 @@ class ChatHandler
bool HandleWaterwalkCommand(const char* args); bool HandleWaterwalkCommand(const char* args);
//! Development Commands //! Development Commands
bool HandleSet32Bit(const char* args);
bool HandleSaveAllCommand(const char* args); bool HandleSaveAllCommand(const char* args);
Player* getSelectedPlayer(); Player* getSelectedPlayer();

View file

@ -159,7 +159,7 @@ void Creature::RemoveCorpse()
m_deathTimer = 0; m_deathTimer = 0;
setDeathState(DEAD); setDeathState(DEAD);
ObjectAccessor::UpdateObjectVisibility(this); UpdateObjectVisibility();
loot.clear(); loot.clear();
uint32 respawnDelay = m_respawnDelay; uint32 respawnDelay = m_respawnDelay;
if (AI()) if (AI())
@ -1585,9 +1585,9 @@ void Creature::Respawn()
// forced recreate creature object at clients // forced recreate creature object at clients
UnitVisibility currentVis = GetVisibility(); UnitVisibility currentVis = GetVisibility();
SetVisibility(VISIBILITY_RESPAWN); SetVisibility(VISIBILITY_RESPAWN);
ObjectAccessor::UpdateObjectVisibility(this); UpdateObjectVisibility();
SetVisibility(currentVis); // restore visibility state SetVisibility(currentVis); // restore visibility state
ObjectAccessor::UpdateObjectVisibility(this); UpdateObjectVisibility();
if(getDeathState()==DEAD) if(getDeathState()==DEAD)
{ {

View file

@ -449,7 +449,7 @@ void GameObject::Update(uint32 /*p_time*/)
if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY))
SaveRespawnTime(); SaveRespawnTime();
ObjectAccessor::UpdateObjectVisibility(this); UpdateObjectVisibility();
break; break;
} }
@ -602,7 +602,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) ) if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) )
return false; return false;
if(!GetGOInfo()->GetDespawnPossibility() && !GetGOInfo()->IsDespawnAtAction()) if (!GetGOInfo()->GetDespawnPossibility() && !GetGOInfo()->IsDespawnAtAction() && data->spawntimesecs >= 0)
{ {
SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
m_spawnedByDefault = true; m_spawnedByDefault = true;

View file

@ -208,62 +208,43 @@ void Guild::SetGINFO(std::string ginfo)
CharacterDatabase.PExecute("UPDATE guild SET info='%s' WHERE guildid='%u'", ginfo.c_str(), m_Id); CharacterDatabase.PExecute("UPDATE guild SET info='%s' WHERE guildid='%u'", ginfo.c_str(), m_Id);
} }
bool Guild::LoadGuildFromDB(uint32 GuildId) bool Guild::LoadGuildFromDB(QueryResult *guildDataResult)
{ {
//set m_Id in case guild data are broken in DB and Guild will be Disbanded (deleted from DB) if (!guildDataResult)
m_Id = GuildId;
QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(TabId) FROM guild_bank_tab WHERE guildid='%u'", GuildId);
if (result)
{
Field *fields = result->Fetch();
m_PurchasedTabs = fields[0].GetUInt32();
if (m_PurchasedTabs > GUILD_BANK_MAX_TABS)
m_PurchasedTabs = GUILD_BANK_MAX_TABS;
delete result;
}
if (!LoadRanksFromDB(GuildId))
return false; return false;
if (!LoadMembersFromDB(GuildId)) Field *fields = guildDataResult->Fetch();
return false;
LoadBankRightsFromDB(GuildId); // Must be after LoadRanksFromDB because it populates rank struct m_Id = fields[0].GetUInt32();
m_Name = fields[1].GetCppString();
m_LeaderGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
m_EmblemStyle = fields[3].GetUInt32();
m_EmblemColor = fields[4].GetUInt32();
m_BorderStyle = fields[5].GetUInt32();
m_BorderColor = fields[6].GetUInt32();
m_BackgroundColor = fields[7].GetUInt32();
GINFO = fields[8].GetCppString();
MOTD = fields[9].GetCppString();
time_t time = fields[10].GetUInt64();
m_GuildBankMoney = fields[11].GetUInt64();
m_PurchasedTabs = fields[12].GetUInt32();
// 0 1 2 3 4 5 if (m_PurchasedTabs > GUILD_BANK_MAX_TABS)
result = CharacterDatabase.PQuery("SELECT name, leaderguid, EmblemStyle, EmblemColor, BorderStyle, BorderColor," m_PurchasedTabs = GUILD_BANK_MAX_TABS;
// 6 7 8 9 10
"BackgroundColor, info, motd, createdate, BankMoney FROM guild WHERE guildid = '%u'", GuildId);
if (!result)
return false;
Field *fields = result->Fetch();
m_Name = fields[0].GetCppString();
m_LeaderGuid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
m_EmblemStyle = fields[2].GetUInt32();
m_EmblemColor = fields[3].GetUInt32();
m_BorderStyle = fields[4].GetUInt32();
m_BorderColor = fields[5].GetUInt32();
m_BackgroundColor = fields[6].GetUInt32();
GINFO = fields[7].GetCppString();
MOTD = fields[8].GetCppString();
time_t time = fields[9].GetUInt64();
m_GuildBankMoney = fields[10].GetUInt64();
delete result;
if (time > 0) if (time > 0)
{ {
tm local = *(localtime(&time)); // dereference and assign tm local = *(localtime(&time)); // dereference and assign
m_CreatedDay = local.tm_mday; m_CreatedDay = local.tm_mday;
m_CreatedMonth = local.tm_mon + 1; m_CreatedMonth = local.tm_mon + 1;
m_CreatedYear = local.tm_year + 1900; m_CreatedYear = local.tm_year + 1900;
} }
return true;
}
bool Guild::CheckGuildStructure()
{
// Repair the structure of guild // Repair the structure of guild
// If the guildmaster doesn't exist or isn't the member of guild // If the guildmaster doesn't exist or isn't the member of guild
// attempt to promote another member // attempt to promote another member
@ -286,24 +267,19 @@ bool Guild::LoadGuildFromDB(uint32 GuildId)
ChangeRank(itr->first, GR_OFFICER); ChangeRank(itr->first, GR_OFFICER);
} }
sLog.outDebug("Guild %u Creation time Loaded day: %u, month: %u, year: %u", GuildId, m_CreatedDay, m_CreatedMonth, m_CreatedYear);
return true; return true;
} }
bool Guild::LoadRanksFromDB(uint32 GuildId) bool Guild::LoadRanksFromDB(QueryResult *guildRanksResult)
{ {
Field *fields; if (!guildRanksResult)
// 0 1 2 3
QueryResult *result = CharacterDatabase.PQuery("SELECT rid,rname,rights,BankMoneyPerDay FROM guild_rank WHERE guildid = '%u' ORDER BY rid ASC", GuildId);
if (!result)
{ {
sLog.outError("Guild %u has broken `guild_rank` data, creating new...",GuildId); sLog.outError("Guild %u has broken `guild_rank` data, creating new...",m_Id);
CreateDefaultGuildRanks(0); CreateDefaultGuildRanks(0);
return true; return true;
} }
Field *fields;
bool broken_ranks = false; bool broken_ranks = false;
//GUILD RANKS are sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges) //GUILD RANKS are sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges)
@ -313,12 +289,27 @@ bool Guild::LoadRanksFromDB(uint32 GuildId)
do do
{ {
fields = result->Fetch(); fields = guildRanksResult->Fetch();
//condition that would be true when all ranks in QueryResult will be processed and guild without ranks is being processed
if (!fields)
break;
uint32 rankID = fields[0].GetUInt32(); uint32 guildId = fields[0].GetUInt32();
std::string rankName = fields[1].GetCppString(); if (guildId < m_Id)
uint32 rankRights = fields[2].GetUInt32(); {
uint32 rankMoney = fields[3].GetUInt32(); //there is in table guild_rank record which doesn't have guildid in guild table, report error
sLog.outErrorDb("Guild %u does not exist but it has a record in guild_rank table, deleting it!", guildId);
CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'", guildId);
continue;
}
if (guildId > m_Id)
//we loaded all ranks for this guild already, break cycle
break;
uint32 rankID = fields[1].GetUInt32();
std::string rankName = fields[2].GetCppString();
uint32 rankRights = fields[3].GetUInt32();
uint32 rankMoney = fields[4].GetUInt32();
if (rankID != m_Ranks.size()) // guild_rank.ids are sequence 0,1,2,3.. if (rankID != m_Ranks.size()) // guild_rank.ids are sequence 0,1,2,3..
broken_ranks = true; broken_ranks = true;
@ -328,28 +319,27 @@ bool Guild::LoadRanksFromDB(uint32 GuildId)
rankRights |= GR_RIGHT_ALL; rankRights |= GR_RIGHT_ALL;
AddRank(rankName,rankRights,rankMoney); AddRank(rankName,rankRights,rankMoney);
}while( result->NextRow() ); }while( guildRanksResult->NextRow() );
delete result;
if (m_Ranks.size() < GUILD_RANKS_MIN_COUNT) // if too few ranks, renew them if (m_Ranks.size() < GUILD_RANKS_MIN_COUNT) // if too few ranks, renew them
{ {
m_Ranks.clear(); m_Ranks.clear();
sLog.outError("Guild %u has broken `guild_rank` data, creating new...",GuildId); sLog.outError("Guild %u has broken `guild_rank` data, creating new...", m_Id);
CreateDefaultGuildRanks(0); // 0 is default locale_idx CreateDefaultGuildRanks(0); // 0 is default locale_idx
broken_ranks = false; broken_ranks = false;
} }
// guild_rank have wrong numbered ranks, repair // guild_rank have wrong numbered ranks, repair
if (broken_ranks) if (broken_ranks)
{ {
sLog.outError("Guild %u has broken `guild_rank` data, repairing...",GuildId); sLog.outError("Guild %u has broken `guild_rank` data, repairing...", m_Id);
CharacterDatabase.BeginTransaction(); CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", GuildId); CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id);
for(size_t i = 0; i < m_Ranks.size(); ++i) for(size_t i = 0; i < m_Ranks.size(); ++i)
{ {
std::string name = m_Ranks[i].Name; std::string name = m_Ranks[i].Name;
uint32 rights = m_Ranks[i].Rights; uint32 rights = m_Ranks[i].Rights;
CharacterDatabase.escape_string(name); CharacterDatabase.escape_string(name);
CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", GuildId, uint32(i), name.c_str(), rights); CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, uint32(i), name.c_str(), rights);
} }
CharacterDatabase.CommitTransaction(); CharacterDatabase.CommitTransaction();
} }
@ -357,46 +347,52 @@ bool Guild::LoadRanksFromDB(uint32 GuildId)
return true; return true;
} }
bool Guild::LoadMembersFromDB(uint32 GuildId) bool Guild::LoadMembersFromDB(QueryResult *guildMembersResult)
{ {
// 0 1 2 3 4 5 if (!guildMembersResult)
QueryResult *result = CharacterDatabase.PQuery("SELECT guild_member.guid,rank, pnote, offnote, BankResetTimeMoney,BankRemMoney,"
// 6 7 8 9 10 11
"BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2,"
// 12 13 14 15 16 17
"BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5,"
// 18 19 20 21 22
"characters.name, characters.level, characters.class, characters.zone, characters.logout_time "
"FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid WHERE guildid = '%u'", GuildId);
if (!result)
return false; return false;
do do
{ {
Field *fields = result->Fetch(); Field *fields = guildMembersResult->Fetch();
//this condition will be true when all rows in QueryResult are processed and new guild without members is going to be loaded - prevent crash
if (!fields)
break;
uint32 guildId = fields[0].GetUInt32();
if (guildId < m_Id)
{
//there is in table guild_member record which doesn't have guildid in guild table, report error
sLog.outErrorDb("Guild %u does not exist but it has a record in guild_member table, deleting it!", guildId);
CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guildid = '%u'", guildId);
continue;
}
if (guildId > m_Id)
//we loaded all members for this guild already, break cycle
break;
MemberSlot newmember; MemberSlot newmember;
uint64 guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); uint64 guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
newmember.RankId = fields[1].GetUInt32(); newmember.RankId = fields[2].GetUInt32();
//don't allow member to have not existing rank! //don't allow member to have not existing rank!
if (newmember.RankId >= m_Ranks.size()) if (newmember.RankId >= m_Ranks.size())
newmember.RankId = GetLowestRank(); newmember.RankId = GetLowestRank();
newmember.Pnote = fields[2].GetCppString(); newmember.Pnote = fields[3].GetCppString();
newmember.OFFnote = fields[3].GetCppString(); newmember.OFFnote = fields[4].GetCppString();
newmember.BankResetTimeMoney = fields[4].GetUInt32(); newmember.BankResetTimeMoney = fields[5].GetUInt32();
newmember.BankRemMoney = fields[5].GetUInt32(); newmember.BankRemMoney = fields[6].GetUInt32();
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{ {
newmember.BankResetTimeTab[i] = fields[6+(2*i)].GetUInt32(); newmember.BankResetTimeTab[i] = fields[7+(2*i)].GetUInt32();
newmember.BankRemSlotsTab[i] = fields[7+(2*i)].GetUInt32(); newmember.BankRemSlotsTab[i] = fields[8+(2*i)].GetUInt32();
} }
newmember.Name = fields[18].GetCppString(); newmember.Name = fields[19].GetCppString();
newmember.Level = fields[19].GetUInt8(); newmember.Level = fields[20].GetUInt8();
newmember.Class = fields[20].GetUInt8(); newmember.Class = fields[21].GetUInt8();
newmember.ZoneId = fields[21].GetUInt32(); newmember.ZoneId = fields[22].GetUInt32();
newmember.LogoutTime = fields[22].GetUInt64(); newmember.LogoutTime = fields[23].GetUInt64();
//this code will remove unexisting character guids from guild //this code will remove unexisting character guids from guild
if (newmember.Level < 1 || newmember.Level > STRONG_MAX_LEVEL) // can be at broken `data` field if (newmember.Level < 1 || newmember.Level > STRONG_MAX_LEVEL) // can be at broken `data` field
@ -421,8 +417,7 @@ bool Guild::LoadMembersFromDB(uint32 GuildId)
members[GUID_LOPART(guid)] = newmember; members[GUID_LOPART(guid)] = newmember;
}while( result->NextRow() ); }while (guildMembersResult->NextRow());
delete result;
if (members.empty()) if (members.empty())
return false; return false;
@ -1464,28 +1459,39 @@ uint32 Guild::GetBankSlotPerDay(uint32 rankId, uint8 TabId)
// ************************************************* // *************************************************
// Rights per day related // Rights per day related
void Guild::LoadBankRightsFromDB(uint32 GuildId) bool Guild::LoadBankRightsFromDB(QueryResult *guildBankTabRightsResult)
{ {
// 0 1 2 3 if (!guildBankTabRightsResult)
QueryResult *result = CharacterDatabase.PQuery("SELECT TabId, rid, gbright, SlotPerDay FROM guild_bank_right WHERE guildid = '%u' ORDER BY TabId", GuildId); return true;
if (!result)
return;
do do
{ {
Field *fields = result->Fetch(); Field *fields = guildBankTabRightsResult->Fetch();
uint8 TabId = fields[0].GetUInt8(); //prevent crash when all rights in result are already processed
uint32 rankId = fields[1].GetUInt32(); if (!fields)
uint16 right = fields[2].GetUInt16(); break;
uint16 SlotPerDay = fields[3].GetUInt16(); uint32 guildId = fields[0].GetUInt32();
if (guildId < m_Id)
{
//there is in table guild_bank_right record which doesn't have guildid in guild table, report error
sLog.outErrorDb("Guild %u does not exist but it has a record in guild_bank_right table, deleting it!", guildId);
CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", guildId);
continue;
}
if (guildId > m_Id)
//we loaded all ranks for this guild bank already, break cycle
break;
uint8 TabId = fields[1].GetUInt8();
uint32 rankId = fields[2].GetUInt32();
uint16 right = fields[3].GetUInt16();
uint16 SlotPerDay = fields[4].GetUInt16();
SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false); SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false);
} while (result->NextRow()); } while (guildBankTabRightsResult->NextRow());
delete result;
return; return true;
} }
// ************************************************* // *************************************************

View file

@ -324,9 +324,10 @@ class Guild
uint32 GetMemberSize() const { return members.size(); } uint32 GetMemberSize() const { return members.size(); }
bool LoadGuildFromDB(uint32 GuildId); bool LoadGuildFromDB(QueryResult *guildDataResult);
bool LoadRanksFromDB(uint32 GuildId); bool CheckGuildStructure();
bool LoadMembersFromDB(uint32 GuildId); bool LoadRanksFromDB(QueryResult *guildRanksResult);
bool LoadMembersFromDB(QueryResult *guildMembersResult);
void SetMemberStats(uint64 guid); void SetMemberStats(uint64 guid);
@ -422,7 +423,7 @@ class Guild
uint32 GetBankMoneyPerDay(uint32 rankId); uint32 GetBankMoneyPerDay(uint32 rankId);
uint32 GetBankSlotPerDay(uint32 rankId, uint8 TabId); uint32 GetBankSlotPerDay(uint32 rankId, uint8 TabId);
// rights per day // rights per day
void LoadBankRightsFromDB(uint32 GuildId); bool LoadBankRightsFromDB(QueryResult *guildBankTabRightsResult);
// Guild Bank Event Logs // Guild Bank Event Logs
void LoadGuildBankEventLogFromDB(); void LoadGuildBankEventLogFromDB();
void UnloadGuildBankEventLog(); void UnloadGuildBankEventLog();

View file

@ -25,7 +25,6 @@
#include "Player.h" #include "Player.h"
#include "Item.h" #include "Item.h"
#include "UpdateData.h" #include "UpdateData.h"
#include "ObjectAccessor.h"
void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
{ {
@ -1300,7 +1299,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
_player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true); _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true);
bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();// current socketbonus state bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();// current socketbonus state
if(SocketBonusActivated ^ SocketBonusToBeActivated) // if there was a change... if(SocketBonusActivated != SocketBonusToBeActivated) // if there was a change...
{ {
_player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT, false); _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT, false);
itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0); itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0);

View file

@ -533,8 +533,8 @@ enum MangosStrings
LANG_GET_UINT_FIELD = 570, LANG_GET_UINT_FIELD = 570,
LANG_GET_FLOAT = 571, //log LANG_GET_FLOAT = 571, //log
LANG_GET_FLOAT_FIELD = 572, LANG_GET_FLOAT_FIELD = 572,
LANG_SET_32BIT = 573, //log // 573, //not used
LANG_SET_32BIT_FIELD = 574, // 574, //not used
LANG_CHANGE_32BIT = 575, //log LANG_CHANGE_32BIT = 575, //log
LANG_CHANGE_32BIT_FIELD = 576, LANG_CHANGE_32BIT_FIELD = 576,

View file

@ -70,7 +70,6 @@ bool ChatHandler::HandleReloadAllCommand(const char*)
HandleReloadReservedNameCommand(""); HandleReloadReservedNameCommand("");
HandleReloadMangosStringCommand(""); HandleReloadMangosStringCommand("");
HandleReloadGameTeleCommand(""); HandleReloadGameTeleCommand("");
HandleReloadBattleEventCommand("");
return true; return true;
} }
@ -4144,30 +4143,6 @@ bool ChatHandler::HandleChangeWeather(const char* args)
return true; return true;
} }
bool ChatHandler::HandleSet32Bit(const char* args)
{
if(!*args)
return false;
char* px = strtok((char*)args, " ");
char* py = strtok(NULL, " ");
if (!px || !py)
return false;
uint32 Opcode = (uint32)atoi(px);
uint32 Value = (uint32)atoi(py);
if (Value > 32) //uint32 = 32 bits
return false;
sLog.outDebug(GetMangosString(LANG_SET_32BIT), Opcode, Value);
m_session->GetPlayer( )->SetUInt32Value( Opcode , 2^Value );
PSendSysMessage(LANG_SET_32BIT_FIELD, Opcode,1);
return true;
}
bool ChatHandler::HandleTeleAddCommand(const char * args) bool ChatHandler::HandleTeleAddCommand(const char * args)
{ {
if(!*args) if(!*args)

View file

@ -218,6 +218,7 @@ BattleGroundMap* MapInstanced::CreateBattleGroundMap(uint32 InstanceId, BattleGr
BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this); BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this);
ASSERT(map->IsBattleGroundOrArena()); ASSERT(map->IsBattleGroundOrArena());
map->SetBG(bg); map->SetBG(bg);
bg->SetBgMap(map);
m_InstancedMaps[InstanceId] = map; m_InstancedMaps[InstanceId] = map;
return map; return map;

View file

@ -372,11 +372,11 @@ void WorldSession::SendSpiritResurrect()
_player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
// or update at original position // or update at original position
else else
ObjectAccessor::UpdateVisibilityForPlayer(_player); _player->UpdateVisibilityForPlayer();
} }
// or update at original position // or update at original position
else else
ObjectAccessor::UpdateVisibilityForPlayer(_player); _player->UpdateVisibilityForPlayer();
_player->SaveToDB(); _player->SaveToDB();
} }

View file

@ -1427,7 +1427,7 @@ void WorldObject::MonsterTextEmote(const char* text, uint64 TargetGuid, bool IsB
{ {
WorldPacket data(SMSG_MESSAGECHAT, 200); WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data,IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE,text,LANG_UNIVERSAL,GetName(),TargetGuid); BuildMonsterChat(&data,IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE,text,LANG_UNIVERSAL,GetName(),TargetGuid);
SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); SendMessageToSetInRange(&data,sWorld.getConfig(IsBossEmote ? CONFIG_LISTEN_RANGE_YELL : CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
} }
void WorldObject::MonsterWhisper(const char* text, uint64 receiver, bool IsBossWhisper) void WorldObject::MonsterWhisper(const char* text, uint64 receiver, bool IsBossWhisper)
@ -1524,7 +1524,7 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),say_do); MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker); TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p); CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(IsBossEmote ? CONFIG_LISTEN_RANGE_YELL : CONFIG_LISTEN_RANGE_TEXTEMOTE));
} }
void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper) void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper)
@ -1849,7 +1849,7 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask; m_phaseMask = newPhaseMask;
if(update && IsInWorld()) if(update && IsInWorld())
ObjectAccessor::UpdateObjectVisibility(this); UpdateObjectVisibility();
} }
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ ) void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1872,3 +1872,12 @@ void WorldObject::PlayDirectSound( uint32 sound_id, Player* target /*= NULL*/ )
else else
SendMessageToSet( &data, true ); SendMessageToSet( &data, true );
} }
void WorldObject::UpdateObjectVisibility()
{
CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY());
Cell cell(p);
GetMap()->UpdateObjectVisibility(this, cell, p);
}

View file

@ -474,6 +474,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
virtual void SaveRespawnTime() {} virtual void SaveRespawnTime() {}
void AddObjectToRemoveList(); void AddObjectToRemoveList();
void UpdateObjectVisibility();
// main visibility check function in normal case (ignore grey zone distance check) // main visibility check function in normal case (ignore grey zone distance check)
bool isVisibleFor(Player const* u, WorldObject const* viewPoint) const { return isVisibleForInState(u,viewPoint,false); } bool isVisibleFor(Player const* u, WorldObject const* viewPoint) const { return isVisibleForInState(u,viewPoint,false); }

View file

@ -442,36 +442,6 @@ ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m)
ObjectAccessor::_buildPacket(iter->getSource(), &i_object, i_updateDatas); ObjectAccessor::_buildPacket(iter->getSource(), &i_object, i_updateDatas);
} }
void
ObjectAccessor::UpdateObjectVisibility(WorldObject *obj)
{
CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
Cell cell(p);
obj->GetMap()->UpdateObjectVisibility(obj, cell, p);
}
void ObjectAccessor::UpdateVisibilityForPlayer( Player* player )
{
WorldObject const* viewPoint = player->GetViewPoint();
Map* m = player->GetMap();
CellPair p(MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()));
Cell cell(p);
m->UpdatePlayerVisibility(player, cell, p);
if (player!=viewPoint)
{
CellPair pView(MaNGOS::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY()));
Cell cellView(pView);
m->UpdateObjectsVisibilityFor(player, cellView, pView);
}
else
m->UpdateObjectsVisibilityFor(player, cell, p);
}
/// Define the static member of HashMapHolder /// Define the static member of HashMapHolder
template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap; template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap;

View file

@ -202,8 +202,6 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
static void UpdateObject(Object* obj, Player* exceptPlayer); static void UpdateObject(Object* obj, Player* exceptPlayer);
static void _buildUpdateObject(Object* obj, UpdateDataMapType &); static void _buildUpdateObject(Object* obj, UpdateDataMapType &);
static void UpdateObjectVisibility(WorldObject* obj);
static void UpdateVisibilityForPlayer(Player* player);
private: private:
struct WorldObjectChangeAccumulator struct WorldObjectChangeAccumulator
{ {

View file

@ -2873,10 +2873,14 @@ void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, Play
void ObjectMgr::LoadGuilds() void ObjectMgr::LoadGuilds()
{ {
Guild *newguild; Guild *newGuild;
uint32 count = 0; uint32 count = 0;
QueryResult *result = CharacterDatabase.Query( "SELECT guildid FROM guild" ); // 0 1 2 3 4 5 6
QueryResult *result = CharacterDatabase.Query("SELECT guild.guildid,guild.name,leaderguid,EmblemStyle,EmblemColor,BorderStyle,BorderColor,"
// 7 8 9 10 11 12
"BackgroundColor,info,motd,createdate,BankMoney,COUNT(guild_bank_tab.guildid) "
"FROM guild LEFT JOIN guild_bank_tab ON guild.guildid = guild_bank_tab.guildid GROUP BY guild.guildid ORDER BY guildid ASC");
if( !result ) if( !result )
{ {
@ -2890,27 +2894,54 @@ void ObjectMgr::LoadGuilds()
return; return;
} }
// load guild ranks
// 0 1 2 3 4
QueryResult *guildRanksResult = CharacterDatabase.Query("SELECT guildid,rid,rname,rights,BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC");
// load guild members
// 0 1 2 3 4 5 6
QueryResult *guildMembersResult = CharacterDatabase.Query("SELECT guildid,guild_member.guid,rank,pnote,offnote,BankResetTimeMoney,BankRemMoney,"
// 7 8 9 10 11 12
"BankResetTimeTab0,BankRemSlotsTab0,BankResetTimeTab1,BankRemSlotsTab1,BankResetTimeTab2,BankRemSlotsTab2,"
// 13 14 15 16 17 18
"BankResetTimeTab3,BankRemSlotsTab3,BankResetTimeTab4,BankRemSlotsTab4,BankResetTimeTab5,BankRemSlotsTab5,"
// 19 20 21 22 23
"characters.name, characters.level, characters.class, characters.zone, characters.logout_time "
"FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid ORDER BY guildid ASC");
// load guild bank tab rights
// 0 1 2 3 4
QueryResult *guildBankTabRightsResult = CharacterDatabase.Query("SELECT guildid,TabId,rid,gbright,SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC");
barGoLink bar( result->GetRowCount() ); barGoLink bar( result->GetRowCount() );
do do
{ {
Field *fields = result->Fetch(); //Field *fields = result->Fetch();
bar.step(); bar.step();
++count; ++count;
newguild = new Guild; newGuild = new Guild;
if(!newguild->LoadGuildFromDB(fields[0].GetUInt32())) if (!newGuild->LoadGuildFromDB(result) ||
!newGuild->LoadRanksFromDB(guildRanksResult) ||
!newGuild->LoadMembersFromDB(guildMembersResult) ||
!newGuild->LoadBankRightsFromDB(guildBankTabRightsResult) ||
!newGuild->CheckGuildStructure()
)
{ {
newguild->Disband(); newGuild->Disband();
delete newguild; delete newGuild;
continue; continue;
} }
AddGuild(newguild); AddGuild(newGuild);
}while( result->NextRow() ); }while( result->NextRow() );
delete result; delete result;
delete guildRanksResult;
delete guildMembersResult;
delete guildBankTabRightsResult;
//delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table //delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table
//you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT //you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT
@ -2925,7 +2956,11 @@ void ObjectMgr::LoadArenaTeams()
{ {
uint32 count = 0; uint32 count = 0;
QueryResult *result = CharacterDatabase.Query( "SELECT arenateamid FROM arena_team" ); // 0 1 2 3 4 5
QueryResult *result = CharacterDatabase.Query( "SELECT arena_team.arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,"
// 6 7 8 9 10 11 12 13 14
"EmblemColor,BorderStyle,BorderColor, rating,games,wins,played,wins2,rank "
"FROM arena_team LEFT JOIN arena_team_stats ON arena_team.arenateamid = arena_team_stats.arenateamid ORDER BY arena_team.arenateamid ASC" );
if( !result ) if( !result )
{ {
@ -2939,6 +2974,12 @@ void ObjectMgr::LoadArenaTeams()
return; return;
} }
// load arena_team members
QueryResult *arenaTeamMembersResult = CharacterDatabase.Query(
// 0 1 2 3 4 5 6 7 8
"SELECT arenateamid,member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class "
"FROM arena_team_member member LEFT JOIN characters chars on member.guid = chars.guid ORDER BY member.arenateamid ASC");
barGoLink bar( result->GetRowCount() ); barGoLink bar( result->GetRowCount() );
do do
@ -2948,16 +2989,19 @@ void ObjectMgr::LoadArenaTeams()
bar.step(); bar.step();
++count; ++count;
ArenaTeam *newarenateam = new ArenaTeam; ArenaTeam *newArenaTeam = new ArenaTeam;
if(!newarenateam->LoadArenaTeamFromDB(fields[0].GetUInt32())) if (!newArenaTeam->LoadArenaTeamFromDB(result) ||
!newArenaTeam->LoadMembersFromDB(arenaTeamMembersResult))
{ {
delete newarenateam; newArenaTeam->Disband(NULL);
delete newArenaTeam;
continue; continue;
} }
AddArenaTeam(newarenateam); AddArenaTeam(newArenaTeam);
}while( result->NextRow() ); }while( result->NextRow() );
delete result; delete result;
delete arenaTeamMembersResult;
sLog.outString(); sLog.outString();
sLog.outString( ">> Loaded %u arenateam definitions", count ); sLog.outString( ">> Loaded %u arenateam definitions", count );

View file

@ -2239,7 +2239,7 @@ void Player::SetGameMaster(bool on)
getHostilRefManager().setOnlineOfflineState(true); getHostilRefManager().setOnlineOfflineState(true);
} }
ObjectAccessor::UpdateVisibilityForPlayer(this); UpdateVisibilityForPlayer();
} }
void Player::SetGMVisible(bool on) void Player::SetGMVisible(bool on)
@ -4152,7 +4152,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
UpdateZone(newzone,newarea); UpdateZone(newzone,newarea);
// update visibility // update visibility
ObjectAccessor::UpdateVisibilityForPlayer(this); UpdateVisibilityForPlayer();
if(!applySickness) if(!applySickness)
return; return;
@ -4205,7 +4205,7 @@ void Player::KillPlayer()
// don't create corpse at this moment, player might be falling // don't create corpse at this moment, player might be falling
// update visibility // update visibility
ObjectAccessor::UpdateObjectVisibility(this); UpdateObjectVisibility();
} }
void Player::CreateCorpse() void Player::CreateCorpse()
@ -10122,10 +10122,42 @@ uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const
if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0) if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0)
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
if (pItem->GetSkill() != 0) if (uint32 item_use_skill = pItem->GetSkill())
{ {
if (GetSkillValue( pItem->GetSkill() ) == 0) if (GetSkillValue(item_use_skill) == 0)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; {
// armor items with scaling stats can downgrade armor skill reqs if related class can learn armor use at some level
if (pProto->Class != ITEM_CLASS_ARMOR)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
ScalingStatDistributionEntry const *ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : NULL;
if (!ssd)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
bool allowScaleSkill = false;
for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); ++i)
{
SkillLineAbilityEntry const *skillInfo = sSkillLineAbilityStore.LookupEntry(i);
if (!skillInfo)
continue;
if (skillInfo->skillId != item_use_skill)
continue;
// can't learn
if (skillInfo->classmask && (skillInfo->classmask & getClassMask()) == 0)
continue;
if (skillInfo->racemask && (skillInfo->racemask & getRaceMask()) == 0)
continue;
allowScaleSkill = true;
break;
}
if (!allowScaleSkill)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
}
} }
if (pProto->RequiredSkill != 0) if (pProto->RequiredSkill != 0)
@ -15136,7 +15168,7 @@ void Player::_LoadQuestStatus(QueryResult *result)
((questStatusData.m_status == QUEST_STATUS_INCOMPLETE || ((questStatusData.m_status == QUEST_STATUS_INCOMPLETE ||
questStatusData.m_status == QUEST_STATUS_COMPLETE || questStatusData.m_status == QUEST_STATUS_COMPLETE ||
questStatusData.m_status == QUEST_STATUS_FAILED) && questStatusData.m_status == QUEST_STATUS_FAILED) &&
(!questStatusData.m_rewarded || pQuest->IsDaily()))) (!questStatusData.m_rewarded || pQuest->IsRepeatable())))
{ {
SetQuestSlot(slot, quest_id, quest_time); SetQuestSlot(slot, quest_id, quest_time);
@ -17759,7 +17791,7 @@ void Player::CorrectMetaGemEnchants(uint8 exceptslot, bool apply)
//was enchant active with/without item? //was enchant active with/without item?
bool wasactive = EnchantmentFitsRequirements(condition, apply ? exceptslot : -1); bool wasactive = EnchantmentFitsRequirements(condition, apply ? exceptslot : -1);
//should it now be? //should it now be?
if(wasactive ^ EnchantmentFitsRequirements(condition, apply ? -1 : exceptslot)) if(wasactive != EnchantmentFitsRequirements(condition, apply ? -1 : exceptslot))
{ {
// ignore item gem conditions // ignore item gem conditions
//if state changed, (dis)apply enchant //if state changed, (dis)apply enchant
@ -20646,7 +20678,28 @@ void Player::SetFarSightGUID( uint64 guid )
SetUInt64Value(PLAYER_FARSIGHT, guid); SetUInt64Value(PLAYER_FARSIGHT, guid);
// need triggering load grids around new view point // need triggering load grids around new view point
ObjectAccessor::UpdateVisibilityForPlayer(this); UpdateVisibilityForPlayer();
}
void Player::UpdateVisibilityForPlayer()
{
WorldObject const* viewPoint = GetViewPoint();
Map* m = GetMap();
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
m->UpdatePlayerVisibility(this, cell, p);
if (this != viewPoint)
{
CellPair pView(MaNGOS::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY()));
Cell cellView(pView);
m->UpdateObjectsVisibilityFor(this, cellView, pView);
}
else
m->UpdateObjectsVisibilityFor(this, cell, p);
} }
void Player::SendDuelCountdown(uint32 counter) void Player::SendDuelCountdown(uint32 counter)

View file

@ -1045,6 +1045,8 @@ class MANGOS_DLL_SPEC Player : public Unit
bool CanInteractWithNPCs(bool alive = true) const; bool CanInteractWithNPCs(bool alive = true) const;
GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const; GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const;
void UpdateVisibilityForPlayer();
bool ToggleAFK(); bool ToggleAFK();
bool ToggleDND(); bool ToggleDND();
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); } bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); }

View file

@ -1033,6 +1033,7 @@ enum Targets
TARGET_ALL_PARTY = 33, TARGET_ALL_PARTY = 33,
TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility
TARGET_SINGLE_PARTY = 35, TARGET_SINGLE_PARTY = 35,
TARGET_ALL_HOSTILE_UNITS_AROUND_CASTER = 36,
TARGET_AREAEFFECT_PARTY = 37, TARGET_AREAEFFECT_PARTY = 37,
TARGET_SCRIPT = 38, TARGET_SCRIPT = 38,
TARGET_SELF_FISHING = 39, TARGET_SELF_FISHING = 39,

View file

@ -23,7 +23,6 @@
#include "Player.h" #include "Player.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSession.h" #include "WorldSession.h"
#include "ObjectAccessor.h"
#include "UpdateMask.h" #include "UpdateMask.h"
void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )

View file

@ -1220,7 +1220,8 @@ bool Spell::IsAliveUnitPresentInTargetList()
{ {
Unit *unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); Unit *unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
if (unit && (unit->isAlive() ^ IsDeathOnlySpell(m_spellInfo))) // either unit is alive and normal spell, or unit dead and deathonly-spell
if (unit && (unit->isAlive() != IsDeathOnlySpell(m_spellInfo)))
needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target
} }
} }
@ -1359,9 +1360,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
case TARGET_RANDOM_CIRCUMFERENCE_POINT: case TARGET_RANDOM_CIRCUMFERENCE_POINT:
{ {
float angle = 2.0 * M_PI * rand_norm(); float angle = 2.0 * M_PI * rand_norm();
float dest_x = m_caster->GetPositionX() + cos(angle) * radius; float dest_x, dest_y, dest_z;
float dest_y = m_caster->GetPositionY() + sin(angle) * radius; m_caster->GetClosePoint(dest_x, dest_y, dest_z, 0.0f, radius, angle);
float dest_z = m_caster->GetMap()->GetHeight(dest_x, dest_y, MAX_HEIGHT);
m_targets.setDestination(dest_x, dest_y, dest_z); m_targets.setDestination(dest_x, dest_y, dest_z);
TagUnitMap.push_back(m_caster); TagUnitMap.push_back(m_caster);
@ -1371,9 +1371,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
{ {
radius *= sqrt(rand_norm()); // Get a random point in circle. Use sqrt(rand) to correct distribution when converting polar to Cartesian coordinates. 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 angle = 2.0 * M_PI * rand_norm();
float dest_x = m_targets.m_destX + cos(angle) * radius; float dest_x, dest_y, dest_z;
float dest_y = m_targets.m_destY + sin(angle) * radius; m_caster->GetClosePoint(dest_x, dest_y, dest_z, 0.0f, radius, angle);
float dest_z = m_caster->GetMap()->GetHeight(dest_x, dest_y, MAX_HEIGHT);
m_targets.setDestination(dest_x, dest_y, dest_z); m_targets.setDestination(dest_x, dest_y, dest_z);
if (radius > 0.0f) if (radius > 0.0f)
@ -1700,13 +1699,24 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
break; break;
} }
case TARGET_ALL_HOSTILE_UNITS_AROUND_CASTER:
FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_HOSTILE);
break;
case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
// special target order switch (m_spellInfo->Id)
if (m_spellInfo->Id==64904) // Hymn of Hope {
// target amount stored in parent spell dummy effect but hard for access case 64844: // Divine Hymn
FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 3, true, false, false); // target amount stored in parent spell dummy effect but hard to access
else FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 3, true, false, false);
FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); break;
case 64904: // Hymn of Hope
// target amount stored in parent spell dummy effect but hard to access
FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 3, true, false, false);
break;
default:
FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY);
break;
}
break; break;
case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
// Wild Growth // Wild Growth

View file

@ -3922,7 +3922,7 @@ void Aura::HandleInvisibilityDetect(bool apply, bool Real)
m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
} }
if(Real && m_target->GetTypeId()==TYPEID_PLAYER) if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target); ((Player*)m_target)->UpdateVisibilityForPlayer();
} }
void Aura::HandleAuraModRoot(bool apply, bool Real) void Aura::HandleAuraModRoot(bool apply, bool Real)
@ -6271,7 +6271,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
void Aura::PeriodicTick() void Aura::PeriodicTick()
{ {
if (!m_target->isAlive() ^ IsDeathOnlySpell(GetSpellProto())) if (!m_target->isAlive() != IsDeathOnlySpell(GetSpellProto()))
return; return;
switch(m_modifier.m_auraname) switch(m_modifier.m_auraname)
@ -6771,229 +6771,243 @@ void Aura::PeriodicTick()
void Aura::PeriodicDummyTick() void Aura::PeriodicDummyTick()
{ {
Unit *caster = GetCaster();
SpellEntry const* spell = GetSpellProto(); SpellEntry const* spell = GetSpellProto();
switch (spell->SpellFamilyName) switch (spell->SpellFamilyName)
{ {
case SPELLFAMILY_GENERIC: case SPELLFAMILY_GENERIC:
switch (spell->Id) switch (spell->Id)
{
// Drink
case 430:
case 431:
case 432:
case 1133:
case 1135:
case 1137:
case 10250:
case 22734:
case 27089:
case 34291:
case 43182:
case 43183:
case 43706:
case 46755:
case 49472: // Drink Coffee
case 57073:
case 61830:
{ {
if (m_target->GetTypeId() != TYPEID_PLAYER) // Drink
return; case 430:
// Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus case 431:
Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); case 432:
for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) case 1133:
case 1135:
case 1137:
case 10250:
case 22734:
case 27089:
case 34291:
case 43182:
case 43183:
case 43706:
case 46755:
case 49472: // Drink Coffee
case 57073:
case 61830:
{ {
if ((*i)->GetId() == GetId()) if (m_target->GetTypeId() != TYPEID_PLAYER)
{
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
((Player*)m_target)->UpdateManaRegen();
// Disable continue
m_isPeriodic = false;
return; return;
// Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
{
if ((*i)->GetId() == GetId())
{
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
((Player*)m_target)->UpdateManaRegen();
// Disable continue
m_isPeriodic = false;
return;
}
}
return;
}
// Forsaken Skills
case 7054:
{
// Possibly need cast one of them (but
// 7038 Forsaken Skill: Swords
// 7039 Forsaken Skill: Axes
// 7040 Forsaken Skill: Daggers
// 7041 Forsaken Skill: Maces
// 7042 Forsaken Skill: Staves
// 7043 Forsaken Skill: Bows
// 7044 Forsaken Skill: Guns
// 7045 Forsaken Skill: 2H Axes
// 7046 Forsaken Skill: 2H Maces
// 7047 Forsaken Skill: 2H Swords
// 7048 Forsaken Skill: Defense
// 7049 Forsaken Skill: Fire
// 7050 Forsaken Skill: Frost
// 7051 Forsaken Skill: Holy
// 7053 Forsaken Skill: Shadow
return;
}
// // Panda
// case 19230: break;
// // Gossip NPC Periodic - Talk
// case 33208: break;
// // Gossip NPC Periodic - Despawn
// case 33209: break;
// // Steal Weapon
// case 36207: break;
// // Simon Game START timer, (DND)
// case 39993: break;
// // Knockdown Fel Cannon: break; The Aggro Burst
// case 40119: break;
// // Old Mount Spell
// case 40154: break;
// // Magnetic Pull
// case 40581: break;
// // Ethereal Ring: break; The Bolt Burst
// case 40801: break;
// // Crystal Prison
// case 40846: break;
// // Copy Weapon
// case 41054: break;
// // Dementia
// case 41404: break;
// // Ethereal Ring Visual, Lightning Aura
// case 41477: break;
// // Ethereal Ring Visual, Lightning Aura (Fork)
// case 41525: break;
// // Ethereal Ring Visual, Lightning Jumper Aura
// case 41567: break;
// // No Man's Land
// case 41955: break;
// // Headless Horseman - Fire
// case 42074: break;
// // Headless Horseman - Visual - Large Fire
// case 42075: break;
// // Headless Horseman - Start Fire, Periodic Aura
// case 42140: break;
// // Ram Speed Boost
// case 42152: break;
// // Headless Horseman - Fires Out Victory Aura
// case 42235: break;
// // Pumpkin Life Cycle
// case 42280: break;
// // Brewfest Request Chick Chuck Mug Aura
// case 42537: break;
// // Squashling
// case 42596: break;
// // Headless Horseman Climax, Head: Periodic
// case 42603: break;
// // Fire Bomb
// case 42621: break;
// // Headless Horseman - Conflagrate, Periodic Aura
// case 42637: break;
// // Headless Horseman - Create Pumpkin Treats Aura
// case 42774: break;
// // Headless Horseman Climax - Summoning Rhyme Aura
// case 42879: break;
// // Tricky Treat
// case 42919: break;
// // Giddyup!
// case 42924: break;
// // Ram - Trot
// case 42992: break;
// // Ram - Canter
// case 42993: break;
// // Ram - Gallop
// case 42994: break;
// // Ram Level - Neutral
// case 43310: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
// case 43884: break;
// // Wretched!
// case 43963: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
// case 44000: break;
// // Energy Feedback
// case 44328: break;
// // Romantic Picnic
// case 45102: break;
// // Romantic Picnic
// case 45123: break;
// // Looking for Love
// case 45124: break;
// // Kite - Lightning Strike Kite Aura
// case 45197: break;
// // Rocket Chicken
// case 45202: break;
// // Copy Offhand Weapon
// case 45205: break;
// // Upper Deck - Kite - Lightning Periodic Aura
// case 45207: break;
// // Kite -Sky Lightning Strike Kite Aura
// case 45251: break;
// // Ribbon Pole Dancer Check Aura
// case 45390: break;
// // Holiday - Midsummer, Ribbon Pole Periodic Visual
// case 45406: break;
// // Parachute
// case 45472: break;
// // Alliance Flag, Extra Damage Debuff
// case 45898: break;
// // Horde Flag, Extra Damage Debuff
// case 45899: break;
// // Ahune - Summoning Rhyme Aura
// case 45926: break;
// // Ahune - Slippery Floor
// case 45945: break;
// // Ahune's Shield
// case 45954: break;
// // Nether Vapor Lightning
// case 45960: break;
// // Darkness
// case 45996: break;
// // Summon Blood Elves Periodic
// case 46041: break;
// // Transform Visual Missile Periodic
// case 46205: break;
// // Find Opening Beam End
// case 46333: break;
// // Ice Spear Control Aura
// case 46371: break;
// // Hailstone Chill
// case 46458: break;
// // Hailstone Chill, Internal
// case 46465: break;
// // Chill, Internal Shifter
// case 46549: break;
// // Summon Ice Spear Knockback Delayer
// case 46878: break;
// // Burninate Effect
// case 47214: break;
// // Fizzcrank Practice Parachute
// case 47228: break;
// // Send Mug Control Aura
// case 47369: break;
// // Direbrew's Disarm (precast)
// case 47407: break;
// // Mole Machine Port Schedule
// case 47489: break;
// case 47941: break; // Crystal Spike
// case 48200: break; // Healer Aura
// case 48630: break; // Summon Gauntlet Mobs Periodic
// case 49313: break; // Proximity Mine Area Aura
// // Mole Machine Portal Schedule
// case 49466: break;
// case 49555: break; // Corpse Explode
// case 49592: break; // Temporal Rift
// case 49957: break; // Cutting Laser
// case 50085: break; // Slow Fall
// // Listening to Music
// case 50493: break;
// // Love Rocket Barrage
// case 50530: break;
// Exist more after, need add later
default:
break;
}
// Prey on the Weak
if (spell->SpellIconID == 2983)
{
Unit *target=m_target->getVictim();
if (target && (m_target->GetHealth() * 100 / m_target->GetMaxHealth() > target->GetHealth() * 100 / target->GetMaxHealth()))
{
if(!m_target->HasAura(58670))
{
int32 basepoints = GetBasePoints();
m_target->CastCustomSpell(m_target, 58670, &basepoints, 0, 0, true);
} }
} }
return; else
m_target->RemoveAurasDueToSpell(58670);
} }
// Forsaken Skills break;
case 7054:
{
// Possibly need cast one of them (but
// 7038 Forsaken Skill: Swords
// 7039 Forsaken Skill: Axes
// 7040 Forsaken Skill: Daggers
// 7041 Forsaken Skill: Maces
// 7042 Forsaken Skill: Staves
// 7043 Forsaken Skill: Bows
// 7044 Forsaken Skill: Guns
// 7045 Forsaken Skill: 2H Axes
// 7046 Forsaken Skill: 2H Maces
// 7047 Forsaken Skill: 2H Swords
// 7048 Forsaken Skill: Defense
// 7049 Forsaken Skill: Fire
// 7050 Forsaken Skill: Frost
// 7051 Forsaken Skill: Holy
// 7053 Forsaken Skill: Shadow
return;
}
// // Panda
// case 19230: break;
// // Gossip NPC Periodic - Talk
// case 33208: break;
// // Gossip NPC Periodic - Despawn
// case 33209: break;
// // Steal Weapon
// case 36207: break;
// // Simon Game START timer, (DND)
// case 39993: break;
// // Knockdown Fel Cannon: break; The Aggro Burst
// case 40119: break;
// // Old Mount Spell
// case 40154: break;
// // Magnetic Pull
// case 40581: break;
// // Ethereal Ring: break; The Bolt Burst
// case 40801: break;
// // Crystal Prison
// case 40846: break;
// // Copy Weapon
// case 41054: break;
// // Dementia
// case 41404: break;
// // Ethereal Ring Visual, Lightning Aura
// case 41477: break;
// // Ethereal Ring Visual, Lightning Aura (Fork)
// case 41525: break;
// // Ethereal Ring Visual, Lightning Jumper Aura
// case 41567: break;
// // No Man's Land
// case 41955: break;
// // Headless Horseman - Fire
// case 42074: break;
// // Headless Horseman - Visual - Large Fire
// case 42075: break;
// // Headless Horseman - Start Fire, Periodic Aura
// case 42140: break;
// // Ram Speed Boost
// case 42152: break;
// // Headless Horseman - Fires Out Victory Aura
// case 42235: break;
// // Pumpkin Life Cycle
// case 42280: break;
// // Brewfest Request Chick Chuck Mug Aura
// case 42537: break;
// // Squashling
// case 42596: break;
// // Headless Horseman Climax, Head: Periodic
// case 42603: break;
// // Fire Bomb
// case 42621: break;
// // Headless Horseman - Conflagrate, Periodic Aura
// case 42637: break;
// // Headless Horseman - Create Pumpkin Treats Aura
// case 42774: break;
// // Headless Horseman Climax - Summoning Rhyme Aura
// case 42879: break;
// // Tricky Treat
// case 42919: break;
// // Giddyup!
// case 42924: break;
// // Ram - Trot
// case 42992: break;
// // Ram - Canter
// case 42993: break;
// // Ram - Gallop
// case 42994: break;
// // Ram Level - Neutral
// case 43310: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
// case 43884: break;
// // Wretched!
// case 43963: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
// case 44000: break;
// // Energy Feedback
// case 44328: break;
// // Romantic Picnic
// case 45102: break;
// // Romantic Picnic
// case 45123: break;
// // Looking for Love
// case 45124: break;
// // Kite - Lightning Strike Kite Aura
// case 45197: break;
// // Rocket Chicken
// case 45202: break;
// // Copy Offhand Weapon
// case 45205: break;
// // Upper Deck - Kite - Lightning Periodic Aura
// case 45207: break;
// // Kite -Sky Lightning Strike Kite Aura
// case 45251: break;
// // Ribbon Pole Dancer Check Aura
// case 45390: break;
// // Holiday - Midsummer, Ribbon Pole Periodic Visual
// case 45406: break;
// // Parachute
// case 45472: break;
// // Alliance Flag, Extra Damage Debuff
// case 45898: break;
// // Horde Flag, Extra Damage Debuff
// case 45899: break;
// // Ahune - Summoning Rhyme Aura
// case 45926: break;
// // Ahune - Slippery Floor
// case 45945: break;
// // Ahune's Shield
// case 45954: break;
// // Nether Vapor Lightning
// case 45960: break;
// // Darkness
// case 45996: break;
// // Summon Blood Elves Periodic
// case 46041: break;
// // Transform Visual Missile Periodic
// case 46205: break;
// // Find Opening Beam End
// case 46333: break;
// // Ice Spear Control Aura
// case 46371: break;
// // Hailstone Chill
// case 46458: break;
// // Hailstone Chill, Internal
// case 46465: break;
// // Chill, Internal Shifter
// case 46549: break;
// // Summon Ice Spear Knockback Delayer
// case 46878: break;
// // Burninate Effect
// case 47214: break;
// // Fizzcrank Practice Parachute
// case 47228: break;
// // Send Mug Control Aura
// case 47369: break;
// // Direbrew's Disarm (precast)
// case 47407: break;
// // Mole Machine Port Schedule
// case 47489: break;
// case 47941: break; // Crystal Spike
// case 48200: break; // Healer Aura
// case 48630: break; // Summon Gauntlet Mobs Periodic
// case 49313: break; // Proximity Mine Area Aura
// // Mole Machine Portal Schedule
// case 49466: break;
// case 49555: break; // Corpse Explode
// case 49592: break; // Temporal Rift
// case 49957: break; // Cutting Laser
// case 50085: break; // Slow Fall
// // Listening to Music
// case 50493: break;
// // Love Rocket Barrage
// case 50530: break;
// Exist more after, need add later
default:
break;
}
break;
case SPELLFAMILY_MAGE: case SPELLFAMILY_MAGE:
{ {
// Mirror Image // Mirror Image
@ -7035,27 +7049,31 @@ void Aura::PeriodicDummyTick()
{ {
switch (spell->Id) switch (spell->Id)
{ {
// Killing Spree
case 51690: case 51690:
{ {
if (m_target->hasUnitState(UNIT_STAT_STUNNED) || m_target->HasAuraType(SPELL_AURA_MOD_FEAR))
return;
std::list<Unit*> targets; std::list<Unit*> targets;
{ {
// eff_radius ==0 // eff_radius ==0
float radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spell->rangeIndex)); float radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spell->rangeIndex));
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(),caster->GetPositionY())); CellPair p(MaNGOS::ComputeCellPair(m_target->GetPositionX(),m_target->GetPositionY()));
Cell cell(p); Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT; cell.data.Part.reserved = ALL_DISTRICT;
MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius); MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(m_target, m_target, radius);
MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster,targets, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(m_target, targets, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p); CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap(), *caster, radius); cell_lock->Visit(cell_lock, grid_object_checker, *m_target->GetMap(), *m_target, radius);
cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap(), *caster, radius); cell_lock->Visit(cell_lock, world_object_checker, *m_target->GetMap(), *m_target, radius);
} }
if(targets.empty()) if(targets.empty())
@ -7065,18 +7083,12 @@ void Aura::PeriodicDummyTick()
std::advance(itr, rand()%targets.size()); std::advance(itr, rand()%targets.size());
Unit* target = *itr; Unit* target = *itr;
caster->CastSpell(target, 57840, true); m_target->CastSpell(target, 57840, true);
caster->CastSpell(target, 57841, true); m_target->CastSpell(target, 57841, true);
return; return;
} }
// Master of Subtlety default:
// case 31666: break; break;
// Killing Spree
// case 51690: break;
// Overkill
// case 58428: break;
// default:
// break;
} }
break; break;
} }
@ -7125,7 +7137,7 @@ void Aura::PeriodicDummyTick()
// Death and Decay // Death and Decay
if (spell->SpellFamilyFlags & UI64LIT(0x0000000000000020)) if (spell->SpellFamilyFlags & UI64LIT(0x0000000000000020))
{ {
if (caster) if (Unit *caster = GetCaster())
caster->CastCustomSpell(m_target, 52212, &m_modifier.m_amount, NULL, NULL, true, NULL, this); caster->CastCustomSpell(m_target, 52212, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
return; return;
} }
@ -7412,6 +7424,17 @@ void Aura::HandleModTargetArmorPct(bool apply, bool Real)
void Aura::HandleAuraModAllCritChance(bool apply, bool Real) void Aura::HandleAuraModAllCritChance(bool apply, bool Real)
{ {
this->HandleAuraModCritPercent(apply, Real); // spells required only Real aura add/remove
this->HandleModSpellCritChance(apply, Real); if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
// included in Player::UpdateSpellCritChance calculation
((Player*)m_target)->UpdateAllSpellCritChances();
} }

View file

@ -2809,7 +2809,7 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
// - with greater than 15 min CD // - with greater than 15 min CD
if ((spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) || if ((spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) ||
(GetSpellRecoveryTime(spellInfo) > 15 * MINUTE * IN_MILISECONDS && !(spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA))) (GetSpellRecoveryTime(spellInfo) > 15 * MINUTE * IN_MILISECONDS && !(spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA)))
if (!player || !player->InArena()) if (player && player->InArena())
return SPELL_FAILED_NOT_IN_ARENA; return SPELL_FAILED_NOT_IN_ARENA;
// Spell casted only on battleground // Spell casted only on battleground

View file

@ -4067,9 +4067,9 @@ void Unit::RemoveArenaAuras(bool onleave)
for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
{ {
if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras
&& !iter->second->IsPassive() // don't remove passive auras && !iter->second->IsPassive() // don't remove passive auras
&& (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable)
&& (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave && (iter->second->IsPositive() != onleave)) // remove positive buffs on enter, negative buffs on leave
RemoveAura(iter); RemoveAura(iter);
else else
++iter; ++iter;
@ -5266,9 +5266,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
} }
switch(dummySpell->Id) switch(dummySpell->Id)
{ {
// Nightfall // Nightfall & Glyph of Corruption
case 18094: case 18094:
case 18095: case 18095:
case 56218:
{ {
target = this; target = this;
triggered_spell_id = 17941; triggered_spell_id = 17941;
@ -9428,7 +9429,7 @@ bool Unit::isTargetableForAttack(bool inverseAlive /*=false*/) const
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))
return false; return false;
if (!(isAlive() ^ inverseAlive)) if (!(isAlive() != inverseAlive))
return false; return false;
return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;

View file

@ -32,7 +32,6 @@
#include "Group.h" #include "Group.h"
#include "Guild.h" #include "Guild.h"
#include "World.h" #include "World.h"
#include "ObjectAccessor.h"
#include "BattleGroundMgr.h" #include "BattleGroundMgr.h"
#include "MapManager.h" #include "MapManager.h"
#include "SocialMgr.h" #include "SocialMgr.h"

View file

@ -25,7 +25,6 @@
#include "World.h" #include "World.h"
#include "WorldRunnable.h" #include "WorldRunnable.h"
#include "Timer.h" #include "Timer.h"
#include "ObjectAccessor.h"
#include "MapManager.h" #include "MapManager.h"
#include "BattleGroundMgr.h" #include "BattleGroundMgr.h"

View file

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

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8505_01_characters_character_spell" #define REVISION_DB_CHARACTERS "required_8505_01_characters_character_spell"
#define REVISION_DB_MANGOS "required_8521_01_mangos_spell_proc_event" #define REVISION_DB_MANGOS "required_8573_01_mangos_mangos_string"
#define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__

View file

@ -177,13 +177,16 @@ Global
{803F488E-4C5A-4866-8D5C-1E6C03C007C2}.Release|x64.Build.0 = Release|Win32 {803F488E-4C5A-4866-8D5C-1E6C03C007C2}.Release|x64.Build.0 = Release|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|x64.ActiveCfg = Debug_NoPCH|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|x64.ActiveCfg = Debug_NoPCH|x64
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug_NoPCH|x64.Build.0 = Debug_NoPCH|x64
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|Win32.ActiveCfg = Debug|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|Win32.ActiveCfg = Debug|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|Win32.Build.0 = Debug|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|Win32.Build.0 = Debug|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|x64.ActiveCfg = Debug|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|x64.ActiveCfg = Debug|x64
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Debug|x64.Build.0 = Debug|x64
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|Win32.ActiveCfg = Release|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|Win32.ActiveCfg = Release|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|Win32.Build.0 = Release|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|Win32.Build.0 = Release|Win32
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|x64.ActiveCfg = Release|Win32 {AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|x64.ActiveCfg = Release|x64
{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE