Jump to content

[fix] Spellstack on target addition


Guest Lightguard

Recommended Posts

2

1

2

1

2

1

diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 1f6a746..bd4cd9d 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1064,6 +1064,19 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI
    if(!spellInfo_1 || !spellInfo_2) return false;
    if(spellInfo_1->Id == spellId_2) return false;

+    SpellChainMap::const_iterator itr_1 = mSpellChains.find(spellInfo_1->Id);
+    SpellChainMap::const_iterator itr_2 = mSpellChains.find(spellId_2);
+    if(itr_1 != mSpellChains.end() && itr_2 != mSpellChains.end())
+    {
+        if(uint32 reqSpell1 = itr_1->second.req)
+            if(GetFirstSpellInChain(reqSpell1) == GetFirstSpellInChain(spellId_2))
+                return true;
+
+        if(uint32 reqSpell2 = itr_2->second.req)
+            if(GetFirstSpellInChain(reqSpell2) == GetFirstSpellInChain(spellInfo_1->Id))
+                return true;
+    }
+
    return GetFirstSpellInChain(spellInfo_1->Id)==GetFirstSpellInChain(spellId_2);
}

Patchfile

Any suggestions to simplify it are welcome.

Link to comment
Share on other sites

Modified function used in many cases. For example for stacking in spellbook. And clear that not always req. spell must be take in checks.

Possible this version more safe (it used req. checks only for cases when both spell have same spellspec):

diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 7ef35a5..62f95af 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1055,13 +1055,43 @@ void SpellMgr::LoadSpellThreats()
    sLog.outString();
}

-bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const
+bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2, bool with_req) const
{
+    if(!spellInfo_1) return false;
+
    SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
-    if(!spellInfo_1 || !spellInfo_2) return false;
-    if(spellInfo_1->Id == spellId_2) return false;
+    if(!spellInfo_2) return false;
+
+    // same spell
+    if(spellInfo_1->Id == spellId_2)
+        return false;
+
+    // not ranked
+    SpellChainNode const* node1 = GetSpellChainNode(spellInfo_1->Id);
+    if(!node1)
+        return false;
+
+    // not ranked
+    SpellChainNode const* node2 = GetSpellChainNode(spellInfo_2->Id);
+    if(!node2)
+        return false;

-    return GetFirstSpellInChain(spellInfo_1->Id)==GetFirstSpellInChain(spellId_2);
+    // from same chain both
+    if(node1->first==node2->first)
+        return true;
+
+    if(with_req)
+    {
+        // maybe req from another chain
+        if(node1->req && GetFirstSpellInChain(node1->req)==node2->first)
+            return true;
+
+        // maybe req from another chain
+        if(node2->req && GetFirstSpellInChain(node2->req)==node1->first)
+            return true;
+    }
+
+    return false;
}

bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index d026ccb..68f43f9 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -720,7 +720,7 @@ class SpellMgr
            return false;
        }

-        bool IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const;
+        bool IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2, bool with_req = false) const;
        static bool canStackSpellRanks(SpellEntry const *spellInfo);
        bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const;

diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 309b551..7065f69 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -3566,7 +3566,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
        if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
        {
            // cannot remove higher rank
-            if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
+            if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId, true))
                if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
                    return false;

@@ -3583,7 +3583,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
            else
                next =  m_Auras.begin();
        }
-        else if( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() && spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId) )
+        else if( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() && spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId, true) )
        {
            // cannot remove higher rank
            if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)

Link to comment
Share on other sites

Hmm, but this also not solve problem with req. adding to check. CompareAuraRanks support currently only same spell ranks only.

More general question is: what must happen if one spell

N3 N2 N1 - spsell ranks

B2 B1 another and B2 dependent from N2 and B1 dependent from N1

Whta do if applied B2 and casted N3 or in reversed case.

Link to comment
Share on other sites

That i don't know and currently have no possibilty to test it.

But, another requested thing was shaman totem stack. This patch would do it.

::Edit::

Added warrior shouts.

diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 7ef35a5..bdb4efa 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -203,6 +203,9 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
            if (IsElementalShield(spellInfo))
                return SPELL_ELEMENTAL_SHIELD;

