diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8da16c6f1..80de1f369 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18696,10 +18696,10 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) void Player::RemoveSpellMods(Spell const* spell) { - if(!spell || (m_SpellModRemoveCount == 0)) + if (!spell || (m_SpellModRemoveCount == 0)) return; - for(int i=0;ilastAffected != spell) + continue; + + mod->lastAffected = NULL; + + if (mod->charges == -1) + { + mod->charges = 1; + if (m_SpellModRemoveCount > 0) + --m_SpellModRemoveCount; + } + else if (mod->charges > 0) + ++mod->charges; + } + } +} + // send Proficiency void Player::SendProficiency(ItemClass itemClass, uint32 itemSubclassMask) { diff --git a/src/game/Player.h b/src/game/Player.h index 8e299ec08..e53c233c8 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -139,7 +139,7 @@ struct SpellModifier int32 value; ClassFamilyMask mask; uint32 spellId; - Spell const* lastAffected; + Spell const* lastAffected; // mark last charge user, used for cleanup delayed remove spellmods at spell success or restore charges at cast fail (Is one pointer only need for cases mixed castes?) }; typedef std::list SpellModList; @@ -1647,6 +1647,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); template T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); void RemoveSpellMods(Spell const* spell); + void ResetSpellModsDueToCanceledSpell (Spell const* spell); static uint32 const infinityCooldownDelay = MONTH; // used for set "infinity cooldowns" for spells and check static uint32 const infinityCooldownDelayCheck = MONTH/2; @@ -2692,16 +2693,23 @@ template T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas totalpct += mod->value; } - if (mod->charges > 0 ) + if (mod->charges > 0) { - --mod->charges; - if (mod->charges == 0) + if (!spell) + spell = FindCurrentSpellBySpellId(spellId); + + // avoid double use spellmod charge by same spell + if (!mod->lastAffected || mod->lastAffected != spell) { - mod->charges = -1; + --mod->charges; + + if (mod->charges == 0) + { + mod->charges = -1; + ++m_SpellModRemoveCount; + } + mod->lastAffected = spell; - if(!mod->lastAffected) - mod->lastAffected = FindCurrentSpellBySpellId(spellId); - ++m_SpellModRemoveCount; } } } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index cfc1db319..fb770fcbe 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -361,7 +361,7 @@ Spell::Spell( Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid o for(int i = 0; i < MAX_EFFECT_INDEX; ++i) m_currentBasePoints[i] = m_spellInfo->CalculateSimpleValue(SpellEffectIndex(i)); - m_spellState = SPELL_STATE_NULL; + m_spellState = SPELL_STATE_PREPARING; m_castPositionX = m_castPositionY = m_castPositionZ = 0; m_TriggerSpells.clear(); @@ -3494,21 +3494,27 @@ void Spell::update(uint32 difftime) void Spell::finish(bool ok) { - if(!m_caster) + if (!m_caster) return; - if(m_spellState == SPELL_STATE_FINISHED) + if (m_spellState == SPELL_STATE_FINISHED) return; + // remove/restore spell mods before m_spellState update + if (Player* modOwner = m_caster->GetSpellModOwner()) + { + if (ok || m_spellState != SPELL_STATE_PREPARING) // fail after start channeling or throw to target not affect spell mods + modOwner->RemoveSpellMods(this); + else + modOwner->ResetSpellModsDueToCanceledSpell(this); + } + m_spellState = SPELL_STATE_FINISHED; - // other code related only to successfully finished spells - if(!ok) - return; - // remove spell mods - if (m_caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_caster)->RemoveSpellMods(this); + // other code related only to successfully finished spells + if (!ok) + return; // handle SPELL_AURA_ADD_TARGET_TRIGGER auras Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER); diff --git a/src/game/Spell.h b/src/game/Spell.h index 7dd71470b..6fff7e224 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -201,12 +201,10 @@ inline ByteBuffer& operator>> (ByteBuffer& buf, SpellCastTargetsReader const& ta enum SpellState { - SPELL_STATE_NULL = 0, - SPELL_STATE_PREPARING = 1, - SPELL_STATE_CASTING = 2, - SPELL_STATE_FINISHED = 3, - SPELL_STATE_IDLE = 4, - SPELL_STATE_DELAYED = 5 + SPELL_STATE_PREPARING = 0, // cast time delay period, non channeled spell + SPELL_STATE_CASTING = 1, // channeled time period spell casting state + SPELL_STATE_FINISHED = 2, // cast finished to success or fail + SPELL_STATE_DELAYED = 3 // spell casted but need time to hit target(s) }; enum SpellTargets diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 20da08f18..e2b741cc3 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11739" + #define REVISION_NR "11740" #endif // __REVISION_NR_H__