Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core/Auras: Expanding functionality of SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT to be able to take care of aura effects inside their handlers #12233

Merged
merged 1 commit into from Jun 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/server/game/Entities/Unit/Unit.cpp
Expand Up @@ -17692,3 +17692,27 @@ void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns c
data << uint32(itr->second);
}
}

int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue /*= false*/) const
{
int32 val = 0;
SpellSpellGroupMapBounds spellGroup = sSpellMgr->GetSpellSpellGroupMapBounds(aurEff->GetSpellInfo()->GetFirstRankSpell()->Id);
for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr)
{
if (sSpellMgr->GetSpellGroupStackRule(itr->second) == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT)
{
AuraEffectList const& auraEffList = GetAuraEffectsByType(auraType);
for (AuraEffectList::const_iterator auraItr = auraEffList.begin(); auraItr != auraEffList.end(); ++auraItr)
{
if (aurEff != (*auraItr) && (!sameMiscValue || aurEff->GetMiscValue() == (*auraItr)->GetMiscValue()) &&
sSpellMgr->IsSpellMemberOfSpellGroup((*auraItr)->GetSpellInfo()->Id, itr->second))
{
// absolute value only
if (abs(val) < abs((*auraItr)->GetAmount()))
val = (*auraItr)->GetAmount();
}
}
}
}
return val;
}
2 changes: 2 additions & 0 deletions src/server/game/Entities/Unit/Unit.h
Expand Up @@ -2152,6 +2152,8 @@ class Unit : public WorldObject
time_t GetLastDamagedTime() const { return _lastDamagedTime; }
void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; }

int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue = false) const;

protected:
explicit Unit (bool isWorldObject);

Expand Down
62 changes: 57 additions & 5 deletions src/server/game/Spells/Auras/SpellAuraEffects.cpp
Expand Up @@ -3497,11 +3497,23 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8
return;

Unit* target = aurApp->GetTarget();
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_RESISTANCE_PCT);
if (abs(spellGroupVal) >= abs(GetAmount()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine a +1% aura, and a +5%.

/!\ Assuming hook is called before auraeffect is applied
/!\ and called AFTER auraeffect is actually removed
/!\ (so Unit::GetHighest... doesn't iterate through it)

Order of actions:
- Apply +1% then +5%
  -> spellGroupVal = 0%, stat is 1%
  -> spellGroupVal = 1%, GetAmount() = 5%, stat is 5%
a) - Remove +1% first
       -> spellGroupVal = 5%, GetAmount() = 1%, no effect
    - Remove +5%
       -> spellGroupVal = 0%, GetAmount() = 5%, remove
b) - Remove +5% first
       -> spellGroupVal = 1%, GetAmount() = 5%, stat is 1%
    - Remove +1%
       -> spellGroupVal = 0%, GetAmount() = 1%, stat is 0%

So I'm giving this a go IFF hooks are called in the order i assume above (which is something I do not remember at all)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are called in that order

return;

for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
{
if (GetMiscValue() & int32(1<<i))
{
if (spellGroupVal)
{
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
{
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)spellGroupVal, !apply);
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)spellGroupVal, !apply);
}
}
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
{
Expand Down Expand Up @@ -3561,19 +3573,29 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;

Unit* target = aurApp->GetTarget();

if (GetMiscValue() < -2 || GetMiscValue() > 4)
{
TC_LOG_ERROR("spells", "WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue());
return;
}

Unit* target = aurApp->GetTarget();
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_STAT, true);
if (abs(spellGroupVal) >= abs(GetAmount()))
return;

for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
// -1 or -2 is all stats (misc < -2 checked in function beginning)
if (GetMiscValue() < 0 || GetMiscValue() == i)
{
if (spellGroupVal)
{
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply);
}

//target->ApplyStatMod(Stats(i), m_amount, apply);
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
Expand Down Expand Up @@ -4099,7 +4121,17 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo
return;

Unit* target = aurApp->GetTarget();
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MELEE_SLOW);
if (abs(spellGroupVal) >= abs(GetAmount()))
return;

if (spellGroupVal)
{
target->ApplyCastTimePercentMod(float(spellGroupVal), !apply);
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply);
}
target->ApplyCastTimePercentMod(float(m_amount), apply);
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
Expand All @@ -4123,7 +4155,15 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
return;

Unit* target = aurApp->GetTarget();
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE);
if (abs(spellGroupVal) >= abs(GetAmount()))
return;

if (spellGroupVal)
{
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), !apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), !apply);
}
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
}
Expand Down Expand Up @@ -4360,7 +4400,8 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
return;

Unit* target = aurApp->GetTarget();
if (!target)
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
if (abs(spellGroupVal) >= abs(GetAmount()))
return;

if (target->GetTypeId() == TYPEID_PLAYER)
Expand All @@ -4372,12 +4413,23 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8

if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER))
{
if (spellGroupVal)
{
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(spellGroupVal), !apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply);
}
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);

if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply);
if (Player* player = target->ToPlayer())
{
if (spellGroupVal)
player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(spellGroupVal), !apply);

player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(GetAmount()), apply);
}
}
else
{
Expand Down
9 changes: 9 additions & 0 deletions src/server/game/Spells/SpellMgr.cpp
Expand Up @@ -765,6 +765,15 @@ SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellIn
return rule;
}

SpellGroupStackRule SpellMgr::GetSpellGroupStackRule(SpellGroup group) const
{
SpellGroupStackMap::const_iterator itr = mSpellGroupStack.find(group);
if (itr != mSpellGroupStack.end())
return itr->second;

return SPELL_GROUP_STACK_RULE_DEFAULT;
}

SpellProcEventEntry const* SpellMgr::GetSpellProcEvent(uint32 spellId) const
{
SpellProcEventMap::const_iterator itr = mSpellProcEventMap.find(spellId);
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Spells/SpellMgr.h
Expand Up @@ -655,6 +655,7 @@ class SpellMgr
// Spell Group Stack Rules table
bool AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, int32 amount, std::map<SpellGroup, int32>& groups) const;
SpellGroupStackRule CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const;
SpellGroupStackRule GetSpellGroupStackRule(SpellGroup groupid) const;

// Spell proc event table
SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const;
Expand Down