aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellMgr.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-06-15 16:20:43 +0200
committerShauren <shauren.trinity@gmail.com>2016-06-15 16:20:43 +0200
commit5da217877be7f22db3bfc8ee06ca1ffad172d281 (patch)
treefc6b5a98a6b1d76bd1e061afec0fabc007922b0c /src/server/game/Spells/SpellMgr.cpp
parent8839369fc534d46816efd22ef0db3f8b9e5c8d44 (diff)
Core/Spells: Automatically generate spell rank info from SkillLineAbility
* This fixes weird spellbook/talent/glyph/profession ui behavior when knowing multiple spells to remove talent or glyph, or multiple spells to open profession ui
Diffstat (limited to 'src/server/game/Spells/SpellMgr.cpp')
-rw-r--r--src/server/game/Spells/SpellMgr.cpp145
1 files changed, 54 insertions, 91 deletions
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index beeb1109dce..e99c4bd661f 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -1261,113 +1261,76 @@ void SpellMgr::LoadSpellRanks()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT first_spell_id, spell_id, rank from spell_ranks ORDER BY first_spell_id, rank");
-
- if (!result)
+ std::map<uint32 /*spell*/, uint32 /*next*/> chains;
+ std::set<uint32> hasPrev;
+ for (SkillLineAbilityEntry const* skillAbility : sSkillLineAbilityStore)
{
- TC_LOG_INFO("server.loading", ">> Loaded 0 spell rank records. DB table `spell_ranks` is empty.");
- return;
- }
+ if (!skillAbility->SupercedesSpell)
+ continue;
- uint32 count = 0;
- bool finished = false;
+ if (!GetSpellInfo(skillAbility->SupercedesSpell) || !GetSpellInfo(skillAbility->SpellID))
+ continue;
- do
- {
- // spellid, rank
- std::list < std::pair < int32, int32 > > rankChain;
- int32 currentSpell = -1;
- int32 lastSpell = -1;
+ chains[skillAbility->SupercedesSpell] = skillAbility->SpellID;
+ hasPrev.insert(skillAbility->SpellID);
+ }
- // fill one chain
- while (currentSpell == lastSpell && !finished)
- {
- Field* fields = result->Fetch();
+ // each key in chains that isn't present in hasPrev is a first rank
+ for (auto itr = chains.begin(); itr != chains.end(); ++itr)
+ {
+ if (hasPrev.count(itr->first))
+ continue;
- currentSpell = fields[0].GetUInt32();
- if (lastSpell == -1)
- lastSpell = currentSpell;
- uint32 spell_id = fields[1].GetUInt32();
- uint32 rank = fields[2].GetUInt8();
+ SpellInfo const* first = GetSpellInfo(itr->first);
+ SpellInfo const* next = GetSpellInfo(itr->second);
- // don't drop the row if we're moving to the next rank
- if (currentSpell == lastSpell)
- {
- rankChain.push_back(std::make_pair(spell_id, rank));
- if (!result->NextRow())
- finished = true;
- }
- else
- break;
- }
- // check if chain is made with valid first spell
- SpellInfo const* first = GetSpellInfo(lastSpell);
- if (!first)
- {
- TC_LOG_ERROR("sql.sql", "The spell rank identifier(first_spell_id) %u listed in `spell_ranks` does not exist!", lastSpell);
+ if (!first || next)
continue;
- }
- // check if chain is long enough
- if (rankChain.size() < 2)
- {
- TC_LOG_ERROR("sql.sql", "There is only 1 spell rank for identifier(first_spell_id) %u in `spell_ranks`, entry is not needed!", lastSpell);
- continue;
- }
- int32 curRank = 0;
- bool valid = true;
- // check spells in chain
- for (std::list<std::pair<int32, int32> >::iterator itr = rankChain.begin(); itr!= rankChain.end(); ++itr)
+
+ mSpellChains[itr->first].first = first;
+ mSpellChains[itr->first].prev = nullptr;
+ mSpellChains[itr->first].next = next;
+ mSpellChains[itr->first].last = next;
+ mSpellChains[itr->first].rank = 1;
+ mSpellInfoMap[itr->first]->ChainEntry = &mSpellChains[itr->first];
+
+ mSpellChains[itr->second].first = first;
+ mSpellChains[itr->second].prev = first;
+ mSpellChains[itr->second].next = nullptr;
+ mSpellChains[itr->second].last = next;
+ mSpellChains[itr->second].rank = 2;
+ mSpellInfoMap[itr->second]->ChainEntry = &mSpellChains[itr->second];
+
+ uint8 rank = 3;
+ auto nextItr = chains.find(itr->second);
+ while (nextItr != chains.end())
{
- SpellInfo const* spell = GetSpellInfo(itr->first);
- if (!spell)
- {
- TC_LOG_ERROR("sql.sql", "The spell %u (rank %u) listed in `spell_ranks` for chain %u does not exist!", itr->first, itr->second, lastSpell);
- valid = false;
- break;
- }
- ++curRank;
- if (itr->second != curRank)
- {
- TC_LOG_ERROR("sql.sql", "The spell %u (rank %u) listed in `spell_ranks` for chain %u does not have a proper rank value (should be %u)!", itr->first, itr->second, lastSpell, curRank);
- valid = false;
+ SpellInfo const* prev = GetSpellInfo(nextItr->first); // already checked in previous iteration (or above, in case this is the first one)
+ SpellInfo const* last = GetSpellInfo(nextItr->second);
+ if (!last)
break;
- }
- }
- if (!valid)
- continue;
- int32 prevRank = 0;
- // insert the chain
- std::list<std::pair<int32, int32> >::iterator itr = rankChain.begin();
- do
- {
- ++count;
- int32 addedSpell = itr->first;
- if (mSpellInfoMap[addedSpell]->ChainEntry)
- TC_LOG_ERROR("sql.sql", "The spell %u (rank: %u, first: %u) listed in `spell_ranks` already has ChainEntry from dbc.", addedSpell, itr->second, lastSpell);
+ mSpellChains[nextItr->first].next = last;
- mSpellChains[addedSpell].first = GetSpellInfo(lastSpell);
- mSpellChains[addedSpell].last = GetSpellInfo(rankChain.back().first);
- mSpellChains[addedSpell].rank = itr->second;
- mSpellChains[addedSpell].prev = GetSpellInfo(prevRank);
- mSpellInfoMap[addedSpell]->ChainEntry = &mSpellChains[addedSpell];
- prevRank = addedSpell;
- ++itr;
+ mSpellChains[nextItr->second].first = first;
+ mSpellChains[nextItr->second].prev = prev;
+ mSpellChains[nextItr->second].next = nullptr;
+ mSpellChains[nextItr->second].last = last;
+ mSpellChains[nextItr->second].rank = rank++;
+ mSpellInfoMap[nextItr->second]->ChainEntry = &mSpellChains[nextItr->second];
- if (itr == rankChain.end())
+ // fill 'last'
+ do
{
- mSpellChains[addedSpell].next = NULL;
- break;
- }
- else
- mSpellChains[addedSpell].next = GetSpellInfo(itr->first);
+ mSpellChains[prev->Id].last = last;
+ prev = mSpellChains[prev->Id].prev;
+ } while (prev);
+
+ nextItr = chains.find(nextItr->second);
}
- while (true);
}
- while (!finished);
- TC_LOG_INFO("server.loading", ">> Loaded %u spell rank records in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u spell rank records in %u ms", uint32(mSpellChains.size()), GetMSTimeDiffToNow(oldMSTime));
}
void SpellMgr::LoadSpellRequired()