36#include <G3D/g3dmath.h>
37#include <boost/multi_index_container.hpp>
38#include <boost/multi_index/composite_key.hpp>
39#include <boost/multi_index/hashed_index.hpp>
40#include <boost/multi_index/member.hpp>
44 struct SpellIdDifficultyIndex;
47 boost::multi_index::multi_index_container<
49 boost::multi_index::indexed_by<
50 boost::multi_index::hashed_unique<
51 boost::multi_index::tag<SpellIdDifficultyIndex>,
52 boost::multi_index::composite_key<
54 boost::multi_index::member<SpellInfo, uint32 const, &SpellInfo::Id>,
55 boost::multi_index::member<SpellInfo, Difficulty const, &SpellInfo::Difficulty>
58 boost::multi_index::hashed_non_unique<
59 boost::multi_index::tag<SpellIdIndex>,
60 boost::multi_index::member<SpellInfo, uint32 const, &SpellInfo::Id>
65 class ServersideSpellName
68 explicit ServersideSpellName(
uint32 id, std::string name) : _nameStorage(
std::move(name))
74 ServersideSpellName(ServersideSpellName
const& right) : _nameStorage(right._nameStorage)
76 Name.ID = right.Name.ID;
80 ServersideSpellName(ServersideSpellName&& right) noexcept : _nameStorage(std::move(right._nameStorage))
82 Name.ID = right.Name.ID;
92 std::fill(std::begin(
Name.Name.Str), std::end(
Name.Name.Str), _nameStorage.c_str());
95 std::string _nameStorage;
98 std::vector<ServersideSpellName> mServersideSpellNames;
100 std::unordered_map<std::pair<uint32, Difficulty>,
SpellProcEntry> mSpellProcMap;
101 std::unordered_map<int32, CreatureImmunities> mCreatureImmunities;
121 for (SkillLineAbilityMap::const_iterator itr = skillBounds.first; itr != skillBounds.second; ++itr)
122 if (itr->second->SkillLine ==
int32(skillId))
148 bool needCheckReagents =
false;
153 switch (spellEffectInfo.Effect)
159 if (spellEffectInfo.ItemType == 0)
169 TC_LOG_ERROR(
"sql.sql",
"The craft spell {} does not have a create item entry.", spellInfo->
Id);
176 else if (!
sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType))
183 TC_LOG_ERROR(
"sql.sql",
"Craft spell {} has created a non-existing item in DB item (Entry: {}) and then...", spellInfo->
Id, spellEffectInfo.ItemType);
188 needCheckReagents =
true;
201 TC_LOG_ERROR(
"sql.sql",
"Spell {} learn to invalid spell {}, and then...", spellInfo->
Id, spellEffectInfo.TriggerSpell);
212 if (needCheckReagents)
223 TC_LOG_ERROR(
"sql.sql",
"Craft spell {} refers to a non-existing reagent in DB, item (Entry: {}) and then...", spellInfo->
Id, spellInfo->
Reagent[j]);
235 SpellChainMap::const_iterator itr =
mSpellChains.find(spell_id);
245 return node->first->Id;
253 return node->last->Id;
262 return node->next->Id;
271 return node->prev->Id;
288 if (rank != node->rank)
289 return GetSpellWithRank(node->rank < rank ? node->next->Id : node->prev->Id, rank, strict);
291 else if (strict && rank > 1)
309 for (SpellsRequiringSpellMap::const_iterator itr = spellsRequiringSpell.first; itr != spellsRequiringSpell.second; ++itr)
311 if (itr->second == spellid)
339 for (SpellLearnSpellMap::const_iterator i = bounds.first; i != bounds.second; ++i)
340 if (i->second.Spell == spell_id2)
347 SpellTargetPositionMap::const_iterator itr =
mSpellTargetPositions.find(std::make_pair(spell_id, effIndex));
362 for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second; ++itr)
364 if (itr->second == groupid)
377 std::set<SpellGroup> usedGroups;
383 if (usedGroups.find(group_id) != usedGroups.end())
385 usedGroups.insert(group_id);
388 for (SpellGroupSpellMap::const_iterator itr = groupSpell.first; itr != groupSpell.second; ++itr)
397 foundSpells.insert(itr->second);
407 for (
auto itr = spellGroupBounds.first; itr != spellGroupBounds.second; ++itr)
414 if (!found->second.count(auraType))
418 auto groupItr = groups.find(group);
419 if (groupItr == groups.end())
420 groups.emplace(group, amount);
423 int32 curr_amount = groups[group];
425 if (std::abs(curr_amount) < std::abs(amount))
426 groupItr->second = amount;
446 std::set<SpellGroup> groups;
447 for (SpellSpellGroupMap::const_iterator itr = spellGroup1.first; itr != spellGroup1.second; ++itr)
453 for (SpellGroupSpellMap::const_iterator itr2 = groupSpell.first; itr2 != groupSpell.second; ++itr2)
455 if (itr2->second < 0)
466 groups.insert(itr->second);
472 for (std::set<SpellGroup>::iterator itr = groups.begin(); itr!= groups.end(); ++itr)
476 rule = found->second;
506 difficulty =
sDifficultyStore.LookupEntry(difficulty->FallbackDifficultyID);
507 }
while (difficulty);
532 auto m = std::find_if(costs.begin(), costs.end(), [](
SpellPowerCost const& cost) { return cost.Amount > 0; });
533 if (m == costs.end())
607 SpellPetAuraMap::const_iterator itr =
mSpellPetAuraMap.find((spell_id<<8) + eff);
684 auto itr = mSpellInfoMap.find(boost::make_tuple(spellId, difficulty));
685 if (itr != mSpellInfoMap.end())
692 itr = mSpellInfoMap.find(boost::make_tuple(spellId,
Difficulty(difficultyEntry->FallbackDifficultyID)));
693 if (itr != mSpellInfoMap.end())
696 difficultyEntry =
sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
697 }
while (difficultyEntry);
710 for (
SpellInfo const& spellInfo : mSpellInfoMap)
711 callback(&spellInfo);
717 callback(&spellInfo);
749 return bg->IsSpellAllowed(
spellId, player);
792 return battlefieldWG->IsEnabled() && (player->
GetTeamId() == battlefieldWG->GetDefenderTeam()) && !battlefieldWG->IsWarTime();
801 return bf->IsWarTime();
814 const_cast<SpellInfo&
>(spellInfo).ChainEntry =
nullptr;
824 std::set<uint32> hasPrev;
827 if (!skillAbility->SupercedesSpell)
833 chains[skillAbility->SupercedesSpell] = skillAbility->Spell;
834 hasPrev.insert(skillAbility->Spell);
838 for (
auto itr = chains.begin(); itr != chains.end(); ++itr)
840 if (hasPrev.count(itr->first))
863 auto nextItr = chains.find(itr->second);
864 while (nextItr != chains.end())
886 nextItr = chains.find(nextItr->second);
905 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell required records. DB table `spell_required` is empty.");
913 Field* fields = result->Fetch();
922 TC_LOG_ERROR(
"sql.sql",
"spell_id {} in `spell_required` table could not be found in dbc, skipped.", spell_id);
929 TC_LOG_ERROR(
"sql.sql",
"req_spell {} in `spell_required` table could not be found in dbc, skipped.", spell_req);
935 TC_LOG_ERROR(
"sql.sql",
"req_spell {} and spell_id {} in `spell_required` table are ranks of the same spell, entry not needed, skipped.", spell_req, spell_id);
941 TC_LOG_ERROR(
"sql.sql",
"Duplicate entry of req_spell {} and spell_id {} in `spell_required`, skipped.", spell_req, spell_id);
945 mSpellReq.insert (std::pair<uint32, uint32>(spell_id, spell_req));
946 mSpellsReqSpell.insert (std::pair<uint32, uint32>(spell_req, spell_id));
948 }
while (result->NextRow());
962 for (
SpellInfo const& entry : mSpellInfoMap)
970 switch (spellEffectInfo.Effect)
973 dbc_node.
skill =
uint16(spellEffectInfo.MiscValue);
974 dbc_node.
step =
uint16(spellEffectInfo.CalcValue());
1007 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell learn spells. DB table `spell_learn_spell` is empty.");
1014 Field* fields = result->Fetch();
1027 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_learn_spell` does not exist.", spell_id);
1033 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_learn_spell` learning non-existing spell {}.", spell_id, node.
Spell);
1039 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_learn_spell` attempts learning talent spell {}, skipped.", spell_id, node.
Spell);
1046 }
while (result->NextRow());
1053 for (
SpellInfo const& entry : mSpellInfoMap)
1063 dbc_node.
Spell = spellEffectInfo.TriggerSpell;
1079 for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
1081 if (itr->second.Spell == dbc_node.
Spell)
1083 TC_LOG_ERROR(
"sql.sql",
"The spell {} is an auto-learn spell {} in spell.dbc and the record in `spell_learn_spell` is redundant. Please update your DB.",
1084 entry.Id, dbc_node.
Spell);
1107 for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
1109 if (
int32(itr->second.Spell) == spellLearnSpell->LearnSpellID)
1111 TC_LOG_ERROR(
"sql.sql",
"Found redundant record (entry: {}, SpellID: {}) in `spell_learn_spell`, spell added automatically from SpellLearnSpell.db2", spellLearnSpell->SpellID, spellLearnSpell->LearnSpellID);
1123 for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr)
1125 if (
int32(itr->second.Spell) == spellLearnSpell->LearnSpellID)
1136 dbcLearnNode.
Spell = spellLearnSpell->LearnSpellID;
1138 dbcLearnNode.
Active =
true;
1141 mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spellLearnSpell->SpellID, dbcLearnNode));
1145 TC_LOG_INFO(
"server.loading",
">> Loaded {} spell learn spells, {} found in Spell.dbc in {} ms", count, dbc_count,
GetMSTimeDiffToNow(oldMSTime));
1155 QueryResult result =
WorldDatabase.Query(
"SELECT ID, EffectIndex, MapID, PositionX, PositionY, PositionZ, Orientation FROM spell_target_position");
1158 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell target coordinates. DB table `spell_target_position` is empty.");
1165 Field* fields = result->Fetch();
1186 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, EffectIndex: {}): target coordinates not provided.", spellId,
uint32(effIndex));
1193 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}) listed in `spell_target_position` does not exist.", spellId);
1197 if (effIndex >= spellInfo->
GetEffects().size())
1199 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, EffectIndex: {}) listed in `spell_target_position` does not have an effect at index {}.", spellId,
uint32(effIndex),
uint32(effIndex));
1203 if (!fields[6].IsNull())
1214 auto hasTarget = [&](
Targets target)
1222 std::pair<uint32, SpellEffIndex> key = std::make_pair(spellId, effIndex);
1228 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, effIndex: {}) listed in `spell_target_position` does not have a target TARGET_DEST_DB (17).", spellId,
uint32(effIndex));
1232 }
while (result->NextRow());
1271 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell group definitions. DB table `spell_group` is empty.");
1275 std::set<uint32> groups;
1279 Field* fields = result->Fetch();
1284 TC_LOG_ERROR(
"sql.sql",
"SpellGroup id {} listed in `spell_group` is in core range, but is not defined in core!", group_id);
1289 groups.insert(group_id);
1292 }
while (result->NextRow());
1296 if (itr->second < 0)
1298 if (groups.find(abs(itr->second)) == groups.end())
1300 TC_LOG_ERROR(
"sql.sql",
"SpellGroup id {} listed in `spell_group` does not exist", abs(itr->second));
1311 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_group` does not exist", itr->second);
1314 else if (spellInfo->
GetRank() > 1)
1316 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_group` is not the first rank of the spell.", itr->second);
1324 for (
auto groupItr = groups.begin(); groupItr != groups.end(); ++groupItr)
1326 std::set<uint32> spells;
1329 for (
auto spellItr = spells.begin(); spellItr != spells.end(); ++spellItr)
1346 std::vector<uint32> sameEffectGroups;
1352 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell group stack rules. DB table `spell_group_stack_rules` is empty.");
1359 Field* fields = result->Fetch();
1365 TC_LOG_ERROR(
"sql.sql",
"SpellGroupStackRule {} listed in `spell_group_stack_rules` does not exist.", stack_rule);
1370 if (bounds.first == bounds.second)
1372 TC_LOG_ERROR(
"sql.sql",
"SpellGroup id {} listed in `spell_group_stack_rules` does not exist.", group_id);
1380 sameEffectGroups.push_back(group_id);
1383 }
while (result->NextRow());
1389 TC_LOG_INFO(
"server.loading",
">> Parsing SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules...");
1391 for (
uint32 group_id : sameEffectGroups)
1393 std::set<uint32> spellIds;
1396 std::unordered_set<uint32> auraTypes;
1400 std::unordered_multiset<
uint32 > frequencyContainer;
1403 std::vector<std::vector<
uint32 >>
const SubGroups =
1408 for (
uint32 spellId : spellIds)
1413 if (!spellEffectInfo.IsAura())
1416 uint32 auraName = spellEffectInfo.ApplyAuraName;
1417 for (std::vector<uint32>
const& subGroup : SubGroups)
1419 if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end())
1422 auraName = subGroup.front();
1427 frequencyContainer.insert(auraName);
1432 size_t auraTypeCount = 0;
1433 for (
uint32 auraName : frequencyContainer)
1435 size_t currentCount = frequencyContainer.count(auraName);
1436 if (currentCount > auraTypeCount)
1438 auraType = auraName;
1439 auraTypeCount = currentCount;
1443 for (std::vector<uint32>
const& subGroup : SubGroups)
1445 if (auraType == subGroup.front())
1447 auraTypes.insert(subGroup.begin(), subGroup.end());
1452 if (auraTypes.empty())
1453 auraTypes.insert(auraType);
1457 for (
uint32 spellId : spellIds)
1464 for (
uint32 auraType : auraTypes)
1481 TC_LOG_ERROR(
"sql.sql",
"SpellId {} listed in `spell_group` with stack rule 3 does not share aura assigned for group {}", spellId, group_id);
1488 TC_LOG_INFO(
"server.loading",
">> Parsed {} SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules in {} ms", count,
GetMSTimeDiffToNow(oldMSTime));
1495 mSpellProcMap.clear();
1498 QueryResult result =
WorldDatabase.Query(
"SELECT SpellId, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, SpellFamilyMask3, "
1500 "ProcFlags, ProcFlags2, SpellTypeMask, SpellPhaseMask, HitMask, AttributesMask, DisableEffectsMask, ProcsPerMinute, Chance, Cooldown, Charges FROM spell_proc");
1507 Field* fields = result->Fetch();
1511 bool allRanks =
false;
1521 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` does not exist", spellId);
1528 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` with all ranks, but spell has no ranks.", spellId);
1532 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` is not the first rank of the spell.", spellId);
1559 if (mSpellProcMap.find({ spellInfo->Id, spellInfo->Difficulty }) != mSpellProcMap.end())
1561 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` already has its first rank in the table.", spellInfo->
Id);
1574 if (procEntry.
Cooldown == Milliseconds::zero())
1579 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has wrong `SchoolMask` set: {}", spellInfo->
Id, procEntry.
SchoolMask);
1581 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has wrong `SpellFamilyName` set: {}", spellInfo->
Id, procEntry.
SpellFamilyName);
1582 if (procEntry.
Chance < 0)
1584 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has negative value in the `Chance` field", spellInfo->
Id);
1589 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has negative value in the `ProcsPerMinute` field", spellInfo->
Id);
1593 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} doesn't have any `ProcFlags` value defined, proc will not be triggered.", spellInfo->
Id);
1595 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has wrong `SpellTypeMask` set: {}", spellInfo->
Id, procEntry.
SpellTypeMask);
1597 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has `SpellTypeMask` value defined, but it will not be used for the defined `ProcFlags` value.", spellInfo->
Id);
1599 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} doesn't have any `SpellPhaseMask` value defined, but it is required for the defined `ProcFlags` value. Proc will not be triggered.", spellInfo->
Id);
1601 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has wrong `SpellPhaseMask` set: {}", spellInfo->
Id, procEntry.
SpellPhaseMask);
1603 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has a `SpellPhaseMask` value defined, but it will not be used for the defined `ProcFlags` value.", spellInfo->
Id);
1607 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has wrong `HitMask` set: {}", spellInfo->
Id, procEntry.
HitMask);
1609 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has `HitMask` value defined, but it will not be used for defined `ProcFlags` and `SpellPhaseMask` values.", spellInfo->
Id);
1611 if ((procEntry.
DisableEffectsMask & (1u << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsAura())
1612 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has DisableEffectsMask with effect {}, but effect {} is not an aura effect", spellInfo->
Id,
static_cast<uint32>(spellEffectInfo.EffectIndex),
static_cast<uint32>(spellEffectInfo.EffectIndex));
1618 if (!spellEffectInfo.IsAura())
1631 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has Attribute PROC_ATTR_REQ_SPELLMOD, but spell has no spell mods. Proc will not be triggered", spellInfo->
Id);
1639 mSpellProcMap[{ spellInfo->
Id, spellInfo->
Difficulty }] = procEntry;
1647 }
while (result->NextRow());
1650 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell proc conditions and data. DB table `spell_proc` is empty.");
1668 isTriggerAura[i] =
false;
1669 isAlwaysTriggeredAura[i] =
false;
1746 TC_LOG_INFO(
"server.loading",
"Generating spell proc data from SpellMap...");
1750 for (
SpellInfo const& spellInfo : mSpellInfoMap)
1753 if (mSpellProcMap.find({ spellInfo.Id, spellInfo.Difficulty }) != mSpellProcMap.end())
1757 if (!spellInfo.ProcFlags)
1760 bool addTriggerFlag =
false;
1765 if (!spellEffectInfo.IsEffect())
1768 uint32 auraName = spellEffectInfo.ApplyAuraName;
1772 if (!isTriggerAura[auraName])
1775 nonProcMask |= 1 << spellEffectInfo.EffectIndex;
1779 procSpellTypeMask |= spellTypeMask[auraName];
1780 if (isAlwaysTriggeredAura[auraName])
1781 addTriggerFlag =
true;
1791 addTriggerFlag =
true;
1799 if (!procSpellTypeMask)
1803 if (spellEffectInfo.IsAura())
1805 TC_LOG_ERROR(
"sql.sql",
"Spell Id {} has DBC ProcFlags 0x{:X} 0x{:X}, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.",
1806 spellInfo.Id,
uint32(spellInfo.ProcFlags[0]),
uint32(spellInfo.ProcFlags[1]));
1816 procEntry.
ProcFlags = spellInfo.ProcFlags;
1819 if (spellEffectInfo.IsEffect() && isTriggerAura[spellEffectInfo.ApplyAuraName])
1832 bool triggersSpell =
false;
1835 if (!spellEffectInfo.IsAura())
1838 switch (spellEffectInfo.ApplyAuraName)
1855 if (spellEffectInfo.CalcValue() <= -100)
1860 triggersSpell = spellEffectInfo.TriggerSpell != 0;
1876 procEntry.
Chance = spellInfo.ProcChance;
1878 procEntry.
Charges = spellInfo.ProcCharges;
1881 && procEntry.
Chance >= 100
1882 && spellInfo.ProcBasePPM <= 0.0f
1890 TC_LOG_ERROR(
"sql.sql",
"Spell Id {} has SPELL_ATTR3_CAN_PROC_FROM_PROCS attribute and no restriction on what spells can cause it to proc and no cooldown. "
1891 "This spell can cause infinite proc loops. Proc data for this spell was not generated, data in `spell_proc` table is required for it to function!",
1896 mSpellProcMap[{ spellInfo.Id, spellInfo.Difficulty }] = procEntry;
1913 TC_LOG_INFO(
"server.loading",
">> Loaded 0 aggro generating spells. DB table `spell_threat` is empty.");
1920 Field* fields = result->Fetch();
1926 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_threat` does not exist.", entry);
1937 }
while (result->NextRow());
1973 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell pet auras. DB table `spell_pet_auras` is empty.");
1980 Field* fields = result->Fetch();
1989 itr->second.AddAura(pet, aura);
1995 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_pet_auras` does not exist.", spell);
2000 TC_LOG_ERROR(
"spells",
"The spell {} listed in `spell_pet_auras` does not have any effect at index {}", spell,
uint32(eff));
2008 TC_LOG_ERROR(
"spells",
"The spell {} listed in `spell_pet_auras` does not have any dummy aura or dummy effect.", spell);
2015 TC_LOG_ERROR(
"sql.sql",
"The aura {} listed in `spell_pet_auras` does not exist.", aura);
2024 }
while (result->NextRow());
2036 QueryResult result =
WorldDatabase.Query(
"SELECT EnchantID, Chance, ProcsPerMinute, HitMask, AttributesMask FROM spell_enchant_proc_data");
2039 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty.");
2046 Field* fields = result->Fetch();
2053 TC_LOG_ERROR(
"sql.sql",
"The enchancment {} listed in `spell_enchant_proc_data` does not exist.", enchantId);
2067 }
while (result->NextRow());
2082 TC_LOG_INFO(
"server.loading",
">> Loaded 0 linked spells. DB table `spell_linked_spell` is empty.");
2089 Field* fields = result->Fetch();
2098 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_linked_spell` does not exist.", abs(trigger));
2106 if (spellEffectInfo.CalcValue() == abs(effect))
2107 TC_LOG_ERROR(
"sql.sql",
"The spell {} Effect: {} listed in `spell_linked_spell` has same bp{} like effect (possible hack).", abs(trigger), abs(effect),
uint32(spellEffectInfo.EffectIndex));
2114 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_linked_spell` does not exist.", abs(effect));
2120 TC_LOG_ERROR(
"sql.sql",
"The spell trigger {}, effect {} listed in `spell_linked_spell` has invalid link type {}, skipped.", trigger, effect, type);
2127 TC_LOG_ERROR(
"sql.sql",
"The spell trigger {} listed in `spell_linked_spell` has invalid link type {}, changed to 0.", trigger, type);
2135 if (trigger == effect)
2137 TC_LOG_ERROR(
"sql.sql",
"The spell trigger {}, effect {} listed in `spell_linked_spell` triggers itself (infinite loop), skipped.", trigger, effect);
2145 }
while (result->NextRow());
2162 if (!creatureFamily)
2165 for (
uint8 j = 0; j < 2; ++j)
2170 std::vector<SkillLineAbilityEntry const*>
const* skillLineAbilities =
sDB2Manager.GetSkillLineAbilitiesBySkill(creatureFamily->
SkillLine[j]);
2171 if (!skillLineAbilities)
2187 if (spellSet.empty())
2190 spellSet.insert(PetLevelupSpellSet::value_type(spell->
SpellLevel, spell->
Id));
2196 TC_LOG_INFO(
"server.loading",
">> Loaded {} pet levelup and default spells for {} families in {} ms", count, family_count,
GetMSTimeDiffToNow(oldMSTime));
2202 bool have_spell =
false;
2222 for (PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)
2224 if (itr->second == petDefSpells.
spellid[j])
2253 uint32 countCreature = 0;
2255 TC_LOG_INFO(
"server.loading",
"Loading summonable creature templates...");
2259 for (
SpellInfo const& spellEntry : mSpellInfoMap)
2264 for (
SpellEffectInfo const& spellEffectInfo : spellEntry.GetEffects())
2268 uint32 creature_id = spellEffectInfo.MiscValue;
2305 QueryResult result =
WorldDatabase.Query(
"SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, flags FROM spell_area");
2308 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell area requirements. DB table `spell_area` is empty.");
2316 Field* fields = result->Fetch();
2338 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` does not exist", spell);
2345 for (SpellAreaMap::const_iterator itr = sa_bounds.first; itr != sa_bounds.second; ++itr)
2347 if (spellArea.
spellId != itr->second.spellId)
2349 if (spellArea.
areaId != itr->second.areaId)
2351 if (spellArea.
questStart != itr->second.questStart)
2353 if (spellArea.
auraSpell != itr->second.auraSpell)
2355 if ((spellArea.
raceMask & itr->second.raceMask).IsEmpty())
2357 if (spellArea.
gender != itr->second.gender)
2367 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` is already listed with similar requirements.", spell);
2374 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has a wrong area ({}) requirement.", spell, spellArea.
areaId);
2380 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has a wrong start quest ({}) requirement.", spell, spellArea.
questStart);
2388 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has a wrong ending quest ({}) requirement.", spell, spellArea.
questEnd);
2398 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has wrong aura spell ({}) requirement", spell, abs(spellArea.
auraSpell));
2404 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has aura spell ({}) requirement for itself", spell, abs(spellArea.
auraSpell));
2413 for (SpellAreaForAuraMap::const_iterator itr = saBound.first; itr != saBound.second; ++itr)
2424 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has the aura spell ({}) requirement that it autocasts itself from the aura.", spell, spellArea.
auraSpell);
2429 for (SpellAreaMap::const_iterator itr2 = saBound2.first; itr2 != saBound2.second; ++itr2)
2440 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has the aura spell ({}) requirement that the spell itself autocasts from the aura.", spell, spellArea.
auraSpell);
2448 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has wrong race mask ({}) requirement.", spell, spellArea.
raceMask.
RawValue);
2454 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has wrong gender ({}) requirement.", spell, spellArea.
gender);
2487 }
while (result->NextRow());
2502 std::unordered_map<int32, BattlePetSpeciesEntry const*> battlePetSpeciesByCreature;
2504 if (battlePetSpecies->CreatureID)
2505 battlePetSpeciesByCreature[battlePetSpecies->CreatureID] = battlePetSpecies;
2509 ASSERT(effect->EffectIndex <
MAX_SPELL_EFFECTS,
"MAX_SPELL_EFFECTS must be at least %d", effect->EffectIndex + 1);
2511 ASSERT(effect->EffectAura <
int32(
TOTAL_AURAS),
"TOTAL_AURAS must be at least %d", effect->EffectAura + 1);
2512 ASSERT(effect->ImplicitTarget[0] <
TOTAL_SPELL_TARGETS,
"TOTAL_SPELL_TARGETS must be at least %u", effect->ImplicitTarget[0] + 1);
2513 ASSERT(effect->ImplicitTarget[1] <
TOTAL_SPELL_TARGETS,
"TOTAL_SPELL_TARGETS must be at least %u", effect->ImplicitTarget[1] + 1);
2515 loadData[{ effect->SpellID,
Difficulty(effect->DifficultyID) }].Effects[effect->EffectIndex] = effect;
2526 switch (effect->EffectAura)
2532 ASSERT(effect->EffectMiscValue[0] <
MAX_SPELLMOD,
"MAX_SPELLMOD must be at least %d", effect->EffectMiscValue[0] + 1);
2540 loadData[{ auraOptions->SpellID,
Difficulty(auraOptions->DifficultyID) }].AuraOptions = auraOptions;
2543 loadData[{ auraRestrictions->SpellID,
Difficulty(auraRestrictions->DifficultyID) }].AuraRestrictions = auraRestrictions;
2546 loadData[{ castingRequirements->SpellID,
DIFFICULTY_NONE }].CastingRequirements = castingRequirements;
2549 loadData[{ categories->SpellID,
Difficulty(categories->DifficultyID) }].Categories = categories;
2552 loadData[{ classOptions->SpellID,
DIFFICULTY_NONE }].ClassOptions = classOptions;
2555 loadData[{ cooldowns->SpellID,
Difficulty(cooldowns->DifficultyID) }].Cooldowns = cooldowns;
2558 loadData[{ equippedItems->SpellID,
DIFFICULTY_NONE }].EquippedItems = equippedItems;
2561 loadData[{ interrupts->SpellID,
Difficulty(interrupts->DifficultyID) }].Interrupts = interrupts;
2564 loadData[{ label->SpellID,
DIFFICULTY_NONE }].Labels.push_back(label);
2567 loadData[{ levels->SpellID,
Difficulty(levels->DifficultyID) }].Levels = levels;
2570 loadData[{ misc->SpellID,
Difficulty(misc->DifficultyID) }].Misc = misc;
2575 uint8 index = power->OrderIndex;
2578 difficulty =
Difficulty(powerDifficulty->DifficultyID);
2579 index = powerDifficulty->OrderIndex;
2582 loadData[{ power->SpellID, difficulty }].Powers[index] = power;
2589 loadData[{ reagentsCurrency->SpellID,
DIFFICULTY_NONE }].ReagentsCurrency.push_back(reagentsCurrency);
2595 loadData[{ shapeshift->SpellID,
DIFFICULTY_NONE }].Shapeshift = shapeshift;
2598 loadData[{ targetRestrictions->SpellID,
Difficulty(targetRestrictions->DifficultyID) }].TargetRestrictions = targetRestrictions;
2609 return first->CasterPlayerConditionID > second->CasterPlayerConditionID;
2613 visuals.insert(where, visual);
2616 for (std::pair<std::pair<uint32, Difficulty>
const,
SpellInfoLoadHelper>& data : loadData)
2619 if (!spellNameEntry)
2629 if (!data.second.AuraOptions)
2630 data.second.AuraOptions = fallbackData->AuraOptions;
2632 if (!data.second.AuraRestrictions)
2633 data.second.AuraRestrictions = fallbackData->AuraRestrictions;
2635 if (!data.second.CastingRequirements)
2636 data.second.CastingRequirements = fallbackData->CastingRequirements;
2638 if (!data.second.Categories)
2639 data.second.Categories = fallbackData->Categories;
2641 if (!data.second.ClassOptions)
2642 data.second.ClassOptions = fallbackData->ClassOptions;
2644 if (!data.second.Cooldowns)
2645 data.second.Cooldowns = fallbackData->Cooldowns;
2647 for (std::size_t i = 0; i < data.second.Effects.size(); ++i)
2648 if (!data.second.Effects[i])
2649 data.second.Effects[i] = fallbackData->Effects[i];
2651 if (!data.second.EquippedItems)
2652 data.second.EquippedItems = fallbackData->EquippedItems;
2654 if (!data.second.Interrupts)
2655 data.second.Interrupts = fallbackData->Interrupts;
2657 if (data.second.Labels.empty())
2658 data.second.Labels = fallbackData->Labels;
2660 if (!data.second.Levels)
2661 data.second.Levels = fallbackData->Levels;
2663 if (!data.second.Misc)
2664 data.second.Misc = fallbackData->Misc;
2666 for (std::size_t i = 0; i < fallbackData->Powers.size(); ++i)
2667 if (!data.second.Powers[i])
2668 data.second.Powers[i] = fallbackData->Powers[i];
2670 if (!data.second.Reagents)
2671 data.second.Reagents = fallbackData->Reagents;
2673 if (data.second.ReagentsCurrency.empty())
2674 data.second.ReagentsCurrency = fallbackData->ReagentsCurrency;
2676 if (!data.second.Scaling)
2677 data.second.Scaling = fallbackData->Scaling;
2679 if (!data.second.Shapeshift)
2680 data.second.Shapeshift = fallbackData->Shapeshift;
2682 if (!data.second.TargetRestrictions)
2683 data.second.TargetRestrictions = fallbackData->TargetRestrictions;
2685 if (!data.second.Totems)
2686 data.second.Totems = fallbackData->Totems;
2690 if (data.second.Visuals.empty())
2691 data.second.Visuals = fallbackData->Visuals;
2694 difficultyEntry =
sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
2695 }
while (difficultyEntry);
2698 mSpellInfoMap.emplace(spellNameEntry, data.first.second, data.second);
2706 mSpellInfoMap.clear();
2707 mServersideSpellNames.clear();
2712 for (
SpellInfo const& spellInfo : mSpellInfoMap)
2713 const_cast<SpellInfo&
>(spellInfo)._UnloadImplicitTargetConditionLists();
2720 std::unordered_map<std::pair<uint32, Difficulty>, std::vector<SpellEffectEntry>> spellEffects;
2723 QueryResult effectsResult =
WorldDatabase.Query(
"SELECT SpellID, EffectIndex, DifficultyID, Effect, EffectAura, EffectAmplitude, EffectAttributes, "
2725 "EffectAuraPeriod, EffectBonusCoefficient, EffectChainAmplitude, EffectChainTargets, EffectItemType, EffectMechanic, EffectPointsPerResource, "
2727 "EffectPosFacing, EffectRealPointsPerLevel, EffectTriggerSpell, BonusCoefficientFromAP, PvpMultiplier, Coefficient, Variance, "
2729 "ResourceCoefficient, GroupSizeBasePointsCoefficient, EffectBasePoints, EffectMiscValue1, EffectMiscValue2, EffectRadiusIndex1, "
2731 "EffectRadiusIndex2, EffectSpellClassMask1, EffectSpellClassMask2, EffectSpellClassMask3, EffectSpellClassMask4, ImplicitTarget1, "
2733 "ImplicitTarget2 FROM serverside_spell_effect");
2738 Field* fields = effectsResult->Fetch();
2743 effect.Effect = fields[3].
GetInt32();
2744 effect.EffectAura = fields[4].
GetInt16();
2745 effect.EffectAmplitude = fields[5].
GetFloat();
2746 effect.EffectAttributes = fields[6].
GetInt32();
2747 effect.EffectAuraPeriod = fields[7].
GetInt32();
2748 effect.EffectBonusCoefficient = fields[8].
GetFloat();
2749 effect.EffectChainAmplitude = fields[9].
GetFloat();
2750 effect.EffectChainTargets = fields[10].
GetInt32();
2751 effect.EffectItemType = fields[11].
GetInt32();
2752 effect.EffectMechanic =
Mechanics(fields[12].GetInt32());
2753 effect.EffectPointsPerResource = fields[13].
GetFloat();
2754 effect.EffectPosFacing = fields[14].
GetFloat();
2755 effect.EffectRealPointsPerLevel = fields[15].
GetFloat();
2756 effect.EffectTriggerSpell = fields[16].
GetInt32();
2757 effect.BonusCoefficientFromAP = fields[17].
GetFloat();
2758 effect.PvpMultiplier = fields[18].
GetFloat();
2759 effect.Coefficient = fields[19].
GetFloat();
2760 effect.Variance = fields[20].
GetFloat();
2761 effect.ResourceCoefficient = fields[21].
GetFloat();
2762 effect.GroupSizeBasePointsCoefficient = fields[22].
GetFloat();
2763 effect.EffectBasePoints = fields[23].
GetFloat();
2764 effect.EffectMiscValue[0] = fields[24].
GetInt32();
2765 effect.EffectMiscValue[1] = fields[25].
GetInt32();
2766 effect.EffectRadiusIndex[0] = fields[26].
GetUInt32();
2767 effect.EffectRadiusIndex[1] = fields[27].
GetUInt32();
2768 effect.EffectSpellClassMask =
flag128(fields[28].GetInt32(), fields[29].GetInt32(), fields[30].GetInt32(), fields[31].GetInt32());
2769 effect.ImplicitTarget[0] = fields[32].
GetInt16();
2770 effect.ImplicitTarget[1] = fields[33].
GetInt16();
2773 if (existingSpellBounds.begin() != existingSpellBounds.end())
2775 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} effext index {} references a regular spell loaded from file. Adding serverside effects to existing spells is not allowed.",
2776 spellId,
uint32(difficulty), effect.EffectIndex);
2782 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} effect index {} references non-existing difficulty {}, skipped",
2783 spellId, effect.EffectIndex,
uint32(difficulty));
2789 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has more than {} effects, effect at index {} skipped",
2796 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid effect type {} at index {}, skipped",
2797 spellId,
uint32(difficulty), effect.Effect, effect.EffectIndex);
2803 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid aura type {} at index {}, skipped",
2804 spellId,
uint32(difficulty), effect.EffectAura, effect.EffectIndex);
2810 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid targetA type {} at index {}, skipped",
2811 spellId,
uint32(difficulty), effect.ImplicitTarget[0], effect.EffectIndex);
2817 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid targetB type {} at index {}, skipped",
2818 spellId,
uint32(difficulty), effect.ImplicitTarget[1], effect.EffectIndex);
2822 if (effect.EffectRadiusIndex[0] && !
sSpellRadiusStore.HasRecord(effect.EffectRadiusIndex[0]))
2824 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid radius id {} at index {}, set to 0",
2825 spellId,
uint32(difficulty), effect.EffectRadiusIndex[0], effect.EffectIndex);
2828 if (effect.EffectRadiusIndex[1] && !
sSpellRadiusStore.HasRecord(effect.EffectRadiusIndex[1]))
2830 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid max radius id {} at index {}, set to 0",
2831 spellId,
uint32(difficulty), effect.EffectRadiusIndex[1], effect.EffectIndex);
2834 spellEffects[{ spellId, difficulty }].push_back(std::move(effect));
2836 }
while (effectsResult->NextRow());
2840 QueryResult spellsResult =
WorldDatabase.Query(
"SELECT Id, DifficultyID, CategoryId, Dispel, Mechanic, Attributes, AttributesEx, AttributesEx2, AttributesEx3, "
2842 "AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, AttributesEx8, AttributesEx9, AttributesEx10, AttributesEx11, AttributesEx12, AttributesEx13, "
2844 "AttributesEx14, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, CasterAuraState, TargetAuraState, "
2846 "ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, "
2848 "CasterAuraType, TargetAuraType, ExcludeCasterAuraType, ExcludeTargetAuraType, CastingTimeIndex, "
2850 "RecoveryTime, CategoryRecoveryTime, StartRecoveryCategory, StartRecoveryTime, InterruptFlags, AuraInterruptFlags1, AuraInterruptFlags2, "
2852 "ChannelInterruptFlags1, ChannelInterruptFlags2, ProcFlags, ProcFlags2, ProcChance, ProcCharges, ProcCooldown, ProcBasePPM, MaxLevel, BaseLevel, SpellLevel, "
2854 "DurationIndex, RangeIndex, Speed, LaunchDelay, StackAmount, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, ContentTuningId, "
2856 "SpellName, ConeAngle, ConeWidth, MaxTargetLevel, MaxAffectedTargets, SpellFamilyName, SpellFamilyFlags1, SpellFamilyFlags2, SpellFamilyFlags3, SpellFamilyFlags4, "
2858 "DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell");
2861 mServersideSpellNames.reserve(spellsResult->GetRowCount());
2865 Field* fields = spellsResult->Fetch();
2870 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} is already loaded from file. Overriding existing spells is not allowed.",
2871 spellId,
uint32(difficulty));
2875 mServersideSpellNames.emplace_back(spellId, fields[66].GetString());
2877 SpellInfo& spellInfo =
const_cast<SpellInfo&
>(*mSpellInfoMap.emplace(&mServersideSpellNames.back().Name, difficulty, spellEffects[{ spellId, difficulty }]).first);
2947 spellInfo.
SpellFamilyFlags =
flag128(fields[72].GetUInt32(), fields[73].GetUInt32(), fields[74].GetUInt32(), fields[75].GetUInt32());
2954 }
while (spellsResult->NextRow());
2963 uint32 oldMSTime2 = oldMSTime;
2968 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell custom attributes from DB. DB table `spell_custom_attr` is empty.");
2974 Field* fields = result->Fetch();
2980 if (spells.begin() == spells.end())
2982 TC_LOG_ERROR(
"sql.sql",
"Table `spell_custom_attr` has wrong spell (entry: {}), ignored.", spellId);
2986 for (
SpellInfo const& spellInfo : spells)
2992 TC_LOG_ERROR(
"sql.sql",
"Spell {} listed in table `spell_custom_attr` with SPELL_ATTR0_CU_SHARE_DAMAGE has no SPELL_EFFECT_SCHOOL_DAMAGE, ignored.", spellId);
2997 const_cast<SpellInfo&
>(spellInfo).AttributesCu |= attributes;
3000 }
while (result->NextRow());
3005 std::set<uint32> talentSpells;
3008 talentSpells.insert(talentInfo->SpellID);
3010 for (
SpellInfo const& spellInfo : mSpellInfoMap)
3019 switch (spellEffectInfo.ApplyAuraName)
3033 switch (spellEffectInfo.ApplyAuraName)
3052 switch (spellEffectInfo.Effect)
3071 switch (spellEffectInfo.Effect)
3109 uint32 enchantId = spellEffectInfo.MiscValue;
3141 bool setFlag =
false;
3144 if (spellEffectInfo.IsEffect())
3146 switch (spellEffectInfo.Effect)
3182 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)
3190 if (spellInfoMutable->
Id == 55095)
3214 spellInfoMutable->
SchoolMask &= ~SPELL_SCHOOL_MASK_NORMAL;
3220 if (talentSpells.count(spellInfoMutable->
Id))
3223 if (G3D::fuzzyNe(spellInfoMutable->
Width, 0.0f))
3240 if (spellInfoMutable->
Id == 5729)
3249 if (spellInfoMutable->
Speed > 0.0f)
3258 if (!spellVisualMissiles)
3264 if (!spellVisualEffectName)
3277 if (visualNeedsAmmo(spellXspellVisual))
3291 for (
SpellInfo const& spellInfo : mSpellInfoMap)
3296 bool allNonBinary =
true;
3297 bool overrideAttr =
false;
3300 if (spellEffectInfo.IsAura() && spellEffectInfo.TriggerSpell)
3302 switch (spellEffectInfo.ApplyAuraName)
3309 overrideAttr =
true;
3311 allNonBinary =
false;
3320 if (overrideAttr && allNonBinary)
3321 spellInfoMutable->
AttributesCu &= ~SPELL_ATTR0_CU_BINARY_SPELL;
3334 if (liquid->SpellID)
3344 for (
uint32 spellId : spellIds)
3347 if (range.begin() == range.end())
3349 TC_LOG_ERROR(
"server.loading",
"Spell info correction specified for non-existing spell {}", spellId);
3353 for (
SpellInfo const& spellInfo : range)
3354 fix(&
const_cast<SpellInfo&
>(spellInfo));
3360 if (spellInfo->
GetEffects().size() <= effectIndex)
3362 TC_LOG_ERROR(
"server.loading",
"Spell effect info correction specified for non-existing effect {} of spell {}",
uint32(effectIndex), spellInfo->
Id);
3922 spellInfo->
Speed = 0.f;
4100 spellInfo->
Speed = 0;
4315 spellInfo->
Speed = 0.0f;
4841 for (
SpellInfo const& s : mSpellInfoMap)
4856 float maxRangeTrigger = spellInfoTrigger.GetMaxRange();
4859 if (maxRangeTrigger < maxRangeMain)
4864 switch (spellEffectInfo.Effect)
4879 if (G3D::fuzzyEq(spellInfo->
ConeAngle, 0.f))
4883 if (spellEffectInfo.IsAreaAuraEffect() && spellEffectInfo.IsTargetingArea())
4892 spellInfo->
ProcFlags = std::array<int32, 2>{};
4919 for (
SpellInfo const& spellInfo : mSpellInfoMap)
4922 const_cast<SpellInfo&
>(spellInfo)._LoadSpellSpecific();
4923 const_cast<SpellInfo&
>(spellInfo)._LoadAuraState();
4933 for (
SpellInfo const& spellInfo : mSpellInfoMap)
4934 const_cast<SpellInfo&
>(spellInfo)._LoadSpellDiminishInfo();
4943 mCreatureImmunities.clear();
4946 if (
QueryResult result =
WorldDatabase.Query(
"SELECT ID, SchoolMask, DispelTypeMask, MechanicsMask, Effects, Auras, ImmuneAoE, ImmuneChain FROM creature_immunities"))
4950 Field* fields = result->Fetch();
4957 immunities.
School = school;
4960 if (fields[6].GetBool())
4962 if (fields[7].GetBool())
4965 if (immunities.
School.to_ullong() != school)
4966 TC_LOG_ERROR(
"sql.sql",
"Invalid value in `SchoolMask` {} for creature immunities {}, truncated", school,
id);
4967 if (immunities.
DispelType.to_ullong() != dispelType)
4968 TC_LOG_ERROR(
"sql.sql",
"Invalid value in `DispelTypeMask` {} for creature immunities {}, truncated", dispelType,
id);
4969 if (immunities.
Mechanic.to_ullong() != mechanics)
4970 TC_LOG_ERROR(
"sql.sql",
"Invalid value in `MechanicsMask` {} for creature immunities {}, truncated", mechanics,
id);
4972 for (std::string_view token :
Trinity::Tokenize(fields[4].GetStringView(),
',',
false))
4977 TC_LOG_ERROR(
"sql.sql",
"Invalid effect type in `Effects` {} for creature immunities {}, skipped", token,
id);
4980 for (std::string_view token :
Trinity::Tokenize(fields[5].GetStringView(),
',',
false))
4985 TC_LOG_ERROR(
"sql.sql",
"Invalid aura type in `Auras` {} for creature immunities {}, skipped", token,
id);
4988 while (result->NextRow());
4991 for (
SpellInfo const& spellInfo : mSpellInfoMap)
4992 const_cast<SpellInfo&
>(spellInfo)._LoadImmunityInfo();
4999 std::unordered_map<uint32, SpellLevelsEntry const*> levelsBySpell;
5001 if (!levels->DifficultyID)
5002 levelsBySpell[levels->SpellID] = levels;
5010 auto levels = levelsBySpell.find(skillLine->Spell);
5011 if (levels != levelsBySpell.end() && levels->second->SpellLevel)
5018 if (skillLine->SkillLine != cFamily->SkillLine[0] && skillLine->SkillLine != cFamily->SkillLine[1])
5038 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell totem model records. DB table `spell_totem_model` is empty.");
5045 Field* fields = result->Fetch();
5054 TC_LOG_ERROR(
"sql.sql",
"SpellID: {} in `spell_totem_model` table could not be found in dbc, skipped.", spellId);
5061 TC_LOG_ERROR(
"sql.sql",
"Race {} defined in `spell_totem_model` does not exists, skipped.",
uint32(race));
5068 TC_LOG_ERROR(
"sql.sql",
"SpellID: {} defined in `spell_totem_model` has non-existing model ({}).", spellId, displayId);
5075 }
while (result->NextRow());
@ BATTLEFIELD_BATTLEID_WG
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< SpellVisualEntry > sSpellVisualStore("SpellVisual.db2", &SpellVisualLoadInfo::Instance)
DB2Storage< SpellInterruptsEntry > sSpellInterruptsStore("SpellInterrupts.db2", &SpellInterruptsLoadInfo::Instance)
DB2Storage< SkillLineEntry > sSkillLineStore("SkillLine.db2", &SkillLineLoadInfo::Instance)
DB2Storage< SpellAuraOptionsEntry > sSpellAuraOptionsStore("SpellAuraOptions.db2", &SpellAuraOptionsLoadInfo::Instance)
DB2Storage< SpellNameEntry > sSpellNameStore("SpellName.db2", &SpellNameLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< LiquidTypeEntry > sLiquidTypeStore("LiquidType.db2", &LiquidTypeLoadInfo::Instance)
DB2Storage< CreatureFamilyEntry > sCreatureFamilyStore("CreatureFamily.db2", &CreatureFamilyLoadInfo::Instance)
DB2Storage< SpellXSpellVisualEntry > sSpellXSpellVisualStore("SpellXSpellVisual.db2", &SpellXSpellVisualLoadInfo::Instance)
DB2Storage< SpellEquippedItemsEntry > sSpellEquippedItemsStore("SpellEquippedItems.db2", &SpellEquippedItemsLoadInfo::Instance)
DB2Storage< SpellReagentsEntry > sSpellReagentsStore("SpellReagents.db2", &SpellReagentsLoadInfo::Instance)
DB2Storage< SpellPowerDifficultyEntry > sSpellPowerDifficultyStore("SpellPowerDifficulty.db2", &SpellPowerDifficultyLoadInfo::Instance)
DB2Storage< SpellRangeEntry > sSpellRangeStore("SpellRange.db2", &SpellRangeLoadInfo::Instance)
DB2Storage< SpellAuraRestrictionsEntry > sSpellAuraRestrictionsStore("SpellAuraRestrictions.db2", &SpellAuraRestrictionsLoadInfo::Instance)
DB2Storage< SpellShapeshiftEntry > sSpellShapeshiftStore("SpellShapeshift.db2", &SpellShapeshiftLoadInfo::Instance)
DB2Storage< SpellVisualEffectNameEntry > sSpellVisualEffectNameStore("SpellVisualEffectName.db2", &SpellVisualEffectNameLoadInfo::Instance)
DB2Storage< SpellMiscEntry > sSpellMiscStore("SpellMisc.db2", &SpellMiscLoadInfo::Instance)
DB2Storage< SpellLevelsEntry > sSpellLevelsStore("SpellLevels.db2", &SpellLevelsLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
DB2Storage< SpellDurationEntry > sSpellDurationStore("SpellDuration.db2", &SpellDurationLoadInfo::Instance)
DB2Storage< SpellLearnSpellEntry > sSpellLearnSpellStore("SpellLearnSpell.db2", &SpellLearnSpellLoadInfo::Instance)
DB2Storage< SpellCooldownsEntry > sSpellCooldownsStore("SpellCooldowns.db2", &SpellCooldownsLoadInfo::Instance)
DB2Storage< SkillLineAbilityEntry > sSkillLineAbilityStore("SkillLineAbility.db2", &SkillLineAbilityLoadInfo::Instance)
DB2Storage< SummonPropertiesEntry > sSummonPropertiesStore("SummonProperties.db2", &SummonPropertiesLoadInfo::Instance)
DB2Storage< SpellReagentsCurrencyEntry > sSpellReagentsCurrencyStore("SpellReagentsCurrency.db2", &SpellReagentsCurrencyLoadInfo::Instance)
DB2Storage< SpellCastingRequirementsEntry > sSpellCastingRequirementsStore("SpellCastingRequirements.db2", &SpellCastingRequirementsLoadInfo::Instance)
DB2Storage< SpellEffectEntry > sSpellEffectStore("SpellEffect.db2", &SpellEffectLoadInfo::Instance)
DB2Storage< SpellRadiusEntry > sSpellRadiusStore("SpellRadius.db2", &SpellRadiusLoadInfo::Instance)
DB2Storage< SpellTargetRestrictionsEntry > sSpellTargetRestrictionsStore("SpellTargetRestrictions.db2", &SpellTargetRestrictionsLoadInfo::Instance)
DB2Storage< ChrRacesEntry > sChrRacesStore("ChrRaces.db2", &ChrRacesLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore("CreatureDisplayInfo.db2", &CreatureDisplayInfoLoadInfo::Instance)
DB2Storage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore("SpellItemEnchantment.db2", &SpellItemEnchantmentLoadInfo::Instance)
DB2Storage< SpellClassOptionsEntry > sSpellClassOptionsStore("SpellClassOptions.db2", &SpellClassOptionsLoadInfo::Instance)
DB2Storage< TalentEntry > sTalentStore("Talent.db2", &TalentLoadInfo::Instance)
DB2Storage< SpellTotemsEntry > sSpellTotemsStore("SpellTotems.db2", &SpellTotemsLoadInfo::Instance)
DB2Storage< SpellCategoriesEntry > sSpellCategoriesStore("SpellCategories.db2", &SpellCategoriesLoadInfo::Instance)
DB2Storage< SpellLabelEntry > sSpellLabelStore("SpellLabel.db2", &SpellLabelLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
DB2Storage< SpellPowerEntry > sSpellPowerStore("SpellPower.db2", &SpellPowerLoadInfo::Instance)
DB2Storage< SpellCastTimesEntry > sSpellCastTimesStore("SpellCastTimes.db2", &SpellCastTimesLoadInfo::Instance)
DB2Storage< SpellScalingEntry > sSpellScalingStore("SpellScaling.db2", &SpellScalingLoadInfo::Instance)
#define MAX_SPELL_REAGENTS
#define MAX_ITEM_ENCHANTMENT_EFFECTS
@ ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
@ SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN
SpellVisualEffectNameType
#define MAX_SPELL_EFFECTS
@ SummonFromBattlePetJournal
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
#define TC_LOG_ERROR(filterType__,...)
#define TC_LOG_INFO(filterType__,...)
std::optional< T > Optional
Optional helper class to wrap optional values within.
constexpr Trinity::RaceMask< uint64 > RACEMASK_ALL_PLAYABLE
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
@ SPELL_ATTR9_SPECIAL_DELAY_CALCULATION
@ SKILL_CATEGORY_PROFESSION
@ SPELL_ATTR5_AI_DOESNT_FACE_TARGET
@ SPELL_ATTR5_EXTRA_INITIAL_PERIOD
@ TARGET_DEST_CASTER_LEFT
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_UNIT_SRC_AREA_ALLY
@ TARGET_DEST_NEARBY_ENTRY_OR_DB
@ TARGET_UNIT_TARGET_ENEMY
@ TARGET_UNIT_NEARBY_ENTRY
@ SPELL_SCHOOL_MASK_NORMAL
@ SPELL_SCHOOL_MASK_MAGIC
@ SPELL_ATTR2_NO_INITIAL_THREAT
@ SPELL_ATTR2_ALLOW_DEAD_TARGET
@ SPELL_ATTR2_IGNORE_LINE_OF_SIGHT
@ SPELL_ATTR1_EXCLUDE_CASTER
@ SPELL_ATTR1_IMMUNITY_PURGES_EFFECT
@ SPELL_ATTR3_ALLOW_AURA_WHILE_DEAD
@ SPELL_ATTR3_DOT_STACKING_RULE
@ SPELL_ATTR3_CAN_PROC_FROM_PROCS
@ SPELL_ATTR3_IGNORE_CASTER_MODIFIERS
@ SPELL_EFFECT_POWER_BURN
@ SPELL_EFFECT_ENERGIZE_PCT
@ SPELL_EFFECT_SUMMON_PET
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY
@ SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
@ SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
@ SPELL_EFFECT_ENCHANT_HELD_ITEM
@ SPELL_EFFECT_ENCHANT_ITEM
@ SPELL_EFFECT_CREATE_LOOT
@ SPELL_EFFECT_HEALTH_LEECH
@ SPELL_EFFECT_WEAPON_DAMAGE
@ SPELL_EFFECT_NORMALIZED_WEAPON_DMG
@ SPELL_EFFECT_APPLY_AURA_ON_PET
@ SPELL_EFFECT_TRIGGER_SPELL
@ SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
@ SPELL_EFFECT_HEAL_MAX_HEALTH
@ SPELL_EFFECT_APPLY_AREA_AURA_PET
@ SPELL_EFFECT_PICKPOCKET
@ SPELL_EFFECT_HEAL_MECHANICAL
@ SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
@ SPELL_EFFECT_APPLY_AREA_AURA_RAID
@ SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
@ SPELL_EFFECT_PERSISTENT_AREA_AURA
@ SPELL_EFFECT_DUAL_WIELD
@ SPELL_EFFECT_POWER_DRAIN
@ SPELL_EFFECT_SCHOOL_DAMAGE
@ SPELL_EFFECT_CHARGE_DEST
@ SPELL_EFFECT_LEARN_SPELL
@ SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
@ SPELL_EFFECT_INTERRUPT_CAST
@ SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS
@ SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
@ SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
@ SPELL_EFFECT_SKILL_STEP
@ SPELL_EFFECT_CREATE_ITEM
@ SPELL_EFFECT_APPLY_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_OWNER
@ SPELL_ATTR0_AURA_IS_DEBUFF
@ SPELL_ATTR0_ONLY_OUTDOORS
@ SPELL_ATTR0_NO_IMMUNITIES
@ SPELL_ATTR0_NO_AURA_CANCEL
@ SPELL_ATTR4_AURA_IS_BUFF
@ SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS
@ SPELL_ATTR8_CAN_ATTACK_IMMUNE_PC
@ SPELL_ATTR6_IGNORE_CASTER_DAMAGE_MODIFIERS
@ SPELL_ATTR6_IGNORE_PHASE_SHIFT
@ SPELL_AURA_MOD_SCHOOL_MASK_DAMAGE_FROM_CASTER
@ SPELL_AURA_MOD_ATTACK_POWER
@ SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_ABILITY_IGNORE_AURASTATE
@ SPELL_AURA_PERIODIC_HEALTH_FUNNEL
@ SPELL_AURA_ADD_PCT_MODIFIER
@ SPELL_AURA_MOD_POSSESS_PET
@ SPELL_AURA_MOD_RESISTANCE
@ SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ SPELL_AURA_ADD_FLAT_MODIFIER
@ SPELL_AURA_REFLECT_SPELLS
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_MOD_MELEE_HASTE
@ SPELL_AURA_MOD_SPELL_CRIT_CHANCE
@ SPELL_AURA_MOD_INVISIBILITY
@ SPELL_AURA_MOD_HIT_CHANCE
@ SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
@ SPELL_AURA_PERIODIC_DAMAGE_PERCENT
@ SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
@ SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
@ SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL
@ SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
@ SPELL_AURA_MOD_RANGED_HASTE
@ SPELL_AURA_IGNORE_SPELL_COOLDOWN
@ SPELL_AURA_MOD_POWER_COST_SCHOOL
@ SPELL_AURA_MECHANIC_IMMUNITY
@ SPELL_AURA_MOD_DAMAGE_TAKEN
@ SPELL_AURA_MOD_SPELL_DAMAGE_FROM_CASTER
@ SPELL_AURA_MOD_DECREASE_SPEED
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE
@ SPELL_AURA_SCHOOL_ABSORB
@ SPELL_AURA_BATTLEGROUND_PLAYER_POSITION_FACTIONAL
@ SPELL_AURA_MOD_WEAPON_CRIT_PERCENT
@ SPELL_AURA_SPELL_MAGNET
@ SPELL_AURA_PERIODIC_LEECH
@ SPELL_AURA_PROC_TRIGGER_DAMAGE
@ SPELL_AURA_MOD_POWER_REGEN_PERCENT
@ SPELL_AURA_DAMAGE_IMMUNITY
@ SPELL_AURA_MOD_DAMAGE_DONE
@ SPELL_AURA_REFLECT_SPELLS_SCHOOL
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_MOD_MECHANIC_RESISTANCE
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT
@ SPELL_AURA_MOD_MELEE_HASTE_3
@ SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL
@ SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
@ SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
@ SPELL_AURA_BATTLEGROUND_PLAYER_POSITION
@ SPELL_AURA_FORCE_REACTION
@ SPELL_AURA_MOD_MELEE_RANGED_HASTE
@ SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ SPELL_AURA_MOD_ATTACK_POWER_PCT
@ SPELL_AURA_INTERCEPT_MELEE_RANGED_ATTACKS
@ SPELL_AURA_MOD_BLOCK_PERCENT
@ TARGET_SELECT_CATEGORY_CONE
@ SPELL_ATTR0_CU_IGNORE_ARMOR
@ SPELL_ATTR0_CU_ENCHANT_PROC
@ SPELL_ATTR0_CU_DIRECT_DAMAGE
@ SPELL_ATTR0_CU_CAN_CRIT
@ SPELL_ATTR0_CU_AURA_CANNOT_BE_SAVED
@ SPELL_ATTR0_CU_NEEDS_AMMO_DATA
@ SPELL_ATTR0_CU_BINARY_SPELL
@ SPELL_ATTR0_CU_SHARE_DAMAGE
@ SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC
@ SPELL_ATTR0_CU_PICKPOCKET
@ SPELL_ATTR0_CU_CONE_LINE
@ SPELL_ATTR0_CU_NO_INITIAL_THREAT
@ SPELL_ATTR0_CU_IS_TALENT
std::vector< SpellXSpellVisualEntry const * > SpellVisualVector
bool IsPrimaryProfessionSkill(uint32 skill)
auto _GetSpellInfo(uint32 spellId)
bool IsPartOfSkillLine(uint32 skillId, uint32 spellId)
bool LoadPetDefaultSpells_helper(CreatureTemplate const *cInfo, PetDefaultSpellsEntry &petDefSpells)
bool IsWeaponSkill(uint32 skill)
std::vector< SpellEffectEntry const * > SpellEffectVector
void ApplySpellFix(std::initializer_list< uint32 > spellIds, void(*fix)(SpellInfo *))
PetFamilySpellsStore sPetFamilySpellsStore
void ApplySpellEffectFix(SpellInfo *spellInfo, SpellEffIndex effectIndex, void(*fix)(SpellEffectInfo *))
std::multimap< uint32, SpellLearnSpellNode > SpellLearnSpellMap
#define PROC_ATTR_ALL_ALLOWED
std::pair< SpellsRequiringSpellMap::const_iterator, SpellsRequiringSpellMap::const_iterator > SpellsRequiringSpellMapBounds
std::pair< SpellSpellGroupMap::const_iterator, SpellSpellGroupMap::const_iterator > SpellSpellGroupMapBounds
std::pair< SpellAreaMap::const_iterator, SpellAreaMap::const_iterator > SpellAreaMapBounds
@ SPELL_GROUP_CORE_RANGE_MAX
@ PROC_ATTR_REQ_EXP_OR_HONOR
@ PROC_ATTR_TRIGGERED_CAN_PROC
@ PROC_ATTR_REQ_POWER_COST
std::pair< SpellAreaForAreaMap::const_iterator, SpellAreaForAreaMap::const_iterator > SpellAreaForAreaMapBounds
@ PROC_SPELL_PHASE_FINISH
@ PROC_SPELL_PHASE_MASK_ALL
#define MAX_CREATURE_SPELL_DATA_SLOT
@ SPELL_GROUP_STACK_RULE_DEFAULT
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT
@ SPELL_GROUP_STACK_RULE_MAX
@ PROC_SPELL_TYPE_MASK_ALL
@ PROC_SPELL_TYPE_NO_DMG_HEAL
std::pair< SpellGroupSpellMap::const_iterator, SpellGroupSpellMap::const_iterator > SpellGroupSpellMapBounds
@ SPELL_AREA_FLAG_AUTOCAST
std::pair< SpellAreaForAuraMap::const_iterator, SpellAreaForAuraMap::const_iterator > SpellAreaForAuraMapBounds
std::pair< SkillLineAbilityMap::const_iterator, SkillLineAbilityMap::const_iterator > SkillLineAbilityMapBounds
@ PROC_FLAG_DEAL_MELEE_ABILITY
@ PROC_FLAG_DEAL_RANGED_ABILITY
@ TAKEN_HIT_PROC_FLAG_MASK
@ PROC_FLAG_DEAL_HELPFUL_ABILITY
@ PROC_FLAG_DEAL_RANGED_ATTACK
@ PROC_FLAG_DEAL_HARMFUL_ABILITY
@ PROC_FLAG_DEAL_HARMFUL_PERIODIC
@ REQ_SPELL_PHASE_PROC_FLAG_MASK
@ PROC_FLAG_DEAL_HELPFUL_SPELL
@ PROC_FLAG_DEAL_HELPFUL_PERIODIC
@ PROC_FLAG_DEAL_HARMFUL_SPELL
@ DONE_HIT_PROC_FLAG_MASK
@ EFFECT_RADIUS_100_YARDS
@ EFFECT_RADIUS_50000_YARDS
@ EFFECT_RADIUS_200_YARDS
@ PROC_FLAG_2_CAST_SUCCESSFUL
std::map< uint32, PetFamilySpellsSet > PetFamilySpellsStore
std::pair< SpellAreaForQuestMap::const_iterator, SpellAreaForQuestMap::const_iterator > SpellAreaForQuestMapBounds
std::pair< SpellLearnSpellMap::const_iterator, SpellLearnSpellMap::const_iterator > SpellLearnSpellMapBounds
std::multimap< uint32, uint32 > PetLevelupSpellSet
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
static void AddBattlePetSpeciesBySpell(uint32 spellId, BattlePetSpeciesEntry const *speciesEntry)
bool CanFlyIn()
Return if we can use mount in battlefield.
virtual uint32 GetData(uint32 dataId) const override
void PSendSysMessage(const char *fmt, Args &&... args)
static bool IsValidSpellFamiliyName(SpellFamilyNames family)
Class used to access individual fields of database query result.
static Player * ToPlayer(Object *o)
Gender GetNativeGender() const override
WorldSession * GetSession() const
Battleground * GetBattleground() const
QuestStatus GetQuestStatus(uint32 quest_id) const
SpellSchoolMask GetSchoolMask() const
Unit * GetActionTarget() const
ProcFlagsSpellType GetSpellTypeMask() const
Spell const * GetProcSpell() const
ProcFlagsHit GetHitMask() const
SpellInfo const * GetSpellInfo() const
ProcFlagsInit GetTypeMask() const
ProcFlagsSpellPhase GetSpellPhaseMask() const
int32 CalcValue(WorldObject const *caster=nullptr, int32 const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
struct SpellEffectInfo::ScalingInfo Scaling
SpellRadiusEntry const * TargetBRadiusEntry
SpellRadiusEntry const * TargetARadiusEntry
SpellImplicitTargetInfo TargetA
SpellImplicitTargetInfo TargetB
Targets GetTarget() const
uint32 RequiresSpellFocus
uint32 ActiveIconFileDataId
bool IsRankOf(SpellInfo const *spellInfo) const
std::array< int32, MAX_SPELL_REAGENTS > Reagent
uint32 ExcludeTargetAuraSpell
SpellInfo const * GetFirstRankSpell() const
float GetMaxRange(bool positive=false, WorldObject *caster=nullptr, Spell *spell=nullptr) const
EnumFlag< SpellAuraInterruptFlags2 > AuraInterruptFlags2
SpellVisualVector _visuals
EnumFlag< SpellAuraInterruptFlags > ChannelInterruptFlags
::Difficulty const Difficulty
SpellRangeEntry const * RangeEntry
bool IsLootCrafting() const
uint32 ExcludeCasterAuraState
uint32 CategoryRecoveryTime
EnumFlag< SpellInterruptFlags > InterruptFlags
void _InitializeSpellPositivity()
bool HasAttribute(SpellAttr0 attribute) const
SpellDurationEntry const * DurationEntry
uint32 MaxAffectedTargets
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
std::vector< SpellEffectInfo > const & GetEffects() const
int32 EquippedItemSubClassMask
SpellChainNode const * ChainEntry
AuraType ExcludeTargetAuraType
void _InitializeExplicitTargetMask()
SpellInfo const * GetNextRankSpell() const
SpellCastTimesEntry const * CastTimeEntry
int32 EquippedItemInventoryTypeMask
uint32 ExcludeTargetAuraState
std::bitset< MAX_SPELL_EFFECTS > NegativeEffects
EnumFlag< SpellAuraInterruptFlags2 > ChannelInterruptFlags2
AuraType ExcludeCasterAuraType
uint32 TargetCreatureType
EnumFlag< SpellAuraInterruptFlags > AuraInterruptFlags
uint32 ExcludeCasterAuraSpell
bool HasAura(AuraType aura) const
uint32 StartRecoveryCategory
bool HasAuraInterruptFlag(SpellAuraInterruptFlags flag) const
bool IsSingleTarget() const
SpellRequiredMap mSpellReq
static bool CanSpellTriggerProcOnEvent(SpellProcEntry const &procEntry, ProcEventInfo &eventInfo)
SpellLinkedMap mSpellLinkedMap
void LoadPetFamilySpellsStore()
SpellGroupStackRule GetSpellGroupStackRule(SpellGroup groupid) const
SkillLineAbilityMap mSkillLineAbilityMap
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const
SpellLearnSpellMapBounds GetSpellLearnSpellMapBounds(uint32 spell_id) const
PetLevelupSpellSet const * GetPetLevelupSpellList(uint32 petFamily) const
void LoadSpellInfoStore()
SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const
SpellAreaForAuraMap mSpellAreaForAuraMap
SpellChainMap mSpellChains
void UnloadSpellInfoStore()
uint32 GetNextSpellInChain(uint32 spell_id) const
static SpellMgr * instance()
SpellPetAuraMap mSpellPetAuraMap
SpellLearnSkillMap mSpellLearnSkills
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id) const
void LoadSkillLineAbilityMap()
SkillLineAbilityMapBounds GetSkillLineAbilityMapBounds(uint32 spell_id) const
void ForEachSpellInfoDifficulty(uint32 spellId, std::function< void(SpellInfo const *)> callback)
SpellAreaForQuestMap mSpellAreaForQuestEndMap
SpellGroupSpellMapBounds GetSpellGroupSpellMapBounds(SpellGroup group_id) const
PetDefaultSpellsMap mPetDefaultSpellsMap
uint32 GetSpellWithRank(uint32 spell_id, uint32 rank, bool strict=false) const
SpellLearnSkillNode const * GetSpellLearnSkill(uint32 spell_id) const
void LoadSpellInfoCustomAttributes()
SpellProcEntry const * GetSpellProcEntry(SpellInfo const *spellInfo) const
std::vector< int32 > const * GetSpellLinked(SpellLinkedType type, uint32 spell_id) const
uint32 GetPrevSpellInChain(uint32 spell_id) const
bool IsSpellRequiringSpell(uint32 spellid, uint32 req_spellid) const
bool IsSpellLearnToSpell(uint32 spell_id1, uint32 spell_id2) const
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const
static CreatureImmunities const * GetCreatureImmunities(int32 creatureImmunitiesId)
void LoadSpellInfoDiminishing()
void LoadSpellTargetPositions()
void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set< uint32 > &foundSpells) const
void LoadSpellInfoImmunities()
void LoadSpellLearnSkills()
uint32 GetLastSpellInChain(uint32 spell_id) const
SpellTotemModelMap mSpellTotemModel
void ForEachSpellInfo(std::function< void(SpellInfo const *)> callback)
void LoadSpellInfoServerside()
bool IsSpellLearnSpell(uint32 spell_id) const
SpellThreatEntry const * GetSpellThreatEntry(uint32 spellID) const
void LoadSpellGroupStackRules()
SpellGroupStackMap mSpellGroupStack
uint32 GetFirstSpellInChain(uint32 spell_id) const
SpellEnchantProcEventMap mSpellEnchantProcEventMap
void LoadPetDefaultSpells()
PetLevelupSpellMap mPetLevelupSpellMap
void LoadSpellLearnSpells()
Trinity::IteratorPair< SpellRequiredMap::const_iterator > GetSpellsRequiredForSpellBounds(uint32 spell_id) const
SpellGroupStackRule CheckSpellGroupStackRules(SpellInfo const *spellInfo1, SpellInfo const *spellInfo2) const
SpellsRequiringSpellMap mSpellsReqSpell
void LoadSpellInfoCorrections()
SpellTargetPositionMap mSpellTargetPositions
void LoadSpellTotemModel()
SpellGroupSpellMap mSpellGroupSpell
PetDefaultSpellsEntry const * GetPetDefaultSpellsEntry(int32 id) const
SpellTargetPosition const * GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const
SameEffectStackMap mSpellSameEffectStack
SpellEnchantProcEntry const * GetSpellEnchantProcEvent(uint32 enchId) const
SpellAreaForAreaMap mSpellAreaForAreaMap
SpellInfo const * GetSpellInfo(uint32 spellId, Difficulty difficulty) const
static bool IsSpellValid(SpellInfo const *spellInfo, Player *player=nullptr, bool msg=true)
Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book,...
uint8 GetSpellRank(uint32 spell_id) const
void UnloadSpellInfoImplicitTargetConditionLists()
SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const
SpellAreaMap mSpellAreaMap
void LoadSpellEnchantProcData()
SpellChainNode const * GetSpellChainNode(uint32 spell_id) const
SpellsRequiringSpellMapBounds GetSpellsRequiringSpellBounds(uint32 spell_id) const
SpellInfo const * AssertSpellInfo(uint32 spellId, Difficulty difficulty) const
bool AddSameEffectStackRuleSpellGroups(SpellInfo const *spellInfo, uint32 auraType, int32 amount, std::map< SpellGroup, int32 > &groups) const
void LoadPetLevelupSpellMap()
SpellLearnSpellMap mSpellLearnSpells
void LoadSpellInfoSpellSpecificAndAuraState()
SpellSpellGroupMap mSpellSpellGroup
PetAura const * GetPetAura(uint32 spell_id, uint8 eff) const
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const
bool IsArenaAllowedEnchancment(uint32 ench_id) const
SpellThreatMap mSpellThreatMap
SpellAreaForQuestMap mSpellAreaForQuestMap
uint32 GetModelForTotem(uint32 spellId, uint8 race) const
void UnloadSpellInfoChains()
bool IsSpellMemberOfSpellGroup(uint32 spellid, SpellGroup groupid) const
std::vector< SpellPowerCost > const & GetPowerCost() const
Utility class to enable range for loop syntax for multimap.equal_range uses.
bool HasAuraType(AuraType auraType) const
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
auto MapEqualRange(M &map, typename M::key_type const &key)
constexpr IteratorPair< iterator, end_iterator > MakeIteratorPair(iterator first, end_iterator second)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
std::array< int16, 2 > SkillLine
std::bitset< MAX_MECHANIC > Mechanic
std::vector< SpellEffectName > Effect
EnumFlag< SpellOtherImmunity > Other
std::bitset< MAX_SPELL_SCHOOL > School
std::bitset< DISPEL_MAX > DispelType
std::vector< AuraType > Aura
uint32 spells[MAX_CREATURE_SPELLS]
uint32 spellid[MAX_CREATURE_SPELL_DATA_SLOT]
Trinity::RaceMask< uint64 > raceMask
bool IsFitToRequirements(Player const *player, uint32 newZone, uint32 newArea) const
std::array< uint32, MAX_ITEM_ENCHANTMENT_EFFECTS > EffectArg
std::array< uint8, MAX_ITEM_ENCHANTMENT_EFFECTS > Effect
ProcFlagsSpellPhase SpellPhaseMask
ProcFlagsSpellType SpellTypeMask
uint32 DisableEffectsMask
ProcAttributes AttributesMask
uint16 SpellVisualMissileSetID
constexpr bool HasRace(uint8 raceId) const
constexpr bool IsEmpty() const