diff options
Diffstat (limited to 'src/server/game/Spells/SpellMgr.cpp')
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 174 |
1 files changed, 142 insertions, 32 deletions
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 0de0e819dcf..d1324088f49 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -398,32 +398,34 @@ void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& } } -bool SpellMgr::AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, int32 amount, std::map<SpellGroup, int32>& groups) const +bool SpellMgr::AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, AuraType auraType, int32 amount, std::map<SpellGroup, int32>& groups) const { uint32 spellId = spellInfo->GetFirstRankSpell()->Id; - SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds(spellId); + auto spellGroupBounds = GetSpellSpellGroupMapBounds(spellId); // Find group with SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT if it belongs to one - for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second; ++itr) + for (auto itr = spellGroupBounds.first; itr != spellGroupBounds.second; ++itr) { SpellGroup group = itr->second; - SpellGroupStackMap::const_iterator found = mSpellGroupStack.find(group); - if (found != mSpellGroupStack.end()) + auto found = mSpellSameEffectStack.find(group); + if (found != mSpellSameEffectStack.end()) { - if (found->second == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT) + // check auraTypes + if (!found->second.count(uint32(auraType))) + continue; + + // Put the highest amount in the map + auto groupItr = groups.find(group); + if (groupItr == groups.end()) + groups.emplace(group, amount); + else { - // Put the highest amount in the map - if (groups.find(group) == groups.end()) - groups[group] = amount; - else - { - int32 curr_amount = groups[group]; - // Take absolute value because this also counts for the highest negative aura - if (abs(curr_amount) < abs(amount)) - groups[group] = amount; - } - // return because a spell should be in only one SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group - return true; + int32 curr_amount = groups[group]; + // Take absolute value because this also counts for the highest negative aura + if (std::abs(curr_amount) < std::abs(amount)) + groupItr->second = amount; } + // return because a spell should be in only one SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group per auraType + return true; } } // Not in a SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group, so return false @@ -1315,19 +1317,19 @@ void SpellMgr::LoadSpellGroups() } int32 spell_id = fields[1].GetInt32(); - groups.insert(std::set<uint32>::value_type(group_id)); - mSpellGroupSpell.insert(SpellGroupSpellMap::value_type((SpellGroup)group_id, spell_id)); + groups.insert(group_id); + mSpellGroupSpell.emplace(SpellGroup(group_id), spell_id); } while (result->NextRow()); - for (SpellGroupSpellMap::iterator itr = mSpellGroupSpell.begin(); itr!= mSpellGroupSpell.end();) + for (auto itr = mSpellGroupSpell.begin(); itr!= mSpellGroupSpell.end();) { if (itr->second < 0) { if (groups.find(abs(itr->second)) == groups.end()) { TC_LOG_ERROR("sql.sql", "SpellGroup id %u listed in `spell_group` does not exist", abs(itr->second)); - mSpellGroupSpell.erase(itr++); + itr = mSpellGroupSpell.erase(itr); } else ++itr; @@ -1335,31 +1337,30 @@ void SpellMgr::LoadSpellGroups() else { SpellInfo const* spellInfo = GetSpellInfo(itr->second); - if (!spellInfo) { TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_group` does not exist", itr->second); - mSpellGroupSpell.erase(itr++); + itr = mSpellGroupSpell.erase(itr); } else if (spellInfo->GetRank() > 1) { TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_group` is not the first rank of the spell.", itr->second); - mSpellGroupSpell.erase(itr++); + itr = mSpellGroupSpell.erase(itr); } else ++itr; } } - for (std::set<uint32>::iterator groupItr = groups.begin(); groupItr != groups.end(); ++groupItr) + for (auto groupItr = groups.begin(); groupItr != groups.end(); ++groupItr) { std::set<uint32> spells; GetSetOfSpellsInSpellGroup(SpellGroup(*groupItr), spells); - for (std::set<uint32>::iterator spellItr = spells.begin(); spellItr != spells.end(); ++spellItr) + for (auto spellItr = spells.begin(); spellItr != spells.end(); ++spellItr) { ++count; - mSpellSpellGroup.insert(SpellSpellGroupMap::value_type(*spellItr, SpellGroup(*groupItr))); + mSpellSpellGroup.emplace(*spellItr, SpellGroup(*groupItr)); } } @@ -1371,6 +1372,9 @@ void SpellMgr::LoadSpellGroupStackRules() uint32 oldMSTime = getMSTime(); mSpellGroupStack.clear(); // need for reload case + mSpellSameEffectStack.clear(); + + std::vector<uint32> sameEffectGroups; // 0 1 QueryResult result = WorldDatabase.Query("SELECT group_id, stack_rule FROM spell_group_stack_rules"); @@ -1393,20 +1397,126 @@ void SpellMgr::LoadSpellGroupStackRules() continue; } - SpellGroupSpellMapBounds spellGroup = GetSpellGroupSpellMapBounds((SpellGroup)group_id); - - if (spellGroup.first == spellGroup.second) + auto bounds = GetSpellGroupSpellMapBounds((SpellGroup)group_id); + if (bounds.first == bounds.second) { TC_LOG_ERROR("sql.sql", "SpellGroup id %u listed in `spell_group_stack_rules` does not exist.", group_id); continue; } - mSpellGroupStack[(SpellGroup)group_id] = (SpellGroupStackRule)stack_rule; + // different container for same effect stack rules, need to check effect types + if (stack_rule != SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT) + mSpellGroupStack.emplace(SpellGroup(group_id), SpellGroupStackRule(stack_rule)); + else + sameEffectGroups.push_back(group_id); ++count; } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u spell group stack rules in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + + count = 0; + oldMSTime = getMSTime(); + TC_LOG_INFO("server.loading", ">> Parsing SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules..."); + + for (uint32 group_id : sameEffectGroups) + { + std::set<uint32> spellIds; + GetSetOfSpellsInSpellGroup(SpellGroup(group_id), spellIds); + + std::unordered_set<uint32> auraTypes; + + // we have to 'guess' what effect this group corresponds to + { + std::unordered_multiset<uint32 /*auraName*/> frequencyContainer; + + // only waylay for the moment (shared group) + std::vector<std::vector<uint32 /*auraName*/>> const SubGroups = + { + { SPELL_AURA_MOD_MELEE_HASTE, SPELL_AURA_MOD_MELEE_RANGED_HASTE, SPELL_AURA_MOD_RANGED_HASTE } + }; + + for (uint32 spellId : spellIds) + { + SpellInfo const* spellInfo = AssertSpellInfo(spellId); + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (!spellInfo->Effects[i].IsAura()) + continue; + + int32 auraName = static_cast<int32>(spellInfo->Effects[i].ApplyAuraName); + for (std::vector<uint32> const& subGroup : SubGroups) + { + if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end()) + { + // count as first aura + auraName = subGroup.front(); + break; + } + } + + frequencyContainer.insert(auraName); + } + } + + uint32 auraType = 0; + size_t auraTypeCount = 0; + for (uint32 auraName : frequencyContainer) + { + size_t currentCount = frequencyContainer.count(auraName); + if (currentCount > auraTypeCount) + { + auraType = auraName; + auraTypeCount = currentCount; + } + } + + for (std::vector<uint32> const& subGroup : SubGroups) + { + if (auraType == subGroup.front()) + { + auraTypes.insert(subGroup.begin(), subGroup.end()); + break; + } + } + + if (auraTypes.empty()) + auraTypes.insert(auraType); + } + + // re-check spells against guessed group + for (uint32 spellId : spellIds) + { + SpellInfo const* spellInfo = AssertSpellInfo(spellId); + + bool found = false; + while (spellInfo) + { + for (uint32 auraType : auraTypes) + { + if (spellInfo->HasAura(AuraType(auraType))) + { + found = true; + break; + } + } + + if (found) + break; + + spellInfo = spellInfo->GetNextRankSpell(); + } + + // not found either, log error + if (!found) + TC_LOG_ERROR("sql.sql", "SpellId %u listed in `spell_group` with stack rule 3 does not share aura assigned for group %u", spellId, group_id); + } + + mSpellSameEffectStack[SpellGroup(group_id)] = auraTypes; + ++count; + } + + TC_LOG_INFO("server.loading", ">> Parsed %u SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } void SpellMgr::LoadSpellProcs() |