diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-06-15 16:20:43 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-06-15 16:20:43 +0200 |
commit | 5da217877be7f22db3bfc8ee06ca1ffad172d281 (patch) | |
tree | fc6b5a98a6b1d76bd1e061afec0fabc007922b0c | |
parent | 8839369fc534d46816efd22ef0db3f8b9e5c8d44 (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
-rw-r--r-- | sql/updates/world/6.x/2016_06_15_06_world.sql | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 39 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 145 |
5 files changed, 59 insertions, 138 deletions
diff --git a/sql/updates/world/6.x/2016_06_15_06_world.sql b/sql/updates/world/6.x/2016_06_15_06_world.sql new file mode 100644 index 00000000000..6d63a4ca441 --- /dev/null +++ b/sql/updates/world/6.x/2016_06_15_06_world.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `spell_ranks`; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1dd3f63097a..e3d114e367c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2905,7 +2905,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent bool dependent_set = false; bool disabled_case = false; - bool superceded_old = false; PlayerSpellMap::iterator itr = m_spells.find(spellId); @@ -2916,7 +2915,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent { uint32 next_active_spell_id = 0; // fix activate state for non-stackable low rank (and find next spell for !active case) - if (!spellInfo->IsStackableWithRanks() && spellInfo->IsRanked()) + if (spellInfo->IsRanked()) { if (uint32 next = sSpellMgr->GetNextSpellInChain(spellId)) { @@ -3029,7 +3028,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent newspell->disabled = disabled; // replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible - if (newspell->active && !newspell->disabled && !spellInfo->IsStackableWithRanks() && spellInfo->IsRanked() != 0) + if (newspell->active && !newspell->disabled && spellInfo->IsRanked()) { for (PlayerSpellMap::iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) { @@ -3053,7 +3052,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent itr2->second->active = false; if (itr2->second->state != PLAYERSPELL_NEW) itr2->second->state = PLAYERSPELL_CHANGED; - superceded_old = true; // new spell replace old in action bars and spell book. } else { @@ -3173,7 +3171,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent } // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell - return active && !disabled && !superceded_old; + return active && !disabled; } void Player::AddTemporarySpell(uint32 spellId) @@ -3379,7 +3377,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) { // if ranked non-stackable spell: need activate lesser rank and update dendence state /// No need to check for spellInfo != NULL here because if cur_active is true, then that means that the spell was already in m_spells, and only valid spells can be pushed there. - if (cur_active && !spellInfo->IsStackableWithRanks() && spellInfo->IsRanked()) + if (cur_active && spellInfo->IsRanked()) { // need manually update dependence state (learn spell ignore like attempts) PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index e7ac181e69f..25a5c874a58 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1257,22 +1257,6 @@ bool SpellInfo::IsQuestTame() const return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY; } -bool SpellInfo::IsProfessionOrRiding(uint32 difficulty) const -{ - SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfo const* effect : effects) - { - if ((effect && effect->Effect == SPELL_EFFECT_SKILL)) - { - uint32 skill = effect->MiscValue; - - if (IsProfessionOrRidingSkill(skill)) - return true; - } - } - return false; -} - bool SpellInfo::IsProfession(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); @@ -1310,23 +1294,6 @@ bool SpellInfo::IsPrimaryProfessionFirstRank(uint32 difficulty) const return IsPrimaryProfession(difficulty) && GetRank() == 1; } -bool SpellInfo::IsAbilityLearnedWithProfession() const -{ - SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id); - - for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) - { - SkillLineAbilityEntry const* pAbility = _spell_idx->second; - if (!pAbility || pAbility->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) - continue; - - if (pAbility->MinSkillLineRank > 0) - return true; - } - - return false; -} - bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const { SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id); @@ -1425,12 +1392,6 @@ bool SpellInfo::IsStackableWithRanks() const if (IsPassive()) return false; - if (IsProfessionOrRiding()) - return false; - - if (IsAbilityLearnedWithProfession()) - return false; - // All stance spells. if any better way, change it. SpellEffectInfoVector effects = GetEffectsForDifficulty(DIFFICULTY_NONE); for (SpellEffectInfo const* effect : effects) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 4faf98a0791..3ca96b3c0e9 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -481,11 +481,9 @@ public: bool IsExplicitDiscovery() const; bool IsLootCrafting() const; bool IsQuestTame() const; - bool IsProfessionOrRiding(uint32 difficulty = DIFFICULTY_NONE) const; bool IsProfession(uint32 difficulty = DIFFICULTY_NONE) const; bool IsPrimaryProfession(uint32 difficulty = DIFFICULTY_NONE) const; bool IsPrimaryProfessionFirstRank(uint32 difficulty = DIFFICULTY_NONE) const; - bool IsAbilityLearnedWithProfession() const; bool IsAbilityOfSkillType(uint32 skillType) const; bool IsAffectingArea(uint32 difficulty) const; 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() |