Merge commit 'origin/master' into 320

This commit is contained in:
tomrus88 2009-08-05 14:52:29 +04:00
commit f97da77cbd
38 changed files with 788 additions and 538 deletions

View file

@ -81,13 +81,14 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
switch(criteria->requiredType)
{
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
break;
@ -689,7 +690,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// std. case: increment at 1
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
@ -1253,6 +1253,24 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, spellCount);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
if(achievementCriteria->win_duel.duelCount)
{
// those requirements couldn't be found in the dbc
AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
if(!data)
continue;
if(!data->Meets(GetPlayer(),unit))
continue;
}
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetReveredFactionCount());
break;
@ -1942,6 +1960,10 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
if(criteria->do_emote.count==0)
continue;
break;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics
if(criteria->win_duel.duelCount==0)
continue;
break;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: // any cases
break;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases

View file

@ -201,16 +201,13 @@ BattleGround::~BattleGround()
// (this is done automatically in mapmanager update, when the instance is reset after the reset time)
int size = m_BgCreatures.size();
for(int i = 0; i < size; ++i)
{
DelCreature(i);
}
size = m_BgObjects.size();
for(int i = 0; i < size; ++i)
{
DelObject(i);
}
if(GetInstanceID()) // not spam by useless queries in case BG templates
if (GetInstanceID()) // not spam by useless queries in case BG templates
{
// delete creature and go respawn times
WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
@ -227,6 +224,9 @@ BattleGround::~BattleGround()
((BattleGroundMap*)map)->SetUnload();
// remove from bg free slot queue
this->RemoveFromBGFreeSlotQueue();
for(BattleGroundScoreMap::const_iterator itr = m_PlayerScores.begin(); itr != m_PlayerScores.end(); ++itr)
delete itr->second;
}
void BattleGround::Update(uint32 diff)
@ -939,7 +939,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
participant = true;
}
std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid);
BattleGroundScoreMap::iterator itr2 = m_PlayerScores.find(guid);
if (itr2 != m_PlayerScores.end())
{
delete itr2->second; // delete player's score
@ -1081,6 +1081,9 @@ void BattleGround::Reset()
m_InBGFreeSlotQueue = false;
m_Players.clear();
for(BattleGroundScoreMap::const_iterator itr = m_PlayerScores.begin(); itr != m_PlayerScores.end(); ++itr)
delete itr->second;
m_PlayerScores.clear();
}
@ -1271,7 +1274,7 @@ bool BattleGround::HasFreeSlots() const
void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
//this procedure is called from virtual function implemented in bg subclass
std::map<uint64, BattleGroundScore*>::const_iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::const_iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -375,8 +375,9 @@ class BattleGround
BattleGroundPlayerMap const& GetPlayers() const { return m_Players; }
uint32 GetPlayersSize() const { return m_Players.size(); }
std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); }
std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); }
typedef std::map<uint64, BattleGroundScore*> BattleGroundScoreMap;
BattleGroundScoreMap::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); }
BattleGroundScoreMap::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); }
uint32 GetPlayerScoresSize() const { return m_PlayerScores.size(); }
uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); }
@ -513,8 +514,8 @@ class BattleGround
void PlayerAddedToBGCheckIfBGIsRunning(Player* plr);
/* Scorekeeping */
// Player scores
std::map<uint64, BattleGroundScore*> m_PlayerScores;
BattleGroundScoreMap m_PlayerScores; // Player scores
// must be implemented in BG subclass
virtual void RemovePlayer(Player * /*player*/, uint64 /*guid*/) {}

View file

@ -659,8 +659,7 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if( itr == m_PlayerScores.end() ) // player not found...
return;

View file

@ -96,8 +96,7 @@ void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -180,8 +180,7 @@ bool BattleGroundBE::SetupBattleGround()
void BattleGroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -778,8 +778,7 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
void BattleGroundEY::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found
return;

View file

@ -1333,7 +1333,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
*data << (int32)(bg->GetPlayerScoresSize());
for(std::map<uint64, BattleGroundScore*>::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr)
for(BattleGround::BattleGroundScoreMap::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr)
{
*data << (uint64)itr->first;
*data << (int32)itr->second->KillingBlows;

View file

@ -72,8 +72,7 @@ void BattleGroundSA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -631,8 +631,7 @@ void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer)
void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found
return;

View file

@ -818,6 +818,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS))
{
pCurrChar->resetTalents(true);
pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
SendNotification(LANG_RESET_TALENTS);
}
@ -835,6 +836,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",
GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow());
if(!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED))
pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
m_playerLoading = false;
delete holder;
}

View file

@ -808,17 +808,17 @@ void Guild::DisplayGuildEventlog(WorldSession *session)
for (GuildEventlog::const_iterator itr = m_GuildEventlog.begin(); itr != m_GuildEventlog.end(); ++itr)
{
// Event type
data << uint8((*itr)->EventType);
data << uint8(itr->EventType);
// Player 1
data << uint64((*itr)->PlayerGuid1);
data << uint64(itr->PlayerGuid1);
// Player 2 not for left/join guild events
if( (*itr)->EventType != GUILD_EVENT_LOG_JOIN_GUILD && (*itr)->EventType != GUILD_EVENT_LOG_LEAVE_GUILD )
data << uint64((*itr)->PlayerGuid2);
if (itr->EventType != GUILD_EVENT_LOG_JOIN_GUILD && itr->EventType != GUILD_EVENT_LOG_LEAVE_GUILD)
data << uint64(itr->PlayerGuid2);
// New Rank - only for promote/demote guild events
if( (*itr)->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || (*itr)->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER )
data << uint8((*itr)->NewRank);
if (itr->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || itr->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
data << uint8(itr->NewRank);
// Event timestamp
data << uint32(time(NULL)-(*itr)->TimeStamp);
data << uint32(time(NULL)-itr->TimeStamp);
}
session->SendPacket(&data);
sLog.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)");
@ -837,14 +837,14 @@ void Guild::LoadGuildEventLogFromDB()
do
{
Field *fields = result->Fetch();
GuildEventlogEntry *NewEvent = new GuildEventlogEntry;
GuildEventlogEntry NewEvent;
// Fill entry
NewEvent->LogGuid = fields[0].GetUInt32();
NewEvent->EventType = fields[1].GetUInt8();
NewEvent->PlayerGuid1 = fields[2].GetUInt32();
NewEvent->PlayerGuid2 = fields[3].GetUInt32();
NewEvent->NewRank = fields[4].GetUInt8();
NewEvent->TimeStamp = fields[5].GetUInt64();
NewEvent.LogGuid = fields[0].GetUInt32();
NewEvent.EventType = fields[1].GetUInt8();
NewEvent.PlayerGuid1 = fields[2].GetUInt32();
NewEvent.PlayerGuid2 = fields[3].GetUInt32();
NewEvent.NewRank = fields[4].GetUInt8();
NewEvent.TimeStamp = fields[5].GetUInt64();
// Add entry to map
m_GuildEventlog.push_front(NewEvent);
@ -854,9 +854,8 @@ void Guild::LoadGuildEventLogFromDB()
// Check lists size in case to many event entries in db
// This cases can happen only if a crash occured somewhere and table has too many log entries
if (!m_GuildEventlog.empty())
{
CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid=%u AND LogGuid < %u", Id, m_GuildEventlog.front()->LogGuid);
}
CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid=%u AND LogGuid < %u", Id, m_GuildEventlog.front().LogGuid);
m_eventlogloaded = true;
}
@ -865,16 +864,8 @@ void Guild::UnloadGuildEventlog()
{
if (!m_eventlogloaded)
return;
GuildEventlogEntry *EventLogEntry;
if( !m_GuildEventlog.empty() )
{
do
{
EventLogEntry = *(m_GuildEventlog.begin());
m_GuildEventlog.pop_front();
delete EventLogEntry;
}while( !m_GuildEventlog.empty() );
}
m_GuildEventlog.clear();
m_eventlogloaded = false;
}
@ -894,27 +885,25 @@ void Guild::RenumGuildEventlog()
// Add entry to guild eventlog
void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank)
{
GuildEventlogEntry *NewEvent = new GuildEventlogEntry;
GuildEventlogEntry NewEvent;
// Fill entry
NewEvent->LogGuid = GuildEventlogMaxGuid++;
NewEvent->EventType = EventType;
NewEvent->PlayerGuid1 = PlayerGuid1;
NewEvent->PlayerGuid2 = PlayerGuid2;
NewEvent->NewRank = NewRank;
NewEvent->TimeStamp = uint32(time(NULL));
NewEvent.LogGuid = GuildEventlogMaxGuid++;
NewEvent.EventType = EventType;
NewEvent.PlayerGuid1 = PlayerGuid1;
NewEvent.PlayerGuid2 = PlayerGuid2;
NewEvent.NewRank = NewRank;
NewEvent.TimeStamp = uint32(time(NULL));
// Check max entry limit and delete from db if needed
if (m_GuildEventlog.size() > GUILD_EVENTLOG_MAX_ENTRIES)
{
GuildEventlogEntry *OldEvent = *(m_GuildEventlog.begin());
CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, m_GuildEventlog.front().LogGuid);
m_GuildEventlog.pop_front();
CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid);
delete OldEvent;
}
// Add entry to map
m_GuildEventlog.push_back(NewEvent);
// Add new eventlog entry into DB
CharacterDatabase.PExecute("INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "')",
Id, NewEvent->LogGuid, uint32(NewEvent->EventType), NewEvent->PlayerGuid1, NewEvent->PlayerGuid2, uint32(NewEvent->NewRank), NewEvent->TimeStamp);
Id, NewEvent.LogGuid, uint32(NewEvent.EventType), NewEvent.PlayerGuid1, NewEvent.PlayerGuid2, uint32(NewEvent.NewRank), NewEvent.TimeStamp);
}
// *************************************************
@ -1486,30 +1475,28 @@ void Guild::LoadGuildBankEventLogFromDB()
do
{
Field *fields = result->Fetch();
GuildBankEvent *NewEvent = new GuildBankEvent;
GuildBankEvent NewEvent;
NewEvent->LogGuid = fields[0].GetUInt32();
NewEvent->LogEntry = fields[1].GetUInt8();
NewEvent.LogGuid = fields[0].GetUInt32();
NewEvent.LogEntry = fields[1].GetUInt8();
uint8 TabId = fields[2].GetUInt8();
NewEvent->PlayerGuid = fields[3].GetUInt32();
NewEvent->ItemOrMoney = fields[4].GetUInt32();
NewEvent->ItemStackCount = fields[5].GetUInt8();
NewEvent->DestTabId = fields[6].GetUInt8();
NewEvent->TimeStamp = fields[7].GetUInt64();
NewEvent.PlayerGuid = fields[3].GetUInt32();
NewEvent.ItemOrMoney = fields[4].GetUInt32();
NewEvent.ItemStackCount = fields[5].GetUInt8();
NewEvent.DestTabId = fields[6].GetUInt8();
NewEvent.TimeStamp = fields[7].GetUInt64();
if (TabId >= GUILD_BANK_MAX_TABS)
{
sLog.outError( "Guild::LoadGuildBankEventLogFromDB: Invalid tabid '%u' for guild bank log entry (guild: '%s', LogGuid: %u), skipped.", TabId, GetName().c_str(), NewEvent->LogGuid);
delete NewEvent;
sLog.outError( "Guild::LoadGuildBankEventLogFromDB: Invalid tabid '%u' for guild bank log entry (guild: '%s', LogGuid: %u), skipped.", TabId, GetName().c_str(), NewEvent.LogGuid);
continue;
}
if (NewEvent->isMoneyEvent() && m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS
|| m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS)
{
delete NewEvent;
if (NewEvent.isMoneyEvent() && m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS ||
m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS)
continue;
}
if (NewEvent->isMoneyEvent())
if (NewEvent.isMoneyEvent())
m_GuildBankEventLog_Money.push_front(NewEvent);
else
m_GuildBankEventLog_Item[TabId].push_front(NewEvent);
@ -1522,43 +1509,24 @@ void Guild::LoadGuildBankEventLogFromDB()
if (!m_GuildBankEventLog_Money.empty())
{
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid=%u AND LogGuid < %u",
Id, m_GuildBankEventLog_Money.front()->LogGuid);
Id, m_GuildBankEventLog_Money.front().LogGuid);
}
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{
if (!m_GuildBankEventLog_Item[i].empty())
{
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid=%u AND LogGuid < %u",
Id, m_GuildBankEventLog_Item[i].front()->LogGuid);
Id, m_GuildBankEventLog_Item[i].front().LogGuid);
}
}
}
void Guild::UnloadGuildBankEventLog()
{
GuildBankEvent *EventLogEntry;
if( !m_GuildBankEventLog_Money.empty() )
{
do
{
EventLogEntry = *(m_GuildBankEventLog_Money.begin());
m_GuildBankEventLog_Money.pop_front();
delete EventLogEntry;
}while( !m_GuildBankEventLog_Money.empty() );
}
m_GuildBankEventLog_Money.clear();
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{
if( !m_GuildBankEventLog_Item[i].empty() )
{
do
{
EventLogEntry = *(m_GuildBankEventLog_Item[i].begin());
m_GuildBankEventLog_Item[i].pop_front();
delete EventLogEntry;
}while( !m_GuildBankEventLog_Item[i].empty() );
}
}
m_GuildBankEventLog_Item[i].clear();
}
void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
@ -1574,24 +1542,24 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
data << uint8(m_GuildBankEventLog_Money.size()); // number of log entries
for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr)
{
data << uint8((*itr)->LogEntry);
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK2)
data << uint8(itr->LogEntry);
data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER));
if (itr->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
itr->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
itr->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
itr->LogEntry == GUILD_BANK_LOG_UNK1 ||
itr->LogEntry == GUILD_BANK_LOG_UNK2)
{
data << uint32((*itr)->ItemOrMoney);
data << uint32(itr->ItemOrMoney);
}
else
{
data << uint32((*itr)->ItemOrMoney);
data << uint32((*itr)->ItemStackCount);
if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
data << uint8((*itr)->DestTabId); // moved tab
data << uint32(itr->ItemOrMoney);
data << uint32(itr->ItemStackCount);
if (itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
data << uint8(itr->DestTabId); // moved tab
}
data << uint32(time(NULL)-(*itr)->TimeStamp);
data << uint32(time(NULL) - itr->TimeStamp);
}
session->SendPacket(&data);
}
@ -1604,24 +1572,24 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
data << uint8(m_GuildBankEventLog_Item[TabId].size());
for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr)
{
data << uint8((*itr)->LogEntry);
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK2)
data << uint8(itr->LogEntry);
data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER));
if (itr->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
itr->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
itr->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
itr->LogEntry == GUILD_BANK_LOG_UNK1 ||
itr->LogEntry == GUILD_BANK_LOG_UNK2)
{
data << uint32((*itr)->ItemOrMoney);
data << uint32(itr->ItemOrMoney);
}
else
{
data << uint32((*itr)->ItemOrMoney);
data << uint32((*itr)->ItemStackCount);
if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
data << uint8((*itr)->DestTabId); // moved tab
data << uint32(itr->ItemOrMoney);
data << uint32(itr->ItemStackCount);
if (itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
data << uint8(itr->DestTabId); // moved tab
}
data << uint32(time(NULL)-(*itr)->TimeStamp);
data << uint32(time(NULL) - itr->TimeStamp);
}
session->SendPacket(&data);
}
@ -1630,24 +1598,23 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
void Guild::LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId)
{
GuildBankEvent *NewEvent = new GuildBankEvent;
GuildBankEvent NewEvent;
NewEvent->LogGuid = LogMaxGuid++;
NewEvent->LogEntry = LogEntry;
NewEvent->PlayerGuid = PlayerGuidLow;
NewEvent->ItemOrMoney = ItemOrMoney;
NewEvent->ItemStackCount = ItemStackCount;
NewEvent->DestTabId = DestTabId;
NewEvent->TimeStamp = uint32(time(NULL));
NewEvent.LogGuid = LogMaxGuid++;
NewEvent.LogEntry = LogEntry;
NewEvent.PlayerGuid = PlayerGuidLow;
NewEvent.ItemOrMoney = ItemOrMoney;
NewEvent.ItemStackCount = ItemStackCount;
NewEvent.DestTabId = DestTabId;
NewEvent.TimeStamp = uint32(time(NULL));
if (NewEvent->isMoneyEvent())
if (NewEvent.isMoneyEvent())
{
if (m_GuildBankEventLog_Money.size() > GUILD_BANK_MAX_LOGS)
{
GuildBankEvent *OldEvent = *(m_GuildBankEventLog_Money.begin());
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'",
Id, m_GuildBankEventLog_Money.front().LogGuid);
m_GuildBankEventLog_Money.pop_front();
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid);
delete OldEvent;
}
m_GuildBankEventLog_Money.push_back(NewEvent);
}
@ -1655,15 +1622,14 @@ void Guild::LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint
{
if (m_GuildBankEventLog_Item[TabId].size() > GUILD_BANK_MAX_LOGS)
{
GuildBankEvent *OldEvent = *(m_GuildBankEventLog_Item[TabId].begin());
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'",
Id, m_GuildBankEventLog_Item[TabId].front().LogGuid);
m_GuildBankEventLog_Item[TabId].pop_front();
CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid);
delete OldEvent;
}
m_GuildBankEventLog_Item[TabId].push_back(NewEvent);
}
CharacterDatabase.PExecute("INSERT INTO guild_bank_eventlog (guildid,LogGuid,LogEntry,TabId,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "')",
Id, NewEvent->LogGuid, uint32(NewEvent->LogEntry), uint32(TabId), NewEvent->PlayerGuid, NewEvent->ItemOrMoney, uint32(NewEvent->ItemStackCount), uint32(NewEvent->DestTabId), NewEvent->TimeStamp);
Id, NewEvent.LogGuid, uint32(NewEvent.LogEntry), uint32(TabId), NewEvent.PlayerGuid, NewEvent.ItemOrMoney, uint32(NewEvent.ItemStackCount), uint32(NewEvent.DestTabId), NewEvent.TimeStamp);
}
// This will renum guids used at load to prevent always going up until infinit

