aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Common.h1
-rw-r--r--src/common/Metric/Metric.cpp2
-rw-r--r--src/common/Metric/Metric.h8
-rw-r--r--src/common/Utilities/Util.h32
-rw-r--r--src/server/authserver/Server/AuthSession.cpp73
-rw-r--r--src/server/authserver/Server/AuthSession.h10
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp5
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp26
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h1
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp12
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.h2
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.cpp5
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp2
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp1
-rw-r--r--src/server/game/Conditions/ConditionMgr.h2
-rw-r--r--src/server/game/DataStores/DBCStructure.h11
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp1
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp61
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h7
-rw-r--r--src/server/game/Entities/Item/Item.cpp12
-rw-r--r--src/server/game/Entities/Object/Object.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp275
-rw-r--r--src/server/game/Entities/Player/Player.h6
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp6
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp25
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp834
-rw-r--r--src/server/game/Entities/Unit/Unit.h54
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp5
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h324
-rw-r--r--src/server/game/Guilds/Guild.cpp285
-rw-r--r--src/server/game/Guilds/Guild.h1138
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp7
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp16
-rw-r--r--src/server/game/Loot/LootMgr.cpp133
-rw-r--r--src/server/game/Loot/LootMgr.h38
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h13
-rw-r--r--src/server/game/Movement/MotionMaster.cpp471
-rw-r--r--src/server/game/Movement/MotionMaster.h165
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp21
-rw-r--r--src/server/game/Scripting/ScriptMgr.h5
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp605
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp188
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h6
-rw-r--r--src/server/game/Spells/Spell.cpp721
-rw-r--r--src/server/game/Spells/Spell.h41
-rw-r--r--src/server/game/Spells/SpellEffects.cpp119
-rw-r--r--src/server/game/Spells/SpellInfo.cpp558
-rw-r--r--src/server/game/Spells/SpellInfo.h31
-rw-r--r--src/server/game/Spells/SpellMgr.cpp100
-rw-r--r--src/server/game/Spells/SpellMgr.h17
-rw-r--r--src/server/game/Spells/SpellScript.cpp68
-rw-r--r--src/server/game/Spells/SpellScript.h8
-rw-r--r--src/server/game/World/World.cpp9
-rw-r--r--src/server/scripts/Commands/cs_cast.cpp15
-rw-r--r--src/server/scripts/Commands/cs_guild.cpp9
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp35
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp119
-rw-r--r--src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h4
-rw-r--r--src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp140
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp4
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp5
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp6
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp4
-rw-r--r--src/server/scripts/Northrend/zone_dragonblight.cpp26
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp1
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.cpp2
-rw-r--r--src/server/scripts/Outland/BlackTemple/black_temple.h18
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_illidan.cpp24
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp93
-rw-r--r--src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp189
-rw-r--r--src/server/scripts/Outland/boss_doomlord_kazzak.cpp4
-rw-r--r--src/server/scripts/Outland/zone_hellfire_peninsula.cpp67
-rw-r--r--src/server/scripts/Pet/pet_hunter.cpp31
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp28
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp65
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp4
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp140
-rw-r--r--src/server/scripts/Spells/spell_item.cpp67
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp20
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp68
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp55
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp10
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp91
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp22
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp10
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq.cpp6
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq04.h12
93 files changed, 4238 insertions, 3740 deletions
diff --git a/src/common/Common.h b/src/common/Common.h
index aa04abacd30..af9b9b17321 100644
--- a/src/common/Common.h
+++ b/src/common/Common.h
@@ -35,6 +35,7 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include <numeric>
#include <cmath>
#include <cstdio>
diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp
index 9484cebcc72..cb6b3b1217b 100644
--- a/src/common/Metric/Metric.cpp
+++ b/src/common/Metric/Metric.cpp
@@ -22,7 +22,7 @@
void Metric::Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger)
{
- _realmName = realmName;
+ _realmName = FormatInfluxDBTagValue(realmName);
_batchTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService);
_overallStatusTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService);
_overallStatusLogger = overallStatusLogger;
diff --git a/src/common/Metric/Metric.h b/src/common/Metric/Metric.h
index 1855e1d0098..9230983da4d 100644
--- a/src/common/Metric/Metric.h
+++ b/src/common/Metric/Metric.h
@@ -79,6 +79,14 @@ private:
static std::string FormatInfluxDBValue(double value) { return std::to_string(value); }
static std::string FormatInfluxDBValue(float value) { return FormatInfluxDBValue(double(value)); }
+ static std::string FormatInfluxDBTagValue(std::string const& value)
+ {
+ // ToDo: should handle '=' and ',' characters too
+ return boost::replace_all_copy(value, " ", "\\ ");
+ }
+
+ // ToDo: should format TagKey and FieldKey too in the same way as TagValue
+
public:
static Metric* instance();
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index fc322a89583..88708a79cd6 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -327,33 +327,35 @@ TC_COMMON_API bool StringToBool(std::string const& str);
// simple class for not-modifyable list
template <typename T>
-class HookList
+class HookList final
{
- typedef typename std::list<T>::iterator ListIterator;
private:
- typename std::list<T> m_list;
+ typedef std::vector<T> ContainerType;
+
+ ContainerType _container;
+
public:
- HookList<T> & operator+=(T t)
- {
- m_list.push_back(t);
- return *this;
- }
- HookList<T> & operator-=(T t)
+ typedef typename ContainerType::iterator iterator;
+
+ HookList<T>& operator+=(T t)
{
- m_list.remove(t);
+ _container.push_back(t);
return *this;
}
+
size_t size()
{
- return m_list.size();
+ return _container.size();
}
- ListIterator begin()
+
+ iterator begin()
{
- return m_list.begin();
+ return _container.begin();
}
- ListIterator end()
+
+ iterator end()
{
- return m_list.end();
+ return _container.end();
}
};
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index 45c2b61436f..b139d50ef8a 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -118,10 +118,10 @@ std::unordered_map<uint8, AuthHandler> AuthSession::InitHandlers()
{
std::unordered_map<uint8, AuthHandler> handlers;
- handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CONNECTED, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge };
- handlers[AUTH_LOGON_PROOF] = { STATUS_CONNECTED, sizeof(AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof };
- handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CONNECTED, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge };
- handlers[AUTH_RECONNECT_PROOF] = { STATUS_CONNECTED, sizeof(AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof };
+ handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge };
+ handlers[AUTH_LOGON_PROOF] = { STATUS_LOGON_PROOF, sizeof(AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof };
+ handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge };
+ handlers[AUTH_RECONNECT_PROOF] = { STATUS_RECONNECT_PROOF, sizeof(AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof };
handlers[REALM_LIST] = { STATUS_AUTHED, REALM_LIST_PACKET_SIZE, &AuthSession::HandleRealmList };
return handlers;
@@ -154,8 +154,7 @@ void AccountInfo::LoadResult(Field* fields)
}
AuthSession::AuthSession(tcp::socket&& socket) : Socket(std::move(socket)),
-_sentChallenge(false), _sentProof(false),
-_status(STATUS_CONNECTED), _build(0), _expversion(0)
+_status(STATUS_CHALLENGE), _build(0), _expversion(0)
{
N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
g.SetDword(7);
@@ -285,10 +284,7 @@ void AuthSession::SendPacket(ByteBuffer& packet)
bool AuthSession::HandleLogonChallenge()
{
- if (_sentChallenge)
- return false;
-
- _sentChallenge = true;
+ _status = STATUS_CLOSED;
sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer().GetReadPointer());
if (challenge->size - (sizeof(sAuthLogonChallenge_C) - AUTH_LOGON_CHALLENGE_INITIAL_SIZE - 1) != challenge->I_len)
@@ -428,7 +424,10 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result)
// Fill the response packet with the result
if (AuthHelper::IsAcceptedClientBuild(_build))
+ {
pkt << uint8(WOW_SUCCESS);
+ _status = STATUS_LOGON_PROOF;
+ }
else
pkt << uint8(WOW_FAIL_VERSION_INVALID);
@@ -477,10 +476,7 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result)
bool AuthSession::HandleLogonProof()
{
TC_LOG_DEBUG("server.authserver", "Entering _HandleLogonProof");
- if (_sentProof)
- return false;
-
- _sentProof = true;
+ _status = STATUS_CLOSED;
// Read the packet
sAuthLogonProof_C *logonProof = reinterpret_cast<sAuthLogonProof_C*>(GetReadBuffer().GetReadPointer());
@@ -500,9 +496,7 @@ bool AuthSession::HandleLogonProof()
// SRP safeguard: abort if A == 0
if (A.IsZero())
- {
return false;
- }
SHA1Hash sha;
sha.UpdateBigNumbers(&A, &B, NULL);
@@ -571,24 +565,6 @@ bool AuthSession::HandleLogonProof()
// Check if SRP6 results match (password is correct), else send an error
if (!memcmp(M.AsByteArray(sha.GetLength()).get(), logonProof->M1, 20))
{
- TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str());
-
- // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
- // No SQL injection (escaped user name) and IP address as received by socket
-
- PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
- stmt->setString(0, K.AsHexStr());
- stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
- stmt->setUInt32(2, GetLocaleByName(_localizationName));
- stmt->setString(3, _os);
- stmt->setString(4, _accountInfo.Login);
- LoginDatabase.DirectExecute(stmt);
-
- // Finish SRP6 and send the final result to the client
- sha.Initialize();
- sha.UpdateBigNumbers(&A, &M, &K, NULL);
- sha.Finalize();
-
// Check auth token
if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty())
{
@@ -610,6 +586,24 @@ bool AuthSession::HandleLogonProof()
}
}
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str());
+
+ // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
+ // No SQL injection (escaped user name) and IP address as received by socket
+
+ PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
+ stmt->setString(0, K.AsHexStr());
+ stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
+ stmt->setUInt32(2, GetLocaleByName(_localizationName));
+ stmt->setString(3, _os);
+ stmt->setString(4, _accountInfo.Login);
+ LoginDatabase.DirectExecute(stmt);
+
+ // Finish SRP6 and send the final result to the client
+ sha.Initialize();
+ sha.UpdateBigNumbers(&A, &M, &K, NULL);
+ sha.Finalize();
+
ByteBuffer packet;
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
{
@@ -705,10 +699,7 @@ bool AuthSession::HandleLogonProof()
bool AuthSession::HandleReconnectChallenge()
{
- if (_sentChallenge)
- return false;
-
- _sentChallenge = true;
+ _status = STATUS_CLOSED;
sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer().GetReadPointer());
if (challenge->size - (sizeof(sAuthLogonChallenge_C) - AUTH_LOGON_CHALLENGE_INITIAL_SIZE - 1) != challenge->I_len)
@@ -768,6 +759,7 @@ void AuthSession::ReconnectChallengeCallback(PreparedQueryResult result)
_accountInfo.LoadResult(fields);
K.SetHexStr(fields[9].GetCString());
_reconnectProof.SetRand(16 * 8);
+ _status = STATUS_RECONNECT_PROOF;
pkt << uint8(WOW_SUCCESS);
pkt.append(_reconnectProof.AsByteArray(16).get(), 16); // 16 bytes random
@@ -779,10 +771,7 @@ void AuthSession::ReconnectChallengeCallback(PreparedQueryResult result)
bool AuthSession::HandleReconnectProof()
{
TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectProof");
- if (_sentProof)
- return false;
-
- _sentProof = true;
+ _status = STATUS_CLOSED;
sAuthReconnectProof_C *reconnectProof = reinterpret_cast<sAuthReconnectProof_C*>(GetReadBuffer().GetReadPointer());
diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h
index 027011629eb..98d2cb9fcdb 100644
--- a/src/server/authserver/Server/AuthSession.h
+++ b/src/server/authserver/Server/AuthSession.h
@@ -34,8 +34,11 @@ struct AuthHandler;
enum AuthStatus
{
- STATUS_CONNECTED = 0,
- STATUS_AUTHED
+ STATUS_CHALLENGE = 0,
+ STATUS_LOGON_PROOF,
+ STATUS_RECONNECT_PROOF,
+ STATUS_AUTHED,
+ STATUS_CLOSED
};
struct AccountInfo
@@ -90,9 +93,6 @@ private:
BigNumber K;
BigNumber _reconnectProof;
- bool _sentChallenge;
- bool _sentProof;
-
AuthStatus _status;
AccountInfo _accountInfo;
std::string _tokenKey;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index bbf03248ec2..6122e5aca7b 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -243,8 +243,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_EQUIP_SET, "DELETE FROM character_equipmentsets WHERE setguid=?", CONNECTION_ASYNC);
// Auras
- PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
// Account data
PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_ASYNC);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index d3d2be4aed5..48315eb44ed 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1671,6 +1671,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
ResetBaseObject();
break;
case SMART_ACTION_CALL_SCRIPT_RESET:
+ SetPhase(0);
OnReset();
break;
case SMART_ACTION_SET_RANGED_MOVEMENT:
@@ -3587,10 +3588,6 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
}
mEvents.push_back((*i));//NOTE: 'world(0)' events still get processed in ANY instance mode
}
- if (mEvents.empty() && obj)
- TC_LOG_ERROR("sql.sql", "SmartScript: Entry %u has events but no events added to list because of instance flags.", obj->GetEntry());
- if (mEvents.empty() && at)
- TC_LOG_ERROR("sql.sql", "SmartScript: AreaTrigger %u has events but no events added to list because of instance flags. NOTE: triggers can not handle any instance flags.", at->id);
}
void SmartScript::GetScript()
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
index 7016494de0e..8df95619ae5 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
@@ -419,6 +419,7 @@ bool BattlefieldWG::SetupBattlefield()
m_StartGroupingTimer = 15 * MINUTE * IN_MILLISECONDS;
m_StartGrouping = false;
+ m_tenacityTeam = TEAM_NEUTRAL;
m_tenacityStack = 0;
KickPosition.Relocate(5728.117f, 2714.346f, 697.733f, 0);
@@ -1084,6 +1085,7 @@ void BattlefieldWG::OnPlayerLeaveWar(Player* player)
player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT);
player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT);
player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT);
+ UpdateTenacity();
}
void BattlefieldWG::OnPlayerLeaveZone(Player* player)
@@ -1289,7 +1291,6 @@ void BattlefieldWG::UpdateVehicleCountWG()
void BattlefieldWG::UpdateTenacity()
{
- TeamId team = TEAM_NEUTRAL;
uint32 alliancePlayers = m_PlayersInWar[TEAM_ALLIANCE].size();
uint32 hordePlayers = m_PlayersInWar[TEAM_HORDE].size();
int32 newStack = 0;
@@ -1305,21 +1306,16 @@ void BattlefieldWG::UpdateTenacity()
if (newStack == int32(m_tenacityStack))
return;
- if (m_tenacityStack > 0 && newStack <= 0) // old buff was on alliance
- team = TEAM_ALLIANCE;
- else if (newStack >= 0) // old buff was on horde
- team = TEAM_HORDE;
-
m_tenacityStack = newStack;
// Remove old buff
- if (team != TEAM_NEUTRAL)
+ if (m_tenacityTeam != TEAM_NEUTRAL)
{
- for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ for (auto itr = m_players[m_tenacityTeam].begin(); itr != m_players[m_tenacityTeam].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr))
if (player->getLevel() >= m_MinLevel)
player->RemoveAurasDueToSpell(SPELL_TENACITY);
- for (auto itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr)
if (Creature* creature = GetCreature(*itr))
creature->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE);
}
@@ -1327,7 +1323,7 @@ void BattlefieldWG::UpdateTenacity()
// Apply new buff
if (newStack)
{
- team = newStack > 0 ? TEAM_ALLIANCE : TEAM_HORDE;
+ m_tenacityTeam = newStack > 0 ? TEAM_ALLIANCE : TEAM_HORDE;
if (newStack < 0)
newStack = -newStack;
@@ -1342,25 +1338,27 @@ void BattlefieldWG::UpdateTenacity()
if (newStack < 5)
buff_honor = 0;
- for (auto itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ for (auto itr = m_PlayersInWar[m_tenacityTeam].begin(); itr != m_PlayersInWar[m_tenacityTeam].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->SetAuraStack(SPELL_TENACITY, player, newStack);
- for (auto itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr)
if (Creature* creature = GetCreature(*itr))
creature->SetAuraStack(SPELL_TENACITY_VEHICLE, creature, newStack);
if (buff_honor != 0)
{
- for (auto itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ for (auto itr = m_PlayersInWar[m_tenacityTeam].begin(); itr != m_PlayersInWar[m_tenacityTeam].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->CastSpell(player, buff_honor, true);
- for (auto itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr)
if (Creature* creature = GetCreature(*itr))
creature->CastSpell(creature, buff_honor, true);
}
}
+ else
+ m_tenacityTeam = TEAM_NEUTRAL;
}
WintergraspCapturePoint::WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl) : BfCapturePoint(battlefield)
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index 7769a9b4b6d..3bd719c1a60 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -393,6 +393,7 @@ class TC_GAME_API BattlefieldWG : public Battlefield
GuidUnorderedSet m_vehicles[BG_TEAMS_COUNT];
GuidVector CanonList;
+ TeamId m_tenacityTeam;
uint32 m_tenacityStack;
uint32 m_saveTimer;
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index ec007df6b6c..f1747bc0d00 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -899,6 +899,10 @@ void ArenaTeam::SaveToDB()
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
+ // Save the effort and go
+ if (itr->WeekGames == 0)
+ continue;
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_MEMBER);
stmt->setUInt16(0, itr->PersonalRating);
stmt->setUInt16(1, itr->WeekGames);
@@ -919,8 +923,12 @@ void ArenaTeam::SaveToDB()
CharacterDatabase.CommitTransaction(trans);
}
-void ArenaTeam::FinishWeek()
+bool ArenaTeam::FinishWeek()
{
+ // No need to go further than this
+ if (Stats.WeekGames == 0)
+ return false;
+
// Reset team stats
Stats.WeekGames = 0;
Stats.WeekWins = 0;
@@ -931,6 +939,8 @@ void ArenaTeam::FinishWeek()
itr->WeekGames = 0;
itr->WeekWins = 0;
}
+
+ return true;
}
bool ArenaTeam::IsFighting() const
diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h
index 7e9f490bff9..e283197346c 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.h
+++ b/src/server/game/Battlegrounds/ArenaTeam.h
@@ -180,7 +180,7 @@ class TC_GAME_API ArenaTeam
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
- void FinishWeek();
+ bool FinishWeek(); // returns true if arena team played this week
void FinishGame(int32 mod);
protected:
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
index 37e26d7e448..6fe11e3bd8c 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
@@ -186,8 +186,9 @@ void ArenaTeamMgr::DistributeArenaPoints()
{
if (ArenaTeam* at = titr->second)
{
- at->FinishWeek();
- at->SaveToDB();
+ if (at->FinishWeek())
+ at->SaveToDB();
+
at->NotifyStatsChanged();
}
}
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 753d0f92ef3..1ae610ecf68 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -843,7 +843,7 @@ void BattlegroundMgr::ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 ar
{
//This method must be atomic, @todo add mutex
//we will use only 1 number created of bgTypeId and bracket_id
- uint64 const scheduleId = ((uint64)arenaMatchmakerRating << 32) | (uint32(arenaType) << 24) | (bgQueueTypeId << 16) | (bgTypeId << 8) | bracket_id;
+ uint64 const scheduleId = ((uint64)arenaMatchmakerRating << 32) | ((uint64)arenaType << 24) | ((uint64)bgQueueTypeId << 16) | ((uint64)bgTypeId << 8) | (uint64)bracket_id;
if (std::find(m_QueueUpdateScheduler.begin(), m_QueueUpdateScheduler.end(), scheduleId) == m_QueueUpdateScheduler.end())
m_QueueUpdateScheduler.push_back(scheduleId);
}
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 85d03ef6b1f..afaa0063a45 100644
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -55,7 +55,6 @@ Channel::Channel(uint32 channelId, uint32 team /*= 0*/, AreaTableEntry const* zo
_channelFlags |= CHANNEL_FLAG_NOT_LFG;
}
-
Channel::Channel(std::string const& name, uint32 team /*= 0*/) :
_announceEnabled(true),
_ownershipEnabled(true),
@@ -749,7 +748,6 @@ void Channel::Say(ObjectGuid guid, std::string const& what, uint32 lang) const
};
SendToAll(builder, !info.IsModerator() ? guid : ObjectGuid::Empty);
-
}
void Channel::Invite(Player const* player, std::string const& newname)
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index c859031b573..7ee775ec676 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1671,7 +1671,6 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
break;
}
case CONDITION_SOURCE_TYPE_QUEST_ACCEPT:
- case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK:
if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
{
TC_LOG_ERROR("sql.sql", "%s SourceEntry specifies non-existing quest, skipped.", cond->ToString().c_str());
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 7bda1376a0d..4d32c3f36dc 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -130,7 +130,7 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_SPELL = 17,
CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT = 18,
CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19,
- CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20,
+ // Condition source type 20 unused
CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21,
CONDITION_SOURCE_TYPE_SMART_EVENT = 22,
CONDITION_SOURCE_TYPE_NPC_VENDOR = 23,
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index a6445b27a44..8431f369b69 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -192,6 +192,17 @@ struct AreaTableEntry
return true;
return (flags & AREA_FLAG_SANCTUARY) != 0;
}
+
+ bool IsFlyable() const
+ {
+ if (flags & AREA_FLAG_OUTLAND)
+ {
+ if (!(flags & AREA_FLAG_NO_FLY_ZONE))
+ return true;
+ }
+
+ return false;
+ }
};
#define MAX_GROUP_AREA_IDS 6
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index bed9123ac4c..9df9d2ad53c 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1695,6 +1695,7 @@ void Creature::setDeathState(DeathState s)
SetLootRecipient(nullptr);
ResetPlayerDamageReq();
+ SetCannotReachTarget(false);
UpdateMovementFlags();
ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING));
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 8c43d287c91..f1365ac3150 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -310,6 +310,18 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
if (map->Is25ManRaid())
loot.maxDuplicates = 3;
+ if (uint32 linkedEntry = GetGOInfo()->GetLinkedGameObjectEntry())
+ {
+ GameObject* linkedGO = new GameObject();
+ if (linkedGO->Create(map->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, map, phaseMask, pos, rotation, 255, GO_STATE_READY))
+ {
+ SetLinkedTrap(linkedGO);
+ map->AddToMap(linkedGO);
+ }
+ else
+ delete linkedGO;
+ }
+
return true;
}
@@ -428,6 +440,10 @@ void GameObject::Update(uint32 diff)
m_SkillupList.clear();
m_usetimes = 0;
+ // If nearby linked trap exists, respawn it
+ if (GameObject* linkedTrap = GetLinkedTrap())
+ linkedTrap->SetLootState(GO_READY);
+
switch (GetGoType())
{
case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now
@@ -511,11 +527,9 @@ void GameObject::Update(uint32 diff)
if (Unit* owner = GetOwner())
{
// Hunter trap: Search units which are unfriendly to the trap's owner
- Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
- Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, target, checker);
- VisitNearbyGridObject(radius, searcher);
- if (!target)
- VisitNearbyWorldObject(radius, searcher);
+ Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
+ Trinity::UnitLastSearcher<Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck> searcher(this, target, checker);
+ VisitNearbyObject(radius, searcher);
}
else
{
@@ -613,6 +627,10 @@ void GameObject::Update(uint32 diff)
}
case GO_JUST_DEACTIVATED:
{
+ // If nearby linked trap exists, despawn it
+ if (GameObject* linkedTrap = GetLinkedTrap())
+ linkedTrap->SetLootState(GO_JUST_DEACTIVATED);
+
//if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed
if (GetGoType() == GAMEOBJECT_TYPE_GOOBER)
{
@@ -1092,25 +1110,8 @@ void GameObject::TriggeringLinkedGameObject(uint32 trapEntry, Unit* target)
if (!trapSpell) // checked at load already
return;
- float range = float(target->GetSpellMaxRangeForTarget(GetOwner(), trapSpell));
-
- // search nearest linked GO
- GameObject* trapGO = nullptr;
- {
- // using original GO distance
- CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY()));
- Cell cell(p);
-
- Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*target, trapEntry, range);
- Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(this, trapGO, go_check);
-
- TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
- cell.Visit(p, object_checker, *GetMap(), *target, range);
- }
-
- // found correct GO
- if (trapGO)
- trapGO->CastSpell(target, trapInfo->trap.spellId);
+ if (GameObject* trapGO = GetLinkedTrap())
+ trapGO->CastSpell(target, trapSpell->Id);
}
GameObject* GameObject::LookupFishingHoleAround(float range)
@@ -1828,18 +1829,23 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge
if (!trigger)
return;
+ // remove immunity flags, to allow spell to target anything
+ trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC);
+
if (Unit* owner = GetOwner())
{
trigger->setFaction(owner->getFaction());
if (owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+ // copy pvp state flags from owner
+ trigger->SetByteValue(UNIT_FIELD_BYTES_2, 1, owner->GetByteValue(UNIT_FIELD_BYTES_2, 1));
// needed for GO casts for proper target validation checks
trigger->SetOwnerGUID(owner->GetGUID());
trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, owner->GetGUID());
}
else
{
- trigger->setFaction(14);
+ trigger->setFaction(spellInfo->IsPositive() ? 35 : 14);
// Set owner guid for target if no owner available - needed by trigger auras
// - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell())
trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, target ? target->GetGUID() : ObjectGuid::Empty);
@@ -2231,6 +2237,11 @@ bool GameObject::IsLootAllowedFor(Player const* player) const
return true;
}
+GameObject* GameObject::GetLinkedTrap()
+{
+ return ObjectAccessor::GetGameObject(*this, m_linkedTrap);
+}
+
void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
{
if (!target)
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 85b37abaf3c..dc7d99bb622 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -495,6 +495,7 @@ struct GameObjectTemplate
{
switch (type)
{
+ case GAMEOBJECT_TYPE_BUTTON: return button.linkedTrap;
case GAMEOBJECT_TYPE_CHEST: return chest.linkedTrapId;
case GAMEOBJECT_TYPE_SPELL_FOCUS: return spellFocus.linkedTrapId;
case GAMEOBJECT_TYPE_GOOBER: return goober.linkedTrapId;
@@ -818,6 +819,9 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
uint32 m_groupLootTimer; // (msecs)timer used for group loot
ObjectGuid::LowType lootingGroupLowGUID; // used to find group which is looting
+ GameObject* GetLinkedTrap();
+ void SetLinkedTrap(GameObject* linkedTrap) { m_linkedTrap = linkedTrap->GetGUID(); }
+
bool hasQuest(uint32 quest_id) const override;
bool hasInvolvedQuest(uint32 quest_id) const override;
bool ActivateToQuest(Player* target) const;
@@ -925,6 +929,9 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
ObjectGuid m_lootRecipient;
uint32 m_lootRecipientGroup;
uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable
+
+ ObjectGuid m_linkedTrap;
+
private:
void RemoveFromOwner();
void SwitchDoorOrButton(bool activate, bool alternative = false);
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 3946e110c26..1173831be0b 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -824,13 +824,13 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
{
ItemTemplate const* proto = GetTemplate();
+ bool const isEnchantSpell = spellInfo->HasEffect(SPELL_EFFECT_ENCHANT_ITEM) || spellInfo->HasEffect(SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) || spellInfo->HasEffect(SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC);
if (spellInfo->EquippedItemClass != -1) // -1 == any item class
{
// Special case - accept vellum for armor/weapon requirements
- if ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && proto->IsArmorVellum())
- ||(spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && proto->IsWeaponVellum()))
- if (spellInfo->IsAbilityOfSkillType(SKILL_ENCHANTING)) // only for enchanting spells
- return true;
+ if (isEnchantSpell && ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && proto->IsArmorVellum())
+ || (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && proto->IsWeaponVellum())))
+ return true;
if (spellInfo->EquippedItemClass != int32(proto->Class))
return false; // wrong item class
@@ -842,7 +842,7 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
}
}
- if (spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
+ if (isEnchantSpell && spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
{
// Special case - accept weapon type for main and offhand requirements
if (proto->InventoryType == INVTYPE_WEAPON &&
@@ -1346,7 +1346,7 @@ bool Item::ItemContainerLoadLootFromDB()
// If container item is in a bag, add that player as an allowed looter
if (GetBagSlot())
- loot_item.allowedGUIDs.insert(GetOwner()->GetGUID().GetCounter());
+ loot_item.AddAllowedLooter(GetOwner());
// Finally add the LootItem to the container
loot.items.push_back(loot_item);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index f7d4fb38cee..a5f5aa18b1d 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -173,7 +173,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
- if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER))
+ if (isType(TYPEMASK_DYNAMICOBJECT | TYPEMASK_CORPSE | TYPEMASK_PLAYER))
updateType = UPDATETYPE_CREATE_OBJECT2;
// UPDATETYPE_CREATE_OBJECT2 for pets...
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 59b109ab754..3e0f9078c2c 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -939,12 +939,21 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
// Absorb, resist some environmental damage type
uint32 absorb = 0;
uint32 resist = 0;
- if (type == DAMAGE_LAVA)
- CalcAbsorbResist(this, SPELL_SCHOOL_MASK_FIRE, DIRECT_DAMAGE, damage, &absorb, &resist);
- else if (type == DAMAGE_SLIME)
- CalcAbsorbResist(this, SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, damage, &absorb, &resist);
-
- damage -= absorb + resist;
+ switch (type)
+ {
+ case DAMAGE_LAVA:
+ case DAMAGE_SLIME:
+ {
+ DamageInfo dmgInfo(this, this, damage, nullptr, type == DAMAGE_LAVA ? SPELL_SCHOOL_MASK_FIRE : SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, BASE_ATTACK);
+ CalcAbsorbResist(dmgInfo);
+ absorb = dmgInfo.GetAbsorb();
+ resist = dmgInfo.GetResist();
+ damage = dmgInfo.GetDamage();
+ break;
+ }
+ default:
+ break;
+ }
DealDamageMods(this, damage, &absorb);
@@ -3314,7 +3323,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
if (active)
{
if (spellInfo->IsPassive() && IsNeedCastPassiveSpellAtLearn(spellInfo))
- CastSpell (this, spellId, true);
+ CastSpell(this, spellId, true);
}
else if (IsInWorld())
{
@@ -3588,6 +3597,15 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
bool need_cast = (!spellInfo->Stances || (form && (spellInfo->Stances & (UI64LIT(1) << (form - 1)))) ||
(!form && spellInfo->HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT)));
+ // Check EquippedItemClass
+ // passive spells which apply aura and have an item requirement are to be added in Player::ApplyItemDependentAuras
+ if (spellInfo->IsPassive() && spellInfo->EquippedItemClass >= 0)
+ {
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (spellInfo->Effects[i].IsAura())
+ return false;
+ }
+
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState)));
}
@@ -4216,9 +4234,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
charDelete_method = CHAR_DELETE_REMOVE;
}
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
if (ObjectGuid::LowType guildId = GetGuildIdFromDB(playerguid))
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->DeleteMember(playerguid, false, false, true);
+ guild->DeleteMember(trans, playerguid, false, false, true);
// close player ticket if any
GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid);
@@ -4245,8 +4264,6 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
// Completely remove from the database
case CHAR_DELETE_REMOVE:
{
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
-
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_COD_ITEM_MAIL);
stmt->setUInt32(0, guid);
PreparedQueryResult resultMail = CharacterDatabase.Query(stmt);
@@ -4535,26 +4552,27 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
trans->Append(stmt);
Corpse::DeleteFromDB(playerguid, trans);
-
- CharacterDatabase.CommitTransaction(trans);
break;
}
// The character gets unlinked from the account, the name gets freed up and appears as deleted ingame
case CHAR_DELETE_UNLINK:
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_DELETE_INFO);
-
stmt->setUInt32(0, guid);
-
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
break;
}
default:
TC_LOG_ERROR("entities.player.cheat", "Player::DeleteFromDB: Tried to delete player (%s) with unsupported delete method (%u).",
playerguid.ToString().c_str(), charDelete_method);
+
+ if (trans->GetSize() > 0)
+ CharacterDatabase.CommitTransaction(trans);
return;
}
+ CharacterDatabase.CommitTransaction(trans);
+
if (updateRealmChars)
sWorld->UpdateRealmCharCount(accountId);
@@ -7377,20 +7395,16 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: Applying mods for item %s", item->GetGUID().ToString().c_str());
- uint8 attacktype = Player::GetAttackBySlot(slot);
-
if (proto->Socket[0].Color) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items
CorrectMetaGemEnchants(slot, apply);
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), apply);
-
_ApplyItemBonuses(proto, slot, apply);
if (slot == EQUIPMENT_SLOT_RANGED)
_ApplyAmmoBonuses();
ApplyItemEquipSpell(item, apply);
+ ApplyItemDependentAuras(item, apply);
ApplyEnchantment(item, apply);
TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: completed");
@@ -7744,86 +7758,26 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
UpdateDamagePhysical(attType);
}
-void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply)
-{
- AuraEffectList const& auraCritList = GetAuraEffectsByType(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT);
- for (AuraEffectList::const_iterator itr = auraCritList.begin(); itr != auraCritList.end(); ++itr)
- _ApplyWeaponDependentAuraCritMod(item, attackType, *itr, apply);
-
- AuraEffectList const& auraDamageFlatList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
- for (AuraEffectList::const_iterator itr = auraDamageFlatList.begin(); itr != auraDamageFlatList.end(); ++itr)
- _ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply);
-
- AuraEffectList const& auraDamagePctList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffectList::const_iterator itr = auraDamagePctList.begin(); itr != auraDamagePctList.end(); ++itr)
- _ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply);
-}
-
-void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
-{
- // don't apply mod if item is broken or cannot be used
- if (item->IsBroken() || !CanUseAttackType(attackType))
- return;
-
- // generic not weapon specific case processes in aura code
- if (aura->GetSpellInfo()->EquippedItemClass == -1)
- return;
-
- BaseModGroup mod;
- switch (attackType)
- {
- case BASE_ATTACK: mod = CRIT_PERCENTAGE; break;
- case OFF_ATTACK: mod = OFFHAND_CRIT_PERCENTAGE;break;
- case RANGED_ATTACK: mod = RANGED_CRIT_PERCENTAGE; break;
- default: return;
- }
-
- if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
- HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply);
-}
-
-void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
+void Player::ApplyItemDependentAuras(Item* item, bool apply)
{
- // don't apply mod if item is broken or cannot be used
- if (item->IsBroken() || !CanUseAttackType(attackType))
- return;
-
- // ignore spell mods for not wands
- if ((aura->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) == 0 && (getClassMask() & CLASSMASK_WAND_USERS) == 0)
- return;
-
- // generic not weapon specific case processes in aura code
- if (aura->GetSpellInfo()->EquippedItemClass == -1)
- return;
-
- UnitMods unitMod;
- switch (attackType)
+ if (apply)
{
- case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
- case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
- case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
- default: return;
- }
+ PlayerSpellMap const& spells = GetSpellMap();
+ for (auto itr = spells.begin(); itr != spells.end(); ++itr)
+ {
+ if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
+ continue;
- UnitModifierType unitModType;
- switch (aura->GetAuraType())
- {
- case SPELL_AURA_MOD_DAMAGE_DONE: unitModType = TOTAL_VALUE; break;
- case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: unitModType = TOTAL_PCT; break;
- default: return;
- }
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ if (!spellInfo || !spellInfo->IsPassive() || spellInfo->EquippedItemClass < 0)
+ continue;
- if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
- {
- HandleStatModifier(unitMod, unitModType, float(aura->GetAmount()), apply);
- if (unitModType == TOTAL_VALUE)
- {
- if (aura->GetAmount() > 0)
- ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, aura->GetAmount(), apply);
- else
- ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, aura->GetAmount(), apply);
+ if (!HasAura(itr->first) && HasItemFitToSpellRequirements(spellInfo))
+ AddAura(itr->first, this); // no SMSG_SPELL_GO in sniff found
}
}
+ else
+ RemoveItemDependentAurasAndCasts(item);
}
void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
@@ -8198,10 +8152,7 @@ void Player::_RemoveAllItemMods()
if (!proto)
continue;
- uint32 attacktype = Player::GetAttackBySlot(i);
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), false);
-
+ ApplyItemDependentAuras(m_items[i], false);
_ApplyItemBonuses(proto, i, false);
if (i == EQUIPMENT_SLOT_RANGED)
@@ -8227,10 +8178,7 @@ void Player::_ApplyAllItemMods()
if (!proto)
continue;
- uint32 attacktype = Player::GetAttackBySlot(i);
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), true);
-
+ ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(proto, i, true);
if (i == EQUIPMENT_SLOT_RANGED)
@@ -12221,9 +12169,6 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
// remove item dependent auras and casts (only weapon and armor slots)
if (slot < EQUIPMENT_SLOT_END)
{
- if (update)
- RemoveItemDependentAurasAndCasts(pItem);
-
// remove held enchantments, update expertise
if (slot == EQUIPMENT_SLOT_MAINHAND)
{
@@ -12374,9 +12319,6 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
if (slot < EQUIPMENT_SLOT_END)
{
- // remove item dependent auras and casts (only weapon and armor slots)
- RemoveItemDependentAurasAndCasts(pItem);
-
// update expertise and armor penetration - passive auras may need it
switch (slot)
{
@@ -15011,20 +14953,20 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
{
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i]))
{
- if (quest->RequiredItemCount[i] > 0 && (itemTemplate->Bonding == BIND_QUEST_ITEM || itemTemplate->Bonding == BIND_QUEST_ITEM1))
- DestroyItemCount(quest->RequiredItemId[i], 9999, true, true);
+ if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM && !quest->IsRepeatable() && !HasQuestForItem(quest->RequiredItemId[i], quest_id, true))
+ DestroyItemCount(quest->RequiredItemId[i], 9999, true);
else
- DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true, true);
+ DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true);
}
}
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
{
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i]))
{
- if (quest->ItemDropQuantity[i] > 0 && (itemTemplate->Bonding == BIND_QUEST_ITEM || itemTemplate->Bonding == BIND_QUEST_ITEM1))
- DestroyItemCount(quest->ItemDrop[i], 9999, true, true);
+ if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM && !quest->IsRepeatable() && !HasQuestForItem(quest->ItemDrop[i], quest_id))
+ DestroyItemCount(quest->ItemDrop[i], 9999, true);
else
- DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i], true, true);
+ DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i], true);
}
}
@@ -15244,13 +15186,13 @@ void Player::FailQuest(uint32 questId)
// Destroy quest items on quest failure.
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i]))
- if (quest->RequiredItemCount[i] > 0 && (itemTemplate->Bonding == BIND_QUEST_ITEM || itemTemplate->Bonding == BIND_QUEST_ITEM1))
- DestroyItemCount(quest->RequiredItemId[i], 9999, true, true);
+ if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM)
+ DestroyItemCount(quest->RequiredItemId[i], 9999, true);
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i]))
- if (quest->ItemDropQuantity[i] > 0 && (itemTemplate->Bonding == BIND_QUEST_ITEM || itemTemplate->Bonding == BIND_QUEST_ITEM1))
- DestroyItemCount(quest->ItemDrop[i], 9999, true, true);
+ if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM)
+ DestroyItemCount(quest->ItemDrop[i], 9999, true);
}
}
@@ -15261,13 +15203,13 @@ void Player::AbandonQuest(uint32 questId)
// Destroy quest items on quest abandon.
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i]))
- if (quest->RequiredItemCount[i] > 0 && (itemTemplate->Bonding == BIND_QUEST_ITEM || itemTemplate->Bonding == BIND_QUEST_ITEM1))
- DestroyItemCount(quest->RequiredItemId[i], 9999, true, true);
+ if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM)
+ DestroyItemCount(quest->RequiredItemId[i], 9999, true);
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i]))
- if (quest->ItemDropQuantity[i] > 0 && (itemTemplate->Bonding == BIND_QUEST_ITEM || itemTemplate->Bonding == BIND_QUEST_ITEM1))
- DestroyItemCount(quest->ItemDrop[i], 9999, true, true);
+ if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM)
+ DestroyItemCount(quest->ItemDrop[i], 9999, true);
}
}
@@ -15971,7 +15913,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
if (!quest)
continue;
- if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId(), this))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, quest->GetQuestId(), this))
continue;
QuestStatus status = GetQuestStatus(questId);
@@ -15995,7 +15937,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
if (!quest)
continue;
- if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId(), this))
+ if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, quest->GetQuestId(), this))
continue;
QuestStatus status = GetQuestStatus(questId);
@@ -16566,12 +16508,12 @@ void Player::ReputationChanged2(FactionEntry const* factionEntry)
}
}
-bool Player::HasQuestForItem(uint32 itemid) const
+bool Player::HasQuestForItem(uint32 itemid, uint32 excludeQuestId /* 0 */, bool turnIn /* false */) const
{
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
{
uint32 questid = GetQuestSlotQuestId(i);
- if (questid == 0)
+ if (questid == 0 || questid == excludeQuestId)
continue;
QuestStatusMap::const_iterator qs_itr = m_QuestStatus.find(questid);
@@ -16580,7 +16522,7 @@ bool Player::HasQuestForItem(uint32 itemid) const
QuestStatusData const& q_status = qs_itr->second;
- if (q_status.Status == QUEST_STATUS_INCOMPLETE)
+ if ((q_status.Status == QUEST_STATUS_INCOMPLETE) || (turnIn && q_status.Status == QUEST_STATUS_COMPLETE))
{
Quest const* qinfo = sObjectMgr->GetQuestTemplate(questid);
if (!qinfo)
@@ -16595,7 +16537,7 @@ bool Player::HasQuestForItem(uint32 itemid) const
// This part for ReqItem drop
for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j)
{
- if (itemid == qinfo->RequiredItemId[j] && q_status.ItemCount[j] < qinfo->RequiredItemCount[j])
+ if ((itemid == qinfo->RequiredItemId[j] && q_status.ItemCount[j] < qinfo->RequiredItemCount[j]) || (turnIn && q_status.ItemCount[j] >= qinfo->RequiredItemCount[j]))
return true;
}
// This part - for ReqSource
@@ -16605,17 +16547,17 @@ bool Player::HasQuestForItem(uint32 itemid) const
if (qinfo->ItemDrop[j] == itemid)
{
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
-
+ uint32 ownedCount = GetItemCount(itemid, true);
// 'unique' item
- if (pProto->MaxCount && int32(GetItemCount(itemid, true)) < pProto->MaxCount)
+ if ((pProto->MaxCount && int32(ownedCount) < pProto->MaxCount) || (turnIn && int32(ownedCount) >= pProto->MaxCount))
return true;
// allows custom amount drop when not 0
if (qinfo->ItemDropQuantity[j])
{
- if (GetItemCount(itemid, true) < qinfo->ItemDropQuantity[j])
+ if ((ownedCount < qinfo->ItemDropQuantity[j]) || (turnIn && ownedCount >= qinfo->ItemDropQuantity[j]))
return true;
- } else if (GetItemCount(itemid, true) < pProto->GetMaxStackSize())
+ } else if (ownedCount < pProto->GetMaxStackSize())
return true;
}
}
@@ -19558,7 +19500,6 @@ void Player::_SaveAuras(SQLTransaction& trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA);
stmt->setUInt32(index++, GetGUID().GetCounter());
stmt->setUInt64(index++, itr->second->GetCasterGUID().GetRawValue());
- stmt->setUInt64(index++, itr->second->GetCastItemGUID().GetRawValue());
stmt->setUInt32(index++, itr->second->GetId());
stmt->setUInt8(index++, effMask);
stmt->setUInt8(index++, recalculateMask);
@@ -20873,29 +20814,30 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
TC_LOG_DEBUG("spells", "Player::AddSpellMod: Player '%s' (%s), SpellID: %d", GetName().c_str(), GetGUID().ToString().c_str(), mod->spellId);
uint16 Opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
- int i = 0;
- flag96 _mask = 0;
- for (int32 eff = 0; eff < 96; ++eff)
+ flag96 modMask;
+ for (uint8 i = 0; i < 3; ++i)
{
- if (eff != 0 && eff % 32 == 0)
- _mask[i++] = 0;
-
- _mask[i] = uint32(1) << (eff - (32 * i));
- if ((mod->mask & _mask))
+ for (uint32 eff = 0; eff < 32; ++eff)
{
- int32 val = 0;
- for (SpellModifier* spellMod : m_spellMods[mod->op])
+ modMask[i] = uint32(1) << eff;
+ if ((mod->mask & modMask))
{
- if (spellMod->type == mod->type && (spellMod->mask & _mask))
- val += spellMod->value;
+ int32 val = 0;
+ for (SpellModifier* spellMod : m_spellMods[mod->op])
+ {
+ if (spellMod->type == mod->type && (spellMod->mask & modMask))
+ val += spellMod->value;
+ }
+ val += apply ? mod->value : -(mod->value);
+ WorldPacket data(Opcode, (1 + 1 + 4));
+ data << uint8(eff + 32 * i);
+ data << uint8(mod->op);
+ data << int32(val);
+ SendDirectMessage(&data);
}
- val += apply ? mod->value : -(mod->value);
- WorldPacket data(Opcode, (1 + 1 + 4));
- data << uint8(eff);
- data << uint8(mod->op);
- data << int32(val);
- SendDirectMessage(&data);
}
+
+ modMask[i] = 0;
}
if (apply)
@@ -23582,9 +23524,9 @@ void Player::RemoveItemDependentAurasAndCasts(Item* pItem)
{
Aura* aura = itr->second;
- // skip passive (passive item dependent spells work in another way) and not self applied auras
+ // skip not self applied auras
SpellInfo const* spellInfo = aura->GetSpellInfo();
- if (aura->IsPassive() || aura->GetCasterGUID() != GetGUID())
+ if (aura->GetCasterGUID() != GetGUID())
{
++itr;
continue;
@@ -24629,9 +24571,9 @@ void Player::AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore cons
void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
{
- QuestItem* qitem = nullptr;
- QuestItem* ffaitem = nullptr;
- QuestItem* conditem = nullptr;
+ NotNormalLootItem* qitem = nullptr;
+ NotNormalLootItem* ffaitem = nullptr;
+ NotNormalLootItem* conditem = nullptr;
LootItem* item = loot->LootItemInSlot(lootSlot, this, &qitem, &ffaitem, &conditem);
@@ -25883,6 +25825,20 @@ void Player::ActivateSpec(uint8 spec)
UnsummonAllTotems();
ExitVehicle();
RemoveAllControlled();
+
+ // remove single target auras at other targets
+ AuraList& scAuras = GetSingleCastAuras();
+ for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
+ {
+ Aura* aura = *iter;
+ if (aura->GetUnitOwner() != this)
+ {
+ aura->Remove();
+ iter = scAuras.begin();
+ }
+ else
+ ++iter;
+ }
/*RemoveAllAurasOnDeath();
if (GetPet())
GetPet()->RemoveAllAurasOnDeath();*/
@@ -26000,6 +25956,13 @@ void Player::ActivateSpec(uint8 spec)
SetPower(POWER_MANA, 0); // Mana must be 0 even if it isn't the active power type.
SetPower(pw, 0);
+
+ Unit::AuraEffectList const& shapeshiftAuras = GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
+ for (AuraEffect* aurEff : shapeshiftAuras)
+ {
+ aurEff->HandleShapeshiftBoosts(this, false);
+ aurEff->HandleShapeshiftBoosts(this, true);
+ }
}
void Player::ResetTimeSync()
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 4ecdad742e9..ed5dc7e954f 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1406,7 +1406,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void MoneyChanged(uint32 value);
void ReputationChanged(FactionEntry const* factionEntry);
void ReputationChanged2(FactionEntry const* factionEntry);
- bool HasQuestForItem(uint32 itemId) const;
+ bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId = 0, bool turnIn = false) const;
bool HasQuestForGO(int32 goId) const;
void UpdateForQuestWorldObjects();
bool CanShareQuest(uint32 questId) const;
@@ -1958,9 +1958,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ResetAllPowers();
- void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
- void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
- void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
+ void ApplyItemDependentAuras(Item* item, bool apply);
void _ApplyItemMods(Item* item, uint8 slot, bool apply);
void _RemoveAllItemMods();
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index fad197949a8..cdb4b931a07 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -131,6 +131,7 @@ void Transport::Update(uint32 diff)
m_goValue.Transport.PathProgress += diff;
uint32 timer = m_goValue.Transport.PathProgress % GetTransportPeriod();
+ bool justStopped = false;
// Set current waypoint
// Desired outcome: _currentFrame->DepartureTime < timer < _nextFrame->ArriveTime
@@ -149,6 +150,7 @@ void Transport::Update(uint32 diff)
if (timer < _currentFrame->DepartureTime)
{
SetMoving(false);
+ justStopped = true;
if (_pendingStop && GetGoState() != GO_STATE_READY)
{
SetGoState(GO_STATE_READY);
@@ -203,12 +205,14 @@ void Transport::Update(uint32 diff)
_positionChangeTimer.Reset(positionUpdateDelay);
if (IsMoving())
{
- float t = CalculateSegmentPos(float(timer) * 0.001f);
+ float t = !justStopped ? CalculateSegmentPos(float(timer) * 0.001f) : 1.0f;
G3D::Vector3 pos, dir;
_currentFrame->Spline->evaluate_percent(_currentFrame->Index, t, pos);
_currentFrame->Spline->evaluate_derivative(_currentFrame->Index, t, dir);
UpdatePosition(pos.x, pos.y, pos.z, std::atan2(dir.y, dir.x) + float(M_PI));
}
+ else if (justStopped)
+ UpdatePosition(_currentFrame->Node->LocX, _currentFrame->Node->LocY, _currentFrame->Node->LocZ, _currentFrame->InitialOrientation);
else
{
/* There are four possible scenarios that trigger loading/unloading passengers:
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 699709fabb1..0cad0b2cb05 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -184,8 +184,17 @@ void Player::UpdateSpellDamageAndHealingBonus()
// Get healing bonus for all schools
SetStatInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_ALL));
// Get damage bonus for all schools
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)));
+ Unit::AuraEffectList const& modDamageAuras = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
+ for (uint16 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
+ {
+ SetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i, std::accumulate(modDamageAuras.begin(), modDamageAuras.end(), 0, [i](int32 negativeMod, AuraEffect const* aurEff)
+ {
+ if (aurEff->GetAmount() < 0 && aurEff->GetMiscValue() & (1 << i))
+ negativeMod += aurEff->GetAmount();
+ return negativeMod;
+ }));
+ SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)) - GetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i));
+ }
}
bool Player::UpdateAllStats()
@@ -530,9 +539,9 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
break;
}
- float attackSpeedMod = GetAPMultiplier(attType, normalized);
+ float const attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod;
+ float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackPowerMod;
float basePct = GetModifierValue(unitMod, BASE_PCT);
float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
@@ -546,8 +555,8 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
if (lvl > 60)
lvl = 60;
- weaponMinDamage = lvl * 0.85f * attackSpeedMod;
- weaponMaxDamage = lvl * 1.25f * attackSpeedMod;
+ weaponMinDamage = lvl * 0.85f * attackPowerMod;
+ weaponMaxDamage = lvl * 1.25f * attackPowerMod;
}
else if (!CanUseAttackType(attType)) // check if player not in form but still can't use (disarm case)
{
@@ -563,8 +572,8 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
}
else if (attType == RANGED_ATTACK) // add ammo DPS to ranged damage
{
- weaponMinDamage += GetAmmoDPS() * attackSpeedMod;
- weaponMaxDamage += GetAmmoDPS() * attackSpeedMod;
+ weaponMinDamage += GetAmmoDPS() * attackPowerMod;
+ weaponMaxDamage += GetAmmoDPS() * attackPowerMod;
}
minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index cecec8660c7..7ff01efa363 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -112,7 +112,7 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo)
break;
}
- if (m_absorb)
+ if (dmgInfo.HitInfo & (HITINFO_PARTIAL_ABSORB | HITINFO_FULL_ABSORB))
m_hitMask |= PROC_HIT_ABSORB;
if (dmgInfo.HitInfo & HITINFO_FULL_RESIST)
@@ -121,6 +121,8 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo)
if (m_block)
m_hitMask |= PROC_HIT_BLOCK;
+ bool const damageNullified = (dmgInfo.HitInfo & (HITINFO_FULL_ABSORB | HITINFO_FULL_RESIST)) != 0 ||
+ (m_hitMask & (PROC_HIT_IMMUNE | PROC_HIT_FULL_BLOCK)) != 0;
switch (dmgInfo.hitOutCome)
{
case MELEE_HIT_MISS:
@@ -138,10 +140,12 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo)
case MELEE_HIT_CRUSHING:
case MELEE_HIT_GLANCING:
case MELEE_HIT_NORMAL:
- m_hitMask |= PROC_HIT_NORMAL;
+ if (!damageNullified)
+ m_hitMask |= PROC_HIT_NORMAL;
break;
case MELEE_HIT_CRIT:
- m_hitMask |= PROC_HIT_CRITICAL;
+ if (!damageNullified)
+ m_hitMask |= PROC_HIT_CRITICAL;
break;
default:
break;
@@ -161,7 +165,7 @@ DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEff
void DamageInfo::ModifyDamage(int32 amount)
{
- amount = std::min(amount, int32(GetDamage()));
+ amount = std::max(amount, -static_cast<int32>(GetDamage()));
m_damage += amount;
}
@@ -179,7 +183,10 @@ void DamageInfo::ResistDamage(uint32 amount)
m_resist += amount;
m_damage -= amount;
if (!m_damage)
+ {
m_hitMask |= PROC_HIT_FULL_RESIST;
+ m_hitMask &= ~(PROC_HIT_NORMAL | PROC_HIT_CRITICAL);
+ }
}
void DamageInfo::BlockDamage(uint32 amount)
@@ -189,7 +196,10 @@ void DamageInfo::BlockDamage(uint32 amount)
m_damage -= amount;
m_hitMask |= PROC_HIT_BLOCK;
if (!m_damage)
+ {
m_hitMask |= PROC_HIT_FULL_BLOCK;
+ m_hitMask &= ~(PROC_HIT_NORMAL | PROC_HIT_CRITICAL);
+ }
}
uint32 DamageInfo::GetHitMask() const
@@ -294,9 +304,6 @@ Unit::Unit(bool isWorldObject) :
m_transform = 0;
m_canModifyStats = false;
- for (uint8 i = 0; i < MAX_SPELL_IMMUNITY; ++i)
- m_spellImmune[i].clear();
-
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
{
m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
@@ -646,7 +653,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
|| HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM, excludeAura));
}
-void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb)
+void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const
{
if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
{
@@ -967,7 +974,7 @@ void Unit::CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castIte
CastSpell(victim, spellId, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
}
-void Unit::CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags /*= TRIGGER_NONE*/, Item* castItem /*= NULL*/, AuraEffect const* triggeredByAura /*= NULL*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/)
+void Unit::CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags /*= TRIGGER_NONE*/, Item* castItem /*= nullptr*/, AuraEffect const* triggeredByAura /*= nullptr*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
@@ -979,7 +986,7 @@ void Unit::CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags
CastSpell(victim, spellInfo, triggerFlags, castItem, triggeredByAura, originalCaster);
}
-void Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem/*= NULL*/, AuraEffect const* triggeredByAura /*= NULL*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/)
+void Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem/*= nullptr*/, AuraEffect const* triggeredByAura /*= nullptr*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/)
{
CastSpell(victim, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
}
@@ -988,7 +995,7 @@ void Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags
{
SpellCastTargets targets;
targets.SetUnitTarget(victim);
- CastSpell(targets, spellInfo, NULL, triggerFlags, castItem, triggeredByAura, originalCaster);
+ CastSpell(targets, spellInfo, nullptr, triggerFlags, castItem, triggeredByAura, originalCaster);
}
void Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
@@ -1042,10 +1049,10 @@ void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered,
SpellCastTargets targets;
targets.SetDst(x, y, z, GetOrientation());
- CastSpell(targets, spellInfo, NULL, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
+ CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
}
-void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem, AuraEffect* triggeredByAura, ObjectGuid originalCaster)
+void Unit::CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
@@ -1054,26 +1061,23 @@ void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castI
return;
}
SpellCastTargets targets;
- targets.SetGOTarget(go);
+ targets.SetDst(x, y, z, GetOrientation());
- CastSpell(targets, spellInfo, NULL, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
+ CastSpell(targets, spellInfo, nullptr, triggerFlags, castItem, triggeredByAura, originalCaster);
}
-// Obsolete func need remove, here only for comotability vs another patches
-uint32 Unit::SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage)
+void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem, AuraEffect* triggeredByAura, ObjectGuid originalCaster)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
- return 0;
- SpellNonMeleeDamage damageInfo(this, victim, spellInfo->Id, spellInfo->SchoolMask);
- damage = SpellDamageBonusDone(victim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
- damage = victim->SpellDamageBonusTaken(this, spellInfo, damage, SPELL_DIRECT_DAMAGE);
+ {
+ TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry()));
+ return;
+ }
+ SpellCastTargets targets;
+ targets.SetGOTarget(go);
- CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
- DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
- SendSpellNonMeleeDamageLog(&damageInfo);
- DealSpellDamage(&damageInfo, true);
- return damageInfo.damage;
+ CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
}
void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType, bool crit)
@@ -1144,8 +1148,11 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
// double blocked amount if block is critical
if (victim->isBlockCritical())
damageInfo->blocked += damageInfo->blocked;
- if (damage < int32(damageInfo->blocked))
+ if (damage <= int32(damageInfo->blocked))
+ {
damageInfo->blocked = uint32(damage);
+ damageInfo->fullBlock = true;
+ }
damage -= damageInfo->blocked;
}
@@ -1155,7 +1162,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_RANGED);
break;
}
- // Magical Attacks
+ // Magical Attacks
case SPELL_DAMAGE_CLASS_NONE:
case SPELL_DAMAGE_CLASS_MAGIC:
{
@@ -1178,24 +1185,30 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
sScriptMgr->ModifySpellDamageTaken(damageInfo->target, damageInfo->attacker, damage);
// Calculate absorb resist
- if (damage > 0)
- {
- CalcAbsorbResist(victim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo);
- damage -= damageInfo->absorb + damageInfo->resist;
- }
- else
+ if (damage < 0)
damage = 0;
damageInfo->damage = damage;
+ DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE, BASE_ATTACK, PROC_HIT_NONE);
+ CalcAbsorbResist(dmgInfo);
+ damageInfo->absorb = dmgInfo.GetAbsorb();
+ damageInfo->resist = dmgInfo.GetResist();
+
+ if (damageInfo->absorb)
+ damageInfo->HitInfo |= (damageInfo->damage - damageInfo->absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
+
+ if (damageInfo->resist)
+ damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
+
+ damageInfo->damage = dmgInfo.GetDamage();
}
void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
{
- if (damageInfo == 0)
+ if (!damageInfo)
return;
Unit* victim = damageInfo->target;
-
if (!victim)
return;
@@ -1396,7 +1409,10 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
{
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
// Calculate absorb & resists
- CalcAbsorbResist(damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist);
+ DamageInfo dmgInfo(*damageInfo);
+ CalcAbsorbResist(dmgInfo);
+ damageInfo->absorb = dmgInfo.GetAbsorb();
+ damageInfo->resist = dmgInfo.GetResist();
if (damageInfo->absorb)
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
@@ -1404,7 +1420,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
if (damageInfo->resist)
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
- damageInfo->damage -= damageInfo->absorb + damageInfo->resist;
+ damageInfo->damage = dmgInfo.GetDamage();
}
else // Impossible get negative result but....
damageInfo->damage = 0;
@@ -1500,46 +1516,47 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
AuraEffectList vDamageShieldsCopy(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD));
- for (AuraEffectList::const_iterator dmgShieldItr = vDamageShieldsCopy.begin(); dmgShieldItr != vDamageShieldsCopy.end(); ++dmgShieldItr)
+ for (AuraEffect const* aurEff : vDamageShieldsCopy)
{
- SpellInfo const* i_spellProto = (*dmgShieldItr)->GetSpellInfo();
+ SpellInfo const* spellInfo = aurEff->GetSpellInfo();
+
// Damage shield can be resisted...
- if (SpellMissInfo missInfo = victim->SpellHitResult(this, i_spellProto, false))
+ SpellMissInfo missInfo = victim->SpellHitResult(this, spellInfo, false);
+ if (missInfo != SPELL_MISS_NONE)
{
- victim->SendSpellMiss(this, i_spellProto->Id, missInfo);
+ victim->SendSpellMiss(this, spellInfo->Id, missInfo);
continue;
}
// ...or immuned
- if (IsImmunedToDamage(i_spellProto))
+ if (IsImmunedToDamage(spellInfo))
{
- victim->SendSpellDamageImmune(this, i_spellProto->Id);
+ victim->SendSpellDamageImmune(this, spellInfo->Id);
continue;
}
- uint32 damage = (*dmgShieldItr)->GetAmount();
-
- if (Unit* caster = (*dmgShieldItr)->GetCaster())
+ uint32 damage = aurEff->GetAmount();
+ if (Unit* caster = aurEff->GetCaster())
{
- damage = caster->SpellDamageBonusDone(this, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
- damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
+ damage = caster->SpellDamageBonusDone(this, spellInfo, damage, SPELL_DIRECT_DAMAGE);
+ damage = SpellDamageBonusTaken(caster, spellInfo, damage, SPELL_DIRECT_DAMAGE);
}
// No Unit::CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that
- victim->DealDamageMods(this, damage, NULL);
+ victim->DealDamageMods(this, damage, nullptr);
/// @todo Move this to a packet handler
WorldPacket data(SMSG_SPELLDAMAGESHIELD, 8 + 8 + 4 + 4 + 4 + 4 + 4);
data << uint64(victim->GetGUID());
data << uint64(GetGUID());
- data << uint32(i_spellProto->Id);
+ data << uint32(spellInfo->Id);
data << uint32(damage); // Damage
- int32 overkill = int32(damage) - int32(GetHealth());
- data << uint32(overkill > 0 ? overkill : 0); // Overkill
- data << uint32(i_spellProto->SchoolMask);
+ int32 const overkill = int32(damage) - int32(GetHealth());
+ data << uint32(std::max(overkill, 0)); // Overkill
+ data << uint32(spellInfo->SchoolMask);
victim->SendMessageToSet(&data, true);
- victim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
+ victim->DealDamage(this, damage, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
}
}
}
@@ -1731,57 +1748,49 @@ uint32 Unit::CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, Spell
return resistance * 10;
}
-void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo /*= NULL*/)
+void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
{
- if (!victim || !victim->IsAlive() || !damage)
+ if (!damageInfo.GetVictim() || !damageInfo.GetVictim()->IsAlive() || !damageInfo.GetDamage())
return;
- DamageInfo dmgInfo = DamageInfo(this, victim, damage, spellInfo, schoolMask, damagetype, BASE_ATTACK);
-
- uint32 spellResistance = CalcSpellResistance(victim, schoolMask, spellInfo);
- dmgInfo.ResistDamage(CalculatePct(damage, spellResistance));
+ uint32 spellResistance = CalcSpellResistance(damageInfo.GetVictim(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo());
+ damageInfo.ResistDamage(CalculatePct(damageInfo.GetDamage(), spellResistance));
// Ignore Absorption Auras
- float auraAbsorbMod = 0;
- AuraEffectList const& AbsIgnoreAurasA = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL);
- for (AuraEffectList::const_iterator itr = AbsIgnoreAurasA.begin(); itr != AbsIgnoreAurasA.end(); ++itr)
+ float auraAbsorbMod(GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL, damageInfo.GetSchoolMask()));
+
+ AuraEffectList const& abilityAbsorbAuras = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL);
+ for (AuraEffect const* aurEff : abilityAbsorbAuras)
{
- if (!((*itr)->GetMiscValue() & schoolMask))
+ if (!(aurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
continue;
- if ((*itr)->GetAmount() > auraAbsorbMod)
- auraAbsorbMod = float((*itr)->GetAmount());
- }
-
- AuraEffectList const& AbsIgnoreAurasB = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL);
- for (AuraEffectList::const_iterator itr = AbsIgnoreAurasB.begin(); itr != AbsIgnoreAurasB.end(); ++itr)
- {
- if (!((*itr)->GetMiscValue() & schoolMask))
+ if (!aurEff->IsAffectedOnSpell(damageInfo.GetSpellInfo()))
continue;
- if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectedOnSpell(spellInfo))
- auraAbsorbMod = float((*itr)->GetAmount());
+ if ((aurEff->GetAmount() > auraAbsorbMod))
+ auraAbsorbMod = float(aurEff->GetAmount());
}
RoundToInterval(auraAbsorbMod, 0.0f, 100.0f);
- int32 absorbIgnoringDamage = CalculatePct(dmgInfo.GetDamage(), auraAbsorbMod);
- dmgInfo.ModifyDamage(-absorbIgnoringDamage);
+ int32 absorbIgnoringDamage = CalculatePct(damageInfo.GetDamage(), auraAbsorbMod);
+ damageInfo.ModifyDamage(-absorbIgnoringDamage);
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSchoolAbsorbCopy(victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
+ AuraEffectList vSchoolAbsorbCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
vSchoolAbsorbCopy.sort(Trinity::AbsorbAuraOrderPred());
// absorb without mana cost
- for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
+ for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
{
AuraEffect* absorbAurEff = *itr;
// Check if aura was removed during iteration - we don't need to work on such auras
- AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID());
+ AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
if (!aurApp)
continue;
- if (!(absorbAurEff->GetMiscValue() & schoolMask))
+ if (!(absorbAurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
continue;
// get amount which can be still absorbed by the aura
@@ -1794,19 +1803,19 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
bool defaultPrevented = false;
- absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb, defaultPrevented);
+ absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb, defaultPrevented);
currentAbsorb = tempAbsorb;
if (defaultPrevented)
continue;
// absorb must be smaller than the damage itself
- currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
+ currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(damageInfo.GetDamage()));
- dmgInfo.AbsorbDamage(currentAbsorb);
+ damageInfo.AbsorbDamage(currentAbsorb);
tempAbsorb = currentAbsorb;
- absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb);
+ absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb);
// Check if our aura is using amount to count damage
if (absorbAurEff->GetAmount() >= 0)
@@ -1820,16 +1829,16 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
}
// absorb by mana cost
- AuraEffectList vManaShieldCopy(victim->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
- for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
+ AuraEffectList vManaShieldCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
+ for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
{
AuraEffect* absorbAurEff = *itr;
// Check if aura was removed during iteration - we don't need to work on such auras
- AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID());
+ AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
if (!aurApp)
continue;
// check damage school mask
- if (!(absorbAurEff->GetMiscValue() & schoolMask))
+ if (!(absorbAurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
continue;
// get amount which can be still absorbed by the aura
@@ -1842,14 +1851,14 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
bool defaultPrevented = false;
- absorbAurEff->GetBase()->CallScriptEffectManaShieldHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb, defaultPrevented);
+ absorbAurEff->GetBase()->CallScriptEffectManaShieldHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb, defaultPrevented);
currentAbsorb = tempAbsorb;
if (defaultPrevented)
continue;
// absorb must be smaller than the damage itself
- currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
+ currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(damageInfo.GetDamage()));
int32 manaReduction = currentAbsorb;
@@ -1857,15 +1866,15 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
if (float manaMultiplier = absorbAurEff->GetSpellInfo()->Effects[absorbAurEff->GetEffIndex()].CalcValueMultiplier(absorbAurEff->GetCaster()))
manaReduction = int32(float(manaReduction) * manaMultiplier);
- int32 manaTaken = -victim->ModifyPower(POWER_MANA, -manaReduction);
+ int32 manaTaken = -damageInfo.GetVictim()->ModifyPower(POWER_MANA, -manaReduction);
// take case when mana has ended up into account
currentAbsorb = currentAbsorb ? int32(float(currentAbsorb) * (float(manaTaken) / float(manaReduction))) : 0;
- dmgInfo.AbsorbDamage(currentAbsorb);
+ damageInfo.AbsorbDamage(currentAbsorb);
tempAbsorb = currentAbsorb;
- absorbAurEff->GetBase()->CallScriptEffectAfterManaShieldHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb);
+ absorbAurEff->GetBase()->CallScriptEffectAfterManaShieldHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb);
// Check if our aura is using amount to count damage
if (absorbAurEff->GetAmount() >= 0)
@@ -1876,39 +1885,39 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
}
}
- dmgInfo.ModifyDamage(absorbIgnoringDamage);
+ damageInfo.ModifyDamage(absorbIgnoringDamage);
// split damage auras - only when not damaging self
- if (victim != this)
+ if (damageInfo.GetVictim() != this)
{
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
- for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
+ AuraEffectList vSplitDamageFlatCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
+ for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
{
// Check if aura was removed during iteration - we don't need to work on such auras
- if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
+ if (!((*itr)->GetBase()->IsAppliedOnTarget(damageInfo.GetVictim()->GetGUID())))
continue;
// check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
+ if (!((*itr)->GetMiscValue() & damageInfo.GetSchoolMask()))
continue;
// Damage can be splitted only if aura has an alive caster
Unit* caster = (*itr)->GetCaster();
- if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
+ if (!caster || (caster == damageInfo.GetVictim()) || !caster->IsInWorld() || !caster->IsAlive())
continue;
int32 splitDamage = (*itr)->GetAmount();
// absorb must be smaller than the damage itself
- splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
+ splitDamage = RoundToInterval(splitDamage, 0, int32(damageInfo.GetDamage()));
- dmgInfo.AbsorbDamage(splitDamage);
+ damageInfo.AbsorbDamage(splitDamage);
// check if caster is immune to damage
- if (caster->IsImmunedToDamage(schoolMask))
+ if (caster->IsImmunedToDamage(damageInfo.GetSchoolMask()))
{
- victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ damageInfo.GetVictim()->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
continue;
}
@@ -1916,66 +1925,62 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
uint32 splitted_absorb = 0;
DealDamageMods(caster, splitted, &splitted_absorb);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, damageInfo.GetSchoolMask(), splitted_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+ DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
}
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
- for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr)
+ AuraEffectList vSplitDamagePctCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
+ for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && damageInfo.GetDamage() > 0; ++itr)
{
// Check if aura was removed during iteration - we don't need to work on such auras
- AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
+ AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
if (!aurApp)
continue;
// check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
+ if (!((*itr)->GetMiscValue() & damageInfo.GetSchoolMask()))
continue;
// Damage can be splitted only if aura has an alive caster
Unit* caster = (*itr)->GetCaster();
- if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
+ if (!caster || (caster == damageInfo.GetVictim()) || !caster->IsInWorld() || !caster->IsAlive())
continue;
- uint32 splitDamage = CalculatePct(dmgInfo.GetDamage(), (*itr)->GetAmount());
+ uint32 splitDamage = CalculatePct(damageInfo.GetDamage(), (*itr)->GetAmount());
- (*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, dmgInfo, splitDamage);
+ (*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, damageInfo, splitDamage);
// absorb must be smaller than the damage itself
- splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
+ splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(damageInfo.GetDamage()));
- dmgInfo.AbsorbDamage(splitDamage);
+ damageInfo.AbsorbDamage(splitDamage);
// check if caster is immune to damage
- if (caster->IsImmunedToDamage(schoolMask))
+ if (caster->IsImmunedToDamage(damageInfo.GetSchoolMask()))
{
- victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
+ damageInfo.GetVictim()->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
continue;
}
uint32 split_absorb = 0;
DealDamageMods(caster, splitDamage, &split_absorb);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, schoolMask, split_absorb, 0, false, 0, false);
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, damageInfo.GetSchoolMask(), split_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+ DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
// break 'Fear' and similar auras
- DamageInfo damageInfo(caster, this, splitDamage, (*itr)->GetSpellInfo(), schoolMask, DIRECT_DAMAGE, BASE_ATTACK);
ProcSkillsAndAuras(caster, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, PROC_HIT_NONE, nullptr, &damageInfo, nullptr);
}
}
-
- *resist = dmgInfo.GetResist();
- *absorb = dmgInfo.GetAbsorb();
}
-void Unit::CalcHealAbsorb(HealInfo& healInfo)
+void Unit::CalcHealAbsorb(HealInfo& healInfo) const
{
if (!healInfo.GetHeal())
return;
@@ -2364,7 +2369,7 @@ void Unit::SendMeleeAttackStop(Unit* victim)
bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
{
// These spells can't be blocked
- if (spellProto && spellProto->HasAttribute(SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK))
+ if (spellProto && (spellProto->HasAttribute(SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK) || spellProto->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)))
return false;
// Can't block when casting/controlled
@@ -2429,11 +2434,6 @@ bool Unit::CanUseAttackType(uint8 attacktype) const
// Melee based spells hit result calculations
SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const
{
- // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore
- // resist and deflect chances
- if (spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
- return SPELL_MISS_NONE;
-
WeaponAttackType attType = BASE_ATTACK;
// Check damage class instead of attack type to correctly handle judgements
@@ -2581,7 +2581,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const
{
// Can`t miss on dead target (on skinning for example)
- if ((!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER) || spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
+ if ((!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER))
return SPELL_MISS_NONE;
SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
@@ -2675,19 +2675,23 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
// Resist
SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool CanReflect)
{
+ if (spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
+ return SPELL_MISS_NONE;
+
// Check for immune
if (victim->IsImmunedToSpell(spellInfo))
return SPELL_MISS_IMMUNE;
+ // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply
+ // returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit
+ if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(spellInfo))
+ return SPELL_MISS_IMMUNE;
+
// All positive spells can`t miss
/// @todo client not show miss log for this spells - so need find info for this in dbc and use it!
if (spellInfo->IsPositive() && !IsHostileTo(victim)) // prevent from affecting enemy by "positive" spell
return SPELL_MISS_NONE;
- // Check for immune
- if (victim->IsImmunedToDamage(spellInfo))
- return SPELL_MISS_IMMUNE;
-
if (this == victim)
return SPELL_MISS_NONE;
@@ -2901,8 +2905,8 @@ float Unit::GetUnitBlockChance(WeaponAttackType attType, Unit const* victim) con
float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victim) const
{
int32 const attackerWeaponSkill = GetWeaponSkillValue(attackType, victim);
- int32 const victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this);
- int32 const skillDiff = victimMaxSkillValueForLevel - attackerWeaponSkill;
+ int32 const victimDefenseSkill = victim->GetDefenseSkillValue(this);
+ int32 const skillDiff = victimDefenseSkill - attackerWeaponSkill;
float chance = 0.0f;
float skillBonus = 0.0f;
@@ -3296,10 +3300,13 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const
bool Unit::CanMoveDuringChannel() const
{
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
- if (spell->getState() != SPELL_STATE_FINISHED)
- return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && spell->IsChannelActive();
+ {
+ if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
+ if (!spell->GetSpellInfo()->IsMoveAllowedChannel())
+ return false;
+ }
- return false;
+ return true;
}
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
@@ -5242,10 +5249,10 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damag
void Unit::ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
{
WeaponAttackType attType = damageInfo ? damageInfo->GetAttackType() : BASE_ATTACK;
- if (typeMaskActor && CanProc())
+ if (typeMaskActor)
ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType);
- if (typeMaskActionTarget && actionTarget && actionTarget->CanProc())
+ if (typeMaskActionTarget && actionTarget)
actionTarget->ProcSkillsAndReactives(true, this, typeMaskActionTarget, hitMask, attType);
TriggerAurasProcOnEvent(actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
@@ -5471,6 +5478,8 @@ FactionTemplateEntry const* Unit::GetFactionTemplateEntry() const
TC_LOG_ERROR("entities.unit", "Creature (template id: %u) has invalid faction (faction template id) #%u", creature->GetCreatureTemplate()->Entry, getFaction());
else
TC_LOG_ERROR("entities.unit", "Unit (name=%s, type=%u) has invalid faction (faction template id) #%u", GetName().c_str(), uint32(GetTypeId()), getFaction());
+
+ ABORT();
}
return entry;
}
@@ -5526,8 +5535,7 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const
}
// check FFA_PVP
- if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP
- && target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP)
+ if (IsFFAPvP() && target->IsFFAPvP())
return REP_HOSTILE;
if (selfPlayerOwner)
@@ -5905,17 +5913,14 @@ void Unit::ModifyAuraState(AuraStateType flag, bool apply)
{
RemoveFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1));
- if (flag != AURA_STATE_ENRAGE) // enrage aura state triggering continues auras
+ Unit::AuraApplicationMap& tAuras = GetAppliedAuras();
+ for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
- Unit::AuraApplicationMap& tAuras = GetAppliedAuras();
- for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
- {
- SpellInfo const* spellProto = (*itr).second->GetBase()->GetSpellInfo();
- if (spellProto->CasterAuraState == uint32(flag))
- RemoveAura(itr);
- else
- ++itr;
- }
+ SpellInfo const* spellProto = itr->second->GetBase()->GetSpellInfo();
+ if (itr->second->GetBase()->GetCasterGUID() == GetGUID() && spellProto->CasterAuraState == uint32(flag) && (spellProto->IsPassive() || flag != AURA_STATE_ENRAGE))
+ RemoveAura(itr);
+ else
+ ++itr;
}
}
}
@@ -6590,7 +6595,7 @@ void Unit::SendHealSpellLog(HealInfo& healInfo, bool critical /*= false*/)
// we guess size
WorldPacket data(SMSG_SPELLHEALLOG, 8 + 8 + 4 + 4 + 4 + 4 + 1 + 1);
data << healInfo.GetTarget()->GetPackGUID();
- data << GetPackGUID();
+ data << healInfo.GetHealer()->GetPackGUID();
data << uint32(healInfo.GetSpellInfo()->Id);
data << uint32(healInfo.GetHeal());
data << uint32(healInfo.GetHeal() - healInfo.GetEffectiveHeal());
@@ -6680,11 +6685,12 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
// Impurity (dummy effect)
if (GetTypeId() == TYPEID_PLAYER)
{
- PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
+ PlayerSpellMap const& playerSpells = ToPlayer()->GetSpellMap();
+ for (auto itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
continue;
+
switch (itr->first)
{
case 49220:
@@ -6693,7 +6699,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
case 49636:
case 49638:
if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
- AddPct(ApCoeffMod, proto->Effects[0].CalcValue());
+ AddPct(ApCoeffMod, proto->Effects[EFFECT_0].CalcValue());
break;
}
}
@@ -6709,33 +6715,28 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage();
// Check for table values
- float coeff = 0;
+ float coeff = 0.0f;
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
if (bonus)
{
+ WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
+ float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
+ APbonus += GetTotalAttackPowerValue(attType);
+
if (damagetype == DOT)
{
coeff = bonus->dot_damage;
if (bonus->ap_dot_bonus > 0)
- {
- WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
- float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
- APbonus += GetTotalAttackPowerValue(attType);
DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
- }
}
else
{
coeff = bonus->direct_damage;
if (bonus->ap_bonus > 0)
- {
- WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
- float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
- APbonus += GetTotalAttackPowerValue(attType);
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
- }
}
}
+
// Default calculation
if (DoneAdvertisedBenefit)
{
@@ -6753,14 +6754,16 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
+ float tmpDamage = (int32(pdamage) + DoneTotal);
+
+ // DOTs calculated in AuraEffect::PeriodicDamageAurasTick
// Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
- float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype));
- // apply spellmod to Done damage (flat and pct)
- if (Player* modOwner = GetSpellModOwner())
+ if (damagetype != DOT)
{
- if (damagetype == DOT)
- modOwner->ApplySpellMod<SPELLMOD_DOT>(spellProto->Id, tmpDamage);
- else
+ tmpDamage *= SpellDamagePctDone(victim, spellProto, damagetype);
+
+ // apply spellmod to Done damage (flat and pct)
+ if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod<SPELLMOD_DAMAGE>(spellProto->Id, tmpDamage);
}
@@ -6787,22 +6790,17 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
if (GetTypeId() == TYPEID_UNIT && !IsPet())
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
- AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
+ float maxModDamagePercentSchool = 0.0f;
+ if (GetTypeId() == TYPEID_PLAYER)
{
- if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
- continue;
-
- if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
- {
- if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
+ for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ if (spellProto->GetSchoolMask() & (1 << i))
+ maxModDamagePercentSchool = std::max(maxModDamagePercentSchool, GetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i));
}
+ else
+ maxModDamagePercentSchool = GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, spellProto->GetSchoolMask());
+
+ DoneTotalMod *= maxModDamagePercentSchool;
uint32 creatureTypeMask = victim->GetCreatureTypeMask();
@@ -7183,13 +7181,9 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
int32 DoneAdvertisedBenefit = 0;
AuraEffectList const& mDamageDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
- for (AuraEffectList::const_iterator i = mDamageDone.begin(); i != mDamageDone.end(); ++i)
- if (((*i)->GetMiscValue() & schoolMask) != 0 &&
- (*i)->GetSpellInfo()->EquippedItemClass == -1 &&
- // -1 == any item class (not wand then)
- (*i)->GetSpellInfo()->EquippedItemInventoryTypeMask == 0)
- // 0 == any inventory type (not wand then)
- DoneAdvertisedBenefit += (*i)->GetAmount();
+ for (AuraEffect const* aurEff : mDamageDone)
+ if (aurEff->GetMiscValue() & schoolMask)
+ DoneAdvertisedBenefit += aurEff->GetAmount();
if (GetTypeId() == TYPEID_PLAYER)
{
@@ -7198,22 +7192,20 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
// Damage bonus from stats
AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
- for (AuraEffectList::const_iterator i = mDamageDoneOfStatPercent.begin(); i != mDamageDoneOfStatPercent.end(); ++i)
+ for (AuraEffect const* aurEff : mDamageDoneOfStatPercent)
{
- if ((*i)->GetMiscValue() & schoolMask)
+ if ((aurEff->GetMiscValue() & schoolMask) != 0)
{
// stat used stored in miscValueB for this aura
- Stats usedStat = Stats((*i)->GetMiscValueB());
- DoneAdvertisedBenefit += int32(CalculatePct(GetStat(usedStat), (*i)->GetAmount()));
+ Stats const usedStat = static_cast<Stats>(aurEff->GetMiscValueB());
+ DoneAdvertisedBenefit += static_cast<int32>(CalculatePct(GetStat(usedStat), aurEff->GetAmount()));
}
}
- // ... and attack power
- AuraEffectList const& mDamageDonebyAP = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER);
- for (AuraEffectList::const_iterator i =mDamageDonebyAP.begin(); i != mDamageDonebyAP.end(); ++i)
- if ((*i)->GetMiscValue() & schoolMask)
- DoneAdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), (*i)->GetAmount()));
+ // ... and attack power
+ DoneAdvertisedBenefit += static_cast<int32>(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER, schoolMask)));
}
+
return DoneAdvertisedBenefit;
}
@@ -7534,6 +7526,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
return healamount;
+ float ApCoeffMod = 1.0f;
int32 DoneTotal = 0;
// done scripted mod (take it from owner)
@@ -7555,6 +7548,35 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
}
}
+ // Custom scripted damage
+ switch (spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_DEATHKNIGHT:
+ // Impurity (dummy effect)
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ PlayerSpellMap const& playerSpells = ToPlayer()->GetSpellMap();
+ for (auto itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
+ {
+ if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
+ continue;
+
+ switch (itr->first)
+ {
+ case 49220:
+ case 49633:
+ case 49635:
+ case 49636:
+ case 49638:
+ if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
+ AddPct(ApCoeffMod, proto->Effects[EFFECT_0].CalcValue());
+ break;
+ }
+ }
+ }
+ break;
+ }
+
// Done fixed damage bonus auras
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
@@ -7568,15 +7590,15 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
{
coeff = bonus->dot_damage;
if (bonus->ap_dot_bonus > 0)
- DoneTotal += int32(bonus->ap_dot_bonus * stack * GetTotalAttackPowerValue(
- (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass !=SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
+ DoneTotal += int32(bonus->ap_dot_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue(
+ (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
}
else
{
coeff = bonus->direct_damage;
if (bonus->ap_bonus > 0)
- DoneTotal += int32(bonus->ap_bonus * stack * GetTotalAttackPowerValue(
- (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass !=SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
+ DoneTotal += int32(bonus->ap_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue(
+ (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
}
}
else
@@ -7622,14 +7644,16 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
DoneTotal = 0;
}
+ float heal = float(int32(healamount) + DoneTotal);
+
+ // DOTs calculated in AuraEffect::HandlePeriodicHealAurasTick
// Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
- float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto));
- // apply spellmod to Done amount
- if (Player* modOwner = GetSpellModOwner())
+ if (damagetype != DOT)
{
- if (damagetype == DOT)
- modOwner->ApplySpellMod<SPELLMOD_DOT>(spellProto->Id, heal);
- else
+ heal *= SpellHealingPctDone(victim, spellProto);
+
+ // apply spellmod to Done amount
+ if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod<SPELLMOD_DAMAGE>(spellProto->Id, heal);
}
@@ -7857,18 +7881,18 @@ int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const
return advertisedBenefit;
}
-bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) const
+bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const
{
// If m_immuneToSchool type contain this school type, IMMUNE damage.
- SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
- for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
- if (itr->type & shoolMask)
+ SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
+ for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
+ if ((itr->first & schoolMask) != 0)
return true;
// If m_immuneToDamage type contain magic, IMMUNE damage.
- SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
- for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
- if (itr->type & shoolMask)
+ SpellImmuneContainer const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
+ for (auto itr = damageList.begin(); itr != damageList.end(); ++itr)
+ if ((itr->first & schoolMask) != 0)
return true;
return false;
@@ -7876,23 +7900,27 @@ bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) const
bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
{
- if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ if (!spellInfo)
return false;
- uint32 shoolMask = spellInfo->GetSchoolMask();
- if (spellInfo->Id != 42292 && spellInfo->Id != 59752)
- {
- // If m_immuneToSchool type contain this school type, IMMUNE damage.
- SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
- for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
- if (itr->type & shoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->spellId)))
- return true;
- }
+ // for example 40175
+ if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) && spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
+ return false;
+
+ if (spellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || spellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ return false;
+
+ uint32 schoolMask = spellInfo->GetSchoolMask();
+ // If m_immuneToSchool type contain this school type, IMMUNE damage.
+ SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
+ for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
+ if ((itr->first & schoolMask) && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->second)))
+ return true;
// If m_immuneToDamage type contain magic, IMMUNE damage.
- SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
- for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
- if (itr->type & shoolMask)
+ SpellImmuneContainer const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
+ for (auto itr = damageList.begin(); itr != damageList.end(); ++itr)
+ if ((itr->first & schoolMask) != 0)
return true;
return false;
@@ -7904,29 +7932,26 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
return false;
// Single spell immunity.
- SpellImmuneList const& idList = m_spellImmune[IMMUNITY_ID];
- for (SpellImmuneList::const_iterator itr = idList.begin(); itr != idList.end(); ++itr)
- if (itr->type == spellInfo->Id)
- return true;
+ SpellImmuneContainer const& idList = m_spellImmune[IMMUNITY_ID];
+ if (idList.count(spellInfo->Id) > 0)
+ return true;
if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
- if (spellInfo->Dispel)
+ if (uint32 dispel = spellInfo->Dispel)
{
- SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
- for (SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
- if (itr->type == spellInfo->Dispel)
- return true;
+ SpellImmuneContainer const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
+ if (dispelList.count(dispel) > 0)
+ return true;
}
// Spells that don't have effectMechanics.
- if (spellInfo->Mechanic)
+ if (uint32 mechanic = spellInfo->Mechanic)
{
- SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
- for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
- if (itr->type == spellInfo->Mechanic)
- return true;
+ SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
+ if (mechanicList.count(mechanic) > 0)
+ return true;
}
bool immuneToAllEffects = true;
@@ -7934,8 +7959,6 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
{
// State/effect immunities applied by aura expect full spell immunity
// Ignore effects with mechanic, they are supposed to be checked separately
- if (!spellInfo->Effects[i].IsEffect())
- continue;
if (!IsImmunedToSpellEffect(spellInfo, i))
{
immuneToAllEffects = false;
@@ -7946,13 +7969,13 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects.
return true;
- if (spellInfo->Id != 42292 && spellInfo->Id != 59752)
+ if (!spellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !spellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
{
- SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
- for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
+ SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
+ for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
{
- SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
- if ((itr->type & spellInfo->GetSchoolMask())
+ SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
+ if ((itr->first & spellInfo->GetSchoolMask())
&& !(immuneSpellInfo && immuneSpellInfo->IsPositive() && spellInfo->IsPositive())
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
return true;
@@ -7965,9 +7988,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
uint32 Unit::GetSchoolImmunityMask() const
{
uint32 mask = 0;
- SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_SCHOOL];
- for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
- mask |= itr->type;
+ SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_SCHOOL];
+ for (auto itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
+ mask |= itr->first;
return mask;
}
@@ -7975,9 +7998,9 @@ uint32 Unit::GetSchoolImmunityMask() const
uint32 Unit::GetMechanicImmunityMask() const
{
uint32 mask = 0;
- SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
- for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
- mask |= (1 << itr->type);
+ SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
+ for (auto itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
+ mask |= (1 << itr->first);
return mask;
}
@@ -7992,33 +8015,35 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
// If m_immuneToEffect type contain this effect type, IMMUNE effect.
uint32 effect = spellInfo->Effects[index].Effect;
- SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
- for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
- if (itr->type == effect)
- return true;
+ auto const& effectList = m_spellImmune[IMMUNITY_EFFECT];
+ if (effectList.count(effect) > 0)
+ return true;
if (uint32 mechanic = spellInfo->Effects[index].Mechanic)
{
- SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
- for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
- if (itr->type == mechanic)
- return true;
+ auto const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
+ if (mechanicList.count(mechanic) > 0)
+ return true;
}
- if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
+ if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
{
- SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE];
- for (SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
- if (itr->type == aura)
- if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
- return true;
-
- // Check for immune to application of harmful magical effects
- AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
- for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
- if (((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school
- !spellInfo->IsPositiveEffect(index)) // Harmful
+ if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
+ {
+ SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE];
+ if (list.count(aura) > 0)
return true;
+
+ if (!spellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ {
+ // Check for immune to application of harmful magical effects
+ AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
+ for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
+ if (((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school
+ !spellInfo->IsPositiveEffect(index)) // Harmful
+ return true;
+ }
+ }
}
return false;
@@ -8069,15 +8094,8 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (APbonus != 0) // Can be negative
{
- bool normalized = false;
- if (spellProto)
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellProto->Effects[i].Effect == SPELL_EFFECT_NORMALIZED_WEAPON_DMG)
- {
- normalized = true;
- break;
- }
- DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType, normalized));
+ bool const normalized = spellProto && spellProto->HasEffect(SPELL_EFFECT_NORMALIZED_WEAPON_DMG);
+ DoneFlatBenefit += int32(APbonus / 14.0f * GetAPMultiplier(attType, normalized));
}
// Done total percent damage auras
@@ -8085,22 +8103,23 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
// Some spells don't benefit from pct done mods
if (spellProto)
- if (!spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
+ {
+ // mods for SPELL_SCHOOL_MASK_NORMAL are already factored in base melee damage calculation
+ if (!spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
{
- AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
+ float maxModDamagePercentSchool = 0.0f;
+ if (GetTypeId() == TYPEID_PLAYER)
{
- if ((*i)->GetMiscValue() & spellProto->GetSchoolMask() && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
- {
- if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
+ for (uint32 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
+ if (spellProto->GetSchoolMask() & (1 << i))
+ maxModDamagePercentSchool = std::max(maxModDamagePercentSchool, GetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i));
}
+ else
+ maxModDamagePercentSchool = GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, spellProto->GetSchoolMask());
+
+ DoneTotalMod *= maxModDamagePercentSchool;
}
+ }
AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
@@ -8324,52 +8343,14 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
{
if (apply)
- {
- for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(), next; itr != m_spellImmune[op].end(); itr = next)
- {
- next = itr; ++next;
- if (itr->type == type)
- {
- m_spellImmune[op].erase(itr);
- next = m_spellImmune[op].begin();
- }
- }
- SpellImmune Immune;
- Immune.spellId = spellId;
- Immune.type = type;
- m_spellImmune[op].push_back(Immune);
- }
+ m_spellImmune[op].emplace(type, spellId);
else
{
- for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(); itr != m_spellImmune[op].end(); ++itr)
- {
- if (itr->spellId == spellId && itr->type == type)
- {
- m_spellImmune[op].erase(itr);
- break;
- }
- }
- }
-}
-
-void Unit::ApplySpellDispelImmunity(const SpellInfo* spellProto, DispelType type, bool apply)
-{
- ApplySpellImmune(spellProto->Id, IMMUNITY_DISPEL, type, apply);
-
- if (apply && spellProto->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
- {
- // Create dispel mask by dispel type
- uint32 dispelMask = SpellInfo::GetDispelMask(type);
- // Dispel all existing auras vs current dispel type
- AuraApplicationMap& auras = GetAppliedAuras();
- for (AuraApplicationMap::iterator itr = auras.begin(); itr != auras.end();)
+ auto bounds = m_spellImmune[op].equal_range(type);
+ for (auto itr = bounds.first; itr != bounds.second;)
{
- SpellInfo const* spell = itr->second->GetBase()->GetSpellInfo();
- if (spell->GetDispelMask() & dispelMask)
- {
- // Dispel aura
- RemoveAura(itr);
- }
+ if (itr->second == spellId)
+ itr = m_spellImmune[op].erase(itr);
else
++itr;
}
@@ -8687,9 +8668,26 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
|| (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster()))
return false;
- // can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit. Ignore stealth if target is player and unit in combat with same player
- if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, (bySpell && bySpell->IsAffectingArea()) || (target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target)))))
- return false;
+ // visibility checks
+ // skip visibility check for GO casts, needs removal when go cast is implemented. Also ignore for gameobject and dynauras
+ if (GetEntry() != WORLD_TRIGGER && (!obj || !obj->isType(TYPEMASK_GAMEOBJECT | TYPEMASK_DYNAMICOBJECT)))
+ {
+ // can't attack invisible
+ if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE))
+ {
+ if (obj && !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
+ return false;
+ else if (!obj)
+ {
+ // ignore stealth for aoe spells. Ignore stealth if target is player and unit in combat with same player
+ bool const ignoreStealthCheck = (bySpell && bySpell->IsAffectingArea()) ||
+ (target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target));
+
+ if (!CanSeeOrDetect(target, ignoreStealthCheck))
+ return false;
+ }
+ }
+ }
// can't attack dead
if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && !target->IsAlive())
@@ -8720,7 +8718,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
// PvP, PvC, CvP case
// can't attack friendly targets
- if ( GetReactionTo(target) > REP_NEUTRAL
+ if (GetReactionTo(target) > REP_NEUTRAL
|| target->GetReactionTo(this) > REP_NEUTRAL)
return false;
@@ -8728,10 +8726,8 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : nullptr;
// Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
- if (
- (playerAffectingAttacker && !playerAffectingTarget) ||
- (!playerAffectingAttacker && playerAffectingTarget)
- )
+ if ((playerAffectingAttacker && !playerAffectingTarget) ||
+ (!playerAffectingAttacker && playerAffectingTarget))
{
Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget;
Unit const* creature = playerAffectingAttacker ? target : this;
@@ -8765,15 +8761,14 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
// additional checks - only PvP case
if (playerAffectingAttacker && playerAffectingTarget)
{
- if (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP)
+ if (target->IsPvP())
return true;
- if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP
- && target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP)
+ if (IsFFAPvP() && target->IsFFAPvP())
return true;
- return (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1)
- || (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1);
+ return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK1)
+ || target->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK1);
}
return true;
}
@@ -9760,9 +9755,6 @@ DiminishingLevels Unit::GetDiminishing(DiminishingGroup group)
if (!diminish.hitCount)
return DIMINISHING_LEVEL_1;
- if (!diminish.hitTime)
- return DIMINISHING_LEVEL_1;
-
// If last spell was cast more than 15 seconds ago - reset the count.
if (!diminish.stack && GetMSTimeDiffToNow(diminish.hitTime) > 15000)
{
@@ -10799,14 +10791,13 @@ uint32 createProcHitMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCond
hitMask |= PROC_HIT_PARRY;
break;
case SPELL_MISS_BLOCK:
- hitMask |= PROC_HIT_BLOCK;
+ // spells can't be partially blocked (it's damage can though)
+ hitMask |= PROC_HIT_BLOCK | PROC_HIT_FULL_BLOCK;
break;
case SPELL_MISS_EVADE:
hitMask |= PROC_HIT_EVADE;
break;
case SPELL_MISS_IMMUNE:
- hitMask |= PROC_HIT_IMMUNE;
- break;
case SPELL_MISS_IMMUNE2:
hitMask |= PROC_HIT_IMMUNE;
break;
@@ -10819,6 +10810,9 @@ uint32 createProcHitMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCond
case SPELL_MISS_REFLECT:
hitMask |= PROC_HIT_REFLECT;
break;
+ case SPELL_MISS_RESIST:
+ hitMask |= PROC_HIT_FULL_RESIST;
+ break;
default:
break;
}
@@ -10827,15 +10821,27 @@ uint32 createProcHitMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCond
{
// On block
if (damageInfo->blocked)
+ {
hitMask |= PROC_HIT_BLOCK;
+ if (damageInfo->fullBlock)
+ hitMask |= PROC_HIT_FULL_BLOCK;
+ }
// On absorb
if (damageInfo->absorb)
hitMask |= PROC_HIT_ABSORB;
- // On crit
- if (damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT)
- hitMask |= PROC_HIT_CRITICAL;
- else
- hitMask |= PROC_HIT_NORMAL;
+
+ // Don't set hit/crit hitMask if damage is nullified
+ bool const damageNullified = (damageInfo->HitInfo & (HITINFO_FULL_ABSORB | HITINFO_FULL_RESIST)) != 0 || (hitMask & PROC_HIT_FULL_BLOCK) != 0;
+ if (!damageNullified)
+ {
+ // On crit
+ if (damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT)
+ hitMask |= PROC_HIT_CRITICAL;
+ else
+ hitMask |= PROC_HIT_NORMAL;
+ }
+ else if ((damageInfo->HitInfo & HITINFO_FULL_RESIST) != 0)
+ hitMask |= PROC_HIT_FULL_RESIST;
}
return hitMask;
@@ -10924,7 +10930,7 @@ void Unit::GetProcAurasTriggeredOnEvent(AuraApplicationProcContainer& aurasTrigg
for (AuraApplication* aurApp : *procAuras)
{
ASSERT(aurApp->GetTarget() == this);
- if (uint8 procEffectMask = aurApp->GetBase()->IsProcTriggeredOnEvent(aurApp, eventInfo, now))
+ if (uint8 procEffectMask = aurApp->GetBase()->GetProcEffectMask(aurApp, eventInfo, now))
{
aurApp->GetBase()->PrepareProcToTrigger(aurApp, eventInfo, now);
aurasTriggeringProc.emplace_back(procEffectMask, aurApp);
@@ -10936,7 +10942,7 @@ void Unit::GetProcAurasTriggeredOnEvent(AuraApplicationProcContainer& aurasTrigg
{
for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr != GetAppliedAuras().end(); ++itr)
{
- if (uint8 procEffectMask = itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo, now))
+ if (uint8 procEffectMask = itr->second->GetBase()->GetProcEffectMask(itr->second, eventInfo, now))
{
itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo, now);
aurasTriggeringProc.emplace_back(procEffectMask, itr->second);
@@ -10955,16 +10961,31 @@ void Unit::TriggerAurasProcOnEvent(Unit* actionTarget, uint32 typeMaskActor, uin
{
// prepare data for self trigger
ProcEventInfo myProcEventInfo(this, actionTarget, actionTarget, typeMaskActor, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
- if (typeMaskActor && CanProc())
+ if (typeMaskActor)
{
AuraApplicationProcContainer myAurasTriggeringProc;
GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, nullptr, myProcEventInfo);
+
+ // needed for example for Cobra Strikes, pet does the attack, but aura is on owner
+ if (Player* modOwner = GetSpellModOwner())
+ {
+ if (modOwner != this && spell)
+ {
+ AuraApplicationList modAuras;
+ for (auto itr = modOwner->GetAppliedAuras().begin(); itr != modOwner->GetAppliedAuras().end(); ++itr)
+ {
+ if (spell->m_appliedMods.count(itr->second->GetBase()) != 0)
+ modAuras.push_back(itr->second);
+ }
+ modOwner->GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, &modAuras, myProcEventInfo);
+ }
+ }
TriggerAurasProcOnEvent(myProcEventInfo, myAurasTriggeringProc);
}
// prepare data for target trigger
ProcEventInfo targetProcEventInfo(this, actionTarget, this, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
- if (typeMaskActionTarget && actionTarget && actionTarget->CanProc())
+ if (typeMaskActionTarget && actionTarget)
{
AuraApplicationProcContainer targetAurasTriggeringProc;
actionTarget->GetProcAurasTriggeredOnEvent(targetAurasTriggeringProc, nullptr, targetProcEventInfo);
@@ -10974,6 +10995,11 @@ void Unit::TriggerAurasProcOnEvent(Unit* actionTarget, uint32 typeMaskActor, uin
void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProcContainer& aurasTriggeringProc)
{
+ Spell const* triggeringSpell = eventInfo.GetProcSpell();
+ bool const disableProcs = triggeringSpell && triggeringSpell->IsProcDisabled();
+ if (disableProcs)
+ SetCantProc(true);
+
for (auto const& aurAppProc : aurasTriggeringProc)
{
AuraApplication* aurApp;
@@ -10992,6 +11018,9 @@ void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProc
if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
SetCantProc(false);
}
+
+ if (disableProcs)
+ SetCantProc(false);
}
SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const
@@ -11441,26 +11470,41 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
{
- if (!normalized || GetTypeId() != TYPEID_PLAYER)
- return float(GetAttackTime(attType)) / 1000.0f;
+ if (GetTypeId() != TYPEID_PLAYER)
+ return GetAttackTime(attType) / 1000.0f;
+
+ Item* weapon = ToPlayer()->GetWeaponForAttack(attType, true);
+ if (!weapon)
+ return BASE_ATTACK_TIME / 1000.0f;
- Item* Weapon = ToPlayer()->GetWeaponForAttack(attType, true);
- if (!Weapon)
- return 2.4f; // fist attack
+ if (!normalized)
+ return weapon->GetTemplate()->Delay / 1000.0f;
- switch (Weapon->GetTemplate()->InventoryType)
+ switch (weapon->GetTemplate()->SubClass)
{
- case INVTYPE_2HWEAPON:
+ case ITEM_SUBCLASS_WEAPON_AXE2:
+ case ITEM_SUBCLASS_WEAPON_MACE2:
+ case ITEM_SUBCLASS_WEAPON_POLEARM:
+ case ITEM_SUBCLASS_WEAPON_SWORD2:
+ case ITEM_SUBCLASS_WEAPON_STAFF:
+ case ITEM_SUBCLASS_WEAPON_FISHING_POLE:
return 3.3f;
- case INVTYPE_RANGED:
- case INVTYPE_RANGEDRIGHT:
- case INVTYPE_THROWN:
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ case ITEM_SUBCLASS_WEAPON_THROWN:
return 2.8f;
- case INVTYPE_WEAPON:
- case INVTYPE_WEAPONMAINHAND:
- case INVTYPE_WEAPONOFFHAND:
+ case ITEM_SUBCLASS_WEAPON_AXE:
+ case ITEM_SUBCLASS_WEAPON_MACE:
+ case ITEM_SUBCLASS_WEAPON_SWORD:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC2:
+ case ITEM_SUBCLASS_WEAPON_FIST:
+ return 2.4f;
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ return 1.7f;
default:
- return Weapon->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7f : 2.4f;
+ return weapon->GetTemplate()->Delay / 1000.0f;
}
}
@@ -12488,8 +12532,9 @@ bool Unit::IsInPartyWith(Unit const* unit) const
else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) ||
(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))
return true;
- else
- return false;
+
+ // else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
+ return u1->getFaction() == u2->getFaction();
}
bool Unit::IsInRaidWith(Unit const* unit) const
@@ -12507,8 +12552,9 @@ bool Unit::IsInRaidWith(Unit const* unit) const
else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) ||
(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))
return true;
- else
- return false;
+
+ // else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
+ return u1->getFaction() == u2->getFaction();
}
void Unit::GetPartyMembers(std::list<Unit*> &TagUnitMap)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 20cdc75c001..917e5d24c79 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -377,13 +377,7 @@ class SpellCastTargets;
typedef std::list<Unit*> UnitList;
typedef std::list<std::pair<Aura*, uint8>> DispelChargesList;
-struct SpellImmune
-{
- uint32 type;
- uint32 spellId;
-};
-
-typedef std::list<SpellImmune> SpellImmuneList;
+typedef std::unordered_multimap<uint32 /*type*/, uint32 /*spellId*/> SpellImmuneContainer;
enum UnitModifierType
{
@@ -425,12 +419,18 @@ enum TriggerCastFlags
TRIGGERED_IGNORE_SET_FACING = 0x00000200, //! Will not adjust facing to target (if any)
TRIGGERED_IGNORE_SHAPESHIFT = 0x00000400, //! Will ignore shapeshift checks
TRIGGERED_IGNORE_CASTER_AURASTATE = 0x00000800, //! Will ignore caster aura states including combat requirements and death state
+ TRIGGERED_DISALLOW_PROC_EVENTS = 0x00001000, //! Disallows proc events from triggered spell (default)
TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE = 0x00002000, //! Will ignore mounted/on vehicle restrictions
+ // reuse = 0x00004000,
+ // reuse = 0x00008000,
TRIGGERED_IGNORE_CASTER_AURAS = 0x00010000, //! Will ignore caster aura restrictions or requirements
TRIGGERED_DONT_RESET_PERIODIC_TIMER = 0x00020000, //! Will allow periodic aura timers to keep ticking (instead of resetting)
TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions
+ TRIGGERED_FULL_MASK = 0x0007FFFF, //! Used when doing CastSpell with triggered == true
+
+ // debug flags (used with .cast triggered commands)
TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements
- TRIGGERED_FULL_MASK = 0xFFFFFFFF
+ TRIGGERED_FULL_DEBUG_MASK = 0xFFFFFFFF
};
enum UnitMods
@@ -983,7 +983,7 @@ struct TC_GAME_API SpellNonMeleeDamage
{
SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _schoolMask)
: target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(0), schoolMask(_schoolMask),
- absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0)
+ absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0), fullBlock(false)
{ }
Unit *target;
@@ -1000,6 +1000,7 @@ struct TC_GAME_API SpellNonMeleeDamage
uint32 HitInfo;
// Used for help
uint32 cleanDamage;
+ bool fullBlock;
};
struct SpellPeriodicAuraLogInfo
@@ -1433,7 +1434,7 @@ class TC_GAME_API Unit : public WorldObject
void Dismount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
- void DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb);
+ void DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const;
uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = NULL, bool durabilityLoss = true);
void Kill(Unit* victim, bool durabilityLoss = true);
void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
@@ -1560,19 +1561,19 @@ class TC_GAME_API Unit : public WorldObject
int32 HealBySpell(HealInfo& healInfo, bool critical = false);
void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powerType);
void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype);
- uint32 SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage);
-
- void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem = NULL, AuraEffect* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastCustomSpell(Unit* victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim, bool triggered, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim = NULL, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
- void CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* victim = NULL, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty);
+
+ void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastCustomSpell(Unit* victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim = nullptr, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
+ void CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* victim = nullptr, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty);
Aura* AddAura(uint32 spellId, Unit* target);
Aura* AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target);
void SetAuraStack(uint32 spellId, Unit* target, uint32 stack);
@@ -1936,7 +1937,7 @@ class TC_GAME_API Unit : public WorldObject
void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask
void UpdateObjectVisibility(bool forced = true) override;
- SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
+ SpellImmuneContainer m_spellImmune[MAX_SPELL_IMMUNITY];
uint32 m_lastSanctuaryTime;
// Threat related methods
@@ -2021,7 +2022,6 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetRemainingPeriodicAmount(ObjectGuid caster, uint32 spellId, AuraType auraType, uint8 effectIndex = 0) const;
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
- void ApplySpellDispelImmunity(const SpellInfo* spellProto, DispelType type, bool apply);
virtual bool IsImmunedToSpell(SpellInfo const* spellInfo) const; // redefined in Creature
uint32 GetSchoolImmunityMask() const;
uint32 GetMechanicImmunityMask() const;
@@ -2033,8 +2033,8 @@ class TC_GAME_API Unit : public WorldObject
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS);
uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK);
uint32 CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const;
- void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL);
- void CalcHealAbsorb(HealInfo& healInfo);
+ void CalcAbsorbResist(DamageInfo& damageInfo);
+ void CalcHealAbsorb(HealInfo& healInfo) const;
void UpdateSpeed(UnitMoveType mtype);
float GetSpeed(UnitMoveType mtype) const;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 21bb6261971..e594cf7f289 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -804,7 +804,10 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction);
if (!factionTemplate)
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has non-existing faction template (%u).", cInfo->Entry, cInfo->faction);
+ {
+ TC_LOG_FATAL("sql.sql", "Creature (Entry: %u) has non-existing faction template (%u). This can lead to crashes, aborting.", cInfo->Entry, cInfo->faction);
+ ABORT();
+ }
// used later for scale
CreatureDisplayInfoEntry const* displayScaleEntry = nullptr;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index df4788a0a1e..ac153f31b8e 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -642,6 +642,7 @@ namespace Trinity
{
public:
GameObjectFocusCheck(Unit const* unit, uint32 focusId) : i_unit(unit), i_focusId(focusId) { }
+
bool operator()(GameObject* go) const
{
if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS)
@@ -657,6 +658,7 @@ namespace Trinity
return go->IsWithinDistInMap(i_unit, dist);
}
+
private:
Unit const* i_unit;
uint32 i_focusId;
@@ -667,6 +669,7 @@ namespace Trinity
{
public:
NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) { }
+
bool operator()(GameObject* go)
{
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, (float)go->GetGOInfo()->fishinghole.radius))
@@ -676,19 +679,20 @@ namespace Trinity
}
return false;
}
- float GetLastRange() const { return i_range; }
+
private:
WorldObject const& i_obj;
- float i_range;
+ float i_range;
// prevent clone
- NearestGameObjectFishingHole(NearestGameObjectFishingHole const&);
+ NearestGameObjectFishingHole(NearestGameObjectFishingHole const&) = delete;
};
class NearestGameObjectCheck
{
public:
- NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) { }
+ NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999.f) { }
+
bool operator()(GameObject* go)
{
if (i_obj.IsWithinDistInMap(go, i_range))
@@ -698,13 +702,13 @@ namespace Trinity
}
return false;
}
- float GetLastRange() const { return i_range; }
+
private:
WorldObject const& i_obj;
float i_range;
// prevent clone this object
- NearestGameObjectCheck(NearestGameObjectCheck const&);
+ NearestGameObjectCheck(NearestGameObjectCheck const&) = delete;
};
// Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO)
@@ -712,6 +716,7 @@ namespace Trinity
{
public:
NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj, uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) { }
+
bool operator()(GameObject* go)
{
if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range))
@@ -721,38 +726,39 @@ namespace Trinity
}
return false;
}
- float GetLastRange() const { return i_range; }
+
private:
WorldObject const& i_obj;
uint32 i_entry;
float i_range;
// prevent clone this object
- NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&);
+ NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&) = delete;
};
// Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO with a certain type)
class NearestGameObjectTypeInObjectRangeCheck
{
- public:
- NearestGameObjectTypeInObjectRangeCheck(WorldObject const& obj, GameobjectTypes type, float range) : i_obj(obj), i_type(type), i_range(range) { }
- bool operator()(GameObject* go)
- {
- if (go->GetGoType() == i_type && i_obj.IsWithinDistInMap(go, i_range))
+ public:
+ NearestGameObjectTypeInObjectRangeCheck(WorldObject const& obj, GameobjectTypes type, float range) : i_obj(obj), i_type(type), i_range(range) { }
+
+ bool operator()(GameObject* go)
{
- i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check
- return true;
+ if (go->GetGoType() == i_type && i_obj.IsWithinDistInMap(go, i_range))
+ {
+ i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check
+ return true;
+ }
+ return false;
}
- return false;
- }
- float GetLastRange() const { return i_range; }
- private:
- WorldObject const& i_obj;
- GameobjectTypes i_type;
- float i_range;
- // prevent clone this object
- NearestGameObjectTypeInObjectRangeCheck(NearestGameObjectTypeInObjectRangeCheck const&);
+ private:
+ WorldObject const& i_obj;
+ GameobjectTypes i_type;
+ float i_range;
+
+ // prevent clone this object
+ NearestGameObjectTypeInObjectRangeCheck(NearestGameObjectTypeInObjectRangeCheck const&) = delete;
};
// Unit checks
@@ -761,6 +767,7 @@ namespace Trinity
{
public:
MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) { }
+
bool operator()(Unit* u)
{
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp)
@@ -770,6 +777,7 @@ namespace Trinity
}
return false;
}
+
private:
Unit const* i_obj;
float i_range;
@@ -780,7 +788,8 @@ namespace Trinity
{
public:
FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) { }
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
(u->isFeared() || u->IsCharmed() || u->isFrozen() || u->HasUnitState(UNIT_STATE_STUNNED) || u->HasUnitState(UNIT_STATE_CONFUSED)))
@@ -789,6 +798,7 @@ namespace Trinity
}
return false;
}
+
private:
Unit const* i_obj;
float i_range;
@@ -798,15 +808,15 @@ namespace Trinity
{
public:
FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) { }
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
- if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
- !(u->HasAura(i_spell)))
- {
+ if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && !u->HasAura(i_spell))
return true;
- }
+
return false;
}
+
private:
Unit const* i_obj;
float i_range;
@@ -817,23 +827,26 @@ namespace Trinity
{
public:
AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { }
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u))
return true;
- else
- return false;
+
+ return false;
}
+
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
};
- class AnyUnfriendlyNoTotemUnitInObjectRangeCheck
+ class NearestAttackableNoTotemUnitInObjectRangeCheck
{
public:
- AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { }
+ NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { }
+
bool operator()(Unit* u)
{
if (!u->IsAlive())
@@ -842,14 +855,19 @@ namespace Trinity
if (u->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
- if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->IsTotem())
+ if (u->GetTypeId() == TYPEID_UNIT && u->ToCreature()->IsTotem())
return false;
if (!u->isTargetableForAttack(false))
return false;
- return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u);
+ if (!i_obj->IsWithinDistInMap(u, i_range) || !i_funit->_IsValidAttackTarget(u, nullptr, i_obj))
+ return false;
+
+ i_range = i_obj->GetDistance(*u);
+ return true;
}
+
private:
WorldObject const* i_obj;
Unit const* i_funit;
@@ -860,13 +878,15 @@ namespace Trinity
{
public:
AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) { }
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->GetTypeId() == TYPEID_PLAYER))
return true;
else
return false;
}
+
private:
WorldObject const* i_obj;
Unit const* i_funit;
@@ -878,7 +898,8 @@ namespace Trinity
{
public:
AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false) : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly) { }
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
if (G3D::fuzzyEq(_range, 0.0f))
return false;
@@ -909,13 +930,15 @@ namespace Trinity
{
public:
AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) { }
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range))
return true;
return false;
}
+
private:
WorldObject const* i_obj;
float i_range;
@@ -926,6 +949,7 @@ namespace Trinity
{
public:
NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { }
+
bool operator()(Unit* u)
{
if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) &&
@@ -937,13 +961,14 @@ namespace Trinity
return false;
}
+
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
// prevent clone this object
- NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&);
+ NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&) = delete;
};
class AnyAoETargetUnitInObjectRangeCheck
@@ -952,17 +977,12 @@ namespace Trinity
AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr)
: i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range)
{
- Unit const* check = i_funit;
- Unit const* owner = i_funit->GetOwner();
- if (owner)
- check = owner;
- i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER);
-
if (!_spellInfo)
if (DynamicObject const* dynObj = i_obj->ToDynObject())
_spellInfo = sSpellMgr->GetSpellInfo(dynObj->GetSpellId());
}
- bool operator()(Unit* u)
+
+ bool operator()(Unit* u) const
{
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
if (u->GetTypeId() == TYPEID_UNIT && u->IsTotem())
@@ -973,8 +993,8 @@ namespace Trinity
return i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr) && i_obj->IsWithinDistInMap(u, i_range);
}
+
private:
- bool i_targetForPlayer;
WorldObject const* i_obj;
Unit const* i_funit;
SpellInfo const* _spellInfo;
@@ -986,9 +1006,9 @@ namespace Trinity
{
public:
CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range)
- : i_funit(funit), i_enemy(enemy), i_range(range)
- { }
- void operator()(Creature* u)
+ : i_funit(funit), i_enemy(enemy), i_range(range) { }
+
+ void operator()(Creature* u) const
{
if (u == i_funit)
return;
@@ -1013,27 +1033,16 @@ namespace Trinity
float i_range;
};
- struct AnyDeadUnitCheck
- {
- bool operator()(Unit* u) { return !u->IsAlive(); }
- };
-
- /*
- struct AnyStealthedCheck
- {
- bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; }
- };
- */
-
// Creature checks
class NearestHostileUnitCheck
{
public:
- explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0, bool playerOnly = false) : me(creature), i_playerOnly(playerOnly)
+ explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0.f, bool playerOnly = false) : me(creature), i_playerOnly(playerOnly)
{
- m_range = (dist == 0 ? 9999 : dist);
+ m_range = (dist == 0.f ? 9999.f : dist);
}
+
bool operator()(Unit* u)
{
if (!me->IsWithinDistInMap(u, m_range))
@@ -1049,21 +1058,22 @@ namespace Trinity
return true;
}
- private:
+ private:
Creature const* me;
float m_range;
bool i_playerOnly;
- NearestHostileUnitCheck(NearestHostileUnitCheck const&);
+ NearestHostileUnitCheck(NearestHostileUnitCheck const&) = delete;
};
class NearestHostileUnitInAttackDistanceCheck
{
public:
- explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature)
+ explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0.f) : me(creature)
{
- m_range = (dist == 0 ? 9999 : dist);
- m_force = (dist == 0 ? false : true);
+ m_range = (dist == 0.f ? 9999.f : dist);
+ m_force = (dist == 0.f ? false : true);
}
+
bool operator()(Unit* u)
{
if (!me->IsWithinDistInMap(u, m_range))
@@ -1083,21 +1093,20 @@ namespace Trinity
m_range = me->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
- float GetLastRange() const { return m_range; }
+
private:
Creature const* me;
float m_range;
bool m_force;
- NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&);
+ NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&) = delete;
};
class NearestHostileUnitInAggroRangeCheck
{
public:
- explicit NearestHostileUnitInAggroRangeCheck(Creature const* creature, bool useLOS = false) : _me(creature), _useLOS(useLOS)
- {
- }
- bool operator()(Unit* u)
+ explicit NearestHostileUnitInAggroRangeCheck(Creature const* creature, bool useLOS = false) : _me(creature), _useLOS(useLOS) { }
+
+ bool operator()(Unit* u) const
{
if (!u->IsHostileTo(_me))
return false;
@@ -1114,20 +1123,19 @@ namespace Trinity
return true;
}
- private:
+ private:
Creature const* _me;
bool _useLOS;
- NearestHostileUnitInAggroRangeCheck(NearestHostileUnitInAggroRangeCheck const&);
+ NearestHostileUnitInAggroRangeCheck(NearestHostileUnitInAggroRangeCheck const&) = delete;
};
class AnyAssistCreatureInRangeCheck
{
public:
AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range)
- : i_funit(funit), i_enemy(enemy), i_range(range)
- {
- }
- bool operator()(Creature* u)
+ : i_funit(funit), i_enemy(enemy), i_range(range) { }
+
+ bool operator()(Creature* u) const
{
if (u == i_funit)
return false;
@@ -1145,6 +1153,7 @@ namespace Trinity
return true;
}
+
private:
Unit* const i_funit;
Unit* const i_enemy;
@@ -1173,14 +1182,14 @@ namespace Trinity
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
- float GetLastRange() const { return i_range; }
+
private:
Creature* const i_obj;
Unit* const i_enemy;
float i_range;
// prevent clone this object
- NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&);
+ NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&) = delete;
};
// Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature)
@@ -1199,7 +1208,7 @@ namespace Trinity
}
return false;
}
- float GetLastRange() const { return i_range; }
+
private:
WorldObject const& i_obj;
uint32 i_entry;
@@ -1207,14 +1216,15 @@ namespace Trinity
float i_range;
// prevent clone this object
- NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&);
+ NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&) = delete;
};
class AnyPlayerInObjectRangeCheck
{
public:
AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range, bool reqAlive = true) : _obj(obj), _range(range), _reqAlive(reqAlive) { }
- bool operator()(Player* u)
+
+ bool operator()(Player* u) const
{
if (_reqAlive && !u->IsAlive())
return false;
@@ -1234,9 +1244,7 @@ namespace Trinity
class NearestPlayerInObjectRangeCheck
{
public:
- NearestPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range)
- {
- }
+ NearestPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) { }
bool operator()(Player* u)
{
@@ -1252,46 +1260,51 @@ namespace Trinity
WorldObject const* i_obj;
float i_range;
- NearestPlayerInObjectRangeCheck(NearestPlayerInObjectRangeCheck const&);
+ NearestPlayerInObjectRangeCheck(NearestPlayerInObjectRangeCheck const&) = delete;
};
class AllFriendlyCreaturesInGrid
{
- public:
- AllFriendlyCreaturesInGrid(Unit const* obj) : unit(obj) { }
- bool operator() (Unit* u)
- {
- if (u->IsAlive() && u->IsVisible() && u->IsFriendlyTo(unit))
- return true;
+ public:
+ AllFriendlyCreaturesInGrid(Unit const* obj) : unit(obj) { }
- return false;
- }
- private:
- Unit const* unit;
+ bool operator()(Unit* u) const
+ {
+ if (u->IsAlive() && u->IsVisible() && u->IsFriendlyTo(unit))
+ return true;
+
+ return false;
+ }
+
+ private:
+ Unit const* unit;
};
class AllGameObjectsWithEntryInRange
{
- public:
- AllGameObjectsWithEntryInRange(const WorldObject* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) { }
- bool operator() (GameObject* go)
- {
- if ((!m_uiEntry || go->GetEntry() == m_uiEntry) && m_pObject->IsWithinDist(go, m_fRange, false))
- return true;
+ public:
+ AllGameObjectsWithEntryInRange(const WorldObject* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) { }
- return false;
- }
- private:
- const WorldObject* m_pObject;
- uint32 m_uiEntry;
- float m_fRange;
+ bool operator()(GameObject* go) const
+ {
+ if ((!m_uiEntry || go->GetEntry() == m_uiEntry) && m_pObject->IsWithinDist(go, m_fRange, false))
+ return true;
+
+ return false;
+ }
+
+ private:
+ WorldObject const* m_pObject;
+ uint32 m_uiEntry;
+ float m_fRange;
};
class AllCreaturesOfEntryInRange
{
public:
AllCreaturesOfEntryInRange(const WorldObject* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) { }
- bool operator() (Unit* unit)
+
+ bool operator()(Unit* unit) const
{
if ((!m_uiEntry || unit->GetEntry() == m_uiEntry) && m_pObject->IsWithinDist(unit, m_fRange, false))
return true;
@@ -1300,63 +1313,69 @@ namespace Trinity
}
private:
- const WorldObject* m_pObject;
+ WorldObject const* m_pObject;
uint32 m_uiEntry;
float m_fRange;
};
class PlayerAtMinimumRangeAway
{
- public:
- PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : unit(unit), fRange(fMinRange) { }
- bool operator() (Player* player)
- {
- //No threat list check, must be done explicit if expected to be in combat with creature
- if (!player->IsGameMaster() && player->IsAlive() && !unit->IsWithinDist(player, fRange, false))
- return true;
+ public:
+ PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : unit(unit), fRange(fMinRange) { }
- return false;
- }
+ bool operator()(Player* player) const
+ {
+ //No threat list check, must be done explicit if expected to be in combat with creature
+ if (!player->IsGameMaster() && player->IsAlive() && !unit->IsWithinDist(player, fRange, false))
+ return true;
- private:
- Unit const* unit;
- float fRange;
+ return false;
+ }
+
+ private:
+ Unit const* unit;
+ float fRange;
};
class GameObjectInRangeCheck
{
- public:
- GameObjectInRangeCheck(float _x, float _y, float _z, float _range, uint32 _entry = 0) :
- x(_x), y(_y), z(_z), range(_range), entry(_entry) { }
- bool operator() (GameObject* go)
- {
- if (!entry || (go->GetGOInfo() && go->GetGOInfo()->entry == entry))
- return go->IsInRange(x, y, z, range);
- else return false;
- }
- private:
- float x, y, z, range;
- uint32 entry;
+ public:
+ GameObjectInRangeCheck(float _x, float _y, float _z, float _range, uint32 _entry = 0) :
+ x(_x), y(_y), z(_z), range(_range), entry(_entry) { }
+
+ bool operator()(GameObject* go) const
+ {
+ if (!entry || (go->GetGOInfo() && go->GetGOInfo()->entry == entry))
+ return go->IsInRange(x, y, z, range);
+ else return false;
+ }
+
+ private:
+ float x, y, z, range;
+ uint32 entry;
};
class AllWorldObjectsInRange
{
- public:
- AllWorldObjectsInRange(const WorldObject* object, float maxRange) : m_pObject(object), m_fRange(maxRange) { }
- bool operator() (WorldObject* go)
- {
- return m_pObject->IsWithinDist(go, m_fRange, false) && m_pObject->InSamePhase(go);
- }
- private:
- const WorldObject* m_pObject;
- float m_fRange;
+ public:
+ AllWorldObjectsInRange(const WorldObject* object, float maxRange) : m_pObject(object), m_fRange(maxRange) { }
+
+ bool operator()(WorldObject* go) const
+ {
+ return m_pObject->IsWithinDist(go, m_fRange, false) && m_pObject->InSamePhase(go);
+ }
+
+ private:
+ WorldObject const* m_pObject;
+ float m_fRange;
};
class ObjectTypeIdCheck
{
public:
ObjectTypeIdCheck(TypeID typeId, bool equals) : _typeId(typeId), _equals(equals) { }
- bool operator()(WorldObject* object)
+
+ bool operator()(WorldObject* object) const
{
return (object->GetTypeId() == _typeId) == _equals;
}
@@ -1370,7 +1389,8 @@ namespace Trinity
{
public:
ObjectGUIDCheck(ObjectGuid GUID) : _GUID(GUID) { }
- bool operator()(WorldObject* object)
+
+ bool operator()(WorldObject* object) const
{
return object->GetGUID() == _GUID;
}
@@ -1383,6 +1403,7 @@ namespace Trinity
{
public:
UnitAuraCheck(bool present, uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty) : _present(present), _spellId(spellId), _casterGUID(casterGUID) { }
+
bool operator()(Unit* unit) const
{
return unit->HasAura(_spellId, _casterGUID) == _present;
@@ -1413,6 +1434,7 @@ namespace Trinity
for (size_t i = 0; i < i_data_cache.size(); ++i)
delete i_data_cache[i];
}
+
void operator()(Player* p);
private:
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index b95d2ed1981..84b2da9b2ea 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -29,10 +29,13 @@
#include "SocialMgr.h"
#include "Opcodes.h"
-#define MAX_GUILD_BANK_TAB_TEXT_LEN 500
-#define EMBLEM_PRICE 10 * GOLD
-std::string _GetGuildEventString(GuildEvents event)
+size_t const MAX_GUILD_BANK_TAB_TEXT_LEN = 500;
+
+uint32 const EMBLEM_PRICE = 10 * GOLD;
+
+// only used in logs
+char const* GetGuildEventString(GuildEvents event)
{
switch (event)
{
@@ -82,18 +85,13 @@ std::string _GetGuildEventString(GuildEvents event)
return "<None>";
}
-inline uint32 _GetGuildBankTabPrice(uint8 tabId)
+inline uint32 GetGuildBankTabPrice(uint8 tabId)
{
- switch (tabId)
- {
- case 0: return 100;
- case 1: return 250;
- case 2: return 500;
- case 3: return 1000;
- case 4: return 2500;
- case 5: return 5000;
- default: return 0;
- }
+ // these prices are in gold units, not copper
+ static uint32 const tabPrices[GUILD_BANK_MAX_TABS] = { 100, 250, 500, 1000, 2500, 5000 };
+ ASSERT(tabId < GUILD_BANK_MAX_TABS);
+
+ return tabPrices[tabId];
}
void Guild::SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, std::string const& param)
@@ -121,7 +119,7 @@ void Guild::SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode
Guild::LogHolder::~LogHolder()
{
// Cleanup
- for (GuildLog::iterator itr = m_log.begin(); itr != m_log.end(); ++itr)
+ for (auto itr = m_log.begin(); itr != m_log.end(); ++itr)
delete (*itr);
}
@@ -154,7 +152,7 @@ inline void Guild::LogHolder::AddEvent(SQLTransaction& trans, LogEntry* entry)
inline void Guild::LogHolder::WritePacket(WorldPacket& data) const
{
data << uint8(m_log.size());
- for (GuildLog::const_iterator itr = m_log.begin(); itr != m_log.end(); ++itr)
+ for (auto itr = m_log.begin(); itr != m_log.end(); ++itr)
(*itr)->WritePacket(data);
}
@@ -175,7 +173,7 @@ void Guild::EventLogEntry::SaveToDB(SQLTransaction& trans) const
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOG);
stmt->setUInt32(0, m_guildId);
stmt->setUInt32(1, m_guid);
- CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ trans->Append(stmt);
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_EVENTLOG);
@@ -186,7 +184,7 @@ void Guild::EventLogEntry::SaveToDB(SQLTransaction& trans) const
stmt->setUInt32(++index, m_playerGuid2);
stmt->setUInt8 (++index, m_newRank);
stmt->setUInt64(++index, m_timestamp);
- CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ trans->Append(stmt);
}
void Guild::EventLogEntry::WritePacket(WorldPacket& data) const
@@ -202,7 +200,7 @@ void Guild::EventLogEntry::WritePacket(WorldPacket& data) const
if (m_eventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || m_eventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
data << uint8(m_newRank);
// Event timestamp
- data << uint32(::time(NULL) - m_timestamp);
+ data << uint32(::time(nullptr) - m_timestamp);
}
// BankEventLogEntry
@@ -214,7 +212,7 @@ void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const
stmt->setUInt32( index, m_guildId);
stmt->setUInt32(++index, m_guid);
stmt->setUInt8 (++index, m_bankTabId);
- CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ trans->Append(stmt);
index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_EVENTLOG);
@@ -227,7 +225,7 @@ void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const
stmt->setUInt16(++index, m_itemStackCount);
stmt->setUInt8 (++index, m_destTabId);
stmt->setUInt64(++index, m_timestamp);
- CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ trans->Append(stmt);
}
void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const
@@ -252,7 +250,7 @@ void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const
data << uint32(m_itemOrMoney);
}
- data << uint32(time(NULL) - m_timestamp);
+ data << uint32(time(nullptr) - m_timestamp);
}
// RankInfo
@@ -434,14 +432,16 @@ bool Guild::BankTab::LoadItemFromDB(Field* fields)
void Guild::BankTab::Delete(SQLTransaction& trans, bool removeItemsFromDB)
{
for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ {
if (Item* pItem = m_items[slotId])
{
pItem->RemoveFromWorld();
if (removeItemsFromDB)
pItem->DeleteFromDB(trans);
delete pItem;
- pItem = NULL;
+ pItem = nullptr;
}
+ }
}
inline void Guild::BankTab::WritePacket(WorldPacket& data) const
@@ -491,12 +491,14 @@ bool Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId, bool ignor
data << uint8(enchCount); // Number of enchantments
for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i)
+ {
if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i)))
{
data << uint8(i);
data << uint32(enchId);
++enchCount;
}
+ }
data.put<uint8>(enchCountPos, enchCount);
}
return true;
@@ -534,7 +536,7 @@ void Guild::BankTab::SetText(std::string const& text)
}
// Sets/removes contents of specified slot.
-// If pItem == NULL contents are removed.
+// If pItem == nullptr contents are removed.
bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item)
{
if (slotId >= GUILD_BANK_MAX_SLOTS)
@@ -546,7 +548,7 @@ bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item)
stmt->setUInt32(0, m_guildId);
stmt->setUInt8 (1, m_tabId);
stmt->setUInt8 (2, slotId);
- CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ trans->Append(stmt);
if (item)
{
@@ -555,13 +557,14 @@ bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item)
stmt->setUInt8 (1, m_tabId);
stmt->setUInt8 (2, slotId);
stmt->setUInt32(3, item->GetGUID().GetCounter());
- CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ trans->Append(stmt);
item->SetGuidValue(ITEM_FIELD_CONTAINED, ObjectGuid::Empty);
item->SetGuidValue(ITEM_FIELD_OWNER, ObjectGuid::Empty);
item->FSetState(ITEM_NEW);
item->SaveToDB(trans); // Not in inventory and can be saved standalone
}
+
return true;
}
@@ -629,7 +632,7 @@ void Guild::Member::SetOfficerNote(std::string const& officerNote)
CharacterDatabase.Execute(stmt);
}
-void Guild::Member::ChangeRank(uint8 newRank)
+void Guild::Member::ChangeRank(SQLTransaction& trans, uint8 newRank)
{
m_rankId = newRank;
@@ -640,7 +643,7 @@ void Guild::Member::ChangeRank(uint8 newRank)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_MEMBER_RANK);
stmt->setUInt8 (0, newRank);
stmt->setUInt32(1, m_guid.GetCounter());
- CharacterDatabase.Execute(stmt);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
void Guild::Member::SaveToDB(SQLTransaction& trans) const
@@ -714,7 +717,7 @@ void Guild::Member::WritePacket(WorldPacket& data, bool sendOfficerNote) const
<< uint32(m_zoneId);
if (!m_flags)
- data << float(float(::time(NULL) - m_logoutTime) / DAY);
+ data << float(float(::time(nullptr) - m_logoutTime) / DAY);
data << m_publicNote;
@@ -839,7 +842,7 @@ void Guild::MoveItemData::LogAction(MoveItemData* pFrom) const
inline void Guild::MoveItemData::CopySlots(SlotIds& ids) const
{
- for (ItemPosCountVec::const_iterator itr = m_vec.begin(); itr != m_vec.end(); ++itr)
+ for (auto itr = m_vec.begin(); itr != m_vec.end(); ++itr)
ids.insert(uint8(itr->pos));
}
@@ -853,16 +856,16 @@ bool Guild::PlayerMoveItemData::InitItem()
if (m_pItem->IsNotEmptyBag())
{
m_pPlayer->SendEquipError(EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS, m_pItem);
- m_pItem = NULL;
+ m_pItem = nullptr;
}
// Bound items cannot be put into bank.
else if (!m_pItem->CanBeTraded())
{
m_pPlayer->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, m_pItem);
- m_pItem = NULL;
+ m_pItem = nullptr;
}
}
- return (m_pItem != NULL);
+ return (m_pItem != nullptr);
}
void Guild::PlayerMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* /*pOther*/, uint32 splitedAmount)
@@ -877,7 +880,7 @@ void Guild::PlayerMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData*
{
m_pPlayer->MoveItemFromInventory(m_container, m_slotId, true);
m_pItem->DeleteFromInventoryDB(trans);
- m_pItem = NULL;
+ m_pItem = nullptr;
}
}
@@ -906,7 +909,7 @@ inline InventoryResult Guild::PlayerMoveItemData::CanStore(Item* pItem, bool swa
bool Guild::BankMoveItemData::InitItem()
{
m_pItem = m_pGuild->_GetItem(m_container, m_slotId);
- return (m_pItem != NULL);
+ return (m_pItem != nullptr);
}
bool Guild::BankMoveItemData::HasStoreRights(MoveItemData* pOther) const
@@ -944,7 +947,7 @@ void Guild::BankMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* pO
else
{
m_pGuild->_RemoveItem(trans, m_container, m_slotId);
- m_pItem = NULL;
+ m_pItem = nullptr;
}
// Decrease amount of player's remaining items (if item is moved to different tab or to player)
if (!pOther->IsBank() || pOther->GetContainer() != m_container)
@@ -954,14 +957,14 @@ void Guild::BankMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* pO
Item* Guild::BankMoveItemData::StoreItem(SQLTransaction& trans, Item* pItem)
{
if (!pItem)
- return NULL;
+ return nullptr;
BankTab* pTab = m_pGuild->GetBankTab(m_container);
if (!pTab)
- return NULL;
+ return nullptr;
Item* pLastItem = pItem;
- for (ItemPosCountVec::const_iterator itr = m_vec.begin(); itr != m_vec.end(); )
+ for (auto itr = m_vec.begin(); itr != m_vec.end(); )
{
ItemPosCount pos(*itr);
++itr;
@@ -1025,7 +1028,7 @@ Item* Guild::BankMoveItemData::_StoreItem(SQLTransaction& trans, BankTab* pTab,
if (pItem && pTab->SetItem(trans, slotId, pItem))
return pItem;
- return NULL;
+ return nullptr;
}
// Tries to reserve space for source item.
@@ -1065,10 +1068,10 @@ void Guild::BankMoveItemData::CanStoreItemInTab(Item* pItem, uint8 skipSlotId, b
Item* pItemDest = m_pGuild->_GetItem(m_container, slotId);
if (pItemDest == pItem)
- pItemDest = NULL;
+ pItemDest = nullptr;
// If merge skip empty, if not merge skip non-empty
- if ((pItemDest != NULL) != merge)
+ if ((pItemDest != nullptr) != merge)
continue;
_ReserveSpace(slotId, pItem, pItemDest, count);
@@ -1095,7 +1098,7 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
Item* pItemDest = m_pGuild->_GetItem(m_container, m_slotId);
// Ignore swapped item (this slot will be empty after move)
if ((pItemDest == pItem) || swap)
- pItemDest = NULL;
+ pItemDest = nullptr;
if (!_ReserveSpace(m_slotId, pItem, pItemDest, count))
return EQUIP_ERR_ITEM_CANT_STACK;
@@ -1128,30 +1131,30 @@ Guild::Guild():
m_createdDate(0),
m_accountsNumber(0),
m_bankMoney(0),
- m_eventLog(NULL)
+ m_eventLog(nullptr)
{
memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*));
}
Guild::~Guild()
{
- SQLTransaction temp(NULL);
+ SQLTransaction temp(nullptr);
_DeleteBankItems(temp);
// Cleanup
delete m_eventLog;
- m_eventLog = NULL;
+ m_eventLog = nullptr;
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
{
delete m_bankEventLog[tabId];
- m_bankEventLog[tabId] = NULL;
+ m_bankEventLog[tabId] = nullptr;
}
- for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
{
delete itr->second;
- itr->second = NULL;
+ itr->second = nullptr;
}
}
@@ -1172,7 +1175,7 @@ bool Guild::Create(Player* pLeader, std::string const& name)
m_info = "";
m_motd = "No message set.";
m_bankMoney = 0;
- m_createdDate = ::time(NULL);
+ m_createdDate = ::time(nullptr);
_CreateLogHolders();
TC_LOG_DEBUG("guild", "GUILD: creating guild [%s] for leader %s (%u)",
@@ -1200,9 +1203,10 @@ bool Guild::Create(Player* pLeader, std::string const& name)
stmt->setUInt64(++index, m_bankMoney);
trans->Append(stmt);
+ _CreateDefaultGuildRanks(trans, pLeaderSession->GetSessionDbLocaleIndex()); // Create default ranks
+ bool ret = AddMember(trans, m_leaderGuid, GR_GUILDMASTER); // Add guildmaster
+
CharacterDatabase.CommitTransaction(trans);
- _CreateDefaultGuildRanks(pLeaderSession->GetSessionDbLocaleIndex()); // Create default ranks
- bool ret = AddMember(m_leaderGuid, GR_GUILDMASTER); // Add guildmaster
if (ret)
sScriptMgr->OnGuildCreate(this, pLeader, name);
@@ -1217,15 +1221,15 @@ void Guild::Disband()
sScriptMgr->OnGuildDisband(this);
_BroadcastEvent(GE_DISBANDED, ObjectGuid::Empty);
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
// Remove all members
while (!m_members.empty())
{
- Members::const_iterator itr = m_members.begin();
- DeleteMember(itr->second->GetGUID(), true);
+ auto itr = m_members.begin();
+ DeleteMember(trans, itr->second->GetGUID(), true);
}
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
-
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD);
stmt->setUInt32(0, m_id);
trans->Append(stmt);
@@ -1313,10 +1317,10 @@ void Guild::HandleRoster(WorldSession* session)
data << m_info;
data << uint32(_GetRanksSize());
- for (Ranks::const_iterator ritr = m_ranks.begin(); ritr != m_ranks.end(); ++ritr)
+ for (auto ritr = m_ranks.begin(); ritr != m_ranks.end(); ++ritr)
ritr->WritePacket(data);
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
itr->second->WritePacket(data, _HasRankRight(session->GetPlayer(), GR_RIGHT_VIEWOFFNOTE));
TC_LOG_DEBUG("guild", "SMSG_GUILD_ROSTER [%s]", session->GetPlayerInfo().c_str());
@@ -1420,7 +1424,9 @@ void Guild::HandleSetLeader(WorldSession* session, std::string const& name)
if (Member* pNewLeader = GetMember(name))
{
_SetLeaderGUID(pNewLeader);
- pOldLeader->ChangeRank(GR_OFFICER);
+
+ SQLTransaction trans(nullptr);
+ pOldLeader->ChangeRank(trans, GR_OFFICER);
_BroadcastEvent(GE_LEADER_CHANGED, ObjectGuid::Empty, player->GetName().c_str(), name.c_str());
}
}
@@ -1436,11 +1442,8 @@ void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string
return;
}
- char aux[2];
- sprintf(aux, "%u", tabId);
-
tab->SetInfo(name, icon);
- _BroadcastEvent(GE_BANK_TAB_UPDATED, ObjectGuid::Empty, aux, name.c_str(), icon.c_str());
+ _BroadcastEvent(GE_BANK_TAB_UPDATED, ObjectGuid::Empty, std::to_string(tabId).c_str(), name.c_str(), icon.c_str());
}
void Guild::HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool officer)
@@ -1472,12 +1475,10 @@ void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string c
rankInfo->SetRights(rights);
_SetRankBankMoneyPerDay(rankId, moneyPerDay);
- for (GuildBankRightsAndSlotsVec::const_iterator itr = rightsAndSlots.begin(); itr != rightsAndSlots.end(); ++itr)
+ for (auto itr = rightsAndSlots.begin(); itr != rightsAndSlots.end(); ++itr)
_SetRankBankTabRightsAndSlots(rankId, *itr);
- char aux[2];
- sprintf(aux, "%u", rankId);
- _BroadcastEvent(GE_RANK_UPDATED, ObjectGuid::Empty, aux, name.c_str());
+ _BroadcastEvent(GE_RANK_UPDATED, ObjectGuid::Empty, std::to_string(rankId).c_str(), name.c_str());
}
}
@@ -1497,10 +1498,10 @@ void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId)
if (tabId != _GetPurchasedTabsSize())
return;
- uint32 tabCost = _GetGuildBankTabPrice(tabId) * GOLD;
- if (!tabCost)
+ if (tabId >= GUILD_BANK_MAX_TABS)
return;
+ uint32 tabCost = GetGuildBankTabPrice(tabId) * GOLD;
if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client
return;
@@ -1570,7 +1571,8 @@ void Guild::HandleAcceptMember(WorldSession* session)
player->GetTeam() != sObjectMgr->GetPlayerTeamByGUID(GetLeaderGUID()))
return;
- AddMember(player->GetGUID());
+ SQLTransaction trans(nullptr);
+ AddMember(trans, player->GetGUID());
}
void Guild::HandleLeaveMember(WorldSession* session)
@@ -1593,7 +1595,8 @@ void Guild::HandleLeaveMember(WorldSession* session)
}
else
{
- DeleteMember(player->GetGUID(), false, false);
+ SQLTransaction trans(nullptr);
+ DeleteMember(trans, player->GetGUID(), false, false);
_LogEvent(GUILD_EVENT_LOG_LEAVE_GUILD, player->GetGUID().GetCounter());
_BroadcastEvent(GE_LEFT, player->GetGUID(), player->GetName().c_str());
@@ -1627,8 +1630,10 @@ void Guild::HandleRemoveMember(WorldSession* session, std::string const& name)
else
{
ObjectGuid guid = member->GetGUID();
+
// After call to DeleteMember pointer to member becomes invalid
- DeleteMember(guid, false, true);
+ SQLTransaction trans(nullptr);
+ DeleteMember(trans, guid, false, true);
_LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUID().GetCounter(), guid.GetCounter());
_BroadcastEvent(GE_REMOVED, ObjectGuid::Empty, name.c_str(), player->GetName().c_str());
}
@@ -1682,7 +1687,8 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& nam
}
uint32 newRankId = member->GetRankId() + (demote ? 1 : -1);
- member->ChangeRank(newRankId);
+ SQLTransaction trans(nullptr);
+ member->ChangeRank(trans, newRankId);
_LogEvent(demote ? GUILD_EVENT_LOG_DEMOTE_PLAYER : GUILD_EVENT_LOG_PROMOTE_PLAYER, player->GetGUID().GetCounter(), member->GetGUID().GetCounter(), newRankId);
_BroadcastEvent(demote ? GE_DEMOTION : GE_PROMOTION, ObjectGuid::Empty, player->GetName().c_str(), name.c_str(), _GetRankName(newRankId).c_str());
}
@@ -1696,12 +1702,11 @@ void Guild::HandleAddNewRank(WorldSession* session, std::string const& name)
// Only leader can add new rank
if (_IsLeader(session->GetPlayer()))
- if (_CreateRank(name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK))
- {
- char aux[2];
- sprintf(aux, "%u", size);
- _BroadcastEvent(GE_RANK_UPDATED, ObjectGuid::Empty, aux, name.c_str());
- }
+ {
+ SQLTransaction trans(nullptr);
+ if (_CreateRank(trans, name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK))
+ _BroadcastEvent(GE_RANK_UPDATED, ObjectGuid::Empty, std::to_string(size).c_str(), name.c_str());
+ }
}
void Guild::HandleRemoveLowestRank(WorldSession* session)
@@ -1973,10 +1978,11 @@ void Guild::LoadRankFromDB(Field* fields)
bool Guild::LoadMemberFromDB(Field* fields)
{
ObjectGuid::LowType lowguid = fields[1].GetUInt32();
- Member *member = new Member(m_id, ObjectGuid(HighGuid::Player, lowguid), fields[2].GetUInt8());
+ Member* member = new Member(m_id, ObjectGuid(HighGuid::Player, lowguid), fields[2].GetUInt8());
if (!member->LoadFromDB(fields))
{
- _DeleteMemberFromDB(lowguid);
+ SQLTransaction trans(nullptr);
+ _DeleteMemberFromDB(trans, lowguid);
delete member;
return false;
}
@@ -2080,6 +2086,8 @@ bool Guild::Validate()
// Min ranks count is 5 and max is 10.
bool broken_ranks = false;
uint8 ranks = _GetRanksSize();
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
if (ranks < GUILD_RANKS_MIN_COUNT || ranks > GUILD_RANKS_MAX_COUNT)
{
TC_LOG_ERROR("guild", "Guild %u has invalid number of ranks, creating new...", m_id);
@@ -2096,24 +2104,20 @@ bool Guild::Validate()
broken_ranks = true;
}
else
- {
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
rankInfo->CreateMissingTabsIfNeeded(_GetPurchasedTabsSize(), trans, true);
- CharacterDatabase.CommitTransaction(trans);
- }
}
}
if (broken_ranks)
{
m_ranks.clear();
- _CreateDefaultGuildRanks(DEFAULT_LOCALE);
+ _CreateDefaultGuildRanks(trans, DEFAULT_LOCALE);
}
// Validate members' data
- for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
if (itr->second->GetRankId() > _GetRanksSize())
- itr->second->ChangeRank(_GetLowestRankId());
+ itr->second->ChangeRank(trans, _GetLowestRankId());
// Repair the structure of the guild.
// If the guildmaster doesn't exist or isn't member of the guild
@@ -2121,7 +2125,8 @@ bool Guild::Validate()
Member* pLeader = GetMember(m_leaderGuid);
if (!pLeader)
{
- DeleteMember(m_leaderGuid);
+ SQLTransaction trans(nullptr);
+ DeleteMember(trans, m_leaderGuid);
// If no more members left, disband guild
if (m_members.empty())
{
@@ -2134,10 +2139,12 @@ bool Guild::Validate()
// Check config if multiple guildmasters are allowed
if (!sConfigMgr->GetBoolDefault("Guild.AllowMultipleGuildMaster", 0))
- for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
if (itr->second->GetRankId() == GR_GUILDMASTER && !itr->second->IsSamePlayer(m_leaderGuid))
- itr->second->ChangeRank(GR_OFFICER);
+ itr->second->ChangeRank(trans, GR_OFFICER);
+ if (trans->GetSize() > 0)
+ CharacterDatabase.CommitTransaction(trans);
_UpdateAccountsNumber();
return true;
}
@@ -2148,8 +2155,8 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
{
WorldPacket data;
- ChatHandler::BuildChatPacket(data, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), NULL, msg);
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ ChatHandler::BuildChatPacket(data, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), nullptr, msg);
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindConnectedPlayer())
if (player->GetSession() && _HasRankRight(player, officerOnly ? GR_RIGHT_OFFCHATLISTEN : GR_RIGHT_GCHATLISTEN) &&
!player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUID().GetCounter()))
@@ -2159,7 +2166,7 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
void Guild::BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
if (itr->second->IsRank(rankId))
if (Player* player = itr->second->FindConnectedPlayer())
player->GetSession()->SendPacket(packet);
@@ -2167,7 +2174,7 @@ void Guild::BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const
void Guild::BroadcastPacket(WorldPacket* packet) const
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindPlayer())
player->GetSession()->SendPacket(packet);
}
@@ -2179,7 +2186,7 @@ void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 max
WorldPacket data(SMSG_CALENDAR_FILTER_GUILD);
data << uint32(count); // count placeholder
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
{
// not sure if needed, maybe client checks it as well
if (count >= CALENDAR_MAX_INVITES)
@@ -2206,7 +2213,7 @@ void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 max
}
// Members handling
-bool Guild::AddMember(ObjectGuid guid, uint8 rankId)
+bool Guild::AddMember(SQLTransaction& trans, ObjectGuid guid, uint8 rankId)
{
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
// Player cannot be in guild
@@ -2269,7 +2276,6 @@ bool Guild::AddMember(ObjectGuid guid, uint8 rankId)
m_members[lowguid] = member;
}
- SQLTransaction trans(NULL);
member->SaveToDB(trans);
_UpdateAccountsNumber();
@@ -2282,7 +2288,7 @@ bool Guild::AddMember(ObjectGuid guid, uint8 rankId)
return true;
}
-void Guild::DeleteMember(ObjectGuid guid, bool isDisbanding, bool isKicked, bool canDeleteGuild)
+void Guild::DeleteMember(SQLTransaction& trans, ObjectGuid guid, bool isDisbanding, bool isKicked, bool canDeleteGuild)
{
ObjectGuid::LowType lowguid = guid.GetCounter();
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
@@ -2291,9 +2297,9 @@ void Guild::DeleteMember(ObjectGuid guid, bool isDisbanding, bool isKicked, bool
// or when he is removed from guild by gm command
if (m_leaderGuid == guid && !isDisbanding)
{
- Member* oldLeader = NULL;
- Member* newLeader = NULL;
- for (Guild::Members::iterator i = m_members.begin(); i != m_members.end(); ++i)
+ Member* oldLeader = nullptr;
+ Member* newLeader = nullptr;
+ for (auto i = m_members.begin(); i != m_members.end(); ++i)
{
if (i->first == lowguid)
oldLeader = i->second;
@@ -2336,19 +2342,22 @@ void Guild::DeleteMember(ObjectGuid guid, bool isDisbanding, bool isKicked, bool
player->SetRank(0);
}
- _DeleteMemberFromDB(lowguid);
+ _DeleteMemberFromDB(trans, lowguid);
if (!isDisbanding)
_UpdateAccountsNumber();
}
-bool Guild::ChangeMemberRank(ObjectGuid guid, uint8 newRank)
+bool Guild::ChangeMemberRank(SQLTransaction& trans, ObjectGuid guid, uint8 newRank)
{
if (newRank <= _GetLowestRankId()) // Validate rank (allow only existing ranks)
+ {
if (Member* member = GetMember(guid))
{
- member->ChangeRank(newRank);
+ member->ChangeRank(trans, newRank);
return true;
}
+ }
+
return false;
}
@@ -2386,7 +2395,7 @@ void Guild::SetBankTabText(uint8 tabId, std::string const& text)
if (BankTab* pTab = GetBankTab(tabId))
{
pTab->SetText(text);
- pTab->SendText(this, NULL);
+ pTab->SendText(this, nullptr);
}
}
@@ -2416,30 +2425,32 @@ void Guild::_CreateNewBankTab()
trans->Append(stmt);
++tabId;
- for (Ranks::iterator itr = m_ranks.begin(); itr != m_ranks.end(); ++itr)
+ for (auto itr = m_ranks.begin(); itr != m_ranks.end(); ++itr)
(*itr).CreateMissingTabsIfNeeded(tabId, trans, false);
CharacterDatabase.CommitTransaction(trans);
}
-void Guild::_CreateDefaultGuildRanks(LocaleConstant loc)
+void Guild::_CreateDefaultGuildRanks(SQLTransaction& trans, LocaleConstant loc)
{
+ ASSERT(trans);
+
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANKS);
stmt->setUInt32(0, m_id);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS);
stmt->setUInt32(0, m_id);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
- _CreateRank(sObjectMgr->GetTrinityString(LANG_GUILD_MASTER, loc), GR_RIGHT_ALL);
- _CreateRank(sObjectMgr->GetTrinityString(LANG_GUILD_OFFICER, loc), GR_RIGHT_ALL);
- _CreateRank(sObjectMgr->GetTrinityString(LANG_GUILD_VETERAN, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
- _CreateRank(sObjectMgr->GetTrinityString(LANG_GUILD_MEMBER, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
- _CreateRank(sObjectMgr->GetTrinityString(LANG_GUILD_INITIATE, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ _CreateRank(trans, sObjectMgr->GetTrinityString(LANG_GUILD_MASTER, loc), GR_RIGHT_ALL);
+ _CreateRank(trans, sObjectMgr->GetTrinityString(LANG_GUILD_OFFICER, loc), GR_RIGHT_ALL);
+ _CreateRank(trans, sObjectMgr->GetTrinityString(LANG_GUILD_VETERAN, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ _CreateRank(trans, sObjectMgr->GetTrinityString(LANG_GUILD_MEMBER, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ _CreateRank(trans, sObjectMgr->GetTrinityString(LANG_GUILD_INITIATE, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
}
-bool Guild::_CreateRank(std::string const& name, uint32 rights)
+bool Guild::_CreateRank(SQLTransaction& trans, std::string const& name, uint32 rights)
{
uint8 newRankId = _GetRanksSize();
if (newRankId >= GUILD_RANKS_MAX_COUNT)
@@ -2449,10 +2460,15 @@ bool Guild::_CreateRank(std::string const& name, uint32 rights)
RankInfo info(m_id, newRankId, name, rights, 0);
m_ranks.push_back(info);
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ bool const isInTransaction = bool(trans);
+ if (!isInTransaction)
+ trans = CharacterDatabase.BeginTransaction();
+
info.CreateMissingTabsIfNeeded(_GetPurchasedTabsSize(), trans);
info.SaveToDB(trans);
- CharacterDatabase.CommitTransaction(trans);
+
+ if (!isInTransaction)
+ CharacterDatabase.CommitTransaction(trans);
return true;
}
@@ -2463,7 +2479,7 @@ void Guild::_UpdateAccountsNumber()
{
// We use a set to be sure each element will be unique
std::set<uint32> accountsIdSet;
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
accountsIdSet.insert(itr->second->GetAccountId());
m_accountsNumber = accountsIdSet.size();
@@ -2487,7 +2503,7 @@ void Guild::_DeleteBankItems(SQLTransaction& trans, bool removeItemsFromDB)
{
m_bankTabs[tabId]->Delete(trans, removeItemsFromDB);
delete m_bankTabs[tabId];
- m_bankTabs[tabId] = NULL;
+ m_bankTabs[tabId] = nullptr;
}
m_bankTabs.clear();
}
@@ -2516,13 +2532,16 @@ void Guild::_SetLeaderGUID(Member* pLeader)
if (!pLeader)
return;
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
m_leaderGuid = pLeader->GetGUID();
- pLeader->ChangeRank(GR_GUILDMASTER);
+ pLeader->ChangeRank(trans, GR_GUILDMASTER);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_LEADER);
stmt->setUInt32(0, m_leaderGuid.GetCounter());
stmt->setUInt32(1, m_id);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
}
void Guild::_SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay)
@@ -2670,13 +2689,13 @@ inline Item* Guild::_GetItem(uint8 tabId, uint8 slotId) const
{
if (const BankTab* tab = GetBankTab(tabId))
return tab->GetItem(slotId);
- return NULL;
+ return nullptr;
}
inline void Guild::_RemoveItem(SQLTransaction& trans, uint8 tabId, uint8 slotId)
{
if (BankTab* pTab = GetBankTab(tabId))
- pTab->SetItem(trans, slotId, NULL);
+ pTab->SetItem(trans, slotId, nullptr);
}
void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount)
@@ -2717,7 +2736,7 @@ void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAm
}
else // 6. No split
{
- // 6.1. Try to merge items in destination (pDest->GetItem() == NULL)
+ // 6.1. Try to merge items in destination (pDest->GetItem() == nullptr)
if (!_DoItemsMove(pSrc, pDest, false)) // Item could not be merged
{
// 6.2. Try to swap items
@@ -2732,7 +2751,7 @@ void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAm
if (!pDest->HasWithdrawRights(pSrc))
return; // Player has no rights to withdraw item from destination (opposite direction)
- // 6.2.3. Swap items (pDest->GetItem() != NULL)
+ // 6.2.3. Swap items (pDest->GetItem() != nullptr)
_DoItemsMove(pSrc, pDest, true);
}
}
@@ -2743,7 +2762,7 @@ void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAm
bool Guild::_DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount)
{
Item* pDestItem = pDest->GetItem();
- bool swap = (pDestItem != NULL);
+ bool swap = (pDestItem != nullptr);
Item* pSrcItem = pSrc->GetItem(splitedAmount != 0);
// 1. Can store source item in destination
@@ -2832,7 +2851,7 @@ void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) cons
void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const
{
- _SendBankList(NULL, tabId, false, &slots);
+ _SendBankList(nullptr, tabId, false, &slots);
}
void Guild::_BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid, const char* param1, const char* param2, const char* param3) const
@@ -2855,10 +2874,10 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid, const char*
BroadcastPacket(&data);
- TC_LOG_DEBUG("guild", "SMSG_GUILD_EVENT [Broadcast] Event: %s (%u)", _GetGuildEventString(guildEvent).c_str(), guildEvent);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_EVENT [Broadcast] Event: %s (%u)", GetGuildEventString(guildEvent), guildEvent);
}
-void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds *slots /*= NULL*/) const
+void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds *slots /*= nullptr*/) const
{
WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
data << uint64(m_bankMoney);
@@ -2882,7 +2901,7 @@ void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/
else if (slots && !slots->empty())
{
data << uint8(slots->size());
- for (SlotIds::const_iterator itr = slots->begin(); itr != slots->end(); ++itr)
+ for (auto itr = slots->begin(); itr != slots->end(); ++itr)
tab->WriteSlotPacket(data, *itr, false);
}
else
@@ -2900,7 +2919,7 @@ void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/
}
else /// @todo - Probably this is just sent to session + those that have sent CMSG_GUILD_BANKER_ACTIVATE
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
{
if (!_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
continue;
@@ -2919,7 +2938,7 @@ void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/
void Guild::ResetTimes()
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
itr->second->ResetValues();
_BroadcastEvent(GE_BANK_TAB_AND_MONEY_UPDATED, ObjectGuid::Empty);
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index e25a3201957..742923f51a1 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -225,54 +225,54 @@ enum GuildMemberFlags
// Emblem info
class TC_GAME_API EmblemInfo
{
-public:
- EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { }
-
- void LoadFromDB(Field* fields);
- void SaveToDB(ObjectGuid::LowType guildId) const;
- void ReadPacket(WorldPacket& recv);
- void WritePacket(WorldPacket& data) const;
-
- uint32 GetStyle() const { return m_style; }
- uint32 GetColor() const { return m_color; }
- uint32 GetBorderStyle() const { return m_borderStyle; }
- uint32 GetBorderColor() const { return m_borderColor; }
- uint32 GetBackgroundColor() const { return m_backgroundColor; }
-
-private:
- uint32 m_style;
- uint32 m_color;
- uint32 m_borderStyle;
- uint32 m_borderColor;
- uint32 m_backgroundColor;
+ public:
+ EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { }
+
+ void LoadFromDB(Field* fields);
+ void SaveToDB(ObjectGuid::LowType guildId) const;
+ void ReadPacket(WorldPacket& recv);
+ void WritePacket(WorldPacket& data) const;
+
+ uint32 GetStyle() const { return m_style; }
+ uint32 GetColor() const { return m_color; }
+ uint32 GetBorderStyle() const { return m_borderStyle; }
+ uint32 GetBorderColor() const { return m_borderColor; }
+ uint32 GetBackgroundColor() const { return m_backgroundColor; }
+
+ private:
+ uint32 m_style;
+ uint32 m_color;
+ uint32 m_borderStyle;
+ uint32 m_borderColor;
+ uint32 m_backgroundColor;
};
// Structure for storing guild bank rights and remaining slots together.
class GuildBankRightsAndSlots
{
-public:
- GuildBankRightsAndSlots() : tabId(TAB_UNDEFINED), rights(0), slots(0) { }
- GuildBankRightsAndSlots(uint8 _tabId) : tabId(_tabId), rights(0), slots(0) { }
- GuildBankRightsAndSlots(uint8 _tabId, uint8 _rights, uint32 _slots) : tabId(_tabId), rights(_rights), slots(_slots) { }
-
- void SetGuildMasterValues()
- {
- rights = GUILD_BANK_RIGHT_FULL;
- slots = uint32(GUILD_WITHDRAW_SLOT_UNLIMITED);
- }
-
- void SetTabId(uint8 _tabId) { tabId = _tabId; }
- void SetSlots(uint32 _slots) { slots = _slots; }
- void SetRights(uint8 _rights) { rights = _rights; }
-
- int8 GetTabId() const { return tabId; }
- int32 GetSlots() const { return slots; }
- int8 GetRights() const { return rights; }
-
-private:
- uint8 tabId;
- uint8 rights;
- uint32 slots;
+ public:
+ GuildBankRightsAndSlots() : tabId(TAB_UNDEFINED), rights(0), slots(0) { }
+ GuildBankRightsAndSlots(uint8 _tabId) : tabId(_tabId), rights(0), slots(0) { }
+ GuildBankRightsAndSlots(uint8 _tabId, uint8 _rights, uint32 _slots) : tabId(_tabId), rights(_rights), slots(_slots) { }
+
+ void SetGuildMasterValues()
+ {
+ rights = GUILD_BANK_RIGHT_FULL;
+ slots = uint32(GUILD_WITHDRAW_SLOT_UNLIMITED);
+ }
+
+ void SetTabId(uint8 _tabId) { tabId = _tabId; }
+ void SetSlots(uint32 _slots) { slots = _slots; }
+ void SetRights(uint8 _rights) { rights = _rights; }
+
+ int8 GetTabId() const { return tabId; }
+ int32 GetSlots() const { return slots; }
+ int8 GetRights() const { return rights; }
+
+ private:
+ uint8 tabId;
+ uint8 rights;
+ uint32 slots;
};
typedef std::vector <GuildBankRightsAndSlots> GuildBankRightsAndSlotsVec;
@@ -281,577 +281,577 @@ typedef std::set <uint8> SlotIds;
class TC_GAME_API Guild
{
-private:
- // Class representing guild member
- class Member
- {
- public:
- Member(ObjectGuid::LowType guildId, ObjectGuid guid, uint8 rankId) :
- m_guildId(guildId),
- m_guid(guid),
- m_zoneId(0),
- m_level(0),
- m_class(0),
- m_flags(GUILDMEMBER_STATUS_NONE),
- m_logoutTime(::time(NULL)),
- m_accountId(0),
- m_rankId(rankId)
+ private:
+ // Class representing guild member
+ class Member
{
- memset(m_bankWithdraw, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(int32));
- }
-
- void SetStats(Player* player);
- void SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId);
- bool CheckStats() const;
+ public:
+ Member(ObjectGuid::LowType guildId, ObjectGuid guid, uint8 rankId) :
+ m_guildId(guildId),
+ m_guid(guid),
+ m_zoneId(0),
+ m_level(0),
+ m_class(0),
+ m_flags(GUILDMEMBER_STATUS_NONE),
+ m_logoutTime(::time(nullptr)),
+ m_accountId(0),
+ m_rankId(rankId)
+ {
+ memset(m_bankWithdraw, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(int32));
+ }
+
+ void SetStats(Player* player);
+ void SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId);
+ bool CheckStats() const;
+
+ void SetPublicNote(std::string const& publicNote);
+ void SetOfficerNote(std::string const& officerNote);
+ void SetZoneID(uint32 id) { m_zoneId = id; }
+ void SetLevel(uint8 var) { m_level = var; }
+
+ void AddFlag(uint8 var) { m_flags |= var; }
+ void RemFlag(uint8 var) { m_flags &= ~var; }
+ void ResetFlags() { m_flags = GUILDMEMBER_STATUS_NONE; }
+
+ bool LoadFromDB(Field* fields);
+ void SaveToDB(SQLTransaction& trans) const;
+ void WritePacket(WorldPacket& data, bool sendOfficerNote) const;
+
+ ObjectGuid GetGUID() const { return m_guid; }
+ std::string const& GetName() const { return m_name; }
+ uint32 GetAccountId() const { return m_accountId; }
+ uint8 GetRankId() const { return m_rankId; }
+ uint64 GetLogoutTime() const { return m_logoutTime; }
+ std::string GetPublicNote() const { return m_publicNote; }
+ std::string GetOfficerNote() const { return m_officerNote; }
+ uint8 GetClass() const { return m_class; }
+ uint8 GetLevel() const { return m_level; }
+ uint8 GetFlags() const { return m_flags; }
+ uint32 GetZoneId() const { return m_zoneId; }
+ bool IsOnline() const { return (m_flags & GUILDMEMBER_STATUS_ONLINE); }
+
+ void ChangeRank(SQLTransaction& trans, uint8 newRank);
+
+ inline void UpdateLogoutTime() { m_logoutTime = ::time(nullptr); }
+ inline bool IsRank(uint8 rankId) const { return m_rankId == rankId; }
+ inline bool IsRankNotLower(uint8 rankId) const { return m_rankId <= rankId; }
+ inline bool IsSamePlayer(ObjectGuid guid) const { return m_guid == guid; }
+
+ void UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId, uint32 amount);
+ int32 GetBankWithdrawValue(uint8 tabId) const;
+ void ResetValues();
+
+ inline Player* FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); }
+ inline Player* FindConnectedPlayer() const { return ObjectAccessor::FindConnectedPlayer(m_guid); }
+
+ private:
+ ObjectGuid::LowType m_guildId;
+ // Fields from characters table
+ ObjectGuid m_guid;
+ std::string m_name;
+ uint32 m_zoneId;
+ uint8 m_level;
+ uint8 m_class;
+ uint8 m_flags;
+ uint64 m_logoutTime;
+ uint32 m_accountId;
+ // Fields from guild_member table
+ uint8 m_rankId;
+ std::string m_publicNote;
+ std::string m_officerNote;
+
+ int32 m_bankWithdraw[GUILD_BANK_MAX_TABS + 1];
+ };
+
+ // Base class for event entries
+ class LogEntry
+ {
+ public:
+ LogEntry(ObjectGuid::LowType guildId, uint32 guid) : m_guildId(guildId), m_guid(guid), m_timestamp(::time(nullptr)) { }
+ LogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) { }
+ virtual ~LogEntry() { }
- void SetPublicNote(std::string const& publicNote);
- void SetOfficerNote(std::string const& officerNote);
- void SetZoneID(uint32 id) { m_zoneId = id; }
- void SetLevel(uint8 var) { m_level = var; }
+ uint32 GetGUID() const { return m_guid; }
+ uint64 GetTimestamp() const { return m_timestamp; }
- void AddFlag(uint8 var) { m_flags |= var; }
- void RemFlag(uint8 var) { m_flags &= ~var; }
- void ResetFlags() { m_flags = GUILDMEMBER_STATUS_NONE; }
+ virtual void SaveToDB(SQLTransaction& trans) const = 0;
+ virtual void WritePacket(WorldPacket& data) const = 0;
- bool LoadFromDB(Field* fields);
- void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data, bool sendOfficerNote) const;
+ protected:
+ ObjectGuid::LowType m_guildId;
+ uint32 m_guid;
+ uint64 m_timestamp;
+ };
- ObjectGuid GetGUID() const { return m_guid; }
- std::string const& GetName() const { return m_name; }
- uint32 GetAccountId() const { return m_accountId; }
- uint8 GetRankId() const { return m_rankId; }
- uint64 GetLogoutTime() const { return m_logoutTime; }
- std::string GetPublicNote() const { return m_publicNote; }
- std::string GetOfficerNote() const { return m_officerNote; }
- uint8 GetClass() const { return m_class; }
- uint8 GetLevel() const { return m_level; }
- uint8 GetFlags() const { return m_flags; }
- uint32 GetZoneId() const { return m_zoneId; }
- bool IsOnline() const { return (m_flags & GUILDMEMBER_STATUS_ONLINE); }
-
- void ChangeRank(uint8 newRank);
-
- inline void UpdateLogoutTime() { m_logoutTime = ::time(NULL); }
- inline bool IsRank(uint8 rankId) const { return m_rankId == rankId; }
- inline bool IsRankNotLower(uint8 rankId) const { return m_rankId <= rankId; }
- inline bool IsSamePlayer(ObjectGuid guid) const { return m_guid == guid; }
-
- void UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId, uint32 amount);
- int32 GetBankWithdrawValue(uint8 tabId) const;
- void ResetValues();
-
- inline Player* FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); }
- inline Player* FindConnectedPlayer() const { return ObjectAccessor::FindConnectedPlayer(m_guid); }
+ // Event log entry
+ class EventLogEntry : public LogEntry
+ {
+ public:
+ EventLogEntry(ObjectGuid::LowType guildId, uint32 guid, GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) :
+ LogEntry(guildId, guid), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
- private:
- ObjectGuid::LowType m_guildId;
- // Fields from characters table
- ObjectGuid m_guid;
- std::string m_name;
- uint32 m_zoneId;
- uint8 m_level;
- uint8 m_class;
- uint8 m_flags;
- uint64 m_logoutTime;
- uint32 m_accountId;
- // Fields from guild_member table
- uint8 m_rankId;
- std::string m_publicNote;
- std::string m_officerNote;
-
- int32 m_bankWithdraw[GUILD_BANK_MAX_TABS + 1];
- };
-
- // Base class for event entries
- class LogEntry
- {
- public:
- LogEntry(ObjectGuid::LowType guildId, uint32 guid) : m_guildId(guildId), m_guid(guid), m_timestamp(::time(NULL)) { }
- LogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) { }
- virtual ~LogEntry() { }
+ EventLogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp, GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) :
+ LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
- uint32 GetGUID() const { return m_guid; }
- uint64 GetTimestamp() const { return m_timestamp; }
+ ~EventLogEntry() { }
- virtual void SaveToDB(SQLTransaction& trans) const = 0;
- virtual void WritePacket(WorldPacket& data) const = 0;
+ void SaveToDB(SQLTransaction& trans) const override;
+ void WritePacket(WorldPacket& data) const override;
- protected:
- ObjectGuid::LowType m_guildId;
- uint32 m_guid;
- uint64 m_timestamp;
- };
-
- // Event log entry
- class EventLogEntry : public LogEntry
- {
- public:
- EventLogEntry(ObjectGuid::LowType guildId, uint32 guid, GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) :
- LogEntry(guildId, guid), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
+ private:
+ GuildEventLogTypes m_eventType;
+ ObjectGuid::LowType m_playerGuid1;
+ ObjectGuid::LowType m_playerGuid2;
+ uint8 m_newRank;
+ };
- EventLogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp, GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) :
- LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
+ // Bank event log entry
+ class BankEventLogEntry : public LogEntry
+ {
+ public:
+ static bool IsMoneyEvent(GuildBankEventLogTypes eventType)
+ {
+ return
+ eventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
+ eventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
+ eventType == GUILD_BANK_LOG_REPAIR_MONEY;
+ }
+
+ BankEventLogEntry(ObjectGuid::LowType guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
+ m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
+
+ BankEventLogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
+ m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
+
+ ~BankEventLogEntry() { }
+
+ void SaveToDB(SQLTransaction& trans) const override;
+ void WritePacket(WorldPacket& data) const override;
+
+ private:
+ GuildBankEventLogTypes m_eventType;
+ uint8 m_bankTabId;
+ ObjectGuid::LowType m_playerGuid;
+ uint32 m_itemOrMoney;
+ uint16 m_itemStackCount;
+ uint8 m_destTabId;
+ };
+
+ // Class encapsulating work with events collection
+ typedef std::list<LogEntry*> GuildLog;
+
+ class LogHolder
+ {
+ public:
+ LogHolder(uint32 maxRecords) : m_maxRecords(maxRecords), m_nextGUID(uint32(GUILD_EVENT_LOG_GUID_UNDEFINED)) { }
+ ~LogHolder();
+
+ uint8 GetSize() const { return uint8(m_log.size()); }
+ // Checks if new log entry can be added to holder when loading from DB
+ inline bool CanInsert() const { return m_log.size() < m_maxRecords; }
+ // Adds event from DB to collection
+ void LoadEvent(LogEntry* entry);
+ // Adds new event to collection and saves it to DB
+ void AddEvent(SQLTransaction& trans, LogEntry* entry);
+ // Writes information about all events to packet
+ void WritePacket(WorldPacket& data) const;
+ uint32 GetNextGUID();
+
+ private:
+ GuildLog m_log;
+ uint32 m_maxRecords;
+ uint32 m_nextGUID;
+ };
+
+ // Class encapsulating guild rank data
+ class RankInfo
+ {
+ public:
+ RankInfo(): m_guildId(0), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
+ RankInfo(ObjectGuid::LowType guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
+ RankInfo(ObjectGuid::LowType guildId, uint8 rankId, std::string const& name, uint32 rights, uint32 money) :
+ m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights),
+ m_bankMoneyPerDay(rankId != GR_GUILDMASTER ? money : GUILD_WITHDRAW_MONEY_UNLIMITED) { }
- ~EventLogEntry() { }
+ void LoadFromDB(Field* fields);
+ void SaveToDB(SQLTransaction& trans) const;
+ void WritePacket(WorldPacket& data) const;
- void SaveToDB(SQLTransaction& trans) const override;
- void WritePacket(WorldPacket& data) const override;
+ uint8 GetId() const { return m_rankId; }
- private:
- GuildEventLogTypes m_eventType;
- ObjectGuid::LowType m_playerGuid1;
- ObjectGuid::LowType m_playerGuid2;
- uint8 m_newRank;
- };
-
- // Bank event log entry
- class BankEventLogEntry : public LogEntry
- {
- public:
- static bool IsMoneyEvent(GuildBankEventLogTypes eventType)
- {
- return
- eventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
- eventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
- eventType == GUILD_BANK_LOG_REPAIR_MONEY;
- }
+ std::string const& GetName() const { return m_name; }
+ void SetName(std::string const& name);
- BankEventLogEntry(ObjectGuid::LowType guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
- LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
- m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
+ uint32 GetRights() const { return m_rights; }
+ void SetRights(uint32 rights);
- BankEventLogEntry(ObjectGuid::LowType guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
- LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
- m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
+ int32 GetBankMoneyPerDay() const { return m_bankMoneyPerDay; }
- ~BankEventLogEntry() { }
+ void SetBankMoneyPerDay(uint32 money);
- void SaveToDB(SQLTransaction& trans) const override;
- void WritePacket(WorldPacket& data) const override;
+ inline int8 GetBankTabRights(uint8 tabId) const
+ {
+ return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].GetRights() : 0;
+ }
- private:
- GuildBankEventLogTypes m_eventType;
- uint8 m_bankTabId;
- ObjectGuid::LowType m_playerGuid;
- uint32 m_itemOrMoney;
- uint16 m_itemStackCount;
- uint8 m_destTabId;
- };
-
- // Class encapsulating work with events collection
- typedef std::list<LogEntry*> GuildLog;
-
- class LogHolder
- {
- public:
- LogHolder(uint32 maxRecords) : m_maxRecords(maxRecords), m_nextGUID(uint32(GUILD_EVENT_LOG_GUID_UNDEFINED)) { }
- ~LogHolder();
-
- uint8 GetSize() const { return uint8(m_log.size()); }
- // Checks if new log entry can be added to holder when loading from DB
- inline bool CanInsert() const { return m_log.size() < m_maxRecords; }
- // Adds event from DB to collection
- void LoadEvent(LogEntry* entry);
- // Adds new event to collection and saves it to DB
- void AddEvent(SQLTransaction& trans, LogEntry* entry);
- // Writes information about all events to packet
- void WritePacket(WorldPacket& data) const;
- uint32 GetNextGUID();
+ inline int32 GetBankTabSlotsPerDay(uint8 tabId) const
+ {
+ return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].GetSlots() : 0;
+ }
- private:
- GuildLog m_log;
- uint32 m_maxRecords;
- uint32 m_nextGUID;
- };
-
- // Class encapsulating guild rank data
- class RankInfo
- {
- public:
- RankInfo(): m_guildId(0), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
- RankInfo(ObjectGuid::LowType guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
- RankInfo(ObjectGuid::LowType guildId, uint8 rankId, std::string const& name, uint32 rights, uint32 money) :
- m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights),
- m_bankMoneyPerDay(rankId != GR_GUILDMASTER ? money : GUILD_WITHDRAW_MONEY_UNLIMITED) { }
+ void SetBankTabSlotsAndRights(GuildBankRightsAndSlots rightsAndSlots, bool saveToDB);
+ void CreateMissingTabsIfNeeded(uint8 ranks, SQLTransaction& trans, bool logOnCreate = false);
- void LoadFromDB(Field* fields);
- void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
+ private:
+ ObjectGuid::LowType m_guildId;
- uint8 GetId() const { return m_rankId; }
+ uint8 m_rankId;
+ std::string m_name;
+ uint32 m_rights;
+ uint32 m_bankMoneyPerDay;
+ GuildBankRightsAndSlots m_bankTabRightsAndSlots[GUILD_BANK_MAX_TABS];
+ };
- std::string const& GetName() const { return m_name; }
- void SetName(std::string const& name);
+ class BankTab
+ {
+ public:
+ BankTab(ObjectGuid::LowType guildId, uint8 tabId) : m_guildId(guildId), m_tabId(tabId)
+ {
+ memset(m_items, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
+ }
+
+ void LoadFromDB(Field* fields);
+ bool LoadItemFromDB(Field* fields);
+ void Delete(SQLTransaction& trans, bool removeItemsFromDB = false);
+
+ void WritePacket(WorldPacket& data) const;
+ bool WriteSlotPacket(WorldPacket& data, uint8 slotId, bool ignoreEmpty = true) const;
+ void WriteInfoPacket(WorldPacket& data) const
+ {
+ data << m_name;
+ data << m_icon;
+ }
+
+ void SetInfo(std::string const& name, std::string const& icon);
+ void SetText(std::string const& text);
+ void SendText(const Guild* guild, WorldSession* session) const;
+
+ inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : NULL; }
+ bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
+
+ private:
+ ObjectGuid::LowType m_guildId;
+ uint8 m_tabId;
+
+ Item* m_items[GUILD_BANK_MAX_SLOTS];
+ std::string m_name;
+ std::string m_icon;
+ std::string m_text;
+ };
+
+ // Movement data
+ class MoveItemData
+ {
+ public:
+ MoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) : m_pGuild(guild), m_pPlayer(player),
+ m_container(container), m_slotId(slotId), m_pItem(NULL), m_pClonedItem(NULL) { }
+ virtual ~MoveItemData() { }
+
+ virtual bool IsBank() const = 0;
+ // Initializes item pointer. Returns true, if item exists, false otherwise.
+ virtual bool InitItem() = 0;
+ // Checks splited amount against item. Splited amount cannot be more that number of items in stack.
+ virtual bool CheckItem(uint32& splitedAmount);
+ // Defines if player has rights to save item in container
+ virtual bool HasStoreRights(MoveItemData* /*pOther*/) const { return true; }
+ // Defines if player has rights to withdraw item from container
+ virtual bool HasWithdrawRights(MoveItemData* /*pOther*/) const { return true; }
+ // Checks if container can store specified item
+ bool CanStore(Item* pItem, bool swap, bool sendError);
+ // Clones stored item
+ bool CloneItem(uint32 count);
+ // Remove item from container (if splited update items fields)
+ virtual void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount = 0) = 0;
+ // Saves item to container
+ virtual Item* StoreItem(SQLTransaction& trans, Item* pItem) = 0;
+ // Log bank event
+ virtual void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const = 0;
+ // Log GM action
+ virtual void LogAction(MoveItemData* pFrom) const;
+ // Copy slots id from position vector
+ void CopySlots(SlotIds& ids) const;
+
+ Item* GetItem(bool isCloned = false) const { return isCloned ? m_pClonedItem : m_pItem; }
+ uint8 GetContainer() const { return m_container; }
+ uint8 GetSlotId() const { return m_slotId; }
+
+ protected:
+ virtual InventoryResult CanStore(Item* pItem, bool swap) = 0;
+
+ Guild* m_pGuild;
+ Player* m_pPlayer;
+ uint8 m_container;
+ uint8 m_slotId;
+ Item* m_pItem;
+ Item* m_pClonedItem;
+ ItemPosCountVec m_vec;
+ };
+
+ class PlayerMoveItemData : public MoveItemData
+ {
+ public:
+ PlayerMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) :
+ MoveItemData(guild, player, container, slotId) { }
+
+ bool IsBank() const override { return false; }
+ bool InitItem() override;
+ void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount = 0) override;
+ Item* StoreItem(SQLTransaction& trans, Item* pItem) override;
+ void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const override;
+ protected:
+ InventoryResult CanStore(Item* pItem, bool swap) override;
+ };
+
+ class BankMoveItemData : public MoveItemData
+ {
+ public:
+ BankMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) :
+ MoveItemData(guild, player, container, slotId) { }
+
+ bool IsBank() const override { return true; }
+ bool InitItem() override;
+ bool HasStoreRights(MoveItemData* pOther) const override;
+ bool HasWithdrawRights(MoveItemData* pOther) const override;
+ void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount) override;
+ Item* StoreItem(SQLTransaction& trans, Item* pItem) override;
+ void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const override;
+ void LogAction(MoveItemData* pFrom) const override;
+
+ protected:
+ InventoryResult CanStore(Item* pItem, bool swap) override;
+
+ private:
+ Item* _StoreItem(SQLTransaction& trans, BankTab* pTab, Item* pItem, ItemPosCount& pos, bool clone) const;
+ bool _ReserveSpace(uint8 slotId, Item* pItem, Item* pItemDest, uint32& count);
+ void CanStoreItemInTab(Item* pItem, uint8 skipSlotId, bool merge, uint32& count);
+ };
+
+ typedef std::unordered_map<uint32, Member*> Members;
+ typedef std::vector<RankInfo> Ranks;
+ typedef std::vector<BankTab*> BankTabs;
- uint32 GetRights() const { return m_rights; }
- void SetRights(uint32 rights);
+ public:
+ static void SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, std::string const& param = "");
+ static void SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode);
- int32 GetBankMoneyPerDay() const { return m_bankMoneyPerDay; }
+ Guild();
+ ~Guild();
- void SetBankMoneyPerDay(uint32 money);
+ bool Create(Player* pLeader, std::string const& name);
+ void Disband();
- inline int8 GetBankTabRights(uint8 tabId) const
+ // Getters
+ ObjectGuid::LowType GetId() const { return m_id; }
+ ObjectGuid GetLeaderGUID() const { return m_leaderGuid; }
+ std::string const& GetName() const { return m_name; }
+ std::string const& GetMOTD() const { return m_motd; }
+ std::string const& GetInfo() const { return m_info; }
+ uint32 GetMemberCount() const { return m_members.size(); }
+ time_t GetCreatedDate() const { return m_createdDate; }
+ uint64 GetBankMoney() const { return m_bankMoney; }
+
+ bool SetName(std::string const& name);
+
+ // Handle client commands
+ void HandleRoster(WorldSession* session);
+ void HandleQuery(WorldSession* session);
+ void HandleSetMOTD(WorldSession* session, std::string const& motd);
+ void HandleSetInfo(WorldSession* session, std::string const& info);
+ void HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo);
+ void HandleSetLeader(WorldSession* session, std::string const& name);
+ void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon);
+ void HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool officer);
+ void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, const GuildBankRightsAndSlotsVec& rightsAndSlots);
+ void HandleBuyBankTab(WorldSession* session, uint8 tabId);
+ void HandleInviteMember(WorldSession* session, std::string const& name);
+ void HandleAcceptMember(WorldSession* session);
+ void HandleLeaveMember(WorldSession* session);
+ void HandleRemoveMember(WorldSession* session, std::string const& name);
+ void HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote);
+ void HandleAddNewRank(WorldSession* session, std::string const& name);
+ void HandleRemoveRank(WorldSession* session, uint8 rankId);
+ void HandleRemoveLowestRank(WorldSession* session);
+ void HandleMemberDepositMoney(WorldSession* session, uint32 amount);
+ bool HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair = false);
+ void HandleMemberLogout(WorldSession* session);
+ void HandleDisband(WorldSession* session);
+
+ void UpdateMemberData(Player* player, uint8 dataid, uint32 value);
+ void OnPlayerStatusChange(Player* player, uint32 flag, bool state);
+
+ // Send info to client
+ void SendInfo(WorldSession* session) const;
+ void SendEventLog(WorldSession* session) const;
+ void SendBankLog(WorldSession* session, uint8 tabId) const;
+ void SendBankTabsInfo(WorldSession* session, bool showTabs = false) const;
+ void SendBankTabData(WorldSession* session, uint8 tabId) const;
+ void SendBankTabText(WorldSession* session, uint8 tabId) const;
+ void SendPermissions(WorldSession* session) const;
+ void SendMoneyInfo(WorldSession* session) const;
+ void SendLoginInfo(WorldSession* session);
+
+ // Load from DB
+ bool LoadFromDB(Field* fields);
+ void LoadRankFromDB(Field* fields);
+ bool LoadMemberFromDB(Field* fields);
+ bool LoadEventLogFromDB(Field* fields);
+ void LoadBankRightFromDB(Field* fields);
+ void LoadBankTabFromDB(Field* fields);
+ bool LoadBankEventLogFromDB(Field* fields);
+ bool LoadBankItemFromDB(Field* fields);
+ bool Validate();
+
+ // Broadcasts
+ void BroadcastToGuild(WorldSession* session, bool officerOnly, std::string const& msg, uint32 language = LANG_UNIVERSAL) const;
+ void BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const;
+ void BroadcastPacket(WorldPacket* packet) const;
+
+ void MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 maxLevel, uint32 minRank);
+
+ template<class Do>
+ void BroadcastWorker(Do& _do, Player* except = nullptr)
{
- return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].GetRights() : 0;
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (Player* player = itr->second->FindConnectedPlayer())
+ if (player != except)
+ _do(player);
}
- inline int32 GetBankTabSlotsPerDay(uint8 tabId) const
- {
- return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].GetSlots() : 0;
- }
+ // Members
+ // Adds member to guild. If rankId == GUILD_RANK_NONE, lowest rank is assigned.
+ bool AddMember(SQLTransaction& trans, ObjectGuid guid, uint8 rankId = GUILD_RANK_NONE);
+ void DeleteMember(SQLTransaction& trans, ObjectGuid guid, bool isDisbanding = false, bool isKicked = false, bool canDeleteGuild = false);
+ bool ChangeMemberRank(SQLTransaction& trans, ObjectGuid guid, uint8 newRank);
- void SetBankTabSlotsAndRights(GuildBankRightsAndSlots rightsAndSlots, bool saveToDB);
- void CreateMissingTabsIfNeeded(uint8 ranks, SQLTransaction& trans, bool logOnCreate = false);
+ // Bank
+ void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount);
+ void SwapItemsWithInventory(Player* player, bool toChar, uint8 tabId, uint8 slotId, uint8 playerBag, uint8 playerSlotId, uint32 splitedAmount);
- private:
- ObjectGuid::LowType m_guildId;
+ // Bank tabs
+ void SetBankTabText(uint8 tabId, std::string const& text);
- uint8 m_rankId;
+ void ResetTimes();
+
+ protected:
+ ObjectGuid::LowType m_id;
std::string m_name;
- uint32 m_rights;
- uint32 m_bankMoneyPerDay;
- GuildBankRightsAndSlots m_bankTabRightsAndSlots[GUILD_BANK_MAX_TABS];
- };
+ ObjectGuid m_leaderGuid;
+ std::string m_motd;
+ std::string m_info;
+ time_t m_createdDate;
- class BankTab
- {
- public:
- BankTab(ObjectGuid::LowType guildId, uint8 tabId) : m_guildId(guildId), m_tabId(tabId)
- {
- memset(m_items, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
- }
+ EmblemInfo m_emblemInfo;
+ uint32 m_accountsNumber;
+ uint64 m_bankMoney;
- void LoadFromDB(Field* fields);
- bool LoadItemFromDB(Field* fields);
- void Delete(SQLTransaction& trans, bool removeItemsFromDB = false);
+ Ranks m_ranks;
+ Members m_members;
+ BankTabs m_bankTabs;
- void WritePacket(WorldPacket& data) const;
- bool WriteSlotPacket(WorldPacket& data, uint8 slotId, bool ignoreEmpty = true) const;
- void WriteInfoPacket(WorldPacket& data) const
+ // These are actually ordered lists. The first element is the oldest entry.
+ LogHolder* m_eventLog;
+ LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1];
+
+ private:
+ inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
+ inline RankInfo const* GetRankInfo(uint8 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : nullptr; }
+ inline RankInfo* GetRankInfo(uint8 rankId) { return rankId < _GetRanksSize() ? &m_ranks[rankId] : nullptr; }
+ inline bool _HasRankRight(Player* player, uint32 right) const
{
- data << m_name;
- data << m_icon;
+ if (player)
+ if (Member const* member = GetMember(player->GetGUID()))
+ return (_GetRankRights(member->GetRankId()) & right) != GR_RIGHT_EMPTY;
+ return false;
}
- void SetInfo(std::string const& name, std::string const& icon);
- void SetText(std::string const& text);
- void SendText(const Guild* guild, WorldSession* session) const;
+ inline uint8 _GetLowestRankId() const { return uint8(m_ranks.size() - 1); }
- inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : NULL; }
- bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
+ inline uint8 _GetPurchasedTabsSize() const { return uint8(m_bankTabs.size()); }
+ inline BankTab* GetBankTab(uint8 tabId) { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : nullptr; }
+ inline BankTab const* GetBankTab(uint8 tabId) const { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : nullptr; }
- private:
- ObjectGuid::LowType m_guildId;
- uint8 m_tabId;
-
- Item* m_items[GUILD_BANK_MAX_SLOTS];
- std::string m_name;
- std::string m_icon;
- std::string m_text;
- };
+ inline Member const* GetMember(ObjectGuid guid) const
+ {
+ auto itr = m_members.find(guid.GetCounter());
+ return itr != m_members.end() ? itr->second : nullptr;
+ }
- // Movement data
- class MoveItemData
- {
- public:
- MoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) : m_pGuild(guild), m_pPlayer(player),
- m_container(container), m_slotId(slotId), m_pItem(NULL), m_pClonedItem(NULL) { }
- virtual ~MoveItemData() { }
-
- virtual bool IsBank() const = 0;
- // Initializes item pointer. Returns true, if item exists, false otherwise.
- virtual bool InitItem() = 0;
- // Checks splited amount against item. Splited amount cannot be more that number of items in stack.
- virtual bool CheckItem(uint32& splitedAmount);
- // Defines if player has rights to save item in container
- virtual bool HasStoreRights(MoveItemData* /*pOther*/) const { return true; }
- // Defines if player has rights to withdraw item from container
- virtual bool HasWithdrawRights(MoveItemData* /*pOther*/) const { return true; }
- // Checks if container can store specified item
- bool CanStore(Item* pItem, bool swap, bool sendError);
- // Clones stored item
- bool CloneItem(uint32 count);
- // Remove item from container (if splited update items fields)
- virtual void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount = 0) = 0;
- // Saves item to container
- virtual Item* StoreItem(SQLTransaction& trans, Item* pItem) = 0;
- // Log bank event
- virtual void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const = 0;
- // Log GM action
- virtual void LogAction(MoveItemData* pFrom) const;
- // Copy slots id from position vector
- void CopySlots(SlotIds& ids) const;
-
- Item* GetItem(bool isCloned = false) const { return isCloned ? m_pClonedItem : m_pItem; }
- uint8 GetContainer() const { return m_container; }
- uint8 GetSlotId() const { return m_slotId; }
+ inline Member* GetMember(ObjectGuid guid)
+ {
+ auto itr = m_members.find(guid.GetCounter());
+ return itr != m_members.end() ? itr->second : nullptr;
+ }
- protected:
- virtual InventoryResult CanStore(Item* pItem, bool swap) = 0;
-
- Guild* m_pGuild;
- Player* m_pPlayer;
- uint8 m_container;
- uint8 m_slotId;
- Item* m_pItem;
- Item* m_pClonedItem;
- ItemPosCountVec m_vec;
- };
-
- class PlayerMoveItemData : public MoveItemData
- {
- public:
- PlayerMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) :
- MoveItemData(guild, player, container, slotId) { }
-
- bool IsBank() const override { return false; }
- bool InitItem() override;
- void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount = 0) override;
- Item* StoreItem(SQLTransaction& trans, Item* pItem) override;
- void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const override;
- protected:
- InventoryResult CanStore(Item* pItem, bool swap) override;
- };
+ inline Member* GetMember(std::string const& name)
+ {
+ for (auto itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (itr->second->GetName() == name)
+ return itr->second;
- class BankMoveItemData : public MoveItemData
- {
- public:
- BankMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) :
- MoveItemData(guild, player, container, slotId) { }
-
- bool IsBank() const override { return true; }
- bool InitItem() override;
- bool HasStoreRights(MoveItemData* pOther) const override;
- bool HasWithdrawRights(MoveItemData* pOther) const override;
- void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount) override;
- Item* StoreItem(SQLTransaction& trans, Item* pItem) override;
- void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const override;
- void LogAction(MoveItemData* pFrom) const override;
+ return nullptr;
+ }
- protected:
- InventoryResult CanStore(Item* pItem, bool swap) override;
+ inline void _DeleteMemberFromDB(SQLTransaction& trans, ObjectGuid::LowType lowguid) const
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER);
+ stmt->setUInt32(0, lowguid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+ }
- private:
- Item* _StoreItem(SQLTransaction& trans, BankTab* pTab, Item* pItem, ItemPosCount& pos, bool clone) const;
- bool _ReserveSpace(uint8 slotId, Item* pItem, Item* pItemDest, uint32& count);
- void CanStoreItemInTab(Item* pItem, uint8 skipSlotId, bool merge, uint32& count);
- };
-
- typedef std::unordered_map<uint32, Member*> Members;
- typedef std::vector<RankInfo> Ranks;
- typedef std::vector<BankTab*> BankTabs;
-
-public:
- static void SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, std::string const& param = "");
- static void SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode);
-
- Guild();
- ~Guild();
-
- bool Create(Player* pLeader, std::string const& name);
- void Disband();
-
- // Getters
- ObjectGuid::LowType GetId() const { return m_id; }
- ObjectGuid GetLeaderGUID() const { return m_leaderGuid; }
- std::string const& GetName() const { return m_name; }
- std::string const& GetMOTD() const { return m_motd; }
- std::string const& GetInfo() const { return m_info; }
- uint32 GetMemberCount() const { return m_members.size(); }
- time_t GetCreatedDate() const { return m_createdDate; }
- uint64 GetBankMoney() const { return m_bankMoney; }
-
- bool SetName(std::string const& name);
-
- // Handle client commands
- void HandleRoster(WorldSession* session);
- void HandleQuery(WorldSession* session);
- void HandleSetMOTD(WorldSession* session, std::string const& motd);
- void HandleSetInfo(WorldSession* session, std::string const& info);
- void HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo);
- void HandleSetLeader(WorldSession* session, std::string const& name);
- void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon);
- void HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool officer);
- void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, const GuildBankRightsAndSlotsVec& rightsAndSlots);
- void HandleBuyBankTab(WorldSession* session, uint8 tabId);
- void HandleInviteMember(WorldSession* session, std::string const& name);
- void HandleAcceptMember(WorldSession* session);
- void HandleLeaveMember(WorldSession* session);
- void HandleRemoveMember(WorldSession* session, std::string const& name);
- void HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote);
- void HandleAddNewRank(WorldSession* session, std::string const& name);
- void HandleRemoveRank(WorldSession* session, uint8 rankId);
- void HandleRemoveLowestRank(WorldSession* session);
- void HandleMemberDepositMoney(WorldSession* session, uint32 amount);
- bool HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair = false);
- void HandleMemberLogout(WorldSession* session);
- void HandleDisband(WorldSession* session);
-
- void UpdateMemberData(Player* player, uint8 dataid, uint32 value);
- void OnPlayerStatusChange(Player* player, uint32 flag, bool state);
-
- // Send info to client
- void SendInfo(WorldSession* session) const;
- void SendEventLog(WorldSession* session) const;
- void SendBankLog(WorldSession* session, uint8 tabId) const;
- void SendBankTabsInfo(WorldSession* session, bool showTabs = false) const;
- void SendBankTabData(WorldSession* session, uint8 tabId) const;
- void SendBankTabText(WorldSession* session, uint8 tabId) const;
- void SendPermissions(WorldSession* session) const;
- void SendMoneyInfo(WorldSession* session) const;
- void SendLoginInfo(WorldSession* session);
-
- // Load from DB
- bool LoadFromDB(Field* fields);
- void LoadRankFromDB(Field* fields);
- bool LoadMemberFromDB(Field* fields);
- bool LoadEventLogFromDB(Field* fields);
- void LoadBankRightFromDB(Field* fields);
- void LoadBankTabFromDB(Field* fields);
- bool LoadBankEventLogFromDB(Field* fields);
- bool LoadBankItemFromDB(Field* fields);
- bool Validate();
-
- // Broadcasts
- void BroadcastToGuild(WorldSession* session, bool officerOnly, std::string const& msg, uint32 language = LANG_UNIVERSAL) const;
- void BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const;
- void BroadcastPacket(WorldPacket* packet) const;
-
- void MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 maxLevel, uint32 minRank);
-
- template<class Do>
- void BroadcastWorker(Do& _do, Player* except = NULL)
- {
- for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
- if (Player* player = itr->second->FindConnectedPlayer())
- if (player != except)
- _do(player);
- }
-
- // Members
- // Adds member to guild. If rankId == GUILD_RANK_NONE, lowest rank is assigned.
- bool AddMember(ObjectGuid guid, uint8 rankId = GUILD_RANK_NONE);
- void DeleteMember(ObjectGuid guid, bool isDisbanding = false, bool isKicked = false, bool canDeleteGuild = false);
- bool ChangeMemberRank(ObjectGuid guid, uint8 newRank);
-
- // Bank
- void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount);
- void SwapItemsWithInventory(Player* player, bool toChar, uint8 tabId, uint8 slotId, uint8 playerBag, uint8 playerSlotId, uint32 splitedAmount);
-
- // Bank tabs
- void SetBankTabText(uint8 tabId, std::string const& text);
-
- void ResetTimes();
-
-protected:
- ObjectGuid::LowType m_id;
- std::string m_name;
- ObjectGuid m_leaderGuid;
- std::string m_motd;
- std::string m_info;
- time_t m_createdDate;
-
- EmblemInfo m_emblemInfo;
- uint32 m_accountsNumber;
- uint64 m_bankMoney;
-
- Ranks m_ranks;
- Members m_members;
- BankTabs m_bankTabs;
-
- // These are actually ordered lists. The first element is the oldest entry.
- LogHolder* m_eventLog;
- LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1];
-
-private:
- inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
- inline const RankInfo* GetRankInfo(uint8 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
- inline RankInfo* GetRankInfo(uint8 rankId) { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
- inline bool _HasRankRight(Player* player, uint32 right) const
- {
- if (player)
- if (Member const* member = GetMember(player->GetGUID()))
- return (_GetRankRights(member->GetRankId()) & right) != GR_RIGHT_EMPTY;
- return false;
- }
-
- inline uint8 _GetLowestRankId() const { return uint8(m_ranks.size() - 1); }
-
- inline uint8 _GetPurchasedTabsSize() const { return uint8(m_bankTabs.size()); }
- inline BankTab* GetBankTab(uint8 tabId) { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : NULL; }
- inline const BankTab* GetBankTab(uint8 tabId) const { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : NULL; }
-
- inline const Member* GetMember(ObjectGuid guid) const
- {
- Members::const_iterator itr = m_members.find(guid.GetCounter());
- return itr != m_members.end() ? itr->second : NULL;
- }
-
- inline Member* GetMember(ObjectGuid guid)
- {
- Members::iterator itr = m_members.find(guid.GetCounter());
- return itr != m_members.end() ? itr->second : NULL;
- }
-
- inline Member* GetMember(std::string const& name)
- {
- for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
- if (itr->second->GetName() == name)
- return itr->second;
-
- return NULL;
- }
-
- inline void _DeleteMemberFromDB(ObjectGuid::LowType lowguid) const
- {
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER);
- stmt->setUInt32(0, lowguid);
- CharacterDatabase.Execute(stmt);
- }
-
- // Creates log holders (either when loading or when creating guild)
- void _CreateLogHolders();
- // Tries to create new bank tab
- void _CreateNewBankTab();
- // Creates default guild ranks with names in given locale
- void _CreateDefaultGuildRanks(LocaleConstant loc);
- // Creates new rank
- bool _CreateRank(std::string const& name, uint32 rights);
- // Update account number when member added/removed from guild
- void _UpdateAccountsNumber();
- bool _IsLeader(Player* player) const;
- void _DeleteBankItems(SQLTransaction& trans, bool removeItemsFromDB = false);
- bool _ModifyBankMoney(SQLTransaction& trans, uint64 amount, bool add);
- void _SetLeaderGUID(Member* pLeader);
-
- void _SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay);
- void _SetRankBankTabRightsAndSlots(uint8 rankId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB = true);
- int8 _GetRankBankTabRights(uint8 rankId, uint8 tabId) const;
- uint32 _GetRankRights(uint8 rankId) const;
- int32 _GetRankBankMoneyPerDay(uint8 rankId) const;
- int32 _GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const;
- std::string _GetRankName(uint8 rankId) const;
-
- int32 _GetMemberRemainingSlots(Member const* member, uint8 tabId) const;
- int32 _GetMemberRemainingMoney(Member const* member) const;
- void _UpdateMemberWithdrawSlots(SQLTransaction& trans, ObjectGuid guid, uint8 tabId);
- bool _MemberHasTabRights(ObjectGuid guid, uint8 tabId, uint32 rights) const;
-
- void _LogEvent(GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2 = 0, uint8 newRank = 0);
- void _LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount = 0, uint8 destTabId = 0);
-
- Item* _GetItem(uint8 tabId, uint8 slotId) const;
- void _RemoveItem(SQLTransaction& trans, uint8 tabId, uint8 slotId);
- void _MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount);
- bool _DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount = 0);
-
- void _SendBankContent(WorldSession* session, uint8 tabId) const;
- void _SendBankMoneyUpdate(WorldSession* session) const;
- void _SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const;
- void _SendBankContentUpdate(uint8 tabId, SlotIds slots) const;
- void _SendBankList(WorldSession* session = NULL, uint8 tabId = 0, bool sendFullSlots = false, SlotIds *slots = NULL) const;
-
- void _BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid, const char* param1 = NULL, const char* param2 = NULL, const char* param3 = NULL) const;
+ // Creates log holders (either when loading or when creating guild)
+ void _CreateLogHolders();
+ // Tries to create new bank tab
+ void _CreateNewBankTab();
+ // Creates default guild ranks with names in given locale
+ void _CreateDefaultGuildRanks(SQLTransaction& trans, LocaleConstant loc);
+ // Creates new rank
+ bool _CreateRank(SQLTransaction& trans, std::string const& name, uint32 rights);
+ // Update account number when member added/removed from guild
+ void _UpdateAccountsNumber();
+ bool _IsLeader(Player* player) const;
+ void _DeleteBankItems(SQLTransaction& trans, bool removeItemsFromDB = false);
+ bool _ModifyBankMoney(SQLTransaction& trans, uint64 amount, bool add);
+ void _SetLeaderGUID(Member* pLeader);
+
+ void _SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay);
+ void _SetRankBankTabRightsAndSlots(uint8 rankId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB = true);
+ int8 _GetRankBankTabRights(uint8 rankId, uint8 tabId) const;
+ uint32 _GetRankRights(uint8 rankId) const;
+ int32 _GetRankBankMoneyPerDay(uint8 rankId) const;
+ int32 _GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const;
+ std::string _GetRankName(uint8 rankId) const;
+
+ int32 _GetMemberRemainingSlots(Member const* member, uint8 tabId) const;
+ int32 _GetMemberRemainingMoney(Member const* member) const;
+ void _UpdateMemberWithdrawSlots(SQLTransaction& trans, ObjectGuid guid, uint8 tabId);
+ bool _MemberHasTabRights(ObjectGuid guid, uint8 tabId, uint32 rights) const;
+
+ void _LogEvent(GuildEventLogTypes eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2 = 0, uint8 newRank = 0);
+ void _LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount = 0, uint8 destTabId = 0);
+
+ Item* _GetItem(uint8 tabId, uint8 slotId) const;
+ void _RemoveItem(SQLTransaction& trans, uint8 tabId, uint8 slotId);
+ void _MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount);
+ bool _DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount = 0);
+
+ void _SendBankContent(WorldSession* session, uint8 tabId) const;
+ void _SendBankMoneyUpdate(WorldSession* session) const;
+ void _SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const;
+ void _SendBankContentUpdate(uint8 tabId, SlotIds slots) const;
+ void _SendBankList(WorldSession* session = NULL, uint8 tabId = 0, bool sendFullSlots = false, SlotIds *slots = NULL) const;
+
+ void _BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid, const char* param1 = NULL, const char* param2 = NULL, const char* param3 = NULL) const;
};
#endif
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 53c62858c04..157511afd96 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1843,13 +1843,10 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
{
// Reset guild
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
-
stmt->setUInt32(0, lowGuid);
-
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
- if (result)
+ if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32()))
- guild->DeleteMember(factionChangeInfo.Guid, false, false, true);
+ guild->DeleteMember(trans, factionChangeInfo.Guid, false, false, true);
Player::LeaveAllArenaTeams(factionChangeInfo.Guid);
}
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index c0b5db65d90..a4d41bbff1f 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -849,12 +849,18 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_COMMAND_SUCCESS, name);
- // Add members from signatures
- for (uint8 i = 0; i < signatures; ++i)
{
- Field* fields = result->Fetch();
- guild->AddMember(ObjectGuid(HighGuid::Player, fields[0].GetUInt32()));
- result->NextRow();
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ // Add members from signatures
+ for (uint8 i = 0; i < signatures; ++i)
+ {
+ Field* fields = result->Fetch();
+ guild->AddMember(trans, ObjectGuid(HighGuid::Player, fields[0].GetUInt32()));
+ result->NextRow();
+ }
+
+ CharacterDatabase.CommitTransaction(trans);
}
}
else
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 9686fb9622f..b69bb41d3ad 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -483,7 +483,7 @@ void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting)
{
ObjectGuid::LowType plguid = player->GetGUID().GetCounter();
- QuestItemMap::const_iterator qmapitr = PlayerQuestItems.find(plguid);
+ NotNormalLootItemMap::const_iterator qmapitr = PlayerQuestItems.find(plguid);
if (qmapitr == PlayerQuestItems.end())
FillQuestLoot(player);
@@ -517,16 +517,16 @@ void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting)
}
}
-QuestItemList* Loot::FillFFALoot(Player* player)
+NotNormalLootItemList* Loot::FillFFALoot(Player* player)
{
- QuestItemList* ql = new QuestItemList();
+ NotNormalLootItemList* ql = new NotNormalLootItemList();
for (uint8 i = 0; i < items.size(); ++i)
{
LootItem &item = items[i];
if (!item.is_looted && item.freeforall && item.AllowedForPlayer(player))
{
- ql->push_back(QuestItem(i));
+ ql->push_back(NotNormalLootItem(i));
++unlootedCount;
}
}
@@ -540,12 +540,12 @@ QuestItemList* Loot::FillFFALoot(Player* player)
return ql;
}
-QuestItemList* Loot::FillQuestLoot(Player* player)
+NotNormalLootItemList* Loot::FillQuestLoot(Player* player)
{
if (items.size() == MAX_NR_LOOT_ITEMS)
return NULL;
- QuestItemList* ql = new QuestItemList();
+ NotNormalLootItemList* ql = new NotNormalLootItemList();
for (uint8 i = 0; i < quest_items.size(); ++i)
{
@@ -553,7 +553,7 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
if (!item.is_looted && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT))))
{
- ql->push_back(QuestItem(i));
+ ql->push_back(NotNormalLootItem(i));
// quest items get blocked when they first appear in a
// player's quest vector
@@ -578,20 +578,20 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
return ql;
}
-QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting)
+NotNormalLootItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting)
{
- QuestItemList* ql = new QuestItemList();
+ NotNormalLootItemList* ql = new NotNormalLootItemList();
for (uint8 i = 0; i < items.size(); ++i)
{
LootItem &item = items[i];
- if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT))))
+ if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player)))
{
if (presentAtLooting)
item.AddAllowedLooter(player);
if (!item.conditions.empty())
{
- ql->push_back(QuestItem(i));
+ ql->push_back(NotNormalLootItem(i));
if (!item.is_counted)
{
++unlootedCount;
@@ -657,11 +657,11 @@ void Loot::NotifyQuestItemRemoved(uint8 questIndex)
++i_next;
if (Player* player = ObjectAccessor::FindPlayer(*i))
{
- QuestItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUID().GetCounter());
if (pq != PlayerQuestItems.end() && pq->second)
{
// find where/if the player has the given item in it's vector
- QuestItemList& pql = *pq->second;
+ NotNormalLootItemList& pql = *pq->second;
uint8 j;
for (j = 0; j < pql.size(); ++j)
@@ -717,17 +717,17 @@ void Loot::DeleteLootMoneyFromContainerItemDB()
CharacterDatabase.Execute(stmt);
}
-LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qitem, QuestItem* *ffaitem, QuestItem* *conditem)
+LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, NotNormalLootItem* *qitem, NotNormalLootItem* *ffaitem, NotNormalLootItem* *conditem)
{
LootItem* item = NULL;
bool is_looted = true;
if (lootSlot >= items.size())
{
uint32 questSlot = lootSlot - items.size();
- QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID().GetCounter());
if (itr != PlayerQuestItems.end() && questSlot < itr->second->size())
{
- QuestItem* qitem2 = &itr->second->at(questSlot);
+ NotNormalLootItem* qitem2 = &itr->second->at(questSlot);
if (qitem)
*qitem = qitem2;
item = &quest_items[qitem2->index];
@@ -740,13 +740,13 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
is_looted = item->is_looted;
if (item->freeforall)
{
- QuestItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUID().GetCounter());
if (itr != PlayerFFAItems.end())
{
- for (QuestItemList::const_iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter)
+ for (NotNormalLootItemList::const_iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter)
if (iter->index == lootSlot)
{
- QuestItem* ffaitem2 = (QuestItem*)&(*iter);
+ NotNormalLootItem* ffaitem2 = (NotNormalLootItem*)&(*iter);
if (ffaitem)
*ffaitem = ffaitem2;
is_looted = ffaitem2->is_looted;
@@ -756,14 +756,14 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
}
else if (!item->conditions.empty())
{
- QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUID().GetCounter());
if (itr != PlayerNonQuestNonFFAConditionalItems.end())
{
- for (QuestItemList::const_iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter)
+ for (NotNormalLootItemList::const_iterator iter=itr->second->begin(); iter!= itr->second->end(); ++iter)
{
if (iter->index == lootSlot)
{
- QuestItem* conditem2 = (QuestItem*)&(*iter);
+ NotNormalLootItem* conditem2 = (NotNormalLootItem*)&(*iter);
if (conditem)
*conditem = conditem2;
is_looted = conditem2->is_looted;
@@ -782,7 +782,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
uint32 Loot::GetMaxSlotInLootFor(Player* player) const
{
- QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID().GetCounter());
return items.size() + (itr != PlayerQuestItems.end() ? itr->second->size() : 0);
}
@@ -802,12 +802,12 @@ bool Loot::hasItemForAll() const
// return true if there is any FFA, quest or conditional item for the player.
bool Loot::hasItemFor(Player* player) const
{
- QuestItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
- QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
+ NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUID().GetCounter());
if (q_itr != lootPlayerQuestItems.end())
{
- QuestItemList* q_list = q_itr->second;
- for (QuestItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
+ NotNormalLootItemList* q_list = q_itr->second;
+ for (NotNormalLootItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
{
const LootItem &item = quest_items[qi->index];
if (!qi->is_looted && !item.is_looted)
@@ -815,12 +815,12 @@ bool Loot::hasItemFor(Player* player) const
}
}
- QuestItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
- QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
+ NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUID().GetCounter());
if (ffa_itr != lootPlayerFFAItems.end())
{
- QuestItemList* ffa_list = ffa_itr->second;
- for (QuestItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
+ NotNormalLootItemList* ffa_list = ffa_itr->second;
+ for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
{
const LootItem &item = items[fi->index];
if (!fi->is_looted && !item.is_looted)
@@ -828,12 +828,12 @@ bool Loot::hasItemFor(Player* player) const
}
}
- QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
- QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUID().GetCounter());
+ NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
+ NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUID().GetCounter());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
- QuestItemList* conditional_list = nn_itr->second;
- for (QuestItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
+ NotNormalLootItemList* conditional_list = nn_itr->second;
+ for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
{
const LootItem &item = items[ci->index];
if (!ci->is_looted && !item.is_looted)
@@ -976,12 +976,12 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
LootSlotType slotType = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT;
- QuestItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems();
- QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUID().GetCounter());
+ NotNormalLootItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems();
+ NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUID().GetCounter());
if (q_itr != lootPlayerQuestItems.end())
{
- QuestItemList* q_list = q_itr->second;
- for (QuestItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
+ NotNormalLootItemList* q_list = q_itr->second;
+ for (NotNormalLootItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
{
LootItem &item = l.quest_items[qi->index];
if (!qi->is_looted && !item.is_looted)
@@ -1017,12 +1017,12 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
}
- QuestItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems();
- QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUID().GetCounter());
+ NotNormalLootItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems();
+ NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUID().GetCounter());
if (ffa_itr != lootPlayerFFAItems.end())
{
- QuestItemList* ffa_list = ffa_itr->second;
- for (QuestItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
+ NotNormalLootItemList* ffa_list = ffa_itr->second;
+ for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
{
LootItem &item = l.items[fi->index];
if (!fi->is_looted && !item.is_looted)
@@ -1035,42 +1035,37 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
}
- QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems();
- QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUID().GetCounter());
+ NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems();
+ NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUID().GetCounter());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
- QuestItemList* conditional_list = nn_itr->second;
- for (QuestItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
+ NotNormalLootItemList* conditional_list = nn_itr->second;
+ for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
{
LootItem &item = l.items[ci->index];
if (!ci->is_looted && !item.is_looted)
{
b << uint8(ci->index);
b << item;
- if (item.follow_loot_rules)
+ switch (lv.permission)
{
- switch (lv.permission)
- {
- case MASTER_PERMISSION:
- b << uint8(LOOT_SLOT_TYPE_MASTER);
- break;
- case RESTRICTED_PERMISSION:
- b << (item.is_blocked ? uint8(LOOT_SLOT_TYPE_LOCKED) : uint8(slotType));
- break;
- case GROUP_PERMISSION:
- case ROUND_ROBIN_PERMISSION:
- if (!item.is_blocked)
- b << uint8(LOOT_SLOT_TYPE_ALLOW_LOOT);
- else
- b << uint8(LOOT_SLOT_TYPE_ROLL_ONGOING);
- break;
- default:
- b << uint8(slotType);
- break;
- }
- }
- else
+ case MASTER_PERMISSION:
+ b << uint8(LOOT_SLOT_TYPE_MASTER);
+ break;
+ case RESTRICTED_PERMISSION:
+ b << (item.is_blocked ? uint8(LOOT_SLOT_TYPE_LOCKED) : uint8(slotType));
+ break;
+ case GROUP_PERMISSION:
+ case ROUND_ROBIN_PERMISSION:
+ if (!item.is_blocked)
+ b << uint8(LOOT_SLOT_TYPE_ALLOW_LOOT);
+ else
+ b << uint8(LOOT_SLOT_TYPE_ROLL_ONGOING);
+ break;
+ default:
b << uint8(slotType);
+ break;
+ }
++itemsShown;
}
}
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index bca5cde1fa5..ecfb864823f 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -180,24 +180,24 @@ struct TC_GAME_API LootItem
const AllowedLooterSet & GetAllowedLooters() const { return allowedGUIDs; }
};
-struct QuestItem
+struct NotNormalLootItem
{
- uint8 index; // position in quest_items;
+ uint8 index; // position in quest_items or items;
bool is_looted;
- QuestItem()
+ NotNormalLootItem()
: index(0), is_looted(false) { }
- QuestItem(uint8 _index, bool _islooted = false)
+ NotNormalLootItem(uint8 _index, bool _islooted = false)
: index(_index), is_looted(_islooted) { }
};
struct Loot;
class LootTemplate;
-typedef std::vector<QuestItem> QuestItemList;
+typedef std::vector<NotNormalLootItem> NotNormalLootItemList;
typedef std::vector<LootItem> LootItemList;
-typedef std::map<uint32, QuestItemList*> QuestItemMap;
+typedef std::map<uint32, NotNormalLootItemList*> NotNormalLootItemMap;
typedef std::list<LootStoreItem*> LootStoreItemList;
typedef std::unordered_map<uint32, LootTemplate*> LootTemplateMap;
@@ -308,9 +308,9 @@ struct TC_GAME_API Loot
{
friend ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv);
- QuestItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; }
- QuestItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; }
- QuestItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; }
+ NotNormalLootItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; }
+ NotNormalLootItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; }
+ NotNormalLootItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; }
std::vector<LootItem> items;
std::vector<LootItem> quest_items;
@@ -340,15 +340,15 @@ struct TC_GAME_API Loot
// void clear();
void clear()
{
- for (QuestItemMap::const_iterator itr = PlayerQuestItems.begin(); itr != PlayerQuestItems.end(); ++itr)
+ for (NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.begin(); itr != PlayerQuestItems.end(); ++itr)
delete itr->second;
PlayerQuestItems.clear();
- for (QuestItemMap::const_iterator itr = PlayerFFAItems.begin(); itr != PlayerFFAItems.end(); ++itr)
+ for (NotNormalLootItemMap::const_iterator itr = PlayerFFAItems.begin(); itr != PlayerFFAItems.end(); ++itr)
delete itr->second;
PlayerFFAItems.clear();
- for (QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.begin(); itr != PlayerNonQuestNonFFAConditionalItems.end(); ++itr)
+ for (NotNormalLootItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.begin(); itr != PlayerNonQuestNonFFAConditionalItems.end(); ++itr)
delete itr->second;
PlayerNonQuestNonFFAConditionalItems.clear();
@@ -377,7 +377,7 @@ struct TC_GAME_API Loot
// Inserts the item into the loot (called by LootTemplate processors)
void AddItem(LootStoreItem const & item);
- LootItem* LootItemInSlot(uint32 lootslot, Player* player, QuestItem** qitem = NULL, QuestItem** ffaitem = NULL, QuestItem** conditem = NULL);
+ LootItem* LootItemInSlot(uint32 lootslot, Player* player, NotNormalLootItem** qitem = NULL, NotNormalLootItem** ffaitem = NULL, NotNormalLootItem** conditem = NULL);
uint32 GetMaxSlotInLootFor(Player* player) const;
bool hasItemForAll() const;
bool hasItemFor(Player* player) const;
@@ -385,14 +385,14 @@ struct TC_GAME_API Loot
private:
void FillNotNormalLootFor(Player* player, bool presentAtLooting);
- QuestItemList* FillFFALoot(Player* player);
- QuestItemList* FillQuestLoot(Player* player);
- QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting);
+ NotNormalLootItemList* FillFFALoot(Player* player);
+ NotNormalLootItemList* FillQuestLoot(Player* player);
+ NotNormalLootItemList* FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting);
GuidSet PlayersLooting;
- QuestItemMap PlayerQuestItems;
- QuestItemMap PlayerFFAItems;
- QuestItemMap PlayerNonQuestNonFFAConditionalItems;
+ NotNormalLootItemMap PlayerQuestItems;
+ NotNormalLootItemMap PlayerFFAItems;
+ NotNormalLootItemMap PlayerNonQuestNonFFAConditionalItems;
// All rolls are registered here. They need to know, when the loot is not valid anymore
LootValidatorRefManager i_LootValidatorRefManager;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index ce0c749c294..bf913081fef 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -374,9 +374,9 @@ enum SpellAttr2
SPELL_ATTR2_IS_ARCANE_CONCENTRATION = 0x00800000, // 23 Only mage Arcane Concentration have this flag
SPELL_ATTR2_UNK24 = 0x01000000, // 24
SPELL_ATTR2_UNK25 = 0x02000000, // 25
- SPELL_ATTR2_UNK26 = 0x04000000, // 26 unaffected by school immunity
+ SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE = 0x04000000, // 26 unaffected by school immunity
SPELL_ATTR2_UNK27 = 0x08000000, // 27
- SPELL_ATTR2_UNK28 = 0x10000000, // 28
+ SPELL_ATTR2_IGNORE_ITEM_CHECK = 0x10000000, // 28 Spell is cast without checking item requirements (charges/reagents/totem)
SPELL_ATTR2_CANT_CRIT = 0x20000000, // 29 Spell can't crit
SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC = 0x40000000, // 30 spell can trigger even if triggered
SPELL_ATTR2_FOOD_BUFF = 0x80000000 // 31 Food or Drink Buff (like Well Fed)
@@ -472,7 +472,7 @@ enum SpellAttr5
SPELL_ATTR5_HASTE_AFFECT_DURATION = 0x00002000, // 13 haste effects decrease duration of this
SPELL_ATTR5_UNK14 = 0x00004000, // 14
SPELL_ATTR5_UNK15 = 0x00008000, // 15 Inflits on multiple targets?
- SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK = 0x00010000, // 16 this allows spells with EquippedItemClass to affect spells from other items if the required item is equipped
+ SPELL_ATTR5_UNK16 = 0x00010000, // 16
SPELL_ATTR5_USABLE_WHILE_FEARED = 0x00020000, // 17 usable while feared
SPELL_ATTR5_USABLE_WHILE_CONFUSED = 0x00040000, // 18 usable while confused
SPELL_ATTR5_DONT_TURN_DURING_CAST = 0x00080000, // 19 Blocks caster's turning when casting (client does not automatically turn caster's model to face UNIT_FIELD_TARGET)
@@ -548,7 +548,7 @@ enum SpellAttr7
SPELL_ATTR7_UNK17 = 0x00020000, // 17 Only 27965 (Suicide) spell.
SPELL_ATTR7_HAS_CHARGE_EFFECT = 0x00040000, // 18 Only spells that have Charge among effects.
SPELL_ATTR7_ZONE_TELEPORT = 0x00080000, // 19 Teleports to specific zones.
- SPELL_ATTR7_UNK20 = 0x00100000, // 20 Blink, Divine Shield, Ice Block
+ SPELL_ATTR7_USABLE_IN_STUN_FEAR_CONFUSION = 0x00100000, // 20 Blink, Divine Shield, Ice Block
SPELL_ATTR7_UNK21 = 0x00200000, // 21 Not set
SPELL_ATTR7_UNK22 = 0x00400000, // 22
SPELL_ATTR7_UNK23 = 0x00800000, // 23 Motivate, Mutilate, Shattering Throw
@@ -1286,10 +1286,11 @@ enum SpellImmunity
IMMUNITY_DAMAGE = 3, // enum SpellSchoolMask
IMMUNITY_DISPEL = 4, // enum DispelType
IMMUNITY_MECHANIC = 5, // enum Mechanics
- IMMUNITY_ID = 6
+ IMMUNITY_ID = 6,
+
+ MAX_SPELL_IMMUNITY
};
-#define MAX_SPELL_IMMUNITY 7
// target enum name consist of:
// TARGET_[OBJECT_TYPE]_[REFERENCE_TYPE(skipped for caster)]_[SELECTION_TYPE(skipped for default)]_[additional specifiers(friendly, BACK_LEFT, etc.]
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 4ad2a314111..105b4245ff3 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -20,7 +20,6 @@
#include "CreatureAISelector.h"
#include "Creature.h"
#include "ScriptSystem.h"
-
#include "ConfusedMovementGenerator.h"
#include "FleeingMovementGenerator.h"
#include "HomeMovementGenerator.h"
@@ -33,9 +32,21 @@
#include "MoveSpline.h"
#include "MoveSplineInit.h"
-inline bool isStatic(MovementGenerator *mv)
+inline bool IsStatic(MovementGenerator* movement)
+{
+ return (movement == &si_idleMovement);
+}
+
+MotionMaster::~MotionMaster()
{
- return (mv == &si_idleMovement);
+ // clear ALL movement generators (including default)
+ while (!empty())
+ {
+ MovementGenerator *curr = top();
+ pop();
+ if (curr && !IsStatic(curr))
+ delete curr; // Skip finalizing on delete, it might launch new movement
+ }
}
void MotionMaster::Initialize()
@@ -66,18 +77,6 @@ void MotionMaster::InitDefault()
}
}
-MotionMaster::~MotionMaster()
-{
- // clear ALL movement generators (including default)
- while (!empty())
- {
- MovementGenerator *curr = top();
- pop();
- if (curr && !isStatic(curr))
- delete curr; // Skip finalizing on delete, it might launch new movement
- }
-}
-
void MotionMaster::UpdateMotion(uint32 diff)
{
if (!_owner)
@@ -97,20 +96,20 @@ void MotionMaster::UpdateMotion(uint32 diff)
else
_cleanFlag &= ~MMCF_UPDATE;
- if (_expList)
+ if (_expireList)
{
- for (size_t i = 0; i < _expList->size(); ++i)
+ for (size_t i = 0; i < _expireList->size(); ++i)
{
- MovementGenerator* mg = (*_expList)[i];
+ MovementGenerator* mg = (*_expireList)[i];
DirectDelete(mg);
}
- delete _expList;
- _expList = NULL;
+ delete _expireList;
+ _expireList = nullptr;
if (empty())
Initialize();
- else if (needInitTop())
+ else if (NeedInitTop())
InitTop();
else if (_cleanFlag & MMCF_RESET)
top()->Reset(_owner);
@@ -122,84 +121,84 @@ void MotionMaster::UpdateMotion(uint32 diff)
_owner->UpdateUnderwaterState(_owner->GetMap(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ());
}
-void MotionMaster::DirectClean(bool reset)
+void MotionMaster::Clear(bool reset /*= true*/)
{
- while (size() > 1)
+ if (_cleanFlag & MMCF_UPDATE)
{
- MovementGenerator *curr = top();
- pop();
- if (curr) DirectDelete(curr);
+ if (reset)
+ _cleanFlag |= MMCF_RESET;
+ else
+ _cleanFlag &= ~MMCF_RESET;
+ DelayedClean();
}
-
- if (empty())
- return;
-
- if (needInitTop())
- InitTop();
- else if (reset)
- top()->Reset(_owner);
+ else
+ DirectClean(reset);
}
-void MotionMaster::DelayedClean()
+void MotionMaster::MovementExpired(bool reset /*= true*/)
{
- while (size() > 1)
+ if (_cleanFlag & MMCF_UPDATE)
{
- MovementGenerator *curr = top();
- pop();
- if (curr)
- DelayedDelete(curr);
+ if (reset)
+ _cleanFlag |= MMCF_RESET;
+ else
+ _cleanFlag &= ~MMCF_RESET;
+ DelayedExpire();
}
+ else
+ DirectExpire(reset);
}
-void MotionMaster::DirectExpire(bool reset)
+MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
{
- if (size() > 1)
- {
- MovementGenerator *curr = top();
- pop();
- DirectDelete(curr);
- }
+ if (empty())
+ return IDLE_MOTION_TYPE;
- while (!empty() && !top())
- --_top;
+ return top()->GetMovementGeneratorType();
+}
- if (empty())
- Initialize();
- else if (needInitTop())
- InitTop();
- else if (reset)
- top()->Reset(_owner);
+MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const
+{
+ if (!_slot[slot])
+ return NULL_MOTION_TYPE;
+ else
+ return _slot[slot]->GetMovementGeneratorType();
}
-void MotionMaster::DelayedExpire()
+MovementGenerator* MotionMaster::GetMotionSlot(int slot) const
{
- if (size() > 1)
+ ASSERT(slot >= 0);
+ return _slot[slot];
+}
+
+void MotionMaster::propagateSpeedChange()
+{
+ for (int i = 0; i <= _top; ++i)
{
- MovementGenerator *curr = top();
- pop();
- DelayedDelete(curr);
+ if (_slot[i])
+ _slot[i]->unitSpeedChanged();
}
+}
- while (!empty() && !top())
- --_top;
+bool MotionMaster::GetDestination(float &x, float &y, float &z)
+{
+ if (_owner->movespline->Finalized())
+ return false;
+
+ G3D::Vector3 const& dest = _owner->movespline->FinalDestination();
+ x = dest.x;
+ y = dest.y;
+ z = dest.z;
+ return true;
}
void MotionMaster::MoveIdle()
{
//! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active
- if (empty() || !isStatic(top()))
+ if (empty() || !IsStatic(top()))
Mutate(&si_idleMovement, MOTION_SLOT_IDLE);
}
-void MotionMaster::MoveRandom(float spawndist)
-{
- if (_owner->GetTypeId() == TYPEID_UNIT)
- {
- TC_LOG_DEBUG("misc", "Creature (GUID: %u) started random movement.", _owner->GetGUID().GetCounter());
- Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE);
- }
-}
-
void MotionMaster::MoveTargetedHome()
{
Clear(false);
@@ -225,18 +224,36 @@ void MotionMaster::MoveTargetedHome()
}
}
-void MotionMaster::MoveConfused()
+void MotionMaster::MoveRandom(float spawndist)
{
+ if (_owner->GetTypeId() == TYPEID_UNIT)
+ {
+ TC_LOG_DEBUG("misc", "Creature (GUID: %u) started random movement.", _owner->GetGUID().GetCounter());
+ Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE);
+ }
+}
+
+void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot)
+{
+ // ignore movement request if target not exist
+ if (!target || target == _owner)
+ return;
+
+ //_owner->AddUnitState(UNIT_STATE_FOLLOW);
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUID().GetCounter());
- Mutate(new ConfusedMovementGenerator<Player>(), MOTION_SLOT_CONTROLLED);
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) follows %s (GUID: %u).", _owner->GetGUID().GetCounter(),
+ target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
+ target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
+ Mutate(new FollowMovementGenerator<Player>(target, dist, angle), slot);
}
else
{
- TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) move confused",
- _owner->GetEntry(), _owner->GetGUID().GetCounter());
- Mutate(new ConfusedMovementGenerator<Creature>(), MOTION_SLOT_CONTROLLED);
+ TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) follows %s (GUID: %u).",
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(),
+ target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
+ target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
+ Mutate(new FollowMovementGenerator<Creature>(target, dist, angle), slot);
}
}
@@ -265,27 +282,44 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle)
}
}
-void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot)
+void MotionMaster::MoveConfused()
{
- // ignore movement request if target not exist
- if (!target || target == _owner)
+ if (_owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUID().GetCounter());
+ Mutate(new ConfusedMovementGenerator<Player>(), MOTION_SLOT_CONTROLLED);
+ }
+ else
+ {
+ TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) move confused",
+ _owner->GetEntry(), _owner->GetGUID().GetCounter());
+ Mutate(new ConfusedMovementGenerator<Creature>(), MOTION_SLOT_CONTROLLED);
+ }
+}
+
+void MotionMaster::MoveFleeing(Unit* enemy, uint32 time)
+{
+ if (!enemy)
return;
- //_owner->AddUnitState(UNIT_STATE_FOLLOW);
if (_owner->GetTypeId() == TYPEID_PLAYER)
{
- TC_LOG_DEBUG("misc", "Player (GUID: %u) follows %s (GUID: %u).", _owner->GetGUID().GetCounter(),
- target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
- Mutate(new FollowMovementGenerator<Player>(target, dist, angle), slot);
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) flees from %s (GUID: %u).", _owner->GetGUID().GetCounter(),
+ enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
+ enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId());
+ Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED);
}
else
{
- TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) follows %s (GUID: %u).",
+ TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) flees from %s (GUID: %u)%s.",
_owner->GetEntry(), _owner->GetGUID().GetCounter(),
- target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId());
- Mutate(new FollowMovementGenerator<Creature>(target, dist, angle), slot);
+ enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
+ enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId(),
+ time ? " for a limited time" : "");
+ if (time)
+ Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED);
+ else
+ Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED);
}
}
@@ -353,6 +387,37 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos)
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
}
+void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/)
+{
+ if (_slot[MOTION_SLOT_CONTROLLED] && _slot[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE)
+ return;
+
+ if (_owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ TC_LOG_DEBUG("misc", "Player (GUID: %u) charged point (X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), x, y, z);
+ Mutate(new PointMovementGenerator<Player>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED);
+ }
+ else
+ {
+ TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) charged point (X: %f Y: %f Z: %f).",
+ _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z);
+ Mutate(new PointMovementGenerator<Creature>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED);
+ }
+}
+
+void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/)
+{
+ G3D::Vector3 dest = path.GetActualEndPosition();
+
+ MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH);
+
+ // Charge movement is not started when using EVENT_CHARGE_PREPATH
+ Movement::MoveSplineInit init(_owner);
+ init.MovebyPath(path.GetPath());
+ init.SetVelocity(speed);
+ init.Launch();
+}
+
void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ)
{
//this function may make players fall below map
@@ -531,37 +596,6 @@ void MotionMaster::MoveFall(uint32 id /*=0*/)
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
}
-void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/)
-{
- if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE)
- return;
-
- if (_owner->GetTypeId() == TYPEID_PLAYER)
- {
- TC_LOG_DEBUG("misc", "Player (GUID: %u) charged point (X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), x, y, z);
- Mutate(new PointMovementGenerator<Player>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED);
- }
- else
- {
- TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) charged point (X: %f Y: %f Z: %f).",
- _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z);
- Mutate(new PointMovementGenerator<Creature>(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED);
- }
-}
-
-void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/)
-{
- G3D::Vector3 dest = path.GetActualEndPosition();
-
- MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH);
-
- // Charge movement is not started when using EVENT_CHARGE_PREPATH
- Movement::MoveSplineInit init(_owner);
- init.MovebyPath(path.GetPath());
- init.SetVelocity(speed);
- init.Launch();
-}
-
void MotionMaster::MoveSeekAssistance(float x, float y, float z)
{
if (_owner->GetTypeId() == TYPEID_PLAYER)
@@ -593,32 +627,6 @@ void MotionMaster::MoveSeekAssistanceDistract(uint32 time)
}
}
-void MotionMaster::MoveFleeing(Unit* enemy, uint32 time)
-{
- if (!enemy)
- return;
-
- if (_owner->GetTypeId() == TYPEID_PLAYER)
- {
- TC_LOG_DEBUG("misc", "Player (GUID: %u) flees from %s (GUID: %u).", _owner->GetGUID().GetCounter(),
- enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId());
- Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED);
- }
- else
- {
- TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) flees from %s (GUID: %u)%s.",
- _owner->GetEntry(), _owner->GetGUID().GetCounter(),
- enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature",
- enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId(),
- time ? " for a limited time" : "");
- if (time)
- Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED);
- else
- Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED);
- }
-}
-
void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
{
if (_owner->GetTypeId() == TYPEID_PLAYER)
@@ -645,7 +653,7 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode)
void MotionMaster::MoveDistract(uint32 timer)
{
- if (Impl[MOTION_SLOT_CONTROLLED])
+ if (_slot[MOTION_SLOT_CONTROLLED])
return;
if (_owner->GetTypeId() == TYPEID_PLAYER)
@@ -662,11 +670,56 @@ void MotionMaster::MoveDistract(uint32 timer)
Mutate(mgen, MOTION_SLOT_CONTROLLED);
}
+void MotionMaster::MovePath(uint32 path_id, bool repeatable)
+{
+ if (!path_id)
+ return;
+
+ Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
+
+ TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).",
+ _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
+ _owner->GetGUID().GetCounter(), path_id, repeatable ? "YES" : "NO");
+}
+
+void MotionMaster::MoveRotate(uint32 time, RotateDirection direction)
+{
+ if (!time)
+ return;
+
+ Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE);
+}
+
+/******************** Private methods ********************/
+
+void MotionMaster::pop()
+{
+ if (empty())
+ return;
+
+ _slot[_top] = nullptr;
+ while (!empty() && !top())
+ --_top;
+}
+
+bool MotionMaster::NeedInitTop() const
+{
+ if (empty())
+ return false;
+ return _initialize[_top];
+}
+
+void MotionMaster::InitTop()
+{
+ top()->Initialize(_owner);
+ _initialize[_top] = false;
+}
+
void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot)
{
- if (MovementGenerator *curr = Impl[slot])
+ if (MovementGenerator *curr = _slot[slot])
{
- Impl[slot] = NULL; // in case a new one is generated in this slot during directdelete
+ _slot[slot] = nullptr; // in case a new one is generated in this slot during directdelete
if (_top == slot && (_cleanFlag & MMCF_UPDATE))
DelayedDelete(curr);
else
@@ -677,110 +730,92 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot)
_top = slot;
}
- Impl[slot] = m;
+ _slot[slot] = m;
if (_top > slot)
- _needInit[slot] = true;
+ _initialize[slot] = true;
else
{
- _needInit[slot] = false;
+ _initialize[slot] = false;
m->Initialize(_owner);
}
}
-void MotionMaster::MovePath(uint32 path_id, bool repeatable)
+void MotionMaster::DirectClean(bool reset)
{
- if (!path_id)
- return;
- //We set waypoint movement as new default movement generator
- // clear ALL movement generators (including default)
- /*while (!empty())
+ while (size() > 1)
{
MovementGenerator *curr = top();
- curr->Finalize(*_owner);
pop();
- if (!isStatic(curr))
- delete curr;
- }*/
-
- //_owner->GetTypeId() == TYPEID_PLAYER ?
- //Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)):
- Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
-
- TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).",
- _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
- _owner->GetGUID().GetCounter(), path_id, repeatable ? "YES" : "NO");
-}
+ if (curr) DirectDelete(curr);
+ }
-void MotionMaster::MoveRotate(uint32 time, RotateDirection direction)
-{
- if (!time)
+ if (empty())
return;
- Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE);
+ if (NeedInitTop())
+ InitTop();
+ else if (reset)
+ top()->Reset(_owner);
}
-void MotionMaster::propagateSpeedChange()
+void MotionMaster::DelayedClean()
{
- /*Impl::container_type::iterator it = Impl::c.begin();
- for (; it != end(); ++it)
- {
- (*it)->unitSpeedChanged();
- }*/
- for (int i = 0; i <= _top; ++i)
+ while (size() > 1)
{
- if (Impl[i])
- Impl[i]->unitSpeedChanged();
+ MovementGenerator *curr = top();
+ pop();
+ if (curr)
+ DelayedDelete(curr);
}
}
-MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
+void MotionMaster::DirectExpire(bool reset)
{
- if (empty())
- return IDLE_MOTION_TYPE;
+ if (size() > 1)
+ {
+ MovementGenerator *curr = top();
+ pop();
+ DirectDelete(curr);
+ }
- return top()->GetMovementGeneratorType();
-}
+ while (!empty() && !top())
+ --_top;
-MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const
-{
- if (!Impl[slot])
- return NULL_MOTION_TYPE;
- else
- return Impl[slot]->GetMovementGeneratorType();
+ if (empty())
+ Initialize();
+ else if (NeedInitTop())
+ InitTop();
+ else if (reset)
+ top()->Reset(_owner);
}
-void MotionMaster::InitTop()
+void MotionMaster::DelayedExpire()
{
- top()->Initialize(_owner);
- _needInit[_top] = false;
+ if (size() > 1)
+ {
+ MovementGenerator *curr = top();
+ pop();
+ DelayedDelete(curr);
+ }
+
+ while (!empty() && !top())
+ --_top;
}
-void MotionMaster::DirectDelete(_Ty curr)
+void MotionMaster::DirectDelete(MovementGenerator* curr)
{
- if (isStatic(curr))
+ if (IsStatic(curr))
return;
curr->Finalize(_owner);
delete curr;
}
-void MotionMaster::DelayedDelete(_Ty curr)
+void MotionMaster::DelayedDelete(MovementGenerator* curr)
{
TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating Movement Generator (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType());
- if (isStatic(curr))
+ if (IsStatic(curr))
return;
- if (!_expList)
- _expList = new ExpireList();
- _expList->push_back(curr);
-}
-
-bool MotionMaster::GetDestination(float &x, float &y, float &z)
-{
- if (_owner->movespline->Finalized())
- return false;
-
- G3D::Vector3 const& dest = _owner->movespline->FinalDestination();
- x = dest.x;
- y = dest.y;
- z = dest.z;
- return true;
+ if (!_expireList)
+ _expireList = new ExpireList();
+ _expireList->push_back(curr);
}
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index d376f6aa58f..0f46f42e08e 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TRINITY_MOTIONMASTER_H
-#define TRINITY_MOTIONMASTER_H
+#ifndef MOTIONMASTER_H
+#define MOTIONMASTER_H
#include "Common.h"
#include <vector>
@@ -32,31 +32,32 @@ class PathGenerator;
// Creature Entry ID used for waypoints show, visible only for GMs
#define VISUAL_WAYPOINT 1
+// assume it is 25 yard per 0.6 second
+#define SPEED_CHARGE 42.0f
-// values 0 ... MAX_DB_MOTION_TYPE-1 used in DB
enum MovementGeneratorType
{
- IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h
- RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h
- WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h
- MAX_DB_MOTION_TYPE = 3, // *** this and below motion types can't be set in DB.
- ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h
- CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h
- CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h
- HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h
- FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h
- POINT_MOTION_TYPE = 8, // PointMovementGenerator.h
- FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h
- DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h
- ASSISTANCE_MOTION_TYPE= 11, // PointMovementGenerator.h (first part of flee for assistance)
- ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance)
- TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance)
- FOLLOW_MOTION_TYPE = 14,
- ROTATE_MOTION_TYPE = 15,
- EFFECT_MOTION_TYPE = 16,
- NULL_MOTION_TYPE = 17,
- SPLINE_CHAIN_MOTION_TYPE = 18, // SplineChainMovementGenerator.h
- MAX_MOTION_TYPE // limit
+ IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h
+ RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h
+ WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h
+ MAX_DB_MOTION_TYPE = 3, // Below motion types can't be set in DB.
+ ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h
+ CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h
+ CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h
+ HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h
+ FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h
+ POINT_MOTION_TYPE = 8, // PointMovementGenerator.h
+ FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h
+ DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h
+ ASSISTANCE_MOTION_TYPE = 11, // PointMovementGenerator.h (first part of flee for assistance)
+ ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance)
+ TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance)
+ FOLLOW_MOTION_TYPE = 14,
+ ROTATE_MOTION_TYPE = 15,
+ EFFECT_MOTION_TYPE = 16,
+ NULL_MOTION_TYPE = 17,
+ SPLINE_CHAIN_MOTION_TYPE = 18, // SplineChainMovementGenerator.h
+ MAX_MOTION_TYPE // limit
};
enum MovementSlot
@@ -80,91 +81,41 @@ enum RotateDirection
ROTATE_DIRECTION_RIGHT
};
-// assume it is 25 yard per 0.6 second
-#define SPEED_CHARGE 42.0f
-
-class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
+class TC_GAME_API MotionMaster
{
private:
- //typedef std::stack<MovementGenerator *> Impl;
- typedef MovementGenerator* _Ty;
-
- void pop()
- {
- if (empty())
- return;
+ typedef std::vector<MovementGenerator*> ExpireList;
- Impl[_top] = NULL;
- while (!empty() && !top())
- --_top;
- }
- void push(_Ty _Val) { ++_top; Impl[_top] = _Val; }
-
- bool needInitTop() const
- {
- if (empty())
- return false;
- return _needInit[_top];
- }
- void InitTop();
public:
-
- explicit MotionMaster(Unit* unit) : _expList(NULL), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE)
+ explicit MotionMaster(Unit* unit) : _expireList(nullptr), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE)
{
for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i)
{
- Impl[i] = NULL;
- _needInit[i] = true;
+ _slot[i] = nullptr;
+ _initialize[i] = true;
}
}
~MotionMaster();
- void Initialize();
- void InitDefault();
-
bool empty() const { return (_top < 0); }
int size() const { return _top + 1; }
- _Ty top() const
- {
- ASSERT(!empty());
- return Impl[_top];
- }
- _Ty GetMotionSlot(int slot) const
- {
- ASSERT(slot >= 0);
- return Impl[slot];
- }
+ MovementGenerator* top() const { ASSERT(!empty()); return _slot[_top]; }
- void DirectDelete(_Ty curr);
- void DelayedDelete(_Ty curr);
+ void Initialize();
+ void InitDefault();
void UpdateMotion(uint32 diff);
- void Clear(bool reset = true)
- {
- if (_cleanFlag & MMCF_UPDATE)
- {
- if (reset)
- _cleanFlag |= MMCF_RESET;
- else
- _cleanFlag &= ~MMCF_RESET;
- DelayedClean();
- }
- else
- DirectClean(reset);
- }
- void MovementExpired(bool reset = true)
- {
- if (_cleanFlag & MMCF_UPDATE)
- {
- if (reset)
- _cleanFlag |= MMCF_RESET;
- else
- _cleanFlag &= ~MMCF_RESET;
- DelayedExpire();
- }
- else
- DirectExpire(reset);
- }
+
+ void Clear(bool reset = true);
+ void MovementExpired(bool reset = true);
+
+ MovementGeneratorType GetCurrentMovementGeneratorType() const;
+ MovementGeneratorType GetMotionSlotType(int slot) const;
+ MovementGenerator* GetMotionSlot(int slot) const;
+
+ void propagateSpeedChange();
+
+ bool GetDestination(float &x, float &y, float &z);
void MoveIdle();
void MoveTargetedHome();
@@ -174,7 +125,9 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
void MoveConfused();
void MoveFleeing(Unit* enemy, uint32 time = 0);
void MovePoint(uint32 id, Position const& pos, bool generatePath = true)
- { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); }
+ {
+ MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath);
+ }
void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true);
/* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops.
@@ -212,27 +165,27 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
void MovePath(uint32 path_id, bool repeatable);
void MoveRotate(uint32 time, RotateDirection direction);
- MovementGeneratorType GetCurrentMovementGeneratorType() const;
- MovementGeneratorType GetMotionSlotType(int slot) const;
+ private:
+ void pop();
- void propagateSpeedChange();
+ bool NeedInitTop() const;
+ void InitTop();
- bool GetDestination(float &x, float &y, float &z);
- private:
- void Mutate(MovementGenerator *m, MovementSlot slot); // use Move* functions instead
+ void Mutate(MovementGenerator *m, MovementSlot slot);
void DirectClean(bool reset);
void DelayedClean();
-
void DirectExpire(bool reset);
void DelayedExpire();
+ void DirectDelete(MovementGenerator* curr);
+ void DelayedDelete(MovementGenerator* curr);
- typedef std::vector<_Ty> ExpireList;
- ExpireList* _expList;
- _Ty Impl[MAX_MOTION_SLOT];
+ ExpireList* _expireList;
+ MovementGenerator* _slot[MAX_MOTION_SLOT];
int _top;
Unit* _owner;
- bool _needInit[MAX_MOTION_SLOT];
+ bool _initialize[MAX_MOTION_SLOT];
uint8 _cleanFlag;
};
-#endif
+
+#endif // MOTIONMASTER_H
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 2737c852d98..b9357d60967 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1202,12 +1202,11 @@ void ScriptMgr::FillSpellSummary()
}
}
-template<typename T, typename F>
-void CreateSpellOrAuraScripts(uint32 spellId, std::list<T*>& scriptVector, F&& extractor)
+template<typename T, typename F, typename O>
+void CreateSpellOrAuraScripts(uint32 spellId, std::vector<T*>& scriptVector, F&& extractor, O* objectInvoker)
{
SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId);
-
- for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr)
+ for (auto itr = bounds.first; itr != bounds.second; ++itr)
{
// When the script is disabled continue with the next one
if (!itr->second.second)
@@ -1218,24 +1217,28 @@ void CreateSpellOrAuraScripts(uint32 spellId, std::list<T*>& scriptVector, F&& e
continue;
T* script = (*tmpscript.*extractor)();
-
if (!script)
continue;
script->_Init(&tmpscript->GetName(), spellId);
+ if (!script->_Load(objectInvoker))
+ {
+ delete script;
+ continue;
+ }
scriptVector.push_back(script);
}
}
-void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector)
+void ScriptMgr::CreateSpellScripts(uint32 spellId, std::vector<SpellScript*>& scriptVector, Spell* invoker) const
{
- CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetSpellScript);
+ CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetSpellScript, invoker);
}
-void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector)
+void ScriptMgr::CreateAuraScripts(uint32 spellId, std::vector<AuraScript*>& scriptVector, Aura* invoker) const
{
- CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetAuraScript);
+ CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetAuraScript, invoker);
}
SpellScriptLoader* ScriptMgr::GetSpellScriptLoader(uint32 scriptId)
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index a6cce299645..22a84804089 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -29,6 +29,7 @@
class AccountMgr;
class AuctionHouseObject;
+class Aura;
class AuraScript;
class Battleground;
class BattlegroundMap;
@@ -896,8 +897,8 @@ class TC_GAME_API ScriptMgr
public: /* SpellScriptLoader */
- void CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector);
- void CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector);
+ void CreateSpellScripts(uint32 spellId, std::vector<SpellScript*>& scriptVector, Spell* invoker) const;
+ void CreateAuraScripts(uint32 spellId, std::vector<AuraScript*>& scriptVector, Aura* invoker) const;
SpellScriptLoader* GetSpellScriptLoader(uint32 scriptId);
public: /* ServerScript */
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 997c2904e9e..2b4e2e4177d 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -204,7 +204,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
&AuraEffect::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
&AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
- &AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
+ &AuraEffect::HandleModMechanicImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
&AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
&AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
@@ -890,14 +890,12 @@ bool AuraEffect::IsAffectedOnSpell(SpellInfo const* spell) const
{
if (!spell)
return false;
- // Check family name
- if (spell->SpellFamilyName != m_spellInfo->SpellFamilyName)
+
+ // Check family name and EffectClassMask
+ if (!spell->IsAffected(m_spellInfo->SpellFamilyName, m_spellInfo->Effects[m_effIndex].SpellClassMask))
return false;
- // Check EffectClassMask
- if (m_spellInfo->Effects[m_effIndex].SpellClassMask & spell->SpellFamilyFlags)
- return true;
- return false;
+ return true;
}
void AuraEffect::SendTickImmune(Unit* target, Unit* caster) const
@@ -976,15 +974,12 @@ bool AuraEffect::CheckEffectProc(AuraApplication* aurApp, ProcEventInfo& eventIn
return false;
// Spell own damage at apply won't break CC
- if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
+ if (spellInfo && spellInfo == GetSpellInfo())
{
- if (spellInfo == GetSpellInfo())
- {
- Aura* aura = GetBase();
- // called from spellcast, should not have ticked yet
- if (aura->GetDuration() == aura->GetMaxDuration())
- return false;
- }
+ Aura* aura = GetBase();
+ // called from spellcast, should not have ticked yet
+ if (aura->GetDuration() == aura->GetMaxDuration())
+ return false;
}
break;
}
@@ -1176,15 +1171,15 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (apply)
{
if (spellId)
- target->CastSpell(target, spellId, true, NULL, this);
+ target->CastSpell(target, spellId, true, nullptr, this);
if (spellId2)
- target->CastSpell(target, spellId2, true, NULL, this);
+ target->CastSpell(target, spellId2, true, nullptr, this);
if (target->GetTypeId() == TYPEID_PLAYER)
{
- const PlayerSpellMap& sp_list = target->ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ PlayerSpellMap const& sp_list = target->ToPlayer()->GetSpellMap();
+ for (auto itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
continue;
@@ -1197,7 +1192,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
continue;
if (spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
- target->CastSpell(target, itr->first, true, NULL, this);
+ target->CastSpell(target, itr->first, true, nullptr, this);
}
// Also do it for Glyphs
@@ -1212,7 +1207,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
continue;
if (spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
- target->CastSpell(target, glyph->SpellId, true, NULL, this);
+ target->CastSpell(target, glyph->SpellId, true, nullptr, this);
}
}
}
@@ -1222,7 +1217,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932);
if (spellInfo && spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
- target->CastSpell(target, 24932, true, NULL, this);
+ target->CastSpell(target, 24932, true, nullptr, this);
}
// Improved Barkskin - apply/remove armor bonus due to shapeshift
if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
@@ -1235,14 +1230,14 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (HotWSpellId)
{ // hacky, but the only way as spell family is not SPELLFAMILY_DRUID
Unit::AuraEffectList const& mModTotalStatPct = target->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
- for (Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
+ for (AuraEffect const* aurEff : mModTotalStatPct)
{
// Heart of the Wild
- if ((*i)->GetSpellInfo()->SpellIconID == 240 && (*i)->GetMiscValue() == 3)
+ if (aurEff->GetSpellInfo()->SpellIconID == 240 && aurEff->GetMiscValue() == 3)
{
- int32 HotWMod = (*i)->GetAmount() / 2; // For each 2% Intelligence, you get 1% stamina and 1% attack power.
+ int32 HotWMod = aurEff->GetAmount() / 2; // For each 2% Intelligence, you get 1% stamina and 1% attack power.
- target->CastCustomSpell(target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
+ target->CastCustomSpell(HotWSpellId, SPELLVALUE_BASE_POINT0, HotWMod, target, true, nullptr, this);
break;
}
}
@@ -1266,13 +1261,13 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
spellId3 = 47180;
break;
}
- target->CastSpell(target, spellId3, true, NULL, this);
+ target->CastSpell(target, spellId3, true, nullptr, this);
}
// Master Shapeshifter - Cat
if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
- target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true);
+ target->CastCustomSpell(48420, SPELLVALUE_BASE_POINT0, bp, target, true);
}
break;
case FORM_DIREBEAR:
@@ -1281,13 +1276,13 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
- target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true);
+ target->CastCustomSpell(48418, SPELLVALUE_BASE_POINT0, bp, target, true);
}
// Survival of the Fittest
if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 0))
{
int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue();
- target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this);
+ target->CastCustomSpell(62069, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, this);
}
break;
case FORM_MOONKIN:
@@ -1295,7 +1290,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
- target->CastCustomSpell(target, 48421, &bp, NULL, NULL, true);
+ target->CastCustomSpell(48421, SPELLVALUE_BASE_POINT0, bp, target, true);
}
break;
// Master Shapeshifter - Tree of Life
@@ -1303,7 +1298,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
- target->CastCustomSpell(target, 48422, &bp, NULL, NULL, true);
+ target->CastCustomSpell(48422, SPELLVALUE_BASE_POINT0, bp, target, true);
}
break;
}
@@ -1317,7 +1312,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
target->RemoveOwnedAura(spellId2, target->GetGUID());
// Improved Barkskin - apply/remove armor bonus due to shapeshift
- if (Player* player=target->ToPlayer())
+ if (Player* player = target->ToPlayer())
{
if (player->HasSpell(63410) || player->HasSpell(63411))
{
@@ -1326,19 +1321,20 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
}
}
- const Unit::AuraEffectList& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
- AuraEffect* newAura = NULL;
+ Unit::AuraEffectList const& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
+ AuraEffect const* newAura = nullptr;
// Iterate through all the shapeshift auras that the target has, if there is another aura with SPELL_AURA_MOD_SHAPESHIFT, then this aura is being removed due to that one being applied
- for (Unit::AuraEffectList::const_iterator itr = shapeshifts.begin(); itr != shapeshifts.end(); ++itr)
+ for (AuraEffect const* aurEff : shapeshifts)
{
- if ((*itr) != this)
+ if (aurEff != this)
{
- newAura = *itr;
+ newAura = aurEff;
break;
}
}
+
Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras();
- for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
+ for (auto itr = tAuras.begin(); itr != tAuras.end();)
{
// Use the new aura to see on what stance the target will be
uint64 newStance = newAura ? (UI64LIT(1) << (newAura->GetMiscValue() - 1)) : 0;
@@ -1779,7 +1775,12 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (aurApp->GetRemoveMode())
return;
+ ShapeshiftForm prevForm = target->GetShapeshiftForm();
target->SetShapeshiftForm(form);
+ // add the shapeshift aura's boosts
+ if (prevForm != form)
+ HandleShapeshiftBoosts(target, true);
+
if (modelid > 0)
{
SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm());
@@ -1851,11 +1852,10 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
default:
break;
}
- }
- // adding/removing linked auras
- // add/remove the shapeshift aura's boosts
- HandleShapeshiftBoosts(target, apply);
+ // remove the shapeshift aura's boosts
+ HandleShapeshiftBoosts(target, false);
+ }
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->InitDataForForm();
@@ -2307,11 +2307,9 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
{
uint8 attacktype = Player::GetAttackBySlot(slot);
+ player->ApplyItemDependentAuras(item, !apply);
if (attacktype < MAX_ATTACK)
- {
player->_ApplyWeaponDamage(slot, item->GetTemplate(), NULL, !apply);
- player->_ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), !apply);
- }
}
}
@@ -3069,249 +3067,13 @@ void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint
/*** IMMUNITY ***/
/*********************************************************/
-void AuraEffect::HandleModStateImmunityMask(AuraApplication const* aurApp, uint8 mode, bool apply) const
+void AuraEffect::HandleModMechanicImmunityMask(AuraApplication const* aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit* target = aurApp->GetTarget();
- std::list <AuraType> aura_immunity_list;
- uint32 mechanic_immunity_list = 0;
- int32 miscVal = GetMiscValue();
-
- switch (miscVal)
- {
- case 27:
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_SILENCE);
- break;
- case 96:
- case 1615:
- {
- if (GetAmount())
- {
- mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT)
- | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN)
- | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM)
- | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR)
- | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED)
- | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN);
-
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT);
- aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
- aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR);
- }
- break;
- }
- case 679:
- {
- if (GetId() == 57742)
- {
- mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT)
- | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN)
- | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM)
- | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR)
- | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED)
- | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN);
-
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT);
- aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
- aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR);
- }
- break;
- }
- case 1557:
- {
- if (GetId() == 64187)
- {
- mechanic_immunity_list = (1 << MECHANIC_STUN);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- }
- else
- {
- mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT)
- | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN)
- | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM)
- | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR)
- | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED)
- | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN);
-
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT);
- aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
- aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR);
- }
- break;
- }
- case 1614:
- case 1694:
- {
- target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_TAUNT);
- break;
- }
- case 1630:
- {
- if (!GetAmount())
- {
- target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_TAUNT);
- }
- else
- {
- mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT)
- | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN)
- | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM)
- | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR)
- | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED)
- | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN);
-
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT);
- aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
- aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR);
- }
- break;
- }
- case 477:
- case 1733:
- {
- if (!GetAmount())
- {
- mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT)
- | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN)
- | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM)
- | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR)
- | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED)
- | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN);
-
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT);
- aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
- aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR);
- }
- break;
- }
- case 878:
- {
- if (GetAmount() == 1)
- {
- mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_STUN)
- | (1 << MECHANIC_DISORIENTED) | (1 << MECHANIC_FREEZE);
-
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- }
- break;
- }
- default:
- break;
- }
-
- if (aura_immunity_list.empty())
- {
- if (miscVal & (1<<10))
- aura_immunity_list.push_back(SPELL_AURA_MOD_STUN);
- if (miscVal & (1<<1))
- aura_immunity_list.push_back(SPELL_AURA_TRANSFORM);
-
- // These flag can be recognized wrong:
- if (miscVal & (1<<6))
- aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
- if (miscVal & (1<<0))
- aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT);
- if (miscVal & (1<<2))
- aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
- if (miscVal & (1<<9))
- aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR);
- if (miscVal & (1<<7))
- aura_immunity_list.push_back(SPELL_AURA_MOD_DISARM);
- }
-
- // apply immunities
- for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter)
- target->ApplySpellImmune(GetId(), IMMUNITY_STATE, *iter, apply);
-
- if (apply && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
- {
- target->RemoveAurasWithMechanic(mechanic_immunity_list, AURA_REMOVE_BY_DEFAULT, GetId());
- for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter)
- target->RemoveAurasByType(*iter);
- }
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
}
void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3320,52 +3082,7 @@ void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8
return;
Unit* target = aurApp->GetTarget();
- uint32 mechanic;
-
- switch (GetId())
- {
- case 34471: // The Beast Within
- case 19574: // Bestial Wrath
- mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_KNOCKOUT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_BANISH, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SHACKLE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DAZE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
- break;
- case 42292: // PvP trinket
- case 59752: // Every Man for Himself
- case 53490: // Bullheaded
- mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
- // Actually we should apply immunities here, too, but the aura has only 100 ms duration, so there is practically no point
- break;
- case 54508: // Demonic Empowerment
- mechanic = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
- break;
- default:
- if (GetMiscValue() < 1)
- return;
- mechanic = 1 << GetMiscValue();
- target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply);
- break;
- }
-
- if (apply && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
- target->RemoveAurasWithMechanic(mechanic, AURA_REMOVE_BY_DEFAULT, GetId());
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
}
void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3374,8 +3091,7 @@ void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const* aurApp, uint
return;
Unit* target = aurApp->GetTarget();
-
- target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, GetMiscValue(), apply);
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
// when removing flag aura, handle flag drop
Player* player = target->ToPlayer();
@@ -3397,11 +3113,7 @@ void AuraEffect::HandleAuraModStateImmunity(AuraApplication const* aurApp, uint8
return;
Unit* target = aurApp->GetTarget();
-
- target->ApplySpellImmune(GetId(), IMMUNITY_STATE, GetMiscValue(), apply);
-
- if (apply && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
- target->RemoveAurasByType(AuraType(GetMiscValue()), ObjectGuid::Empty, GetBase());
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
}
void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3410,8 +3122,7 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
return;
Unit* target = aurApp->GetTarget();
-
- target->ApplySpellImmune(GetId(), IMMUNITY_SCHOOL, GetMiscValue(), (apply));
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
if (GetSpellInfo()->Mechanic == MECHANIC_BANISH)
{
@@ -3421,12 +3132,15 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
{
bool banishFound = false;
Unit::AuraEffectList const& banishAuras = target->GetAuraEffectsByType(GetAuraType());
- for (Unit::AuraEffectList::const_iterator i = banishAuras.begin(); i != banishAuras.end(); ++i)
- if ((*i)->GetSpellInfo()->Mechanic == MECHANIC_BANISH)
+ for (AuraEffect const* aurEff : banishAuras)
+ {
+ if (aurEff->GetSpellInfo()->Mechanic == MECHANIC_BANISH)
{
banishFound = true;
break;
}
+ }
+
if (!banishFound)
target->ClearUnitState(UNIT_STATE_ISOLATED);
}
@@ -3439,23 +3153,6 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
if (GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
&& GetSpellInfo()->HasAttribute(SPELL_ATTR2_DAMAGE_REDUCED_SHIELD))
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
-
- /// @todo optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else
- if (apply
- && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
- && GetSpellInfo()->IsPositive()) // Only positive immunity removes auras
- {
- uint32 schoolMask = GetMiscValue();
- target->RemoveAppliedAuras([this, schoolMask](AuraApplication const* aurApp)
- {
- SpellInfo const* spell = aurApp->GetBase()->GetSpellInfo();
- return (spell->GetSchoolMask() & schoolMask) // Check for school mask
- && GetSpellInfo()->CanDispelAura(spell)
- && !aurApp->IsPositive() // Don't remove positive spells
- && !spell->IsPassive() // Don't remove passive auras
- && spell->Id != GetId(); // Don't remove self
- });
- }
}
void AuraEffect::HandleAuraModDmgImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3464,8 +3161,7 @@ void AuraEffect::HandleAuraModDmgImmunity(AuraApplication const* aurApp, uint8 m
return;
Unit* target = aurApp->GetTarget();
-
- target->ApplySpellImmune(GetId(), IMMUNITY_DAMAGE, GetMiscValue(), apply);
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
}
void AuraEffect::HandleAuraModDispelImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3474,8 +3170,7 @@ void AuraEffect::HandleAuraModDispelImmunity(AuraApplication const* aurApp, uint
return;
Unit* target = aurApp->GetTarget();
-
- target->ApplySpellDispelImmunity(m_spellInfo, DispelType(GetMiscValue()), (apply));
+ m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply);
}
/*********************************************************/
@@ -4071,29 +3766,14 @@ void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, u
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- Unit* target = aurApp->GetTarget();
+ Player* target = aurApp->GetTarget()->ToPlayer();
- if (target->GetTypeId() != TYPEID_PLAYER)
+ if (!target)
return;
- for (int i = 0; i < MAX_ATTACK; ++i)
- if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
- target->ToPlayer()->_ApplyWeaponDependentAuraCritMod(pItem, WeaponAttackType(i), this, apply);
-
- // mods must be applied base at equipped weapon class and subclass comparison
- // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
- // GetMiscValue() comparison with item generated damage types
-
- if (GetSpellInfo()->EquippedItemClass == -1)
- {
- target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- }
- else
- {
- // done in Player::_ApplyWeaponDependentAuraMods
- }
+ target->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
+ target->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
+ target->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
}
void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4394,6 +4074,7 @@ void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp,
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAttackPowerAndDamage(false);
}
+
/********************************/
/*** DAMAGE BONUS ***/
/********************************/
@@ -4404,79 +4085,22 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
- // apply item specific bonuses for already equipped weapon
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- for (int i = 0; i < MAX_ATTACK; ++i)
- if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
- target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
- }
-
- // GetMiscValue() is bitmask of spell schools
- // 1 (0-bit) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
- // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
- // 127 - full bitmask any damages
- //
- // mods must be applied base at equipped weapon class and subclass comparison
- // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
- // GetMiscValue() comparison with item generated damage types
-
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
- {
- // apply generic physical damage bonuses including wand case
- if (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
- {
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
-
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- if (GetAmount() > 0)
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, GetAmount(), apply);
- else
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, GetAmount(), apply);
- }
- }
- else
- {
- // done in Player::_ApplyWeaponDependentAuraMods
- }
- }
-
- // Skip non magic case for speedup
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0)
- return;
-
- if (GetSpellInfo()->EquippedItemClass != -1 || GetSpellInfo()->EquippedItemInventoryTypeMask != 0)
+ if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
{
- // wand magic case (skip generic to all item spell bonuses)
- // done in Player::_ApplyWeaponDependentAuraMods
-
- // Skip item specific requirements for not wand magic damage
- return;
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
}
- // Magic damage modifiers implemented in Unit::SpellDamageBonus
+ // Magic damage modifiers implemented in Unit::SpellBaseDamageBonusDone
// This information for client side use only
if (target->GetTypeId() == TYPEID_PLAYER)
{
- if (GetAmount() > 0)
- {
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
- {
- if ((GetMiscValue() & (1<<i)) != 0)
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, GetAmount(), apply);
- }
- }
- else
- {
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
- {
- if ((GetMiscValue() & (1<<i)) != 0)
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, GetAmount(), apply);
- }
- }
+ uint16 baseField = GetAmount() >= 0 ? PLAYER_FIELD_MOD_DAMAGE_DONE_POS : PLAYER_FIELD_MOD_DAMAGE_DONE_NEG;
+ for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ if (GetMiscValue() & (1 << i))
+ target->ApplyModUInt32Value(baseField + i, GetAmount(), apply);
+
if (Guardian* pet = target->ToPlayer()->GetGuardianPet())
pet->UpdateAttackPowerAndDamage();
}
@@ -4492,14 +4116,7 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
if (abs(spellGroupVal) >= abs(GetAmount()))
return;
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- for (int i = 0; i < MAX_ATTACK; ++i)
- if (Item* item = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), false))
- target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(item, WeaponAttackType(i), this, apply);
- }
-
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER))
+ if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
{
if (spellGroupVal)
{
@@ -4507,22 +4124,25 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply);
}
+
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
+ }
- if (Player* player = target->ToPlayer())
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ {
+ for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
- if (spellGroupVal)
- player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(spellGroupVal), !apply);
+ if (GetMiscValue() & (1 << i))
+ {
+ if (spellGroupVal)
+ target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(spellGroupVal), !apply);
- player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(GetAmount()), apply);
+ target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(GetAmount()), apply);
+ }
}
}
- else
- {
- // done in Player::_ApplyWeaponDependentAuraMods for SPELL_SCHOOL_MASK_NORMAL && EquippedItemClass != -1 and also for wand case
- }
}
void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -5446,13 +5066,11 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
{
// Master of Subtlety
case 31666:
- if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
- target->RemoveAurasDueToSpell(31665);
+ target->RemoveAurasDueToSpell(31665);
break;
// Overkill
case 58428:
- if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
- target->RemoveAurasDueToSpell(58427);
+ target->RemoveAurasDueToSpell(58427);
break;
}
break;
@@ -5849,8 +5467,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
}
}
- uint32 absorb = 0;
- uint32 resist = 0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
// AOE spells are not affected by the new periodic system.
@@ -5945,13 +5561,16 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
int32 dmg = damage;
-
if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ caster->ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
- caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
+ DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
+ caster->CalcAbsorbResist(damageInfo);
+ damage = damageInfo.GetDamage();
+ uint32 absorb = damageInfo.GetAbsorb();
+ uint32 resist = damageInfo.GetResist();
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u absorb is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
@@ -5960,10 +5579,12 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
// Set trigger flag
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
- uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
- damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
+ uint32 hitMask = damageInfo.GetHitMask();
if (damage)
+ {
+ hitMask |= crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+ }
int32 overkill = damage - target->GetHealth();
if (overkill < 0)
@@ -5972,7 +5593,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo);
- DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
@@ -5993,8 +5613,6 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE)
return;
- uint32 absorb = 0;
- uint32 resist = 0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
@@ -6009,6 +5627,9 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
else
damage = std::max(int32(damage * GetDonePct()), 0);
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(GetSpellInfo()->Id, damage);
+
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
// Calculate armor mitigation
@@ -6020,12 +5641,14 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
}
if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
+ {
if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
{
damage = uint32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
if (caster->GetTypeId() != TYPEID_PLAYER)
damage = uint32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
}
+ }
bool crit = false;
@@ -6037,29 +5660,33 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
int32 dmg = damage;
if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ caster->ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
- caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo);
+ DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
+ caster->CalcAbsorbResist(damageInfo);
+ uint32 absorb = damageInfo.GetAbsorb();
+ uint32 resist = damageInfo.GetResist();
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
+ // SendSpellNonMeleeDamageLog expects non-absorbed/non-resisted damage
caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit);
+ damage = damageInfo.GetDamage();
// Set trigger flag
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
- uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
- damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
+ uint32 hitMask = damageInfo.GetHitMask();
if (damage)
+ {
+ hitMask |= crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+ }
if (caster->IsAlive())
- {
- DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
- }
int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
if (caster->IsAlive())
@@ -6478,6 +6105,12 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv
Unit* target = aurApp->GetTarget();
Unit* triggerTarget = eventInfo.GetProcTarget();
+ if (triggerTarget->HasUnitState(UNIT_STATE_ISOLATED) || triggerTarget->IsImmunedToDamage(GetSpellInfo()))
+ {
+ SendTickImmune(triggerTarget, target);
+ return;
+ }
+
SpellNonMeleeDamage damageInfo(target, triggerTarget, GetId(), GetSpellInfo()->SchoolMask);
uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE);
damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 2bfdde97b4b..05bfe7c0534 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -198,7 +198,7 @@ class TC_GAME_API AuraEffect
void HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// immunity
- void HandleModStateImmunityMask(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleModMechanicImmunityMask(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModEffectImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModStateImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 970bb93b271..45ea44f1dfb 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -360,7 +360,7 @@ m_procCooldown(std::chrono::steady_clock::time_point::min())
AuraScript* Aura::GetScriptByName(std::string const& scriptName) const
{
- for (std::list<AuraScript*>::const_iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
+ for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
if ((*itr)->_GetScriptName()->compare(scriptName) == 0)
return *itr;
return NULL;
@@ -381,12 +381,10 @@ void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount)
Aura::~Aura()
{
// unload scripts
- while (!m_loadedScripts.empty())
+ for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
{
- std::list<AuraScript*>::iterator itr = m_loadedScripts.begin();
(*itr)->_Unload();
delete (*itr);
- m_loadedScripts.erase(itr);
}
// free effects memory
@@ -987,6 +985,10 @@ bool Aura::CanBeSaved() const
if (IsUsingCharges() && !GetCharges())
return false;
+ // don't save permanent auras triggered by items, they'll be recasted on login if necessary
+ if (GetCastItemGUID() && IsPermanent())
+ return false;
+
return true;
}
@@ -1291,20 +1293,27 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_PRIEST:
if (!caster)
break;
+
// Devouring Plague
- if (GetSpellInfo()->SpellFamilyFlags[0] & 0x02000000 && GetEffect(0))
+ if (GetSpellInfo()->SpellFamilyFlags[0] & 0x02000000)
{
+ AuraEffect const* devouringPlague = GetEffect(EFFECT_0);
+ if (!devouringPlague)
+ break;
+
// Improved Devouring Plague
if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
{
- uint32 damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), DOT);
- damage *= caster->SpellDamagePctDone(target, GetSpellInfo(), SPELL_DIRECT_DAMAGE);
+ int32 damage = (devouringPlague->GetAmount() + devouringPlague->GetBonusAmount()) * devouringPlague->GetDonePct();
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(GetSpellInfo()->Id, damage);
+
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
- int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * int32(damage) / 100;
- int32 heal = int32(CalculatePct(basepoints0, 15));
- caster->CastCustomSpell(target, 63675, &basepoints0, NULL, NULL, true, NULL, GetEffect(0));
- caster->CastCustomSpell(caster, 75999, &heal, NULL, NULL, true, NULL, GetEffect(0));
+ int32 basepoints0 = CalculatePct(devouringPlague->GetTotalTicks() * static_cast<int32>(damage), aurEff->GetAmount());
+ int32 heal = CalculatePct(basepoints0, 15);
+ caster->CastCustomSpell(63675, SPELLVALUE_BASE_POINT0, basepoints0, target, true, nullptr, devouringPlague);
+ caster->CastCustomSpell(75999, SPELLVALUE_BASE_POINT0, heal, (Unit*)nullptr, true, nullptr, devouringPlague);
}
}
// Power Word: Shield
@@ -1591,6 +1600,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
target->CastSpell(target, 31666, true);
else
{
+ // Remove counter aura
+ target->RemoveAurasDueToSpell(31666);
+
int32 basepoints0 = aurEff->GetAmount();
target->CastCustomSpell(target, 31665, &basepoints0, NULL, NULL, true);
}
@@ -1601,7 +1613,12 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (!apply)
target->CastSpell(target, 58428, true);
else
+ {
+ // Remove counter aura
+ target->RemoveAurasDueToSpell(58428);
+
target->CastSpell(target, 58427, true);
+ }
}
break;
}
@@ -1865,13 +1882,34 @@ void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInf
AddProcCooldown(now + procEntry->Cooldown);
}
-uint8 Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const
+uint8 Aura::GetProcEffectMask(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const
{
SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId());
// only auras with spell proc entry can trigger proc
if (!procEntry)
return 0;
+ // check spell triggering us
+ if (Spell const* spell = eventInfo.GetProcSpell())
+ {
+ // Do not allow auras to proc from effect triggered from itself
+ if (spell->IsTriggeredByAura(m_spellInfo))
+ return 0;
+
+ // check if aura can proc when spell is triggered (exception for hunter auto shot & wands)
+ if (spell->IsTriggered() && !(procEntry->AttributesMask & PROC_ATTR_TRIGGERED_CAN_PROC) && !(eventInfo.GetTypeMask() & AUTO_ATTACK_PROC_FLAG_MASK))
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED))
+ return 0;
+ }
+
+ // check don't break stealth attr present
+ if (m_spellInfo->HasAura(SPELL_AURA_MOD_STEALTH))
+ {
+ if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
+ if (spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
+ return 0;
+ }
+
// check if we have charges to proc with
if (IsUsingCharges())
{
@@ -1889,16 +1927,9 @@ uint8 Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& event
return 0;
// do checks against db data
- if (!sSpellMgr->CanSpellTriggerProcOnEvent(*procEntry, eventInfo))
+ if (!SpellMgr::CanSpellTriggerProcOnEvent(*procEntry, eventInfo))
return 0;
- // check if aura can proc when spell is triggered (exception for hunter auto shot & wands)
- if (!(procEntry->AttributesMask & PROC_ATTR_TRIGGERED_CAN_PROC) && !(eventInfo.GetTypeMask() & AUTO_ATTACK_PROC_FLAG_MASK))
- if (Spell const* spell = eventInfo.GetProcSpell())
- if (spell->IsTriggered())
- if (!GetSpellInfo()->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED))
- return 0;
-
// do checks using conditions table
if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId(), eventInfo.GetActor(), eventInfo.GetActionTarget()))
return 0;
@@ -1909,11 +1940,11 @@ uint8 Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& event
return 0;
// At least one effect has to pass checks to proc aura
- uint8 procEffectMask = 0;
+ uint8 procEffectMask = aurApp->GetEffectMask();
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (aurApp->HasEffect(i))
- if (GetEffect(i)->CheckEffectProc(aurApp, eventInfo))
- procEffectMask |= (1 << i);
+ if (procEffectMask & (1 << i))
+ if ((procEntry->AttributesMask & (PROC_ATTR_DISABLE_EFF_0 << i)) || !GetEffect(i)->CheckEffectProc(aurApp, eventInfo))
+ procEffectMask &= ~(1 << i);
if (!procEffectMask)
return 0;
@@ -2024,30 +2055,21 @@ void Aura::_DeleteRemovedApplications()
void Aura::LoadScripts()
{
- sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts);
- for (std::list<AuraScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end();)
+ sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts, this);
+ for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
{
- if (!(*itr)->_Load(this))
- {
- std::list<AuraScript*>::iterator bitr = itr;
- ++itr;
- delete (*bitr);
- m_loadedScripts.erase(bitr);
- continue;
- }
TC_LOG_DEBUG("spells", "Aura::LoadScripts: Script `%s` for aura `%u` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id);
(*itr)->Register();
- ++itr;
}
}
bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target)
{
bool result = true;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET);
- std::list<AuraScript::CheckAreaTargetHandler>::iterator hookItrEnd = (*scritr)->DoCheckAreaTarget.end(), hookItr = (*scritr)->DoCheckAreaTarget.begin();
+ auto hookItrEnd = (*scritr)->DoCheckAreaTarget.end(), hookItr = (*scritr)->DoCheckAreaTarget.begin();
for (; hookItr != hookItrEnd; ++hookItr)
result &= hookItr->Call(*scritr, target);
@@ -2058,10 +2080,10 @@ bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target)
void Aura::CallScriptDispel(DispelInfo* dispelInfo)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL);
- std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin();
+ auto hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin();
for (; hookItr != hookItrEnd; ++hookItr)
hookItr->Call(*scritr, dispelInfo);
@@ -2071,10 +2093,10 @@ void Aura::CallScriptDispel(DispelInfo* dispelInfo)
void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL);
- std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin();
+ auto hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin();
for (; hookItr != hookItrEnd; ++hookItr)
hookItr->Call(*scritr, dispelInfo);
@@ -2085,10 +2107,10 @@ void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo)
bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode)
{
bool preventDefault = false;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp);
- std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin();
+ auto effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, mode);
@@ -2105,10 +2127,10 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplicati
bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode)
{
bool preventDefault = false;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp);
- std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin();
+ auto effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, mode);
@@ -2123,10 +2145,10 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplicat
void Aura::CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp);
- std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin();
+ auto effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, mode);
@@ -2137,10 +2159,10 @@ void Aura::CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraAppl
void Aura::CallScriptAfterEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp);
- std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin();
+ auto effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, mode);
@@ -2152,10 +2174,10 @@ void Aura::CallScriptAfterEffectRemoveHandlers(AuraEffect const* aurEff, AuraApp
bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp)
{
bool preventDefault = false;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp);
- std::list<AuraScript::EffectPeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin();
+ auto effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff);
@@ -2171,10 +2193,10 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplic
void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC);
- std::list<AuraScript::EffectUpdatePeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin();
+ auto effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff);
@@ -2185,10 +2207,10 @@ void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff)
void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 & amount, bool & canBeRecalculated)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
- std::list<AuraScript::EffectCalcAmountHandler>::iterator effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin();
+ auto effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, amount, canBeRecalculated);
@@ -2199,10 +2221,10 @@ void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 &
void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool & isPeriodic, int32 & amplitude)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
- std::list<AuraScript::EffectCalcPeriodicHandler>::iterator effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin();
+ auto effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, isPeriodic, amplitude);
@@ -2213,10 +2235,10 @@ void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool &
void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier* & spellMod)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
- std::list<AuraScript::EffectCalcSpellModHandler>::iterator effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin();
+ auto effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, spellMod);
@@ -2227,10 +2249,10 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellM
void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool& defaultPrevented)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
- std::list<AuraScript::EffectAbsorbHandler>::iterator effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin();
+ auto effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
@@ -2245,10 +2267,10 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co
void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
- std::list<AuraScript::EffectAbsorbHandler>::iterator effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin();
+ auto effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
@@ -2259,10 +2281,10 @@ void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplicati
void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & /*defaultPrevented*/)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp);
- std::list<AuraScript::EffectManaShieldHandler>::iterator effEndItr = (*scritr)->OnEffectManaShield.end(), effItr = (*scritr)->OnEffectManaShield.begin();
+ auto effEndItr = (*scritr)->OnEffectManaShield.end(), effItr = (*scritr)->OnEffectManaShield.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
@@ -2273,10 +2295,10 @@ void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplicatio
void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp);
- std::list<AuraScript::EffectManaShieldHandler>::iterator effEndItr = (*scritr)->AfterEffectManaShield.end(), effItr = (*scritr)->AfterEffectManaShield.begin();
+ auto effEndItr = (*scritr)->AfterEffectManaShield.end(), effItr = (*scritr)->AfterEffectManaShield.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
@@ -2287,10 +2309,10 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli
void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp);
- std::list<AuraScript::EffectSplitHandler>::iterator effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin();
+ auto effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, dmgInfo, splitAmount);
@@ -2302,10 +2324,10 @@ void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication con
bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool result = true;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
- std::list<AuraScript::CheckProcHandler>::iterator hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
+ auto hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
result &= hookItr->Call(*scritr, eventInfo);
@@ -2318,10 +2340,10 @@ bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventI
bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool prepare = true;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
- std::list<AuraScript::AuraProcHandler>::iterator effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
+ auto effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
for (; effItr != effEndItr; ++effItr)
effItr->Call(*scritr, eventInfo);
@@ -2337,10 +2359,10 @@ bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEven
bool Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool handled = false;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
- std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
+ auto hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
hookItr->Call(*scritr, eventInfo);
@@ -2353,10 +2375,10 @@ bool Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo&
void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
- std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
+ auto hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
hookItr->Call(*scritr, eventInfo);
@@ -2367,10 +2389,10 @@ void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventI
bool Aura::CallScriptCheckEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool result = true;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC, aurApp);
- std::list<AuraScript::CheckEffectProcHandler>::iterator hookItrEnd = (*scritr)->DoCheckEffectProc.end(), hookItr = (*scritr)->DoCheckEffectProc.begin();
+ auto hookItrEnd = (*scritr)->DoCheckEffectProc.end(), hookItr = (*scritr)->DoCheckEffectProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
if (hookItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
result &= hookItr->Call(*scritr, aurEff, eventInfo);
@@ -2384,10 +2406,10 @@ bool Aura::CallScriptCheckEffectProcHandlers(AuraEffect const* aurEff, AuraAppli
bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool preventDefault = false;
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
- std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
+ auto effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, eventInfo);
@@ -2402,10 +2424,10 @@ bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplicatio
void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
- for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
- std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
+ auto effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
for (; effItr != effEndItr; ++effItr)
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
effItr->Call(*scritr, aurEff, eventInfo);
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index a6dd29f11d0..1533746893a 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -204,7 +204,7 @@ class TC_GAME_API Aura
bool IsUsingCharges() const { return m_isUsingCharges; }
void SetUsingCharges(bool val) { m_isUsingCharges = val; }
void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now);
- uint8 IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const;
+ uint8 GetProcEffectMask(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const;
float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
void TriggerProcOnEvent(uint8 procEffectMask, AuraApplication* aurApp, ProcEventInfo& eventInfo);
@@ -238,9 +238,11 @@ class TC_GAME_API Aura
AuraScript* GetScriptByName(std::string const& scriptName) const;
- std::list<AuraScript*> m_loadedScripts;
+ std::vector<AuraScript*> m_loadedScripts;
+
private:
void _DeleteRemovedApplications();
+
protected:
SpellInfo const* const m_spellInfo;
ObjectGuid const m_casterGuid;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index a83a5a122ad..c082c0a7584 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -626,12 +626,10 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO
Spell::~Spell()
{
// unload scripts
- while (!m_loadedScripts.empty())
+ for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
{
- std::list<SpellScript*>::iterator itr = m_loadedScripts.begin();
(*itr)->_Unload();
delete (*itr);
- m_loadedScripts.erase(itr);
}
if (m_referencedFromCurrentSpell && m_selfContainer && *m_selfContainer == this)
@@ -647,7 +645,8 @@ Spell::~Spell()
delete m_spellValue;
- CheckEffectExecuteData();
+ // missing cleanup somewhere, mem leaks so let's crash
+ AssertEffectExecuteData();
}
void Spell::InitExplicitTargets(SpellCastTargets const& targets)
@@ -1119,8 +1118,14 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
SpellTargetObjectTypes objectType = targetType.GetObjectType();
SpellTargetCheckTypes selectionType = targetType.GetCheckType();
ConditionContainer* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
- float coneAngle = float(M_PI) / 2;
- float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
+ float coneAngle = float(M_PI) / 2.f;
+
+ float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+ // Workaround for some spells that don't have RadiusEntry set in dbc (but SpellRange instead)
+ if (G3D::fuzzyEq(radius, 0.f))
+ radius = m_spellInfo->GetMaxRange(m_spellInfo->IsPositiveEffect(effIndex), m_caster, this);
+
+ radius *= m_spellValue->RadiusMod;
if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
{
@@ -1206,7 +1211,13 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
return;
}
std::list<WorldObject*> targets;
- float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
+ float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+ // Workaround for some spells that don't have RadiusEntry set in dbc (but SpellRange instead)
+ if (G3D::fuzzyEq(radius, 0.f))
+ radius = m_spellInfo->GetMaxRange(m_spellInfo->IsPositiveEffect(effIndex), m_caster, this);
+
+ radius *= m_spellValue->RadiusMod;
+
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
@@ -1992,11 +2003,17 @@ void Spell::prepareDataForTriggerSystem()
// Hunter trap spells - activation proc for Lock and Load, Entrapment and Misdirection
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER &&
- (m_spellInfo->SpellFamilyFlags[0] & 0x18 || // Freezing and Frost Trap, Freezing Arrow
- m_spellInfo->Id == 57879 || // Snake Trap - done this way to avoid double proc
- m_spellInfo->SpellFamilyFlags[2] & 0x00024000)) // Explosive and Immolation Trap
+ (m_spellInfo->SpellFamilyFlags[0] & 0x18 || // Freezing and Frost Trap, Freezing Arrow
+ m_spellInfo->Id == 57879 || // Snake Trap - done this way to avoid double proc
+ m_spellInfo->SpellFamilyFlags[2] & 0x00024000)) // Explosive and Immolation Trap
+ {
m_procAttacker |= PROC_FLAG_DONE_TRAP_ACTIVATION;
+ // also fill up other flags (DoAllEffectOnTarget only fills up flag if both are not set)
+ m_procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
+ m_procVictim |= PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG;
+ }
+
// Hellfire Effect - trigger as DOT
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags[0] & 0x00000040)
{
@@ -2050,7 +2067,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
return;
if (checkIfValid)
- if (m_spellInfo->CheckTarget(m_caster, target, implicit) != SPELL_CAST_OK)
+ if (m_spellInfo->CheckTarget(m_caster, target, implicit || m_caster->GetEntry() == WORLD_TRIGGER) != SPELL_CAST_OK) // skip stealth checks for GO casts
return;
// Check for effect immune skip if immuned
@@ -2308,7 +2325,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
m_spellAura = nullptr; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied
// Spells with this flag cannot trigger if effect is cast on self
- bool canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2);
+ bool const canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2);
Unit* spellHitTarget = nullptr;
if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
@@ -2352,7 +2369,19 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (m_damage > 0)
positive = false;
else if (!m_healing)
- positive = m_spellInfo->IsPositive();
+ {
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (!(target->effectMask & (1 << i)))
+ continue;
+
+ if (!m_spellInfo->IsPositiveEffect(i))
+ {
+ positive = false;
+ break;
+ }
+ }
+ }
switch (m_spellInfo->DmgClass)
{
@@ -2413,15 +2442,29 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// Fill base damage struct (unitTarget - is real spell target)
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask);
- // Add bonuses and fill damageInfo struct
- caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit);
- caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
+ // Check damage immunity
+ if (unitTarget->IsImmunedToDamage(m_spellInfo))
+ {
+ hitMask = PROC_HIT_IMMUNE;
+ m_damage = 0;
+
+ // no packet found in sniffs
+ }
+ else
+ {
+ // Add bonuses and fill damageInfo struct
+ caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit);
+ caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
- // Send log damage message to client
- caster->SendSpellNonMeleeDamageLog(&damageInfo);
+ // Send log damage message to client
+ caster->SendSpellNonMeleeDamageLog(&damageInfo);
- hitMask |= createProcHitMask(&damageInfo, missInfo);
- procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+ hitMask |= createProcHitMask(&damageInfo, missInfo);
+ procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+
+ m_damage = damageInfo.damage;
+ caster->DealSpellDamage(&damageInfo, true);
+ }
// Do triggers for unit
if (canEffectTrigger)
@@ -2433,10 +2476,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
caster->ToPlayer()->CastItemCombatSpell(spellDamageInfo);
}
-
- m_damage = damageInfo.damage;
-
- caster->DealSpellDamage(&damageInfo, true);
}
// Passive spell hits/misses or active spells only misses (only triggers)
else
@@ -2502,7 +2541,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
return SPELL_MISS_EVADE;
// For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
- if (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))
+ if (m_spellInfo->Speed && unit->IsImmunedToSpell(m_spellInfo))
return SPELL_MISS_IMMUNE;
// disable effects to which unit is immune
@@ -2551,12 +2590,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
return SPELL_MISS_EVADE;
if (m_caster->_IsValidAttackTarget(unit, m_spellInfo))
- {
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
-
- if (!m_spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
- unit->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
- }
else if (m_caster->IsFriendlyTo(unit))
{
// for delayed spells ignore negative spells (after duel end) for friendly targets
@@ -2720,8 +2754,8 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
// info confirmed with retail sniffs of permafrost and shadow weaving
if (!m_hitTriggerSpells.empty())
{
- int _duration = 0;
- for (HitTriggerSpellList::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
+ int32 _duration = 0;
+ for (auto i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
{
if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
{
@@ -2933,7 +2967,8 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
if ((_triggeredCastFlags & TRIGGERED_IGNORE_COMBO_POINTS) || m_CastItem || !m_caster->m_playerMovingMe)
m_needComboPoints = false;
- SpellCastResult result = CheckCast(true);
+ uint32 param1 = 0, param2 = 0;
+ SpellCastResult result = CheckCast(true, &param1, &param2);
if (result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
{
// Periodic auras should be interrupted when aura triggers a spell which can't be cast
@@ -2954,7 +2989,10 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
}
- SendCastResult(result);
+ if (param1 || param2)
+ SendCastResult(result, &param1, &param2);
+ else
+ SendCastResult(result);
finish(false);
return;
@@ -2979,7 +3017,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
m_casttime = m_spellInfo->CalcCastTime(this);
if (m_caster->GetTypeId() == TYPEID_UNIT && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) // _UNIT actually means creature. for some reason.
- if (!(IsNextMeleeSwingSpell() || IsAutoRepeat() || _triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING))
+ if (!(m_spellInfo->IsNextMeleeSwingSpell() || IsAutoRepeat() || (_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING)))
{
if (m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget());
@@ -2992,8 +3030,8 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
// (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && !(m_caster->IsCharmed() && m_caster->GetCharmerGUID().IsCreature()) && m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
{
- // 1. Is a channel spell, 2. Has no casttime, 3. And has flag to allow movement during channel
- if (!(m_spellInfo->IsChanneled() && !m_casttime && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))
+ // 1. Has casttime, 2. Or doesn't have flag to allow movement during channel
+ if (m_casttime || !m_spellInfo->IsMoveAllowedChannel())
{
SendCastResult(SPELL_FAILED_MOVING);
finish(false);
@@ -3141,10 +3179,11 @@ void Spell::cast(bool skipCheck)
// skip check if done already (for instant cast spells for example)
if (!skipCheck)
{
- SpellCastResult castResult = CheckCast(false);
+ uint32 param1 = 0, param2 = 0;
+ SpellCastResult castResult = CheckCast(false, &param1, &param2);
if (castResult != SPELL_CAST_OK)
{
- SendCastResult(castResult);
+ SendCastResult(castResult, &param1, &param2);
SendInterrupted(0);
//restore spell mods
if (m_caster->GetTypeId() == TYPEID_PLAYER)
@@ -3548,7 +3587,7 @@ void Spell::update(uint32 difftime)
(m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))))
{
// don't cancel for melee, autorepeat, triggered and instant spells
- if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))
+ if (!m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->IsMoveAllowedChannel()))
{
// if charmed by creature, trust the AI not to cheat and allow the cast to proceed
// @todo this is a hack, "creature" movesplines don't differentiate turning/moving right now
@@ -3570,7 +3609,7 @@ void Spell::update(uint32 difftime)
m_timer -= difftime;
}
- if (m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat())
+ if (m_timer == 0 && !m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat())
// don't CheckCast for instant spells - done in spell::prepare, skip duplicate checks, needed for range checks for example
cast(!m_casttime);
break;
@@ -3690,7 +3729,7 @@ void Spell::finish(bool ok)
m_caster->AttackStop();
}
-void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError)
+void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/)
{
data << uint8(castCount); // single cast or multi 2.3 (0/1)
data << uint32(spellInfo->Id);
@@ -3698,115 +3737,185 @@ void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo con
switch (result)
{
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
- data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id
+ if (param1)
+ data << uint32(*param1);
+ else
+ data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id
break;
case SPELL_FAILED_REQUIRES_AREA: // AreaTable.dbc id
- // hardcode areas limitation case
- switch (spellInfo->Id)
+ if (param1)
+ data << uint32(*param1);
+ else
{
- case 41617: // Cenarion Mana Salve
- case 41619: // Cenarion Healing Salve
- data << uint32(3905);
- break;
- case 41618: // Bottled Nethergon Energy
- case 41620: // Bottled Nethergon Vapor
- data << uint32(3842);
- break;
- case 45373: // Bloodberry Elixir
- data << uint32(4075);
- break;
- default: // default case (don't must be)
- data << uint32(0);
- break;
+ // hardcode areas limitation case
+ switch (spellInfo->Id)
+ {
+ case 41617: // Cenarion Mana Salve
+ case 41619: // Cenarion Healing Salve
+ data << uint32(3905);
+ break;
+ case 41618: // Bottled Nethergon Energy
+ case 41620: // Bottled Nethergon Vapor
+ data << uint32(3842);
+ break;
+ case 45373: // Bloodberry Elixir
+ data << uint32(4075);
+ break;
+ default: // default case (don't must be)
+ data << uint32(0);
+ break;
+ }
}
break;
case SPELL_FAILED_TOTEMS:
- if (spellInfo->Totem[0])
- data << uint32(spellInfo->Totem[0]);
- if (spellInfo->Totem[1])
- data << uint32(spellInfo->Totem[1]);
+ if (param1)
+ {
+ data << uint32(*param1);
+ if (param2)
+ data << uint32(*param2);
+ }
+ else
+ {
+ if (spellInfo->Totem[0])
+ data << uint32(spellInfo->Totem[0]);
+ if (spellInfo->Totem[1])
+ data << uint32(spellInfo->Totem[1]);
+ }
break;
case SPELL_FAILED_TOTEM_CATEGORY:
- if (spellInfo->TotemCategory[0])
- data << uint32(spellInfo->TotemCategory[0]);
- if (spellInfo->TotemCategory[1])
- data << uint32(spellInfo->TotemCategory[1]);
+ if (param1)
+ {
+ data << uint32(*param1);
+ if (param2)
+ data << uint32(*param2);
+ }
+ else
+ {
+ if (spellInfo->TotemCategory[0])
+ data << uint32(spellInfo->TotemCategory[0]);
+ if (spellInfo->TotemCategory[1])
+ data << uint32(spellInfo->TotemCategory[1]);
+ }
break;
case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
case SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND:
case SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND:
- data << uint32(spellInfo->EquippedItemClass);
- data << uint32(spellInfo->EquippedItemSubClassMask);
+ if (param1 && param2)
+ {
+ data << uint32(*param1);
+ data << uint32(*param2);
+ }
+ else
+ {
+ data << uint32(spellInfo->EquippedItemClass);
+ data << uint32(spellInfo->EquippedItemSubClassMask);
+ }
break;
case SPELL_FAILED_TOO_MANY_OF_ITEM:
{
- uint32 item = 0;
- for (int8 eff = 0; eff < MAX_SPELL_EFFECTS; eff++)
- if (spellInfo->Effects[eff].ItemType)
- item = spellInfo->Effects[eff].ItemType;
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item);
- if (proto && proto->ItemLimitCategory)
- data << uint32(proto->ItemLimitCategory);
- break;
+ if (param1)
+ data << uint32(*param1);
+ else
+ {
+ uint32 item = 0;
+ for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS && !item; ++effIndex)
+ if (uint32 itemType = spellInfo->Effects[effIndex].ItemType)
+ item = itemType;
+
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item);
+ if (proto && proto->ItemLimitCategory)
+ data << uint32(proto->ItemLimitCategory);
+ }
+ break;
}
case SPELL_FAILED_CUSTOM_ERROR:
data << uint32(customError);
break;
case SPELL_FAILED_REAGENTS:
{
- uint32 missingItem = 0;
- for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
+ if (param1)
+ data << uint32(*param1);
+ else
{
- if (spellInfo->Reagent[i] <= 0)
- continue;
+ uint32 missingItem = 0;
+ for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
+ {
+ if (spellInfo->Reagent[i] <= 0)
+ continue;
- uint32 itemid = spellInfo->Reagent[i];
- uint32 itemcount = spellInfo->ReagentCount[i];
+ uint32 itemid = spellInfo->Reagent[i];
+ uint32 itemcount = spellInfo->ReagentCount[i];
- if (!caster->HasItemCount(itemid, itemcount))
- {
- missingItem = itemid;
- break;
+ if (!caster->HasItemCount(itemid, itemcount))
+ {
+ missingItem = itemid;
+ break;
+ }
}
- }
- data << uint32(missingItem); // first missing item
+ data << uint32(missingItem); // first missing item
+ }
break;
}
case SPELL_FAILED_PREVENTED_BY_MECHANIC:
- data << uint32(spellInfo->Mechanic);
+ if (param1)
+ data << uint32(*param1);
+ else
+ data << uint32(spellInfo->Mechanic);
break;
case SPELL_FAILED_NEED_EXOTIC_AMMO:
- data << uint32(spellInfo->EquippedItemSubClassMask);
+ if (param1)
+ data << uint32(*param1);
+ else
+ data << uint32(spellInfo->EquippedItemSubClassMask);
break;
case SPELL_FAILED_NEED_MORE_ITEMS:
- data << uint32(0); // Item entry
- data << uint32(0); // Count
+ if (param1 && param2)
+ {
+ data << uint32(*param1);
+ data << uint32(*param2);
+ }
+ else
+ {
+ data << uint32(0); // Item entry
+ data << uint32(0); // Count
+ }
break;
case SPELL_FAILED_MIN_SKILL:
- data << uint32(0); // SkillLine.dbc Id
- data << uint32(0); // Amount
+ if (param1 && param2)
+ {
+ data << uint32(*param1);
+ data << uint32(*param2);
+ }
+ else
+ {
+ data << uint32(0); // SkillLine.dbc Id
+ data << uint32(0); // Amount
+ }
break;
case SPELL_FAILED_FISHING_TOO_LOW:
- data << uint32(0); // Skill level
+ if (param1)
+ data << uint32(*param1);
+ else
+ data << uint32(0); // Skill level
break;
default:
break;
}
}
-void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/)
+void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/)
{
if (result == SPELL_CAST_OK)
return;
WorldPacket data(SMSG_CAST_FAILED, 1 + 4 + 1);
- WriteCastResultInfo(data, caster, spellInfo, castCount, result, customError);
+ WriteCastResultInfo(data, caster, spellInfo, castCount, result, customError, param1, param2);
- caster->GetSession()->SendPacket(&data);
+ caster->SendDirectMessage(&data);
}
-void Spell::SendCastResult(SpellCastResult result)
+void Spell::SendCastResult(SpellCastResult result, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) const
{
if (result == SPELL_CAST_OK)
return;
@@ -3814,13 +3923,13 @@ void Spell::SendCastResult(SpellCastResult result)
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return;
- if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
+ if (m_caster->ToPlayer()->IsLoading()) // don't send cast results at loading time
return;
if (_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR)
result = SPELL_FAILED_DONT_REPORT;
- SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError);
+ SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError, param1, param2);
}
void Spell::SendPetCastResult(SpellCastResult result)
@@ -4469,7 +4578,7 @@ void Spell::TakeAmmo()
}
}
-SpellCastResult Spell::CheckRuneCost(uint32 runeCostID)
+SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) const
{
if (m_spellInfo->PowerType != POWER_RUNE || !runeCostID)
return SPELL_CAST_OK;
@@ -4494,7 +4603,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 runeCostID)
{
runeCost[i] = src->RuneCost[i];
if (Player* modOwner = m_caster->GetSpellModOwner())
- modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], this);
+ modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], const_cast<Spell*>(this));
}
runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later
@@ -4730,7 +4839,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT
}
}
-SpellCastResult Spell::CheckCast(bool strict)
+SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/)
{
// check death state
if (!m_caster->IsAlive() && !m_spellInfo->IsPassive() && !(m_spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD) || (IsTriggered() && !m_triggeredByAuraSpell)))
@@ -4793,13 +4902,15 @@ SpellCastResult Spell::CheckCast(bool strict)
bool checkForm = true;
// Ignore form req aura
Unit::AuraEffectList const& ignore = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT);
- for (Unit::AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
+ for (AuraEffect const* aurEff : ignore)
{
- if (!(*i)->IsAffectedOnSpell(m_spellInfo))
+ if (!aurEff->IsAffectedOnSpell(m_spellInfo))
continue;
+
checkForm = false;
break;
}
+
if (checkForm)
{
// Cannot be used in this stance/form
@@ -4895,14 +5006,18 @@ SpellCastResult Spell::CheckCast(bool strict)
if (!(m_spellInfo->IsPassive() && (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget() == m_caster)))
{
// Check explicit target for m_originalCaster - todo: get rid of such workarounds
- SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_originalCaster ? m_originalCaster : m_caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());
+ Unit* caster = m_caster;
+ if (m_originalCaster && m_caster->GetEntry() != WORLD_TRIGGER) // Do a simplified check for gameobject casts
+ caster = m_originalCaster;
+
+ SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());
if (castResult != SPELL_CAST_OK)
return castResult;
}
if (Unit* target = m_targets.GetUnitTarget())
{
- SpellCastResult castResult = m_spellInfo->CheckTarget(m_caster, target, false);
+ SpellCastResult castResult = m_spellInfo->CheckTarget(m_caster, target, m_caster->GetEntry() == WORLD_TRIGGER); // skip stealth checks for GO casts
if (castResult != SPELL_CAST_OK)
return castResult;
@@ -5003,7 +5118,7 @@ SpellCastResult Spell::CheckCast(bool strict)
// always (except passive spells) check items (only player related checks)
if (!m_spellInfo->IsPassive())
{
- castResult = CheckItems();
+ castResult = CheckItems(param1, param2);
if (castResult != SPELL_CAST_OK)
return castResult;
}
@@ -5023,7 +5138,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURAS))
{
- castResult = CheckCasterAuras();
+ castResult = CheckCasterAuras(param1);
if (castResult != SPELL_CAST_OK)
return castResult;
}
@@ -5037,6 +5152,7 @@ SpellCastResult Spell::CheckCast(bool strict)
bool hasNonDispelEffect = false;
uint32 dispelMask = 0;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL)
{
if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START))
@@ -5052,6 +5168,7 @@ SpellCastResult Spell::CheckCast(bool strict)
hasNonDispelEffect = true;
break;
}
+ }
if (!hasNonDispelEffect && !hasDispellableAura && dispelMask && !IsTriggered())
{
@@ -5166,7 +5283,7 @@ SpellCastResult Spell::CheckCast(bool strict)
m_caster->RemoveMovementImpairingAuras();
}
- if (m_caster->HasUnitState(UNIT_STATE_ROOT))
+ if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURAS) && m_caster->HasUnitState(UNIT_STATE_ROOT))
return SPELL_FAILED_ROOTED;
if (GetSpellInfo()->NeedsExplicitUnitTarget())
@@ -5635,139 +5752,114 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
return CheckCast(true);
}
-SpellCastResult Spell::CheckCasterAuras() const
+SpellCastResult Spell::CheckCasterAuras(uint32* param1) const
{
// spells totally immuned to caster auras (wsg flag drop, give marks etc)
if (m_spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CASTER_AURAS))
return SPELL_CAST_OK;
- uint8 school_immune = 0;
- uint32 mechanic_immune = 0;
- uint32 dispel_immune = 0;
-
- // Check if the spell grants school or mechanic immunity.
- // We use bitmasks so the loop is done only once and not on every aura check below.
- if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ bool usableWhileStunned = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED);
+ bool usableWhileFeared = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED);
+ bool usableWhileConfused = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED);
+ if (m_spellInfo->HasAttribute(SPELL_ATTR7_USABLE_IN_STUN_FEAR_CONFUSION))
{
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_SCHOOL_IMMUNITY)
- school_immune |= uint32(m_spellInfo->Effects[i].MiscValue);
- else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MECHANIC_IMMUNITY)
- mechanic_immune |= 1 << uint32(m_spellInfo->Effects[i].MiscValue);
- else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_DISPEL_IMMUNITY)
- dispel_immune |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue));
- }
- // immune movement impairment and loss of control
- if (m_spellInfo->Id == 42292 || m_spellInfo->Id == 59752 || m_spellInfo->Id == 19574 || m_spellInfo->Id == 53490)
- mechanic_immune = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+ usableWhileStunned = true;
+ usableWhileFeared = true;
+ usableWhileConfused = true;
}
- bool usableInStun = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED);
-
// Glyph of Pain Suppression
// there is no other way to handle it
if (m_spellInfo->Id == 33206 && !m_caster->HasAura(63248))
- usableInStun = false;
+ usableWhileStunned = false;
// Check whether the cast should be prevented by any state you might have.
- SpellCastResult prevented_reason = SPELL_CAST_OK;
- // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out
- uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state
- if (unitflag & UNIT_FLAG_STUNNED)
- {
- // spell is usable while stunned, check if caster has allowed stun auras, another stun types must prevent cast spell
- if (usableInStun)
- {
- static uint32 const allowedStunMask =
- 1 << MECHANIC_STUN
- | 1 << MECHANIC_FREEZE
- | 1 << MECHANIC_SAPPED
- | 1 << MECHANIC_SLEEP;
-
- bool foundNotStun = false;
- Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN);
- for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i)
- {
- uint32 mechanicMask = (*i)->GetSpellInfo()->GetAllEffectsMechanicMask();
- if (mechanicMask && !(mechanicMask & allowedStunMask))
- {
- foundNotStun = true;
- break;
- }
- }
- if (foundNotStun)
- prevented_reason = SPELL_FAILED_STUNNED;
- }
- else
- prevented_reason = SPELL_FAILED_STUNNED;
- }
- else if (unitflag & UNIT_FLAG_CONFUSED && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED))
- prevented_reason = SPELL_FAILED_CONFUSED;
- else if (unitflag & UNIT_FLAG_FLEEING && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED))
- prevented_reason = SPELL_FAILED_FLEEING;
- else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
- prevented_reason = SPELL_FAILED_SILENCED;
- else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
- prevented_reason = SPELL_FAILED_PACIFIED;
+ SpellCastResult result = SPELL_CAST_OK;
+
+ // Get unit state
+ uint32 const unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS);
+ if (m_caster->GetCharmerGUID())
+ {
+ if (Unit* charmer = m_caster->GetCharmer())
+ if (charmer->GetUnitBeingMoved() != m_caster && CheckCasterNotImmunedCharmAuras(param1))
+ result = SPELL_FAILED_CHARMED;
+ }
+ else if (unitflag & UNIT_FLAG_STUNNED && !usableWhileStunned && CheckCasterNotImmunedStunAuras(param1))
+ result = SPELL_FAILED_STUNNED;
+ else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && CheckCasterNotImmunedSilenceAuras(param1))
+ result = SPELL_FAILED_SILENCED;
+ else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && CheckCasterNotImmunedPacifyAuras(param1))
+ result = SPELL_FAILED_PACIFIED;
+ else if (unitflag & UNIT_FLAG_FLEEING && !usableWhileFeared && CheckCasterNotImmunedFearAuras(param1))
+ result = SPELL_FAILED_FLEEING;
+ else if (unitflag & UNIT_FLAG_CONFUSED && !usableWhileConfused && CheckCasterNotImmunedDisorientAuras(param1))
+ result = SPELL_FAILED_CONFUSED;
// Attr must make flag drop spell totally immune from all effects
- if (prevented_reason != SPELL_CAST_OK)
+ if (result != SPELL_CAST_OK)
+ return (param1 && *param1) ? SPELL_FAILED_PREVENTED_BY_MECHANIC : result;
+
+ return SPELL_CAST_OK;
+}
+
+// based on sub_00804430 from 12340 client
+bool Spell::CheckCasterHasNotImmunedAuraType(AuraType auraType, uint32* param1) const
+{
+ // Checking auras is needed now, because you are prevented by some state but the spell grants immunity.
+ Unit::AuraEffectList const& auraEffects = m_caster->GetAuraEffectsByType(auraType);
+ if (auraEffects.empty())
+ return false;
+
+ for (AuraEffect const* aurEff : auraEffects)
{
- if (school_immune || mechanic_immune || dispel_immune)
- {
- //Checking auras is needed now, because you are prevented by some state but the spell grants immunity.
- Unit::AuraApplicationMap const& auras = m_caster->GetAppliedAuras();
- for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- {
- Aura const* aura = itr->second->GetBase();
- SpellInfo const* auraInfo = aura->GetSpellInfo();
- if (auraInfo->GetAllEffectsMechanicMask() & mechanic_immune)
- continue;
- if (auraInfo->GetSchoolMask() & school_immune && !auraInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
- continue;
- if (auraInfo->GetDispelMask() & dispel_immune)
- continue;
+ SpellInfo const* auraInfo = aurEff->GetSpellInfo();
+ if (m_spellInfo->CanSpellCastOverrideAuraEffect(auraInfo, aurEff->GetEffIndex()))
+ continue;
- //Make a second check for spell failed so the right SPELL_FAILED message is returned.
- //That is needed when your casting is prevented by multiple states and you are only immune to some of them.
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect* part = aura->GetEffect(i))
- {
- switch (part->GetAuraType())
- {
- case SPELL_AURA_MOD_STUN:
- if (!usableInStun || !(auraInfo->GetAllEffectsMechanicMask() & (1<<MECHANIC_STUN)))
- return SPELL_FAILED_STUNNED;
- break;
- case SPELL_AURA_MOD_CONFUSE:
- if (!m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED))
- return SPELL_FAILED_CONFUSED;
- break;
- case SPELL_AURA_MOD_FEAR:
- if (!m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED))
- return SPELL_FAILED_FLEEING;
- break;
- case SPELL_AURA_MOD_SILENCE:
- case SPELL_AURA_MOD_PACIFY:
- case SPELL_AURA_MOD_PACIFY_SILENCE:
- if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
- return SPELL_FAILED_PACIFIED;
- else if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
- return SPELL_FAILED_SILENCED;
- break;
- default: break;
- }
- }
- }
- }
+ if (param1)
+ {
+ *param1 = auraInfo->Effects[aurEff->GetEffIndex()].Mechanic;
+ if (!*param1)
+ *param1 = auraInfo->Mechanic;
}
- // You are prevented from casting and the spell cast does not grant immunity. Return a failed error.
- else
- return prevented_reason;
+ return true;
}
- return SPELL_CAST_OK;
+
+ return false;
+}
+
+bool Spell::CheckCasterNotImmunedCharmAuras(uint32* param1) const
+{
+ return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_CHARM, param1) ||
+ CheckCasterHasNotImmunedAuraType(SPELL_AURA_AOE_CHARM, param1) ||
+ CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_POSSESS, param1);
+}
+
+bool Spell::CheckCasterNotImmunedStunAuras(uint32* param1) const
+{
+ return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_STUN, param1);
+}
+
+bool Spell::CheckCasterNotImmunedSilenceAuras(uint32* param1) const
+{
+ return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_SILENCE, param1) ||
+ CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_PACIFY_SILENCE, param1);
+}
+
+bool Spell::CheckCasterNotImmunedPacifyAuras(uint32* param1) const
+{
+ return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_PACIFY, param1) ||
+ CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_PACIFY_SILENCE, param1);
+}
+
+bool Spell::CheckCasterNotImmunedFearAuras(uint32* param1) const
+{
+ return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_FEAR, param1);
+}
+
+bool Spell::CheckCasterNotImmunedDisorientAuras(uint32* param1) const
+{
+ return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_CONFUSE, param1);
}
bool Spell::CanAutoCast(Unit* target)
@@ -5826,7 +5918,7 @@ bool Spell::CanAutoCast(Unit* target)
return false;
}
-SpellCastResult Spell::CheckRange(bool strict)
+SpellCastResult Spell::CheckRange(bool strict) const
{
// Don't check for instant cast spells
if (!strict && m_casttime == 0)
@@ -5856,20 +5948,20 @@ SpellCastResult Spell::CheckRange(bool strict)
if (m_targets.HasDst() && !m_targets.HasTraj())
{
if (m_caster->GetExactDistSq(m_targets.GetDstPos()) > maxRange)
- return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT;
+ return SPELL_FAILED_OUT_OF_RANGE;
if (minRange > 0.0f && m_caster->GetExactDistSq(m_targets.GetDstPos()) < minRange)
- return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT;
+ return SPELL_FAILED_OUT_OF_RANGE;
}
return SPELL_CAST_OK;
}
-std::pair<float, float> Spell::GetMinMaxRange(bool strict)
+std::pair<float, float> Spell::GetMinMaxRange(bool strict) const
{
float rangeMod = 0.0f;
float minRange = 0.0f;
float maxRange = 0.0f;
- if (strict && IsNextMeleeSwingSpell())
+ if (strict && m_spellInfo->IsNextMeleeSwingSpell())
{
maxRange = 100.0f;
return std::pair<float, float>(minRange, maxRange);
@@ -5911,14 +6003,14 @@ std::pair<float, float> Spell::GetMinMaxRange(bool strict)
maxRange *= ranged->GetTemplate()->RangedModRange * 0.01f;
if (Player* modOwner = m_caster->GetSpellModOwner())
- modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, maxRange, this);
+ modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, maxRange, const_cast<Spell*>(this));
maxRange += rangeMod;
return std::pair<float, float>(minRange, maxRange);
}
-SpellCastResult Spell::CheckPower()
+SpellCastResult Spell::CheckPower() const
{
// item cast not used power
if (m_CastItem)
@@ -5954,12 +6046,15 @@ SpellCastResult Spell::CheckPower()
return SPELL_CAST_OK;
}
-SpellCastResult Spell::CheckItems()
+SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) const
{
Player* player = m_caster->ToPlayer();
if (!player)
return SPELL_CAST_OK;
+ if (m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_ITEM_CHECK))
+ return SPELL_CAST_OK;
+
if (!m_CastItem)
{
if (m_castItemGUID)
@@ -6035,10 +6130,11 @@ SpellCastResult Spell::CheckItems()
// check target item
if (m_targets.GetItemTargetGUID())
{
- if (!m_targets.GetItemTarget())
+ Item* item = m_targets.GetItemTarget();
+ if (!item)
return SPELL_FAILED_ITEM_GONE;
- if (!m_targets.GetItemTarget()->IsFitToSpellRequirements(m_spellInfo))
+ if (!item->IsFitToSpellRequirements(m_spellInfo))
return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
}
// if not item target then required item must be equipped
@@ -6088,7 +6184,11 @@ SpellCastResult Spell::CheckItems()
}
}
if (!player->HasItemCount(itemid, itemcount))
+ {
+ if (param1)
+ *param1 = itemid;
return SPELL_FAILED_REAGENTS;
+ }
}
}
@@ -6292,21 +6392,29 @@ SpellCastResult Spell::CheckItems()
}
case SPELL_EFFECT_PROSPECTING:
{
- if (!m_targets.GetItemTarget())
+ Item* item = m_targets.GetItemTarget();
+ if (!item)
return SPELL_FAILED_CANT_BE_PROSPECTED;
//ensure item is a prospectable ore
- if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_FLAG_IS_PROSPECTABLE))
+ if (!(item->GetTemplate()->Flags & ITEM_FLAG_IS_PROSPECTABLE))
return SPELL_FAILED_CANT_BE_PROSPECTED;
//prevent prospecting in trade slot
- if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
+ if (item->GetOwnerGUID() != m_caster->GetGUID())
return SPELL_FAILED_CANT_BE_PROSPECTED;
//Check for enough skill in jewelcrafting
- uint32 item_prospectingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank;
- if (item_prospectingskilllevel >player->GetSkillValue(SKILL_JEWELCRAFTING))
+ uint32 item_prospectingskilllevel = item->GetTemplate()->RequiredSkillRank;
+ if (item_prospectingskilllevel > player->GetSkillValue(SKILL_JEWELCRAFTING))
return SPELL_FAILED_LOW_CASTLEVEL;
//make sure the player has the required ores in inventory
- if (m_targets.GetItemTarget()->GetCount() < 5)
+ if (item->GetCount() < 5)
+ {
+ if (param1 && param2)
+ {
+ *param1 = item->GetEntry();
+ *param2 = 5;
+ }
return SPELL_FAILED_NEED_MORE_ITEMS;
+ }
if (!LootTemplates_Prospecting.HaveLootFor(m_targets.GetItemTargetEntry()))
return SPELL_FAILED_CANT_BE_PROSPECTED;
@@ -6315,21 +6423,29 @@ SpellCastResult Spell::CheckItems()
}
case SPELL_EFFECT_MILLING:
{
- if (!m_targets.GetItemTarget())
+ Item* item = m_targets.GetItemTarget();
+ if (!item)
return SPELL_FAILED_CANT_BE_MILLED;
//ensure item is a millable herb
- if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_FLAG_IS_MILLABLE))
+ if (!(item->GetTemplate()->Flags & ITEM_FLAG_IS_MILLABLE))
return SPELL_FAILED_CANT_BE_MILLED;
//prevent milling in trade slot
- if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
+ if (item->GetOwnerGUID() != m_caster->GetGUID())
return SPELL_FAILED_CANT_BE_MILLED;
//Check for enough skill in inscription
- uint32 item_millingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank;
+ uint32 item_millingskilllevel = item->GetTemplate()->RequiredSkillRank;
if (item_millingskilllevel > player->GetSkillValue(SKILL_INSCRIPTION))
return SPELL_FAILED_LOW_CASTLEVEL;
//make sure the player has the required herbs in inventory
- if (m_targets.GetItemTarget()->GetCount() < 5)
+ if (item->GetCount() < 5)
+ {
+ if (param1 && param2)
+ {
+ *param1 = item->GetEntry();
+ *param2 = 5;
+ }
return SPELL_FAILED_NEED_MORE_ITEMS;
+ }
if (!LootTemplates_Milling.HaveLootFor(m_targets.GetItemTargetEntry()))
return SPELL_FAILED_CANT_BE_MILLED;
@@ -6601,14 +6717,14 @@ bool Spell::UpdatePointers()
CurrentSpellTypes Spell::GetCurrentContainer() const
{
- if (IsNextMeleeSwingSpell())
- return(CURRENT_MELEE_SPELL);
+ if (m_spellInfo->IsNextMeleeSwingSpell())
+ return CURRENT_MELEE_SPELL;
else if (IsAutoRepeat())
- return(CURRENT_AUTOREPEAT_SPELL);
+ return CURRENT_AUTOREPEAT_SPELL;
else if (m_spellInfo->IsChanneled())
- return(CURRENT_CHANNELED_SPELL);
- else
- return(CURRENT_GENERIC_SPELL);
+ return CURRENT_CHANNELED_SPELL;
+
+ return CURRENT_GENERIC_SPELL;
}
bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* losPosition) const
@@ -6687,11 +6803,6 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
return true;
}
-bool Spell::IsNextMeleeSwingSpell() const
-{
- return m_spellInfo->HasAttribute(SPELL_ATTR0_ON_NEXT_SWING);
-}
-
bool Spell::IsAutoActionResetSpell() const
{
/// @todo changed SPELL_INTERRUPT_FLAG_AUTOATTACK -> SPELL_INTERRUPT_FLAG_INTERRUPT to fix compile - is this check correct at all?
@@ -7069,7 +7180,7 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value)
void Spell::PrepareTargetProcessing()
{
- CheckEffectExecuteData();
+ AssertEffectExecuteData();
}
void Spell::FinishTargetProcessing()
@@ -7094,7 +7205,7 @@ void Spell::InitEffectExecuteData(uint8 effIndex)
}
}
-void Spell::CheckEffectExecuteData()
+void Spell::AssertEffectExecuteData() const
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
ASSERT(!m_effectExecuteData[i]);
@@ -7102,29 +7213,20 @@ void Spell::CheckEffectExecuteData()
void Spell::LoadScripts()
{
- sScriptMgr->CreateSpellScripts(m_spellInfo->Id, m_loadedScripts);
- for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end();)
+ sScriptMgr->CreateSpellScripts(m_spellInfo->Id, m_loadedScripts, this);
+ for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
{
- if (!(*itr)->_Load(this))
- {
- std::list<SpellScript*>::iterator bitr = itr;
- ++itr;
- delete (*bitr);
- m_loadedScripts.erase(bitr);
- continue;
- }
TC_LOG_DEBUG("spells", "Spell::LoadScripts: Script `%s` for spell `%u` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id);
(*itr)->Register();
- ++itr;
}
}
void Spell::CallScriptBeforeCastHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_CAST);
- std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->BeforeCast.end(), hookItr = (*scritr)->BeforeCast.begin();
+ auto hookItrEnd = (*scritr)->BeforeCast.end(), hookItr = (*scritr)->BeforeCast.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr);
@@ -7134,10 +7236,10 @@ void Spell::CallScriptBeforeCastHandlers()
void Spell::CallScriptOnCastHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_CAST);
- std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->OnCast.end(), hookItr = (*scritr)->OnCast.begin();
+ auto hookItrEnd = (*scritr)->OnCast.end(), hookItr = (*scritr)->OnCast.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr);
@@ -7147,10 +7249,10 @@ void Spell::CallScriptOnCastHandlers()
void Spell::CallScriptAfterCastHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_CAST);
- std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->AfterCast.end(), hookItr = (*scritr)->AfterCast.begin();
+ auto hookItrEnd = (*scritr)->AfterCast.end(), hookItr = (*scritr)->AfterCast.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr);
@@ -7161,10 +7263,10 @@ void Spell::CallScriptAfterCastHandlers()
SpellCastResult Spell::CallScriptCheckCastHandlers()
{
SpellCastResult retVal = SPELL_CAST_OK;
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CHECK_CAST);
- std::list<SpellScript::CheckCastHandler>::iterator hookItrEnd = (*scritr)->OnCheckCast.end(), hookItr = (*scritr)->OnCheckCast.begin();
+ auto hookItrEnd = (*scritr)->OnCheckCast.end(), hookItr = (*scritr)->OnCheckCast.begin();
for (; hookItr != hookItrEnd; ++hookItr)
{
SpellCastResult tempResult = (*hookItr).Call(*scritr);
@@ -7179,7 +7281,7 @@ SpellCastResult Spell::CallScriptCheckCastHandlers()
void Spell::PrepareScriptHitHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
(*scritr)->_InitHit();
}
@@ -7187,9 +7289,9 @@ bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMo
{
// execute script effect handler hooks and check if effects was prevented
bool preventDefault = false;
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
- std::list<SpellScript::EffectHandler>::iterator effItr, effEndItr;
+ HookList<SpellScript::EffectHandler>::iterator effItr, effEndItr;
SpellScriptHookType hookType;
switch (mode)
{
@@ -7233,10 +7335,10 @@ bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMo
void Spell::CallScriptSuccessfulDispel(SpellEffIndex effIndex)
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL);
- std::list<SpellScript::EffectHandler>::iterator hookItrEnd = (*scritr)->OnEffectSuccessfulDispel.end(), hookItr = (*scritr)->OnEffectSuccessfulDispel.begin();
+ auto hookItrEnd = (*scritr)->OnEffectSuccessfulDispel.end(), hookItr = (*scritr)->OnEffectSuccessfulDispel.begin();
for (; hookItr != hookItrEnd; ++hookItr)
hookItr->Call(*scritr, effIndex);
@@ -7246,10 +7348,10 @@ void Spell::CallScriptSuccessfulDispel(SpellEffIndex effIndex)
void Spell::CallScriptBeforeHitHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_HIT);
- std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin();
+ auto hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr);
@@ -7259,10 +7361,10 @@ void Spell::CallScriptBeforeHitHandlers()
void Spell::CallScriptOnHitHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_HIT);
- std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->OnHit.end(), hookItr = (*scritr)->OnHit.begin();
+ auto hookItrEnd = (*scritr)->OnHit.end(), hookItr = (*scritr)->OnHit.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr);
@@ -7272,10 +7374,10 @@ void Spell::CallScriptOnHitHandlers()
void Spell::CallScriptAfterHitHandlers()
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_HIT);
- std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->AfterHit.end(), hookItr = (*scritr)->AfterHit.begin();
+ auto hookItrEnd = (*scritr)->AfterHit.end(), hookItr = (*scritr)->AfterHit.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr);
@@ -7285,10 +7387,10 @@ void Spell::CallScriptAfterHitHandlers()
void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT);
- std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectAreaTargetSelect.end(), hookItr = (*scritr)->OnObjectAreaTargetSelect.begin();
+ auto hookItrEnd = (*scritr)->OnObjectAreaTargetSelect.end(), hookItr = (*scritr)->OnObjectAreaTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget())
hookItr->Call(*scritr, targets);
@@ -7299,10 +7401,10 @@ void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& ta
void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT);
- std::list<SpellScript::ObjectTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin();
+ auto hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget())
hookItr->Call(*scritr, target);
@@ -7313,10 +7415,10 @@ void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffI
void Spell::CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
- for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT);
- std::list<SpellScript::DestinationTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnDestinationTargetSelect.end(), hookItr = (*scritr)->OnDestinationTargetSelect.begin();
+ auto hookItrEnd = (*scritr)->OnDestinationTargetSelect.end(), hookItr = (*scritr)->OnDestinationTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget())
hookItr->Call(*scritr, target);
@@ -7331,15 +7433,15 @@ bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToC
if (m_loadedScripts.empty())
return true;
- for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
+ for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
{
- std::list<SpellScript::ObjectTargetSelectHandler>::iterator targetSelectHookEnd = (*itr)->OnObjectTargetSelect.end(), targetSelectHookItr = (*itr)->OnObjectTargetSelect.begin();
+ auto targetSelectHookEnd = (*itr)->OnObjectTargetSelect.end(), targetSelectHookItr = (*itr)->OnObjectTargetSelect.begin();
for (; targetSelectHookItr != targetSelectHookEnd; ++targetSelectHookItr)
if (((*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) ||
(!(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)))
return false;
- std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator areaTargetSelectHookEnd = (*itr)->OnObjectAreaTargetSelect.end(), areaTargetSelectHookItr = (*itr)->OnObjectAreaTargetSelect.begin();
+ auto areaTargetSelectHookEnd = (*itr)->OnObjectAreaTargetSelect.end(), areaTargetSelectHookItr = (*itr)->OnObjectAreaTargetSelect.begin();
for (; areaTargetSelectHookItr != areaTargetSelectHookEnd; ++areaTargetSelectHookItr)
if (((*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) ||
(!(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)))
@@ -7389,25 +7491,24 @@ void Spell::PrepareTriggersExecutedOnHit()
// save auras which were present on spell caster on cast, to prevent triggered auras from affecting caster
// and to correctly calculate proc chance when combopoints are present
Unit::AuraEffectList const& targetTriggers = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_TARGET_TRIGGER);
- for (Unit::AuraEffectList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
+ for (AuraEffect const* aurEff : targetTriggers)
{
- if (!(*i)->IsAffectedOnSpell(m_spellInfo))
+ if (!aurEff->IsAffectedOnSpell(m_spellInfo))
continue;
- SpellInfo const* auraSpellInfo = (*i)->GetSpellInfo();
- uint32 auraSpellIdx = (*i)->GetEffIndex();
+
+ SpellInfo const* auraSpellInfo = aurEff->GetSpellInfo();
+ uint32 auraSpellIdx = aurEff->GetEffIndex();
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(auraSpellInfo->Effects[auraSpellIdx].TriggerSpell))
{
// calculate the chance using spell base amount, because aura amount is not updated on combo-points change
// this possibly needs fixing
- int32 auraBaseAmount = (*i)->GetBaseAmount();
+ int32 auraBaseAmount = aurEff->GetBaseAmount();
// proc chance is stored in effect amount
- int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
+ int32 chance = m_caster->CalculateSpellDamage(nullptr, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
+ chance *= aurEff->GetBase()->GetStackAmount();
+
// build trigger and add to the list
- HitTriggerSpell spellTriggerInfo;
- spellTriggerInfo.triggeredSpell = spellInfo;
- spellTriggerInfo.triggeredByAura = auraSpellInfo;
- spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount();
- m_hitTriggerSpells.push_back(spellTriggerInfo);
+ m_hitTriggerSpells.emplace_back(spellInfo, auraSpellInfo, chance);
}
}
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 5087ececa09..aa3b6ca358a 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -397,7 +397,7 @@ class TC_GAME_API Spell
void TakeReagents();
void TakeCastItem();
- SpellCastResult CheckCast(bool strict);
+ SpellCastResult CheckCast(bool strict, uint32* param1 = nullptr, uint32* param2 = nullptr);
SpellCastResult CheckPetCast(Unit* target);
// handlers
@@ -407,11 +407,19 @@ class TC_GAME_API Spell
void _handle_immediate_phase();
void _handle_finish_phase();
- SpellCastResult CheckItems();
- SpellCastResult CheckRange(bool strict);
- SpellCastResult CheckPower();
- SpellCastResult CheckRuneCost(uint32 runeCostID);
- SpellCastResult CheckCasterAuras() const;
+ SpellCastResult CheckItems(uint32* param1, uint32* param2) const;
+ SpellCastResult CheckRange(bool strict) const;
+ SpellCastResult CheckPower() const;
+ SpellCastResult CheckRuneCost(uint32 runeCostID) const;
+ SpellCastResult CheckCasterAuras(uint32* param1) const;
+
+ bool CheckCasterHasNotImmunedAuraType(AuraType auraType, uint32* param1) const;
+ bool CheckCasterNotImmunedCharmAuras(uint32* param1) const;
+ bool CheckCasterNotImmunedStunAuras(uint32* param1) const;
+ bool CheckCasterNotImmunedSilenceAuras(uint32* param1) const;
+ bool CheckCasterNotImmunedPacifyAuras(uint32* param1) const;
+ bool CheckCasterNotImmunedFearAuras(uint32* param1) const;
+ bool CheckCasterNotImmunedDisorientAuras(uint32* param1) const;
int32 CalculateDamage(uint8 i, Unit const* target) const { return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i]); }
@@ -430,9 +438,9 @@ class TC_GAME_API Spell
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); }
void CheckDst() { if (!m_targets.HasDst()) m_targets.SetDst(*m_caster); }
- static void WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError);
- static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE);
- void SendCastResult(SpellCastResult result);
+ static void WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError, uint32* param1 = nullptr, uint32* param2 = nullptr);
+ static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, uint32* param1 = nullptr, uint32* param2 = nullptr);
+ void SendCastResult(SpellCastResult result, uint32* param1 = nullptr, uint32* param2 = nullptr) const;
void SendPetCastResult(SpellCastResult result);
void SendSpellStart();
void SendSpellGo();
@@ -473,12 +481,14 @@ class TC_GAME_API Spell
bool IsAutoRepeat() const { return m_autoRepeat; }
void SetAutoRepeat(bool rep) { m_autoRepeat = rep; }
void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; }
- bool IsNextMeleeSwingSpell() const;
bool IsTriggered() const { return (_triggeredCastFlags & TRIGGERED_FULL_MASK) != 0; }
bool IsIgnoringCooldowns() const { return (_triggeredCastFlags & TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD) != 0; }
+ bool IsProcDisabled() const { return (_triggeredCastFlags & TRIGGERED_DISALLOW_PROC_EVENTS) != 0; }
bool IsChannelActive() const { return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0; }
bool IsAutoActionResetSpell() const;
+ bool IsTriggeredByAura(SpellInfo const* auraSpellInfo) const { return (auraSpellInfo == m_triggeredByAuraSpell); }
+
bool IsDeletable() const { return !m_referencedFromCurrentSpell && !m_executedCurrently; }
void SetReferencedFromCurrent(bool yes) { m_referencedFromCurrentSpell = yes; }
bool IsInterruptable() const { return !m_executedCurrently; }
@@ -507,7 +517,7 @@ class TC_GAME_API Spell
void CancelGlobalCooldown();
void SendLoot(ObjectGuid guid, LootType loottype);
- std::pair<float, float> GetMinMaxRange(bool strict);
+ std::pair<float, float> GetMinMaxRange(bool strict) const;
Unit* const m_caster;
@@ -636,7 +646,7 @@ class TC_GAME_API Spell
// spell execution log
void InitEffectExecuteData(uint8 effIndex);
- void CheckEffectExecuteData();
+ void AssertEffectExecuteData() const;
// Scripting system
void LoadScripts();
@@ -654,10 +664,13 @@ class TC_GAME_API Spell
void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
void CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
bool CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck);
- std::list<SpellScript*> m_loadedScripts;
+ std::vector<SpellScript*> m_loadedScripts;
struct HitTriggerSpell
{
+ HitTriggerSpell(SpellInfo const* spellInfo, SpellInfo const* auraSpellInfo, int32 procChance) :
+ triggeredSpell(spellInfo), triggeredByAura(auraSpellInfo), chance(procChance) { }
+
SpellInfo const* triggeredSpell;
SpellInfo const* triggeredByAura;
// uint8 triggeredByEffIdx This might be needed at a later stage - No need known for now
@@ -666,7 +679,7 @@ class TC_GAME_API Spell
bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura = NULL) const;
void PrepareTriggersExecutedOnHit();
- typedef std::list<HitTriggerSpell> HitTriggerSpellList;
+ typedef std::vector<HitTriggerSpell> HitTriggerSpellList;
HitTriggerSpellList m_hitTriggerSpells;
// effect helpers
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index f321925aa8c..7afcf52172a 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -292,14 +292,18 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
if (!unitTarget || !unitTarget->IsAlive())
return;
- uint32 absorb = 0;
- uint32 resist = 0;
-
- m_caster->CalcAbsorbResist(unitTarget, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo);
-
- m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
+ // CalcAbsorbResist already in Player::EnvironmentalDamage
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
unitTarget->ToPlayer()->EnvironmentalDamage(DAMAGE_FIRE, damage);
+ else
+ {
+ DamageInfo damageInfo(m_caster, unitTarget, damage, m_spellInfo, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK);
+ m_caster->CalcAbsorbResist(damageInfo);
+
+ uint32 absorb = damageInfo.GetAbsorb();
+ uint32 resist = damageInfo.GetResist();
+ m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
+ }
}
void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
@@ -395,9 +399,9 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Conflagrate - consumes Immolate or Shadowflame
else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
{
- AuraEffect const* aura = NULL; // found req. aura for damage calculation
+ AuraEffect const* aura = nullptr; // found req. aura for damage calculation
- Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
+ Unit::AuraEffectList const& mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
{
// for caster applied auras only
@@ -420,15 +424,22 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// found Immolate or Shadowflame
if (aura)
{
- uint32 pdamage = uint32(std::max(aura->GetAmount(), 0));
- pdamage = m_caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
- pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
- uint32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 1));
- uint8 baseTotalTicks = uint8(m_caster->CalcSpellDuration(aura->GetSpellInfo()) / aura->GetSpellInfo()->Effects[EFFECT_0].Amplitude);
- damage += int32(CalculatePct(pdamage * baseTotalTicks, pct_dir));
+ // Calculate damage of Immolate/Shadowflame tick
+ int32 pdamage = (aura->GetAmount() + aura->GetBonusAmount()) * aura->GetDonePct();
+ if (Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(GetSpellInfo()->Id, pdamage);
- uint32 pct_dot = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 2)) / 3;
- m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(int32(CalculatePct(pdamage * baseTotalTicks, pct_dot)));
+ pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT);
+
+ // And multiply by amount of ticks to get damage potential
+ pdamage *= aura->GetSpellInfo()->GetMaxTicks();
+
+ int32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_1);
+ damage += CalculatePct(pdamage, pct_dir);
+
+ int32 pct_dot = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2);
+ int32 const dotBasePoints = CalculatePct(pdamage, pct_dot);
+ m_spellValue->EffectBasePoints[EFFECT_1] = dotBasePoints / m_spellInfo->GetMaxTicks();
apply_direct_bonus = false;
// Glyph of Conflagrate
@@ -1393,9 +1404,12 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
return;
}
- int32 tickheal = targetAura->GetAmount();
- if (Unit* auraCaster = targetAura->GetCaster())
- tickheal = auraCaster->SpellHealingBonusDone(unitTarget, targetAura->GetSpellInfo(), tickheal, DOT);
+ int32 tickheal = (targetAura->GetAmount() + targetAura->GetBonusAmount()) * targetAura->GetDonePct();
+ if (Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(targetAura->GetId(), tickheal);
+
+ unitTarget->SpellHealingBonusTaken(m_caster, targetAura->GetSpellInfo(), tickheal, DOT);
+
//int32 tickheal = targetAura->GetSpellInfo()->EffectBasePoints[idx] + 1;
//It is said that talent bonus should not be included
@@ -2103,6 +2117,8 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex)
m_castItemEntry = 0;
player->StoreItem(dest, pNewItem, true);
+ player->SendNewItem(pNewItem, 1, true, false);
+ player->ItemAddedQuestCheck(newitemid, 1);
return;
}
}
@@ -2147,6 +2163,8 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex)
player->EquipItem(dest, pNewItem, true);
player->AutoUnequipOffhandIfNeed();
+ player->SendNewItem(pNewItem, 1, true, false);
+ player->ItemAddedQuestCheck(newitemid, 1);
return;
}
}
@@ -3362,8 +3380,10 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
}
}
- // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
- if (fixed_bonus || spell_bonus)
+ // if (addPctMods) { percent mods are added in Unit::CalculateDamage } else { percent mods are added in Unit::MeleeDamageBonusDone }
+ // this distinction is neccessary to properly inform the client about his autoattack damage values from Script_UnitDamage
+ bool addPctMods = !m_spellInfo->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && (m_spellSchoolMask & SPELL_SCHOOL_MASK_NORMAL);
+ if (addPctMods)
{
UnitMods unitMod;
switch (m_attackType)
@@ -3374,17 +3394,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
}
- float weapon_total_pct = 1.0f;
- if (m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL)
- weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
-
+ float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
if (fixed_bonus)
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
if (spell_bonus)
spell_bonus = int32(spell_bonus * weapon_total_pct);
}
- int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true);
+ int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, addPctMods);
// Sequence is important
for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
@@ -3399,17 +3416,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
weaponDamage += fixed_bonus;
break;
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
- weaponDamage = int32(weaponDamage* weaponDamagePercentMod);
+ weaponDamage = int32(weaponDamage * weaponDamagePercentMod);
default:
break; // not weapon damage effect, just skip
}
}
- if (spell_bonus)
- weaponDamage += spell_bonus;
-
- if (totalDamagePercentMod != 1.0f)
- weaponDamage = int32(weaponDamage* totalDamagePercentMod);
+ weaponDamage += spell_bonus;
+ weaponDamage = int32(weaponDamage * totalDamagePercentMod);
// prevent negative damage
uint32 eff_damage(std::max(weaponDamage, 0));
@@ -3531,21 +3545,12 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
if (Battleground* bg = player->GetBattleground())
bg->SetDroppedFlagGUID(pGameObj->GetGUID(), player->GetTeam() == ALLIANCE ? TEAM_HORDE: TEAM_ALLIANCE);
- if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
+ if (GameObject* linkedTrap = pGameObj->GetLinkedTrap())
{
- GameObject* linkedGO = new GameObject();
- if (linkedGO->Create(map->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, map, m_caster->GetPhaseMask(), Position(x, y, z, target->GetOrientation()), rot, 255, GO_STATE_READY))
- {
- linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
- linkedGO->SetSpellId(m_spellInfo->Id);
-
- ExecuteLogEffectSummonObject(effIndex, linkedGO);
+ linkedTrap->SetRespawnTime(duration > 0 ? duration / IN_MILLISECONDS : 0);
+ linkedTrap->SetSpellId(m_spellInfo->Id);
- // Wild object not have owner and check clickable by players
- map->AddToMap(linkedGO);
- }
- else
- delete linkedGO;
+ ExecuteLogEffectSummonObject(effIndex, linkedTrap);
}
}
@@ -5137,26 +5142,14 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
cMap->AddToMap(pGameObj);
- if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
+ if (GameObject* linkedTrap = pGameObj->GetLinkedTrap())
{
- GameObject* linkedGO = new GameObject;
- if (linkedGO->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, cMap, m_caster->GetPhaseMask(), pos, rot, 255, GO_STATE_READY))
- {
- linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
- //linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
- linkedGO->SetSpellId(m_spellInfo->Id);
- linkedGO->SetOwnerGUID(m_caster->GetGUID());
+ linkedTrap->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
+ //linkedTrap->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
+ linkedTrap->SetSpellId(m_spellInfo->Id);
+ linkedTrap->SetOwnerGUID(m_caster->GetGUID());
- ExecuteLogEffectSummonObject(effIndex, linkedGO);
-
- linkedGO->GetMap()->AddToMap(linkedGO);
- }
- else
- {
- delete linkedGO;
- linkedGO = NULL;
- return;
- }
+ ExecuteLogEffectSummonObject(effIndex, linkedTrap);
}
}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 925d5ec57a3..c0fbdf51889 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -16,6 +16,7 @@
*/
#include "SpellAuraDefines.h"
+#include "SpellAuras.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "Spell.h"
@@ -894,6 +895,31 @@ bool SpellInfo::HasAreaAuraEffect() const
return false;
}
+bool SpellInfo::HasOnlyDamageEffects() const
+{
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (Effects[i].IsEffect())
+ {
+ switch (Effects[i].Effect)
+ {
+ case SPELL_EFFECT_WEAPON_DAMAGE:
+ case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
+ case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
+ case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
+ case SPELL_EFFECT_SCHOOL_DAMAGE:
+ case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
+ case SPELL_EFFECT_HEALTH_LEECH:
+ continue;
+ default:
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
bool SpellInfo::IsExplicitDiscovery() const
{
return ((Effects[0].Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM
@@ -1181,12 +1207,22 @@ bool SpellInfo::IsPositiveEffect(uint8 effIndex) const
bool SpellInfo::IsChanneled() const
{
- return HasAttribute(SPELL_ATTR1_CHANNELED_1) || HasAttribute(SPELL_ATTR1_CHANNELED_2);
+ return HasAttribute(SpellAttr1(SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2));
+}
+
+bool SpellInfo::IsMoveAllowedChannel() const
+{
+ return IsChanneled() && HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING);
}
bool SpellInfo::NeedsComboPoints() const
{
- return HasAttribute(SPELL_ATTR1_REQ_COMBO_POINTS1) || HasAttribute(SPELL_ATTR1_REQ_COMBO_POINTS2);
+ return HasAttribute(SpellAttr1(SPELL_ATTR1_REQ_COMBO_POINTS1 | SPELL_ATTR1_REQ_COMBO_POINTS2));
+}
+
+bool SpellInfo::IsNextMeleeSwingSpell() const
+{
+ return HasAttribute(SpellAttr0(SPELL_ATTR0_ON_NEXT_SWING | SPELL_ATTR0_ON_NEXT_SWING_2));
}
bool SpellInfo::IsBreakingStealth() const
@@ -1210,6 +1246,20 @@ bool SpellInfo::HasInitialAggro() const
return !(HasAttribute(SPELL_ATTR1_NO_THREAT) || HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO));
}
+bool SpellInfo::IsAffected(uint32 familyName, flag96 const& familyFlags) const
+{
+ if (!familyName)
+ return true;
+
+ if (familyName != SpellFamilyName)
+ return false;
+
+ if (familyFlags && !(familyFlags & SpellFamilyFlags))
+ return false;
+
+ return true;
+}
+
bool SpellInfo::IsAffectedBySpellMods() const
{
return !HasAttribute(SPELL_ATTR3_NO_DONE_BONUS);
@@ -1221,42 +1271,41 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const
return false;
SpellInfo const* affectSpell = sSpellMgr->GetSpellInfo(mod->spellId);
- // False if affect_spell == NULL or spellFamily not equal
- if (!affectSpell || affectSpell->SpellFamilyName != SpellFamilyName)
+ if (!affectSpell)
return false;
- // true
- if (mod->mask & SpellFamilyFlags)
- return true;
-
- return false;
+ return IsAffected(affectSpell->SpellFamilyName, mod->mask);
}
-bool SpellInfo::CanPierceImmuneAura(SpellInfo const* aura) const
+bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
{
- // these spells pierce all avalible spells (Resurrection Sickness for example)
+ // aura can't be pierced
+ if (!auraSpellInfo || auraSpellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ return false;
+
+ // these spells pierce all available spells (Resurrection Sickness for example)
if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return true;
- // these spells (Cyclone for example) can pierce all... // ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
- if (HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !(aura && (aura->Mechanic == MECHANIC_IMMUNE_SHIELD || aura->Mechanic == MECHANIC_INVULNERABILITY || aura->Mechanic == MECHANIC_BANISH)))
+ // Dispels other auras on immunity, check if this spell makes the unit immune to aura
+ if (HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) && CanSpellProvideImmunityAgainstAura(auraSpellInfo))
return true;
return false;
}
-bool SpellInfo::CanDispelAura(SpellInfo const* aura) const
+bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const
{
- // These spells (like Mass Dispel) can dispell all auras, except death persistent ones (like Dungeon and Battleground Deserter)
- if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) && !aura->IsDeathPersistent())
- return true;
-
// These auras (like Divine Shield) can't be dispelled
- if (aura->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ if (auraSpellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
+ // These spells (like Mass Dispel) can dispel all auras
+ if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ return true;
+
// These auras (Cyclone for example) are not dispelable
- if (aura->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
+ if (auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
return false;
return true;
@@ -1411,9 +1460,11 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
// continent limitation (virtual continent)
if (HasAttribute(SPELL_ATTR4_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())
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(area_id);
+ if (!areaEntry)
+ areaEntry = sAreaTableStore.LookupEntry(zone_id);
+
+ if (!areaEntry || !areaEntry->IsFlyable() || !player->CanFlyInZone(map_id, zone_id))
return SPELL_FAILED_INCORRECT_AREA;
}
@@ -1982,9 +2033,27 @@ void SpellInfo::_LoadSpellSpecific()
case 8115: // Agility
case 8091: // Armor
return SPELL_SPECIFIC_SCROLL;
+ default:
+ break;
+ }
+
+ switch (Id)
+ {
case 12880: // Enrage (Enrage)
+ case 14201:
+ case 14202:
+ case 14203:
+ case 14204:
case 57518: // Enrage (Wrecking Crew)
+ case 57519:
+ case 57520:
+ case 57521:
+ case 57522:
+ case 57514: // Enrage (Imp. Defensive Stance)
+ case 57516:
return SPELL_SPECIFIC_WARRIOR_ENRAGE;
+ default:
+ break;
}
}
break;
@@ -2441,6 +2510,437 @@ int32 SpellInfo::GetDiminishingReturnsLimitDuration(bool triggered) const
return triggered ? _diminishInfoTriggered.DiminishDurationLimit : _diminishInfoNonTriggered.DiminishDurationLimit;
}
+void SpellInfo::_LoadImmunityInfo()
+{
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ uint32 schoolImmunityMask = 0;
+ uint32 applyHarmfulAuraImmunityMask = 0;
+ uint32 mechanicImmunityMask = 0;
+ uint32 dispelImmunity = 0;
+ uint32 damageImmunityMask = 0;
+
+ int32 miscVal = Effects[i].MiscValue;
+ int32 amount = Effects[i].CalcValue();
+
+ ImmunityInfo& immuneInfo = _immunityInfo[i];
+
+ switch (Effects[i].ApplyAuraName)
+ {
+ case SPELL_AURA_MECHANIC_IMMUNITY_MASK:
+ {
+ switch (miscVal)
+ {
+ case 96: // Free Friend, Uncontrollable Frenzy, Warlord's Presence
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ break;
+ }
+ case 1615: // Incite Rage, Wolf Spirit, Overload, Lightning Tendrils
+ {
+ switch (Id)
+ {
+ case 43292: // Incite Rage
+ case 49172: // Wolf Spirit
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ // no break intended
+ case 61869: // Overload
+ case 63481:
+ case 61887: // Lightning Tendrils
+ case 63486:
+ mechanicImmunityMask |= (1 << MECHANIC_INTERRUPT) | (1 << MECHANIC_SILENCE);
+
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK);
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK_DEST);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 679: // Mind Control, Avenging Fury
+ {
+ if (Id == 57742) // Avenging Fury
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ }
+ break;
+ }
+ case 1557: // Startling Roar, Warlord Roar, Break Bonds, Stormshield
+ {
+ if (Id == 64187) // Stormshield
+ {
+ mechanicImmunityMask |= (1 << MECHANIC_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ }
+ else
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ }
+ break;
+ }
+ case 1614: // Fixate
+ case 1694: // Fixated, Lightning Tendrils
+ {
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_ATTACK_ME);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_TAUNT);
+ break;
+ }
+ case 1630: // Fervor, Berserk
+ {
+ if (Id == 64112) // Berserk
+ {
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_ATTACK_ME);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_TAUNT);
+ }
+ else
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ }
+ break;
+ }
+ case 477: // Bladestorm
+ case 1733: // Bladestorm, Killing Spree
+ {
+ if (!amount)
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK);
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK_DEST);
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ }
+ break;
+ }
+ case 878: // Whirlwind, Fog of Corruption, Determination
+ {
+ if (Id == 66092) // Determination
+ {
+ mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_STUN)
+ | (1 << MECHANIC_DISORIENTED) | (1 << MECHANIC_FREEZE);
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (immuneInfo.AuraTypeImmune.empty())
+ {
+ if (miscVal & (1 << 10))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ if (miscVal & (1 << 1))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_TRANSFORM);
+
+ // These flag can be recognized wrong:
+ if (miscVal & (1 << 6))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ if (miscVal & (1 << 0))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ if (miscVal & (1 << 2))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ if (miscVal & (1 << 9))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ if (miscVal & (1 << 7))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DISARM);
+ }
+ break;
+ }
+ case SPELL_AURA_MECHANIC_IMMUNITY:
+ {
+ switch (Id)
+ {
+ case 34471: // The Beast Within
+ case 19574: // Bestial Wrath
+ case 42292: // PvP trinket
+ case 59752: // Every Man for Himself
+ case 53490: // Bullheaded
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+ break;
+ case 54508: // Demonic Empowerment
+ mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN);
+ break;
+ default:
+ if (miscVal < 1)
+ continue;
+
+ mechanicImmunityMask |= 1 << miscVal;
+ break;
+ }
+ break;
+ }
+ case SPELL_AURA_EFFECT_IMMUNITY:
+ {
+ immuneInfo.SpellEffectImmune.insert(static_cast<SpellEffects>(miscVal));
+ break;
+ }
+ case SPELL_AURA_STATE_IMMUNITY:
+ {
+ immuneInfo.AuraTypeImmune.insert(static_cast<AuraType>(miscVal));
+ break;
+ }
+ case SPELL_AURA_SCHOOL_IMMUNITY:
+ {
+ schoolImmunityMask |= uint32(miscVal);
+ break;
+ }
+ case SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL:
+ {
+ applyHarmfulAuraImmunityMask |= uint32(miscVal);
+ break;
+ }
+ case SPELL_AURA_DAMAGE_IMMUNITY:
+ {
+ damageImmunityMask |= uint32(miscVal);
+ break;
+ }
+ case SPELL_AURA_DISPEL_IMMUNITY:
+ {
+ dispelImmunity = uint32(miscVal);
+ break;
+ }
+ default:
+ break;
+ }
+
+ immuneInfo.SchoolImmuneMask = schoolImmunityMask;
+ immuneInfo.ApplyHarmfulAuraImmuneMask = applyHarmfulAuraImmunityMask;
+ immuneInfo.MechanicImmuneMask = mechanicImmunityMask;
+ immuneInfo.DispelImmune = dispelImmunity;
+ immuneInfo.DamageSchoolMask = damageImmunityMask;
+
+ immuneInfo.AuraTypeImmune.shrink_to_fit();
+ immuneInfo.SpellEffectImmune.shrink_to_fit();
+ }
+}
+
+void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool apply) const
+{
+ ImmunityInfo const* immuneInfo = _immunityInfo + effIndex;
+
+ if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
+ {
+ target->ApplySpellImmune(Id, IMMUNITY_SCHOOL, schoolImmunity, apply);
+
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ {
+ target->RemoveAppliedAuras([this, schoolImmunity](AuraApplication const* aurApp) -> bool
+ {
+ SpellInfo const* auraSpellInfo = aurApp->GetBase()->GetSpellInfo();
+ return ((auraSpellInfo->GetSchoolMask() & schoolImmunity) != 0 && // Check for school mask
+ CanDispelAura(auraSpellInfo) &&
+ (IsPositive() != aurApp->IsPositive()) && // Check spell vs aura possitivity
+ !auraSpellInfo->IsPassive() && // Don't remove passive auras
+ auraSpellInfo->Id != Id); // Don't remove self
+ });
+ }
+ }
+
+ if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask)
+ {
+ for (uint32 i = 0; i < MAX_MECHANIC; ++i)
+ if (mechanicImmunity & (1 << i))
+ target->ApplySpellImmune(Id, IMMUNITY_MECHANIC, i, apply);
+
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
+ }
+
+ if (uint32 dispelImmunity = immuneInfo->DispelImmune)
+ {
+ target->ApplySpellImmune(Id, IMMUNITY_DISPEL, dispelImmunity, apply);
+
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ {
+ target->RemoveAppliedAuras([dispelImmunity](AuraApplication const* aurApp) -> bool
+ {
+ SpellInfo const* spellInfo = aurApp->GetBase()->GetSpellInfo();
+ if (spellInfo->Dispel == dispelImmunity)
+ return true;
+
+ return false;
+ });
+ }
+ }
+
+ if (uint32 damageImmunity = immuneInfo->DamageSchoolMask)
+ target->ApplySpellImmune(Id, IMMUNITY_DAMAGE, damageImmunity, apply);
+
+ for (AuraType auraType : immuneInfo->AuraTypeImmune)
+ {
+ target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply);
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ target->RemoveAurasByType(auraType);
+ }
+
+ for (SpellEffects effectType : immuneInfo->SpellEffectImmune)
+ target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply);
+}
+
+bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const
+{
+ if (!auraSpellInfo)
+ return false;
+
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ ImmunityInfo const* immuneInfo = _immunityInfo + i;
+
+ if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ {
+ if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
+ if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0)
+ return true;
+ }
+
+ if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask)
+ if ((mechanicImmunity & (1 << auraSpellInfo->Mechanic)) != 0)
+ return true;
+
+ if (uint32 dispelImmunity = immuneInfo->DispelImmune)
+ if (auraSpellInfo->Dispel == dispelImmunity)
+ return true;
+
+ bool immuneToAllEffects = true;
+ for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ uint32 effectName = auraSpellInfo->Effects[effIndex].Effect;
+ if (!effectName)
+ continue;
+
+ auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(static_cast<SpellEffects>(effectName));
+ if (spellImmuneItr == immuneInfo->SpellEffectImmune.cend())
+ {
+ immuneToAllEffects = false;
+ break;
+ }
+
+ if (uint32 mechanic = auraSpellInfo->Effects[effIndex].Mechanic)
+ {
+ if (!(immuneInfo->MechanicImmuneMask & (1 << mechanic)))
+ {
+ immuneToAllEffects = false;
+ break;
+ }
+ }
+
+ if (!auraSpellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
+ {
+ if (uint32 auraName = auraSpellInfo->Effects[effIndex].ApplyAuraName)
+ {
+ bool isImmuneToAuraEffectApply = false;
+ auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(static_cast<AuraType>(auraName));
+ if (auraImmuneItr != immuneInfo->AuraTypeImmune.cend())
+ isImmuneToAuraEffectApply = true;
+
+ if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(effIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ {
+ if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask)
+ if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0)
+ isImmuneToAuraEffectApply = true;
+ }
+
+ if (!isImmuneToAuraEffectApply)
+ {
+ immuneToAllEffects = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (immuneToAllEffects)
+ return true;
+ }
+
+ return false;
+}
+
+// based on client sub_007FDFA0
+bool SpellInfo::CanSpellCastOverrideAuraEffect(SpellInfo const* auraSpellInfo, uint8 auraEffIndex) const
+{
+ if (!HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ return false;
+
+ if (auraSpellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ return false;
+
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (Effects[i].Effect != SPELL_EFFECT_APPLY_AURA)
+ continue;
+
+ uint32 const miscValue = static_cast<uint32>(Effects[i].MiscValue);
+ switch (Effects[i].ApplyAuraName)
+ {
+ case SPELL_AURA_STATE_IMMUNITY:
+ if (miscValue != auraSpellInfo->Effects[auraEffIndex].ApplyAuraName)
+ continue;
+ break;
+ case SPELL_AURA_SCHOOL_IMMUNITY:
+ case SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL:
+ if (auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE) || !(auraSpellInfo->SchoolMask & miscValue))
+ continue;
+ break;
+ case SPELL_AURA_DISPEL_IMMUNITY:
+ if (miscValue != auraSpellInfo->Dispel)
+ continue;
+ break;
+ case SPELL_AURA_MECHANIC_IMMUNITY:
+ if (miscValue != auraSpellInfo->Mechanic)
+ {
+ if (miscValue != auraSpellInfo->Effects[auraEffIndex].Mechanic)
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
float SpellInfo::GetMinRange(bool positive) const
{
if (!RangeEntry)
@@ -2843,8 +3343,16 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
// Special case: effects which determine positivity of whole spell
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if (Effects[i].IsAura() && Effects[i].ApplyAuraName == SPELL_AURA_MOD_STEALTH)
- return true;
+ if (Effects[i].IsAura())
+ {
+ switch (Effects[i].ApplyAuraName)
+ {
+ case SPELL_AURA_MOD_STEALTH:
+ return true;
+ case SPELL_AURA_CHANNEL_DEATH_ITEM:
+ return false;
+ }
+ }
}
switch (Effects[effIndex].Effect)
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index b2566ecf533..d7b48ddb4d2 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -24,6 +24,8 @@
#include "Object.h"
#include "SpellAuraDefines.h"
+#include <boost/container/flat_set.hpp>
+
class Unit;
class Player;
class Item;
@@ -300,6 +302,18 @@ struct TC_GAME_API SpellDiminishInfo
int32 DiminishDurationLimit = 0;
};
+struct TC_GAME_API ImmunityInfo
+{
+ uint32 SchoolImmuneMask = 0;
+ uint32 ApplyHarmfulAuraImmuneMask = 0;
+ uint32 MechanicImmuneMask = 0;
+ uint32 DispelImmune = 0;
+ uint32 DamageSchoolMask = 0;
+
+ boost::container::flat_set<AuraType> AuraTypeImmune;
+ boost::container::flat_set<SpellEffects> SpellEffectImmune;
+};
+
class TC_GAME_API SpellInfo
{
friend class SpellMgr;
@@ -388,6 +402,7 @@ class TC_GAME_API SpellInfo
bool HasEffect(SpellEffects effect) const;
bool HasAura(AuraType aura) const;
bool HasAreaAuraEffect() const;
+ bool HasOnlyDamageEffects() const;
inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }
@@ -429,17 +444,21 @@ class TC_GAME_API SpellInfo
bool IsPositive() const;
bool IsPositiveEffect(uint8 effIndex) const;
bool IsChanneled() const;
+ bool IsMoveAllowedChannel() const;
bool NeedsComboPoints() const;
+ bool IsNextMeleeSwingSpell() const;
bool IsBreakingStealth() const;
bool IsRangedWeaponSpell() const;
bool IsAutoRepeatRangedSpell() const;
bool HasInitialAggro() const;
+ bool IsAffected(uint32 familyName, flag96 const& familyFlags) const;
+
bool IsAffectedBySpellMods() const;
bool IsAffectedBySpellMod(SpellModifier const* mod) const;
- bool CanPierceImmuneAura(SpellInfo const* aura) const;
- bool CanDispelAura(SpellInfo const* aura) const;
+ bool CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const;
+ bool CanDispelAura(SpellInfo const* auraSpellInfo) const;
bool IsSingleTarget() const;
bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const;
@@ -495,6 +514,11 @@ class TC_GAME_API SpellInfo
DiminishingLevels GetDiminishingReturnsMaxLevel(bool triggered) const;
int32 GetDiminishingReturnsLimitDuration(bool triggered) const;
+ // spell immunities
+ void ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool apply) const;
+ bool CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const;
+ bool CanSpellCastOverrideAuraEffect(SpellInfo const* auraSpellInfo, uint8 auraEffIndex) const;
+
private:
// loading helpers
void _InitializeExplicitTargetMask();
@@ -504,6 +528,7 @@ class TC_GAME_API SpellInfo
void _LoadSpellSpecific();
void _LoadAuraState();
void _LoadSpellDiminishInfo();
+ void _LoadImmunityInfo();
// unloading helpers
void _UnloadImplicitTargetConditionLists();
@@ -513,6 +538,8 @@ class TC_GAME_API SpellInfo
SpellDiminishInfo _diminishInfoNonTriggered;
SpellDiminishInfo _diminishInfoTriggered;
+
+ ImmunityInfo _immunityInfo[MAX_SPELL_EFFECTS];
};
#endif // _SPELLINFO_H
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 02584542676..bd13f1b2c7b 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -492,7 +492,7 @@ SpellProcEntry const* SpellMgr::GetSpellProcEntry(uint32 spellId) const
return NULL;
}
-bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const
+bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo)
{
// proc type doesn't match
if (!(eventInfo.GetTypeMask() & procEntry.ProcFlags))
@@ -535,20 +535,13 @@ bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcE
return false;
// check spell family name/flags (if set) for spells
- if (eventInfo.GetTypeMask() & (PERIODIC_PROC_FLAG_MASK | SPELL_PROC_FLAG_MASK | PROC_FLAG_DONE_TRAP_ACTIVATION))
+ if (eventInfo.GetTypeMask() & (PERIODIC_PROC_FLAG_MASK | SPELL_PROC_FLAG_MASK))
{
- SpellInfo const* eventSpellInfo = eventInfo.GetSpellInfo();
-
- if (procEntry.SpellFamilyName && eventSpellInfo && (procEntry.SpellFamilyName != eventSpellInfo->SpellFamilyName))
- return false;
-
- if (procEntry.SpellFamilyMask && eventSpellInfo && !(procEntry.SpellFamilyMask & eventSpellInfo->SpellFamilyFlags))
- return false;
- }
+ if (SpellInfo const* eventSpellInfo = eventInfo.GetSpellInfo())
+ if (!eventSpellInfo->IsAffected(procEntry.SpellFamilyName, procEntry.SpellFamilyMask))
+ return false;
- // check spell type mask (if set)
- if (eventInfo.GetTypeMask() & (SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK))
- {
+ // check spell type mask (if set)
if (procEntry.SpellTypeMask && !(eventInfo.GetSpellTypeMask() & procEntry.SpellTypeMask))
return false;
}
@@ -1524,6 +1517,9 @@ void SpellMgr::LoadSpellProcs()
TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `HitMask` set: %u", spellInfo->Id, procEntry.HitMask);
if (procEntry.HitMask && !(procEntry.ProcFlags & TAKEN_HIT_PROC_FLAG_MASK || (procEntry.ProcFlags & DONE_HIT_PROC_FLAG_MASK && (!procEntry.SpellPhaseMask || procEntry.SpellPhaseMask & (PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH)))))
TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `HitMask` value defined, but it will not be used for defined `ProcFlags` and `SpellPhaseMask` values.", spellInfo->Id);
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if ((procEntry.AttributesMask & (PROC_ATTR_DISABLE_EFF_0 << i)) && !spellInfo->Effects[i].IsAura())
+ TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has Attribute PROC_ATTR_DISABLE_EFF_%u, but effect %u is not an aura effect", spellInfo->Id, static_cast<uint32>(i), static_cast<uint32>(i));
mSpellProcMap[spellInfo->Id] = procEntry;
@@ -1593,6 +1589,8 @@ void SpellMgr::LoadSpellProcs()
isTriggerAura[SPELL_AURA_ABILITY_IGNORE_AURASTATE] = true;
isAlwaysTriggeredAura[SPELL_AURA_OVERRIDE_CLASS_SCRIPTS] = true;
+ isAlwaysTriggeredAura[SPELL_AURA_MOD_STEALTH] = true;
+ isAlwaysTriggeredAura[SPELL_AURA_MOD_CONFUSE] = true;
isAlwaysTriggeredAura[SPELL_AURA_MOD_FEAR] = true;
isAlwaysTriggeredAura[SPELL_AURA_MOD_ROOT] = true;
isAlwaysTriggeredAura[SPELL_AURA_MOD_STUN] = true;
@@ -1615,9 +1613,14 @@ void SpellMgr::LoadSpellProcs()
if (!spellInfo)
continue;
+ // Data already present in DB, overwrites default proc
if (mSpellProcMap.find(spellInfo->Id) != mSpellProcMap.end())
continue;
+ // Nothing to do if no flags set
+ if (!spellInfo->ProcFlags)
+ continue;
+
bool addTriggerFlag = false;
uint32 procSpellTypeMask = PROC_SPELL_TYPE_NONE;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -1635,15 +1638,27 @@ void SpellMgr::LoadSpellProcs()
procSpellTypeMask |= spellTypeMask[auraName];
if (isAlwaysTriggeredAura[auraName])
addTriggerFlag = true;
+
+ // many proc auras with taken procFlag mask don't have attribute "can proc with triggered"
+ // they should proc nevertheless (example mage armor spells with judgement)
+ if (!addTriggerFlag && (spellInfo->ProcFlags & TAKEN_HIT_PROC_FLAG_MASK) != 0)
+ {
+ switch (auraName)
+ {
+ case SPELL_AURA_PROC_TRIGGER_SPELL:
+ case SPELL_AURA_PROC_TRIGGER_DAMAGE:
+ addTriggerFlag = true;
+ break;
+ default:
+ break;
+ }
+ }
break;
}
if (!procSpellTypeMask)
continue;
- if (!spellInfo->ProcFlags)
- continue;
-
SpellProcEntry procEntry;
procEntry.SchoolMask = 0;
procEntry.ProcFlags = spellInfo->ProcFlags;
@@ -2603,6 +2618,8 @@ void SpellMgr::LoadSpellInfoCorrections()
case 2895: // Wrath of Air Totem rank 1 (Aura)
case 68933: // Wrath of Air Totem rank 2 (Aura)
case 29200: // Purify Helboar Meat
+ case 10872: // Abolish Disease Effect
+ case 3137: // Abolish Poison Effect
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo();
break;
@@ -2630,6 +2647,15 @@ void SpellMgr::LoadSpellInfoCorrections()
// because of bug in dbc
spellInfo->ProcChance = 0;
break;
+ case 51528: // Maelstrom Weapon (Rank 1)
+ case 51529: // Maelstrom Weapon (Rank 2)
+ case 51530: // Maelstrom Weapon (Rank 3)
+ case 51531: // Maelstrom Weapon (Rank 4)
+ case 51532: // Maelstrom Weapon (Rank 5)
+ // due to discrepancies between ranks
+ spellInfo->EquippedItemSubClassMask = 0x0000FC33;
+ spellInfo->AttributesEx3 |= SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED;
+ break;
case 20335: // Heart of the Crusader
case 20336:
case 20337:
@@ -2755,15 +2781,14 @@ void SpellMgr::LoadSpellInfoCorrections()
case 44544: // Fingers of Frost
spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(685904631, 1151048, 0);
break;
- case 53257: // Cobra Strikes
- spellInfo->ProcCharges = 2;
- spellInfo->StackAmount = 0;
- break;
case 49224: // Magic Suppression - DK
case 49610: // Magic Suppression - DK
case 49611: // Magic Suppression - DK
spellInfo->ProcCharges = 0;
break;
+ case 52212: // Death and Decay
+ spellInfo->AttributesEx6 |= SPELL_ATTR6_CAN_TARGET_INVISIBLE;
+ break;
case 37408: // Oscillation Field
spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
break;
@@ -2843,6 +2868,19 @@ void SpellMgr::LoadSpellInfoCorrections()
case 27915: // Anchor to Skulls
case 27931: // Anchor to Skulls
case 27937: // Anchor to Skulls
+ case 16177: // Ancestral Fortitude (Rank 1)
+ case 16236: // Ancestral Fortitude (Rank 2)
+ case 16237: // Ancestral Fortitude (Rank 3)
+ case 47930: // Grace
+ case 45145: // Snake Trap Effect (Rank 1)
+ case 13812: // Explosive Trap Effect (Rank 1)
+ case 14314: // Explosive Trap Effect (Rank 2)
+ case 14315: // Explosive Trap Effect (Rank 3)
+ case 27026: // Explosive Trap Effect (Rank 4)
+ case 49064: // Explosive Trap Effect (Rank 5)
+ case 49065: // Explosive Trap Effect (Rank 6)
+ case 43446: // Explosive Trap Effect (Hexlord Malacrass)
+ case 68979: // Unleashed Souls
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13);
break;
// target allys instead of enemies, target A is src_caster, spells with effect like that have ally target
@@ -2950,9 +2988,6 @@ void SpellMgr::LoadSpellInfoCorrections()
case 71839: // Drain Life - Bryntroll Heroic
spellInfo->AttributesEx2 |= SPELL_ATTR2_CANT_CRIT;
break;
- case 34471: // The Beast Within
- spellInfo->AttributesEx5 |= SPELL_ATTR5_USABLE_WHILE_CONFUSED | SPELL_ATTR5_USABLE_WHILE_FEARED | SPELL_ATTR5_USABLE_WHILE_STUNNED;
- break;
case 56606: // Ride Jokkum
case 61791: // Ride Vehicle (Yogg-Saron)
/// @todo: remove this when basepoints of all Ride Vehicle auras are calculated correctly
@@ -3004,6 +3039,10 @@ void SpellMgr::LoadSpellInfoCorrections()
case 68766: // Desecration (Rank 2)
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(2); // Melee Range
break;
+ case 46946: // Safeguard (Rank 1)
+ case 46947: // Safeguard (Rank 2)
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(34); // Twenty-Five yards
+ break;
// VIOLET HOLD SPELLS
//
case 54258: // Water Globule (Ichoron)
@@ -3488,3 +3527,18 @@ void SpellMgr::LoadSpellInfoDiminishing()
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo diminishing infos in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
+
+void SpellMgr::LoadSpellInfoImmunities()
+{
+ uint32 oldMSTime = getMSTime();
+
+ for (SpellInfo* spellInfo : mSpellInfoMap)
+ {
+ if (!spellInfo)
+ continue;
+
+ spellInfo->_LoadImmunityInfo();
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded SpellInfo immunity infos in %u ms", GetMSTimeDiffToNow(oldMSTime));
+}
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index f119d164789..a08ff921a2e 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -165,9 +165,8 @@ enum ProcFlags
| PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS | PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_POS
| PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG | PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG
| PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS
- | PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG | PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG,
-
- SPELL_CAST_PROC_FLAG_MASK = SPELL_PROC_FLAG_MASK | PROC_FLAG_DONE_TRAP_ACTIVATION,
+ | PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG | PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG
+ | PROC_FLAG_DONE_TRAP_ACTIVATION,
PERIODIC_PROC_FLAG_MASK = PROC_FLAG_DONE_PERIODIC | PROC_FLAG_TAKEN_PERIODIC,
@@ -175,7 +174,8 @@ enum ProcFlags
| PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS | PROC_FLAG_DONE_SPELL_RANGED_DMG_CLASS
| PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG
| PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG
- | PROC_FLAG_DONE_PERIODIC | PROC_FLAG_DONE_MAINHAND_ATTACK | PROC_FLAG_DONE_OFFHAND_ATTACK,
+ | PROC_FLAG_DONE_PERIODIC | PROC_FLAG_DONE_TRAP_ACTIVATION
+ | PROC_FLAG_DONE_MAINHAND_ATTACK | PROC_FLAG_DONE_OFFHAND_ATTACK,
TAKEN_HIT_PROC_FLAG_MASK = PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK | PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK
| PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS | PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS
@@ -238,7 +238,11 @@ enum ProcAttributes
PROC_ATTR_REQ_EXP_OR_HONOR = 0x0000001, // requires proc target to give exp or honor for aura proc
PROC_ATTR_TRIGGERED_CAN_PROC = 0x0000002, // aura can proc even with triggered spells
PROC_ATTR_REQ_MANA_COST = 0x0000004, // requires triggering spell to have a mana cost for aura proc
- PROC_ATTR_REQ_SPELLMOD = 0x0000008 // requires triggering spell to be affected by proccing aura to drop charges
+ PROC_ATTR_REQ_SPELLMOD = 0x0000008, // requires triggering spell to be affected by proccing aura to drop charges
+
+ PROC_ATTR_DISABLE_EFF_0 = 0x0000010, // explicitly disables aura proc from effects, USE ONLY IF 100% SURE AURA SHOULDN'T PROC
+ PROC_ATTR_DISABLE_EFF_1 = 0x0000020, // used to avoid a console error if the spell has invalid trigger spell and handled elsewhere
+ PROC_ATTR_DISABLE_EFF_2 = 0x0000040 // or handling not needed
};
struct SpellProcEntry
@@ -606,7 +610,7 @@ class TC_GAME_API SpellMgr
// Spell proc table
SpellProcEntry const* GetSpellProcEntry(uint32 spellId) const;
- bool CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
+ static bool CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo);
// Spell bonus data table
SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const;
@@ -680,6 +684,7 @@ class TC_GAME_API SpellMgr
void LoadSpellInfoCorrections();
void LoadSpellInfoSpellSpecificAndAuraState();
void LoadSpellInfoDiminishing();
+ void LoadSpellInfoImmunities();
private:
SpellDifficultySearcherMap mSpellDifficultySearcherMap;
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 67aaa582776..950456394d8 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -301,35 +301,35 @@ void SpellScript::DestinationTargetSelectHandler::Call(SpellScript* spellScript,
bool SpellScript::_Validate(SpellInfo const* entry)
{
- for (std::list<EffectHandler>::iterator itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr)
+ for (auto itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectLaunch` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectHandler>::iterator itr = OnEffectLaunchTarget.begin(); itr != OnEffectLaunchTarget.end(); ++itr)
+ for (auto itr = OnEffectLaunchTarget.begin(); itr != OnEffectLaunchTarget.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectLaunchTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectHandler>::iterator itr = OnEffectHit.begin(); itr != OnEffectHit.end(); ++itr)
+ for (auto itr = OnEffectHit.begin(); itr != OnEffectHit.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectHit` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectHandler>::iterator itr = OnEffectHitTarget.begin(); itr != OnEffectHitTarget.end(); ++itr)
+ for (auto itr = OnEffectHitTarget.begin(); itr != OnEffectHitTarget.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectHitTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectHandler>::iterator itr = OnEffectSuccessfulDispel.begin(); itr != OnEffectSuccessfulDispel.end(); ++itr)
+ for (auto itr = OnEffectSuccessfulDispel.begin(); itr != OnEffectSuccessfulDispel.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSuccessfulDispel` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<ObjectAreaTargetSelectHandler>::iterator itr = OnObjectAreaTargetSelect.begin(); itr != OnObjectAreaTargetSelect.end(); ++itr)
+ for (auto itr = OnObjectAreaTargetSelect.begin(); itr != OnObjectAreaTargetSelect.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<ObjectTargetSelectHandler>::iterator itr = OnObjectTargetSelect.begin(); itr != OnObjectTargetSelect.end(); ++itr)
+ for (auto itr = OnObjectTargetSelect.begin(); itr != OnObjectTargetSelect.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<DestinationTargetSelectHandler>::iterator itr = OnDestinationTargetSelect.begin(); itr != OnDestinationTargetSelect.end(); ++itr)
+ for (auto itr = OnDestinationTargetSelect.begin(); itr != OnDestinationTargetSelect.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnDestinationTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
@@ -624,9 +624,9 @@ SpellInfo const* SpellScript::GetTriggeringSpell()
return m_spell->m_triggeredByAuraSpell;
}
-void SpellScript::FinishCast(SpellCastResult result)
+void SpellScript::FinishCast(SpellCastResult result, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/)
{
- m_spell->SendCastResult(result);
+ m_spell->SendCastResult(result, param1, param2);
m_spell->finish(result == SPELL_CAST_OK);
}
@@ -648,99 +648,99 @@ SpellValue const* SpellScript::GetSpellValue()
bool AuraScript::_Validate(SpellInfo const* entry)
{
- for (std::list<CheckAreaTargetHandler>::iterator itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr)
+ for (auto itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr)
if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && !entry->HasEffect(SPELL_EFFECT_APPLY_AURA))
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr)
+ for (auto itr = OnDispel.begin(); itr != OnDispel.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<AuraDispelHandler>::iterator itr = AfterDispel.begin(); itr != AfterDispel.end(); ++itr)
+ for (auto itr = AfterDispel.begin(); itr != AfterDispel.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr)
+ for (auto itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectApply` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectApplyHandler>::iterator itr = OnEffectRemove.begin(); itr != OnEffectRemove.end(); ++itr)
+ for (auto itr = OnEffectRemove.begin(); itr != OnEffectRemove.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectRemove` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectApplyHandler>::iterator itr = AfterEffectApply.begin(); itr != AfterEffectApply.end(); ++itr)
+ for (auto itr = AfterEffectApply.begin(); itr != AfterEffectApply.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectApply` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectApplyHandler>::iterator itr = AfterEffectRemove.begin(); itr != AfterEffectRemove.end(); ++itr)
+ for (auto itr = AfterEffectRemove.begin(); itr != AfterEffectRemove.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectRemove` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectPeriodicHandler>::iterator itr = OnEffectPeriodic.begin(); itr != OnEffectPeriodic.end(); ++itr)
+ for (auto itr = OnEffectPeriodic.begin(); itr != OnEffectPeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectPeriodic` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectUpdatePeriodicHandler>::iterator itr = OnEffectUpdatePeriodic.begin(); itr != OnEffectUpdatePeriodic.end(); ++itr)
+ for (auto itr = OnEffectUpdatePeriodic.begin(); itr != OnEffectUpdatePeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectUpdatePeriodic` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectCalcAmountHandler>::iterator itr = DoEffectCalcAmount.begin(); itr != DoEffectCalcAmount.end(); ++itr)
+ for (auto itr = DoEffectCalcAmount.begin(); itr != DoEffectCalcAmount.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `DoEffectCalcAmount` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectCalcPeriodicHandler>::iterator itr = DoEffectCalcPeriodic.begin(); itr != DoEffectCalcPeriodic.end(); ++itr)
+ for (auto itr = DoEffectCalcPeriodic.begin(); itr != DoEffectCalcPeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `DoEffectCalcPeriodic` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectCalcSpellModHandler>::iterator itr = DoEffectCalcSpellMod.begin(); itr != DoEffectCalcSpellMod.end(); ++itr)
+ for (auto itr = DoEffectCalcSpellMod.begin(); itr != DoEffectCalcSpellMod.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `DoEffectCalcSpellMod` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectAbsorbHandler>::iterator itr = OnEffectAbsorb.begin(); itr != OnEffectAbsorb.end(); ++itr)
+ for (auto itr = OnEffectAbsorb.begin(); itr != OnEffectAbsorb.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectAbsorb` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectAbsorbHandler>::iterator itr = AfterEffectAbsorb.begin(); itr != AfterEffectAbsorb.end(); ++itr)
+ for (auto itr = AfterEffectAbsorb.begin(); itr != AfterEffectAbsorb.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectAbsorb` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectManaShieldHandler>::iterator itr = OnEffectManaShield.begin(); itr != OnEffectManaShield.end(); ++itr)
+ for (auto itr = OnEffectManaShield.begin(); itr != OnEffectManaShield.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectManaShield` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectManaShieldHandler>::iterator itr = AfterEffectManaShield.begin(); itr != AfterEffectManaShield.end(); ++itr)
+ for (auto itr = AfterEffectManaShield.begin(); itr != AfterEffectManaShield.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectManaShield` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectSplitHandler>::iterator itr = OnEffectSplit.begin(); itr != OnEffectSplit.end(); ++itr)
+ for (auto itr = OnEffectSplit.begin(); itr != OnEffectSplit.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<CheckProcHandler>::iterator itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr)
+ for (auto itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<CheckEffectProcHandler>::iterator itr = DoCheckEffectProc.begin(); itr != DoCheckEffectProc.end(); ++itr)
+ for (auto itr = DoCheckEffectProc.begin(); itr != DoCheckEffectProc.end(); ++itr)
if (!itr->GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `DoCheckEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString().c_str(), m_scriptName->c_str());
- for (std::list<AuraProcHandler>::iterator itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr)
+ for (auto itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<AuraProcHandler>::iterator itr = OnProc.begin(); itr != OnProc.end(); ++itr)
+ for (auto itr = OnProc.begin(); itr != OnProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<AuraProcHandler>::iterator itr = AfterProc.begin(); itr != AfterProc.end(); ++itr)
+ for (auto itr = AfterProc.begin(); itr != AfterProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
- for (std::list<EffectProcHandler>::iterator itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr)
+ for (auto itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectProcHandler>::iterator itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr)
+ for (auto itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 1ec10f03820..af30b6a7879 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -63,9 +63,9 @@ class TC_GAME_API _SpellScript
public:
_SpellScript() : m_currentScriptState(SPELL_SCRIPT_STATE_NONE), m_scriptName(NULL), m_scriptSpellId(0) {}
virtual ~_SpellScript() { }
- virtual void _Register();
- virtual void _Unload();
- virtual void _Init(std::string const* scriptname, uint32 spellId);
+ void _Register();
+ void _Unload();
+ void _Init(std::string const* scriptname, uint32 spellId);
std::string const* _GetScriptName() const;
protected:
@@ -441,7 +441,7 @@ class TC_GAME_API SpellScript : public _SpellScript
SpellInfo const* GetTriggeringSpell();
// finishes spellcast prematurely with selected error message
- void FinishCast(SpellCastResult result);
+ void FinishCast(SpellCastResult result, uint32* param1 = nullptr, uint32* param2 = nullptr);
void SetCustomCastResultMessage(SpellCustomErrors result);
};
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 59a1e757183..7bbf73d028d 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1449,12 +1449,12 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading SpellInfo custom attributes...");
sSpellMgr->LoadSpellInfoCustomAttributes();
- TC_LOG_INFO("server.loading", "Loading SpellInfo SpellSpecific and AuraState...");
- sSpellMgr->LoadSpellInfoSpellSpecificAndAuraState();
-
TC_LOG_INFO("server.loading", "Loading SpellInfo diminishing infos...");
sSpellMgr->LoadSpellInfoDiminishing();
+ TC_LOG_INFO("server.loading", "Loading SpellInfo immunity infos...");
+ sSpellMgr->LoadSpellInfoImmunities();
+
TC_LOG_INFO("server.loading", "Loading GameObject models...");
LoadGameObjectModelList(m_dataPath);
@@ -1514,6 +1514,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Spell Learn Skills...");
sSpellMgr->LoadSpellLearnSkills(); // must be after LoadSpellRanks
+ TC_LOG_INFO("server.loading", "Loading SpellInfo SpellSpecific and AuraState...");
+ sSpellMgr->LoadSpellInfoSpellSpecificAndAuraState(); // must be after LoadSpellRanks
+
TC_LOG_INFO("server.loading", "Loading Spell Learn Spells...");
sSpellMgr->LoadSpellLearnSpells();
diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp
index 44c606a360f..45e6c65cc6b 100644
--- a/src/server/scripts/Commands/cs_cast.cpp
+++ b/src/server/scripts/Commands/cs_cast.cpp
@@ -99,8 +99,7 @@ public:
return false;
}
- bool triggered = (triggeredStr != NULL);
-
+ TriggerCastFlags triggered = (triggeredStr != NULL) ? TRIGGERED_FULL_DEBUG_MASK : TRIGGERED_NONE;
handler->GetSession()->GetPlayer()->CastSpell(target, spellId, triggered);
return true;
@@ -132,8 +131,7 @@ public:
return false;
}
- bool triggered = (triggeredStr != NULL);
-
+ TriggerCastFlags triggered = (triggeredStr != NULL) ? TRIGGERED_FULL_DEBUG_MASK : TRIGGERED_NONE;
caster->CastSpell(handler->GetSession()->GetPlayer(), spellId, triggered);
return true;
@@ -167,8 +165,7 @@ public:
return false;
}
- bool triggered = (triggeredStr != NULL);
-
+ TriggerCastFlags triggered = (triggeredStr != NULL) ? TRIGGERED_FULL_DEBUG_MASK : TRIGGERED_NONE;
float x, y, z;
handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, dist);
@@ -230,8 +227,7 @@ public:
return false;
}
- bool triggered = (triggeredStr != NULL);
-
+ TriggerCastFlags triggered = (triggeredStr != NULL) ? TRIGGERED_FULL_DEBUG_MASK : TRIGGERED_NONE;
caster->CastSpell(caster->GetVictim(), spellId, triggered);
return true;
@@ -274,8 +270,7 @@ public:
return false;
}
- bool triggered = (triggeredStr != NULL);
-
+ TriggerCastFlags triggered = (triggeredStr != NULL) ? TRIGGERED_FULL_DEBUG_MASK : TRIGGERED_NONE;
caster->CastSpell(x, y, z, spellId, triggered);
return true;
diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp
index 98fc852b573..8c4bf73395d 100644
--- a/src/server/scripts/Commands/cs_guild.cpp
+++ b/src/server/scripts/Commands/cs_guild.cpp
@@ -146,7 +146,8 @@ public:
return false;
// player's guild membership checked in AddMember before add
- return targetGuild->AddMember(targetGuid);
+ SQLTransaction trans(nullptr);
+ return targetGuild->AddMember(trans, targetGuid);
}
static bool HandleGuildUninviteCommand(ChatHandler* handler, char const* args)
@@ -164,7 +165,8 @@ public:
if (!targetGuild)
return false;
- targetGuild->DeleteMember(targetGuid, false, true, true);
+ SQLTransaction trans(nullptr);
+ targetGuild->DeleteMember(trans, targetGuid, false, true, true);
return true;
}
@@ -191,7 +193,8 @@ public:
return false;
uint8 newRank = uint8(atoi(rankStr));
- return targetGuild->ChangeMemberRank(targetGuid, newRank);
+ SQLTransaction trans(nullptr);
+ return targetGuild->ChangeMemberRank(trans, targetGuid, newRank);
}
static bool HandleGuildRenameCommand(ChatHandler* handler, char const* _args)
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 16217fbaea6..5487b9c7b2f 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -2268,19 +2268,20 @@ public:
// melee damage by specific school
if (!spellStr)
{
- uint32 absorb = 0;
- uint32 resist = 0;
+ Player* attacker = handler->GetSession()->GetPlayer();
+ DamageInfo dmgInfo(attacker, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK);
+ attacker->CalcAbsorbResist(dmgInfo);
- handler->GetSession()->GetPlayer()->CalcAbsorbResist(target, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
-
- if (damage <= absorb + resist)
+ if (!dmgInfo.GetDamage())
return true;
- damage -= absorb + resist;
+ damage = dmgInfo.GetDamage();
- handler->GetSession()->GetPlayer()->DealDamageMods(target, damage, &absorb);
- handler->GetSession()->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false);
- handler->GetSession()->GetPlayer()->SendAttackStateUpdate (HITINFO_AFFECTS_VICTIM, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0);
+ uint32 absorb = dmgInfo.GetAbsorb();
+ uint32 resist = dmgInfo.GetResist();
+ attacker->DealDamageMods(target, damage, &absorb);
+ attacker->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false);
+ attacker->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0);
return true;
}
@@ -2288,10 +2289,22 @@ public:
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
uint32 spellid = handler->extractSpellIdFromLink((char*)args);
- if (!spellid || !sSpellMgr->GetSpellInfo(spellid))
+ if (!spellid)
+ return false;
+
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
+ if (!spellInfo)
return false;
- handler->GetSession()->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage);
+ Player* attacker = handler->GetSession()->GetPlayer();
+ SpellNonMeleeDamage dmgInfo(attacker, target, spellid, spellInfo->GetSchoolMask());
+ damage = attacker->SpellDamageBonusDone(target, spellInfo, damage, SPELL_DIRECT_DAMAGE);
+ damage = target->SpellDamageBonusTaken(attacker, spellInfo, damage, SPELL_DIRECT_DAMAGE);
+
+ attacker->CalculateSpellDamageTaken(&dmgInfo, damage, spellInfo);
+ attacker->DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb);
+ attacker->SendSpellNonMeleeDamageLog(&dmgInfo);
+ attacker->DealSpellDamage(&dmgInfo, true);
return true;
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
index a43e2ee37dd..89617a9f4ef 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
@@ -578,7 +578,7 @@ public:
bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
{
- if (player && player->IsAlive())
+ if (player->IsAlive())
if (InstanceScript* instance = player->GetInstanceScript())
if (Creature* infiltrator = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_SCARSHIELD_INFILTRATOR)))
{
diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
index d0430ebb3e5..67bda699643 100644
--- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
+++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
@@ -54,7 +54,6 @@ enum Yells
enum Spells
{
SPELL_UNLOCK = 6421,
-
SPELL_DARK_OFFERING = 7154
};
@@ -205,6 +204,123 @@ public:
};
+enum ArugalSpells
+{
+ SPELL_TELE_UPPER = 7587,
+ SPELL_TELE_SPAWN = 7586,
+ SPELL_TELE_STAIRS = 7136,
+ NUM_TELEPORT_SPELLS = 3,
+ SPELL_ARUGAL_CURSE = 7621,
+ SPELL_THUNDERSHOCK = 7803,
+ SPELL_VOIDBOLT = 7588
+};
+
+enum ArugalTexts
+{
+ SAY_AGGRO = 1, // You, too, shall serve!
+ SAY_TRANSFORM = 2, // Release your rage!
+ SAY_SLAY = 3 // Another falls!
+};
+
+enum ArugalEvents
+{
+ EVENT_VOID_BOLT = 1,
+ EVENT_TELEPORT,
+ EVENT_THUNDERSHOCK,
+ EVENT_CURSE
+};
+
+class boss_archmage_arugal : public CreatureScript
+{
+ public:
+ boss_archmage_arugal() : CreatureScript("boss_archmage_arugal") { }
+
+ struct boss_archmage_arugalAI : public BossAI
+ {
+ boss_archmage_arugalAI(Creature* creature) : BossAI(creature, BOSS_ARUGAL) { }
+
+ uint32 teleportSpells[NUM_TELEPORT_SPELLS] =
+ {
+ SPELL_TELE_SPAWN,
+ SPELL_TELE_UPPER,
+ SPELL_TELE_STAIRS
+ };
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
+
+ void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_ARUGAL_CURSE)
+ Talk(SAY_TRANSFORM);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_CURSE, Seconds(7));
+ events.ScheduleEvent(EVENT_TELEPORT, Seconds(15));
+ events.ScheduleEvent(EVENT_VOID_BOLT, Seconds(1));
+ events.ScheduleEvent(EVENT_THUNDERSHOCK, Seconds(10));
+ }
+
+ void AttackStart(Unit* who) override
+ {
+ AttackStartCaster(who, 100.0f); // void bolt range is 100.f
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CURSE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 30.0f, true))
+ DoCast(target, SPELL_ARUGAL_CURSE);
+ events.Repeat(Seconds(15));
+ break;
+ case EVENT_TELEPORT:
+ {
+ // ensure we never cast the same teleport twice in a row
+ uint8 spellIndex = urand(1, NUM_TELEPORT_SPELLS-1);
+ std::swap(teleportSpells[0], teleportSpells[spellIndex]);
+ DoCast(teleportSpells[0]);
+ events.Repeat(Seconds(20));
+ break;
+ }
+ case EVENT_THUNDERSHOCK:
+ DoCastAOE(SPELL_THUNDERSHOCK);
+ events.Repeat(Seconds(30));
+ break;
+ case EVENT_VOID_BOLT:
+ DoCastVictim(SPELL_VOIDBOLT);
+ events.Repeat(Seconds(5));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_archmage_arugalAI>(creature);
+ }
+};
+
class spell_shadowfang_keep_haunting_spirits : public SpellScriptLoader
{
public:
@@ -248,5 +364,6 @@ void AddSC_shadowfang_keep()
{
new npc_shadowfang_prisoner();
new npc_arugal_voidwalker();
+ new boss_archmage_arugal();
new spell_shadowfang_keep_haunting_spirits();
}
diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h
index 88edc3f1ee1..7e508191f69 100644
--- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h
+++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h
@@ -26,8 +26,8 @@ enum DataTypes
TYPE_FREE_NPC = 1,
TYPE_RETHILGORE = 2,
TYPE_FENRUS = 3,
- TYPE_NANDOS = 4
+ TYPE_NANDOS = 4,
+ BOSS_ARUGAL = 5
};
#endif
-
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index adcb4f9fc9a..d9c929794cc 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -175,7 +175,7 @@ void AddSC_arathi_highlands();
void AddSC_blasted_lands();
void AddSC_burning_steppes();
void AddSC_duskwood();
-void AddSC_eastern_plaguelands();
+//void AddSC_eastern_plaguelands();
void AddSC_ghostlands();
void AddSC_hinterlands();
void AddSC_isle_of_queldanas();
@@ -352,7 +352,7 @@ void AddEasternKingdomsScripts()
AddSC_blasted_lands();
AddSC_burning_steppes();
AddSC_duskwood();
- AddSC_eastern_plaguelands();
+ //AddSC_eastern_plaguelands();
AddSC_ghostlands();
AddSC_hinterlands();
AddSC_isle_of_queldanas();
diff --git a/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp
deleted file mode 100644
index c35c8629cef..00000000000
--- a/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Eastern_Plaguelands
-SD%Complete: 100
-SDComment: Quest support: 5211. Special vendor Augustus the Touched
-SDCategory: Eastern Plaguelands
-EndScriptData */
-
-/* ContentData
-npc_ghoul_flayer
-npc_augustus_the_touched
-npc_darrowshire_spirit
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "Player.h"
-#include "WorldSession.h"
-
-class npc_ghoul_flayer : public CreatureScript
-{
-public:
- npc_ghoul_flayer() : CreatureScript("npc_ghoul_flayer") { }
-
- struct npc_ghoul_flayerAI : public ScriptedAI
- {
- npc_ghoul_flayerAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- void JustDied(Unit* killer) override
- {
- if (killer->GetTypeId() == TYPEID_PLAYER)
- me->SummonCreature(11064, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000);
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_ghoul_flayerAI(creature);
- }
-};
-
-/*######
-## npc_augustus_the_touched
-######*/
-
-class npc_augustus_the_touched : public CreatureScript
-{
-public:
- npc_augustus_the_touched() : CreatureScript("npc_augustus_the_touched") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
- {
- ClearGossipMenuFor(player);
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(creature->GetGUID());
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (creature->IsVendor() && player->GetQuestRewardStatus(6164))
- AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
- return true;
- }
-};
-
-/*######
-## npc_darrowshire_spirit
-######*/
-
-enum DarrowshireSpirit
-{
- SPELL_SPIRIT_SPAWNIN = 17321
-};
-
-class npc_darrowshire_spirit : public CreatureScript
-{
-public:
- npc_darrowshire_spirit() : CreatureScript("npc_darrowshire_spirit") { }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- SendGossipMenuFor(player, 3873, creature->GetGUID());
- player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_darrowshire_spiritAI(creature);
- }
-
- struct npc_darrowshire_spiritAI : public ScriptedAI
- {
- npc_darrowshire_spiritAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override
- {
- DoCast(me, SPELL_SPIRIT_SPAWNIN);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
-
- void EnterCombat(Unit* /*who*/) override { }
- };
-};
-
-void AddSC_eastern_plaguelands()
-{
- new npc_ghoul_flayer();
- new npc_augustus_the_touched();
- new npc_darrowshire_spirit();
-}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
index 5d41908435e..722b7768617 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
@@ -279,7 +279,7 @@ class spell_anetheron_vampiric_aura : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
@@ -287,7 +287,7 @@ class spell_anetheron_vampiric_aura : public SpellScriptLoader
return;
int32 bp = damageInfo->GetDamage() * 3;
- eventInfo.GetActor()->CastCustomSpell(SPELL_VAMPIRIC_AURA_HEAL, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetActor(), true);
+ eventInfo.GetActor()->CastCustomSpell(SPELL_VAMPIRIC_AURA_HEAL, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetActor(), true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index 3bc3ec45e5f..976ef3e34db 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -417,8 +417,9 @@ class npc_snobold_vassal : public CreatureScript
switch (eventId)
{
case EVENT_FIRE_BOMB:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -me->GetVehicleBase()->GetCombatReach(), true))
- me->CastSpell(target, SPELL_FIRE_BOMB);
+ if (me->GetVehicleBase())
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -me->GetVehicleBase()->GetCombatReach(), true))
+ me->CastSpell(target, SPELL_FIRE_BOMB);
_events.Repeat(Seconds(20));
break;
case EVENT_HEAD_CRACK:
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 77805dbfcb2..15e4885d4a7 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -1115,7 +1115,7 @@ class spell_putricide_ooze_tank_protection : public SpellScriptLoader
PreventDefaultAction();
Unit* actionTarget = eventInfo.GetActionTarget();
- actionTarget->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true);
+ actionTarget->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index a2348119dff..f3021cdbab5 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -1099,6 +1099,12 @@ class spell_sindragosa_s_fury : public SpellScriptLoader
if (!GetHitUnit()->IsAlive() || !_targetCount)
return;
+ if (GetHitUnit()->IsImmunedToDamage(GetSpellInfo()))
+ {
+ GetCaster()->SendSpellDamageImmune(GetHitUnit(), GetSpellInfo()->Id);
+ return;
+ }
+
float resistance = float(GetHitUnit()->GetResistance(SpellSchoolMask(GetSpellInfo()->SchoolMask)));
uint32 minResistFactor = uint32((resistance / (resistance + 510.0f)) * 10.0f) * 2;
uint32 randomResist = urand(0, (9 - minResistFactor) * 100) / 100 + minResistFactor;
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp
index b25f7ed3eca..82abb2836ba 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp
@@ -222,11 +222,11 @@ class spell_uk_second_wind : public SpellScriptLoader
return (spellInfo->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN))) != 0;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActionTarget();
- caster->CastSpell(caster, SPELL_SECOND_WIND_TRIGGER, true);
+ caster->CastSpell(caster, SPELL_SECOND_WIND_TRIGGER, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp
index c22cd2d9ad7..cb5a7462000 100644
--- a/src/server/scripts/Northrend/zone_dragonblight.cpp
+++ b/src/server/scripts/Northrend/zone_dragonblight.cpp
@@ -701,6 +701,31 @@ class npc_torturer_lecraft : public CreatureScript
}
};
+enum MessengerTorvus
+{
+ NPC_MESSENGER_TORVUS = 26649,
+ QUEST_MESSAGE_FROM_THE_WEST = 12033,
+
+ TALK_0 = 0
+};
+
+class at_nearby_messenger_torvus : public AreaTriggerScript
+{
+public:
+ at_nearby_messenger_torvus() : AreaTriggerScript("at_nearby_messenger_torvus") { }
+
+ bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
+ {
+ if (player->IsAlive())
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(QUEST_MESSAGE_FROM_THE_WEST))
+ if (player->CanTakeQuest(quest, false))
+ if (Creature* creature = player->FindNearestCreature(NPC_MESSENGER_TORVUS, 50.0f, true))
+ creature->AI()->Talk(TALK_0, player);
+
+ return true;
+ }
+};
+
void AddSC_dragonblight()
{
new npc_commander_eligor_dawnbringer();
@@ -708,4 +733,5 @@ void AddSC_dragonblight()
new spell_q12096_q12092_bark();
new npc_wyrmrest_defender();
new npc_torturer_lecraft();
+ new at_nearby_messenger_torvus();
}
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 2effc1d9a2a..54ae9c27aeb 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -281,6 +281,7 @@ public:
void UpdateAI(uint32 diff) override
{
+ VehicleAI::UpdateAI(diff);
events.Update(diff);
switch (events.ExecuteEvent())
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.cpp
index 1b0d5c22833..bcfd40234b7 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.cpp
@@ -48,7 +48,7 @@ class spell_mark_of_malice : public SpellScriptLoader
if (aurEff->GetBase()->GetCharges() > 1)
return;
- GetTarget()->CastSpell(GetTarget(), SPELL_MARK_OF_MALICE_TRIGGERED, true);
+ GetTarget()->CastSpell(GetTarget(), SPELL_MARK_OF_MALICE_TRIGGERED, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h
index 0856639f4c2..9d2c3dacb3f 100644
--- a/src/server/scripts/Outland/BlackTemple/black_temple.h
+++ b/src/server/scripts/Outland/BlackTemple/black_temple.h
@@ -47,27 +47,29 @@ enum DataTypes
DATA_BLOOD_ELF_COUNCIL_VOICE = 15,
DATA_GO_ILLIDAN_GATE = 16,
- DATA_GO_ILLIDAN_DOOR_R = 17,
- DATA_GO_ILLIDAN_DOOR_L = 18
};
enum CreatureIds
{
+ //Bosses
NPC_HIGH_WARLORD_NAJENTUS = 22887,
NPC_SUPREMUS = 22898,
NPC_SHADE_OF_AKAMA = 22841,
- NPC_AKAMA_SHADE = 23191, // This is the Akama that starts the Shade of Akama encounter.
- NPC_AKAMA = 23089, // This is the Akama that starts the Illidan encounter.
+ NPC_TERON_GOREFIEND = 22871,
+ NPC_GURTOGG_BLOODBOIL = 22948,
+ NPC_RELIQUARY_OF_SOULS = 22856,
+ NPC_MOTHER_SHAHRAZ = 22947,
+ NPC_ILLIDARI_COUNCIL = 23426,
+ NPC_ILLIDAN_STORMRAGE = 22917,
+ //Misc
NPC_GATHIOS_THE_SHATTERER = 22949,
NPC_HIGH_NETHERMANCER_ZEREVOR = 22950,
NPC_LADY_MALANDE = 22951,
NPC_VERAS_DARKSHADOW = 22952,
- NPC_ILLIDARI_COUNCIL = 23426,
NPC_BLOOD_ELF_COUNCIL_VOICE = 23499,
-
- NPC_ILLIDAN_STORMRAGE = 22917,
-
+ NPC_AKAMA = 23089, // This is the Akama that starts the Illidan encounter.
+ NPC_AKAMA_SHADE = 23191, // This is the Akama that starts the Shade of Akama encounter.
NPC_SUPREMUS_VOLCANO = 23085
};
diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
index a2215862219..07578b4c9ae 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
@@ -539,8 +539,7 @@ public:
void EnterCombat(Unit* /*who*/) override
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- me->setActive(true);
- DoZoneInCombat();
+ _EnterCombat();
}
void AttackStart(Unit* who) override
@@ -561,9 +560,6 @@ public:
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- for (uint8 i = DATA_GO_ILLIDAN_DOOR_R; i < DATA_GO_ILLIDAN_DOOR_L + 1; ++i)
- instance->HandleGameObject(instance->GetGuidData(i), true);
-
_JustDied();
}
@@ -1412,23 +1408,13 @@ public:
IllidanGUID = instance->GetGuidData(DATA_ILLIDAN_STORMRAGE);
GateGUID = instance->GetGuidData(DATA_GO_ILLIDAN_GATE);
- DoorGUID[0] = instance->GetGuidData(DATA_GO_ILLIDAN_DOOR_R);
- DoorGUID[1] = instance->GetGuidData(DATA_GO_ILLIDAN_DOOR_L);
if (JustCreated) // close all doors at create
- {
instance->HandleGameObject(GateGUID, false);
-
- for (uint8 i = 0; i < 2; ++i)
- instance->HandleGameObject(DoorGUID[i], false);
- }
else // open all doors, raid wiped
{
instance->HandleGameObject(GateGUID, true);
WalkCount = 1; // skip first wp
-
- for (uint8 i = 0; i < 2; ++i)
- instance->HandleGameObject(DoorGUID[i], true);
}
KillAllElites();
@@ -1480,9 +1466,6 @@ public:
void BeginTalk()
{
- instance->SetBossState(DATA_ILLIDAN_STORMRAGE, IN_PROGRESS);
- for (uint8 i = 0; i < 2; ++i)
- instance->HandleGameObject(DoorGUID[i], false);
if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
{
illidan->RemoveAurasDueToSpell(SPELL_KNEEL);
@@ -1674,10 +1657,6 @@ public:
{
switch (WalkCount)
{
- case 6:
- for (uint8 i = 0; i < 2; ++i)
- instance->HandleGameObject(DoorGUID[i], true);
- break;
case 8:
if (Phase == PHASE_WALK)
EnterPhase(PHASE_TALK);
@@ -1795,7 +1774,6 @@ public:
ObjectGuid ChannelGUID;
ObjectGuid SpiritGUID[2];
ObjectGuid GateGUID;
- ObjectGuid DoorGUID[2];
uint32 ChannelCount;
uint32 WalkCount;
uint32 TalkCount;
diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
index 347843ec7ff..d83e9f8aed9 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
@@ -46,7 +46,7 @@ enum Spells
SPELL_FIXATE = 40607,
SPELL_CHAIN_LIGHTNING = 39945,
SPELL_DESTRUCTIVE_POISON = 40874,
- SPELL_AKAMA_SOUL_EXPEL = 40902,
+ SPELL_AKAMA_SOUL_RETRIEVE = 40902,
// Shade
SPELL_THREAT = 41602,
SPELL_SHADE_OF_AKAMA_TRIGGER = 40955,
@@ -108,7 +108,7 @@ enum Events
EVENT_CHAIN_LIGHTNING = 4,
EVENT_DESTRUCTIVE_POISON = 5,
EVENT_START_BROKEN_FREE = 6,
- EVENT_START_SOUL_EXPEL = 7,
+ EVENT_START_SOUL_RETRIEVE = 7,
EVENT_EVADE_CHECK = 8,
EVENT_BROKEN_FREE_1 = 9,
EVENT_BROKEN_FREE_2 = 10,
@@ -246,11 +246,11 @@ public:
events.ScheduleEvent(EVENT_START_CHANNELERS_AND_SPAWNERS, Seconds(1));
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
events.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10));
- if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
AttackStart(akama);
}
- if (spell->Id == SPELL_AKAMA_SOUL_EXPEL)
+ if (spell->Id == SPELL_AKAMA_SOUL_RETRIEVE)
DoCastSelf(SPELL_AKAMA_SOUL_EXPEL_CHANNEL);
}
@@ -273,7 +273,7 @@ public:
{
DoCastSelf(SPELL_SHADE_OF_AKAMA_TRIGGER);
- if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
akama->AI()->DoAction(ACTION_SHADE_OF_AKAMA_DEAD);
for (ObjectGuid const& spawnerGuid : _spawners)
@@ -401,7 +401,7 @@ public:
_isInCombat = true;
me->SetWalk(false);
me->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
- if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
shade->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
AttackStart(shade);
@@ -445,7 +445,7 @@ public:
{
me->SetWalk(false);
me->SetFacingTo(0.08726646f, true);
- _events.ScheduleEvent(EVENT_START_SOUL_EXPEL, Seconds(1));
+ _events.ScheduleEvent(EVENT_START_SOUL_RETRIEVE, Seconds(1));
}
}
@@ -489,14 +489,14 @@ public:
break;
case EVENT_CHAIN_LIGHTNING:
DoCastVictim(SPELL_CHAIN_LIGHTNING);
- _events.Repeat(randtime(Seconds(8), Seconds(15)));
+ _events.Repeat(Seconds(8), Seconds(15));
break;
case EVENT_DESTRUCTIVE_POISON:
DoCastSelf(SPELL_DESTRUCTIVE_POISON);
- _events.Repeat(randtime(Seconds(3), Seconds(7)));
+ _events.Repeat(Seconds(3), Seconds(7));
break;
- case EVENT_START_SOUL_EXPEL:
- DoCast(SPELL_AKAMA_SOUL_EXPEL);
+ case EVENT_START_SOUL_RETRIEVE:
+ DoCast(SPELL_AKAMA_SOUL_RETRIEVE);
_events.ScheduleEvent(EVENT_START_BROKEN_FREE, Seconds(15));
break;
case EVENT_START_BROKEN_FREE:
@@ -541,7 +541,7 @@ public:
{
_summons.DespawnAll();
Talk(SAY_DEAD);
- if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
if (shade->IsAlive())
shade->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
}
@@ -587,7 +587,7 @@ public:
{
_scheduler.Schedule(Seconds(2), [this](TaskContext channel)
{
- if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
DoCastSelf(SPELL_SHADE_SOUL_CHANNEL);
@@ -657,12 +657,12 @@ public:
if (_leftSide)
{
_events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Milliseconds(100));
- _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, randtime(Seconds(2), Seconds(5)));
+ _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, Seconds(2), Seconds(5));
}
else
{
_events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Seconds(10));
- _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, randtime(Seconds(2), Seconds(5)));
+ _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, Seconds(2), Seconds(5));
}
break;
case ACTION_STOP_SPAWNING:
@@ -687,15 +687,15 @@ public:
{
case EVENT_SPAWN_WAVE_B:
DoCastSelf(SPELL_ASHTONGUE_WAVE_B);
- _events.Repeat(randtime(Seconds(50), Seconds(60)));
+ _events.Repeat(Seconds(50), Seconds(60));
break;
case EVENT_SUMMON_ASHTONGUE_SORCERER: // left
DoCastSelf(SPELL_SUMMON_ASHTONGUE_SORCERER);
- _events.Repeat(randtime(Seconds(30), Seconds(35)));
+ _events.Repeat(Seconds(30), Seconds(35));
break;
case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right
DoCastSelf(SPELL_SUMMON_ASHTONGUE_DEFENDER);
- _events.Repeat(randtime(Seconds(30), Seconds(40)));
+ _events.Repeat(Seconds(30), Seconds(40));
break;
default:
break;
@@ -736,16 +736,13 @@ public:
void Reset() override
{
- if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
me->GetMotionMaster()->MovePoint(0, shade->GetPosition());
- else
- {
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
- AttackStart(akama);
- }
+ else if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
+ AttackStart(akama);
}
Initialize();
}
@@ -777,7 +774,7 @@ public:
_scheduler.Schedule(Seconds(1) + Milliseconds(500), [this](TaskContext sorcer_channel)
{
- if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
+ if (Creature* shade = _instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
{
@@ -789,7 +786,7 @@ public:
{
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
_switchToCombat = true;
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
AttackStart(akama);
}
}
@@ -837,7 +834,7 @@ public:
void Reset() override
{
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
AttackStart(akama);
}
@@ -849,9 +846,9 @@ public:
void EnterCombat(Unit* /*who*/) override
{
_events.ScheduleEvent(EVENT_HEROIC_STRIKE, Seconds(5));
- _events.ScheduleEvent(EVENT_SHIELD_BASH, randtime(Seconds(10), Seconds(16)));
- _events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, randtime(Seconds(10), Seconds(16)));
- _events.ScheduleEvent(EVENT_WINDFURY, randtime(Seconds(8), Seconds(12)));
+ _events.ScheduleEvent(EVENT_SHIELD_BASH, Seconds(10), Seconds(16));
+ _events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, Seconds(10), Seconds(16));
+ _events.ScheduleEvent(EVENT_WINDFURY, Seconds(8), Seconds(12));
}
@@ -868,19 +865,19 @@ public:
{
case EVENT_DEBILITATING_STRIKE:
DoCastVictim(SPELL_DEBILITATING_STRIKE);
- _events.Repeat(randtime(Seconds(20), Seconds(25)));
+ _events.Repeat(Seconds(20), Seconds(25));
break;
case EVENT_HEROIC_STRIKE:
DoCastSelf(SPELL_HEROIC_STRIKE);
- _events.Repeat(randtime(Seconds(5), Seconds(15)));
+ _events.Repeat(Seconds(5), Seconds(15));
break;
case EVENT_SHIELD_BASH:
DoCastVictim(SPELL_SHIELD_BASH);
- _events.Repeat(randtime(Seconds(10), Seconds(20)));
+ _events.Repeat(Seconds(10), Seconds(20));
break;
case EVENT_WINDFURY:
DoCastVictim(SPELL_WINDFURY);
- _events.Repeat(randtime(Seconds(6), Seconds(8)));
+ _events.Repeat(Seconds(6), Seconds(8));
break;
default:
break;
@@ -915,7 +912,7 @@ public:
void Reset() override
{
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
AttackStart(akama);
}
@@ -926,8 +923,8 @@ public:
void EnterCombat(Unit* /*who*/) override
{
- _events.ScheduleEvent(EVENT_DEBILITATING_POISON, randtime(Milliseconds(500), Seconds(2)));
- _events.ScheduleEvent(EVENT_EVISCERATE, randtime(Seconds(2), Seconds(5)));
+ _events.ScheduleEvent(EVENT_DEBILITATING_POISON, Milliseconds(500), Seconds(2));
+ _events.ScheduleEvent(EVENT_EVISCERATE, Seconds(2), Seconds(5));
}
void EnterEvadeMode(EvadeReason /*why*/) override { }
@@ -945,11 +942,11 @@ public:
{
case EVENT_DEBILITATING_POISON:
DoCastVictim(SPELL_DEBILITATING_POISON);
- _events.Repeat(randtime(Seconds(15), Seconds(20)));
+ _events.Repeat(Seconds(15), Seconds(20));
break;
case EVENT_EVISCERATE:
DoCastVictim(SPELL_EVISCERATE);
- _events.Repeat(randtime(Seconds(12), Seconds(20)));
+ _events.Repeat(Seconds(12), Seconds(20));
break;
default:
break;
@@ -984,7 +981,7 @@ public:
void Reset() override
{
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
AttackStart(akama);
}
@@ -1014,11 +1011,11 @@ public:
{
case EVENT_RAIN_OF_FIRE:
DoCastVictim(SPELL_RAIN_OF_FIRE);
- _events.Repeat(randtime(Seconds(15), Seconds(20)));
+ _events.Repeat(Seconds(15), Seconds(20));
break;
case EVENT_LIGHTNING_BOLT:
DoCastVictim(SPELL_LIGHTNING_BOLT);
- _events.Repeat(randtime(Seconds(8), Seconds(15)));
+ _events.Repeat(Seconds(8), Seconds(15));
break;
default:
break;
@@ -1062,7 +1059,7 @@ public:
{
Initialize();
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
AttackStart(akama);
}
@@ -1073,7 +1070,7 @@ public:
void EnterCombat(Unit* /*who*/) override
{
- _events.ScheduleEvent(EVENT_SPIRIT_HEAL, randtime(Seconds(5), Seconds(6)));
+ _events.ScheduleEvent(EVENT_SPIRIT_HEAL, Seconds(5), Seconds(6));
}
void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override
@@ -1083,7 +1080,7 @@ public:
{
DoCastSelf(SPELL_SPIRIT_MEND);
_spiritMend = true;
- _events.ScheduleEvent(EVENT_SPIRIT_MEND_RESET, randtime(Seconds(10),Seconds(15)));
+ _events.ScheduleEvent(EVENT_SPIRIT_MEND_RESET, Seconds(10),Seconds(15));
}
if (!_chainHeal)
@@ -1091,7 +1088,7 @@ public:
{
DoCastSelf(SPELL_CHAIN_HEAL);
_chainHeal = true;
- _events.ScheduleEvent(EVENT_CHAIN_HEAL_RESET, randtime(Seconds(10), Seconds(15)));
+ _events.ScheduleEvent(EVENT_CHAIN_HEAL_RESET, Seconds(10), Seconds(15));
}
}
@@ -1108,7 +1105,7 @@ public:
{
case EVENT_SPIRIT_HEAL:
DoCastSelf(SPELL_SPIRITBINDER_SPIRIT_HEAL);
- _events.Repeat(randtime(Seconds(13), Seconds(16)));
+ _events.Repeat(Seconds(13), Seconds(16));
break;
case EVENT_SPIRIT_MEND_RESET:
_spiritMend = false;
@@ -1157,7 +1154,7 @@ public:
if (motionType != POINT_MOTION_TYPE)
return;
- if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE)))
+ if (Creature* akama = _instance->GetCreature(DATA_AKAMA_SHADE))
me->SetFacingToObject(akama);
}
diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp
index bac996918ac..2784792fe8d 100644
--- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp
+++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp
@@ -22,17 +22,20 @@
DoorData const doorData[] =
{
{ GO_NAJENTUS_GATE, DATA_HIGH_WARLORD_NAJENTUS, DOOR_TYPE_PASSAGE },
- { GO_NAJENTUS_GATE, DATA_SUPREMUS, DOOR_TYPE_ROOM },
+ { GO_NAJENTUS_GATE, DATA_SUPREMUS, DOOR_TYPE_ROOM },
{ GO_SUPREMUS_GATE, DATA_SUPREMUS, DOOR_TYPE_PASSAGE },
- { GO_SHADE_OF_AKAMA_DOOR, DATA_SHADE_OF_AKAMA, DOOR_TYPE_ROOM },
- { GO_TERON_DOOR_1, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM },
- { GO_TERON_DOOR_2, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM },
+ { GO_SHADE_OF_AKAMA_DOOR, DATA_SHADE_OF_AKAMA, DOOR_TYPE_ROOM },
+ { GO_TERON_DOOR_1, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM },
+ { GO_TERON_DOOR_2, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM },
{ GO_GURTOGG_DOOR, DATA_GURTOGG_BLOODBOIL, DOOR_TYPE_PASSAGE },
{ GO_TEMPLE_DOOR, DATA_RELIQUARY_OF_SOULS, DOOR_TYPE_PASSAGE },
{ GO_MOTHER_SHAHRAZ_DOOR, DATA_MOTHER_SHAHRAZ, DOOR_TYPE_PASSAGE },
- { GO_COUNCIL_DOOR_1, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM },
- { GO_COUNCIL_DOOR_2, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM },
- { 0, 0, DOOR_TYPE_ROOM } // END
+ { GO_COUNCIL_DOOR_1, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM },
+ { GO_COUNCIL_DOOR_2, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM },
+ //{ GO_ILLIDAN_GATE, DATA_GO_ILLIDAN_GATE, DOOR_TYPE_PASSAGE },
+ { GO_ILLIDAN_DOOR_R, DATA_ILLIDAN_STORMRAGE, DOOR_TYPE_ROOM },
+ { GO_ILLIDAN_DOOR_L, DATA_ILLIDAN_STORMRAGE, DOOR_TYPE_ROOM },
+ { 0, 0, DOOR_TYPE_ROOM } // END
};
BossBoundaryData const boundaries =
@@ -49,6 +52,27 @@ BossBoundaryData const boundaries =
{ DATA_ILLIDAN_STORMRAGE, new EllipseBoundary(Position(694.8f, 309.0f), 70.0 , 85.0) }
};
+ObjectData const creatureData[] =
+{
+ { NPC_HIGH_WARLORD_NAJENTUS, DATA_HIGH_WARLORD_NAJENTUS },
+ { NPC_SUPREMUS, DATA_SUPREMUS },
+ { NPC_SHADE_OF_AKAMA, DATA_SHADE_OF_AKAMA },
+ { NPC_TERON_GOREFIEND, DATA_TERON_GOREFIEND },
+ { NPC_GURTOGG_BLOODBOIL, DATA_GURTOGG_BLOODBOIL },
+ { NPC_RELIQUARY_OF_SOULS, DATA_RELIQUARY_OF_SOULS },
+ { NPC_MOTHER_SHAHRAZ, DATA_MOTHER_SHAHRAZ },
+ { NPC_ILLIDARI_COUNCIL, DATA_ILLIDARI_COUNCIL },
+ { NPC_ILLIDAN_STORMRAGE, DATA_ILLIDAN_STORMRAGE },
+ { NPC_AKAMA_SHADE, DATA_AKAMA_SHADE },
+ { NPC_AKAMA, DATA_AKAMA },
+ { NPC_GATHIOS_THE_SHATTERER, DATA_GATHIOS_THE_SHATTERER },
+ { NPC_HIGH_NETHERMANCER_ZEREVOR, DATA_HIGH_NETHERMANCER_ZEREVOR },
+ { NPC_LADY_MALANDE, DATA_LADY_MALANDE },
+ { NPC_VERAS_DARKSHADOW, DATA_VERAS_DARKSHADOW },
+ { NPC_BLOOD_ELF_COUNCIL_VOICE, DATA_BLOOD_ELF_COUNCIL_VOICE },
+ { 0, 0 } // end
+};
+
class instance_black_temple : public InstanceMapScript
{
public:
@@ -61,165 +85,28 @@ class instance_black_temple : public InstanceMapScript
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
+ LoadObjectData(creatureData, nullptr);
LoadBossBoundaries(boundaries);
}
- void OnCreatureCreate(Creature* creature) override
- {
- switch (creature->GetEntry())
- {
- case NPC_HIGH_WARLORD_NAJENTUS:
- NajentusGUID = creature->GetGUID();
- break;
- case NPC_SUPREMUS:
- SupremusGUID = creature->GetGUID();
- break;
- case NPC_SHADE_OF_AKAMA:
- ShadeOfAkamaGUID = creature->GetGUID();
- break;
- case NPC_AKAMA_SHADE:
- AkamaShadeGUID = creature->GetGUID();
- break;
- case NPC_AKAMA:
- AkamaGUID = creature->GetGUID();
- break;
- case NPC_GATHIOS_THE_SHATTERER:
- GathiosTheShattererGUID = creature->GetGUID();
- break;
- case NPC_HIGH_NETHERMANCER_ZEREVOR:
- HighNethermancerZerevorGUID = creature->GetGUID();
- break;
- case NPC_LADY_MALANDE:
- LadyMalandeGUID = creature->GetGUID();
- break;
- case NPC_VERAS_DARKSHADOW:
- VerasDarkshadowGUID = creature->GetGUID();
- break;
- case NPC_ILLIDARI_COUNCIL:
- IllidariCouncilGUID = creature->GetGUID();
- break;
- case NPC_BLOOD_ELF_COUNCIL_VOICE:
- BloodElfCouncilVoiceGUID = creature->GetGUID();
- break;
- case NPC_ILLIDAN_STORMRAGE:
- IllidanStormrageGUID = creature->GetGUID();
- break;
- default:
- break;
- }
- }
-
void OnGameObjectCreate(GameObject* go) override
{
- switch (go->GetEntry())
- {
- case GO_NAJENTUS_GATE:
- case GO_SUPREMUS_GATE:
- case GO_SHADE_OF_AKAMA_DOOR:
- case GO_TERON_DOOR_1:
- case GO_TERON_DOOR_2:
- case GO_GURTOGG_DOOR:
- case GO_TEMPLE_DOOR:
- case GO_MOTHER_SHAHRAZ_DOOR:
- case GO_COUNCIL_DOOR_1:
- case GO_COUNCIL_DOOR_2:
- AddDoor(go, true);
- break;
- case GO_ILLIDAN_GATE:
- IllidanGateGUID = go->GetGUID();
- break;
- case GO_ILLIDAN_DOOR_R:
- IllidanDoorGUIDs[0] = go->GetGUID();
- break;
- case GO_ILLIDAN_DOOR_L:
- IllidanDoorGUIDs[1] = go->GetGUID();
- break;
- default:
- break;
- }
- }
+ if (go->GetEntry() == GO_ILLIDAN_GATE)
+ IllidanGateGUID = go->GetGUID();
- void OnGameObjectRemove(GameObject* go) override
- {
- switch (go->GetEntry())
- {
- case GO_NAJENTUS_GATE:
- case GO_SUPREMUS_GATE:
- case GO_SHADE_OF_AKAMA_DOOR:
- case GO_TERON_DOOR_1:
- case GO_TERON_DOOR_2:
- case GO_GURTOGG_DOOR:
- case GO_TEMPLE_DOOR:
- case GO_MOTHER_SHAHRAZ_DOOR:
- case GO_COUNCIL_DOOR_1:
- case GO_COUNCIL_DOOR_2:
- AddDoor(go, false);
- break;
- default:
- break;
- }
+ InstanceScript::OnGameObjectCreate(go);
}
ObjectGuid GetGuidData(uint32 type) const override
{
- switch (type)
- {
- case DATA_HIGH_WARLORD_NAJENTUS:
- return NajentusGUID;
- case DATA_SUPREMUS:
- return SupremusGUID;
- case DATA_SHADE_OF_AKAMA:
- return ShadeOfAkamaGUID;
- case DATA_AKAMA_SHADE:
- return AkamaShadeGUID;
- case DATA_AKAMA:
- return AkamaGUID;
- case DATA_GATHIOS_THE_SHATTERER:
- return GathiosTheShattererGUID;
- case DATA_HIGH_NETHERMANCER_ZEREVOR:
- return HighNethermancerZerevorGUID;
- case DATA_LADY_MALANDE:
- return LadyMalandeGUID;
- case DATA_VERAS_DARKSHADOW:
- return VerasDarkshadowGUID;
- case DATA_ILLIDARI_COUNCIL:
- return IllidariCouncilGUID;
- case DATA_BLOOD_ELF_COUNCIL_VOICE:
- return BloodElfCouncilVoiceGUID;
- case DATA_ILLIDAN_STORMRAGE:
- return IllidanStormrageGUID;
- case DATA_GO_ILLIDAN_GATE:
- return IllidanGateGUID;
- case DATA_GO_ILLIDAN_DOOR_R:
- return IllidanDoorGUIDs[0];
- case DATA_GO_ILLIDAN_DOOR_L:
- return IllidanDoorGUIDs[1];
- default:
- break;
- }
+ if (type == DATA_GO_ILLIDAN_GATE)
+ return IllidanGateGUID;
- return ObjectGuid::Empty;
+ return InstanceScript::GetGuidData(type);
}
protected:
- ObjectGuid NajentusGUID;
- ObjectGuid SupremusGUID;
- ObjectGuid ShadeOfAkamaGUID;
- ObjectGuid AkamaShadeGUID;
- ObjectGuid AkamaGUID;
-
- ObjectGuid GathiosTheShattererGUID;
- ObjectGuid HighNethermancerZerevorGUID;
- ObjectGuid LadyMalandeGUID;
- ObjectGuid VerasDarkshadowGUID;
-
- ObjectGuid IllidariCouncilGUID;
- ObjectGuid BloodElfCouncilVoiceGUID;
-
- ObjectGuid IllidanStormrageGUID;
-
ObjectGuid IllidanGateGUID;
- ObjectGuid IllidanDoorGUIDs[2];
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
index f305c1e47be..daea6d24a4a 100644
--- a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
+++ b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
@@ -239,14 +239,14 @@ class spell_twisted_reflection : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
if (!damageInfo || !damageInfo->GetDamage())
return;
- eventInfo.GetActionTarget()->CastSpell(eventInfo.GetActor(), SPELL_TWISTED_REFLECTION_HEAL, true);
+ eventInfo.GetActionTarget()->CastSpell(eventInfo.GetActor(), SPELL_TWISTED_REFLECTION_HEAL, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
index d4faeef73b9..3b364d557ed 100644
--- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
+++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
@@ -332,8 +332,14 @@ public:
enum FelGuard
{
- SPELL_SUMMON_POO = 37688,
- NPC_DERANGED_HELBOAR = 16863
+ SPELL_SUMMON_POO = 37688,
+ SPELL_FAKE_BLOOD = 37692,
+ NPC_DERANGED_HELBOAR = 16863,
+
+ EVENT_SEARCH_HELBOAR = 1,
+ EVENT_HELBOAR_FOUND = 2,
+ EVENT_SUMMON_POO = 3,
+ EVENT_FOLLOW_PLAYER = 4
};
class npc_fel_guard_hound : public CreatureScript
@@ -350,8 +356,8 @@ public:
void Initialize()
{
- checkTimer = 5000; //check for creature every 5 sec
helboarGUID.Clear();
+ _events.ScheduleEvent(EVENT_SEARCH_HELBOAR, Seconds(3));
}
void Reset() override
@@ -366,29 +372,54 @@ public:
if (Creature* helboar = ObjectAccessor::GetCreature(*me, helboarGUID))
{
- helboar->RemoveCorpse();
- DoCast(SPELL_SUMMON_POO);
-
- if (Player* owner = me->GetCharmerOrOwnerPlayerOrPlayerItself())
- me->GetMotionMaster()->MoveFollow(owner, 0.0f, 0.0f);
+ _events.CancelEvent(EVENT_SEARCH_HELBOAR);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
+ me->CastSpell(helboar, SPELL_FAKE_BLOOD);
+ _events.ScheduleEvent(EVENT_HELBOAR_FOUND, Seconds(2));
}
}
void UpdateAI(uint32 diff) override
{
- if (checkTimer <= diff)
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- if (Creature* helboar = me->FindNearestCreature(NPC_DERANGED_HELBOAR, 10.0f, false))
+ switch (eventId)
{
- if (helboar->GetGUID() != helboarGUID && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE && !me->FindCurrentSpellBySpellId(SPELL_SUMMON_POO))
- {
- helboarGUID = helboar->GetGUID();
- me->GetMotionMaster()->MovePoint(1, helboar->GetPositionX(), helboar->GetPositionY(), helboar->GetPositionZ());
- }
+ case EVENT_SEARCH_HELBOAR:
+ if (Creature* helboar = me->FindNearestCreature(NPC_DERANGED_HELBOAR, 10.0f, false))
+ {
+ if (helboar->GetGUID() != helboarGUID && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE && !me->FindCurrentSpellBySpellId(SPELL_SUMMON_POO))
+ {
+ helboarGUID = helboar->GetGUID();
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(1, helboar->GetPositionX(), helboar->GetPositionY(), helboar->GetPositionZ());
+ helboar->DespawnOrUnsummon(Seconds(10));
+ }
+ }
+ _events.Repeat(Seconds(3));
+ break;
+ case EVENT_HELBOAR_FOUND:
+ if (Creature* helboar = ObjectAccessor::GetCreature(*me, helboarGUID))
+ {
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
+ me->CastSpell(helboar, SPELL_FAKE_BLOOD);
+ _events.ScheduleEvent(EVENT_SUMMON_POO, Seconds(1));
+ }
+ break;
+ case EVENT_SUMMON_POO:
+ DoCast(SPELL_SUMMON_POO);
+ _events.ScheduleEvent(EVENT_FOLLOW_PLAYER, Seconds(2));
+ break;
+ case EVENT_FOLLOW_PLAYER:
+ me->SetWalk(false);
+ if (Player* owner = me->GetCharmerOrOwnerPlayerOrPlayerItself())
+ me->GetMotionMaster()->MoveFollow(owner, 0.0f, 0.0f);
+ _events.ScheduleEvent(EVENT_SEARCH_HELBOAR, Seconds(3));
+ break;
}
- checkTimer = 5000;
}
- else checkTimer -= diff;
if (!UpdateVictim())
return;
@@ -397,7 +428,7 @@ public:
}
private:
- uint32 checkTimer;
+ EventMap _events;
ObjectGuid helboarGUID;
};
diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp
index a155dbc36c4..7092300af4d 100644
--- a/src/server/scripts/Pet/pet_hunter.cpp
+++ b/src/server/scripts/Pet/pet_hunter.cpp
@@ -42,6 +42,10 @@ enum PetSpellsMisc
SPELL_PET_GUARD_DOG_HAPPINESS = 54445,
SPELL_PET_SILVERBACK_RANK_1 = 62800,
SPELL_PET_SILVERBACK_RANK_2 = 62801,
+
+ SPELL_PET_SWOOP = 52825,
+ SPELL_PET_CHARGE = 61685,
+
PET_ICON_ID_GROWL = 201,
PET_ICON_ID_CLAW = 262,
PET_ICON_ID_BITE = 1680,
@@ -162,10 +166,29 @@ class spell_pet_charge : public SpellScriptLoader
{
PrepareAuraScript(spell_pet_charge_AuraScript);
- void HandleDummy(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_PET_SWOOP) ||
+ !sSpellMgr->GetSpellInfo(SPELL_PET_CHARGE))
+ return false;
+ return true;
+ }
+
+ void HandleDummy(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
{
// Prevent console log
PreventDefaultAction();
+
+ // Remove +% AP aura
+ Unit* pet = eventInfo.GetActor();
+ Aura* aura = pet->GetAura(SPELL_PET_SWOOP, pet->GetGUID());
+ if (!aura)
+ aura = pet->GetAura(SPELL_PET_CHARGE, pet->GetGUID());
+
+ if (!aura)
+ return;
+
+ aura->DropCharge(AURA_REMOVE_BY_EXPIRE);
}
void Register() override
@@ -213,7 +236,7 @@ class spell_pet_guard_dog : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell((Unit*)nullptr, SPELL_PET_GUARD_DOG_HAPPINESS, true);
+ caster->CastSpell((Unit*)nullptr, SPELL_PET_GUARD_DOG_HAPPINESS, true, nullptr, aurEff);
float addThreat = CalculatePct(ASSERT_NOTNULL(eventInfo.GetSpellInfo())->Effects[EFFECT_0].CalcValue(caster), aurEff->GetAmount());
eventInfo.GetProcTarget()->AddThreat(caster, addThreat);
@@ -260,14 +283,14 @@ class spell_pet_silverback : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
static uint32 const triggerSpell[2] = { SPELL_PET_SILVERBACK_RANK_1, SPELL_PET_SILVERBACK_RANK_2 };
PreventDefaultAction();
uint32 spellId = triggerSpell[GetSpellInfo()->GetRank() - 1];
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index 7cce7e4655e..13eec799493 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -600,7 +600,7 @@ class spell_dk_butchery : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastCustomSpell(SPELL_DK_BUTCHERY_RUNIC_POWER, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), (Unit*)nullptr, true);
+ eventInfo.GetActor()->CastCustomSpell(SPELL_DK_BUTCHERY_RUNIC_POWER, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1249,10 +1249,10 @@ class spell_dk_glyph_of_scourge_strike : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DK_GLYPH_OF_SCOURGE_STRIKE_SCRIPT, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DK_GLYPH_OF_SCOURGE_STRIKE_SCRIPT, true, nullptr, aurEff);
}
void Register() override
@@ -1588,10 +1588,10 @@ class spell_dk_pvp_4p_bonus : public SpellScriptLoader
return (spellInfo->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_SNARE))) != 0;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActionTarget()->CastSpell((Unit*)nullptr, SPELL_DK_RUNIC_RETURN, true);
+ eventInfo.GetActionTarget()->CastSpell((Unit*)nullptr, SPELL_DK_RUNIC_RETURN, true, nullptr, aurEff);
}
void Register() override
@@ -1624,10 +1624,10 @@ class spell_dk_mark_of_blood : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DK_MARK_OF_BLOOD_HEAL, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DK_MARK_OF_BLOOD_HEAL, true, nullptr, aurEff);
}
void Register() override
@@ -1668,7 +1668,7 @@ class spell_dk_necrosis : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- eventInfo.GetActor()->CastCustomSpell(SPELL_DK_NECROSIS_DAMAGE, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true);
+ eventInfo.GetActor()->CastCustomSpell(SPELL_DK_NECROSIS_DAMAGE, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, nullptr, aurEff);
}
void Register() override
@@ -2327,7 +2327,7 @@ class spell_dk_sudden_doom : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
@@ -2347,7 +2347,7 @@ class spell_dk_sudden_doom : public SpellScriptLoader
if (!spellId)
return;
- caster->CastSpell(eventInfo.GetProcTarget(), spellId, true);
+ caster->CastSpell(eventInfo.GetProcTarget(), spellId, true, nullptr, aurEff);
}
void Register() override
@@ -2424,7 +2424,7 @@ class spell_dk_threat_of_thassarian : public SpellScriptLoader
return;
spellId = sSpellMgr->GetSpellWithRank(spellId, spellInfo->GetRank());
- caster->CastSpell(eventInfo.GetProcTarget(), spellId, true);
+ caster->CastSpell(eventInfo.GetProcTarget(), spellId, true, nullptr, aurEff);
}
void Register() override
@@ -2478,7 +2478,7 @@ class spell_dk_unholy_blight : public SpellScriptLoader
// Add remaining ticks to healing done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_DK_UNHOLY_BLIGHT_DAMAGE, SPELL_AURA_PERIODIC_DAMAGE);
- caster->CastCustomSpell(SPELL_DK_UNHOLY_BLIGHT_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_DK_UNHOLY_BLIGHT_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2541,7 +2541,7 @@ class spell_dk_vendetta : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
int32 amount = caster->CountPctFromMaxHealth(aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_DK_VENDETTA_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_DK_VENDETTA_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -2586,7 +2586,7 @@ class spell_dk_wandering_plague : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_DK_WANDERING_PLAGUE_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_DK_WANDERING_PLAGUE_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index 49baab54bf0..56624346772 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -486,10 +486,10 @@ class spell_dru_glyph_of_barkskin : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DRUID_BARKSKIN_01, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DRUID_BARKSKIN_01, true, nullptr, aurEff);
}
void Register() override
@@ -530,7 +530,7 @@ class spell_dru_glyph_of_innervate : public SpellScriptLoader
int32 amount = CalculatePct(static_cast<int32>(caster->GetCreatePowers(POWER_MANA)), aurEff->GetAmount());
amount /= spellInfo->GetMaxTicks();
- caster->CastCustomSpell(SPELL_DRUID_GLYPH_OF_INNERVATE_REGEN, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_DRUID_GLYPH_OF_INNERVATE_REGEN, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -567,10 +567,10 @@ class spell_dru_glyph_of_rake : public SpellScriptLoader
return eventInfo.GetProcTarget()->GetTypeId() == TYPEID_UNIT;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_GLYPH_OF_RAKE_TRIGGERED, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_GLYPH_OF_RAKE_TRIGGERED, true, nullptr, aurEff);
}
void Register() override
@@ -616,7 +616,7 @@ class spell_dru_glyph_of_rejuvenation : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- eventInfo.GetActor()->CastCustomSpell(SPELL_DRUID_GLYPH_OF_REJUVENATION_HEAL, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true);
+ eventInfo.GetActor()->CastCustomSpell(SPELL_DRUID_GLYPH_OF_REJUVENATION_HEAL, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, nullptr, aurEff);
}
void Register() override
@@ -762,10 +762,10 @@ class spell_dru_glyph_of_starfire_dummy : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_GLYPH_OF_STARFIRE_SCRIPT, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_GLYPH_OF_STARFIRE_SCRIPT, true, nullptr, aurEff);
}
void Register() override
@@ -905,7 +905,7 @@ class spell_dru_leader_of_the_pack : public SpellScriptLoader
return;
int32 amount = caster->CountPctFromMaxHealth(aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_DRUID_IMP_LEADER_OF_THE_PACK_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_DRUID_IMP_LEADER_OF_THE_PACK_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
// Because of how proc system works, we can't store proc cd on db, it would be applied to entire aura
// so aura could only proc once per 6 seconds, independently of caster
@@ -915,12 +915,11 @@ class spell_dru_leader_of_the_pack : public SpellScriptLoader
if (aurEff->GetCasterGUID() != caster->GetGUID())
return;
- AuraEffect const* impLotpMana = caster->GetAuraEffectOfRankedSpell(SPELL_DRUID_IMP_LEADER_OF_THE_PACK_R1, EFFECT_1, aurEff->GetCasterGUID());
- if (!impLotpMana)
- return;
+ AuraEffect const* impLotpMana = caster->GetAuraEffectOfRankedSpell(SPELL_DRUID_IMP_LEADER_OF_THE_PACK_R1, EFFECT_0, aurEff->GetCasterGUID());
+ ASSERT(impLotpMana);
- int32 manaAmount = CalculatePct(static_cast<int32>(caster->GetMaxPower(POWER_MANA)), impLotpMana->GetAmount());
- caster->CastCustomSpell(SPELL_DRUID_IMP_LEADER_OF_THE_PACK_MANA, SPELLVALUE_BASE_POINT0, manaAmount, (Unit*)nullptr, true);
+ int32 manaAmount = CalculatePct(static_cast<int32>(caster->GetMaxPower(POWER_MANA)), impLotpMana->GetSpellInfo()->Effects[EFFECT_1].CalcValue());
+ caster->CastCustomSpell(SPELL_DRUID_IMP_LEADER_OF_THE_PACK_MANA, SPELLVALUE_BASE_POINT0, manaAmount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1043,7 +1042,7 @@ class spell_dru_living_seed : public SpellScriptLoader
return;
int32 amount = CalculatePct(healInfo->GetHeal(), aurEff->GetAmount());
- GetTarget()->CastCustomSpell(SPELL_DRUID_LIVING_SEED_PROC, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, NULL, aurEff);
+ GetTarget()->CastCustomSpell(SPELL_DRUID_LIVING_SEED_PROC, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, nullptr, aurEff);
}
void Register() override
@@ -1162,11 +1161,11 @@ class spell_dru_omen_of_clarity : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
Unit* target = GetTarget();
if (target->HasAura(SPELL_DRUID_BALANCE_T10_BONUS))
- target->CastSpell((Unit*)nullptr, SPELL_DRUID_BALANCE_T10_BONUS_PROC, true, nullptr);
+ target->CastSpell((Unit*)nullptr, SPELL_DRUID_BALANCE_T10_BONUS_PROC, true, nullptr, aurEff);
}
void Register() override
@@ -1335,7 +1334,7 @@ class spell_dru_revitalize : public SpellScriptLoader
return;
}
- eventInfo.GetActor()->CastSpell(target, spellId, true);
+ eventInfo.GetActor()->CastSpell(target, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1420,7 +1419,7 @@ class spell_dru_savage_defense : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
int32 amount = static_cast<int32>(CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK), aurEff->GetAmount()));
- caster->CastCustomSpell(GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1613,7 +1612,7 @@ class spell_dru_survival_instincts : public SpellScriptLoader
{
Unit* target = GetTarget();
int32 bp0 = target->CountPctFromMaxHealth(aurEff->GetAmount());
- target->CastCustomSpell(target, SPELL_DRUID_SURVIVAL_INSTINCTS, &bp0, NULL, NULL, true);
+ target->CastCustomSpell(target, SPELL_DRUID_SURVIVAL_INSTINCTS, &bp0, nullptr, nullptr, true, nullptr, aurEff);
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
@@ -1654,7 +1653,7 @@ class spell_dru_swift_flight_passive : public SpellScriptLoader
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
+ void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool & /*canBeRecalculated*/)
{
if (Player* caster = GetCaster()->ToPlayer())
if (caster->Has310Flyer(false))
@@ -1756,7 +1755,7 @@ class spell_dru_t3_2p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* target = eventInfo.GetProcTarget();
@@ -1777,7 +1776,7 @@ class spell_dru_t3_2p_bonus : public SpellScriptLoader
return;
}
- eventInfo.GetActor()->CastSpell(target, spellId, true);
+ eventInfo.GetActor()->CastSpell(target, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1810,10 +1809,10 @@ class spell_dru_t3_6p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_BLESSING_OF_THE_CLAW, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_BLESSING_OF_THE_CLAW, true, nullptr, aurEff);
}
void Register() override
@@ -1854,7 +1853,7 @@ class spell_dru_t3_8p_bonus : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
int32 amount = CalculatePct(spellInfo->CalcPowerCost(caster, spellInfo->GetSchoolMask()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_DRUID_EXHILARATE, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_DRUID_EXHILARATE, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1887,10 +1886,10 @@ class spell_dru_t4_2p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DRUID_INFUSION, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_DRUID_INFUSION, true, nullptr, aurEff);
}
void Register() override
@@ -1924,7 +1923,7 @@ class spell_dru_item_t6_trinket : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
@@ -1956,7 +1955,7 @@ class spell_dru_item_t6_trinket : public SpellScriptLoader
return;
if (roll_chance_i(chance))
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -2076,7 +2075,7 @@ class spell_dru_t10_balance_4p_bonus : public SpellScriptLoader
// Add remaining ticks to damage done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_DRUID_LANGUISH, SPELL_AURA_PERIODIC_DAMAGE);
- caster->CastCustomSpell(SPELL_DRUID_LANGUISH, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_DRUID_LANGUISH, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2180,12 +2179,12 @@ class spell_dru_t10_restoration_4p_bonus_dummy : public SpellScriptLoader
return caster->GetGroup() || caster != eventInfo.GetProcTarget();
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
int32 amount = static_cast<int32>(eventInfo.GetHealInfo()->GetHeal());
- eventInfo.GetActor()->CastCustomSpell(SPELL_DRUID_REJUVENATION_T10_PROC, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ eventInfo.GetActor()->CastCustomSpell(SPELL_DRUID_REJUVENATION_T10_PROC, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index f1eaf45770e..d0fcd1080bb 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -3570,7 +3570,7 @@ class spell_gen_vampiric_touch : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
@@ -3579,7 +3579,7 @@ class spell_gen_vampiric_touch : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
int32 bp = damageInfo->GetDamage() / 2;
- caster->CastCustomSpell(SPELL_VAMPIRIC_TOUCH_HEAL, SPELLVALUE_BASE_POINT0, bp, caster, true);
+ caster->CastCustomSpell(SPELL_VAMPIRIC_TOUCH_HEAL, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp
index 2eba605f8b3..b341c5799ed 100644
--- a/src/server/scripts/Spells/spell_hunter.cpp
+++ b/src/server/scripts/Spells/spell_hunter.cpp
@@ -225,7 +225,7 @@ class spell_hun_chimera_shot : public SpellScriptLoader
// first, calculate damage of basic tick (C&P from AuraEffect::HandlePeriodicDamageAurasTick)
basePoint = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct();
if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod<SPELLMOD_DOT>(aurEff->GetSpellInfo()->Id, basePoint);
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(aurEff->GetId(), basePoint);
basePoint = unitTarget->SpellDamageBonusTaken(caster, aurEff->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount());
// then, multiply to get damage potential
@@ -275,6 +275,70 @@ class spell_hun_chimera_shot : public SpellScriptLoader
}
};
+// -53256 - Cobra Strikes
+class spell_hun_cobra_strikes : public SpellScriptLoader
+{
+ public:
+ spell_hun_cobra_strikes() : SpellScriptLoader("spell_hun_cobra_strikes") { }
+
+ class spell_hun_cobra_strikes_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_hun_cobra_strikes_AuraScript);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell))
+ return false;
+ return true;
+ }
+
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+
+ SpellInfo const* triggeredSpellInfo = sSpellMgr->AssertSpellInfo(GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell);
+ GetTarget()->CastCustomSpell(triggeredSpellInfo->Id, SPELLVALUE_AURA_STACK, triggeredSpellInfo->StackAmount, (Unit*)nullptr, true);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_hun_cobra_strikes_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_hun_cobra_strikes_AuraScript();
+ }
+};
+
+// 53257 - Cobra Strikes (triggered spell)
+class spell_hun_cobra_strikes_triggered : public SpellScriptLoader
+{
+ public:
+ spell_hun_cobra_strikes_triggered() : SpellScriptLoader("spell_hun_cobra_strikes_triggered") { }
+
+ class spell_hun_cobra_strikes_triggered_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_hun_cobra_strikes_triggered_AuraScript);
+
+ void HandleStackDrop(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ {
+ ModStackAmount(-1);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_hun_cobra_strikes_triggered_AuraScript::HandleStackDrop, EFFECT_0, SPELL_AURA_ADD_FLAT_MODIFIER);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_hun_cobra_strikes_triggered_AuraScript();
+ }
+};
+
// 781 - Disengage
class spell_hun_disengage : public SpellScriptLoader
{
@@ -385,10 +449,10 @@ class spell_hun_glyph_of_mend_pet : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_HUNTER_GLYPH_OF_MEND_PET_HAPPINESS, true);
+ eventInfo.GetProcTarget()->CastSpell((Unit*)nullptr, SPELL_HUNTER_GLYPH_OF_MEND_PET_HAPPINESS, true, nullptr, aurEff);
}
void Register() override
@@ -420,10 +484,10 @@ class spell_hun_hunting_party : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
@@ -681,30 +745,58 @@ class spell_hun_masters_call : public SpellScriptLoader
return true;
}
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ SpellCastResult DoCheckCast()
+ {
+ Pet* pet = GetCaster()->ToPlayer()->GetPet();
+ ASSERT(pet); // checked in Spell::CheckCast
+
+ if (!pet->IsAlive())
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+
+ // Do a mini Spell::CheckCasterAuras on the pet, no other way of doing this
+ SpellCastResult result = SPELL_CAST_OK;
+ uint32 const unitflag = pet->GetUInt32Value(UNIT_FIELD_FLAGS);
+ if (pet->GetCharmerGUID())
+ result = SPELL_FAILED_CHARMED;
+ else if (unitflag & UNIT_FLAG_STUNNED)
+ result = SPELL_FAILED_STUNNED;
+ else if (unitflag & UNIT_FLAG_FLEEING)
+ result = SPELL_FAILED_FLEEING;
+ else if (unitflag & UNIT_FLAG_CONFUSED)
+ result = SPELL_FAILED_CONFUSED;
+
+ if (result != SPELL_CAST_OK)
+ return result;
+
+ Unit* target = GetExplTargetUnit();
+ if (!target)
+ return SPELL_FAILED_BAD_TARGETS;
+
+ if (!pet->IsWithinLOSInMap(target))
+ return SPELL_FAILED_LINE_OF_SIGHT;
+
+ return SPELL_CAST_OK;
+ }
+
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- if (Unit* ally = GetHitUnit())
- if (Player* caster = GetCaster()->ToPlayer())
- if (Pet* target = caster->GetPet())
- {
- TriggerCastFlags castMask = TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_CASTER_AURASTATE);
- target->CastSpell(ally, GetEffectValue(), castMask);
- target->CastSpell(ally, GetSpellInfo()->Effects[EFFECT_0].CalcValue(), castMask);
- }
+ GetCaster()->ToPlayer()->GetPet()->CastSpell(GetHitUnit(), GetEffectValue(), true);
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
- if (Unit* target = GetHitUnit())
- {
- // Cannot be processed while pet is dead
- TriggerCastFlags castMask = TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_CASTER_AURASTATE);
- target->CastSpell(target, SPELL_HUNTER_MASTERS_CALL_TRIGGERED, castMask);
- }
+ GetHitUnit()->CastSpell((Unit*)nullptr, SPELL_HUNTER_MASTERS_CALL_TRIGGERED, true);
}
void Register() override
{
+ OnCheckCast += SpellCheckCastFn(spell_hun_masters_call_SpellScript::DoCheckCast);
+
OnEffectHitTarget += SpellEffectFn(spell_hun_masters_call_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
OnEffectHitTarget += SpellEffectFn(spell_hun_masters_call_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
@@ -1022,7 +1114,7 @@ class spell_hun_rapid_recuperation_trigger : public SpellScriptLoader
}
}
- void HandleRapidKillingProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleRapidKillingProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
static uint32 const triggerSpells[2] = { SPELL_HUNTER_RAPID_RECUPERATION_MANA_R1, SPELL_HUNTER_RAPID_RECUPERATION_MANA_R2 };
@@ -1035,7 +1127,7 @@ class spell_hun_rapid_recuperation_trigger : public SpellScriptLoader
uint8 rank = GetSpellInfo()->GetRank();
uint32 spellId = triggerSpells[rank - 1];
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1368,7 +1460,7 @@ class spell_hun_thrill_of_the_hunt : public SpellScriptLoader
if (!amount)
return;
- caster->CastCustomSpell(SPELL_HUNTER_THRILL_OF_THE_HUNT_MANA, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_HUNTER_THRILL_OF_THE_HUNT_MANA, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1449,7 +1541,7 @@ class spell_hun_viper_attack_speed : public SpellScriptLoader
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (GetTarget()->HasAura(SPELL_HUNTER_ASPECT_OF_THE_VIPER))
- GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_VICIOUS_VIPER, true, NULL, aurEff);
+ GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_VICIOUS_VIPER, true, nullptr, aurEff);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
@@ -1476,6 +1568,8 @@ void AddSC_hunter_spell_scripts()
new spell_hun_aspect_of_the_beast();
new spell_hun_ascpect_of_the_viper();
new spell_hun_chimera_shot();
+ new spell_hun_cobra_strikes();
+ new spell_hun_cobra_strikes_triggered();
new spell_hun_disengage();
new spell_hun_glyph_of_arcane_shot();
new spell_hun_glyph_of_mend_pet();
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index b45df66e0ac..9ef5c5d0b4d 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -148,7 +148,7 @@ class spell_item_alchemists_stone : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
@@ -172,7 +172,7 @@ class spell_item_alchemists_stone : public SpellScriptLoader
}
int32 amount = CalculatePct(spellInfo->Effects[i].CalcValue(caster), 40);
- caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
}
@@ -220,7 +220,7 @@ class spell_item_anger_capacitor : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
@@ -237,7 +237,7 @@ class spell_item_anger_capacitor : public SpellScriptLoader
if (player->GetWeaponForAttack(OFF_ATTACK, true) && urand(0, 1))
spellId = SPELL_MANIFEST_ANGER_OFF_HAND;
- caster->CastSpell(target, spellId, true);
+ caster->CastSpell(target, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -358,7 +358,7 @@ class spell_item_aura_of_madness : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
static std::vector<uint32> const triggeredSpells[MAX_CLASSES] =
{
@@ -391,7 +391,7 @@ class spell_item_aura_of_madness : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
uint32 spellId = Trinity::Containers::SelectRandomContainerElement(triggeredSpells[caster->getClass()]);
- caster->CastSpell(caster, spellId, true);
+ caster->CastSpell(caster, spellId, true, nullptr, aurEff);
if (roll_chance_i(10))
caster->Unit::Say(SAY_MADNESS);
@@ -427,10 +427,10 @@ class spell_item_dementia : public SpellScriptLoader
return true;
}
- void HandlePeriodicDummy(AuraEffect const* /*aurEff*/)
+ void HandlePeriodicDummy(AuraEffect const* aurEff)
{
PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), RAND(SPELL_DEMENTIA_POS, SPELL_DEMENTIA_NEG), true);
+ GetTarget()->CastSpell(GetTarget(), RAND(SPELL_DEMENTIA_POS, SPELL_DEMENTIA_NEG), true, nullptr, aurEff);
}
void Register() override
@@ -490,7 +490,7 @@ class spell_item_blessing_of_ancient_kings : public SpellScriptLoader
protEff->GetBase()->RefreshDuration();
}
else
- GetTarget()->CastCustomSpell(SPELL_PROTECTION_OF_ANCIENT_KINGS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, NULL, aurEff);
+ GetTarget()->CastCustomSpell(SPELL_PROTECTION_OF_ANCIENT_KINGS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, nullptr, aurEff);
}
void Register() override
@@ -616,7 +616,7 @@ class spell_item_deathbringers_will : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
static std::vector<uint32> const triggeredSpells[MAX_CLASSES] =
{
@@ -648,12 +648,12 @@ class spell_item_deathbringers_will : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- auto const& randomSpells = triggeredSpells[caster->getClass()];
+ std::vector<uint32> const& randomSpells = triggeredSpells[caster->getClass()];
if (randomSpells.empty())
return;
uint32 spellId = Trinity::Containers::SelectRandomContainerElement(randomSpells);
- caster->CastSpell(caster, spellId, true);
+ caster->CastSpell(caster, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1083,7 +1083,7 @@ class spell_item_frozen_shadoweave : public SpellScriptLoader
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
Unit* caster = eventInfo.GetActor();
- caster->CastCustomSpell(SPELL_SHADOWMEND, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_SHADOWMEND, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1128,9 +1128,9 @@ class spell_item_gnomish_death_ray : public SpellScriptLoader
if (Unit* target = GetHitUnit())
{
if (urand(0, 99) < 15)
- caster->CastSpell(caster, SPELL_GNOMISH_DEATH_RAY_SELF, true, NULL); // failure
+ caster->CastSpell(caster, SPELL_GNOMISH_DEATH_RAY_SELF, true); // failure
else
- caster->CastSpell(target, SPELL_GNOMISH_DEATH_RAY_TARGET, true, NULL);
+ caster->CastSpell(target, SPELL_GNOMISH_DEATH_RAY_TARGET, true);
}
}
@@ -1169,10 +1169,10 @@ class spell_item_healing_touch_refund : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_HEALING_TOUCH_MANA, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_HEALING_TOUCH_MANA, true, nullptr, aurEff);
}
void Register() override
@@ -1226,7 +1226,7 @@ class spell_item_heartpierce : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
@@ -1243,6 +1243,7 @@ class spell_item_heartpierce : public SpellScriptLoader
case POWER_RAGE:
spellId = Rage;
break;
+ // Death Knights can't use daggers, but oh well
case POWER_RUNIC_POWER:
spellId = RunicPower;
break;
@@ -1250,7 +1251,7 @@ class spell_item_heartpierce : public SpellScriptLoader
return;
}
- caster->CastSpell((Unit*)nullptr, spellId, true);
+ caster->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1380,14 +1381,14 @@ class spell_item_mark_of_conquest : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
if (eventInfo.GetTypeMask() & (PROC_FLAG_DONE_RANGED_AUTO_ATTACK | PROC_FLAG_DONE_SPELL_RANGED_DMG_CLASS))
{
// in that case, do not cast heal spell
PreventDefaultAction();
// but mana instead
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MARK_OF_CONQUEST_ENERGIZE, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MARK_OF_CONQUEST_ENERGIZE, true, nullptr, aurEff);
}
}
@@ -1546,7 +1547,7 @@ class spell_item_net_o_matic : public SpellScriptLoader
else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
spellId = SPELL_NET_O_MATIC_TRIGGERED2;
- GetCaster()->CastSpell(target, spellId, true, NULL);
+ GetCaster()->CastSpell(target, spellId, true, nullptr);
}
}
@@ -1602,7 +1603,7 @@ class spell_item_noggenfogger_elixir : public SpellScriptLoader
case 2: spellId = SPELL_NOGGENFOGGER_ELIXIR_TRIGGERED2; break;
}
- caster->CastSpell(caster, spellId, true, NULL);
+ caster->CastSpell(caster, spellId, true, nullptr);
}
void Register() override
@@ -1734,7 +1735,7 @@ class spell_item_pet_healing : public SpellScriptLoader
int32 bp = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
Unit* caster = eventInfo.GetActor();
- caster->CastCustomSpell(SPELL_HEALTH_LINK, SPELLVALUE_BASE_POINT0, bp, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_HEALTH_LINK, SPELLVALUE_BASE_POINT0, bp, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -2206,7 +2207,7 @@ class spell_item_swift_hand_justice_dummy : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
int32 amount = caster->CountPctFromMaxHealth(aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_SWIFT_HAND_OF_JUSTICE_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_SWIFT_HAND_OF_JUSTICE_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -2244,10 +2245,10 @@ class spell_item_totem_of_flowing_water : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_LESSER_HEALING_WAVE_MANA, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_LESSER_HEALING_WAVE_MANA, true, nullptr, aurEff);
}
void Register() override
@@ -3741,17 +3742,17 @@ class spell_item_shard_of_the_scale : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
if (eventInfo.GetTypeMask() & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS)
- caster->CastSpell(target, HealProc, true);
+ caster->CastSpell(target, HealProc, true, nullptr, aurEff);
if (eventInfo.GetTypeMask() & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG)
- caster->CastSpell(target, DamageProc, true);
+ caster->CastSpell(target, DamageProc, true, nullptr, aurEff);
}
void Register() override
@@ -3887,7 +3888,7 @@ class spell_item_sunwell_neck : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Player* player = eventInfo.GetActor()->ToPlayer();
@@ -3895,10 +3896,10 @@ class spell_item_sunwell_neck : public SpellScriptLoader
// Aggression checks are in the spell system... just cast and forget
if (player->GetReputationRank(FACTION_ALDOR) == REP_EXALTED)
- player->CastSpell(target, Aldors, true);
+ player->CastSpell(target, Aldors, true, nullptr, aurEff);
if (player->GetReputationRank(FACTION_SCRYERS) == REP_EXALTED)
- player->CastSpell(target, Scryers, true);
+ player->CastSpell(target, Scryers, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index 8c37b3ac506..5c496024599 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -114,14 +114,14 @@ class spell_mage_arcane_potency : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
static uint32 const triggerSpell[2] = { SPELL_MAGE_ARCANE_POTENCY_RANK_1, SPELL_MAGE_ARCANE_POTENCY_RANK_2 };
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
uint32 spellId = triggerSpell[GetSpellInfo()->GetRank() - 1];
- caster->CastSpell(caster, spellId, true);
+ caster->CastSpell(caster, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -383,11 +383,11 @@ class spell_mage_imp_blizzard : public SpellScriptLoader
return true;
}
- void HandleChill(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleChill(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
uint32 triggerSpellId = sSpellMgr->GetSpellWithRank(SPELL_MAGE_CHILLED, GetSpellInfo()->GetRank());
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), triggerSpellId, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), triggerSpellId, true, nullptr, aurEff);
}
void Register() override
@@ -420,10 +420,10 @@ class spell_mage_imp_mana_gems : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MAGE_MANA_SURGE, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_MAGE_MANA_SURGE, true, nullptr, aurEff);
}
void Register() override
@@ -836,7 +836,7 @@ class spell_mage_hot_streak : public SpellScriptLoader
return;
Unit* caster = eventInfo.GetActor();
- caster->CastSpell(caster, SPELL_MAGE_HOT_STREAK_PROC, true);
+ caster->CastSpell(caster, SPELL_MAGE_HOT_STREAK_PROC, true, nullptr, aurEff);
}
// reset counter
@@ -1032,7 +1032,7 @@ class spell_mage_magic_absorption : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActionTarget();
int32 bp = CalculatePct(static_cast<int32>(caster->GetMaxPower(POWER_MANA)), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_MAGE_MAGIC_ABSORPTION_MANA, SPELLVALUE_BASE_POINT0, bp, caster, true);
+ caster->CastCustomSpell(SPELL_MAGE_MAGIC_ABSORPTION_MANA, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
}
void Register() override
@@ -1080,10 +1080,10 @@ class spell_mage_mana_shield : public SpellScriptLoader
}
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
Unit* caster = eventInfo.GetActionTarget();
- caster->CastSpell(caster, SPELL_MAGE_ARCANE_SURGE, true);
+ caster->CastSpell(caster, SPELL_MAGE_ARCANE_SURGE, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index 20665034298..693990edd0a 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -156,9 +156,16 @@ class spell_pal_ardent_defender : public SpellScriptLoader
enum Spell
{
- PAL_SPELL_ARDENT_DEFENDER_HEAL = 66235,
+ PAL_SPELL_ARDENT_DEFENDER_HEAL = 66235
};
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(PAL_SPELL_ARDENT_DEFENDER_HEAL))
+ return false;
+ return true;
+ }
+
bool Load() override
{
healPct = GetSpellInfo()->Effects[EFFECT_1].CalcValue();
@@ -192,7 +199,7 @@ class spell_pal_ardent_defender : public SpellScriptLoader
: float(defenseSkillValue) / float(reqDefForMaxHeal);
int32 healAmount = int32(victim->CountPctFromMaxHealth(uint32(healPct * pctFromDefense)));
- victim->CastCustomSpell(victim, PAL_SPELL_ARDENT_DEFENDER_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff);
+ victim->CastCustomSpell(PAL_SPELL_ARDENT_DEFENDER_HEAL, SPELLVALUE_BASE_POINT0, healAmount, victim, true, nullptr, aurEff);
victim->GetSpellHistory()->AddCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL, 0, std::chrono::minutes(2));
}
else if (remainingHealth < int32(allowedHealth))
@@ -824,7 +831,7 @@ class spell_pal_glyph_of_holy_light_dummy : public SpellScriptLoader
Unit* target = eventInfo.GetProcTarget();
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_PALADIN_GLYPH_OF_HOLY_LIGHT_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_PALADIN_GLYPH_OF_HOLY_LIGHT_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -976,12 +983,12 @@ class spell_pal_heart_of_the_crusader : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
uint32 spellId = sSpellMgr->GetSpellWithRank(SPELL_PALADIN_HEART_OF_THE_CRUSADER_EFF_R1, GetSpellInfo()->GetRank());
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1385,7 +1392,7 @@ class spell_pal_item_t6_trinket : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
@@ -1411,7 +1418,7 @@ class spell_pal_item_t6_trinket : public SpellScriptLoader
return;
if (roll_chance_i(chance))
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1542,7 +1549,7 @@ class spell_pal_judgement_of_light_heal : public SpellScriptLoader
Unit* caster = eventInfo.GetProcTarget();
int32 amount = static_cast<int32>(caster->CountPctFromMaxHealth(aurEff->GetAmount()));
- caster->CastCustomSpell(SPELL_PALADIN_JUDGEMENT_OF_LIGHT_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_PALADIN_JUDGEMENT_OF_LIGHT_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff, GetCasterGUID());
}
void Register() override
@@ -1586,7 +1593,7 @@ class spell_pal_judgement_of_wisdom_mana : public SpellScriptLoader
Unit* caster = eventInfo.GetProcTarget();
int32 amount = CalculatePct(static_cast<int32>(caster->GetCreateMana()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_PALADIN_JUDGEMENT_OF_WISDOM_MANA, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_PALADIN_JUDGEMENT_OF_WISDOM_MANA, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff, GetCasterGUID());
}
void Register() override
@@ -1655,13 +1662,13 @@ class spell_pal_judgements_of_the_wise : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell((Unit*)nullptr, SPELL_PALADIN_JUDGEMENTS_OF_THE_WISE_MANA, true);
- caster->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true);
+ caster->CastSpell((Unit*)nullptr, SPELL_PALADIN_JUDGEMENTS_OF_THE_WISE_MANA, true, nullptr, aurEff);
+ caster->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
@@ -1782,7 +1789,7 @@ class spell_pal_light_s_beacon : public SpellScriptLoader
/// @todo: caster must be the healed unit to perform distance checks correctly
/// but that will break animation on clientside
/// caster in spell packets must be the healing unit
- eventInfo.GetActor()->CastCustomSpell(healSpellId, SPELLVALUE_BASE_POINT0, heal, beaconTarget, true);
+ eventInfo.GetActor()->CastCustomSpell(healSpellId, SPELLVALUE_BASE_POINT0, heal, beaconTarget, true, nullptr, aurEff);
}
void Register() override
@@ -1896,7 +1903,7 @@ class spell_pal_righteous_vengeance : public SpellScriptLoader
// Add remaining ticks to damage done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_PALADIN_RIGHTEOUS_VENGEANCE_DAMAGE, SPELL_AURA_PERIODIC_DAMAGE);
- caster->CastCustomSpell(SPELL_PALADIN_RIGHTEOUS_VENGEANCE_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_PALADIN_RIGHTEOUS_VENGEANCE_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -1990,7 +1997,7 @@ class spell_pal_sacred_shield_dummy : public SpellScriptLoader
cooldown = Seconds(bonus->GetAmount());
_cooldownEnd = now + cooldown;
- caster->CastSpell(eventInfo.GetActionTarget(), SPELL_PALADIN_SACRED_SHIELD_TRIGGER, true);
+ caster->CastSpell(eventInfo.GetActionTarget(), SPELL_PALADIN_SACRED_SHIELD_TRIGGER, true, nullptr, aurEff);
}
void Register() override
@@ -2092,7 +2099,7 @@ class spell_pal_seal_of_vengeance : public SpellScriptLoader
5 33% 38%
*/
- void HandleApplyDoT(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleApplyDoT(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
@@ -2100,22 +2107,23 @@ class spell_pal_seal_of_vengeance : public SpellScriptLoader
return;
// don't cast triggered, spell already has SPELL_ATTR4_CAN_CAST_WHILE_CASTING attr
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), DoTSpell, false);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), DoTSpell, TRIGGERED_DONT_RESET_PERIODIC_TIMER, nullptr, aurEff);
}
- void HandleSeal(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleSeal(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
- AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PALADIN, 0x00000000, 0x00000800, 0x00000000, caster->GetGUID());
- if (!aurEff)
+ // get current aura on target, if any
+ AuraEffect const* sealDot = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PALADIN, 0x00000000, 0x00000800, 0x00000000, caster->GetGUID());
+ if (!sealDot)
return;
- uint8 stacks = aurEff->GetBase()->GetStackAmount();
- uint8 maxStacks = aurEff->GetSpellInfo()->StackAmount;
+ uint8 const stacks = sealDot->GetBase()->GetStackAmount();
+ uint8 const maxStacks = sealDot->GetSpellInfo()->StackAmount;
if (stacks < maxStacks && !(eventInfo.GetTypeMask() & PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS))
return;
@@ -2125,7 +2133,7 @@ class spell_pal_seal_of_vengeance : public SpellScriptLoader
amount *= stacks;
amount /= maxStacks;
- caster->CastCustomSpell(DamageSpell, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(DamageSpell, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2209,7 +2217,7 @@ class spell_pal_spiritual_attunement : public SpellScriptLoader
HealInfo* healInfo = eventInfo.GetHealInfo();
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetEffectiveHeal()), aurEff->GetAmount());
- eventInfo.GetActionTarget()->CastCustomSpell(SPELL_PALADIN_SPIRITUAL_ATTUNEMENT_MANA, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ eventInfo.GetActionTarget()->CastCustomSpell(SPELL_PALADIN_SPIRITUAL_ATTUNEMENT_MANA, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -2256,10 +2264,10 @@ class spell_pal_sheath_of_light : public SpellScriptLoader
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PALADIN_SHEATH_OF_LIGHT_HEAL);
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
amount /= spellInfo->GetMaxTicks();
- // Add remaining ticks to damage done
+ // Add remaining ticks to healing done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_PALADIN_SHEATH_OF_LIGHT_HEAL, SPELL_AURA_PERIODIC_HEAL);
- caster->CastCustomSpell(SPELL_PALADIN_SHEATH_OF_LIGHT_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_PALADIN_SHEATH_OF_LIGHT_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2294,7 +2302,7 @@ class spell_pal_t3_6p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
@@ -2325,7 +2333,7 @@ class spell_pal_t3_6p_bonus : public SpellScriptLoader
return;
}
- caster->CastSpell(target, spellId, true);
+ caster->CastSpell(target, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -2371,10 +2379,10 @@ class spell_pal_t8_2p_bonus : public SpellScriptLoader
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PALADIN_HOLY_MENDING);
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
amount /= spellInfo->GetMaxTicks();
- // Add remaining ticks to damage done
+ // Add remaining ticks to healing done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_PALADIN_HOLY_MENDING, SPELL_AURA_PERIODIC_HEAL);
- caster->CastCustomSpell(SPELL_PALADIN_HOLY_MENDING, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_PALADIN_HOLY_MENDING, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 16bf769a9ae..8a4bdeedccc 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -120,7 +120,7 @@ class spell_pri_aq_3p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
@@ -132,7 +132,7 @@ class spell_pri_aq_3p_bonus : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), 10);
- caster->CastCustomSpell(SPELL_PRIEST_ORACULAR_HEAL, SPELLVALUE_BASE_POINT0, amount, caster, true);
+ caster->CastCustomSpell(SPELL_PRIEST_ORACULAR_HEAL, SPELLVALUE_BASE_POINT0, amount, caster, true, nullptr, aurEff);
}
void Register() override
@@ -236,7 +236,7 @@ class spell_pri_body_and_soul : public SpellScriptLoader
return;
if (roll_chance_i(aurEff->GetAmount()))
- caster->CastSpell(caster, SPELL_PRIEST_BODY_AND_SOUL_POISON_TRIGGER, true);
+ caster->CastSpell(caster, SPELL_PRIEST_BODY_AND_SOUL_POISON_TRIGGER, true, nullptr, aurEff);
}
void Register() override
@@ -412,7 +412,7 @@ class spell_pri_glyph_of_dispel_magic : public SpellScriptLoader
Unit* target = eventInfo.GetProcTarget();
int32 amount = static_cast<int32>(target->CountPctFromMaxHealth(aurEff->GetAmount()));
- caster->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_DISPEL_MAGIC_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_DISPEL_MAGIC_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -660,15 +660,15 @@ class spell_pri_item_t6_trinket : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
if (eventInfo.GetSpellTypeMask() & PROC_SPELL_TYPE_HEAL)
- caster->CastSpell((Unit*)nullptr, SPELL_PRIEST_DIVINE_BLESSING, true);
+ caster->CastSpell((Unit*)nullptr, SPELL_PRIEST_DIVINE_BLESSING, true, nullptr, aurEff);
if (eventInfo.GetSpellTypeMask() & PROC_SPELL_TYPE_DAMAGE)
- caster->CastSpell((Unit*)nullptr, SPELL_PRIEST_DIVINE_WRATH, true);
+ caster->CastSpell((Unit*)nullptr, SPELL_PRIEST_DIVINE_WRATH, true, nullptr, aurEff);
}
void Register() override
@@ -1091,17 +1091,22 @@ class spell_pri_renew : public SpellScriptLoader
void HandleApplyEffect(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
- if (Unit* caster = GetCaster())
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ // Empowered Renew
+ if (AuraEffect const* empoweredRenewAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT, EFFECT_1))
{
- // Empowered Renew
- if (AuraEffect const* empoweredRenewAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT, EFFECT_1))
- {
- uint32 heal = caster->SpellHealingBonusDone(GetTarget(), GetSpellInfo(), GetEffect(EFFECT_0)->GetAmount(), DOT);
- heal = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT);
+ int32 heal = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct();
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(GetId(), heal);
+ heal = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT);
- int32 basepoints0 = empoweredRenewAurEff->GetAmount() * GetEffect(EFFECT_0)->GetTotalTicks() * int32(heal) / 100;
- caster->CastCustomSpell(GetTarget(), SPELL_PRIEST_EMPOWERED_RENEW, &basepoints0, NULL, NULL, true, NULL, aurEff);
- }
+ heal *= GetSpellInfo()->GetMaxTicks();
+
+ int32 basepoints0 = CalculatePct(heal, empoweredRenewAurEff->GetAmount());
+ caster->CastCustomSpell(SPELL_PRIEST_EMPOWERED_RENEW, SPELLVALUE_BASE_POINT0, basepoints0, GetTarget(), true, nullptr, aurEff);
}
}
@@ -1147,11 +1152,11 @@ class spell_pri_shadowfiend_death : public SpellScriptLoader
return shadowfiend->HealthBelowPctDamaged(1, damageInfo->GetDamage());
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActionTarget()->GetOwner();
- caster->CastSpell(caster, SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA, true);
+ caster->CastSpell(caster, SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA, true, nullptr, aurEff);
}
void Register() override
@@ -1227,7 +1232,7 @@ class spell_pri_vampiric_embrace : public SpellScriptLoader
int32 selfHeal = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
int32 partyHeal = selfHeal / 5;
Unit* caster = eventInfo.GetActor();
- caster->CastCustomSpell((Unit*)nullptr, SPELL_PRIEST_VAMPIRIC_EMBRACE_HEAL, &partyHeal, &selfHeal, nullptr, true);
+ caster->CastCustomSpell((Unit*)nullptr, SPELL_PRIEST_VAMPIRIC_EMBRACE_HEAL, &partyHeal, &selfHeal, nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -1275,16 +1280,16 @@ class spell_pri_vampiric_touch : public SpellScriptLoader
{
int32 damage = aurEff->GetAmount() * 8;
// backfire damage
- caster->CastCustomSpell(target, SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL, &damage, NULL, NULL, true, NULL, aurEff);
+ caster->CastCustomSpell(SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL, SPELLVALUE_BASE_POINT0, damage, target, true, nullptr, aurEff);
}
}
}
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
@@ -1319,10 +1324,10 @@ class spell_pri_t3_4p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_PRIEST_ARMOR_OF_FAITH, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_PRIEST_ARMOR_OF_FAITH, true, nullptr, aurEff);
}
void Register() override
@@ -1418,7 +1423,7 @@ class spell_pri_t10_heal_2p_bonus : public SpellScriptLoader
Unit* target = eventInfo.GetProcTarget();
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_PRIEST_BLESSED_HEALING, SPELL_AURA_PERIODIC_HEAL);
- caster->CastCustomSpell(SPELL_PRIEST_BLESSED_HEALING, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_PRIEST_BLESSED_HEALING, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index 47c9fa56eae..f3d30af1f84 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -232,10 +232,10 @@ class spell_rog_deadly_brew : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_ROGUE_CRIPPLING_POISON, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_ROGUE_CRIPPLING_POISON, true, nullptr, aurEff);
}
void Register() override
@@ -625,7 +625,7 @@ class spell_rog_quick_recovery : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
int32 amount = CalculatePct(spellInfo->CalcPowerCost(caster, spellInfo->GetSchoolMask()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_ROGUE_QUICK_RECOVERY_ENERGY, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_ROGUE_QUICK_RECOVERY_ENERGY, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -721,10 +721,10 @@ class spell_rog_glyph_of_backstab : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_ROGUE_GLYPH_OF_BACKSTAB_TRIGGER, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_ROGUE_GLYPH_OF_BACKSTAB_TRIGGER, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 397427b505f..37b08aee7ca 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -119,7 +119,7 @@ class spell_sha_ancestral_awakening : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- eventInfo.GetActor()->CastCustomSpell(SPELL_SHAMAN_ANCESTRAL_AWAKENING_DUMMY, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ eventInfo.GetActor()->CastCustomSpell(SPELL_SHAMAN_ANCESTRAL_AWAKENING_DUMMY, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -423,7 +423,7 @@ class spell_sha_earth_shield : public SpellScriptLoader
{
PreventDefaultAction();
- GetTarget()->CastCustomSpell(SPELL_SHAMAN_EARTH_SHIELD_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff, GetCasterGUID());
+ GetTarget()->CastCustomSpell(SPELL_SHAMAN_EARTH_SHIELD_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, nullptr, aurEff, GetCasterGUID());
}
void Register() override
@@ -732,25 +732,25 @@ class spell_sha_flametongue_weapon : public SpellScriptLoader
Item* item = ASSERT_NOTNULL(player->GetWeaponForAttack(attType));
- float basePoints(GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue());
+ float const basePoints = GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue();
// Flametongue max damage is normalized based on a 4.0 speed weapon
// Tooltip says max damage = BasePoints / 25, so BasePoints / 25 / 4 to get base damage per 1.0s AS
float fireDamage = basePoints / 100.0f;
- float attackSpeed = player->GetAttackTime(attType) / 1000.f;
+ float const attackSpeed = player->GetAttackTime(attType) / 1000.f;
fireDamage *= attackSpeed;
// clip value between (BasePoints / 77) and (BasePoints / 25) as the tooltip indicates
RoundToInterval(fireDamage, basePoints / 77.0f, basePoints / 25.0f);
// Calculate Spell Power scaling
- float spellPowerBonus(player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) + target->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE));
+ float spellPowerBonus = player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) + target->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE);
float const spCoeff = 0.03811f;
spellPowerBonus *= spCoeff * attackSpeed;
// All done, now proc damage
int32 amount = static_cast<int32>(fireDamage + spellPowerBonus);
- player->CastCustomSpell(SPELL_SHAMAN_FLAMETONGUE_ATTACK, SPELLVALUE_BASE_POINT0, amount, target, true, item);
+ player->CastCustomSpell(SPELL_SHAMAN_FLAMETONGUE_ATTACK, SPELLVALUE_BASE_POINT0, amount, target, true, item, aurEff);
}
void Register() override
@@ -798,7 +798,7 @@ class spell_sha_frozen_power : public SpellScriptLoader
if (caster->GetDistance(target) < minDistance)
return;
- caster->CastSpell(target, SPELL_SHAMAN_FREEZE, true);
+ caster->CastSpell(target, SPELL_SHAMAN_FREEZE, true, nullptr, aurEff);
}
void Register() override
@@ -881,7 +881,7 @@ class spell_sha_glyph_of_healing_wave : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_SHAMAN_GLYPH_OF_HEALING_WAVE_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true);
+ caster->CastCustomSpell(SPELL_SHAMAN_GLYPH_OF_HEALING_WAVE_HEAL, SPELLVALUE_BASE_POINT0, amount, (Unit*)nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -941,7 +941,7 @@ class spell_sha_glyph_of_totem_of_wrath : public SpellScriptLoader
int32 bp0 = CalculatePct(totemSpell->Effects[EFFECT_0].CalcValue(caster), aurEff->GetAmount());
int32 bp1 = CalculatePct(totemSpell->Effects[EFFECT_1].CalcValue(caster), aurEff->GetAmount());
- caster->CastCustomSpell((Unit*)nullptr, SPELL_SHAMAN_TOTEM_OF_WRATH_SPELL_POWER, &bp0, &bp1, nullptr, true);
+ caster->CastCustomSpell((Unit*)nullptr, SPELL_SHAMAN_TOTEM_OF_WRATH_SPELL_POWER, &bp0, &bp1, nullptr, true, nullptr, aurEff);
}
void Register() override
@@ -997,7 +997,8 @@ class spell_sha_healing_stream_totem : public SpellScriptLoader
damage = int32(target->SpellHealingBonusTaken(owner, triggeringSpell, damage, HEAL));
}
- caster->CastCustomSpell(target, SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL, &damage, 0, 0, true, 0, 0, GetOriginalCaster()->GetGUID());
+
+ caster->CastCustomSpell(SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL, SPELLVALUE_BASE_POINT0, damage, target, true, nullptr, nullptr, GetOriginalCaster()->GetGUID());
}
}
}
@@ -1044,9 +1045,8 @@ class spell_sha_heroism : public SpellScriptLoader
void Register() override
{
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_1, TARGET_UNIT_CASTER_AREA_RAID);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_2, TARGET_UNIT_CASTER_AREA_RAID);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_ALL, TARGET_UNIT_CASTER_AREA_RAID);
+
AfterHit += SpellHitFn(spell_sha_heroism_SpellScript::ApplyDebuff);
}
};
@@ -1091,17 +1091,17 @@ class spell_sha_imp_water_shield : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
// Get Water Shield
- AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x00000000, 0x00000020, 0x00000000, caster->GetGUID());
- if (!aurEff)
+ AuraEffect const* waterShield = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x00000000, 0x00000020, 0x00000000, caster->GetGUID());
+ if (!waterShield)
return;
- uint32 spellId = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- caster->CastSpell((Unit*)nullptr, spellId, true);
+ uint32 spellId = waterShield->GetSpellInfo()->Effects[waterShield->GetEffIndex()].TriggerSpell;
+ caster->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1135,7 +1135,7 @@ class spell_sha_lightning_overload : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
@@ -1161,7 +1161,7 @@ class spell_sha_lightning_overload : public SpellScriptLoader
spellId = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_CHAIN_LIGHTNING_OVERLOAD_R1, spellInfo->GetRank());
}
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true);
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1196,7 +1196,7 @@ class spell_sha_item_lightning_shield : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
- GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD, true, NULL, aurEff);
+ GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD, true, nullptr, aurEff);
}
void Register() override
@@ -1231,7 +1231,7 @@ class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
- GetTarget()->CastSpell(GetTarget(), SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE, true, NULL, aurEff);
+ GetTarget()->CastSpell(GetTarget(), SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE, true, nullptr, aurEff);
}
void Register() override
@@ -1306,7 +1306,7 @@ class spell_sha_item_t6_trinket : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
@@ -1338,7 +1338,7 @@ class spell_sha_item_t6_trinket : public SpellScriptLoader
return;
if (roll_chance_i(chance))
- eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true);
+ eventInfo.GetActor()->CastSpell((Unit*)nullptr, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1507,7 +1507,7 @@ class spell_sha_maelstrom_weapon : public SpellScriptLoader
if (!aurEff || !roll_chance_i(aurEff->GetAmount()))
return;
- caster->CastSpell((Unit*)nullptr, SPELL_SHAMAN_MAELSTROM_POWER, true);
+ caster->CastSpell((Unit*)nullptr, SPELL_SHAMAN_MAELSTROM_POWER, true, nullptr, aurEff);
}
void Register() override
@@ -1593,7 +1593,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader
effValue += dummy->GetAmount();
// Regenerate 6% of Total Mana Every 3 secs
int32 effBasePoints0 = int32(CalculatePct(unitTarget->GetMaxPower(POWER_MANA), effValue));
- caster->CastCustomSpell(unitTarget, SPELL_SHAMAN_MANA_TIDE_TOTEM, &effBasePoints0, NULL, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID());
+ caster->CastCustomSpell(SPELL_SHAMAN_MANA_TIDE_TOTEM, SPELLVALUE_BASE_POINT0, effBasePoints0, unitTarget, true, nullptr, nullptr, GetOriginalCaster()->GetGUID());
}
}
}
@@ -1777,8 +1777,8 @@ class spell_sha_spirit_hunt : public SpellScriptLoader
return;
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- caster->CastCustomSpell(SPELL_SHAMAN_SPIRIT_HUNT_HEAL, SPELLVALUE_BASE_POINT0, amount, caster, true);
- caster->CastCustomSpell(SPELL_SHAMAN_SPIRIT_HUNT_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_SHAMAN_SPIRIT_HUNT_HEAL, SPELLVALUE_BASE_POINT0, amount, caster, true, nullptr, aurEff);
+ caster->CastCustomSpell(SPELL_SHAMAN_SPIRIT_HUNT_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -1810,20 +1810,20 @@ class spell_sha_static_shock : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
// Get Lightning Shield
- AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x00000400, 0x00000000, 0x00000000, caster->GetGUID());
- if (!aurEff)
+ AuraEffect const* lightningShield = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x00000400, 0x00000000, 0x00000000, caster->GetGUID());
+ if (!lightningShield)
return;
- uint32 spellId = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_LIGHTNING_SHIELD_DAMAGE_R1, aurEff->GetSpellInfo()->GetRank());
- eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true);
- aurEff->GetBase()->DropCharge();
+ uint32 spellId = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_LIGHTNING_SHIELD_DAMAGE_R1, lightningShield->GetSpellInfo()->GetRank());
+ eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), spellId, true, nullptr, aurEff);
+ lightningShield->GetBase()->DropCharge();
}
void Register() override
@@ -1919,14 +1919,14 @@ public:
return true;
}
- void HandleDummy(AuraEffect const* /*aurEff*/)
+ void HandleDummy(AuraEffect const* aurEff)
{
Unit* target = GetTarget();
for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
if (!target->m_SummonSlot[i])
return;
- target->CastSpell(target, SPELL_SHAMAN_TOTEMIC_MASTERY, true);
+ target->CastSpell(target, SPELL_SHAMAN_TOTEMIC_MASTERY, true, nullptr, aurEff);
PreventDefaultAction();
}
@@ -1962,7 +1962,7 @@ class spell_sha_t3_6p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
@@ -1993,7 +1993,7 @@ class spell_sha_t3_6p_bonus : public SpellScriptLoader
return;
}
- caster->CastSpell(target, spellId, true);
+ caster->CastSpell(target, spellId, true, nullptr, aurEff);
}
void Register() override
@@ -2037,12 +2037,12 @@ class spell_sha_t8_elemental_4p_bonus : public SpellScriptLoader
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
amount /= spellInfo->GetMaxTicks();
- // Add remaining ticks to healing done
+ // Add remaining ticks to damage done
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_SHAMAN_ELECTRIFIED, SPELL_AURA_PERIODIC_DAMAGE);
- caster->CastCustomSpell(SPELL_SHAMAN_ELECTRIFIED, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_SHAMAN_ELECTRIFIED, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2086,12 +2086,12 @@ class spell_sha_t9_elemental_4p_bonus : public SpellScriptLoader
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
amount /= spellInfo->GetMaxTicks();
- // Add remaining ticks to healing done
+ // Add remaining ticks to damage done
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_SHAMAN_LAVA_BURST_BONUS_DAMAGE, SPELL_AURA_PERIODIC_DAMAGE);
- caster->CastCustomSpell(SPELL_SHAMAN_LAVA_BURST_BONUS_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_SHAMAN_LAVA_BURST_BONUS_DAMAGE, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2185,7 +2185,7 @@ class spell_sha_t10_restoration_4p_bonus : public SpellScriptLoader
Unit* target = eventInfo.GetProcTarget();
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_SHAMAN_CHAINED_HEAL, SPELL_AURA_PERIODIC_HEAL);
- caster->CastCustomSpell(SPELL_SHAMAN_CHAINED_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true);
+ caster->CastCustomSpell(SPELL_SHAMAN_CHAINED_HEAL, SPELLVALUE_BASE_POINT0, amount, target, true, nullptr, aurEff);
}
void Register() override
@@ -2221,7 +2221,6 @@ class spell_sha_windfury_weapon : public SpellScriptLoader
bool CheckProc(ProcEventInfo& eventInfo)
{
-
Player* player = eventInfo.GetActor()->ToPlayer();
if (!player)
return false;
@@ -2241,7 +2240,7 @@ class spell_sha_windfury_weapon : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
@@ -2281,7 +2280,7 @@ class spell_sha_windfury_weapon : public SpellScriptLoader
// Attack twice
for (uint8 i = 0; i < 2; ++i)
- player->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, item);
+ player->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, item, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index cccebab6259..1a8252ad7ec 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -596,11 +596,11 @@ class spell_warl_glyph_of_corruption_nightfall : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell(caster, SPELL_WARLOCK_SHADOW_TRANCE, true);
+ caster->CastSpell(caster, SPELL_WARLOCK_SHADOW_TRANCE, true, nullptr, aurEff);
}
void Register() override
@@ -632,11 +632,11 @@ public:
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell(caster, SPELL_WARLOCK_GLYPH_OF_LIFE_TAP_TRIGGERED, true);
+ caster->CastSpell(caster, SPELL_WARLOCK_GLYPH_OF_LIFE_TAP_TRIGGERED, true, nullptr, aurEff);
}
void Register() override
@@ -1135,7 +1135,7 @@ class spell_warl_seed_of_corruption_dummy : public SpellScriptLoader
return;
uint32 spellId = sSpellMgr->GetSpellWithRank(SPELL_WARLOCK_SEED_OF_CORRUPTION_DAMAGE_R1, GetSpellInfo()->GetRank());
- caster->CastSpell(eventInfo.GetActionTarget(), spellId, true);
+ caster->CastSpell(eventInfo.GetActionTarget(), spellId, true, nullptr, aurEff);
}
void Register() override
@@ -1193,7 +1193,7 @@ class spell_warl_seed_of_corruption_generic : public SpellScriptLoader
if (!caster)
return;
- caster->CastSpell(eventInfo.GetActionTarget(), SPELL_WARLOCK_SEED_OF_CORRUPTION_GENERIC, true);
+ caster->CastSpell(eventInfo.GetActionTarget(), SPELL_WARLOCK_SEED_OF_CORRUPTION_GENERIC, true, nullptr, aurEff);
}
void Register() override
@@ -1344,11 +1344,11 @@ class spell_warl_soul_leech : public SpellScriptLoader
uint32 selfSpellId = casterMana[impSoulLeechRank - 1];
uint32 petSpellId = petMana[impSoulLeechRank - 1];
- caster->CastSpell((Unit*)nullptr, selfSpellId, true);
- caster->CastSpell((Unit*)nullptr, petSpellId, true);
+ caster->CastSpell((Unit*)nullptr, selfSpellId, true, nullptr, aurEff);
+ caster->CastSpell((Unit*)nullptr, petSpellId, true, nullptr, aurEff);
if (roll_chance_i(impSoulLeech->GetAmount()))
- caster->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true);
+ caster->CastSpell((Unit*)nullptr, SPELL_REPLENISHMENT, true, nullptr, aurEff);
}
void Register() override
@@ -1422,11 +1422,11 @@ class spell_warl_t4_2p_bonus : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell(caster, Trigger, true);
+ caster->CastSpell(caster, Trigger, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 084c0441a0b..81fb4ec2457 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -486,11 +486,11 @@ class spell_warr_glyph_of_blocking : public SpellScriptLoader
return true;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastSpell(caster, SPELL_WARRIOR_GLYPH_OF_BLOCKING, true);
+ caster->CastSpell(caster, SPELL_WARRIOR_GLYPH_OF_BLOCKING, true, nullptr, aurEff);
}
void Register() override
@@ -562,7 +562,7 @@ class spell_warr_improved_spell_reflection : public SpellScriptLoader
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
- caster->CastCustomSpell(SPELL_WARRIOR_IMPROVED_SPELL_REFLECTION_TRIGGER, SPELLVALUE_MAX_TARGETS, aurEff->GetAmount(), caster, true);
+ caster->CastCustomSpell(SPELL_WARRIOR_IMPROVED_SPELL_REFLECTION_TRIGGER, SPELLVALUE_MAX_TARGETS, aurEff->GetAmount(), caster, true, nullptr, aurEff);
}
void Register() override
@@ -832,14 +832,14 @@ class spell_warr_second_wind : public SpellScriptLoader
return (spellInfo->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN))) != 0;
}
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
static uint32 const triggeredSpells[2] = { SPELL_WARRIOR_SECOND_WIND_TRIGGER_1, SPELL_WARRIOR_SECOND_WIND_TRIGGER_2 };
PreventDefaultAction();
Unit* caster = eventInfo.GetActionTarget();
uint32 spellId = triggeredSpells[GetSpellInfo()->GetRank() - 1];
- caster->CastSpell(caster, spellId, true);
+ caster->CastSpell(caster, spellId, true, nullptr, aurEff);
}
void Register() override
diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp
index 690600867d9..f106f96f5ec 100644
--- a/src/tools/vmap4_extractor/mpq_libmpq.cpp
+++ b/src/tools/vmap4_extractor/mpq_libmpq.cpp
@@ -19,6 +19,7 @@
#include "mpq_libmpq04.h"
#include <deque>
#include <cstdio>
+#include <algorithm>
ArchiveSet gOpenArchives;
@@ -52,6 +53,11 @@ MPQArchive::MPQArchive(const char* filename)
gOpenArchives.push_front(this);
}
+bool MPQArchive::isOpened() const
+{
+ return std::find(gOpenArchives.begin(), gOpenArchives.end(), this) != gOpenArchives.end();
+}
+
void MPQArchive::close()
{
//gOpenArchives.erase(erase(&mpq_a);
diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h
index 97b77d4643b..f4a9d2aa596 100644
--- a/src/tools/vmap4_extractor/mpq_libmpq04.h
+++ b/src/tools/vmap4_extractor/mpq_libmpq04.h
@@ -34,7 +34,7 @@ public:
mpq_archive_s *mpq_a;
MPQArchive(const char* filename);
- ~MPQArchive() { close(); }
+ ~MPQArchive() { if (isOpened()) close(); }
void GetFileListTo(std::vector<std::string>& filelist) {
uint32_t filenum;
@@ -66,6 +66,7 @@ public:
private:
void close();
+ bool isOpened() const;
};
typedef std::deque<MPQArchive*> ArchiveSet;
@@ -95,13 +96,8 @@ public:
inline void flipcc(char *fcc)
{
- char t;
- t=fcc[0];
- fcc[0]=fcc[3];
- fcc[3]=t;
- t=fcc[1];
- fcc[1]=fcc[2];
- fcc[2]=t;
+ std::swap(fcc[0], fcc[3]);
+ std::swap(fcc[1], fcc[2]);
}
#endif