+            if (spellInfo->Attributes == 320)
+                return SPELL_TOTEM_AURA;
+
            break;
        }

@@ -262,6 +265,8 @@ bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSp
        case SPELL_BLESSING:
        case SPELL_AURA:
        case SPELL_CURSE:
+        case SPELL_TOTEM_AURA:
+        case SPELL_POSITIVE_SHOUT:
            return spellId_spec==i_spellId_spec;
        default:
            return false;
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index d026ccb..d79828d 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -96,7 +96,8 @@ enum SpellSpecific
    SPELL_BATTLE_ELIXIR     = 14,
    SPELL_GUARDIAN_ELIXIR   = 15,
    SPELL_FLASK_ELIXIR      = 16,
-    SPELL_PRESENCE          = 17
+    SPELL_PRESENCE          = 17,
+    SPELL_TOTEM_AURA        = 18
};

SpellSpecific GetSpellSpecific(uint32 spellId); 

Patchfile

List of affected totem spells

Link to comment
Share on other sites

More general question is: what must happen if one spell

N3 N2 N1 - spsell ranks

B2 B1 another and B2 dependent from N2 and B1 dependent from N1

Whta do if applied B2 and casted N3 or in reversed case.

also, blessing of might, and battleshout, if they are casted, whichever one is higher should overwrite the lower.

Yeah pally lesser/greater are still stacking, that's what we've been discussing.

I added the warrior shouts to the last patch. (1 line...)

Link to comment
Share on other sites

Yeah pally lesser/greater are still stacking, that's what we've been discussing.

I added the warrior shouts to the last patch. (1 line...)

Yea I know you're talking about the problems of them stacking those spells, seperate from each other but

I mean both of them together.

How it should work: (like it does on offy)

If I use a low level might in a group, and a warrior in the group casts battleshout, that's higher than my lower level might, the battleshout should overwrite the lower might. thats how it is on official.

How I hear it currently works on mangos:

People are saying pally buffs are stacking and diff ranks of shout are stacking, but i'm talking about them together, battleshout should overwrite might.

Link to comment
Share on other sites

Hm, that would change the whole thing. And make all the patches made before, just useless...

yea, and unfortunately, its true, thats how it is on official. Pallies were always crying about how much they had to buff people, which were 10-15m, and i think they're like 30m buffs now and an overzealous warrior would hit battleshout which only lasts like 2m-3m and overwrite their might buffs that they used reagents for. Pallies QQ'd all the time.

but, You could do a patch just to fix the stacking of the same name spells and work on a fix for different named spells that don't stack and overwrite each other later.

Link to comment
Share on other sites

Well, thinking about it for a while i've come to this conclusion:

(Should also be applied to other functions probably)

Basically, this modification checks for three simple things: ApplyAuraName[0] Spellfamily and Spellfamilyflags.

These values seem to be the same in spells that's stacking we're trying to control. If anyone finds any problem with it, please report it.

(The auras listed here are just examples, that's not complete yet)

diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 7ef35a5..5001392 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -255,14 +255,21 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s
    }
}

-bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec)
+bool IsSingleFromSpellSpecificRanksPerTarget(SpellEntry const* spellInfo_1, SpellEntry const* spellInfo_2)
{
-    switch(spellId_spec)
+    AuraType spellAura_1 = spellInfo_1->ApplyAuraName[0];
+    AuraType spellAura_2 = spellInfo_2->ApplyAuraName[0];
+    switch(spellAura_1)
    {
-        case SPELL_BLESSING:
-        case SPELL_AURA:
-        case SPELL_CURSE:
-            return spellId_spec==i_spellId_spec;
+        case SPELL_AURA_MOD_ATTACK_POWER:
+        case SPELL_AURA_MOD_STAT:
+        case SPELL_AURA_MOD_RESISTANCE:
+        case SPELL_AURA_MOD_INCREASE_HEALTH:
+        case SPELL_AURA_MOD_POWER_REGEN:
+        case SPELL_AURA_MOD_REGEN:
+        case SPELL_AURA_MOD_TARGET_RESISTANCE:
+        case SPELL_AURA_MOD_HEALING_DONE:
+            return spellAura_1==spellAura_2;
        default:
            return false;
    }
@@ -1061,6 +1068,11 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI
    if(!spellInfo_1 || !spellInfo_2) return false;
    if(spellInfo_1->Id == spellId_2) return false;

+    if(spellInfo_1->EffectApplyAuraName[0] == spellInfo_2->EffectApplyAuraName[0] &&
+       spellInfo_1->SpellFamilyName == spellInfo_2->SpellFamilyName &&
+       spellInfo_1->SpellFamilyFlags == spellInfo_2->SpellFamilyFlags)
+       return true;
+
    return GetFirstSpellInChain(spellInfo_1->Id)==GetFirstSpellInChain(spellId_2);
}

diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index d026ccb..b39845d 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -146,7 +146,7 @@ inline bool IsLootCraftingSpell(SpellEntry const *spellInfo)

int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
-bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec);
+bool IsSingleFromSpellSpecificRanksPerTarget(SpellEntry const* spellInfo_1, SpellEntry const* spellInfo_2);
bool IsPassiveSpell(uint32 spellId);

inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto)
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 739f05c..e6af916 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -3561,7 +3561,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
        SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);

        bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
-        bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellId_spec,i_spellId_spec);
+        bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellProto,i_spellProto);

        if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
        {

Patchfile

List of * Blessing of Might created with this check

List of * of the Wild created with this check

Link to comment
Share on other sites

  • 1 month later...

Ok, this one works correctly.

This patch checks if the 2 auras are of the same type, and depending on CompareAuraRanks (basepoints) decides if the existing has to be replaced or not.

I included only SPELL_AURA_MOD_ATTACK_POWER for testing, as we should be sure about which aura types are affected by this stacking system (if not all).

diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 863c01d..466fd52 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -256,17 +256,27 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s
    }
}

-bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec)
+bool IsSingleFromSpellSpecificRanksPerTarget(SpellEntry const *spellInfo_1, SpellEntry const *spellInfo_2)
{
-    switch(spellId_spec)
+    if(!spellInfo_1 || !spellInfo_2)
+        return false;
+
+    uint32 aur_1 = spellInfo_1->EffectApplyAuraName[0];
+    uint32 aur_2 = spellInfo_2->EffectApplyAuraName[0];
+
+    if(!aur_1 ||!aur_2)
+        return false;
+
+    switch(aur_1)
    {
-        case SPELL_BLESSING:
-        case SPELL_AURA:
-        case SPELL_CURSE:
-            return spellId_spec==i_spellId_spec;
+        case SPELL_AURA_MOD_ATTACK_POWER:
+            if(aur_1==aur_2)
+                return true;
        default:
            return false;
    }
+
+    return false;
}

bool IsPositiveTarget(uint32 targetA, uint32 targetB)
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 8061dbe..4a47914 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -146,7 +146,7 @@ inline bool IsLootCraftingSpell(SpellEntry const *spellInfo)

int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
-bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec);
+bool IsSingleFromSpellSpecificRanksPerTarget(SpellEntry const *spellInfo_1, SpellEntry const *spellInfo_2);
bool IsPassiveSpell(uint32 spellId);

inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto)
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index a2928a4..d902b2d 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -3547,7 +3547,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
        SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);

        bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
-        bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellId_spec,i_spellId_spec);
+        bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellProto,i_spellProto);

        if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
        {
@@ -3569,7 +3569,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
            else
                next =  m_Auras.begin();
        }
-        else if( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() && spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId) )
+        else if( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() )
        {
            // cannot remove higher rank
            if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0) 

Patchfile

::Edit::

Forgot default case. Added.

But still it will also need effect indexes, and lots of info from off.

Link to comment
Share on other sites

I haven't tested it but, note that procs stack with buffs.

For example the 1000AP proc from the lvl80 epic trinket stacks with Blessing of Might, but most procs with same stat buff does not stack together, excluding 1H Weapon enchant procs, e.g. Berserking and Moongose.

Congratulation on the patch, this is important to work blizzlike so we can compare mangos and blizz expiriences more apropriately and eventually get closer to the original.

Link to comment
Share on other sites

  • 4 weeks later...
  • 3 weeks later...
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use