View file

@ -458,8 +458,8 @@ class Guild
TabListMap m_TabListMap;
/** These are actually ordered lists. The first element is the oldest entry.*/
typedef std::list<GuildEventlogEntry*> GuildEventlog;
typedef std::list<GuildBankEvent*> GuildBankEventLog;
typedef std::list<GuildEventlogEntry> GuildEventlog;
typedef std::list<GuildBankEvent> GuildBankEventLog;
GuildEventlog m_GuildEventlog;
GuildBankEventLog m_GuildBankEventLog_Money;
GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS];

View file

@ -44,7 +44,11 @@ INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK);
INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex);
ObjectAccessor::ObjectAccessor() {}
ObjectAccessor::~ObjectAccessor() {}
ObjectAccessor::~ObjectAccessor()
{
for(Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr)
delete itr->second;
}
Creature*
ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid)

View file

@ -170,6 +170,9 @@ ObjectMgr::~ObjectMgr()
for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr)
delete itr->second;
for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
delete itr->second;
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
itr->second.Clear();

View file

@ -194,9 +194,12 @@ void PetAI::UpdateAI(const uint32 diff)
}
}
// Autocast (casted only in combat or persistent spells in any state)
if (m_creature->GetGlobalCooldown() == 0 && !m_creature->IsNonMeleeSpellCasted(false))
{
//Autocast
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
@ -210,11 +213,29 @@ void PetAI::UpdateAI(const uint32 diff)
// ignore some combinations of combat state and combat/noncombat spells
if (!inCombat)
{
// ignore attacking spells, and allow only self/around spells
if (!IsPositiveSpell(spellInfo->Id))
continue;
// non combat spells allowed
// only pet spells have IsNonCombatSpell and not fit this reqs:
// Consume Shadows, Lesser Invisibility, so ignore checks for its
if (!IsNonCombatSpell(spellInfo))
{
// allow only spell without spell cost or with spell cost but not duration limit
int32 duration = GetSpellDuration(spellInfo);
if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0)
continue;
// allow only spell without cooldown > duration
int32 cooldown = GetSpellRecoveryTime(spellInfo);
if (cooldown >= 0 && duration >= 0 && cooldown > duration)
continue;
}
}
else
{
// just ignore non-combat spells
if (IsNonCombatSpell(spellInfo))
continue;
}
@ -223,7 +244,7 @@ void PetAI::UpdateAI(const uint32 diff)
if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
{
m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell));
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell));
continue;
}
else
@ -239,7 +260,7 @@ void PetAI::UpdateAI(const uint32 diff)
if(spell->CanAutoCast(Target))
{
m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(Target, spell));
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(Target, spell));
spellUsed = true;
break;
}
@ -250,14 +271,14 @@ void PetAI::UpdateAI(const uint32 diff)
}
//found units to cast on to
if (!m_targetSpellStore.empty())
if (!targetSpellStore.empty())
{
uint32 index = urand(0, m_targetSpellStore.size() - 1);
uint32 index = urand(0, targetSpellStore.size() - 1);
Spell* spell = m_targetSpellStore[index].second;
Unit* target = m_targetSpellStore[index].first;
Spell* spell = targetSpellStore[index].second;
Unit* target = targetSpellStore[index].first;
m_targetSpellStore.erase(m_targetSpellStore.begin() + index);
targetSpellStore.erase(targetSpellStore.begin() + index);
SpellCastTargets targets;
targets.setUnitTarget( target );
@ -276,11 +297,10 @@ void PetAI::UpdateAI(const uint32 diff)
spell->prepare(&targets);
}
while (!m_targetSpellStore.empty())
{
delete m_targetSpellStore.begin()->second;
m_targetSpellStore.erase(m_targetSpellStore.begin());
}
// deleted cached Spell objects
for(TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
delete itr->second;
}
}

View file

@ -52,8 +52,5 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI
bool inCombat;
std::set<uint64> m_AllySet;
uint32 m_updateAlliesTimer;
typedef std::pair<Unit*, Spell*> TargetSpellPair;
std::vector<TargetSpellPair> m_targetSpellStore;
};
#endif

View file

@ -689,14 +689,14 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
switch(iProto->Spells[0].SpellCategory)
{
case 11: // food
if(iProto->Stackable > 4)
count = 4;
count = getClass()==CLASS_DEATH_KNIGHT ? 10 : 4;
break;
case 59: // drink
if(iProto->Stackable > 2)
count = 2;
count = 2;
break;
}
if(iProto->Stackable < count)
count = iProto->Stackable;
}
StoreNewItemInBestSlots(item_id, count);
@ -13853,61 +13853,6 @@ void Player::SendQuestUpdateAddCreatureOrGo( Quest const* pQuest, uint64 guid, u
/*** LOAD SYSTEM ***/
/*********************************************************/
bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )
{
bool delete_result = true;
if (!result)
{
// 0 1 2 3 4 5 6 7 8 9 10 11
result = CharacterDatabase.PQuery("SELECT guid, data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login, zone, level FROM characters WHERE guid = '%u'",guid);
if (!result)
return false;
}
else
delete_result = false;
Field *fields = result->Fetch();
if (!LoadValues( fields[1].GetString()))
{
sLog.outError("Player #%d have broken data in `data` field. Can't be loaded for character list.",GUID_LOPART(guid));
if (delete_result)
delete result;
return false;
}
// overwrite possible wrong/corrupted guid
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
m_name = fields[2].GetCppString();
Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat());
SetLocationMapId(fields[6].GetUInt32());
// the instance id is not needed at character enum
m_Played_time[PLAYED_TIME_TOTAL] = fields[7].GetUInt32();
m_Played_time[PLAYED_TIME_LEVEL] = fields[8].GetUInt32();
m_atLoginFlags = fields[9].GetUInt32();
// I don't see these used anywhere ..
/*_LoadGroup();
_LoadBoundInstances();*/
if (delete_result)
delete result;
for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i)
m_items[i] = NULL;
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
m_deathState = DEAD;
return true;
}
void Player::_LoadDeclinedNames(QueryResult* result)
{
if(!result)
@ -14762,7 +14707,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
delete result;
}
if(getClass() == CLASS_WARRIOR)
if(getClass() == CLASS_WARRIOR && !HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true);
}
@ -15564,26 +15509,9 @@ void Player::SaveToDB()
// first save/honor gain after midnight will also update the player's honor fields
UpdateHonorFields();
int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0;
//save, far from tavern/city
//save, but in tavern/city
sLog.outDebug("The value of player %s at save: ", m_name.c_str());
outDebugValues();
// save state (after auras removing), if aura remove some flags then it must set it back by self)
uint32 tmp_bytes = GetUInt32Value(UNIT_FIELD_BYTES_1);
uint32 tmp_bytes2 = GetUInt32Value(UNIT_FIELD_BYTES_2);
uint32 tmp_flags = GetUInt32Value(UNIT_FIELD_FLAGS);
uint32 tmp_pflags = GetUInt32Value(PLAYER_FLAGS);
uint32 tmp_displayid = GetDisplayId();
// Set player sit state to standing on save, also stealth and shifted form
SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND);
SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
bool inworld = IsInWorld();
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",GetGUIDLow());
@ -15638,66 +15566,47 @@ void Player::SaveToDB()
ss << "', ";
ss << m_taxi; // string with TaxiMaskSize numbers
ss << m_taxi << ", "; // string with TaxiMaskSize numbers
ss << ", ";
ss << (inworld ? 1 : 0);
ss << (IsInWorld() ? 1 : 0) << ", ";
ss << ", ";
ss << m_cinematic;
ss << m_cinematic << ", ";
ss << ", ";
ss << m_Played_time[PLAYED_TIME_TOTAL];
ss << ", ";
ss << m_Played_time[PLAYED_TIME_LEVEL];
ss << m_Played_time[PLAYED_TIME_TOTAL] << ", ";
ss << m_Played_time[PLAYED_TIME_LEVEL] << ", ";
ss << ", ";
ss << finiteAlways(m_rest_bonus);
ss << ", ";
ss << (uint64)time(NULL);
ss << ", ";
ss << is_save_resting;
ss << ", ";
ss << m_resetTalentsCost;
ss << ", ";
ss << (uint64)m_resetTalentsTime;
ss << finiteAlways(m_rest_bonus) << ", ";
ss << (uint64)time(NULL) << ", ";
ss << (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0) << ", ";
//save, far from tavern/city
//save, but in tavern/city
ss << m_resetTalentsCost << ", ";
ss << (uint64)m_resetTalentsTime << ", ";
ss << ", ";
ss << finiteAlways(m_movementInfo.t_x);
ss << ", ";
ss << finiteAlways(m_movementInfo.t_y);
ss << ", ";
ss << finiteAlways(m_movementInfo.t_z);
ss << ", ";
ss << finiteAlways(m_movementInfo.t_o);
ss << ", ";
ss << finiteAlways(m_movementInfo.t_x) << ", ";
ss << finiteAlways(m_movementInfo.t_y) << ", ";
ss << finiteAlways(m_movementInfo.t_z) << ", ";
ss << finiteAlways(m_movementInfo.t_o) << ", ";
if (m_transport)
ss << m_transport->GetGUIDLow();
else
ss << "0";
ss << ", ";
ss << ", ";
ss << m_ExtraFlags;
ss << m_ExtraFlags << ", ";
ss << ", ";
ss << uint32(m_stableSlots); // to prevent save uint8 as char
ss << uint32(m_stableSlots) << ", "; // to prevent save uint8 as char
ss << ", ";
ss << uint32(m_atLoginFlags);
ss << uint32(m_atLoginFlags) << ", ";
ss << ", ";
ss << GetZoneId();
ss << GetZoneId() << ", ";
ss << ", ";
ss << (uint64)m_deathExpireTime;
ss << (uint64)m_deathExpireTime << ", '";
ss << ", '";
ss << m_taxi.SaveTaxiDestinationsToString();
ss << "', '0', ";
ss << GetBattleGroundId();
ss << ", ";
ss << GetBGTeam();
ss << ", ";
ss << m_taxi.SaveTaxiDestinationsToString() << "', ";
ss << "'0', "; // arena_pending_points
ss << GetBattleGroundId() << ", ";
ss << GetBGTeam() << ", ";
ss << m_bgEntryPoint.mapid << ", "
<< finiteAlways(m_bgEntryPoint.coord_x) << ", "
<< finiteAlways(m_bgEntryPoint.coord_y) << ", "
@ -15724,12 +15633,6 @@ void Player::SaveToDB()
CharacterDatabase.CommitTransaction();
// restore state (before aura apply, if aura remove flag then aura must set it ack by self)
SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes);
SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2);
SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags);
SetUInt32Value(PLAYER_FLAGS, tmp_pflags);
// save pet (hunter pet level and experience and all type pets health/mana).
if(Pet* pet = GetPet())
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
@ -15798,26 +15701,13 @@ void Player::_SaveAuras()
SpellEntry const *spellInfo = itr2->second->GetSpellProto();
//skip all auras from spells that are passive or need a shapeshift
if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost()))
//skip all auras from spells that are passive
//do not save single target auras (unless they were cast by the player)
if (!itr2->second->IsPassive() && (itr2->second->GetCasterGUID() == GetGUID() || !itr2->second->IsSingleTarget()))
{
//do not save single target auras (unless they were cast by the player)
if (!(itr2->second->GetCasterGUID() != GetGUID() && itr2->second->IsSingleTarget()))
{
uint8 i;
// or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras
for (i = 0; i < 3; ++i)
if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT ||
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH)
break;
if (i == 3)
{
CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" UI64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')",
GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), stackCounter, itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges()));
}
}
CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" UI64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')",
GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), stackCounter, itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges()));
}
if(itr == auras.end())
@ -18146,11 +18036,6 @@ void Player::SendInitialPacketsBeforeAddToMap()
m_reputationMgr.SendInitialReputations();
m_achievementMgr.SendAllAchievementData();
// update zone
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea); // also call SendInitWorldStates();
SendEquipmentSetList();
data.Initialize(SMSG_LOGIN_SETTIMESPEED, 4 + 4 + 4);
@ -18160,7 +18045,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
GetSession()->SendPacket( &data );
// set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment
if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight())
if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY) || isInFlight())
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_FLYING2);
m_mover = this;
@ -18168,6 +18053,11 @@ void Player::SendInitialPacketsBeforeAddToMap()
void Player::SendInitialPacketsAfterAddToMap()
{
// update zone
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea); // also call SendInitWorldStates();
WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement
data << uint32(0x00000000); // on blizz it increments periodically
GetSession()->SendPacket(&data);
@ -19103,13 +18993,6 @@ void Player::SetClientControl(Unit* target, uint8 allowMove)
void Player::UpdateZoneDependentAuras( uint32 newZone )
{
// remove new continent flight forms
if( !IsAllowUseFlyMountsHere() )
{
RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
RemoveSpellsCausingAura(SPELL_AURA_FLY);
}
// Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update
SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAreaMapBounds(newZone);
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
@ -19682,13 +19565,11 @@ uint32 Player::CalculateTalentsPoints() const
return uint32(talentPointsForLevel * sWorld.getRate(RATE_TALENT));
}
bool Player::IsAllowUseFlyMountsHere() const
bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const
{
if (isGameMaster())
return true;
uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), GetZoneId());
return v_map == 530 || v_map == 571 && HasSpell(54197);
// continent checked in SpellMgr::GetSpellAllowedInLocationError at cast and area update
uint32 v_map = GetVirtualMapForMapAndZone(mapid, zone);
return v_map != 571 || HasSpell(54197); // Cold Weather Flying
}
struct DoPlayerLearnSpell

