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() );
if(!local)
{

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_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';
--
@ -178,6 +178,87 @@ LOCK TABLES `areatrigger_teleport` WRITE;
/*!40000 ALTER TABLE `areatrigger_teleport` ENABLE KEYS */;
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`
--
@ -583,6 +664,27 @@ LOCK TABLES `creature_addon` WRITE;
/*!40000 ALTER TABLE `creature_addon` ENABLE KEYS */;
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`
--
@ -1422,6 +1524,27 @@ LOCK TABLES `gameobject` WRITE;
/*!40000 ALTER TABLE `gameobject` ENABLE KEYS */;
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`
--
@ -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),
(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),
(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),
(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),

View file

@ -89,4 +89,4 @@ INSERT INTO battleground_events (map, event1, event2, description) VALUES
(@RL_MAP, 254, 0, 'doors'),
(@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_02_mangos_gameobject_battleground.sql \
8549_03_mangos_battleground_events.sql \
8573_01_mangos_mangos_string.sql \
README
## Additional files to include when running 'make dist'
@ -212,4 +213,5 @@ EXTRA_DIST = \
8548_01_mangos_creature_battleground.sql \
8548_02_mangos_gameobject_battleground.sql \
8549_03_mangos_battleground_events.sql \
8573_01_mangos_mangos_string.sql \
README

View file

@ -161,14 +161,12 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
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(!result)
if(!arenaTeamDataResult)
return false;
Field *fields = result->Fetch();
Field *fields = arenaTeamDataResult->Fetch();
m_TeamId = fields[0].GetUInt32();
m_Name = fields[1].GetCppString();
@ -179,72 +177,74 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
m_EmblemColor = fields[6].GetUInt32();
m_BorderStyle = fields[7].GetUInt32();
m_BorderColor = fields[8].GetUInt32();
delete result;
// only load here, so additional checks can be made
LoadStatsFromDB(ArenaTeamId);
LoadMembersFromDB(ArenaTeamId);
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;
}
//load team stats
m_stats.rating = fields[9].GetUInt32();
m_stats.games_week = fields[10].GetUInt32();
m_stats.wins_week = fields[11].GetUInt32();
m_stats.games_season = fields[12].GetUInt32();
m_stats.wins_season = fields[13].GetUInt32();
m_stats.rank = fields[14].GetUInt32();
return true;
}
void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId)
bool ArenaTeam::LoadMembersFromDB(QueryResult *arenaTeamMembersResult)
{
// 0 1 2 3 4 5
QueryResult *result = CharacterDatabase.PQuery("SELECT rating,games,wins,played,wins2,rank FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId);
if(!arenaTeamMembersResult)
return false;
if(!result)
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;
bool captainPresentInTeam = false;
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;
newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
newmember.games_week = fields[1].GetUInt32();
newmember.wins_week = fields[2].GetUInt32();
newmember.games_season = fields[3].GetUInt32();
newmember.wins_season = fields[4].GetUInt32();
newmember.personal_rating = fields[5].GetUInt32();
newmember.name = fields[6].GetCppString();
newmember.Class = fields[7].GetUInt8();
newmember.guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
newmember.games_week = fields[2].GetUInt32();
newmember.wins_week = fields[3].GetUInt32();
newmember.games_season = fields[4].GetUInt32();
newmember.wins_season = fields[5].GetUInt32();
newmember.personal_rating = fields[6].GetUInt32();
newmember.name = fields[7].GetCppString();
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);
}while( result->NextRow() );
delete result;
}while (arenaTeamMembersResult->NextRow());
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)
@ -291,9 +291,12 @@ void ArenaTeam::DelMember(uint64 guid)
void ArenaTeam::Disband(WorldSession *session)
{
// event
if (session)
{
WorldPacket data;
session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), "");
BroadcastPacket(&data);
}
while (!m_members.empty())
{

View file

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

View file

@ -152,6 +152,7 @@ BattleGround::BattleGround()
m_MinPlayers = 0;
m_MapId = 0;
m_Map = NULL;
m_TeamStartLocX[BG_TEAM_ALLIANCE] = 0;
m_TeamStartLocX[BG_TEAM_HORDE] = 0;
@ -214,10 +215,12 @@ BattleGround::~BattleGround()
}
sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID());
// unload map
if (Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
if (map->IsBattleGroundOrArena())
((BattleGroundMap*)map)->SetUnload();
// map can be null at bg destruction
if (m_Map)
m_Map->SetUnload();
// remove from bg free slot queue
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)
{
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
// 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
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))
{
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
void BattleGround::DoorClose(uint64 const& guid)
{
GameObject *obj = HashMapHolder<GameObject>::Find(guid);
GameObject *obj = GetBgMap()->GetGameObject(guid);
if (obj)
{
//if doors are open, close it
@ -1359,7 +1358,7 @@ void BattleGround::DoorClose(uint64 const& guid)
void BattleGround::DoorOpen(uint64 const& guid)
{
GameObject *obj = HashMapHolder<GameObject>::Find(guid);
GameObject *obj = GetBgMap()->GetGameObject(guid);
if (obj)
{
//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)
{
GameObject *obj = HashMapHolder<GameObject>::Find(guid);
Map* map = GetBgMap();
GameObject *obj = map->GetGameObject(guid);
if(!obj)
return;
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
if (!map)
return;
if (respawntime == 0)
{
//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)
{
Creature* obj = HashMapHolder<Creature>::Find(guid);
Map* map = GetBgMap();
Creature* obj = map->GetCreature(guid);
if (!obj)
return;
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
if (!map)
return;
if (respawntime == 0)
{
obj->Respawn();
@ -1508,12 +1505,13 @@ bool BattleGround::DelObject(uint32 type)
if (!m_BgObjects[type])
return true;
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
GameObject *obj = GetBgMap()->GetGameObject(m_BgObjects[type]);
if (!obj)
{
sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type]));
return false;
}
obj->SetRespawnTime(0); // not save respawn time
obj->Delete();
m_BgObjects[type] = 0;
@ -1560,11 +1558,20 @@ buffs are in their positions when battleground starts
*/
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())
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;
while (index >= 0 && m_BgObjects[index] != go_guid)
index--;

View file

@ -36,6 +36,7 @@ class GameObject;
class Group;
class Player;
class WorldPacket;
class BattleGroundMap;
struct WorldSafeLocsEntry;
@ -395,6 +396,14 @@ class BattleGround
void SetMapId(uint32 MapID) { m_MapId = 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 GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const
{
@ -619,6 +628,7 @@ class BattleGround
/* Start location */
uint32 m_MapId;
BattleGroundMap* m_Map;
float m_TeamStartLocX[BG_TEAMS_COUNT];
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];

View file

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

View file

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

View file

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

View file

@ -21,6 +21,7 @@
#include "Common.h"
#include "Policies/Singleton.h"
#include "Utilities/EventProcessor.h"
#include "BattleGround.h"
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
SpawnEvent(WS_EVENT_SPIRITGUIDES_SPAWN, 0, true);
SpawnEvent(WS_EVENT_FLAG_A, 0, true);
SpawnEvent(WS_EVENT_FLAG_H, 0, true);
}
@ -149,7 +150,7 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
GameObject *obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID(team));
GameObject *obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID(team));
if (obj)
obj->Delete();
else
@ -533,7 +534,7 @@ void BattleGroundWS::Reset()
m_FlagState[i] = BG_WS_FLAG_STATE_ON_BASE;
m_TeamScores[i] = 0;
}
bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID());
bool isBGWeekend = BattleGroundMgr::IsBGWeekend(GetTypeID());
m_ReputationCapture = (isBGWeekend) ? 45 : 35;
m_HonorWinKills = (isBGWeekend) ? 3 : 1;
m_HonorEndKills = (isBGWeekend) ? 4 : 2;

View file

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

View file

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

View file

@ -449,7 +449,7 @@ void GameObject::Update(uint32 /*p_time*/)
if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY))
SaveRespawnTime();
ObjectAccessor::UpdateObjectVisibility(this);
UpdateObjectVisibility();
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) )
return false;
if(!GetGOInfo()->GetDespawnPossibility() && !GetGOInfo()->IsDespawnAtAction())
if (!GetGOInfo()->GetDespawnPossibility() && !GetGOInfo()->IsDespawnAtAction() && data->spawntimesecs >= 0)
{
SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
m_spawnedByDefault = true;

View file

@ -208,53 +208,29 @@ void Guild::SetGINFO(std::string ginfo)
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)
m_Id = GuildId;
if (!guildDataResult)
return false;
Field *fields = guildDataResult->Fetch();
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();
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;
if (!LoadMembersFromDB(GuildId))
return false;
LoadBankRightsFromDB(GuildId); // Must be after LoadRanksFromDB because it populates rank struct
// 0 1 2 3 4 5
result = CharacterDatabase.PQuery("SELECT name, leaderguid, EmblemStyle, EmblemColor, BorderStyle, BorderColor,"
// 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)
{
@ -264,6 +240,11 @@ bool Guild::LoadGuildFromDB(uint32 GuildId)
m_CreatedYear = local.tm_year + 1900;
}
return true;
}
bool Guild::CheckGuildStructure()
{
// Repair the structure of guild
// If the guildmaster doesn't exist or isn't the member of guild
// attempt to promote another member
@ -286,24 +267,19 @@ bool Guild::LoadGuildFromDB(uint32 GuildId)
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;
}
bool Guild::LoadRanksFromDB(uint32 GuildId)
bool Guild::LoadRanksFromDB(QueryResult *guildRanksResult)
{
Field *fields;
// 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)
if (!guildRanksResult)
{
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);
return true;
}
Field *fields;
bool broken_ranks = false;
//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
{
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();
std::string rankName = fields[1].GetCppString();
uint32 rankRights = fields[2].GetUInt32();
uint32 rankMoney = fields[3].GetUInt32();
uint32 guildId = fields[0].GetUInt32();
if (guildId < m_Id)
{
//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..
broken_ranks = true;
@ -328,28 +319,27 @@ bool Guild::LoadRanksFromDB(uint32 GuildId)
rankRights |= GR_RIGHT_ALL;
AddRank(rankName,rankRights,rankMoney);
}while( result->NextRow() );
delete result;
}while( guildRanksResult->NextRow() );
if (m_Ranks.size() < GUILD_RANKS_MIN_COUNT) // if too few ranks, renew them
{
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
broken_ranks = false;
}
// guild_rank have wrong numbered ranks, repair
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.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)
{
std::string name = m_Ranks[i].Name;
uint32 rights = m_Ranks[i].Rights;
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();
}
@ -357,46 +347,52 @@ bool Guild::LoadRanksFromDB(uint32 GuildId)
return true;
}
bool Guild::LoadMembersFromDB(uint32 GuildId)
bool Guild::LoadMembersFromDB(QueryResult *guildMembersResult)
{
// 0 1 2 3 4 5
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)
if (!guildMembersResult)
return false;
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;
uint64 guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
newmember.RankId = fields[1].GetUInt32();
uint64 guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
newmember.RankId = fields[2].GetUInt32();
//don't allow member to have not existing rank!
if (newmember.RankId >= m_Ranks.size())
newmember.RankId = GetLowestRank();
newmember.Pnote = fields[2].GetCppString();
newmember.OFFnote = fields[3].GetCppString();
newmember.BankResetTimeMoney = fields[4].GetUInt32();
newmember.BankRemMoney = fields[5].GetUInt32();
newmember.Pnote = fields[3].GetCppString();
newmember.OFFnote = fields[4].GetCppString();
newmember.BankResetTimeMoney = fields[5].GetUInt32();
newmember.BankRemMoney = fields[6].GetUInt32();
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{
newmember.BankResetTimeTab[i] = fields[6+(2*i)].GetUInt32();
newmember.BankRemSlotsTab[i] = fields[7+(2*i)].GetUInt32();
newmember.BankResetTimeTab[i] = fields[7+(2*i)].GetUInt32();
newmember.BankRemSlotsTab[i] = fields[8+(2*i)].GetUInt32();
}
newmember.Name = fields[18].GetCppString();
newmember.Level = fields[19].GetUInt8();
newmember.Class = fields[20].GetUInt8();
newmember.ZoneId = fields[21].GetUInt32();
newmember.LogoutTime = fields[22].GetUInt64();
newmember.Name = fields[19].GetCppString();
newmember.Level = fields[20].GetUInt8();
newmember.Class = fields[21].GetUInt8();
newmember.ZoneId = fields[22].GetUInt32();
newmember.LogoutTime = fields[23].GetUInt64();
//this code will remove unexisting character guids from guild
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;
}while( result->NextRow() );
delete result;
}while (guildMembersResult->NextRow());
if (members.empty())
return false;
@ -1464,28 +1459,39 @@ uint32 Guild::GetBankSlotPerDay(uint32 rankId, uint8 TabId)
// *************************************************
// Rights per day related
void Guild::LoadBankRightsFromDB(uint32 GuildId)
bool Guild::LoadBankRightsFromDB(QueryResult *guildBankTabRightsResult)
{
// 0 1 2 3
QueryResult *result = CharacterDatabase.PQuery("SELECT TabId, rid, gbright, SlotPerDay FROM guild_bank_right WHERE guildid = '%u' ORDER BY TabId", GuildId);
if (!result)
return;
if (!guildBankTabRightsResult)
return true;
do
{
Field *fields = result->Fetch();
uint8 TabId = fields[0].GetUInt8();
uint32 rankId = fields[1].GetUInt32();
uint16 right = fields[2].GetUInt16();
uint16 SlotPerDay = fields[3].GetUInt16();
Field *fields = guildBankTabRightsResult->Fetch();
//prevent crash when all rights in result are already processed
if (!fields)
break;
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);
} while (result->NextRow());
delete result;
} while (guildBankTabRightsResult->NextRow());
return;
return true;
}
// *************************************************

View file

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

View file

@ -25,7 +25,6 @@
#include "Player.h"
#include "Item.h"
#include "UpdateData.h"
#include "ObjectAccessor.h"
void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
{
@ -1300,7 +1299,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
_player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true);
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);
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_FLOAT = 571, //log
LANG_GET_FLOAT_FIELD = 572,
LANG_SET_32BIT = 573, //log
LANG_SET_32BIT_FIELD = 574,
// 573, //not used
// 574, //not used
LANG_CHANGE_32BIT = 575, //log
LANG_CHANGE_32BIT_FIELD = 576,

View file

@ -70,7 +70,6 @@ bool ChatHandler::HandleReloadAllCommand(const char*)
HandleReloadReservedNameCommand("");
HandleReloadMangosStringCommand("");
HandleReloadGameTeleCommand("");
HandleReloadBattleEventCommand("");
return true;
}
@ -4144,30 +4143,6 @@ bool ChatHandler::HandleChangeWeather(const char* args)
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)
{
if(!*args)

View file

@ -218,6 +218,7 @@ BattleGroundMap* MapInstanced::CreateBattleGroundMap(uint32 InstanceId, BattleGr
BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this);
ASSERT(map->IsBattleGroundOrArena());
map->SetBG(bg);
bg->SetBgMap(map);
m_InstancedMaps[InstanceId] = 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());
// or update at original position
else
ObjectAccessor::UpdateVisibilityForPlayer(_player);
_player->UpdateVisibilityForPlayer();
}
// or update at original position
else
ObjectAccessor::UpdateVisibilityForPlayer(_player);
_player->UpdateVisibilityForPlayer();
_player->SaveToDB();
}

View file

@ -1427,7 +1427,7 @@ void WorldObject::MonsterTextEmote(const char* text, uint64 TargetGuid, bool IsB
{
WorldPacket data(SMSG_MESSAGECHAT, 200);
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)
@ -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);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
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)
@ -1849,7 +1849,7 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask;
if(update && IsInWorld())
ObjectAccessor::UpdateObjectVisibility(this);
UpdateObjectVisibility();
}
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1872,3 +1872,12 @@ void WorldObject::PlayDirectSound( uint32 sound_id, Player* target /*= NULL*/ )
else
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() {}
void AddObjectToRemoveList();
void UpdateObjectVisibility();
// 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); }

View file

@ -442,36 +442,6 @@ ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m)
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
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 _buildUpdateObject(Object* obj, UpdateDataMapType &);
static void UpdateObjectVisibility(WorldObject* obj);
static void UpdateVisibilityForPlayer(Player* player);
private:
struct WorldObjectChangeAccumulator
{

View file

@ -2873,10 +2873,14 @@ void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, Play
void ObjectMgr::LoadGuilds()
{
Guild *newguild;
Guild *newGuild;
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 )
{
@ -2890,27 +2894,54 @@ void ObjectMgr::LoadGuilds()
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() );
do
{
Field *fields = result->Fetch();
//Field *fields = result->Fetch();
bar.step();
++count;
newguild = new Guild;
if(!newguild->LoadGuildFromDB(fields[0].GetUInt32()))
newGuild = new Guild;
if (!newGuild->LoadGuildFromDB(result) ||
!newGuild->LoadRanksFromDB(guildRanksResult) ||
!newGuild->LoadMembersFromDB(guildMembersResult) ||
!newGuild->LoadBankRightsFromDB(guildBankTabRightsResult) ||
!newGuild->CheckGuildStructure()
)
{
newguild->Disband();
delete newguild;
newGuild->Disband();
delete newGuild;
continue;
}
AddGuild(newguild);
AddGuild(newGuild);
}while( result->NextRow() );
delete result;
delete guildRanksResult;
delete guildMembersResult;
delete guildBankTabRightsResult;
//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
@ -2925,7 +2956,11 @@ void ObjectMgr::LoadArenaTeams()
{
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 )
{
@ -2939,6 +2974,12 @@ void ObjectMgr::LoadArenaTeams()
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() );
do
@ -2948,16 +2989,19 @@ void ObjectMgr::LoadArenaTeams()
bar.step();
++count;
ArenaTeam *newarenateam = new ArenaTeam;
if(!newarenateam->LoadArenaTeamFromDB(fields[0].GetUInt32()))
ArenaTeam *newArenaTeam = new ArenaTeam;
if (!newArenaTeam->LoadArenaTeamFromDB(result) ||
!newArenaTeam->LoadMembersFromDB(arenaTeamMembersResult))
{
delete newarenateam;
newArenaTeam->Disband(NULL);
delete newArenaTeam;
continue;
}
AddArenaTeam(newarenateam);
AddArenaTeam(newArenaTeam);
}while( result->NextRow() );
delete result;
delete arenaTeamMembersResult;
sLog.outString();
sLog.outString( ">> Loaded %u arenateam definitions", count );

View file

@ -2239,7 +2239,7 @@ void Player::SetGameMaster(bool on)
getHostilRefManager().setOnlineOfflineState(true);
}
ObjectAccessor::UpdateVisibilityForPlayer(this);
UpdateVisibilityForPlayer();
}
void Player::SetGMVisible(bool on)
@ -4152,7 +4152,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
UpdateZone(newzone,newarea);
// update visibility
ObjectAccessor::UpdateVisibilityForPlayer(this);
UpdateVisibilityForPlayer();
if(!applySickness)
return;
@ -4205,7 +4205,7 @@ void Player::KillPlayer()
// don't create corpse at this moment, player might be falling
// update visibility
ObjectAccessor::UpdateObjectVisibility(this);
UpdateObjectVisibility();
}
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)
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)
{
// 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)
@ -15136,7 +15168,7 @@ void Player::_LoadQuestStatus(QueryResult *result)
((questStatusData.m_status == QUEST_STATUS_INCOMPLETE ||
questStatusData.m_status == QUEST_STATUS_COMPLETE ||
questStatusData.m_status == QUEST_STATUS_FAILED) &&
(!questStatusData.m_rewarded || pQuest->IsDaily())))
(!questStatusData.m_rewarded || pQuest->IsRepeatable())))
{
SetQuestSlot(slot, quest_id, quest_time);
@ -17759,7 +17791,7 @@ void Player::CorrectMetaGemEnchants(uint8 exceptslot, bool apply)
//was enchant active with/without item?
bool wasactive = EnchantmentFitsRequirements(condition, apply ? exceptslot : -1);
//should it now be?
if(wasactive ^ EnchantmentFitsRequirements(condition, apply ? -1 : exceptslot))
if(wasactive != EnchantmentFitsRequirements(condition, apply ? -1 : exceptslot))
{
// ignore item gem conditions
//if state changed, (dis)apply enchant
@ -20646,7 +20678,28 @@ void Player::SetFarSightGUID( uint64 guid )
SetUInt64Value(PLAYER_FARSIGHT, guid);
// 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)

View file

@ -1045,6 +1045,8 @@ class MANGOS_DLL_SPEC Player : public Unit
bool CanInteractWithNPCs(bool alive = true) const;
GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const;
void UpdateVisibilityForPlayer();
bool ToggleAFK();
bool ToggleDND();
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_AROUND_CASTER_2 = 34, // used in Tranquility
TARGET_SINGLE_PARTY = 35,
TARGET_ALL_HOSTILE_UNITS_AROUND_CASTER = 36,
TARGET_AREAEFFECT_PARTY = 37,
TARGET_SCRIPT = 38,
TARGET_SELF_FISHING = 39,

View file

@ -23,7 +23,6 @@
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "ObjectAccessor.h"
#include "UpdateMask.h"
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);
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
}
}
@ -1359,9 +1360,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
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);
float dest_x, dest_y, dest_z;
m_caster->GetClosePoint(dest_x, dest_y, dest_z, 0.0f, radius, angle);
m_targets.setDestination(dest_x, dest_y, dest_z);
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.
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);
float dest_x, dest_y, dest_z;
m_caster->GetClosePoint(dest_x, dest_y, dest_z, 0.0f, radius, angle);
m_targets.setDestination(dest_x, dest_y, dest_z);
if (radius > 0.0f)
@ -1700,14 +1699,25 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
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:
// special target order
if (m_spellInfo->Id==64904) // Hymn of Hope
// target amount stored in parent spell dummy effect but hard for access
switch (m_spellInfo->Id)
{
case 64844: // Divine Hymn
// target amount stored in parent spell dummy effect but hard to access
FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 3, true, false, false);
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);
else
break;
default:
FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY);
break;
}
break;
case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
// Wild Growth
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellIconID == 2864)

View file

@ -3922,7 +3922,7 @@ void Aura::HandleInvisibilityDetect(bool apply, bool Real)
m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
}
if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
((Player*)m_target)->UpdateVisibilityForPlayer();
}
void Aura::HandleAuraModRoot(bool apply, bool Real)
@ -6271,7 +6271,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
void Aura::PeriodicTick()
{
if (!m_target->isAlive() ^ IsDeathOnlySpell(GetSpellProto()))
if (!m_target->isAlive() != IsDeathOnlySpell(GetSpellProto()))
return;
switch(m_modifier.m_auraname)
@ -6771,7 +6771,6 @@ void Aura::PeriodicTick()
void Aura::PeriodicDummyTick()
{
Unit *caster = GetCaster();
SpellEntry const* spell = GetSpellProto();
switch (spell->SpellFamilyName)
{
@ -6993,6 +6992,21 @@ void Aura::PeriodicDummyTick()
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);
}
}
else
m_target->RemoveAurasDueToSpell(58670);
}
break;
case SPELLFAMILY_MAGE:
{
@ -7035,27 +7049,31 @@ void Aura::PeriodicDummyTick()
{
switch (spell->Id)
{
// Killing Spree
case 51690:
{
if (m_target->hasUnitState(UNIT_STAT_STUNNED) || m_target->HasAuraType(SPELL_AURA_MOD_FEAR))
return;
std::list<Unit*> targets;
{
// eff_radius ==0
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.data.Part.reserved = ALL_DISTRICT;
MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius);
MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster,targets, u_check);
MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(m_target, m_target, radius);
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>, WorldTypeMapContainer > world_object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap(), *caster, radius);
cell_lock->Visit(cell_lock, world_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, *m_target->GetMap(), *m_target, radius);
}
if(targets.empty())
@ -7065,18 +7083,12 @@ void Aura::PeriodicDummyTick()
std::advance(itr, rand()%targets.size());
Unit* target = *itr;
caster->CastSpell(target, 57840, true);
caster->CastSpell(target, 57841, true);
m_target->CastSpell(target, 57840, true);
m_target->CastSpell(target, 57841, true);
return;
}
// Master of Subtlety
// case 31666: break;
// Killing Spree
// case 51690: break;
// Overkill
// case 58428: break;
// default:
// break;
default:
break;
}
break;
}
@ -7125,7 +7137,7 @@ void Aura::PeriodicDummyTick()
// Death and Decay
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);
return;
}
@ -7412,6 +7424,17 @@ void Aura::HandleModTargetArmorPct(bool apply, bool Real)
void Aura::HandleAuraModAllCritChance(bool apply, bool Real)
{
this->HandleAuraModCritPercent(apply, Real);
this->HandleModSpellCritChance(apply, Real);
// spells required only Real aura add/remove
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
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())
if (player && player->InArena())
return SPELL_FAILED_NOT_IN_ARENA;
// Spell casted only on battleground

View file

@ -4069,7 +4069,7 @@ void Unit::RemoveArenaAuras(bool onleave)
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->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);
else
++iter;
@ -5266,9 +5266,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
switch(dummySpell->Id)
{
// Nightfall
// Nightfall & Glyph of Corruption
case 18094:
case 18095:
case 56218:
{
target = this;
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))
return false;
if (!(isAlive() ^ inverseAlive))
if (!(isAlive() != inverseAlive))
return false;
return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#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"
#endif // __REVISION_SQL_H__

View file

@ -177,13 +177,16 @@ Global
{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.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.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.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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE