Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 5266) +++ src/game/Player.cpp (working copy) @@ -56,6 +56,7 @@ #include "ArenaTeam.h" #include "Chat.h" #include "Database/DatabaseImpl.h" +#include "Spell.h" #include @@ -14746,13 +14747,22 @@ return total; } -bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod) +bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) { if (!mod || !spellInfo) return false; - if ((mod->charges == -1) && (mod->lastAffected != spellInfo->Id)) - return false; + if(mod->charges == -1 && mod->lastAffected ) // marked as expired but locked until spell casting finish + { + // prevent apply to any spell expect spell that trigger expire + if(spell) + { + if(mod->lastAffected != spell) + return false; + } + else if(mod->lastAffected != FindCurrentSpellBySpellId(spellInfo->Id)) + return false; + } return spellmgr.IsAffectedBySpell(spellInfo,mod->spellId,mod->effectId,mod->mask); } @@ -14791,24 +14801,26 @@ } } -void Player::RemoveSpellMods(uint32 spellId) +void Player::RemoveSpellMods(Spell const* spell) { - if(!spellId || (m_SpellModRemoveCount == 0)) + if(!spell || (m_SpellModRemoveCount == 0)) return; for(int i=0;icharges == -1 && mod->lastAffected == spellId) + for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();) { - RemoveAurasDueToSpell(mod->spellId); - if (m_spellMods[i].empty()) - break; - else - next = m_spellMods[i].begin(); + SpellModifier *mod = *itr; + ++itr; + + if (mod && mod->charges == -1 && (mod->lastAffected == spell || mod->lastAffected==NULL)) + { + RemoveAurasDueToSpell(mod->spellId); + if (m_spellMods[i].empty()) + break; + else + itr = m_spellMods[i].begin(); + } } } } Index: src/game/Player.h =================================================================== --- src/game/Player.h (revision 5266) +++ src/game/Player.h (working copy) @@ -80,7 +80,7 @@ uint64 mask; uint32 spellId; uint32 effectId; - uint32 lastAffected; + Spell const* lastAffected; }; typedef HM_NAMESPACE::hash_map PlayerSpellMap; @@ -1332,9 +1332,9 @@ void AddSpellMod(SpellModifier* mod, bool apply); int32 GetTotalFlatMods(uint32 spellId, uint8 op); int32 GetTotalPctMods(uint32 spellId, uint8 op); - bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod); - template T ApplySpellMod(uint32 spellId, uint8 op, T &basevalue); - void RemoveSpellMods(uint32 spellId); + bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); + template T ApplySpellMod(uint32 spellId, uint8 op, T &basevalue, Spell const* spell = NULL); + void RemoveSpellMods(Spell const* spell); bool HasSpellCooldown(uint32 spell_id) const { @@ -2079,7 +2079,7 @@ void RemoveItemsSetItem(Player*player,ItemPrototype const *proto); // "the bodies of template functions must be made available in a header file" -template T Player::ApplySpellMod(uint32 spellId, uint8 op, T &basevalue) +template T Player::ApplySpellMod(uint32 spellId, uint8 op, T &basevalue, Spell const* spell) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) return 0; @@ -2089,7 +2089,7 @@ { SpellModifier *mod = *itr; - if(!IsAffectedBySpellmod(spellInfo,mod)) + if(!IsAffectedBySpellmod(spellInfo,mod,spell)) continue; if (mod->type == SPELLMOD_FLAT) totalflat += mod->value; @@ -2101,7 +2101,9 @@ if (mod->charges == 0) { mod->charges = -1; - mod->lastAffected = spellId; + mod->lastAffected = spell; + if(!mod->lastAffected) + mod->lastAffected = FindCurrentSpellBySpellId(spellId); m_SpellModRemoveCount++; } } Index: src/game/Spell.cpp =================================================================== --- src/game/Spell.cpp (revision 5266) +++ src/game/Spell.cpp (working copy) @@ -298,7 +298,7 @@ casttime = GetCastTime(sCastTimesStore.LookupEntry(m_spellInfo->CastingTimeIndex)); if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_CASTING_TIME, casttime); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_CASTING_TIME, casttime,this); casttime = int32(casttime*m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED)); @@ -719,7 +719,7 @@ float multiplier = m_spellInfo->DmgMultiplier[effectNumber]; // Apply multiplier mods if(Player* modOwner = m_originalCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier,this); m_damageMultipliers[effectNumber] *= multiplier; } } @@ -835,7 +835,7 @@ if(m_originalCaster) if(Player* modOwner = m_originalCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius,this); uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; switch(cur) @@ -1565,7 +1565,7 @@ return; } - if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget()) + if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget() && m_targets.getUnitTarget() != m_caster) m_caster->SetInFront(m_targets.getUnitTarget()); castResult = CheckMana( &mana); @@ -1795,7 +1795,7 @@ //remove spell mods if (m_caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_caster)->RemoveSpellMods(m_spellInfo->Id); + ((Player*)m_caster)->RemoveSpellMods(this); } void Spell::SendSpellCooldown() @@ -1847,10 +1847,10 @@ // Now we have cooldown data (if found any), time to apply mods if(rec > 0) - _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec); + _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec, this); if(catrec > 0) - _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec); + _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec, this); // replace negative cooldowns by 0 if (rec < 0) rec = 0; @@ -3513,7 +3513,7 @@ float min_range = GetMinRange(srange); if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); Unit *target = m_targets.getUnitTarget(); @@ -3585,7 +3585,7 @@ manaCost+= m_caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+m_spellInfo->School); if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, manaCost); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, manaCost, this); manaCost*= (1.0f+m_caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+m_spellInfo->School)); if (manaCost < 0) @@ -3913,7 +3913,7 @@ //check resist chance int32 resistChance = 100; //must be initialized to 100 for percent modifiers - ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance); + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; if (roll_chance_f(resistChance)) return; @@ -3937,7 +3937,7 @@ //check resist chance int32 resistChance = 100; //must be initialized to 100 for percent modifiers - ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance); + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; if (roll_chance_f(resistChance)) return; Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 5266) +++ src/game/SpellAuras.cpp (working copy) @@ -1001,7 +1001,7 @@ mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types mod->spellId = m_spellId; mod->effectId = m_effIndex; - mod->lastAffected = 0; + mod->lastAffected = NULL; SpellAffection const *spellAffect = spellmgr.GetSpellAffection(m_spellId, m_effIndex); @@ -1194,7 +1194,7 @@ mod->type = SPELLMOD_PCT; mod->spellId = m_spellId; mod->effectId = m_effIndex; - mod->lastAffected = 0; + mod->lastAffected = NULL; mod->mask = 0x00008000 | 0x00001000; mod->charges = 0; @@ -1216,7 +1216,7 @@ mod->type = SPELLMOD_FLAT; mod->spellId = m_spellId; mod->effectId = m_effIndex; - mod->lastAffected = 0; + mod->lastAffected = NULL; mod->mask = 0x4000000000000LL; mod->charges = 0; Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 5266) +++ src/game/SpellEffects.cpp (working copy) @@ -625,7 +625,7 @@ mod->type = SPELLMOD_PCT; mod->spellId = 0; mod->effectId = 0; - mod->lastAffected = 0; + mod->lastAffected = NULL; mod->mask = 0x20800000000LL; mod->charges = 0; @@ -716,7 +716,7 @@ float cost = m_currentBasePoints[0]+1; if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this); uint32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE); Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5266) +++ src/game/Unit.cpp (working copy) @@ -3359,6 +3359,14 @@ } } +Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const +{ + for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) + if(m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id==spell_id) + return m_currentSpells[i]; + return NULL; +} + bool Unit::isInFront(Unit const* target, float radius) const { return IsWithinDistInMap(target, radius) && HasInArc( M_PI, target ); @@ -5045,7 +5053,7 @@ mod->type = SPELLMOD_PCT; mod->spellId = 0; mod->effectId = 0; - mod->lastAffected = 0; + mod->lastAffected = NULL; mod->mask = 0x0000000000000003LL; mod->charges = 0; ((Player*)this)->AddSpellMod(mod, true); Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 5266) +++ src/game/Unit.h (working copy) @@ -857,7 +857,10 @@ // delayed+channeled spells are always interrupted void InterruptNonMeleeSpells(bool withDelayed); + Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; + Spell* m_currentSpells[CURRENT_MAX_SPELL]; + uint32 m_addDmgOnce; uint64 m_TotemSlot[4]; uint64 m_ObjectSlot[4];