View file

@ -1351,7 +1351,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool LoadFromDB(uint32 guid, SqlQueryHolder *holder);
bool MinimalLoadFromDB(QueryResult *result, uint32 guid);
static bool LoadValuesArrayFromDB(Tokens& data,uint64 guid);
static uint32 GetUInt32ValueFromArray(Tokens const& data, uint16 index);
static float GetFloatValueFromArray(Tokens const& data, uint16 index);
@ -2065,7 +2064,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING); }
bool IsAllowUseFlyMountsHere() const;
bool IsKnowHowFlyIn(uint32 mapid, uint32 zone) const;
void SetClientControl(Unit* target, uint8 allowMove);
void SetMover(Unit* target) { m_mover = target ? target : this; }

View file

@ -581,7 +581,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
ROLLBACK(DUMP_FILE_BROKEN);
if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId))
if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId,true))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, vals.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);

View file

@ -2389,6 +2389,7 @@ enum SummonType
SUMMON_TYPE_UNKNOWN5 = 409,
SUMMON_TYPE_UNKNOWN2 = 427,
SUMMON_TYPE_POSESSED2 = 428,
SUMMON_TYPE_INFERNO = 711,
SUMMON_TYPE_GUARDIAN2 = 1161,
SUMMON_TYPE_ELEMENTAL = 1561,
SUMMON_TYPE_FORCE_OF_NATURE = 1562

View file

