diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Chat.cpp | 2 | ||||
-rw-r--r-- | src/game/Chat.h | 2 | ||||
-rw-r--r-- | src/game/Level3.cpp | 10 | ||||
-rw-r--r-- | src/game/NPCHandler.cpp | 5 | ||||
-rw-r--r-- | src/game/Player.cpp | 9 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 293 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 20 | ||||
-rw-r--r-- | src/game/World.cpp | 3 |
8 files changed, 197 insertions, 147 deletions
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 4a4a6f8d2be..0a646c93e83 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -281,7 +281,7 @@ ChatCommand * ChatHandler::getCommandTable() { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL }, { "skinning_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL }, { "spell_affect", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAffectCommand, "", NULL }, - { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, + { "spell_required", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellRequiredCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 2a7b1b62bdd..7356835bfb8 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -248,7 +248,7 @@ class ChatHandler bool HandleReloadSkillExtraItemTemplateCommand(const char* args); bool HandleReloadSkillFishingBaseLevelCommand(const char* args); bool HandleReloadSpellAffectCommand(const char* args); - bool HandleReloadSpellChainCommand(const char* args); + bool HandleReloadSpellRequiredCommand(const char* args); bool HandleReloadSpellElixirCommand(const char* args); bool HandleReloadSpellLearnSpellCommand(const char* args); bool HandleReloadSpellProcEventCommand(const char* args); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 13f6b101a7b..34a3592db8e 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -145,7 +145,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*) HandleReloadSkillDiscoveryTemplateCommand("a"); HandleReloadSkillExtraItemTemplateCommand("a"); HandleReloadSpellAffectCommand("a"); - HandleReloadSpellChainCommand("a"); + HandleReloadSpellRequiredCommand("a"); HandleReloadSpellElixirCommand("a"); HandleReloadSpellLearnSpellCommand("a"); HandleReloadSpellProcEventCommand("a"); @@ -423,11 +423,11 @@ bool ChatHandler::HandleReloadSpellAffectCommand(const char*) return true; } -bool ChatHandler::HandleReloadSpellChainCommand(const char*) +bool ChatHandler::HandleReloadSpellRequiredCommand(const char*) { - sLog.outString( "Re-Loading Spell Chain Data... " ); - spellmgr.LoadSpellChains(); - SendGlobalSysMessage("DB table `spell_chain` (spell ranks) reloaded."); + sLog.outString( "Re-Loading Spell Required Data... " ); + spellmgr.LoadSpellRequired(); + SendGlobalSysMessage("DB table `spell_required` reloaded."); return true; } diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 04c31ff8f8d..6bb916d9fe0 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -174,6 +174,7 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell); SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell); + uint32 req_spell = spellmgr.GetSpellRequired(tSpell->spell); data << uint32(tSpell->spell); data << uint8(_player->GetTrainerSpellState(tSpell)); @@ -184,8 +185,8 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) data << uint8(tSpell->reqlevel); data << uint32(tSpell->reqskill); data << uint32(tSpell->reqskillvalue); - data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0); - data << uint32(chain_node && chain_node->prev ? chain_node->req : 0); + data << uint32(chain_node && chain_node->prev ? chain_node->prev : req_spell); + data << uint32(chain_node && chain_node->prev ? req_spell : 0); data << uint32(0); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e9a7a0f73ed..314e6c5ac09 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2952,8 +2952,8 @@ void Player::removeSpell(uint32 spell_id, bool disabled) removeSpell(node->next,disabled); } //unlearn spells dependent from recently removed spells - SpellRequiredMap const& reqMap = spellmgr.GetSpellRequiredMap(); - SpellRequiredMap::const_iterator itr2 = reqMap.find(spell_id); + SpellsRequiringSpellMap const& reqMap = spellmgr.GetSpellsRequiringSpell(); + SpellsRequiringSpellMap::const_iterator itr2 = reqMap.find(spell_id); for (uint32 i=reqMap.count(spell_id);i>0;i--,itr2++) removeSpell(itr2->second,disabled); @@ -3546,9 +3546,12 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell // check prev.rank requirement if(spell_chain->prev && !HasSpell(spell_chain->prev)) return TRAINER_SPELL_RED; + } + if(uint32 spell_req = spellmgr.GetSpellRequired(trainer_spell->spell)) + { // check additional spell requirement - if(spell_chain->req && !HasSpell(spell_chain->req)) + if(!HasSpell(spell_req)) return TRAINER_SPELL_RED; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index cddf7d83e72..fb14164b98e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1411,20 +1411,12 @@ SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spell return NULL; } -void SpellMgr::LoadSpellChains() +void SpellMgr::LoadSpellRequired() { - mSpellChains.clear(); // need for reload case - mSpellReq.clear(); // need for reload case - - QueryResult *result = WorldDatabase.Query("SELECT spell_id, first_spell, rank, req_spell from spell_chain ORDER BY first_spell, rank"); + mSpellsReqSpell.clear(); // need for reload case + mSpellReq.clear(); // need for reload case - struct SpellChainEntry - { - uint32 spell; - uint32 first; - uint32 req; - uint8 rank; - }; + QueryResult *result = WorldDatabase.Query("SELECT spell_id, req_spell from spell_required"); if(result == NULL) { @@ -1438,172 +1430,209 @@ void SpellMgr::LoadSpellChains() } uint32 rows = 0; - SpellChainEntry *SpellChainTable = new SpellChainEntry [result->GetRowCount()]; - barGoLink bar( result->GetRowCount() ); do { bar.step(); Field *fields = result->Fetch(); - SpellChainTable[rows].spell = fields[0].GetUInt32(); - SpellChainTable[rows].first = fields[1].GetUInt32(); - SpellChainTable[rows].rank = fields[2].GetUInt32(); - SpellChainTable[rows].req = fields[3].GetUInt32(); - - if (SpellChainTable[rows].req) - mSpellReq.insert (std::pair<uint32, uint32>(SpellChainTable[rows].req, SpellChainTable[rows].spell)); + uint32 spell_id = fields[0].GetUInt32(); + uint32 spell_req = fields[1].GetUInt32(); + mSpellsReqSpell.insert (std::pair<uint32, uint32>(spell_req, spell_id)); + mSpellReq[spell_id] = spell_req; ++rows; } while( result->NextRow() ); delete result; - uint32 cur_row=0; - do - { - uint32 spell_id=SpellChainTable[cur_row].spell; - SpellChainNode node; - node.first = SpellChainTable[cur_row].first; - node.rank = SpellChainTable[cur_row].rank; - node.req = SpellChainTable[cur_row].req; - //get field "prev" - if (spell_id == node.first || cur_row==0) - { - if (node.rank!=1) - sLog.outErrorDb("Incorrect rank for entry: %u",spell_id); - node.prev = 0; - } - else if (SpellChainTable[cur_row-1].rank!=node.rank-1) - { - sLog.outErrorDb("Spells %u and %u (first: %u, rank: %d, req: %u) listed in `spell_chain` have not compatible rank data." - ,spell_id,SpellChainTable[cur_row-1].spell,node.first,node.rank,node.req); - node.prev = 0; - } - else - node.prev=SpellChainTable[cur_row-1].spell; + sLog.outString(); + sLog.outString( ">> Loaded %u spell required records", rows ); +} - //get field "next" - if (cur_row==rows-1 || SpellChainTable[cur_row+1].first!= node.first ) - { - //get field "last" - for (uint32 last_row = 1; cur_row - last_row < rows && SpellChainTable[cur_row - last_row].first == node.first; ++last_row) - mSpellChains[SpellChainTable[cur_row-last_row].spell].last = spell_id; - node.last = spell_id; - node.next = 0; - } - else if (SpellChainTable[cur_row+1].rank!=node.rank+1) - { - sLog.outErrorDb("Spells %u and %u (first: %u, rank: %d, req: %u) listed in `spell_chain` have not compatible rank data." - ,spell_id,SpellChainTable[cur_row+1].spell,node.first,node.rank,node.req); - node.next = 0; - } - else - { - node.next=SpellChainTable[cur_row+1].spell; - node.last=0; - } +void SpellMgr::LoadSpellChains() +{ + mSpellChains.clear(); // need for reload case + struct SpellRankEntry + { + uint32 SkillId; + char const *SpellName; + uint32 DurationIndex; + uint32 RangeIndex; + uint32 SpellVisual; + uint32 ProcFlags; + uint64 SpellFamilyFlags; + uint32 TargetAuraState; + uint32 ManaCost; + + bool operator()(const SpellRankEntry & _Left,const SpellRankEntry & _Right)const + { + return (_Left.SkillId != _Right.SkillId ? _Left.SkillId < _Right.SkillId + : _Left.SpellName!=_Right.SpellName ? _Left.SpellName < _Right.SpellName + : _Left.ProcFlags!=_Right.ProcFlags ? _Left.ProcFlags < _Right.ProcFlags + : _Left.SpellFamilyFlags!=_Right.SpellFamilyFlags ? _Left.SpellFamilyFlags < _Right.SpellFamilyFlags + : (_Left.SpellVisual!=_Right.SpellVisual) && (!_Left.SpellVisual || !_Right.SpellVisual) ? _Left.SpellVisual < _Right.SpellVisual + : (_Left.ManaCost!=_Right.ManaCost) && (!_Left.ManaCost || !_Right.ManaCost) ? _Left.ManaCost < _Right.ManaCost + : (_Left.DurationIndex!=_Right.DurationIndex) && (!_Left.DurationIndex || !_Right.DurationIndex)? _Left.DurationIndex < _Right.DurationIndex + : (_Left.RangeIndex!=_Right.RangeIndex) && (!_Left.RangeIndex || !_Right.RangeIndex || _Left.RangeIndex==1 || !_Right.RangeIndex==1) ? _Left.RangeIndex < _Right.RangeIndex + : _Left.TargetAuraState < _Right.TargetAuraState + ); + } + }; + struct SpellRankValue + { + uint32 Id; + char const *Rank; + }; - cur_row++; + std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry> RankMap; - if(!sSpellStore.LookupEntry(spell_id)) - { - sLog.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id); + for (uint32 ability_id=0;ability_id<sSkillLineAbilityStore.GetNumRows();ability_id++) + { + SkillLineAbilityEntry const *AbilityInfo=sSkillLineAbilityStore.LookupEntry(ability_id); + if (!AbilityInfo) continue; - } - if(!sSpellStore.LookupEntry(node.first)) - { - sLog.outErrorDb("Spell %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.", - spell_id,node.first,node.rank,node.req); + //get only spell with lowest ability_id to prevent doubles + uint32 spell_id=AbilityInfo->spellId; + if(mSkillLineAbilityMap.lower_bound(spell_id)->second->id!=ability_id) continue; - } + SpellEntry const *SpellInfo=sSpellStore.LookupEntry(spell_id); + if (!SpellInfo) + continue; + std::string sRank = SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; + if(sRank.empty()) + continue; + + SpellRankEntry entry; + SpellRankValue value; + entry.SkillId=AbilityInfo->skillId; + entry.SpellName=SpellInfo->SpellName[sWorld.GetDefaultDbcLocale()]; + entry.DurationIndex=SpellInfo->DurationIndex; + entry.RangeIndex=SpellInfo->rangeIndex; + entry.ProcFlags=SpellInfo->procFlags; + entry.SpellFamilyFlags=SpellInfo->SpellFamilyFlags; + entry.TargetAuraState=SpellInfo->TargetAuraState; + entry.SpellVisual=SpellInfo->SpellVisual; + entry.ManaCost=SpellInfo->manaCost; + + value.Id=spell_id; + value.Rank=SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; + RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(entry,value)); + } - if(node.req!=0 && !sSpellStore.LookupEntry(node.req)) + barGoLink bar(RankMap.size()); + + uint32 count=0; + + for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr = RankMap.begin();itr!=RankMap.end();) + { + SpellRankEntry entry=itr->first; + //trac errors in extracted data + std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator> RankErrorMap; + for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++) { - sLog.outErrorDb("Spell %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.", - spell_id,node.first,node.rank,node.req); - continue; + bar.step(); + RankErrorMap.insert(std::pair<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator>(itr2->second.Rank,itr2)); } - - // talents not required data in spell chain for work, but must be checked if present for intergrity - if(TalentSpellPos const* pos = GetTalentSpellPos(spell_id)) + for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();) { - if(node.rank!=pos->rank+1) - { - sLog.outErrorDb("Talent %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.", - spell_id,node.first,node.rank,node.req); - continue; - } - - if(TalentEntry const* talentEntry = sTalentStore.LookupEntry(pos->talent_id)) + char const * err_entry=itr2->first; + uint32 rank_count=RankErrorMap.count(itr2->first); + if (rank_count>1) + for (itr2 = RankErrorMap.lower_bound(err_entry);itr2!=RankErrorMap.upper_bound(err_entry);itr2++) { - if(node.first!=talentEntry->RankID[0]) - { - sLog.outErrorDb("Talent %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.", - spell_id,node.first,node.rank,node.req); - continue; - } - - if(node.rank > 1 && node.prev != talentEntry->RankID[node.rank-1-1]) + sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u",itr2->first,itr2->second->second.Id); + if (itr2->second->second.Id!=21084) //only one exception to these rules (not needed in 3.0.3) { - sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong prev rank spell.", - spell_id,node.prev,node.first,node.rank,node.req); - continue; + sLog.outDebug("Spell %u removed from chain data.",itr2->second->second.Id); + RankMap.erase(itr2->second); + itr=RankMap.lower_bound(entry); } } + else + itr2++; } - mSpellChains[spell_id] = node; - } - while( cur_row<rows ); + //do not proceed for spells with less than 2 ranks + uint32 spell_max_rank=RankMap.count(entry); + if (spell_max_rank<2) + { + itr=RankMap.upper_bound(entry); + continue; + } - delete[] SpellChainTable; + itr=RankMap.upper_bound(entry); - // additional integrity checks - for(SpellChainMap::iterator i = mSpellChains.begin(); i != mSpellChains.end(); ++i) - { - if(i->second.prev) + //order spells by spells by spellLevel + std::list<uint32> RankedSpells; + uint32 min_spell_lvl=0; + std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator min_itr; + for (;RankMap.count(entry);) { - SpellChainMap::iterator i_prev = mSpellChains.find(i->second.prev); - if(i_prev == mSpellChains.end()) + for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found previous rank spell in table.", - i->first,i->second.prev,i->second.first,i->second.rank,i->second.req); + SpellEntry const *SpellInfo=sSpellStore.LookupEntry(itr2->second.Id); + if (SpellInfo->spellLevel<min_spell_lvl || itr2==RankMap.lower_bound(entry)) + { + min_spell_lvl=SpellInfo->spellLevel; + min_itr=itr2; + } } - else if( i_prev->second.first != i->second.first ) + RankedSpells.push_back(min_itr->second.Id); + RankMap.erase(min_itr); + } + + //use data from talent.dbc + uint16 talent_id=0; + for(std::list<uint32>::iterator itr2 = RankedSpells.begin();itr2!=RankedSpells.end();) + { + if (TalentSpellPos const* TalentPos=GetTalentSpellPos(*itr2)) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different first spell in chain compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).", - i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, - i_prev->second.prev,i_prev->second.first,i_prev->second.rank,i_prev->second.req); + talent_id=TalentPos->talent_id; + RankedSpells.erase(itr2); + itr2 = RankedSpells.begin(); } - else if( i_prev->second.rank+1 != i->second.rank ) + else + itr2++; + } + if (talent_id) + { + TalentEntry const *TalentInfo = sTalentStore.LookupEntry(talent_id); + for (uint8 rank=5;rank;rank--) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different rank compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).", - i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, - i_prev->second.prev,i_prev->second.first,i_prev->second.rank,i_prev->second.req); + if (TalentInfo->RankID[rank-1]) + RankedSpells.push_front(TalentInfo->RankID[rank-1]); } } - if(i->second.req) + count++; + + itr=RankMap.upper_bound(entry); + uint32 spell_rank=1; + for(std::list<uint32>::iterator itr2 = RankedSpells.begin();itr2!=RankedSpells.end();spell_rank++) { - SpellChainMap::iterator i_req = mSpellChains.find(i->second.req); - if(i_req == mSpellChains.end()) - { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found required rank spell in table.", - i->first,i->second.prev,i->second.first,i->second.rank,i->second.req); - } - else if( i_req->second.first == i->second.first ) + uint32 spell_id=*itr2; + mSpellChains[spell_id].rank=spell_rank; + mSpellChains[spell_id].first=RankedSpells.front(); + mSpellChains[spell_id].last=RankedSpells.back(); + + itr2++; + if (spell_rank<2) + mSpellChains[spell_id].prev=0; + + if (spell_id==RankedSpells.back()) + mSpellChains[spell_id].next=0; + else { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell from same spell chain (prev: %u, first: %u, rank: %d, req: %u).", - i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, - i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req); + mSpellChains[*itr2].prev=spell_id; + mSpellChains[spell_id].next=*itr2; } } } sLog.outString(); - sLog.outString( ">> Loaded %u spell chain records", rows ); + sLog.outString( ">> Loaded %u spell chains",count); } void SpellMgr::LoadSpellLearnSkills() diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index e3bc4c55b99..abe0c39d9d0 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -657,12 +657,15 @@ struct SpellChainNode uint32 next; uint32 first; uint32 last; - uint32 req; uint8 rank; }; typedef UNORDERED_MAP<uint32, SpellChainNode> SpellChainMap; -typedef std::multimap<uint32, uint32> SpellRequiredMap; + +// spell_id req_spell +typedef UNORDERED_MAP<uint32, uint32> SpellRequiredMap; + +typedef std::multimap<uint32, uint32> SpellsRequiringSpellMap; // Spell learning properties (accessed using SpellMgr functions) struct SpellLearnSkillNode @@ -787,6 +790,15 @@ class SpellMgr return &itr->second; } + uint32 GetSpellRequired(uint32 spell_id) const + { + SpellRequiredMap::const_iterator itr = mSpellReq.find(spell_id); + if(itr == mSpellReq.end()) + return NULL; + + return itr->second; + } + uint32 GetFirstSpellInChain(uint32 spell_id) const { if(SpellChainNode const* node = GetSpellChainNode(spell_id)) @@ -803,7 +815,7 @@ class SpellMgr return 0; } - SpellRequiredMap const& GetSpellRequiredMap() const { return mSpellReq; } + SpellsRequiringSpellMap const& GetSpellsRequiringSpell() const { return mSpellsReqSpell; } // Note: not use rank for compare to spell ranks: spell chains isn't linear order // Use IsHighRankOfSpell instead @@ -947,6 +959,7 @@ class SpellMgr // Loading data at server startup void LoadSpellChains(); + void LoadSpellRequired(); void LoadSpellLearnSkills(); void LoadSpellLearnSpells(); void LoadSpellScriptTarget(); @@ -963,6 +976,7 @@ class SpellMgr private: SpellScriptTarget mSpellScriptTarget; SpellChainMap mSpellChains; + SpellsRequiringSpellMap mSpellsReqSpell; SpellRequiredMap mSpellReq; SpellLearnSkillMap mSpellLearnSkills; SpellLearnSpellMap mSpellLearnSpells; diff --git a/src/game/World.cpp b/src/game/World.cpp index baecc8871fb..47598dafc65 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1091,6 +1091,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Spell Chain Data..." ); spellmgr.LoadSpellChains(); + sLog.outString( "Loading Spell Required Data..." ); + spellmgr.LoadSpellRequired(); + sLog.outString( "Loading Spell Elixir types..." ); spellmgr.LoadSpellElixirs(); |