OregonCore  revision 3611e8a-git
Your Favourite TBC server
SpellEffects.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "SharedDefines.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "Opcodes.h"
24 #include "Log.h"
25 #include "UpdateMask.h"
26 #include "World.h"
27 #include "ObjectMgr.h"
28 #include "SpellMgr.h"
29 #include "Player.h"
30 #include "SkillExtraItems.h"
31 #include "Unit.h"
32 #include "CreatureAI.h"
33 #include "Spell.h"
34 #include "DynamicObject.h"
35 #include "SpellAuras.h"
36 #include "Pet.h"
37 #include "GameObject.h"
38 #include "GossipDef.h"
39 #include "Creature.h"
40 #include "Totem.h"
41 #include "Battleground.h"
42 #include "BattlegroundEY.h"
43 #include "BattlegroundWS.h"
44 #include "OutdoorPvPMgr.h"
45 #include "Language.h"
46 #include "SocialMgr.h"
47 #include "Util.h"
48 #include "TemporarySummon.h"
49 #include "GridNotifiers.h"
50 #include "GridNotifiersImpl.h"
51 #include "CellImpl.h"
52 #include "ScriptMgr.h"
53 #include "GameObjectAI.h"
54 #include "InstanceData.h"
55 #include "MoveSplineInit.h"
56 
58 {
59  &Spell::EffectNULL, // 0
60  &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
61  &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
62  &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
63  &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
64  &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
65  &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
66  &Spell::EffectEnvironmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
67  &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
68  &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
69  &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
70  &Spell::EffectBind, // 11 SPELL_EFFECT_BIND
71  &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
72  &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
73  &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
74  &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
75  &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
76  &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
77  &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
78  &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
79  &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
80  &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
81  &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
82  &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
83  &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
84  &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
85  &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
86  &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
87  &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
88  &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
89  &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
90  &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
91  &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
92  &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
93  &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
94  &Spell::EffectApplyAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
95  &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
96  &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
97  &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
98  &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
99  &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
100  &Spell::EffectUnused, // 41 SPELL_EFFECT_41 (old SPELL_EFFECT_SUMMON_WILD)
101  &Spell::SummonClassPet, // 42 SPELL_EFFECT_SUMMON_CLASS_PET
102  &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
103  &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
104  &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
105  &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN spawn/login animation, expected by spawn unit cast, also base points store some dynflags
106  &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
107  &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
108  &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
109  &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
110  &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused from pre-1.2.1
111  &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT unused from pre-1.2.1
112  &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
113  &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
114  &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
115  &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
116  &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
117  &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
118  &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
119  &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
120  &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
121  &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
122  &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
123  &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
124  &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused
125  &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused from pre-1.2.1
126  &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
127  &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
128  &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
129  &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
130  &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
131  &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
132  &Spell::EffectUnused, // 73 SPELL_EFFECT_73 (old SPELL_EFFECT_SUMMON_POSSESSED
133  &Spell::EffectUnused, // 74 SPELL_EFFECT_74 (old SPELL_EFFECT_SUMMON_TOTEM)
134  &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
135  &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
136  &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
137  &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
138  &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
139  &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
140  &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
141  &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
142  &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
143  &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
144  &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
145  &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
146  &Spell::EffectUnused, // 87 SPELL_EFFECT_87 (old SPELL_EFFECT_SUMMON_TOTEM_SLOT1)
147  &Spell::EffectUnused, // 88 SPELL_EFFECT_88 (old SPELL_EFFECT_SUMMON_TOTEM_SLOT2)
148  &Spell::EffectUnused, // 89 SPELL_EFFECT_89 (old SPELL_EFFECT_SUMMON_TOTEM_SLOT3)
149  &Spell::EffectUnused, // 90 SPELL_EFFECT_90 (old SPELL_EFFECT_SUMMON_TOTEM_SLOT4)
150  &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
151  &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
152  &Spell::EffectUnused, // 93 SPELL_EFFECT_93 (old SPELL_EFFECT_SUMMON_PHANTASM)
153  &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
154  &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
155  &Spell::EffectUnused, // 96 SPELL_EFFECT_CHARGE
156  &Spell::EffectUnused, // 97 SPELL_EFFECT_97 (old SPELL_EFFECT_SUMMON_CRITTER)
157  &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
158  &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
159  &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
160  &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
161  &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
162  &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
163  &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
164  &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
165  &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
166  &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
167  &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
168  &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
169  &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
170  &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
171  &Spell::EffectUnused, //112 SPELL_EFFECT_112 (old SPELL_EFFECT_SUMMON_DEMON)
172  &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
173  &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
174  &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
175  &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
176  &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
177  &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
178  &Spell::EffectApplyAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
179  &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
180  &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
181  &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
182  &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
183  &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
184  &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
185  &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
186  &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
187  &Spell::EffectApplyAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
188  &Spell::EffectApplyAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
189  &Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT
190  &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
191  &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
192  &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
193  &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
194  &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
195  &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
196  &Spell::EffectEnergizePct, //137 SPELL_EFFECT_ENERGIZE_PCT
197  &Spell::EffectNULL, //138 SPELL_EFFECT_LEAP_BACK
198  &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID), unused
199  &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
200  &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
201  &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
202  &Spell::EffectApplyAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
203  &Spell::EffectKnockBack, //144 SPELL_EFFECT_KNOCK_BACK_2 Spectral Blast
204  &Spell::EffectPlayerPull, //145 SPELL_EFFECT_145 Black Hole Effect
205  &Spell::EffectUnused, //146 SPELL_EFFECT_ACTIVATE_RUNE unused
206  &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
207  &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
208  &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
209  &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
210  &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
211  &Spell::EffectSummonFriend, //152 SPELL_EFFECT_SUMMON_FRIEND summon Refer-a-Friend
212  &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
213 };
214 
216 {
217  sLog.outDebug("WORLD: Spell Effect DUMMY");
218 }
219 
221 {
222  // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
223 }
224 
226 {
227  if (!unitTarget || unitTarget->IsAlive())
228  return;
229 
231  return;
232 
233  if (!unitTarget->IsInWorld())
234  return;
235 
236  Player* pTarget = unitTarget->ToPlayer();
237 
238  if (pTarget->isRessurectRequested()) // already have one active request
239  return;
240 
241  uint32 health = damage;
242  uint32 mana = m_spellInfo->EffectMiscValue[effIndex];
244  SendResurrectRequest(pTarget);
245 }
246 
248 {
249  if (!unitTarget || !unitTarget->IsAlive())
250  return;
251 
254  return;
255 
256  // Demonic Sacrifice
257  if (m_spellInfo->Id == 18788 && unitTarget->GetTypeId() == TYPEID_UNIT)
258  {
259  uint32 entry = unitTarget->GetEntry();
260  uint32 spellID;
261  switch (entry)
262  {
263  case 416:
264  spellID = 18789;
265  break; //imp
266  case 417:
267  spellID = 18792;
268  break; //fellhunter
269  case 1860:
270  spellID = 18790;
271  break; //void
272  case 1863:
273  spellID = 18791;
274  break; //succubus
275  case 17252:
276  spellID = 35701;
277  break; //fellguard
278  default:
279  sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry);
280  return;
281  }
282 
283  m_caster->CastSpell(m_caster, spellID, true);
284  }
285 
286  if (m_caster == unitTarget) // prevent interrupt message
287  finish();
288 
289  WorldPacket data(SMSG_SPELLINSTAKILLLOG, 8 + 8 + 4);
290  data << uint64(m_caster->GetGUID());
291  data << uint64(unitTarget->GetGUID());
292  data << uint32(m_spellInfo->Id);
293  m_caster->SendMessageToSet(&data, true);
294 
296 }
297 
299 {
300  uint32 absorb = 0;
301  uint32 resist = 0;
302 
303  // Note: this hack with damage replace required until GO casting not implemented
304  // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
305  // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
307 
309 
311  if (m_caster->GetTypeId() == TYPEID_PLAYER)
313 }
314 
316 {
317 }
318 
320 {
321  if (unitTarget && unitTarget->IsAlive())
322  {
323  switch (m_spellInfo->SpellFamilyName)
324  {
325  case SPELLFAMILY_GENERIC:
326  {
327  //Gore
328  if (m_spellInfo->SpellIconID == 2269)
329  damage += (uint32)rand32() % 2 ? damage : 0;
330 
331  // Meteor like spells (divided damage to targets)
333  {
334  uint32 count = 0;
335  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
336  {
337  if (ihit->deleted)
338  continue;
339 
340  if (ihit->effectMask & (1 << effIndex))
341  ++count;
342  }
343 
344  damage /= count; // divide to all targets
345  }
346 
347  switch (m_spellInfo->Id) // better way to check unknown
348  {
349  case 35354: //Hand of Death
350  {
351  if (unitTarget && unitTarget->HasAura(38528, 0)) //Protection of Elune
352  damage = 0;
353  break;
354  }
355  // percent from health with min
356  case 25599: // Thundercrash
357  {
358  damage = unitTarget->GetHealth() / 2;
359  if (damage < 200)
360  damage = 200;
361  break;
362  }
363  // arcane charge. must only affect demons (also undead?)
364  case 45072:
365  {
368  return;
369  break;
370  }
371  // gruul's shatter
372  case 33671:
373  {
374  // don't damage self and only players
376  return;
377 
378  float radius = GetSpellRadius(m_spellInfo, 0, false);
379  if (!radius) return;
380  float distance = m_caster->GetDistance2d(unitTarget);
381  damage = (distance > radius) ? 0 : int32(m_spellInfo->EffectBasePoints[0] * ((radius - distance) / radius));
382  // Set the damage directly without spell bonus damage
383  m_damage += damage;
384  damage = 0;
385  break;
386  }
387  // Cataclysmic Bolt
388  case 38441:
389  damage = unitTarget->GetMaxHealth() / 2;
390  break;
391  }
392  break;
393  }
394 
395  case SPELLFAMILY_MAGE:
396  {
397  // Arcane Blast
398  if (m_spellInfo->SpellFamilyFlags & 0x20000000LL)
399  m_caster->CastSpell(m_caster, 36032, true);
400  break;
401  }
402  case SPELLFAMILY_WARRIOR:
403  {
404  // Bloodthirst
405  if (m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
407  // Shield Slam
408  else if (m_spellInfo->SpellFamilyFlags & 0x100000000LL)
410  // Victory Rush
411  else if (m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
412  {
415  }
416  break;
417  }
418  case SPELLFAMILY_WARLOCK:
419  {
420  // Incinerate Rank 1 & 2
421  if ((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID == 2128)
422  {
423  // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
425  damage += int32(damage * 0.25);
426  }
427 
428  // Conflagrate - consumes immolate
430  {
431  // for caster applied auras only
433  for (Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
434  {
435  if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
436  ((*i)->GetSpellProto()->SpellFamilyFlags & 4) &&
437  (*i)->GetCasterGUID() == m_caster->GetGUID())
438  {
440  break;
441  }
442  }
443  }
444  break;
445  }
446  case SPELLFAMILY_PRIEST:
447  {
448  // Shadow Word: Death - deals damage equal to damage done to caster
449  if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
450  {
452  if (back_damage < int64(unitTarget->GetHealth()))
453  m_caster->CastCustomSpell(m_caster, 32409, &back_damage, 0, 0, true);
454  }
455  break;
456  }
457  case SPELLFAMILY_DRUID:
458  {
459  // Ferocious Bite
460  if ((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual == 6587)
461  {
462  // converts each extra point of energy into ($f1+$AP/630) additional damage
463  float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effIndex];
464  damage += int32((m_caster->GetPower(POWER_ENERGY) - GetPowerCost()) * multiple);
466  }
467  // Rake
468  else if (m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
470  // Swipe
471  else if (m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
473  // Starfire
474  else if (m_spellInfo->SpellFamilyFlags & 0x0004LL)
475  {
477  for (Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
478  {
479  // Starfire Bonus (caster)
480  switch ((*i)->GetModifier()->m_miscvalue)
481  {
482  case 5481: // Nordrassil Regalia - bonus
483  {
484  Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
485  for (Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
486  {
487  // Moonfire or Insect Swarm (target debuff from any casters)
488  if ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL)
489  {
490  int32 mod = (*i)->GetModifier()->m_amount;
491  damage += damage * mod / 100;
492  break;
493  }
494  }
495  break;
496  }
497  case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
498  {
499  damage += (*i)->GetModifier()->m_amount;
500  break;
501  }
502  }
503  }
504  }
505  //Mangle Bonus for the initial damage of Lacerate and Rake
506  if ((m_spellInfo->SpellFamilyFlags == 0x0000000000001000LL && m_spellInfo->SpellIconID == 494) ||
507  (m_spellInfo->SpellFamilyFlags == 0x0000010000000000LL && m_spellInfo->SpellIconID == 2246))
508  {
510  for (Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
511  if ((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID)
512  {
513  damage = int32(damage * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f);
514  break;
515  }
516  }
517  break;
518  }
519  case SPELLFAMILY_ROGUE:
520  {
521  // Envenom
522  if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
523  {
524  // consume from stack dozes not more that have combo-points
525  if (uint32 combo = m_caster->ToPlayer()->GetComboPoints())
526  {
527  // count consumed deadly poison doses at target
528  uint32 doses = 0;
529 
530  // remove consumed poison doses
532  for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end() && combo;)
533  {
534  // Deadly poison (only attacker applied)
535  if ((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
536  (*itr)->GetSpellProto()->SpellVisual == 5100 && (*itr)->GetCasterGUID() == m_caster->GetGUID())
537  {
538  --combo;
539  ++doses;
540 
541  unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex());
542 
543  itr = auras.begin();
544  }
545  else
546  ++itr;
547  }
548 
549  damage *= doses;
551 
552  // Eviscerate and Envenom Bonus Damage (item set effect)
553  if (m_caster->GetDummyAura(37169))
554  damage += m_caster->ToPlayer()->GetComboPoints() * 40;
555  }
556  }
557  // Eviscerate
558  else if ((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId() == TYPEID_PLAYER)
559  {
560  if (uint32 combo = m_caster->ToPlayer()->GetComboPoints())
561  {
563 
564  // Eviscerate and Envenom Bonus Damage (item set effect)
565  if (m_caster->GetDummyAura(37169))
566  damage += combo * 40;
567  }
568  }
569  break;
570  }
571  case SPELLFAMILY_HUNTER:
572  {
573  // Mongoose Bite
574  if ((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual == 342)
576  // Arcane Shot
577  else if ((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
579  // Steady Shot
580  else if (m_spellInfo->SpellFamilyFlags & 0x100000000LL)
581  {
584 
585  bool found = false;
586 
587  // check dazed affect
589  for (Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
590  {
591  if ((*iter)->GetSpellProto()->SpellIconID == 15 && (*iter)->GetSpellProto()->Dispel == 0)
592  {
593  found = true;
594  break;
595  }
596  }
597 
598  // @todo should this be put on taken but not done?
599  if (found)
600  damage += m_spellInfo->EffectBasePoints[1];
601  }
602  //Explosive Trap Effect
603  else if (m_spellInfo->SpellFamilyFlags & 0x00000004)
605  break;
606  }
607  case SPELLFAMILY_PALADIN:
608  {
609  //Judgement of Vengeance
610  if ((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID == 2292)
611  {
612  uint32 stacks = 0;
614  for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
615  {
616  if ((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID() == m_caster->GetGUID())
617  {
618  stacks = (*itr)->GetStackAmount();
619  break;
620  }
621  }
622 
623  if (!stacks)
624  //No damage if the target isn't affected by this
625  damage = -1;
626  else
627  damage *= stacks;
628  }
629  break;
630  }
631  case SPELLFAMILY_SHAMAN:
632  {
633  // Lightning Bolt & Chain Lightning
634  if (m_spellInfo->SpellFamilyFlags & 0x0003LL)
635  {
637  for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
638  {
639  if ((*itr)->GetId() == 28857 || (*itr)->GetId() == 34230 || (*itr)->GetId() == 41040)
640  {
641  damage += (*itr)->GetModifierValue();
642  break;
643  }
644  }
645  }
646  break;
647  }
648  }
649 
650  if (m_originalCaster && damage > 0)
652 
653  m_damage += damage;
654  }
655 }
656 
658 {
659  if (!unitTarget && !gameObjTarget && !itemTarget)
660  return;
661 
662  uint32 spell_id = 0;
663  int32 bp = 0;
664 
665  // selection by spell family
666  switch (m_spellInfo->SpellFamilyName)
667  {
668  case SPELLFAMILY_GENERIC:
669  {
670  switch (m_spellInfo->Id)
671  {
672  // Wrath of the Astromancer
673  case 42784:
674  {
675  uint32 count = 0;
676  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
677  {
678  if (ihit->deleted)
679  continue;
680 
681  if (ihit->effectMask & (1 << effIndex))
682  ++count;
683  }
684 
685  damage = 12000; // maybe wrong value
686  damage /= count;
687 
688  SpellEntry const* spellInfo = sSpellStore.LookupEntry(42784);
689 
690  // now deal the damage
691  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
692  {
693  if (ihit->deleted)
694  continue;
695 
696  if (ihit->effectMask & (1 << effIndex))
697  {
698  if (Unit* casttarget = Unit::GetUnit((*unitTarget), ihit->targetGUID))
699  m_caster->DealDamage(casttarget, damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, spellInfo, false);
700  }
701  }
702 
703  return;
704  }
705  case 7671: // Transformation (human<->worgen)
706  {
707  if (!unitTarget)
708  return;
709 
710  // Transform Visual
711  unitTarget->CastSpell(unitTarget, 24085, true);
712  return;
713  }
714  case 8063: // Deviate Fish
715  {
716  if (m_caster->GetTypeId() != TYPEID_PLAYER)
717  return;
718 
719  uint32 spell_id = 0;
720  switch (urand(1, 5))
721  {
722  case 1:
723  spell_id = 8064;
724  break; // Sleepy
725  case 2:
726  spell_id = 8065;
727  break; // Invigorate
728  case 3:
729  spell_id = 8066;
730  break; // Shrink
731  case 4:
732  spell_id = 8067;
733  break; // Party Time!
734  case 5:
735  spell_id = 8068;
736  break; // Healthy Spirit
737  }
738  m_caster->CastSpell(m_caster, spell_id, true, NULL);
739  return;
740  }
741  case 8213: // Savory Deviate Delight
742  {
743  if (m_caster->GetTypeId() != TYPEID_PLAYER)
744  return;
745 
746  uint32 spell_id = 0;
747  switch (urand(1, 2))
748  {
749  // Flip Out - ninja
750  case 1:
751  spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220);
752  break;
753  // Yaaarrrr - pirate
754  case 2:
755  spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222);
756  break;
757  }
758 
759  m_caster->CastSpell(m_caster, spell_id, true, NULL);
760  return;
761  }
762  case 8593: // Symbol of life (restore creature to life)
763  case 31225: // Shimmering Vessel (restore creature to life)
764  {
766  return;
768  return;
769  }
770  case 33655: // Q: Mission: Gateways Murketh and Shaadraz
771  {
772  if (m_caster->GetTypeId() != TYPEID_PLAYER || !((Player*)m_caster)->IsFlying())
773  return;
774 
775  Player* player = m_caster->ToPlayer();
776 
777  if (m_caster->GetDistance(-145.554f, 1511.28f, 34.3641f) < 25)
778  player->KilledMonsterCredit(19291, 0);
779  if (m_caster->GetDistance(-304.408f, 1524.45f, 37.9685f) < 25)
780  player->KilledMonsterCredit(19292, 0);
781  return;
782  }
783  case 12162: // Deep wounds
784  case 12850: // (now good common check for this spells)
785  case 12868:
786  {
787  if (!unitTarget)
788  return;
789 
790  float damage;
791  // DW should benefit of attack power, damage percent mods etc.
792  // @todo check if using offhand damage is correct and if it should be divided by 2
795  else
797 
798  switch (m_spellInfo->Id)
799  {
800  case 12162:
801  damage *= 0.2f;
802  break; // Rank 1
803  case 12850:
804  damage *= 0.4f;
805  break; // Rank 2
806  case 12868:
807  damage *= 0.6f;
808  break; // Rank 3
809  default:
810  sLog.outError("Spell::EffectDummy: Spell %u not handled in DW", m_spellInfo->Id);
811  return;
812  };
813 
814  int32 deepWoundsDotBasePoints0 = int32(damage / 4);
815  m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
816  return;
817  }
818  case 12975: //Last Stand
819  {
820  int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth() * 0.3);
821  m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
822  return;
823  }
824  case 13120: // net-o-matic
825  {
826  if (!unitTarget)
827  return;
828 
829  uint32 spell_id = 0;
830 
831  uint32 roll = urand(0, 99);
832 
833  if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
834  spell_id = 16566;
835  else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
836  spell_id = 13119;
837  else // normal root
838  spell_id = 13099;
839 
840  m_caster->CastSpell(unitTarget, spell_id, true, NULL);
841  return;
842  }
843  case 13278: // Gnomish Death Ray (First Dummy)
844  m_caster->CastSpell(m_caster, 13493, true, NULL);
845  break;
846  case 13280: // Gnomish Death Ray (Second Dummy)
847  {
848  if (!unitTarget)
849  return;
850 
851  if (urand(0, 100) < 15)
852  m_caster->CastSpell(m_caster, 13279, true, NULL); // fail - shitty gnomish technology
853  else
854  m_caster->CastSpell(unitTarget, 13279, true, NULL); // Boom!
855 
856  return;
857  }
858  case 13567: // Dummy Trigger
859  {
860  // can be used for different aura triggering, so select by aura
862  return;
863 
864  switch (m_triggeredByAuraSpell->Id)
865  {
866  case 26467: // Persistent Shield
867  m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
868  break;
869  default:
870  sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u", m_triggeredByAuraSpell->Id);
871  break;
872  }
873  return;
874  }
875  case 14537: // Six Demon Bag
876  {
877  if (!unitTarget || !unitTarget->IsAlive())
878  return;
879 
880  uint32 ClearSpellId[6] =
881  {
882  15662, // Fireball
883  11538, // Frostball
884  21179, // Chain Lightning
885  14621, // Polymorph
886  25189, // Enveloping Winds
887  14642 // Summon Felhund minion
888  };
889 
890  uint32 rand = urand(0, 100);
891 
892  if (rand < 25) // Fireball (25% chance)
893  spell_id = ClearSpellId[0];
894  else if (rand >= 25 && rand < 50) // Frostball (25% chance)
895  spell_id = ClearSpellId[1];
896  else if (rand >= 50 && rand < 70) // Chain Lighting (25% chance)
897  spell_id = ClearSpellId[2];
898  else if (rand >= 70 && rand < 80) // Polymorph (10% chance)
899  {
900  spell_id = ClearSpellId[3];
901  if (urand(0, 100) <= 30) // 30% chance to self-cast
903  }
904  else if (rand >= 80 && rand < 95) // Enveloping Winds (15% chance)
905  spell_id = ClearSpellId[4];
906  else // Summon Felhund minion (5% chance)
907  {
908  spell_id = ClearSpellId[5];
910  }
911 
912  m_caster->CastSpell(unitTarget, spell_id, true, NULL);
913  return;
914  }
915  case 14185: // Preparation Rogue
916  {
917  if (m_caster->GetTypeId() != TYPEID_PLAYER)
918  return;
919 
920  //immediately finishes the cooldown on certain Rogue abilities
921  const PlayerSpellMap& sp_list = m_caster->ToPlayer()->GetSpellMap();
922  for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
923  {
924  uint32 classspell = itr->first;
925  SpellEntry const* spellInfo = sSpellStore.LookupEntry(classspell);
926 
927  if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
928  m_caster->ToPlayer()->RemoveSpellCooldown(classspell, true);
929  }
930  return;
931  }
932  case 15998: // Capture Worg Pup
933  case 29435: // Capture Female Kaliri Hatchling
934  {
936  return;
937 
939  return;
940  }
941  case 16589: // Noggenfogger Elixir
942  {
943  if (m_caster->GetTypeId() != TYPEID_PLAYER)
944  return;
945 
946  uint32 spell_id = 0;
947  switch (urand(1, 3))
948  {
949  case 1:
950  spell_id = 16595;
951  break;
952  case 2:
953  spell_id = 16593;
954  break;
955  default:
956  spell_id = 16591;
957  break;
958  }
959 
960  m_caster->CastSpell(m_caster, spell_id, true, NULL);
961  return;
962  }
963  case 17251: // Spirit Healer Res
964  {
965  if (!unitTarget || !m_originalCaster)
966  return;
967 
969  {
971  data << uint64(unitTarget->GetGUID());
973  }
974  return;
975  }
976  case 17271: // Test Fetid Skull
977  {
979  return;
980 
981  uint32 spell_id = roll_chance_i(50)
982  ? 17269 // Create Resonating Skull
983  : 17270; // Create Bone Dust
984 
985  m_caster->CastSpell(m_caster, spell_id, true, NULL);
986  return;
987  }
988  case 20577: // Cannibalize
989  {
990  if (unitTarget)
991  m_caster->CastSpell(m_caster, 20578, false, NULL);
992 
993  return;
994  }
995  case 23019: // Crystal Prison Dummy DND
996  {
998  return;
999 
1000  Creature* creatureTarget = unitTarget->ToCreature();
1001 
1002  GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime() - time(NULL));
1003  sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019");
1004 
1005  creatureTarget->ForcedDespawn();
1006 
1008  data << uint64(Crystal_Prison->GetGUID());
1009  m_caster->SendMessageToSet(&data, true);
1010 
1011  return;
1012  }
1013  case 23074: // Arcanite Dragonling
1014  {
1015  if (!m_CastItem)
1016  return;
1017 
1018  m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
1019  return;
1020  }
1021  case 23075: // Mithril Mechanical Dragonling
1022  {
1023  if (!m_CastItem)
1024  return;
1025 
1026  m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
1027  return;
1028  }
1029  case 23076: // Mechanical Dragonling
1030  {
1031  if (!m_CastItem)
1032  return;
1033 
1034  m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
1035  return;
1036  }
1037  case 23133: // Gnomish Battle Chicken
1038  {
1039  if (!m_CastItem)
1040  return;
1041 
1042  m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
1043  return;
1044  }
1045  case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
1046  {
1047  int32 r = irand(0, 119);
1048  if (r < 20) // Transporter Malfunction - 1/6 polymorph
1049  m_caster->CastSpell(m_caster, 23444, true);
1050  else if (r < 100) // Evil Twin - 4/6 evil twin
1051  m_caster->CastSpell(m_caster, 23445, true);
1052  else // 1/6 miss the target
1053  m_caster->CastSpell(m_caster, 36902, true);
1054 
1055  return;
1056  }
1057  case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
1058  {
1059  if (roll_chance_i(50)) // Gadgetzan Transporter - success
1060  m_caster->CastSpell(m_caster, 23441, true);
1061  else // failure
1062  m_caster->CastSpell(m_caster, 23446, true);
1063 
1064  return;
1065  }
1066  case 23645: // Hourglass Sand
1067  m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
1068  return;
1069  case 23725: // Gift of Life (warrior bwl trinket)
1070  m_caster->CastSpell(m_caster, 23782, true);
1071  m_caster->CastSpell(m_caster, 23783, true);
1072  return;
1073  case 24930: // Hallow's End Candy
1074  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1075  return;
1076 
1077  switch (irand(0, 3))
1078  {
1079  case 0:
1080  m_caster->CastSpell(m_caster, 24927, true); // Ghost
1081  break;
1082  case 1:
1083  m_caster->CastSpell(m_caster, 24926, true); // Pirate
1084  if (m_caster->getGender() == GENDER_MALE)
1085  m_caster->CastSpell(m_caster, 44743, true);
1086  else
1087  m_caster->CastSpell(m_caster, 44742, true);
1088  break;
1089  case 2:
1090  m_caster->CastSpell(m_caster, 24925, true); // Skeleton
1091  break;
1092  case 3:
1093  m_caster->CastSpell(m_caster, 24924, true); // Huge and Orange
1094  break;
1095  }
1096  return;
1097  case 25860: // Reindeer Transformation
1098  {
1100  return;
1101 
1102  float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
1103  float speed = m_caster->GetSpeedRate(MOVE_RUN);
1104 
1106 
1107  //5 different spells used depending on mounted speed and if mount can fly or not
1108  if (flyspeed >= 4.1f)
1109  // Flying Reindeer
1110  m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
1111  else if (flyspeed >= 3.8f)
1112  // Flying Reindeer
1113  m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
1114  else if (flyspeed >= 1.6f)
1115  // Flying Reindeer
1116  m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
1117  else if (speed >= 2.0f)
1118  // Reindeer
1119  m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
1120  else
1121  // Reindeer
1122  m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
1123 
1124  return;
1125  }
1126  //case 26074: // Holiday Cheer
1127  // return; -- implemented at client side
1128  case 28006: // Arcane Cloaking
1129  {
1131  m_caster->CastSpell(unitTarget, 29294, true);
1132 
1133  return;
1134  }
1135  // Polarity Shift
1136  case 28089:
1137  if (unitTarget)
1138  unitTarget->CastSpell(unitTarget, roll_chance_i(50) ? 28059 : 28084, true, NULL, NULL, m_caster->GetGUID());
1139  break;
1140  // Polarity Shift
1141  case 39096:
1142  if (unitTarget)
1143  unitTarget->CastSpell(unitTarget, roll_chance_i(50) ? 39088 : 39091, true, NULL, NULL, m_caster->GetGUID());
1144  break;
1145  case 29200: // Purify Helboar Meat
1146  {
1147  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1148  return;
1149 
1150  uint32 spell_id = roll_chance_i(50)
1151  ? 29277 // Summon Purified Helboar Meat
1152  : 29278; // Summon Toxic Helboar Meat
1153 
1154  m_caster->CastSpell(m_caster, spell_id, true, NULL);
1155  return;
1156  }
1157  case 29858: // Soulshatter
1158  {
1161  m_caster->CastSpell(unitTarget, 32835, true);
1162 
1163  return;
1164  }
1165  case 29970: // Deactivate Blizzard (Naxxramas: Sapphiron)
1166  {
1167  if (!unitTarget)
1168  return;
1169 
1171  return;
1172  }
1173  case 30004: // Flame Wreath
1174  {
1176  return;
1177 
1178  m_caster->CastSpell(unitTarget, 29946, true);
1179  return;
1180  }
1181  case 30458: // Nigh Invulnerability
1182  {
1183  if (!m_CastItem)
1184  return;
1185 
1186  if (roll_chance_i(86)) // Nigh-Invulnerability - success
1187  m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1188  else // backfire in 14% casts
1189  m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1190 
1191  return;
1192  }
1193  case 30507: // Poultryizer
1194  {
1195  if (!m_CastItem)
1196  return;
1197 
1198  if (roll_chance_i(80)) // Poultryized! - success
1199  m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1200  else // backfire 20%
1201  m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1202 
1203  return;
1204  }
1205  case 33060: // Make a Wish
1206  {
1207  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1208  return;
1209 
1210  uint32 spell_id = 0;
1211 
1212  switch (urand(1, 5))
1213  {
1214  case 1:
1215  spell_id = 33053;
1216  break; // Mr Pinchy's Blessing
1217  case 2:
1218  spell_id = 33057;
1219  break; // Summon Mighty Mr. Pinchy
1220  case 3:
1221  spell_id = 33059;
1222  break; // Summon Furious Mr. Pinchy
1223  case 4:
1224  spell_id = 33062;
1225  break; // Tiny Magical Crawdad
1226  case 5:
1227  spell_id = 33064;
1228  break; // Mr. Pinchy's Gift
1229  }
1230 
1231  m_caster->CastSpell(m_caster, spell_id, true, NULL);
1232  return;
1233  }
1234  case 35745: // Socrethar's Stone
1235  {
1236  uint32 spell_id;
1237  switch (m_caster->GetAreaId())
1238  {
1239  case 3900:
1240  spell_id = 35743;
1241  break; // Socrethar Portal
1242  case 3742:
1243  spell_id = 35744;
1244  break; // Socrethar Portal
1245  default:
1246  return;
1247  }
1248 
1249  m_caster->CastSpell(m_caster, spell_id, true);
1250  return;
1251  }
1252  case 37674: // Chaos Blast
1253  {
1254  if (!unitTarget)
1255  return;
1256 
1257  int32 basepoints0 = 100;
1258  m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1259  return;
1260  }
1261  case 40109: // Knockdown Fel Cannon: The Bolt
1262  {
1263  if (!unitTarget)
1264  return;
1265 
1266  unitTarget->CastSpell(unitTarget, 40075, true);
1267  return;
1268  }
1269  case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1270  {
1271  // selecting one from Bloodstained Fortune item
1272  uint32 newitemid;
1273  switch (urand(1, 20))
1274  {
1275  case 1:
1276  newitemid = 32688;
1277  break;
1278  case 2:
1279  newitemid = 32689;
1280  break;
1281  case 3:
1282  newitemid = 32690;
1283  break;
1284  case 4:
1285  newitemid = 32691;
1286  break;
1287  case 5:
1288  newitemid = 32692;
1289  break;
1290  case 6:
1291  newitemid = 32693;
1292  break;
1293  case 7:
1294  newitemid = 32700;
1295  break;
1296  case 8:
1297  newitemid = 32701;
1298  break;
1299  case 9:
1300  newitemid = 32702;
1301  break;
1302  case 10:
1303  newitemid = 32703;
1304  break;
1305  case 11:
1306  newitemid = 32704;
1307  break;
1308  case 12:
1309  newitemid = 32705;
1310  break;
1311  case 13:
1312  newitemid = 32706;
1313  break;
1314  case 14:
1315  newitemid = 32707;
1316  break;
1317  case 15:
1318  newitemid = 32708;
1319  break;
1320  case 16:
1321  newitemid = 32709;
1322  break;
1323  case 17:
1324  newitemid = 32710;
1325  break;
1326  case 18:
1327  newitemid = 32711;
1328  break;
1329  case 19:
1330  newitemid = 32712;
1331  break;
1332  case 20:
1333  newitemid = 32713;
1334  break;
1335  default:
1336  return;
1337  }
1338 
1339  DoCreateItem(effIndex, newitemid);
1340  return;
1341  }
1342  case 40834: // Agonizing Flames
1343  {
1345  return;
1346 
1347  m_caster->CastSpell(unitTarget, 40932, true);
1348  break;
1349  }
1350  // Salvage Wreckage
1351  case 42287:
1352  {
1354  return;
1355 
1356  if (roll_chance_i(66))
1357  m_caster->CastSpell(m_caster, 42289, true, m_CastItem); // Summon Mirefin Burrower
1358  else
1359  m_caster->CastSpell(m_caster, 42288, true); // Summon Salvaged Lockbox
1360 
1362 
1363  return;
1364  }
1365  // Demon Broiled Surprise
1366  case 43723:
1367  {
1368  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1369  return;
1370 
1371  Player* player = m_caster->ToPlayer();
1372 
1373  if (player && player->GetQuestStatus(11379) == QUEST_STATUS_INCOMPLETE)
1374  {
1375  Creature* creature = player->FindNearestCreature(19973, 10, false);
1376  if (!creature)
1377  {
1379  return;
1380  }
1381 
1382  player->CastSpell(player, 43753, false);
1383  }
1384  return;
1385  }
1386  case 44875: // Complete Raptor Capture
1387  {
1389  return;
1390 
1392 
1393  //cast spell Raptor Capture Credit
1394  m_caster->CastSpell(m_caster, 42337, true, NULL);
1395  return;
1396  }
1397  case 37473: // Detect Whispers (related to quest 10607 - Whispers of the Raven God_Whispers of the Raven God)
1398  {
1399  if (!unitTarget)
1400  return;
1401 
1403  break;
1404  }
1405  case 37573: //Temporal Phase Modulator
1406  {
1407  if (!unitTarget)
1408  return;
1409 
1410  TempSummon* tempSummon = dynamic_cast<TempSummon*>(unitTarget);
1411  if (!tempSummon)
1412  return;
1413 
1414  uint32 health = tempSummon->GetHealth();
1415  const uint32 entry_list[6] = {21821, 21820, 21817};
1416 
1417  float x = tempSummon->GetPositionX();
1418  float y = tempSummon->GetPositionY();
1419  float z = tempSummon->GetPositionZ();
1420  float o = tempSummon->GetOrientation();
1421 
1422  tempSummon->UnSummon();
1423 
1424  Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 180000);
1425  if (!pCreature)
1426  return;
1427 
1428  pCreature->SetHealth(health);
1429 
1430  if (pCreature->IsAIEnabled)
1431  pCreature->AI()->AttackStart(m_caster);
1432 
1433  return;
1434  }
1435  case 34665: //Administer Antidote
1436  {
1438  || unitTarget->GetEntry() != 16880 || unitTarget->IsPet())
1439  return;
1440 
1441  unitTarget->ToCreature()->UpdateEntry(16992);
1443 
1444  if (unitTarget->IsAIEnabled)
1446 
1447  return;
1448  }
1449  case 44997: // Converting Sentry
1450  {
1452  return;
1453 
1454  Creature* creatureTarget = (Creature*)unitTarget;
1455 
1456  creatureTarget->ForcedDespawn();
1457 
1458  //Converted Sentry Credit
1459  m_caster->CastSpell(m_caster, 45009, true);
1460  return;
1461  }
1462  case 45030: // Impale Emissary
1463  {
1464  // Emissary of Hate Credit
1465  m_caster->CastSpell(m_caster, 45088, true);
1466  return;
1467  }
1468  case 50243: // Teach Language
1469  {
1470  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1471  return;
1472 
1473  // spell has a 1/3 chance to trigger one of the below
1474  if (roll_chance_i(66))
1475  return;
1476  if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
1477  {
1478  // 1000001 - gnomish binary
1479  m_caster->CastSpell(m_caster, 50242, true);
1480  }
1481  else
1482  {
1483  // 01001000 - goblin binary
1484  m_caster->CastSpell(m_caster, 50246, true);
1485  }
1486 
1487  return;
1488  }
1489  case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1490  {
1491  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1492  return;
1493 
1495  bg->EventPlayerDroppedFlag(m_caster->ToPlayer());
1496 
1497  m_caster->CastSpell(m_caster, 30452, true, NULL);
1498  return;
1499  }
1500 
1501  case 35372: // Protectorate Igniter
1502  {
1503  if (Creature* victim = unitTarget->ToCreature())
1504  {
1505  victim->setDeathState(JUST_DIED);
1506  victim->RemoveCorpse(true);
1507  }
1508  }
1509  break;
1510  case 45226: // banging the gong
1511  if (InstanceData* pInstance = m_caster->GetInstanceData())
1512  pInstance->ProcessEvent(unitTarget, 1);
1513  break;
1514  // Arcane Torrent (Mana)
1515  case 28730:
1516  {
1517  Unit* caster = GetCaster();
1518  if (!caster)
1519  break;
1520 
1521  Aura* dummy = caster->GetDummyAura(28734);
1522  if (dummy)
1523  {
1524  int32 bp = m_spellInfo->EffectBasePoints[effIndex] * dummy->GetStackAmount();
1525  caster->CastCustomSpell(caster, 28733, &bp, NULL, NULL, true);
1526  caster->RemoveAurasDueToSpell(28734);
1527  }
1528  break;
1529  }
1530  // Arcane Torrent (Energy)
1531  case 25046:
1532  {
1533  Unit* caster = GetCaster();
1534  if (!caster)
1535  break;
1536 
1537  // Search Mana Tap auras on caster
1538  Aura* dummy = caster->GetDummyAura(28734);
1539  if (dummy)
1540  {
1541  int32 bp = dummy->GetStackAmount() * 10;
1542  caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true);
1543  caster->RemoveAurasDueToSpell(28734);
1544  }
1545  break;
1546  }
1547  case 39105: //Activate Nether-wraith Beacon
1548  {
1549  Player* player = m_caster->ToPlayer();
1550  if (!player)
1551  break;
1552  for (int i = 0; i < 2; i++)
1553  {
1554  float x, y, z;
1555  player->GetClosePoint(x, y, z, player->GetObjectBoundingRadius(), 20.0f, i * static_cast<float>(M_PI));
1556  Creature* nether = player->SummonCreature(22408, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 180000);
1557  if (nether)
1558  nether->AI()->AttackStart(player);
1559  }
1560  break;
1561  }
1562  }
1563 
1564  //All IconID Check in there
1565  switch (m_spellInfo->SpellIconID)
1566  {
1567  // Berserking (troll racial traits)
1568  case 1661:
1569  {
1570  uint32 healthPerc = uint32((float(m_caster->GetHealth()) / m_caster->GetMaxHealth()) * 100);
1571  int32 melee_mod = 10;
1572  if (healthPerc <= 40)
1573  melee_mod = 30;
1574  if (healthPerc < 100 && healthPerc > 40)
1575  melee_mod = 10 + (100 - healthPerc) / 3;
1576 
1577  int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1578  int32 hasteModBasePoints1 = (5 - melee_mod);
1579  int32 hasteModBasePoints2 = 5;
1580 
1581  // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1583  m_caster->CastCustomSpell(m_caster, 26635, &hasteModBasePoints0, &hasteModBasePoints1, &hasteModBasePoints2, true, NULL);
1584  return;
1585  }
1586  case 30543: //Turn Cooldown : chess event karazhan dummy
1587  {
1588  return;
1589  }
1590  case 32225: //Chess Event: Take Action Melee
1591  {
1592  switch (m_caster->GetEntry())
1593  {
1594  case 21684:
1595  m_caster->CastSpell(m_caster, 37150, true);
1596  break;//King Liane Melee Attack
1597  case 21683:
1598  m_caster->CastSpell(m_caster, 37149, true);
1599  break;//Human Conjur Melee Attack
1600  case 21682:
1601  m_caster->CastSpell(m_caster, 37147, true);
1602  break;//Human Cleric Melee Attack
1603  case 21664:
1604  m_caster->CastSpell(m_caster, 37143, true);
1605  break;//Human Charger Melee Attack
1606  case 21160:
1607  m_caster->CastSpell(m_caster, 37142, true);
1608  break; //Water Elemental melee Attack
1609  case 17211:
1610  m_caster->CastSpell(m_caster, 32227, true);
1611  break; //Human Footan Melee Attack
1612  case 21752:
1613  m_caster->CastSpell(m_caster, 37348, true);
1614  break; //Warchief Blackhand Melee Attack
1615  case 21750:
1616  m_caster->CastSpell(m_caster, 37345, true);
1617  break; //Orc Warlock Melee Attack
1618  case 21747:
1619  m_caster->CastSpell(m_caster, 37337, true);
1620  break; //Orc Necrolyte Melee Attack
1621  case 21748:
1622  m_caster->CastSpell(m_caster, 37339, true);
1623  break; //Orc Wolf Melee Attack
1624  case 21726:
1625  m_caster->CastSpell(m_caster, 37220, true);
1626  break; //Summoned Deamon
1627  case 17469:
1628  m_caster->CastSpell(m_caster, 32228, true);
1629  break; //Orc Gunt Melee Attack
1630  }
1631  return;
1632  }
1633  }
1634  }
1635  case SPELLFAMILY_MAGE:
1636  switch (m_spellInfo->Id)
1637  {
1638  case 11958: // Cold Snap
1639  {
1640  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1641  return;
1642 
1643  // immediately finishes the cooldown on Frost spells
1644  const PlayerSpellMap& sp_list = m_caster->ToPlayer()->GetSpellMap();
1645  for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1646  {
1647  if (itr->second.state == PLAYERSPELL_REMOVED)
1648  continue;
1649 
1650  uint32 classspell = itr->first;
1651  SpellEntry const* spellInfo = sSpellStore.LookupEntry(classspell);
1652 
1653  if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1655  spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1656  m_caster->ToPlayer()->RemoveSpellCooldown(classspell, true);
1657  }
1658  return;
1659  }
1660  case 32826:
1661  {
1663  {
1664  //Polymorph Cast Visual Rank 1
1665  const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1666  unitTarget->CastSpell(unitTarget, spell_list[urand(0, 5)], true);
1667  }
1668  return;
1669  }
1670  }
1671  break;
1672  case SPELLFAMILY_WARRIOR:
1673  // Charge
1674  if (m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867)
1675  {
1676  int32 chargeBasePoints0 = damage;
1677  m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1678  return;
1679  }
1680  // Execute
1681  if (m_spellInfo->SpellFamilyFlags & 0x20000000)
1682  {
1683  if (!unitTarget)
1684  return;
1685 
1686  spell_id = 20647;
1689  break;
1690  }
1691  if (m_spellInfo->Id == 21977) //Warrior's Wrath
1692  {
1693  if (!unitTarget)
1694  return;
1695 
1696  m_caster->CastSpell(unitTarget, 21887, true); // spell mod
1697  return;
1698  }
1699  if (m_spellInfo->Id == 30284) //Chess: Change Facing
1700  {
1702 
1703  // and client
1704  WorldPacket data;
1705  m_caster->BuildHeartBeatMsg(&data);
1706  m_caster->SendMessageToSet(&data, false);
1707 
1708  return;
1709  }
1710  if (m_spellInfo->Id == 37151 || m_spellInfo->Id == 37148 || m_spellInfo->Id == 37144) //MoveSpells for Chess_Event - dunno why has spellfamilyname for Warrior Spells
1711  {
1713  {
1714  if (unitTarget->GetTypeId() == TYPEID_UNIT && !(unitTarget->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL))) //if UNIT_FLAG_NOT_SELECTABLE than field is occuped
1715  {
1716  //cast transform Field
1717  if (m_caster)
1718  {
1719  unitTarget->CastSpell(unitTarget, 32745, true); //implemented
1720  m_caster->CastSpell(m_caster, 30543, true); //not implemented -- handled in this function
1722 
1723  //create new Move Marker
1724  m_caster->CastSpell(unitTarget, 32261, true);
1725 
1726  //Register Scripts
1727  //prepare Move
1728  float speed = m_caster->GetSpeed(MOVE_WALK);
1729  speed *= 0.001f;
1730  ScriptInfo *si = new ScriptInfo;
1732  si->MoveTo.DestX = unitTarget->GetPositionX();
1733  si->MoveTo.DestY = unitTarget->GetPositionY();
1734  si->MoveTo.DestZ = unitTarget->GetPositionZ();
1736 
1737  //prepare change facing
1738  ScriptInfo *si2 = new ScriptInfo;
1740  si2->CastSpell.SpellID = 38011;
1741 
1742  //insert scripts
1743  m_caster->GetMap()->ScriptCommandStart((*si2), 2 + 1 + si->MoveTo.TravelTime / IN_MILLISECONDS, m_caster, m_caster);
1745 
1746  //set cooldowns
1747  uint32 cooldown = 12000;
1748  uint32 SpellTurn = 30284;
1749  time_t cd = time(NULL) + cooldown / IN_MILLISECONDS;
1751  m_caster->ToCreature()->_AddCreatureSpellCooldown(SpellTurn, cd);
1753 
1754  //send cooldowns to player
1755  if (m_caster->isCharmed())
1756  {
1757  Unit* charmer = m_caster->GetCharmer();
1758  if (charmer && charmer->GetTypeId() == TYPEID_PLAYER)
1759  {
1760  WorldPacket data(SMSG_SPELL_COOLDOWN, (8 + 1 + 16));
1761  data << m_caster->GetGUID();
1762  data << uint8(0x0);
1763  data << m_spellInfo->Id;
1764  data << cooldown;
1765  data << SpellTurn;
1766  data << cooldown;
1767  charmer->ToPlayer()->GetSession()->SendPacket(&data);
1768  }
1769  }
1770  }
1771  }
1772  }
1773  return;
1774  }
1775  break;
1776  case SPELLFAMILY_WARLOCK:
1777  //Life Tap (only it have this with dummy effect)
1778  if (m_spellInfo->SpellFamilyFlags == 0x40000)
1779  {
1780  float cost = damage;
1781 
1782  if (Player* modOwner = m_caster->GetSpellModOwner())
1783  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost, this);
1784 
1786 
1787  if (int32(m_caster->GetHealth()) > dmg)
1788  {
1789  // Shouldn't Appear in Combat Log
1790  m_caster->ModifyHealth(-dmg);
1791 
1792  int32 mana = dmg;
1793 
1795  for (Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1796  {
1797  // only Imp. Life Tap have this in combination with dummy aura
1798  if ((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1799  mana = ((*itr)->GetModifier()->m_amount + 100) * mana / 100;
1800  }
1801 
1802  m_caster->CastCustomSpell(m_caster, 31818, &mana, NULL, NULL, true, NULL);
1803 
1804  // Mana Feed
1806  manaFeedVal = manaFeedVal * mana / 100;
1807  if (manaFeedVal > 0 && m_caster->isPlayer() && m_caster->ToPlayer()->GetPet())
1808  m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1809  }
1810  else
1812  return;
1813  }
1814  break;
1815  case SPELLFAMILY_PRIEST:
1816  switch (m_spellInfo->Id)
1817  {
1818  case 28598: // Touch of Weakness triggered spell
1819  {
1821  return;
1822 
1823  uint32 spellid = 0;
1824  switch (m_triggeredByAuraSpell->Id)
1825  {
1826  case 2652:
1827  spellid = 2943;
1828  break; // Rank 1
1829  case 19261:
1830  spellid = 19249;
1831  break; // Rank 2
1832  case 19262:
1833  spellid = 19251;
1834  break; // Rank 3
1835  case 19264:
1836  spellid = 19252;
1837  break; // Rank 4
1838  case 19265:
1839  spellid = 19253;
1840  break; // Rank 5
1841  case 19266:
1842  spellid = 19254;
1843  break; // Rank 6
1844  case 25461:
1845  spellid = 25460;
1846  break; // Rank 7
1847  default:
1848  sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandled spell %u", m_triggeredByAuraSpell->Id);
1849  return;
1850  }
1851  m_caster->CastSpell(unitTarget, spellid, true, NULL);
1852  return;
1853  }
1854  }
1855  break;
1856  case SPELLFAMILY_DRUID:
1857  switch (m_spellInfo->Id)
1858  {
1859  case 5420: // Tree of Life passive
1860  {
1861  // Tree of Life area effect
1862  int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT) / 4);
1863  m_caster->CastCustomSpell(m_caster, 34123, &health_mod, NULL, NULL, true, NULL);
1864  return;
1865  }
1866  }
1867  break;
1868  case SPELLFAMILY_ROGUE:
1869  switch (m_spellInfo->Id)
1870  {
1871  case 31231: // Cheat Death
1872  {
1873  m_caster->CastSpell(m_caster, 45182, true);
1874  return;
1875  }
1876  case 5938: // Shiv
1877  {
1878  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1879  return;
1880 
1881  Player* pCaster = m_caster->ToPlayer();
1882 
1883  Item* item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1884  if (!item)
1885  return;
1886 
1887  ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
1888 
1889  // all poison enchantments is temporary
1890  if (uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
1891  {
1892  if (SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1893  {
1894  for (int s = 0; s < 3; s++)
1895  {
1896  if (pEnchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1897  continue;
1898 
1899  SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1900  if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1901  continue;
1902 
1903  m_caster->CastSpell(unitTarget, combatEntry, true, item);
1904  }
1905  }
1906  }
1907 
1908  m_caster->CastSpell(unitTarget, 5940, true);
1909  return;
1910  }
1911  }
1912  break;
1913  case SPELLFAMILY_HUNTER:
1914  // Kill command
1915  if (m_spellInfo->SpellFamilyFlags & 0x00080000000000LL)
1916  {
1917  if (m_caster->getClass() != CLASS_HUNTER)
1918  return;
1919 
1920  // clear hunter crit aura state
1922 
1923  // additional damage from pet to pet target
1924  Unit* pet = m_caster->GetGuardianPet();
1925  if (!pet || !pet->GetVictim())
1926  return;
1927 
1928  uint32 spell_id = 0;
1929  switch (m_spellInfo->Id)
1930  {
1931  case 34026:
1932  spell_id = 34027;
1933  break; // rank 1
1934  default:
1935  sLog.outError("Spell::EffectDummy: Spell %u not handled in KC", m_spellInfo->Id);
1936  return;
1937  }
1938 
1939  pet->CastSpell(pet->GetVictim(), spell_id, true);
1940  return;
1941  }
1942 
1943  switch (m_spellInfo->Id)
1944  {
1945  case 23989: //Readiness talent
1946  {
1947  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1948  return;
1949 
1950  //immediately finishes the cooldown for hunter abilities
1951  const PlayerSpellMap& sp_list = m_caster->ToPlayer()->GetSpellMap();
1952  for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1953  {
1954  uint32 classspell = itr->first;
1955  SpellEntry const* spellInfo = sSpellStore.LookupEntry(classspell);
1956 
1957  if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0)
1958  m_caster->ToPlayer()->RemoveSpellCooldown(classspell, true);
1959  }
1960  return;
1961  }
1962  case 37506: // Scatter Shot
1963  {
1964  if (m_caster->GetTypeId() != TYPEID_PLAYER)
1965  return;
1966 
1967  // break Auto Shot and autohit
1969  m_caster->AttackStop();
1971  return;
1972  }
1973  }
1974  break;
1975  case SPELLFAMILY_PALADIN:
1976  switch (m_spellInfo->SpellIconID)
1977  {
1978  case 156: // Holy Shock
1979  {
1980  if (!unitTarget)
1981  return;
1982 
1983  int hurt = 0;
1984  int heal = 0;
1985 
1986  switch (m_spellInfo->Id)
1987  {
1988  case 20473:
1989  hurt = 25912;
1990  heal = 25914;
1991  break;
1992  case 20929:
1993  hurt = 25911;
1994  heal = 25913;
1995  break;
1996  case 20930:
1997  hurt = 25902;
1998  heal = 25903;
1999  break;
2000  case 27174:
2001  hurt = 27176;
2002  heal = 27175;
2003  break;
2004  case 33072:
2005  hurt = 33073;
2006  heal = 33074;
2007  break;
2008  default:
2009  sLog.outError("Spell::EffectDummy: Spell %u not handled in HS", m_spellInfo->Id);
2010  return;
2011  }
2012 
2014  m_caster->CastSpell(unitTarget, heal, true, 0);
2015  else
2016  m_caster->CastSpell(unitTarget, hurt, true, 0);
2017 
2018  return;
2019  }
2020  case 561: // Judgement of command
2021  {
2022  if (!unitTarget)
2023  return;
2024 
2025  uint32 spell_id = m_spellInfo->EffectBasePoints[effIndex] + 1; // m_currentBasePoints[effIndex]+1;
2026  SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
2027  if (!spell_proto)
2028  return;
2029 
2031  {
2032  // decreased damage (/2) for non-stunned target.
2033  SpellModifier* mod = new SpellModifier;
2034  mod->op = SPELLMOD_DAMAGE;
2035  mod->value = -50;
2036  mod->type = SPELLMOD_PCT;
2037  mod->spellId = m_spellInfo->Id;
2038  mod->effectId = effIndex;
2039  mod->lastAffected = NULL;
2040  mod->mask = 0x0000020000000000LL;
2041  mod->charges = 0;
2042 
2043  m_caster->ToPlayer()->AddSpellMod(mod, true);
2044  m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
2045  // mod deleted
2046  m_caster->ToPlayer()->AddSpellMod(mod, false);
2047  }
2048  else
2049  m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
2050 
2051  return;
2052  }
2053  }
2054 
2055  switch (m_spellInfo->Id)
2056  {
2057  case 31789: // Righteous Defense (step 1)
2058  {
2059  if (m_caster->GetTypeId() != TYPEID_PLAYER)
2060  {
2062  return;
2063  }
2064 
2065  // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
2067  if (friendTarget)
2068  {
2069  Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
2070  if (!player || !player->IsInSameRaidWith((Player*)m_caster))
2071  friendTarget = NULL;
2072  }
2073 
2074  // non-standard cast requirement check
2075  if (!friendTarget || friendTarget->getAttackers().empty())
2076  {
2077  // clear cooldown at fail
2078  ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id, true);
2080  return;
2081  }
2082 
2083  // Righteous Defense (step 2) (in old version 31980 dummy effect)
2084  // Clear targets for eff 1
2085  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2086  {
2087  if (ihit->deleted)
2088  continue;
2089 
2090  ihit->effectMask &= ~(1 << 1);
2091  }
2092 
2093  // not empty (checked)
2094  Unit::AttackerSet attackers = friendTarget->getAttackers();
2095 
2096  // selected from list 3
2097  for (uint32 i = 0; i < std::min(size_t(3), attackers.size()); ++i)
2098  {
2099  Unit::AttackerSet::iterator aItr = attackers.begin();
2100  std::advance(aItr, rand() % attackers.size());
2101  AddUnitTarget((*aItr), 1);
2102  attackers.erase(aItr);
2103  }
2104 
2105  // now let next effect cast spell at each target.
2106  return;
2107  }
2108  case 37877: // Blessing of Faith
2109  {
2110  if (!unitTarget)
2111  return;
2112 
2113  uint32 spell_id = 0;
2114  switch (unitTarget->getClass())
2115  {
2116  case CLASS_DRUID:
2117  spell_id = 37878;
2118  break;
2119  case CLASS_PALADIN:
2120  spell_id = 37879;
2121  break;
2122  case CLASS_PRIEST:
2123  spell_id = 37880;
2124  break;
2125  case CLASS_SHAMAN:
2126  spell_id = 37881;
2127  break;
2128  default:
2129  return; // ignore for not healing classes
2130  }
2131 
2132  m_caster->CastSpell(m_caster, spell_id, true);
2133  return;
2134  }
2135  }
2136  break;
2137  case SPELLFAMILY_SHAMAN:
2138 
2139  // Flametongue Totem & Weapon Proc
2140  if (m_spellInfo->SpellFamilyFlags & 0x400200000LL)
2141  {
2142  // damage is based on the speed of the weapon...
2143  // but we need to know which weapon was used main or off
2146  spell_id = 16368;
2147  break;
2148  }
2149 
2150  //Shaman Rockbiter Weapon
2151  if (m_spellInfo->SpellFamilyFlags == 0x400000)
2152  {
2153  uint32 spell_id = 0;
2154  switch (m_spellInfo->Id)
2155  {
2156  case 8017:
2157  spell_id = 36494;
2158  break; // Rank 1
2159  case 8018:
2160  spell_id = 36750;
2161  break; // Rank 2
2162  case 8019:
2163  spell_id = 36755;
2164  break; // Rank 3
2165  case 10399:
2166  spell_id = 36759;
2167  break; // Rank 4
2168  case 16314:
2169  spell_id = 36763;
2170  break; // Rank 5
2171  case 16315:
2172  spell_id = 36766;
2173  break; // Rank 6
2174  case 16316:
2175  spell_id = 36771;
2176  break; // Rank 7
2177  case 25479:
2178  spell_id = 36775;
2179  break; // Rank 8
2180  case 25485:
2181  spell_id = 36499;
2182  break; // Rank 9
2183  default:
2184  sLog.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo->Id);
2185  return;
2186  }
2187 
2188  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
2189 
2190  if (!spellInfo)
2191  {
2192  sLog.outError("WORLD: unknown spell id %i\n", spell_id);
2193  return;
2194  }
2195 
2196  if (m_caster->GetTypeId() != TYPEID_PLAYER)
2197  return;
2198 
2199  for (int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
2200  {
2202  {
2203  if (item->IsFitToSpellRequirements(m_spellInfo))
2204  {
2205  Spell* spell = new Spell(m_caster, spellInfo, true);
2206 
2207  // enchanting spell selected by calculated damage-per-sec in enchanting effect
2208  // at calculation applied affect from Elemental Weapons talent
2209  // real enchantment damage-1
2210  spell->m_currentBasePoints[1] = damage - 1;
2211 
2212  SpellCastTargets targets;
2213  targets.setItemTarget(item);
2214  spell->prepare(&targets);
2215  }
2216  }
2217  }
2218  return;
2219  }
2220 
2221  if (m_spellInfo->Id == 39610) // Mana-Tide Totem effect
2222  {
2224  return;
2225 
2226  // Regenerate 6% of Total Mana Every 3 secs
2227  int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
2228  m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
2229  return;
2230  }
2231 
2232  break;
2233  }
2234 
2235  //spells triggered by dummy effect should not miss
2236  if (spell_id)
2237  {
2238  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
2239 
2240  if (!spellInfo)
2241  {
2242  sLog.outError("EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
2243  return;
2244  }
2245 
2246  Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true);
2247  if (bp) spell->m_currentBasePoints[0] = bp;
2248  SpellCastTargets targets;
2249  targets.setUnitTarget(unitTarget);
2250  spell->prepare(&targets);
2251  }
2252 
2253  // pet auras
2254  if (PetAura const* petSpell = sSpellMgr.GetPetAura(m_spellInfo->Id))
2255  {
2256  m_caster->AddPetAura(petSpell);
2257  return;
2258  }
2259 
2261  sScriptMgr.EffectDummyCreature(m_caster, m_spellInfo->Id, effIndex, unitTarget->ToCreature());
2262 }
2263 
2265 {
2266  uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2267 
2268  // normal case
2269  SpellEntry const* spellInfo = sSpellStore.LookupEntry(triggered_spell_id);
2270 
2271  if (!spellInfo)
2272  {
2273  sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, triggered_spell_id);
2274  return;
2275  }
2276 
2277  int32 bp = damage;
2278  m_caster->CastCustomSpell(unitTarget, triggered_spell_id, &bp, &bp, &bp, true, NULL, NULL, m_originalCasterGUID);
2279 }
2280 
2282 {
2283  uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2284  SpellEntry const* spellInfo = sSpellStore.LookupEntry(triggered_spell_id);
2285 
2286  if (!spellInfo)
2287  {
2288  sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
2289  return;
2290  }
2291 
2292  finish();
2293 
2294  Spell* spell = new Spell(m_caster, spellInfo, true);
2295  SpellCastTargets targets;
2296  targets.setUnitTarget(unitTarget);
2297  spell->prepare(&targets);
2298 
2300  Spell* curr_spell = m_caster->GetCurrentSpell(spell->GetCurrentContainer());
2301  spell->m_selfContainer = &curr_spell;
2302 }
2303 
2305 {
2306  if (!unitTarget)
2307  return;
2308 
2309  uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2310 
2311  // normal case
2312  SpellEntry const* spellInfo = sSpellStore.LookupEntry(triggered_spell_id);
2313 
2314  if (!spellInfo)
2315  {
2316  sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
2317  return;
2318  }
2319 
2320  switch (m_spellInfo->Id)
2321  {
2322  case 45391:
2323  unitTarget->CastSpell((Unit*)NULL, triggered_spell_id, true, NULL, NULL, m_originalCasterGUID);
2324  break;
2325  case 45388:
2326  unitTarget->CastSpell(m_caster, triggered_spell_id, true, NULL, NULL, m_originalCasterGUID);
2327  break;
2328  case 45782:
2329  unitTarget->CastSpell((Unit*)NULL, triggered_spell_id, true, NULL, NULL, m_originalCasterGUID);
2330  break;
2331  default:
2332  unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
2333  break;
2334  }
2335 }
2336 
2338 {
2339  uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2340 
2341  // special cases
2342  switch (triggered_spell_id)
2343  {
2344  // Vanish
2345  case 18461:
2346  {
2349 
2350  // if this spell is given to NPC it must handle rest by it's own AI
2351  if (m_caster->GetTypeId() != TYPEID_PLAYER)
2352  return;
2353 
2354  // get highest rank of the Stealth spell
2355  bool found = false;
2356  SpellEntry const* spellInfo;
2357  const PlayerSpellMap& sp_list = m_caster->ToPlayer()->GetSpellMap();
2358  for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2359  {
2360  // only highest rank is shown in spell book, so simply check if shown in spell book
2361  if (!itr->second.active || itr->second.disabled || itr->second.state == PLAYERSPELL_REMOVED)
2362  continue;
2363 
2364  spellInfo = sSpellStore.LookupEntry(itr->first);
2365  if (!spellInfo)
2366  continue;
2367 
2369  {
2370  found = true;
2371  break;
2372  }
2373  }
2374 
2375  // no Stealth spell found
2376  if (!found)
2377  return;
2378 
2379  // reset cooldown on it if needed
2380  if (m_caster->ToPlayer()->HasSpellCooldown(spellInfo->Id))
2381  m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
2382 
2383  // Remove from combat
2384  m_caster->CombatStop();
2385 
2386  m_TriggerSpells.push_back(spellInfo);
2387  return;
2388  }
2389  // just skip
2390  case 23770: // Sayge's Dark Fortune of *
2391  // not exist, common cooldown can be implemented in scripts if need.
2392  return;
2393  // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2394  case 29284:
2395  {
2396  const SpellEntry* spell = sSpellStore.LookupEntry(24575);
2397  if (!spell)
2398  return;
2399 
2400  for (uint32 i = 0; i < spell->StackAmount; ++i)
2402  return;
2403  }
2404  // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2405  case 29286:
2406  {
2407  const SpellEntry* spell = sSpellStore.LookupEntry(26464);
2408  if (!spell)
2409  return;
2410 
2411  for (uint32 i = 0; i < spell->StackAmount; ++i)
2413  return;
2414  }
2415  // Righteous Defense
2416  case 31980:
2417  {
2419  return;
2420  }
2421  // Cloak of Shadows
2422  case 35729 :
2423  {
2424  uint32 dispelMask = GetDispelMask(DISPEL_ALL);
2425  Unit::AuraMap& Auras = m_caster->GetAuras();
2426  for (Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2427  {
2428  // remove all harmful spells on you...
2429  SpellEntry const* spell = iter->second->GetSpellProto();
2430  if ((spell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC // only affect magic spells
2431  || ((1 << spell->Dispel) & dispelMask))
2432  // ignore positive and passive auras
2433  && !iter->second->IsPositive() && !iter->second->IsPassive())
2434  {
2436  iter = Auras.begin();
2437  }
2438  }
2439  return;
2440  }
2441  // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2442  case 41967:
2443  {
2444  if (Unit* pet = m_caster->GetGuardianPet())
2445  pet->CastSpell(pet, 28305, true);
2446  return;
2447  }
2448  }
2449 
2450  // normal case
2451  SpellEntry const* spellInfo = sSpellStore.LookupEntry(triggered_spell_id);
2452 
2453  if (!spellInfo)
2454  {
2455  sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
2456  return;
2457  }
2458 
2459  // some triggered spells require specific equipment
2460  if (spellInfo->EquippedItemClass >= 0 && m_caster->GetTypeId() == TYPEID_PLAYER)
2461  {
2462  // main hand weapon required
2463  if (spellInfo->AttributesEx3 & SPELL_ATTR3_MAIN_HAND)
2464  {
2466 
2467  // skip spell if no weapon in slot or broken
2468  if (!item || item->IsBroken())
2469  return;
2470 
2471  // skip spell if weapon not fit to triggered spell
2472  if (!item->IsFitToSpellRequirements(spellInfo))
2473  return;
2474  }
2475 
2476  // offhand hand weapon required
2477  if (spellInfo->AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
2478  {
2480 
2481  // skip spell if no weapon in slot or broken
2482  if (!item || item->IsBroken())
2483  return;
2484 
2485  // skip spell if weapon not fit to triggered spell
2486  if (!item->IsFitToSpellRequirements(spellInfo))
2487  return;
2488  }
2489  }
2490 
2491  if (unitTarget)
2492  m_caster->CastSpell(unitTarget, spellInfo, true, m_CastItem, NULL, m_originalCasterGUID);
2493 }
2494 
2496 {
2497  uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2498 
2499  // normal case
2500  SpellEntry const* spellInfo = sSpellStore.LookupEntry(triggered_spell_id);
2501 
2502  if (!spellInfo)
2503  {
2504  sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2505  m_spellInfo->Id, effIndex, triggered_spell_id);
2506  return;
2507  }
2508 
2509  #ifdef OREGON_DEBUG
2510  if (m_CastItem)
2511  DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2512  #endif
2513 
2514  Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID);
2515 
2516  SpellCastTargets targets;
2517  targets.setDst(&m_targets.m_dstPos);
2518  spell->m_CastItem = m_CastItem;
2519  spell->prepare(&targets, NULL);
2520 }
2521 
2523 {
2524  if (!unitTarget || unitTarget->isInFlight())
2525  return;
2526 
2527  // If not exist data for dest location - return
2528  if (!m_targets.HasDst())
2529  {
2530  sLog.outError("Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id);
2531  return;
2532  }
2533 
2534  // Init dest coordinates
2535  uint32 mapid = m_targets.m_dstPos.GetMapId();
2536  if (mapid == MAPID_INVALID)
2537  mapid = unitTarget->GetMapId();
2538  float x, y, z, orientation;
2539  m_targets.m_dstPos.GetPosition(x, y, z, orientation);
2540  if (!orientation && m_targets.getUnitTarget())
2541  orientation = m_targets.getUnitTarget()->GetOrientation();
2542  DEBUG_LOG("Spell::EffectTeleportUnits - teleport unit to %u %f %f %f %f\n", mapid, x, y, z, orientation);
2543 
2545  unitTarget->ToPlayer()->TeleportTo(mapid, x, y, z, orientation, unitTarget == m_caster ? TELE_TO_SPELL | TELE_TO_NOT_LEAVE_COMBAT : 0);
2546  else if (mapid == unitTarget->GetMapId())
2547  unitTarget->NearTeleportTo(x, y, z, orientation, unitTarget == m_caster);
2548  else
2549  {
2550  sLog.outError("Spell::EffectTeleportUnits - spellId %u attempted to teleport creature to a different map.", m_spellInfo->Id);
2551  return;
2552  }
2553 
2554  // post effects for TARGET_DST_DB
2555  switch (m_spellInfo->Id)
2556  {
2557  // Dimensional Ripper - Everlook
2558  case 23442:
2559  {
2560  int32 r = irand(0, 119);
2561  if (r >= 70) // 7/12 success
2562  {
2563  if (r < 100) // 4/12 evil twin
2564  m_caster->CastSpell(m_caster, 23445, true);
2565  else // 1/12 fire
2566  m_caster->CastSpell(m_caster, 23449, true);
2567  }
2568  return;
2569  }
2570  // Ultrasafe Transporter: Toshley's Station
2571  case 36941:
2572  {
2573  if (roll_chance_i(50)) // 50% success
2574  {
2575  int32 rand_eff = urand(1, 7);
2576  switch (rand_eff)
2577  {
2578  case 1:
2579  // soul split - evil
2580  m_caster->CastSpell(m_caster, 36900, true);
2581  break;
2582  case 2:
2583  // soul split - good
2584  m_caster->CastSpell(m_caster, 36901, true);
2585  break;
2586  case 3:
2587  // Increase the size
2588  m_caster->CastSpell(m_caster, 36895, true);
2589  break;
2590  case 4:
2591  // Decrease the size
2592  m_caster->CastSpell(m_caster, 36893, true);
2593  break;
2594  case 5:
2595  // Transform
2596  {
2597  if (m_caster->ToPlayer() && m_caster->ToPlayer()->GetTeam() == ALLIANCE)
2598  m_caster->CastSpell(m_caster, 36897, true);
2599  else
2600  m_caster->CastSpell(m_caster, 36899, true);
2601  break;
2602  }
2603  case 6:
2604  // chicken
2605  m_caster->CastSpell(m_caster, 36940, true);
2606  break;
2607  case 7:
2608  // evil twin
2609  m_caster->CastSpell(m_caster, 23445, true);
2610  break;
2611  }
2612  }
2613  return;
2614  }
2615  // Dimensional Ripper - Area 52
2616  case 36890:
2617  {
2618  if (roll_chance_i(50)) // 50% success
2619  {
2620  int32 rand_eff = urand(1, 4);
2621  switch (rand_eff)
2622  {
2623  case 1:
2624  // soul split - evil
2625  m_caster->CastSpell(m_caster, 36900, true);
2626  break;
2627  case 2:
2628  // soul split - good
2629  m_caster->CastSpell(m_caster, 36901, true);
2630  break;
2631  case 3:
2632  // Increase the size
2633  m_caster->CastSpell(m_caster, 36895, true);
2634  break;
2635  case 4:
2636  // Transform
2637  {
2638  if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
2639  m_caster->CastSpell(m_caster, 36897, true);
2640  else
2641  m_caster->CastSpell(m_caster, 36899, true);
2642  break;
2643  }
2644  }
2645  }
2646  return;
2647  }
2648  }
2649 }
2650 
2652 {
2653  if (!unitTarget)
2654  return;
2655 
2656  // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2657  if (!unitTarget->IsAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2659  return;
2660 
2662  if (!caster)
2663  return;
2664 
2665  DEBUG_LOG("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[effIndex]);
2666 
2667  Aura* Aur = CreateAura(m_spellInfo, effIndex, &damage, unitTarget, caster, m_CastItem);
2668 
2669  // Now Reduce spell duration using data received at spell hit
2670  int32 duration = Aur->GetAuraMaxDuration();
2672  duration = m_spellValue->Duration;
2674  {
2677  }
2678 
2679  //mod duration of channeled aura by spell haste
2681  caster->ModSpellCastTime(m_spellInfo, duration, this);
2682 
2683  // if Aura removed and deleted, do not continue.
2684  if (Aur->IsExpired())
2685  {
2686  delete Aur;
2687  return;
2688  }
2689 
2690  if (duration != Aur->GetAuraMaxDuration())
2691  {
2692  Aur->SetAuraMaxDuration(duration);
2693  Aur->SetAuraDuration(duration);
2694  }
2695 
2696  bool added = unitTarget->AddAura(Aur);
2697 
2698  // Aura not added and deleted in AddAura call;
2699  if (!added)
2700  return;
2701 
2702  // found crash at character loading, broken pointer to Aur...
2703  // Aur was deleted in AddAura()...
2704  if (!Aur)
2705  return;
2706 
2707  // @todo Make a way so it works for every related spell!
2708  if (unitTarget->GetTypeId() == TYPEID_PLAYER || (unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsPet())) // Negative buff should only be applied on players
2709  {
2710  uint32 spellId = 0;
2712  spellId = 6788; // Weakened Soul
2714  spellId = 25771; // Forbearance
2716  spellId = 41425; // Hypothermia
2717  else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
2718  spellId = 11196; // Recently Bandaged
2719  else if ((m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000))
2720  spellId = 23230; // Blood Fury - Healing Reduction
2721 
2722  SpellEntry const* AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
2723  if (AdditionalSpellInfo)
2724  {
2725  // applied at target by target
2726  Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, NULL, unitTarget, unitTarget, 0);
2727  unitTarget->AddAura(AdditionalAura);
2728  DEBUG_LOG("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]);
2729  }
2730  }
2731 
2732  // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2733  if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2734  m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2735 }
2736 
2738 {
2740  return;
2741 
2742  Player* _player = unitTarget->ToPlayer();
2743  uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[effIndex];
2744 
2745  _player->RemoveSpell(spellToUnlearn);
2746 
2747  DEBUG_LOG("Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow());
2748 }
2749 
2751 {
2752  if (m_spellInfo->EffectMiscValue[effIndex] < 0 || m_spellInfo->EffectMiscValue[effIndex] >= MAX_POWERS)
2753  return;
2754 
2755  Powers drain_power = Powers(m_spellInfo->EffectMiscValue[effIndex]);
2756 
2757  if (!unitTarget)
2758  return;
2759  if (!unitTarget->IsAlive())
2760  return;
2761  if (unitTarget->getPowerType() != drain_power)
2762  return;
2763  if (damage < 0)
2764  return;
2765 
2766  uint32 curPower = unitTarget->GetPower(drain_power);
2767 
2768  //add spell damage bonus
2770 
2771  // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2772  uint32 power = damage;
2773  if (drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER)
2774  power -= unitTarget->ToPlayer()->GetSpellCritDamageReduction(power);
2775 
2776  int32 new_damage;
2777  if (curPower < power)
2778  new_damage = curPower;
2779  else
2780  new_damage = power;
2781 
2782  unitTarget->ModifyPower(drain_power, -new_damage);
2783 
2784  if (drain_power == POWER_MANA)
2785  {
2786  float manaMultiplier = m_spellInfo->EffectMultipleValue[effIndex];
2787 
2788  if (Player* modOwner = m_caster->GetSpellModOwner())
2789  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2790 
2791  int32 gain = int32(new_damage * manaMultiplier);
2792 
2794  }
2795 }
2796 
2798 {
2800  {
2802  if (bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2803  {
2804  switch (m_spellInfo->Id)
2805  {
2806  case 23333: // Pickup Horde Flag
2807  /*do not uncomment .
2808  if (bg->GetTypeID() == BATTLEGROUND_WS)
2809  bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2810  sLog.outDebug("Send Event Horde Flag Picked Up");
2811  break;
2812  not used :
2813  case 23334: // Drop Horde Flag
2814  if (bg->GetTypeID() == BATTLEGROUND_WS)
2815  bg->EventPlayerDroppedFlag((Player*)m_caster);
2816  sLog.outDebug("Drop Horde Flag");
2817  break;
2818  */
2819  case 23335: // Pickup Alliance Flag
2820  /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2821  if (bg->GetTypeID() == BATTLEGROUND_WS)
2822  bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2823  sLog.outDebug("Send Event Alliance Flag Picked Up");
2824  break;
2825  not used :
2826  case 23336: // Drop Alliance Flag
2827  if (bg->GetTypeID() == BATTLEGROUND_WS)
2828  bg->EventPlayerDroppedFlag((Player*)m_caster);
2829  sLog.outDebug("Drop Alliance Flag");
2830  break;
2831  case 23385: // Alliance Flag Returns
2832  if (bg->GetTypeID() == BATTLEGROUND_WS)
2833  bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2834  sLog.outDebug("Alliance Flag Returned");
2835  break;
2836  case 23386: // Horde Flag Returns
2837  if (bg->GetTypeID() == BATTLEGROUND_WS)
2838  bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2839  sLog.outDebug("Horde Flag Returned");
2840  break;*/
2841  case 34976:
2842  /*
2843  if (bg->GetTypeID() == BATTLEGROUND_EY)
2844  bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2845  */
2846  break;
2847  default:
2848  sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2849  break;
2850  }
2851  }
2852  }
2853  sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[effIndex], m_spellInfo->Id);
2854 
2855  Object* pTarget;
2856  if (focusObject)
2857  pTarget = focusObject;
2858  else if (unitTarget)
2859  pTarget = unitTarget;
2860  else if (gameObjTarget)
2861  pTarget = gameObjTarget;
2862  else
2863  pTarget = NULL;
2864 
2866 }
2867 
2869 {
2870  if (m_spellInfo->EffectMiscValue[effIndex] < 0 || m_spellInfo->EffectMiscValue[effIndex] >= MAX_POWERS)
2871  return;
2872 
2873  Powers powertype = Powers(m_spellInfo->EffectMiscValue[effIndex]);
2874 
2875  if (!unitTarget)
2876  return;
2877  if (!unitTarget->IsAlive())
2878  return;
2879  if (unitTarget->getPowerType() != powertype)
2880  return;
2881  if (damage < 0)
2882  return;
2883 
2884  int32 curPower = int32(unitTarget->GetPower(powertype));
2885 
2886  // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2887  uint32 power = damage;
2888  if (powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER)
2889  power -= unitTarget->ToPlayer()->GetSpellCritDamageReduction(power);
2890 
2891  int32 new_damage = (curPower < int32(power)) ? curPower : int32(power);
2892 
2893  unitTarget->ModifyPower(powertype, -new_damage);
2894  float multiplier = m_spellInfo->EffectMultipleValue[effIndex];
2895 
2896  if (Player* modOwner = m_caster->GetSpellModOwner())
2897  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2898 
2899  new_damage = int32(new_damage * multiplier);
2900  //m_damage+=new_damage; should not apply spell bonus
2901  //@todo no log
2902  //unitTarget->ModifyHealth(-new_damage);
2903  if (m_originalCaster)
2904  m_originalCaster->DealDamage(unitTarget, new_damage);
2905 }
2906 
2908 {
2909 }
2910 
2912 {
2913  if (unitTarget && unitTarget->IsAlive() && damage >= 0)
2914  {
2915  // Try to get original caster
2917 
2918  // Skip if m_originalCaster not available
2919  if (!caster)
2920  return;
2921 
2922  int32 addhealth = damage;
2923 
2924  // Vessel of the Naaru (Vial of the Sunwell trinket)
2925  if (m_spellInfo->Id == 45064)
2926  {
2927  // Amount of heal - depends from stacked Holy Energy
2928  int damageAmount = 0;
2929  Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2930  for (Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2931  if ((*i)->GetId() == 45062)
2932  damageAmount += (*i)->GetModifierValue();
2933  if (damageAmount)
2935 
2936  addhealth += damageAmount;
2937  }
2938  // Swiftmend - consumes Regrowth or Rejuvenation
2940  {
2942  // find most short by duration
2943  Aura* targetAura = NULL;
2944  for (Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2945  {
2946  if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2947  && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10))
2948  {
2949  if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2950  targetAura = *i;
2951  }
2952  }
2953 
2954  if (!targetAura)
2955  {
2956  sLog.outError("Target(GUID:" UI64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2957  return;
2958  }
2959 
2960  int32 tickheal = targetAura->GetModifierValuePerStack();
2961  if (Unit* auraCaster = targetAura->GetCaster())
2962  tickheal = auraCaster->SpellHealingBonus(targetAura->GetSpellProto(), tickheal, DOT, unitTarget);
2963  //int32 tickheal = targetAura->GetSpellProto()->EffectBasePoints[idx] + 1;
2964  //It is said that talent bonus should not be included
2965 
2966  int32 tickcount = 0;
2967  // Rejuvenation
2968  if (targetAura->GetSpellProto()->SpellFamilyFlags & 0x10)
2969  tickcount = 4;
2970  // Regrowth
2971  else // if (targetAura->GetSpellInfo()->SpellFamilyFlags[0] & 0x40)
2972  tickcount = 6;
2973 
2974  addhealth += tickheal * tickcount;
2975 
2976  unitTarget->RemoveAurasByCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID());
2977 
2978  //addhealth += tickheal * tickcount;
2979  //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
2980  }
2981  else
2982  addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth, HEAL, unitTarget);
2983 
2984  m_damage -= addhealth;
2985  }
2986 }
2987 
2989 {
2990  if (unitTarget && unitTarget->IsAlive() && damage >= 0)
2991  {
2992  // Try to get original caster
2994 
2995  // Skip if m_originalCaster not available
2996  if (!caster)
2997  return;
2998 
2999  uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
3000 
3001  caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
3002  int32 gain = unitTarget->ModifyHealth(int32(addhealth));
3004 
3005  if (caster->GetTypeId() == TYPEID_PLAYER)
3006  if (Battleground* bg = caster->ToPlayer()->GetBattleground())
3007  bg->UpdatePlayerScore(caster->ToPlayer(), SCORE_HEALING_DONE, gain);
3008  }
3009 }
3010 
3012 {
3013  // Mechanic creature type should be correctly checked by targetCreatureType field
3014  if (unitTarget && unitTarget->IsAlive() && damage >= 0)
3015  {
3016  // Try to get original caster
3018 
3019  // Skip if m_originalCaster not available
3020  if (!caster)
3021  return;
3022 
3023  uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
3024  caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
3026  }
3027 }
3028 
3030 {
3031  if (!unitTarget)
3032  return;
3033  if (!unitTarget->IsAlive())
3034  return;
3035 
3036  if (damage < 0)
3037  return;
3038 
3039  DEBUG_LOG("HealthLeech :%i", damage);
3040 
3041  float multiplier = m_spellInfo->EffectMultipleValue[effIndex];
3042 
3043  if (Player* modOwner = m_caster->GetSpellModOwner())
3044  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
3045 
3046  int32 new_damage = int32(damage * multiplier);
3047  uint32 curHealth = unitTarget->GetHealth();
3048  new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
3049  if (int64(curHealth) < new_damage)
3050  new_damage = curHealth;
3051 
3052  if (m_caster->IsAlive())
3053  {
3054  new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
3055 
3056  m_caster->ModifyHealth(new_damage);
3057 
3058  if (m_caster->GetTypeId() == TYPEID_PLAYER)
3060  }
3061  // m_healthLeech+=tmpvalue;
3062  // m_damage+=new_damage;
3063 }
3064 
3065 void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
3066 {
3068  return;
3069 
3070  Player* player = unitTarget->ToPlayer();
3071 
3072  uint32 newitemid = itemtype;
3073  ItemTemplate const* pProto = sObjectMgr.GetItemTemplate(newitemid);
3074  if (!pProto)
3075  {
3076  player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
3077  return;
3078  }
3079 
3080  uint32 num_to_add;
3081 
3082  // @todo maybe all this can be replaced by using correct calculated `damage` value
3084  {
3085  num_to_add = damage;
3086  /*int32 basePoints = m_currentBasePoints[i];
3087  int32 randomPoints = m_spellInfo->EffectDieSides[i];
3088  if (randomPoints)
3089  num_to_add = basePoints + irand(1, randomPoints);
3090  else
3091  num_to_add = basePoints + 1;*/
3092  }
3093  else if (pProto->MaxCount == 1)
3094  num_to_add = 1;
3095  else if (player->getLevel() >= m_spellInfo->spellLevel)
3096  {
3097  num_to_add = damage;
3098  /*int32 basePoints = m_currentBasePoints[i];
3099  float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
3100  num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);*/
3101  }
3102  else
3103  num_to_add = 2;
3104 
3105  if (num_to_add < 1)
3106  num_to_add = 1;
3107  if (num_to_add > pProto->Stackable)
3108  num_to_add = pProto->Stackable;
3109 
3110  // init items_count to 1, since 1 item will be created regardless of specialization
3111  int items_count = 1;
3112  // the chance to create additional items
3113  float additionalCreateChance = 0.0f;
3114  // the maximum number of created additional items
3115  uint8 additionalMaxNum = 0;
3116  // get the chance and maximum number for creating extra items
3117  if (canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum))
3118  {
3119  // roll with this chance till we roll not to create or we create the max num
3120  while (roll_chance_f(additionalCreateChance) && items_count <= additionalMaxNum)
3121  ++items_count;
3122  }
3123 
3124  // really will be created more items
3125  num_to_add *= items_count;
3126 
3127  // can the player store the new item?
3128  ItemPosCountVec dest;
3129  uint32 no_space = 0;
3130  uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space);
3131  if (msg != EQUIP_ERR_OK)
3132  {
3133  // convert to possible store amount
3135  num_to_add -= no_space;
3136  else
3137  {
3138  // if not created by another reason from full inventory or unique items amount limitation
3139  player->SendEquipError(msg, NULL, NULL);
3140  return;
3141  }
3142  }
3143 
3144  if (num_to_add)
3145  {
3146  // create the new item and store it
3147  Item* pItem = player->StoreNewItem(dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
3148 
3149  // was it successful? return error if not
3150  if (!pItem)
3151  {
3152  player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
3153  return;
3154  }
3155 
3156  // set the "Crafted by ..." property of the item
3158  pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
3159 
3160  // send info to the client
3161  if (pItem)
3162  player->SendNewItem(pItem, num_to_add, true, true);
3163 
3164  // we succeeded in creating at least one item, so a levelup is possible
3165  player->UpdateCraftSkill(m_spellInfo->Id);
3166  }
3167 }
3168 
3170 {
3171  DoCreateItem(effIndex, m_spellInfo->EffectItemType[effIndex]);
3172 }
3173 
3175 {
3177  float radius = GetSpellRadius(m_spellInfo, effIndex, false);
3178  int32 duration = GetSpellDuration(m_spellInfo);
3179 
3180  // Caster not in world, might be spell triggered from aura removal
3181  if (!caster->IsInWorld())
3182  return;
3183 
3184  // Apply spell mods to radius
3185  if (Player* modOwner = m_originalCaster->GetSpellModOwner())
3186  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
3187 
3188  // Apply spell mods to duration
3189  if (Player* modOwner = m_originalCaster->GetSpellModOwner())
3190  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3191 
3192  DynamicObject* dynObj = new DynamicObject(false);
3193  if (!dynObj->CreateDynamicObject(sObjectMgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, effIndex, m_targets.m_dstPos, duration, radius))
3194  {
3195  delete dynObj;
3196  return;
3197  }
3198 
3199  dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3200  caster->AddDynObject(dynObj);
3201  dynObj->GetMap()->AddToMap(dynObj);
3202 }
3203 
3205 {
3206  if (!unitTarget)
3207  return;
3208  if (!unitTarget->IsAlive())
3209  return;
3210 
3211  if (m_spellInfo->EffectMiscValue[effIndex] < 0 || m_spellInfo->EffectMiscValue[effIndex] >= MAX_POWERS)
3212  return;
3213 
3214  // Some level depends spells
3215  int multiplier = 0;
3216  int level_diff = 0;
3217  switch (m_spellInfo->Id)
3218  {
3219  case 9512: // Restore Energy
3220  level_diff = m_caster->getLevel() - 40;
3221  multiplier = 2;
3222  break;
3223  case 24571: // Blood Fury
3224  level_diff = m_caster->getLevel() - 60;
3225  multiplier = 10;
3226  break;
3227  case 24532: // Burst of Energy
3228  level_diff = m_caster->getLevel() - 60;
3229  multiplier = 4;
3230  break;
3231  default:
3232  break;
3233  }
3234 
3235  if (level_diff > 0)
3236  damage -= multiplier * level_diff;
3237 
3238  if (damage < 0)
3239  return;
3240 
3241  // Handle Mana Gems / Serpent-Coil Braid
3243  if (unitTarget->HasAura(37447, 0))
3244  unitTarget->CastSpell(unitTarget, 37445, true);
3245 
3246  Powers power = Powers(m_spellInfo->EffectMiscValue[effIndex]);
3247 
3248  if (unitTarget->GetMaxPower(power) == 0)
3249  return;
3250 
3251  unitTarget->ModifyPower(power, damage);
3253 
3254  // Mad Alchemist's Potion
3255  if (m_spellInfo->Id == 45051)
3256  {
3257  // find elixirs on target
3258  bool guardianFound = false;
3259  bool battleFound = false;
3260  Unit::AuraMap& Auras = unitTarget->GetAuras();
3261  for (Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
3262  {
3263  uint32 spell_id = itr->second->GetId();
3264  if (!guardianFound)
3265  if (sSpellMgr.IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_GUARDIAN))
3266  guardianFound = true;
3267  if (!battleFound)
3268  if (sSpellMgr.IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_BATTLE))
3269  battleFound = true;
3270  if (battleFound && guardianFound)
3271  break;
3272  }
3273 
3274  // get all available elixirs by mask and spell level
3275  std::set<uint32> avalibleElixirs;
3276  if (!guardianFound)
3277  sSpellMgr.GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_GUARDIAN, avalibleElixirs);
3278  if (!battleFound)
3279  sSpellMgr.GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, avalibleElixirs);
3280  for (std::set<uint32>::iterator itr = avalibleElixirs.begin(); itr != avalibleElixirs.end() ;)
3281  {
3282  SpellEntry const* spellInfo = sSpellStore.LookupEntry(*itr);
3283  if (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel())
3284  avalibleElixirs.erase(itr++);
3285  else if (sSpellMgr.IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_SHATTRATH))
3286  avalibleElixirs.erase(itr++);
3287  else if (sSpellMgr.IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_UNSTABLE))
3288  avalibleElixirs.erase(itr++);
3289  else
3290  ++itr;
3291  }
3292 
3293  if (!avalibleElixirs.empty())
3294  {
3295  // cast random elixir on target
3296  uint32 rand_spell = urand(0, avalibleElixirs.size() - 1);
3297  std::set<uint32>::iterator itr = avalibleElixirs.begin();
3298  std::advance(itr, rand_spell);
3299  m_caster->CastSpell(unitTarget, *itr, true, m_CastItem);
3300  }
3301  }
3302 }
3303 
3305 {
3306  if (!unitTarget)
3307  return;
3308  if (!unitTarget->IsAlive())
3309  return;
3310 
3311  if (m_spellInfo->EffectMiscValue[effIndex] < 0 || m_spellInfo->EffectMiscValue[effIndex] >= MAX_POWERS)
3312  return;
3313 
3314  Powers power = Powers(m_spellInfo->EffectMiscValue[effIndex]);
3315 
3316  uint32 maxPower = unitTarget->GetMaxPower(power);
3317  if (maxPower == 0)
3318  return;
3319 
3320  uint32 gain = damage * maxPower / 100;
3321  unitTarget->ModifyPower(power, gain);
3323 }
3324 
3325 void Spell::SendLoot(uint64 guid, LootType loottype)
3326 {
3327  Player* player = m_caster->ToPlayer();
3328  if (!player)
3329  return;
3330 
3331  if (gameObjTarget)
3332  {
3333  if (sScriptMgr.GOHello(player, gameObjTarget))
3334  return;
3335 
3336  if (gameObjTarget->AI()->GossipHello(player))
3337  return;
3338 
3339  switch (gameObjTarget->GetGoType())
3340  {
3341  case GAMEOBJECT_TYPE_DOOR:
3343  gameObjTarget->UseDoorOrButton(0, false, player);
3345  return;
3346 
3348  // start or end quest
3349  player->PrepareQuestMenu(guid);
3350  player->SendPreparedQuest(guid);
3351  return;
3352 
3354  // triggering linked GO
3355  if (uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
3357  return;
3358 
3360  // goober_scripts can be triggered if the player don't have the quest
3361  if (gameObjTarget->GetGOInfo()->goober.eventId)
3362  {
3363  DEBUG_LOG("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId, gameObjTarget->GetDBTableGUIDLow());
3364  player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
3365  }
3366 
3367  // cast goober spell
3368  if (gameObjTarget->GetGOInfo()->goober.questId)
3369  // Quest require to be active for GO using
3371  return;
3372 
3374 
3375  gameObjTarget->AddUniqueUse(player);
3377 
3378  //TODO? Objective counting called without spell check but with quest objective check
3379  // if send spell id then this line will duplicate to spell casting call (double counting)
3380  // So we or have this line and not required in quest_template have reqSpellIdN
3381  // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
3383 
3384  // triggering linked GO
3385  if (uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
3387 
3388  return;
3389 
3390  case GAMEOBJECT_TYPE_CHEST:
3391  // @todo possible must be moved to loot release (in different from linked triggering)
3392  if (gameObjTarget->GetGOInfo()->chest.eventId)
3393  {
3394  DEBUG_LOG("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId, gameObjTarget->GetDBTableGUIDLow());
3395  player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
3396  }
3397 
3398  // triggering linked GO
3399  if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
3401 
3402  // Don't return, let loots been taken
3403  default:
3404  break;
3405  }
3406  }
3407 
3408  // Send loot
3409  player->SendLoot(guid, loottype);
3410 }
3411 
3413 {
3414  if (!m_caster)
3415  return;
3416 
3418  {
3420  return;
3421  }
3422 
3423  Player* player = m_caster->ToPlayer();
3424  if (!player)
3425  return;
3426 
3427  LootType loottype = LOOT_CORPSE;
3428  uint32 lockId = 0;
3429  uint64 guid = 0;
3430 
3431  // Get lockId
3432  if (gameObjTarget)
3433  {
3434  GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3435  // Arathi Basin banner opening !
3436  if ((goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune) ||
3437  (goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK) ||
3438  (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND))
3439  {
3440  // CanUseBattlegroundObject() already called in CanCast()
3441  // in battleground check
3442  if (Battleground* bg = player->GetBattleground())
3443  bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3444  return;
3445  }
3446  // handle outdoor pvp object opening, return true if go was registered for handling
3447  // these objects must have been spawned by outdoorpvp!
3448  else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr.HandleOpenGo(player, gameObjTarget->GetGUID()))
3449  return;
3450 
3451  lockId = gameObjTarget->GetGOInfo()->GetLockId();
3452  guid = gameObjTarget->GetGUID();
3453  }
3454  else if (itemTarget)
3455  {
3456  lockId = itemTarget->GetProto()->LockID;
3457  guid = itemTarget->GetGUID();
3458  }
3459  else
3460  {
3461  sLog.outError("WORLD: Open Lock - No GameObject/Item Target! SpellId; %u", m_spellInfo->Id);
3462  return;
3463  }
3464 
3465  if (!lockId) // possible case for GO and maybe for items.
3466  {
3467  SendLoot(guid, loottype);
3468  return;
3469  }
3470 
3471  // Get LockInfo
3472  LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);
3473 
3474  if (!lockInfo)
3475  {
3476  sLog.outError("Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
3477  (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
3478  return;
3479  }
3480 
3481  // check key
3482  for (int i = 0; i < 5; ++i)
3483  {
3484  // type == 1 This means lockInfo->key[i] is an item
3485  if (lockInfo->keytype[i] == LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry() == lockInfo->key[i])
3486  {
3487  SendLoot(guid, loottype);
3488  return;
3489  }
3490  }
3491 
3492  uint32 SkillId = 0;
3493  // Check and skill-up skill
3495  SkillId = m_spellInfo->EffectMiscValue[EFFECT_1];
3496  // pickpocketing spells
3498  SkillId = SKILL_LOCKPICKING;
3499 
3500  uint32 reqSkillValue = lockInfo->requiredminingskill;
3501  if (m_spellInfo->EffectMiscValue[effIndex] == LOCKTYPE_PICKLOCK)
3502  reqSkillValue = lockInfo->requiredlockskill;
3503 
3504  if (SkillId)
3505  {
3506  loottype = LOOT_SKINNING;
3507 
3508  // update skill if really known
3509  uint32 SkillValue = player->GetPureSkillValue(SkillId);
3510  if (SkillValue) // non only item base skill
3511  {
3512  if (gameObjTarget)
3513  {
3514  // Allow one skill-up until respawned
3515  if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) && player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue))
3517  }
3518  else if (itemTarget)
3519  {
3520  // Do one skill-up
3521  uint32 SkillValue = player->GetPureSkillValue(SkillId);
3522  player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
3523  }
3524  }
3525  }
3526 
3527  SendLoot(guid, loottype);
3528 }
3529 
3531 {
3532  if (m_caster->GetTypeId() != TYPEID_PLAYER)
3533  return;
3534 
3535  Player* player = m_caster->ToPlayer();
3536 
3537  // applied only to using item
3538  if (!m_CastItem)
3539  return;
3540 
3541  // ... only to item in own inventory/bank/equip_slot
3542  if (m_CastItem->GetOwnerGUID() != player->GetGUID())
3543  return;
3544 
3545  uint32 newitemid = m_spellInfo->EffectItemType[effIndex];
3546  if (!newitemid)
3547  return;
3548 
3549  uint16 pos = m_CastItem->GetPos();
3550 
3551  Item* pNewItem = Item::CreateItem(newitemid, 1, player);
3552  if (!pNewItem)
3553  return;
3554 
3556  {
3559  }
3560 
3562  {
3564  player->DurabilityLoss(pNewItem, loosePercent);
3565  }
3566 
3567  if (player->IsInventoryPos(pos))
3568  {
3569  ItemPosCountVec dest;
3570  uint8 msg = player->CanStoreItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true);
3571  if (msg == EQUIP_ERR_OK)
3572  {
3573  player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3574 
3575  // prevent crash at access and unexpected charges counting with item update queue corrupt
3577  m_targets.setItemTarget(NULL);
3578 
3579  m_CastItem = NULL;
3580 
3581  player->StoreItem(dest, pNewItem, true);
3582  player->SendNewItem(pNewItem, 1, true, false);
3583  player->ItemAddedQuestCheck(newitemid, 1);
3584  return;
3585  }
3586  }
3587  else if (player->IsBankPos (pos))
3588  {
3589  ItemPosCountVec dest;
3590  uint8 msg = player->CanBankItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true);
3591  if (msg == EQUIP_ERR_OK)
3592  {
3593  player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3594 
3595  // prevent crash at access and unexpected charges counting with item update queue corrupt
3597  m_targets.setItemTarget(NULL);
3598 
3599  m_CastItem = NULL;
3600 
3601  player->BankItem(dest, pNewItem, true);
3602  return;
3603  }
3604  }
3605  else if (player->IsEquipmentPos (pos))
3606  {
3607  uint16 dest;
3608  uint8 msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true);
3609  if (msg == EQUIP_ERR_OK)
3610  {
3611  player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3612 
3613  // prevent crash at access and unexpected charges counting with item update queue corrupt
3615  m_targets.setItemTarget(NULL);
3616 
3617  m_CastItem = NULL;
3618 
3619  player->EquipItem(dest, pNewItem, true);
3620  player->AutoUnequipOffhandIfNeed();
3621  player->SendNewItem(pNewItem, 1, true, false);
3622  player->ItemAddedQuestCheck(newitemid, 1);
3623  return;
3624  }
3625  }
3626 
3627  // fail
3628  delete pNewItem;
3629 }
3630 
3632 {
3633  EffectOpenLock(effIndex); //no difference for now
3634 }
3635 
3637 {
3639  return;
3640  Player* p_target = unitTarget->ToPlayer();
3641 
3643  if (m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3644  {
3645  p_target->AddWeaponProficiency(subClassMask);
3646  p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3647  }
3648  if (m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3649  {
3650  p_target->AddArmorProficiency(subClassMask);
3651  p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3652  }
3653 }
3654 
3656 {
3657  uint32 entry = m_spellInfo->EffectMiscValue[effIndex];
3658  if (!entry)
3659  return;
3660 
3661  uint32 prop_id = m_spellInfo->EffectMiscValueB[effIndex];
3662  SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(prop_id);
3663  if (!properties)
3664  {
3665  sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
3666  return;
3667  }
3668 
3669  if (!m_originalCaster)
3670  return;
3671 
3672  int32 duration = GetSpellDuration(m_spellInfo);
3673  if (Player* modOwner = m_originalCaster->GetSpellModOwner())
3674  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3675 
3676  Position pos;
3677  GetSummonPosition(effIndex, pos);
3678 
3679  TempSummon* summon = NULL;
3680 
3681  switch (properties->Category)
3682  {
3683  case SUMMON_CATEGORY_WILD:
3684  case SUMMON_CATEGORY_ALLY:
3685  if (properties->Flags & 512)
3686  {
3687  SummonGuardian(effIndex, entry, properties);
3688  break;
3689  }
3690  switch (properties->Type)
3691  {
3692  case SUMMON_TYPE_PET:
3693  case SUMMON_TYPE_GUARDIAN:
3694  case SUMMON_TYPE_GUARDIAN2:
3695  case SUMMON_TYPE_MINION:
3696  SummonGuardian(effIndex, entry, properties);
3697  break;
3698  case SUMMON_TYPE_TOTEM:
3699  {
3700  summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id);
3701  if (!summon || !summon->IsTotem())
3702  return;
3703 
3704  if (damage) // if not spell info, DB values used
3705  {
3706  summon->SetMaxHealth(damage);
3707  summon->SetHealth(damage);
3708  }
3709  break;
3710  }
3711  case SUMMON_TYPE_MINIPET:
3712  {
3713  // If "resummoning" the same minipet, despawn only.
3715 
3716  if (oldCritter)
3717  {
3718  oldCritter->UnSummon();
3719 
3720  if (oldCritter->GetEntry() == entry)
3721  return;
3722  }
3723 
3724  summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster);
3725  if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
3726  return;
3727 
3728  m_caster->SetCritterGUID(summon->GetGUID());
3729 
3730  summon->SelectLevel(); // some summoned creaters have different from 1 DB data for level/hp
3732 
3734 
3735  summon->AI()->EnterEvadeMode();
3736  break;
3737  }
3738  default:
3739  {
3740  TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
3741  summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration);
3742  if (!summon)
3743  return;
3744 
3745  if (properties->Category == SUMMON_CATEGORY_ALLY)
3746  {
3749  summon->SetLevel(m_originalCaster->getLevel());
3751  }
3752 
3753  switch (m_spellInfo->Id)
3754  {
3755  case 45392:
3756  if (summon->IsAIEnabled)
3757  summon->AI()->AttackStart(m_caster);
3758  break;
3759  default:
3760  if (summon->IsAIEnabled && m_originalCaster->IsInCombat())
3761  summon->AI()->EnterCombat(nullptr);
3762  break;
3763  }
3764  }
3765  return;
3766  }
3767  break;
3768  case SUMMON_CATEGORY_PET:
3769  SummonClassPet(effIndex);
3770  break;
3772  // only player may have a puppet, or else
3773  // there will be a failed assertion in Puppet::Puppet
3774  if (m_caster->GetTypeId() != TYPEID_PLAYER)
3775  break;
3776 
3777  summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster);
3778 
3779  uint32 faction = properties->Faction;
3780  if (!faction)
3781  faction = m_originalCaster->getFaction();
3782 
3783  summon->setFaction(faction);
3784 
3785  if (prop_id == 65) // Eye of Kilrogg
3786  summon->CastSpell(summon, 2585, true);
3787  break;
3788  }
3789 
3790  if (summon)
3791  {
3794  }
3795 }
3796 
3798 {
3799  if (!unitTarget)
3800  return;
3801 
3803  {
3804  if (m_caster->GetTypeId() == TYPEID_PLAYER)
3805  EffectLearnPetSpell(effIndex);
3806 
3807  return;
3808  }
3809 
3810  Player* player = unitTarget->ToPlayer();
3811 
3812  uint32 spellToLearn = (m_spellInfo->Id == SPELL_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[effIndex];
3813  player->LearnSpell(spellToLearn);
3814 
3815  DEBUG_LOG("Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow());
3816 }
3817 
3819 {
3820  if (!unitTarget)
3821  return;
3822 
3823  // Fill possible dispell list
3824  std::vector <Aura*> dispel_list;
3825 
3827  {
3830  }
3831 
3832  // Create dispel mask by dispel type
3833  uint32 dispel_type = m_spellInfo->EffectMiscValue[effIndex];
3834  uint32 dispelMask = GetDispelMask(DispelType(dispel_type));
3835  Unit::AuraMap const& auras = unitTarget->GetAuras();
3836  for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3837  {
3838  Aura* aur = (*itr).second;
3839  if (aur && (1 << aur->GetSpellProto()->Dispel) & dispelMask)
3840  {
3841  if (aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3842  {
3843  // do not remove positive auras if friendly target
3844  // negative auras if non-friendly target
3845  if (aur->IsPositive() == unitTarget->IsFriendlyTo(m_caster))
3846  continue;
3847  }
3848  // Add every aura stack to dispel list
3849  for (int stack_amount = 0; stack_amount < aur->GetStackAmount(); ++stack_amount)
3850  dispel_list.push_back(aur);
3851  }
3852  }
3853  // Ok if exist some buffs for dispel try dispel it
3854  if (!dispel_list.empty())
3855  {
3856  std::list < std::pair<uint32, uint64> > success_list; // (spell_id,casterGuid)
3857  std::list < uint32 > fail_list; // spell_id
3858 
3859  int32 list_size = dispel_list.size();
3860  // dispel N = damage buffs (or while exist buffs for dispel)
3861  for (int32 count = 0; count < damage && list_size > 0; ++count)
3862  {
3863  // Random select buff for dispel
3864  Aura* aur = dispel_list[urand(0, list_size - 1)];
3865 
3866  SpellEntry const* spellInfo = aur->GetSpellProto();
3867  // Base dispel chance
3868  // @todo possible chance depend from spell level??
3869  int32 miss_chance = 0;
3870  // Apply dispel mod from aura caster
3871  if (Unit* caster = aur->GetCaster())
3872  {
3873  if (Player* modOwner = caster->GetSpellModOwner())
3874  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3875  }
3876  // Try dispel
3877  if (roll_chance_i(miss_chance))
3878  fail_list.push_back(aur->GetId());
3879  else
3880  success_list.push_back(std::pair<uint32, uint64>(aur->GetId(), aur->GetCasterGUID()));
3881  // Remove buff from list for prevent doubles
3882  for (std::vector<Aura*>::iterator j = dispel_list.begin(); j != dispel_list.end();)
3883  {
3884  Aura* dispelled = *j;
3885  if (dispelled->GetId() == aur->GetId() && dispelled->GetCasterGUID() == aur->GetCasterGUID())
3886  {
3887  j = dispel_list.erase(j);
3888  --list_size;
3889  break;
3890  }
3891  else
3892  ++j;
3893  }
3894  }
3895  // Send success log and really remove auras
3896  if (!success_list.empty())
3897  {
3898  int32 count = success_list.size();
3899  WorldPacket data(SMSG_SPELLDISPELLOG, 8 + 8 + 4 + 1 + 4 + count * 5);
3900  data << unitTarget->GetPackGUID(); // Victim GUID
3901  data << m_caster->GetPackGUID(); // Caster GUID
3902  data << uint32(m_spellInfo->Id); // dispel spell id
3903  data << uint8(0); // not used
3904  data << uint32(count); // count
3905  for (std::list<std::pair<uint32, uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3906  {
3907  SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3908  data << uint32(spellInfo->Id); // Spell Id
3909  data << uint8(0); // 0 - dispelled != 0 cleansed
3910  if (spellInfo->StackAmount != 0)
3911  {
3912  //Why are Aura's Removed by EffIndex? Auras should be removed as a whole.....
3914  }
3915  else
3916  unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3917  }
3918  m_caster->SendMessageToSet(&data, true);
3919 
3920  // On succes dispel
3921  // Devour Magic
3923  {
3924  uint32 heal_spell = 0;
3925  switch (m_spellInfo->Id)
3926  {
3927  case 19505:
3928  heal_spell = 19658;
3929  break;
3930  case 19731:
3931  heal_spell = 19732;
3932  break;
3933  case 19734:
3934  heal_spell = 19733;
3935  break;
3936  case 19736:
3937  heal_spell = 19735;
3938  break;
3939  case 27276:
3940  heal_spell = 27278;
3941  break;
3942  case 27277:
3943  heal_spell = 27279;
3944  break;
3945  default:
3946  sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3947  break;
3948  }
3949  if (heal_spell)
3950  m_caster->CastSpell(m_caster, heal_spell, true);
3951  }
3952  }
3953  // Send fail log to client
3954  if (!fail_list.empty())
3955  {
3956  // Failed to dispell
3957  WorldPacket data(SMSG_DISPEL_FAILED, 8 + 8 + 4 + 4 * fail_list.size());
3958  data << uint64(m_caster->GetGUID()); // Caster GUID
3959  data << uint64(unitTarget->GetGUID()); // Victim GUID
3960  data << uint32(m_spellInfo->Id); // dispel spell id
3961  for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3962  data << uint32(*j); // Spell Id
3963  m_caster->SendMessageToSet(&data, true);
3964  }
3965  }
3966 }
3967 
3969 {
3970  unitTarget->SetCanDualWield(true);
3971  if (unitTarget->GetTypeId() == TYPEID_UNIT)
3973 }
3974 
3976 {
3977  // @todo create a proper pull towards distract spell center for distract
3978  DEBUG_LOG("WORLD: Spell Effect DUMMY");
3979 }
3980 
3982 {
3983  // Check for possible target
3984  if (!unitTarget || unitTarget->IsInCombat())
3985  return;
3986 
3987  // target must be OK to do this
3989  return;
3990 
3991  float angle = unitTarget->GetAngle(&m_targets.m_dstPos);
3992  unitTarget->SetFacingTo(angle);
3993 
3995 
3996  if (unitTarget->GetTypeId() == TYPEID_UNIT)
3998 }
3999 
4001 {
4002  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4003  return;
4004 
4005  // victim must be creature and attackable
4007  return;
4008 
4009  // victim have to be alive and humanoid or undead
4012 }
4013 
4015 {
4016  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4017  return;
4018 
4019  float radius = GetSpellRadius(m_spellInfo, effIndex, false);
4020  int32 duration = GetSpellDuration(m_spellInfo);
4021  // Caster not in world, might be spell triggered from aura removal
4022  if (!m_caster->IsInWorld())
4023  return;
4024 
4025  DynamicObject* dynObj = new DynamicObject(true);
4026  if (!dynObj->CreateDynamicObject(sObjectMgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, 4, m_targets.m_dstPos, duration, radius))
4027  {
4028  delete dynObj;
4029  return;
4030  }
4031  dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
4032  dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
4033  m_caster->AddDynObject(dynObj);
4034 
4035  dynObj->setActive(true); //must before add to map to be put in world container
4036  dynObj->GetMap()->AddToMap(dynObj); //grid will also be loaded
4037 
4038  // Need to update visibility of object for client to accept farsight guid
4039  ((Player*)m_caster)->SetViewpoint(dynObj, true);
4040  //((Player*)m_caster)->UpdateVisibilityOf(dynObj);
4041 }
4042 
4044 {
4045  if (!unitTarget)
4046  return;
4047 
4048  if (unitTarget->isInFlight())
4049  return;
4050 
4051  float dis = GetSpellRadius(m_spellInfo, effIndex, false);
4052 
4053  float fx, fy, fz;
4054  m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
4055 
4057 }
4058 
4060 {
4062  return;
4063 
4064  if (damage < 0)
4065  return;
4066 
4067  uint32 skillid = m_spellInfo->EffectMiscValue[effIndex];
4068  uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid);
4069  unitTarget->ToPlayer()->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
4070 }
4071 
4073 {
4075  return;
4076 
4077  // 2.4.3 honor-spells don't scale with level and won't be casted by an item
4078  // also we must use damage+1 (spelldescription says +25 honor but damage is only 24)
4079  unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage + 1);
4080  DEBUG_LOG("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUIDLow());
4081 }
4082 
4084 {
4086  return;
4087  // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4088  // uint16 skillmax = unitTarget->ToPlayer()->(skillid);
4089  // unitTarget->ToPlayer()->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4090 }
4091 
4093 {
4094  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4095  return;
4096  if (!itemTarget)
4097  return;
4098 
4099  Player* p_caster = m_caster->ToPlayer();
4100 
4101  p_caster->UpdateCraftSkill(m_spellInfo->Id);
4102 
4103  uint32 enchant_id = m_spellInfo->EffectMiscValue[effIndex];
4104  if (!enchant_id)
4105  return;
4106 
4107  SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4108  if (!pEnchant)
4109  return;
4110 
4111  // item can be in trade slot and have owner diff. from caster
4112  Player* item_owner = itemTarget->GetOwner();
4113  if (!item_owner)
4114  return;
4115 
4116  if (item_owner != p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
4117  {
4118  sLog.outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4119  p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4121  item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4122  }
4123 
4124  // remove old enchanting before applying new if equipped
4125  item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, false);
4126 
4127  itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4128 
4129  // add new enchanting if equipped
4131 
4132  // update trade window for show enchantment for caster in trade window
4134  p_caster->GetSession()->SendUpdateTrade();
4135 }
4136 
4138 {
4139  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4140  return;
4141 
4142  Player* p_caster = m_caster->ToPlayer();
4143 
4144  if (!itemTarget)
4145  return;
4146 
4147  uint32 enchant_id = m_spellInfo->EffectMiscValue[effIndex];
4148 
4149  // Shaman Rockbiter Weapon
4150  if (effIndex == 0 && m_spellInfo->Effect[1] == SPELL_EFFECT_DUMMY)
4151  {
4152  int32 enchnting_damage = CalculateDamage(1, NULL);//+1;
4153 
4154  // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
4155  // with already applied percent bonus from Elemental Weapons talent
4156  // Note: damage calculated (correctly) with rounding int32(float(v)) but
4157  // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4158  switch (enchnting_damage)
4159  {
4160  // Rank 1
4161  case 2:
4162  enchant_id = 29;
4163  break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4164  // Rank 2
4165  case 4:
4166  enchant_id = 6;
4167  break; // 0% [ 7% == 4, 14% == 4]
4168  case 5:
4169  enchant_id = 3025;
4170  break; // 20%
4171  // Rank 3
4172  case 6:
4173  enchant_id = 1;
4174  break; // 0% [ 7% == 6, 14% == 6]
4175  case 7:
4176  enchant_id = 3027;
4177  break; // 20%
4178  // Rank 4
4179  case 9:
4180  enchant_id = 3032;
4181  break; // 0% [ 7% == 6]
4182  case 10:
4183  enchant_id = 503;
4184  break; // 14%
4185  case 11:
4186  enchant_id = 3031;
4187  break; // 20%
4188  // Rank 5
4189  case 15:
4190  enchant_id = 3035;
4191  break; // 0%
4192  case 16:
4193  enchant_id = 1663;
4194  break; // 7%
4195  case 17:
4196  enchant_id = 3033;
4197  break; // 14%
4198  case 18:
4199  enchant_id = 3034;
4200  break; // 20%
4201  // Rank 6
4202  case 28:
4203  enchant_id = 3038;
4204  break; // 0%
4205  case 29:
4206  enchant_id = 683;
4207  break; // 7%
4208  case 31:
4209  enchant_id = 3036;
4210  break; // 14%
4211  case 33:
4212  enchant_id = 3037;
4213  break; // 20%
4214  // Rank 7
4215  case 40:
4216  enchant_id = 3041;
4217  break; // 0%
4218  case 42:
4219  enchant_id = 1664;
4220  break; // 7%
4221  case 45:
4222  enchant_id = 3039;
4223  break; // 14%
4224  case 48:
4225  enchant_id = 3040;
4226  break; // 20%
4227  // Rank 8
4228  case 49:
4229  enchant_id = 3044;
4230  break; // 0%
4231  case 52:
4232  enchant_id = 2632;
4233  break; // 7%
4234  case 55:
4235  enchant_id = 3042;
4236  break; // 14%
4237  case 58:
4238  enchant_id = 3043;
4239  break; // 20%
4240  // Rank 9
4241  case 62:
4242  enchant_id = 2633;
4243  break; // 0%
4244  case 66:
4245  enchant_id = 3018;
4246  break; // 7%
4247  case 70:
4248  enchant_id = 3019;
4249  break; // 14%
4250  case 74:
4251  enchant_id = 3020;
4252  break; // 20%
4253  default:
4254  sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW", enchnting_damage);
4255  return;
4256  }
4257  }
4258 
4259  if (!enchant_id)
4260  {
4261  sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) has 0 as enchanting id", m_spellInfo->Id, effIndex);
4262  return;
4263  }
4264 
4265  SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4266  if (!pEnchant)
4267  {
4268  sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) has invalid enchanting id %u ", m_spellInfo->Id, effIndex, enchant_id);
4269  return;
4270  }
4271 
4272  // select enchantment duration
4273  uint32 duration;
4274 
4275  // rogue family enchantments exception by duration
4276  if (m_spellInfo->Id == 38615)
4277  duration = 1800; // 30 mins
4278  // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4280  duration = 3600; // 1 hour
4281  // shaman family enchantments
4283  duration = 1800; // 30 mins
4284  // other cases with this SpellVisual already selected
4285  else if (m_spellInfo->SpellVisual == 215)
4286  duration = 1800; // 30 mins
4287  // some fishing pole bonuses
4288  else if (m_spellInfo->SpellVisual == 563)
4289  duration = 600; // 10 mins
4290  // shaman rockbiter enchantments
4291  else if (m_spellInfo->SpellVisual == 0)
4292  duration = 1800; // 30 mins
4293  else if (m_spellInfo->Id == 29702)
4294  duration = 300; // 5 mins
4295  else if (m_spellInfo->Id == 37360)
4296  duration = 300; // 5 mins
4297  // default case
4298  else
4299  duration = 3600; // 1 hour
4300 
4301  // item can be in trade slot and have owner diff. from caster
4302  Player* item_owner = itemTarget->GetOwner();
4303  if (!item_owner)
4304  return;
4305 
4306  if (item_owner != p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
4307  {
4308  sLog.outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4309  p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4311  item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4312  }
4313 
4314  // remove old enchanting before applying new if equipped
4315  item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, false);
4316 
4317  itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * IN_MILLISECONDS, 0);
4318 
4319  // add new enchanting if equipped
4321 
4322  // update trade window for show enchantment for caster in trade window
4324  p_caster->GetSession()->SendUpdateTrade();
4325 }
4326 
4328 {
4329  if (m_caster->GetPetGUID())
4330  return;
4331 
4332  if (!unitTarget)
4333  return;
4334 
4336  return;
4337 
4338  Creature* creatureTarget = unitTarget->ToCreature();
4339 
4340  if (creatureTarget->IsPet())
4341  return;
4342 
4343  if (m_caster->getClass() != CLASS_HUNTER)
4344  return;
4345 
4346  // cast finish successfully
4347  //SendChannelUpdate(0);
4348  finish();
4349 
4350  Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
4351  if (!pet) // in very specific state like near world end/etc.
4352  return;
4353 
4354  // "kill" original creature
4355  creatureTarget->ForcedDespawn();
4356 
4357  // prepare visual effect for levelup
4358  pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel() - 1);
4359 
4360  // add to world
4361  pet->GetMap()->AddToMap(pet->ToCreature());
4362 
4363  // visual effect for levelup
4364  pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel());
4365 
4366  // caster have pet now
4367  m_caster->SetMinion(pet, true);
4368 
4369  if (m_caster->GetTypeId() == TYPEID_PLAYER)
4370  {
4373  }
4374 }
4375 
4377 {
4378  Player* owner = NULL;
4379  if (m_originalCaster)
4380  {
4382  owner = m_originalCaster->ToPlayer();
4383  else if (m_originalCaster->IsTotem())
4385  }
4386 
4387  uint32 petentry = m_spellInfo->EffectMiscValue[effIndex];
4388 
4389  if (!owner)
4390  {
4391  SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67);
4392  if (properties)
4393  SummonGuardian(effIndex, petentry, properties);
4394  return;
4395  }
4396 
4397  Pet* OldSummon = owner->GetPet();
4398 
4399  // if pet requested type already exist
4400  if (OldSummon)
4401  {
4402  if (petentry == 0 || OldSummon->GetEntry() == petentry)
4403  {
4404  // pet in corpse state can't be summoned
4405  if (OldSummon->isDead())
4406  return;
4407 
4408  ASSERT(OldSummon->GetMap() == owner->GetMap());
4409 
4410  //OldSummon->GetMap()->RemoveFromMap(OldSummon->ToCreature(),false);
4411 
4412  float px, py, pz;
4413  owner->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4414 
4415  OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation());
4416  //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4417  //OldSummon->SetMap(owner->GetMap());
4418  //owner->GetMap()->AddToMap(OldSummon->ToCreature());
4419 
4420  if (owner->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled())
4421  owner->ToPlayer()->PetSpellInitialize();
4422 
4423  return;
4424  }
4425 
4426  if (owner->GetTypeId() == TYPEID_PLAYER)
4427  owner->ToPlayer()->RemovePet(OldSummon, (OldSummon->getPetType() == HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT), false);
4428  else
4429  return;
4430  }
4431 
4432  float x, y, z;
4433  owner->GetClosePoint(x, y, z, owner->GetObjectSize());
4434  Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0);
4435  if (!pet)
4436  return;
4437 
4438  if (m_caster->GetTypeId() == TYPEID_UNIT)
4439  {
4440  if (m_caster->IsTotem())
4442  else
4444  }
4445 
4447 
4448  // generate new name for summon pet
4449  std::string new_name = sObjectMgr.GeneratePetName(petentry);
4450  if (!new_name.empty())
4451  pet->SetName(new_name);
4452 }
4453 
4455 {
4456  uint32 pet_entry = m_spellInfo->EffectMiscValue[effIndex];
4457  if (!pet_entry)
4458  return;
4459 
4460  Player* caster = NULL;
4461  if (m_originalCaster)
4462  {
4464  caster = m_originalCaster->ToPlayer();
4465  else if (m_originalCaster->IsTotem())
4467  }
4468 
4469  uint32 petentry = m_spellInfo->EffectMiscValue[effIndex];
4470 
4471  if (!caster)
4472  {
4473  SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67);
4474  if (properties)
4475  SummonGuardian(effIndex, petentry, properties);
4476  return;
4477  }
4478 
4479  // set timer for unsummon
4480  int32 duration = GetSpellDuration(m_spellInfo);
4481 
4482  Pet* OldSummon = caster->GetPet();
4483 
4484  // if pet requested type already exist
4485  if (OldSummon)
4486  {
4487  if (petentry == 0 || OldSummon->GetEntry() == petentry)
4488  {
4489  // pet in corpse state can't be summoned
4490  if (OldSummon->isDead())
4491  return;
4492 
4493  ASSERT(OldSummon->GetMap() == caster->GetMap());
4494 
4495  float px, py, pz;
4496  caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4497 
4498  OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation());
4499 
4500  if (caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled())
4501  caster->ToPlayer()->PetSpellInitialize();
4502 
4503  return;
4504  }
4505 
4506  if (caster->GetTypeId() == TYPEID_PLAYER)
4507  caster->ToPlayer()->RemovePet(OldSummon, PET_SAVE_AS_DELETED, false);
4508  else
4509  return;
4510  }
4511 
4512  /*
4513  // in another case summon new
4514  uint32 level = caster->getLevel();
4515 
4516  // level of pet summoned using engineering item based at engineering skill level
4517  if (m_CastItem)
4518  {
4519  ItemTemplate const *proto = m_CastItem->GetProto();
4520  if (proto && proto->RequiredSkill == SKILL_ENGINEERING)
4521  {
4522  uint16 skill202 = caster->GetSkillValue(SKILL_ENGINEERING);
4523  if (skill202)
4524  {
4525  level = skill202 / 5;
4526  }
4527  }
4528  }
4529  */
4530 
4531  // select center of summon position
4532  WorldLocation center = m_targets.m_dstPos;
4533 
4534  float radius = GetSpellRadius(m_spellInfo, effIndex, false);
4535 
4536  int32 amount = damage > 0 ? damage : 1;
4537 
4538  for (int32 count = 0; count < amount; ++count)
4539  {
4540  float px, py, pz;
4541  // If dest location if present
4543  {
4544  // Summon 1 unit in dest location
4545  if (count == 0)
4546  m_targets.m_dstPos.GetPosition(px, py, pz);
4547  // Summon in random point all other units if location present
4548  else
4549  m_caster->GetRandomPoint(center, radius, px, py, pz);
4550  }
4551  // Summon if dest location not present near caster
4552  else
4553  m_caster->GetClosePoint(px, py, pz, m_caster->GetObjectSize());
4554 
4555  Pet* pet = caster->SummonPet(m_spellInfo->EffectMiscValue[effIndex], px, py, pz, m_caster->GetOrientation(), CLASS_PET, duration);
4556  if (!pet)
4557  return;
4558 
4562  }
4563 }
4564 
4566 {
4567  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4568  return;
4569 
4570  Player* _player = m_caster->ToPlayer();
4571 
4572  Pet* pet = _player->GetPet();
4573  if (!pet)
4574  return;
4575  if (!pet->IsAlive())
4576  return;
4577 
4578  SpellEntry const* learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[effIndex]);
4579  if (!learn_spellproto)
4580  return;
4581 
4582  pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
4583  pet->learnSpell(learn_spellproto->Id);
4584 
4586  _player->PetSpellInitialize();
4587 }
4588 
4590 {
4591  // this effect use before aura Taunt apply for prevent taunt already attacking target
4592  // for spell as marked "non effective at already attacking target"
4594  || unitTarget->GetVictim() == m_caster)
4595  {
4597  return;
4598  }
4599 
4600  // Also use this effect to set the taunter's threat to the taunted creature's highest value
4602  {
4603  float myThreat = unitTarget->getThreatManager().getThreat(m_caster);
4604  float itsThreat = unitTarget->getThreatManager().getCurrentVictim()->getThreat();
4605  if (itsThreat > myThreat)
4606  unitTarget->getThreatManager().addThreat(m_caster, itsThreat - myThreat);
4607  }
4608 
4609  //Set aggro victim to caster