aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql6
-rw-r--r--sql/updates/characters/master/2020_06_12_00_characters.sql2
-rw-r--r--src/common/Utilities/IteratorPair.h6
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp12
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.cpp54
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp5
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp102
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h4
-rw-r--r--src/server/game/AI/CreatureAI.cpp8
-rw-r--r--src/server/game/AI/CreatureAI.h25
-rw-r--r--src/server/game/AI/CreatureAIImpl.h31
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.cpp3
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp18
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp32
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp4
-rw-r--r--src/server/game/Chat/ChatLink.cpp10
-rw-r--r--src/server/game/Combat/ThreatManager.cpp2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp171
-rw-r--r--src/server/game/Conditions/DisableMgr.cpp2
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp64
-rw-r--r--src/server/game/DataStores/DB2Stores.h2
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp4
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp18
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp17
-rw-r--r--src/server/game/Entities/Creature/Trainer.cpp6
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp8
-rw-r--r--src/server/game/Entities/Item/Item.cpp4
-rw-r--r--src/server/game/Entities/Object/Updates/ViewerDependentValues.h4
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp38
-rw-r--r--src/server/game/Entities/Player/Player.cpp146
-rw-r--r--src/server/game/Entities/Totem/Totem.cpp20
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp135
-rw-r--r--src/server/game/Entities/Unit/Unit.h4
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp54
-rw-r--r--src/server/game/Handlers/PetHandler.cpp27
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp14
-rw-r--r--src/server/game/Handlers/ToyHandler.cpp2
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp5
-rw-r--r--src/server/game/Loot/LootMgr.cpp10
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp90
-rw-r--r--src/server/game/Skills/SkillDiscovery.cpp11
-rw-r--r--src/server/game/Skills/SkillExtraItems.cpp8
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp54
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp86
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h24
-rw-r--r--src/server/game/Spells/Spell.cpp144
-rw-r--r--src/server/game/Spells/Spell.h16
-rw-r--r--src/server/game/Spells/SpellEffects.cpp54
-rw-r--r--src/server/game/Spells/SpellHistory.cpp15
-rw-r--r--src/server/game/Spells/SpellInfo.cpp865
-rw-r--r--src/server/game/Spells/SpellInfo.h44
-rw-r--r--src/server/game/Spells/SpellMgr.cpp570
-rw-r--r--src/server/game/Spells/SpellMgr.h33
-rw-r--r--src/server/game/Spells/SpellScript.cpp14
-rw-r--r--src/server/game/Spells/SpellScript.h7
-rw-r--r--src/server/game/Tools/CharacterDatabaseCleaner.cpp2
-rw-r--r--src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp8
-rw-r--r--src/server/scripts/Commands/cs_cast.cpp2
-rw-r--r--src/server/scripts/Commands/cs_disable.cpp2
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp19
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp21
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp12
-rw-r--r--src/server/scripts/Commands/cs_pet.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp2
-rw-r--r--src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp2
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp10
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp4
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp12
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp2
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp10
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp4
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp4
-rw-r--r--src/server/scripts/Spells/spell_item.cpp12
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp10
-rw-r--r--src/server/scripts/Spells/spell_monk.cpp2
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp8
-rw-r--r--src/server/scripts/Spells/spell_pet.cpp6
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp14
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp6
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp14
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp6
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp2
-rw-r--r--src/server/scripts/World/duel_reset.cpp4
-rw-r--r--src/server/scripts/World/guards.cpp1
-rw-r--r--src/server/scripts/World/item_scripts.cpp5
-rw-r--r--src/server/scripts/World/mob_generic_creature.cpp3
-rw-r--r--src/server/scripts/World/npc_professions.cpp4
-rw-r--r--src/server/scripts/World/npcs_special.cpp2
101 files changed, 1599 insertions, 1764 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 625ad4ef783..7f03bea5193 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -511,6 +511,7 @@ CREATE TABLE `character_aura` (
`spell` int(10) unsigned NOT NULL,
`effectMask` int(10) unsigned NOT NULL,
`recalculateMask` int(10) unsigned NOT NULL DEFAULT '0',
+ `difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
`stackCount` tinyint(3) unsigned NOT NULL DEFAULT '1',
`maxDuration` int(11) NOT NULL DEFAULT '0',
`remainTime` int(11) NOT NULL DEFAULT '0',
@@ -3342,6 +3343,7 @@ CREATE TABLE `pet_aura` (
`spell` int(10) unsigned NOT NULL,
`effectMask` int(10) unsigned NOT NULL,
`recalculateMask` int(10) unsigned NOT NULL DEFAULT '0',
+ `difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
`stackCount` tinyint(3) unsigned NOT NULL DEFAULT '1',
`maxDuration` int(11) NOT NULL DEFAULT '0',
`remainTime` int(11) NOT NULL DEFAULT '0',
@@ -3774,8 +3776,8 @@ INSERT INTO `updates` VALUES
('2020_04_24_00_characters.sql','85E2E0395A9457A53D73A9E0A7BB39B7E4C429BF','RELEASED','2020-04-24 22:04:59',0),
('2020_04_25_00_characters_2017_04_03_00_characters.sql','00FA3EFADAF807AC96619A3FE47216E21C3FCB19','RELEASED','2020-04-25 00:00:00',0),
('2020_04_26_00_characters_2017_04_12_00_characters.sql','86AA94DA9B1EA283101100886C10F648C0CE6494','RELEASED','2020-04-26 00:00:00',0),
-('2020_04_26_01_characters_2017_04_12_01_characters.sql','5A8A1215E3A2356722F52CD7A64BBE03D21FBEA3','RELEASED','2020-04-26 00:00:00',0);
-
+('2020_04_26_01_characters_2017_04_12_01_characters.sql','5A8A1215E3A2356722F52CD7A64BBE03D21FBEA3','RELEASED','2020-04-26 00:00:00',0),
+('2020_06_12_00_characters.sql','DF16C99EFACA4DFADDDF35644AAC63F9B4AA2BD6','RELEASED','2020-06-11 16:24:56',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/master/2020_06_12_00_characters.sql b/sql/updates/characters/master/2020_06_12_00_characters.sql
new file mode 100644
index 00000000000..885111dc1f7
--- /dev/null
+++ b/sql/updates/characters/master/2020_06_12_00_characters.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `character_aura` ADD `difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `recalculateMask`;
+ALTER TABLE `pet_aura` ADD `difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `recalculateMask`;
diff --git a/src/common/Utilities/IteratorPair.h b/src/common/Utilities/IteratorPair.h
index 1e06f2ef920..319fadada09 100644
--- a/src/common/Utilities/IteratorPair.h
+++ b/src/common/Utilities/IteratorPair.h
@@ -44,6 +44,12 @@ namespace Trinity
namespace Containers
{
+ template<typename iterator>
+ constexpr Trinity::IteratorPair<iterator> MakeIteratorPair(std::pair<iterator, iterator> iterators)
+ {
+ return iterators;
+ }
+
template<class M>
inline auto MapEqualRange(M& map, typename M::key_type const& key) -> IteratorPair<decltype(map.begin())>
{
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 24ae14580f9..c17fe356680 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -86,7 +86,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, extendState, resettime, entranceId FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_AURA_EFFECTS, "SELECT casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, timer FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC);
@@ -343,8 +343,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT, "DELETE FROM character_transmog_outfits WHERE setguid=?", CONNECTION_ASYNC);
// Auras
- PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_AURA_EFFECT, "INSERT INTO character_aura_effect (guid, casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
@@ -715,7 +715,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER, "DELETE FROM character_pet_declinedname WHERE owner = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME, "DELETE FROM character_pet_declinedname WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_PET_DECLINEDNAME, "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_PET_AURA, "SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_PET_AURA, "SELECT casterGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_AURA_EFFECT, "SELECT casterGuid, spell, effectMask, effectIndex, amount, baseAmount FROM pet_aura_effect WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_SPELL, "SELECT spell, active FROM pet_spell WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time, categoryId, categoryEnd FROM pet_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_SYNCH);
@@ -730,8 +730,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_PET_SPELL_CHARGES, "INSERT INTO pet_spell_charges (guid, categoryId, rechargeStart, rechargeEnd) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PET_SPELL_BY_SPELL, "DELETE FROM pet_spell WHERE guid = ? and spell = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_PET_SPELL, "INSERT INTO pet_spell (guid, spell, active) VALUES (?, ?, ?)", CONNECTION_BOTH);
- PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
+ PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, casterGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
PrepareStatement(CHAR_INS_PET_AURA_EFFECT, "INSERT INTO pet_aura_effect (guid, casterGuid, spell, effectMask, effectIndex, amount, baseAmount) "
"VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType, specialization FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp
index fd42e251915..2f2461b5ab0 100644
--- a/src/server/game/AI/CoreAI/CombatAI.cpp
+++ b/src/server/game/AI/CoreAI/CombatAI.cpp
@@ -20,6 +20,7 @@
#include "Creature.h"
#include "CreatureAIImpl.h"
#include "Log.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
@@ -55,7 +56,7 @@ void AggressorAI::UpdateAI(uint32 /*diff*/)
void CombatAI::InitializeAI()
{
for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i)
- if (me->m_spells[i] && sSpellMgr->GetSpellInfo(me->m_spells[i]))
+ if (me->m_spells[i] && sSpellMgr->GetSpellInfo(me->m_spells[i], me->GetMap()->GetDifficultyID()))
spells.push_back(me->m_spells[i]);
CreatureAI::InitializeAI();
@@ -69,18 +70,22 @@ void CombatAI::Reset()
void CombatAI::JustDied(Unit* killer)
{
for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
- if (AISpellInfo[*i].condition == AICOND_DIE)
- me->CastSpell(killer, *i, true);
+ if (AISpellInfoType const* info = GetAISpellInfo(*i, me->GetMap()->GetDifficultyID()))
+ if (info->condition == AICOND_DIE)
+ me->CastSpell(killer, *i, true);
}
void CombatAI::EnterCombat(Unit* who)
{
for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
{
- if (AISpellInfo[*i].condition == AICOND_AGGRO)
- me->CastSpell(who, *i, false);
- else if (AISpellInfo[*i].condition == AICOND_COMBAT)
- events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand32() % AISpellInfo[*i].cooldown);
+ if (AISpellInfoType const* info = GetAISpellInfo(*i, me->GetMap()->GetDifficultyID()))
+ {
+ if (info->condition == AICOND_AGGRO)
+ me->CastSpell(who, *i, false);
+ else if (info->condition == AICOND_COMBAT)
+ events.ScheduleEvent(*i, info->cooldown + rand32() % info->cooldown);
+ }
}
}
@@ -97,7 +102,8 @@ void CombatAI::UpdateAI(uint32 diff)
if (uint32 spellId = events.ExecuteEvent())
{
DoCast(spellId);
- events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand32() % AISpellInfo[spellId].cooldown);
+ if (AISpellInfoType const* info = GetAISpellInfo(spellId, me->GetMap()->GetDifficultyID()))
+ events.ScheduleEvent(spellId, info->cooldown + rand32() % info->cooldown);
}
else
DoMeleeAttackIfReady();
@@ -118,8 +124,10 @@ void CasterAI::InitializeAI()
m_attackDist = 30.0f;
for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr)
- if (AISpellInfo[*itr].condition == AICOND_COMBAT && m_attackDist > GetAISpellInfo(*itr)->maxRange)
- m_attackDist = GetAISpellInfo(*itr)->maxRange;
+ if (AISpellInfoType const* info = GetAISpellInfo(*itr, me->GetMap()->GetDifficultyID()))
+ if (info->condition == AICOND_COMBAT && m_attackDist > info->maxRange)
+ m_attackDist = info->maxRange;
+
if (m_attackDist == 30.0f)
m_attackDist = MELEE_RANGE;
}
@@ -133,17 +141,20 @@ void CasterAI::EnterCombat(Unit* who)
uint32 count = 0;
for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count)
{
- if (AISpellInfo[*itr].condition == AICOND_AGGRO)
- me->CastSpell(who, *itr, false);
- else if (AISpellInfo[*itr].condition == AICOND_COMBAT)
+ if (AISpellInfoType const* info = GetAISpellInfo(*itr, me->GetMap()->GetDifficultyID()))
{
- uint32 cooldown = GetAISpellInfo(*itr)->realCooldown;
- if (count == spell)
+ if (info->condition == AICOND_AGGRO)
+ me->CastSpell(who, *itr, false);
+ else if (info->condition == AICOND_COMBAT)
{
- DoCast(spells[spell]);
- cooldown += me->GetCurrentSpellCastTime(*itr);
+ uint32 cooldown = info->realCooldown;
+ if (count == spell)
+ {
+ DoCast(spells[spell]);
+ cooldown += me->GetCurrentSpellCastTime(*itr);
+ }
+ events.ScheduleEvent(*itr, cooldown);
}
- events.ScheduleEvent(*itr, cooldown);
}
}
}
@@ -168,7 +179,8 @@ void CasterAI::UpdateAI(uint32 diff)
{
DoCast(spellId);
uint32 casttime = me->GetCurrentSpellCastTime(spellId);
- events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown);
+ if (AISpellInfoType const* info = GetAISpellInfo(spellId, me->GetMap()->GetDifficultyID()))
+ events.ScheduleEvent(spellId, (casttime ? casttime : 500) + info->realCooldown);
}
}
@@ -181,7 +193,7 @@ ArcherAI::ArcherAI(Creature* c) : CreatureAI(c)
if (!me->m_spells[0])
TC_LOG_ERROR("misc", "ArcherAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry());
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0], me->GetMap()->GetDifficultyID());
m_minRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
if (!m_minRange)
@@ -230,7 +242,7 @@ TurretAI::TurretAI(Creature* c) : CreatureAI(c)
if (!me->m_spells[0])
TC_LOG_ERROR("misc", "TurretAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry());
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0], me->GetMap()->GetDifficultyID());
m_minRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
me->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
me->m_SightDistance = me->m_CombatDistance;
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index cc0969ab15d..a39e4a8dfc0 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -20,6 +20,7 @@
#include "Errors.h"
#include "Group.h"
#include "Log.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Pet.h"
@@ -146,7 +147,7 @@ void PetAI::UpdateAI(uint32 diff)
if (!spellID)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID, me->GetMap()->GetDifficultyID());
if (!spellInfo)
continue;
@@ -184,7 +185,7 @@ void PetAI::UpdateAI(uint32 diff)
}
}
- if (spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_JUMP_DEST))
+ if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST))
{
if (!spellUsed)
delete spell;
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index a2f0f8f664b..4d2bda5faa0 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -53,7 +53,7 @@ void TotemAI::UpdateAI(uint32 /*diff*/)
return;
// Search spell
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell());
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell(), me->GetMap()->GetDifficultyID());
if (!spellInfo)
return;
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 14b162ca4a6..8d1ed85a6e8 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -18,6 +18,7 @@
#include "UnitAI.h"
#include "Creature.h"
#include "CreatureAIImpl.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "Player.h"
#include "QuestDef.h"
@@ -90,7 +91,7 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spellId)
if (me->HasUnitState(UNIT_STATE_CASTING) || !me->isAttackReady())
return true;
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, me->GetMap()->GetDifficultyID()))
{
if (me->IsWithinCombatRange(me->GetVictim(), spellInfo->GetMaxRange(false)))
{
@@ -116,8 +117,11 @@ void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAg
void UnitAI::DoCast(uint32 spellId)
{
Unit* target = NULL;
+ AITarget aiTargetType = AITARGET_SELF;
+ if (AISpellInfoType const* info = GetAISpellInfo(spellId, me->GetMap()->GetDifficultyID()))
+ aiTargetType = info->target;
- switch (AISpellInfo[spellId].target)
+ switch (aiTargetType)
{
default:
case AITARGET_SELF:
@@ -128,7 +132,7 @@ void UnitAI::DoCast(uint32 spellId)
break;
case AITARGET_ENEMY:
{
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, me->GetMap()->GetDifficultyID()))
{
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
target = SelectTarget(SELECT_TARGET_RANDOM, 0, spellInfo->GetMaxRange(false), playerOnly);
@@ -143,7 +147,7 @@ void UnitAI::DoCast(uint32 spellId)
break;
case AITARGET_DEBUFF:
{
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, me->GetMap()->GetDifficultyID()))
{
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
float range = spellInfo->GetMaxRange(false);
@@ -190,16 +194,9 @@ void UnitAI::DoCastAOE(uint32 spellId, bool triggered)
void UnitAI::FillAISpellInfo()
{
- AISpellInfo = new AISpellInfoType[sSpellMgr->GetSpellInfoStoreSize()];
-
- AISpellInfoType* AIInfo = AISpellInfo;
- const SpellInfo* spellInfo;
-
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i, ++AIInfo)
+ sSpellMgr->ForEachSpellInfo([](SpellInfo const* spellInfo)
{
- spellInfo = sSpellMgr->GetSpellInfo(i);
- if (!spellInfo)
- continue;
+ AISpellInfoType* AIInfo = &AISpellInfo[{ spellInfo->Id, spellInfo->Difficulty }];
if (spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
AIInfo->condition = AICOND_DIE;
@@ -215,7 +212,7 @@ void UnitAI::FillAISpellInfo()
UPDATE_TARGET(AITARGET_SELF)
else
{
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -239,7 +236,80 @@ void UnitAI::FillAISpellInfo()
}
AIInfo->realCooldown = spellInfo->RecoveryTime + spellInfo->StartRecoveryTime;
AIInfo->maxRange = spellInfo->GetMaxRange(false) * 3 / 4;
- }
+
+ AIInfo->Effects = 0;
+ AIInfo->Targets = 0;
+
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
+ {
+ if (!effect)
+ continue;
+
+ // Spell targets self.
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_SELF - 1);
+
+ // Spell targets a single enemy.
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY - 1);
+
+ // Spell targets AoE at enemy.
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_SRC_CASTER ||
+ effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_AOE_ENEMY - 1);
+
+ // Spell targets an enemy.
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY ||
+ effect->TargetA.GetTarget() == TARGET_SRC_CASTER ||
+ effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_ANY_ENEMY - 1);
+
+ // Spell targets a single friend (or self).
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND - 1);
+
+ // Spell targets AoE friends.
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY ||
+ effect->TargetA.GetTarget() == TARGET_SRC_CASTER)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_AOE_FRIEND - 1);
+
+ // Spell targets any friend (or self).
+ if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY ||
+ effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY ||
+ effect->TargetA.GetTarget() == TARGET_SRC_CASTER)
+ AIInfo->Targets |= 1 << (SELECT_TARGET_ANY_FRIEND - 1);
+
+ // Make sure that this spell includes a damage effect.
+ if (effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE ||
+ effect->Effect == SPELL_EFFECT_INSTAKILL ||
+ effect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
+ effect->Effect == SPELL_EFFECT_HEALTH_LEECH)
+ AIInfo->Effects |= 1 << (SELECT_EFFECT_DAMAGE - 1);
+
+ // Make sure that this spell includes a healing effect (or an apply aura with a periodic heal).
+ if (effect->Effect == SPELL_EFFECT_HEAL ||
+ effect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH ||
+ effect->Effect == SPELL_EFFECT_HEAL_MECHANICAL ||
+ (effect->Effect == SPELL_EFFECT_APPLY_AURA && effect->ApplyAuraName == 8))
+ AIInfo->Effects |= 1 << (SELECT_EFFECT_HEALING - 1);
+
+ // Make sure that this spell applies an aura.
+ if (effect->Effect == SPELL_EFFECT_APPLY_AURA)
+ AIInfo->Effects |= 1 << (SELECT_EFFECT_AURA - 1);
+ }
+ });
}
uint32 UnitAI::GetDialogStatus(Player* /*player*/)
@@ -287,7 +357,7 @@ bool DefaultTargetSelector::operator()(Unit const* target) const
}
SpellTargetSelector::SpellTargetSelector(Unit* caster, uint32 spellId) :
- _caster(caster), _spellInfo(sSpellMgr->GetSpellInfo(spellId))
+ _caster(caster), _spellInfo(sSpellMgr->GetSpellInfo(spellId, caster->GetMap()->GetDifficultyID()))
{
ASSERT(_spellInfo);
}
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index ac5e9165715..508d9e70d70 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -22,6 +22,7 @@
#include "EventMap.h"
#include "ObjectGuid.h"
#include "ThreatManager.h"
+#include <unordered_map>
#define CAST_AI(a, b) (dynamic_cast<a*>(b))
#define ENSURE_AI(a,b) (EnsureAI<a>(b))
@@ -40,6 +41,7 @@ class SpellInfo;
class Unit;
struct AISpellInfoType;
enum DamageEffectType : uint8;
+enum Difficulty : uint8;
enum SpellEffIndex : uint8;
//Selection method used by SelectTarget
@@ -270,7 +272,7 @@ class TC_GAME_API UnitAI
void DoMeleeAttackIfReady();
bool DoSpellAttackIfReady(uint32 spellId);
- static AISpellInfoType* AISpellInfo;
+ static std::unordered_map<std::pair<uint32, Difficulty>, AISpellInfoType> AISpellInfo;
static void FillAISpellInfo();
// Called when a player opens a gossip dialog with the creature.
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index 3c65160aaf6..80d59e4e7cc 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -17,6 +17,7 @@
#include "CreatureAI.h"
#include "AreaBoundary.h"
+#include "Containers.h"
#include "Creature.h"
#include "CreatureAIImpl.h"
#include "CreatureTextMgr.h"
@@ -41,8 +42,11 @@ void CreatureAI::OnCharmed(bool apply)
}
}
-AISpellInfoType* UnitAI::AISpellInfo;
-AISpellInfoType* GetAISpellInfo(uint32 i) { return &UnitAI::AISpellInfo[i]; }
+std::unordered_map<std::pair<uint32, Difficulty>, AISpellInfoType> UnitAI::AISpellInfo;
+AISpellInfoType* GetAISpellInfo(uint32 spellId, Difficulty difficulty)
+{
+ return Trinity::Containers::MapGetValuePtr(UnitAI::AISpellInfo, { spellId, difficulty });
+}
CreatureAI::CreatureAI(Creature* creature) : UnitAI(creature), me(creature), _boundary(nullptr), _negateBoundary(false), m_MoveInLineOfSight_locked(false)
{
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index edc09a650c7..b274a4794d1 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -36,31 +36,6 @@ typedef std::vector<AreaBoundary const*> CreatureBoundary;
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
-//Spell targets used by SelectSpell
-enum SelectTargetType
-{
- SELECT_TARGET_DONTCARE = 0, //All target types allowed
-
- SELECT_TARGET_SELF, //Only Self casting
-
- SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy
- SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy
- SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy
-
- SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend
- SELECT_TARGET_AOE_FRIEND, //Only AoE Friend
- SELECT_TARGET_ANY_FRIEND //AoE or Single Friend
-};
-
-//Spell Effects used by SelectSpell
-enum SelectEffect
-{
- SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed
- SELECT_EFFECT_DAMAGE, //Spell does damage
- SELECT_EFFECT_HEALING, //Spell does healing
- SELECT_EFFECT_AURA //Spell applies an aura
-};
-
enum SCEquip
{
EQUIP_NO_CHANGE = -1,
diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h
index a14446bf457..cbc7c5912a0 100644
--- a/src/server/game/AI/CreatureAIImpl.h
+++ b/src/server/game/AI/CreatureAIImpl.h
@@ -22,6 +22,7 @@
#include <functional>
class WorldObject;
+enum Difficulty : uint8;
template<typename First, typename Second, typename... Rest>
inline First const& RAND(First const& first, Second const& second, Rest const&... rest)
@@ -49,6 +50,31 @@ enum AICondition
#define AI_DEFAULT_COOLDOWN 5000
+//Spell targets used by SelectSpell
+enum SelectTargetType : uint8
+{
+ SELECT_TARGET_DONTCARE = 0, //All target types allowed
+
+ SELECT_TARGET_SELF, //Only Self casting
+
+ SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy
+ SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy
+ SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy
+
+ SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend
+ SELECT_TARGET_AOE_FRIEND, //Only AoE Friend
+ SELECT_TARGET_ANY_FRIEND //AoE or Single Friend
+};
+
+//Spell Effects used by SelectSpell
+enum SelectEffect : uint8
+{
+ SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed
+ SELECT_EFFECT_DAMAGE, //Spell does damage
+ SELECT_EFFECT_HEALING, //Spell does healing
+ SELECT_EFFECT_AURA //Spell applies an aura
+};
+
struct AISpellInfoType
{
AISpellInfoType() : target(AITARGET_SELF), condition(AICOND_COMBAT)
@@ -58,9 +84,12 @@ struct AISpellInfoType
uint32 cooldown;
uint32 realCooldown;
float maxRange;
+
+ uint8 Targets; // set of enum SelectTarget
+ uint8 Effects; // set of enum SelectEffect
};
-AISpellInfoType* GetAISpellInfo(uint32 i);
+AISpellInfoType* GetAISpellInfo(uint32 spellId, Difficulty difficulty);
TC_GAME_API bool InstanceHasScript(WorldObject const* obj, char const* scriptName);
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index 7a7c7b8c0d0..6d5b7060099 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -18,6 +18,7 @@
#include "PlayerAI.h"
#include "Creature.h"
#include "Item.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
@@ -498,7 +499,7 @@ PlayerAI::TargetedSpell PlayerAI::VerifySpellCast(uint32 spellId, Unit* target)
if (!knownRank)
return {};
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(knownRank);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(knownRank, me->GetMap()->GetDifficultyID());
if (!spellInfo)
return {};
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index 59fdee4d181..71125e716a6 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -20,6 +20,7 @@
#include "DB2Stores.h"
#include "Cell.h"
#include "CellImpl.h"
+#include "CreatureAIImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "InstanceScript.h"
@@ -30,13 +31,6 @@
#include "SpellMgr.h"
#include "TemporarySummon.h"
-// Spell summary for ScriptedAI::SelectSpell
-struct TSpellSummary
-{
- uint8 Targets; // set of enum SelectTarget
- uint8 Effects; // set of enum SelectEffect
-} extern* SpellSummary;
-
void SummonList::Summon(Creature const* summon)
{
storage_.push_back(summon->GetGUID());
@@ -231,23 +225,25 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
uint32 spellCount = 0;
SpellInfo const* tempSpell = nullptr;
+ AISpellInfoType const* aiSpell = nullptr;
//Check if each spell is viable(set it to null if not)
for (uint32 i = 0; i < MAX_CREATURE_SPELLS; i++)
{
- tempSpell = sSpellMgr->GetSpellInfo(me->m_spells[i]);
+ tempSpell = sSpellMgr->GetSpellInfo(me->m_spells[i], me->GetMap()->GetDifficultyID());
+ aiSpell = GetAISpellInfo(me->m_spells[i], me->GetMap()->GetDifficultyID());
//This spell doesn't exist
- if (!tempSpell)
+ if (!tempSpell || !aiSpell)
continue;
// Targets and Effects checked first as most used restrictions
//Check the spell targets if specified
- if (targets && !(SpellSummary[me->m_spells[i]].Targets & (1 << (targets-1))))
+ if (targets && !(aiSpell->Targets & (1 << (targets-1))))
continue;
//Check the type of spell if we are looking for a specific spell type
- if (effect && !(SpellSummary[me->m_spells[i]].Effects & (1 << (effect-1))))
+ if (effect && !(aiSpell->Effects & (1 << (effect-1))))
continue;
//Check for school if specified
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index 53fb97be2aa..bb61dfbaab0 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -24,6 +24,8 @@
#include "TaskScheduler.h"
class InstanceScript;
+enum SelectTargetType : uint8;
+enum SelectEffect : uint8;
class TC_GAME_API SummonList
{
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 04af075e9af..ebf884133a4 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -656,7 +656,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
// unless target is outside spell range, out of mana, or LOS.
bool _allowMove = false;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell, me->GetMap()->GetDifficultyID());
std::vector<SpellPowerCost> costs = spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask());
bool hasPower = true;
for (SpellPowerCost const& cost : costs)
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 37e40a133bf..7e660acf4a7 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -566,7 +566,7 @@ bool SmartAIMgr::IsGameObjectValid(SmartScriptHolder const& e, uint32 entry)
bool SmartAIMgr::IsSpellValid(SmartScriptHolder const& e, uint32 entry)
{
- if (!sSpellMgr->GetSpellInfo(entry))
+ if (!sSpellMgr->GetSpellInfo(entry, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
return false;
@@ -717,7 +717,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_SPELLHIT_TARGET:
if (e.event.spellHit.spell)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.event.spellHit.spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.event.spellHit.spell, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
@@ -780,7 +780,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
break;
case SMART_EVENT_VICTIM_CASTING:
- if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId))
+ if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
return false;
@@ -1131,8 +1131,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsSpellValid(e, e.action.cast.spell))
return false;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell);
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell, DIFFICULTY_NONE);
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (effect && (effect->IsEffect(SPELL_EFFECT_KILL_CREDIT) || effect->IsEffect(SPELL_EFFECT_KILL_CREDIT2)))
{
@@ -1650,31 +1650,23 @@ void SmartAIMgr::LoadHelperStores()
{
uint32 oldMSTime = getMSTime();
- SpellInfo const* spellInfo = NULL;
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
+ sSpellMgr->ForEachSpellInfo([this](SpellInfo const* spellInfo)
{
- spellInfo = sSpellMgr->GetSpellInfo(i);
- if (!spellInfo)
- continue;
-
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect)
continue;
if (effect->IsEffect(SPELL_EFFECT_SUMMON))
- SummonCreatureSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(i, SpellEffIndex(effect->EffectIndex))));
-
+ SummonCreatureSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex))));
else if (effect->IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD))
- SummonGameObjectSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(i, SpellEffIndex(effect->EffectIndex))));
-
+ SummonGameObjectSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex))));
else if (effect->IsEffect(SPELL_EFFECT_KILL_CREDIT) || effect->IsEffect(SPELL_EFFECT_KILL_CREDIT2))
- KillCreditSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(i, SpellEffIndex(effect->EffectIndex))));
-
+ KillCreditSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex))));
else if (effect->IsEffect(SPELL_EFFECT_CREATE_ITEM))
- CreateItemSpellStore.insert(std::make_pair(uint32(effect->ItemType), std::make_pair(i, SpellEffIndex(effect->EffectIndex))));
+ CreateItemSpellStore.insert(std::make_pair(uint32(effect->ItemType), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex))));
}
- }
+ });
TC_LOG_INFO("server.loading", ">> Loaded SmartAIMgr Helpers in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 63e681f2273..ca8a7627527 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -137,14 +137,14 @@ bool CriteriaData::IsValid(Criteria const* criteria)
case CRITERIA_DATA_TYPE_S_AURA:
case CRITERIA_DATA_TYPE_T_AURA:
{
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(Aura.SpellId);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(Aura.SpellId, DIFFICULTY_NONE);
if (!spellEntry)
{
TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell id in value1 (%u), ignored.",
criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId);
return false;
}
- SpellEffectInfo const* effect = spellEntry->GetEffect(DIFFICULTY_NONE, Aura.EffectIndex);
+ SpellEffectInfo const* effect = spellEntry->GetEffect(Aura.EffectIndex);
if (!effect)
{
TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell effect index in value2 (%u), ignored.",
diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp
index ba2e635c08b..d9f28c0b987 100644
--- a/src/server/game/Chat/ChatLink.cpp
+++ b/src/server/game/Chat/ChatLink.cpp
@@ -461,7 +461,7 @@ bool SpellChatLink::Initialize(std::istringstream& iss)
return false;
}
// Validate spell
- _spell = sSpellMgr->GetSpellInfo(spellId);
+ _spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!_spell)
{
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |spell command", iss.str().c_str(), spellId);
@@ -594,7 +594,7 @@ bool TradeChatLink::Initialize(std::istringstream& iss)
return false;
}
// Validate spell
- _spell = sSpellMgr->GetSpellInfo(spellId);
+ _spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!_spell)
{
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |trade command", iss.str().c_str(), spellId);
@@ -652,7 +652,7 @@ bool TalentChatLink::Initialize(std::istringstream& iss)
return false;
}
// Validate talent's spell
- _spell = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
+ _spell = sSpellMgr->GetSpellInfo(talentInfo->SpellID, DIFFICULTY_NONE);
if (!_spell)
{
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |trade command", iss.str().c_str(), talentInfo->SpellID);
@@ -684,7 +684,7 @@ bool EnchantmentChatLink::Initialize(std::istringstream& iss)
return false;
}
// Validate spell
- _spell = sSpellMgr->GetSpellInfo(spellId);
+ _spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!_spell)
{
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |enchant command", iss.str().c_str(), spellId);
@@ -723,7 +723,7 @@ bool GlyphChatLink::Initialize(std::istringstream& iss)
return false;
}
// Validate glyph's spell
- _spell = sSpellMgr->GetSpellInfo(_glyph->SpellID);
+ _spell = sSpellMgr->GetSpellInfo(_glyph->SpellID, DIFFICULTY_NONE);
if (!_spell)
{
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |glyph command", iss.str().c_str(), _glyph->SpellID);
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 76503bc6084..f7240308aef 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -40,7 +40,7 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float
threat *= threatEntry->pctMod;
// Energize is not affected by Mods
- for (SpellEffectInfo const* effect : threatSpell->GetEffectsForDifficulty(hatedUnit->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : threatSpell->GetEffects())
if (effect && (effect->Effect == SPELL_EFFECT_ENERGIZE || effect->ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE))
return threat;
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index f47af683485..cbc704b38fa 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1357,105 +1357,110 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond) const
bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const
{
- uint32 conditionEffMask = cond->SourceGroup;
- SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->AssertSpellInfo(cond->SourceEntry));
- std::list<uint32> sharedMasks;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ bool valid = false;
+ sSpellMgr->ForEachSpellInfoDifficulty(cond->SourceEntry, [&](SpellInfo const* spellInfo)
{
- SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, i);
- if (!effect)
- continue;
-
- // check if effect is already a part of some shared mask
- bool found = false;
- for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ uint32 conditionEffMask = cond->SourceGroup;
+ std::list<uint32> sharedMasks;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if ((1 << i) & *itr)
+ SpellEffectInfo const* effect = spellInfo->GetEffect(i);
+ if (!effect)
+ continue;
+
+ // check if effect is already a part of some shared mask
+ bool found = false;
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
{
- found = true;
- break;
+ if ((1 << i) & *itr)
+ {
+ found = true;
+ break;
+ }
}
- }
-
- if (found)
- continue;
- // build new shared mask with found effect
- uint32 sharedMask = 1 << i;
- ConditionContainer* cmp = effect->ImplicitTargetConditions;
- for (uint8 effIndex = i + 1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
- {
- SpellEffectInfo const* inner = spellInfo->GetEffect(DIFFICULTY_NONE, effIndex);
- if (!inner)
+ if (found)
continue;
- if (inner->ImplicitTargetConditions == cmp)
- sharedMask |= 1 << effIndex;
- }
+ // build new shared mask with found effect
+ uint32 sharedMask = 1 << i;
+ ConditionContainer* cmp = effect->ImplicitTargetConditions;
+ for (uint8 effIndex = i + 1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ SpellEffectInfo const* inner = spellInfo->GetEffect(effIndex);
+ if (!inner)
+ continue;
- sharedMasks.push_back(sharedMask);
- }
+ if (inner->ImplicitTargetConditions == cmp)
+ sharedMask |= 1 << effIndex;
+ }
- for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
- {
- // some effect indexes should have same data
- if (uint32 commonMask = *itr & conditionEffMask)
+ sharedMasks.push_back(sharedMask);
+ }
+
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
{
- uint8 firstEffIndex = 0;
- for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex)
- if ((1<<firstEffIndex) & *itr)
- break;
+ // some effect indexes should have same data
+ if (uint32 commonMask = *itr & conditionEffMask)
+ {
+ uint8 firstEffIndex = 0;
+ for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex)
+ if ((1 << firstEffIndex) & *itr)
+ break;
- if (firstEffIndex >= MAX_SPELL_EFFECTS)
- return false;
+ if (firstEffIndex >= MAX_SPELL_EFFECTS)
+ return;
- SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, firstEffIndex);
- if (!effect)
- continue;
+ SpellEffectInfo const* effect = spellInfo->GetEffect(firstEffIndex);
+ if (!effect)
+ continue;
- // get shared data
- ConditionContainer* sharedList = effect->ImplicitTargetConditions;
+ // get shared data
+ ConditionContainer* sharedList = effect->ImplicitTargetConditions;
- // there's already data entry for that sharedMask
- if (sharedList)
- {
- // we have overlapping masks in db
- if (conditionEffMask != *itr)
+ // there's already data entry for that sharedMask
+ if (sharedList)
{
- TC_LOG_ERROR("sql.sql", "%s in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - "
- "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->ToString().c_str(), cond->SourceGroup);
- return false;
+ // we have overlapping masks in db
+ if (conditionEffMask != *itr)
+ {
+ TC_LOG_ERROR("sql.sql", "%s in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - "
+ "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring (Difficulty %u).",
+ cond->ToString().c_str(), cond->SourceGroup, uint32(spellInfo->Difficulty));
+ return;
+ }
}
- }
- // no data for shared mask, we can create new submask
- else
- {
- // add new list, create new shared mask
- sharedList = new ConditionContainer();
- bool assigned = false;
- for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i)
+ // no data for shared mask, we can create new submask
+ else
{
- SpellEffectInfo const* eff = spellInfo->GetEffect(DIFFICULTY_NONE, i);
- if (!eff)
- continue;
-
- if ((1 << i) & commonMask)
+ // add new list, create new shared mask
+ sharedList = new ConditionContainer();
+ bool assigned = false;
+ for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i)
{
- const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = sharedList;
- assigned = true;
+ SpellEffectInfo const* eff = spellInfo->GetEffect(i);
+ if (!eff)
+ continue;
+
+ if ((1 << i) & commonMask)
+ {
+ const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = sharedList;
+ assigned = true;
+ }
}
- }
- if (!assigned)
- {
- delete sharedList;
- break;
+ if (!assigned)
+ {
+ delete sharedList;
+ break;
+ }
}
+ sharedList->push_back(cond);
+ break;
}
- sharedList->push_back(cond);
- break;
}
- }
+ valid = true;
+ });
return true;
}
@@ -1711,7 +1716,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
}
case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str());
@@ -1731,7 +1736,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
if (!((1 << i) & cond->SourceGroup))
continue;
- SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, i);
+ SpellEffectInfo const* effect = spellInfo->GetEffect(i);
if (!effect)
continue;
@@ -1780,7 +1785,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
case CONDITION_SOURCE_TYPE_SPELL:
case CONDITION_SOURCE_TYPE_SPELL_PROC:
{
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry);
+ SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE);
if (!spellProto)
{
TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str());
@@ -1802,7 +1807,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
return false;
}
- if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
+ if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str());
return false;
@@ -1815,7 +1820,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const
return false;
}
- if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
+ if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str());
return false;
@@ -1879,7 +1884,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
{
case CONDITION_AURA:
{
- if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
+ if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "%s has non existing spell (Id: %d), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1);
return false;
@@ -2048,7 +2053,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
}
case CONDITION_SPELL:
{
- if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
+ if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "%s has non existing spell (Id: %d), skipped", cond->ToString(true).c_str(), cond->ConditionValue1);
return false;
diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp
index 20c7f95a016..8b21de0197d 100644
--- a/src/server/game/Conditions/DisableMgr.cpp
+++ b/src/server/game/Conditions/DisableMgr.cpp
@@ -94,7 +94,7 @@ void LoadDisables()
switch (type)
{
case DISABLE_TYPE_SPELL:
- if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL))
+ if (!(sSpellMgr->GetSpellInfo(entry, DIFFICULTY_NONE) || flags & SPELL_DISABLE_DEPRECATED_SPELL))
{
TC_LOG_ERROR("sql.sql", "Spell entry %u from `disables` doesn't exist in dbc, skipped.", entry);
continue;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 54231bead60..aa758b408dd 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -421,8 +421,6 @@ namespace
SpecializationSpellsContainer _specializationSpellsBySpec;
std::unordered_set<std::pair<int32, uint32>> _specsBySpecSet;
std::unordered_set<uint8> _spellFamilyNames;
- SpellPowerContainer _spellPowers;
- SpellPowerDifficultyContainer _spellPowerDifficulties;
SpellProcsPerMinuteModContainer _spellProcsPerMinuteMods;
TalentsByPosition _talentsByPosition;
ToyItemIdsContainer _toys;
@@ -1139,26 +1137,6 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
for (SpellClassOptionsEntry const* classOption : sSpellClassOptionsStore)
_spellFamilyNames.insert(classOption->SpellClassSet);
- for (SpellPowerEntry const* power : sSpellPowerStore)
- {
- if (SpellPowerDifficultyEntry const* powerDifficulty = sSpellPowerDifficultyStore.LookupEntry(power->ID))
- {
- std::vector<SpellPowerEntry const*>& powers = _spellPowerDifficulties[power->SpellID][powerDifficulty->DifficultyID];
- if (powers.size() <= powerDifficulty->OrderIndex)
- powers.resize(powerDifficulty->OrderIndex + 1);
-
- powers[powerDifficulty->OrderIndex] = power;
- }
- else
- {
- std::vector<SpellPowerEntry const*>& powers = _spellPowers[power->SpellID];
- if (powers.size() <= power->OrderIndex)
- powers.resize(power->OrderIndex + 1);
-
- powers[power->OrderIndex] = power;
- }
- }
-
for (SpellProcsPerMinuteModEntry const* ppmMod : sSpellProcsPerMinuteModStore)
_spellProcsPerMinuteMods[ppmMod->SpellProcsPerMinuteID].push_back(ppmMod);
@@ -2626,48 +2604,6 @@ bool DB2Manager::IsValidSpellFamiliyName(SpellFamilyNames family)
return _spellFamilyNames.count(family) > 0;
}
-std::vector<SpellPowerEntry const*> DB2Manager::GetSpellPowers(uint32 spellId, Difficulty difficulty /*= DIFFICULTY_NONE*/, bool* hasDifficultyPowers /*= nullptr*/) const
-{
- std::vector<SpellPowerEntry const*> powers;
-
- auto difficultyItr = _spellPowerDifficulties.find(spellId);
- if (difficultyItr != _spellPowerDifficulties.end())
- {
- if (hasDifficultyPowers)
- *hasDifficultyPowers = true;
-
- DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
- while (difficultyEntry)
- {
- auto powerDifficultyItr = difficultyItr->second.find(difficultyEntry->ID);
- if (powerDifficultyItr != difficultyItr->second.end())
- {
- if (powerDifficultyItr->second.size() > powers.size())
- powers.resize(powerDifficultyItr->second.size());
-
- for (SpellPowerEntry const* difficultyPower : powerDifficultyItr->second)
- if (!powers[difficultyPower->OrderIndex])
- powers[difficultyPower->OrderIndex] = difficultyPower;
- }
-
- difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
- }
- }
-
- auto itr = _spellPowers.find(spellId);
- if (itr != _spellPowers.end())
- {
- if (itr->second.size() > powers.size())
- powers.resize(itr->second.size());
-
- for (SpellPowerEntry const* power : itr->second)
- if (!powers[power->OrderIndex])
- powers[power->OrderIndex] = power;
- }
-
- return powers;
-}
-
std::vector<SpellProcsPerMinuteModEntry const*> DB2Manager::GetSpellProcsPerMinuteMods(uint32 spellprocsPerMinuteId) const
{
auto itr = _spellProcsPerMinuteMods.find(spellprocsPerMinuteId);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index cc508a8883f..843b1b0479f 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -190,6 +190,7 @@ TC_GAME_API extern DB2Storage<SpellLevelsEntry> sSpellLevels
TC_GAME_API extern DB2Storage<SpellMiscEntry> sSpellMiscStore;
TC_GAME_API extern DB2Storage<SpellNameEntry> sSpellNameStore;
TC_GAME_API extern DB2Storage<SpellPowerEntry> sSpellPowerStore;
+TC_GAME_API extern DB2Storage<SpellPowerDifficultyEntry> sSpellPowerDifficultyStore;
TC_GAME_API extern DB2Storage<SpellProcsPerMinuteEntry> sSpellProcsPerMinuteStore;
TC_GAME_API extern DB2Storage<SpellRadiusEntry> sSpellRadiusStore;
TC_GAME_API extern DB2Storage<SpellRangeEntry> sSpellRangeStore;
@@ -358,7 +359,6 @@ public:
std::vector<SpecializationSpellsEntry const*> const* GetSpecializationSpells(uint32 specId) const;
bool IsSpecSetMember(int32 specSetId, uint32 specId) const;
static bool IsValidSpellFamiliyName(SpellFamilyNames family);
- std::vector<SpellPowerEntry const*> GetSpellPowers(uint32 spellId, Difficulty difficulty = DIFFICULTY_NONE, bool* hasDifficultyPowers = nullptr) const;
std::vector<SpellProcsPerMinuteModEntry const*> GetSpellProcsPerMinuteMods(uint32 spellprocsPerMinuteId) const;
std::vector<TalentEntry const*> const& GetTalentsByPosition(uint32 class_, uint32 tier, uint32 column) const;
static bool IsTotemCategoryCompatibleWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 92dcaa236bc..dac3557f501 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -1263,6 +1263,8 @@ enum SpellProcsPerMinuteModType
SPELL_PPM_MOD_BATTLEGROUND = 7
};
+constexpr std::size_t MAX_POWERS_PER_SPELL = 4;
+
enum SpellShapeshiftFormFlags
{
SHAPESHIFT_FORM_IS_NOT_A_SHAPESHIFT = 0x0001,
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
index c5621e86986..b1c386d2e51 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -552,11 +552,11 @@ bool UnitFitToActionRequirement(Unit* unit, Unit* caster, AreaTriggerAction cons
{
case AREATRIGGER_ACTION_USER_FRIEND:
{
- return caster->_IsValidAssistTarget(unit, sSpellMgr->GetSpellInfo(action.Param));
+ return caster->_IsValidAssistTarget(unit, sSpellMgr->GetSpellInfo(action.Param, caster->GetMap()->GetDifficultyID()));
}
case AREATRIGGER_ACTION_USER_ENEMY:
{
- return caster->_IsValidAttackTarget(unit, sSpellMgr->GetSpellInfo(action.Param));
+ return caster->_IsValidAttackTarget(unit, sSpellMgr->GetSpellInfo(action.Param, caster->GetMap()->GetDifficultyID()));
}
case AREATRIGGER_ACTION_USER_RAID:
{
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 1f124d16ed1..2d66f88a745 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2109,7 +2109,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const
return false;
bool immunedToAllEffects = true;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect || !effect->IsEffect())
continue;
@@ -2129,7 +2129,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit* caster) const
{
- SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), index);
+ SpellEffectInfo const* effect = spellInfo->GetEffect(index);
if (!effect)
return true;
@@ -2165,7 +2165,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim)
{
if (!m_spells[i])
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spells[i]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spells[i], GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "WORLD: unknown spell id %i", m_spells[i]);
@@ -2173,7 +2173,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim)
}
bool bcontinue = true;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (effect && ((effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) ||
(effect->Effect == SPELL_EFFECT_INSTAKILL) ||
@@ -2217,7 +2217,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim)
{
if (!m_spells[i])
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spells[i]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spells[i], GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "WORLD: unknown spell id %i", m_spells[i]);
@@ -2225,7 +2225,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim)
}
bool bcontinue = true;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (effect && (effect->Effect == SPELL_EFFECT_HEAL))
{
@@ -2567,7 +2567,7 @@ bool Creature::LoadCreaturesAddon()
{
for (std::vector<uint32>::const_iterator itr = cainfo->auras.begin(); itr != cainfo->auras.end(); ++itr)
{
- SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(*itr);
+ SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(*itr, GetMap()->GetDifficultyID());
if (!AdditionalSpellInfo)
{
TC_LOG_ERROR("sql.sql", "Creature (%s) has wrong spell %u defined in `auras` field.", GetGUID().ToString().c_str(), *itr);
@@ -2931,7 +2931,7 @@ float Creature::GetPetChaseDistance() const
if (!spellID)
continue;
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID, GetMap()->GetDifficultyID()))
{
if (spellInfo->GetRecoveryTime() == 0 && // No cooldown
spellInfo->RangeEntry->ID != 1 /*Self*/ && spellInfo->RangeEntry->ID != 2 /*Combat Range*/ &&
@@ -3100,7 +3100,7 @@ void Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
SpellInfo const* spellInfo = focusSpell->GetSpellInfo();
// don't use spell focus for vehicle spells
- if (spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE))
+ if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
return;
if ((!target || target == this) && !focusSpell->GetCastTime()) // instant cast, untargeted (or self-targeted) spell doesn't need any facing updates
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 76be982fdb2..8dc0ea6e352 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -450,19 +450,10 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
packet.SuggestedPartyMembers = quest->GetSuggestedPlayers();
// RewardSpell can teach multiple spells in trigger spell effects. But not all effects must be SPELL_EFFECT_LEARN_SPELL. See example spell 33950
- if (quest->GetRewSpell())
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
- if (spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL))
- {
- SpellEffectInfoVector effects = spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE);
- for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr)
- {
- if ((*itr)->IsEffect(SPELL_EFFECT_LEARN_SPELL))
- packet.LearnSpells.push_back((*itr)->TriggerSpell);
- }
- }
- }
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell(), DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
+ if (effect->IsEffect(SPELL_EFFECT_LEARN_SPELL))
+ packet.LearnSpells.push_back(effect->TriggerSpell);
quest->BuildQuestRewards(packet.Rewards, _session->GetPlayer());
diff --git a/src/server/game/Entities/Creature/Trainer.cpp b/src/server/game/Entities/Creature/Trainer.cpp
index db1c0a528b6..bfdf21a06bd 100644
--- a/src/server/game/Entities/Creature/Trainer.cpp
+++ b/src/server/game/Entities/Creature/Trainer.cpp
@@ -26,7 +26,7 @@ namespace Trainer
{
bool Spell::IsCastable() const
{
- return sSpellMgr->AssertSpellInfo(SpellId)->HasEffect(SPELL_EFFECT_LEARN_SPELL);
+ return sSpellMgr->AssertSpellInfo(SpellId, DIFFICULTY_NONE)->HasEffect(SPELL_EFFECT_LEARN_SPELL);
}
Trainer::Trainer(uint32 id, Type type, std::string greeting, std::vector<Spell> spells) : _id(id), _type(type), _spells(std::move(spells))
@@ -111,7 +111,7 @@ namespace Trainer
if (state != SpellState::Available)
return false;
- SpellInfo const* trainerSpellInfo = sSpellMgr->AssertSpellInfo(trainerSpell->SpellId);
+ SpellInfo const* trainerSpellInfo = sSpellMgr->AssertSpellInfo(trainerSpell->SpellId, DIFFICULTY_NONE);
if (trainerSpellInfo->IsPrimaryProfessionFirstRank() && !player->GetFreePrimaryProfessionPoints())
return false;
@@ -142,7 +142,7 @@ namespace Trainer
// check ranks
bool hasLearnSpellEffect = false;
bool knowsAllLearnedSpells = true;
- for (SpellEffectInfo const* spellEffect : sSpellMgr->AssertSpellInfo(trainerSpell->SpellId)->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* spellEffect : sSpellMgr->AssertSpellInfo(trainerSpell->SpellId, DIFFICULTY_NONE)->GetEffects())
{
if (!spellEffect || !spellEffect->IsEffect(SPELL_EFFECT_LEARN_SPELL))
continue;
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index 58e277f61f8..6d74efec87d 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -243,7 +243,7 @@ void DynamicObject::UnbindFromCaster()
SpellInfo const* DynamicObject::GetSpellInfo() const
{
- return sSpellMgr->GetSpellInfo(GetSpellId());
+ return sSpellMgr->GetSpellInfo(GetSpellId(), GetMap()->GetDifficultyID());
}
void DynamicObject::BuildValuesCreate(ByteBuffer* data, Player const* target) const
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 8cb05644006..4059e6e72d6 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1331,7 +1331,7 @@ void GameObject::TriggeringLinkedGameObject(uint32 trapEntry, Unit* target)
if (!trapInfo || trapInfo->type != GAMEOBJECT_TYPE_TRAP)
return;
- SpellInfo const* trapSpell = sSpellMgr->GetSpellInfo(trapInfo->trap.spell);
+ SpellInfo const* trapSpell = sSpellMgr->GetSpellInfo(trapInfo->trap.spell, GetMap()->GetDifficultyID());
if (!trapSpell) // checked at load already
return;
@@ -2053,7 +2053,7 @@ void GameObject::Use(Unit* user)
if (!spellId)
return;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
{
if (user->GetTypeId() != TYPEID_PLAYER || !sOutdoorPvPMgr->HandleCustomSpell(user->ToPlayer(), spellId, this))
@@ -2079,12 +2079,12 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /* = tru
void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags triggered)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
return;
bool self = false;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)
{
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index abe8914e48a..41fcbf6b32e 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -119,7 +119,7 @@ void AddItemsSetItem(Player* player, Item* item)
if (eff->SetBonuses.count(itemSetSpell))
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id %u in items set %u effects", itemSetSpell->SpellID, setid);
@@ -174,7 +174,7 @@ void RemoveItemsSetItem(Player* player, ItemTemplate const* proto)
if (!eff->SetBonuses.count(itemSetSpell))
continue;
- player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID), nullptr, false);
+ player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE), nullptr, false);
eff->SetBonuses.erase(itemSetSpell);
}
}
diff --git a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
index 1901e5e623d..834321320ef 100644
--- a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
+++ b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
@@ -115,8 +115,8 @@ public:
CreatureTemplate const* cinfo = unit->ToCreature()->GetCreatureTemplate();
// this also applies for transform auras
- if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(unit->getTransForm()))
- for (SpellEffectInfo const* effect : transform->GetEffectsForDifficulty(unit->GetMap()->GetDifficultyID()))
+ if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(unit->getTransForm(), unit->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : transform->GetEffects())
if (effect && effect->IsAura(SPELL_AURA_TRANSFORM))
if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(effect->MiscValue))
{
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index f6f62c98247..bb6d87b2072 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -157,7 +157,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
return false;
uint32 summonSpellId = fields[14].GetUInt32();
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summonSpellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summonSpellId, owner->GetMap()->GetDifficultyID());
bool isTemporarySummon = spellInfo && spellInfo->GetDuration() > 0;
if (current && isTemporarySummon)
@@ -1167,8 +1167,8 @@ void Pet::_LoadAuras(uint32 timediff)
stmt->setUInt32(0, m_charmInfo->GetPetNumber());
/*
- 0 1 2 3 4 5 6 7
- SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?
+ 0 1 2 3 4 5 6 7 8
+ SELECT casterGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?
*/
if (PreparedQueryResult auraResult = CharacterDatabase.Query(stmt))
{
@@ -1182,15 +1182,22 @@ void Pet::_LoadAuras(uint32 timediff)
AuraKey key{ casterGuid, itemGuid, fields[1].GetUInt32(), fields[2].GetUInt32() };
uint32 recalculateMask = fields[3].GetUInt32();
- uint8 stackCount = fields[4].GetUInt8();
- int32 maxDuration = fields[5].GetInt32();
- int32 remainTime = fields[6].GetInt32();
- uint8 remainCharges = fields[7].GetUInt8();
+ Difficulty difficulty = Difficulty(fields[4].GetUInt8());
+ uint8 stackCount = fields[5].GetUInt8();
+ int32 maxDuration = fields[6].GetInt32();
+ int32 remainTime = fields[7].GetInt32();
+ uint8 remainCharges = fields[8].GetUInt8();
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId, difficulty);
if (!spellInfo)
{
- TC_LOG_ERROR("entities.pet", "Unknown aura (spellid %u), ignore.", key.SpellId);
+ TC_LOG_ERROR("entities.pet", "Pet::_LoadAuras: Unknown aura (spellid %u), ignore.", key.SpellId);
+ continue;
+ }
+
+ if (difficulty != DIFFICULTY_NONE && !sDifficultyStore.LookupEntry(difficulty))
+ {
+ TC_LOG_ERROR("entities.pet", "Pet::_LoadAuras: Unknown difficulty %u (spellid %u), ignore.", uint32(difficulty), key.SpellId);
continue;
}
@@ -1216,7 +1223,7 @@ void Pet::_LoadAuras(uint32 timediff)
AuraLoadEffectInfo& info = effectInfo[key];
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
- if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, NULL, info.BaseAmounts.data(), NULL, casterGuid))
+ if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, NULL, difficulty, info.BaseAmounts.data(), NULL, casterGuid))
{
if (!aura->CanBeSaved())
{
@@ -1265,6 +1272,7 @@ void Pet::_SaveAuras(CharacterDatabaseTransaction& trans)
stmt->setUInt32(index++, key.SpellId);
stmt->setUInt32(index++, key.EffectMask);
stmt->setUInt32(index++, recalculateMask);
+ stmt->setUInt8(index++, aura->GetCastDifficulty());
stmt->setUInt8(index++, aura->GetStackAmount());
stmt->setInt32(index++, aura->GetMaxDuration());
stmt->setInt32(index++, aura->GetDuration());
@@ -1292,7 +1300,7 @@ void Pet::_SaveAuras(CharacterDatabaseTransaction& trans)
bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
// do pet spell book cleanup
@@ -1358,7 +1366,7 @@ bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpel
if (itr2->second.state == PETSPELL_REMOVED)
continue;
- SpellInfo const* oldRankSpellInfo = sSpellMgr->GetSpellInfo(itr2->first);
+ SpellInfo const* oldRankSpellInfo = sSpellMgr->GetSpellInfo(itr2->first, DIFFICULTY_NONE);
if (!oldRankSpellInfo)
continue;
@@ -1451,7 +1459,7 @@ void Pet::InitLevelupSpellsForLevel()
{
for (uint8 i = 0; i < MAX_CREATURE_SPELL_DATA_SLOT; ++i)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(defSpells->spellid[i]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(defSpells->spellid[i], DIFFICULTY_NONE);
if (!spellInfo)
continue;
@@ -1540,7 +1548,7 @@ void Pet::CleanupActionBar()
m_charmInfo->SetActionBar(i, 0, ACT_PASSIVE);
else if (ab->GetType() == ACT_ENABLED)
{
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ab->GetAction()))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ab->GetAction(), DIFFICULTY_NONE))
ToggleAutocast(spellInfo, true);
}
}
@@ -1782,7 +1790,7 @@ void Pet::LearnSpecializationSpells()
for (size_t j = 0; j < specSpells->size(); ++j)
{
SpecializationSpellsEntry const* specSpell = specSpells->at(j);
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID, DIFFICULTY_NONE);
if (!spellInfo || spellInfo->SpellLevel > getLevel())
continue;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 597628b6f4c..5ac0bbb1bc8 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1778,7 +1778,7 @@ void Player::SetObjectScale(float scale)
bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit* caster) const
{
- SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), index);
+ SpellEffectInfo const* effect = spellInfo->GetEffect(index);
if (!effect || !effect->IsEffect())
return false;
@@ -2800,7 +2800,7 @@ void DeleteSpellFromAllPlayers(uint32 spellId)
bool Player::AddTalent(TalentEntry const* talent, uint8 spec, bool learning)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: %u) does not exist.", talent->SpellID);
@@ -2827,14 +2827,14 @@ bool Player::AddTalent(TalentEntry const* talent, uint8 spec, bool learning)
void Player::RemoveTalent(TalentEntry const* talent)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
return;
RemoveSpell(talent->SpellID, true);
// search for spells that the talent teaches and unlearn them
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL)
RemoveSpell(effect->TriggerSpell, true);
@@ -2849,7 +2849,7 @@ void Player::RemoveTalent(TalentEntry const* talent)
bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, int32 fromSkill /*= 0*/)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
// do character spell book cleanup (all characters)
@@ -3015,7 +3015,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
if (itr2->second->state == PLAYERSPELL_REMOVED)
continue;
- SpellInfo const* i_spellInfo = sSpellMgr->GetSpellInfo(itr2->first);
+ SpellInfo const* i_spellInfo = sSpellMgr->GetSpellInfo(itr2->first, DIFFICULTY_NONE);
if (!i_spellInfo)
continue;
@@ -3212,7 +3212,7 @@ bool Player::HandlePassiveSpellLearn(SpellInfo const* spellInfo)
// passive spells which apply aura and have an item requirement are to be added manually, instead of casted
if (spellInfo->EquippedItemClass >= 0)
{
- for (SpellEffectInfo const* effectInfo : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effectInfo : spellInfo->GetEffects())
if (effectInfo && effectInfo->IsAura())
{
if (!HasAura(spellInfo->Id) && HasItemFitToSpellRequirements(spellInfo))
@@ -3283,7 +3283,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled /*= false*/, bool learn_
// unlearn non talent higher ranks (recursive)
if (uint32 nextSpell = sSpellMgr->GetNextSpellInChain(spell_id))
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(nextSpell);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(nextSpell, DIFFICULTY_NONE);
if (HasSpell(nextSpell) && !spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT))
RemoveSpell(nextSpell, disabled, false);
}
@@ -3325,7 +3325,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled /*= false*/, bool learn_
RemovePetAura(petSpell);
// update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning)
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, DIFFICULTY_NONE);
if (spellInfo && spellInfo->IsPrimaryProfessionFirstRank())
{
uint32 freeProfs = GetFreePrimaryProfessionPoints()+1;
@@ -3449,7 +3449,7 @@ void Player::RemoveArenaSpellCooldowns(bool removeActivePetCooldowns)
// remove cooldowns on spells that have < 10 min CD
GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, DIFFICULTY_NONE);
return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS;
}, true);
@@ -5442,7 +5442,7 @@ bool Player::UpdateCraftSkill(uint32 spellid)
uint32 SkillValue = GetPureSkillValue(_spell_idx->second->SkillupSkillLineID);
// Alchemy Discoveries here
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spellid);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spellid, DIFFICULTY_NONE);
if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY)
{
if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->SkillupSkillLineID, spellid, this))
@@ -6026,7 +6026,7 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type) co
switch (type)
{
case ACTION_BUTTON_SPELL:
- if (!sSpellMgr->GetSpellInfo(action))
+ if (!sSpellMgr->GetSpellInfo(action, DIFFICULTY_NONE))
{
TC_LOG_DEBUG("entities.player", "Player::IsActionButtonDataValid: Spell action %u not added into button %u for player %s (%s): spell does not exist. This can be due to a character imported from a different expansion",
action, button, GetName().c_str(), GetGUID().ToString().c_str());
@@ -7918,7 +7918,7 @@ void Player::ApplyItemDependentAuras(Item* item, bool apply)
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first, DIFFICULTY_NONE);
if (!spellInfo || !spellInfo->IsPassive() || spellInfo->EquippedItemClass < 0)
continue;
@@ -7955,11 +7955,11 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool formChange /*= fal
continue;
// check if it is valid spell
- SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(effectData->SpellID);
+ SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(effectData->SpellID, DIFFICULTY_NONE);
if (!spellproto)
continue;
- if (spellproto->HasAura(GetMap()->GetDifficultyID(), SPELL_AURA_MOD_XP_PCT)
+ if (spellproto->HasAura(SPELL_AURA_MOD_XP_PCT)
&& !GetSession()->GetCollectionMgr()->CanApplyHeirloomXpBonus(item->GetEntry(), getLevel())
&& sDB2Manager.GetHeirloomByItemId(item->GetEntry()))
continue;
@@ -8033,7 +8033,7 @@ void Player::UpdateItemSetAuras(bool formChange /*= false*/)
for (ItemSetSpellEntry const* itemSetSpell : eff->SetBonuses)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
if (itemSetSpell->ChrSpecID && itemSetSpell->ChrSpecID != GetPrimarySpecialization())
ApplyEquipSpell(spellInfo, nullptr, false, false); // item set aura is not for current spec
@@ -8074,7 +8074,7 @@ void Player::ApplyArtifactPowers(Item* item, bool apply)
void Player::ApplyArtifactPowerRank(Item* artifact, ArtifactPowerRankEntry const* artifactPowerRank, bool apply)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(artifactPowerRank->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(artifactPowerRank->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
return;
@@ -8189,7 +8189,7 @@ void Player::ApplyAzeriteEssence(AzeriteItem* item, uint32 azeriteEssenceId, uin
void Player::ApplyAzeriteEssencePower(AzeriteItem* item, AzeriteEssencePowerEntry const* azeriteEssencePower, bool major, bool apply)
{
- if (SpellInfo const* powerSpell = sSpellMgr->GetSpellInfo(azeriteEssencePower->MinorPowerDescription))
+ if (SpellInfo const* powerSpell = sSpellMgr->GetSpellInfo(azeriteEssencePower->MinorPowerDescription, DIFFICULTY_NONE))
{
if (apply)
CastSpell(this, powerSpell, true, item);
@@ -8199,7 +8199,7 @@ void Player::ApplyAzeriteEssencePower(AzeriteItem* item, AzeriteEssencePowerEntr
if (major)
{
- if (SpellInfo const* powerSpell = sSpellMgr->GetSpellInfo(azeriteEssencePower->MajorPowerDescription))
+ if (SpellInfo const* powerSpell = sSpellMgr->GetSpellInfo(azeriteEssencePower->MajorPowerDescription, DIFFICULTY_NONE))
{
if (powerSpell->IsPassive())
{
@@ -8293,7 +8293,7 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
if (effectData->TriggerType != ITEM_SPELLTRIGGER_CHANCE_ON_HIT)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player.items", "Player::CastItemCombatSpell: Player '%s' (%s) cast unknown item spell (ID: %i)",
@@ -8302,7 +8302,7 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
}
// not allow proc extra attack spell at extra attack
- if (m_extraAttacks && spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_ADD_EXTRA_ATTACKS))
+ if (m_extraAttacks && spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
return;
float chance = (float)spellInfo->ProcChance;
@@ -8352,7 +8352,7 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
if (entry && (entry->AttributesMask & ENCHANT_PROC_ATTR_WHITE_HIT) && damageInfo.GetSpellInfo())
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->EffectArg[s]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->EffectArg[s], DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player.items", "Player::CastItemCombatSpell: Player '%s' (%s) cast unknown spell (EnchantID: %u, SpellID: %i), ignoring",
@@ -8400,8 +8400,8 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if (spellInfo->GetEffect(DIFFICULTY_NONE, i)->IsEffect())
- values.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->GetEffect(DIFFICULTY_NONE, i)->CalcValue(this), effectPct));
+ if (spellInfo->GetEffect(i)->IsEffect())
+ values.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->GetEffect(i)->CalcValue(this), effectPct));
}
}
@@ -8421,7 +8421,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec
uint32 learn_spell_id = item->GetEffect(0)->SpellID;
uint32 learning_spell_id = item->GetEffect(1)->SpellID;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learn_spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learn_spell_id, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) has wrong spell id %u, ignoring", item->GetEntry(), learn_spell_id);
@@ -8451,7 +8451,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec
if (effectData->TriggerType != ITEM_SPELLTRIGGER_ON_USE)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) has wrong spell id %u, ignoring", item->GetEntry(), effectData->SpellID);
@@ -8485,7 +8485,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec
if (pEnchant->Effect[s] != ITEM_ENCHANTMENT_TYPE_USE_SPELL)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->EffectArg[s]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->EffectArg[s], DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Enchant %i, cast unknown spell %i", enchant_id, pEnchant->EffectArg[s]);
@@ -12383,7 +12383,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
if (pProto && IsInCombat() && (pProto->GetClass() == ITEM_CLASS_WEAPON || pProto->GetInventoryType() == INVTYPE_RELIC) && m_weaponChangeTimer == 0)
{
uint32 cooldownSpell = getClass() == CLASS_ROGUE ? 6123 : 6119;
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell);
+ SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell, DIFFICULTY_NONE);
if (!spellProto)
TC_LOG_ERROR("entities.player", "Player::EquipItem: Weapon switch cooldown spell %u for player '%s' (%s) couldn't be found in Spell.dbc",
@@ -15573,13 +15573,13 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
if (quest->GetSrcSpell() > 0)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetSrcSpell());
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetSrcSpell(), GetMap()->GetDifficultyID());
Unit* caster = this;
if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_ACCEPT) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER) && !spellInfo->HasTargetType(TARGET_DEST_CASTER_SUMMON))
if (Unit* unit = questGiver->ToUnit())
- unit->CastSpell(this, quest->GetSrcSpell(), true);
+ caster = unit;
- caster->CastSpell(this, quest->GetSrcSpell(), true);
+ caster->CastSpell(this, spellInfo, true);
}
SetQuestSlot(log_slot, quest_id, qtime);
@@ -15892,13 +15892,13 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
// cast spells after mark quest complete (some spells have quest completed state requirements in spell_area data)
if (quest->GetRewSpell() > 0)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell(), GetMap()->GetDifficultyID());
Unit* caster = this;
if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
if (Unit* unit = questGiver->ToUnit())
caster = unit;
- caster->CastSpell(this, quest->GetRewSpell(), true);
+ caster->CastSpell(this, spellInfo, true);
}
else
{
@@ -15906,13 +15906,13 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
{
if (quest->RewardDisplaySpell[i] > 0)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->RewardDisplaySpell[i]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->RewardDisplaySpell[i], GetMap()->GetDifficultyID());
Unit* caster = this;
if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
if (Unit * unit = questGiver->ToUnit())
caster = unit;
- caster->CastSpell(this, quest->RewardDisplaySpell[i], true);
+ caster->CastSpell(this, spellInfo, true);
}
}
}
@@ -18823,8 +18823,8 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe
}
/*
- 0 1 2 3 4 5 6 7 8 9 10
- SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ?
+ 0 1 2 3 4 5 6 7 8 9 10 11
+ SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ?
*/
if (auraResult)
{
@@ -18835,14 +18835,15 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe
itemGuid.SetRawValue(fields[1].GetBinary());
AuraKey key{ casterGuid, itemGuid, fields[2].GetUInt32(), fields[3].GetUInt32() };
uint32 recalculateMask = fields[4].GetUInt32();
- uint8 stackCount = fields[5].GetUInt8();
- int32 maxDuration = fields[6].GetInt32();
- int32 remainTime = fields[7].GetInt32();
- uint8 remainCharges = fields[8].GetUInt8();
- uint32 castItemId = fields[9].GetUInt32();
- int32 castItemLevel = fields[10].GetInt32();
-
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId);
+ Difficulty difficulty = Difficulty(fields[5].GetUInt8());
+ uint8 stackCount = fields[6].GetUInt8();
+ int32 maxDuration = fields[7].GetInt32();
+ int32 remainTime = fields[8].GetInt32();
+ uint8 remainCharges = fields[9].GetUInt8();
+ uint32 castItemId = fields[10].GetUInt32();
+ int32 castItemLevel = fields[11].GetInt32();
+
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId, difficulty);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::_LoadAuras: Player '%s' (%s) has an invalid aura (SpellID: %u), ignoring.",
@@ -18850,6 +18851,13 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe
continue;
}
+ if (difficulty != DIFFICULTY_NONE && !sDifficultyStore.LookupEntry(difficulty))
+ {
+ TC_LOG_ERROR("entities.player", "Player::_LoadAuras: Player '%s' (%s) has an invalid aura difficulty %u (SpellID: %u), ignoring.",
+ GetName().c_str(), GetGUID().ToString().c_str(), uint32(difficulty), key.SpellId);
+ continue;
+ }
+
// negative effects should continue counting down after logout
if (remainTime != -1 && !spellInfo->IsPositive())
{
@@ -18872,7 +18880,7 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe
AuraLoadEffectInfo& info = effectInfo[key];
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
- if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, info.BaseAmounts.data(), nullptr, casterGuid, itemGuid, castItemId, castItemLevel))
+ if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, difficulty, info.BaseAmounts.data(), nullptr, casterGuid, itemGuid, castItemId, castItemLevel))
{
if (!aura->CanBeSaved())
{
@@ -20813,6 +20821,7 @@ void Player::_SaveAuras(CharacterDatabaseTransaction& trans)
stmt->setUInt32(index++, key.SpellId);
stmt->setUInt32(index++, key.EffectMask);
stmt->setUInt32(index++, recalculateMask);
+ stmt->setUInt8(index++, aura->GetCastDifficulty());
stmt->setUInt8(index++, aura->GetStackAmount());
stmt->setInt32(index++, aura->GetMaxDuration());
stmt->setInt32(index++, aura->GetDuration());
@@ -21771,7 +21780,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
{
//returning of reagents only for players, so best done here
uint32 spellId = pet ? *pet->m_unitData->CreatedBySpell : m_oldpetspell;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (spellInfo)
{
@@ -22094,7 +22103,7 @@ void Player::VehicleSpellInitialize()
for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i)
{
uint32 spellId = vehicle->m_spells[i];
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
continue;
@@ -22106,7 +22115,7 @@ void Player::VehicleSpellInitialize()
}
if (spellInfo->IsPassive())
- vehicle->CastSpell(vehicle, spellId, true);
+ vehicle->CastSpell(vehicle, spellInfo, true);
petSpells.ActionButtons[i] = MAKE_UNIT_ACTION_BUTTON(spellId, i + 8);
}
@@ -22182,7 +22191,7 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod
template <class T>
void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell /*= nullptr*/) const
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
return;
@@ -23329,7 +23338,7 @@ void Player::UpdatePotionCooldown(Spell* spell)
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(m_lastPotionId))
for (uint8 idx = 0; idx < proto->Effects.size(); ++idx)
if (proto->Effects[idx]->TriggerType == ITEM_SPELLTRIGGER_ON_USE)
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Effects[idx]->SpellID))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Effects[idx]->SpellID, DIFFICULTY_NONE))
GetSpellHistory()->SendCooldownEvent(spellInfo, m_lastPotionId);
}
// from spell cases (m_lastPotionId set in Spell::SendSpellCooldown)
@@ -24282,10 +24291,11 @@ void Player::ApplyEquipCooldown(Item* pItem)
std::chrono::steady_clock::time_point now = GameTime::GetGameTimeSteadyPoint();
for (ItemEffectEntry const* effectData : pItem->GetEffects())
{
+ SpellInfo const* effectSpellInfo = sSpellMgr->AssertSpellInfo(effectData->SpellID, DIFFICULTY_NONE);
// apply proc cooldown to equip auras if we have any
if (effectData->TriggerType == ITEM_SPELLTRIGGER_ON_EQUIP)
{
- SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(effectData->SpellID);
+ SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(effectSpellInfo);
if (!procEntry)
continue;
@@ -24299,7 +24309,7 @@ void Player::ApplyEquipCooldown(Item* pItem)
continue;
// Don't replace longer cooldowns by equip cooldown if we have any.
- if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->AssertSpellInfo(effectData->SpellID)) > 30 * IN_MILLISECONDS)
+ if (GetSpellHistory()->GetRemainingCooldown(effectSpellInfo) > 30 * IN_MILLISECONDS)
continue;
GetSpellHistory()->AddCooldown(effectData->SpellID, pItem->GetEntry(), std::chrono::seconds(30));
@@ -24333,7 +24343,7 @@ void Player::ResetSpells(bool myClassOnly)
for (PlayerSpellMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(iter->first);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(iter->first, DIFFICULTY_NONE);
if (!spellInfo)
continue;
@@ -24458,13 +24468,13 @@ void Player::LearnQuestRewardedSpells(Quest const* quest)
return;
}
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, DIFFICULTY_NONE);
if (!spellInfo)
return;
// check learned spells state
bool found = false;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(effect->TriggerSpell))
{
@@ -24477,7 +24487,7 @@ void Player::LearnQuestRewardedSpells(Quest const* quest)
if (!found)
return;
- SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, EFFECT_0);
+ SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0);
if (!effect)
return;
@@ -24525,7 +24535,7 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue)
for (SkillLineAbilityEntry const* ability : *skillLineAbilities)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ability->Spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ability->Spell, DIFFICULTY_NONE);
if (!spellInfo)
continue;
@@ -26669,7 +26679,7 @@ TalentLearnResult Player::LearnPvpTalent(uint32 talentID, uint8 slot, int32* spe
bool Player::AddPvpTalent(PvpTalentEntry const* talent, uint8 activeTalentGroup, uint8 slot)
{
ASSERT(talent);
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: %u) does not exist.", talent->SpellID);
@@ -26696,7 +26706,7 @@ bool Player::AddPvpTalent(PvpTalentEntry const* talent, uint8 activeTalentGroup,
void Player::RemovePvpTalent(PvpTalentEntry const* talent)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
return;
@@ -26906,7 +26916,7 @@ void Player::SendTalentsInfoData()
continue;
}
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID, DIFFICULTY_NONE);
if (!spellEntry)
{
TC_LOG_ERROR("entities.player", "Player::SendTalentsInfoData: Player '%s' (%s) has unknown talent spell: %u",
@@ -26930,7 +26940,7 @@ void Player::SendTalentsInfoData()
continue;
}
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID, DIFFICULTY_NONE);
if (!spellEntry)
{
TC_LOG_ERROR("entities.player", "Player::SendTalentsInfoData: Player '%s' (%s) has unknown pvp talent spell: %u",
@@ -27334,14 +27344,14 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec)
if (talentInfo->SpellID == 0)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
continue;
RemoveSpell(talentInfo->SpellID, true);
// search for spells that the talent teaches and unlearn them
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL)
RemoveSpell(effect->TriggerSpell, true);
@@ -27355,14 +27365,14 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec)
if (!talentInfo)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
continue;
RemoveSpell(talentInfo->SpellID, true);
// search for spells that the talent teaches and unlearn them
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL)
RemoveSpell(effect->TriggerSpell, true);
@@ -28407,7 +28417,7 @@ SpellInfo const* Player::GetCastSpellInfo(SpellInfo const* spellInfo) const
auto overrides = m_overrideSpells.find(spellInfo->Id);
if (overrides != m_overrideSpells.end())
for (uint32 spellId : overrides->second)
- if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()))
return Unit::GetCastSpellInfo(newInfo);
return Unit::GetCastSpellInfo(spellInfo);
@@ -28436,7 +28446,7 @@ void Player::LearnSpecializationSpells()
for (size_t j = 0; j < specSpells->size(); ++j)
{
SpecializationSpellsEntry const* specSpell = (*specSpells)[j];
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID, DIFFICULTY_NONE);
if (!spellInfo || spellInfo->SpellLevel > getLevel())
continue;
diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp
index 34f321d9cd3..c422bc181ca 100644
--- a/src/server/game/Entities/Totem/Totem.cpp
+++ b/src/server/game/Entities/Totem/Totem.cpp
@@ -73,7 +73,7 @@ void Totem::InitStats(uint32 duration)
Minion::InitStats(duration);
// Get spell cast by totem
- if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell()))
+ if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell(), GetMap()->GetDifficultyID()))
if (totemSpell->CalcCastTime(getLevel())) // If spell has cast time -> its an active totem
m_type = TOTEM_ACTIVE;
@@ -120,7 +120,7 @@ void Totem::UnSummon(uint32 msTime)
{
owner->SendAutoRepeatCancel(this);
- if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(m_unitData->CreatedBySpell))
+ if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(m_unitData->CreatedBySpell, GetMap()->GetDifficultyID()))
GetSpellHistory()->SendCooldownEvent(spell, 0, nullptr, false);
if (Group* group = owner->GetGroup())
@@ -142,17 +142,17 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Uni
/// @todo possibly all negative auras immune?
if (GetEntry() == 5925)
return false;
- if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), index))
+ if (SpellEffectInfo const* effect = spellInfo->GetEffect(index))
{
switch (effect->ApplyAuraName)
{
- case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_PERIODIC_LEECH:
- case SPELL_AURA_MOD_FEAR:
- case SPELL_AURA_TRANSFORM:
- return true;
- default:
- break;
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_MOD_FEAR:
+ case SPELL_AURA_TRANSFORM:
+ return true;
+ default:
+ break;
}
}
else
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 88fb805a71d..29596e4b705 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -539,7 +539,7 @@ void Player::UpdateMastery()
{
if (Aura* aura = GetAura(chrSpec->MasterySpellID[i]))
{
- for (SpellEffectInfo const* effect : aura->GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : aura->GetSpellInfo()->GetEffects())
{
if (!effect)
continue;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 43ae9f624d0..29f2d6433ce 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -172,7 +172,7 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo)
DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType, WeaponAttackType attackType, uint32 hitMask)
: m_attacker(spellNonMeleeDamage.attacker), m_victim(spellNonMeleeDamage.target), m_damage(spellNonMeleeDamage.damage), m_originalDamage(spellNonMeleeDamage.originalDamage),
- m_spellInfo(sSpellMgr->GetSpellInfo(spellNonMeleeDamage.SpellID)), m_schoolMask(SpellSchoolMask(spellNonMeleeDamage.schoolMask)), m_damageType(damageType),
+ m_spellInfo(spellNonMeleeDamage.Spell), m_schoolMask(SpellSchoolMask(spellNonMeleeDamage.schoolMask)), m_damageType(damageType),
m_attackType(attackType), m_absorb(spellNonMeleeDamage.absorb), m_resist(spellNonMeleeDamage.resist), m_block(spellNonMeleeDamage.blocked), m_hitMask(hitMask)
{
if (spellNonMeleeDamage.blocked)
@@ -278,8 +278,8 @@ SpellSchoolMask ProcEventInfo::GetSchoolMask() const
return SPELL_SCHOOL_MASK_NONE;
}
-SpellNonMeleeDamage::SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _SpellXSpellVisualID, uint32 _schoolMask, ObjectGuid _castId)
- : target(_target), attacker(_attacker), castId(_castId), SpellID(_SpellID), SpellXSpellVisualID(_SpellXSpellVisualID), damage(0), originalDamage(0),
+SpellNonMeleeDamage::SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellInfo const* _spellInfo, uint32 _SpellXSpellVisualID, uint32 _schoolMask, ObjectGuid _castId)
+ : target(_target), attacker(_attacker), castId(_castId), Spell(_spellInfo), SpellXSpellVisualID(_SpellXSpellVisualID), damage(0), originalDamage(0),
schoolMask(_schoolMask), absorb(0), resist(0), periodicLog(false), blocked(0), HitInfo(0), cleanDamage(0), fullBlock(false), preHitHealth(_target->GetHealth())
{
}
@@ -884,7 +884,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (victim->GetTypeId() != TYPEID_PLAYER)
{
// Part of Evade mechanics. DoT's and Thorns / Retribution Aura do not contribute to this
- if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(GetMap()->GetDifficultyID(), SPELL_AURA_DAMAGE_SHIELD)))
+ if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD)))
victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME);
victim->AddThreat(this, float(damage), damageSchoolMask, spellProto);
@@ -988,7 +988,7 @@ void Unit::CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castIte
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);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str());
@@ -1038,7 +1038,7 @@ void Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit*
void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit* victim, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str());
@@ -1052,7 +1052,7 @@ void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit*
void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str());
@@ -1066,7 +1066,7 @@ void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered,
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);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str());
@@ -1080,7 +1080,7 @@ void Unit::CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags
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, GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str());
@@ -1220,16 +1220,15 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage const* damageInfo, bool durabilit
if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
return;
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(damageInfo->SpellID);
- if (!spellProto)
+ if (!damageInfo->Spell)
{
- TC_LOG_DEBUG("entities.unit", "Unit::DealSpellDamage has wrong damageInfo->SpellID: %u", damageInfo->SpellID);
+ TC_LOG_DEBUG("entities.unit", "Unit::DealSpellDamage has no spell");
return;
}
// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
+ DealDamage(victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), damageInfo->Spell, durabilityLoss);
}
/// @todo for melee need create structure as in
@@ -1576,7 +1575,7 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s
if (effIndex != -1)
{
// bleeding effects are not reduced by armor
- if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), effIndex))
+ if (SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex))
{
if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE ||
effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
@@ -1938,7 +1937,7 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
uint32 split_absorb = 0;
DealDamageMods(caster, splitDamage, &split_absorb);
- SpellNonMeleeDamage log(this, caster, (*itr)->GetSpellInfo()->Id, (*itr)->GetBase()->GetSpellXSpellVisualId(), damageInfo.GetSchoolMask(), (*itr)->GetBase()->GetCastGUID());
+ SpellNonMeleeDamage log(this, caster, (*itr)->GetSpellInfo(), (*itr)->GetBase()->GetSpellXSpellVisualId(), damageInfo.GetSchoolMask(), (*itr)->GetBase()->GetCastGUID());
CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
log.damage = splitDamage;
@@ -2360,12 +2359,12 @@ int32 Unit::GetMechanicResistChance(SpellInfo const* spellInfo) const
return 0;
int32 resistMech = 0;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect || !effect->IsEffect())
break;
- int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex, GetMap()->GetDifficultyID());
+ int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex);
if (effectMech)
{
int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effectMech);
@@ -3252,7 +3251,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3
return nullptr;
// update basepoints with new values - effect amount will be recalculated in ModStackAmount
- for (SpellEffectInfo const* effect : foundAura->GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : newAura->GetEffects())
{
if (!effect)
continue;
@@ -3522,12 +3521,12 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura)
SpellInfo const* spellProto = aura->GetSpellInfo();
// passive spell special case (only non stackable with ranks)
- if (spellProto->IsPassiveStackableWithRanks(GetMap()->GetDifficultyID()))
+ if (spellProto->IsPassiveStackableWithRanks())
return;
if (!IsHighestExclusiveAura(aura))
{
- if (!aura->GetSpellInfo()->IsAffectingArea(GetMap()->GetDifficultyID()))
+ if (!aura->GetSpellInfo()->IsAffectingArea())
{
Unit* caster = aura->GetCaster();
if (caster && caster->GetTypeId() == TYPEID_PLAYER)
@@ -3896,7 +3895,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, U
if (aura->IsSingleTarget())
aura->UnregisterSingleTarget();
- if (Aura* newAura = Aura::TryRefreshStackOrCreate(aura->GetSpellInfo(), aura->GetCastGUID(), effMask, stealer, nullptr, &baseDamage[0], nullptr, aura->GetCasterGUID()))
+ if (Aura* newAura = Aura::TryRefreshStackOrCreate(aura->GetSpellInfo(), aura->GetCastGUID(), effMask, stealer, nullptr, aura->GetCastDifficulty(), &baseDamage[0], nullptr, aura->GetCasterGUID()))
{
// created aura must not be single target aura,, so stealer won't loose it on recast
if (newAura->IsSingleTarget())
@@ -4086,7 +4085,7 @@ void Unit::RemoveMovementImpairingAuras(bool withRoot)
}
// turn off snare auras by setting amount to 0
- for (SpellEffectInfo const* effect : aura->GetSpellInfo()->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : aura->GetSpellInfo()->GetEffects())
{
if (!effect || !effect->IsEffect())
continue;
@@ -4252,7 +4251,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type)
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
{
Aura const* aura = iter->second->GetBase();
- if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type))
+ if (aura->GetSpellInfo()->HasAura(type))
++iter;
else
_UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT);
@@ -4261,7 +4260,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type)
for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
{
Aura* aura = iter->second;
- if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type))
+ if (aura->GetSpellInfo()->HasAura(type))
++iter;
else
RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT);
@@ -4273,7 +4272,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type1, AuraType type2)
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
{
Aura const* aura = iter->second->GetBase();
- if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type2))
+ if (aura->GetSpellInfo()->HasAura(type1) || aura->GetSpellInfo()->HasAura(type2))
++iter;
else
_UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT);
@@ -4282,7 +4281,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type1, AuraType type2)
for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
{
Aura* aura = iter->second;
- if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type2))
+ if (aura->GetSpellInfo()->HasAura(type1) || aura->GetSpellInfo()->HasAura(type2))
++iter;
else
RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT);
@@ -4572,9 +4571,9 @@ bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const
if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic)))
return true;
- for (SpellEffectInfo const* effect : iter->second->GetBase()->GetSpellEffectInfos())
- if (effect && effect->Effect && effect->Mechanic)
- if (mechanicMask & (1 << effect->Mechanic))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
+ if (effect && effect->Effect && effect->Mechanic)
+ if (mechanicMask & (1 << effect->Mechanic))
return true;
}
@@ -5035,7 +5034,7 @@ void Unit::AddGameObject(GameObject* gameObj)
if (gameObj->GetSpellId())
{
- SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(gameObj->GetSpellId());
+ SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(gameObj->GetSpellId(), GetMap()->GetDifficultyID());
// Need disable spell use for owner
if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
@@ -5067,7 +5066,7 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del)
{
RemoveAurasDueToSpell(spellid);
- SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(spellid);
+ SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(spellid, GetMap()->GetDifficultyID());
// Need activate spell use for owner
if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
@@ -5196,7 +5195,7 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage const* log)
packet.Me = log->target->GetGUID();
packet.CasterGUID = log->attacker->GetGUID();
packet.CastID = log->castId;
- packet.SpellID = log->SpellID;
+ packet.SpellID = log->Spell ? log->Spell->Id : 0;
packet.Damage = log->damage;
packet.OriginalDamage = log->originalDamage;
if (log->damage > log->preHitHealth)
@@ -5862,7 +5861,7 @@ void Unit::ModifyAuraState(AuraStateType flag, bool apply)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first, DIFFICULTY_NONE);
if (!spellInfo || !spellInfo->IsPassive())
continue;
if (spellInfo->CasterAuraState == uint32(flag))
@@ -5875,7 +5874,7 @@ void Unit::ModifyAuraState(AuraStateType flag, bool apply)
{
if (itr->second.state == PETSPELL_REMOVED)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first, DIFFICULTY_NONE);
if (!spellInfo || !spellInfo->IsPassive())
continue;
if (spellInfo->CasterAuraState == uint32(flag))
@@ -6125,7 +6124,7 @@ void Unit::SetMinion(Minion *minion, bool apply)
minion->SetSpeedRate(UnitMoveType(i), m_speed_rate[i]);
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->m_unitData->CreatedBySpell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->m_unitData->CreatedBySpell, GetMap()->GetDifficultyID());
if (spellInfo && (spellInfo->IsCooldownStartedOnEvent()))
GetSpellHistory()->StartCooldown(spellInfo, 0, nullptr, true);
@@ -6152,8 +6151,8 @@ void Unit::SetMinion(Minion *minion, bool apply)
else if (minion->IsTotem())
{
// All summoned by totem minions must disappear when it is removed.
- if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell()))
- for (SpellEffectInfo const* effect : spInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell(), GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spInfo->GetEffects())
{
if (!effect || effect->Effect != SPELL_EFFECT_SUMMON)
continue;
@@ -6162,7 +6161,7 @@ void Unit::SetMinion(Minion *minion, bool apply)
}
}
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->m_unitData->CreatedBySpell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->m_unitData->CreatedBySpell, GetMap()->GetDifficultyID());
// Remove infinity cooldown
if (spellInfo && (spellInfo->IsCooldownStartedOnEvent()))
GetSpellHistory()->SendCooldownEvent(spellInfo);
@@ -6619,7 +6618,7 @@ void Unit::EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers po
int32 gain = victim->ModifyPower(powerType, damage);
int32 overEnergize = damage - gain;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo);
SendEnergizeSpellLog(victim, spellId, damage, overEnergize, powerType);
@@ -7142,7 +7141,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
DoneTotal += int32(DoneAdvertisedBenefit * coeff * stack);
}
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellProto->GetEffects())
{
if (!effect)
continue;
@@ -7257,7 +7256,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
return false;
});
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellProto->GetEffects())
{
if (!effect)
continue;
@@ -7363,7 +7362,7 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
uint32 schoolImmunityMask = 0;
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)))
+ if ((itr->first & schoolMask) && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->second, GetMap()->GetDifficultyID())))
schoolImmunityMask |= itr->first;
// // We need to be immune to all types
@@ -7408,7 +7407,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const
}
bool immuneToAllEffects = true;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
// State/effect immunities applied by aura expect full spell immunity
// Ignore effects with mechanic, they are supposed to be checked separately
@@ -7433,7 +7432,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const
if ((itr->first & schoolMask) == 0)
continue;
- SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
+ SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second, GetMap()->GetDifficultyID());
if (!(immuneSpellInfo && immuneSpellInfo->IsPositive() && spellInfo->IsPositive() && caster && IsFriendlyTo(caster)))
if (!spellInfo->CanPierceImmuneAura(immuneSpellInfo))
schoolImmunityMask |= itr->first;
@@ -7480,7 +7479,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit
if (!spellInfo)
return false;
- SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), index);
+ SpellEffectInfo const* effect = spellInfo->GetEffect(index);
if (!effect)
return false;
@@ -7559,7 +7558,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (APbonus != 0) // Can be negative
{
- bool const normalized = spellProto && spellProto->HasEffect(GetMap()->GetDifficultyID(), SPELL_EFFECT_NORMALIZED_WEAPON_DMG);
+ bool const normalized = spellProto && spellProto->HasEffect(SPELL_EFFECT_NORMALIZED_WEAPON_DMG);
DoneFlatBenefit += int32(APbonus / 3.5f * GetAPMultiplier(attType, normalized));
}
@@ -8126,12 +8125,12 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
// can't attack invisible
if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE))
{
- if (obj && !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficultyID())))
+ 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(GetMap()->GetDifficultyID())) ||
+ bool const ignoreStealthCheck = (bySpell && bySpell->IsAffectingArea()) ||
(target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target));
if (!CanSeeOrDetect(target, ignoreStealthCheck))
@@ -8252,7 +8251,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co
return false;
// can't assist invisible
- if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficultyID())))
+ if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
return false;
// can't assist dead
@@ -9045,7 +9044,7 @@ float Unit::ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index
// function uses real base points (typically value - 1)
int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints /*= nullptr*/, float* variance /*= nullptr*/, uint32 castItemId /*= 0*/, int32 itemLevel /*= -1*/) const
{
- SpellEffectInfo const* effect = spellProto->GetEffect(GetMap()->GetDifficultyID(), effect_index);
+ SpellEffectInfo const* effect = spellProto->GetEffect(effect_index);
if (variance)
*variance = 0.0f;
@@ -9137,7 +9136,7 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in
sSpellMgr->IsSpellMemberOfSpellGroup(spellProto->Id, SPELL_GROUP_ELIXIR_BATTLE) ||
sSpellMgr->IsSpellMemberOfSpellGroup(spellProto->Id, SPELL_GROUP_ELIXIR_GUARDIAN)))
{
- SpellEffectInfo const* effect = spellProto->GetEffect(DIFFICULTY_NONE, EFFECT_0);
+ SpellEffectInfo const* effect = spellProto->GetEffect(EFFECT_0);
if (target->HasAura(53042) && effect && target->HasSpell(effect->TriggerSpell))
duration *= 2;
}
@@ -9378,7 +9377,7 @@ bool Unit::IsInDisallowedMountForm() const
bool Unit::IsDisallowedMountForm(uint32 spellId, ShapeshiftForm form, uint32 displayId) const
{
- if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()))
if (transformSpellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_MOUNTED))
return false;
@@ -10152,7 +10151,7 @@ void CharmInfo::InitPossessCreateSpells()
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
{
uint32 spellId = _unit->ToCreature()->m_spells[i];
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _unit->GetMap()->GetDifficultyID());
if (spellInfo)
{
if (spellInfo->IsPassive())
@@ -10179,7 +10178,7 @@ void CharmInfo::InitCharmCreateSpells()
for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x)
{
uint32 spellId = _unit->ToCreature()->m_spells[x];
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _unit->GetMap()->GetDifficultyID());
if (!spellInfo)
{
@@ -10309,7 +10308,7 @@ void CharmInfo::LoadPetActionBar(const std::string& data)
// check correctness
if (PetActionBar[index].IsActionBarForSpell())
{
- SpellInfo const* spelInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction());
+ SpellInfo const* spelInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction(), _unit->GetMap()->GetDifficultyID());
if (!spelInfo)
SetActionBar(index, 0, ACT_PASSIVE);
else if (!spelInfo->IsAutocastable())
@@ -10731,7 +10730,7 @@ bool Unit::IsPolymorphed() const
if (!transformId)
return false;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(transformId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(transformId, GetMap()->GetDifficultyID());
if (!spellInfo)
return false;
@@ -10974,7 +10973,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp
bool DirectDamage = false;
bool AreaEffect = false;
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellProto->GetEffects())
{
if (!effect)
continue;
@@ -11033,7 +11032,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp
CastingTime /= 2;
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellProto->GetEffects())
{
if (!effect)
continue;
@@ -11089,7 +11088,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
if (!spellInfo->IsChanneled() && DotDuration > 0)
DotFactor = DotDuration / 15000.0f;
- if (uint32 DotTicks = spellInfo->GetMaxTicks(GetMap()->GetDifficultyID()))
+ if (uint32 DotTicks = spellInfo->GetMaxTicks())
DotFactor /= DotTicks;
}
@@ -12251,7 +12250,7 @@ Aura* Unit::AddAura(uint32 spellId, Unit* target)
if (!target)
return NULL;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID());
if (!spellInfo)
return NULL;
@@ -12278,7 +12277,7 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint32 effMask, Unit* target)
}
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
- if (Aura* aura = Aura::TryRefreshStackOrCreate(spellInfo, castId, effMask, target, this))
+ if (Aura* aura = Aura::TryRefreshStackOrCreate(spellInfo, castId, effMask, target, this, GetMap()->GetDifficultyID()))
{
aura->ApplyForTargets();
return aura;
@@ -13023,14 +13022,14 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this;
ObjectGuid origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID();
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId, caster->GetMap()->GetDifficultyID());
// if (!spellEntry) should be checked at npc_spellclick load
if (seatId > -1)
{
uint8 i = 0;
bool valid = false;
- for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellEntry->GetEffects())
{
if (!effect)
continue;
@@ -13054,12 +13053,12 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
else // This can happen during Player::_LoadAuras
{
int32 bp0[MAX_SPELL_EFFECTS];
- for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellEntry->GetEffects())
if (effect)
bp0[effect->EffectIndex] = effect->BasePoints;
bp0[i] = seatId;
- Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, bp0, NULL, origCasterGUID);
+ Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, GetMap()->GetDifficultyID(), bp0, NULL, origCasterGUID);
}
}
else
@@ -13067,7 +13066,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
if (IsInMap(caster))
caster->CastSpell(target, spellEntry, flags, NULL, NULL, origCasterGUID);
else
- Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID);
+ Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, GetMap()->GetDifficultyID(), NULL, NULL, origCasterGUID);
}
result = true;
@@ -14495,7 +14494,7 @@ SpellInfo const* Unit::GetCastSpellInfo(SpellInfo const* spellInfo) const
{
bool matches = auraEffect->GetMiscValue() ? uint32(auraEffect->GetMiscValue()) == spellInfo->Id : auraEffect->IsAffectingSpell(spellInfo);
if (matches)
- if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo(auraEffect->GetAmount()))
+ if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo(auraEffect->GetAmount(), GetMap()->GetDifficultyID()))
return newInfo;
}
@@ -14518,7 +14517,7 @@ uint32 Unit::GetCastSpellXSpellVisualId(SpellInfo const* spellInfo) const
{
if (uint32(effect->GetMiscValue()) == spellInfo->Id)
{
- if (SpellInfo const* visualSpell = sSpellMgr->GetSpellInfo(effect->GetMiscValueB()))
+ if (SpellInfo const* visualSpell = sSpellMgr->GetSpellInfo(effect->GetMiscValueB(), GetMap()->GetDifficultyID()))
{
spellInfo = visualSpell;
break;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 48ab77e3856..f6ac8d6d3f5 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -685,12 +685,12 @@ struct CalcDamageInfo
// Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode
struct TC_GAME_API SpellNonMeleeDamage
{
- SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _SpellXSpellVisualID, uint32 _schoolMask, ObjectGuid _castId = ObjectGuid::Empty);
+ SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellInfo const* _spellInfo, uint32 _SpellXSpellVisualID, uint32 _schoolMask, ObjectGuid _castId = ObjectGuid::Empty);
Unit *target;
Unit *attacker;
ObjectGuid castId;
- uint32 SpellID;
+ SpellInfo const* Spell;
uint32 SpellXSpellVisualID;
uint32 damage;
uint32 originalDamage;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 0b2b6ca4ae6..e38539429ae 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -639,14 +639,14 @@ void ObjectMgr::LoadCreatureTemplateAddons()
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
{
uint32 spellId = uint32(atoul(*itr));
- SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!AdditionalSpellInfo)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell %u defined in `auras` field in `creature_template_addon`.", entry, spellId);
continue;
}
- if (AdditionalSpellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE))
+ if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_template_addon`.", entry, spellId);
if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), spellId) != creatureAddon.auras.end())
@@ -1024,7 +1024,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
for (uint8 j = 0; j < MAX_CREATURE_SPELLS; ++j)
{
- if (cInfo->spells[j] && !sSpellMgr->GetSpellInfo(cInfo->spells[j]))
+ if (cInfo->spells[j] && !sSpellMgr->GetSpellInfo(cInfo->spells[j], DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has non-existing Spell%d (%u), set to 0.", cInfo->Entry, j+1, cInfo->spells[j]);
const_cast<CreatureTemplate*>(cInfo)->spells[j] = 0;
@@ -1124,14 +1124,14 @@ void ObjectMgr::LoadCreatureAddons()
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
{
uint32 spellId = uint32(atoul(*itr));
- SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!AdditionalSpellInfo)
{
TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") has wrong spell %u defined in `auras` field in `creature_addon`.", guid, spellId);
continue;
}
- if (AdditionalSpellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE))
+ if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_addon`.", guid, spellId);
if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), spellId) != creatureAddon.auras.end())
@@ -4273,7 +4273,7 @@ void ObjectMgr::LoadQuests()
if (qinfo->_sourceSpellID)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_sourceSpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_sourceSpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SourceSpellid` = %u but spell %u doesn't exist, quest can't be done.",
@@ -4356,7 +4356,7 @@ void ObjectMgr::LoadQuests()
TC_LOG_ERROR("sql.sql", "Quest %u objective %u has invalid currency amount %d", qinfo->GetQuestId(), obj.ID, obj.Amount);
break;
case QUEST_OBJECTIVE_LEARNSPELL:
- if (!sSpellMgr->GetSpellInfo(obj.ObjectID))
+ if (!sSpellMgr->GetSpellInfo(obj.ObjectID, DIFFICULTY_NONE))
TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing spell id %d", qinfo->GetQuestId(), obj.ID, obj.ObjectID);
break;
case QUEST_OBJECTIVE_WINPETBATTLEAGAINSTNPC:
@@ -4489,7 +4489,7 @@ void ObjectMgr::LoadQuests()
{
if (qinfo->RewardDisplaySpell[i])
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardDisplaySpell[i]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardDisplaySpell[i], DIFFICULTY_NONE);
if (!spellInfo)
{
@@ -4509,7 +4509,7 @@ void ObjectMgr::LoadQuests()
if (qinfo->_rewardSpell > 0)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_rewardSpell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_rewardSpell, DIFFICULTY_NONE);
if (!spellInfo)
{
@@ -4679,13 +4679,13 @@ void ObjectMgr::LoadQuests()
}
// check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
+ for (SpellNameEntry const* spellNameEntry : sSpellNameStore)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE);
if (!spellInfo)
continue;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect || effect->Effect != SPELL_EFFECT_QUEST_COMPLETE)
continue;
@@ -5136,7 +5136,7 @@ void ObjectMgr::LoadScripts(ScriptsType type)
case SCRIPT_COMMAND_REMOVE_AURA:
{
- if (!sSpellMgr->GetSpellInfo(tmp.RemoveAura.SpellID))
+ if (!sSpellMgr->GetSpellInfo(tmp.RemoveAura.SpellID, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA for script id %u",
tableName.c_str(), tmp.RemoveAura.SpellID, tmp.id);
@@ -5153,7 +5153,7 @@ void ObjectMgr::LoadScripts(ScriptsType type)
case SCRIPT_COMMAND_CAST_SPELL:
{
- if (!sSpellMgr->GetSpellInfo(tmp.CastSpell.SpellID))
+ if (!sSpellMgr->GetSpellInfo(tmp.CastSpell.SpellID, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_CAST_SPELL for script id %u",
tableName.c_str(), tmp.CastSpell.SpellID, tmp.id);
@@ -5239,7 +5239,7 @@ void ObjectMgr::LoadSpellScripts()
for (ScriptMapMap::const_iterator itr = sSpellScripts.begin(); itr != sSpellScripts.end(); ++itr)
{
uint32 spellId = uint32(itr->first) & 0x00FFFFFF;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
@@ -5267,9 +5267,9 @@ void ObjectMgr::LoadEventScripts()
evt_scripts.insert(eventId);
// Load all possible script entries from spells
- for (uint32 i = 1; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
- if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(i))
- for (SpellEffectInfo const* effect : spell->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellNameEntry const* spellNameEntry : sSpellNameStore)
+ if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spell->GetEffects())
if (effect && effect->Effect == SPELL_EFFECT_SEND_EVENT)
if (effect->MiscValue)
evt_scripts.insert(effect->MiscValue);
@@ -5358,7 +5358,7 @@ void ObjectMgr::LoadSpellScriptNames()
spellId = -spellId;
}
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName.c_str(), fields[0].GetInt32());
@@ -5410,7 +5410,7 @@ void ObjectMgr::ValidateSpellScripts()
for (auto spell : _spellScriptsStore)
{
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell.first);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell.first, DIFFICULTY_NONE);
auto const bounds = sObjectMgr->GetSpellScriptsBounds(spell.first);
@@ -5662,7 +5662,7 @@ void ObjectMgr::LoadInstanceEncounters()
break;
}
case ENCOUNTER_CREDIT_CAST_SPELL:
- if (!sSpellMgr->GetSpellInfo(creditEntry))
+ if (!sSpellMgr->GetSpellInfo(creditEntry, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!",
creditEntry, entry, dungeonEncounter->Name->Str[sWorld->GetDefaultDbcLocale()]);
@@ -6963,7 +6963,7 @@ inline void CheckGOLinkedTrapId(GameObjectTemplate const* goInfo, uint32 dataN,
inline void CheckGOSpellId(GameObjectTemplate const* goInfo, uint32 dataN, uint32 N)
{
- if (sSpellMgr->GetSpellInfo(dataN))
+ if (sSpellMgr->GetSpellInfo(dataN, DIFFICULTY_NONE))
return;
TC_LOG_ERROR("sql.sql", "Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist.",
@@ -7798,7 +7798,7 @@ void ObjectMgr::LoadNPCSpellClickSpells()
}
uint32 spellid = fields[1].GetUInt32();
- SpellInfo const* spellinfo = sSpellMgr->GetSpellInfo(spellid);
+ SpellInfo const* spellinfo = sSpellMgr->GetSpellInfo(spellid, DIFFICULTY_NONE);
if (!spellinfo)
{
TC_LOG_ERROR("sql.sql", "Table npc_spellclick_spells creature: %u references unknown spellid %u. Skipping entry.", npc_entry, spellid);
@@ -8637,7 +8637,7 @@ void ObjectMgr::LoadTrainers()
spell.ReqAbility[2] = fields[7].GetUInt32();
spell.ReqLevel = fields[8].GetUInt8();
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell.SpellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell.SpellId, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Table `trainer_spell` references non-existing spell (SpellId: %u) for TrainerId %u, ignoring", spell.SpellId, trainerId);
@@ -8655,7 +8655,7 @@ void ObjectMgr::LoadTrainers()
for (std::size_t i = 0; i < spell.ReqAbility.size(); ++i)
{
uint32 requiredSpell = spell.ReqAbility[i];
- if (requiredSpell && !sSpellMgr->GetSpellInfo(requiredSpell))
+ if (requiredSpell && !sSpellMgr->GetSpellInfo(requiredSpell, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Table `trainer_spell` references non-existing spell (ReqAbility" SZFMTD ": %u) for TrainerId %u and SpellId %u, ignoring",
i + 1, requiredSpell, spell.SpellId, trainerId);
@@ -9471,9 +9471,9 @@ void ObjectMgr::LoadFactionChangeSpells()
uint32 alliance = fields[0].GetUInt32();
uint32 horde = fields[1].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(alliance))
+ if (!sSpellMgr->GetSpellInfo(alliance, DIFFICULTY_NONE))
TC_LOG_ERROR("sql.sql", "Spell %u (alliance_id) referenced in `player_factionchange_spells` does not exist, pair skipped!", alliance);
- else if (!sSpellMgr->GetSpellInfo(horde))
+ else if (!sSpellMgr->GetSpellInfo(horde, DIFFICULTY_NONE))
TC_LOG_ERROR("sql.sql", "Spell %u (horde_id) referenced in `player_factionchange_spells` does not exist, pair skipped!", horde);
else
FactionChangeSpells[alliance] = horde;
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 7428cb9994e..3d91ce9afaa 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -21,6 +21,7 @@
#include "DatabaseEnv.h"
#include "Group.h"
#include "Log.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -86,7 +87,7 @@ void WorldSession::HandlePetAction(WorldPackets::Pet::PetAction& packet)
if (!pet->IsAlive())
{
- SpellInfo const* spell = (flag == ACT_ENABLED || flag == ACT_PASSIVE) ? sSpellMgr->GetSpellInfo(spellid) : NULL;
+ SpellInfo const* spell = (flag == ACT_ENABLED || flag == ACT_PASSIVE) ? sSpellMgr->GetSpellInfo(spellid, pet->GetMap()->GetDifficultyID()) : NULL;
if (!spell)
return;
if (!spell->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
@@ -295,14 +296,14 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
unit_target = ObjectAccessor::GetUnit(*_player, guid2);
// do not cast unknown spells
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid, pet->GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("spells.pet", "WORLD: unknown PET spell id %i", spellid);
return;
}
- for (SpellEffectInfo const* effect: spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect: spellInfo->GetEffects())
{
if (effect && (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY))
return;
@@ -484,7 +485,7 @@ void WorldSession::HandlePetSetAction(WorldPackets::Pet::PetSetAction& packet)
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
{
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, pet->GetMap()->GetDifficultyID()))
{
//sign for autocast
if (act_state == ACT_ENABLED)
@@ -615,7 +616,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPackets::Pet::PetSpellAutoc
return;
}
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.SpellID, pet->GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("spells.pet", "WorldSession::HandlePetSpellAutocastOpcode: Unknown spell id %u used by %s.", packet.SpellID, packet.PetGUID.ToString().c_str());
@@ -643,18 +644,18 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPackets::Pet::PetSpellAutoc
void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell& petCastSpell)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petCastSpell.Cast.SpellID);
- if (!spellInfo)
+ Unit* caster = ObjectAccessor::GetUnit(*_player, petCastSpell.PetGUID);
+ if (!caster)
{
- TC_LOG_ERROR("spells.pet", "WorldSession::HandlePetCastSpellOpcode: unknown spell id %i tried to cast by %s",
- petCastSpell.Cast.SpellID, petCastSpell.PetGUID.ToString().c_str());
+ TC_LOG_ERROR("entities.pet", "WorldSession::HandlePetCastSpellOpcode: Caster %s not found.", petCastSpell.PetGUID.ToString().c_str());
return;
}
- Unit* caster = ObjectAccessor::GetUnit(*_player, petCastSpell.PetGUID);
- if (!caster)
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petCastSpell.Cast.SpellID, caster->GetMap()->GetDifficultyID());
+ if (!spellInfo)
{
- TC_LOG_ERROR("entities.pet", "WorldSession::HandlePetCastSpellOpcode: Caster %s not found.", petCastSpell.PetGUID.ToString().c_str());
+ TC_LOG_ERROR("spells.pet", "WorldSession::HandlePetCastSpellOpcode: unknown spell id %i tried to cast by %s",
+ petCastSpell.Cast.SpellID, petCastSpell.PetGUID.ToString().c_str());
return;
}
@@ -706,7 +707,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell&
{
spell->SendPetCastResult(result);
- if (!caster->GetSpellHistory()->HasCooldown(spellInfo->Id))
+ if (!caster->GetSpellHistory()->HasCooldown(spellInfo))
caster->GetSpellHistory()->ResetCooldown(spellInfo->Id, true);
spell->finish(false);
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 7c079d3a40a..db35fca9e07 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -25,6 +25,7 @@
#include "GuildMgr.h"
#include "Item.h"
#include "Log.h"
+#include "Map.h"
#include "Player.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -97,7 +98,7 @@ void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet)
{
for (ItemEffectEntry const* effect : item->GetEffects())
{
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect->SpellID))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect->SpellID, user->GetMap()->GetDifficultyID()))
{
if (!spellInfo->CanBeUsedInCombat())
{
@@ -275,7 +276,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER)
return;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cast.Cast.SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cast.Cast.SpellID, mover->GetMap()->GetDifficultyID());
if (!spellInfo)
{
TC_LOG_ERROR("network", "WORLD: unknown spell id %u", cast.Cast.SpellID);
@@ -350,7 +351,7 @@ void WorldSession::HandleCancelCastOpcode(WorldPackets::Spells::CancelCast& pack
void WorldSession::HandleCancelAuraOpcode(WorldPackets::Spells::CancelAura& cancelAura)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cancelAura.SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cancelAura.SpellID, _player->GetMap()->GetDifficultyID());
if (!spellInfo)
return;
@@ -376,7 +377,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPackets::Spells::CancelAura& canc
_player->RemoveOwnedAura(cancelAura.SpellID, cancelAura.CasterGUID, 0, AURA_REMOVE_BY_CANCEL);
// If spell being removed is a resource tracker, see if player was tracking both (herbs / minerals) and remove the other
- if (sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES) && spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_TRACK_RESOURCES))
+ if (sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES) && spellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES))
{
Unit::AuraEffectList const& auraEffects = _player->GetAuraEffectsByType(SPELL_AURA_TRACK_RESOURCES);
if (!auraEffects.empty())
@@ -397,8 +398,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPackets::Spells::CancelAura& canc
void WorldSession::HandlePetCancelAuraOpcode(WorldPackets::Spells::PetCancelAura& packet)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.SpellID);
- if (!spellInfo)
+ if (sSpellMgr->GetSpellInfo(packet.SpellID, DIFFICULTY_NONE))
{
TC_LOG_ERROR("network", "WORLD: unknown PET spell id %u", packet.SpellID);
return;
@@ -491,7 +491,7 @@ void WorldSession::HandleSelfResOpcode(WorldPackets::Spells::SelfRes& selfRes)
if (std::find(selfResSpells.begin(), selfResSpells.end(), selfRes.SpellID) == selfResSpells.end())
return;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(selfRes.SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(selfRes.SpellID, _player->GetMap()->GetDifficultyID());
if (spellInfo)
_player->CastSpell(_player, spellInfo, false, nullptr);
diff --git a/src/server/game/Handlers/ToyHandler.cpp b/src/server/game/Handlers/ToyHandler.cpp
index 44351ddbacf..42a0408b6e3 100644
--- a/src/server/game/Handlers/ToyHandler.cpp
+++ b/src/server/game/Handlers/ToyHandler.cpp
@@ -69,7 +69,7 @@ void WorldSession::HandleUseToy(WorldPackets::Toy::UseToy& packet)
if (effect == item->Effects.end())
return;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.Cast.SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.Cast.SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("network", "HandleUseToy: unknown spell id: %u used by Toy Item entry %u", packet.Cast.SpellID, itemId);
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 8563528df03..95da9a2f69e 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -22,6 +22,7 @@
#include "Item.h"
#include "Language.h"
#include "Log.h"
+#include "Map.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "SocialMgr.h"
@@ -353,7 +354,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPackets::Trade::AcceptTrade& acc
// not accept if spell can't be cast now (cheating)
if (uint32 my_spell_id = my_trade->GetSpell())
{
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(my_spell_id);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(my_spell_id, _player->GetMap()->GetDifficultyID());
Item* castItem = my_trade->GetSpellCastItem();
if (!spellEntry || !his_trade->GetItem(TRADE_SLOT_NONTRADED) ||
@@ -388,7 +389,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPackets::Trade::AcceptTrade& acc
// not accept if spell can't be cast now (cheating)
if (uint32 his_spell_id = his_trade->GetSpell())
{
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(his_spell_id);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(his_spell_id, trader->GetMap()->GetDifficultyID());
Item* castItem = his_trade->GetSpellCastItem();
if (!spellEntry || !my_trade->GetItem(TRADE_SLOT_NONTRADED) || (his_trade->HasSpellCastItem() && !castItem))
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index b7f20ee3fd0..0ed93f24730 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -1094,9 +1094,9 @@ void LoadLootTemplates_Spell()
uint32 count = LootTemplates_Spell.LoadAndCollectLootIds(lootIdSet);
// remove real entries and check existence loot
- for (uint32 spell_id = 1; spell_id < sSpellMgr->GetSpellInfoStoreSize(); ++spell_id)
+ for (SpellNameEntry const* spellNameEntry : sSpellNameStore)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE);
if (!spellInfo)
continue;
@@ -1104,15 +1104,15 @@ void LoadLootTemplates_Spell()
if (!spellInfo->IsLootCrafting())
continue;
- if (lootIdSet.find(spell_id) == lootIdSet.end())
+ if (lootIdSet.find(spellInfo->Id) == lootIdSet.end())
{
// not report about not trainable spells (optionally supported by DB)
// ignore 61756 (Northrend Inscription Research (FAST QA VERSION) for example
if (!spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT) || (spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL)))
- LootTemplates_Spell.ReportNonExistingId(spell_id, "Spell", spellInfo->Id);
+ LootTemplates_Spell.ReportNonExistingId(spellInfo->Id, "Spell", spellInfo->Id);
}
else
- lootIdSet.erase(spell_id);
+ lootIdSet.erase(spellInfo->Id);
}
// output error for any still listed (not referenced from appropriate table) ids
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index b70f38a8970..b912f51cf9d 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1131,7 +1131,7 @@ ScriptMgr* ScriptMgr::instance()
void ScriptMgr::Initialize()
{
- ASSERT(sSpellMgr->GetSpellInfo(SPELL_HOTSWAP_VISUAL_SPELL_EFFECT)
+ ASSERT(sSpellMgr->GetSpellInfo(SPELL_HOTSWAP_VISUAL_SPELL_EFFECT, DIFFICULTY_NONE)
&& "Reload hotswap spell effect for creatures isn't valid!");
uint32 oldMSTime = getMSTime();
@@ -1228,8 +1228,7 @@ void ScriptMgr::Unload()
{
sScriptRegistryCompositum->Unload();
- delete[] SpellSummary;
- delete[] UnitAI::AISpellInfo;
+ UnitAI::AISpellInfo.clear();
}
void ScriptMgr::LoadDatabase()
@@ -1241,91 +1240,6 @@ void ScriptMgr::LoadDatabase()
void ScriptMgr::FillSpellSummary()
{
UnitAI::FillAISpellInfo();
-
- SpellSummary = new TSpellSummary[sSpellMgr->GetSpellInfoStoreSize()];
-
- SpellInfo const* pTempSpell;
-
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
- {
- SpellSummary[i].Effects = 0;
- SpellSummary[i].Targets = 0;
-
- pTempSpell = sSpellMgr->GetSpellInfo(i);
- // This spell doesn't exist.
- if (!pTempSpell)
- continue;
-
- for (SpellEffectInfo const* effect : pTempSpell->GetEffectsForDifficulty(DIFFICULTY_NONE))
- {
- if (!effect)
- continue;
-
- // Spell targets self.
- if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1);
-
- // Spell targets a single enemy.
- if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
-
- // Spell targets AoE at enemy.
- if (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_SRC_CASTER ||
- effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
-
- // Spell targets an enemy.
- if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY ||
- effect->TargetA.GetTarget() == TARGET_SRC_CASTER ||
- effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
-
- // Spell targets a single friend (or self).
- if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER ||
- effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
-
- // Spell targets AoE friends.
- if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY ||
- effect->TargetA.GetTarget() == TARGET_SRC_CASTER)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
-
- // Spell targets any friend (or self).
- if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER ||
- effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY ||
- effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY ||
- effect->TargetA.GetTarget() == TARGET_SRC_CASTER)
- SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
-
- // Make sure that this spell includes a damage effect.
- if (effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE ||
- effect->Effect == SPELL_EFFECT_INSTAKILL ||
- effect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
- effect->Effect == SPELL_EFFECT_HEALTH_LEECH)
- SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
-
- // Make sure that this spell includes a healing effect (or an apply aura with a periodic heal).
- if (effect->Effect == SPELL_EFFECT_HEAL ||
- effect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH ||
- effect->Effect == SPELL_EFFECT_HEAL_MECHANICAL ||
- (effect->Effect == SPELL_EFFECT_APPLY_AURA && effect->ApplyAuraName == 8))
- SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1);
-
- // Make sure that this spell applies an aura.
- if (effect->Effect == SPELL_EFFECT_APPLY_AURA)
- SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1);
- }
- }
}
template<typename T, typename F, typename O>
diff --git a/src/server/game/Skills/SkillDiscovery.cpp b/src/server/game/Skills/SkillDiscovery.cpp
index 2529060e6b3..1117589d0ab 100644
--- a/src/server/game/Skills/SkillDiscovery.cpp
+++ b/src/server/game/Skills/SkillDiscovery.cpp
@@ -16,6 +16,7 @@
*/
#include "DatabaseEnv.h"
+#include "DB2Stores.h"
#include "Log.h"
#include "World.h"
#include "Util.h"
@@ -84,7 +85,7 @@ void LoadSkillDiscoveryTable()
if (reqSkillOrSpell > 0) // spell case
{
uint32 absReqSkillOrSpell = uint32(reqSkillOrSpell);
- SpellInfo const* reqSpellInfo = sSpellMgr->GetSpellInfo(absReqSkillOrSpell);
+ SpellInfo const* reqSpellInfo = sSpellMgr->GetSpellInfo(absReqSkillOrSpell, DIFFICULTY_NONE);
if (!reqSpellInfo)
{
if (reportedReqSpells.find(absReqSkillOrSpell) == reportedReqSpells.end())
@@ -139,9 +140,9 @@ void LoadSkillDiscoveryTable()
TC_LOG_ERROR("sql.sql", "Some items can't be successfully discovered, their chance field value is < 0.000001 in the `skill_discovery_template` DB table. List:\n%s", ssNonDiscoverableEntries.str().c_str());
// report about empty data for explicit discovery spells
- for (uint32 spell_id = 1; spell_id < sSpellMgr->GetSpellInfoStoreSize(); ++spell_id)
+ for (SpellNameEntry const* spellNameEntry : sSpellNameStore)
{
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE);
if (!spellEntry)
continue;
@@ -149,8 +150,8 @@ void LoadSkillDiscoveryTable()
if (!spellEntry->IsExplicitDiscovery())
continue;
- if (SkillDiscoveryStore.find(int32(spell_id)) == SkillDiscoveryStore.end())
- TC_LOG_ERROR("sql.sql", "Spell (ID: %u) has got 100%% chance random discovery ability, but does not have data in the `skill_discovery_template` table.", spell_id);
+ if (SkillDiscoveryStore.find(int32(spellEntry->Id)) == SkillDiscoveryStore.end())
+ TC_LOG_ERROR("sql.sql", "Spell (ID: %u) has got 100%% chance random discovery ability, but does not have data in the `skill_discovery_template` table.", spellEntry->Id);
}
TC_LOG_INFO("server.loading", ">> Loaded %u skill discovery definitions in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
diff --git a/src/server/game/Skills/SkillExtraItems.cpp b/src/server/game/Skills/SkillExtraItems.cpp
index 2b3ed8da563..8737586a5c3 100644
--- a/src/server/game/Skills/SkillExtraItems.cpp
+++ b/src/server/game/Skills/SkillExtraItems.cpp
@@ -71,14 +71,14 @@ void LoadSkillPerfectItemTable()
uint32 spellId = fields[0].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(spellId))
+ if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Skill perfection data for spell %u has a non-existing spell id in the `skill_perfect_item_template`!", spellId);
continue;
}
uint32 requiredSpecialization = fields[1].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(requiredSpecialization))
+ if (!sSpellMgr->GetSpellInfo(requiredSpecialization, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Skill perfection data for spell %u has a non-existing required specialization spell id %u in the `skill_perfect_item_template`!", spellId, requiredSpecialization);
continue;
@@ -158,14 +158,14 @@ void LoadSkillExtraItemTable()
uint32 spellId = fields[0].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(spellId))
+ if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Skill specialization %u has a non-existing spell id in the `skill_extra_item_template`!", spellId);
continue;
}
uint32 requiredSpecialization = fields[1].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(requiredSpecialization))
+ if (!sSpellMgr->GetSpellInfo(requiredSpecialization, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "Skill specialization %u has a non-existing required specialization spell id %u in the `skill_extra_item_template`!", spellId, requiredSpecialization);
continue;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index ae1c88099bd..aef183d8b97 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -563,7 +563,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
AuraEffect::AuraEffect(Aura* base, uint32 effIndex, int32 *baseAmount, Unit* caster) :
m_base(base), m_spellInfo(base->GetSpellInfo()),
-_effectInfo(base->GetSpellEffectInfo(effIndex)),
+_effectInfo(m_spellInfo->GetEffect(effIndex)),
m_baseAmount(baseAmount ? *baseAmount : _effectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())),
m_damage(0), m_critChance(0.0f), m_donePct(1.0f),
m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex),
@@ -1216,7 +1216,7 @@ bool AuraEffect::CheckEffectProc(AuraApplication* aurApp, ProcEventInfo& eventIn
{
// Don't proc extra attacks while already processing extra attack spell
uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell;
- if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId))
+ if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty()))
if (aurApp->GetTarget()->m_extraAttacks && triggeredSpellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
return false;
break;
@@ -1359,7 +1359,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (itr->first == spellId || itr->first == spellId2 || itr->first == spellId3 || itr->first == spellId4)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first, DIFFICULTY_NONE);
if (!spellInfo || !(spellInfo->IsPassive() || spellInfo->HasAttribute(SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
@@ -1735,7 +1735,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (modelid > 0)
{
- SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm());
+ SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm(), GetBase()->GetCastDifficulty());
if (!transformSpellInfo || !GetSpellInfo()->IsPositive())
target->SetDisplayId(modelid);
}
@@ -1828,7 +1828,7 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
if (apply)
{
// update active transform spell only when transform not set or not overwriting negative by positive case
- SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm());
+ SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm(), GetBase()->GetCastDifficulty());
if (!transformSpellInfo || !GetSpellInfo()->IsPositive() || transformSpellInfo->IsPositive())
{
target->setTransForm(GetId());
@@ -2550,7 +2550,7 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
}
//some spell has one aura of mount and one of vehicle
- for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
if (effect && effect->Effect == SPELL_EFFECT_SUMMON && effect->MiscValue == GetMiscValue())
displayId = 0;
}
@@ -4688,10 +4688,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
uint32 spellId = 24659;
if (apply && caster)
{
- SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId);
+ SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId, GetBase()->GetCastDifficulty());
for (uint32 i = 0; i < spell->StackAmount; ++i)
- caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
+ caster->CastSpell(target, spell, true, NULL, NULL, GetCasterGUID());
break;
}
target->RemoveAurasDueToSpell(spellId);
@@ -4703,9 +4703,9 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
uint32 spellId = 24662;
if (apply && caster)
{
- SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId);
+ SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId, GetBase()->GetCastDifficulty());
for (uint32 i = 0; i < spell->StackAmount; ++i)
- caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
+ caster->CastSpell(target, spell, true, NULL, NULL, GetCasterGUID());
break;
}
target->RemoveAurasDueToSpell(spellId);
@@ -4964,11 +4964,11 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo
Unit* target = aurApp->GetTarget();
uint32 triggeredSpellId = GetSpellEffectInfo()->TriggerSpell;
- SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId);
+ SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId, GetBase()->GetCastDifficulty());
if (!triggeredSpellInfo)
return;
- Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficultyID()) ? GetCaster() : target;
+ Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCaster() : target;
if (!caster)
return;
@@ -4984,13 +4984,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo
}
else
{
- ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficultyID()) ? GetCasterGUID() : target->GetGUID();
+ ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID();
target->RemoveAura(triggeredSpellId, casterGUID, 0, aurApp->GetRemoveMode());
}
}
else if (mode & AURA_EFFECT_HANDLE_REAPPLY && apply)
{
- ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficultyID()) ? GetCasterGUID() : target->GetGUID();
+ ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID();
// change the stack amount to be equal to stack amount of our aura
if (Aura* triggeredAura = target->GetAura(triggeredSpellId, casterGUID))
triggeredAura->ModStackAmount(GetBase()->GetStackAmount() - triggeredAura->GetStackAmount());
@@ -5259,7 +5259,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
// generic casting code with custom spells and target/caster customs
uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell;
- SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId);
+ SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty());
SpellInfo const* auraSpellInfo = GetSpellInfo();
uint32 auraId = auraSpellInfo->Id;
@@ -5519,11 +5519,11 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
}
// Reget trigger spell proto
- triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId);
+ triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty());
if (triggeredSpellInfo)
{
- if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficultyID()) ? caster : target)
+ if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target)
{
triggerCaster->CastSpell(target, triggeredSpellInfo, true, NULL, this);
TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id);
@@ -5536,9 +5536,9 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const
{
uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell;
- if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId))
+ if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty()))
{
- if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficultyID()) ? caster : target)
+ if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target)
{
int32 basepoints = GetAmount();
triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, nullptr, this);
@@ -5580,7 +5580,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
break;
case 38772: // Grievous Wound
{
- if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_1))
+ if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(EFFECT_1))
{
uint32 percent = effect->CalcValue(caster);
if (!target->HealthBelowPct(percent))
@@ -5779,7 +5779,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
// SendSpellNonMeleeDamageLog expects non-absorbed/non-resisted damage
- SpellNonMeleeDamage log(caster, target, GetId(), GetBase()->GetSpellXSpellVisualId(), GetSpellInfo()->GetSchoolMask(), GetBase()->GetCastGUID());
+ SpellNonMeleeDamage log(caster, target, GetSpellInfo(), GetBase()->GetSpellXSpellVisualId(), GetSpellInfo()->GetSchoolMask(), GetBase()->GetCastGUID());
log.damage = damage;
log.originalDamage = dmg;
log.absorb = absorb;
@@ -6090,7 +6090,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
SpellInfo const* spellProto = GetSpellInfo();
// maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
- SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, GetBase()->GetSpellXSpellVisualId(), spellProto->SchoolMask, GetBase()->GetCastGUID());
+ SpellNonMeleeDamage damageInfo(caster, target, spellProto, GetBase()->GetSpellXSpellVisualId(), spellProto->SchoolMask, GetBase()->GetCastGUID());
// no SpellDamageBonus for burn mana
caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);
@@ -6131,7 +6131,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve
Unit* triggerTarget = eventInfo.GetProcTarget();
uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell;
- if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId))
+ if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty()))
{
TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell %u from aura %u proc", triggeredSpellInfo->Id, GetId());
triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, NULL, this);
@@ -6146,7 +6146,7 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp
Unit* triggerTarget = eventInfo.GetProcTarget();
uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell;
- if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId))
+ if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty()))
{
int32 basepoints0 = GetAmount();
TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellWithValueAuraProc: Triggering spell %u with value %d from aura %u proc", triggeredSpellInfo->Id, basepoints0, GetId());
@@ -6166,7 +6166,7 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv
return;
}
- SpellNonMeleeDamage damageInfo(target, triggerTarget, GetId(), GetBase()->GetSpellXSpellVisualId(), GetSpellInfo()->SchoolMask, GetBase()->GetCastGUID());
+ SpellNonMeleeDamage damageInfo(target, triggerTarget, GetSpellInfo(), GetBase()->GetSpellXSpellVisualId(), GetSpellInfo()->SchoolMask, GetBase()->GetCastGUID());
uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE, GetSpellEffectInfo());
damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE, GetSpellEffectInfo());
target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo());
@@ -6327,7 +6327,7 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b
return;
Unit* target = aurApp->GetTarget();
- SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(GetSpellEffectInfo()->TriggerSpell);
+ SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(GetSpellEffectInfo()->TriggerSpell, GetBase()->GetCastDifficulty());
if (!triggerSpellInfo)
return;
@@ -6338,7 +6338,7 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b
else
{
std::vector<uint32> summonedEntries;
- for (auto spellEffect : triggerSpellInfo->GetEffectsForDifficulty(target->FindMap()->GetDifficultyID()))
+ for (auto spellEffect : triggerSpellInfo->GetEffects())
if (spellEffect && spellEffect->Effect == SPELL_EFFECT_SUMMON)
if (uint32 summonEntry = spellEffect->MiscValue)
summonedEntries.push_back(summonEntry);
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 54f520b5e85..bc43ee19e9b 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -89,7 +89,7 @@ void AuraApplication::_InitFlags(Unit* caster, uint32 effMask)
if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget()))
{
bool negativeFound = false;
- for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetBase()->GetSpellInfo()->GetEffects())
{
if (effect && ((1 << effect->EffectIndex) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex))
{
@@ -104,7 +104,7 @@ void AuraApplication::_InitFlags(Unit* caster, uint32 effMask)
else
{
bool positiveFound = false;
- for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetBase()->GetSpellInfo()->GetEffects())
{
if (effect && ((1 << effect->EffectIndex) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex))
{
@@ -234,14 +234,14 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availab
{
case TYPEID_UNIT:
case TYPEID_PLAYER:
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellProto->GetEffects())
{
if (effect && effect->IsUnitOwnedAuraEffect())
effMask |= 1 << effect->EffectIndex;
}
break;
case TYPEID_DYNAMICOBJECT:
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellProto->GetEffects())
{
if (effect && effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA)
effMask |= 1 << effect->EffectIndex;
@@ -255,7 +255,7 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availab
return effMask & availableEffectMask;
}
-Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= nullptr*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
+Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= nullptr*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
{
ASSERT(spellproto);
ASSERT(owner);
@@ -281,10 +281,10 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid cast
return foundAura;
}
else
- return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ return Create(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
}
-Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
+Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
{
ASSERT(spellproto);
ASSERT(owner);
@@ -294,10 +294,10 @@ Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 try
if (!effMask)
return nullptr;
- return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ return Create(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
}
-Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
+Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
{
ASSERT(effMask);
ASSERT(spellproto);
@@ -327,10 +327,10 @@ Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMas
{
case TYPEID_UNIT:
case TYPEID_PLAYER:
- aura = new UnitAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ aura = new UnitAura(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
break;
case TYPEID_DYNAMICOBJECT:
- aura = new DynObjAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ aura = new DynObjAura(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
break;
default:
ABORT();
@@ -343,8 +343,9 @@ Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMas
return aura;
}
-Aura::Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) :
-m_spellInfo(spellproto), m_castGuid(castId), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()),
+Aura::Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Difficulty castDifficulty,
+ Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) :
+m_spellInfo(spellproto), m_castDifficulty(castDifficulty), m_castGuid(castId), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()),
m_castItemGuid(castItem ? castItem->GetGUID() : castItemGuid), m_castItemId(castItem ? castItem->GetEntry() : castItemId),
m_castItemLevel(castItemLevel), m_spellXSpellVisualId(caster ? caster->GetCastSpellXSpellVisualId(spellproto) : spellproto->GetSpellXSpellVisualId()),
m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),
@@ -353,9 +354,8 @@ m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEven
m_procCooldown(std::chrono::steady_clock::time_point::min()),
m_lastProcAttemptTime(std::chrono::steady_clock::now() - Seconds(10)), m_lastProcSuccessTime(std::chrono::steady_clock::now() - Seconds(120))
{
- std::vector<SpellPowerEntry const*> powers = sDB2Manager.GetSpellPowers(GetId(), caster ? caster->GetMap()->GetDifficultyID() : DIFFICULTY_NONE);
- for (SpellPowerEntry const* power : powers)
- if (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f)
+ for (SpellPowerEntry const* power : m_spellInfo->PowerCosts)
+ if (power && (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f))
m_periodicCosts.push_back(power);
if (!m_periodicCosts.empty())
@@ -376,24 +376,12 @@ AuraScript* Aura::GetScriptByName(std::string const& scriptName) const
return nullptr;
}
-SpellEffectInfo const* Aura::GetSpellEffectInfo(uint32 index) const
-{
- if (index >= _spelEffectInfos.size())
- return nullptr;
-
- return _spelEffectInfos[index];
-}
-
void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount)
{
// shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism
- _spelEffectInfos = m_spellInfo->GetEffectsForDifficulty(GetOwner()->GetMap()->GetDifficultyID());
-
- ASSERT(!_spelEffectInfos.empty());
-
- _effects.resize(GetSpellEffectInfos().size());
+ _effects.resize(GetSpellInfo()->GetEffects().size());
- for (SpellEffectInfo const* effect : GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
{
if (effect && effMask & (1 << effect->EffectIndex))
_effects[effect->EffectIndex] = new AuraEffect(this, effect->EffectIndex, baseAmount ? baseAmount + effect->EffectIndex : NULL, caster);
@@ -855,7 +843,7 @@ void Aura::SetCharges(uint8 charges)
uint8 Aura::CalcMaxCharges(Unit* caster) const
{
uint32 maxProcCharges = m_spellInfo->ProcCharges;
- if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId()))
+ if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo()))
maxProcCharges = procEntry->Charges;
if (caster)
@@ -976,7 +964,7 @@ bool Aura::ModStackAmount(int32 num, AuraRemoveMode removeMode /*= AURA_REMOVE_B
bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const
{
uint32 count = 0;
- for (SpellEffectInfo const* effect : GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
if (effect && HasEffect(effect->EffectIndex) && AuraType(effect->ApplyAuraName) == auraType)
++count;
@@ -985,7 +973,7 @@ bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const
bool Aura::IsArea() const
{
- for (SpellEffectInfo const* effect : GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
if (effect && HasEffect(effect->EffectIndex) && effect->IsAreaAuraEffect())
return true;
@@ -1358,7 +1346,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
// check cooldown
if (caster->GetTypeId() == TYPEID_PLAYER)
{
- if (caster->GetSpellHistory()->HasCooldown(aura->GetId()))
+ if (caster->GetSpellHistory()->HasCooldown(aura->GetSpellInfo()))
{
// This additional check is needed to add a minimal delay before cooldown in in effect
// to allow all bubbles broken by a single damage source proc mana return
@@ -1515,14 +1503,14 @@ bool Aura::CanStackWith(Aura const* existingAura) const
if (IsPassive() && sameCaster && (m_spellInfo->IsDifferentRankOf(existingSpellInfo) || (m_spellInfo->Id == existingSpellInfo->Id && m_castItemGuid.IsEmpty())))
return false;
- for (SpellEffectInfo const* effect : existingAura->GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : existingSpellInfo->GetEffects())
{
// prevent remove triggering aura by triggered aura
if (effect && effect->TriggerSpell == GetId())
return true;
}
- for (SpellEffectInfo const* effect : GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
{
// prevent remove triggered aura by triggering aura refresh
if (effect && effect->TriggerSpell == existingAura->GetId())
@@ -1535,7 +1523,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const
// * The minimap tracking list will only show a check mark next to the last skill activated
// Sometimes this bugs out and doesn't switch the check mark. It has no effect on the actual tracking though.
// * The minimap dots are yellow for both resources
- if (m_spellInfo->HasAura(GetOwner()->GetMap()->GetDifficultyID(), SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(GetOwner()->GetMap()->GetDifficultyID(), SPELL_AURA_TRACK_RESOURCES))
+ if (m_spellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES))
return sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES);
// check spell specific stack rules
@@ -1574,7 +1562,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const
// check same periodic auras
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- SpellEffectInfo const* effect = GetSpellEffectInfo(i);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(i);
if (!effect)
continue;
switch (effect->ApplyAuraName)
@@ -1592,7 +1580,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const
case SPELL_AURA_OBS_MOD_HEALTH:
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
{
- SpellEffectInfo const* existingEffect = GetSpellEffectInfo(i);
+ SpellEffectInfo const* existingEffect = m_spellInfo->GetEffect(i);
// periodic auras which target areas are not allowed to stack this way (replenishment for example)
if (effect->IsTargetingArea() || (existingEffect && existingEffect->IsTargetingArea()))
break;
@@ -1662,7 +1650,7 @@ void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInf
SetNeedClientUpdateForTargets();
}
- SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId());
+ SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo());
ASSERT(procEntry);
// cooldowns should be added to the whole aura (see 51698 area aura)
@@ -1673,7 +1661,7 @@ void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInf
uint32 Aura::GetProcEffectMask(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const
{
- SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId());
+ SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo());
// only auras with spell proc entry can trigger proc
if (!procEntry)
return 0;
@@ -1692,7 +1680,7 @@ uint32 Aura::GetProcEffectMask(AuraApplication* aurApp, ProcEventInfo& eventInfo
}
// check don't break stealth attr present
- if (m_spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_MOD_STEALTH))
+ if (m_spellInfo->HasAura(SPELL_AURA_MOD_STEALTH))
{
if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
@@ -2253,8 +2241,9 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli
}
}
-UnitAura::UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
- : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
+UnitAura::UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty,
+ int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
+ : Aura(spellproto, castId, owner, caster, castDifficulty, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
{
m_AuraDRGroup = DIMINISHING_NONE;
LoadScripts();
@@ -2289,7 +2278,7 @@ void UnitAura::Remove(AuraRemoveMode removeMode)
void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* caster)
{
- for (SpellEffectInfo const* effect : GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
{
if (!effect || !HasEffect(effect->EffectIndex))
continue;
@@ -2357,8 +2346,9 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c
}
}
-DynObjAura::DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
- : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
+DynObjAura::DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty,
+ int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
+ : Aura(spellproto, castId, owner, caster, castDifficulty, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
{
LoadScripts();
ASSERT(GetDynobjOwner());
@@ -2387,7 +2377,7 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit*
Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster();
float radius = GetDynobjOwner()->GetRadius();
- for (SpellEffectInfo const* effect : GetSpellEffectInfos())
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
{
if (!effect || !HasEffect(effect->EffectIndex))
continue;
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 2d8bdb477a1..5b5e0001aa8 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -119,15 +119,16 @@ class TC_GAME_API Aura
typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap;
static uint32 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availableEffectMask, WorldObject* owner);
- static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = nullptr, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
- static Aura* TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
- static Aura* Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
- Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = nullptr, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
+ static Aura* TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
+ static Aura* Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Difficulty castDifficulty, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
void _InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount);
virtual ~Aura();
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
uint32 GetId() const{ return GetSpellInfo()->Id; }
+ Difficulty GetCastDifficulty() const { return m_castDifficulty; }
ObjectGuid GetCastGUID() const { return m_castGuid; }
ObjectGuid GetCasterGUID() const { return m_casterGuid; }
@@ -288,10 +289,7 @@ class TC_GAME_API Aura
std::vector<AuraScript*> m_loadedScripts;
- AuraEffectVector GetAuraEffects() const { return _effects; }
-
- SpellEffectInfoVector GetSpellEffectInfos() const { return _spelEffectInfos; }
- SpellEffectInfo const* GetSpellEffectInfo(uint32 index) const;
+ AuraEffectVector const& GetAuraEffects() const { return _effects; }
private:
AuraScript* GetScriptByName(std::string const& scriptName) const;
@@ -299,6 +297,7 @@ class TC_GAME_API Aura
protected:
SpellInfo const* const m_spellInfo;
+ Difficulty const m_castDifficulty;
ObjectGuid const m_castGuid;
ObjectGuid const m_casterGuid;
ObjectGuid const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
@@ -334,14 +333,13 @@ class TC_GAME_API Aura
Unit::AuraApplicationList m_removedApplications;
AuraEffectVector _effects;
- SpellEffectInfoVector _spelEffectInfos;
};
class TC_GAME_API UnitAura : public Aura
{
- friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
public:
- UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override;
void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override;
@@ -360,9 +358,9 @@ class TC_GAME_API UnitAura : public Aura
class TC_GAME_API DynObjAura : public Aura
{
- friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
public:
- DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index ada40659922..f9c6b64e7f3 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -492,13 +492,10 @@ void SpellCastTargets::OutDebug() const
TC_LOG_DEBUG("spells", "pitch: %f", m_pitch);
}
-SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* caster)
+SpellValue::SpellValue(SpellInfo const* proto, Unit const* caster)
{
- // todo 6.x
- SpellEffectInfoVector effects = proto->GetEffectsForDifficulty(diff);
- ASSERT(effects.size() <= MAX_SPELL_EFFECTS);
memset(EffectBasePoints, 0, sizeof(EffectBasePoints));
- for (SpellEffectInfo const* effect : effects)
+ for (SpellEffectInfo const* effect : proto->GetEffects())
if (effect)
EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, 0, -1);
@@ -523,10 +520,8 @@ protected:
Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) :
m_spellInfo(info), m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster),
-m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo, caster)), _spellEvent(nullptr)
+m_spellValue(new SpellValue(m_spellInfo, caster)), _spellEvent(nullptr)
{
- _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID());
-
m_customError = SPELL_CUSTOM_ERROR_NONE;
m_skipCheck = skipCheck;
m_fromClient = false;
@@ -751,7 +746,7 @@ void Spell::SelectSpellTargets()
uint32 processedAreaEffectsMask = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -846,10 +841,10 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar
// targets for effect already selected
if (effectMask & processedEffectMask)
return;
- if (SpellEffectInfo const* _effect = GetEffect(effIndex))
+ if (SpellEffectInfo const* _effect = m_spellInfo->GetEffect(effIndex))
{
// choose which targets we can select at once
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
//for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
if (!effect || effect->EffectIndex <= uint32(effIndex))
@@ -1020,7 +1015,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
return;
}
- SpellEffectInfo const* effect = GetEffect(effIndex);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex);
if (!effect)
return;
@@ -1155,7 +1150,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
std::list<WorldObject*> targets;
SpellTargetObjectTypes objectType = targetType.GetObjectType();
SpellTargetCheckTypes selectionType = targetType.GetCheckType();
- SpellEffectInfo const* effect = GetEffect(effIndex);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex);
if (!effect)
return;
@@ -1241,7 +1236,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
}
std::list<WorldObject*> targets;
- SpellEffectInfo const* effect = GetEffect(effIndex);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex);
if (!effect)
return;
float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod;
@@ -1286,7 +1281,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex))
{
/// @todo fix this check
- if (HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || HasEffect(SPELL_EFFECT_BIND))
+ if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND))
dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
else if (st->target_mapId == m_caster->GetMapId())
dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
@@ -1334,7 +1329,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
}
default:
{
- if (SpellEffectInfo const* effect = GetEffect(effIndex))
+ if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex))
{
float dist = effect->CalcRadius(m_caster);
float angle = targetType.CalcDirectionAngle();
@@ -1393,7 +1388,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici
break;
default:
{
- if (SpellEffectInfo const* effect = GetEffect(effIndex))
+ if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex))
{
float angle = targetType.CalcDirectionAngle();
float objSize = target->GetCombatReach();
@@ -1435,7 +1430,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT
return;
default:
{
- if (SpellEffectInfo const* effect = GetEffect(effIndex))
+ if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex))
{
float angle = targetType.CalcDirectionAngle();
float dist = effect->CalcRadius(m_caster);
@@ -1527,7 +1522,7 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImpli
void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask)
{
- SpellEffectInfo const* effect = GetEffect(effIndex);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex);
if (!effect)
return;
@@ -1538,7 +1533,7 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg
if (maxTargets > 1)
{
// mark damage multipliers as used
- for (SpellEffectInfo const* eff : GetEffects())
+ for (SpellEffectInfo const* eff : m_spellInfo->GetEffects())
if (eff && (effMask & (1 << eff->EffectIndex)))
m_damageMultipliers[eff->EffectIndex] = 1.0f;
m_applyMultiplierMask |= effMask;
@@ -1599,7 +1594,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge
// We should check if triggered spell has greater range (which is true in many cases, and initial spell has too short max range)
// limit max range to 300 yards, sometimes triggered spells can have 50000yds
float bestDist = m_spellInfo->GetMaxRange(false);
- if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(effect->TriggerSpell))
+ if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(effect->TriggerSpell, GetCastDifficulty()))
bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(false)), std::min(dist2d, 300.0f));
std::list<WorldObject*>::const_iterator itr = targets.begin();
@@ -1658,7 +1653,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex)
{
// special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER
/// @todo this is a workaround - target shouldn't be stored in target map for those spells
- SpellEffectInfo const* effect = GetEffect(effIndex);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex);
if (!effect)
return;
switch (effect->Effect)
@@ -2035,7 +2030,7 @@ class ProcReflectDelayed : public BasicEvent
void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/, Position const* losPosition /*= nullptr*/)
{
uint32 validEffectMask = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(target, effect, losPosition))
validEffectMask |= 1 << effect->EffectIndex;
@@ -2050,7 +2045,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
return;
// Check for effect immune skip if immuned
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && target->IsImmunedToSpellEffect(m_spellInfo, effect->EffectIndex, m_caster))
effectMask &= ~(1 << effect->EffectIndex);
@@ -2133,7 +2128,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
void Spell::AddGOTarget(GameObject* go, uint32 effectMask)
{
uint32 validEffectMask = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(go, effect))
validEffectMask |= 1 << effect->EffectIndex;
@@ -2191,7 +2186,7 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask)
void Spell::AddItemTarget(Item* item, uint32 effectMask)
{
uint32 validEffectMask = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(item, effect))
validEffectMask |= 1 << effect->EffectIndex;
@@ -2240,7 +2235,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
{
uint32 farMask = 0;
// create far target mask
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && effect->IsFarUnitTargetEffect())
if ((1 << effect->EffectIndex) & mask)
farMask |= (1 << effect->EffectIndex);
@@ -2255,7 +2250,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// do far effects on the unit
// can't use default call because of threading, do stuff as fast as possible
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (farMask & (1 << effect->EffectIndex)))
HandleEffects(unit, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET);
return;
@@ -2415,7 +2410,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else if (m_damage > 0)
{
// Fill base damage struct (unitTarget - is real spell target)
- SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_SpellVisual, m_spellSchoolMask, m_castId);
+ SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo, m_SpellVisual, m_spellSchoolMask, m_castId);
// Check damage immunity
if (unitTarget->IsImmunedToDamage(m_spellInfo))
@@ -2457,7 +2452,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else
{
// Fill base damage struct (unitTarget - is real spell target)
- SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_SpellVisual, m_spellSchoolMask);
+ SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo, m_SpellVisual, m_spellSchoolMask);
hitMask |= createProcHitMask(&damageInfo, missInfo);
// Do triggers for unit
if (canEffectTrigger)
@@ -2526,7 +2521,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
// disable effects to which unit is immune
SpellMissInfo returnVal = SPELL_MISS_IMMUNE;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)))
if (unit->IsImmunedToSpellEffect(m_spellInfo, effect->EffectIndex, m_caster))
effectMask &= ~(1 << effect->EffectIndex);
@@ -2579,7 +2574,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
}
uint32 aura_effmask = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex) && effect->IsUnitOwnedAuraEffect()))
aura_effmask |= 1 << effect->EffectIndex;
@@ -2603,7 +2598,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
if (m_originalCaster)
{
int32 basePoints[MAX_SPELL_EFFECTS];
- for (SpellEffectInfo const* auraSpellEffect : GetEffects())
+ for (SpellEffectInfo const* auraSpellEffect : m_spellInfo->GetEffects())
if (auraSpellEffect)
basePoints[auraSpellEffect->EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect->EffectIndex)) ?
m_spellValue->EffectBasePoints[auraSpellEffect->EffectIndex] :
@@ -2612,7 +2607,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
bool refresh = false;
bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER);
m_spellAura = Aura::TryRefreshStackOrCreate(m_spellInfo, m_castId, effectMask, unit,
- m_originalCaster, basePoints,
+ m_originalCaster, GetCastDifficulty(), basePoints,
m_CastItem, ObjectGuid::Empty, &refresh, resetPeriodicTimer, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel);
if (m_spellAura)
{
@@ -2647,7 +2642,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
{
m_spellAura->Remove();
bool found = false;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex) && effect->Effect != SPELL_EFFECT_APPLY_AURA))
found = true;
if (!found)
@@ -2668,7 +2663,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
{
int32 origDuration = duration;
duration = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect)
if (AuraEffect const* eff = m_spellAura->GetEffect(effect->EffectIndex))
if (int32 period = eff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED
@@ -2691,7 +2686,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
}
}
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)))
HandleEffects(unit, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET);
@@ -2764,7 +2759,7 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo* target)
PrepareScriptHitHandlers();
CallScriptBeforeHitHandlers(SPELL_MISS_NONE);
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)))
HandleEffects(NULL, NULL, go, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET);
@@ -2784,7 +2779,7 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo* target)
PrepareScriptHitHandlers();
CallScriptBeforeHitHandlers(SPELL_MISS_NONE);
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex)))
HandleEffects(NULL, target->item, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET);
@@ -2801,7 +2796,7 @@ bool Spell::UpdateChanneledTargetList()
uint32 channelTargetEffectMask = m_channelTargetEffectMask;
uint32 channelAuraMask = 0;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA)
channelAuraMask |= 1 << effect->EffectIndex;
@@ -2998,7 +2993,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) && m_spellInfo->IsBreakingStealth())
{
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST);
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && effect->GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT)
{
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK);
@@ -3493,7 +3488,7 @@ void Spell::_handle_immediate_phase()
PrepareScriptHitHandlers();
// handle effects with SPELL_EFFECT_HANDLE_HIT mode
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
// don't do anything for empty effect
if (!effect || !effect->IsEffect())
@@ -3521,7 +3516,7 @@ void Spell::_handle_finish_phase()
m_caster->m_playerMovingMe->GainSpellComboPoints(m_comboPointGain);
}
- if (m_caster->m_extraAttacks && HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
+ if (m_caster->m_extraAttacks && m_spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
{
if (Unit* victim = ObjectAccessor::GetUnit(*m_caster, m_targets.GetOrigUnitTargetGUID()))
m_caster->HandleProcExtraAttackFor(victim);
@@ -3572,7 +3567,7 @@ void Spell::update(uint32 difftime)
// check if the player caster has moved before the spell finished
// with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect
- SpellEffectInfo const* effect = GetEffect(EFFECT_0);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0);
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
((effect && effect->Effect != SPELL_EFFECT_STUCK) || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) &&
@@ -3678,7 +3673,7 @@ void Spell::finish(bool ok)
{
// Unsummon statue
uint32 spell = m_caster->m_unitData->CreatedBySpell;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell, GetCastDifficulty());
if (spellInfo && spellInfo->IconFileDataId == 134230)
{
TC_LOG_DEBUG("spells", "Statue %s is unsummoned in spell %d finish", m_caster->GetGUID().ToString().c_str(), m_spellInfo->Id);
@@ -3818,7 +3813,7 @@ inline void FillSpellCastFailedArgs(T& packet, ObjectGuid castId, SpellInfo cons
else
{
uint32 item = 0;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
if (effect->ItemType)
item = effect->ItemType;
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item);
@@ -4114,7 +4109,7 @@ void Spell::SendSpellGo()
castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list
}
- if (HasEffect(SPELL_EFFECT_ACTIVATE_RUNE))
+ if (m_spellInfo->HasEffect(SPELL_EFFECT_ACTIVATE_RUNE))
castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list
if (m_targets.HasTraj())
@@ -4290,7 +4285,7 @@ void Spell::SendSpellExecuteLog()
spellExecuteLog.Caster = m_caster->GetGUID();
spellExecuteLog.SpellID = m_spellInfo->Id;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -4803,7 +4798,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT
gameObjTarget = pGOTarget;
destTarget = &m_destTargets[i]._position;
- effectInfo = GetEffect(i);
+ effectInfo = m_spellInfo->GetEffect(i);
if (!effectInfo)
{
TC_LOG_ERROR("spells", "Spell: %u HandleEffects at EffectIndex: %u missing effect", m_spellInfo->Id, i);
@@ -4950,7 +4945,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving() && (!m_caster->IsCharmed() || !m_caster->GetCharmerGUID().IsCreature()) && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
// skip stuck spell to allow use it in falling case and apply spell limitations at movement
- SpellEffectInfo const* effect = GetEffect(EFFECT_0);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0);
if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || (effect && effect->Effect != SPELL_EFFECT_STUCK)) &&
(IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED)))
return SPELL_FAILED_MOVING;
@@ -5051,7 +5046,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
}
// check pet presence
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_PET)
{
@@ -5144,7 +5139,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (castResult != SPELL_CAST_OK)
return castResult;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -5181,7 +5176,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (!pet)
return SPELL_FAILED_NO_PET;
- SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell);
+ SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE);
if (!learn_spellproto)
return SPELL_FAILED_NOT_KNOWN;
@@ -5212,7 +5207,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (!pet || pet->GetOwner() != m_caster)
return SPELL_FAILED_BAD_TARGETS;
- SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell);
+ SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE);
if (!learn_spellproto)
return SPELL_FAILED_NOT_KNOWN;
@@ -5645,7 +5640,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
}
}
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -5704,7 +5699,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
}
case SPELL_AURA_MOUNTED:
{
- if (m_caster->IsInWater() && m_spellInfo->HasAura(m_caster->GetMap()->GetDifficultyID(), SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
+ if (m_caster->IsInWater() && m_spellInfo->HasAura(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
return SPELL_FAILED_ONLY_ABOVEWATER;
// Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells
@@ -6069,7 +6064,7 @@ bool Spell::CanAutoCast(Unit* target)
ObjectGuid targetguid = target->GetGUID();
// check if target already has the same or a more powerful aura
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -6300,7 +6295,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 /
{
// such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example
SpellCastResult failReason = SPELL_CAST_OK;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
// skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.GetUnitTarget() is not the real target but the caster
if (!effect || effect->TargetA.GetTarget() == TARGET_UNIT_PET)
@@ -6456,7 +6451,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 /
}
// special checks for spell effects
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -6491,7 +6486,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 /
player->SendEquipError(msg, nullptr, nullptr, effect->ItemType);
return SPELL_FAILED_DONT_REPORT;
}
- else if (SpellEffectInfo const* efi = GetEffect(EFFECT_1))
+ else if (SpellEffectInfo const* efi = m_spellInfo->GetEffect(EFFECT_1))
player->CastSpell(m_caster, efi->CalcValue(), false); // move this to anywhere
return SPELL_FAILED_DONT_REPORT;
}
@@ -6925,7 +6920,7 @@ bool Spell::UpdatePointers()
WorldObject* transport = NULL;
// update effect destinations (in case of moved transport dest target)
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -6959,6 +6954,11 @@ CurrentSpellTypes Spell::GetCurrentContainer() const
return CURRENT_GENERIC_SPELL;
}
+Difficulty Spell::GetCastDifficulty() const
+{
+ return m_caster->GetMap()->GetDifficultyID();
+}
+
bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, Position const* losPosition) const
{
if (!effect->IsEffect())
@@ -7265,7 +7265,7 @@ bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const
void Spell::HandleLaunchPhase()
{
// handle effects with SPELL_EFFECT_HANDLE_LAUNCH mode
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
// don't do anything for empty effect
if (!effect || !effect->IsEffect())
@@ -7275,7 +7275,7 @@ void Spell::HandleLaunchPhase()
}
float multiplier[MAX_SPELL_EFFECTS];
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (m_applyMultiplierMask & (1 << effect->EffectIndex)))
multiplier[effect->EffectIndex] = effect->CalcDamageMultiplier(m_originalCaster, this);
@@ -7307,7 +7307,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
if (!unit)
return;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (effect && (targetInfo.effectMask & (1<<effect->EffectIndex)))
{
@@ -7356,7 +7356,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk
if (!lockInfo)
return SPELL_FAILED_BAD_TARGETS;
- SpellEffectInfo const* effect = GetEffect(effIndex);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex);
if (!effect)
return SPELL_FAILED_BAD_TARGETS; // no idea about correct error
@@ -7691,7 +7691,7 @@ bool Spell::CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredBy
{
bool only_on_caster = (triggeredByAura && (triggeredByAura->HasAttribute(SPELL_ATTR4_PROC_ONLY_ON_CASTER)));
// If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (effect && ((effMask & (1 << effect->EffectIndex)) && (!only_on_caster || (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER))))
return true;
@@ -7710,7 +7710,7 @@ void Spell::PrepareTriggersExecutedOnHit()
if (!aurEff->IsAffectingSpell(m_spellInfo))
continue;
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo()->TriggerSpell))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo()->TriggerSpell, GetCastDifficulty()))
{
// calculate the chance using spell base amount, because aura amount is not updated on combo-points change
// this possibly needs fixing
@@ -7802,16 +7802,6 @@ void Spell::CancelGlobalCooldown()
m_caster->GetSpellHistory()->CancelGlobalCooldown(m_spellInfo);
}
-bool Spell::HasEffect(SpellEffectName effect) const
-{
- for (SpellEffectInfo const* eff : GetEffects())
- {
- if (eff && eff->IsEffect(effect))
- return true;
- }
- return false;
-}
-
namespace Trinity
{
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index b8b72b5dcfc..e4ed1464a9f 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -297,7 +297,7 @@ class TC_GAME_API SpellCastTargets
struct SpellValue
{
- explicit SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* caster);
+ explicit SpellValue(SpellInfo const* proto, Unit const* caster);
int32 EffectBasePoints[MAX_SPELL_EFFECTS];
uint32 CustomBasePointsMask;
uint32 MaxAffectedTargets;
@@ -677,6 +677,7 @@ class TC_GAME_API Spell
Unit* GetCaster() const { return m_caster; }
Unit* GetOriginalCaster() const { return m_originalCaster; }
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
+ Difficulty GetCastDifficulty() const;
std::vector<SpellPowerCost> const& GetPowerCost() const { return m_powerCost; }
bool UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
@@ -685,17 +686,6 @@ class TC_GAME_API Spell
void SetSpellValue(SpellValueMod mod, int32 value);
- std::vector<SpellEffectInfo const*> const& GetEffects() const { return _effects; }
- SpellEffectInfo const* GetEffect(uint32 index) const
- {
- if (index >= _effects.size())
- return nullptr;
-
- return _effects[index];
- }
-
- bool HasEffect(SpellEffectName effect) const;
-
Spell** m_selfContainer; // pointer to our spell container (if applicable)
SpellInfo const* GetTriggeredByAuraSpell() const { return m_triggeredByAuraSpell; }
@@ -905,8 +895,6 @@ class TC_GAME_API Spell
Spell(Spell const& right) = delete;
Spell& operator=(Spell const& right) = delete;
-
- std::vector<SpellEffectInfo const*> _effects;
};
namespace Trinity
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index e7d78a0ec57..a9fa7bfee03 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -429,7 +429,7 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
DamageInfo damageInfo(m_caster, unitTarget, damage, m_spellInfo, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK);
m_caster->CalcAbsorbResist(damageInfo);
- SpellNonMeleeDamage log(m_caster, unitTarget, m_spellInfo->Id, m_SpellVisual, m_spellInfo->GetSchoolMask(), m_castId);
+ SpellNonMeleeDamage log(m_caster, unitTarget, m_spellInfo, m_SpellVisual, m_spellInfo->GetSchoolMask(), m_castId);
log.damage = damageInfo.GetDamage();
log.originalDamage = damage;
log.absorb = damageInfo.GetAbsorb();
@@ -658,7 +658,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex /*effIndex*/)
case 29284:
{
// Brittle Armor
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(24575);
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(24575, GetCastDifficulty());
if (!spell)
return;
@@ -670,7 +670,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex /*effIndex*/)
case 29286:
{
// Mercurial Shield
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(26464);
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(26464, GetCastDifficulty());
if (!spell)
return;
@@ -703,7 +703,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex /*effIndex*/)
}
// normal case
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id, GetCastDifficulty());
if (!spellInfo)
{
TC_LOG_ERROR("spells.effecttriggerspell", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
@@ -713,13 +713,13 @@ void Spell::EffectTriggerSpell(SpellEffIndex /*effIndex*/)
SpellCastTargets targets;
if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
{
- if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID()))
+ if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo))
return;
targets.SetUnitTarget(unitTarget);
}
else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH)
{
- if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID()) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
+ if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
return;
if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION)
@@ -753,7 +753,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex /*effIndex*/)
uint32 triggered_spell_id = effectInfo->TriggerSpell;
// normal case
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id, GetCastDifficulty());
if (!spellInfo)
{
TC_LOG_ERROR("spells.effecttrigermissilespell", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u.", m_spellInfo->Id, triggered_spell_id);
@@ -763,13 +763,13 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex /*effIndex*/)
SpellCastTargets targets;
if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
{
- if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID()))
+ if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo))
return;
targets.SetUnitTarget(unitTarget);
}
else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
{
- if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID()) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
+ if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
return;
if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION)
@@ -803,7 +803,7 @@ void Spell::EffectForceCast(SpellEffIndex /*effIndex*/)
uint32 triggered_spell_id = effectInfo->TriggerSpell;
// normal case
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id, GetCastDifficulty());
if (!spellInfo)
{
@@ -855,7 +855,7 @@ void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex /*effIndex*/)
return;
uint32 triggered_spell_id = effectInfo->TriggerSpell;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id, GetCastDifficulty());
if (!spellInfo)
{
@@ -1504,7 +1504,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)
return;
}
- if (Aura* aura = Aura::TryCreate(m_spellInfo, m_castId, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel))
+ if (Aura* aura = Aura::TryCreate(m_spellInfo, m_castId, MAX_EFFECT_MASK, dynObj, caster, GetCastDifficulty(), &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel))
{
m_spellAura = aura;
m_spellAura->_RegisterForTargets();
@@ -2051,8 +2051,8 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
int32 basePoints = effectInfo->CalcValue();
if (basePoints > MAX_VEHICLE_SEATS)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(basePoints);
- if (spellInfo && spellInfo->HasAura(m_originalCaster->GetMap()->GetDifficultyID(), SPELL_AURA_CONTROL_VEHICLE))
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(basePoints, GetCastDifficulty());
+ if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
spellId = spellInfo->Id;
}
@@ -2711,7 +2711,7 @@ void Spell::EffectLearnPetSpell(SpellEffIndex effIndex)
if (!pet)
return;
- SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effectInfo->TriggerSpell);
+ SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effectInfo->TriggerSpell, DIFFICULTY_NONE);
if (!learn_spellproto)
return;
@@ -2767,7 +2767,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// and handle all effects at once
for (uint8 index = effIndex + 1; index < MAX_SPELL_EFFECTS; ++index)
{
- SpellEffectInfo const* effect = GetEffect(index);
+ SpellEffectInfo const* effect = m_spellInfo->GetEffect(index);
if (!effect)
continue;
switch (effect->Effect)
@@ -2852,7 +2852,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// Blood Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x400000)
{
- if (SpellEffectInfo const* effect = GetEffect(EFFECT_2))
+ if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_2))
{
float bonusPct = effect->CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
// Death Knight T8 Melee 4P Bonus
@@ -2868,7 +2868,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
bool normalized = false;
float weaponDamagePercentMod = 1.0f;
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -2914,7 +2914,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, addPctMods);
// Sequence is important
- for (SpellEffectInfo const* effect : GetEffects())
+ for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -3344,8 +3344,8 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
return;
// Effects for 58418 and 58420 are all DIFFICULTY_NONE so always valid
- uint32 spellID = GetEffect(EFFECT_0)->CalcValue();
- uint32 questID = GetEffect(EFFECT_1)->CalcValue();
+ uint32 spellID = m_spellInfo->GetEffect(EFFECT_0)->CalcValue();
+ uint32 questID = m_spellInfo->GetEffect(EFFECT_1)->CalcValue();
if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE)
unitTarget->CastSpell(unitTarget, spellID, true);
@@ -3395,7 +3395,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
{
/// @todo a hack, range = 11, should after some time cast, otherwise too far
m_caster->CastSpell(parent, 62496, true);
- unitTarget->CastSpell(parent, GetEffect(EFFECT_0)->CalcValue()); // DIFFICULTY_NONE, so effect always valid
+ unitTarget->CastSpell(parent, m_spellInfo->GetEffect(EFFECT_0)->CalcValue()); // DIFFICULTY_NONE, so effect always valid
}
}
}
@@ -3678,7 +3678,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation(), TELE_TO_SPELL);
// Stuck spell trigger Hearthstone cooldown
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(8690);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(8690, GetCastDifficulty());
if (!spellInfo)
return;
Spell spell(player, spellInfo, TRIGGERED_FULL_MASK);
@@ -4528,7 +4528,7 @@ void Spell::EffectDestroyAllTotems(SpellEffIndex /*effIndex*/)
if (totem && totem->IsTotem())
{
uint32 spell_id = totem->m_unitData->CreatedBySpell;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, GetCastDifficulty());
if (spellInfo)
{
std::vector<SpellPowerCost> costs = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
@@ -5363,7 +5363,7 @@ void Spell::EffectCastButtons(SpellEffIndex /*effIndex*/)
if (!spell_id)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, GetCastDifficulty());
if (!spellInfo)
continue;
@@ -5374,7 +5374,7 @@ void Spell::EffectCastButtons(SpellEffIndex /*effIndex*/)
continue;
TriggerCastFlags triggerFlags = TriggerCastFlags(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY | TRIGGERED_DONT_REPORT_CAST_ERROR);
- m_caster->CastSpell(m_caster, spell_id, triggerFlags);
+ m_caster->CastSpell(m_caster, spellInfo, triggerFlags);
}
}
@@ -5475,7 +5475,7 @@ void Spell::EffectResurrectWithAura(SpellEffIndex effIndex)
uint32 health = target->CountPctFromMaxHealth(damage);
uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage);
uint32 resurrectAura = 0;
- if (sSpellMgr->GetSpellInfo(effectInfo->TriggerSpell))
+ if (sSpellMgr->GetSpellInfo(effectInfo->TriggerSpell, DIFFICULTY_NONE))
resurrectAura = effectInfo->TriggerSpell;
if (resurrectAura && target->HasAura(resurrectAura))
diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp
index 06ef2e8eb96..dd6ccf991f2 100644
--- a/src/server/game/Spells/SpellHistory.cpp
+++ b/src/server/game/Spells/SpellHistory.cpp
@@ -19,6 +19,7 @@
#include "DatabaseEnv.h"
#include "DB2Stores.h"
#include "Item.h"
+#include "Map.h"
#include "ObjectMgr.h"
#include "Pet.h"
#include "PetPackets.h"
@@ -44,7 +45,7 @@ struct SpellHistory::PersistenceHelper<Player>
static bool ReadCooldown(Field* fields, uint32* spellId, CooldownEntry* cooldownEntry)
{
*spellId = fields[0].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(*spellId))
+ if (!sSpellMgr->GetSpellInfo(*spellId, DIFFICULTY_NONE))
return false;
cooldownEntry->SpellId = *spellId;
@@ -96,7 +97,7 @@ struct SpellHistory::PersistenceHelper<Pet>
static bool ReadCooldown(Field* fields, uint32* spellId, CooldownEntry* cooldownEntry)
{
*spellId = fields[0].GetUInt32();
- if (!sSpellMgr->GetSpellInfo(*spellId))
+ if (!sSpellMgr->GetSpellInfo(*spellId, DIFFICULTY_NONE))
return false;
cooldownEntry->SpellId = *spellId;
@@ -273,7 +274,7 @@ bool SpellHistory::IsReady(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, bo
if (IsSchoolLocked(spellInfo->GetSchoolMask()))
return false;
- if (HasCooldown(spellInfo->Id, itemId, ignoreCategoryCooldown))
+ if (HasCooldown(spellInfo, itemId, ignoreCategoryCooldown))
return false;
if (!HasCharge(spellInfo->ChargeCategoryId))
@@ -519,7 +520,7 @@ void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /
player->SendDirectMessage(WorldPackets::Spells::CooldownEvent(player != _owner, categoryItr->second->SpellId).Write());
if (startCooldown)
- StartCooldown(sSpellMgr->AssertSpellInfo(categoryItr->second->SpellId), itemId, spell);
+ StartCooldown(sSpellMgr->AssertSpellInfo(categoryItr->second->SpellId, _owner->GetMap()->GetDifficultyID()), itemId, spell);
}
player->SendDirectMessage(WorldPackets::Spells::CooldownEvent(player != _owner, spellInfo->Id).Write());
@@ -633,7 +634,7 @@ bool SpellHistory::HasCooldown(SpellInfo const* spellInfo, uint32 itemId /*= 0*/
bool SpellHistory::HasCooldown(uint32 spellId, uint32 itemId /*= 0*/, bool ignoreCategoryCooldown /*= false*/) const
{
- return HasCooldown(sSpellMgr->AssertSpellInfo(spellId), itemId, ignoreCategoryCooldown);
+ return HasCooldown(sSpellMgr->AssertSpellInfo(spellId, _owner->GetMap()->GetDifficultyID()), itemId, ignoreCategoryCooldown);
}
uint32 SpellHistory::GetRemainingCooldown(SpellInfo const* spellInfo) const
@@ -693,7 +694,7 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim
spellCooldown.Flags = SPELL_COOLDOWN_FLAG_NONE;
for (uint32 spellId : knownSpells)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(spellId, _owner->GetMap()->GetDifficultyID());
if (spellInfo->IsCooldownStartedOnEvent())
continue;
@@ -926,7 +927,7 @@ void SpellHistory::RestoreCooldownStateAfterDuel()
// add all profession CDs created while in duel (if any)
for (auto const& c : _spellCooldowns)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(c.first);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(c.first, DIFFICULTY_NONE);
if (spellInfo->RecoveryTime > 10 * MINUTE * IN_MILLISECONDS ||
spellInfo->CategoryRecoveryTime > 10 * MINUTE * IN_MILLISECONDS)
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 04134692877..d9c797b053c 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -400,36 +400,39 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
{TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 150 TARGET_UNIT_OWN_CRITTER
};
-SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* _effect)
+SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const* _effect)
{
+ ASSERT(spellInfo);
+ ASSERT(_effect);
+
_spellInfo = spellInfo;
- EffectIndex = _effect ? _effect->EffectIndex : effIndex;
- Effect = _effect ? _effect->Effect : 0;
- ApplyAuraName = _effect ? _effect->EffectAura : 0;
- ApplyAuraPeriod = _effect ? _effect->EffectAuraPeriod : 0;
- RealPointsPerLevel = _effect ? _effect->EffectRealPointsPerLevel : 0.0f;
- BasePoints = _effect ? _effect->EffectBasePoints : 0;
- PointsPerResource = _effect ? _effect->EffectPointsPerResource : 0.0f;
- Amplitude = _effect ? _effect->EffectAmplitude : 0.0f;
- ChainAmplitude = _effect ? _effect->EffectChainAmplitude : 0.0f;
- BonusCoefficient = _effect ? _effect->EffectBonusCoefficient : 0.0f;
- MiscValue = _effect ? _effect->EffectMiscValue[0] : 0;
- MiscValueB = _effect ? _effect->EffectMiscValue[1] : 0;
- Mechanic = Mechanics(_effect ? _effect->EffectMechanic : 0);
- PositionFacing = _effect ? _effect->EffectPosFacing : 0.0f;
- TargetA = SpellImplicitTargetInfo(_effect ? _effect->ImplicitTarget[0] : 0);
- TargetB = SpellImplicitTargetInfo(_effect ? _effect->ImplicitTarget[1] : 0);
- RadiusEntry = _effect && _effect->EffectRadiusIndex[0] ? sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex[0]) : NULL;
- MaxRadiusEntry = _effect && _effect->EffectRadiusIndex[1] ? sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex[1]) : NULL;
- ChainTargets = _effect ? _effect->EffectChainTargets : 0;
- ItemType = _effect ? _effect->EffectItemType : 0;
- TriggerSpell = _effect ? _effect->EffectTriggerSpell : 0;
- SpellClassMask = _effect ? _effect->EffectSpellClassMask : flag128();
- BonusCoefficientFromAP = _effect ? _effect->BonusCoefficientFromAP : 0.0f;
+ EffectIndex = _effect->EffectIndex;
+ Effect = _effect->Effect;
+ ApplyAuraName = _effect->EffectAura;
+ ApplyAuraPeriod = _effect->EffectAuraPeriod;
+ RealPointsPerLevel = _effect->EffectRealPointsPerLevel;
+ BasePoints = _effect->EffectBasePoints;
+ PointsPerResource = _effect->EffectPointsPerResource;
+ Amplitude = _effect->EffectAmplitude;
+ ChainAmplitude = _effect->EffectChainAmplitude;
+ BonusCoefficient = _effect->EffectBonusCoefficient;
+ MiscValue = _effect->EffectMiscValue[0];
+ MiscValueB = _effect->EffectMiscValue[1];
+ Mechanic = Mechanics(_effect->EffectMechanic);
+ PositionFacing = _effect->EffectPosFacing;
+ TargetA = SpellImplicitTargetInfo(_effect->ImplicitTarget[0]);
+ TargetB = SpellImplicitTargetInfo(_effect->ImplicitTarget[1]);
+ RadiusEntry = sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex[0]);
+ MaxRadiusEntry = sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex[1]);
+ ChainTargets = _effect->EffectChainTargets;
+ ItemType = _effect->EffectItemType;
+ TriggerSpell = _effect->EffectTriggerSpell;
+ SpellClassMask = _effect->EffectSpellClassMask;
+ BonusCoefficientFromAP = _effect->BonusCoefficientFromAP;
Scaling.Coefficient = _effect->Coefficient;
Scaling.Variance = _effect->Variance;
Scaling.ResourceCoefficient = _effect->ResourceCoefficient;
- ImplicitTargetConditions = NULL;
+ ImplicitTargetConditions = nullptr;
}
bool SpellEffectInfo::IsEffect() const
@@ -1090,22 +1093,25 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
};
-SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals)
- : _hasPowerDifficultyData(false)
+SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, SpellInfoLoadHelper const& data, SpellVisualVector&& visuals)
{
- Id = data.Entry->ID;
+ Id = spellName->ID;
+ Difficulty = difficulty;
- for (SpellEffectEntryMap::value_type const& itr : effectsMap)
+ _effects.reserve(32);
+ for (SpellEffectEntry const* spellEffect : data.Effects)
{
- SpellEffectEntryVector const& effects = itr.second;
- _effects[itr.first].resize(effects.size());
+ if (!spellEffect)
+ continue;
+
+ if (uint32(spellEffect->EffectIndex) >= _effects.size())
+ _effects.resize(spellEffect->EffectIndex + 1);
- for (size_t i = 0; i < effects.size(); ++i)
- if (SpellEffectEntry const* effect = effects[i])
- _effects[itr.first][effect->EffectIndex] = new SpellEffectInfo(this, effect->EffectIndex, effect);
+ _effects[spellEffect->EffectIndex] = new SpellEffectInfo(this, spellEffect);
}
+ _effects.shrink_to_fit();
- SpellName = data.Entry->Name;
+ SpellName = spellName->Name;
// SpellMiscEntry
SpellMiscEntry const* _misc = data.Misc;
@@ -1136,9 +1142,6 @@ SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const&
ContentTuningId = _misc ? _misc->ContentTuningID : 0;
_visuals = std::move(visuals);
- // sort all visuals so that the ones without a condition requirement are last on the list
- for (auto& visualPair : _visuals)
- std::sort(visualPair.second.begin(), visualPair.second.end(), [](SpellXSpellVisualEntry const* first, SpellXSpellVisualEntry const* second) { return first->CasterPlayerConditionID > second->CasterPlayerConditionID; });
// SpellScalingEntry
SpellScalingEntry const* _scaling = data.Scaling;
@@ -1224,7 +1227,7 @@ SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const&
SpellLevel = _levels ? _levels->SpellLevel : 0;
// SpellPowerEntry
- PowerCosts = sDB2Manager.GetSpellPowers(Id, DIFFICULTY_NONE, &_hasPowerDifficultyData);
+ PowerCosts = data.Powers;
// SpellReagentsEntry
SpellReagentsEntry const* _reagents = data.Reagents;
@@ -1271,9 +1274,9 @@ SpellInfo::~SpellInfo()
void SpellInfo::_UnloadSpellEffects()
{
- for (SpellEffectInfoMap::value_type& i : _effects)
- for (size_t j = 0; j < i.second.size(); ++j)
- delete i.second[j];
+ for (SpellEffectInfo const* effect : _effects)
+ delete effect;
+
_effects.clear();
}
@@ -1282,88 +1285,53 @@ uint32 SpellInfo::GetCategory() const
return CategoryId;
}
-bool SpellInfo::HasEffect(uint32 difficulty, SpellEffectName effect) const
+bool SpellInfo::HasEffect(SpellEffectName effect) const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* eff : effects)
- {
+ for (SpellEffectInfo const* eff : _effects)
if (eff && eff->IsEffect(effect))
return true;
- }
- return false;
-}
-bool SpellInfo::HasEffect(SpellEffectName effect) const
-{
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* eff : itr->second)
- {
- if (eff && eff->IsEffect(effect))
- return true;
- }
- }
return false;
}
-bool SpellInfo::HasAura(uint32 difficulty, AuraType aura) const
+bool SpellInfo::HasAura(AuraType aura) const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
- {
+ for (SpellEffectInfo const* effect : _effects)
if (effect && effect->IsAura(aura))
return true;
- }
+
return false;
}
-bool SpellInfo::HasAreaAuraEffect(uint32 difficulty) const
+bool SpellInfo::HasAreaAuraEffect() const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
- {
+ for (SpellEffectInfo const* effect : _effects)
if (effect && effect->IsAreaAuraEffect())
return true;
- }
- return false;
-}
-bool SpellInfo::HasAreaAuraEffect() const
-{
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect && effect->IsAreaAuraEffect())
- return true;
- }
- }
return false;
}
bool SpellInfo::HasOnlyDamageEffects() const
{
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
+ for (SpellEffectInfo const* effect : _effects)
{
- for (SpellEffectInfo const* effect : itr->second)
+ if (!effect)
+ continue;
+
+ switch (effect->Effect)
{
- if (!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:
+ case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT:
continue;
-
- switch (effect->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:
- case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT:
- continue;
- default:
- return false;
- }
+ default:
+ return false;
}
}
@@ -1372,25 +1340,10 @@ bool SpellInfo::HasOnlyDamageEffects() const
bool SpellInfo::HasTargetType(::Targets target) const
{
- for (auto itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect && (effect->TargetA.GetTarget() == target || effect->TargetB.GetTarget() == target))
- return true;
- }
- }
- return false;
-}
-
-bool SpellInfo::HasTargetType(uint32 difficulty, ::Targets target) const
-{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
- {
+ for (SpellEffectInfo const* effect : _effects)
if (effect && (effect->TargetA.GetTarget() == target || effect->TargetB.GetTarget() == target))
return true;
- }
+
return false;
}
@@ -1401,8 +1354,8 @@ bool SpellInfo::HasAnyAuraInterruptFlag() const
bool SpellInfo::IsExplicitDiscovery() const
{
- SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0);
- SpellEffectInfo const* effect1 = GetEffect(DIFFICULTY_NONE, EFFECT_1);
+ SpellEffectInfo const* effect0 = GetEffect(EFFECT_0);
+ SpellEffectInfo const* effect1 = GetEffect(EFFECT_1);
return ((effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || effect0->Effect == SPELL_EFFECT_CREATE_LOOT))
&& effect1 && effect1->Effect == SPELL_EFFECT_SCRIPT_EFFECT)
@@ -1416,15 +1369,14 @@ bool SpellInfo::IsLootCrafting() const
bool SpellInfo::IsQuestTame() const
{
- SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0);
- SpellEffectInfo const* effect1 = GetEffect(DIFFICULTY_NONE, EFFECT_1);
+ SpellEffectInfo const* effect0 = GetEffect(EFFECT_0);
+ SpellEffectInfo const* effect1 = GetEffect(EFFECT_1);
return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY;
}
-bool SpellInfo::IsProfession(uint32 difficulty) const
+bool SpellInfo::IsProfession() const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
+ for (SpellEffectInfo const* effect : _effects)
{
if (effect && effect->Effect == SPELL_EFFECT_SKILL)
{
@@ -1437,10 +1389,9 @@ bool SpellInfo::IsProfession(uint32 difficulty) const
return false;
}
-bool SpellInfo::IsPrimaryProfession(uint32 difficulty) const
+bool SpellInfo::IsPrimaryProfession() const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for(SpellEffectInfo const* effect : effects)
+ for (SpellEffectInfo const* effect : _effects)
{
if (effect && effect->Effect == SPELL_EFFECT_SKILL)
{
@@ -1453,9 +1404,9 @@ bool SpellInfo::IsPrimaryProfession(uint32 difficulty) const
return false;
}
-bool SpellInfo::IsPrimaryProfessionFirstRank(uint32 difficulty) const
+bool SpellInfo::IsPrimaryProfessionFirstRank() const
{
- return IsPrimaryProfession(difficulty) && GetRank() == 1;
+ return IsPrimaryProfession() && GetRank() == 1;
}
bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const
@@ -1469,26 +1420,22 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const
return false;
}
-bool SpellInfo::IsAffectingArea(uint32 difficulty) const
+bool SpellInfo::IsAffectingArea() const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
- {
+ for (SpellEffectInfo const* effect : _effects)
if (effect && effect->IsEffect() && (effect->IsTargetingArea() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect->IsAreaAuraEffect()))
return true;
- }
+
return false;
}
// checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example)
-bool SpellInfo::IsTargetingArea(uint32 difficulty) const
+bool SpellInfo::IsTargetingArea() const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
- {
+ for (SpellEffectInfo const* effect : _effects)
if (effect && effect->IsEffect() && effect->IsTargetingArea())
return true;
- }
+
return false;
}
@@ -1497,7 +1444,7 @@ bool SpellInfo::NeedsExplicitUnitTarget() const
return (GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK) != 0;
}
-bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const
+bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const
{
if (NeedsExplicitUnitTarget())
return true;
@@ -1517,8 +1464,7 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uin
if (triggeringSpell->IsChanneled())
{
uint32 mask = 0;
- SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
- for (SpellEffectInfo const* effect : effects)
+ for (SpellEffectInfo const* effect : _effects)
{
if (!effect)
continue;
@@ -1557,8 +1503,7 @@ bool SpellInfo::IsStackableWithRanks() const
return false;
// All stance spells. if any better way, change it.
- SpellEffectInfoVector effects = GetEffectsForDifficulty(DIFFICULTY_NONE);
- for (SpellEffectInfo const* effect : effects)
+ for (SpellEffectInfo const* effect : _effects)
{
if (!effect)
continue;
@@ -1582,9 +1527,9 @@ bool SpellInfo::IsStackableWithRanks() const
return true;
}
-bool SpellInfo::IsPassiveStackableWithRanks(uint32 difficulty) const
+bool SpellInfo::IsPassiveStackableWithRanks() const
{
- return IsPassive() && !HasEffect(difficulty, SPELL_EFFECT_APPLY_AURA);
+ return IsPassive() && !HasEffect(SPELL_EFFECT_APPLY_AURA);
}
bool SpellInfo::IsMultiSlotAura() const
@@ -1624,8 +1569,7 @@ bool SpellInfo::IsAllowingDeadTarget() const
bool SpellInfo::IsGroupBuff() const
{
- SpellEffectInfoVector effects = GetEffectsForDifficulty(DIFFICULTY_NONE);
- for (SpellEffectInfo const* effect : effects)
+ for (SpellEffectInfo const* effect : _effects)
{
if (!effect)
continue;
@@ -1778,7 +1722,7 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const
if (!IsAffectedBySpellMods())
return false;
- SpellInfo const* affectSpell = sSpellMgr->GetSpellInfo(mod->spellId);
+ SpellInfo const* affectSpell = sSpellMgr->GetSpellInfo(mod->spellId, Difficulty);
if (!affectSpell)
return false;
@@ -2087,7 +2031,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
// aura limitations
if (player)
{
- for (SpellEffectInfo const* effect : GetEffectsForDifficulty(player->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : _effects)
{
if (!effect || !effect->IsAura())
continue;
@@ -2256,7 +2200,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
return SPELL_FAILED_TARGET_AURASTATE;
if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
- if (HasEffect(caster->GetMap()->GetDifficultyID(), SPELL_EFFECT_SELF_RESURRECT) || HasEffect(caster->GetMap()->GetDifficultyID(), SPELL_EFFECT_RESURRECT))
+ if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT))
return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED;
if (HasAttribute(SPELL_ATTR8_BATTLE_RESURRECTION))
@@ -2314,7 +2258,7 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
if (vehicle)
{
uint16 checkMask = 0;
- for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : _effects)
{
if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
{
@@ -2325,7 +2269,7 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
}
}
- if (HasAura(caster->GetMap()->GetDifficultyID(), SPELL_AURA_MOUNTED))
+ if (HasAura(SPELL_AURA_MOUNTED))
checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL;
if (!checkMask)
@@ -2339,7 +2283,7 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
// Can only summon uncontrolled minions/guardians when on controlled vehicle
if (vehicleSeat->Flags & (VEHICLE_SEAT_FLAG_CAN_CONTROL | VEHICLE_SEAT_FLAG_UNK2))
{
- for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : _effects)
{
if (!effect || effect->Effect != SPELL_EFFECT_SUMMON)
continue;
@@ -2384,14 +2328,11 @@ uint32 SpellInfo::GetAllEffectsMechanicMask() const
uint32 mask = 0;
if (Mechanic)
mask |= 1 << Mechanic;
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect && effect->IsEffect() && effect->Mechanic)
- mask |= 1 << effect->Mechanic;
- }
- }
+
+ for (SpellEffectInfo const* effect : _effects)
+ if (effect && effect->IsEffect() && effect->Mechanic)
+ mask |= 1 << effect->Mechanic;
+
return mask;
}
@@ -2400,14 +2341,10 @@ uint32 SpellInfo::GetEffectMechanicMask(uint32 effIndex) const
uint32 mask = 0;
if (Mechanic)
mask |= 1 << Mechanic;
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect && effect->EffectIndex == effIndex && effect->IsEffect() && effect->Mechanic)
- mask |= 1 << effect->Mechanic;
- }
- }
+
+ if (effIndex < _effects.size() && _effects[effIndex] && _effects[effIndex]->IsEffect() && _effects[effIndex]->Mechanic)
+ mask |= 1 << _effects[effIndex]->Mechanic;
+
return mask;
}
@@ -2416,24 +2353,23 @@ uint32 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
uint32 mask = 0;
if (Mechanic)
mask |= 1 << Mechanic;
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect && (effectMask & (1 << effect->EffectIndex)) && effect->Mechanic)
- mask |= 1 << effect->Mechanic;
- }
- }
+
+ for (SpellEffectInfo const* effect : _effects)
+ if (effect && (effectMask & (1 << effect->EffectIndex)) && effect->Mechanic)
+ mask |= 1 << effect->Mechanic;
+
return mask;
}
-Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex, uint32 difficulty) const
+Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex) const
{
- SpellEffectInfo const* effect = GetEffect(difficulty, effIndex);
+ SpellEffectInfo const* effect = GetEffect(effIndex);
if (effect && effect->IsEffect() && effect->Mechanic)
return Mechanics(effect->Mechanic);
+
if (Mechanic)
return Mechanics(Mechanic);
+
return MECHANIC_NONE;
}
@@ -2514,10 +2450,9 @@ void SpellInfo::_LoadAuraState()
return AURA_STATE_BLEEDING;
if (GetSchoolMask() & SPELL_SCHOOL_MASK_FROST)
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- for (SpellEffectInfo const* effect : itr->second)
- if (effect && (effect->IsAura(SPELL_AURA_MOD_STUN) || effect->IsAura(SPELL_AURA_MOD_ROOT)))
- return AURA_STATE_FROZEN;
+ for (SpellEffectInfo const* effect : _effects)
+ if (effect && (effect->IsAura(SPELL_AURA_MOD_STUN) || effect->IsAura(SPELL_AURA_MOD_ROOT)))
+ return AURA_STATE_FROZEN;
switch (Id)
{
@@ -2550,27 +2485,24 @@ void SpellInfo::_LoadSpellSpecific()
{
bool food = false;
bool drink = false;
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
+ for (SpellEffectInfo const* effect : _effects)
{
- for (SpellEffectInfo const* effect : itr->second)
+ if (!effect || !effect->IsAura())
+ continue;
+ switch (effect->ApplyAuraName)
{
- if (!effect || !effect->IsAura())
- continue;
- switch (effect->ApplyAuraName)
- {
- // Food
+ // Food
case SPELL_AURA_MOD_REGEN:
case SPELL_AURA_OBS_MOD_HEALTH:
food = true;
break;
- // Drink
+ // Drink
case SPELL_AURA_MOD_POWER_REGEN:
case SPELL_AURA_OBS_MOD_POWER:
drink = true;
break;
default:
break;
- }
}
}
@@ -2609,7 +2541,7 @@ void SpellInfo::_LoadSpellSpecific()
// Arcane brillance and Arcane intelect (normal check fails because of flags difference)
if (SpellFamilyFlags[0] & 0x400)
return SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE;
- SpellEffectInfo const* effect = GetEffect(DIFFICULTY_NONE, EFFECT_0);
+ SpellEffectInfo const* effect = GetEffect(EFFECT_0);
if (effect && (SpellFamilyFlags[0] & 0x1000000) && effect->ApplyAuraName == SPELL_AURA_MOD_CONFUSE)
return SPELL_SPECIFIC_MAGE_POLYMORPH;
@@ -2696,14 +2628,12 @@ void SpellInfo::_LoadSpellSpecific()
break;
}
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
+ for (SpellEffectInfo const* effect : _effects)
{
- for (SpellEffectInfo const* effect : itr->second)
+ if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA)
{
- if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA)
+ switch (effect->ApplyAuraName)
{
- switch (effect->ApplyAuraName)
- {
case SPELL_AURA_MOD_CHARM:
case SPELL_AURA_MOD_POSSESS_PET:
case SPELL_AURA_MOD_POSSESS:
@@ -2713,11 +2643,10 @@ void SpellInfo::_LoadSpellSpecific()
/// @workaround For non-stacking tracking spells (We need generic solution)
if (Id == 30645) // Gas Cloud Tracking
return SPELL_SPECIFIC_NORMAL;
- /* fallthrough */
+ /* fallthrough */
case SPELL_AURA_TRACK_RESOURCES:
case SPELL_AURA_TRACK_STEALTHED:
return SPELL_SPECIFIC_TRACKER;
- }
}
}
}
@@ -2732,7 +2661,7 @@ void SpellInfo::_LoadSpellDiminishInfo()
if (IsPositive())
return DIMINISHING_NONE;
- if (HasAura(DIFFICULTY_NONE, SPELL_AURA_MOD_TAUNT))
+ if (HasAura(SPELL_AURA_MOD_TAUNT))
return DIMINISHING_TAUNT;
switch (Id)
@@ -3459,15 +3388,12 @@ void SpellInfo::_LoadImmunityInfo()
_allowedMechanicMask |= immuneInfo.MechanicImmuneMask;
};
- for (auto const& effects : _effects)
+ for (SpellEffectInfo const* effect : _effects)
{
- for (SpellEffectInfo const* effect : effects.second)
- {
- if (!effect)
- continue;
+ if (!effect)
+ continue;
- loadImmunityInfoFn(const_cast<SpellEffectInfo*>(effect));
- }
+ loadImmunityInfoFn(const_cast<SpellEffectInfo*>(effect));
}
if (HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED))
@@ -3570,7 +3496,7 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf
if (!auraSpellInfo)
return false;
- for (SpellEffectInfo const* effectInfo : GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effectInfo : _effects)
{
if (!effectInfo)
continue;
@@ -3593,7 +3519,7 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf
return true;
bool immuneToAllEffects = true;
- for (SpellEffectInfo const* auraSpellEffectInfo : auraSpellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* auraSpellEffectInfo : auraSpellInfo->GetEffects())
{
if (!auraSpellEffectInfo)
continue;
@@ -3659,7 +3585,7 @@ bool SpellInfo::SpellCancelsAuraEffect(AuraEffect const* aurEff) const
if (aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
- for (SpellEffectInfo const* effectInfo : GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effectInfo : _effects)
{
if (!effectInfo)
continue;
@@ -3786,13 +3712,13 @@ uint32 SpellInfo::CalcCastTime(uint8 level, Spell* spell /*= NULL*/) const
return (castTime > 0) ? uint32(castTime) : 0;
}
-uint32 SpellInfo::GetMaxTicks(uint32 difficulty) const
+uint32 SpellInfo::GetMaxTicks() const
{
int32 DotDuration = GetDuration();
if (DotDuration == 0)
return 1;
- for (SpellEffectInfo const* effect : GetEffectsForDifficulty(difficulty))
+ for (SpellEffectInfo const* effect : _effects)
{
if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA)
switch (effect->ApplyAuraName)
@@ -3828,190 +3754,184 @@ uint32 SpellInfo::GetRecoveryTime() const
std::vector<SpellPowerCost> SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask, Spell* spell) const
{
std::vector<SpellPowerCost> costs;
- auto collector = [this, caster, schoolMask, spell, &costs](std::vector<SpellPowerEntry const*> const& powers)
+ costs.reserve(MAX_POWERS_PER_SPELL);
+ int32 healthCost = 0;
+
+ for (SpellPowerEntry const* power : PowerCosts)
{
- costs.reserve(powers.size());
- int32 healthCost = 0;
+ if (!power)
+ continue;
+ if (power->RequiredAuraSpellID && !caster->HasAura(power->RequiredAuraSpellID))
+ continue;
- for (SpellPowerEntry const* power : powers)
+ // Spell drain all exist power on cast (Only paladin lay of Hands)
+ if (HasAttribute(SPELL_ATTR1_DRAIN_ALL_POWER))
{
- if (power->RequiredAuraSpellID && !caster->HasAura(power->RequiredAuraSpellID))
- continue;
-
- // Spell drain all exist power on cast (Only paladin lay of Hands)
- if (HasAttribute(SPELL_ATTR1_DRAIN_ALL_POWER))
+ // If power type - health drain all
+ if (power->PowerType == POWER_HEALTH)
{
- // If power type - health drain all
- if (power->PowerType == POWER_HEALTH)
- {
- healthCost = caster->GetHealth();
- continue;
- }
- // Else drain all power
- if (power->PowerType < MAX_POWERS)
- {
- SpellPowerCost cost;
- cost.Power = Powers(power->PowerType);
- cost.Amount = caster->GetPower(cost.Power);
- costs.push_back(cost);
- continue;
- }
-
- TC_LOG_ERROR("spells", "SpellInfo::CalcPowerCost: Unknown power type '%d' in spell %d", power->PowerType, Id);
+ healthCost = caster->GetHealth();
continue;
}
-
- // Base powerCost
- int32 powerCost = power->ManaCost;
- // PCT cost from total amount
- if (power->PowerCostPct)
+ // Else drain all power
+ if (power->PowerType < MAX_POWERS)
{
- switch (power->PowerType)
- {
- // health as power used
- case POWER_HEALTH:
- powerCost += int32(CalculatePct(caster->GetMaxHealth(), power->PowerCostPct));
- break;
- case POWER_MANA:
- powerCost += int32(CalculatePct(caster->GetCreateMana(), power->PowerCostPct));
- break;
- case POWER_RAGE:
- case POWER_FOCUS:
- case POWER_ENERGY:
- powerCost += int32(CalculatePct(caster->GetMaxPower(Powers(power->PowerType)), power->PowerCostPct));
- break;
- case POWER_RUNES:
- case POWER_RUNIC_POWER:
- TC_LOG_DEBUG("spells", "CalculateManaCost: Not implemented yet!");
- break;
- default:
- TC_LOG_ERROR("spells", "CalculateManaCost: Unknown power type '%d' in spell %d", power->PowerType, Id);
- continue;
- }
+ SpellPowerCost cost;
+ cost.Power = Powers(power->PowerType);
+ cost.Amount = caster->GetPower(cost.Power);
+ costs.push_back(cost);
+ continue;
}
- if (power->PowerCostMaxPct)
- healthCost += int32(CalculatePct(caster->GetMaxHealth(), power->PowerCostMaxPct));
-
- int32 optionalCost = int32(power->OptionalCost);
- optionalCost += caster->GetTotalAuraModifier(SPELL_AURA_MOD_ADDITIONAL_POWER_COST, [this, power](AuraEffect const* aurEff) -> bool
- {
- return aurEff->GetMiscValue() == power->PowerType
- && aurEff->IsAffectingSpell(this);
- });
+ TC_LOG_ERROR("spells", "SpellInfo::CalcPowerCost: Unknown power type '%d' in spell %d", power->PowerType, Id);
+ continue;
+ }
- if (optionalCost)
+ // Base powerCost
+ int32 powerCost = power->ManaCost;
+ // PCT cost from total amount
+ if (power->PowerCostPct)
+ {
+ switch (power->PowerType)
{
- int32 remainingPower = caster->GetPower(Powers(power->PowerType)) - powerCost;
- powerCost += RoundToInterval<int32>(remainingPower, 0, optionalCost);
+ // health as power used
+ case POWER_HEALTH:
+ powerCost += int32(CalculatePct(caster->GetMaxHealth(), power->PowerCostPct));
+ break;
+ case POWER_MANA:
+ powerCost += int32(CalculatePct(caster->GetCreateMana(), power->PowerCostPct));
+ break;
+ case POWER_RAGE:
+ case POWER_FOCUS:
+ case POWER_ENERGY:
+ powerCost += int32(CalculatePct(caster->GetMaxPower(Powers(power->PowerType)), power->PowerCostPct));
+ break;
+ case POWER_RUNES:
+ case POWER_RUNIC_POWER:
+ TC_LOG_DEBUG("spells", "CalculateManaCost: Not implemented yet!");
+ break;
+ default:
+ TC_LOG_ERROR("spells", "CalculateManaCost: Unknown power type '%d' in spell %d", power->PowerType, Id);
+ continue;
}
+ }
- if (power->PowerType != POWER_HEALTH)
- {
- // Flat mod from caster auras by spell school and power type
- Unit::AuraEffectList const& auras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL);
- for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
- {
- if (!((*i)->GetMiscValue() & schoolMask))
- continue;
+ if (power->PowerCostMaxPct)
+ healthCost += int32(CalculatePct(caster->GetMaxHealth(), power->PowerCostMaxPct));
- if (!((*i)->GetMiscValueB() & (1 << power->PowerType)))
- continue;
+ int32 optionalCost = int32(power->OptionalCost);
+ optionalCost += caster->GetTotalAuraModifier(SPELL_AURA_MOD_ADDITIONAL_POWER_COST, [this, power](AuraEffect const* aurEff) -> bool
+ {
+ return aurEff->GetMiscValue() == power->PowerType
+ && aurEff->IsAffectingSpell(this);
+ });
- powerCost += (*i)->GetAmount();
- }
- }
+ if (optionalCost)
+ {
+ int32 remainingPower = caster->GetPower(Powers(power->PowerType)) - powerCost;
+ powerCost += RoundToInterval<int32>(remainingPower, 0, optionalCost);
+ }
- // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
- if (HasAttribute(SPELL_ATTR4_SPELL_VS_EXTEND_COST))
+ if (power->PowerType != POWER_HEALTH)
+ {
+ // Flat mod from caster auras by spell school and power type
+ Unit::AuraEffectList const& auras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL);
+ for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
{
- uint32 speed = 0;
- if (SpellShapeshiftFormEntry const* ss = sSpellShapeshiftFormStore.LookupEntry(caster->GetShapeshiftForm()))
- speed = ss->CombatRoundTime;
- else
- {
- WeaponAttackType slot = BASE_ATTACK;
- if (HasAttribute(SPELL_ATTR3_REQ_OFFHAND))
- slot = OFF_ATTACK;
+ if (!((*i)->GetMiscValue() & schoolMask))
+ continue;
- speed = caster->GetBaseAttackTime(slot);
- }
+ if (!((*i)->GetMiscValueB() & (1 << power->PowerType)))
+ continue;
- powerCost += speed / 100;
+ powerCost += (*i)->GetAmount();
}
+ }
- // Apply cost mod by spell
- if (Player* modOwner = caster->GetSpellModOwner())
+ // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
+ if (HasAttribute(SPELL_ATTR4_SPELL_VS_EXTEND_COST))
+ {
+ uint32 speed = 0;
+ if (SpellShapeshiftFormEntry const* ss = sSpellShapeshiftFormStore.LookupEntry(caster->GetShapeshiftForm()))
+ speed = ss->CombatRoundTime;
+ else
{
- if (power->OrderIndex == 0)
- modOwner->ApplySpellMod(Id, SPELLMOD_COST, powerCost, spell);
- else if (power->OrderIndex == 1)
- modOwner->ApplySpellMod(Id, SPELLMOD_SPELL_COST2, powerCost, spell);
- }
+ WeaponAttackType slot = BASE_ATTACK;
+ if (HasAttribute(SPELL_ATTR3_REQ_OFFHAND))
+ slot = OFF_ATTACK;
- if (!caster->IsControlledByPlayer() && G3D::fuzzyEq(power->PowerCostPct, 0.0f) && SpellLevel)
- {
- if (HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
- {
- GtNpcManaCostScalerEntry const* spellScaler = sNpcManaCostScalerGameTable.GetRow(SpellLevel);
- GtNpcManaCostScalerEntry const* casterScaler = sNpcManaCostScalerGameTable.GetRow(caster->getLevel());
- if (spellScaler && casterScaler)
- powerCost *= casterScaler->Scaler / spellScaler->Scaler;
- }
+ speed = caster->GetBaseAttackTime(slot);
}
- // PCT mod from user auras by spell school and power type
- Unit::AuraEffectList const& aurasPct = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
- for (Unit::AuraEffectList::const_iterator i = aurasPct.begin(); i != aurasPct.end(); ++i)
- {
- if (!((*i)->GetMiscValue() & schoolMask))
- continue;
+ powerCost += speed / 100;
+ }
- if (!((*i)->GetMiscValueB() & (1 << power->PowerType)))
- continue;
+ // Apply cost mod by spell
+ if (Player* modOwner = caster->GetSpellModOwner())
+ {
+ if (power->OrderIndex == 0)
+ modOwner->ApplySpellMod(Id, SPELLMOD_COST, powerCost, spell);
+ else if (power->OrderIndex == 1)
+ modOwner->ApplySpellMod(Id, SPELLMOD_SPELL_COST2, powerCost, spell);
+ }
- powerCost += CalculatePct(powerCost, (*i)->GetAmount());
+ if (!caster->IsControlledByPlayer() && G3D::fuzzyEq(power->PowerCostPct, 0.0f) && SpellLevel)
+ {
+ if (HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
+ {
+ GtNpcManaCostScalerEntry const* spellScaler = sNpcManaCostScalerGameTable.GetRow(SpellLevel);
+ GtNpcManaCostScalerEntry const* casterScaler = sNpcManaCostScalerGameTable.GetRow(caster->getLevel());
+ if (spellScaler && casterScaler)
+ powerCost *= casterScaler->Scaler / spellScaler->Scaler;
}
+ }
- if (power->PowerType == POWER_HEALTH)
- {
- healthCost += powerCost;
+ // PCT mod from user auras by spell school and power type
+ Unit::AuraEffectList const& aurasPct = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
+ for (Unit::AuraEffectList::const_iterator i = aurasPct.begin(); i != aurasPct.end(); ++i)
+ {
+ if (!((*i)->GetMiscValue() & schoolMask))
continue;
- }
- bool found = false;
- for (SpellPowerCost& cost : costs)
- {
- if (cost.Power == Powers(power->PowerType))
- {
- cost.Amount += powerCost;
- found = true;
- }
- }
+ if (!((*i)->GetMiscValueB() & (1 << power->PowerType)))
+ continue;
- if (!found)
+ powerCost += CalculatePct(powerCost, (*i)->GetAmount());
+ }
+
+ if (power->PowerType == POWER_HEALTH)
+ {
+ healthCost += powerCost;
+ continue;
+ }
+
+ bool found = false;
+ for (SpellPowerCost& cost : costs)
+ {
+ if (cost.Power == Powers(power->PowerType))
{
- SpellPowerCost cost;
- cost.Power = Powers(power->PowerType);
- cost.Amount = powerCost;
- costs.push_back(cost);
+ cost.Amount += powerCost;
+ found = true;
}
}
- if (healthCost > 0)
+ if (!found)
{
SpellPowerCost cost;
- cost.Power = POWER_HEALTH;
- cost.Amount = healthCost;
+ cost.Power = Powers(power->PowerType);
+ cost.Amount = powerCost;
costs.push_back(cost);
}
- };
+ }
- if (!_hasPowerDifficultyData) // optimization - use static data for 99.5% cases (4753 of 4772 in build 6.1.0.19702)
- collector(PowerCosts);
- else
- collector(sDB2Manager.GetSpellPowers(Id, caster->GetMap()->GetDifficultyID()));
+ if (healthCost > 0)
+ {
+ SpellPowerCost cost;
+ cost.Power = POWER_HEALTH;
+ cost.Amount = healthCost;
+ costs.push_back(cost);
+ }
return costs;
}
@@ -4191,7 +4111,7 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const
return this;
bool needRankSelection = false;
- for (SpellEffectInfo const* effect : GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : _effects)
{
if (effect && IsPositiveEffect(effect->Effect) &&
(effect->Effect == SPELL_EFFECT_APPLY_AURA ||
@@ -4245,36 +4165,11 @@ bool SpellInfo::IsHighRankOf(SpellInfo const* spellInfo) const
uint32 SpellInfo::GetSpellXSpellVisualId(Unit const* caster /*= nullptr*/) const
{
- if (caster)
+ for (SpellXSpellVisualEntry const* visual : _visuals)
{
- Difficulty difficulty = caster->GetMap()->GetDifficultyID();
- DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
- while (difficultyEntry)
- {
- auto itr = _visuals.find(difficulty);
- if (itr != _visuals.end())
- {
- for (SpellXSpellVisualEntry const* visual : itr->second)
- {
- PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->CasterPlayerConditionID);
- if (!playerCondition || (caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition)))
- return visual->ID;
- }
- }
-
- difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
- }
- }
-
- auto itr = _visuals.find(DIFFICULTY_NONE);
- if (itr != _visuals.end())
- {
- for (SpellXSpellVisualEntry const* visual : itr->second)
- {
- PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->CasterPlayerConditionID);
- if (!playerCondition || (caster && caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition)))
- return visual->ID;
- }
+ PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->CasterPlayerConditionID);
+ if (!playerCondition || (caster && caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition)))
+ return visual->ID;
}
return 0;
@@ -4299,29 +4194,26 @@ void SpellInfo::_InitializeExplicitTargetMask()
bool dstSet = false;
uint32 targetMask = Targets;
// prepare target mask using effect target entries
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
+ for (SpellEffectInfo const* effect : _effects)
{
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (!effect || !effect->IsEffect())
- continue;
+ if (!effect || !effect->IsEffect())
+ continue;
- targetMask |= effect->TargetA.GetExplicitTargetMask(srcSet, dstSet);
- targetMask |= effect->TargetB.GetExplicitTargetMask(srcSet, dstSet);
+ targetMask |= effect->TargetA.GetExplicitTargetMask(srcSet, dstSet);
+ targetMask |= effect->TargetB.GetExplicitTargetMask(srcSet, dstSet);
- // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided
- if (effect->GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT)
- continue;
+ // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided
+ if (effect->GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT)
+ continue;
- // extend explicit target mask only if valid targets for effect could not be provided by target types
- uint32 effectTargetMask = effect->GetMissingTargetMask(srcSet, dstSet, targetMask);
+ // extend explicit target mask only if valid targets for effect could not be provided by target types
+ uint32 effectTargetMask = effect->GetMissingTargetMask(srcSet, dstSet, targetMask);
- // don't add explicit object/dest flags when spell has no max range
- if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f)
- effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION);
+ // don't add explicit object/dest flags when spell has no max range
+ if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f)
+ effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION);
- targetMask |= effectTargetMask;
- }
+ targetMask |= effectTargetMask;
}
ExplicitTargetMask = targetMask;
@@ -4393,32 +4285,22 @@ bool SpellInfo::_IsPositiveEffect(uint32 effIndex, bool deep) const
}
// Special case: effects which determine positivity of whole spell
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect && effect->IsAura() && effect->ApplyAuraName == SPELL_AURA_MOD_STEALTH)
- return true;
- }
- }
+ for (SpellEffectInfo const* effect : _effects)
+ if (effect && effect->IsAura() && effect->ApplyAuraName == SPELL_AURA_MOD_STEALTH)
+ return true;
- for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr)
+ if (SpellEffectInfo const* effect = GetEffect(effIndex))
{
- for (SpellEffectInfo const* effect : itr->second)
+ switch (effect->Effect)
{
- if (!effect || effect->EffectIndex != effIndex)
- continue;
-
- switch (effect->Effect)
- {
case SPELL_EFFECT_DUMMY:
// some explicitly required dummy effect sets
switch (Id)
{
- case 28441:
- return false; // AB Effect 000
- default:
- break;
+ case 28441:
+ return false; // AB Effect 000
+ default:
+ break;
}
break;
// always positive effects (check before target checks that provided non-positive result in some case for positive effects)
@@ -4463,20 +4345,17 @@ bool SpellInfo::_IsPositiveEffect(uint32 effIndex, bool deep) const
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
if (!deep)
{
- if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell))
+ if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, Difficulty))
{
// negative targets of main spell return early
- for (SpellEffectInfoMap::const_iterator it = spellTriggeredProto->_effects.begin(); it != spellTriggeredProto->_effects.end(); ++it)
+ for (SpellEffectInfo const* eff : spellTriggeredProto->_effects)
{
- for (SpellEffectInfo const* eff : itr->second)
- {
- if (!eff || !eff->Effect)
- continue;
- // if non-positive trigger cast targeted to positive target this main cast is non-positive
- // this will place this spell auras as debuffs
- if (_IsPositiveTarget(eff->TargetA.GetTarget(), eff->TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(eff->EffectIndex, true))
- return false;
- }
+ if (!eff || !eff->Effect)
+ continue;
+ // if non-positive trigger cast targeted to positive target this main cast is non-positive
+ // this will place this spell auras as debuffs
+ if (_IsPositiveTarget(eff->TargetA.GetTarget(), eff->TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(eff->EffectIndex, true))
+ return false;
}
}
}
@@ -4486,15 +4365,12 @@ bool SpellInfo::_IsPositiveEffect(uint32 effIndex, bool deep) const
case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment.
{
bool more = false;
- for (SpellEffectInfoMap::const_iterator i = _effects.begin(); i != _effects.end(); ++i)
+ for (SpellEffectInfo const* eff : _effects)
{
- for (SpellEffectInfo const* eff : i->second)
+ if (eff && eff->EffectIndex != 0)
{
- if (eff && eff->EffectIndex != 0)
- {
- more = true;
- break;
- }
+ more = true;
+ break;
}
}
if (effIndex == 0 && !more)
@@ -4581,21 +4457,21 @@ bool SpellInfo::_IsPositiveEffect(uint32 effIndex, bool deep) const
}
default:
break;
- }
+ }
- // non-positive targets
- if (!_IsPositiveTarget(effect->TargetA.GetTarget(), effect->TargetB.GetTarget()))
- return false;
+ // non-positive targets
+ if (!_IsPositiveTarget(effect->TargetA.GetTarget(), effect->TargetB.GetTarget()))
+ return false;
- // negative spell if triggered spell is negative
- if (!deep && !effect->ApplyAuraName && effect->TriggerSpell)
- {
- if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell))
+ // negative spell if triggered spell is negative
+ if (!deep && !effect->ApplyAuraName && effect->TriggerSpell)
+ {
+ if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, Difficulty))
if (!spellTriggeredProto->_IsPositiveSpell())
return false;
- }
}
}
+
// ok, positive
return true;
}
@@ -4635,93 +4511,20 @@ bool SpellInfo::_IsPositiveTarget(uint32 targetA, uint32 targetB)
void SpellInfo::_UnloadImplicitTargetConditionLists()
{
// find the same instances of ConditionList and delete them.
- for (auto itr = _effects.begin(); itr != _effects.end(); ++itr)
+ for (uint32 i = 0; i < _effects.size(); ++i)
{
- for (uint32 i = 0; i < itr->second.size(); ++i)
+ if (SpellEffectInfo const* effect = _effects[i])
{
- if (SpellEffectInfo const* effect = itr->second[i])
- {
- ConditionContainer* cur = effect->ImplicitTargetConditions;
- if (!cur)
- continue;
- for (uint8 j = i; j < itr->second.size(); ++j)
- {
- if (SpellEffectInfo const* eff = itr->second[j])
- {
- if (eff->ImplicitTargetConditions == cur)
- const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = NULL;
- }
- }
- delete cur;
- }
- }
- }
-}
-
-SpellEffectInfoVector SpellInfo::GetEffectsForDifficulty(uint32 difficulty) const
-{
- SpellEffectInfoVector effList;
-
- // downscale difficulty if original was not found
- DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
- while (difficultyEntry)
- {
- SpellEffectInfoMap::const_iterator effectItr = _effects.find(difficulty);
- if (effectItr != _effects.end())
- {
- for (SpellEffectInfo const* effect : effectItr->second)
- {
- if (effect)
- {
- if (effect->EffectIndex >= effList.size())
- effList.resize(effect->EffectIndex + 1);
-
- if (!effList[effect->EffectIndex])
- effList[effect->EffectIndex] = effect;
- }
- }
- }
+ ConditionContainer* cur = effect->ImplicitTargetConditions;
+ if (!cur)
+ continue;
- difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
- }
+ for (uint8 j = i; j < _effects.size(); ++j)
+ if (SpellEffectInfo const* eff = _effects[j])
+ if (eff->ImplicitTargetConditions == cur)
+ const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = nullptr;
- // DIFFICULTY_NONE effects are the default effects, always active if current difficulty's effects don't overwrite
- SpellEffectInfoMap::const_iterator itr = _effects.find(DIFFICULTY_NONE);
- if (itr != _effects.end())
- {
- for (SpellEffectInfo const* effect : itr->second)
- {
- if (effect)
- {
- if (effect->EffectIndex >= effList.size())
- effList.resize(effect->EffectIndex + 1);
-
- if (!effList[effect->EffectIndex])
- effList[effect->EffectIndex] = effect;
- }
+ delete cur;
}
}
-
- return effList;
-}
-
-SpellEffectInfo const* SpellInfo::GetEffect(uint32 difficulty, uint32 index) const
-{
- DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
- while (difficultyEntry)
- {
- SpellEffectInfoMap::const_iterator itr = _effects.find(difficulty);
- if (itr != _effects.end())
- if (itr->second.size() > index && itr->second[index])
- return itr->second[index];
-
- difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
- }
-
- SpellEffectInfoMap::const_iterator itr = _effects.find(DIFFICULTY_NONE);
- if (itr != _effects.end())
- if (itr->second.size() > index)
- return itr->second[index];
-
- return nullptr;
}
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index e4b8709308b..4af84e40376 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -365,7 +365,7 @@ public:
RealPointsPerLevel(0), BasePoints(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0),
BonusCoefficient(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), PositionFacing(0),
RadiusEntry(NULL), ChainTargets(0), ItemType(0), TriggerSpell(0), BonusCoefficientFromAP(0.0f), ImplicitTargetConditions(NULL) { }
- SpellEffectInfo(SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* effect);
+ SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const* effect);
bool IsEffect() const;
bool IsEffect(SpellEffectName effectName) const;
@@ -410,10 +410,6 @@ private:
};
typedef std::vector<SpellEffectInfo const*> SpellEffectInfoVector;
-typedef std::unordered_map<uint32, SpellEffectInfoVector> SpellEffectInfoMap;
-
-typedef std::vector<SpellEffectEntry const*> SpellEffectEntryVector;
-typedef std::unordered_map<uint32, SpellEffectEntryVector> SpellEffectEntryMap;
typedef std::vector<SpellXSpellVisualEntry const*> SpellVisualVector;
typedef std::unordered_map<uint32, SpellVisualVector> SpellVisualMap;
@@ -442,6 +438,7 @@ class TC_GAME_API SpellInfo
public:
uint32 Id;
+ ::Difficulty Difficulty;
uint32 CategoryId;
uint32 Dispel;
uint32 Mechanic;
@@ -492,7 +489,7 @@ class TC_GAME_API SpellInfo
uint32 BaseLevel;
uint32 SpellLevel;
SpellDurationEntry const* DurationEntry;
- std::vector<SpellPowerEntry const*> PowerCosts;
+ std::array<SpellPowerEntry const*, MAX_POWERS_PER_SPELL> PowerCosts;
uint32 RangeIndex;
SpellRangeEntry const* RangeEntry;
float Speed;
@@ -533,18 +530,15 @@ class TC_GAME_API SpellInfo
uint32 ExplicitTargetMask;
SpellChainNode const* ChainEntry;
- SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals);
+ SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, SpellInfoLoadHelper const& data, SpellVisualVector&& visuals);
~SpellInfo();
uint32 GetCategory() const;
- bool HasEffect(uint32 difficulty, SpellEffectName effect) const;
bool HasEffect(SpellEffectName effect) const;
- bool HasAura(uint32 difficulty, AuraType aura) const;
- bool HasAreaAuraEffect(uint32 difficulty) const;
+ bool HasAura(AuraType aura) const;
bool HasAreaAuraEffect() const;
bool HasOnlyDamageEffects() const;
bool HasTargetType(::Targets target) const;
- bool HasTargetType(uint32 difficulty, ::Targets target) const;
bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }
@@ -571,20 +565,20 @@ class TC_GAME_API SpellInfo
bool IsExplicitDiscovery() const;
bool IsLootCrafting() const;
bool IsQuestTame() const;
- bool IsProfession(uint32 difficulty = DIFFICULTY_NONE) const;
- bool IsPrimaryProfession(uint32 difficulty = DIFFICULTY_NONE) const;
- bool IsPrimaryProfessionFirstRank(uint32 difficulty = DIFFICULTY_NONE) const;
+ bool IsProfession() const;
+ bool IsPrimaryProfession() const;
+ bool IsPrimaryProfessionFirstRank() const;
bool IsAbilityOfSkillType(uint32 skillType) const;
- bool IsAffectingArea(uint32 difficulty) const;
- bool IsTargetingArea(uint32 difficulty) const;
+ bool IsAffectingArea() const;
+ bool IsTargetingArea() const;
bool NeedsExplicitUnitTarget() const;
- bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const;
+ bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const;
bool IsPassive() const;
bool IsAutocastable() const;
bool IsStackableWithRanks() const;
- bool IsPassiveStackableWithRanks(uint32 difficulty) const;
+ bool IsPassiveStackableWithRanks() const;
bool IsMultiSlotAura() const;
bool IsStackableOnOneSlotWithDifferentCasters() const;
bool IsCooldownStartedOnEvent() const;
@@ -632,7 +626,7 @@ class TC_GAME_API SpellInfo
uint32 GetAllEffectsMechanicMask() const;
uint32 GetEffectMechanicMask(uint32 effIndex) const;
uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const;
- Mechanics GetEffectMechanic(uint32 effIndex, uint32 difficulty) const;
+ Mechanics GetEffectMechanic(uint32 effIndex) const;
//bool HasAnyEffectMechanic() const;
uint32 GetDispelMask() const;
static uint32 GetDispelMask(DispelType type);
@@ -648,7 +642,7 @@ class TC_GAME_API SpellInfo
int32 GetDuration() const;
int32 GetMaxDuration() const;
- uint32 GetMaxTicks(uint32 difficulty) const;
+ uint32 GetMaxTicks() const;
uint32 CalcCastTime(uint8 level = 0, Spell* spell = nullptr) const;
uint32 GetRecoveryTime() const;
@@ -671,9 +665,8 @@ class TC_GAME_API SpellInfo
uint32 GetSpellXSpellVisualId(Unit const* caster = nullptr) const;
uint32 GetSpellVisual(Unit const* caster = nullptr) const;
- SpellEffectInfoVector GetEffectsForDifficulty(uint32 difficulty) const;
- SpellEffectInfo const* GetEffect(uint32 difficulty, uint32 index) const;
- SpellEffectInfo const* GetEffect(uint32 index) const { return GetEffect(DIFFICULTY_NONE, index); }
+ SpellEffectInfoVector const& GetEffects() const { return _effects; }
+ SpellEffectInfo const* GetEffect(uint32 index) const { return index < _effects.size() ? _effects[index] : nullptr; }
// spell diminishing returns
DiminishingGroup GetDiminishingReturnsGroupForSpell() const;
@@ -704,9 +697,8 @@ class TC_GAME_API SpellInfo
void _UnloadSpellEffects();
private:
- SpellEffectInfoMap _effects;
- SpellVisualMap _visuals;
- bool _hasPowerDifficultyData;
+ SpellEffectInfoVector _effects;
+ SpellVisualVector _visuals;
SpellSpecificType _spellSpecific;
AuraStateType _auraState;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index c00b07a157f..1e2bc42c17d 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -32,6 +32,36 @@
#include "SpellAuraDefines.h"
#include "SpellInfo.h"
#include <G3D/g3dmath.h>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/composite_key.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/member.hpp>
+
+namespace
+{
+ struct SpellIdDifficultyIndex;
+ struct SpellIdIndex;
+
+ boost::multi_index::multi_index_container<
+ SpellInfo,
+ boost::multi_index::indexed_by<
+ boost::multi_index::hashed_unique<
+ boost::multi_index::tag<SpellIdDifficultyIndex>,
+ boost::multi_index::composite_key<
+ SpellInfo,
+ boost::multi_index::member<SpellInfo, uint32, &SpellInfo::Id>,
+ boost::multi_index::member<SpellInfo, Difficulty, &SpellInfo::Difficulty>
+ >
+ >,
+ boost::multi_index::hashed_non_unique<
+ boost::multi_index::tag<SpellIdIndex>,
+ boost::multi_index::member<SpellInfo, uint32, &SpellInfo::Id>
+ >
+ >
+ > mSpellInfoMap;
+
+ std::unordered_map<std::pair<uint32, Difficulty>, SpellProcEntry> mSpellProcMap;
+}
PetFamilySpellsStore sPetFamilySpellsStore;
@@ -80,7 +110,7 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg
bool needCheckReagents = false;
// check effects
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -128,7 +158,7 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg
}
case SPELL_EFFECT_LEARN_SPELL:
{
- SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(effect->TriggerSpell);
+ SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE);
if (!IsSpellValid(spellInfo2, player, msg))
{
if (msg)
@@ -425,12 +455,25 @@ SpellGroupStackRule SpellMgr::GetSpellGroupStackRule(SpellGroup group) const
return SPELL_GROUP_STACK_RULE_DEFAULT;
}
-SpellProcEntry const* SpellMgr::GetSpellProcEntry(uint32 spellId) const
+SpellProcEntry const* SpellMgr::GetSpellProcEntry(SpellInfo const* spellInfo) const
{
- SpellProcMap::const_iterator itr = mSpellProcMap.find(spellId);
- if (itr != mSpellProcMap.end())
- return &itr->second;
- return NULL;
+ SpellProcEntry const* procEntry = Trinity::Containers::MapGetValuePtr(mSpellProcMap, { spellInfo->Id, spellInfo->Difficulty });
+ if (procEntry)
+ return procEntry;
+
+ if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(spellInfo->Difficulty))
+ {
+ do
+ {
+ procEntry = Trinity::Containers::MapGetValuePtr(mSpellProcMap, { spellInfo->Id, Difficulty(difficulty->FallbackDifficultyID) });
+ if (procEntry)
+ return procEntry;
+
+ difficulty = sDifficultyStore.LookupEntry(difficulty->FallbackDifficultyID);
+ } while (difficulty);
+ }
+
+ return nullptr;
}
bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo)
@@ -619,6 +662,44 @@ SpellAreaForQuestAreaMapBounds SpellMgr::GetSpellAreaForQuestAreaMapBounds(uint3
return mSpellAreaForQuestAreaMap.equal_range(std::pair<uint32, uint32>(area_id, quest_id));
}
+SpellInfo const* SpellMgr::GetSpellInfo(uint32 spellId, Difficulty difficulty) const
+{
+ auto itr = mSpellInfoMap.find(boost::make_tuple(spellId, difficulty));
+ if (itr != mSpellInfoMap.end())
+ return &*itr;
+
+ if (DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty))
+ {
+ do
+ {
+ itr = mSpellInfoMap.find(boost::make_tuple(spellId, Difficulty(difficultyEntry->FallbackDifficultyID)));
+ if (itr != mSpellInfoMap.end())
+ return &*itr;
+
+ difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
+ } while (difficultyEntry);
+ }
+
+ return nullptr;
+}
+
+auto _GetSpellInfo(uint32 spellId)
+{
+ return Trinity::Containers::MakeIteratorPair(mSpellInfoMap.get<SpellIdIndex>().equal_range(spellId));
+}
+
+void SpellMgr::ForEachSpellInfo(std::function<void(SpellInfo const*)> callback)
+{
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
+ callback(&spellInfo);
+}
+
+void SpellMgr::ForEachSpellInfoDifficulty(uint32 spellId, std::function<void(SpellInfo const*)> callback)
+{
+ for (SpellInfo const& spellInfo : _GetSpellInfo(spellId))
+ callback(&spellInfo);
+}
+
bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 newArea) const
{
if (gender != GENDER_NONE) // is not expected gender
@@ -712,7 +793,8 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
void SpellMgr::UnloadSpellInfoChains()
{
for (SpellChainMap::iterator itr = mSpellChains.begin(); itr != mSpellChains.end(); ++itr)
- mSpellInfoMap[itr->first]->ChainEntry = NULL;
+ for (SpellInfo const& spellInfo : _GetSpellInfo(itr->first))
+ const_cast<SpellInfo&>(spellInfo).ChainEntry = NULL;
mSpellChains.clear();
}
@@ -728,7 +810,7 @@ void SpellMgr::LoadSpellRanks()
if (!skillAbility->SupercedesSpell)
continue;
- if (!GetSpellInfo(skillAbility->SupercedesSpell) || !GetSpellInfo(skillAbility->Spell))
+ if (!GetSpellInfo(skillAbility->SupercedesSpell, DIFFICULTY_NONE) || !GetSpellInfo(skillAbility->Spell, DIFFICULTY_NONE))
continue;
chains[skillAbility->SupercedesSpell] = skillAbility->Spell;
@@ -741,29 +823,31 @@ void SpellMgr::LoadSpellRanks()
if (hasPrev.count(itr->first))
continue;
- SpellInfo const* first = AssertSpellInfo(itr->first);
- SpellInfo const* next = AssertSpellInfo(itr->second);
+ SpellInfo const* first = AssertSpellInfo(itr->first, DIFFICULTY_NONE);
+ SpellInfo const* next = AssertSpellInfo(itr->second, DIFFICULTY_NONE);
mSpellChains[itr->first].first = first;
mSpellChains[itr->first].prev = nullptr;
mSpellChains[itr->first].next = next;
mSpellChains[itr->first].last = next;
mSpellChains[itr->first].rank = 1;
- mSpellInfoMap[itr->first]->ChainEntry = &mSpellChains[itr->first];
+ for (SpellInfo const& difficultyInfo : _GetSpellInfo(itr->first))
+ const_cast<SpellInfo&>(difficultyInfo).ChainEntry = &mSpellChains[itr->first];
mSpellChains[itr->second].first = first;
mSpellChains[itr->second].prev = first;
mSpellChains[itr->second].next = nullptr;
mSpellChains[itr->second].last = next;
mSpellChains[itr->second].rank = 2;
- mSpellInfoMap[itr->second]->ChainEntry = &mSpellChains[itr->second];
+ for (SpellInfo const& difficultyInfo : _GetSpellInfo(itr->second))
+ const_cast<SpellInfo&>(difficultyInfo).ChainEntry = &mSpellChains[itr->second];
uint8 rank = 3;
auto nextItr = chains.find(itr->second);
while (nextItr != chains.end())
{
- SpellInfo const* prev = AssertSpellInfo(nextItr->first); // already checked in previous iteration (or above, in case this is the first one)
- SpellInfo const* last = AssertSpellInfo(nextItr->second);
+ SpellInfo const* prev = AssertSpellInfo(nextItr->first, DIFFICULTY_NONE); // already checked in previous iteration (or above, in case this is the first one)
+ SpellInfo const* last = AssertSpellInfo(nextItr->second, DIFFICULTY_NONE);
mSpellChains[nextItr->first].next = last;
@@ -772,7 +856,8 @@ void SpellMgr::LoadSpellRanks()
mSpellChains[nextItr->second].next = nullptr;
mSpellChains[nextItr->second].last = last;
mSpellChains[nextItr->second].rank = rank++;
- mSpellInfoMap[nextItr->second]->ChainEntry = &mSpellChains[nextItr->second];
+ for (SpellInfo const& difficultyInfo : _GetSpellInfo(nextItr->second))
+ const_cast<SpellInfo&>(difficultyInfo).ChainEntry = &mSpellChains[nextItr->second];
// fill 'last'
do
@@ -814,14 +899,14 @@ void SpellMgr::LoadSpellRequired()
uint32 spell_req = fields[1].GetUInt32();
// check if chain is made with valid first spell
- SpellInfo const* spell = GetSpellInfo(spell_id);
+ SpellInfo const* spell = GetSpellInfo(spell_id, DIFFICULTY_NONE);
if (!spell)
{
TC_LOG_ERROR("sql.sql", "spell_id %u in `spell_required` table could not be found in dbc, skipped.", spell_id);
continue;
}
- SpellInfo const* reqSpell = GetSpellInfo(spell_req);
+ SpellInfo const* reqSpell = GetSpellInfo(spell_req, DIFFICULTY_NONE);
if (!reqSpell)
{
TC_LOG_ERROR("sql.sql", "req_spell %u in `spell_required` table could not be found in dbc, skipped.", spell_req);
@@ -857,12 +942,12 @@ void SpellMgr::LoadSpellLearnSkills()
// search auto-learned skills and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0;
- for (SpellInfo const* entry : mSpellInfoMap)
+ for (SpellInfo const& entry : mSpellInfoMap)
{
- if (!entry)
+ if (entry.Difficulty != DIFFICULTY_NONE)
continue;
- for (SpellEffectInfo const* effect : entry->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : entry.GetEffects())
{
if (!effect)
continue;
@@ -889,7 +974,7 @@ void SpellMgr::LoadSpellLearnSkills()
continue;
}
- mSpellLearnSkills[entry->Id] = dbc_node;
+ mSpellLearnSkills[entry.Id] = dbc_node;
++dbc_count;
break;
}
@@ -925,14 +1010,14 @@ void SpellMgr::LoadSpellLearnSpells()
node.Active = fields[2].GetBool();
node.AutoLearned = false;
- SpellInfo const* spellInfo = GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = GetSpellInfo(spell_id, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_learn_spell` does not exist.", spell_id);
continue;
}
- if (!GetSpellInfo(node.Spell))
+ if (!GetSpellInfo(node.Spell, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_learn_spell` learning non-existing spell %u.", spell_id, node.Spell);
continue;
@@ -954,14 +1039,12 @@ void SpellMgr::LoadSpellLearnSpells()
// search auto-learned spells and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0;
- for (uint32 spell = 0; spell < GetSpellInfoStoreSize(); ++spell)
+ for (SpellInfo const& entry : mSpellInfoMap)
{
- SpellInfo const* entry = GetSpellInfo(spell);
-
- if (!entry)
+ if (entry.Difficulty != DIFFICULTY_NONE)
continue;
- for (SpellEffectInfo const* effect : entry->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : entry.GetEffects())
{
if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL)
{
@@ -971,15 +1054,15 @@ void SpellMgr::LoadSpellLearnSpells()
dbc_node.OverridesSpell = 0;
// ignore learning not existed spells (broken/outdated/or generic learnig spell 483
- if (!GetSpellInfo(dbc_node.Spell))
+ if (!GetSpellInfo(dbc_node.Spell, DIFFICULTY_NONE))
continue;
// talent or passive spells or skill-step spells auto-cast and not need dependent learning,
// pet teaching spells must not be dependent learning (cast)
// other required explicit dependent learning
- dbc_node.AutoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry->HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP);
+ dbc_node.AutoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry.HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry.IsPassive() || entry.HasEffect(SPELL_EFFECT_SKILL_STEP);
- SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell);
+ SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(entry.Id);
bool found = false;
for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
@@ -987,7 +1070,7 @@ void SpellMgr::LoadSpellLearnSpells()
if (itr->second.Spell == dbc_node.Spell)
{
TC_LOG_ERROR("sql.sql", "The spell %u is an auto-learn spell %u in spell.dbc and the record in `spell_learn_spell` is redundant. Please update your DB.",
- spell, dbc_node.Spell);
+ entry.Id, dbc_node.Spell);
found = true;
break;
}
@@ -995,7 +1078,7 @@ void SpellMgr::LoadSpellLearnSpells()
if (!found) // add new spell-spell pair if not found
{
- mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell, dbc_node));
+ mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(entry.Id, dbc_node));
++dbc_count;
}
}
@@ -1004,7 +1087,7 @@ void SpellMgr::LoadSpellLearnSpells()
for (SpellLearnSpellEntry const* spellLearnSpell : sSpellLearnSpellStore)
{
- if (!GetSpellInfo(spellLearnSpell->SpellID))
+ if (!GetSpellInfo(spellLearnSpell->SpellID, DIFFICULTY_NONE))
continue;
SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spellLearnSpell->LearnSpellID);
@@ -1092,7 +1175,7 @@ void SpellMgr::LoadSpellTargetPositions()
continue;
}
- SpellInfo const* spellInfo = GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Spell (Id: %u) listed in `spell_target_position` does not exist.", spellId);
@@ -1200,7 +1283,7 @@ void SpellMgr::LoadSpellGroups()
}
else
{
- SpellInfo const* spellInfo = GetSpellInfo(itr->second);
+ SpellInfo const* spellInfo = GetSpellInfo(itr->second, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_group` does not exist", itr->second);
@@ -1302,8 +1385,8 @@ void SpellMgr::LoadSpellGroupStackRules()
for (uint32 spellId : spellIds)
{
- SpellInfo const* spellInfo = AssertSpellInfo(spellId);
- for (SpellEffectInfo const* effectInfo : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ SpellInfo const* spellInfo = AssertSpellInfo(spellId, DIFFICULTY_NONE);
+ for (SpellEffectInfo const* effectInfo : spellInfo->GetEffects())
{
if (!effectInfo->IsAura())
continue;
@@ -1351,14 +1434,14 @@ void SpellMgr::LoadSpellGroupStackRules()
// re-check spells against guessed group
for (uint32 spellId : spellIds)
{
- SpellInfo const* spellInfo = AssertSpellInfo(spellId);
+ SpellInfo const* spellInfo = AssertSpellInfo(spellId, DIFFICULTY_NONE);
bool found = false;
while (spellInfo)
{
for (uint32 auraType : auraTypes)
{
- if (spellInfo->HasAura(DIFFICULTY_NONE, AuraType(auraType)))
+ if (spellInfo->HasAura(AuraType(auraType)))
{
found = true;
break;
@@ -1410,7 +1493,7 @@ void SpellMgr::LoadSpellProcs()
spellId = -spellId;
}
- SpellInfo const* spellInfo = GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_proc` does not exist", spellId);
@@ -1450,7 +1533,7 @@ void SpellMgr::LoadSpellProcs()
while (spellInfo)
{
- if (mSpellProcMap.find(spellInfo->Id) != mSpellProcMap.end())
+ if (mSpellProcMap.find({ spellInfo->Id, spellInfo->Difficulty }) != mSpellProcMap.end())
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_proc` already has its first rank in the table.", spellInfo->Id);
break;
@@ -1500,7 +1583,7 @@ void SpellMgr::LoadSpellProcs()
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);
- mSpellProcMap[spellInfo->Id] = procEntry;
+ mSpellProcMap[{ spellInfo->Id, spellInfo->Difficulty }] = procEntry;
if (allRanks)
spellInfo = spellInfo->GetNextRankSpell();
@@ -1608,22 +1691,19 @@ void SpellMgr::LoadSpellProcs()
count = 0;
oldMSTime = getMSTime();
- for (SpellInfo const* spellInfo : mSpellInfoMap)
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
{
- if (!spellInfo)
- continue;
-
// Data already present in DB, overwrites default proc
- if (mSpellProcMap.find(spellInfo->Id) != mSpellProcMap.end())
+ if (mSpellProcMap.find({ spellInfo.Id, spellInfo.Difficulty }) != mSpellProcMap.end())
continue;
// Nothing to do if no flags set
- if (!spellInfo->ProcFlags)
+ if (!spellInfo.ProcFlags)
continue;
bool addTriggerFlag = false;
uint32 procSpellTypeMask = PROC_SPELL_TYPE_NONE;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo.GetEffects())
{
if (!effect || !effect->IsEffect())
continue;
@@ -1641,7 +1721,7 @@ void SpellMgr::LoadSpellProcs()
// 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)
+ if (!addTriggerFlag && (spellInfo.ProcFlags & TAKEN_HIT_PROC_FLAG_MASK) != 0)
{
switch (auraName)
{
@@ -1658,11 +1738,11 @@ void SpellMgr::LoadSpellProcs()
if (!procSpellTypeMask)
{
- for (SpellEffectInfo const* effectInfo : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effectInfo : spellInfo.GetEffects())
{
if (effectInfo && effectInfo->IsAura())
{
- TC_LOG_ERROR("sql.sql", "Spell Id %u has DBC ProcFlags %u, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.", spellInfo->Id, spellInfo->ProcFlags);
+ TC_LOG_ERROR("sql.sql", "Spell Id %u has DBC ProcFlags %u, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.", spellInfo.Id, spellInfo.ProcFlags);
break;
}
}
@@ -1672,20 +1752,20 @@ void SpellMgr::LoadSpellProcs()
SpellProcEntry procEntry;
procEntry.SchoolMask = 0;
- procEntry.ProcFlags = spellInfo->ProcFlags;
+ procEntry.ProcFlags = spellInfo.ProcFlags;
procEntry.SpellFamilyName = 0;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo.GetEffects())
if (effect && effect->IsEffect() && isTriggerAura[effect->ApplyAuraName])
procEntry.SpellFamilyMask |= effect->SpellClassMask;
if (procEntry.SpellFamilyMask)
- procEntry.SpellFamilyName = spellInfo->SpellFamilyName;
+ procEntry.SpellFamilyName = spellInfo.SpellFamilyName;
procEntry.SpellTypeMask = procSpellTypeMask;
procEntry.SpellPhaseMask = PROC_SPELL_PHASE_HIT;
procEntry.HitMask = PROC_HIT_NONE; // uses default proc @see SpellMgr::CanSpellTriggerProcOnEvent
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo.GetEffects())
{
if (!effect || !effect->IsAura())
continue;
@@ -1713,17 +1793,17 @@ void SpellMgr::LoadSpellProcs()
procEntry.AttributesMask = 0;
procEntry.DisableEffectsMask = 0;
- if (spellInfo->ProcFlags & PROC_FLAG_KILL)
+ if (spellInfo.ProcFlags & PROC_FLAG_KILL)
procEntry.AttributesMask |= PROC_ATTR_REQ_EXP_OR_HONOR;
if (addTriggerFlag)
procEntry.AttributesMask |= PROC_ATTR_TRIGGERED_CAN_PROC;
procEntry.ProcsPerMinute = 0;
- procEntry.Chance = spellInfo->ProcChance;
- procEntry.Cooldown = Milliseconds(spellInfo->ProcCooldown);
- procEntry.Charges = spellInfo->ProcCharges;
+ procEntry.Chance = spellInfo.ProcChance;
+ procEntry.Cooldown = Milliseconds(spellInfo.ProcCooldown);
+ procEntry.Charges = spellInfo.ProcCharges;
- mSpellProcMap[spellInfo->Id] = procEntry;
+ mSpellProcMap[{ spellInfo.Id, spellInfo.Difficulty }] = procEntry;
++count;
}
@@ -1751,7 +1831,7 @@ void SpellMgr::LoadSpellThreats()
uint32 entry = fields[0].GetUInt32();
- if (!GetSpellInfo(entry))
+ if (!GetSpellInfo(entry, DIFFICULTY_NONE))
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_threat` does not exist.", entry);
continue;
@@ -1819,7 +1899,7 @@ void SpellMgr::LoadSpellPetAuras()
itr->second.AddAura(pet, aura);
else
{
- SpellInfo const* spellInfo = GetSpellInfo(spell);
+ SpellInfo const* spellInfo = GetSpellInfo(spell, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_pet_auras` does not exist.", spell);
@@ -1840,7 +1920,7 @@ void SpellMgr::LoadSpellPetAuras()
continue;
}
- SpellInfo const* spellInfo2 = GetSpellInfo(aura);
+ SpellInfo const* spellInfo2 = GetSpellInfo(aura, DIFFICULTY_NONE);
if (!spellInfo2)
{
TC_LOG_ERROR("sql.sql", "The aura %u listed in `spell_pet_auras` does not exist.", aura);
@@ -1866,20 +1946,16 @@ void SpellMgr::LoadEnchantCustomAttr()
mEnchantCustomAttr.resize(size);
for (uint32 i = 0; i < size; ++i)
- mEnchantCustomAttr[i] = 0;
+ mEnchantCustomAttr[i] = false;
uint32 count = 0;
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
{
- SpellInfo const* spellInfo = GetSpellInfo(i);
- if (!spellInfo)
- continue;
-
/// @todo find a better check
- if (!spellInfo->HasAttribute(SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT))
+ if (!spellInfo.HasAttribute(SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !spellInfo.HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT))
continue;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo.GetEffects())
{
if (effect && effect->Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY)
{
@@ -1963,7 +2039,7 @@ void SpellMgr::LoadSpellLinked()
int32 effect = fields[1].GetInt32();
int32 type = fields[2].GetUInt8();
- SpellInfo const* spellInfo = GetSpellInfo(abs(trigger));
+ SpellInfo const* spellInfo = GetSpellInfo(abs(trigger), DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_linked_spell` does not exist.", abs(trigger));
@@ -1971,13 +2047,13 @@ void SpellMgr::LoadSpellLinked()
}
if (effect >= 0)
- for (SpellEffectInfo const* eff : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* eff : spellInfo->GetEffects())
{
if (eff && eff->CalcValue() == abs(effect))
TC_LOG_ERROR("sql.sql", "The spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack)", abs(trigger), abs(effect), eff->EffectIndex);
}
- spellInfo = GetSpellInfo(abs(effect));
+ spellInfo = GetSpellInfo(abs(effect), DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_linked_spell` does not exist.", abs(effect));
@@ -2025,17 +2101,13 @@ void SpellMgr::LoadPetLevelupSpellMap()
if (!skillLine)
continue;
- //if (skillLine->skillId != creatureFamily->SkillLine[0] &&
- // (!creatureFamily->SkillLine[1] || skillLine->skillId != creatureFamily->SkillLine[1]))
- // continue;
-
if (skillLine->SkillLine != creatureFamily->SkillLine[j])
continue;
if (skillLine->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN)
continue;
- SpellInfo const* spell = GetSpellInfo(skillLine->Spell);
+ SpellInfo const* spell = GetSpellInfo(skillLine->Spell, DIFFICULTY_NONE);
if (!spell) // not exist or triggered or talent
continue;
@@ -2115,13 +2187,11 @@ void SpellMgr::LoadPetDefaultSpells()
oldMSTime = getMSTime();
// different summon spells
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
+ for (SpellInfo const& spellEntry : mSpellInfoMap)
{
- SpellInfo const* spellEntry = GetSpellInfo(i);
- if (!spellEntry)
- continue;
+ if (spellEntry.Difficulty != DIFFICULTY_NONE)
- for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellEntry.GetEffects())
{
if (effect && (effect->Effect == SPELL_EFFECT_SUMMON || effect->Effect == SPELL_EFFECT_SUMMON_PET))
{
@@ -2187,7 +2257,7 @@ void SpellMgr::LoadSpellAreas()
spellArea.gender = Gender(fields[8].GetUInt8());
spellArea.flags = fields[9].GetUInt8();
- if (SpellInfo const* spellInfo = GetSpellInfo(spell))
+ if (SpellInfo const* spellInfo = GetSpellInfo(spell, DIFFICULTY_NONE))
{
if (spellArea.flags & SPELL_AREA_FLAG_AUTOCAST)
const_cast<SpellInfo*>(spellInfo)->Attributes |= SPELL_ATTR0_CANT_CANCEL;
@@ -2251,7 +2321,7 @@ void SpellMgr::LoadSpellAreas()
if (spellArea.auraSpell)
{
- SpellInfo const* spellInfo = GetSpellInfo(abs(spellArea.auraSpell));
+ SpellInfo const* spellInfo = GetSpellInfo(abs(spellArea.auraSpell), DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_area` has wrong aura spell (%u) requirement", spell, abs(spellArea.auraSpell));
@@ -2351,8 +2421,8 @@ void SpellMgr::LoadSpellInfoStore()
uint32 oldMSTime = getMSTime();
UnloadSpellInfoStore();
- mSpellInfoMap.resize(sSpellNameStore.GetNumRows(), NULL);
- std::unordered_map<uint32, SpellInfoLoadHelper> loadData;
+
+ std::unordered_map<std::pair<uint32, Difficulty>, SpellInfoLoadHelper> loadData;
std::unordered_map<int32, BattlePetSpeciesEntry const*> battlePetSpeciesByCreature;
std::unordered_map<uint32, BattlePetSpeciesEntry const*> battlePetSpeciesBySpellId;
@@ -2360,9 +2430,6 @@ void SpellMgr::LoadSpellInfoStore()
if (battlePetSpecies->CreatureID)
battlePetSpeciesByCreature[battlePetSpecies->CreatureID] = battlePetSpecies;
- std::unordered_map<int32, SpellEffectEntryMap> effectsBySpell;
- std::unordered_map<uint32, SpellVisualMap> visualsBySpell;
-
for (SpellEffectEntry const* effect : sSpellEffectStore)
{
ASSERT(effect->EffectIndex < MAX_SPELL_EFFECTS, "MAX_SPELL_EFFECTS must be at least %d", effect->EffectIndex + 1);
@@ -2371,11 +2438,7 @@ void SpellMgr::LoadSpellInfoStore()
ASSERT(effect->ImplicitTarget[0] < TOTAL_SPELL_TARGETS, "TOTAL_SPELL_TARGETS must be at least %u", effect->ImplicitTarget[0] + 1);
ASSERT(effect->ImplicitTarget[1] < TOTAL_SPELL_TARGETS, "TOTAL_SPELL_TARGETS must be at least %u", effect->ImplicitTarget[1] + 1);
- SpellEffectEntryVector& effectsForDifficulty = effectsBySpell[effect->SpellID][effect->DifficultyID];
- if (effectsForDifficulty.size() <= std::size_t(effect->EffectIndex))
- effectsForDifficulty.resize(std::size_t(effect->EffectIndex + 1));
-
- effectsForDifficulty[effect->EffectIndex] = effect;
+ loadData[{ effect->SpellID, Difficulty(effect->DifficultyID) }].Effects[effect->EffectIndex] = effect;
if (effect->Effect == SPELL_EFFECT_SUMMON)
if (SummonPropertiesEntry const* summonProperties = sSummonPropertiesStore.LookupEntry(effect->EffectMiscValue[1]))
@@ -2385,68 +2448,131 @@ void SpellMgr::LoadSpellInfoStore()
}
for (SpellAuraOptionsEntry const* auraOptions : sSpellAuraOptionsStore)
- if (!auraOptions->DifficultyID) // TODO: implement
- loadData[auraOptions->SpellID].AuraOptions = auraOptions;
+ loadData[{ auraOptions->SpellID, Difficulty(auraOptions->DifficultyID) }].AuraOptions = auraOptions;
for (SpellAuraRestrictionsEntry const* auraRestrictions : sSpellAuraRestrictionsStore)
- if (!auraRestrictions->DifficultyID) // TODO: implement
- loadData[auraRestrictions->SpellID].AuraRestrictions = auraRestrictions;
+ loadData[{ auraRestrictions->SpellID, Difficulty(auraRestrictions->DifficultyID) }].AuraRestrictions = auraRestrictions;
for (SpellCastingRequirementsEntry const* castingRequirements : sSpellCastingRequirementsStore)
- loadData[castingRequirements->SpellID].CastingRequirements = castingRequirements;
+ loadData[{ castingRequirements->SpellID, DIFFICULTY_NONE }].CastingRequirements = castingRequirements;
for (SpellCategoriesEntry const* categories : sSpellCategoriesStore)
- if (!categories->DifficultyID) // TODO: implement
- loadData[categories->SpellID].Categories = categories;
+ loadData[{ categories->SpellID, Difficulty(categories->DifficultyID) }].Categories = categories;
for (SpellClassOptionsEntry const* classOptions : sSpellClassOptionsStore)
- loadData[classOptions->SpellID].ClassOptions = classOptions;
+ loadData[{ classOptions->SpellID, DIFFICULTY_NONE }].ClassOptions = classOptions;
for (SpellCooldownsEntry const* cooldowns : sSpellCooldownsStore)
- if (!cooldowns->DifficultyID) // TODO: implement
- loadData[cooldowns->SpellID].Cooldowns = cooldowns;
+ loadData[{ cooldowns->SpellID, Difficulty(cooldowns->DifficultyID) }].Cooldowns = cooldowns;
for (SpellEquippedItemsEntry const* equippedItems : sSpellEquippedItemsStore)
- loadData[equippedItems->SpellID].EquippedItems = equippedItems;
+ loadData[{ equippedItems->SpellID, DIFFICULTY_NONE }].EquippedItems = equippedItems;
for (SpellInterruptsEntry const* interrupts : sSpellInterruptsStore)
- if (!interrupts->DifficultyID) // TODO: implement
- loadData[interrupts->SpellID].Interrupts = interrupts;
+ loadData[{ interrupts->SpellID, Difficulty(interrupts->DifficultyID) }].Interrupts = interrupts;
for (SpellLevelsEntry const* levels : sSpellLevelsStore)
- if (!levels->DifficultyID) // TODO: implement
- loadData[levels->SpellID].Levels = levels;
+ loadData[{ levels->SpellID, Difficulty(levels->DifficultyID) }].Levels = levels;
for (SpellMiscEntry const* misc : sSpellMiscStore)
- if (!misc->DifficultyID)
- loadData[misc->SpellID].Misc = misc;
+ loadData[{ misc->SpellID, Difficulty(misc->DifficultyID) }].Misc = misc;
+
+ for (SpellPowerEntry const* power : sSpellPowerStore)
+ {
+ Difficulty difficulty = DIFFICULTY_NONE;
+ uint8 index = power->OrderIndex;
+ if (SpellPowerDifficultyEntry const* powerDifficulty = sSpellPowerDifficultyStore.LookupEntry(power->ID))
+ {
+ difficulty = Difficulty(powerDifficulty->DifficultyID);
+ index = powerDifficulty->OrderIndex;
+ }
+
+ loadData[{ power->SpellID, difficulty }].Powers[index] = power;
+ }
for (SpellReagentsEntry const* reagents : sSpellReagentsStore)
- loadData[reagents->SpellID].Reagents = reagents;
+ loadData[{ reagents->SpellID, DIFFICULTY_NONE }].Reagents = reagents;
for (SpellScalingEntry const* scaling : sSpellScalingStore)
- loadData[scaling->SpellID].Scaling = scaling;
+ loadData[{ scaling->SpellID, DIFFICULTY_NONE }].Scaling = scaling;
for (SpellShapeshiftEntry const* shapeshift : sSpellShapeshiftStore)
- loadData[shapeshift->SpellID].Shapeshift = shapeshift;
+ loadData[{ shapeshift->SpellID, DIFFICULTY_NONE }].Shapeshift = shapeshift;
for (SpellTargetRestrictionsEntry const* targetRestrictions : sSpellTargetRestrictionsStore)
- if (!targetRestrictions->DifficultyID) // TODO: implement
- loadData[targetRestrictions->SpellID].TargetRestrictions = targetRestrictions;
+ loadData[{ targetRestrictions->SpellID, Difficulty(targetRestrictions->DifficultyID) }].TargetRestrictions = targetRestrictions;
for (SpellTotemsEntry const* totems : sSpellTotemsStore)
- loadData[totems->SpellID].Totems = totems;
+ loadData[{ totems->SpellID, DIFFICULTY_NONE }].Totems = totems;
for (SpellXSpellVisualEntry const* visual : sSpellXSpellVisualStore)
- visualsBySpell[visual->SpellID][visual->DifficultyID].push_back(visual);
+ {
+ SpellVisualVector& visuals = loadData[{ visual->SpellID, Difficulty(visual->DifficultyID) }].Visuals;
+
+ auto where = std::lower_bound(visuals.begin(), visuals.end(), visual, [](SpellXSpellVisualEntry const* first, SpellXSpellVisualEntry const* second)
+ {
+ return first->CasterPlayerConditionID > second->CasterPlayerConditionID;
+ });
- for (uint32 i = 0; i < sSpellNameStore.GetNumRows(); ++i)
+ // sorted with unconditional visuals being last
+ visuals.insert(where, visual);
+ }
+
+ for (std::pair<std::pair<uint32, Difficulty> const, SpellInfoLoadHelper>& data : loadData)
{
- if (SpellNameEntry const* spellNameEntry = sSpellNameStore.LookupEntry(i))
+ SpellNameEntry const* spellNameEntry = sSpellNameStore.LookupEntry(data.first.first);
+ if (!spellNameEntry)
+ continue;
+
+ SpellVisualVector visuals = data.second.Visuals; // copy, need to ensure source remains unmodified
+
+ // fill blanks
+ if (DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(data.first.second))
{
- loadData[i].Entry = spellNameEntry;
- mSpellInfoMap[i] = new SpellInfo(loadData[i], effectsBySpell[i], std::move(visualsBySpell[i]));
+ do
+ {
+ if (SpellInfoLoadHelper const* fallbackData = Trinity::Containers::MapGetValuePtr(loadData, { data.first.first, Difficulty(difficultyEntry->FallbackDifficultyID) }))
+ {
+ if (!data.second.AuraOptions)
+ data.second.AuraOptions = fallbackData->AuraOptions;
+
+ if (!data.second.AuraRestrictions)
+ data.second.AuraRestrictions = fallbackData->AuraRestrictions;
+
+ if (!data.second.Categories)
+ data.second.Categories = fallbackData->Categories;
+
+ if (!data.second.Cooldowns)
+ data.second.Cooldowns = fallbackData->Cooldowns;
+
+ for (std::size_t i = 0; i < data.second.Effects.size(); ++i)
+ if (!data.second.Effects[i])
+ data.second.Effects[i] = fallbackData->Effects[i];
+
+ if (!data.second.Interrupts)
+ data.second.Interrupts = fallbackData->Interrupts;
+
+ if (!data.second.Levels)
+ data.second.Levels = fallbackData->Levels;
+
+ if (!data.second.Misc)
+ data.second.Misc = fallbackData->Misc;
+
+ for (std::size_t i = 0; i < fallbackData->Powers.size(); ++i)
+ if (!data.second.Powers[i])
+ data.second.Powers[i] = fallbackData->Powers[i];
+
+ if (!data.second.TargetRestrictions)
+ data.second.TargetRestrictions = fallbackData->TargetRestrictions;
+
+ visuals.insert(visuals.end(), fallbackData->Visuals.begin(), fallbackData->Visuals.end());
+ }
+
+ difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
+ } while (difficultyEntry);
}
+
+ mSpellInfoMap.emplace(spellNameEntry, data.first.second, data.second, std::move(visuals));
}
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo store in %u ms", GetMSTimeDiffToNow(oldMSTime));
@@ -2454,24 +2580,19 @@ void SpellMgr::LoadSpellInfoStore()
void SpellMgr::UnloadSpellInfoStore()
{
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
- delete mSpellInfoMap[i];
-
mSpellInfoMap.clear();
}
void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists()
{
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
- if (mSpellInfoMap[i])
- mSpellInfoMap[i]->_UnloadImplicitTargetConditionLists();
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
+ const_cast<SpellInfo&>(spellInfo)._UnloadImplicitTargetConditionLists();
}
void SpellMgr::LoadSpellInfoCustomAttributes()
{
uint32 oldMSTime = getMSTime();
uint32 oldMSTime2 = oldMSTime;
- SpellInfo* spellInfo = NULL;
QueryResult result = WorldDatabase.Query("SELECT entry, attributes FROM spell_custom_attr");
@@ -2487,24 +2608,27 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
uint32 spellId = fields[0].GetUInt32();
uint32 attributes = fields[1].GetUInt32();
- spellInfo = _GetSpellInfo(spellId);
- if (!spellInfo)
+ auto spells = _GetSpellInfo(spellId);
+ if (spells.begin() == spells.end())
{
TC_LOG_ERROR("sql.sql", "Table `spell_custom_attr` has wrong spell (entry: %u), ignored.", spellId);
continue;
}
// TODO: validate attributes
- if (attributes & SPELL_ATTR0_CU_SHARE_DAMAGE)
+ for (SpellInfo const& spellInfo : spells)
{
- if (!spellInfo->HasEffect(SPELL_EFFECT_SCHOOL_DAMAGE))
+ if (attributes & SPELL_ATTR0_CU_SHARE_DAMAGE)
{
- TC_LOG_ERROR("sql.sql", "Spell %u listed in table `spell_custom_attr` with SPELL_ATTR0_CU_SHARE_DAMAGE has no SPELL_EFFECT_SCHOOL_DAMAGE, ignored.", spellId);
- continue;
+ if (!spellInfo.HasEffect(SPELL_EFFECT_SCHOOL_DAMAGE))
+ {
+ TC_LOG_ERROR("sql.sql", "Spell %u listed in table `spell_custom_attr` with SPELL_ATTR0_CU_SHARE_DAMAGE has no SPELL_EFFECT_SCHOOL_DAMAGE, ignored.", spellId);
+ continue;
+ }
}
- }
- spellInfo->AttributesCu |= attributes;
+ const_cast<SpellInfo&>(spellInfo).AttributesCu |= attributes;
+ }
++count;
} while (result->NextRow());
@@ -2516,13 +2640,10 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(i))
talentSpells.insert(talentInfo->SpellID);
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
{
- spellInfo = mSpellInfoMap[i];
- if (!spellInfo)
- continue;
-
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ SpellInfo* spellInfoMutable = const_cast<SpellInfo*>(&spellInfo);
+ for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects())
{
if (!effect)
continue;
@@ -2535,7 +2656,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
case SPELL_AURA_AOE_CHARM:
case SPELL_AURA_MOD_FEAR:
case SPELL_AURA_MOD_STUN:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
break;
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_PERIODIC_DAMAGE:
@@ -2547,7 +2668,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
case SPELL_AURA_OBS_MOD_HEALTH:
case SPELL_AURA_OBS_MOD_POWER:
case SPELL_AURA_POWER_BURN:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
break;
}
@@ -2559,7 +2680,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
case SPELL_EFFECT_HEAL:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_DIRECT_DAMAGE;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_DIRECT_DAMAGE;
break;
case SPELL_EFFECT_POWER_DRAIN:
case SPELL_EFFECT_POWER_BURN:
@@ -2569,17 +2690,17 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
case SPELL_EFFECT_ENERGIZE_PCT:
case SPELL_EFFECT_ENERGIZE:
case SPELL_EFFECT_HEAL_MECHANICAL:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
break;
case SPELL_EFFECT_CHARGE:
case SPELL_EFFECT_CHARGE_DEST:
case SPELL_EFFECT_JUMP:
case SPELL_EFFECT_JUMP_DEST:
case SPELL_EFFECT_LEAP_BACK:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_CHARGE;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_CHARGE;
break;
case SPELL_EFFECT_PICKPOCKET:
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_PICKPOCKET;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_PICKPOCKET;
break;
case SPELL_EFFECT_ENCHANT_ITEM:
case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY:
@@ -2587,7 +2708,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
case SPELL_EFFECT_ENCHANT_HELD_ITEM:
{
// only enchanting profession enchantments procs can stack
- if (IsPartOfSkillLine(SKILL_ENCHANTING, i))
+ if (IsPartOfSkillLine(SKILL_ENCHANTING, spellInfo.Id))
{
uint32 enchantId = effect->MiscValue;
SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId);
@@ -2599,17 +2720,16 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
if (enchant->Effect[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
continue;
- SpellInfo* procInfo = _GetSpellInfo(enchant->EffectArg[s]);
- if (!procInfo)
- continue;
+ for (SpellInfo const& procInfo : _GetSpellInfo(enchant->EffectArg[s]))
+ {
+ // if proced directly from enchantment, not via proc aura
+ // NOTE: Enchant Weapon - Blade Ward also has proc aura spell and is proced directly
+ // however its not expected to stack so this check is good
+ if (procInfo.HasAura(SPELL_AURA_PROC_TRIGGER_SPELL))
+ continue;
- // if proced directly from enchantment, not via proc aura
- // NOTE: Enchant Weapon - Blade Ward also has proc aura spell and is proced directly
- // however its not expected to stack so this check is good
- if (procInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_PROC_TRIGGER_SPELL))
- continue;
-
- procInfo->AttributesCu |= SPELL_ATTR0_CU_ENCHANT_PROC;
+ const_cast<SpellInfo&>(procInfo).AttributesCu |= SPELL_ATTR0_CU_ENCHANT_PROC;
+ }
}
}
break;
@@ -2618,10 +2738,10 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
}
// spells ignoring hit result should not be binary
- if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
+ if (!spellInfoMutable->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
{
bool setFlag = false;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects())
{
if (!effect)
continue;
@@ -2657,23 +2777,23 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
default:
{
// No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag
- if (!effect->CalcValue() && !((effect->Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfo->HasAttribute(SPELL_ATTR0_CU_AURA_CC)) && !spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)))
+ if (!effect->CalcValue() && !((effect->Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfoMutable->HasAttribute(SPELL_ATTR0_CU_AURA_CC)) && !spellInfoMutable->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)))
break;
// Sindragosa Frost Breath
- if (spellInfo->Id == 69649 || spellInfo->Id == 71056 || spellInfo->Id == 71057 || spellInfo->Id == 71058 || spellInfo->Id == 73061 || spellInfo->Id == 73062 || spellInfo->Id == 73063 || spellInfo->Id == 73064)
+ if (spellInfoMutable->Id == 69649 || spellInfoMutable->Id == 71056 || spellInfoMutable->Id == 71057 || spellInfoMutable->Id == 71058 || spellInfoMutable->Id == 73061 || spellInfoMutable->Id == 73062 || spellInfoMutable->Id == 73063 || spellInfoMutable->Id == 73064)
break;
// Frostbolt
- if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfo->SpellFamilyFlags[0] & 0x20))
+ if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfoMutable->SpellFamilyFlags[0] & 0x20))
break;
// Frost Fever
- if (spellInfo->Id == 55095)
+ if (spellInfoMutable->Id == 55095)
break;
// Haunt
- if (spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellInfo->SpellFamilyFlags[1] & 0x40000))
+ if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellInfoMutable->SpellFamilyFlags[1] & 0x40000))
break;
setFlag = true;
@@ -2683,7 +2803,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
if (setFlag)
{
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_BINARY_SPELL;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_BINARY_SPELL;
break;
}
}
@@ -2691,61 +2811,58 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
}
// Remove normal school mask to properly calculate damage
- if ((spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL) && (spellInfo->SchoolMask & SPELL_SCHOOL_MASK_MAGIC))
+ if ((spellInfoMutable->SchoolMask & SPELL_SCHOOL_MASK_NORMAL) && (spellInfoMutable->SchoolMask & SPELL_SCHOOL_MASK_MAGIC))
{
- spellInfo->SchoolMask &= ~SPELL_SCHOOL_MASK_NORMAL;
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC;
+ spellInfoMutable->SchoolMask &= ~SPELL_SCHOOL_MASK_NORMAL;
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC;
}
- if (!spellInfo->_IsPositiveEffect(EFFECT_0, false))
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0;
+ if (!spellInfoMutable->_IsPositiveEffect(EFFECT_0, false))
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0;
- if (!spellInfo->_IsPositiveEffect(EFFECT_1, false))
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF1;
+ if (!spellInfoMutable->_IsPositiveEffect(EFFECT_1, false))
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF1;
- if (!spellInfo->_IsPositiveEffect(EFFECT_2, false))
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF2;
+ if (!spellInfoMutable->_IsPositiveEffect(EFFECT_2, false))
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF2;
- if (talentSpells.count(spellInfo->Id))
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_IS_TALENT;
+ if (talentSpells.count(spellInfoMutable->Id))
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_IS_TALENT;
- switch (spellInfo->SpellFamilyName)
+ switch (spellInfoMutable->SpellFamilyName)
{
case SPELLFAMILY_WARRIOR:
// Shout / Piercing Howl
- if (spellInfo->SpellFamilyFlags[0] & 0x20000/* || spellInfo->SpellFamilyFlags[1] & 0x20*/)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
+ if (spellInfoMutable->SpellFamilyFlags[0] & 0x20000/* || spellInfo->SpellFamilyFlags[1] & 0x20*/)
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
break;
case SPELLFAMILY_DRUID:
// Roar
- if (spellInfo->SpellFamilyFlags[0] & 0x8)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
+ if (spellInfoMutable->SpellFamilyFlags[0] & 0x8)
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
break;
case SPELLFAMILY_GENERIC:
// Stoneclaw Totem effect
- if (spellInfo->Id == 5729)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
+ if (spellInfoMutable->Id == 5729)
+ spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
break;
default:
break;
}
- spellInfo->_InitializeExplicitTargetMask();
+ spellInfoMutable->_InitializeExplicitTargetMask();
}
// addition for binary spells, ommit spells triggering other spells
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
{
- spellInfo = mSpellInfoMap[i];
- if (!spellInfo)
- continue;
-
- if (spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL))
+ SpellInfo* spellInfoMutable = const_cast<SpellInfo*>(&spellInfo);
+ if (spellInfoMutable->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL))
continue;
bool allNonBinary = true;
bool overrideAttr = false;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects())
{
if (!effect)
continue;
@@ -2756,7 +2873,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
{
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
- if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(effect->TriggerSpell))
+ if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE))
{
overrideAttr = true;
if (triggerSpell->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL))
@@ -2770,7 +2887,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
}
if (overrideAttr && allNonBinary)
- spellInfo->AttributesCu &= ~SPELL_ATTR0_CU_BINARY_SPELL;
+ spellInfoMutable->AttributesCu &= ~SPELL_ATTR0_CU_BINARY_SPELL;
}
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo custom attributes in %u ms", GetMSTimeDiffToNow(oldMSTime));
@@ -2780,14 +2897,15 @@ inline void ApplySpellFix(std::initializer_list<uint32> spellIds, void(*fix)(Spe
{
for (uint32 spellId : spellIds)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
- if (!spellInfo)
+ auto range = _GetSpellInfo(spellId);
+ if (range.begin() == range.end())
{
TC_LOG_ERROR("server.loading", "Spell info correction specified for non-existing spell %u", spellId);
continue;
}
- fix(const_cast<SpellInfo*>(spellInfo));
+ for (SpellInfo const& spellInfo : range)
+ fix(&const_cast<SpellInfo&>(spellInfo));
}
}
@@ -3724,14 +3842,13 @@ void SpellMgr::LoadSpellInfoCorrections()
const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
});
- SpellInfo* spellInfo = NULL;
- for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
+ for (SpellInfo const& s : mSpellInfoMap)
{
- spellInfo = (SpellInfo*)mSpellInfoMap[i];
+ SpellInfo* spellInfo = &const_cast<SpellInfo&>(s);
if (!spellInfo)
continue;
- for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spellInfo->GetEffects())
{
if (!effect)
continue;
@@ -3739,7 +3856,7 @@ void SpellMgr::LoadSpellInfoCorrections()
if (effect->IsEffect() && (effect->TargetA.GetTarget() == TARGET_DEST_TRAJ || effect->TargetB.GetTarget() == TARGET_DEST_TRAJ))
{
// Get triggered spell if any
- if (SpellInfo* spellInfoTrigger = const_cast<SpellInfo*>(GetSpellInfo(effect->TriggerSpell)))
+ if (SpellInfo* spellInfoTrigger = const_cast<SpellInfo*>(GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE)))
{
float maxRangeMain = spellInfo->GetMaxRange();
float maxRangeTrigger = spellInfoTrigger->GetMaxRange();
@@ -3768,11 +3885,11 @@ void SpellMgr::LoadSpellInfoCorrections()
}
// disable proc for magnet auras, they're handled differently
- if (spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_SPELL_MAGNET))
+ if (spellInfo->HasAura(SPELL_AURA_SPELL_MAGNET))
spellInfo->ProcFlags = 0;
// due to the way spell system works, unit would change orientation in Spell::_cast
- if (spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE))
+ if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
spellInfo->AttributesEx5 |= SPELL_ATTR5_DONT_TURN_DURING_CAST;
if (spellInfo->ActiveIconFileDataId == 135754) // flight
@@ -3793,14 +3910,11 @@ void SpellMgr::LoadSpellInfoSpellSpecificAndAuraState()
{
uint32 oldMSTime = getMSTime();
- for (SpellInfo* spellInfo : mSpellInfoMap)
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
{
- if (!spellInfo)
- continue;
-
// AuraState depends on SpellSpecific
- spellInfo->_LoadSpellSpecific();
- spellInfo->_LoadAuraState();
+ const_cast<SpellInfo&>(spellInfo)._LoadSpellSpecific();
+ const_cast<SpellInfo&>(spellInfo)._LoadAuraState();
}
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo SpellSpecific and AuraState in %u ms", GetMSTimeDiffToNow(oldMSTime));
@@ -3810,13 +3924,8 @@ void SpellMgr::LoadSpellInfoDiminishing()
{
uint32 oldMSTime = getMSTime();
- for (SpellInfo* spellInfo : mSpellInfoMap)
- {
- if (!spellInfo)
- continue;
-
- spellInfo->_LoadSpellDiminishInfo();
- }
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
+ const_cast<SpellInfo&>(spellInfo)._LoadSpellDiminishInfo();
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo diminishing infos in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
@@ -3825,13 +3934,8 @@ void SpellMgr::LoadSpellInfoImmunities()
{
uint32 oldMSTime = getMSTime();
- for (SpellInfo* spellInfo : mSpellInfoMap)
- {
- if (!spellInfo)
- continue;
-
- spellInfo->_LoadImmunityInfo();
- }
+ for (SpellInfo const& spellInfo : mSpellInfoMap)
+ const_cast<SpellInfo&>(spellInfo)._LoadImmunityInfo();
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo immunity infos in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
@@ -3845,7 +3949,7 @@ void SpellMgr::LoadPetFamilySpellsStore()
for (SkillLineAbilityEntry const* skillLine : sSkillLineAbilityStore)
{
- SpellInfo const* spellInfo = GetSpellInfo(skillLine->Spell);
+ SpellInfo const* spellInfo = GetSpellInfo(skillLine->Spell, DIFFICULTY_NONE);
if (!spellInfo)
continue;
@@ -3890,7 +3994,7 @@ void SpellMgr::LoadSpellTotemModel()
uint8 race = fields[1].GetUInt8();
uint32 displayId = fields[2].GetUInt32();
- SpellInfo const* spellEntry = GetSpellInfo(spellId);
+ SpellInfo const* spellEntry = GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellEntry)
{
TC_LOG_ERROR("sql.sql", "SpellID: %u in `spell_totem_model` table could not be found in dbc, skipped.", spellId);
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index c121f1ec8f1..4ff3bfc858c 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -21,12 +21,14 @@
// For static or at-server-startup loaded spell data
#include "Define.h"
+#include "DBCEnums.h"
#include "Duration.h"
#include "IteratorPair.h"
#include "RaceMask.h"
#include "SharedDefines.h"
#include "Util.h"
+#include <functional>
#include <map>
#include <set>
#include <vector>
@@ -45,16 +47,19 @@ struct SpellCastingRequirementsEntry;
struct SpellCategoriesEntry;
struct SpellClassOptionsEntry;
struct SpellCooldownsEntry;
+struct SpellEffectEntry;
struct SpellEquippedItemsEntry;
struct SpellInterruptsEntry;
struct SpellLevelsEntry;
struct SpellMiscEntry;
struct SpellNameEntry;
+struct SpellPowerEntry;
struct SpellReagentsEntry;
struct SpellScalingEntry;
struct SpellShapeshiftEntry;
struct SpellTargetRestrictionsEntry;
struct SpellTotemsEntry;
+struct SpellXSpellVisualEntry;
// only used in code
enum SpellCategories
@@ -282,8 +287,6 @@ struct SpellProcEntry
uint32 Charges; // if nonzero - owerwrite procCharges field for given Spell.dbc entry, defines how many times proc can occur before aura remove, 0 - infinite
};
-typedef std::unordered_map<uint32, SpellProcEntry> SpellProcMap;
-
enum EnchantProcAttributes
{
ENCHANT_PROC_ATTR_WHITE_HIT = 0x0000001, // enchant shall only proc off white hits (not abilities)
@@ -578,8 +581,6 @@ typedef std::map<int32, PetDefaultSpellsEntry> PetDefaultSpellsMap;
typedef std::vector<uint32> SpellCustomAttribute;
typedef std::vector<bool> EnchantCustomAttribute;
-typedef std::vector<SpellInfo*> SpellInfoMap;
-
typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
bool IsPrimaryProfessionSkill(uint32 skill);
@@ -602,23 +603,24 @@ TC_GAME_API extern PetFamilySpellsStore sPetFamilySpells
struct SpellInfoLoadHelper
{
- SpellNameEntry const* Entry = nullptr;
-
SpellAuraOptionsEntry const* AuraOptions = nullptr;
SpellAuraRestrictionsEntry const* AuraRestrictions = nullptr;
SpellCastingRequirementsEntry const* CastingRequirements = nullptr;
SpellCategoriesEntry const* Categories = nullptr;
SpellClassOptionsEntry const* ClassOptions = nullptr;
SpellCooldownsEntry const* Cooldowns = nullptr;
+ std::array<SpellEffectEntry const*, MAX_SPELL_EFFECTS> Effects = { };
SpellEquippedItemsEntry const* EquippedItems = nullptr;
SpellInterruptsEntry const* Interrupts = nullptr;
SpellLevelsEntry const* Levels = nullptr;
SpellMiscEntry const* Misc = nullptr;
+ std::array<SpellPowerEntry const*, MAX_POWERS_PER_SPELL> Powers;
SpellReagentsEntry const* Reagents = nullptr;
SpellScalingEntry const* Scaling = nullptr;
SpellShapeshiftEntry const* Shapeshift = nullptr;
SpellTargetRestrictionsEntry const* TargetRestrictions = nullptr;
SpellTotemsEntry const* Totems = nullptr;
+ std::vector<SpellXSpellVisualEntry const*> Visuals; // only to group visuals when parsing sSpellXSpellVisualStore, not for loading
};
typedef std::map<std::pair<uint32 /*SpellId*/, uint8 /*RaceId*/>, uint32 /*DisplayId*/> SpellTotemModelMap;
@@ -675,7 +677,7 @@ class TC_GAME_API SpellMgr
SpellGroupStackRule GetSpellGroupStackRule(SpellGroup groupid) const;
// Spell proc table
- SpellProcEntry const* GetSpellProcEntry(uint32 spellId) const;
+ SpellProcEntry const* GetSpellProcEntry(SpellInfo const* spellInfo) const;
static bool CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo);
// Spell threat table
@@ -702,16 +704,18 @@ class TC_GAME_API SpellMgr
SpellAreaForQuestAreaMapBounds GetSpellAreaForQuestAreaMapBounds(uint32 area_id, uint32 quest_id) const;
// SpellInfo object management
- SpellInfo const* GetSpellInfo(uint32 spellId) const { return spellId < GetSpellInfoStoreSize() ? mSpellInfoMap[spellId] : NULL; }
+ SpellInfo const* GetSpellInfo(uint32 spellId, Difficulty difficulty) const;
+
// Use this only with 100% valid spellIds
- SpellInfo const* AssertSpellInfo(uint32 spellId) const
+ SpellInfo const* AssertSpellInfo(uint32 spellId, Difficulty difficulty) const
{
- ASSERT(spellId < GetSpellInfoStoreSize());
- SpellInfo const* spellInfo = mSpellInfoMap[spellId];
+ SpellInfo const* spellInfo = GetSpellInfo(spellId, difficulty);
ASSERT(spellInfo);
return spellInfo;
}
- uint32 GetSpellInfoStoreSize() const { return uint32(mSpellInfoMap.size()); }
+
+ void ForEachSpellInfo(std::function<void(SpellInfo const*)> callback);
+ void ForEachSpellInfoDifficulty(uint32 spellId, std::function<void(SpellInfo const*)> callback);
void LoadPetFamilySpellsStore();
@@ -719,9 +723,6 @@ class TC_GAME_API SpellMgr
BattlePetSpeciesEntry const* GetBattlePetSpecies(uint32 spellId) const;
- private:
- SpellInfo* _GetSpellInfo(uint32 spellId) { return spellId < GetSpellInfoStoreSize() ? mSpellInfoMap[spellId] : NULL; }
-
// Modifiers
public:
@@ -766,7 +767,6 @@ class TC_GAME_API SpellMgr
SpellGroupSpellMap mSpellGroupSpell;
SpellGroupStackMap mSpellGroupStack;
SameEffectStackMap mSpellSameEffectStack;
- SpellProcMap mSpellProcMap;
SpellThreatMap mSpellThreatMap;
SpellPetAuraMap mSpellPetAuraMap;
SpellLinkedMap mSpellLinkedMap;
@@ -781,7 +781,6 @@ class TC_GAME_API SpellMgr
SkillLineAbilityMap mSkillLineAbilityMap;
PetLevelupSpellMap mPetLevelupSpellMap;
PetDefaultSpellsMap mPetDefaultSpellsMap; // only spells not listed in related mPetLevelupSpellMap entry
- SpellInfoMap mSpellInfoMap;
SpellTotemModelMap mSpellTotemModel;
std::unordered_map<uint32, BattlePetSpeciesEntry const*> mBattlePets;
};
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index e2a54597b2e..10722473019 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -39,7 +39,7 @@ bool _SpellScript::_ValidateSpellInfo(uint32 const* begin, uint32 const* end)
bool allValid = true;
while (begin != end)
{
- if (!sSpellMgr->GetSpellInfo(*begin))
+ if (!sSpellMgr->GetSpellInfo(*begin, DIFFICULTY_NONE))
{
TC_LOG_ERROR("scripts.spells", "_SpellScript::ValidateSpellInfo: Spell %u does not exist.", *begin);
allValid = false;
@@ -685,6 +685,11 @@ void SpellScript::SetCustomCastResultMessage(SpellCustomErrors result)
m_spell->m_customError = result;
}
+Difficulty SpellScript::GetCastDifficulty() const
+{
+ return m_spell->GetCastDifficulty();
+}
+
SpellValue const* SpellScript::GetSpellValue() const
{
return m_spell->m_spellValue;
@@ -692,7 +697,7 @@ SpellValue const* SpellScript::GetSpellValue() const
SpellEffectInfo const* SpellScript::GetEffectInfo(SpellEffIndex effIndex) const
{
- return m_spell->GetEffect(effIndex);
+ return GetSpellInfo()->GetEffect(effIndex);
}
bool AuraScript::_Validate(SpellInfo const* entry)
@@ -1230,3 +1235,8 @@ AuraApplication const* AuraScript::GetTargetApplication() const
{
return m_auraApplication;
}
+
+Difficulty AuraScript::GetCastDifficulty() const
+{
+ return GetAura()->GetCastDifficulty();
+}
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 5b57a7df5b6..40920ba6f20 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -47,6 +47,7 @@ class WorldObject;
struct SpellDestination;
struct SpellModifier;
struct SpellValue;
+enum Difficulty : uint8;
enum class ItemContext : uint8;
#define SPELL_EFFECT_ANY (uint16)-1
@@ -483,6 +484,9 @@ class TC_GAME_API SpellScript : public _SpellScript
void FinishCast(SpellCastResult result, uint32* param1 = nullptr, uint32* param2 = nullptr);
void SetCustomCastResultMessage(SpellCustomErrors result);
+
+ // returns desired cast difficulty for triggered spells
+ Difficulty GetCastDifficulty() const;
};
// AuraScript interface - enum used for runtime checks of script function calls
@@ -936,6 +940,9 @@ class TC_GAME_API AuraScript : public _SpellScript
Unit* GetTarget() const;
// returns AuraApplication object of currently processed target
AuraApplication const* GetTargetApplication() const;
+
+ // returns desired cast difficulty for triggered spells
+ Difficulty GetCastDifficulty() const;
};
//
diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.cpp b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
index 0f384a9b2d7..86210d8f56e 100644
--- a/src/server/game/Tools/CharacterDatabaseCleaner.cpp
+++ b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
@@ -130,7 +130,7 @@ void CharacterDatabaseCleaner::CleanCharacterSkills()
bool CharacterDatabaseCleaner::SpellCheck(uint32 spell_id)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, DIFFICULTY_NONE);
return spellInfo && !spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT);
}
diff --git a/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp b/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp
index d14fa3065e1..510a110df47 100644
--- a/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp
+++ b/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp
@@ -604,13 +604,13 @@ class spell_garothi_fel_bombardment_periodic : public AuraScript
bool Validate(SpellInfo const* spellInfo) override
{
- return ValidateSpellInfo({ uint32(spellInfo->GetEffect(DIFFICULTY_NONE, EFFECT_0)->BasePoints) });
+ return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->BasePoints) });
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
- caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_0)->BasePoints), true);
+ caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->GetEffect(EFFECT_0)->BasePoints), true);
}
void Register() override
@@ -757,13 +757,13 @@ class spell_garothi_annihilation_selector : public SpellScript
bool Validate(SpellInfo const* spellInfo) override
{
- return ValidateSpellInfo({ uint32(spellInfo->GetEffect(DIFFICULTY_NONE, EFFECT_0)->BasePoints) });
+ return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->BasePoints) });
}
void HandleHit(SpellEffIndex effIndex)
{
if (Unit* caster = GetCaster())
- caster->CastSpell(GetHitUnit(), uint32(GetSpellInfo()->GetEffect(DIFFICULTY_NONE, effIndex)->BasePoints), true);
+ caster->CastSpell(GetHitUnit(), uint32(GetSpellInfo()->GetEffect(effIndex)->BasePoints), true);
}
void Register() override
diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp
index b35374a0dac..9b783e28634 100644
--- a/src/server/scripts/Commands/cs_cast.cpp
+++ b/src/server/scripts/Commands/cs_cast.cpp
@@ -56,7 +56,7 @@ public:
static bool CheckSpellExistsAndIsValid(ChatHandler* handler, uint32 spellId)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND);
diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp
index 212f1ba20c8..837d64af9c4 100644
--- a/src/server/scripts/Commands/cs_disable.cpp
+++ b/src/server/scripts/Commands/cs_disable.cpp
@@ -98,7 +98,7 @@ public:
{
case DISABLE_TYPE_SPELL:
{
- if (!sSpellMgr->GetSpellInfo(entry))
+ if (!sSpellMgr->GetSpellInfo(entry, DIFFICULTY_NONE))
{
handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND);
handler->SetSentErrorMessage(true);
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index f0c6981f0f0..1de918cbc81 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -86,13 +86,13 @@ public:
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
uint32 spell = handler->extractSpellIdFromLink((char*)args);
- if (!spell || !sSpellMgr->GetSpellInfo(spell))
+ if (!spell || !sSpellMgr->GetSpellInfo(spell, DIFFICULTY_NONE))
return false;
char const* all = strtok(NULL, " ");
bool allRanks = all ? (strncmp(all, "all", strlen(all)) == 0) : false;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell, DIFFICULTY_NONE);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer()))
{
handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell);
@@ -120,16 +120,13 @@ public:
static bool HandleLearnAllGMCommand(ChatHandler* handler, char const* /*args*/)
{
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
+ for (std::pair<uint32 const, SkillLineAbilityEntry const*> skillSpell : Trinity::Containers::MakeIteratorPair(sSpellMgr->GetSkillLineAbilityMapBounds(SKILL_INTERNAL)))
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(skillSpell.second->Spell, DIFFICULTY_NONE);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false))
continue;
- if (!spellInfo->IsAbilityOfSkillType(SKILL_INTERNAL))
- continue;
-
- handler->GetSession()->GetPlayer()->LearnSpell(i, false);
+ handler->GetSession()->GetPlayer()->LearnSpell(skillSpell.second->Spell, false);
}
handler->SendSysMessage(LANG_LEARNING_GM_SKILLS);
@@ -156,7 +153,7 @@ public:
if (!entry)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry->Spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry->Spell, DIFFICULTY_NONE);
if (!spellInfo)
continue;
@@ -197,7 +194,7 @@ public:
if (playerClass != talentInfo->ClassID)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID, DIFFICULTY_NONE);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false))
continue;
@@ -439,7 +436,7 @@ public:
if (skillLine->ClassMask && (skillLine->ClassMask & classmask) == 0)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(skillLine->Spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(skillLine->Spell, DIFFICULTY_NONE);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player, false))
continue;
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index e64c7161469..7db339d63c6 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -839,11 +839,10 @@ public:
uint32 count = 0;
uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS);
- // Search in Spell.dbc
- for (uint32 id = 0; id < sSpellMgr->GetSpellInfoStoreSize(); id++)
+ // Search in SpellName.dbc
+ for (SpellNameEntry const* spellName : sSpellNameStore)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id);
- if (spellInfo)
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellName->ID, DIFFICULTY_NONE))
{
int locale = handler->GetSessionDbcLocale();
std::string name = spellInfo->SpellName->Str[locale];
@@ -875,16 +874,16 @@ public:
return true;
}
- bool known = target && target->HasSpell(id);
+ bool known = target && target->HasSpell(spellInfo->Id);
SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0);
bool learn = effect ? (effect->Effect == SPELL_EFFECT_LEARN_SPELL) : false;
- SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell) : NULL;
+ SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell, spellInfo->Difficulty) : NULL;
bool talent = spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT);
bool passive = spellInfo->IsPassive();
- bool active = target && target->HasAura(id);
+ bool active = target && target->HasAura(spellInfo->Id);
// unit32 used to prevent interpreting uint8 as char at output
// find rank of learned spell for learning spell, or talent rank
@@ -893,9 +892,9 @@ public:
// send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format
std::ostringstream ss;
if (handler->GetSession())
- ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name;
+ ss << spellInfo->Id << " - |cffffffff|Hspell:" << spellInfo->Id << "|h[" << name;
else
- ss << id << " - " << name;
+ ss << spellInfo->Id << " - " << name;
// include rank in link name
if (rank)
@@ -938,7 +937,7 @@ public:
uint32 id = atoi((char*)args);
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id, DIFFICULTY_NONE))
{
int locale = handler->GetSessionDbcLocale();
std::string name = spellInfo->SpellName->Str[locale];
@@ -953,7 +952,7 @@ public:
SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0);
bool learn = effect? (effect->Effect == SPELL_EFFECT_LEARN_SPELL) : false;
- SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell) : NULL;
+ SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE) : NULL;
bool talent = spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT);
bool passive = spellInfo->IsPassive();
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 23804a75a21..d35904921eb 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -322,10 +322,10 @@ 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 (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, target->GetMap()->GetDifficultyID()))
{
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, target->GetMapId(), spellId, target->GetMap()->GenerateLowGuid<HighGuid::Cast>());
- Aura::TryRefreshStackOrCreate(spellInfo, castId, MAX_EFFECT_MASK, target, target);
+ Aura::TryRefreshStackOrCreate(spellInfo, castId, MAX_EFFECT_MASK, target, target, target->GetMap()->GetDifficultyID());
}
return true;
@@ -795,7 +795,7 @@ public:
if (!spellIid)
return false;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellIid);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellIid, target->GetMap()->GetDifficultyID());
if (!spellInfo)
{
handler->PSendSysMessage(LANG_UNKNOWN_SPELL, owner == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str());
@@ -1017,7 +1017,7 @@ public:
if (player->IsInFlight() || player->IsInCombat())
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_UNSTUCK_ID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_UNSTUCK_ID, DIFFICULTY_NONE);
if (!spellInfo)
return false;
@@ -2426,11 +2426,11 @@ public:
if (!spellid)
return false;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid, attacker->GetMap()->GetDifficultyID());
if (!spellInfo)
return false;
- SpellNonMeleeDamage damageInfo(attacker, target, spellid, spellInfo->GetSpellXSpellVisualId(handler->GetSession()->GetPlayer()), spellInfo->SchoolMask);
+ SpellNonMeleeDamage damageInfo(attacker, target, spellInfo, spellInfo->GetSpellXSpellVisualId(handler->GetSession()->GetPlayer()), spellInfo->SchoolMask);
damageInfo.damage = damage;
attacker->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
target->DealSpellDamage(&damageInfo, true);
diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp
index 1e0cd4ab835..124d67fb722 100644
--- a/src/server/scripts/Commands/cs_pet.cpp
+++ b/src/server/scripts/Commands/cs_pet.cpp
@@ -148,7 +148,7 @@ public:
uint32 spellId = handler->extractSpellIdFromLink((char*)args);
- if (!spellId || !sSpellMgr->GetSpellInfo(spellId))
+ if (!spellId || !sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
return false;
// Check if pet already has it
@@ -160,7 +160,7 @@ public:
}
// Check if spell is valid
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo))
{
handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId);
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
index 1c4f1c112eb..b1c88b9c6d2 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
@@ -311,7 +311,7 @@ public:
void EnfeebleHealthEffect()
{
- SpellInfo const* info = sSpellMgr->GetSpellInfo(SPELL_ENFEEBLE_EFFECT);
+ SpellInfo const* info = sSpellMgr->GetSpellInfo(SPELL_ENFEEBLE_EFFECT, GetDifficulty());
if (!info)
return;
diff --git a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
index f297095ff31..0dfe70efd5f 100644
--- a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
@@ -819,7 +819,7 @@ class spell_baleroc_vital_flame : public AuraScript
}
stacks = GetCaster()->GetAuraCount(SPELL_VITAL_SPARK);
- int32 healingPct = sSpellMgr->AssertSpellInfo(SPELL_VITAL_SPARK)->GetEffect(EFFECT_0)->BasePoints * stacks;
+ int32 healingPct = sSpellMgr->AssertSpellInfo(SPELL_VITAL_SPARK, GetCastDifficulty())->GetEffect(EFFECT_0)->BasePoints * stacks;
if (GetAura()->GetEffect(EFFECT_0)->GetAmount() < healingPct)
GetAura()->GetEffect(EFFECT_0)->SetAmount(healingPct);
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp
index b39f0f66507..eb129c37473 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp
@@ -131,7 +131,7 @@ public:
// phase the player
target->CastSpell(target, SPELL_INSANITY_TARGET + insanityHandled, true);
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_INSANITY_TARGET + insanityHandled);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_INSANITY_TARGET + insanityHandled, GetDifficulty());
if (!spellInfo)
return;
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp
index 874e9c77235..7500fec1759 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp
@@ -232,8 +232,8 @@ class spell_saviana_conflagration_init : public SpellScriptLoader
bool Validate(SpellInfo const* /*spell*/) override
{
- if (!sSpellMgr->GetSpellInfo(SPELL_FLAME_BEACON)
- || !sSpellMgr->GetSpellInfo(SPELL_CONFLAGRATION_2))
+ if (!sSpellMgr->GetSpellInfo(SPELL_FLAME_BEACON, DIFFICULTY_NONE)
+ || !sSpellMgr->GetSpellInfo(SPELL_CONFLAGRATION_2, DIFFICULTY_NONE))
return false;
return true;
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
index 7b2575f8935..c5f5fb349de 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
@@ -815,7 +815,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader
// this is an additional effect to be executed
void PeriodicTick(AuraEffect const* aurEff)
{
- SpellInfo const* damageSpell = sSpellMgr->AssertSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE);
+ SpellInfo const* damageSpell = sSpellMgr->AssertSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE, GetCastDifficulty());
int32 damage = damageSpell->GetEffect(EFFECT_0)->CalcValue();
float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber() / 10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks)
damage = int32(damage * multiplier);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
index d40e5b8beb8..2ab13c49d28 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
@@ -1845,7 +1845,7 @@ class spell_igb_rocket_pack : public SpellScriptLoader
void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
- SpellInfo const* damageInfo = sSpellMgr->AssertSpellInfo(SPELL_ROCKET_PACK_DAMAGE);
+ SpellInfo const* damageInfo = sSpellMgr->AssertSpellInfo(SPELL_ROCKET_PACK_DAMAGE, GetCastDifficulty());
GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->GetEffect(EFFECT_0)->CalcValue() + aurEff->GetTickNumber() * aurEff->GetPeriod()), NULL, TRIGGERED_FULL_MASK);
GetTarget()->CastSpell(nullptr, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 11b5ad24e9a..7f69a62017d 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -589,7 +589,7 @@ class spell_marrowgar_coldflame_damage : public SpellScriptLoader
if (target->HasAura(SPELL_IMPALED))
return false;
- if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(target->GetMap()->GetDifficultyID(), EFFECT_0))
+ if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(EFFECT_0))
if (target->GetExactDist2d(GetOwner()) > effect->CalcRadius())
return false;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 116843c2398..e277bb150a1 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -401,14 +401,14 @@ class boss_professor_putricide : public CreatureScript
{
case PHASE_COMBAT_2:
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_CREATE_CONCOCTION);
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_CREATE_CONCOCTION, GetDifficulty());
DoCast(me, SPELL_CREATE_CONCOCTION);
events.ScheduleEvent(EVENT_PHASE_TRANSITION, spell->CalcCastTime() + 100);
break;
}
case PHASE_COMBAT_3:
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_GUZZLE_POTIONS);
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_GUZZLE_POTIONS, GetDifficulty());
DoCast(me, SPELL_GUZZLE_POTIONS);
events.ScheduleEvent(EVENT_PHASE_TRANSITION, spell->CalcCastTime() + 100);
break;
@@ -1154,7 +1154,7 @@ class spell_putricide_choking_gas_bomb : public SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
uint32 skipIndex = urand(0, 2);
- for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffectsForDifficulty(GetCaster()->GetMap()->GetDifficultyID()))
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
{
if (!effect || effect->EffectIndex == skipIndex)
continue;
@@ -1317,7 +1317,7 @@ class spell_putricide_mutated_plague : public SpellScriptLoader
return;
uint32 triggerSpell = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell;
- SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell);
+ SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell, GetCastDifficulty());
int32 damage = spell->GetEffect(EFFECT_0)->CalcValue(caster);
float multiplier = 2.0f;
@@ -1333,7 +1333,7 @@ class spell_putricide_mutated_plague : public SpellScriptLoader
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
uint32 healSpell = uint32(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue());
- SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell);
+ SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell, GetCastDifficulty());
if (!healSpellInfo)
return;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
index d0fdf6557c1..f8d8fcea526 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
@@ -552,7 +552,7 @@ class spell_rotface_mutated_infection : public SpellScriptLoader
void HandleEffectRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
- target->CastSpell(target, uint32(GetAura()->GetSpellEffectInfo(EFFECT_2)->CalcValue()), true, nullptr, aurEff, GetCasterGUID());
+ target->CastSpell(target, uint32(GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue()), true, nullptr, aurEff, GetCasterGUID());
}
void Register() override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index e1cc3c12f54..6f9f082ef8c 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -1124,7 +1124,7 @@ class spell_sindragosa_s_fury : public SpellScriptLoader
uint32 damage = (uint32(GetEffectValue() / _targetCount) * randomResist) / 10;
- SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo()->Id, GetSpell()->m_SpellVisual, GetSpellInfo()->SchoolMask);
+ SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo(), GetSpell()->m_SpellVisual, GetSpellInfo()->SchoolMask);
damageInfo.damage = damage;
GetCaster()->DealSpellDamage(&damageInfo, false);
GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo);
@@ -1564,7 +1564,7 @@ class spell_frostwarden_handler_focus_fire : public SpellScriptLoader
PreventDefaultAction();
if (Unit* caster = GetCaster())
{
- if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(caster->GetMap()->GetDifficultyID(), EFFECT_1))
+ if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(EFFECT_1))
caster->AddThreat(GetTarget(), -float(effect->CalcValue()));
caster->GetAI()->SetData(DATA_WHELP_MARKER, 0);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
index b4616c9629f..67e665862ff 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
@@ -57,7 +57,7 @@ class icecrown_citadel_teleport : public GameObjectScript
ClearGossipMenuFor(player);
CloseGossipMenuFor(player);
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(TeleportSpells[gossipListId]);
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(TeleportSpells[gossipListId], DIFFICULTY_NONE);
if (!spell)
return false;
@@ -88,7 +88,7 @@ class at_frozen_throne_teleport : public AreaTriggerScript
{
if (player->IsInCombat())
{
- if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(FROZEN_THRONE_TELEPORT))
+ if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(FROZEN_THRONE_TELEPORT, DIFFICULTY_NONE))
{
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, player->GetMapId(), spell->Id, player->GetMap()->GenerateLowGuid<HighGuid::Cast>());
Spell::SendCastResult(player, spell, 0, castId, SPELL_FAILED_AFFECTING_COMBAT);
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 117c21d197a..8fbf23d4a44 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -1335,9 +1335,7 @@ public:
bool Validate(SpellInfo const* spellInfo) override
{
- if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->CalcValue()))
- return false;
- return true;
+ return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->CalcValue()) });
}
void HandleScript(SpellEffIndex /*effIndex*/)
@@ -1441,9 +1439,7 @@ public:
bool Validate(SpellInfo const* /*spellInfo*/) override
{
- if (!sSpellMgr->GetSpellInfo(SPELL_FATAL_STRIKE_DAMAGE))
- return false;
- return true;
+ return ValidateSpellInfo({ SPELL_FATAL_STRIKE_DAMAGE });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
@@ -1520,9 +1516,7 @@ public:
bool Validate(SpellInfo const* /*spellInfo*/) override
{
- if (!sSpellMgr->GetSpellInfo(SPELL_FIGHT_WYRM))
- return false;
- return true;
+ return ValidateSpellInfo({ SPELL_FIGHT_WYRM });
}
void HandleDummy(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index d0c189e7931..19f4018af10 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -330,7 +330,7 @@ class spell_dk_dancing_rune_weapon : public SpellScriptLoader
return;
int32 amount = static_cast<int32>(damageInfo->GetDamage()) / 2;
- SpellNonMeleeDamage log(drw, drw->GetVictim(), spellInfo->Id, spellInfo->GetSpellXSpellVisualId(drw), spellInfo->GetSchoolMask());
+ SpellNonMeleeDamage log(drw, drw->GetVictim(), spellInfo, spellInfo->GetSpellXSpellVisualId(drw), spellInfo->GetSchoolMask());
log.damage = amount;
drw->DealDamage(drw->GetVictim(), amount, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
drw->SendSpellNonMeleeDamageLog(&log);
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index 9dc071b08a2..48d63353a34 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -994,7 +994,7 @@ public:
if (player->GetSkillValue(SKILL_RIDING) < 75)
return SPELL_FAILED_APPRENTICE_RIDING_REQUIREMENT;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(player->IsInWater() ? SPELL_DRUID_FORM_AQUATIC : SPELL_DRUID_FORM_STAG);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(player->IsInWater() ? SPELL_DRUID_FORM_AQUATIC : SPELL_DRUID_FORM_STAG, GetCastDifficulty());
return spellInfo->CheckLocation(player->GetMapId(), player->GetZoneId(), player->GetAreaId(), player);
}
@@ -1053,7 +1053,7 @@ public:
SpellCastResult CheckLocationForForm(uint32 spell)
{
Player* player = GetTarget()->ToPlayer();
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell, GetCastDifficulty());
return spellInfo->CheckLocation(player->GetMapId(), player->GetZoneId(), player->GetAreaId(), player);
}
};
@@ -1135,7 +1135,7 @@ public:
SpellCastResult CheckLocationForForm(uint32 spell_id)
{
Player* player = GetTarget()->ToPlayer();
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, GetCastDifficulty());
if (!player->GetMap()->IsOutdoors(player->GetPhaseShift(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()))
return SPELL_FAILED_ONLY_OUTDOORS;
@@ -1244,9 +1244,9 @@ class spell_dru_t10_balance_4p_bonus : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_DRUID_LANGUISH);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_DRUID_LANGUISH, GetCastDifficulty());
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- amount /= spellInfo->GetMaxTicks(DIFFICULTY_NONE);
+ amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to damage done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_DRUID_LANGUISH, SPELL_AURA_PERIODIC_DAMAGE);
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 85fb71cccec..2824a5e637b 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -1976,9 +1976,9 @@ class spell_gen_mounted_charge: public SpellScriptLoader
void Register() override
{
- SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId);
+ SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId, DIFFICULTY_NONE);
- if (spell->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_SCRIPT_EFFECT))
+ if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT))
OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT);
if (spell->GetEffect(EFFECT_0)->Effect == SPELL_EFFECT_CHARGE)
diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp
index 54b75b7df89..f51d7730b8e 100644
--- a/src/server/scripts/Spells/spell_hunter.cpp
+++ b/src/server/scripts/Spells/spell_hunter.cpp
@@ -728,9 +728,9 @@ class spell_hun_readiness : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
// immediately finishes the cooldown on your other Hunter abilities except Bestial Wrath
- GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr)
+ GetCaster()->GetSpellHistory()->ResetCooldowns([this](SpellHistory::CooldownStorageType::iterator itr)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty());
///! If spellId in cooldown map isn't valid, the above will return a null pointer.
if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER &&
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 7461e52e1b4..2c32c6fd220 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -161,9 +161,9 @@ class spell_item_alchemist_stone : public SpellScriptLoader
uint32 spellId = 0;
int32 amount = int32(eventInfo.GetDamageInfo()->GetDamage() * 0.4f);
- if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_HEAL))
+ if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(SPELL_EFFECT_HEAL))
spellId = SPELL_ALCHEMIST_STONE_EXTRA_HEAL;
- else if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_ENERGIZE))
+ else if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(SPELL_EFFECT_ENERGIZE))
spellId = SPELL_ALCHEMIST_STONE_EXTRA_MANA;
if (!spellId)
@@ -517,7 +517,7 @@ class spell_item_deadly_precision_dummy : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_DEADLY_PRECISION);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_DEADLY_PRECISION, GetCastDifficulty());
GetCaster()->CastCustomSpell(spellInfo->Id, SPELLVALUE_AURA_STACK, spellInfo->StackAmount, GetCaster(), true);
}
@@ -1100,7 +1100,7 @@ class spell_item_gnomish_death_ray : public SpellScriptLoader
}
};
-// Item 10721: Gnomish Harm Prevention Belt
+// Item 10721: Gnomish Harm Prevention Belt
// 13234 - Harm Prevention Belt
enum HarmPreventionBelt
{
@@ -1118,9 +1118,7 @@ public:
bool Validate(SpellInfo const* /*spellInfo*/) override
{
- if (!sSpellMgr->GetSpellInfo(SPELL_FORCEFIELD_COLLAPSE))
- return false;
- return true;
+ return ValidateSpellInfo({ SPELL_FORCEFIELD_COLLAPSE });
}
void HandleProc(ProcEventInfo& /*eventInfo*/)
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index 0a4e847eb14..ec0993b2939 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -167,7 +167,7 @@ class spell_mage_cauterize_AuraScript : public AuraScript
}
GetTarget()->SetHealth(GetTarget()->CountPctFromMaxHealth(effect1->GetAmount()));
- GetTarget()->CastSpell(GetTarget(), GetAura()->GetSpellEffectInfo(EFFECT_2)->TriggerSpell, TRIGGERED_FULL_MASK);
+ GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->GetEffect(EFFECT_2)->TriggerSpell, TRIGGERED_FULL_MASK);
GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_CAUTERIZE_DOT, TRIGGERED_FULL_MASK);
GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_CAUTERIZED, TRIGGERED_FULL_MASK);
}
@@ -326,10 +326,10 @@ class spell_mage_ignite : public AuraScript
{
PreventDefaultAction();
- SpellInfo const* igniteDot = sSpellMgr->AssertSpellInfo(SPELL_MAGE_IGNITE);
+ SpellInfo const* igniteDot = sSpellMgr->AssertSpellInfo(SPELL_MAGE_IGNITE, GetCastDifficulty());
int32 pct = aurEff->GetAmount();
- int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks(DIFFICULTY_NONE));
+ int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks());
amount += eventInfo.GetProcTarget()->GetRemainingPeriodicAmount(eventInfo.GetActor()->GetGUID(), SPELL_MAGE_IGNITE, SPELL_AURA_PERIODIC_DAMAGE);
GetTarget()->CastCustomSpell(SPELL_MAGE_IGNITE, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, nullptr, aurEff);
}
@@ -518,7 +518,7 @@ class spell_mage_ring_of_frost : public AuraScript
void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
std::list<TempSummon*> minions;
- GetTarget()->GetAllMinionsByEntry(minions, sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON)->GetEffect(EFFECT_0)->MiscValue);
+ GetTarget()->GetAllMinionsByEntry(minions, sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffect(EFFECT_0)->MiscValue);
// Get the last summoned RoF, save it and despawn older ones
for (TempSummon* summon : minions)
@@ -568,7 +568,7 @@ class spell_mage_ring_of_frost_freeze : public SpellScript
void FilterTargets(std::list<WorldObject*>& targets)
{
WorldLocation const* dest = GetExplTargetDest();
- float outRadius = sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON)->GetEffect(EFFECT_0)->CalcRadius();
+ float outRadius = sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffect(EFFECT_0)->CalcRadius();
float inRadius = 6.5f;
targets.remove_if([dest, outRadius, inRadius](WorldObject* target)
diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp
index 534d57fb091..e501e20e7e3 100644
--- a/src/server/scripts/Spells/spell_monk.cpp
+++ b/src/server/scripts/Spells/spell_monk.cpp
@@ -132,7 +132,7 @@ class spell_monk_provoke : public SpellScript
{
if (GetExplTargetUnit()->GetEntry() != BlackOxStatusEntry)
{
- SpellInfo const* singleTarget = sSpellMgr->AssertSpellInfo(SPELL_MONK_PROVOKE_SINGLE_TARGET);
+ SpellInfo const* singleTarget = sSpellMgr->AssertSpellInfo(SPELL_MONK_PROVOKE_SINGLE_TARGET, GetCastDifficulty());
SpellCastResult singleTargetExplicitResult = singleTarget->CheckExplicitTarget(GetCaster(), GetExplTargetUnit());
if (singleTargetExplicitResult != SPELL_CAST_OK)
return singleTargetExplicitResult;
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index 9f37671c8f3..3d43d162418 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -765,7 +765,7 @@ class spell_pal_holy_shock : public SpellScriptLoader
bool Validate(SpellInfo const* spellInfo) override
{
- SpellInfo const* firstRankSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1);
+ SpellInfo const* firstRankSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1, DIFFICULTY_NONE);
if (!firstRankSpellInfo)
return false;
@@ -940,7 +940,7 @@ class spell_pal_judgement : public SpellScriptLoader
{
if ((*i)->GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_SEAL && (*i)->GetEffIndex() == EFFECT_2)
{
- if (sSpellMgr->GetSpellInfo((*i)->GetAmount()))
+ if (sSpellMgr->GetSpellInfo((*i)->GetAmount(), GetCastDifficulty()))
{
spellId = (*i)->GetAmount();
break;
@@ -1411,9 +1411,9 @@ class spell_pal_t8_2p_bonus : public SpellScriptLoader
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PALADIN_HOLY_MENDING);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PALADIN_HOLY_MENDING, GetCastDifficulty());
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- amount /= spellInfo->GetMaxTicks(DIFFICULTY_NONE);
+ amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to damage done
amount += target->GetRemainingPeriodicAmount(caster->GetGUID(), SPELL_PALADIN_HOLY_MENDING, SPELL_AURA_PERIODIC_HEAL);
diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp
index 7aaba87a2da..0ff0ebde0e5 100644
--- a/src/server/scripts/Spells/spell_pet.cpp
+++ b/src/server/scripts/Spells/spell_pet.cpp
@@ -897,7 +897,7 @@ public:
if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty()); // Then get the SpellProto and add the dummy effect value
AddPct(mod, spellInfo->GetEffect(EFFECT_0)->CalcValue());
}
@@ -939,7 +939,7 @@ public:
if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty()); // Then get the SpellProto and add the dummy effect value
mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1)->CalcValue());
}
@@ -969,7 +969,7 @@ public:
if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty()); // Then get the SpellProto and add the dummy effect value
mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1)->CalcValue());
}
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 7436742b425..34a09aa9150 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -541,8 +541,8 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader
if (!healInfo || !healInfo->GetHeal())
return;
- SpellInfo const* triggeredSpellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL);
- int32 heal = int32(CalculatePct(healInfo->GetHeal(), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks(DIFFICULTY_NONE));
+ SpellInfo const* triggeredSpellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, GetCastDifficulty());
+ int32 heal = int32(CalculatePct(healInfo->GetHeal(), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks());
GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff);
}
@@ -752,7 +752,7 @@ class spell_pri_leap_of_faith_effect_trigger : public SpellScriptLoader
SpellCastTargets targets;
targets.SetDst(destPos);
targets.SetUnitTarget(GetCaster());
- GetHitUnit()->CastSpell(targets, sSpellMgr->GetSpellInfo(GetEffectValue()), NULL);
+ GetHitUnit()->CastSpell(targets, sSpellMgr->GetSpellInfo(GetEffectValue(), GetCastDifficulty()), NULL);
}
void Register() override
@@ -963,7 +963,7 @@ class spell_pri_penance : public SpellScriptLoader
bool Validate(SpellInfo const* spellInfo) override
{
- SpellInfo const* firstRankSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_PENANCE_R1);
+ SpellInfo const* firstRankSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_PENANCE_R1, DIFFICULTY_NONE);
if (!firstRankSpellInfo)
return false;
@@ -1340,9 +1340,9 @@ class spell_pri_t10_heal_2p_bonus : public SpellScriptLoader
if (!healInfo || !healInfo->GetHeal())
return;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_BLESSED_HEALING);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_BLESSED_HEALING, GetCastDifficulty());
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- amount /= spellInfo->GetMaxTicks(DIFFICULTY_NONE);
+ amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to healing done
Unit* caster = eventInfo.GetActor();
@@ -1523,7 +1523,7 @@ class spell_pri_angelic_feather_trigger : public SpellScriptLoader
{
SpellCastTargets targets;
targets.SetDst(destPos);
- GetCaster()->CastSpell(targets, sSpellMgr->GetSpellInfo(SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER), nullptr);
+ GetCaster()->CastSpell(targets, sSpellMgr->GetSpellInfo(SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER, GetCastDifficulty()), nullptr);
}
}
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index b53a9822eff..5f1121648f0 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -288,7 +288,7 @@ class spell_rog_deadly_poison : public SpellScriptLoader
if (enchant->Effect[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
continue;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(enchant->EffectArg[s]);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(enchant->EffectArg[s], DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("spells", "Player::CastItemCombatSpell Enchant %i, player (Name: %s, %s) cast unknown spell %i", enchant->ID, player->GetName().c_str(), player->GetGUID().ToString().c_str(), enchant->EffectArg[s]);
@@ -486,9 +486,9 @@ class spell_rog_preparation : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
- caster->GetSpellHistory()->ResetCooldowns([caster](SpellHistory::CooldownStorageType::iterator itr)
+ caster->GetSpellHistory()->ResetCooldowns([caster, this](SpellHistory::CooldownStorageType::iterator itr)
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty());
if (spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE)
return false;
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 108c5aaf9f5..0a4b6fbac58 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -894,7 +894,7 @@ class spell_sha_lava_surge_proc : public SpellScriptLoader
void ResetCooldown()
{
- GetCaster()->GetSpellHistory()->RestoreCharge(sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_LAVA_BURST)->ChargeCategoryId);
+ GetCaster()->GetSpellHistory()->RestoreCharge(sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_LAVA_BURST, GetCastDifficulty())->ChargeCategoryId);
}
void Register() override
@@ -1087,9 +1087,9 @@ class spell_sha_t8_elemental_4p_bonus : public SpellScriptLoader
if (!damageInfo || !damageInfo->GetDamage())
return;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_ELECTRIFIED);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_ELECTRIFIED, GetCastDifficulty());
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- amount /= spellInfo->GetMaxTicks(DIFFICULTY_NONE);
+ amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to damage done
Unit* caster = eventInfo.GetActor();
@@ -1134,9 +1134,9 @@ class spell_sha_t9_elemental_4p_bonus : public SpellScriptLoader
if (!damageInfo || !damageInfo->GetDamage())
return;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_LAVA_BURST_BONUS_DAMAGE);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_LAVA_BURST_BONUS_DAMAGE, GetCastDifficulty());
int32 amount = CalculatePct(static_cast<int32>(damageInfo->GetDamage()), aurEff->GetAmount());
- amount /= spellInfo->GetMaxTicks(DIFFICULTY_NONE);
+ amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to damage done
Unit* caster = eventInfo.GetActor();
@@ -1226,9 +1226,9 @@ class spell_sha_t10_restoration_4p_bonus : public SpellScriptLoader
if (!healInfo || !healInfo->GetHeal())
return;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_CHAINED_HEAL);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_SHAMAN_CHAINED_HEAL, GetCastDifficulty());
int32 amount = CalculatePct(static_cast<int32>(healInfo->GetHeal()), aurEff->GetAmount());
- amount /= spellInfo->GetMaxTicks(DIFFICULTY_NONE);
+ amount /= spellInfo->GetMaxTicks();
// Add remaining ticks to healing done
Unit* caster = eventInfo.GetActor();
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index b6da66601ee..3c8480e85f2 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -301,7 +301,7 @@ class spell_warl_demonic_circle_summon : public SpellScriptLoader
// WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST; allowing him to cast the WARLOCK_DEMONIC_CIRCLE_TELEPORT.
// If not in range remove the WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST.
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT, GetCastDifficulty());
if (GetTarget()->IsWithinDist(circle, spellInfo->GetMaxRange(true)))
{
@@ -464,7 +464,7 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader
break;
case CREATURE_FAMILY_VOIDWALKER:
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, GetCastDifficulty());
int32 hp = int32(targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(targetCreature, spellInfo, 0)));
targetCreature->CastCustomSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, &hp, NULL, NULL, true);
break;
@@ -759,7 +759,7 @@ class spell_warl_health_funnel : public SpellScriptLoader
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), SPELLMOD_COST, damage);
- SpellNonMeleeDamage damageInfo(caster, caster, GetSpellInfo()->Id, GetAura()->GetSpellXSpellVisualId(), GetSpellInfo()->SchoolMask, GetAura()->GetCastGUID());
+ SpellNonMeleeDamage damageInfo(caster, caster, GetSpellInfo(), GetAura()->GetSpellXSpellVisualId(), GetSpellInfo()->SchoolMask, GetAura()->GetCastGUID());
damageInfo.periodicLog = true;
damageInfo.damage = damage;
caster->DealSpellDamage(&damageInfo, false);
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 2693b112697..7f9be35dd77 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -1203,7 +1203,7 @@ public:
//Get the Remaining Damage from the aura (if exist)
int32 remainingDamage = target->GetRemainingPeriodicAmount(target->GetGUID(), SPELL_WARRIOR_TRAUMA_EFFECT, SPELL_AURA_PERIODIC_DAMAGE);
//Get 25% of damage from the spell casted (Slam & Whirlwind) plus Remaining Damage from Aura
- int32 damage = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()) / sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_TRAUMA_EFFECT)->GetMaxTicks(DIFFICULTY_NONE)) + remainingDamage;
+ int32 damage = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()) / sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_TRAUMA_EFFECT, GetCastDifficulty())->GetMaxTicks()) + remainingDamage;
GetCaster()->CastCustomSpell(SPELL_WARRIOR_TRAUMA_EFFECT, SPELLVALUE_BASE_POINT0, damage, target, true);
}
diff --git a/src/server/scripts/World/duel_reset.cpp b/src/server/scripts/World/duel_reset.cpp
index 8bcf0ab0239..7ad9fb596e7 100644
--- a/src/server/scripts/World/duel_reset.cpp
+++ b/src/server/scripts/World/duel_reset.cpp
@@ -97,7 +97,7 @@ class DuelResetScript : public PlayerScript
{
SpellHistory::Clock::time_point now = GameTime::GetGameTimeSystemPoint();
uint32 cooldownDuration = itr->second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.CooldownEnd - now).count() : 0;
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, DIFFICULTY_NONE);
return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS
&& spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS
&& !itr->second.OnHold
@@ -111,7 +111,7 @@ class DuelResetScript : public PlayerScript
// remove cooldowns on spells that have < 10 min CD and has no onHold
player->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
{
- SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, DIFFICULTY_NONE);
return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS
&& spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS
&& !itr->second.OnHold;
diff --git a/src/server/scripts/World/guards.cpp b/src/server/scripts/World/guards.cpp
index 67e85c2e79f..be2eae2e239 100644
--- a/src/server/scripts/World/guards.cpp
+++ b/src/server/scripts/World/guards.cpp
@@ -29,6 +29,7 @@ guard_shattrath_scryer
EndContentData */
#include "ScriptMgr.h"
+#include "CreatureAIImpl.h"
#include "GuardAI.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp
index 628ca0edcae..7e11fda4382 100644
--- a/src/server/scripts/World/item_scripts.cpp
+++ b/src/server/scripts/World/item_scripts.cpp
@@ -32,6 +32,7 @@ EndContentData */
#include "ScriptMgr.h"
#include "GameObject.h"
#include "Item.h"
+#include "Map.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "Spell.h"
@@ -69,7 +70,7 @@ public:
disabled = true;
break;
case 34475:
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES, player->GetMap()->GetDifficultyID()))
Spell::SendCastResult(player, spellInfo, 0, castId, SPELL_FAILED_NOT_ON_GROUND);
break;
}
@@ -278,7 +279,7 @@ public:
if (!player->GetTransport() || player->GetAreaId() != AREA_ID_SHATTERED_STRAITS)
{
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_PETROV_BOMB))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_PETROV_BOMB, DIFFICULTY_NONE))
Spell::SendCastResult(player, spellInfo, 0, castId, SPELL_FAILED_NOT_HERE);
return true;
diff --git a/src/server/scripts/World/mob_generic_creature.cpp b/src/server/scripts/World/mob_generic_creature.cpp
index 613eb339b01..bc313e70eda 100644
--- a/src/server/scripts/World/mob_generic_creature.cpp
+++ b/src/server/scripts/World/mob_generic_creature.cpp
@@ -16,6 +16,7 @@
*/
#include "ScriptMgr.h"
+#include "Map.h"
#include "PassiveAI.h"
#include "ScriptedCreature.h"
#include "SpellMgr.h"
@@ -29,7 +30,7 @@ public:
{
trigger_periodicAI(Creature* creature) : NullCreatureAI(creature)
{
- spell = me->m_spells[0] ? sSpellMgr->GetSpellInfo(me->m_spells[0]) : NULL;
+ spell = me->m_spells[0] ? sSpellMgr->GetSpellInfo(me->m_spells[0], me->GetMap()->GetDifficultyID()) : NULL;
interval = me->GetBaseAttackTime(BASE_ATTACK);
timer = interval;
}
diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp
index 0d5bd2a29dc..1fd6ce702a9 100644
--- a/src/server/scripts/World/npc_professions.cpp
+++ b/src/server/scripts/World/npc_professions.cpp
@@ -282,11 +282,11 @@ void ProcessCastaction(Player* player, Creature* creature, uint32 spellId, uint3
bool EquippedOk(Player* player, uint32 spellId)
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spell)
return false;
- for (SpellEffectInfo const* effect : spell->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ for (SpellEffectInfo const* effect : spell->GetEffects())
{
if (!effect)
continue;
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 8bc2fe634c0..095933d4c03 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -2257,7 +2257,7 @@ public:
break;
}
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
if (SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0))
if (effect0->Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD)
return effect0->MiscValue;