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