[11740] Restore spellmod charges used by fail spell cast

Signed-off-by: VladimirMangos <vladimir@getmangos.com>

Also

 * Prevent more one charge use for same spell cast
 * Cleanup enum SpellState from unused cases
 * Propertly remove spellmod charges at spell finish in case pet/totem caster
This commit is contained in:
rowman 2011-07-16 10:10:52 +04:00 committed by VladimirMangos
parent f1bec402e9
commit 222612fa51
5 changed files with 63 additions and 26 deletions

View file

@ -18696,10 +18696,10 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
void Player::RemoveSpellMods(Spell const* spell) void Player::RemoveSpellMods(Spell const* spell)
{ {
if(!spell || (m_SpellModRemoveCount == 0)) if (!spell || (m_SpellModRemoveCount == 0))
return; return;
for(int i=0;i<MAX_SPELLMOD;++i) for(int i = 0; i < MAX_SPELLMOD; ++i)
{ {
for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();) for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();)
{ {
@ -18718,6 +18718,31 @@ void Player::RemoveSpellMods(Spell const* spell)
} }
} }
void Player::ResetSpellModsDueToCanceledSpell (Spell const* spell)
{
for(int i = 0; i < MAX_SPELLMOD; ++i )
{
for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
{
SpellModifier *mod = *itr;
if (mod->lastAffected != 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 // send Proficiency
void Player::SendProficiency(ItemClass itemClass, uint32 itemSubclassMask) void Player::SendProficiency(ItemClass itemClass, uint32 itemSubclassMask)
{ {

View file

@ -139,7 +139,7 @@ struct SpellModifier
int32 value; int32 value;
ClassFamilyMask mask; ClassFamilyMask mask;
uint32 spellId; 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<SpellModifier*> SpellModList; typedef std::list<SpellModifier*> SpellModList;
@ -1647,6 +1647,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
void RemoveSpellMods(Spell const* spell); 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 infinityCooldownDelay = MONTH; // used for set "infinity cooldowns" for spells and check
static uint32 const infinityCooldownDelayCheck = MONTH/2; static uint32 const infinityCooldownDelayCheck = MONTH/2;
@ -2692,16 +2693,23 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas
totalpct += mod->value; totalpct += mod->value;
} }
if (mod->charges > 0 ) if (mod->charges > 0)
{ {
--mod->charges; if (!spell)
if (mod->charges == 0) 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; mod->lastAffected = spell;
if(!mod->lastAffected)
mod->lastAffected = FindCurrentSpellBySpellId(spellId);
++m_SpellModRemoveCount;
} }
} }
} }

View file

@ -361,7 +361,7 @@ Spell::Spell( Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid o
for(int i = 0; i < MAX_EFFECT_INDEX; ++i) for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
m_currentBasePoints[i] = m_spellInfo->CalculateSimpleValue(SpellEffectIndex(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_castPositionX = m_castPositionY = m_castPositionZ = 0;
m_TriggerSpells.clear(); m_TriggerSpells.clear();
@ -3494,21 +3494,27 @@ void Spell::update(uint32 difftime)
void Spell::finish(bool ok) void Spell::finish(bool ok)
{ {
if(!m_caster) if (!m_caster)
return; return;
if(m_spellState == SPELL_STATE_FINISHED) if (m_spellState == SPELL_STATE_FINISHED)
return; 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; m_spellState = SPELL_STATE_FINISHED;
// other code related only to successfully finished spells
if(!ok)
return;
// remove spell mods // other code related only to successfully finished spells
if (m_caster->GetTypeId() == TYPEID_PLAYER) if (!ok)
((Player*)m_caster)->RemoveSpellMods(this); return;
// handle SPELL_AURA_ADD_TARGET_TRIGGER auras // handle SPELL_AURA_ADD_TARGET_TRIGGER auras
Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER); Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER);

View file

@ -201,12 +201,10 @@ inline ByteBuffer& operator>> (ByteBuffer& buf, SpellCastTargetsReader const& ta
enum SpellState enum SpellState
{ {
SPELL_STATE_NULL = 0, SPELL_STATE_PREPARING = 0, // cast time delay period, non channeled spell
SPELL_STATE_PREPARING = 1, SPELL_STATE_CASTING = 1, // channeled time period spell casting state
SPELL_STATE_CASTING = 2, SPELL_STATE_FINISHED = 2, // cast finished to success or fail
SPELL_STATE_FINISHED = 3, SPELL_STATE_DELAYED = 3 // spell casted but need time to hit target(s)
SPELL_STATE_IDLE = 4,
SPELL_STATE_DELAYED = 5
}; };
enum SpellTargets enum SpellTargets

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11739" #define REVISION_NR "11740"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__