Index: src/game/SharedDefines.h =================================================================== --- src/game/SharedDefines.h (revision 5143) +++ src/game/SharedDefines.h (working copy) @@ -359,7 +359,7 @@ SPELL_EFFECT_123 = 123, SPELL_EFFECT_PLAYER_PULL = 124, SPELL_EFFECT_REDUCE_THREAT_PERCENT = 125, - SPELL_EFFECT_STEAL_BENEFICIAL_BUFF = 126, + SPELL_EFFECT_SPELL_STEAL = 126, SPELL_EFFECT_PROSPECTING = 127, SPELL_EFFECT_APPLY_AURA_NEW2 = 128, SPELL_EFFECT_129 = 129, Index: src/game/Spell.cpp =================================================================== --- src/game/Spell.cpp (revision 5143) +++ src/game/Spell.cpp (working copy) @@ -3108,6 +3108,27 @@ } } + // DISPEL - returns Nothing to dispel if no aura targets + bool noDispel[3]; + noDispel[0] = false; noDispel[1] = false; noDispel[2] = false; + for(int j = 0; j < 3; j++) + { + if(m_spellInfo->Effect[j] == SPELL_EFFECT_DISPEL && m_targets.getUnitTarget()) + { + if(m_targets.getUnitTarget()->DispelAura(m_spellInfo->Id, j, m_caster, false, false, false) == 0) + noDispel[j] = true; + } + } + if(noDispel[0] && noDispel[1] && noDispel[2]) + return SPELL_FAILED_NOTHING_TO_DISPEL; + + // SPELL STEAL - returns Nothing to steal if no aura targets + if(m_spellInfo->Effect[0] == SPELL_EFFECT_SPELL_STEAL && m_targets.getUnitTarget()) + { + if(m_targets.getUnitTarget()->DispelAura(m_spellInfo->Id, 0, m_caster, false, false, false) == 0) + return SPELL_FAILED_NOTHING_TO_STEAL; + } + for (int i = 0; i < 3; i++) { switch(m_spellInfo->EffectApplyAuraName[i]) Index: src/game/Spell.h =================================================================== --- src/game/Spell.h (revision 5143) +++ src/game/Spell.h (working copy) @@ -458,7 +458,7 @@ void EffectSkinPlayerCorpse(uint32 i); void EffectApplyPetAura(uint32 i); void EffectSummonDemon(uint32 i); - void EffectStealBeneficialBuff(uint32 i); + void EffectSpellSteal(uint32 i); void EffectUnlearnSpecialization(uint32 i); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 5143) +++ src/game/SpellAuras.cpp (working copy) @@ -2729,6 +2729,7 @@ //immune movement impairement and loss of control if(GetId()==42292) mechanic=0x9967da6; + std::vector removeId; if(apply) { @@ -2746,6 +2747,7 @@ if( ((1<Mechanic) & mechanic) || ((1<EffectMechanic[iter->second->GetEffIndex()]) & mechanic)) { m_target->RemoveAurasDueToSpell(spell->Id); + removeId.push_back(spell->Id); if(Auras.empty()) break; else @@ -2753,6 +2755,26 @@ } } } + + if(m_target->GetTypeId() == TYPEID_PLAYER && removeId.size()) + { + // Struct for immunities SMSG_SPELLDISPELLOG always that type + WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+2+4+12*removeId.size()); + data.append(m_target->GetPackGUID()); + data << uint8(0x0); + data << uint32(0x0); + data << uint8(0x1); + data << uint32(removeId.size()); + + for(uint32 j = 0; j < removeId.size(); j++) + { + data << uint32(removeId[j]); + data << uint32(0x0); + data << uint32(0x64); + } + + ((Player*)m_target)->GetSession()->SendPacket(&data); + } } m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply); @@ -2827,6 +2849,7 @@ if(IsPositiveSpell(GetId())) //Only positive immunity removes auras { uint32 school_mask = m_modifier.m_miscvalue; + std::vector auras2remove; Unit::AuraMap& Auras = m_target->GetAuras(); for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) { @@ -2838,6 +2861,7 @@ && !iter->second->IsPositive() //Don't remove positive spells && spell->Id != GetId()) //Don't remove self { + auras2remove.push_back(spell->Id); m_target->RemoveAurasDueToSpell(spell->Id); if(Auras.empty()) break; @@ -2845,6 +2869,26 @@ next = Auras.begin(); } } + + if(m_target->GetTypeId() == TYPEID_PLAYER && auras2remove.size()) + { + // Struct for immunities SMSG_SPELLDISPELLOG always that type + WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+2+4+12*auras2remove.size()); + data.append(m_target->GetPackGUID()); + data << uint8(0x0); + data << uint32(0x0); + data << uint8(0x1); + data << uint32(auras2remove.size()); + + for(uint32 j = 0; j < auras2remove.size(); j++) + { + data << uint32(auras2remove[j]); + data << uint32(0x0); + data << uint32(0x64); + } + + ((Player*)m_target)->GetSession()->SendPacket(&data); + } } } } Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 5143) +++ src/game/SpellEffects.cpp (working copy) @@ -184,7 +184,7 @@ &Spell::EffectNULL, //123 SPELL_EFFECT_123 taxi/flight related &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster) &Spell::EffectReduceThreatPercent, //125 SPELL_EFFECT_REDUCE_THREAT_PERCENT - &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect? + &Spell::EffectSpellSteal, //126 SPELL_EFFECT_126 spell steal effect? &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell &Spell::EffectApplyAura, //128 SPELL_EFFECT_APPLY_AURA_NEW2 probably apply aura again &Spell::EffectNULL, //129 SPELL_EFFECT_129 probably apply aura again @@ -2335,15 +2335,66 @@ { if(!unitTarget) return; - + std::vector removeId; for(int n = 0 ; n < damage; ++n) - if(unitTarget->RemoveFirstAuraByDispel(m_spellInfo->EffectMiscValue[i], m_caster)) + { + uint32 dispelled_id =unitTarget->DispelAura(m_spellInfo->Id, i, m_caster, true, true, false); + if(dispelled_id) + { + removeId.push_back(dispelled_id); sLog.outDebug("Spell: Removed aura type %u from %s %u (removed by %s %u)", m_spellInfo->EffectMiscValue[i], unitTarget->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", unitTarget->GetGUIDLow(), m_caster->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", m_caster->GetGUIDLow() ); + } + } + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+2+4+4*removeId.size()); + data.append(unitTarget->GetPackGUID()); + if(m_CastItem && unitTarget == m_caster) + { + data << uint8(0x0); + data << uint32(0x0); + } + else + { + data.append(m_caster->GetPackGUID()); + data << uint32(m_spellInfo->Id); + } + data << uint8(0x0); + data << uint32(removeId.size()); + for(uint32 j = 0; j < removeId.size(); j++) + data << uint32(removeId[j]); + ((Player*)unitTarget)->GetSession()->SendPacket(&data); } +void Spell::EffectSpellSteal(uint32 i) +{ + if(!unitTarget || !unitTarget->isAlive()) + return; + + uint32 resultId; + for(int j = 0; j <= m_spellInfo->EffectBasePoints[i]; j++) + resultId = unitTarget->DispelAura(m_spellInfo->Id, i, m_caster, true, true, true); + + if(!resultId || m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + // Packet should sends only to players + if(unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+2+4+4); + data.append(unitTarget->GetPackGUID()); + data.append(m_caster->GetPackGUID()); + data << uint32(m_spellInfo->Id); + data << uint8(0x0); + data << uint32(0x1); + data << uint32(resultId); + ((Player*)unitTarget)->GetSession()->SendPacket(&data); +} + void Spell::EffectDualWield(uint32 /*i*/) { if (unitTarget->GetTypeId() == TYPEID_PLAYER) @@ -4574,89 +4625,3 @@ ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster ); } -void Spell::EffectStealBeneficialBuff(uint32 /*i*/) -{ - sLog.outDebug("Effect: StealBeneficialBuff"); - - // get the auras of the target - Unit::AuraMap& Auras = unitTarget->GetAuras(); - - // count possible for steal auras - uint32 count = 0; - for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) - { - if( iter->second->IsPositive() && //only steel positive spell - !iter->second->IsPassive() && //don't steal passive abilities - !iter->second->IsPersistent() && //don't steal persistent auras - iter->second->GetSpellProto()->Dispel == m_spellInfo->Dispel ) - //only steal magic effects - ++count; - } - - // not found any? - if(!count) - return; - - // random buff to steal - uint32 remove_prev_positive = urand(0, count-1); - - // id of the spell we'll steal - uint32 spellId = 0; - - // select aura by index - count = 0; - for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) - { - if( iter->second->IsPositive() && //only steel positive spell - !iter->second->IsPassive() && //don't steal passive abilities - !iter->second->IsPersistent() && //don't steal persistent auras - iter->second->GetSpellProto()->Dispel == m_spellInfo->Dispel ) - //only steal magic effects - { - if(count==remove_prev_positive) - { - spellId = iter->first.first; // store the id of the last stealable spell - break; - } - - ++count; - } - } - - // we found a stealable buff - if(spellId) - { - // max duration 2 minutes (in msecs) - const int32 max_dur = 2*MINUTE*1000; - - // go through all the effects of the spell - for(int i=0; i<3; ++i) - { - // get the corresponding aura from the victim - Aura * aur = unitTarget->GetAura(spellId, i); - - if(!aur) - continue; - - // we have to check against the (remaining) duration on the victim - int32 dur = aur->GetAuraDuration(); - int32 basePoints = aur->GetBasePoints(); - - // construct the new aura for the attacker - Aura * new_aur = new Aura(aur->GetSpellProto(), i, &basePoints, m_caster); - - if(!new_aur) - continue; - - // set its duration and maximum duration - new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur ); - new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur ); - - // add the new aura - m_caster->AddAura(new_aur); - } - - // remove the auras caused by the stolen spell from the victim - unitTarget->RemoveAurasDueToSpell(spellId); - } -} Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5143) +++ src/game/Unit.cpp (working copy) @@ -3540,39 +3540,116 @@ return true; } -bool Unit::RemoveFirstAuraByDispel(uint32 dispel_type, Unit *pCaster) +uint32 Unit::DispelAura(uint32 dispel_id, int32 effIndex, Unit *pCaster, bool removeAura, bool checkResist, bool steal) { - AuraMap::iterator i; - for (i = m_Auras.begin(); i != m_Auras.end();) - { - if ((*i).second && (*i).second->GetSpellProto()->Dispel == dispel_type) - { - SpellEntry const* spellInfo = (*i).second->GetSpellProto(); - uint32 eff = (*i).second->GetEffIndex(); - - if(dispel_type == 1) - { - bool positive = true; - - if(!IsPositiveTarget(spellInfo->EffectImplicitTargetA[eff],spellInfo->EffectImplicitTargetB[eff])) - positive = false; - else - positive = (spellInfo->AttributesEx & (1<<7))==0; - - if(positive && IsFriendlyTo(pCaster)) // PBW - { - ++i; - continue; - } - } - RemoveAura(i); - return true; - } - else - ++i; - } - - return false; + // Steal can only be enabled while RemoveAura is also true + if(steal) + ASSERT(removeAura); + + SpellEntry const *dispelProto = sSpellStore.LookupEntry(dispel_id); + if(!dispelProto) return 0; + + uint32 dispel_type = dispelProto->EffectMiscValue[effIndex]; + uint32 removeId = 0; + AuraMap::iterator i; + for (i = m_Auras.begin(); i != m_Auras.end();) + { + if ((*i).second && (*i).second->GetSpellProto()->Dispel == dispel_type) + { + if(dispel_type == 1) + { + bool positive = true; + switch((*i).second->GetSpellProto()->EffectImplicitTargetA[(*i).second->GetEffIndex()]) + { + case TARGET_CHAIN_DAMAGE: + case TARGET_ALL_ENEMY_IN_AREA: + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + case TARGET_ALL_AROUND_CASTER: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_DUELVSPLAYER: + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_CURRENT_SELECTED_ENEMY: + positive = false; + break; + default: + positive = ((*i).second->GetSpellProto()->AttributesEx & (1<<7)) ? false : true; + } + if(positive == IsFriendlyTo(pCaster)) + { + ++i; + continue; + } + } + removeId = (*i).second->GetSpellProto()->Id; + SpellEntry const *spellProto = (*i).second->GetSpellProto(); + // Resists check + if((*i).second->GetCasterGUID() && checkResist) + { + // Dispel resist handling + int32 Chance = 0; // Base chance + Unit *auraCaster = (*i).second->GetCaster(); + if(auraCaster && pCaster->GetTypeId() == TYPEID_PLAYER) + { + if(auraCaster->GetTypeId() == TYPEID_PLAYER) + ((Player*)auraCaster)->ApplySpellMod(removeId, SPELLMOD_RESIST_DISPEL_CHANCE, Chance); + Chance = Chance - spellProto->spellLevel + dispelProto->spellLevel; + if(Chance < 0 ) Chance = 0; + if(urand(1,100) <= Chance) + { + // Resist + WorldPacket data(SMSG_DISPEL_FAILED, 8+4+8+4+4+4); + data.append(pCaster->GetPackGUID()); + data << uint32(0x0); + data.append(this->GetPackGUID()); + data << uint32(0x0); + data << uint32(dispel_id); + data << uint32(spellProto->Id); + ((Player*)pCaster)->GetSession()->SendPacket(&data); + return 0; + } + } + } + // Remove + if(removeAura) + { + // Stealing buffs + if(steal && pCaster) + { + int32 effect0 = 0; + int32 effect1 = 0; + int32 effect2 = 0; + SpellEntry const *originalSpell = sSpellStore.LookupEntry(removeId); + // Add auras for the caster + for(int j = 0; j < 3; j++) + { + Aura *oldAur = GetAura(removeId, j); + if(oldAur) + { + int32 newBasePoints = oldAur->GetModifier()->m_amount-1; + Aura* Aur = new Aura(originalSpell, j, &newBasePoints, pCaster, pCaster, NULL); + if(Aur->GetAuraDuration() > 120000) + Aur->SetAuraDuration(120000); + bool added = pCaster->AddAura(Aur); + if(!added) + sLog.outError("Error in Spell Steal - aura cannot be added!"); + } + } + } + // Unstable Affliction + if(spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && spellProto->SpellIconID == 2039 && + spellProto->EffectApplyAuraName[0] == SPELL_AURA_PERIODIC_DAMAGE) + { + int32 damagePoints = int32((*i).second->GetBasePoints() * 9); + CastCustomSpell(this, 31117, &damagePoints, 0, 0, true); + } + RemoveAurasDueToSpell(removeId); + } + break; + } + else + ++i; + } + return removeId; } void Unit::RemoveAreaAurasByOthers(uint64 guid) Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 5143) +++ src/game/Unit.h (working copy) @@ -807,7 +807,7 @@ bool AddAura(Aura *aur); - bool RemoveFirstAuraByDispel(uint32 dispel_type, Unit *pCaster); + uint32 DispelAura(uint32 dispel_id, int32 effIndex, Unit *pCaster, bool removeAura, bool checkResist, bool steal); void RemoveAura(AuraMap::iterator &i, bool onDeath = false); void RemoveAura(uint32 spellId, uint32 effindex); void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex);