Public feed #891102

Dispel Spellsteal

public diff v1 · immutable
Raw Edit
·published 2008-02-04 10:52 UTC
rendered paste body
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<uint32> removeId;      if(apply)     {@@ -2746,6 +2747,7 @@                 if( ((1<<spell->Mechanic) & mechanic) || ((1<<spell->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<uint32> 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<uint32> 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);