@ -1679,12 +1679,19 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap)
case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
{
// targets the ground, not the units in the area
if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
switch(m_spellInfo->Effect[i])
{
FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
case SPELL_EFFECT_PERSISTENT_AREA_AURA:
break;
case SPELL_EFFECT_SUMMON:
TagUnitMap.push_back(m_caster);
break;
default:
FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
// exclude caster (this can be important if this not original caster)
TagUnitMap.remove(m_caster);
// exclude caster (this can be important if this not original caster)
TagUnitMap.remove(m_caster);
break;
}
break;
}
@ -1705,9 +1712,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap)
case TARGET_ALL_RAID_AROUND_CASTER:
{
if(m_spellInfo->Id == 57669) // Replenishment (special target selection)
FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 10, true, false, false);
else if (m_spellInfo->Id==52759) //Ancestral Awakening (special target selection)
FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 1, true, false, false);
FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 10, true, false, true);
else if (m_spellInfo->Id==52759) // Ancestral Awakening (special target selection)
FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 1, true, false, true);
else
FillRaidOrPartyTargets(TagUnitMap, m_caster, m_caster, radius, true, true, true);
break;
@ -4324,6 +4331,7 @@ SpellCastResult Spell::CheckCast(bool strict)
case SUMMON_TYPE_DEMON:
case SUMMON_TYPE_SUMMON:
case SUMMON_TYPE_ELEMENTAL:
case SUMMON_TYPE_INFERNO:
{
if(m_caster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
@ -4547,16 +4555,16 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED:
case SPELL_AURA_FLY:
case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED:
{
// not allow cast fly spells at old maps by players (all spells is self target)
if(m_caster->GetTypeId() == TYPEID_PLAYER)
// not allow cast fly spells if not have req. skills (all spells is self target)
// allow always ghost flight spells
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isAlive())
{
if( !((Player*)m_caster)->IsAllowUseFlyMountsHere() )
return SPELL_FAILED_NOT_HERE;
if (!((Player*)m_caster)->IsKnowHowFlyIn(m_caster->GetMapId(),zone))
return m_IsTriggeredSpell ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_NOT_HERE;
}
break;
}
case SPELL_AURA_PERIODIC_MANA_LEECH:

View file

@ -1027,7 +1027,7 @@ void Aura::_AddAura()
}
}
void Aura::_RemoveAura()
bool Aura::_RemoveAura()
{
// Remove all triggered by aura spells vs unlimited duration
// except same aura replace case
@ -1051,10 +1051,10 @@ void Aura::_RemoveAura()
uint8 slot = GetAuraSlot();
if(slot >= MAX_AURAS) // slot not set
return;
return false;
if(m_target->GetVisibleAura(slot) == 0)
return;
return false;
bool lastaura = true;
@ -1075,96 +1075,98 @@ void Aura::_RemoveAura()
}
// only remove icon when the last aura of the spell is removed (current aura already removed from list)
if (lastaura)
if (!lastaura)
return false;
// unregister aura diminishing (and store last time)
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(), false);
SetAura(true);
SetAuraFlags(AFLAG_NONE);
SetAuraLevel(0);
SendAuraUpdate(true);
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
//*****************************************************
// Update target aura state flag (at last aura remove)
//*****************************************************
// Enrage aura state
if(m_spellProto->Dispel == DISPEL_ENRAGE)
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
uint32 removeState = 0;
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
switch(m_spellProto->SpellFamilyName)
{
// unregister aura diminishing (and store last time)
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(), false);
SetAura(true);
SetAuraFlags(AFLAG_NONE);
SetAuraLevel(0);
SendAuraUpdate(true);
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
//*****************************************************
// Update target aura state flag (at last aura remove)
//*****************************************************
// Enrage aura state
if(m_spellProto->Dispel == DISPEL_ENRAGE)
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
uint32 removeState = 0;
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
switch(m_spellProto->SpellFamilyName)
case SPELLFAMILY_PALADIN:
if (IsSealSpell(m_spellProto))
removeState = AURA_STATE_JUDGEMENT; // Update Seals information
break;
case SPELLFAMILY_WARLOCK:
// Conflagrate aura state on Immolate and Shadowflame,
if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
(m_spellProto->SpellFamilyFlags2 & 0x00000002))
{
case SPELLFAMILY_PALADIN:
if (IsSealSpell(m_spellProto))
removeState = AURA_STATE_JUDGEMENT; // Update Seals information
break;
case SPELLFAMILY_WARLOCK:
// Conflagrate aura state on Immolate and Shadowflame,
if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
(m_spellProto->SpellFamilyFlags2 & 0x00000002))
{
removeFamilyFlag = UI64LIT(0x0000000000000004);
removeFamilyFlag2 = 0x00000002;
removeState = AURA_STATE_CONFLAGRATE;
}
break;
case SPELLFAMILY_DRUID:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50))
{
removeFamilyFlag = 0x50;
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
}
break;
case SPELLFAMILY_WARRIOR:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000))
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
break;
case SPELLFAMILY_ROGUE:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000))
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
break;
case SPELLFAMILY_HUNTER:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000))
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
removeFamilyFlag = UI64LIT(0x0000000000000004);
removeFamilyFlag2 = 0x00000002;
removeState = AURA_STATE_CONFLAGRATE;
}
// Remove state (but need check other auras for it)
if (removeState)
break;
case SPELLFAMILY_DRUID:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50))
{
bool found = false;
Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
{
found = true;
break;
}
}
// this has been last aura
if(!found)
m_target->ModifyAuraState(AuraState(removeState), false);
removeFamilyFlag = 0x50;
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
}
break;
case SPELLFAMILY_WARRIOR:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000))
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
break;
case SPELLFAMILY_ROGUE:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000))
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
break;
case SPELLFAMILY_HUNTER:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000))
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
// reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto());
}
}
// Remove state (but need check other auras for it)
if (removeState)
{
bool found = false;
Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
{
found = true;
break;
}
}
// this has been last aura
if(!found)
m_target->ModifyAuraState(AuraState(removeState), false);
}
// reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto());
}
return true;
}
void Aura::SendAuraUpdate(bool remove)
@ -3314,9 +3316,17 @@ void Aura::HandleModCharm(bool apply, bool Real)
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
{
//does not appear to have relevance. Why code added initially? See note below at !apply
//to prevent client crash
//m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
// creature with pet number expected have class set
if(m_target->GetByteValue(UNIT_FIELD_BYTES_0, 1)==0)
{
if(cinfo->unit_class==0)
sLog.outErrorDb("Creature (Entry: %u) have unit_class = 0 but used in charmed spell, that will be result client crash.",cinfo->Entry);
else
sLog.outError("Creature (Entry: %u) have unit_class = %u but at charming have class 0!!! that will be result client crash.",cinfo->Entry,cinfo->unit_class);
m_target->SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_MAGE);
}
//just to enable stat window
charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
//if charmed two demons the same session, the 2nd gets the 1st one's name
@ -3352,13 +3362,8 @@ void Aura::HandleModCharm(bool apply, bool Real)
// restore UNIT_FIELD_BYTES_0
if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
{
//does not appear to have relevance. Why code added initially? Class, gender, powertype should be same.
//db field removed and replaced with better way to set class, restore using this if problems
/*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
if(cainfo && cainfo->bytes0 != 0)
m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
else
m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/
// DB must have proper class set in field at loading, not req. restore, including workaround case at apply
// m_target->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->unit_class);
if(m_target->GetCharmInfo())
m_target->GetCharmInfo()->SetPetNumber(0, true);
@ -5555,6 +5560,107 @@ void Aura::HandleShapeshiftBoosts(bool apply)
m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
}
void Aura::HandleSpellSpecificBoosts(bool apply)
{
uint32 spellId1 = 0;
uint32 spellId2 = 0;
uint32 spellId3 = 0;
switch(GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_WARRIOR:
{
if(!apply)
{
// Remove Blood Frenzy only if target no longer has any Deep Wound or Rend (applying is handled by procs)
if (GetSpellProto()->Mechanic != MECHANIC_BLEED)
return;
// If target still has one of Warrior's bleeds, do nothing
Unit::AuraList const& PeriodicDamage = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator i = PeriodicDamage.begin(); i != PeriodicDamage.end(); ++i)
if( (*i)->GetCasterGUID() == GetCasterGUID() &&
(*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR &&
(*i)->GetSpellProto()->Mechanic == MECHANIC_BLEED)
return;
spellId1 = 30069;
spellId2 = 30070;
}
break;
}
case SPELLFAMILY_HUNTER:
{
if(GetSpellSpecific(m_spellProto->Id) != SPELL_ASPECT)
return;
// Aspect of the Dragonhawk dodge
if (GetSpellProto()->SpellFamilyFlags2 & 0x00001000)
spellId1 = 61848;
else
return;
break;
}
case SPELLFAMILY_PALADIN:
{
// Only process on player casting paladin aura
// all aura bonuses applied also in aura area effect way to caster
if (GetCasterGUID() != m_target->GetGUID() || !IS_PLAYER_GUID(GetCasterGUID()))
return;
if (GetSpellSpecific(m_spellProto->Id) != SPELL_AURA)
return;
// Sanctified Retribution and Swift Retribution (they share one aura), but not Retribution Aura (already gets modded)
if ((GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000008))==0)
spellId1 = 63531; // placeholder for talent spell mods
// Improved Concentration Aura (auras bonus)
spellId2 = 63510; // placeholder for talent spell mods
// Improved Devotion Aura (auras bonus)
spellId3 = 63514; // placeholder for talent spell mods
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
if (GetSpellSpecific(m_spellProto->Id) != SPELL_PRESENCE)
return;
// Frost Presence health
if (GetId() == 48263)
spellId1 = 61261;
// Unholy Presence move speed
else if (GetId() == 48265)
spellId1 = 49772;
else
return;
break;
}
default:
return;
}
if (apply)
{
if (spellId1)
m_target->CastSpell(m_target, spellId1, true, NULL, this);
if (spellId2)
m_target->CastSpell(m_target, spellId2, true, NULL, this);
if (spellId3)
m_target->CastSpell(m_target, spellId3, true, NULL, this);
}
else
{
if (spellId1)
m_target->RemoveAurasByCasterSpell(spellId1, GetCasterGUID());
if (spellId2)
m_target->RemoveAurasByCasterSpell(spellId2, GetCasterGUID());
if (spellId3)
m_target->RemoveAurasByCasterSpell(spellId3, GetCasterGUID());
}
}
void Aura::HandleAuraEmpathy(bool apply, bool /*Real*/)
{
if(m_target->GetTypeId() != TYPEID_UNIT)
@ -5751,14 +5857,6 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
void Aura::CleanupTriggeredSpells()
{
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000001000000020)))
{
// Blood Frenzy remove
m_target->RemoveAurasDueToSpell(30069);
m_target->RemoveAurasDueToSpell(30070);
return;
}
uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
if(!tSpellId)
return;

View file

@ -297,7 +297,7 @@ class MANGOS_DLL_SPEC Aura
void ApplyModifier(bool apply, bool Real = false);
void _AddAura();
void _RemoveAura();
bool _RemoveAura();
bool IsUpdated() { return m_updated; }
void SetUpdated(bool val) { m_updated = val; }
@ -311,6 +311,7 @@ class MANGOS_DLL_SPEC Aura
// add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras
void HandleShapeshiftBoosts(bool apply);
void HandleSpellSpecificBoosts(bool apply);
// Allow Apply Aura Handler to modify and access m_AuraDRGroup
void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }

View file

