37#include <G3D/g3dmath.h>
38#include <boost/multi_index/composite_key.hpp>
39#include <boost/multi_index/hashed_index.hpp>
40#include <boost/multi_index/member.hpp>
41#include <boost/multi_index_container.hpp>
45 struct SpellIdDifficultyIndex;
48 boost::multi_index::multi_index_container<
50 boost::multi_index::indexed_by<
51 boost::multi_index::hashed_unique<
52 boost::multi_index::tag<SpellIdDifficultyIndex>,
53 boost::multi_index::composite_key<
55 boost::multi_index::member<SpellInfo, uint32 const, &SpellInfo::Id>,
56 boost::multi_index::member<SpellInfo, Difficulty const, &SpellInfo::Difficulty>
59 boost::multi_index::hashed_non_unique<
60 boost::multi_index::tag<SpellIdIndex>,
61 boost::multi_index::member<SpellInfo, uint32 const, &SpellInfo::Id>
66 class ServersideSpellName
69 explicit ServersideSpellName(
uint32 id, std::string_view name) : _nameStorage(name)
75 ServersideSpellName(ServersideSpellName
const& right) : _nameStorage(right._nameStorage)
77 Name.ID = right.Name.ID;
81 ServersideSpellName(ServersideSpellName&& right)
noexcept : _nameStorage(std::move(right._nameStorage))
83 Name.ID = right.Name.ID;
93 std::fill(std::begin(
Name.Name.Str), std::end(
Name.Name.Str), _nameStorage.c_str());
96 std::string _nameStorage;
99 std::vector<ServersideSpellName> mServersideSpellNames;
101 std::unordered_map<std::pair<uint32, Difficulty>,
SpellProcEntry> mSpellProcMap;
102 std::unordered_map<int32, CreatureImmunities> mCreatureImmunities;
122 for (SkillLineAbilityMap::const_iterator itr = skillBounds.first; itr != skillBounds.second; ++itr)
123 if (itr->second->SkillLine == skillId)
149 bool needCheckReagents =
false;
154 switch (spellEffectInfo.Effect)
160 if (spellEffectInfo.ItemType == 0)
170 TC_LOG_ERROR(
"sql.sql",
"The craft spell {} does not have a create item entry.", spellInfo->
Id);
177 else if (!
sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType))
184 TC_LOG_ERROR(
"sql.sql",
"Craft spell {} has created a non-existing item in DB item (Entry: {}) and then...", spellInfo->
Id, spellEffectInfo.ItemType);
189 needCheckReagents =
true;
202 TC_LOG_ERROR(
"sql.sql",
"Spell {} learn to invalid spell {}, and then...", spellInfo->
Id, spellEffectInfo.TriggerSpell);
213 if (needCheckReagents)
224 TC_LOG_ERROR(
"sql.sql",
"Craft spell {} refers to a non-existing reagent in DB, item (Entry: {}) and then...", spellInfo->
Id, spellInfo->
Reagent[j]);
236 SpellChainMap::const_iterator itr =
mSpellChains.find(spell_id);
254 return node->last->Id;
263 return node->next->Id;
272 return node->prev->Id;
289 if (rank != node->rank)
290 return GetSpellWithRank(node->rank < rank ? node->next->Id : node->prev->Id, rank, strict);
292 else if (strict && rank > 1)
310 for (SpellsRequiringSpellMap::const_iterator itr = spellsRequiringSpell.first; itr != spellsRequiringSpell.second; ++itr)
312 if (itr->second == spellid)
340 for (SpellLearnSpellMap::const_iterator i = bounds.first; i != bounds.second; ++i)
341 if (i->second.Spell == spell_id2)
353 SpellTargetPositionMap::const_iterator itr =
mSpellTargetPositions.find(std::make_pair(spell_id, effIndex));
373 for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second; ++itr)
375 if (itr->second == groupid)
388 std::set<SpellGroup> usedGroups;
394 if (usedGroups.find(group_id) != usedGroups.end())
396 usedGroups.insert(group_id);
399 for (SpellGroupSpellMap::const_iterator itr = groupSpell.first; itr != groupSpell.second; ++itr)
408 foundSpells.insert(itr->second);
418 for (
auto itr = spellGroupBounds.first; itr != spellGroupBounds.second; ++itr)
425 if (!found->second.contains(auraType))
429 auto groupItr = groups.find(group);
430 if (groupItr == groups.end())
431 groups.emplace(group, amount);
436 if (std::abs(curr_amount) < std::abs(amount))
437 groupItr->second = amount;
457 std::set<SpellGroup> groups;
458 for (SpellSpellGroupMap::const_iterator itr = spellGroup1.first; itr != spellGroup1.second; ++itr)
464 for (SpellGroupSpellMap::const_iterator itr2 = groupSpell.first; itr2 != groupSpell.second; ++itr2)
466 if (itr2->second < 0)
477 groups.insert(itr->second);
483 for (std::set<SpellGroup>::iterator itr = groups.begin(); itr!= groups.end(); ++itr)
487 rule = found->second;
517 difficulty =
sDifficultyStore.LookupEntry(difficulty->FallbackDifficultyID);
518 }
while (difficulty);
617 SpellPetAuraMap::const_iterator itr =
mSpellPetAuraMap.find((spell_id<<8) + eff);
694 auto itr = mSpellInfoMap.find(boost::make_tuple(spellId, difficulty));
695 if (itr != mSpellInfoMap.end())
702 itr = mSpellInfoMap.find(boost::make_tuple(spellId,
Difficulty(difficultyEntry->FallbackDifficultyID)));
703 if (itr != mSpellInfoMap.end())
706 difficultyEntry =
sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
707 }
while (difficultyEntry);
720 for (
SpellInfo const& spellInfo : mSpellInfoMap)
721 callback(&spellInfo);
727 callback(&spellInfo);
796 return battlefieldWG->IsEnabled() && (player->
GetTeamId() == battlefieldWG->GetDefenderTeam()) && !battlefieldWG->IsWarTime();
805 return bf->IsWarTime();
828 std::set<uint32> hasPrev;
831 if (!skillAbility->SupercedesSpell)
837 chains[skillAbility->SupercedesSpell] = skillAbility->Spell;
838 hasPrev.insert(skillAbility->Spell);
842 for (
auto itr = chains.begin(); itr != chains.end(); ++itr)
844 if (hasPrev.count(itr->first))
867 auto nextItr = chains.find(itr->second);
868 while (nextItr != chains.end())
890 nextItr = chains.find(nextItr->second);
909 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell required records. DB table `spell_required` is empty.");
917 Field* fields = result->Fetch();
926 TC_LOG_ERROR(
"sql.sql",
"spell_id {} in `spell_required` table could not be found in dbc, skipped.", spell_id);
933 TC_LOG_ERROR(
"sql.sql",
"req_spell {} in `spell_required` table could not be found in dbc, skipped.", spell_req);
939 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);
945 TC_LOG_ERROR(
"sql.sql",
"Duplicate entry of req_spell {} and spell_id {} in `spell_required`, skipped.", spell_req, spell_id);
949 mSpellReq.insert (std::pair<uint32, uint32>(spell_id, spell_req));
950 mSpellsReqSpell.insert (std::pair<uint32, uint32>(spell_req, spell_id));
952 }
while (result->NextRow());
966 for (
SpellInfo const& entry : mSpellInfoMap)
974 switch (spellEffectInfo.Effect)
977 dbc_node.
skill =
uint16(spellEffectInfo.MiscValue);
978 dbc_node.
step =
uint16(spellEffectInfo.CalcValueAsInt());
1012 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell learn spells. DB table `spell_learn_spell` is empty.");
1019 Field* fields = result->Fetch();
1033 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_learn_spell` does not exist.", spell_id);
1039 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_learn_spell` learning non-existing spell {}.", spell_id, node.
Spell);
1045 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_learn_spell` attempts learning talent spell {}, skipped.", spell_id, node.
Spell);
1052 }
while (result->NextRow());
1059 for (
SpellInfo const& entry : mSpellInfoMap)
1070 dbc_node.
Spell = spellEffectInfo.TriggerSpell;
1086 for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
1088 if (itr->second.Spell == dbc_node.
Spell)
1090 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.",
1091 entry.Id, dbc_node.
Spell);
1114 for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
1116 if (
int32(itr->second.Spell) == spellLearnSpell->LearnSpellID)
1118 TC_LOG_ERROR(
"sql.sql",
"Found redundant record (entry: {}, SpellID: {}) in `spell_learn_spell`, spell added automatically from SpellLearnSpell.db2", spellLearnSpell->SpellID, spellLearnSpell->LearnSpellID);
1130 for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr)
1132 if (
int32(itr->second.Spell) == spellLearnSpell->LearnSpellID)
1143 dbcLearnNode.
SourceSpell = spellLearnSpell->SpellID;
1144 dbcLearnNode.
Spell = spellLearnSpell->LearnSpellID;
1146 dbcLearnNode.
Active =
true;
1149 mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spellLearnSpell->SpellID, dbcLearnNode));
1156 TC_LOG_INFO(
"server.loading",
">> Loaded {} spell learn spells, {} found in Spell.dbc in {} ms", count, dbc_count,
GetMSTimeDiffToNow(oldMSTime));
1166 QueryResult result =
WorldDatabase.Query(
"SELECT ID, EffectIndex, OrderIndex, MapID, PositionX, PositionY, PositionZ, Orientation FROM spell_target_position");
1169 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell target coordinates. DB table `spell_target_position` is empty.");
1175 Field* fields = result->Fetch();
1180 SpellTargetPosition st(fields[3].GetUInt16(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat());
1185 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, EffectIndex: {}) is using a non-existant MapID (ID: {}).", spellId,
uint32(effIndex), st.
GetMapId());
1191 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, EffectIndex: {}): target coordinates not provided.", spellId,
uint32(effIndex));
1198 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}) listed in `spell_target_position` does not exist.", spellId);
1202 if (effIndex >= spellInfo->
GetEffects().size())
1204 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));
1220 auto hasTarget = [&](
Targets target)
1229 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, effIndex: {}) listed in `spell_target_position` does not have a target TARGET_DEST_DB ({}) or TARGET_DEST_NEARBY_DB ({}) or TARGET_DEST_NEARBY_ENTRY_OR_DB ({}).",
1233 if (fields[2].GetInt32() != 0)
1235 TC_LOG_ERROR(
"sql.sql",
"Spell (Id: {}, effIndex: {}) listed in `spell_target_position` does not have a target TARGET_DEST_NEARBY_DB ({}) but lists multiple points, only one is allowed.",
1243 }
while (result->NextRow());
1277 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell group definitions. DB table `spell_group` is empty.");
1281 std::set<uint32> groups;
1285 Field* fields = result->Fetch();
1290 TC_LOG_ERROR(
"sql.sql",
"SpellGroup id {} listed in `spell_group` is in core range, but is not defined in core!", group_id);
1295 groups.insert(group_id);
1298 }
while (result->NextRow());
1302 if (itr->second < 0)
1304 if (groups.find(abs(itr->second)) == groups.end())
1306 TC_LOG_ERROR(
"sql.sql",
"SpellGroup id {} listed in `spell_group` does not exist", abs(itr->second));
1317 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_group` does not exist", itr->second);
1320 else if (spellInfo->
GetRank() > 1)
1322 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_group` is not the first rank of the spell.", itr->second);
1330 for (
auto groupItr = groups.begin(); groupItr != groups.end(); ++groupItr)
1332 std::set<uint32> spells;
1335 for (
auto spellItr = spells.begin(); spellItr != spells.end(); ++spellItr)
1352 std::vector<uint32> sameEffectGroups;
1358 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell group stack rules. DB table `spell_group_stack_rules` is empty.");
1365 Field* fields = result->Fetch();
1371 TC_LOG_ERROR(
"sql.sql",
"SpellGroupStackRule {} listed in `spell_group_stack_rules` does not exist.", stack_rule);
1376 if (bounds.first == bounds.second)
1378 TC_LOG_ERROR(
"sql.sql",
"SpellGroup id {} listed in `spell_group_stack_rules` does not exist.", group_id);
1386 sameEffectGroups.push_back(group_id);
1389 }
while (result->NextRow());
1395 TC_LOG_INFO(
"server.loading",
">> Parsing SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules...");
1397 for (
uint32 group_id : sameEffectGroups)
1399 std::set<uint32> spellIds;
1402 std::unordered_set<uint32> auraTypes;
1406 std::unordered_multiset<
uint32 > frequencyContainer;
1409 std::vector<std::vector<
uint32 >>
const SubGroups =
1414 for (
uint32 spellId : spellIds)
1419 if (!spellEffectInfo.IsAura())
1422 uint32 auraName = spellEffectInfo.ApplyAuraName;
1423 for (std::vector<uint32>
const& subGroup : SubGroups)
1425 if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end())
1428 auraName = subGroup.front();
1433 frequencyContainer.insert(auraName);
1438 size_t auraTypeCount = 0;
1439 for (
uint32 auraName : frequencyContainer)
1441 size_t currentCount = frequencyContainer.count(auraName);
1442 if (currentCount > auraTypeCount)
1444 auraType = auraName;
1445 auraTypeCount = currentCount;
1449 for (std::vector<uint32>
const& subGroup : SubGroups)
1451 if (auraType == subGroup.front())
1453 auraTypes.insert(subGroup.begin(), subGroup.end());
1458 if (auraTypes.empty())
1459 auraTypes.insert(auraType);
1463 for (
uint32 spellId : spellIds)
1470 for (
uint32 auraType : auraTypes)
1487 TC_LOG_ERROR(
"sql.sql",
"SpellId {} listed in `spell_group` with stack rule 3 does not share aura assigned for group {}", spellId, group_id);
1494 TC_LOG_INFO(
"server.loading",
">> Parsed {} SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules in {} ms", count,
GetMSTimeDiffToNow(oldMSTime));
1501 mSpellProcMap.clear();
1504 QueryResult result =
WorldDatabase.Query(
"SELECT SpellId, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, SpellFamilyMask3, "
1506 "ProcFlags, ProcFlags2, SpellTypeMask, SpellPhaseMask, HitMask, AttributesMask, DisableEffectsMask, ProcsPerMinute, Chance, Cooldown, Charges FROM spell_proc");
1513 Field* fields = result->Fetch();
1517 bool allRanks =
false;
1527 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` does not exist", spellId);
1534 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` with all ranks, but spell has no ranks.", spellId);
1538 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` is not the first rank of the spell.", spellId);
1565 if (mSpellProcMap.find({ spellInfo->Id, spellInfo->Difficulty }) != mSpellProcMap.end())
1567 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_proc` already has its first rank in the table.", spellInfo->
Id);
1580 if (procEntry.
Cooldown == Milliseconds::zero())
1585 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has wrong `SchoolMask` set: {}", spellInfo->
Id, procEntry.
SchoolMask);
1587 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has wrong `SpellFamilyName` set: {}", spellInfo->
Id, procEntry.
SpellFamilyName);
1588 if (procEntry.
Chance < 0)
1590 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has negative value in the `Chance` field", spellInfo->
Id);
1595 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has negative value in the `ProcsPerMinute` field", spellInfo->
Id);
1599 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);
1601 TC_LOG_ERROR(
"sql.sql",
"`spell_proc` table entry for spellId {} has wrong `SpellTypeMask` set: {}", spellInfo->
Id, procEntry.
SpellTypeMask);
1603 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);
1605 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);
1607 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has wrong `SpellPhaseMask` set: {}", spellInfo->
Id, procEntry.
SpellPhaseMask);
1609 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);
1613 TC_LOG_ERROR(
"sql.sql",
"The `spell_proc` table entry for spellId {} has wrong `HitMask` set: {}", spellInfo->
Id, procEntry.
HitMask);
1615 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);
1617 if ((procEntry.
DisableEffectsMask & (1u << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsAura())
1618 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));
1624 if (!spellEffectInfo.IsAura())
1637 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);
1645 mSpellProcMap[{ spellInfo->
Id, spellInfo->
Difficulty }] = procEntry;
1653 }
while (result->NextRow());
1656 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell proc conditions and data. DB table `spell_proc` is empty.");
1674 isTriggerAura[i] =
false;
1675 isAlwaysTriggeredAura[i] =
false;
1752 TC_LOG_INFO(
"server.loading",
"Generating spell proc data from SpellMap...");
1756 std::unordered_map<std::pair<uint32, Difficulty>,
SpellProcEntry> generatedSpellProcMap;
1758 for (
SpellInfo const& spellInfo : mSpellInfoMap)
1765 if (!spellInfo.ProcFlags)
1768 bool addTriggerFlag =
false;
1773 if (!spellEffectInfo.IsEffect())
1776 uint32 auraName = spellEffectInfo.ApplyAuraName;
1780 if (!isTriggerAura[auraName])
1783 nonProcMask |= 1 << spellEffectInfo.EffectIndex;
1787 procSpellTypeMask |= spellTypeMask[auraName];
1788 if (isAlwaysTriggeredAura[auraName])
1789 addTriggerFlag =
true;
1799 addTriggerFlag =
true;
1807 if (!procSpellTypeMask)
1811 if (spellEffectInfo.IsAura())
1813 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.",
1814 spellInfo.Id,
uint32(spellInfo.ProcFlags[0]),
uint32(spellInfo.ProcFlags[1]));
1824 procEntry.
ProcFlags = spellInfo.ProcFlags;
1827 if (spellEffectInfo.IsEffect() && isTriggerAura[spellEffectInfo.ApplyAuraName])
1840 bool triggersSpell =
false;
1843 if (!spellEffectInfo.IsAura())
1846 switch (spellEffectInfo.ApplyAuraName)
1863 if (spellEffectInfo.CalcValueAsInt() <= -100)
1868 triggersSpell = spellEffectInfo.TriggerSpell != 0;
1884 procEntry.
Chance = spellInfo.ProcChance;
1886 procEntry.
Charges = spellInfo.ProcCharges;
1889 && procEntry.
Chance >= 100
1890 && spellInfo.ProcBasePPM <= 0.0f
1898 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. "
1899 "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!",
1904 generatedSpellProcMap[{ spellInfo.Id, spellInfo.Difficulty }] = procEntry;
1908 mSpellProcMap.merge(generatedSpellProcMap);
1923 TC_LOG_INFO(
"server.loading",
">> Loaded 0 aggro generating spells. DB table `spell_threat` is empty.");
1930 Field* fields = result->Fetch();
1936 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_threat` does not exist.", entry);
1947 }
while (result->NextRow());
1961 TC_LOG_INFO(
"server.loading",
">> Loaded {} SkillLineAbility MultiMap Data in {} ms",
1975 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell pet auras. DB table `spell_pet_auras` is empty.");
1982 Field* fields = result->Fetch();
1991 itr->second.AddAura(pet, aura);
1997 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_pet_auras` does not exist.", spell);
2002 TC_LOG_ERROR(
"spells",
"The spell {} listed in `spell_pet_auras` does not have any effect at index {}", spell,
uint32(eff));
2010 TC_LOG_ERROR(
"spells",
"The spell {} listed in `spell_pet_auras` does not have any dummy aura or dummy effect.", spell);
2017 TC_LOG_ERROR(
"sql.sql",
"The aura {} listed in `spell_pet_auras` does not exist.", aura);
2026 }
while (result->NextRow());
2038 QueryResult result =
WorldDatabase.Query(
"SELECT EnchantID, Chance, ProcsPerMinute, HitMask, AttributesMask FROM spell_enchant_proc_data");
2041 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty.");
2048 Field* fields = result->Fetch();
2055 TC_LOG_ERROR(
"sql.sql",
"The enchancment {} listed in `spell_enchant_proc_data` does not exist.", enchantId);
2069 }
while (result->NextRow());
2084 TC_LOG_INFO(
"server.loading",
">> Loaded 0 linked spells. DB table `spell_linked_spell` is empty.");
2091 Field* fields = result->Fetch();
2100 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_linked_spell` does not exist.", abs(trigger));
2108 if (spellEffectInfo.CalcValueAsInt() == abs(effect))
2109 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));
2116 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_linked_spell` does not exist.", abs(effect));
2122 TC_LOG_ERROR(
"sql.sql",
"The spell trigger {}, effect {} listed in `spell_linked_spell` has invalid link type {}, skipped.", trigger, effect, type);
2129 TC_LOG_ERROR(
"sql.sql",
"The spell trigger {} listed in `spell_linked_spell` has invalid link type {}, changed to 0.", trigger, type);
2137 if (trigger == effect)
2139 TC_LOG_ERROR(
"sql.sql",
"The spell trigger {}, effect {} listed in `spell_linked_spell` triggers itself (infinite loop), skipped.", trigger, effect);
2147 }
while (result->NextRow());
2164 if (!creatureFamily)
2167 for (
uint8 j = 0; j < 2; ++j)
2172 std::vector<SkillLineAbilityEntry const*>
const* skillLineAbilities =
sDB2Manager.GetSkillLineAbilitiesBySkill(creatureFamily->
SkillLine[j]);
2173 if (!skillLineAbilities)
2189 if (spellSet.empty())
2192 spellSet.insert(PetLevelupSpellSet::value_type(spell->
SpellLevel, spell->
Id));
2198 TC_LOG_INFO(
"server.loading",
">> Loaded {} pet levelup and default spells for {} families in {} ms", count, family_count,
GetMSTimeDiffToNow(oldMSTime));
2204 bool have_spell =
false;
2224 for (PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)
2226 if (itr->second == petDefSpells.
spellid[j])
2255 uint32 countCreature = 0;
2257 TC_LOG_INFO(
"server.loading",
"Loading summonable creature templates...");
2261 for (
SpellInfo const& spellEntry : mSpellInfoMap)
2266 for (
SpellEffectInfo const& spellEffectInfo : spellEntry.GetEffects())
2270 uint32 creature_id = spellEffectInfo.MiscValue;
2307 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");
2310 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell area requirements. DB table `spell_area` is empty.");
2318 Field* fields = result->Fetch();
2340 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` does not exist", spell);
2347 for (SpellAreaMap::const_iterator itr = sa_bounds.first; itr != sa_bounds.second; ++itr)
2349 if (spellArea.
spellId != itr->second.spellId)
2351 if (spellArea.
areaId != itr->second.areaId)
2353 if (spellArea.
questStart != itr->second.questStart)
2355 if (spellArea.
auraSpell != itr->second.auraSpell)
2357 if ((spellArea.
raceMask & itr->second.raceMask).IsEmpty())
2359 if (spellArea.
gender != itr->second.gender)
2369 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` is already listed with similar requirements.", spell);
2376 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has a wrong area ({}) requirement.", spell, spellArea.
areaId);
2382 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has a wrong start quest ({}) requirement.", spell, spellArea.
questStart);
2390 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has a wrong ending quest ({}) requirement.", spell, spellArea.
questEnd);
2400 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has wrong aura spell ({}) requirement", spell, abs(spellArea.
auraSpell));
2406 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has aura spell ({}) requirement for itself", spell, abs(spellArea.
auraSpell));
2415 for (SpellAreaForAuraMap::const_iterator itr = saBound.first; itr != saBound.second; ++itr)
2426 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);
2431 for (SpellAreaMap::const_iterator itr2 = saBound2.first; itr2 != saBound2.second; ++itr2)
2442 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);
2450 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has wrong race mask ({}) requirement.", spell, spellArea.
raceMask.
RawValue);
2456 TC_LOG_ERROR(
"sql.sql",
"The spell {} listed in `spell_area` has wrong gender ({}) requirement.", spell, spellArea.
gender);
2489 }
while (result->NextRow());
2504 std::unordered_map<int32, BattlePetSpeciesEntry const*> battlePetSpeciesByCreature;
2506 if (battlePetSpecies->CreatureID)
2507 battlePetSpeciesByCreature[battlePetSpecies->CreatureID] = battlePetSpecies;
2511 ASSERT(effect->EffectIndex <
MAX_SPELL_EFFECTS,
"MAX_SPELL_EFFECTS must be at least %d", effect->EffectIndex + 1);
2513 ASSERT(effect->EffectAura <
int32(
TOTAL_AURAS),
"TOTAL_AURAS must be at least %d", effect->EffectAura + 1);
2514 ASSERT(effect->ImplicitTarget[0] <
TOTAL_SPELL_TARGETS,
"TOTAL_SPELL_TARGETS must be at least %u", effect->ImplicitTarget[0] + 1);
2515 ASSERT(effect->ImplicitTarget[1] <
TOTAL_SPELL_TARGETS,
"TOTAL_SPELL_TARGETS must be at least %u", effect->ImplicitTarget[1] + 1);
2517 loadData[{ effect->SpellID,
Difficulty(effect->DifficultyID) }].Effects[effect->EffectIndex] = effect;
2528 switch (effect->EffectAura)
2536 TC_LOG_ERROR(
"server.loading",
"Invalid spell modifier type {} found on spell {} effect index {}, consider increasing MAX_SPELLMOD",
2537 effect->EffectMiscValue[0], effect->SpellID, effect->EffectIndex);
2546 loadData[{ auraOptions->SpellID,
Difficulty(auraOptions->DifficultyID) }].AuraOptions = auraOptions;
2549 loadData[{ auraRestrictions->SpellID,
Difficulty(auraRestrictions->DifficultyID) }].AuraRestrictions = auraRestrictions;
2552 loadData[{ castingRequirements->SpellID,
DIFFICULTY_NONE }].CastingRequirements = castingRequirements;
2555 loadData[{ categories->SpellID,
Difficulty(categories->DifficultyID) }].Categories = categories;
2558 loadData[{ classOptions->SpellID,
DIFFICULTY_NONE }].ClassOptions = classOptions;
2561 loadData[{ cooldowns->SpellID,
Difficulty(cooldowns->DifficultyID) }].Cooldowns = cooldowns;
2567 std::vector<SpellEmpowerStageEntry const*>& empowerStages = loadData[{empower->SpellID,
DIFFICULTY_NONE}].EmpowerStages;
2571 empowerStages.insert(where, empowerStage);
2576 loadData[{ equippedItems->SpellID,
DIFFICULTY_NONE }].EquippedItems = equippedItems;
2579 loadData[{ interrupts->SpellID,
Difficulty(interrupts->DifficultyID) }].Interrupts = interrupts;
2582 loadData[{ label->SpellID,
DIFFICULTY_NONE }].Labels.push_back(label);
2585 loadData[{ levels->SpellID,
Difficulty(levels->DifficultyID) }].Levels = levels;
2588 loadData[{ misc->SpellID,
Difficulty(misc->DifficultyID) }].Misc = misc;
2593 uint8 index = power->OrderIndex;
2596 difficulty =
Difficulty(powerDifficulty->DifficultyID);
2597 index = powerDifficulty->OrderIndex;
2600 loadData[{ power->SpellID, difficulty }].Powers[index] = power;
2607 loadData[{ reagentsCurrency->SpellID,
DIFFICULTY_NONE }].ReagentsCurrency.push_back(reagentsCurrency);
2613 loadData[{ shapeshift->SpellID,
DIFFICULTY_NONE }].Shapeshift = shapeshift;
2616 loadData[{ targetRestrictions->SpellID,
Difficulty(targetRestrictions->DifficultyID) }].TargetRestrictions = targetRestrictions;
2625 auto where = std::ranges::lower_bound(visuals, std::make_pair(visual->Priority, visual->CasterPlayerConditionID), std::ranges::greater(),
2626 [](
SpellXSpellVisualEntry const* other) { return std::make_pair(other->Priority, other->CasterPlayerConditionID); });
2629 visuals.insert(where, visual);
2632 for (
auto& [key, data] : loadData)
2635 if (!spellNameEntry)
2645 if (!data.AuraOptions)
2646 data.AuraOptions = fallbackData->AuraOptions;
2648 if (!data.AuraRestrictions)
2649 data.AuraRestrictions = fallbackData->AuraRestrictions;
2651 if (!data.CastingRequirements)
2652 data.CastingRequirements = fallbackData->CastingRequirements;
2654 if (!data.Categories)
2655 data.Categories = fallbackData->Categories;
2657 if (!data.ClassOptions)
2658 data.ClassOptions = fallbackData->ClassOptions;
2660 if (!data.Cooldowns)
2661 data.Cooldowns = fallbackData->Cooldowns;
2663 for (std::size_t i = 0; i < data.Effects.size(); ++i)
2664 if (!data.Effects[i])
2665 data.Effects[i] = fallbackData->Effects[i];
2667 if (data.EmpowerStages.empty())
2668 data.EmpowerStages = fallbackData->EmpowerStages;
2670 if (!data.EquippedItems)
2671 data.EquippedItems = fallbackData->EquippedItems;
2673 if (!data.Interrupts)
2674 data.Interrupts = fallbackData->Interrupts;
2676 if (data.Labels.empty())
2677 data.Labels = fallbackData->Labels;
2680 data.Levels = fallbackData->Levels;
2683 data.Misc = fallbackData->Misc;
2685 for (std::size_t i = 0; i < fallbackData->Powers.size(); ++i)
2686 if (!data.Powers[i])
2687 data.Powers[i] = fallbackData->Powers[i];
2690 data.Reagents = fallbackData->Reagents;
2692 if (data.ReagentsCurrency.empty())
2693 data.ReagentsCurrency = fallbackData->ReagentsCurrency;
2696 data.Scaling = fallbackData->Scaling;
2698 if (!data.Shapeshift)
2699 data.Shapeshift = fallbackData->Shapeshift;
2701 if (!data.TargetRestrictions)
2702 data.TargetRestrictions = fallbackData->TargetRestrictions;
2705 data.Totems = fallbackData->Totems;
2709 if (data.Visuals.empty())
2710 data.Visuals = fallbackData->Visuals;
2713 difficultyEntry =
sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID);
2714 }
while (difficultyEntry);
2717 mSpellInfoMap.emplace(spellNameEntry, key.second, data);
2725 mSpellInfoMap.clear();
2726 mServersideSpellNames.clear();
2731 for (
SpellInfo const& spellInfo : mSpellInfoMap)
2739 std::unordered_map<std::pair<uint32, Difficulty>, std::vector<SpellEffectEntry>> spellEffects;
2742 QueryResult effectsResult =
WorldDatabase.Query(
"SELECT SpellID, EffectIndex, DifficultyID, Effect, EffectAura, EffectAmplitude, EffectAttributes, "
2744 "EffectAuraPeriod, EffectBonusCoefficient, EffectChainAmplitude, EffectChainTargets, EffectItemType, EffectMechanic, EffectPointsPerResource, "
2746 "EffectPosFacing, EffectRealPointsPerLevel, EffectTriggerSpell, BonusCoefficientFromAP, PvpMultiplier, Coefficient, Variance, "
2748 "ResourceCoefficient, GroupSizeBasePointsCoefficient, EffectBasePoints, EffectMiscValue1, EffectMiscValue2, EffectRadiusIndex1, "
2750 "EffectRadiusIndex2, EffectSpellClassMask1, EffectSpellClassMask2, EffectSpellClassMask3, EffectSpellClassMask4, ImplicitTarget1, "
2752 "ImplicitTarget2 FROM serverside_spell_effect");
2757 Field* fields = effectsResult->Fetch();
2762 effect.Effect = fields[3].
GetInt32();
2763 effect.EffectAura = fields[4].
GetInt16();
2764 effect.EffectAmplitude = fields[5].
GetFloat();
2765 effect.EffectAttributes = fields[6].
GetInt32();
2766 effect.EffectAuraPeriod = fields[7].
GetInt32();
2767 effect.EffectBonusCoefficient = fields[8].
GetFloat();
2768 effect.EffectChainAmplitude = fields[9].
GetFloat();
2769 effect.EffectChainTargets = fields[10].
GetInt32();
2770 effect.EffectItemType = fields[11].
GetInt32();
2771 effect.EffectMechanic =
Mechanics(fields[12].GetInt32());
2772 effect.EffectPointsPerResource = fields[13].
GetFloat();
2773 effect.EffectPosFacing = fields[14].
GetFloat();
2774 effect.EffectRealPointsPerLevel = fields[15].
GetFloat();
2775 effect.EffectTriggerSpell = fields[16].
GetInt32();
2776 effect.BonusCoefficientFromAP = fields[17].
GetFloat();
2777 effect.PvpMultiplier = fields[18].
GetFloat();
2778 effect.Coefficient = fields[19].
GetFloat();
2779 effect.Variance = fields[20].
GetFloat();
2780 effect.ResourceCoefficient = fields[21].
GetFloat();
2781 effect.GroupSizeBasePointsCoefficient = fields[22].
GetFloat();
2782 effect.EffectBasePoints = fields[23].
GetFloat();
2783 effect.EffectMiscValue[0] = fields[24].
GetInt32();
2784 effect.EffectMiscValue[1] = fields[25].
GetInt32();
2785 effect.EffectRadiusIndex[0] = fields[26].
GetUInt32();
2786 effect.EffectRadiusIndex[1] = fields[27].
GetUInt32();
2787 effect.EffectSpellClassMask =
flag128(fields[28].GetInt32(), fields[29].GetInt32(), fields[30].GetInt32(), fields[31].GetInt32());
2788 effect.ImplicitTarget[0] = fields[32].
GetInt16();
2789 effect.ImplicitTarget[1] = fields[33].
GetInt16();
2792 if (existingSpellBounds.begin() != existingSpellBounds.end())
2794 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} effect index {} references a regular spell loaded from file. Adding serverside effects to existing spells is not allowed.",
2795 spellId,
uint32(difficulty), effect.EffectIndex);
2801 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} effect index {} references non-existing difficulty {}, skipped",
2802 spellId, effect.EffectIndex,
uint32(difficulty));
2808 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has more than {} effects, effect at index {} skipped",
2815 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid effect type {} at index {}, skipped",
2816 spellId,
uint32(difficulty), effect.Effect, effect.EffectIndex);
2822 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid aura type {} at index {}, skipped",
2823 spellId,
uint32(difficulty), effect.EffectAura, effect.EffectIndex);
2829 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid targetA type {} at index {}, skipped",
2830 spellId,
uint32(difficulty), effect.ImplicitTarget[0], effect.EffectIndex);
2836 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid targetB type {} at index {}, skipped",
2837 spellId,
uint32(difficulty), effect.ImplicitTarget[1], effect.EffectIndex);
2841 if (effect.EffectRadiusIndex[0] && !
sSpellRadiusStore.HasRecord(effect.EffectRadiusIndex[0]))
2843 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid radius id {} at index {}, set to 0",
2844 spellId,
uint32(difficulty), effect.EffectRadiusIndex[0], effect.EffectIndex);
2847 if (effect.EffectRadiusIndex[1] && !
sSpellRadiusStore.HasRecord(effect.EffectRadiusIndex[1]))
2849 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} has invalid max radius id {} at index {}, set to 0",
2850 spellId,
uint32(difficulty), effect.EffectRadiusIndex[1], effect.EffectIndex);
2853 spellEffects[{ spellId, difficulty }].push_back(std::move(effect));
2855 }
while (effectsResult->NextRow());
2859 QueryResult spellsResult =
WorldDatabase.Query(
"SELECT Id, DifficultyID, CategoryId, Dispel, Mechanic, Attributes, AttributesEx, AttributesEx2, AttributesEx3, "
2861 "AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, AttributesEx8, AttributesEx9, AttributesEx10, AttributesEx11, AttributesEx12, AttributesEx13, "
2863 "AttributesEx14, AttributesEx15, AttributesEx16, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, "
2865 "CasterAuraState, TargetAuraState, ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, "
2867 "CasterAuraType, TargetAuraType, ExcludeCasterAuraType, ExcludeTargetAuraType, CastingTimeIndex, "
2869 "RecoveryTime, CategoryRecoveryTime, StartRecoveryCategory, StartRecoveryTime, InterruptFlags, AuraInterruptFlags1, AuraInterruptFlags2, "
2871 "ChannelInterruptFlags1, ChannelInterruptFlags2, ProcFlags, ProcFlags2, ProcChance, ProcCharges, ProcCooldown, ProcBasePPM, MaxLevel, BaseLevel, SpellLevel, "
2873 "DurationIndex, RangeIndex, Speed, LaunchDelay, StackAmount, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, ContentTuningId, "
2875 "SpellName, ConeAngle, ConeWidth, MaxTargetLevel, MaxAffectedTargets, SpellFamilyName, SpellFamilyFlags1, SpellFamilyFlags2, SpellFamilyFlags3, SpellFamilyFlags4, "
2877 "DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell");
2880 mServersideSpellNames.reserve(spellsResult->GetRowCount());
2884 Field* fields = spellsResult->Fetch();
2889 TC_LOG_ERROR(
"sql.sql",
"Serverside spell {} difficulty {} is already loaded from file. Overriding existing spells is not allowed.",
2890 spellId,
uint32(difficulty));
2894 mServersideSpellNames.emplace_back(spellId, fields[68].GetStringView());
2896 SpellInfo& spellInfo =
const_cast<SpellInfo&
>(*mSpellInfoMap.emplace(&mServersideSpellNames.back().Name, difficulty, spellEffects[{ spellId, difficulty }]).first);
2968 spellInfo.
SpellFamilyFlags =
flag128(fields[74].GetUInt32(), fields[75].GetUInt32(), fields[76].GetUInt32(), fields[77].GetUInt32());
2975 }
while (spellsResult->NextRow());
2984 uint32 oldMSTime2 = oldMSTime;
2989 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell custom attributes from DB. DB table `spell_custom_attr` is empty.");
2995 Field* fields = result->Fetch();
3001 if (spells.begin() == spells.end())
3003 TC_LOG_ERROR(
"sql.sql",
"Table `spell_custom_attr` has wrong spell (entry: {}), ignored.", spellId);
3007 for (
SpellInfo const& spellInfo : spells)
3013 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);
3018 const_cast<SpellInfo&
>(spellInfo).AttributesCu |= attributes;
3021 }
while (result->NextRow());
3026 std::set<uint32> talentSpells;
3029 talentSpells.insert(talentInfo->SpellID);
3031 for (
SpellInfo const& spellInfo : mSpellInfoMap)
3040 switch (spellEffectInfo.ApplyAuraName)
3054 switch (spellEffectInfo.ApplyAuraName)
3073 switch (spellEffectInfo.Effect)
3092 switch (spellEffectInfo.Effect)
3130 uint32 enchantId = spellEffectInfo.MiscValue;
3162 bool setFlag =
false;
3165 if (spellEffectInfo.IsEffect())
3167 switch (spellEffectInfo.Effect)
3203 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)
3211 if (spellInfoMutable->
Id == 55095)
3235 spellInfoMutable->
SchoolMask &= ~SPELL_SCHOOL_MASK_NORMAL;
3241 if (talentSpells.count(spellInfoMutable->
Id))
3244 if (G3D::fuzzyNe(spellInfoMutable->
Width, 0.0f))
3261 if (spellInfoMutable->
Id == 5729)
3270 if (spellInfoMutable->
Speed > 0.0f)
3279 if (!spellVisualMissiles)
3285 if (!spellVisualEffectName)
3298 if (visualNeedsAmmo(spellXspellVisual))
3312 for (
SpellInfo const& spellInfo : mSpellInfoMap)
3317 bool allNonBinary =
true;
3318 bool overrideAttr =
false;
3321 if (spellEffectInfo.IsAura() && spellEffectInfo.TriggerSpell)
3323 switch (spellEffectInfo.ApplyAuraName)
3330 overrideAttr =
true;
3332 allNonBinary =
false;
3341 if (overrideAttr && allNonBinary)
3342 spellInfoMutable->
AttributesCu &= ~SPELL_ATTR0_CU_BINARY_SPELL;
3355 if (liquid->SpellID)
3365 for (
uint32 spellId : spellIds)
3368 if (range.begin() == range.end())
3370 TC_LOG_ERROR(
"server.loading",
"Spell info correction specified for non-existing spell {}", spellId);
3374 for (
SpellInfo const& spellInfo : range)
3375 fix(&
const_cast<SpellInfo&
>(spellInfo));
3381 if (spellInfo->
GetEffects().size() <= effectIndex)
3383 TC_LOG_ERROR(
"server.loading",
"Spell effect info correction specified for non-existing effect {} of spell {}",
uint32(effectIndex), spellInfo->
Id);
3947 spellInfo->
Speed = 0.f;
4154 spellInfo->
Speed = 0;
4369 spellInfo->
Speed = 0.0f;
5023 spellInfo->
AttributesEx8 &= ~SPELL_ATTR8_ONLY_TARGET_IF_SAME_CREATOR;
5098 spellInfo->
AttributesEx4 &= ~SPELL_ATTR4_USE_FACING_FROM_SPELL;
5235 for (
SpellInfo const& s : mSpellInfoMap)
5250 float maxRangeTrigger = spellInfoTrigger.GetMaxRange();
5253 if (maxRangeTrigger < maxRangeMain)
5258 switch (spellEffectInfo.Effect)
5273 if (G3D::fuzzyEq(spellInfo->
ConeAngle, 0.f))
5277 if (spellEffectInfo.IsAreaAuraEffect() && spellEffectInfo.IsTargetingArea())
5286 spellInfo->
ProcFlags = std::array<int32, 2>{};
5320 for (
SpellInfo const& spellInfo : mSpellInfoMap)
5323 const_cast<SpellInfo&
>(spellInfo)._LoadSpellSpecific();
5324 const_cast<SpellInfo&
>(spellInfo)._LoadAuraState();
5334 for (
SpellInfo const& spellInfo : mSpellInfoMap)
5344 mCreatureImmunities.clear();
5347 if (
QueryResult result =
WorldDatabase.Query(
"SELECT ID, SchoolMask, DispelTypeMask, MechanicsMask, Effects, Auras, ImmuneAoE, ImmuneChain FROM creature_immunities"))
5351 Field* fields = result->Fetch();
5358 immunities.
School = school;
5361 if (fields[6].GetBool())
5363 if (fields[7].GetBool())
5366 if (immunities.
School.to_ullong() != school)
5367 TC_LOG_ERROR(
"sql.sql",
"Invalid value in `SchoolMask` {} for creature immunities {}, truncated", school,
id);
5368 if (immunities.
DispelType.to_ullong() != dispelType)
5369 TC_LOG_ERROR(
"sql.sql",
"Invalid value in `DispelTypeMask` {} for creature immunities {}, truncated", dispelType,
id);
5370 if (immunities.
Mechanic.to_ullong() != mechanics)
5371 TC_LOG_ERROR(
"sql.sql",
"Invalid value in `MechanicsMask` {} for creature immunities {}, truncated", mechanics,
id);
5373 for (std::string_view token :
Trinity::Tokenize(fields[4].GetStringView(),
',',
false))
5378 TC_LOG_ERROR(
"sql.sql",
"Invalid effect type in `Effects` {} for creature immunities {}, skipped", token,
id);
5381 for (std::string_view token :
Trinity::Tokenize(fields[5].GetStringView(),
',',
false))
5386 TC_LOG_ERROR(
"sql.sql",
"Invalid aura type in `Auras` {} for creature immunities {}, skipped", token,
id);
5389 while (result->NextRow());
5392 for (
SpellInfo const& spellInfo : mSpellInfoMap)
5550 std::unordered_map<uint32, SpellLevelsEntry const*> levelsBySpell;
5552 if (!levels->DifficultyID)
5553 levelsBySpell[levels->SpellID] = levels;
5561 auto levels = levelsBySpell.find(skillLine->Spell);
5562 if (levels != levelsBySpell.end() && levels->second->SpellLevel)
5569 if (skillLine->SkillLine != cFamily->SkillLine[0] && skillLine->SkillLine != cFamily->SkillLine[1])
5589 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell totem model records. DB table `spell_totem_model` is empty.");
5596 Field* fields = result->Fetch();
5605 TC_LOG_ERROR(
"sql.sql",
"SpellID: {} in `spell_totem_model` table could not be found in dbc, skipped.", spellId);
5612 TC_LOG_ERROR(
"sql.sql",
"Race {} defined in `spell_totem_model` does not exists, skipped.",
uint32(race));
5619 TC_LOG_ERROR(
"sql.sql",
"SpellID: {} defined in `spell_totem_model` has non-existing model ({}).", spellId, displayId);
5626 }
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< SpellEmpowerEntry > sSpellEmpowerStore("SpellEmpower.db2", &SpellEmpowerLoadInfo::Instance)
DB2Storage< SpellEffectEntry > sSpellEffectStore("SpellEffect.db2", &SpellEffectLoadInfo::Instance)
DB2Storage< SpellRadiusEntry > sSpellRadiusStore("SpellRadius.db2", &SpellRadiusLoadInfo::Instance)
DB2Storage< SpellEmpowerStageEntry > sSpellEmpowerStageStore("SpellEmpowerStage.db2", &SpellEmpowerStageLoadInfo::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
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__, message__,...)
#define TC_LOG_INFO(filterType__, message__,...)
std::optional< T > Optional
Optional helper class to wrap optional values within.
constexpr Trinity::RaceMask< uint64 > RACEMASK_ALL_PLAYABLE
@ SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC
@ SPELL_ATTR9_FORCE_DEST_LOCATION
@ 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_CREATE_CONVERSATION
@ 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
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
@ 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
bool IsPartOfSkillLine(uint32 skillId, uint32 spellId)
#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
TC_GAME_API PetFamilySpellsStore sPetFamilySpellsStore
@ 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
@ EFFECT_RADIUS_0_5_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(char const *fmt, Args &&... args)
static bool IsValidSpellFamiliyName(SpellFamilyNames family)
Class used to access individual fields of database query result.
float GetFloat() const noexcept
uint64 GetUInt64() const noexcept
int16 GetInt16() const noexcept
bool GetBool() const noexcept
uint32 GetUInt32() const noexcept
uint16 GetUInt16() const noexcept
uint8 GetUInt8() const noexcept
int32 GetInt32() const noexcept
int8 GetInt8() const noexcept
int64 GetInt64() const noexcept
Gender GetNativeGender() const override
WorldSession * GetSession() 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
SpellEffectValue CalcValue(WorldObject const *caster=nullptr, SpellEffectValue 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
void _LoadSpellDiminishInfo()
uint32 ActiveIconFileDataId
bool IsRankOf(SpellInfo const *spellInfo) const
std::array< int32, MAX_SPELL_REAGENTS > Reagent
uint32 ExcludeTargetAuraSpell
float GetMaxRange(bool positive=false, WorldObject const *caster=nullptr, Spell *spell=nullptr) const
SpellInfo const * GetFirstRankSpell() const
EnumFlag< SpellAuraInterruptFlags2 > AuraInterruptFlags2
SpellVisualVector _visuals
EnumFlag< SpellAuraInterruptFlags > ChannelInterruptFlags
::Difficulty const Difficulty
SpellRangeEntry const * RangeEntry
bool IsLootCrafting() const
uint32 ExcludeCasterAuraState
void _UnloadImplicitTargetConditionLists()
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
void _LoadSqrtTargetLimit(int32 maxTargets, int32 numNonDiminishedTargets, Optional< uint32 > maxTargetsValueHolderSpell, Optional< SpellEffIndex > maxTargetsValueHolderEffect, Optional< uint32 > numNonDiminishedTargetsValueHolderSpell, Optional< SpellEffIndex > numNonDiminishedTargetsValueHolderEffect)
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()
SpellLearnedBySpellMap mSpellLearnedBySpells
bool IsSpellLearnSpell(uint32 spell_id) const
SpellThreatEntry const * GetSpellThreatEntry(uint32 spellID) const
void LoadSpellGroupStackRules()
Trinity::IteratorPair< SpellTargetPositionMap::const_iterator > GetSpellTargetPositions(uint32 spell_id, SpellEffIndex effIndex) const
SpellGroupStackMap mSpellGroupStack
uint32 GetFirstSpellInChain(uint32 spell_id) const
bool AddSameEffectStackRuleSpellGroups(SpellInfo const *spellInfo, AuraType auraType, SpellEffectValue amount, std::map< SpellGroup, SpellEffectValue > &groups) 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
void LoadPetLevelupSpellMap()
SpellLearnSpellMap mSpellLearnSpells
void LoadSpellInfoSpellSpecificAndAuraState()
SpellSpellGroupMap mSpellSpellGroup
PetAura const * GetPetAura(uint32 spell_id, uint8 eff) const
void LoadSpellInfoTargetCaps()
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const
bool IsArenaAllowedEnchancment(uint32 ench_id) const
SpellThreatMap mSpellThreatMap
SpellAreaForQuestMap mSpellAreaForQuestMap
uint32 GetModelForTotem(uint32 spellId, uint8 race) const
Trinity::IteratorPair< SpellLearnedBySpellMap::const_iterator > GetSpellLearnedBySpellMapBounds(uint32 learnedSpellId) 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
constexpr uint32 GetMapId() const
constexpr void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0, uint32 p4=0)
STAMP_AS_EXPECTED_SIGNATURE & noexcept
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]
constexpr void SetOrientation(float orientation)
constexpr float GetPositionX() const
constexpr float GetPositionY() const
constexpr float GetPositionZ() const
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 IsEmpty() const
constexpr bool HasRace(uint32 raceId) const