[9691] Up to date mangos_spell_check old data and add some new.
[getmangos.git] / src / game / SpellEffects.cpp
blobce3ab384cc34e14d8da96d748e847cdf239eb345
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused from pre-1.2.1
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvironmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectBind, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectUnused, // 12 SPELL_EFFECT_PORTAL unused from pre-1.2.1, exist 2 spell, but not exist any data about its real usage
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused from pre-1.2.1
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused from pre-1.2.1
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused from pre-1.2.1
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectEmpty, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectEmpty, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectEmpty, // 25 SPELL_EFFECT_WEAPON spell per weapon type, in ItemSubclassmask store mask that can be used for usability check at equip, but current way using skill also work.
86 &Spell::EffectEmpty, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectLeapForward, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectEmpty, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectEmpty, // 39 SPELL_EFFECT_LANGUAGE misc store lang id
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectJump, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN spawn/login animation, expected by spawn unit cast, also base points store some dynflags
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused from pre-1.2.1
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT unused from pre-1.2.1
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectCreateRandomItem, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectRestoreItemCharges, // 66 SPELL_EFFECT_RESTORE_ITEM_CHARGES itemtype - is affected item ID
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectNULL, // 73 SPELL_EFFECT_UNTRAIN_TALENTS one spell: Trainer: Untrain Talents
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectNULL, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
148 &Spell::EffectNULL, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
149 &Spell::EffectNULL, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
150 &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_93 (old SPELL_EFFECT_SUMMON_PHANTASM)
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectSummonAllTotems, // 97 SPELL_EFFECT_SUMMON_ALL_TOTEMS
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112 (old SPELL_EFFECT_SUMMON_DEMON)
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectLeapBack, //138 SPELL_EFFECT_LEAP_BACK Leap back
199 &Spell::EffectNULL, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectNULL, //148 SPELL_EFFECT_148 single spell: Inflicts Fire damage to an enemy.
209 &Spell::EffectCharge2, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectNULL, //150 SPELL_EFFECT_150 2 spells in 3.3.2
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectTeachTaxiNode, //154 SPELL_EFFECT_TEACH_TAXI_NODE single spell: Teach River's Heart Taxi Path
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL, //160 SPELL_EFFECT_160 single spell: Nerub'ar Web Random Unit
221 &Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectEmpty(SpellEffectIndex /*eff_idx*/)
227 // NOT NEED ANY IMPLEMENTATION CODE, EFFECT POSISBLE USED AS MARKER OR CLIENT INFORM
230 void Spell::EffectNULL(SpellEffectIndex /*eff_idx*/)
232 sLog.outDebug("WORLD: Spell Effect DUMMY");
235 void Spell::EffectUnused(SpellEffectIndex /*eff_idx*/)
237 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
240 void Spell::EffectResurrectNew(SpellEffectIndex eff_idx)
242 if(!unitTarget || unitTarget->isAlive())
243 return;
245 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
246 return;
248 if(!unitTarget->IsInWorld())
249 return;
251 Player* pTarget = ((Player*)unitTarget);
253 if(pTarget->isRessurectRequested()) // already have one active request
254 return;
256 uint32 health = damage;
257 uint32 mana = m_spellInfo->EffectMiscValue[eff_idx];
258 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
259 SendResurrectRequest(pTarget);
262 void Spell::EffectInstaKill(SpellEffectIndex /*eff_idx*/)
264 if( !unitTarget || !unitTarget->isAlive() )
265 return;
267 // Demonic Sacrifice
268 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
270 uint32 entry = unitTarget->GetEntry();
271 uint32 spellID;
272 switch(entry)
274 case 416: spellID=18789; break; //imp
275 case 417: spellID=18792; break; //fellhunter
276 case 1860: spellID=18790; break; //void
277 case 1863: spellID=18791; break; //succubus
278 case 17252: spellID=35701; break; //fellguard
279 default:
280 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry);
281 return;
284 m_caster->CastSpell(m_caster, spellID, true);
287 if(m_caster == unitTarget) // prevent interrupt message
288 finish();
290 m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
293 void Spell::EffectEnvironmentalDMG(SpellEffectIndex eff_idx)
295 uint32 absorb = 0;
296 uint32 resist = 0;
298 // Note: this hack with damage replace required until GO casting not implemented
299 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
300 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
301 damage = m_spellInfo->CalculateSimpleValue(eff_idx);
303 m_caster->CalcAbsorbResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
305 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
306 if(m_caster->GetTypeId() == TYPEID_PLAYER)
307 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage);
310 void Spell::EffectSchoolDMG(SpellEffectIndex effect_idx)
312 if( unitTarget && unitTarget->isAlive())
314 switch(m_spellInfo->SpellFamilyName)
316 case SPELLFAMILY_GENERIC:
318 switch(m_spellInfo->Id) // better way to check unknown
320 // Meteor like spells (divided damage to targets)
321 case 24340: case 26558: case 28884: // Meteor
322 case 36837: case 38903: case 41276: // Meteor
323 case 26789: // Shard of the Fallen Star
324 case 31436: // Malevolent Cleave
325 case 35181: // Dive Bomb
326 case 40810: case 43267: case 43268: // Saber Lash
327 case 42384: // Brutal Swipe
328 case 45150: // Meteor Slash
329 case 64422: case 64688: // Sonic Screech
330 case 70492: case 72505: // Ooze Eruption
331 case 71904: // Chaos Bane
332 case 72624: case 72625: // Ooze Eruption
334 uint32 count = 0;
335 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
336 if(ihit->effectMask & (1<<effect_idx))
337 ++count;
339 damage /= count; // divide to all targets
340 break;
342 // percent from health with min
343 case 25599: // Thundercrash
345 damage = unitTarget->GetHealth() / 2;
346 if(damage < 200)
347 damage = 200;
348 break;
350 // Intercept (warrior spell trigger)
351 case 20253:
352 case 61491:
354 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
355 break;
357 // percent max target health
358 case 29142: // Eyesore Blaster
359 case 35139: // Throw Boom's Doom
360 case 49882: // Leviroth Self-Impale
362 damage = damage * unitTarget->GetMaxHealth() / 100;
363 break;
365 // Cataclysmic Bolt
366 case 38441:
368 damage = unitTarget->GetMaxHealth() / 2;
369 break;
371 // Tympanic Tantrum
372 case 62775:
374 damage = unitTarget->GetMaxHealth() / 10;
375 break;
377 // Hand of Rekoning (name not have typos ;) )
378 case 67485:
379 damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
380 break;
382 break;
384 case SPELLFAMILY_MAGE:
385 // remove Arcane Blast buffs at any non-Arcane Blast arcane damage spell.
386 // NOTE: it removed at hit instead cast because currently spell done-damage calculated at hit instead cast
387 if ((m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_ARCANE) && !(m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000)))
388 m_caster->RemoveAurasDueToSpell(36032); // Arcane Blast buff
389 break;
390 case SPELLFAMILY_WARRIOR:
392 // Bloodthirst
393 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
395 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
397 // Shield Slam
398 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
399 damage += int32(m_caster->GetShieldBlockValue());
400 // Victory Rush
401 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
403 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
404 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
406 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
407 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
408 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
409 // Heroic Throw ${$m1+$AP*.50}
410 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
411 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
412 // Shattering Throw ${$m1+$AP*.50}
413 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0040000000000000))
414 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
415 // Shockwave ${$m3/100*$AP}
416 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
418 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, EFFECT_INDEX_2, m_spellInfo->EffectBasePoints[EFFECT_INDEX_2], unitTarget);
419 if (pct > 0)
420 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
421 break;
423 // Thunder Clap
424 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000080))
426 damage+=int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
428 break;
430 case SPELLFAMILY_WARLOCK:
432 // Incinerate Rank 1 & 2
433 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
435 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
436 // Check aura state for speed but aura state set not only for Immolate spell
437 if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
439 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
440 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
442 // Immolate
443 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
444 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
446 damage += damage/4;
447 break;
452 // Shadowflame
453 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
455 // Apply DOT part
456 switch(m_spellInfo->Id)
458 case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
459 case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
460 default:
461 sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
462 break;
465 // Conflagrate - consumes Immolate or Shadowflame
466 else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
468 Aura const* aura = NULL; // found req. aura for damage calculation
470 Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
471 for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
473 // for caster applied auras only
474 if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
475 (*i)->GetCasterGUID()!=m_caster->GetGUID())
476 continue;
478 // Immolate
479 if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
481 aura = *i; // it selected always if exist
482 break;
485 // Shadowflame
486 if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
487 aura = *i; // remember but wait possible Immolate as primary priority
490 // found Immolate or Shadowflame
491 if (aura)
493 // DoT not have applied spell bonuses in m_amount
494 int32 damagetick = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), aura->GetModifier()->m_amount, DOT);
495 damage += damagetick * 4;
497 // Glyph of Conflagrate
498 if (!m_caster->HasAura(56235))
499 unitTarget->RemoveAurasByCasterSpell(aura->GetId(), m_caster->GetGUID());
500 break;
503 break;
505 case SPELLFAMILY_PRIEST:
507 // Shadow Word: Death - deals damage equal to damage done to caster
508 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000))
509 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
510 // Improved Mind Blast (Mind Blast in shadow form bonus)
511 else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000)))
513 Unit::AuraList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
514 for(Unit::AuraList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
516 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST &&
517 ((*i)->GetSpellProto()->SpellIconID == 95))
519 int chance = (*i)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1);
520 if (roll_chance_i(chance))
521 // Mind Trauma
522 m_caster->CastSpell(unitTarget, 48301, true);
523 break;
527 break;
529 case SPELLFAMILY_DRUID:
531 // Ferocious Bite
532 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
534 // converts up to 30 points of energy into ($f1+$AP/410) additional damage
535 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
536 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
537 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
538 uint32 energy = m_caster->GetPower(POWER_ENERGY);
539 uint32 used_energy = energy > 30 ? 30 : energy;
540 damage += int32(used_energy * multiple);
541 m_caster->SetPower(POWER_ENERGY,energy-used_energy);
543 // Rake
544 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[EFFECT_INDEX_2] == SPELL_EFFECT_ADD_COMBO_POINTS)
546 // $AP*0.01 bonus
547 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
549 // Swipe
550 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
552 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
554 break;
556 case SPELLFAMILY_ROGUE:
558 // Envenom
559 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)))
561 // consume from stack dozes not more that have combo-points
562 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
564 Aura *poison = 0;
565 // Lookup for Deadly poison (only attacker applied)
566 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
567 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
568 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
569 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x10000)) &&
570 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
572 poison = *itr;
573 break;
575 // count consumed deadly poison doses at target
576 if (poison)
578 bool needConsume = true;
579 uint32 spellId = poison->GetId();
580 uint32 doses = poison->GetStackAmount();
581 if (doses > combo)
582 doses = combo;
584 // Master Poisoner
585 Unit::AuraList const& auraList = ((Player*)m_caster)->GetAurasByType(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL);
586 for(Unit::AuraList::const_iterator iter = auraList.begin(); iter!=auraList.end(); ++iter)
588 if ((*iter)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellProto()->SpellIconID == 1960)
590 if (int32 chance = (*iter)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2))
591 if (roll_chance_i(chance))
592 needConsume = false;
594 break;
598 if(needConsume)
599 for (uint32 i = 0; i < doses; ++i)
600 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
602 damage *= doses;
603 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
605 // Eviscerate and Envenom Bonus Damage (item set effect)
606 if(m_caster->GetDummyAura(37169))
607 damage += ((Player*)m_caster)->GetComboPoints()*40;
610 // Eviscerate
611 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
613 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
615 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
616 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
618 // Eviscerate and Envenom Bonus Damage (item set effect)
619 if(m_caster->GetDummyAura(37169))
620 damage += combo*40;
623 // Gouge
624 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
626 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
628 // Instant Poison
629 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
631 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
633 // Wound Poison
634 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
636 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
638 break;
640 case SPELLFAMILY_HUNTER:
642 //Gore
643 if (m_spellInfo->SpellIconID == 1578)
645 if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
646 damage *= 2;
648 // Mongoose Bite
649 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
651 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
653 // Counterattack
654 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
656 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
658 // Arcane Shot
659 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
661 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
663 // Steady Shot
664 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
666 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
667 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
669 // Explosive Trap Effect
670 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
672 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
674 break;
676 case SPELLFAMILY_PALADIN:
678 // Judgement of Righteousness - receive benefit from Spell Damage and Attack power
679 if (m_spellInfo->Id == 20187)
681 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
682 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
683 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
684 damage += int32(ap * 0.2f) + int32(holy * 32 / 100);
686 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
687 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
689 uint32 debuf_id;
690 switch(m_spellInfo->Id)
692 case 53733: debuf_id = 53742; break;// Judgement of Corruption -> Blood Corruption
693 case 31804: debuf_id = 31803; break;// Judgement of Vengeance -> Holy Vengeance
694 default: return;
697 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
698 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
699 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
700 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
701 // Get stack of Holy Vengeance on the target added by caster
702 uint32 stacks = 0;
703 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
704 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
706 if( ((*itr)->GetId() == debuf_id) && (*itr)->GetCasterGUID()==m_caster->GetGUID())
708 stacks = (*itr)->GetStackAmount();
709 break;
712 // + 10% for each application of Holy Vengeance on the target
713 if(stacks)
714 damage += damage * stacks * 10 /100;
716 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
717 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
719 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
720 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
721 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
722 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
724 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
725 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
727 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
728 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
729 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
730 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
732 // Hammer of the Righteous
733 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
735 // Add main hand dps * effect[2] amount
736 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
737 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, EFFECT_INDEX_2, m_spellInfo->EffectBasePoints[EFFECT_INDEX_2], unitTarget);
738 damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
740 // Shield of Righteousness
741 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
743 damage+=int32(m_caster->GetShieldBlockValue());
745 // Judgement
746 else if (m_spellInfo->Id == 54158)
748 // [1 + 0.25 * SPH + 0.16 * AP]
749 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.16f);
751 break;
755 if(damage >= 0)
756 m_damage += damage;
760 void Spell::EffectDummy(SpellEffectIndex eff_idx)
762 if (!unitTarget && !gameObjTarget && !itemTarget)
763 return;
765 // selection by spell family
766 switch(m_spellInfo->SpellFamilyName)
768 case SPELLFAMILY_GENERIC:
770 switch(m_spellInfo->Id)
772 case 8063: // Deviate Fish
774 if (m_caster->GetTypeId() != TYPEID_PLAYER)
775 return;
777 uint32 spell_id = 0;
778 switch(urand(1,5))
780 case 1: spell_id = 8064; break; // Sleepy
781 case 2: spell_id = 8065; break; // Invigorate
782 case 3: spell_id = 8066; break; // Shrink
783 case 4: spell_id = 8067; break; // Party Time!
784 case 5: spell_id = 8068; break; // Healthy Spirit
786 m_caster->CastSpell(m_caster, spell_id, true, NULL);
787 return;
789 case 8213: // Savory Deviate Delight
791 if (m_caster->GetTypeId() != TYPEID_PLAYER)
792 return;
794 uint32 spell_id = 0;
795 switch(urand(1,2))
797 // Flip Out - ninja
798 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
799 // Yaaarrrr - pirate
800 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
803 m_caster->CastSpell(m_caster,spell_id,true,NULL);
804 return;
806 case 8593: // Symbol of life (restore creature to life)
807 case 31225: // Shimmering Vessel (restore creature to life)
809 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
810 return;
812 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
813 return;
815 case 13120: // net-o-matic
817 if (!unitTarget)
818 return;
820 uint32 spell_id = 0;
822 uint32 roll = urand(0, 99);
824 if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
825 spell_id = 16566;
826 else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
827 spell_id = 13119;
828 else // normal root
829 spell_id = 13099;
831 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
832 return;
834 case 13567: // Dummy Trigger
836 // can be used for different aura triggering, so select by aura
837 if (!m_triggeredByAuraSpell || !unitTarget)
838 return;
840 switch(m_triggeredByAuraSpell->Id)
842 case 26467: // Persistent Shield
843 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
844 break;
845 default:
846 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
847 break;
849 return;
851 case 15998: // Capture Worg Pup
852 case 29435: // Capture Female Kaliri Hatchling
854 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
855 return;
857 Creature* creatureTarget = (Creature*)unitTarget;
859 creatureTarget->ForcedDespawn();
860 return;
862 case 16589: // Noggenfogger Elixir
864 if (m_caster->GetTypeId() != TYPEID_PLAYER)
865 return;
867 uint32 spell_id = 0;
868 switch(urand(1, 3))
870 case 1: spell_id = 16595; break;
871 case 2: spell_id = 16593; break;
872 default:spell_id = 16591; break;
875 m_caster->CastSpell(m_caster, spell_id, true, NULL);
876 return;
878 case 17251: // Spirit Healer Res
880 if (!unitTarget)
881 return;
883 Unit* caster = GetAffectiveCaster();
885 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
887 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
888 data << uint64(unitTarget->GetGUID());
889 ((Player*)caster)->GetSession()->SendPacket( &data );
891 return;
893 case 17271: // Test Fetid Skull
895 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
896 return;
898 uint32 spell_id = roll_chance_i(50)
899 ? 17269 // Create Resonating Skull
900 : 17270; // Create Bone Dust
902 m_caster->CastSpell(m_caster, spell_id, true, NULL);
903 return;
905 case 20577: // Cannibalize
907 if (unitTarget)
908 m_caster->CastSpell(m_caster, 20578, false, NULL);
910 return;
912 case 23019: // Crystal Prison Dummy DND
914 if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
915 return;
917 Creature* creatureTarget = (Creature*)unitTarget;
918 if (creatureTarget->isPet())
919 return;
921 GameObject* pGameObj = new GameObject;
923 Map *map = creatureTarget->GetMap();
925 // create before death for get proper coordinates
926 if (!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
927 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
928 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
930 delete pGameObj;
931 return;
934 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
935 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
936 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
937 pGameObj->SetSpellId(m_spellInfo->Id);
939 creatureTarget->ForcedDespawn();
941 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
942 map->Add(pGameObj);
944 return;
946 case 23074: // Arcanite Dragonling
948 if (!m_CastItem)
949 return;
951 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
952 return;
954 case 23075: // Mithril Mechanical Dragonling
956 if (!m_CastItem)
957 return;
959 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
960 return;
962 case 23076: // Mechanical Dragonling
964 if (!m_CastItem)
965 return;
967 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
968 return;
970 case 23133: // Gnomish Battle Chicken
972 if (!m_CastItem)
973 return;
975 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
976 return;
978 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
980 int32 r = irand(0, 119);
981 if (r < 20) // Transporter Malfunction - 1/6 polymorph
982 m_caster->CastSpell(m_caster, 23444, true);
983 else if (r < 100) // Evil Twin - 4/6 evil twin
984 m_caster->CastSpell(m_caster, 23445, true);
985 else // Transporter Malfunction - 1/6 miss the target
986 m_caster->CastSpell(m_caster, 36902, true);
988 return;
990 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
992 if (roll_chance_i(50)) // Gadgetzan Transporter - success
993 m_caster->CastSpell(m_caster, 23441, true);
994 else // Gadgetzan Transporter Failure - failure
995 m_caster->CastSpell(m_caster, 23446, true);
997 return;
999 case 23645: // Hourglass Sand
1000 m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
1001 return;
1002 case 23725: // Gift of Life (warrior bwl trinket)
1003 m_caster->CastSpell(m_caster, 23782, true);
1004 m_caster->CastSpell(m_caster, 23783, true);
1005 return;
1006 case 25860: // Reindeer Transformation
1008 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1009 return;
1011 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
1012 float speed = m_caster->GetSpeedRate(MOVE_RUN);
1014 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1016 //5 different spells used depending on mounted speed and if mount can fly or not
1017 if (flyspeed >= 4.1f)
1018 // Flying Reindeer
1019 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
1020 else if (flyspeed >= 3.8f)
1021 // Flying Reindeer
1022 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
1023 else if (flyspeed >= 1.6f)
1024 // Flying Reindeer
1025 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
1026 else if (speed >= 2.0f)
1027 // Reindeer
1028 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
1029 else
1030 // Reindeer
1031 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
1033 return;
1035 case 26074: // Holiday Cheer
1036 // implemented at client side
1037 return;
1038 case 28006: // Arcane Cloaking
1040 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
1041 // Naxxramas Entry Flag Effect DND
1042 m_caster->CastSpell(unitTarget, 29294, true);
1044 return;
1046 case 29200: // Purify Helboar Meat
1048 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1049 return;
1051 uint32 spell_id = roll_chance_i(50)
1052 ? 29277 // Summon Purified Helboar Meat
1053 : 29278; // Summon Toxic Helboar Meat
1055 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1056 return;
1058 case 29858: // Soulshatter
1060 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
1061 m_caster->CastSpell(unitTarget,32835,true);
1063 return;
1065 case 30458: // Nigh Invulnerability
1067 if (!m_CastItem)
1068 return;
1070 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1071 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1072 else // Complete Vulnerability - backfire in 14% casts
1073 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1075 return;
1077 case 30507: // Poultryizer
1079 if (!m_CastItem)
1080 return;
1082 if (roll_chance_i(80)) // Poultryized! - success
1083 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1084 else // Poultryized! - backfire 20%
1085 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1087 return;
1089 case 33060: // Make a Wish
1091 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1092 return;
1094 uint32 spell_id = 0;
1096 switch(urand(1,5))
1098 case 1: spell_id = 33053; break; // Mr Pinchy's Blessing
1099 case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy
1100 case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy
1101 case 4: spell_id = 33062; break; // Tiny Magical Crawdad
1102 case 5: spell_id = 33064; break; // Mr. Pinchy's Gift
1105 m_caster->CastSpell(m_caster, spell_id, true, NULL);
1106 return;
1108 case 35745: // Socrethar's Stone
1110 uint32 spell_id;
1111 switch(m_caster->GetAreaId())
1113 case 3900: spell_id = 35743; break; // Socrethar Portal
1114 case 3742: spell_id = 35744; break; // Socrethar Portal
1115 default: return;
1118 m_caster->CastSpell(m_caster, spell_id, true);
1119 return;
1121 case 37674: // Chaos Blast
1123 if (!unitTarget)
1124 return;
1126 int32 basepoints0 = 100;
1127 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1128 return;
1130 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1132 // selecting one from Bloodstained Fortune item
1133 uint32 newitemid;
1134 switch(urand(1, 20))
1136 case 1: newitemid = 32688; break;
1137 case 2: newitemid = 32689; break;
1138 case 3: newitemid = 32690; break;
1139 case 4: newitemid = 32691; break;
1140 case 5: newitemid = 32692; break;
1141 case 6: newitemid = 32693; break;
1142 case 7: newitemid = 32700; break;
1143 case 8: newitemid = 32701; break;
1144 case 9: newitemid = 32702; break;
1145 case 10: newitemid = 32703; break;
1146 case 11: newitemid = 32704; break;
1147 case 12: newitemid = 32705; break;
1148 case 13: newitemid = 32706; break;
1149 case 14: newitemid = 32707; break;
1150 case 15: newitemid = 32708; break;
1151 case 16: newitemid = 32709; break;
1152 case 17: newitemid = 32710; break;
1153 case 18: newitemid = 32711; break;
1154 case 19: newitemid = 32712; break;
1155 case 20: newitemid = 32713; break;
1156 default:
1157 return;
1160 DoCreateItem(eff_idx, newitemid);
1161 return;
1163 case 42287: // Salvage Wreckage
1165 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1166 return;
1168 if (roll_chance_i(66))
1169 m_caster->CastSpell(m_caster, 42289, true, m_CastItem);
1170 else
1171 m_caster->CastSpell(m_caster, 42288, true);
1173 return;
1175 case 43036: // Dismembering Corpse
1177 if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER)
1178 return;
1180 if (unitTarget->HasAura(43059, EFFECT_INDEX_0))
1181 return;
1183 unitTarget->CastSpell(m_caster, 43037, true);
1184 unitTarget->CastSpell(unitTarget, 43059, true);
1185 return;
1187 // Demon Broiled Surprise
1188 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1189 case 43723:
1191 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1192 return;
1194 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1195 return;
1198 case 43882: // Scourging Crystal Controller Dummy
1200 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1201 return;
1203 // see spell dummy 50133
1204 unitTarget->RemoveAurasDueToSpell(43874);
1205 return;
1207 case 44454: // Tasty Reef Fish
1209 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1210 return;
1212 m_caster->CastSpell(unitTarget, 44455, true, m_CastItem);
1213 return;
1215 case 44875: // Complete Raptor Capture
1217 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1218 return;
1220 Creature* creatureTarget = (Creature*)unitTarget;
1222 creatureTarget->ForcedDespawn();
1224 //cast spell Raptor Capture Credit
1225 m_caster->CastSpell(m_caster, 42337, true, NULL);
1226 return;
1228 case 44997: // Converting Sentry
1230 //Converted Sentry Credit
1231 m_caster->CastSpell(m_caster, 45009, true);
1232 return;
1234 case 45030: // Impale Emissary
1236 // Emissary of Hate Credit
1237 m_caster->CastSpell(m_caster, 45088, true);
1238 return;
1240 case 45980: // Re-Cursive Transmatter Injection
1242 if (m_caster->GetTypeId() == TYPEID_PLAYER && unitTarget)
1244 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(46022))
1246 m_caster->CastSpell(unitTarget, pSpell, true);
1247 ((Player*)m_caster)->KilledMonsterCredit(pSpell->EffectMiscValue[EFFECT_INDEX_0], 0);
1250 if (unitTarget->GetTypeId() == TYPEID_UNIT)
1251 ((Creature*)unitTarget)->ForcedDespawn();
1254 return;
1256 case 45685: // Magnataur On Death 2
1258 m_caster->RemoveAurasDueToSpell(45673);
1259 m_caster->RemoveAurasDueToSpell(45672);
1260 m_caster->RemoveAurasDueToSpell(45677);
1261 m_caster->RemoveAurasDueToSpell(45681);
1262 m_caster->RemoveAurasDueToSpell(45683);
1263 return;
1265 case 45990: // Collect Oil
1267 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1268 return;
1270 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(45991))
1272 unitTarget->CastSpell(unitTarget, pSpell, true);
1273 ((Creature*)unitTarget)->ForcedDespawn(GetSpellDuration(pSpell) + 1);
1276 return;
1278 case 46167: // Planning for the Future: Create Snowfall Glade Pup Cover
1279 case 50926: // Gluttonous Lurkers: Create Zul'Drak Rat Cover
1280 case 51026: // Create Drakkari Medallion Cover
1281 case 51592: // Pickup Primordial Hatchling
1282 case 51961: // Captured Chicken Cover
1283 case 55364: // Create Ghoul Drool Cover
1285 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
1286 return;
1288 uint32 spellId = 0;
1290 switch(m_spellInfo->Id)
1292 case 46167: spellId = 46773; break;
1293 case 50926: spellId = 50927; break;
1294 case 51026: spellId = 50737; break;
1295 case 51592: spellId = 51593; break;
1296 case 51961: spellId = 51037; break;
1297 case 55364: spellId = 55363; break;
1300 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(spellId))
1302 unitTarget->CastSpell(m_caster, spellId, true);
1304 Creature* creatureTarget = (Creature*)unitTarget;
1306 if (const SpellCastTimesEntry *pCastTime = sSpellCastTimesStore.LookupEntry(pSpell->CastingTimeIndex))
1307 creatureTarget->ForcedDespawn(pCastTime->CastTime + 1);
1309 return;
1311 case 46485: // Greatmother's Soulcatcher
1313 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1314 return;
1316 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(46486))
1318 m_caster->CastSpell(unitTarget, pSpell, true);
1320 if (const SpellEntry *pSpellCredit = sSpellStore.LookupEntry(pSpell->EffectMiscValue[EFFECT_INDEX_0]))
1321 ((Player*)m_caster)->KilledMonsterCredit(pSpellCredit->EffectMiscValue[EFFECT_INDEX_0], 0);
1323 ((Creature*)unitTarget)->ForcedDespawn();
1326 return;
1328 case 46606: // Plague Canister Dummy
1330 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1331 return;
1333 unitTarget->CastSpell(m_caster, 43160, true);
1334 unitTarget->setDeathState(JUST_DIED);
1335 unitTarget->SetHealth(0);
1336 return;
1338 case 46797: // Quest - Borean Tundra - Set Explosives Cart
1340 if (!unitTarget)
1341 return;
1343 // Quest - Borean Tundra - Summon Explosives Cart
1344 unitTarget->CastSpell(unitTarget,46798,true,m_CastItem,NULL,m_originalCasterGUID);
1345 break;
1347 case 49357: // Brewfest Mount Transformation
1349 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1350 return;
1352 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1353 return;
1355 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1357 // Ram for Alliance, Kodo for Horde
1358 if (((Player *)m_caster)->GetTeam() == ALLIANCE)
1360 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1361 // 100% Ram
1362 m_caster->CastSpell(m_caster, 43900, true);
1363 else
1364 // 60% Ram
1365 m_caster->CastSpell(m_caster, 43899, true);
1367 else
1369 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1370 // 100% Kodo
1371 m_caster->CastSpell(m_caster, 49379, true);
1372 else
1373 // 60% Kodo
1374 m_caster->CastSpell(m_caster, 49378, true);
1376 return;
1378 case 50133: // Scourging Crystal Controller
1380 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1381 return;
1383 if (unitTarget->HasAura(43874))
1385 // someone else is already channeling target
1386 if (unitTarget->HasAura(43878))
1387 return;
1389 m_caster->CastSpell(unitTarget, 43878, true, m_CastItem);
1392 return;
1394 case 50243: // Teach Language
1396 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1397 return;
1399 // spell has a 1/3 chance to trigger one of the below
1400 if (roll_chance_i(66))
1401 return;
1403 if (((Player*)m_caster)->GetTeam() == ALLIANCE)
1405 // 1000001 - gnomish binary
1406 m_caster->CastSpell(m_caster, 50242, true);
1408 else
1410 // 01001000 - goblin binary
1411 m_caster->CastSpell(m_caster, 50246, true);
1414 return;
1416 case 51276: // Incinerate Corpse
1418 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1419 return;
1421 unitTarget->CastSpell(unitTarget, 51278, true);
1422 unitTarget->CastSpell(m_caster, 51279, true);
1424 unitTarget->setDeathState(JUST_DIED);
1425 return;
1427 case 51330: // Shoot RJR
1429 if (!unitTarget)
1430 return;
1432 // guessed chances
1433 if (roll_chance_i(75))
1434 m_caster->CastSpell(unitTarget, roll_chance_i(50) ? 51332 : 51366, true, m_CastItem);
1435 else
1436 m_caster->CastSpell(unitTarget, 51331, true, m_CastItem);
1438 return;
1440 case 51333: // Dig For Treasure
1442 if (!unitTarget)
1443 return;
1445 if (roll_chance_i(75))
1446 m_caster->CastSpell(unitTarget, 51370, true, m_CastItem);
1447 else
1448 m_caster->CastSpell(m_caster, 51345, true);
1450 return;
1452 case 51582: // Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1454 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1455 return;
1457 if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1458 bg->EventPlayerDroppedFlag((Player*)m_caster);
1460 m_caster->CastSpell(m_caster, 30452, true, NULL);
1461 return;
1463 case 52308: // Take Sputum Sample
1465 switch(eff_idx)
1467 case EFFECT_INDEX_0:
1469 uint32 spellID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0);
1470 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
1472 if (m_caster->HasAura(reqAuraID, EFFECT_INDEX_0))
1473 m_caster->CastSpell(m_caster, spellID, true, NULL);
1474 return;
1476 case EFFECT_INDEX_1:
1477 return; // additional data for dummy[0]
1479 return;
1481 case 52759: // Ancestral Awakening
1483 if (!unitTarget)
1484 return;
1486 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1487 return;
1489 case 52845: // Brewfest Mount Transformation (Faction Swap)
1491 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1492 return;
1494 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1495 return;
1497 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1499 // Ram for Horde, Kodo for Alliance
1500 if (((Player *)m_caster)->GetTeam() == HORDE)
1502 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1503 // Swift Brewfest Ram, 100% Ram
1504 m_caster->CastSpell(m_caster, 43900, true);
1505 else
1506 // Brewfest Ram, 60% Ram
1507 m_caster->CastSpell(m_caster, 43899, true);
1509 else
1511 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1512 // Great Brewfest Kodo, 100% Kodo
1513 m_caster->CastSpell(m_caster, 49379, true);
1514 else
1515 // Brewfest Riding Kodo, 60% Kodo
1516 m_caster->CastSpell(m_caster, 49378, true);
1518 return;
1520 case 53341: // Rune of Cinderglacier
1521 case 53343: // Rune of Razorice
1523 // Runeforging Credit
1524 m_caster->CastSpell(m_caster, 54586, true);
1525 return;
1527 case 55004: // Nitro Boosts
1529 if (!m_CastItem)
1530 return;
1532 if (roll_chance_i(95)) // Nitro Boosts - success
1533 m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
1534 else // Knocked Up - backfire 5%
1535 m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
1537 return;
1539 case 55818: // Hurl Boulder
1541 // unclear how many summon min/max random, best guess below
1542 uint32 random = urand(3,5);
1544 for(uint32 i = 0; i < random; ++i)
1545 m_caster->CastSpell(m_caster, 55528, true);
1547 return;
1549 case 58418: // Portal to Orgrimmar
1550 case 58420: // Portal to Stormwind
1551 return; // implemented in EffectScript[0]
1552 case 58601: // Remove Flight Auras
1554 m_caster->RemoveSpellsCausingAura(SPELL_AURA_FLY);
1555 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
1556 return;
1558 case 59640: // Underbelly Elixir
1560 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1561 return;
1563 uint32 spell_id = 0;
1564 switch(urand(1,3))
1566 case 1: spell_id = 59645; break;
1567 case 2: spell_id = 59831; break;
1568 case 3: spell_id = 59843; break;
1571 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1572 return;
1574 case 60932: // Disengage (one from creature versions)
1576 if (!unitTarget)
1577 return;
1579 m_caster->CastSpell(unitTarget,60934,true,NULL);
1580 return;
1582 case 67019: // Flask of the North
1584 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1585 return;
1587 uint32 spell_id = 0;
1588 switch(m_caster->getClass())
1590 case CLASS_WARRIOR:
1591 case CLASS_DEATH_KNIGHT:
1592 spell_id = 67018; // STR for Warriors, Death Knights
1593 break;
1594 case CLASS_ROGUE:
1595 case CLASS_HUNTER:
1596 spell_id = 67017; // AP for Rogues, Hunters
1597 break;
1598 case CLASS_PRIEST:
1599 case CLASS_MAGE:
1600 case CLASS_WARLOCK:
1601 spell_id = 67016; // SPD for Priests, Mages, Warlocks
1602 break;
1603 case CLASS_SHAMAN:
1604 // random (SPD, AP)
1605 spell_id = roll_chance_i(50) ? 67016 : 67017;
1606 break;
1607 case CLASS_PALADIN:
1608 case CLASS_DRUID:
1609 default:
1610 // random (SPD, STR)
1611 spell_id = roll_chance_i(50) ? 67016 : 67018;
1612 break;
1614 m_caster->CastSpell(m_caster, spell_id, true);
1615 return;
1618 break;
1620 case SPELLFAMILY_MAGE:
1622 switch(m_spellInfo->Id)
1624 case 11958: // Cold Snap
1626 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1627 return;
1629 // immediately finishes the cooldown on Frost spells
1630 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1631 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1633 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1635 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1636 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1637 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1639 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
1641 else
1642 ++itr;
1644 return;
1646 case 31687: // Summon Water Elemental
1648 if (m_caster->HasAura(70937)) // Glyph of Eternal Water (permanent limited by known spells version)
1649 m_caster->CastSpell(m_caster, 70908, true);
1650 else // temporary version
1651 m_caster->CastSpell(m_caster, 70907, true);
1653 return;
1655 case 32826: // Polymorph Cast Visual
1657 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
1659 //Polymorph Cast Visual Rank 1
1660 const uint32 spell_list[6] =
1662 32813, // Squirrel Form
1663 32816, // Giraffe Form
1664 32817, // Serpent Form
1665 32818, // Dragonhawk Form
1666 32819, // Worgen Form
1667 32820 // Sheep Form
1669 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1671 return;
1675 // Conjure Mana Gem
1676 if (eff_idx == EFFECT_INDEX_1 && m_spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_CREATE_ITEM)
1678 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1679 return;
1681 // checked in create item check, avoid unexpected
1682 if (Item* item = ((Player*)m_caster)->GetItemByLimitedCategory(ITEM_LIMIT_CATEGORY_MANA_GEM))
1683 if (item->HasMaxCharges())
1684 return;
1686 unitTarget->CastSpell( unitTarget, m_spellInfo->CalculateSimpleValue(eff_idx), true, m_CastItem);
1687 return;
1689 break;
1691 case SPELLFAMILY_WARRIOR:
1693 // Charge
1694 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1696 int32 chargeBasePoints0 = damage;
1697 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1698 return;
1700 // Execute
1701 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1703 if (!unitTarget)
1704 return;
1706 uint32 rage = m_caster->GetPower(POWER_RAGE);
1708 // up to max 30 rage cost
1709 if (rage > 300)
1710 rage = 300;
1712 // Glyph of Execution bonus
1713 uint32 rage_modified = rage;
1715 if (Aura *aura = m_caster->GetDummyAura(58367))
1716 rage_modified += aura->GetModifier()->m_amount*10;
1718 int32 basePoints0 = damage+int32(rage_modified * m_spellInfo->DmgMultiplier[eff_idx] +
1719 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1721 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1723 // Sudden Death
1724 if (m_caster->HasAura(52437))
1726 Unit::AuraList const& auras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
1727 for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1729 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1730 if ((*itr)->GetSpellProto()->SpellIconID == 1989)
1732 // saved rage top stored in next affect
1733 uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1)*10;
1734 if(lastrage < rage)
1735 rage -= lastrage;
1736 break;
1741 m_caster->SetPower(POWER_RAGE,m_caster->GetPower(POWER_RAGE)-rage);
1742 return;
1744 // Slam
1745 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1747 if(!unitTarget)
1748 return;
1750 // dummy cast itself ignored by client in logs
1751 m_caster->CastCustomSpell(unitTarget,50782,&damage,NULL,NULL,true);
1752 return;
1754 // Concussion Blow
1755 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1757 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1758 return;
1761 switch(m_spellInfo->Id)
1763 // Warrior's Wrath
1764 case 21977:
1766 if (!unitTarget)
1767 return;
1768 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1769 return;
1771 // Last Stand
1772 case 12975:
1774 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1775 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1776 return;
1778 // Bloodthirst
1779 case 23881:
1781 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1782 return;
1785 break;
1787 case SPELLFAMILY_WARLOCK:
1789 // Life Tap
1790 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1792 // In 303 exist spirit depend
1793 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1794 switch (m_spellInfo->Id)
1796 case 1454: damage+=spirit; break;
1797 case 1455: damage+=spirit*15/10; break;
1798 case 1456: damage+=spirit*2; break;
1799 case 11687: damage+=spirit*25/10; break;
1800 case 11688:
1801 case 11689:
1802 case 27222:
1803 case 57946: damage+=spirit*3; break;
1804 default:
1805 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1806 return;
1808 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1809 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1810 if (unitTarget && (int32(unitTarget->GetHealth()) > damage))
1812 // Shouldn't Appear in Combat Log
1813 unitTarget->ModifyHealth(-damage);
1815 int32 mana = damage;
1816 // Improved Life Tap mod
1817 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1818 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1820 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1821 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1823 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1825 // Mana Feed
1826 int32 manaFeedVal = 0;
1827 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1828 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1830 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1831 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1833 if (manaFeedVal > 0)
1835 manaFeedVal = manaFeedVal * mana / 100;
1836 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1839 else
1840 SendCastResult(SPELL_FAILED_FIZZLE);
1842 return;
1844 break;
1846 case SPELLFAMILY_PRIEST:
1848 // Penance
1849 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1851 if (!unitTarget)
1852 return;
1854 int hurt = 0;
1855 int heal = 0;
1856 switch(m_spellInfo->Id)
1858 case 47540: hurt = 47758; heal = 47757; break;
1859 case 53005: hurt = 53001; heal = 52986; break;
1860 case 53006: hurt = 53002; heal = 52987; break;
1861 case 53007: hurt = 53003; heal = 52988; break;
1862 default:
1863 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1864 return;
1867 // prevent interrupted message for main spell
1868 finish(true);
1870 // replace cast by selected spell, this also make it interruptible including target death case
1871 if (m_caster->IsFriendlyTo(unitTarget))
1872 m_caster->CastSpell(unitTarget, heal, false);
1873 else
1874 m_caster->CastSpell(unitTarget, hurt, false);
1876 return;
1878 break;
1880 case SPELLFAMILY_DRUID:
1882 // Starfall
1883 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100)
1885 //Shapeshifting into an animal form or mounting cancels the effect.
1886 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1888 if(m_triggeredByAuraSpell)
1889 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1890 return;
1893 //Any effect which causes you to lose control of your character will supress the starfall effect.
1894 if (m_caster->hasUnitState(UNIT_STAT_NO_FREE_MOVE))
1895 return;
1897 switch(m_spellInfo->Id)
1899 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1900 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1901 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1902 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1903 default:
1904 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1905 return;
1908 break;
1910 case SPELLFAMILY_ROGUE:
1912 switch(m_spellInfo->Id)
1914 case 5938: // Shiv
1916 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1917 return;
1919 Player *pCaster = ((Player*)m_caster);
1921 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1922 if (!item)
1923 return;
1925 // all poison enchantments is temporary
1926 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1927 if (!enchant_id)
1928 return;
1930 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1931 if (!pEnchant)
1932 return;
1934 for (int s = 0; s < 3; ++s)
1936 if (pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1937 continue;
1939 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1940 if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1941 continue;
1943 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1946 m_caster->CastSpell(unitTarget, 5940, true);
1947 return;
1949 case 14185: // Preparation
1951 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1952 return;
1954 //immediately finishes the cooldown on certain Rogue abilities
1955 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1956 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1958 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1960 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1961 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1962 else
1963 ++itr;
1965 return;
1967 case 31231: // Cheat Death
1969 m_caster->CastSpell(m_caster, 45182, true);
1970 return;
1973 break;
1975 case SPELLFAMILY_HUNTER:
1977 // Steady Shot
1978 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1980 if (!unitTarget || !unitTarget->isAlive())
1981 return;
1983 bool found = false;
1985 // check dazed affect
1986 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1987 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1989 if ((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1991 found = true;
1992 break;
1996 if (found)
1997 m_damage+= damage;
1998 return;
2001 // Disengage
2002 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000400000000000))
2004 Unit* target = unitTarget;
2005 uint32 spellid;
2006 switch(m_spellInfo->Id)
2008 case 57635: spellid = 57636; break; // one from creature cases
2009 case 61507: spellid = 61508; break; // one from creature cases
2010 default:
2011 sLog.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo->Id);
2012 return;
2014 if (!target || !target->isAlive())
2015 return;
2016 m_caster->CastSpell(target,spellid,true,NULL);
2019 switch(m_spellInfo->Id)
2021 case 23989: // Readiness talent
2023 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2024 return;
2026 //immediately finishes the cooldown for hunter abilities
2027 const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
2028 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
2030 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2032 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
2033 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
2034 else
2035 ++itr;
2037 return;
2039 case 37506: // Scatter Shot
2041 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2042 return;
2044 // break Auto Shot and autohit
2045 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
2046 m_caster->AttackStop();
2047 ((Player*)m_caster)->SendAttackSwingCancelAttack();
2048 return;
2050 // Last Stand
2051 case 53478:
2053 if (!unitTarget)
2054 return;
2055 int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3);
2056 unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
2057 return;
2059 // Master's Call
2060 case 53271:
2062 Pet* pet = m_caster->GetPet();
2063 if (!pet || !unitTarget)
2064 return;
2066 pet->CastSpell(unitTarget, m_spellInfo->CalculateSimpleValue(eff_idx), true);
2067 return;
2070 break;
2072 case SPELLFAMILY_PALADIN:
2074 switch(m_spellInfo->SpellIconID)
2076 case 156: // Holy Shock
2078 if (!unitTarget)
2079 return;
2081 int hurt = 0;
2082 int heal = 0;
2084 switch(m_spellInfo->Id)
2086 case 20473: hurt = 25912; heal = 25914; break;
2087 case 20929: hurt = 25911; heal = 25913; break;
2088 case 20930: hurt = 25902; heal = 25903; break;
2089 case 27174: hurt = 27176; heal = 27175; break;
2090 case 33072: hurt = 33073; heal = 33074; break;
2091 case 48824: hurt = 48822; heal = 48820; break;
2092 case 48825: hurt = 48823; heal = 48821; break;
2093 default:
2094 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
2095 return;
2098 if (m_caster->IsFriendlyTo(unitTarget))
2099 m_caster->CastSpell(unitTarget, heal, true);
2100 else
2101 m_caster->CastSpell(unitTarget, hurt, true);
2103 return;
2105 case 561: // Judgement of command
2107 if (!unitTarget)
2108 return;
2110 uint32 spell_id = m_currentBasePoints[eff_idx]+1;
2111 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
2112 if (!spell_proto)
2113 return;
2115 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
2116 return;
2120 switch(m_spellInfo->Id)
2122 case 31789: // Righteous Defense (step 1)
2124 if (m_caster->GetTypeId() != TYPEID_PLAYER)
2126 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
2127 return;
2130 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
2131 Unit* friendTarget = !unitTarget || unitTarget->IsFriendlyTo(m_caster) ? unitTarget : unitTarget->getVictim();
2132 if (friendTarget)
2134 Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
2135 if (!player || !player->IsInSameRaidWith((Player*)m_caster))
2136 friendTarget = NULL;
2139 // non-standard cast requirement check
2140 if (!friendTarget || friendTarget->getAttackers().empty())
2142 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
2143 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
2144 return;
2147 // Righteous Defense (step 2) (in old version 31980 dummy effect)
2148 // Clear targets for eff 1
2149 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2150 ihit->effectMask &= ~(1<<1);
2152 // not empty (checked), copy
2153 Unit::AttackerSet attackers = friendTarget->getAttackers();
2155 // selected from list 3
2156 for(uint32 i = 0; i < std::min(size_t(3),attackers.size()); ++i)
2158 Unit::AttackerSet::iterator aItr = attackers.begin();
2159 std::advance(aItr, rand() % attackers.size());
2160 AddUnitTarget((*aItr), EFFECT_INDEX_1);
2161 attackers.erase(aItr);
2164 // now let next effect cast spell at each target.
2165 return;
2167 case 37877: // Blessing of Faith
2169 if (!unitTarget)
2170 return;
2172 uint32 spell_id = 0;
2173 switch(unitTarget->getClass())
2175 case CLASS_DRUID: spell_id = 37878; break;
2176 case CLASS_PALADIN: spell_id = 37879; break;
2177 case CLASS_PRIEST: spell_id = 37880; break;
2178 case CLASS_SHAMAN: spell_id = 37881; break;
2179 default: return; // ignore for not healing classes
2182 m_caster->CastSpell(m_caster, spell_id, true);
2183 return;
2186 break;
2188 case SPELLFAMILY_SHAMAN:
2190 // Cleansing Totem
2191 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
2193 if (unitTarget)
2194 m_caster->CastSpell(unitTarget, 52025, true);
2195 return;
2197 // Healing Stream Totem
2198 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
2200 if (unitTarget)
2202 if (Unit *owner = m_caster->GetOwner())
2204 // Restorative Totems
2205 Unit::AuraList const& mDummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
2206 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2207 // only its have dummy with specific icon
2208 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (*i)->GetSpellProto()->SpellIconID == 338)
2209 damage += (*i)->GetModifier()->m_amount * damage / 100;
2211 // Glyph of Healing Stream Totem
2212 if (Aura *dummy = owner->GetDummyAura(55456))
2213 damage += dummy->GetModifier()->m_amount * damage / 100;
2215 m_caster->CastCustomSpell(unitTarget, 52042, &damage, NULL, NULL, true, 0, 0, m_originalCasterGUID);
2217 return;
2219 // Mana Spring Totem
2220 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
2222 if (!unitTarget || unitTarget->getPowerType()!=POWER_MANA)
2223 return;
2224 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
2225 return;
2227 if (m_spellInfo->Id == 39610) // Mana Tide Totem effect
2229 if (!unitTarget || unitTarget->getPowerType() != POWER_MANA)
2230 return;
2231 // Glyph of Mana Tide
2232 if (Unit *owner = m_caster->GetOwner())
2233 if (Aura *dummy = owner->GetDummyAura(55441))
2234 damage+=dummy->GetModifier()->m_amount;
2235 // Regenerate 6% of Total Mana Every 3 secs
2236 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
2237 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
2238 return;
2240 // Lava Lash
2241 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
2243 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2244 return;
2245 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
2246 if (item)
2248 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
2249 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2250 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
2252 if ((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
2253 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
2254 (*itr)->GetCastItemGUID() == item->GetGUID())
2256 m_damage += m_damage * damage / 100;
2257 return;
2261 return;
2263 // Fire Nova
2264 if (m_spellInfo->SpellIconID == 33)
2266 // fire totems slot
2267 Totem* totem = m_caster->GetTotem(TOTEM_SLOT_FIRE);
2268 if (!totem)
2269 return;
2271 uint32 triggered_spell_id;
2272 switch(m_spellInfo->Id)
2274 case 1535: triggered_spell_id = 8349; break;
2275 case 8498: triggered_spell_id = 8502; break;
2276 case 8499: triggered_spell_id = 8503; break;
2277 case 11314: triggered_spell_id = 11306; break;
2278 case 11315: triggered_spell_id = 11307; break;
2279 case 25546: triggered_spell_id = 25535; break;
2280 case 25547: triggered_spell_id = 25537; break;
2281 case 61649: triggered_spell_id = 61650; break;
2282 case 61657: triggered_spell_id = 61654; break;
2283 default: return;
2286 totem->CastSpell(totem, triggered_spell_id, true, NULL, NULL, m_caster->GetGUID());
2288 // Fire Nova Visual
2289 totem->CastSpell(totem, 19823, true, NULL, NULL, m_caster->GetGUID());
2290 return;
2292 break;
2294 case SPELLFAMILY_DEATHKNIGHT:
2296 // Death Coil
2297 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
2299 if (m_caster->IsFriendlyTo(unitTarget))
2301 if (unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
2302 return;
2304 int32 bp = int32(damage * 1.5f);
2305 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
2307 else
2309 int32 bp = damage;
2310 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
2312 return;
2314 // Hungering Cold
2315 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000100000000000))
2317 m_caster->CastSpell(m_caster, 51209, true);
2318 return;
2320 // Death Strike
2321 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
2323 uint32 count = 0;
2324 Unit::AuraMap const& auras = unitTarget->GetAuras();
2325 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2327 if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
2328 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
2329 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
2331 ++count;
2332 // max. 15%
2333 if (count == 3)
2334 break;
2338 int32 bp = int32(count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[EFFECT_INDEX_0] / 100);
2340 // Improved Death Strike (percent stored in not existed EFFECT_INDEX_2 effect base points)
2341 Unit::AuraList const& auraMod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
2342 for(Unit::AuraList::const_iterator iter = auraMod.begin(); iter != auraMod.end(); ++iter)
2344 // only required spell have spellicon for SPELL_AURA_ADD_FLAT_MODIFIER
2345 if ((*iter)->GetSpellProto()->SpellIconID == 2751 && (*iter)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
2347 bp += (*iter)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2) * bp / 100;
2348 break;
2352 m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
2353 return;
2355 break;
2359 // pet auras
2360 if (PetAura const* petSpell = sSpellMgr.GetPetAura(m_spellInfo->Id, eff_idx))
2362 m_caster->AddPetAura(petSpell);
2363 return;
2366 // Script based implementation. Must be used only for not good for implementation in core spell effects
2367 // So called only for not processed cases
2368 if (gameObjTarget)
2369 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, eff_idx, gameObjTarget);
2370 else if (unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
2371 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, eff_idx, (Creature*)unitTarget);
2372 else if (itemTarget)
2373 Script->EffectDummyItem(m_caster, m_spellInfo->Id, eff_idx, itemTarget);
2376 void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx)
2378 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2380 // normal case
2381 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2383 if(!spellInfo)
2385 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2386 return;
2389 int32 bp = damage;
2390 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
2393 void Spell::EffectTriggerRitualOfSummoning(SpellEffectIndex eff_idx)
2395 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2396 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2398 if(!spellInfo)
2400 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2401 return;
2404 finish();
2406 m_caster->CastSpell(unitTarget,spellInfo,false);
2409 void Spell::EffectForceCast(SpellEffectIndex eff_idx)
2411 if( !unitTarget )
2412 return;
2414 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2416 // normal case
2417 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2419 if(!spellInfo)
2421 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2422 return;
2425 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
2428 void Spell::EffectTriggerSpell(SpellEffectIndex effIndex)
2430 // only unit case known
2431 if (!unitTarget)
2433 if(gameObjTarget || itemTarget)
2434 sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
2435 return;
2438 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2440 // special cases
2441 switch(triggered_spell_id)
2443 // Vanish (not exist)
2444 case 18461:
2446 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2447 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2448 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
2450 // if this spell is given to NPC it must handle rest by it's own AI
2451 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2452 return;
2454 // get highest rank of the Stealth spell
2455 uint32 spellId = 0;
2456 const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
2457 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2459 // only highest rank is shown in spell book, so simply check if shown in spell book
2460 if (!itr->second.active || itr->second.disabled || itr->second.state == PLAYERSPELL_REMOVED)
2461 continue;
2463 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2464 if (!spellInfo)
2465 continue;
2467 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
2469 spellId = spellInfo->Id;
2470 break;
2474 // no Stealth spell found
2475 if (!spellId)
2476 return;
2478 // reset cooldown on it if needed
2479 if (((Player*)unitTarget)->HasSpellCooldown(spellId))
2480 ((Player*)unitTarget)->RemoveSpellCooldown(spellId);
2482 m_caster->CastSpell(unitTarget, spellId, true);
2483 return;
2485 // just skip
2486 case 23770: // Sayge's Dark Fortune of *
2487 // not exist, common cooldown can be implemented in scripts if need.
2488 return;
2489 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2490 case 29284:
2492 // Brittle Armor
2493 SpellEntry const* spell = sSpellStore.LookupEntry(24575);
2494 if (!spell)
2495 return;
2497 for (uint32 j=0; j < spell->StackAmount; ++j)
2498 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2499 return;
2501 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2502 case 29286:
2504 // Mercurial Shield
2505 SpellEntry const* spell = sSpellStore.LookupEntry(26464);
2506 if (!spell)
2507 return;
2509 for (uint32 j=0; j < spell->StackAmount; ++j)
2510 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2511 return;
2513 // Righteous Defense
2514 case 31980:
2516 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
2517 return;
2519 // Cloak of Shadows
2520 case 35729:
2522 Unit::AuraMap& Auras = unitTarget->GetAuras();
2523 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2525 // remove all harmful spells on you...
2526 if( // ignore positive and passive auras
2527 !iter->second->IsPositive() && !iter->second->IsPassive() &&
2528 // ignore physical auras
2529 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
2531 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
2532 iter = Auras.begin();
2535 return;
2537 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2538 case 41967:
2540 if (Unit *pet = unitTarget->GetPet())
2541 pet->CastSpell(pet, 28305, true);
2542 return;
2546 // normal case
2547 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2548 if (!spellInfo)
2550 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2551 return;
2554 // select formal caster for triggered spell
2555 Unit* caster = m_caster;
2557 // some triggered spells require specific equipment
2558 if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
2560 // main hand weapon required
2561 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
2563 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK, true, false);
2565 // skip spell if no weapon in slot or broken
2566 if (!item)
2567 return;
2569 // skip spell if weapon not fit to triggered spell
2570 if (!item->IsFitToSpellRequirements(spellInfo))
2571 return;
2574 // offhand hand weapon required
2575 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
2577 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, false);
2579 // skip spell if no weapon in slot or broken
2580 if (!item)
2581 return;
2583 // skip spell if weapon not fit to triggered spell
2584 if (!item->IsFitToSpellRequirements(spellInfo))
2585 return;
2588 else
2590 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2591 // so this just for speedup places in else
2592 caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
2595 caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
2598 void Spell::EffectTriggerMissileSpell(SpellEffectIndex effect_idx)
2600 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2602 // normal case
2603 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2605 if(!spellInfo)
2607 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2608 m_spellInfo->Id,effect_idx,triggered_spell_id);
2609 return;
2612 if (m_CastItem)
2613 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2615 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2618 void Spell::EffectJump(SpellEffectIndex eff_idx)
2620 if(m_caster->isInFlight())
2621 return;
2623 // Init dest coordinates
2624 float x,y,z,o;
2625 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2627 x = m_targets.m_destX;
2628 y = m_targets.m_destY;
2629 z = m_targets.m_destZ;
2631 if(m_spellInfo->EffectImplicitTargetA[eff_idx] == TARGET_BEHIND_VICTIM)
2633 // explicit cast data from client or server-side cast
2634 // some spell at client send caster
2635 Unit* pTarget = NULL;
2636 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2637 pTarget = m_targets.getUnitTarget();
2638 else if(unitTarget->getVictim())
2639 pTarget = m_caster->getVictim();
2640 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2641 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2643 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2645 else
2646 o = m_caster->GetOrientation();
2648 else if(unitTarget)
2650 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2651 o = m_caster->GetOrientation();
2653 else if(gameObjTarget)
2655 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2656 o = m_caster->GetOrientation();
2658 else
2660 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2661 return;
2664 m_caster->NearTeleportTo(x, y, z, o, true);
2667 void Spell::EffectTeleportUnits(SpellEffectIndex eff_idx)
2669 if(!unitTarget || unitTarget->isInFlight())
2670 return;
2672 switch (m_spellInfo->EffectImplicitTargetB[eff_idx])
2674 case TARGET_INNKEEPER_COORDINATES:
2676 // Only players can teleport to innkeeper
2677 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2678 return;
2680 ((Player*)unitTarget)->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
2681 return;
2683 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2684 case TARGET_TABLE_X_Y_Z_COORDINATES:
2686 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
2687 if(!st)
2689 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2690 return;
2693 if(st->target_mapId==unitTarget->GetMapId())
2694 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2695 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2696 ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0);
2697 break;
2699 case TARGET_BEHIND_VICTIM:
2701 Unit *pTarget = NULL;
2703 // explicit cast data from client or server-side cast
2704 // some spell at client send caster
2705 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2706 pTarget = m_targets.getUnitTarget();
2707 else if(unitTarget->getVictim())
2708 pTarget = unitTarget->getVictim();
2709 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2710 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2712 // Init dest coordinates
2713 float x = m_targets.m_destX;
2714 float y = m_targets.m_destY;
2715 float z = m_targets.m_destZ;
2716 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2717 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2718 return;
2720 default:
2722 // If not exist data for dest location - return
2723 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2725 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", eff_idx, m_spellInfo->EffectImplicitTargetB[eff_idx], m_spellInfo->Id );
2726 return;
2728 // Init dest coordinates
2729 float x = m_targets.m_destX;
2730 float y = m_targets.m_destY;
2731 float z = m_targets.m_destZ;
2732 float orientation = unitTarget->GetOrientation();
2733 // Teleport
2734 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2735 return;
2739 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2740 switch ( m_spellInfo->Id )
2742 // Dimensional Ripper - Everlook
2743 case 23442:
2745 int32 r = irand(0, 119);
2746 if ( r >= 70 ) // 7/12 success
2748 if ( r < 100 ) // 4/12 evil twin
2749 m_caster->CastSpell(m_caster, 23445, true);
2750 else // 1/12 fire
2751 m_caster->CastSpell(m_caster, 23449, true);
2753 return;
2755 // Ultrasafe Transporter: Toshley's Station
2756 case 36941:
2758 if ( roll_chance_i(50) ) // 50% success
2760 int32 rand_eff = urand(1, 7);
2761 switch ( rand_eff )
2763 case 1:
2764 // soul split - evil
2765 m_caster->CastSpell(m_caster, 36900, true);
2766 break;
2767 case 2:
2768 // soul split - good
2769 m_caster->CastSpell(m_caster, 36901, true);
2770 break;
2771 case 3:
2772 // Increase the size
2773 m_caster->CastSpell(m_caster, 36895, true);
2774 break;
2775 case 4:
2776 // Decrease the size
2777 m_caster->CastSpell(m_caster, 36893, true);
2778 break;
2779 case 5:
2780 // Transform
2782 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2783 m_caster->CastSpell(m_caster, 36897, true);
2784 else
2785 m_caster->CastSpell(m_caster, 36899, true);
2786 break;
2788 case 6:
2789 // chicken
2790 m_caster->CastSpell(m_caster, 36940, true);
2791 break;
2792 case 7:
2793 // evil twin
2794 m_caster->CastSpell(m_caster, 23445, true);
2795 break;
2798 return;
2800 // Dimensional Ripper - Area 52
2801 case 36890:
2803 if ( roll_chance_i(50) ) // 50% success
2805 int32 rand_eff = urand(1, 4);
2806 switch ( rand_eff )
2808 case 1:
2809 // soul split - evil
2810 m_caster->CastSpell(m_caster, 36900, true);
2811 break;
2812 case 2:
2813 // soul split - good
2814 m_caster->CastSpell(m_caster, 36901, true);
2815 break;
2816 case 3:
2817 // Increase the size
2818 m_caster->CastSpell(m_caster, 36895, true);
2819 break;
2820 case 4:
2821 // Transform
2823 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2824 m_caster->CastSpell(m_caster, 36897, true);
2825 else
2826 m_caster->CastSpell(m_caster, 36899, true);
2827 break;
2831 return;
2836 void Spell::EffectApplyAura(SpellEffectIndex eff_idx)
2838 if(!unitTarget)
2839 return;
2841 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2842 if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) &&
2843 (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2844 return;
2846 Unit* caster = GetAffectiveCaster();
2847 if(!caster)
2849 // FIXME: currently we can't have auras applied explIcitly by gameobjects
2850 // so for auras from wild gameobjects (no owner) target used
2851 if (m_originalCasterGUID.IsGameobject())
2852 caster = unitTarget;
2853 else
2854 return;
2857 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]);
2859 Aura* Aur = CreateAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, caster, m_CastItem);
2861 // Now Reduce spell duration using data received at spell hit
2862 int32 duration = Aur->GetAuraMaxDuration();
2863 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
2864 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
2865 Aur->setDiminishGroup(m_diminishGroup);
2867 // if Aura removed and deleted, do not continue.
2868 if(duration== 0 && !(Aur->IsPermanent()))
2870 delete Aur;
2871 return;
2874 if(duration != Aur->GetAuraMaxDuration())
2876 Aur->SetAuraMaxDuration(duration);
2877 Aur->SetAuraDuration(duration);
2880 unitTarget->AddAura(Aur);
2883 void Spell::EffectUnlearnSpecialization(SpellEffectIndex eff_idx)
2885 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2886 return;
2888 Player *_player = (Player*)unitTarget;
2889 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[eff_idx];
2891 _player->removeSpell(spellToUnlearn);
2893 sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2896 void Spell::EffectPowerDrain(SpellEffectIndex eff_idx)
2898 if(m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
2899 return;
2901 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
2903 if(!unitTarget)
2904 return;
2905 if(!unitTarget->isAlive())
2906 return;
2907 if(unitTarget->getPowerType() != drain_power)
2908 return;
2909 if(damage < 0)
2910 return;
2912 uint32 curPower = unitTarget->GetPower(drain_power);
2914 //add spell damage bonus
2915 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2917 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2918 uint32 power = damage;
2919 if (drain_power == POWER_MANA)
2920 power -= unitTarget->GetSpellCritDamageReduction(power);
2922 int32 new_damage;
2923 if(curPower < power)
2924 new_damage = curPower;
2925 else
2926 new_damage = power;
2928 unitTarget->ModifyPower(drain_power,-new_damage);
2930 // Don`t restore from self drain
2931 if(drain_power == POWER_MANA && m_caster != unitTarget)
2933 float manaMultiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2934 if(manaMultiplier==0)
2935 manaMultiplier = 1;
2937 if(Player *modOwner = m_caster->GetSpellModOwner())
2938 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2940 int32 gain = int32(new_damage * manaMultiplier);
2942 m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2946 void Spell::EffectSendEvent(SpellEffectIndex effectIndex)
2949 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2951 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[effectIndex], m_spellInfo->Id);
2952 m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[effectIndex], m_caster, focusObject);
2955 void Spell::EffectPowerBurn(SpellEffectIndex eff_idx)
2957 if (m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
2958 return;
2960 Powers powertype = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
2962 if (!unitTarget)
2963 return;
2964 if (!unitTarget->isAlive())
2965 return;
2966 if (unitTarget->getPowerType()!=powertype)
2967 return;
2968 if (damage < 0)
2969 return;
2971 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2972 if (m_spellInfo->ManaCostPercentage)
2974 int32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2975 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2976 if(damage > maxdamage)
2977 damage = maxdamage;
2980 int32 curPower = int32(unitTarget->GetPower(powertype));
2982 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2983 int32 power = damage;
2984 if (powertype == POWER_MANA)
2985 power -= unitTarget->GetSpellCritDamageReduction(power);
2987 int32 new_damage = (curPower < power) ? curPower : power;
2989 unitTarget->ModifyPower(powertype, -new_damage);
2990 float multiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2992 if (Player *modOwner = m_caster->GetSpellModOwner())
2993 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2995 new_damage = int32(new_damage * multiplier);
2996 m_damage += new_damage;
2999 void Spell::EffectHeal(SpellEffectIndex /*eff_idx*/)
3001 if (unitTarget && unitTarget->isAlive() && damage >= 0)
3003 // Try to get original caster
3004 Unit *caster = GetAffectiveCaster();
3005 if (!caster)
3006 return;
3008 int32 addhealth = damage;
3010 // Seal of Light proc
3011 if (m_spellInfo->Id == 20167)
3013 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
3014 int32 holy = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellInfo)) +
3015 caster->SpellBaseHealingBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
3016 addhealth += int32(ap * 0.15) + int32(holy * 15 / 100);
3018 // Vessel of the Naaru (Vial of the Sunwell trinket)
3019 else if (m_spellInfo->Id == 45064)
3021 // Amount of heal - depends from stacked Holy Energy
3022 int damageAmount = 0;
3023 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
3024 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
3025 if ((*i)->GetId() == 45062)
3026 damageAmount+=(*i)->GetModifier()->m_amount;
3027 if (damageAmount)
3028 m_caster->RemoveAurasDueToSpell(45062);
3030 addhealth += damageAmount;
3032 // Death Pact (percent heal)
3033 else if (m_spellInfo->Id==48743)
3034 addhealth = addhealth * unitTarget->GetMaxHealth() / 100;
3035 // Swiftmend - consumes Regrowth or Rejuvenation
3036 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
3038 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
3039 // find most short by duration
3040 Aura *targetAura = NULL;
3041 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
3043 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
3044 // Regrowth or Rejuvenation 0x40 | 0x10
3045 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000050)))
3047 if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
3048 targetAura = *i;
3052 if (!targetAura)
3054 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
3055 return;
3057 int idx = 0;
3058 while(idx < 3)
3060 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
3061 break;
3062 idx++;
3065 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
3066 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
3068 // Glyph of Swiftmend
3069 if (!caster->HasAura(54824))
3070 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
3072 addhealth += tickheal * tickcount;
3074 else
3075 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
3077 m_healing += addhealth;
3079 // Chain Healing
3080 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000100))
3082 // check for Riptide
3083 if (unitTarget != m_targets.getUnitTarget())
3084 return;
3085 Aura* riptide = unitTarget->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0x00000010, caster->GetGUID());
3086 if (!riptide)
3087 return;
3088 m_healing += m_healing/4;
3089 unitTarget->RemoveAura(riptide);
3094 void Spell::EffectHealPct(SpellEffectIndex /*eff_idx*/)
3096 if (unitTarget && unitTarget->isAlive() && damage >= 0)
3098 // Try to get original caster
3099 Unit *caster = GetAffectiveCaster();
3100 if (!caster)
3101 return;
3103 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
3104 if (Player* modOwner = m_caster->GetSpellModOwner())
3105 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
3107 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
3108 unitTarget->getHostileRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
3112 void Spell::EffectHealMechanical(SpellEffectIndex /*eff_idx*/)
3114 // Mechanic creature type should be correctly checked by targetCreatureType field
3115 if (unitTarget && unitTarget->isAlive() && damage >= 0)
3117 // Try to get original caster
3118 Unit *caster = GetAffectiveCaster();
3119 if (!caster)
3120 return;
3122 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, damage, HEAL);
3123 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
3127 void Spell::EffectHealthLeech(SpellEffectIndex eff_idx)
3129 if (!unitTarget)
3130 return;
3131 if (!unitTarget->isAlive())
3132 return;
3134 if (damage < 0)
3135 return;
3137 sLog.outDebug("HealthLeech :%i", damage);
3139 uint32 curHealth = unitTarget->GetHealth();
3140 damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage );
3141 if ((int32)curHealth < damage)
3142 damage = curHealth;
3144 float multiplier = m_spellInfo->EffectMultipleValue[eff_idx];
3146 if (Player *modOwner = m_caster->GetSpellModOwner())
3147 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
3149 int32 heal = int32(damage*multiplier);
3150 if (m_caster->isAlive())
3152 heal = m_caster->SpellHealingBonus(m_caster, m_spellInfo, heal, HEAL);
3153 m_caster->DealHeal(m_caster, heal, m_spellInfo);
3157 void Spell::DoCreateItem(SpellEffectIndex eff_idx, uint32 itemtype)
3159 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3160 return;
3162 Player* player = (Player*)unitTarget;
3164 uint32 newitemid = itemtype;
3165 ItemPrototype const *pProto = ObjectMgr::GetItemPrototype( newitemid );
3166 if(!pProto)
3168 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
3169 return;
3172 // bg reward have some special in code work
3173 uint32 bgType = 0;
3174 switch(m_spellInfo->Id)
3176 case SPELL_AV_MARK_WINNER:
3177 case SPELL_AV_MARK_LOSER:
3178 bgType = BATTLEGROUND_AV;
3179 break;
3180 case SPELL_WS_MARK_WINNER:
3181 case SPELL_WS_MARK_LOSER:
3182 bgType = BATTLEGROUND_WS;
3183 break;
3184 case SPELL_AB_MARK_WINNER:
3185 case SPELL_AB_MARK_LOSER:
3186 bgType = BATTLEGROUND_AB;
3187 break;
3188 default:
3189 break;
3192 uint32 num_to_add;
3194 // TODO: maybe all this can be replaced by using correct calculated `damage` value
3195 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
3197 int32 basePoints = m_currentBasePoints[eff_idx];
3198 int32 randomPoints = m_spellInfo->EffectDieSides[eff_idx];
3199 if (randomPoints)
3200 num_to_add = basePoints + irand(1, randomPoints);
3201 else
3202 num_to_add = basePoints + 1;
3204 else if (pProto->MaxCount == 1)
3205 num_to_add = 1;
3206 else if(player->getLevel() >= m_spellInfo->spellLevel)
3208 int32 basePoints = m_currentBasePoints[eff_idx];
3209 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[eff_idx];
3210 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
3212 else
3213 num_to_add = 2;
3215 if (num_to_add < 1)
3216 num_to_add = 1;
3217 if (num_to_add > pProto->GetMaxStackSize())
3218 num_to_add = pProto->GetMaxStackSize();
3220 // init items_count to 1, since 1 item will be created regardless of specialization
3221 int items_count=1;
3222 // the chance to create additional items
3223 float additionalCreateChance=0.0f;
3224 // the maximum number of created additional items
3225 uint8 additionalMaxNum=0;
3226 // get the chance and maximum number for creating extra items
3227 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
3229 // roll with this chance till we roll not to create or we create the max num
3230 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
3231 ++items_count;
3234 // really will be created more items
3235 num_to_add *= items_count;
3237 // can the player store the new item?
3238 ItemPosCountVec dest;
3239 uint32 no_space = 0;
3240 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
3241 if( msg != EQUIP_ERR_OK )
3243 // convert to possible store amount
3244 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
3245 num_to_add -= no_space;
3246 else
3248 // ignore mana gem case (next effect will recharge existed example)
3249 if (eff_idx == EFFECT_INDEX_0 && m_spellInfo->Effect[EFFECT_INDEX_1] == SPELL_EFFECT_DUMMY )
3250 return;
3252 // if not created by another reason from full inventory or unique items amount limitation
3253 player->SendEquipError( msg, NULL, NULL, newitemid );
3254 return;
3258 if(num_to_add)
3260 // create the new item and store it
3261 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
3263 // was it successful? return error if not
3264 if(!pItem)
3266 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
3267 return;
3270 // set the "Crafted by ..." property of the item
3271 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
3272 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
3274 // send info to the client
3275 if(pItem)
3276 player->SendNewItem(pItem, num_to_add, true, bgType == 0);
3278 // we succeeded in creating at least one item, so a levelup is possible
3279 if(bgType == 0)
3280 player->UpdateCraftSkill(m_spellInfo->Id);
3283 // for battleground marks send by mail if not add all expected
3284 if(no_space > 0 && bgType)
3286 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
3287 bg->SendRewardMarkByMail(player, newitemid, no_space);
3291 void Spell::EffectCreateItem(SpellEffectIndex eff_idx)
3293 DoCreateItem(eff_idx,m_spellInfo->EffectItemType[eff_idx]);
3296 void Spell::EffectCreateItem2(SpellEffectIndex eff_idx)
3298 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
3299 return;
3300 Player* player = (Player*)m_caster;
3302 uint32 item_id = m_spellInfo->EffectItemType[eff_idx];
3304 DoCreateItem(eff_idx, item_id);
3306 // special case: fake item replaced by generate using spell_loot_template
3307 if (IsLootCraftingSpell(m_spellInfo))
3309 if (!player->HasItemCount(item_id, 1))
3310 return;
3312 // remove reagent
3313 uint32 count = 1;
3314 player->DestroyItemCount(item_id, count, true);
3316 // create some random items
3317 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
3321 void Spell::EffectCreateRandomItem(SpellEffectIndex /*eff_idx*/)
3323 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
3324 return;
3325 Player* player = (Player*)m_caster;
3327 // create some random items
3328 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
3331 void Spell::EffectPersistentAA(SpellEffectIndex eff_idx)
3333 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
3335 if (Player* modOwner = m_caster->GetSpellModOwner())
3336 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
3338 int32 duration = GetSpellDuration(m_spellInfo);
3339 DynamicObject* dynObj = new DynamicObject;
3340 if (!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, eff_idx, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
3342 delete dynObj;
3343 return;
3345 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3346 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
3347 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
3348 m_caster->AddDynObject(dynObj);
3349 m_caster->GetMap()->Add(dynObj);
3352 void Spell::EffectEnergize(SpellEffectIndex eff_idx)
3354 if(!unitTarget)
3355 return;
3356 if(!unitTarget->isAlive())
3357 return;
3359 if(m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
3360 return;
3362 Powers power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
3364 // Some level depends spells
3365 int level_multiplier = 0;
3366 int level_diff = 0;
3367 switch (m_spellInfo->Id)
3369 case 9512: // Restore Energy
3370 level_diff = m_caster->getLevel() - 40;
3371 level_multiplier = 2;
3372 break;
3373 case 24571: // Blood Fury
3374 level_diff = m_caster->getLevel() - 60;
3375 level_multiplier = 10;
3376 break;
3377 case 24532: // Burst of Energy
3378 level_diff = m_caster->getLevel() - 60;
3379 level_multiplier = 4;
3380 break;
3381 case 31930: // Judgements of the Wise
3382 case 48542: // Revitalize (mana restore case)
3383 case 63375: // Improved Stormstrike
3384 case 68082: // Glyph of Seal of Command
3385 damage = damage * unitTarget->GetCreateMana() / 100;
3386 break;
3387 default:
3388 break;
3391 if (level_diff > 0)
3392 damage -= level_multiplier * level_diff;
3394 if(damage < 0)
3395 return;
3397 if(unitTarget->GetMaxPower(power) == 0)
3398 return;
3400 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
3402 // Mad Alchemist's Potion
3403 if (m_spellInfo->Id == 45051)
3405 // find elixirs on target
3406 uint32 elixir_mask = 0;
3407 Unit::AuraMap& Auras = unitTarget->GetAuras();
3408 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
3410 uint32 spell_id = itr->second->GetId();
3411 if(uint32 mask = sSpellMgr.GetSpellElixirMask(spell_id))
3412 elixir_mask |= mask;
3415 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3416 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
3418 // get all available elixirs by mask and spell level
3419 std::vector<uint32> elixirs;
3420 SpellElixirMap const& m_spellElixirs = sSpellMgr.GetSpellElixirMap();
3421 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
3423 if (itr->second & elixir_mask)
3425 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
3426 continue;
3428 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
3429 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
3430 continue;
3432 elixirs.push_back(itr->first);
3436 if (!elixirs.empty())
3438 // cast random elixir on target
3439 uint32 rand_spell = urand(0,elixirs.size()-1);
3440 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
3445 void Spell::EffectEnergisePct(SpellEffectIndex eff_idx)
3447 if (!unitTarget)
3448 return;
3449 if (!unitTarget->isAlive())
3450 return;
3452 if (m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
3453 return;
3455 Powers power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
3457 uint32 maxPower = unitTarget->GetMaxPower(power);
3458 if (maxPower == 0)
3459 return;
3461 uint32 gain = damage * maxPower / 100;
3462 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
3465 void Spell::SendLoot(uint64 guid, LootType loottype)
3467 if (gameObjTarget)
3469 switch (gameObjTarget->GetGoType())
3471 case GAMEOBJECT_TYPE_DOOR:
3472 case GAMEOBJECT_TYPE_BUTTON:
3473 case GAMEOBJECT_TYPE_QUESTGIVER:
3474 case GAMEOBJECT_TYPE_SPELL_FOCUS:
3475 case GAMEOBJECT_TYPE_GOOBER:
3476 gameObjTarget->Use(m_caster);
3477 return;
3479 case GAMEOBJECT_TYPE_CHEST:
3480 gameObjTarget->Use(m_caster);
3481 // Don't return, let loots been taken
3482 break;
3484 default:
3485 sLog.outError("Spell::SendLoot unhandled GameObject type %u (entry %u).", gameObjTarget->GetGoType(), gameObjTarget->GetEntry());
3486 return;
3490 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3491 return;
3493 // Send loot
3494 ((Player*)m_caster)->SendLoot(guid, loottype);
3497 void Spell::EffectOpenLock(SpellEffectIndex eff_idx)
3499 if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
3501 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
3502 return;
3505 Player* player = (Player*)m_caster;
3507 uint32 lockId = 0;
3508 uint64 guid = 0;
3510 // Get lockId
3511 if (gameObjTarget)
3513 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3514 // Arathi Basin banner opening !
3515 if (goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
3516 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK)
3518 //CanUseBattleGroundObject() already called in CheckCast()
3519 // in battleground check
3520 if (BattleGround *bg = player->GetBattleGround())
3522 // check if it's correct bg
3523 if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
3524 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3525 return;
3528 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
3530 //CanUseBattleGroundObject() already called in CheckCast()
3531 // in battleground check
3532 if (BattleGround *bg = player->GetBattleGround())
3534 if (bg->GetTypeID() == BATTLEGROUND_EY)
3535 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3536 return;
3539 lockId = goInfo->GetLockId();
3540 guid = gameObjTarget->GetGUID();
3542 else if (itemTarget)
3544 lockId = itemTarget->GetProto()->LockID;
3545 guid = itemTarget->GetGUID();
3547 else
3549 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3550 return;
3553 SkillType skillId = SKILL_NONE;
3554 int32 reqSkillValue = 0;
3555 int32 skillValue;
3557 SpellCastResult res = CanOpenLock(eff_idx, lockId, skillId, reqSkillValue, skillValue);
3558 if (res != SPELL_CAST_OK)
3560 SendCastResult(res);
3561 return;
3564 SendLoot(guid, LOOT_SKINNING);
3566 // not allow use skill grow at item base open
3567 if (!m_CastItem && skillId != SKILL_NONE)
3569 // update skill if really known
3570 if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3572 if (gameObjTarget)
3574 // Allow one skill-up until respawned
3575 if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
3576 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
3577 gameObjTarget->AddToSkillupList(player->GetGUIDLow());
3579 else if (itemTarget)
3581 // Do one skill-up
3582 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3588 void Spell::EffectSummonChangeItem(SpellEffectIndex eff_idx)
3590 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3591 return;
3593 Player *player = (Player*)m_caster;
3595 // applied only to using item
3596 if (!m_CastItem)
3597 return;
3599 // ... only to item in own inventory/bank/equip_slot
3600 if (m_CastItem->GetOwnerGUID()!=player->GetGUID())
3601 return;
3603 uint32 newitemid = m_spellInfo->EffectItemType[eff_idx];
3604 if (!newitemid)
3605 return;
3607 uint16 pos = m_CastItem->GetPos();
3609 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3610 if (!pNewItem)
3611 return;
3613 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3615 if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3616 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3619 if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3621 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3622 player->DurabilityLoss(pNewItem, loosePercent);
3625 if (player->IsInventoryPos(pos))
3627 ItemPosCountVec dest;
3628 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3629 if (msg == EQUIP_ERR_OK)
3631 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3633 // prevent crash at access and unexpected charges counting with item update queue corrupt
3634 if (m_CastItem==m_targets.getItemTarget())
3635 m_targets.setItemTarget(NULL);
3637 m_CastItem = NULL;
3639 player->StoreItem( dest, pNewItem, true);
3640 return;
3643 else if (player->IsBankPos (pos))
3645 ItemPosCountVec dest;
3646 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3647 if (msg == EQUIP_ERR_OK)
3649 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3651 // prevent crash at access and unexpected charges counting with item update queue corrupt
3652 if (m_CastItem==m_targets.getItemTarget())
3653 m_targets.setItemTarget(NULL);
3655 m_CastItem = NULL;
3657 player->BankItem( dest, pNewItem, true);
3658 return;
3661 else if (player->IsEquipmentPos (pos))
3663 uint16 dest;
3664 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3665 if (msg == EQUIP_ERR_OK)
3667 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3669 // prevent crash at access and unexpected charges counting with item update queue corrupt
3670 if (m_CastItem==m_targets.getItemTarget())
3671 m_targets.setItemTarget(NULL);
3673 m_CastItem = NULL;
3675 player->EquipItem( dest, pNewItem, true);
3676 player->AutoUnequipOffhandIfNeed();
3677 return;
3681 // fail
3682 delete pNewItem;
3685 void Spell::EffectProficiency(SpellEffectIndex /*eff_idx*/)
3687 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3688 return;
3689 Player *p_target = (Player*)unitTarget;
3691 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3692 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3694 p_target->AddWeaponProficiency(subClassMask);
3695 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3697 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3699 p_target->AddArmorProficiency(subClassMask);
3700 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3704 void Spell::EffectApplyAreaAura(SpellEffectIndex eff_idx)
3706 if (!unitTarget)
3707 return;
3708 if (!unitTarget->isAlive())
3709 return;
3711 AreaAura* Aur = new AreaAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, m_caster, m_CastItem);
3712 unitTarget->AddAura(Aur);
3715 void Spell::EffectSummonType(SpellEffectIndex eff_idx)
3717 uint32 prop_id = m_spellInfo->EffectMiscValueB[eff_idx];
3718 SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
3719 if(!summon_prop)
3721 sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
3722 return;
3725 switch(summon_prop->Group)
3727 // faction handled later on, or loaded from template
3728 case SUMMON_PROP_GROUP_WILD:
3729 case SUMMON_PROP_GROUP_FRIENDLY:
3731 switch(summon_prop->Type)
3733 case SUMMON_PROP_TYPE_OTHER:
3735 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3736 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3737 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3738 if(prop_id == 121 || prop_id == 647)
3739 DoSummonTotem(eff_idx);
3740 else
3741 DoSummonWild(eff_idx, summon_prop->FactionId);
3742 break;
3744 case SUMMON_PROP_TYPE_SUMMON:
3745 case SUMMON_PROP_TYPE_GUARDIAN:
3746 case SUMMON_PROP_TYPE_ARMY:
3747 case SUMMON_PROP_TYPE_DK:
3748 case SUMMON_PROP_TYPE_CONSTRUCT:
3750 // JC golems - 32804, etc -- fits much better totem AI
3751 if(m_spellInfo->SpellIconID == 2056)
3752 DoSummonTotem(eff_idx);
3753 if(prop_id == 832) // scrapbot
3754 DoSummonWild(eff_idx, summon_prop->FactionId);
3755 else
3756 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3757 break;
3759 case SUMMON_PROP_TYPE_TOTEM:
3760 DoSummonTotem(eff_idx, summon_prop->Slot);
3761 break;
3762 case SUMMON_PROP_TYPE_CRITTER:
3763 DoSummonCritter(eff_idx, summon_prop->FactionId);
3764 break;
3765 case SUMMON_PROP_TYPE_PHASING:
3766 case SUMMON_PROP_TYPE_LIGHTWELL:
3767 case SUMMON_PROP_TYPE_REPAIR_BOT:
3768 DoSummonWild(eff_idx, summon_prop->FactionId);
3769 break;
3770 case SUMMON_PROP_TYPE_SIEGE_VEH:
3771 case SUMMON_PROP_TYPE_DRAKE_VEH:
3772 // TODO
3773 // EffectSummonVehicle(i);
3774 break;
3775 default:
3776 sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
3777 break;
3779 break;
3781 case SUMMON_PROP_GROUP_PETS:
3783 // FIXME : multiple summons - not yet supported as pet
3784 //1562 - force of nature - sid 33831
3785 //1161 - feral spirit - sid 51533
3786 if(prop_id == 1562) // 3 uncontrolable instead of one controllable :/
3787 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3788 else
3789 DoSummon(eff_idx);
3790 break;
3792 case SUMMON_PROP_GROUP_CONTROLLABLE:
3794 // no type here
3795 // maybe wrong - but thats the handler currently used for those
3796 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3797 break;
3799 case SUMMON_PROP_GROUP_VEHICLE:
3801 // TODO
3802 // EffectSummonVehicle(i);
3803 break;
3805 default:
3806 sLog.outError("EffectSummonType: Unhandled summon group type %u", summon_prop->Group);
3807 break;
3811 void Spell::DoSummon(SpellEffectIndex eff_idx)
3813 if (m_caster->GetPetGUID())
3814 return;
3816 if (!unitTarget)
3817 return;
3818 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
3819 if (!pet_entry)
3820 return;
3821 uint32 level = m_caster->getLevel();
3822 Pet* spawnCreature = new Pet(SUMMON_PET);
3824 int32 duration = GetSpellDuration(m_spellInfo);
3825 if(Player* modOwner = m_caster->GetSpellModOwner())
3826 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3828 if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3830 // Summon in dest location
3831 float x, y, z;
3832 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3834 x = m_targets.m_destX;
3835 y = m_targets.m_destY;
3836 z = m_targets.m_destZ;
3837 spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
3840 // set timer for unsummon
3841 if (duration > 0)
3842 spawnCreature->SetDuration(duration);
3844 return;
3847 Map *map = m_caster->GetMap();
3848 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3849 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3850 m_spellInfo->EffectMiscValue[eff_idx], pet_number))
3852 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[eff_idx]);
3853 delete spawnCreature;
3854 return;
3857 // Summon in dest location
3858 float x, y, z;
3859 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3861 x = m_targets.m_destX;
3862 y = m_targets.m_destY;
3863 z = m_targets.m_destZ;
3865 else
3866 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3868 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3869 spawnCreature->SetSummonPoint(x, y, z, -m_caster->GetOrientation());
3871 if (!spawnCreature->IsPositionValid())
3873 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3874 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3875 delete spawnCreature;
3876 return;
3879 // set timer for unsummon
3880 if (duration > 0)
3881 spawnCreature->SetDuration(duration);
3883 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3884 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3885 spawnCreature->setPowerType(POWER_MANA);
3886 spawnCreature->setFaction(m_caster->getFaction());
3887 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3888 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3889 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3890 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3891 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3892 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3893 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3894 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3896 spawnCreature->InitStatsForLevel(level, m_caster);
3898 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3900 spawnCreature->UpdateWalkMode(m_caster);
3902 spawnCreature->AIM_Initialize();
3903 spawnCreature->InitPetCreateSpells();
3904 spawnCreature->InitLevelupSpellsForLevel();
3905 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3906 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3908 std::string name = m_caster->GetName();
3909 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3910 spawnCreature->SetName( name );
3912 map->Add((Creature*)spawnCreature);
3914 m_caster->SetPet(spawnCreature);
3916 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3918 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3919 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3920 ((Player*)m_caster)->PetSpellInitialize();
3923 if (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
3924 ((Creature*)m_caster)->AI()->JustSummoned((Creature*)spawnCreature);
3927 void Spell::EffectLearnSpell(SpellEffectIndex eff_idx)
3929 if (!unitTarget)
3930 return;
3932 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3934 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3935 EffectLearnPetSpell(eff_idx);
3937 return;
3940 Player *player = (Player*)unitTarget;
3942 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[eff_idx];
3943 player->learnSpell(spellToLearn,false);
3945 sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3948 void Spell::EffectDispel(SpellEffectIndex eff_idx)
3950 if (!unitTarget)
3951 return;
3953 // Fill possible dispell list
3954 std::vector <Aura *> dispel_list;
3956 // Create dispel mask by dispel type
3957 uint32 dispel_type = m_spellInfo->EffectMiscValue[eff_idx];
3958 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3959 Unit::AuraMap const& auras = unitTarget->GetAuras();
3960 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3962 Aura *aur = (*itr).second;
3963 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3965 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3967 bool positive = true;
3968 if (!aur->IsPositive())
3969 positive = false;
3970 else
3971 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3973 // do not remove positive auras if friendly target
3974 // negative auras if non-friendly target
3975 if (positive == unitTarget->IsFriendlyTo(m_caster))
3976 continue;
3978 // Add aura to dispel list (all stack cases)
3979 for(int k = 0; k < aur->GetStackAmount(); ++k)
3980 dispel_list.push_back(aur);
3983 // Ok if exist some buffs for dispel try dispel it
3984 if (!dispel_list.empty())
3986 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3987 std::list < uint32 > fail_list; // spell_id
3989 // some spells have effect value = 0 and all from its by meaning expect 1
3990 if(!damage)
3991 damage = 1;
3993 // Dispell N = damage buffs (or while exist buffs for dispel)
3994 for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
3996 // Random select buff for dispel
3997 std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
3998 std::advance(dispel_itr,urand(0, dispel_list.size()-1));
4000 Aura *aur = *dispel_itr;
4002 // remove entry from dispel_list
4003 dispel_list.erase(dispel_itr);
4005 SpellEntry const* spellInfo = aur->GetSpellProto();
4006 // Base dispel chance
4007 // TODO: possible chance depend from spell level??
4008 int32 miss_chance = 0;
4009 // Apply dispel mod from aura caster
4010 if (Unit *caster = aur->GetCaster())
4012 if ( Player* modOwner = caster->GetSpellModOwner() )
4013 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
4015 // Try dispel
4016 if (roll_chance_i(miss_chance))
4017 fail_list.push_back(spellInfo->Id);
4018 else
4019 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
4021 // Send success log and really remove auras
4022 if (!success_list.empty())
4024 int32 count = success_list.size();
4025 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
4026 data << unitTarget->GetPackGUID(); // Victim GUID
4027 data << m_caster->GetPackGUID(); // Caster GUID
4028 data << uint32(m_spellInfo->Id); // Dispel spell id
4029 data << uint8(0); // not used
4030 data << uint32(count); // count
4031 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
4033 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
4034 data << uint32(spellInfo->Id); // Spell Id
4035 data << uint8(0); // 0 - dispeled !=0 cleansed
4036 unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
4038 m_caster->SendMessageToSet(&data, true);
4040 // On success dispel
4041 // Devour Magic
4042 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
4044 int32 heal_amount = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
4045 m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
4048 // Send fail log to client
4049 if (!fail_list.empty())
4051 // Failed to dispell
4052 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
4053 data << uint64(m_caster->GetGUID()); // Caster GUID
4054 data << uint64(unitTarget->GetGUID()); // Victim GUID
4055 data << uint32(m_spellInfo->Id); // Dispell spell id
4056 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
4057 data << uint32(*j); // Spell Id
4058 m_caster->SendMessageToSet(&data, true);
4063 void Spell::EffectDualWield(SpellEffectIndex /*eff_idx*/)
4065 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
4066 ((Player*)unitTarget)->SetCanDualWield(true);
4069 void Spell::EffectPull(SpellEffectIndex /*eff_idx*/)
4071 // TODO: create a proper pull towards distract spell center for distract
4072 sLog.outDebug("WORLD: Spell Effect DUMMY");
4075 void Spell::EffectDistract(SpellEffectIndex /*eff_idx*/)
4077 // Check for possible target
4078 if (!unitTarget || unitTarget->isInCombat())
4079 return;
4081 // target must be OK to do this
4082 if( unitTarget->hasUnitState(UNIT_STAT_CAN_NOT_REACT) )
4083 return;
4085 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
4087 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
4089 // For players just turn them
4090 WorldPacket data;
4091 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
4092 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
4093 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
4095 else
4097 // Set creature Distracted, Stop it, And turn it
4098 unitTarget->SetOrientation(angle);
4099 unitTarget->StopMoving();
4100 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
4104 void Spell::EffectPickPocket(SpellEffectIndex /*eff_idx*/)
4106 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4107 return;
4109 // victim must be creature and attackable
4110 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
4111 return;
4113 // victim have to be alive and humanoid or undead
4114 if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
4116 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
4118 if (chance > irand(0, 19))
4120 // Stealing successful
4121 //sLog.outDebug("Sending loot from pickpocket");
4122 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
4124 else
4126 // Reveal action + get attack
4127 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
4128 if (((Creature*)unitTarget)->AI())
4129 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
4134 void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
4136 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4137 return;
4139 int32 duration = GetSpellDuration(m_spellInfo);
4140 DynamicObject* dynObj = new DynamicObject;
4142 // set radius to 0: spell not expected to work as persistent aura
4143 if(!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, eff_idx, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, 0))
4145 delete dynObj;
4146 return;
4148 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
4149 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
4150 m_caster->AddDynObject(dynObj);
4151 m_caster->GetMap()->Add(dynObj);
4152 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
4155 void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction)
4157 uint32 creature_entry = m_spellInfo->EffectMiscValue[eff_idx];
4158 if (!creature_entry)
4159 return;
4161 uint32 level = m_caster->getLevel();
4163 // level of creature summoned using engineering item based at engineering skill level
4164 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
4166 ItemPrototype const *proto = m_CastItem->GetProto();
4167 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
4169 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
4170 if (skill202)
4171 level = skill202/5;
4175 // select center of summon position
4176 float center_x = m_targets.m_destX;
4177 float center_y = m_targets.m_destY;
4178 float center_z = m_targets.m_destZ;
4180 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4181 int32 duration = GetSpellDuration(m_spellInfo);
4182 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
4184 int32 amount = damage > 0 ? damage : 1;
4186 for(int32 count = 0; count < amount; ++count)
4188 float px, py, pz;
4189 // If dest location if present
4190 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4192 // Summon 1 unit in dest location
4193 if (count == 0)
4195 px = m_targets.m_destX;
4196 py = m_targets.m_destY;
4197 pz = m_targets.m_destZ;
4199 // Summon in random point all other units if location present
4200 else
4201 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
4203 // Summon if dest location not present near caster
4204 else
4205 m_caster->GetClosePoint(px, py, pz, 3.0f);
4207 if(Creature *summon = m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration))
4209 summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4210 summon->SetCreatorGUID(m_caster->GetGUID());
4212 if(forceFaction)
4213 summon->setFaction(forceFaction);
4218 void Spell::DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction)
4220 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
4221 if (!pet_entry)
4222 return;
4224 // in another case summon new
4225 uint32 level = m_caster->getLevel();
4227 // level of pet summoned using engineering item based at engineering skill level
4228 if (m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
4230 ItemPrototype const *proto = m_CastItem->GetProto();
4231 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
4233 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
4234 if (skill202)
4236 level = skill202 / 5;
4241 // select center of summon position
4242 float center_x = m_targets.m_destX;
4243 float center_y = m_targets.m_destY;
4244 float center_z = m_targets.m_destZ;
4246 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4247 int32 duration = GetSpellDuration(m_spellInfo);
4248 if(Player* modOwner = m_caster->GetSpellModOwner())
4249 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
4251 int32 amount = damage > 0 ? damage : 1;
4253 for(int32 count = 0; count < amount; ++count)
4255 Pet* spawnCreature = new Pet(GUARDIAN_PET);
4257 Map *map = m_caster->GetMap();
4258 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4259 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
4260 m_spellInfo->EffectMiscValue[eff_idx], pet_number))
4262 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[eff_idx]);
4263 delete spawnCreature;
4264 return;
4267 float px, py, pz;
4268 // If dest location if present
4269 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4271 // Summon 1 unit in dest location
4272 if (count == 0)
4274 px = m_targets.m_destX;
4275 py = m_targets.m_destY;
4276 pz = m_targets.m_destZ;
4278 // Summon in random point all other units if location present
4279 else
4280 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
4282 // Summon if dest location not present near caster
4283 else
4284 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
4286 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
4287 spawnCreature->SetSummonPoint(px, py, pz, m_caster->GetOrientation());
4289 if (!spawnCreature->IsPositionValid())
4291 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
4292 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
4293 delete spawnCreature;
4294 return;
4297 if (duration > 0)
4298 spawnCreature->SetDuration(duration);
4300 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
4301 spawnCreature->setPowerType(POWER_MANA);
4302 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
4303 spawnCreature->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
4304 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
4305 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4306 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
4307 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
4308 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4310 spawnCreature->InitStatsForLevel(level, m_caster);
4311 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
4313 spawnCreature->AIM_Initialize();
4315 m_caster->AddGuardian(spawnCreature);
4317 map->Add((Creature*)spawnCreature);
4321 void Spell::EffectTeleUnitsFaceCaster(SpellEffectIndex eff_idx)
4323 if (!unitTarget)
4324 return;
4326 if (unitTarget->isInFlight())
4327 return;
4329 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4331 float fx, fy, fz;
4332 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
4334 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
4337 void Spell::EffectLearnSkill(SpellEffectIndex eff_idx)
4339 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4340 return;
4342 if (damage < 0)
4343 return;
4345 uint32 skillid = m_spellInfo->EffectMiscValue[eff_idx];
4346 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
4347 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
4350 void Spell::EffectAddHonor(SpellEffectIndex /*eff_idx*/)
4352 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4353 return;
4355 // not scale value for item based reward (/10 value expected)
4356 if (m_CastItem)
4358 ((Player*)unitTarget)->RewardHonor(NULL, 1, float(damage / 10));
4359 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
4360 return;
4363 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4364 if (damage <= 50)
4366 float honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
4367 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
4368 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %f honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
4370 else
4372 //maybe we have correct honor_gain in damage already
4373 ((Player*)unitTarget)->RewardHonor(NULL, 1, (float)damage);
4374 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
4378 void Spell::EffectTradeSkill(SpellEffectIndex /*eff_idx*/)
4380 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4381 return;
4382 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4383 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4384 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4387 void Spell::EffectEnchantItemPerm(SpellEffectIndex eff_idx)
4389 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4390 return;
4391 if (!itemTarget)
4392 return;
4394 Player* p_caster = (Player*)m_caster;
4396 // not grow at item use at item case
4397 p_caster->UpdateCraftSkill(m_spellInfo->Id);
4399 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4400 if (!enchant_id)
4401 return;
4403 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4404 if (!pEnchant)
4405 return;
4407 // item can be in trade slot and have owner diff. from caster
4408 Player* item_owner = itemTarget->GetOwner();
4409 if (!item_owner)
4410 return;
4412 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4414 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4415 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4416 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4417 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4420 // remove old enchanting before applying new if equipped
4421 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
4423 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4425 // add new enchanting if equipped
4426 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
4428 // update trade window for show enchantment for caster in trade window
4429 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4430 p_caster->GetSession()->SendUpdateTrade();
4433 void Spell::EffectEnchantItemPrismatic(SpellEffectIndex eff_idx)
4435 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4436 return;
4437 if (!itemTarget)
4438 return;
4440 Player* p_caster = (Player*)m_caster;
4442 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4443 if (!enchant_id)
4444 return;
4446 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4447 if (!pEnchant)
4448 return;
4450 // support only enchantings with add socket in this slot
4452 bool add_socket = false;
4453 for(int i = 0; i < 3; ++i)
4455 if (pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
4457 add_socket = true;
4458 break;
4461 if (!add_socket)
4463 sLog.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (%u), not suppoted yet.",
4464 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
4465 return;
4469 // item can be in trade slot and have owner diff. from caster
4470 Player* item_owner = itemTarget->GetOwner();
4471 if (!item_owner)
4472 return;
4474 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4476 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4477 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4478 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4479 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4482 // remove old enchanting before applying new if equipped
4483 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
4485 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4487 // add new enchanting if equipped
4488 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
4490 // update trade window for show enchantment for caster in trade window
4491 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4492 p_caster->GetSession()->SendUpdateTrade();
4495 void Spell::EffectEnchantItemTmp(SpellEffectIndex eff_idx)
4497 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4498 return;
4500 Player* p_caster = (Player*)m_caster;
4502 // Rockbiter Weapon apply to both weapon
4503 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000))
4505 uint32 spell_id = 0;
4507 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4508 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4509 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4510 switch(damage)
4512 // Rank 1
4513 case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4514 // Rank 2
4515 case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
4516 case 5: spell_id = 36751; break; // 20%
4517 // Rank 3
4518 case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
4519 case 7: spell_id = 36755; break; // 20%
4520 // Rank 4
4521 case 9: spell_id = 36761; break; // 0% [ 7% == 6]
4522 case 10: spell_id = 36758; break; // 14%
4523 case 11: spell_id = 36760; break; // 20%
4524 default:
4525 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage);
4526 return;
4530 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
4531 if (!spellInfo)
4533 sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
4534 return;
4537 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
4539 if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
4541 if (item->IsFitToSpellRequirements(m_spellInfo))
4543 Spell *spell = new Spell(m_caster, spellInfo, true);
4544 SpellCastTargets targets;
4545 targets.setItemTarget( item );
4546 spell->prepare(&targets);
4550 return;
4553 if (!itemTarget)
4554 return;
4556 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4558 if (!enchant_id)
4560 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,eff_idx);
4561 return;
4564 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4565 if(!pEnchant)
4567 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,eff_idx,enchant_id);
4568 return;
4571 // select enchantment duration
4572 uint32 duration;
4574 // rogue family enchantments exception by duration
4575 if(m_spellInfo->Id == 38615) // Poison
4576 duration = 1800; // 30 mins
4577 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4578 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
4579 duration = 3600; // 1 hour
4580 // shaman family enchantments
4581 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
4582 duration = 1800; // 30 mins
4583 // other cases with this SpellVisual already selected
4584 else if(m_spellInfo->SpellVisual[0] == 215)
4585 duration = 1800; // 30 mins
4586 // some fishing pole bonuses
4587 else if(m_spellInfo->SpellVisual[0] == 563)
4588 duration = 600; // 10 mins
4589 // shaman rockbiter enchantments
4590 else if(m_spellInfo->SpellVisual[0] == 0)
4591 duration = 1800; // 30 mins
4592 else if(m_spellInfo->Id == 29702) // Greater Ward of Shielding
4593 duration = 300; // 5 mins
4594 else if(m_spellInfo->Id == 37360) // Consecrated Weapon
4595 duration = 300; // 5 mins
4596 // default case
4597 else
4598 duration = 3600; // 1 hour
4600 // item can be in trade slot and have owner diff. from caster
4601 Player* item_owner = itemTarget->GetOwner();
4602 if(!item_owner)
4603 return;
4605 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4607 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4608 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4609 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4610 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4613 // remove old enchanting before applying new if equipped
4614 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4616 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4618 // add new enchanting if equipped
4619 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4621 // update trade window for show enchantment for caster in trade window
4622 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4623 p_caster->GetSession()->SendUpdateTrade();
4626 void Spell::EffectTameCreature(SpellEffectIndex /*eff_idx*/)
4628 // Caster must be player, checked in Spell::CheckCast
4629 // Spell can be triggered, we need to check original caster prior to caster
4630 Player* plr = (Player*)GetAffectiveCaster();
4632 Creature* creatureTarget = (Creature*)unitTarget;
4634 // cast finish successfully
4635 //SendChannelUpdate(0);
4636 finish();
4638 Pet* pet = plr->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
4639 if(!pet) // in versy specific state like near world end/etc.
4640 return;
4642 // "kill" original creature
4643 creatureTarget->ForcedDespawn();
4645 uint32 level = (creatureTarget->getLevel() < (plr->getLevel() - 5)) ? (plr->getLevel() - 5) : creatureTarget->getLevel();
4647 // prepare visual effect for levelup
4648 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4650 // add to world
4651 pet->GetMap()->Add((Creature*)pet);
4653 // visual effect for levelup
4654 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4656 // caster have pet now
4657 plr->SetPet(pet);
4659 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4660 plr->PetSpellInitialize();
4663 void Spell::EffectSummonPet(SpellEffectIndex eff_idx)
4665 uint32 petentry = m_spellInfo->EffectMiscValue[eff_idx];
4667 Pet *OldSummon = m_caster->GetPet();
4669 // if pet requested type already exist
4670 if( OldSummon )
4672 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4674 // pet in corpse state can't be summoned
4675 if( OldSummon->isDead() )
4676 return;
4678 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4680 float px, py, pz;
4681 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4683 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4684 m_caster->GetMap()->Add((Creature*)OldSummon);
4686 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4688 ((Player*)m_caster)->PetSpellInitialize();
4690 return;
4693 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4694 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4695 else
4696 return;
4699 Pet* NewSummon = new Pet;
4701 // petentry==0 for hunter "call pet" (current pet summoned if any)
4702 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster, petentry))
4704 if(NewSummon->getPetType() == SUMMON_PET)
4706 // Remove Demonic Sacrifice auras (known pet)
4707 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4708 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4710 if((*itr)->GetModifier()->m_miscvalue == 2228)
4712 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4713 itr = auraClassScripts.begin();
4715 else
4716 ++itr;
4720 return;
4723 // not error in case fail hunter call pet
4724 if(!petentry)
4726 delete NewSummon;
4727 return;
4730 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4732 if(!cInfo)
4734 sLog.outError("EffectSummonPet: creature entry %u not found.", petentry);
4735 delete NewSummon;
4736 return;
4739 Map *map = m_caster->GetMap();
4740 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4741 if(!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4742 petentry, pet_number))
4744 delete NewSummon;
4745 return;
4748 float px, py, pz;
4749 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4751 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4753 if(!NewSummon->IsPositionValid())
4755 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4756 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4757 delete NewSummon;
4758 return;
4761 uint32 petlevel = m_caster->getLevel();
4762 NewSummon->setPetType(SUMMON_PET);
4764 uint32 faction = m_caster->getFaction();
4765 if(m_caster->GetTypeId() == TYPEID_UNIT)
4767 if ( ((Creature*)m_caster)->isTotem() )
4768 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4769 else
4770 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4773 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4774 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4775 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
4776 NewSummon->setFaction(faction);
4777 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4778 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4779 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL)));
4780 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4781 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4782 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4784 NewSummon->UpdateWalkMode(m_caster);
4786 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4787 // this enables pet details window (Shift+P)
4789 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4790 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4791 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
4793 if(m_caster->IsPvP())
4794 NewSummon->SetPvP(true);
4796 if(m_caster->IsFFAPvP())
4797 NewSummon->SetFFAPvP(true);
4799 NewSummon->InitStatsForLevel(petlevel, m_caster);
4800 NewSummon->InitPetCreateSpells();
4801 NewSummon->InitLevelupSpellsForLevel();
4802 NewSummon->InitTalentForLevel();
4804 if(NewSummon->getPetType() == SUMMON_PET)
4806 // Remove Demonic Sacrifice auras (new pet)
4807 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4808 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4810 if((*itr)->GetModifier()->m_miscvalue == 2228)
4812 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4813 itr = auraClassScripts.begin();
4815 else
4816 ++itr;
4819 // generate new name for summon pet
4820 std::string new_name = sObjectMgr.GeneratePetName(petentry);
4821 if(!new_name.empty())
4822 NewSummon->SetName(new_name);
4824 else if(NewSummon->getPetType() == HUNTER_PET)
4826 NewSummon->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
4827 NewSummon->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_ABANDONED);
4830 NewSummon->AIM_Initialize();
4831 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4832 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4834 map->Add((Creature*)NewSummon);
4836 m_caster->SetPet(NewSummon);
4837 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4839 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4841 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4842 ((Player*)m_caster)->PetSpellInitialize();
4846 void Spell::EffectLearnPetSpell(SpellEffectIndex eff_idx)
4848 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4849 return;
4851 Player *_player = (Player*)m_caster;
4853 Pet *pet = _player->GetPet();
4854 if(!pet)
4855 return;
4856 if(!pet->isAlive())
4857 return;
4859 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[eff_idx]);
4860 if(!learn_spellproto)
4861 return;
4863 pet->learnSpell(learn_spellproto->Id);
4865 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4866 _player->PetSpellInitialize();
4869 void Spell::EffectTaunt(SpellEffectIndex /*eff_idx*/)
4871 if (!unitTarget)
4872 return;
4874 // this effect use before aura Taunt apply for prevent taunt already attacking target
4875 // for spell as marked "non effective at already attacking target"
4876 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4878 if (unitTarget->getVictim()==m_caster)
4880 SendCastResult(SPELL_FAILED_DONT_REPORT);
4881 return;
4885 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4886 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4887 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4890 void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
4892 if(!unitTarget)
4893 return;
4894 if(!unitTarget->isAlive())
4895 return;
4897 // multiple weapon dmg effect workaround
4898 // execute only the last weapon damage
4899 // and handle all effects at once
4900 for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
4902 switch(m_spellInfo->Effect[j])
4904 case SPELL_EFFECT_WEAPON_DAMAGE:
4905 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4906 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4907 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4908 if (j < int(eff_idx)) // we must calculate only at last weapon effect
4909 return;
4910 break;
4914 // some spell specific modifiers
4915 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4917 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4918 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4919 bool normalized = false;
4921 int32 spell_bonus = 0; // bonus specific for spell
4922 switch(m_spellInfo->SpellFamilyName)
4924 case SPELLFAMILY_WARRIOR:
4926 // Devastate bonus and sunder armor refresh
4927 if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
4929 uint32 stack = 0;
4930 // Need refresh all Sunder Armor auras from this caster
4931 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4932 SpellEntry const *spellInfo;
4933 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4935 spellInfo = (*itr).second->GetSpellProto();
4936 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4937 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4938 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4940 (*itr).second->RefreshAura();
4941 stack = (*itr).second->GetStackAmount();
4942 break;
4945 if (stack)
4946 spell_bonus += stack * CalculateDamage(EFFECT_INDEX_2, unitTarget);
4947 if (!stack || stack < spellInfo->StackAmount)
4948 // Devastate causing Sunder Armor Effect
4949 // and no need to cast over max stack amount
4950 m_caster->CastSpell(unitTarget, 58567, true);
4952 break;
4954 case SPELLFAMILY_ROGUE:
4956 // Mutilate (for each hand)
4957 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4959 bool found = false;
4960 // fast check
4961 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4962 found = true;
4963 // full aura scan
4964 else
4966 Unit::AuraMap const& auras = unitTarget->GetAuras();
4967 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4969 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4971 found = true;
4972 break;
4977 if(found)
4978 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4980 // Fan of Knives
4981 else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
4983 Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,true);
4984 if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
4985 totalDamagePercentMod *= 1.5f; // 150% to daggers
4987 break;
4989 case SPELLFAMILY_PALADIN:
4991 // Judgement of Command - receive benefit from Spell Damage and Attack Power
4992 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000000000))
4994 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
4995 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
4996 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
4997 spell_bonus += int32(ap * 0.08f) + int32(holy * 13 / 100);
4999 break;
5001 case SPELLFAMILY_HUNTER:
5003 // Kill Shot
5004 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x80000000000000))
5006 // 0.4*RAP added to damage (that is 0.2 if we apply PercentMod (200%) to spell_bonus, too)
5007 spellBonusNeedWeaponDamagePercentMod = true;
5008 spell_bonus += int32( 0.2f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK) );
5010 break;
5012 case SPELLFAMILY_SHAMAN:
5014 // Skyshatter Harness item set bonus
5015 // Stormstrike
5016 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
5018 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5019 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
5021 // Stormstrike AP Buff
5022 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
5024 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
5025 break;
5029 break;
5031 case SPELLFAMILY_DEATHKNIGHT:
5033 // Blood Strike, Heart Strike, Obliterate
5034 // Blood-Caked Strike, Scourge Strike
5035 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
5036 m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
5038 uint32 count = 0;
5039 Unit::AuraMap const& auras = unitTarget->GetAuras();
5040 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
5042 if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
5043 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
5044 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
5045 ++count;
5048 if (count)
5050 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
5051 float bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? EFFECT_INDEX_0 : EFFECT_INDEX_2, unitTarget) / 100.0f;
5052 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
5053 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
5054 m_spellInfo->SpellIconID == 1736)
5055 bonus /= 2.0f;
5057 totalDamagePercentMod *= 1.0f + bonus;
5060 // Heart Strike secondary target
5061 if (m_spellInfo->SpellIconID == 3145)
5062 if (m_targets.getUnitTarget() != unitTarget)
5063 weaponDamagePercentMod /= 2.0f;
5065 // Glyph of Blood Strike
5066 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000) &&
5067 m_caster->HasAura(59332) &&
5068 unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
5070 totalDamagePercentMod *= 1.2f; // 120% if snared
5072 // Glyph of Death Strike
5073 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010) &&
5074 m_caster->HasAura(59336))
5076 int32 rp = m_caster->GetPower(POWER_RUNIC_POWER) / 10;
5077 if(rp > 25)
5078 rp = 25;
5079 totalDamagePercentMod *= 1.0f + rp / 100.0f;
5081 // Glyph of Plague Strike
5082 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001) &&
5083 m_caster->HasAura(58657) )
5085 totalDamagePercentMod *= 1.2f;
5087 break;
5091 int32 fixed_bonus = 0;
5092 for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
5094 switch(m_spellInfo->Effect[j])
5096 case SPELL_EFFECT_WEAPON_DAMAGE:
5097 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
5098 fixed_bonus += CalculateDamage(SpellEffectIndex(j), unitTarget);
5099 break;
5100 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
5101 fixed_bonus += CalculateDamage(SpellEffectIndex(j), unitTarget);
5102 normalized = true;
5103 break;
5104 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
5105 weaponDamagePercentMod *= float(CalculateDamage(SpellEffectIndex(j), unitTarget)) / 100.0f;
5107 // applied only to prev.effects fixed damage
5108 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
5109 break;
5110 default:
5111 break; // not weapon damage effect, just skip
5115 // apply weaponDamagePercentMod to spell bonus also
5116 if(spellBonusNeedWeaponDamagePercentMod)
5117 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
5119 // non-weapon damage
5120 int32 bonus = spell_bonus + fixed_bonus;
5122 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
5123 if(bonus)
5125 UnitMods unitMod;
5126 switch(m_attackType)
5128 default:
5129 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
5130 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
5131 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
5134 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
5135 bonus = int32(bonus*weapon_total_pct);
5138 // + weapon damage with applied weapon% dmg to base weapon damage in call
5139 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
5141 // total damage
5142 bonus = int32(bonus*totalDamagePercentMod);
5144 // prevent negative damage
5145 m_damage+= uint32(bonus > 0 ? bonus : 0);
5147 // Hemorrhage
5148 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
5150 if(m_caster->GetTypeId()==TYPEID_PLAYER)
5151 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
5153 // Mangle (Cat): CP
5154 else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
5156 if(m_caster->GetTypeId()==TYPEID_PLAYER)
5157 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
5160 // take ammo
5161 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
5163 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK, true, false);
5165 // wands don't have ammo
5166 if (!pItem || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
5167 return;
5169 if (pItem->GetProto()->InventoryType == INVTYPE_THROWN)
5171 if(pItem->GetMaxStackCount()==1)
5173 // decrease durability for non-stackable throw weapon
5174 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
5176 else
5178 // decrease items amount for stackable throw weapon
5179 uint32 count = 1;
5180 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
5183 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
5184 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
5188 void Spell::EffectThreat(SpellEffectIndex /*eff_idx*/)
5190 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
5191 return;
5193 if(!unitTarget->CanHaveThreatList())
5194 return;
5196 unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
5199 void Spell::EffectHealMaxHealth(SpellEffectIndex /*eff_idx*/)
5201 if(!unitTarget)
5202 return;
5203 if(!unitTarget->isAlive())
5204 return;
5206 uint32 heal = m_caster->GetMaxHealth();
5208 m_healing += heal;
5211 void Spell::EffectInterruptCast(SpellEffectIndex /*eff_idx*/)
5213 if(!unitTarget)
5214 return;
5215 if(!unitTarget->isAlive())
5216 return;
5218 // TODO: not all spells that used this effect apply cooldown at school spells
5219 // also exist case: apply cooldown to interrupted cast only and to all spells
5220 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
5222 if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
5224 SpellEntry const* curSpellInfo = spell->m_spellInfo;
5225 // check if we can interrupt spell
5226 if ((curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
5228 unitTarget->ProhibitSpellSchool(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo));
5229 unitTarget->InterruptSpell(CurrentSpellTypes(i),false);
5235 void Spell::EffectSummonObjectWild(SpellEffectIndex eff_idx)
5237 uint32 gameobject_id = m_spellInfo->EffectMiscValue[eff_idx];
5239 GameObject* pGameObj = new GameObject;
5241 WorldObject* target = focusObject;
5242 if( !target )
5243 target = m_caster;
5245 float x, y, z;
5246 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5248 x = m_targets.m_destX;
5249 y = m_targets.m_destY;
5250 z = m_targets.m_destZ;
5252 else
5253 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
5255 Map *map = target->GetMap();
5257 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5258 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
5260 delete pGameObj;
5261 return;
5264 int32 duration = GetSpellDuration(m_spellInfo);
5266 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
5267 pGameObj->SetSpellId(m_spellInfo->Id);
5269 // Wild object not have owner and check clickable by players
5270 map->Add(pGameObj);
5272 if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER)
5274 Player *pl = (Player*)m_caster;
5275 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
5277 switch(pGameObj->GetMapId())
5279 case 489: //WS
5281 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
5283 uint32 team = ALLIANCE;
5285 if(pl->GetTeam() == team)
5286 team = HORDE;
5288 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
5290 break;
5292 case 566: //EY
5294 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
5296 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
5298 break;
5303 pGameObj->SummonLinkedTrapIfAny();
5306 void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
5308 // TODO: we must implement hunter pet summon at login there (spell 6962)
5310 switch(m_spellInfo->SpellFamilyName)
5312 case SPELLFAMILY_GENERIC:
5314 switch(m_spellInfo->Id)
5316 case 8856: // Bending Shinbone
5318 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
5319 return;
5321 uint32 spell_id = 0;
5322 switch(urand(1, 5))
5324 case 1: spell_id = 8854; break;
5325 default: spell_id = 8855; break;
5328 m_caster->CastSpell(m_caster,spell_id,true,NULL);
5329 return;
5331 case 17512: // Piccolo of the Flaming Fire
5333 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5334 return;
5336 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
5337 return;
5339 case 20589: // Escape artist
5341 if (!unitTarget)
5342 return;
5344 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5345 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5346 return;
5348 case 24590: // Brittle Armor - need remove one 24575 Brittle Armor aura
5349 unitTarget->RemoveSingleSpellAurasFromStack(24575);
5350 return;
5351 case 26275: // PX-238 Winter Wondervolt TRAP
5353 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
5355 // check presence
5356 for(int j = 0; j < 4; ++j)
5357 if (unitTarget->HasAura(spells[j], EFFECT_INDEX_0))
5358 return;
5360 // select spell
5361 uint32 iTmpSpellId = spells[urand(0,3)];
5363 // cast
5364 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
5365 return;
5367 case 26465: // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5368 unitTarget->RemoveSingleSpellAurasFromStack(26464);
5369 return;
5370 case 25140: // Orb teleport spells
5371 case 25143:
5372 case 25650:
5373 case 25652:
5374 case 29128:
5375 case 29129:
5376 case 35376:
5377 case 35727:
5379 if (!unitTarget)
5380 return;
5382 uint32 spellid;
5383 switch(m_spellInfo->Id)
5385 case 25140: spellid = 32571; break;
5386 case 25143: spellid = 32572; break;
5387 case 25650: spellid = 30140; break;
5388 case 25652: spellid = 30141; break;
5389 case 29128: spellid = 32568; break;
5390 case 29129: spellid = 32569; break;
5391 case 35376: spellid = 25649; break;
5392 case 35727: spellid = 35730; break;
5393 default:
5394 return;
5397 unitTarget->CastSpell(unitTarget,spellid,false);
5398 return;
5400 case 22539: // Shadow Flame (All script effects, not just end ones to
5401 case 22972: // prevent player from dodging the last triggered spell)
5402 case 22975:
5403 case 22976:
5404 case 22977:
5405 case 22978:
5406 case 22979:
5407 case 22980:
5408 case 22981:
5409 case 22982:
5410 case 22983:
5411 case 22984:
5412 case 22985:
5414 if (!unitTarget || !unitTarget->isAlive())
5415 return;
5417 // Onyxia Scale Cloak
5418 if (unitTarget->GetDummyAura(22683))
5419 return;
5421 // Shadow Flame
5422 m_caster->CastSpell(unitTarget, 22682, true);
5423 return;
5425 case 26656: // Summon Black Qiraji Battle Tank
5427 if (!unitTarget)
5428 return;
5430 // Prevent stacking of mounts
5431 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5433 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5434 if (unitTarget->GetAreaId() == 3428)
5435 unitTarget->CastSpell(unitTarget, 25863, false);
5436 else
5437 unitTarget->CastSpell(unitTarget, 26655, false);
5439 return;
5441 case 29830: // Mirren's Drinking Hat
5443 uint32 item = 0;
5444 switch ( urand(1, 6) )
5446 case 1:
5447 case 2:
5448 case 3:
5449 item = 23584; break; // Loch Modan Lager
5450 case 4:
5451 case 5:
5452 item = 23585; break; // Stouthammer Lite
5453 case 6:
5454 item = 23586; break; // Aerie Peak Pale Ale
5457 if (item)
5458 DoCreateItem(eff_idx,item);
5460 break;
5462 case 30918: // Improved Sprint
5464 if (!unitTarget)
5465 return;
5467 // Removes snares and roots.
5468 unitTarget->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK,30918,true);
5469 break;
5471 case 41126: // Flame Crash
5473 if (!unitTarget)
5474 return;
5476 unitTarget->CastSpell(unitTarget, 41131, true);
5477 break;
5479 case 44455: // Character Script Effect Reverse Cast
5481 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
5482 return;
5484 Creature* pTarget = (Creature*)unitTarget;
5486 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(m_spellInfo->CalculateSimpleValue(eff_idx)))
5488 // if we used item at least once...
5489 if (pTarget->isTemporarySummon() && pTarget->GetEntry() == pSpell->EffectMiscValue[eff_idx])
5491 TemporarySummon* pSummon = (TemporarySummon*)pTarget;
5493 // can only affect "own" summoned
5494 if (pSummon->GetSummonerGuid() == m_caster->GetObjectGuid())
5496 if (pTarget->hasUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE))
5497 pTarget->GetMotionMaster()->MovementExpired();
5499 pTarget->GetMotionMaster()->MovePoint(0, m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ());
5502 return;
5505 // or if we are first time used item
5506 m_caster->CastSpell(pTarget, pSpell, true);
5507 pTarget->ForcedDespawn();
5510 return;
5512 case 44876: // Force Cast - Portal Effect: Sunwell Isle
5514 if (!unitTarget)
5515 return;
5517 unitTarget->CastSpell(unitTarget, 44870, true);
5518 break;
5520 case 45668: // Ultra-Advanced Proto-Typical Shortening Blaster
5522 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
5523 return;
5525 if (roll_chance_i(25)) // chance unknown, using 25
5526 return;
5528 static uint32 const spellPlayer[5] =
5530 45674, // Bigger!
5531 45675, // Shrunk
5532 45678, // Yellow
5533 45682, // Ghost
5534 45684 // Polymorph
5537 static uint32 const spellTarget[5] =
5539 45673, // Bigger!
5540 45672, // Shrunk
5541 45677, // Yellow
5542 45681, // Ghost
5543 45683 // Polymorph
5546 m_caster->CastSpell(m_caster, spellPlayer[urand(0,4)], true);
5547 unitTarget->CastSpell(unitTarget, spellTarget[urand(0,4)], true);
5549 return;
5551 case 45691: // Magnataur On Death 1
5553 // assuming caster is creature, if not, then return
5554 if (m_caster->GetTypeId() != TYPEID_UNIT)
5555 return;
5557 Player* pPlayer = ((Creature*)m_caster)->GetLootRecipient();
5559 if (!pPlayer)
5560 return;
5562 if (pPlayer->HasAura(45674) || pPlayer->HasAura(45675) || pPlayer->HasAura(45678) || pPlayer->HasAura(45682) || pPlayer->HasAura(45684))
5563 pPlayer->CastSpell(pPlayer, 45686, true);
5565 m_caster->CastSpell(m_caster, 45685, true);
5567 return;
5569 case 46203: // Goblin Weather Machine
5571 if (!unitTarget)
5572 return;
5574 uint32 spellId = 0;
5575 switch(rand() % 4)
5577 case 0: spellId = 46740; break;
5578 case 1: spellId = 46739; break;
5579 case 2: spellId = 46738; break;
5580 case 3: spellId = 46736; break;
5582 unitTarget->CastSpell(unitTarget, spellId, true);
5583 break;
5585 case 46642: //5,000 Gold
5587 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5588 return;
5590 ((Player*)unitTarget)->ModifyMoney(50000000);
5591 break;
5593 case 47097: // Surge Needle Teleporter
5595 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5596 return;
5598 if (unitTarget->GetAreaId() == 4156)
5599 unitTarget->CastSpell(unitTarget, 47324, true);
5600 else if (unitTarget->GetAreaId() == 4157)
5601 unitTarget->CastSpell(unitTarget, 47325, true);
5603 break;
5605 case 48603: // High Executor's Branding Iron
5606 // Torture the Torturer: High Executor's Branding Iron Impact
5607 unitTarget->CastSpell(unitTarget, 48614, true);
5608 return;
5609 case 51770: // Emblazon Runeblade
5611 Unit* caster = GetAffectiveCaster();
5612 if (!caster)
5613 return;
5615 caster->CastSpell(caster, damage, false);
5616 break;
5618 case 52751: // Death Gate
5620 if (!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
5621 return;
5623 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5624 unitTarget->CastSpell(unitTarget, damage, false);
5625 break;
5627 case 54729: // Winged Steed of the Ebon Blade
5629 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5630 return;
5632 // Prevent stacking of mounts
5633 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5635 // Triggered spell id dependent of riding skill
5636 if (uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
5638 if (skillval >= 300)
5639 unitTarget->CastSpell(unitTarget, 54727, true);
5640 else
5641 unitTarget->CastSpell(unitTarget, 54726, true);
5643 return;
5645 case 54436: // Demonic Empowerment (succubus Vanish effect)
5647 if (!unitTarget)
5648 return;
5650 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5651 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5652 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
5653 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN);
5654 return;
5656 case 55693: // Remove Collapsing Cave Aura
5658 if (!unitTarget)
5659 return;
5661 unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(eff_idx));
5662 break;
5664 case 58418: // Portal to Orgrimmar
5665 case 58420: // Portal to Stormwind
5667 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || eff_idx != EFFECT_INDEX_0)
5668 return;
5670 uint32 spellID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0);
5671 uint32 questID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
5673 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
5674 unitTarget->CastSpell(unitTarget, spellID, true);
5676 return;
5678 case 59317: // Teleporting
5680 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5681 return;
5683 // return from top
5684 if (((Player*)unitTarget)->GetAreaId() == 4637)
5685 unitTarget->CastSpell(unitTarget, 59316, true);
5686 // teleport atop
5687 else
5688 unitTarget->CastSpell(unitTarget, 59314, true);
5690 return;
5691 } // random spell learn instead placeholder
5692 case 60893: // Northrend Alchemy Research
5693 case 61177: // Northrend Inscription Research
5694 case 61288: // Minor Inscription Research
5695 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5696 case 64323: // Book of Glyph Mastery
5698 if (m_caster->GetTypeId() != TYPEID_PLAYER)
5699 return;
5701 // learn random explicit discovery recipe (if any)
5702 if (uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
5703 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
5705 return;
5707 case 69377: //Fortitude
5709 if (!unitTarget)
5710 return;
5712 m_caster->CastSpell(unitTarget, 72590, true);
5713 return;
5715 case 69378: //Blessing of Forgotten Kings
5717 if (!unitTarget)
5718 return;
5720 m_caster->CastSpell(unitTarget, 72586, true);
5721 return;
5723 case 69381: //Gift of the Wild
5725 if (!unitTarget)
5726 return;
5728 m_caster->CastSpell(unitTarget, 72588, true);
5729 return;
5732 break;
5734 case SPELLFAMILY_WARLOCK:
5736 switch(m_spellInfo->Id)
5738 case 6201: // Healthstone creating spells
5739 case 6202:
5740 case 5699:
5741 case 11729:
5742 case 11730:
5743 case 27230:
5744 case 47871:
5745 case 47878:
5747 if (!unitTarget)
5748 return;
5750 uint32 itemtype;
5751 uint32 rank = 0;
5752 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5753 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
5755 if ((*i)->GetId() == 18692)
5757 rank = 1;
5758 break;
5760 else if ((*i)->GetId() == 18693)
5762 rank = 2;
5763 break;
5767 static uint32 const itypes[8][3] =
5769 { 5512, 19004, 19005}, // Minor Healthstone
5770 { 5511, 19006, 19007}, // Lesser Healthstone
5771 { 5509, 19008, 19009}, // Healthstone
5772 { 5510, 19010, 19011}, // Greater Healthstone
5773 { 9421, 19012, 19013}, // Major Healthstone
5774 {22103, 22104, 22105}, // Master Healthstone
5775 {36889, 36890, 36891}, // Demonic Healthstone
5776 {36892, 36893, 36894} // Fel Healthstone
5779 switch(m_spellInfo->Id)
5781 case 6201:
5782 itemtype=itypes[0][rank];break; // Minor Healthstone
5783 case 6202:
5784 itemtype=itypes[1][rank];break; // Lesser Healthstone
5785 case 5699:
5786 itemtype=itypes[2][rank];break; // Healthstone
5787 case 11729:
5788 itemtype=itypes[3][rank];break; // Greater Healthstone
5789 case 11730:
5790 itemtype=itypes[4][rank];break; // Major Healthstone
5791 case 27230:
5792 itemtype=itypes[5][rank];break; // Master Healthstone
5793 case 47871:
5794 itemtype=itypes[6][rank];break; // Demonic Healthstone
5795 case 47878:
5796 itemtype=itypes[7][rank];break; // Fel Healthstone
5797 default:
5798 return;
5800 DoCreateItem( eff_idx, itemtype );
5801 return;
5803 case 47193: // Demonic Empowerment
5805 if (!unitTarget)
5806 return;
5808 uint32 entry = unitTarget->GetEntry();
5809 uint32 spellID;
5810 switch(entry)
5812 case 416: spellID = 54444; break; //imp
5813 case 417: spellID = 54509; break; //fellhunter
5814 case 1860: spellID = 54443; break; //void
5815 case 1863: spellID = 54435; break; //succubus
5816 case 17252: spellID = 54508; break; //fellguard
5817 default:
5818 return;
5820 unitTarget->CastSpell(unitTarget,spellID,true);
5821 return;
5823 case 47422: // Everlasting Affliction
5825 // Need refresh caster corruption auras on target
5826 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5827 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5829 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5830 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5831 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5832 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5833 (*itr).second->RefreshAura();
5835 return;
5837 case 63521: // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5839 // Divine Plea, refresh on target (3 aura slots)
5840 if (Aura* aura = unitTarget->GetAura(54428, EFFECT_INDEX_0))
5841 aura->RefreshAura();
5843 return;
5846 break;
5848 case SPELLFAMILY_PRIEST:
5850 switch(m_spellInfo->Id)
5852 case 47948: // Pain and Suffering
5854 if (!unitTarget)
5855 return;
5857 // Refresh Shadow Word: Pain on target
5858 Unit::AuraMap& auras = unitTarget->GetAuras();
5859 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5861 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5862 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5863 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5864 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5866 (*itr).second->RefreshAura();
5867 return;
5870 return;
5872 default:
5873 break;
5875 break;
5877 case SPELLFAMILY_HUNTER:
5879 switch(m_spellInfo->Id)
5881 case 53209: // Chimera Shot
5883 if (!unitTarget)
5884 return;
5886 uint32 spellId = 0;
5887 int32 basePoint = 0;
5888 Unit* target = unitTarget;
5889 Unit::AuraMap& Auras = unitTarget->GetAuras();
5890 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5892 Aura *aura = (*i).second;
5893 if (aura->GetCasterGUID() != m_caster->GetGUID())
5894 continue;
5896 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5897 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5898 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5899 continue;
5901 // Refresh aura duration
5902 aura->RefreshAura();
5904 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5905 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
5907 // m_amount already include RAP bonus
5908 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5909 spellId = 53353; // Chimera Shot - Serpent
5912 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5913 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
5915 uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
5916 if (!target_max_mana)
5917 continue;
5919 // ignore non positive values (can be result apply spellmods to aura damage
5920 uint32 pdamage = aura->GetModifier()->m_amount > 0 ? aura->GetModifier()->m_amount : 0;
5922 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5923 uint32 maxmana = m_caster->GetMaxPower(POWER_MANA) * pdamage * 2 / 100;
5925 pdamage = target_max_mana * pdamage / 100;
5926 if (pdamage > maxmana)
5927 pdamage = maxmana;
5929 pdamage *= 4; // total aura damage
5930 basePoint = pdamage * 60 / 100;
5931 spellId = 53358; // Chimera Shot - Viper
5932 target = m_caster;
5935 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5936 if (familyFlag & UI64LIT(0x0000000000008000))
5937 spellId = 53359; // Chimera Shot - Scorpid
5938 // ?? nothing say in spell desc (possibly need addition check)
5939 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5940 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5942 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5946 if (spellId)
5947 m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
5949 return;
5951 case 53412: // Invigoration (pet triggered script, master targeted)
5953 if (!unitTarget)
5954 return;
5956 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5957 for(Unit::AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
5959 // Invigoration (master talent)
5960 if ((*i)->GetModifier()->m_miscvalue == 8 && (*i)->GetSpellProto()->SpellIconID == 3487)
5962 if (roll_chance_i((*i)->GetModifier()->m_amount))
5964 unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetGUID());
5965 break;
5969 return;
5971 case 53271: // Master's Call
5973 if (!unitTarget)
5974 return;
5976 // script effect have in value, but this outdated removed part
5977 unitTarget->CastSpell(unitTarget, 62305, true);
5978 return;
5980 default:
5981 break;
5983 break;
5985 case SPELLFAMILY_PALADIN:
5987 // Judgement (seal trigger)
5988 if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
5990 if (!unitTarget || !unitTarget->isAlive())
5991 return;
5993 uint32 spellId1 = 0;
5994 uint32 spellId2 = 0;
5996 // Judgement self add switch
5997 switch (m_spellInfo->Id)
5999 case 53407: spellId1 = 20184; break; // Judgement of Justice
6000 case 20271: // Judgement of Light
6001 case 57774: spellId1 = 20185; break; // Judgement of Light
6002 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
6003 default:
6004 sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
6005 return;
6008 // offensive seals have aura dummy in 2 effect
6009 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
6010 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
6012 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
6013 if ((*itr)->GetEffIndex() != EFFECT_INDEX_2 || !IsSealSpell((*itr)->GetSpellProto()))
6014 continue;
6015 spellId2 = (*itr)->GetModifier()->m_amount;
6016 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
6017 if (!judge)
6018 continue;
6019 break;
6022 // if there were no offensive seals than there is seal with proc trigger aura
6023 if (!spellId2)
6025 Unit::AuraList const& procTriggerAuras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
6026 for(Unit::AuraList::const_iterator itr = procTriggerAuras.begin(); itr != procTriggerAuras.end(); ++itr)
6028 if ((*itr)->GetEffIndex() != EFFECT_INDEX_0 || !IsSealSpell((*itr)->GetSpellProto()))
6029 continue;
6030 spellId2 = 54158;
6031 break;
6035 if (spellId1)
6036 m_caster->CastSpell(unitTarget, spellId1, true);
6038 if (spellId2)
6039 m_caster->CastSpell(unitTarget, spellId2, true);
6041 return;
6044 case SPELLFAMILY_POTION:
6046 switch(m_spellInfo->Id)
6048 case 28698: // Dreaming Glory
6050 if (!unitTarget)
6051 return;
6053 unitTarget->CastSpell(unitTarget, 28694, true);
6054 break;
6056 case 28702: // Netherbloom
6058 if (!unitTarget)
6059 return;
6061 // 25% chance of casting a random buff
6062 if (roll_chance_i(75))
6063 return;
6065 // triggered spells are 28703 to 28707
6066 // Note: some sources say, that there was the possibility of
6067 // receiving a debuff. However, this seems to be removed by a patch.
6068 const uint32 spellid = 28703;
6070 // don't overwrite an existing aura
6071 for(uint8 i = 0; i < 5; ++i)
6072 if (unitTarget->HasAura(spellid + i, EFFECT_INDEX_0))
6073 return;
6075 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
6076 break;
6078 case 28720: // Nightmare Vine
6080 if (!unitTarget)
6081 return;
6083 // 25% chance of casting Nightmare Pollen
6084 if (roll_chance_i(75))
6085 return;
6087 unitTarget->CastSpell(unitTarget, 28721, true);
6088 break;
6091 break;
6093 case SPELLFAMILY_DEATHKNIGHT:
6095 switch(m_spellInfo->Id)
6097 case 50842: // Pestilence
6099 if (!unitTarget)
6100 return;
6102 Unit* mainTarget = m_targets.getUnitTarget();
6103 if (!mainTarget)
6104 return;
6106 // do only refresh diseases on main target if caster has Glyph of Disease
6107 if (mainTarget == unitTarget && !m_caster->HasAura(63334))
6108 return;
6110 // Blood Plague
6111 if (mainTarget->HasAura(55078))
6112 m_caster->CastSpell(unitTarget, 55078, true);
6114 // Frost Fever
6115 if (mainTarget->HasAura(55095))
6116 m_caster->CastSpell(unitTarget, 55095, true);
6118 break;
6121 break;
6125 // normal DB scripted effect
6126 if (!unitTarget)
6127 return;
6129 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
6130 m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
6133 void Spell::EffectSanctuary(SpellEffectIndex /*eff_idx*/)
6135 if(!unitTarget)
6136 return;
6137 //unitTarget->CombatStop();
6139 unitTarget->CombatStop();
6140 unitTarget->getHostileRefManager().deleteReferences(); // stop all fighting
6141 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
6142 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
6144 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
6148 void Spell::EffectAddComboPoints(SpellEffectIndex /*eff_idx*/)
6150 if(!unitTarget)
6151 return;
6153 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6154 return;
6156 if(damage <= 0)
6157 return;
6159 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
6162 void Spell::EffectDuel(SpellEffectIndex eff_idx)
6164 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
6165 return;
6167 Player *caster = (Player*)m_caster;
6168 Player *target = (Player*)unitTarget;
6170 // caster or target already have requested duel
6171 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
6172 return;
6174 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
6175 // Don't have to check the target's map since you cannot challenge someone across maps
6176 uint32 mapid = caster->GetMapId();
6177 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
6179 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
6180 return;
6183 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
6184 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
6186 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
6187 return;
6190 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
6191 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
6193 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
6194 return;
6197 //CREATE DUEL FLAG OBJECT
6198 GameObject* pGameObj = new GameObject;
6200 uint32 gameobject_id = m_spellInfo->EffectMiscValue[eff_idx];
6202 Map *map = m_caster->GetMap();
6203 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
6204 map, m_caster->GetPhaseMask(),
6205 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
6206 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
6207 m_caster->GetPositionZ(),
6208 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6210 delete pGameObj;
6211 return;
6214 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
6215 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
6216 int32 duration = GetSpellDuration(m_spellInfo);
6217 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
6218 pGameObj->SetSpellId(m_spellInfo->Id);
6220 m_caster->AddGameObject(pGameObj);
6221 map->Add(pGameObj);
6222 //END
6224 // Send request
6225 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
6226 data << uint64(pGameObj->GetGUID());
6227 data << uint64(caster->GetGUID());
6228 caster->GetSession()->SendPacket(&data);
6229 target->GetSession()->SendPacket(&data);
6231 // create duel-info
6232 DuelInfo *duel = new DuelInfo;
6233 duel->initiator = caster;
6234 duel->opponent = target;
6235 duel->startTime = 0;
6236 duel->startTimer = 0;
6237 caster->duel = duel;
6239 DuelInfo *duel2 = new DuelInfo;
6240 duel2->initiator = caster;
6241 duel2->opponent = caster;
6242 duel2->startTime = 0;
6243 duel2->startTimer = 0;
6244 target->duel = duel2;
6246 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
6247 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
6250 void Spell::EffectStuck(SpellEffectIndex /*eff_idx*/)
6252 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6253 return;
6255 if(!sWorld.getConfig(CONFIG_BOOL_CAST_UNSTUCK))
6256 return;
6258 Player* pTarget = (Player*)unitTarget;
6260 sLog.outDebug("Spell Effect: Stuck");
6261 sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ());
6263 if(pTarget->isInFlight())
6264 return;
6266 // homebind location is loaded always
6267 pTarget->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
6269 // Stuck spell trigger Hearthstone cooldown
6270 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
6271 if(!spellInfo)
6272 return;
6273 Spell spell(pTarget, spellInfo, true, 0);
6274 spell.SendSpellCooldown();
6277 void Spell::EffectSummonPlayer(SpellEffectIndex /*eff_idx*/)
6279 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6280 return;
6282 // Evil Twin (ignore player summon, but hide this for summoner)
6283 if(unitTarget->GetDummyAura(23445))
6284 return;
6286 float x, y, z;
6287 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
6289 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
6291 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
6292 data << uint64(m_caster->GetGUID()); // summoner guid
6293 data << uint32(m_caster->GetZoneId()); // summoner zone
6294 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs
6295 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6298 static ScriptInfo generateActivateCommand()
6300 ScriptInfo si;
6301 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
6302 return si;
6305 void Spell::EffectActivateObject(SpellEffectIndex eff_idx)
6307 if(!gameObjTarget)
6308 return;
6310 static ScriptInfo activateCommand = generateActivateCommand();
6312 int32 delay_secs = m_spellInfo->CalculateSimpleValue(eff_idx);
6314 gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
6317 void Spell::EffectApplyGlyph(SpellEffectIndex eff_idx)
6319 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6320 return;
6322 Player *player = (Player*)m_caster;
6324 // apply new one
6325 if(uint32 glyph = m_spellInfo->EffectMiscValue[eff_idx])
6327 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
6329 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
6331 if(gp->TypeFlags != gs->TypeFlags)
6333 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
6334 return; // glyph slot mismatch
6338 // remove old glyph
6339 player->ApplyGlyph(m_glyphIndex, false);
6340 player->SetGlyph(m_glyphIndex, glyph);
6341 player->ApplyGlyph(m_glyphIndex, true);
6342 player->SendTalentsInfoData(false);
6347 void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc)
6349 // DBC store slots starting from 1, with no slot 0 value)
6350 int slot = slot_dbc ? slot_dbc - 1 : TOTEM_SLOT_NONE;
6352 // unsummon old totem
6353 if(slot < MAX_TOTEM_SLOT)
6354 if (Totem *OldTotem = m_caster->GetTotem(TotemSlot(slot)))
6355 OldTotem->UnSummon();
6357 uint32 team = 0;
6358 if (m_caster->GetTypeId()==TYPEID_PLAYER)
6359 team = ((Player*)m_caster)->GetTeam();
6361 Totem* pTotem = new Totem;
6363 if(!pTotem->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
6364 m_spellInfo->EffectMiscValue[eff_idx], team ))
6366 delete pTotem;
6367 return;
6370 float angle = slot < MAX_TOTEM_SLOT ? M_PI_F/MAX_TOTEM_SLOT - (slot*2*M_PI_F/MAX_TOTEM_SLOT) : 0;
6372 float x, y, z;
6373 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
6375 // totem must be at same Z in case swimming caster and etc.
6376 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
6377 z = m_caster->GetPositionZ();
6379 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
6380 pTotem->SetSummonPoint(x, y, z, m_caster->GetOrientation());
6382 if (slot < MAX_TOTEM_SLOT)
6383 m_caster->_AddTotem(TotemSlot(slot),pTotem);
6385 pTotem->SetOwner(m_caster->GetGUID());
6386 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initialized
6388 int32 duration=GetSpellDuration(m_spellInfo);
6389 if (Player* modOwner = m_caster->GetSpellModOwner())
6390 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
6391 pTotem->SetDuration(duration);
6393 if (damage) // if not spell info, DB values used
6395 pTotem->SetMaxHealth(damage);
6396 pTotem->SetHealth(damage);
6399 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6401 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6402 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
6404 if(m_caster->IsPvP())
6405 pTotem->SetPvP(true);
6407 if(m_caster->IsFFAPvP())
6408 pTotem->SetFFAPvP(true);
6410 pTotem->Summon(m_caster);
6412 if (slot < MAX_TOTEM_SLOT && m_caster->GetTypeId() == TYPEID_PLAYER)
6414 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
6415 data << uint8(slot);
6416 data << uint64(pTotem->GetGUID());
6417 data << uint32(duration);
6418 data << uint32(m_spellInfo->Id);
6419 ((Player*)m_caster)->SendDirectMessage(&data);
6423 void Spell::EffectEnchantHeldItem(SpellEffectIndex eff_idx)
6425 // this is only item spell effect applied to main-hand weapon of target player (players in area)
6426 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6427 return;
6429 Player* item_owner = (Player*)unitTarget;
6430 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
6432 if(!item )
6433 return;
6435 // must be equipped
6436 if(!item ->IsEquipped())
6437 return;
6439 if (m_spellInfo->EffectMiscValue[eff_idx])
6441 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
6442 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
6443 if(!duration)
6444 duration = m_currentBasePoints[eff_idx]+1; //Base points after ..
6445 if(!duration)
6446 duration = 10; //10 seconds for enchants which don't have listed duration
6448 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
6449 if(!pEnchant)
6450 return;
6452 // Always go to temp enchantment slot
6453 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
6455 // Enchantment will not be applied if a different one already exists
6456 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
6457 return;
6459 // Apply the temporary enchantment
6460 item->SetEnchantment(slot, enchant_id, duration*IN_MILLISECONDS, 0);
6461 item_owner->ApplyEnchantment(item, slot, true);
6465 void Spell::EffectDisEnchant(SpellEffectIndex /*eff_idx*/)
6467 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6468 return;
6470 Player* p_caster = (Player*)m_caster;
6471 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
6472 return;
6474 p_caster->UpdateCraftSkill(m_spellInfo->Id);
6476 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
6478 // item will be removed at disenchanting end
6481 void Spell::EffectInebriate(SpellEffectIndex /*eff_idx*/)
6483 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6484 return;
6486 Player *player = (Player*)unitTarget;
6487 uint16 currentDrunk = player->GetDrunkValue();
6488 uint16 drunkMod = damage * 256;
6489 if (currentDrunk + drunkMod > 0xFFFF)
6490 currentDrunk = 0xFFFF;
6491 else
6492 currentDrunk += drunkMod;
6493 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
6496 void Spell::EffectFeedPet(SpellEffectIndex eff_idx)
6498 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6499 return;
6501 Player *_player = (Player*)m_caster;
6503 Item* foodItem = m_targets.getItemTarget();
6504 if(!foodItem)
6505 return;
6507 Pet *pet = _player->GetPet();
6508 if(!pet)
6509 return;
6511 if(!pet->isAlive())
6512 return;
6514 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
6515 if(benefit <= 0)
6516 return;
6518 uint32 count = 1;
6519 _player->DestroyItemCount(foodItem,count,true);
6520 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6522 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[eff_idx], &benefit, NULL, NULL, true);
6525 void Spell::EffectDismissPet(SpellEffectIndex /*eff_idx*/)
6527 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6528 return;
6530 Pet* pet = m_caster->GetPet();
6532 // not let dismiss dead pet
6533 if(!pet||!pet->isAlive())
6534 return;
6536 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
6539 void Spell::EffectSummonObject(SpellEffectIndex eff_idx)
6541 uint32 go_id = m_spellInfo->EffectMiscValue[eff_idx];
6543 uint8 slot = 0;
6544 switch(m_spellInfo->Effect[eff_idx])
6546 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
6547 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
6548 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
6549 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
6550 default: return;
6553 if(uint64 guid = m_caster->m_ObjectSlot[slot])
6555 if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
6556 obj->SetLootState(GO_JUST_DEACTIVATED);
6557 m_caster->m_ObjectSlot[slot] = 0;
6560 GameObject* pGameObj = new GameObject;
6562 float x, y, z;
6563 // If dest location if present
6564 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6566 x = m_targets.m_destX;
6567 y = m_targets.m_destY;
6568 z = m_targets.m_destZ;
6570 // Summon in random point all other units if location present
6571 else
6572 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
6574 Map *map = m_caster->GetMap();
6575 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
6576 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6578 delete pGameObj;
6579 return;
6582 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
6583 int32 duration = GetSpellDuration(m_spellInfo);
6584 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
6585 pGameObj->SetSpellId(m_spellInfo->Id);
6586 m_caster->AddGameObject(pGameObj);
6588 map->Add(pGameObj);
6590 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
6592 pGameObj->SummonLinkedTrapIfAny();
6595 void Spell::EffectResurrect(SpellEffectIndex /*eff_idx*/)
6597 if(!unitTarget)
6598 return;
6599 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6600 return;
6602 if(unitTarget->isAlive())
6603 return;
6604 if(!unitTarget->IsInWorld())
6605 return;
6607 switch (m_spellInfo->Id)
6609 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6610 case 8342:
6611 if (roll_chance_i(67))
6613 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
6614 return;
6616 break;
6617 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6618 case 22999:
6619 if (roll_chance_i(50))
6621 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
6622 return;
6624 break;
6625 default:
6626 break;
6629 Player* pTarget = ((Player*)unitTarget);
6631 if(pTarget->isRessurectRequested()) // already have one active request
6632 return;
6634 uint32 health = pTarget->GetMaxHealth() * damage / 100;
6635 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
6637 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
6638 SendResurrectRequest(pTarget);
6641 void Spell::EffectAddExtraAttacks(SpellEffectIndex /*eff_idx*/)
6643 if(!unitTarget || !unitTarget->isAlive())
6644 return;
6646 if( unitTarget->m_extraAttacks )
6647 return;
6649 unitTarget->m_extraAttacks = damage;
6652 void Spell::EffectParry(SpellEffectIndex /*eff_idx*/)
6654 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6655 ((Player*)unitTarget)->SetCanParry(true);
6658 void Spell::EffectBlock(SpellEffectIndex /*eff_idx*/)
6660 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6661 ((Player*)unitTarget)->SetCanBlock(true);
6664 void Spell::EffectLeapForward(SpellEffectIndex eff_idx)
6666 if(unitTarget->isInFlight())
6667 return;
6669 if( m_spellInfo->rangeIndex == 1) //self range
6671 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
6673 // before caster
6674 float fx, fy, fz;
6675 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
6676 float ox, oy, oz;
6677 unitTarget->GetPosition(ox, oy, oz);
6679 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
6680 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5f, fx,fy,oz+0.5f,fx2,fy2,fz2, -0.5f))
6682 fx = fx2;
6683 fy = fy2;
6684 fz = fz2;
6685 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
6688 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
6692 void Spell::EffectLeapBack(SpellEffectIndex eff_idx)
6694 if(unitTarget->isInFlight())
6695 return;
6697 m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[eff_idx])/10,float(damage)/10);
6700 void Spell::EffectReputation(SpellEffectIndex eff_idx)
6702 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6703 return;
6705 Player *_player = (Player*)unitTarget;
6707 int32 rep_change = m_currentBasePoints[eff_idx]+1; // field store reputation change -1
6709 uint32 faction_id = m_spellInfo->EffectMiscValue[eff_idx];
6711 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
6713 if(!factionEntry)
6714 return;
6716 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
6719 void Spell::EffectQuestComplete(SpellEffectIndex eff_idx)
6721 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6722 return;
6724 Player *_player = (Player*)m_caster;
6726 uint32 quest_id = m_spellInfo->EffectMiscValue[eff_idx];
6727 _player->AreaExploredOrEventHappens(quest_id);
6730 void Spell::EffectSelfResurrect(SpellEffectIndex eff_idx)
6732 if(!unitTarget || unitTarget->isAlive())
6733 return;
6734 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6735 return;
6736 if(!unitTarget->IsInWorld())
6737 return;
6739 uint32 health = 0;
6740 uint32 mana = 0;
6742 // flat case
6743 if(damage < 0)
6745 health = uint32(-damage);
6746 mana = m_spellInfo->EffectMiscValue[eff_idx];
6748 // percent case
6749 else
6751 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
6752 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
6753 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
6756 Player *plr = ((Player*)unitTarget);
6757 plr->ResurrectPlayer(0.0f);
6759 plr->SetHealth( health );
6760 plr->SetPower(POWER_MANA, mana );
6761 plr->SetPower(POWER_RAGE, 0 );
6762 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
6764 plr->SpawnCorpseBones();
6767 void Spell::EffectSkinning(SpellEffectIndex /*eff_idx*/)
6769 if(unitTarget->GetTypeId() != TYPEID_UNIT )
6770 return;
6771 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
6772 return;
6774 Creature* creature = (Creature*) unitTarget;
6775 int32 targetLevel = creature->getLevel();
6777 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
6779 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
6780 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6782 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
6784 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
6786 // Double chances for elites
6787 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
6790 void Spell::EffectCharge(SpellEffectIndex /*eff_idx*/)
6792 if (!unitTarget)
6793 return;
6795 //TODO: research more ContactPoint/attack distance.
6796 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6797 float x, y, z;
6798 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6800 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6801 ((Creature *)unitTarget)->StopMoving();
6803 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6804 m_caster->MonsterMove(x, y, z, 1);
6806 // not all charge effects used in negative spells
6807 if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6808 m_caster->Attack(unitTarget, true);
6811 void Spell::EffectCharge2(SpellEffectIndex /*eff_idx*/)
6813 float x, y, z;
6814 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6816 x = m_targets.m_destX;
6817 y = m_targets.m_destY;
6818 z = m_targets.m_destZ;
6820 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6821 ((Creature *)unitTarget)->StopMoving();
6823 else if (unitTarget && unitTarget != m_caster)
6824 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6825 else
6826 return;
6828 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6829 m_caster->MonsterMove(x, y, z, 1);
6831 // not all charge effects used in negative spells
6832 if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6833 m_caster->Attack(unitTarget, true);
6836 void Spell::DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction)
6838 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6839 return;
6840 Player* player = (Player*)m_caster;
6842 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
6843 if(!pet_entry)
6844 return;
6846 Pet* old_critter = player->GetMiniPet();
6848 // for same pet just despawn
6849 if(old_critter && old_critter->GetEntry() == pet_entry)
6851 player->RemoveMiniPet();
6852 return;
6855 // despawn old pet before summon new
6856 if(old_critter)
6857 player->RemoveMiniPet();
6859 // summon new pet
6860 Pet* critter = new Pet(MINI_PET);
6862 Map *map = m_caster->GetMap();
6863 uint32 pet_number = sObjectMgr.GeneratePetNumber();
6864 if(!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
6865 pet_entry, pet_number))
6867 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
6868 delete critter;
6869 return;
6872 float x, y, z;
6873 // If dest location if present
6874 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6876 x = m_targets.m_destX;
6877 y = m_targets.m_destY;
6878 z = m_targets.m_destZ;
6880 // Summon if dest location not present near caster
6881 else
6882 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
6884 critter->Relocate(x, y, z, m_caster->GetOrientation());
6885 critter->SetSummonPoint(x, y, z, m_caster->GetOrientation());
6887 if(!critter->IsPositionValid())
6889 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6890 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
6891 delete critter;
6892 return;
6895 critter->SetOwnerGUID(m_caster->GetGUID());
6896 critter->SetCreatorGUID(m_caster->GetGUID());
6898 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6899 critter->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
6900 critter->AIM_Initialize();
6901 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6902 //critter->InitLevelupSpellsForLevel(); // none?
6903 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6904 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
6905 // some mini-pets have quests
6907 // set timer for unsummon
6908 int32 duration = GetSpellDuration(m_spellInfo);
6909 if(duration > 0)
6910 critter->SetDuration(duration);
6912 std::string name = player->GetName();
6913 name.append(petTypeSuffix[critter->getPetType()]);
6914 critter->SetName( name );
6915 player->SetMiniPet(critter);
6917 map->Add((Creature*)critter);
6920 void Spell::EffectKnockBack(SpellEffectIndex eff_idx)
6922 if(!unitTarget)
6923 return;
6925 unitTarget->KnockBackFrom(m_caster,float(m_spellInfo->EffectMiscValue[eff_idx])/10,float(damage)/10);
6928 void Spell::EffectSendTaxi(SpellEffectIndex eff_idx)
6930 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6931 return;
6933 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[eff_idx],m_spellInfo->Id);
6936 void Spell::EffectPlayerPull(SpellEffectIndex eff_idx)
6938 if(!unitTarget)
6939 return;
6941 float dist = unitTarget->GetDistance2d(m_caster);
6942 if (damage && dist > damage)
6943 dist = float(damage);
6945 unitTarget->KnockBackFrom(m_caster,-dist,float(m_spellInfo->EffectMiscValue[eff_idx])/10);
6948 void Spell::EffectDispelMechanic(SpellEffectIndex eff_idx)
6950 if(!unitTarget)
6951 return;
6953 uint32 mechanic = m_spellInfo->EffectMiscValue[eff_idx];
6955 Unit::AuraMap& Auras = unitTarget->GetAuras();
6956 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6958 next = iter;
6959 ++next;
6960 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6961 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6963 unitTarget->RemoveAurasDueToSpell(spell->Id);
6964 if(Auras.empty())
6965 break;
6966 else
6967 next = Auras.begin();
6970 return;
6973 void Spell::EffectSummonDeadPet(SpellEffectIndex /*eff_idx*/)
6975 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6976 return;
6977 Player *_player = (Player*)m_caster;
6978 Pet *pet = _player->GetPet();
6979 if(!pet)
6980 return;
6981 if(pet->isAlive())
6982 return;
6983 if(damage < 0)
6984 return;
6985 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6986 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6987 pet->setDeathState( ALIVE );
6988 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6989 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6991 pet->AIM_Initialize();
6993 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6994 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6997 void Spell::EffectSummonAllTotems(SpellEffectIndex eff_idx)
6999 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7000 return;
7002 int32 start_button = ACTION_BUTTON_SHAMAN_TOTEMS_BAR + m_spellInfo->EffectMiscValue[eff_idx];
7003 int32 amount_buttons = m_spellInfo->EffectMiscValueB[eff_idx];
7005 for(int32 slot = 0; slot < amount_buttons; ++slot)
7006 if (ActionButton const* actionButton = ((Player*)m_caster)->GetActionButton(start_button+slot))
7007 if (actionButton->GetType()==ACTION_BUTTON_SPELL)
7008 if (uint32 spell_id = actionButton->GetAction())
7009 m_caster->CastSpell(unitTarget,spell_id,true);
7012 void Spell::EffectDestroyAllTotems(SpellEffectIndex /*eff_idx*/)
7014 int32 mana = 0;
7015 for(int slot = 0; slot < MAX_TOTEM_SLOT; ++slot)
7017 if (Totem* totem = m_caster->GetTotem(TotemSlot(slot)))
7019 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
7020 if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id))
7022 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
7023 mana += manacost * damage / 100;
7025 totem->UnSummon();
7029 if (mana)
7030 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
7033 void Spell::EffectDurabilityDamage(SpellEffectIndex eff_idx)
7035 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7036 return;
7038 int32 slot = m_spellInfo->EffectMiscValue[eff_idx];
7040 // FIXME: some spells effects have value -1/-2
7041 // Possibly its mean -1 all player equipped items and -2 all items
7042 if(slot < 0)
7044 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
7045 return;
7048 // invalid slot value
7049 if(slot >= INVENTORY_SLOT_BAG_END)
7050 return;
7052 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
7053 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
7056 void Spell::EffectDurabilityDamagePCT(SpellEffectIndex eff_idx)
7058 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7059 return;
7061 int32 slot = m_spellInfo->EffectMiscValue[eff_idx];
7063 // FIXME: some spells effects have value -1/-2
7064 // Possibly its mean -1 all player equipped items and -2 all items
7065 if(slot < 0)
7067 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
7068 return;
7071 // invalid slot value
7072 if(slot >= INVENTORY_SLOT_BAG_END)
7073 return;
7075 if(damage <= 0)
7076 return;
7078 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
7079 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
7082 void Spell::EffectModifyThreatPercent(SpellEffectIndex /*eff_idx*/)
7084 if(!unitTarget)
7085 return;
7087 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
7090 void Spell::EffectTransmitted(SpellEffectIndex eff_idx)
7092 uint32 name_id = m_spellInfo->EffectMiscValue[eff_idx];
7094 GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
7096 if (!goinfo)
7098 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
7099 return;
7102 float fx, fy, fz;
7104 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
7106 fx = m_targets.m_destX;
7107 fy = m_targets.m_destY;
7108 fz = m_targets.m_destZ;
7110 //FIXME: this can be better check for most objects but still hack
7111 else if(m_spellInfo->EffectRadiusIndex[eff_idx] && m_spellInfo->speed==0)
7113 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
7114 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
7116 else
7118 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
7119 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
7120 float dis = rand_norm_f() * (max_dis - min_dis) + min_dis;
7122 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
7125 Map *cMap = m_caster->GetMap();
7127 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
7129 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
7130 { // but this is not proper, we really need to ignore not materialized objects
7131 SendCastResult(SPELL_FAILED_NOT_HERE);
7132 SendChannelUpdate(0);
7133 return;
7136 // replace by water level in this case
7137 fz = cMap->GetWaterLevel(fx, fy);
7139 // if gameobject is summoning object, it should be spawned right on caster's position
7140 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
7142 m_caster->GetPosition(fx, fy, fz);
7145 GameObject* pGameObj = new GameObject;
7147 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
7148 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
7150 delete pGameObj;
7151 return;
7154 int32 duration = GetSpellDuration(m_spellInfo);
7156 switch(goinfo->type)
7158 case GAMEOBJECT_TYPE_FISHINGNODE:
7160 m_caster->SetChannelObjectGUID(pGameObj->GetGUID());
7161 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
7163 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
7164 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
7165 int32 lastSec = 0;
7166 switch(urand(0, 3))
7168 case 0: lastSec = 3; break;
7169 case 1: lastSec = 7; break;
7170 case 2: lastSec = 13; break;
7171 case 3: lastSec = 17; break;
7174 duration = duration - lastSec*IN_MILLISECONDS + FISHING_BOBBER_READY_TIME*IN_MILLISECONDS;
7175 break;
7177 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
7179 if(m_caster->GetTypeId() == TYPEID_PLAYER)
7181 pGameObj->AddUniqueUse((Player*)m_caster);
7182 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
7184 break;
7186 case GAMEOBJECT_TYPE_FISHINGHOLE:
7187 case GAMEOBJECT_TYPE_CHEST:
7188 default:
7189 break;
7192 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
7194 pGameObj->SetOwnerGUID(m_caster->GetGUID());
7196 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
7197 pGameObj->SetSpellId(m_spellInfo->Id);
7199 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
7200 //m_caster->AddGameObject(pGameObj);
7201 //m_ObjToDel.push_back(pGameObj);
7203 cMap->Add(pGameObj);
7205 pGameObj->SummonLinkedTrapIfAny();
7208 void Spell::EffectProspecting(SpellEffectIndex /*eff_idx*/)
7210 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7211 return;
7213 Player* p_caster = (Player*)m_caster;
7214 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
7215 return;
7217 if(itemTarget->GetCount() < 5)
7218 return;
7220 if( sWorld.getConfig(CONFIG_BOOL_SKILL_PROSPECTING))
7222 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
7223 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
7224 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
7227 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
7230 void Spell::EffectMilling(SpellEffectIndex /*eff_idx*/)
7232 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7233 return;
7235 Player* p_caster = (Player*)m_caster;
7236 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
7237 return;
7239 if(itemTarget->GetCount() < 5)
7240 return;
7242 if( sWorld.getConfig(CONFIG_BOOL_SKILL_MILLING))
7244 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
7245 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
7246 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
7249 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
7252 void Spell::EffectSkill(SpellEffectIndex /*eff_idx*/)
7254 sLog.outDebug("WORLD: SkillEFFECT");
7257 void Spell::EffectSpiritHeal(SpellEffectIndex /*eff_idx*/)
7259 // TODO player can't see the heal-animation - he should respawn some ticks later
7260 if (!unitTarget || unitTarget->isAlive())
7261 return;
7262 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
7263 return;
7264 if (!unitTarget->IsInWorld())
7265 return;
7266 if (m_spellInfo->Id == 22012 && !unitTarget->HasAura(2584))
7267 return;
7269 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
7270 ((Player*)unitTarget)->SpawnCorpseBones();
7273 // remove insignia spell effect
7274 void Spell::EffectSkinPlayerCorpse(SpellEffectIndex /*eff_idx*/)
7276 sLog.outDebug("Effect: SkinPlayerCorpse");
7277 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
7278 return;
7280 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
7283 void Spell::EffectStealBeneficialBuff(SpellEffectIndex eff_idx)
7285 sLog.outDebug("Effect: StealBeneficialBuff");
7287 if(!unitTarget || unitTarget==m_caster) // can't steal from self
7288 return;
7290 std::vector <Aura *> steal_list;
7291 // Create dispel mask by dispel type
7292 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[eff_idx]) );
7293 Unit::AuraMap const& auras = unitTarget->GetAuras();
7294 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
7296 Aura *aur = (*itr).second;
7297 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
7299 // Need check for passive? this
7300 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
7301 steal_list.push_back(aur);
7304 // Ok if exist some buffs for dispel try dispel it
7305 if (!steal_list.empty())
7307 std::list < std::pair<uint32,uint64> > success_list;
7308 int32 list_size = steal_list.size();
7309 // Dispell N = damage buffs (or while exist buffs for dispel)
7310 for (int32 count=0; count < damage && list_size > 0; ++count)
7312 // Random select buff for dispel
7313 Aura *aur = steal_list[urand(0, list_size-1)];
7314 // Not use chance for steal
7315 // TODO possible need do it
7316 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
7318 // Remove buff from list for prevent doubles
7319 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
7321 Aura *stealed = *j;
7322 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
7324 j = steal_list.erase(j);
7325 --list_size;
7327 else
7328 ++j;
7331 // Really try steal and send log
7332 if (!success_list.empty())
7334 int32 count = success_list.size();
7335 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
7336 data << unitTarget->GetPackGUID(); // Victim GUID
7337 data << m_caster->GetPackGUID(); // Caster GUID
7338 data << uint32(m_spellInfo->Id); // Dispell spell id
7339 data << uint8(0); // not used
7340 data << uint32(count); // count
7341 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
7343 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
7344 data << uint32(spellInfo->Id); // Spell Id
7345 data << uint8(0); // 0 - steals !=0 transfers
7346 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
7348 m_caster->SendMessageToSet(&data, true);
7353 void Spell::EffectKillCreditPersonal(SpellEffectIndex eff_idx)
7355 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7356 return;
7358 ((Player*)unitTarget)->KilledMonsterCredit(m_spellInfo->EffectMiscValue[eff_idx], 0);
7361 void Spell::EffectKillCredit(SpellEffectIndex eff_idx)
7363 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7364 return;
7366 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[eff_idx], unitTarget);
7369 void Spell::EffectQuestFail(SpellEffectIndex eff_idx)
7371 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7372 return;
7374 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[eff_idx]);
7377 void Spell::EffectActivateRune(SpellEffectIndex eff_idx)
7379 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7380 return;
7382 Player *plr = (Player*)m_caster;
7384 if(plr->getClass() != CLASS_DEATH_KNIGHT)
7385 return;
7387 for(uint32 j = 0; j < MAX_RUNES; ++j)
7389 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == RuneType(m_spellInfo->EffectMiscValue[eff_idx]))
7391 plr->SetRuneCooldown(j, 0);
7396 void Spell::EffectTitanGrip(SpellEffectIndex /*eff_idx*/)
7398 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
7399 ((Player*)unitTarget)->SetCanTitanGrip(true);
7402 void Spell::EffectRenamePet(SpellEffectIndex /*eff_idx*/)
7404 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
7405 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
7406 return;
7408 unitTarget->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
7411 void Spell::EffectPlayMusic(SpellEffectIndex eff_idx)
7413 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7414 return;
7416 uint32 soundid = m_spellInfo->EffectMiscValue[eff_idx];
7418 if (!sSoundEntriesStore.LookupEntry(soundid))
7420 sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
7421 return;
7424 WorldPacket data(SMSG_PLAY_MUSIC, 4);
7425 data << uint32(soundid);
7426 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
7429 void Spell::EffectSpecCount(SpellEffectIndex /*eff_idx*/)
7431 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7432 return;
7434 ((Player*)unitTarget)->UpdateSpecCount(damage);
7437 void Spell::EffectActivateSpec(SpellEffectIndex /*eff_idx*/)
7439 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7440 return;
7442 uint32 spec = damage-1;
7444 ((Player*)unitTarget)->ActivateSpec(spec);
7447 void Spell::EffectBind(SpellEffectIndex eff_idx)
7449 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7450 return;
7452 Player* player = (Player*)unitTarget;
7454 uint32 area_id;
7455 WorldLocation loc;
7456 if (m_spellInfo->EffectImplicitTargetA[eff_idx] == TARGET_TABLE_X_Y_Z_COORDINATES ||
7457 m_spellInfo->EffectImplicitTargetB[eff_idx] == TARGET_TABLE_X_Y_Z_COORDINATES)
7459 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
7460 if (!st)
7462 sLog.outError( "Spell::EffectBind - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
7463 return;
7466 loc.mapid = st->target_mapId;
7467 loc.coord_x = st->target_X;
7468 loc.coord_y = st->target_Y;
7469 loc.coord_z = st->target_Y;
7470 loc.orientation = st->target_Orientation;
7471 area_id = sMapMgr.GetAreaId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z);
7473 else
7475 player->GetPosition(loc);
7476 area_id = player->GetAreaId();
7479 player->SetHomebindToLocation(loc,area_id);
7481 // binding
7482 WorldPacket data( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
7483 data << float(loc.coord_x);
7484 data << float(loc.coord_y);
7485 data << float(loc.coord_z);
7486 data << uint32(loc.mapid);
7487 data << uint32(area_id);
7488 player->SendDirectMessage( &data );
7490 DEBUG_LOG("New Home Position X is %f", loc.coord_x);
7491 DEBUG_LOG("New Home Position Y is %f", loc.coord_y);
7492 DEBUG_LOG("New Home Position Z is %f", loc.coord_z);
7493 DEBUG_LOG("New Home MapId is %u", loc.mapid);
7494 DEBUG_LOG("New Home AreaId is %u", area_id);
7496 // zone update
7497 data.Initialize(SMSG_PLAYERBOUND, 8+4);
7498 data << uint64(player->GetGUID());
7499 data << uint32(area_id);
7500 player->SendDirectMessage( &data );
7503 void Spell::EffectRestoreItemCharges( SpellEffectIndex eff_idx )
7505 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
7506 return;
7508 Player* player = (Player*)unitTarget;
7510 ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(m_spellInfo->EffectItemType[eff_idx]);
7511 if (!itemProto)
7512 return;
7514 // In case item from limited category recharge any from category, is this valid checked early in spell checks
7515 Item* item;
7516 if (itemProto->ItemLimitCategory)
7517 item = player->GetItemByLimitedCategory(itemProto->ItemLimitCategory);
7518 else
7519 item = player->GetItemByEntry(m_spellInfo->EffectItemType[eff_idx]);
7521 if (!item)
7522 return;
7524 item->RestoreCharges();
7527 void Spell::EffectTeachTaxiNode( SpellEffectIndex eff_idx )
7529 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
7530 return;
7532 Player* player = (Player*)unitTarget;
7534 uint32 taxiNodeId = m_spellInfo->EffectMiscValue[eff_idx];
7535 if (!sTaxiNodesStore.LookupEntry(taxiNodeId))
7536 return;
7538 if (player->m_taxi.SetTaximaskNode(taxiNodeId))
7540 WorldPacket data(SMSG_NEW_TAXI_PATH, 0);
7541 player->SendDirectMessage( &data );
7543 data.Initialize( SMSG_TAXINODE_STATUS, 9 );
7544 data << uint64( m_caster->GetGUID() );
7545 data << uint8( 1 );
7546 player->SendDirectMessage( &data );