@ -1856,6 +1856,28 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(m_caster, 51209, true);
return;
}
// Death Strike
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
{
uint32 count = 0;
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
{
if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
itr->second->GetCasterGUID() == m_caster->GetGUID() &&
IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
{
++count;
// max. 15%
if(count == 3)
break;
}
}
int32 bp = count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[0] / 100;
m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
return;
}
break;
}
@ -1942,7 +1964,7 @@ void Spell::EffectTriggerSpell(uint32 i)
// special cases
switch(triggered_spell_id)
{
// Vanish
// Vanish (not exist)
case 18461:
{
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
@ -1991,7 +2013,8 @@ void Spell::EffectTriggerSpell(uint32 i)
// Brittle Armor - (need add max stack of 24575 Brittle Armor)
case 29284:
{
const SpellEntry *spell = sSpellStore.LookupEntry(24575);
// Brittle Armor
SpellEntry const* spell = sSpellStore.LookupEntry(24575);
if (!spell)
return;
@ -2002,7 +2025,8 @@ void Spell::EffectTriggerSpell(uint32 i)
// Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
case 29286:
{
const SpellEntry *spell = sSpellStore.LookupEntry(26464);
// Mercurial Shield
SpellEntry const* spell = sSpellStore.LookupEntry(26464);
if (!spell)
return;
@ -2017,7 +2041,7 @@ void Spell::EffectTriggerSpell(uint32 i)
return;
}
// Cloak of Shadows
case 35729 :
case 35729:
{
Unit::AuraMap& Auras = m_caster->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
@ -2348,7 +2372,7 @@ void Spell::EffectApplyAura(uint32 i)
return;
// ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
if( !unitTarget->isAlive() && !IsDeathPersistentSpell(m_spellInfo) &&
(unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
return;
@ -2391,7 +2415,7 @@ void Spell::EffectApplyAura(uint32 i)
return;
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000000000)))
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000002000000000)))
m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
}
@ -3260,12 +3284,17 @@ void Spell::EffectSummonType(uint32 i)
case SUMMON_TYPE_POSESSED2:
case SUMMON_TYPE_FORCE_OF_NATURE:
case SUMMON_TYPE_GUARDIAN2:
EffectSummonGuardian(i);
// Jewelery statue case (totem like)
if(m_spellInfo->SpellIconID == 2056)
EffectSummonTotem(i);
else
EffectSummonGuardian(i);
break;
case SUMMON_TYPE_WILD:
EffectSummonWild(i);
break;
case SUMMON_TYPE_DEMON:
case SUMMON_TYPE_INFERNO:
EffectSummonDemon(i);
break;
case SUMMON_TYPE_SUMMON:
@ -3311,6 +3340,16 @@ void Spell::EffectSummon(uint32 i)
if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
{
// Summon in dest location
float x, y, z;
if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
{
x = m_targets.m_destX;
y = m_targets.m_destY;
z = m_targets.m_destZ;
spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
}
// set timer for unsummon
int32 duration = GetSpellDuration(m_spellInfo);
if(duration > 0)
@ -3508,25 +3547,12 @@ void Spell::EffectDispel(uint32 i)
}
m_caster->SendMessageToSet(&data, true);
// On succes dispel
// On success dispel
// Devour Magic
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
{
uint32 heal_spell = 0;
switch (m_spellInfo->Id)
{
case 19505: heal_spell = 19658; break;
case 19731: heal_spell = 19732; break;
case 19734: heal_spell = 19733; break;
case 19736: heal_spell = 19735; break;
case 27276: heal_spell = 27278; break;
case 27277: heal_spell = 27279; break;
default:
sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
break;
}
if (heal_spell)
m_caster->CastSpell(m_caster, heal_spell, true);
int32 heal_amount = m_spellInfo->CalculateSimpleValue(1);
m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
}
}
// Send fail log to client
@ -3699,13 +3725,6 @@ void Spell::EffectSummonGuardian(uint32 i)
if(!pet_entry)
return;
// Jewelery statue case (totem like)
if(m_spellInfo->SpellIconID == 2056)
{
EffectSummonTotem(i);
return;
}
// set timer for unsummon
int32 duration = GetSpellDuration(m_spellInfo);
@ -4501,6 +4520,38 @@ void Spell::EffectWeaponDmg(uint32 i)
}
}
}
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
// Blood Strike, Heart Strike, Obliterate
// Blood-Caked Strike, Scourge Strike
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
{
uint32 count = 0;
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
{
if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
itr->second->GetCasterGUID() == m_caster->GetGUID() &&
IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
++count;
}
if (count)
{
// Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
double bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? 0 : 2, unitTarget) / 100.0f;
// Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
m_spellInfo->SpellIconID == 1736)
bonus /= 2.0f;
totalDamagePercentMod += bonus;
}
}
break;
}
}
@ -5173,6 +5224,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
{
uint32 spellId = 0;
int32 basePoint = 0;
Unit* target = unitTarget;
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
@ -5197,6 +5249,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
{
spellId = 53358; // 53358 Chimera Shot - Viper
basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
target = m_caster;
}
// Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
if (familyFlag & UI64LIT(0x0000000000008000))
@ -5209,7 +5262,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
//}
}
if (spellId)
m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
return;
}
default:
@ -5219,8 +5272,8 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
case SPELLFAMILY_PALADIN:
{
// Judgement
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000800000))
// Judgement (seal trigger)
if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
{
if(!unitTarget || !unitTarget->isAlive())
return;
@ -5230,12 +5283,12 @@ void Spell::EffectScriptEffect(uint32 effIndex)
// Judgement self add switch
switch (m_spellInfo->Id)
{
case 41467: break; // Judgement
case 53407: spellId1 = 20184; break; // Judgement of Justice
case 20271: // Judgement of Light
case 57774: spellId1 = 20185; break; // Judgement of Light
case 53408: spellId1 = 20186; break; // Judgement of Wisdom
default:
sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
return;
}
// all seals have aura dummy in 2 effect
@ -6219,7 +6272,7 @@ void Spell::EffectSummonDeadPet(uint32 /*i*/)
pet->AIM_Initialize();
_player->PetSpellInitialize();
// _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
}
@ -6503,6 +6556,9 @@ void Spell::EffectSummonDemon(uint32 i)
int32 amount = damage > 0 ? damage : 1;
if (m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_INFERNO)
amount = 1;
for(int32 count = 0; count < amount; ++count)
{
float px, py, pz;
@ -6535,13 +6591,15 @@ void Spell::EffectSummonDemon(uint32 i)
// TODO: Add damage/mana/hp according to level
// Enslave demon effect, without mana cost and cooldown
if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
{
// Enslave demon effect, without mana cost and cooldown
m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
// Inferno effect
Charmed->CastSpell(Charmed, 22703, true, 0);
// Inferno effect for non player calls
if (m_spellInfo->EffectMiscValueB[i]!=SUMMON_TYPE_INFERNO)
Charmed->CastSpell(Charmed, 22703, true, 0);
}
}
}

View file

