aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Spells/SpellMgr.cpp')
-rw-r--r--src/server/game/Spells/SpellMgr.cpp183
1 files changed, 149 insertions, 34 deletions
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 1dcc18773e1..eb2621954cf 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -335,32 +335,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, uint32 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(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
@@ -374,8 +376,6 @@ SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellIn
uint32 spellid_1 = spellInfo1->GetFirstRankSpell()->Id;
uint32 spellid_2 = spellInfo2->GetFirstRankSpell()->Id;
- if (spellid_1 == spellid_2)
- return SPELL_GROUP_STACK_RULE_DEFAULT;
// find SpellGroups which are common for both spells
SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds(spellid_1);
@@ -1181,19 +1181,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;
@@ -1201,31 +1201,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));
}
}
@@ -1237,6 +1236,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");
@@ -1259,20 +1261,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;
+ mSpellGroupStack.emplace(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)
+ 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 (SpellEffectInfo const* effectInfo : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ {
+ if (!effectInfo->IsAura())
+ continue;
+
+ int32 auraName = static_cast<int32>(effectInfo->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(DIFFICULTY_NONE, 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()
@@ -3342,6 +3450,13 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Speed = 0.0f; // This spell's summon happens instantly
});
+ // Chilled to the Bone
+ ApplySpellFix({ 70106 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS;
+ spellInfo->AttributesEx6 |= SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS;
+ });
+
// Ice Lock
ApplySpellFix({ 71614 }, [](SpellInfo* spellInfo)
{