@ -188,6 +188,9 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
if (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000011010002))
return SPELL_BLESSING;
if (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002190))
return SPELL_HAND;
if ((spellInfo->SpellFamilyFlags & UI64LIT(0x00000820180400)) && (spellInfo->AttributesEx3 & 0x200))
return SPELL_JUDGEMENT;
@ -238,6 +241,7 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_PRESENCE:
case SPELL_HAND:
return spellSpec1==spellSpec2;
case SPELL_BATTLE_ELIXIR:
return spellSpec2==SPELL_BATTLE_ELIXIR
@ -261,6 +265,7 @@ bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSp
case SPELL_BLESSING:
case SPELL_AURA:
case SPELL_CURSE:
case SPELL_HAND:
return spellId_spec==i_spellId_spec;
default:
return false;
@ -1463,9 +1468,15 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN )
{
// Paladin Seals
if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) )
if (IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2))
return true;
// Swift Retribution / Improved Devotion Aura (talents) and Paladin Auras
if ((spellInfo_1->SpellFamilyFlags2 & 0x00000020) && (spellInfo_2->SpellIconID == 291 || spellInfo_2->SpellIconID == 3028) ||
(spellInfo_2->SpellFamilyFlags2 & 0x00000020) && (spellInfo_1->SpellIconID == 291 || spellInfo_1->SpellIconID == 3028))
return false;
}
// Combustion and Fire Protection Aura (multi-family check)
if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 )
return false;
@ -1494,6 +1505,18 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 )
return false;
break;
case SPELLFAMILY_DEATHKNIGHT:
if (spellInfo_2->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
{
// Frost Presence and Frost Presence (triggered)
if( spellInfo_1->SpellIconID == 2632 && spellInfo_2->SpellIconID == 2632 )
return false;
// Unholy Presence and Unholy Presence (triggered)
if( spellInfo_1->SpellIconID == 2633 && spellInfo_2->SpellIconID == 2633 )
return false;
}
break;
default:
break;
}
@ -2529,10 +2552,15 @@ void SpellMgr::LoadSpellAreas()
continue;
}
if(spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_DUMMY && spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_PHASE)
switch(spellInfo->EffectApplyAuraName[0])
{
sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase aura in effect 0", spell,abs(spellArea.auraSpell));
continue;
case SPELL_AURA_DUMMY:
case SPELL_AURA_PHASE:
case SPELL_AURA_GHOST:
break;
default:
sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase/ghost aura in effect 0", spell,abs(spellArea.auraSpell));
continue;
}
if(abs(spellArea.auraSpell)==spellArea.spellId)
@ -2625,8 +2653,12 @@ void SpellMgr::LoadSpellAreas()
SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player)
{
// allow in GM-mode
if (player && player->isGameMaster())
return SPELL_CAST_OK;
// normal case
if( spellInfo->AreaGroupId > 0)
if (spellInfo->AreaGroupId > 0)
{
bool found = false;
AreaGroupEntry const* groupEntry = sAreaGroupStore.LookupEntry(spellInfo->AreaGroupId);
@ -2645,9 +2677,18 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
return SPELL_FAILED_INCORRECT_AREA;
}
// continent limitation (virtual continent)
if (spellInfo->AttributesEx4 & SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND)
{
uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id);
MapEntry const* mapEntry = sMapStore.LookupEntry(v_map);
if(!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent())
return SPELL_FAILED_INCORRECT_AREA;
}
// DB base check (if non empty then must fit at least single for allow)
SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id);
if(saBounds.first != saBounds.second)
if (saBounds.first != saBounds.second)
{
for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
@ -2674,21 +2715,21 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
case 44535: // Spirit Heal (mana)
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
return mapEntry->IsBattleGround() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 44521: // Preparation
{
if(!player)
if (!player)
return SPELL_FAILED_REQUIRES_AREA;
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
if(!mapEntry->IsBattleGround())
if (!mapEntry->IsBattleGround())
return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround();
@ -2700,21 +2741,21 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
case 35775: // Green Team (Horde)
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
return mapEntry->IsBattleArena() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 32727: // Arena Preparation
{
if(!player)
if (!player)
return SPELL_FAILED_REQUIRES_AREA;
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
if(!mapEntry->IsBattleArena())
if (!mapEntry->IsBattleArena())
return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround();

View file

@ -40,7 +40,8 @@ struct SpellModifier;
enum SpellCategories
{
SPELLCATEGORY_HEALTH_MANA_POTIONS = 4,
SPELLCATEGORY_DEVOUR_MAGIC = 12
SPELLCATEGORY_DEVOUR_MAGIC = 12,
SPELLCATEGORY_JUDGEMENT = 1210, // Judgement (seal trigger)
};
enum SpellFamilyNames
@ -96,7 +97,8 @@ enum SpellSpecific
SPELL_BATTLE_ELIXIR = 14,
SPELL_GUARDIAN_ELIXIR = 15,
SPELL_FLASK_ELIXIR = 16,
SPELL_PRESENCE = 17
SPELL_PRESENCE = 17,
SPELL_HAND = 18,
};
SpellSpecific GetSpellSpecific(uint32 spellId);
@ -122,7 +124,7 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo);
inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
{
for(int i= 0; i < 3; ++i)
for(int i = 0; i < 3; ++i)
if(SpellEffects(spellInfo->Effect[i])==effect)
return true;
return false;
@ -130,12 +132,20 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura)
{
for(int i= 0; i < 3; ++i)
for(int i = 0; i < 3; ++i)
if(AuraType(spellInfo->EffectApplyAuraName[i])==aura)
return true;
return false;
}
inline bool IsSpellLastAuraEffect(SpellEntry const *spellInfo, int effecIdx)
{
for(int i = effecIdx+1; i < 3; ++i)
if(spellInfo->EffectApplyAuraName[i])
return false;
return true;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
inline bool IsSealSpell(SpellEntry const *spellInfo)

View file

@ -647,7 +647,11 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(!cVictim->isPet())
{
cVictim->DeleteThreatList();
cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
// only lootable if it has loot or can drop gold
if(cVictim->GetCreatureInfo()->lootid || cVictim->GetCreatureInfo()->maxgold > 0)
cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
else
cVictim->lootForBody = true; // needed for skinning
}
// Call creature just died function
if (cVictim->AI())
@ -3402,8 +3406,10 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_
bool Unit::AddAura(Aura *Aur)
{
SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
// ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
if( !isAlive() && Aur->GetId() != 20584 && Aur->GetId() != 8326 && Aur->GetId() != 2584 &&
if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) &&
(GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) )
{
delete Aur;
@ -3419,7 +3425,6 @@ bool Unit::AddAura(Aura *Aur)
return false;
}
SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
AuraType aurName = Aur->GetModifier()->m_auraname;
spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex());
@ -3531,6 +3536,10 @@ bool Unit::AddAura(Aura *Aur)
Aur->ApplyModifier(true,true);
sLog.outDebug("Aura %u now is in use", aurName);
if(IsSpellLastAuraEffect(aurSpellInfo,Aur->GetEffIndex()))
Aur->HandleSpellSpecificBoosts(true);
return true;
}
@ -3876,13 +3885,24 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flags)
}
}
void Unit::RemoveNotOwnSingleTargetAuras()
void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase)
{
// single target auras from other casters
for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
{
if (iter->second->GetCasterGUID()!=GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto()))
RemoveAura(iter);
{
if(!newPhase)
RemoveAura(iter);
else
{
Unit* caster = iter->second->GetCaster();
if(!caster || !caster->InSamePhase(newPhase))
RemoveAura(iter);
else
++iter;
}
}
else
++iter;
}
@ -3892,7 +3912,7 @@ void Unit::RemoveNotOwnSingleTargetAuras()
for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end(); )
{
Aura* aura = *iter;
if (aura->GetTarget() != this)
if (aura->GetTarget() != this && !aura->GetTarget()->InSamePhase(newPhase))
{
scAuras.erase(iter); // explicitly remove, instead waiting remove in RemoveAura
aura->GetTarget()->RemoveAura(aura);
@ -3957,7 +3977,14 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
Aur->ApplyModifier(false,true);
Aur->_RemoveAura();
if(Aur->_RemoveAura())
{
// last aura in stack removed
if(IsSpellLastAuraEffect(Aur->GetSpellProto(),Aur->GetEffIndex()))
Aur->HandleSpellSpecificBoosts(false);
}
delete Aur;
if(caster_channeled)
@ -5676,8 +5703,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 40471;
chance = 15.0f;
}
// Judgement
else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000800000))
// Judgement (any)
else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT)
{
triggered_spell_id = 40472;
chance = 50.0f;
@ -5883,6 +5910,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 58879;
break;
}
// Shaman T8 Elemental 4P Bonus
case 64928:
{
basepoints0 = int32( triggerAmount * damage / 100 );
triggered_spell_id = 64930; // Electrified
break;
}
}
// Storm, Earth and Fire
if (dummySpell->SpellIconID == 3063)
@ -6114,6 +6148,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 50526;
break;
}
// Blood-Caked Blade
if (dummySpell->SpellIconID == 138)
{
triggered_spell_id = dummySpell->EffectTriggerSpell[effIndex];
break;
}
break;
}
default:
@ -11821,6 +11861,12 @@ void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo)
void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
{
if(newPhaseMask==GetPhaseMask())
return;
if(IsInWorld())
RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target
WorldObject::SetPhaseMask(newPhaseMask,update);
if(IsInWorld())

View file

@ -1209,7 +1209,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
void RemoveAurasDueToSpellByCancel(uint32 spellId);
void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo);
void RemoveNotOwnSingleTargetAuras();
void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
void RemoveSpellsCausingAura(AuraType auraType);
void RemoveRankAurasDueToSpell(uint32 spellId);