[9529] Make Player::IsValidPos const
[getmangos.git] / src / game / SpellEffects.cpp
blob64fc9e6cc2e0e3e98938ad28ebe9ffe0f834e3d0
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused from pre-1.2.1
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvironmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectBind, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectUnused, // 12 SPELL_EFFECT_PORTAL unused from pre-1.2.1, exist 2 spell, but not exist any data about its real usage
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused from pre-1.2.1
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused from pre-1.2.1
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused from pre-1.2.1
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectEmpty, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectEmpty, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectEmpty, // 25 SPELL_EFFECT_WEAPON spell per weapon type, in ItemSubclassmask store mask that can be used for usability check at equip, but current way using skill also work.
86 &Spell::EffectEmpty, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectLeapForward, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectEmpty, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectEmpty, // 39 SPELL_EFFECT_LANGUAGE misc store lang id
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectJump, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN spawn/login animation, expected by spawn unit cast, also base points store some dynflags
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused from pre-1.2.1
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT unused from pre-1.2.1
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectCreateRandomItem, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectRestoreItemCharges, // 66 SPELL_EFFECT_RESTORE_ITEM_CHARGES itemtype - is affected item ID
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectNULL, // 73 SPELL_EFFECT_UNTRAIN_TALENTS one spell: Trainer: Untrain Talents
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectNULL, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
148 &Spell::EffectNULL, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
149 &Spell::EffectNULL, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
150 &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_93 (old SPELL_EFFECT_SUMMON_PHANTASM)
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectSummonAllTotems, // 97 SPELL_EFFECT_SUMMON_ALL_TOTEMS
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112 (old SPELL_EFFECT_SUMMON_DEMON)
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectLeapBack, //138 SPELL_EFFECT_LEAP_BACK Leap back
199 &Spell::EffectNULL, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectNULL, //148 SPELL_EFFECT_148 single spell: Inflicts Fire damage to an enemy.
209 &Spell::EffectCharge2, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectNULL, //150 SPELL_EFFECT_150 2 spells in 3.3.2
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectTeachTaxiNode, //154 SPELL_EFFECT_TEACH_TAXI_NODE single spell: Teach River's Heart Taxi Path
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL, //160 SPELL_EFFECT_160 single spell: Nerub'ar Web Random Unit
221 &Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectEmpty(SpellEffectIndex /*eff_idx*/)
227 // NOT NEED ANY IMPLEMENTATION CODE, EFFECT POSISBLE USED AS MARKER OR CLIENT INFORM
230 void Spell::EffectNULL(SpellEffectIndex /*eff_idx*/)
232 sLog.outDebug("WORLD: Spell Effect DUMMY");
235 void Spell::EffectUnused(SpellEffectIndex /*eff_idx*/)
237 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
240 void Spell::EffectResurrectNew(SpellEffectIndex eff_idx)
242 if(!unitTarget || unitTarget->isAlive())
243 return;
245 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
246 return;
248 if(!unitTarget->IsInWorld())
249 return;
251 Player* pTarget = ((Player*)unitTarget);
253 if(pTarget->isRessurectRequested()) // already have one active request
254 return;
256 uint32 health = damage;
257 uint32 mana = m_spellInfo->EffectMiscValue[eff_idx];
258 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
259 SendResurrectRequest(pTarget);
262 void Spell::EffectInstaKill(SpellEffectIndex /*eff_idx*/)
264 if( !unitTarget || !unitTarget->isAlive() )
265 return;
267 // Demonic Sacrifice
268 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
270 uint32 entry = unitTarget->GetEntry();
271 uint32 spellID;
272 switch(entry)
274 case 416: spellID=18789; break; //imp
275 case 417: spellID=18792; break; //fellhunter
276 case 1860: spellID=18790; break; //void
277 case 1863: spellID=18791; break; //succubus
278 case 17252: spellID=35701; break; //fellguard
279 default:
280 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry);
281 return;
284 m_caster->CastSpell(m_caster, spellID, true);
287 if(m_caster == unitTarget) // prevent interrupt message
288 finish();
290 m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
293 void Spell::EffectEnvironmentalDMG(SpellEffectIndex eff_idx)
295 uint32 absorb = 0;
296 uint32 resist = 0;
298 // Note: this hack with damage replace required until GO casting not implemented
299 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
300 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
301 damage = m_spellInfo->CalculateSimpleValue(eff_idx);
303 m_caster->CalcAbsorbResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
305 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
306 if(m_caster->GetTypeId() == TYPEID_PLAYER)
307 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage);
310 void Spell::EffectSchoolDMG(SpellEffectIndex effect_idx)
312 if( unitTarget && unitTarget->isAlive())
314 switch(m_spellInfo->SpellFamilyName)
316 case SPELLFAMILY_GENERIC:
318 switch(m_spellInfo->Id) // better way to check unknown
320 // Meteor like spells (divided damage to targets)
321 case 24340: case 26558: case 28884: // Meteor
322 case 36837: case 38903: case 41276: // Meteor
323 case 26789: // Shard of the Fallen Star
324 case 31436: // Malevolent Cleave
325 case 35181: // Dive Bomb
326 case 40810: case 43267: case 43268: // Saber Lash
327 case 42384: // Brutal Swipe
328 case 45150: // Meteor Slash
329 case 64422: case 64688: // Sonic Screech
330 case 70492: case 72505: // Ooze Eruption
331 case 71904: // Chaos Bane
332 case 72624: case 72625: // Ooze Eruption
334 uint32 count = 0;
335 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
336 if(ihit->effectMask & (1<<effect_idx))
337 ++count;
339 damage /= count; // divide to all targets
340 break;
342 // percent from health with min
343 case 25599: // Thundercrash
345 damage = unitTarget->GetHealth() / 2;
346 if(damage < 200)
347 damage = 200;
348 break;
350 // Intercept (warrior spell trigger)
351 case 20253:
352 case 61491:
354 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
355 break;
357 // Cataclysmic Bolt
358 case 38441:
360 damage = unitTarget->GetMaxHealth() / 2;
361 break;
363 // Tympanic Tantrum
364 case 62775:
366 damage = unitTarget->GetMaxHealth() / 10;
367 break;
369 // Hand of Rekoning (name not have typos ;) )
370 case 67485:
371 damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
372 break;
374 break;
376 case SPELLFAMILY_MAGE:
377 // remove Arcane Blast buffs at any non-Arcane Blast arcane damage spell.
378 // NOTE: it removed at hit instead cast because currently spell done-damage calculated at hit instead cast
379 if ((m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_ARCANE) && !(m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000)))
380 m_caster->RemoveAurasDueToSpell(36032); // Arcane Blast buff
381 break;
382 case SPELLFAMILY_WARRIOR:
384 // Bloodthirst
385 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
387 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
389 // Shield Slam
390 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
391 damage += int32(m_caster->GetShieldBlockValue());
392 // Victory Rush
393 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
395 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
396 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
398 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
399 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
400 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
401 // Heroic Throw ${$m1+$AP*.50}
402 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
403 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
404 // Shockwave ${$m3/100*$AP}
405 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
407 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, EFFECT_INDEX_2, m_spellInfo->EffectBasePoints[EFFECT_INDEX_2], unitTarget);
408 if (pct > 0)
409 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
410 break;
412 // Thunder Clap
413 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000080))
415 damage+=int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
417 break;
419 case SPELLFAMILY_WARLOCK:
421 // Incinerate Rank 1 & 2
422 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
424 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
425 // Check aura state for speed but aura state set not only for Immolate spell
426 if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
428 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
429 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
431 // Immolate
432 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
433 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
435 damage += damage/4;
436 break;
441 // Shadowflame
442 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
444 // Apply DOT part
445 switch(m_spellInfo->Id)
447 case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
448 case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
449 default:
450 sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
451 break;
454 // Conflagrate - consumes Immolate or Shadowflame
455 else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
457 Aura const* aura = NULL; // found req. aura for damage calculation
459 Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
460 for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
462 // for caster applied auras only
463 if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
464 (*i)->GetCasterGUID()!=m_caster->GetGUID())
465 continue;
467 // Immolate
468 if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
470 aura = *i; // it selected always if exist
471 break;
474 // Shadowflame
475 if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
476 aura = *i; // remember but wait possible Immolate as primary priority
479 // found Immolate or Shadowflame
480 if (aura)
482 // DoT not have applied spell bonuses in m_amount
483 int32 damagetick = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), aura->GetModifier()->m_amount, DOT);
484 damage += damagetick * 4;
486 // Glyph of Conflagrate
487 if (!m_caster->HasAura(56235))
488 unitTarget->RemoveAurasByCasterSpell(aura->GetId(), m_caster->GetGUID());
489 break;
492 break;
494 case SPELLFAMILY_PRIEST:
496 // Shadow Word: Death - deals damage equal to damage done to caster
497 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000))
498 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
499 // Improved Mind Blast (Mind Blast in shadow form bonus)
500 else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000)))
502 Unit::AuraList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
503 for(Unit::AuraList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
505 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST &&
506 ((*i)->GetSpellProto()->SpellIconID == 95))
508 int chance = (*i)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1);
509 if (roll_chance_i(chance))
510 // Mind Trauma
511 m_caster->CastSpell(unitTarget, 48301, true);
512 break;
516 break;
518 case SPELLFAMILY_DRUID:
520 // Ferocious Bite
521 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
523 // converts up to 30 points of energy into ($f1+$AP/410) additional damage
524 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
525 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
526 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
527 uint32 energy = m_caster->GetPower(POWER_ENERGY);
528 uint32 used_energy = energy > 30 ? 30 : energy;
529 damage += int32(used_energy * multiple);
530 m_caster->SetPower(POWER_ENERGY,energy-used_energy);
532 // Rake
533 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[EFFECT_INDEX_2] == SPELL_EFFECT_ADD_COMBO_POINTS)
535 // $AP*0.01 bonus
536 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
538 // Swipe
539 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
541 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
543 break;
545 case SPELLFAMILY_ROGUE:
547 // Envenom
548 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)))
550 // consume from stack dozes not more that have combo-points
551 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
553 Aura *poison = 0;
554 // Lookup for Deadly poison (only attacker applied)
555 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
556 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
557 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
558 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x10000)) &&
559 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
561 poison = *itr;
562 break;
564 // count consumed deadly poison doses at target
565 if (poison)
567 bool needConsume = true;
568 uint32 spellId = poison->GetId();
569 uint32 doses = poison->GetStackAmount();
570 if (doses > combo)
571 doses = combo;
573 // Master Poisoner
574 Unit::AuraList const& auraList = ((Player*)m_caster)->GetAurasByType(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL);
575 for(Unit::AuraList::const_iterator iter = auraList.begin(); iter!=auraList.end(); ++iter)
577 if ((*iter)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellProto()->SpellIconID == 1960)
579 if (int32 chance = (*iter)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2))
580 if (roll_chance_i(chance))
581 needConsume = false;
583 break;
587 if(needConsume)
588 for (uint32 i = 0; i < doses; ++i)
589 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
591 damage *= doses;
592 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
594 // Eviscerate and Envenom Bonus Damage (item set effect)
595 if(m_caster->GetDummyAura(37169))
596 damage += ((Player*)m_caster)->GetComboPoints()*40;
599 // Eviscerate
600 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
602 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
604 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
605 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
607 // Eviscerate and Envenom Bonus Damage (item set effect)
608 if(m_caster->GetDummyAura(37169))
609 damage += combo*40;
612 // Gouge
613 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
615 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
617 // Instant Poison
618 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
620 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
622 // Wound Poison
623 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
625 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
627 break;
629 case SPELLFAMILY_HUNTER:
631 //Gore
632 if (m_spellInfo->SpellIconID == 1578)
634 if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
635 damage *= 2;
637 // Mongoose Bite
638 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
640 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
642 // Counterattack
643 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
645 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
647 // Arcane Shot
648 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
650 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
652 // Steady Shot
653 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
655 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
656 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
658 // Explosive Trap Effect
659 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
661 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
663 break;
665 case SPELLFAMILY_PALADIN:
667 // Judgement of Righteousness - receive benefit from Spell Damage and Attack power
668 if (m_spellInfo->Id == 20187)
670 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
671 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
672 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
673 damage += int32(ap * 0.2f) + int32(holy * 32 / 100);
675 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
676 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
678 uint32 debuf_id;
679 switch(m_spellInfo->Id)
681 case 53733: debuf_id = 53742; break;// Judgement of Corruption -> Blood Corruption
682 case 31804: debuf_id = 31803; break;// Judgement of Vengeance -> Holy Vengeance
683 default: return;
686 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
687 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
688 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
689 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
690 // Get stack of Holy Vengeance on the target added by caster
691 uint32 stacks = 0;
692 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
693 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
695 if( ((*itr)->GetId() == debuf_id) && (*itr)->GetCasterGUID()==m_caster->GetGUID())
697 stacks = (*itr)->GetStackAmount();
698 break;
701 // + 10% for each application of Holy Vengeance on the target
702 if(stacks)
703 damage += damage * stacks * 10 /100;
705 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
706 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
708 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
709 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
710 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
711 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
713 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
714 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
716 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
717 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
718 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
719 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
721 // Hammer of the Righteous
722 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
724 // Add main hand dps * effect[2] amount
725 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
726 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, EFFECT_INDEX_2, m_spellInfo->EffectBasePoints[EFFECT_INDEX_2], unitTarget);
727 damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
729 // Shield of Righteousness
730 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
732 damage+=int32(m_caster->GetShieldBlockValue());
734 // Judgement
735 else if (m_spellInfo->Id == 54158)
737 // [1 + 0.25 * SPH + 0.16 * AP]
738 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.16f);
740 break;
744 if(damage >= 0)
745 m_damage += damage;
749 void Spell::EffectDummy(SpellEffectIndex eff_idx)
751 if (!unitTarget && !gameObjTarget && !itemTarget)
752 return;
754 // selection by spell family
755 switch(m_spellInfo->SpellFamilyName)
757 case SPELLFAMILY_GENERIC:
759 switch(m_spellInfo->Id)
761 case 8063: // Deviate Fish
763 if (m_caster->GetTypeId() != TYPEID_PLAYER)
764 return;
766 uint32 spell_id = 0;
767 switch(urand(1,5))
769 case 1: spell_id = 8064; break; // Sleepy
770 case 2: spell_id = 8065; break; // Invigorate
771 case 3: spell_id = 8066; break; // Shrink
772 case 4: spell_id = 8067; break; // Party Time!
773 case 5: spell_id = 8068; break; // Healthy Spirit
775 m_caster->CastSpell(m_caster, spell_id, true, NULL);
776 return;
778 case 8213: // Savory Deviate Delight
780 if (m_caster->GetTypeId() != TYPEID_PLAYER)
781 return;
783 uint32 spell_id = 0;
784 switch(urand(1,2))
786 // Flip Out - ninja
787 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
788 // Yaaarrrr - pirate
789 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
792 m_caster->CastSpell(m_caster,spell_id,true,NULL);
793 return;
795 case 8593: // Symbol of life (restore creature to life)
796 case 31225: // Shimmering Vessel (restore creature to life)
798 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
799 return;
801 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
802 return;
804 case 13120: // net-o-matic
806 if (!unitTarget)
807 return;
809 uint32 spell_id = 0;
811 uint32 roll = urand(0, 99);
813 if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
814 spell_id = 16566;
815 else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
816 spell_id = 13119;
817 else // normal root
818 spell_id = 13099;
820 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
821 return;
823 case 13567: // Dummy Trigger
825 // can be used for different aura triggering, so select by aura
826 if (!m_triggeredByAuraSpell || !unitTarget)
827 return;
829 switch(m_triggeredByAuraSpell->Id)
831 case 26467: // Persistent Shield
832 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
833 break;
834 default:
835 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
836 break;
838 return;
840 case 15998: // Capture Worg Pup
841 case 29435: // Capture Female Kaliri Hatchling
843 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
844 return;
846 Creature* creatureTarget = (Creature*)unitTarget;
848 creatureTarget->ForcedDespawn();
849 return;
851 case 16589: // Noggenfogger Elixir
853 if (m_caster->GetTypeId() != TYPEID_PLAYER)
854 return;
856 uint32 spell_id = 0;
857 switch(urand(1, 3))
859 case 1: spell_id = 16595; break;
860 case 2: spell_id = 16593; break;
861 default:spell_id = 16591; break;
864 m_caster->CastSpell(m_caster, spell_id, true, NULL);
865 return;
867 case 17251: // Spirit Healer Res
869 if (!unitTarget)
870 return;
872 Unit* caster = GetAffectiveCaster();
874 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
876 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
877 data << uint64(unitTarget->GetGUID());
878 ((Player*)caster)->GetSession()->SendPacket( &data );
880 return;
882 case 17271: // Test Fetid Skull
884 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
885 return;
887 uint32 spell_id = roll_chance_i(50)
888 ? 17269 // Create Resonating Skull
889 : 17270; // Create Bone Dust
891 m_caster->CastSpell(m_caster, spell_id, true, NULL);
892 return;
894 case 20577: // Cannibalize
896 if (unitTarget)
897 m_caster->CastSpell(m_caster, 20578, false, NULL);
899 return;
901 case 23019: // Crystal Prison Dummy DND
903 if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
904 return;
906 Creature* creatureTarget = (Creature*)unitTarget;
907 if (creatureTarget->isPet())
908 return;
910 GameObject* pGameObj = new GameObject;
912 Map *map = creatureTarget->GetMap();
914 // create before death for get proper coordinates
915 if (!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
916 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
917 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
919 delete pGameObj;
920 return;
923 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
924 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
925 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
926 pGameObj->SetSpellId(m_spellInfo->Id);
928 creatureTarget->ForcedDespawn();
930 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
931 map->Add(pGameObj);
933 return;
935 case 23074: // Arcanite Dragonling
937 if (!m_CastItem)
938 return;
940 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
941 return;
943 case 23075: // Mithril Mechanical Dragonling
945 if (!m_CastItem)
946 return;
948 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
949 return;
951 case 23076: // Mechanical Dragonling
953 if (!m_CastItem)
954 return;
956 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
957 return;
959 case 23133: // Gnomish Battle Chicken
961 if (!m_CastItem)
962 return;
964 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
965 return;
967 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
969 int32 r = irand(0, 119);
970 if (r < 20) // Transporter Malfunction - 1/6 polymorph
971 m_caster->CastSpell(m_caster, 23444, true);
972 else if (r < 100) // Evil Twin - 4/6 evil twin
973 m_caster->CastSpell(m_caster, 23445, true);
974 else // Transporter Malfunction - 1/6 miss the target
975 m_caster->CastSpell(m_caster, 36902, true);
977 return;
979 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
981 if (roll_chance_i(50)) // Gadgetzan Transporter - success
982 m_caster->CastSpell(m_caster, 23441, true);
983 else // Gadgetzan Transporter Failure - failure
984 m_caster->CastSpell(m_caster, 23446, true);
986 return;
988 case 23645: // Hourglass Sand
989 m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
990 return;
991 case 23725: // Gift of Life (warrior bwl trinket)
992 m_caster->CastSpell(m_caster, 23782, true);
993 m_caster->CastSpell(m_caster, 23783, true);
994 return;
995 case 25860: // Reindeer Transformation
997 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
998 return;
1000 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
1001 float speed = m_caster->GetSpeedRate(MOVE_RUN);
1003 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1005 //5 different spells used depending on mounted speed and if mount can fly or not
1006 if (flyspeed >= 4.1f)
1007 // Flying Reindeer
1008 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
1009 else if (flyspeed >= 3.8f)
1010 // Flying Reindeer
1011 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
1012 else if (flyspeed >= 1.6f)
1013 // Flying Reindeer
1014 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
1015 else if (speed >= 2.0f)
1016 // Reindeer
1017 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
1018 else
1019 // Reindeer
1020 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
1022 return;
1024 case 26074: // Holiday Cheer
1025 // implemented at client side
1026 return;
1027 case 28006: // Arcane Cloaking
1029 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
1030 // Naxxramas Entry Flag Effect DND
1031 m_caster->CastSpell(unitTarget, 29294, true);
1033 return;
1035 case 29200: // Purify Helboar Meat
1037 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1038 return;
1040 uint32 spell_id = roll_chance_i(50)
1041 ? 29277 // Summon Purified Helboar Meat
1042 : 29278; // Summon Toxic Helboar Meat
1044 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1045 return;
1047 case 29858: // Soulshatter
1049 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
1050 m_caster->CastSpell(unitTarget,32835,true);
1052 return;
1054 case 30458: // Nigh Invulnerability
1056 if (!m_CastItem)
1057 return;
1059 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1060 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1061 else // Complete Vulnerability - backfire in 14% casts
1062 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1064 return;
1066 case 30507: // Poultryizer
1068 if (!m_CastItem)
1069 return;
1071 if (roll_chance_i(80)) // Poultryized! - success
1072 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1073 else // Poultryized! - backfire 20%
1074 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1076 return;
1078 case 33060: // Make a Wish
1080 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1081 return;
1083 uint32 spell_id = 0;
1085 switch(urand(1,5))
1087 case 1: spell_id = 33053; break; // Mr Pinchy's Blessing
1088 case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy
1089 case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy
1090 case 4: spell_id = 33062; break; // Tiny Magical Crawdad
1091 case 5: spell_id = 33064; break; // Mr. Pinchy's Gift
1094 m_caster->CastSpell(m_caster, spell_id, true, NULL);
1095 return;
1097 case 35745: // Socrethar's Stone
1099 uint32 spell_id;
1100 switch(m_caster->GetAreaId())
1102 case 3900: spell_id = 35743; break; // Socrethar Portal
1103 case 3742: spell_id = 35744; break; // Socrethar Portal
1104 default: return;
1107 m_caster->CastSpell(m_caster, spell_id, true);
1108 return;
1110 case 37674: // Chaos Blast
1112 if (!unitTarget)
1113 return;
1115 int32 basepoints0 = 100;
1116 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1117 return;
1119 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1121 // selecting one from Bloodstained Fortune item
1122 uint32 newitemid;
1123 switch(urand(1, 20))
1125 case 1: newitemid = 32688; break;
1126 case 2: newitemid = 32689; break;
1127 case 3: newitemid = 32690; break;
1128 case 4: newitemid = 32691; break;
1129 case 5: newitemid = 32692; break;
1130 case 6: newitemid = 32693; break;
1131 case 7: newitemid = 32700; break;
1132 case 8: newitemid = 32701; break;
1133 case 9: newitemid = 32702; break;
1134 case 10: newitemid = 32703; break;
1135 case 11: newitemid = 32704; break;
1136 case 12: newitemid = 32705; break;
1137 case 13: newitemid = 32706; break;
1138 case 14: newitemid = 32707; break;
1139 case 15: newitemid = 32708; break;
1140 case 16: newitemid = 32709; break;
1141 case 17: newitemid = 32710; break;
1142 case 18: newitemid = 32711; break;
1143 case 19: newitemid = 32712; break;
1144 case 20: newitemid = 32713; break;
1145 default:
1146 return;
1149 DoCreateItem(eff_idx, newitemid);
1150 return;
1152 case 42287: // Salvage Wreckage
1154 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1155 return;
1157 if (roll_chance_i(66))
1158 m_caster->CastSpell(m_caster, 42289, true, m_CastItem);
1159 else
1160 m_caster->CastSpell(m_caster, 42288, true);
1162 return;
1164 case 43036: // Dismembering Corpse
1166 if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER)
1167 return;
1169 if (unitTarget->HasAura(43059, EFFECT_INDEX_0))
1170 return;
1172 unitTarget->CastSpell(m_caster, 43037, true);
1173 unitTarget->CastSpell(unitTarget, 43059, true);
1174 return;
1176 // Demon Broiled Surprise
1177 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1178 case 43723:
1180 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1181 return;
1183 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1184 return;
1187 case 43882: // Scourging Crystal Controller Dummy
1189 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1190 return;
1192 // see spell dummy 50133
1193 unitTarget->RemoveAurasDueToSpell(43874);
1194 return;
1196 case 44454: // Tasty Reef Fish
1198 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1199 return;
1201 m_caster->CastSpell(unitTarget, 44455, true, m_CastItem);
1202 return;
1204 case 44875: // Complete Raptor Capture
1206 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1207 return;
1209 Creature* creatureTarget = (Creature*)unitTarget;
1211 creatureTarget->ForcedDespawn();
1213 //cast spell Raptor Capture Credit
1214 m_caster->CastSpell(m_caster, 42337, true, NULL);
1215 return;
1217 case 44997: // Converting Sentry
1219 //Converted Sentry Credit
1220 m_caster->CastSpell(m_caster, 45009, true);
1221 return;
1223 case 45030: // Impale Emissary
1225 // Emissary of Hate Credit
1226 m_caster->CastSpell(m_caster, 45088, true);
1227 return;
1229 case 45980: // Re-Cursive Transmatter Injection
1231 if (m_caster->GetTypeId() == TYPEID_PLAYER && unitTarget)
1233 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(46022))
1235 m_caster->CastSpell(unitTarget, pSpell, true);
1236 ((Player*)m_caster)->KilledMonsterCredit(pSpell->EffectMiscValue[EFFECT_INDEX_0], 0);
1239 if (unitTarget->GetTypeId() == TYPEID_UNIT)
1240 ((Creature*)unitTarget)->ForcedDespawn();
1243 return;
1245 case 45685: // Magnataur On Death 2
1247 m_caster->RemoveAurasDueToSpell(45673);
1248 m_caster->RemoveAurasDueToSpell(45672);
1249 m_caster->RemoveAurasDueToSpell(45677);
1250 m_caster->RemoveAurasDueToSpell(45681);
1251 m_caster->RemoveAurasDueToSpell(45683);
1252 return;
1254 case 45990: // Collect Oil
1256 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1257 return;
1259 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(45991))
1261 unitTarget->CastSpell(unitTarget, pSpell, true);
1262 ((Creature*)unitTarget)->ForcedDespawn(GetSpellDuration(pSpell) + 1);
1265 return;
1267 case 46167: // Planning for the Future: Create Snowfall Glade Pup Cover
1268 case 50926: // Gluttonous Lurkers: Create Zul'Drak Rat Cover
1269 case 51026: // Create Drakkari Medallion Cover
1270 case 51592: // Pickup Primordial Hatchling
1271 case 51961: // Captured Chicken Cover
1273 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
1274 return;
1276 uint32 spellId = 0;
1278 switch(m_spellInfo->Id)
1280 case 46167: spellId = 46773; break;
1281 case 50926: spellId = 50927; break;
1282 case 51026: spellId = 50737; break;
1283 case 51592: spellId = 51593; break;
1284 case 51961: spellId = 51037; break;
1287 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(spellId))
1289 unitTarget->CastSpell(m_caster, spellId, true);
1291 Creature* creatureTarget = (Creature*)unitTarget;
1293 if (const SpellCastTimesEntry *pCastTime = sSpellCastTimesStore.LookupEntry(pSpell->CastingTimeIndex))
1294 creatureTarget->ForcedDespawn(pCastTime->CastTime + 1);
1296 return;
1298 case 46485: // Greatmother's Soulcatcher
1300 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1301 return;
1303 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(46486))
1305 m_caster->CastSpell(unitTarget, pSpell, true);
1307 if (const SpellEntry *pSpellCredit = sSpellStore.LookupEntry(pSpell->EffectMiscValue[EFFECT_INDEX_0]))
1308 ((Player*)m_caster)->KilledMonsterCredit(pSpellCredit->EffectMiscValue[EFFECT_INDEX_0], 0);
1310 ((Creature*)unitTarget)->ForcedDespawn();
1313 return;
1315 case 46606: // Plague Canister Dummy
1317 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1318 return;
1320 unitTarget->CastSpell(m_caster, 43160, true);
1321 unitTarget->setDeathState(JUST_DIED);
1322 unitTarget->SetHealth(0);
1323 return;
1325 case 46797: // Quest - Borean Tundra - Set Explosives Cart
1327 if (!unitTarget)
1328 return;
1330 // Quest - Borean Tundra - Summon Explosives Cart
1331 unitTarget->CastSpell(unitTarget,46798,true,m_CastItem,NULL,m_originalCasterGUID);
1332 break;
1334 case 49357: // Brewfest Mount Transformation
1336 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1337 return;
1339 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1340 return;
1342 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1344 // Ram for Alliance, Kodo for Horde
1345 if (((Player *)m_caster)->GetTeam() == ALLIANCE)
1347 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1348 // 100% Ram
1349 m_caster->CastSpell(m_caster, 43900, true);
1350 else
1351 // 60% Ram
1352 m_caster->CastSpell(m_caster, 43899, true);
1354 else
1356 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1357 // 100% Kodo
1358 m_caster->CastSpell(m_caster, 49379, true);
1359 else
1360 // 60% Kodo
1361 m_caster->CastSpell(m_caster, 49378, true);
1363 return;
1365 case 50133: // Scourging Crystal Controller
1367 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1368 return;
1370 if (unitTarget->HasAura(43874))
1372 // someone else is already channeling target
1373 if (unitTarget->HasAura(43878))
1374 return;
1376 m_caster->CastSpell(unitTarget, 43878, true, m_CastItem);
1379 return;
1381 case 50243: // Teach Language
1383 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1384 return;
1386 // spell has a 1/3 chance to trigger one of the below
1387 if (roll_chance_i(66))
1388 return;
1390 if (((Player*)m_caster)->GetTeam() == ALLIANCE)
1392 // 1000001 - gnomish binary
1393 m_caster->CastSpell(m_caster, 50242, true);
1395 else
1397 // 01001000 - goblin binary
1398 m_caster->CastSpell(m_caster, 50246, true);
1401 return;
1403 case 51276: // Incinerate Corpse
1405 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1406 return;
1408 unitTarget->CastSpell(unitTarget, 51278, true);
1409 unitTarget->CastSpell(m_caster, 51279, true);
1411 unitTarget->setDeathState(JUST_DIED);
1412 return;
1414 case 51330: // Shoot RJR
1416 if (!unitTarget)
1417 return;
1419 // guessed chances
1420 if (roll_chance_i(75))
1421 m_caster->CastSpell(unitTarget, roll_chance_i(50) ? 51332 : 51366, true, m_CastItem);
1422 else
1423 m_caster->CastSpell(unitTarget, 51331, true, m_CastItem);
1425 return;
1427 case 51333: // Dig For Treasure
1429 if (!unitTarget)
1430 return;
1432 if (roll_chance_i(75))
1433 m_caster->CastSpell(unitTarget, 51370, true, m_CastItem);
1434 else
1435 m_caster->CastSpell(m_caster, 51345, true);
1437 return;
1439 case 51582: // Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1441 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1442 return;
1444 if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1445 bg->EventPlayerDroppedFlag((Player*)m_caster);
1447 m_caster->CastSpell(m_caster, 30452, true, NULL);
1448 return;
1450 case 52308: // Take Sputum Sample
1452 switch(eff_idx)
1454 case EFFECT_INDEX_0:
1456 uint32 spellID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0);
1457 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
1459 if (m_caster->HasAura(reqAuraID, EFFECT_INDEX_0))
1460 m_caster->CastSpell(m_caster, spellID, true, NULL);
1461 return;
1463 case EFFECT_INDEX_1:
1464 return; // additional data for dummy[0]
1466 return;
1468 case 52759: // Ancestral Awakening
1470 if (!unitTarget)
1471 return;
1473 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1474 return;
1476 case 52845: // Brewfest Mount Transformation (Faction Swap)
1478 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1479 return;
1481 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
1482 return;
1484 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
1486 // Ram for Horde, Kodo for Alliance
1487 if (((Player *)m_caster)->GetTeam() == HORDE)
1489 if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f)
1490 // Swift Brewfest Ram, 100% Ram
1491 m_caster->CastSpell(m_caster, 43900, true);
1492 else
1493 // Brewfest Ram, 60% Ram
1494 m_caster->CastSpell(m_caster, 43899, true);
1496 else
1498 if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f)
1499 // Great Brewfest Kodo, 100% Kodo
1500 m_caster->CastSpell(m_caster, 49379, true);
1501 else
1502 // Brewfest Riding Kodo, 60% Kodo
1503 m_caster->CastSpell(m_caster, 49378, true);
1505 return;
1507 case 53341: // Rune of Cinderglacier
1508 case 53343: // Rune of Razorice
1510 // Runeforging Credit
1511 m_caster->CastSpell(m_caster, 54586, true);
1512 return;
1514 case 55004: // Nitro Boosts
1516 if (!m_CastItem)
1517 return;
1519 if (roll_chance_i(95)) // Nitro Boosts - success
1520 m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
1521 else // Knocked Up - backfire 5%
1522 m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
1524 return;
1526 case 55818: // Hurl Boulder
1528 // unclear how many summon min/max random, best guess below
1529 uint32 random = urand(3,5);
1531 for(uint32 i = 0; i < random; ++i)
1532 m_caster->CastSpell(m_caster, 55528, true);
1534 return;
1536 case 58418: // Portal to Orgrimmar
1537 case 58420: // Portal to Stormwind
1538 return; // implemented in EffectScript[0]
1539 case 58601: // Remove Flight Auras
1541 m_caster->RemoveSpellsCausingAura(SPELL_AURA_FLY);
1542 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
1543 return;
1545 case 59640: // Underbelly Elixir
1547 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1548 return;
1550 uint32 spell_id = 0;
1551 switch(urand(1,3))
1553 case 1: spell_id = 59645; break;
1554 case 2: spell_id = 59831; break;
1555 case 3: spell_id = 59843; break;
1558 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1559 return;
1561 case 60932: // Disengage (one from creature versions)
1563 if (!unitTarget)
1564 return;
1566 m_caster->CastSpell(unitTarget,60934,true,NULL);
1567 return;
1569 case 67019: // Flask of the North
1571 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1572 return;
1574 uint32 spell_id = 0;
1575 switch(m_caster->getClass())
1577 case CLASS_WARRIOR:
1578 case CLASS_DEATH_KNIGHT:
1579 spell_id = 67018; // STR for Warriors, Death Knights
1580 break;
1581 case CLASS_ROGUE:
1582 case CLASS_HUNTER:
1583 spell_id = 67017; // AP for Rogues, Hunters
1584 break;
1585 case CLASS_PRIEST:
1586 case CLASS_MAGE:
1587 case CLASS_WARLOCK:
1588 spell_id = 67016; // SPD for Priests, Mages, Warlocks
1589 break;
1590 case CLASS_SHAMAN:
1591 // random (SPD, AP)
1592 spell_id = roll_chance_i(50) ? 67016 : 67017;
1593 break;
1594 case CLASS_PALADIN:
1595 case CLASS_DRUID:
1596 default:
1597 // random (SPD, STR)
1598 spell_id = roll_chance_i(50) ? 67016 : 67018;
1599 break;
1601 m_caster->CastSpell(m_caster, spell_id, true);
1602 return;
1605 break;
1607 case SPELLFAMILY_MAGE:
1609 switch(m_spellInfo->Id)
1611 case 11958: // Cold Snap
1613 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1614 return;
1616 // immediately finishes the cooldown on Frost spells
1617 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1618 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1620 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1622 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1623 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1624 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1626 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
1628 else
1629 ++itr;
1631 return;
1633 case 31687: // Summon Water Elemental
1635 if (m_caster->HasAura(70937)) // Glyph of Eternal Water (permanent limited by known spells version)
1636 m_caster->CastSpell(m_caster, 70908, true);
1637 else // temporary version
1638 m_caster->CastSpell(m_caster, 70907, true);
1640 return;
1642 case 32826: // Polymorph Cast Visual
1644 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
1646 //Polymorph Cast Visual Rank 1
1647 const uint32 spell_list[6] =
1649 32813, // Squirrel Form
1650 32816, // Giraffe Form
1651 32817, // Serpent Form
1652 32818, // Dragonhawk Form
1653 32819, // Worgen Form
1654 32820 // Sheep Form
1656 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1658 return;
1662 // Conjure Mana Gem
1663 if (eff_idx == EFFECT_INDEX_1 && m_spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_CREATE_ITEM)
1665 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1666 return;
1668 // checked in create item check, avoid unexpected
1669 if (Item* item = ((Player*)m_caster)->GetItemByLimitedCategory(ITEM_LIMIT_CATEGORY_MANA_GEM))
1670 if (item->HasMaxCharges())
1671 return;
1673 unitTarget->CastSpell( unitTarget, m_spellInfo->CalculateSimpleValue(eff_idx), true, m_CastItem);
1674 return;
1676 break;
1678 case SPELLFAMILY_WARRIOR:
1680 // Charge
1681 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1683 int32 chargeBasePoints0 = damage;
1684 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1685 return;
1687 // Execute
1688 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1690 if (!unitTarget)
1691 return;
1693 uint32 rage = m_caster->GetPower(POWER_RAGE);
1695 // up to max 30 rage cost
1696 if (rage > 300)
1697 rage = 300;
1699 // Glyph of Execution bonus
1700 uint32 rage_modified = rage;
1702 if (Aura *aura = m_caster->GetDummyAura(58367))
1703 rage_modified += aura->GetModifier()->m_amount*10;
1705 int32 basePoints0 = damage+int32(rage_modified * m_spellInfo->DmgMultiplier[eff_idx] +
1706 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1708 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1710 // Sudden Death
1711 if (m_caster->HasAura(52437))
1713 Unit::AuraList const& auras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
1714 for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1716 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1717 if ((*itr)->GetSpellProto()->SpellIconID == 1989)
1719 // saved rage top stored in next affect
1720 uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_1)*10;
1721 if(lastrage < rage)
1722 rage -= lastrage;
1723 break;
1728 m_caster->SetPower(POWER_RAGE,m_caster->GetPower(POWER_RAGE)-rage);
1729 return;
1731 // Slam
1732 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1734 if(!unitTarget)
1735 return;
1737 // dummy cast itself ignored by client in logs
1738 m_caster->CastCustomSpell(unitTarget,50782,&damage,NULL,NULL,true);
1739 return;
1741 // Concussion Blow
1742 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1744 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1745 return;
1748 switch(m_spellInfo->Id)
1750 // Warrior's Wrath
1751 case 21977:
1753 if (!unitTarget)
1754 return;
1755 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1756 return;
1758 // Last Stand
1759 case 12975:
1761 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1762 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1763 return;
1765 // Bloodthirst
1766 case 23881:
1768 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1769 return;
1772 break;
1774 case SPELLFAMILY_WARLOCK:
1776 // Life Tap
1777 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1779 // In 303 exist spirit depend
1780 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1781 switch (m_spellInfo->Id)
1783 case 1454: damage+=spirit; break;
1784 case 1455: damage+=spirit*15/10; break;
1785 case 1456: damage+=spirit*2; break;
1786 case 11687: damage+=spirit*25/10; break;
1787 case 11688:
1788 case 11689:
1789 case 27222:
1790 case 57946: damage+=spirit*3; break;
1791 default:
1792 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1793 return;
1795 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1796 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1797 if (unitTarget && (int32(unitTarget->GetHealth()) > damage))
1799 // Shouldn't Appear in Combat Log
1800 unitTarget->ModifyHealth(-damage);
1802 int32 mana = damage;
1803 // Improved Life Tap mod
1804 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1805 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1807 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1808 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1810 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1812 // Mana Feed
1813 int32 manaFeedVal = 0;
1814 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1815 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1817 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1818 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1820 if (manaFeedVal > 0)
1822 manaFeedVal = manaFeedVal * mana / 100;
1823 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1826 else
1827 SendCastResult(SPELL_FAILED_FIZZLE);
1829 return;
1831 break;
1833 case SPELLFAMILY_PRIEST:
1835 // Penance
1836 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1838 if (!unitTarget)
1839 return;
1841 int hurt = 0;
1842 int heal = 0;
1843 switch(m_spellInfo->Id)
1845 case 47540: hurt = 47758; heal = 47757; break;
1846 case 53005: hurt = 53001; heal = 52986; break;
1847 case 53006: hurt = 53002; heal = 52987; break;
1848 case 53007: hurt = 53003; heal = 52988; break;
1849 default:
1850 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1851 return;
1854 // prevent interrupted message for main spell
1855 finish(true);
1857 // replace cast by selected spell, this also make it interruptible including target death case
1858 if (m_caster->IsFriendlyTo(unitTarget))
1859 m_caster->CastSpell(unitTarget, heal, false);
1860 else
1861 m_caster->CastSpell(unitTarget, hurt, false);
1863 return;
1865 break;
1867 case SPELLFAMILY_DRUID:
1869 // Starfall
1870 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100)
1872 //Shapeshifting into an animal form or mounting cancels the effect.
1873 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1875 if(m_triggeredByAuraSpell)
1876 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1877 return;
1880 //Any effect which causes you to lose control of your character will supress the starfall effect.
1881 if (m_caster->hasUnitState(UNIT_STAT_NO_FREE_MOVE))
1882 return;
1884 switch(m_spellInfo->Id)
1886 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1887 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1888 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1889 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1890 default:
1891 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1892 return;
1895 break;
1897 case SPELLFAMILY_ROGUE:
1899 switch(m_spellInfo->Id)
1901 case 5938: // Shiv
1903 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1904 return;
1906 Player *pCaster = ((Player*)m_caster);
1908 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1909 if (!item)
1910 return;
1912 // all poison enchantments is temporary
1913 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1914 if (!enchant_id)
1915 return;
1917 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1918 if (!pEnchant)
1919 return;
1921 for (int s = 0; s < 3; ++s)
1923 if (pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1924 continue;
1926 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1927 if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1928 continue;
1930 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1933 m_caster->CastSpell(unitTarget, 5940, true);
1934 return;
1936 case 14185: // Preparation
1938 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1939 return;
1941 //immediately finishes the cooldown on certain Rogue abilities
1942 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1943 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1945 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1947 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1948 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1949 else
1950 ++itr;
1952 return;
1954 case 31231: // Cheat Death
1956 m_caster->CastSpell(m_caster, 45182, true);
1957 return;
1960 break;
1962 case SPELLFAMILY_HUNTER:
1964 // Steady Shot
1965 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1967 if (!unitTarget || !unitTarget->isAlive())
1968 return;
1970 bool found = false;
1972 // check dazed affect
1973 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1974 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1976 if ((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1978 found = true;
1979 break;
1983 if (found)
1984 m_damage+= damage;
1985 return;
1988 // Disengage
1989 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000400000000000))
1991 Unit* target = unitTarget;
1992 uint32 spellid;
1993 switch(m_spellInfo->Id)
1995 case 57635: spellid = 57636; break; // one from creature cases
1996 case 61507: spellid = 61508; break; // one from creature cases
1997 default:
1998 sLog.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo->Id);
1999 return;
2001 if (!target || !target->isAlive())
2002 return;
2003 m_caster->CastSpell(target,spellid,true,NULL);
2006 switch(m_spellInfo->Id)
2008 case 23989: // Readiness talent
2010 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2011 return;
2013 //immediately finishes the cooldown for hunter abilities
2014 const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
2015 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
2017 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2019 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
2020 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
2021 else
2022 ++itr;
2024 return;
2026 case 37506: // Scatter Shot
2028 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2029 return;
2031 // break Auto Shot and autohit
2032 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
2033 m_caster->AttackStop();
2034 ((Player*)m_caster)->SendAttackSwingCancelAttack();
2035 return;
2037 // Last Stand
2038 case 53478:
2040 if (!unitTarget)
2041 return;
2042 int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3);
2043 unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
2044 return;
2046 // Master's Call
2047 case 53271:
2049 Pet* pet = m_caster->GetPet();
2050 if (!pet || !unitTarget)
2051 return;
2053 pet->CastSpell(unitTarget, m_spellInfo->CalculateSimpleValue(eff_idx), true);
2054 return;
2057 break;
2059 case SPELLFAMILY_PALADIN:
2061 switch(m_spellInfo->SpellIconID)
2063 case 156: // Holy Shock
2065 if (!unitTarget)
2066 return;
2068 int hurt = 0;
2069 int heal = 0;
2071 switch(m_spellInfo->Id)
2073 case 20473: hurt = 25912; heal = 25914; break;
2074 case 20929: hurt = 25911; heal = 25913; break;
2075 case 20930: hurt = 25902; heal = 25903; break;
2076 case 27174: hurt = 27176; heal = 27175; break;
2077 case 33072: hurt = 33073; heal = 33074; break;
2078 case 48824: hurt = 48822; heal = 48820; break;
2079 case 48825: hurt = 48823; heal = 48821; break;
2080 default:
2081 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
2082 return;
2085 if (m_caster->IsFriendlyTo(unitTarget))
2086 m_caster->CastSpell(unitTarget, heal, true);
2087 else
2088 m_caster->CastSpell(unitTarget, hurt, true);
2090 return;
2092 case 561: // Judgement of command
2094 if (!unitTarget)
2095 return;
2097 uint32 spell_id = m_currentBasePoints[eff_idx]+1;
2098 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
2099 if (!spell_proto)
2100 return;
2102 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
2103 return;
2107 switch(m_spellInfo->Id)
2109 case 31789: // Righteous Defense (step 1)
2111 if (m_caster->GetTypeId() != TYPEID_PLAYER)
2113 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
2114 return;
2117 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
2118 Unit* friendTarget = !unitTarget || unitTarget->IsFriendlyTo(m_caster) ? unitTarget : unitTarget->getVictim();
2119 if (friendTarget)
2121 Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
2122 if (!player || !player->IsInSameRaidWith((Player*)m_caster))
2123 friendTarget = NULL;
2126 // non-standard cast requirement check
2127 if (!friendTarget || friendTarget->getAttackers().empty())
2129 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
2130 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
2131 return;
2134 // Righteous Defense (step 2) (in old version 31980 dummy effect)
2135 // Clear targets for eff 1
2136 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2137 ihit->effectMask &= ~(1<<1);
2139 // not empty (checked), copy
2140 Unit::AttackerSet attackers = friendTarget->getAttackers();
2142 // selected from list 3
2143 for(uint32 i = 0; i < std::min(size_t(3),attackers.size()); ++i)
2145 Unit::AttackerSet::iterator aItr = attackers.begin();
2146 std::advance(aItr, rand() % attackers.size());
2147 AddUnitTarget((*aItr), EFFECT_INDEX_1);
2148 attackers.erase(aItr);
2151 // now let next effect cast spell at each target.
2152 return;
2154 case 37877: // Blessing of Faith
2156 if (!unitTarget)
2157 return;
2159 uint32 spell_id = 0;
2160 switch(unitTarget->getClass())
2162 case CLASS_DRUID: spell_id = 37878; break;
2163 case CLASS_PALADIN: spell_id = 37879; break;
2164 case CLASS_PRIEST: spell_id = 37880; break;
2165 case CLASS_SHAMAN: spell_id = 37881; break;
2166 default: return; // ignore for not healing classes
2169 m_caster->CastSpell(m_caster, spell_id, true);
2170 return;
2173 break;
2175 case SPELLFAMILY_SHAMAN:
2177 // Cleansing Totem
2178 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
2180 if (unitTarget)
2181 m_caster->CastSpell(unitTarget, 52025, true);
2182 return;
2184 // Healing Stream Totem
2185 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
2187 if (unitTarget)
2189 if (Unit *owner = m_caster->GetOwner())
2191 // Restorative Totems
2192 Unit::AuraList const& mDummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
2193 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2194 // only its have dummy with specific icon
2195 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (*i)->GetSpellProto()->SpellIconID == 338)
2196 damage += (*i)->GetModifier()->m_amount * damage / 100;
2198 // Glyph of Healing Stream Totem
2199 if (Aura *dummy = owner->GetDummyAura(55456))
2200 damage += dummy->GetModifier()->m_amount * damage / 100;
2202 m_caster->CastCustomSpell(unitTarget, 52042, &damage, NULL, NULL, true, 0, 0, m_originalCasterGUID);
2204 return;
2206 // Mana Spring Totem
2207 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
2209 if (!unitTarget || unitTarget->getPowerType()!=POWER_MANA)
2210 return;
2211 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
2212 return;
2214 if (m_spellInfo->Id == 39610) // Mana Tide Totem effect
2216 if (!unitTarget || unitTarget->getPowerType() != POWER_MANA)
2217 return;
2218 // Glyph of Mana Tide
2219 if (Unit *owner = m_caster->GetOwner())
2220 if (Aura *dummy = owner->GetDummyAura(55441))
2221 damage+=dummy->GetModifier()->m_amount;
2222 // Regenerate 6% of Total Mana Every 3 secs
2223 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
2224 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
2225 return;
2227 // Lava Lash
2228 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
2230 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2231 return;
2232 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
2233 if (item)
2235 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
2236 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2237 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
2239 if ((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
2240 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
2241 (*itr)->GetCastItemGUID() == item->GetGUID())
2243 m_damage += m_damage * damage / 100;
2244 return;
2248 return;
2250 // Fire Nova
2251 if (m_spellInfo->SpellIconID == 33)
2253 // fire totems slot
2254 Totem* totem = m_caster->GetTotem(TOTEM_SLOT_FIRE);
2255 if (!totem)
2256 return;
2258 uint32 triggered_spell_id;
2259 switch(m_spellInfo->Id)
2261 case 1535: triggered_spell_id = 8349; break;
2262 case 8498: triggered_spell_id = 8502; break;
2263 case 8499: triggered_spell_id = 8503; break;
2264 case 11314: triggered_spell_id = 11306; break;
2265 case 11315: triggered_spell_id = 11307; break;
2266 case 25546: triggered_spell_id = 25535; break;
2267 case 25547: triggered_spell_id = 25537; break;
2268 case 61649: triggered_spell_id = 61650; break;
2269 case 61657: triggered_spell_id = 61654; break;
2270 default: return;
2273 totem->CastSpell(totem, triggered_spell_id, true, NULL, NULL, m_caster->GetGUID());
2275 // Fire Nova Visual
2276 totem->CastSpell(totem, 19823, true, NULL, NULL, m_caster->GetGUID());
2277 return;
2279 break;
2281 case SPELLFAMILY_DEATHKNIGHT:
2283 // Death Coil
2284 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
2286 if (m_caster->IsFriendlyTo(unitTarget))
2288 if (unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
2289 return;
2291 int32 bp = int32(damage * 1.5f);
2292 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
2294 else
2296 int32 bp = damage;
2297 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
2299 return;
2301 // Hungering Cold
2302 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000100000000000))
2304 m_caster->CastSpell(m_caster, 51209, true);
2305 return;
2307 // Death Strike
2308 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
2310 uint32 count = 0;
2311 Unit::AuraMap const& auras = unitTarget->GetAuras();
2312 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2314 if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
2315 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
2316 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
2318 ++count;
2319 // max. 15%
2320 if (count == 3)
2321 break;
2325 int32 bp = int32(count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[EFFECT_INDEX_0] / 100);
2327 // Improved Death Strike (percent stored in not existed EFFECT_INDEX_2 effect base points)
2328 Unit::AuraList const& auraMod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
2329 for(Unit::AuraList::const_iterator iter = auraMod.begin(); iter != auraMod.end(); ++iter)
2331 // only required spell have spellicon for SPELL_AURA_ADD_FLAT_MODIFIER
2332 if ((*iter)->GetSpellProto()->SpellIconID == 2751 && (*iter)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
2334 bp += (*iter)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2) * bp / 100;
2335 break;
2339 m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
2340 return;
2342 break;
2346 // pet auras
2347 if (PetAura const* petSpell = sSpellMgr.GetPetAura(m_spellInfo->Id, eff_idx))
2349 m_caster->AddPetAura(petSpell);
2350 return;
2353 // Script based implementation. Must be used only for not good for implementation in core spell effects
2354 // So called only for not processed cases
2355 if (gameObjTarget)
2356 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, eff_idx, gameObjTarget);
2357 else if (unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
2358 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, eff_idx, (Creature*)unitTarget);
2359 else if (itemTarget)
2360 Script->EffectDummyItem(m_caster, m_spellInfo->Id, eff_idx, itemTarget);
2363 void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx)
2365 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2367 // normal case
2368 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2370 if(!spellInfo)
2372 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2373 return;
2376 int32 bp = damage;
2377 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
2380 void Spell::EffectTriggerRitualOfSummoning(SpellEffectIndex eff_idx)
2382 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2383 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2385 if(!spellInfo)
2387 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2388 return;
2391 finish();
2393 m_caster->CastSpell(unitTarget,spellInfo,false);
2396 void Spell::EffectForceCast(SpellEffectIndex eff_idx)
2398 if( !unitTarget )
2399 return;
2401 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[eff_idx];
2403 // normal case
2404 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2406 if(!spellInfo)
2408 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2409 return;
2412 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
2415 void Spell::EffectTriggerSpell(SpellEffectIndex effIndex)
2417 // only unit case known
2418 if (!unitTarget)
2420 if(gameObjTarget || itemTarget)
2421 sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
2422 return;
2425 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2427 // special cases
2428 switch(triggered_spell_id)
2430 // Vanish (not exist)
2431 case 18461:
2433 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2434 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2435 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
2437 // if this spell is given to NPC it must handle rest by it's own AI
2438 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2439 return;
2441 // get highest rank of the Stealth spell
2442 uint32 spellId = 0;
2443 const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
2444 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2446 // only highest rank is shown in spell book, so simply check if shown in spell book
2447 if (!itr->second.active || itr->second.disabled || itr->second.state == PLAYERSPELL_REMOVED)
2448 continue;
2450 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2451 if (!spellInfo)
2452 continue;
2454 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
2456 spellId = spellInfo->Id;
2457 break;
2461 // no Stealth spell found
2462 if (!spellId)
2463 return;
2465 // reset cooldown on it if needed
2466 if (((Player*)unitTarget)->HasSpellCooldown(spellId))
2467 ((Player*)unitTarget)->RemoveSpellCooldown(spellId);
2469 m_caster->CastSpell(unitTarget, spellId, true);
2470 return;
2472 // just skip
2473 case 23770: // Sayge's Dark Fortune of *
2474 // not exist, common cooldown can be implemented in scripts if need.
2475 return;
2476 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2477 case 29284:
2479 // Brittle Armor
2480 SpellEntry const* spell = sSpellStore.LookupEntry(24575);
2481 if (!spell)
2482 return;
2484 for (uint32 j=0; j < spell->StackAmount; ++j)
2485 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2486 return;
2488 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2489 case 29286:
2491 // Mercurial Shield
2492 SpellEntry const* spell = sSpellStore.LookupEntry(26464);
2493 if (!spell)
2494 return;
2496 for (uint32 j=0; j < spell->StackAmount; ++j)
2497 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2498 return;
2500 // Righteous Defense
2501 case 31980:
2503 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
2504 return;
2506 // Cloak of Shadows
2507 case 35729:
2509 Unit::AuraMap& Auras = unitTarget->GetAuras();
2510 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2512 // remove all harmful spells on you...
2513 if( // ignore positive and passive auras
2514 !iter->second->IsPositive() && !iter->second->IsPassive() &&
2515 // ignore physical auras
2516 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
2518 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
2519 iter = Auras.begin();
2522 return;
2524 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2525 case 41967:
2527 if (Unit *pet = unitTarget->GetPet())
2528 pet->CastSpell(pet, 28305, true);
2529 return;
2533 // normal case
2534 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2535 if (!spellInfo)
2537 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2538 return;
2541 // select formal caster for triggered spell
2542 Unit* caster = m_caster;
2544 // some triggered spells require specific equipment
2545 if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
2547 // main hand weapon required
2548 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
2550 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK, true, false);
2552 // skip spell if no weapon in slot or broken
2553 if (!item)
2554 return;
2556 // skip spell if weapon not fit to triggered spell
2557 if (!item->IsFitToSpellRequirements(spellInfo))
2558 return;
2561 // offhand hand weapon required
2562 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
2564 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, false);
2566 // skip spell if no weapon in slot or broken
2567 if (!item)
2568 return;
2570 // skip spell if weapon not fit to triggered spell
2571 if (!item->IsFitToSpellRequirements(spellInfo))
2572 return;
2575 else
2577 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2578 // so this just for speedup places in else
2579 caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
2582 caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
2585 void Spell::EffectTriggerMissileSpell(SpellEffectIndex effect_idx)
2587 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2589 // normal case
2590 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2592 if(!spellInfo)
2594 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2595 m_spellInfo->Id,effect_idx,triggered_spell_id);
2596 return;
2599 if (m_CastItem)
2600 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2602 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2605 void Spell::EffectJump(SpellEffectIndex eff_idx)
2607 if(m_caster->isInFlight())
2608 return;
2610 // Init dest coordinates
2611 float x,y,z,o;
2612 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2614 x = m_targets.m_destX;
2615 y = m_targets.m_destY;
2616 z = m_targets.m_destZ;
2618 if(m_spellInfo->EffectImplicitTargetA[eff_idx] == TARGET_BEHIND_VICTIM)
2620 // explicit cast data from client or server-side cast
2621 // some spell at client send caster
2622 Unit* pTarget = NULL;
2623 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2624 pTarget = m_targets.getUnitTarget();
2625 else if(unitTarget->getVictim())
2626 pTarget = m_caster->getVictim();
2627 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2628 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2630 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2632 else
2633 o = m_caster->GetOrientation();
2635 else if(unitTarget)
2637 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2638 o = m_caster->GetOrientation();
2640 else if(gameObjTarget)
2642 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2643 o = m_caster->GetOrientation();
2645 else
2647 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2648 return;
2651 m_caster->NearTeleportTo(x, y, z, o, true);
2654 void Spell::EffectTeleportUnits(SpellEffectIndex eff_idx)
2656 if(!unitTarget || unitTarget->isInFlight())
2657 return;
2659 switch (m_spellInfo->EffectImplicitTargetB[eff_idx])
2661 case TARGET_INNKEEPER_COORDINATES:
2663 // Only players can teleport to innkeeper
2664 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2665 return;
2667 ((Player*)unitTarget)->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
2668 return;
2670 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2671 case TARGET_TABLE_X_Y_Z_COORDINATES:
2673 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
2674 if(!st)
2676 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2677 return;
2680 if(st->target_mapId==unitTarget->GetMapId())
2681 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2682 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2683 ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0);
2684 break;
2686 case TARGET_BEHIND_VICTIM:
2688 Unit *pTarget = NULL;
2690 // explicit cast data from client or server-side cast
2691 // some spell at client send caster
2692 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2693 pTarget = m_targets.getUnitTarget();
2694 else if(unitTarget->getVictim())
2695 pTarget = unitTarget->getVictim();
2696 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2697 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2699 // Init dest coordinates
2700 float x = m_targets.m_destX;
2701 float y = m_targets.m_destY;
2702 float z = m_targets.m_destZ;
2703 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2704 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2705 return;
2707 default:
2709 // If not exist data for dest location - return
2710 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2712 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", eff_idx, m_spellInfo->EffectImplicitTargetB[eff_idx], m_spellInfo->Id );
2713 return;
2715 // Init dest coordinates
2716 float x = m_targets.m_destX;
2717 float y = m_targets.m_destY;
2718 float z = m_targets.m_destZ;
2719 float orientation = unitTarget->GetOrientation();
2720 // Teleport
2721 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2722 return;
2726 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2727 switch ( m_spellInfo->Id )
2729 // Dimensional Ripper - Everlook
2730 case 23442:
2732 int32 r = irand(0, 119);
2733 if ( r >= 70 ) // 7/12 success
2735 if ( r < 100 ) // 4/12 evil twin
2736 m_caster->CastSpell(m_caster, 23445, true);
2737 else // 1/12 fire
2738 m_caster->CastSpell(m_caster, 23449, true);
2740 return;
2742 // Ultrasafe Transporter: Toshley's Station
2743 case 36941:
2745 if ( roll_chance_i(50) ) // 50% success
2747 int32 rand_eff = urand(1, 7);
2748 switch ( rand_eff )
2750 case 1:
2751 // soul split - evil
2752 m_caster->CastSpell(m_caster, 36900, true);
2753 break;
2754 case 2:
2755 // soul split - good
2756 m_caster->CastSpell(m_caster, 36901, true);
2757 break;
2758 case 3:
2759 // Increase the size
2760 m_caster->CastSpell(m_caster, 36895, true);
2761 break;
2762 case 4:
2763 // Decrease the size
2764 m_caster->CastSpell(m_caster, 36893, true);
2765 break;
2766 case 5:
2767 // Transform
2769 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2770 m_caster->CastSpell(m_caster, 36897, true);
2771 else
2772 m_caster->CastSpell(m_caster, 36899, true);
2773 break;
2775 case 6:
2776 // chicken
2777 m_caster->CastSpell(m_caster, 36940, true);
2778 break;
2779 case 7:
2780 // evil twin
2781 m_caster->CastSpell(m_caster, 23445, true);
2782 break;
2785 return;
2787 // Dimensional Ripper - Area 52
2788 case 36890:
2790 if ( roll_chance_i(50) ) // 50% success
2792 int32 rand_eff = urand(1, 4);
2793 switch ( rand_eff )
2795 case 1:
2796 // soul split - evil
2797 m_caster->CastSpell(m_caster, 36900, true);
2798 break;
2799 case 2:
2800 // soul split - good
2801 m_caster->CastSpell(m_caster, 36901, true);
2802 break;
2803 case 3:
2804 // Increase the size
2805 m_caster->CastSpell(m_caster, 36895, true);
2806 break;
2807 case 4:
2808 // Transform
2810 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2811 m_caster->CastSpell(m_caster, 36897, true);
2812 else
2813 m_caster->CastSpell(m_caster, 36899, true);
2814 break;
2818 return;
2823 void Spell::EffectApplyAura(SpellEffectIndex eff_idx)
2825 if(!unitTarget)
2826 return;
2828 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2829 if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) &&
2830 (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2831 return;
2833 Unit* caster = GetAffectiveCaster();
2834 if(!caster)
2836 // FIXME: currently we can't have auras applied explIcitly by gameobjects
2837 // so for auras from wild gameobjects (no owner) target used
2838 if (IS_GAMEOBJECT_GUID(m_originalCasterGUID))
2839 caster = unitTarget;
2840 else
2841 return;
2844 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]);
2846 Aura* Aur = CreateAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, caster, m_CastItem);
2848 // Now Reduce spell duration using data received at spell hit
2849 int32 duration = Aur->GetAuraMaxDuration();
2850 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
2851 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
2852 Aur->setDiminishGroup(m_diminishGroup);
2854 // if Aura removed and deleted, do not continue.
2855 if(duration== 0 && !(Aur->IsPermanent()))
2857 delete Aur;
2858 return;
2861 if(duration != Aur->GetAuraMaxDuration())
2863 Aur->SetAuraMaxDuration(duration);
2864 Aur->SetAuraDuration(duration);
2867 unitTarget->AddAura(Aur);
2870 void Spell::EffectUnlearnSpecialization(SpellEffectIndex eff_idx)
2872 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2873 return;
2875 Player *_player = (Player*)unitTarget;
2876 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[eff_idx];
2878 _player->removeSpell(spellToUnlearn);
2880 sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2883 void Spell::EffectPowerDrain(SpellEffectIndex eff_idx)
2885 if(m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
2886 return;
2888 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
2890 if(!unitTarget)
2891 return;
2892 if(!unitTarget->isAlive())
2893 return;
2894 if(unitTarget->getPowerType() != drain_power)
2895 return;
2896 if(damage < 0)
2897 return;
2899 uint32 curPower = unitTarget->GetPower(drain_power);
2901 //add spell damage bonus
2902 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2904 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2905 uint32 power = damage;
2906 if (drain_power == POWER_MANA)
2907 power -= unitTarget->GetSpellCritDamageReduction(power);
2909 int32 new_damage;
2910 if(curPower < power)
2911 new_damage = curPower;
2912 else
2913 new_damage = power;
2915 unitTarget->ModifyPower(drain_power,-new_damage);
2917 // Don`t restore from self drain
2918 if(drain_power == POWER_MANA && m_caster != unitTarget)
2920 float manaMultiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2921 if(manaMultiplier==0)
2922 manaMultiplier = 1;
2924 if(Player *modOwner = m_caster->GetSpellModOwner())
2925 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2927 int32 gain = int32(new_damage * manaMultiplier);
2929 m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2933 void Spell::EffectSendEvent(SpellEffectIndex effectIndex)
2936 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2938 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[effectIndex], m_spellInfo->Id);
2939 m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[effectIndex], m_caster, focusObject);
2942 void Spell::EffectPowerBurn(SpellEffectIndex eff_idx)
2944 if (m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
2945 return;
2947 Powers powertype = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
2949 if (!unitTarget)
2950 return;
2951 if (!unitTarget->isAlive())
2952 return;
2953 if (unitTarget->getPowerType()!=powertype)
2954 return;
2955 if (damage < 0)
2956 return;
2958 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2959 if (m_spellInfo->ManaCostPercentage)
2961 int32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2962 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2963 if(damage > maxdamage)
2964 damage = maxdamage;
2967 int32 curPower = int32(unitTarget->GetPower(powertype));
2969 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2970 int32 power = damage;
2971 if (powertype == POWER_MANA)
2972 power -= unitTarget->GetSpellCritDamageReduction(power);
2974 int32 new_damage = (curPower < power) ? curPower : power;
2976 unitTarget->ModifyPower(powertype, -new_damage);
2977 float multiplier = m_spellInfo->EffectMultipleValue[eff_idx];
2979 if (Player *modOwner = m_caster->GetSpellModOwner())
2980 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2982 new_damage = int32(new_damage * multiplier);
2983 m_damage += new_damage;
2986 void Spell::EffectHeal(SpellEffectIndex /*eff_idx*/)
2988 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2990 // Try to get original caster
2991 Unit *caster = GetAffectiveCaster();
2992 if (!caster)
2993 return;
2995 int32 addhealth = damage;
2997 // Seal of Light proc
2998 if (m_spellInfo->Id == 20167)
3000 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
3001 int32 holy = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellInfo)) +
3002 caster->SpellBaseHealingBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
3003 addhealth += int32(ap * 0.15) + int32(holy * 15 / 100);
3005 // Vessel of the Naaru (Vial of the Sunwell trinket)
3006 else if (m_spellInfo->Id == 45064)
3008 // Amount of heal - depends from stacked Holy Energy
3009 int damageAmount = 0;
3010 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
3011 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
3012 if ((*i)->GetId() == 45062)
3013 damageAmount+=(*i)->GetModifier()->m_amount;
3014 if (damageAmount)
3015 m_caster->RemoveAurasDueToSpell(45062);
3017 addhealth += damageAmount;
3019 // Death Pact (percent heal)
3020 else if (m_spellInfo->Id==48743)
3021 addhealth = addhealth * unitTarget->GetMaxHealth() / 100;
3022 // Swiftmend - consumes Regrowth or Rejuvenation
3023 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
3025 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
3026 // find most short by duration
3027 Aura *targetAura = NULL;
3028 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
3030 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
3031 // Regrowth or Rejuvenation 0x40 | 0x10
3032 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000050)))
3034 if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
3035 targetAura = *i;
3039 if (!targetAura)
3041 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
3042 return;
3044 int idx = 0;
3045 while(idx < 3)
3047 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
3048 break;
3049 idx++;
3052 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
3053 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
3055 // Glyph of Swiftmend
3056 if (!caster->HasAura(54824))
3057 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
3059 addhealth += tickheal * tickcount;
3061 else
3062 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
3064 m_healing+=addhealth;
3068 void Spell::EffectHealPct(SpellEffectIndex /*eff_idx*/)
3070 if (unitTarget && unitTarget->isAlive() && damage >= 0)
3072 // Try to get original caster
3073 Unit *caster = GetAffectiveCaster();
3074 if (!caster)
3075 return;
3077 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
3078 if (Player* modOwner = m_caster->GetSpellModOwner())
3079 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
3081 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
3082 unitTarget->getHostileRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
3086 void Spell::EffectHealMechanical(SpellEffectIndex /*eff_idx*/)
3088 // Mechanic creature type should be correctly checked by targetCreatureType field
3089 if (unitTarget && unitTarget->isAlive() && damage >= 0)
3091 // Try to get original caster
3092 Unit *caster = GetAffectiveCaster();
3093 if (!caster)
3094 return;
3096 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, damage, HEAL);
3097 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
3101 void Spell::EffectHealthLeech(SpellEffectIndex eff_idx)
3103 if (!unitTarget)
3104 return;
3105 if (!unitTarget->isAlive())
3106 return;
3108 if (damage < 0)
3109 return;
3111 sLog.outDebug("HealthLeech :%i", damage);
3113 uint32 curHealth = unitTarget->GetHealth();
3114 damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage );
3115 if ((int32)curHealth < damage)
3116 damage = curHealth;
3118 float multiplier = m_spellInfo->EffectMultipleValue[eff_idx];
3120 if (Player *modOwner = m_caster->GetSpellModOwner())
3121 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
3123 int32 heal = int32(damage*multiplier);
3124 if (m_caster->isAlive())
3126 heal = m_caster->SpellHealingBonus(m_caster, m_spellInfo, heal, HEAL);
3127 m_caster->DealHeal(m_caster, heal, m_spellInfo);
3131 void Spell::DoCreateItem(SpellEffectIndex eff_idx, uint32 itemtype)
3133 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3134 return;
3136 Player* player = (Player*)unitTarget;
3138 uint32 newitemid = itemtype;
3139 ItemPrototype const *pProto = ObjectMgr::GetItemPrototype( newitemid );
3140 if(!pProto)
3142 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
3143 return;
3146 // bg reward have some special in code work
3147 uint32 bgType = 0;
3148 switch(m_spellInfo->Id)
3150 case SPELL_AV_MARK_WINNER:
3151 case SPELL_AV_MARK_LOSER:
3152 bgType = BATTLEGROUND_AV;
3153 break;
3154 case SPELL_WS_MARK_WINNER:
3155 case SPELL_WS_MARK_LOSER:
3156 bgType = BATTLEGROUND_WS;
3157 break;
3158 case SPELL_AB_MARK_WINNER:
3159 case SPELL_AB_MARK_LOSER:
3160 bgType = BATTLEGROUND_AB;
3161 break;
3162 default:
3163 break;
3166 uint32 num_to_add;
3168 // TODO: maybe all this can be replaced by using correct calculated `damage` value
3169 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
3171 int32 basePoints = m_currentBasePoints[eff_idx];
3172 int32 randomPoints = m_spellInfo->EffectDieSides[eff_idx];
3173 if (randomPoints)
3174 num_to_add = basePoints + irand(1, randomPoints);
3175 else
3176 num_to_add = basePoints + 1;
3178 else if (pProto->MaxCount == 1)
3179 num_to_add = 1;
3180 else if(player->getLevel() >= m_spellInfo->spellLevel)
3182 int32 basePoints = m_currentBasePoints[eff_idx];
3183 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[eff_idx];
3184 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
3186 else
3187 num_to_add = 2;
3189 if (num_to_add < 1)
3190 num_to_add = 1;
3191 if (num_to_add > pProto->GetMaxStackSize())
3192 num_to_add = pProto->GetMaxStackSize();
3194 // init items_count to 1, since 1 item will be created regardless of specialization
3195 int items_count=1;
3196 // the chance to create additional items
3197 float additionalCreateChance=0.0f;
3198 // the maximum number of created additional items
3199 uint8 additionalMaxNum=0;
3200 // get the chance and maximum number for creating extra items
3201 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
3203 // roll with this chance till we roll not to create or we create the max num
3204 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
3205 ++items_count;
3208 // really will be created more items
3209 num_to_add *= items_count;
3211 // can the player store the new item?
3212 ItemPosCountVec dest;
3213 uint32 no_space = 0;
3214 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
3215 if( msg != EQUIP_ERR_OK )
3217 // convert to possible store amount
3218 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
3219 num_to_add -= no_space;
3220 else
3222 // ignore mana gem case (next effect will recharge existed example)
3223 if (eff_idx == EFFECT_INDEX_0 && m_spellInfo->Effect[EFFECT_INDEX_1] == SPELL_EFFECT_DUMMY )
3224 return;
3226 // if not created by another reason from full inventory or unique items amount limitation
3227 player->SendEquipError( msg, NULL, NULL, newitemid );
3228 return;
3232 if(num_to_add)
3234 // create the new item and store it
3235 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
3237 // was it successful? return error if not
3238 if(!pItem)
3240 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
3241 return;
3244 // set the "Crafted by ..." property of the item
3245 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
3246 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
3248 // send info to the client
3249 if(pItem)
3250 player->SendNewItem(pItem, num_to_add, true, bgType == 0);
3252 // we succeeded in creating at least one item, so a levelup is possible
3253 if(bgType == 0)
3254 player->UpdateCraftSkill(m_spellInfo->Id);
3257 // for battleground marks send by mail if not add all expected
3258 if(no_space > 0 && bgType)
3260 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
3261 bg->SendRewardMarkByMail(player, newitemid, no_space);
3265 void Spell::EffectCreateItem(SpellEffectIndex eff_idx)
3267 DoCreateItem(eff_idx,m_spellInfo->EffectItemType[eff_idx]);
3270 void Spell::EffectCreateItem2(SpellEffectIndex eff_idx)
3272 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
3273 return;
3274 Player* player = (Player*)m_caster;
3276 uint32 item_id = m_spellInfo->EffectItemType[eff_idx];
3278 DoCreateItem(eff_idx, item_id);
3280 // special case: fake item replaced by generate using spell_loot_template
3281 if (IsLootCraftingSpell(m_spellInfo))
3283 if (!player->HasItemCount(item_id, 1))
3284 return;
3286 // remove reagent
3287 uint32 count = 1;
3288 player->DestroyItemCount(item_id, count, true);
3290 // create some random items
3291 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
3295 void Spell::EffectCreateRandomItem(SpellEffectIndex /*eff_idx*/)
3297 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
3298 return;
3299 Player* player = (Player*)m_caster;
3301 // create some random items
3302 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
3305 void Spell::EffectPersistentAA(SpellEffectIndex eff_idx)
3307 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
3309 if (Player* modOwner = m_caster->GetSpellModOwner())
3310 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
3312 int32 duration = GetSpellDuration(m_spellInfo);
3313 DynamicObject* dynObj = new DynamicObject;
3314 if (!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, eff_idx, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
3316 delete dynObj;
3317 return;
3319 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3320 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
3321 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
3322 m_caster->AddDynObject(dynObj);
3323 m_caster->GetMap()->Add(dynObj);
3326 void Spell::EffectEnergize(SpellEffectIndex eff_idx)
3328 if(!unitTarget)
3329 return;
3330 if(!unitTarget->isAlive())
3331 return;
3333 if(m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
3334 return;
3336 Powers power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
3338 // Some level depends spells
3339 int level_multiplier = 0;
3340 int level_diff = 0;
3341 switch (m_spellInfo->Id)
3343 case 9512: // Restore Energy
3344 level_diff = m_caster->getLevel() - 40;
3345 level_multiplier = 2;
3346 break;
3347 case 24571: // Blood Fury
3348 level_diff = m_caster->getLevel() - 60;
3349 level_multiplier = 10;
3350 break;
3351 case 24532: // Burst of Energy
3352 level_diff = m_caster->getLevel() - 60;
3353 level_multiplier = 4;
3354 break;
3355 case 31930: // Judgements of the Wise
3356 case 48542: // Revitalize (mana restore case)
3357 case 63375: // Improved Stormstrike
3358 damage = damage * unitTarget->GetCreateMana() / 100;
3359 break;
3360 default:
3361 break;
3364 if (level_diff > 0)
3365 damage -= level_multiplier * level_diff;
3367 if(damage < 0)
3368 return;
3370 if(unitTarget->GetMaxPower(power) == 0)
3371 return;
3373 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
3375 // Mad Alchemist's Potion
3376 if (m_spellInfo->Id == 45051)
3378 // find elixirs on target
3379 uint32 elixir_mask = 0;
3380 Unit::AuraMap& Auras = unitTarget->GetAuras();
3381 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
3383 uint32 spell_id = itr->second->GetId();
3384 if(uint32 mask = sSpellMgr.GetSpellElixirMask(spell_id))
3385 elixir_mask |= mask;
3388 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3389 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
3391 // get all available elixirs by mask and spell level
3392 std::vector<uint32> elixirs;
3393 SpellElixirMap const& m_spellElixirs = sSpellMgr.GetSpellElixirMap();
3394 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
3396 if (itr->second & elixir_mask)
3398 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
3399 continue;
3401 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
3402 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
3403 continue;
3405 elixirs.push_back(itr->first);
3409 if (!elixirs.empty())
3411 // cast random elixir on target
3412 uint32 rand_spell = urand(0,elixirs.size()-1);
3413 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
3418 void Spell::EffectEnergisePct(SpellEffectIndex eff_idx)
3420 if (!unitTarget)
3421 return;
3422 if (!unitTarget->isAlive())
3423 return;
3425 if (m_spellInfo->EffectMiscValue[eff_idx] < 0 || m_spellInfo->EffectMiscValue[eff_idx] >= MAX_POWERS)
3426 return;
3428 Powers power = Powers(m_spellInfo->EffectMiscValue[eff_idx]);
3430 uint32 maxPower = unitTarget->GetMaxPower(power);
3431 if (maxPower == 0)
3432 return;
3434 uint32 gain = damage * maxPower / 100;
3435 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
3438 void Spell::SendLoot(uint64 guid, LootType loottype)
3440 if (gameObjTarget)
3442 switch (gameObjTarget->GetGoType())
3444 case GAMEOBJECT_TYPE_DOOR:
3445 case GAMEOBJECT_TYPE_BUTTON:
3446 case GAMEOBJECT_TYPE_QUESTGIVER:
3447 case GAMEOBJECT_TYPE_SPELL_FOCUS:
3448 case GAMEOBJECT_TYPE_GOOBER:
3449 gameObjTarget->Use(m_caster);
3450 return;
3452 case GAMEOBJECT_TYPE_CHEST:
3453 gameObjTarget->Use(m_caster);
3454 // Don't return, let loots been taken
3455 break;
3457 default:
3458 sLog.outError("Spell::SendLoot unhandled GameObject type %u (entry %u).", gameObjTarget->GetGoType(), gameObjTarget->GetEntry());
3459 return;
3463 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3464 return;
3466 // Send loot
3467 ((Player*)m_caster)->SendLoot(guid, loottype);
3470 void Spell::EffectOpenLock(SpellEffectIndex eff_idx)
3472 if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
3474 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
3475 return;
3478 Player* player = (Player*)m_caster;
3480 uint32 lockId = 0;
3481 uint64 guid = 0;
3483 // Get lockId
3484 if (gameObjTarget)
3486 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3487 // Arathi Basin banner opening !
3488 if (goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
3489 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK)
3491 //CanUseBattleGroundObject() already called in CheckCast()
3492 // in battleground check
3493 if (BattleGround *bg = player->GetBattleGround())
3495 // check if it's correct bg
3496 if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
3497 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3498 return;
3501 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
3503 //CanUseBattleGroundObject() already called in CheckCast()
3504 // in battleground check
3505 if (BattleGround *bg = player->GetBattleGround())
3507 if (bg->GetTypeID() == BATTLEGROUND_EY)
3508 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3509 return;
3512 lockId = goInfo->GetLockId();
3513 guid = gameObjTarget->GetGUID();
3515 else if (itemTarget)
3517 lockId = itemTarget->GetProto()->LockID;
3518 guid = itemTarget->GetGUID();
3520 else
3522 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3523 return;
3526 SkillType skillId = SKILL_NONE;
3527 int32 reqSkillValue = 0;
3528 int32 skillValue;
3530 SpellCastResult res = CanOpenLock(eff_idx, lockId, skillId, reqSkillValue, skillValue);
3531 if (res != SPELL_CAST_OK)
3533 SendCastResult(res);
3534 return;
3537 SendLoot(guid, LOOT_SKINNING);
3539 // not allow use skill grow at item base open
3540 if (!m_CastItem && skillId != SKILL_NONE)
3542 // update skill if really known
3543 if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3545 if (gameObjTarget)
3547 // Allow one skill-up until respawned
3548 if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
3549 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
3550 gameObjTarget->AddToSkillupList(player->GetGUIDLow());
3552 else if (itemTarget)
3554 // Do one skill-up
3555 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3561 void Spell::EffectSummonChangeItem(SpellEffectIndex eff_idx)
3563 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3564 return;
3566 Player *player = (Player*)m_caster;
3568 // applied only to using item
3569 if (!m_CastItem)
3570 return;
3572 // ... only to item in own inventory/bank/equip_slot
3573 if (m_CastItem->GetOwnerGUID()!=player->GetGUID())
3574 return;
3576 uint32 newitemid = m_spellInfo->EffectItemType[eff_idx];
3577 if (!newitemid)
3578 return;
3580 uint16 pos = m_CastItem->GetPos();
3582 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3583 if (!pNewItem)
3584 return;
3586 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3588 if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3589 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3592 if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3594 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3595 player->DurabilityLoss(pNewItem, loosePercent);
3598 if (player->IsInventoryPos(pos))
3600 ItemPosCountVec dest;
3601 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3602 if (msg == EQUIP_ERR_OK)
3604 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3606 // prevent crash at access and unexpected charges counting with item update queue corrupt
3607 if (m_CastItem==m_targets.getItemTarget())
3608 m_targets.setItemTarget(NULL);
3610 m_CastItem = NULL;
3612 player->StoreItem( dest, pNewItem, true);
3613 return;
3616 else if (player->IsBankPos (pos))
3618 ItemPosCountVec dest;
3619 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3620 if (msg == EQUIP_ERR_OK)
3622 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3624 // prevent crash at access and unexpected charges counting with item update queue corrupt
3625 if (m_CastItem==m_targets.getItemTarget())
3626 m_targets.setItemTarget(NULL);
3628 m_CastItem = NULL;
3630 player->BankItem( dest, pNewItem, true);
3631 return;
3634 else if (player->IsEquipmentPos (pos))
3636 uint16 dest;
3637 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3638 if (msg == EQUIP_ERR_OK)
3640 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3642 // prevent crash at access and unexpected charges counting with item update queue corrupt
3643 if (m_CastItem==m_targets.getItemTarget())
3644 m_targets.setItemTarget(NULL);
3646 m_CastItem = NULL;
3648 player->EquipItem( dest, pNewItem, true);
3649 player->AutoUnequipOffhandIfNeed();
3650 return;
3654 // fail
3655 delete pNewItem;
3658 void Spell::EffectProficiency(SpellEffectIndex /*eff_idx*/)
3660 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3661 return;
3662 Player *p_target = (Player*)unitTarget;
3664 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3665 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3667 p_target->AddWeaponProficiency(subClassMask);
3668 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3670 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3672 p_target->AddArmorProficiency(subClassMask);
3673 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3677 void Spell::EffectApplyAreaAura(SpellEffectIndex eff_idx)
3679 if (!unitTarget)
3680 return;
3681 if (!unitTarget->isAlive())
3682 return;
3684 AreaAura* Aur = new AreaAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, m_caster, m_CastItem);
3685 unitTarget->AddAura(Aur);
3688 void Spell::EffectSummonType(SpellEffectIndex eff_idx)
3690 uint32 prop_id = m_spellInfo->EffectMiscValueB[eff_idx];
3691 SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
3692 if(!summon_prop)
3694 sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
3695 return;
3698 switch(summon_prop->Group)
3700 // faction handled later on, or loaded from template
3701 case SUMMON_PROP_GROUP_WILD:
3702 case SUMMON_PROP_GROUP_FRIENDLY:
3704 switch(summon_prop->Type)
3706 case SUMMON_PROP_TYPE_OTHER:
3708 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3709 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3710 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3711 if(prop_id == 121 || prop_id == 647)
3712 DoSummonTotem(eff_idx);
3713 else
3714 DoSummonWild(eff_idx, summon_prop->FactionId);
3715 break;
3717 case SUMMON_PROP_TYPE_SUMMON:
3718 case SUMMON_PROP_TYPE_GUARDIAN:
3719 case SUMMON_PROP_TYPE_ARMY:
3720 case SUMMON_PROP_TYPE_DK:
3721 case SUMMON_PROP_TYPE_CONSTRUCT:
3723 // JC golems - 32804, etc -- fits much better totem AI
3724 if(m_spellInfo->SpellIconID == 2056)
3725 DoSummonTotem(eff_idx);
3726 if(prop_id == 832) // scrapbot
3727 DoSummonWild(eff_idx, summon_prop->FactionId);
3728 else
3729 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3730 break;
3732 case SUMMON_PROP_TYPE_TOTEM:
3733 DoSummonTotem(eff_idx, summon_prop->Slot);
3734 break;
3735 case SUMMON_PROP_TYPE_CRITTER:
3736 DoSummonCritter(eff_idx, summon_prop->FactionId);
3737 break;
3738 case SUMMON_PROP_TYPE_PHASING:
3739 case SUMMON_PROP_TYPE_LIGHTWELL:
3740 case SUMMON_PROP_TYPE_REPAIR_BOT:
3741 DoSummonWild(eff_idx, summon_prop->FactionId);
3742 break;
3743 case SUMMON_PROP_TYPE_SIEGE_VEH:
3744 case SUMMON_PROP_TYPE_DRAKE_VEH:
3745 // TODO
3746 // EffectSummonVehicle(i);
3747 break;
3748 default:
3749 sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
3750 break;
3752 break;
3754 case SUMMON_PROP_GROUP_PETS:
3756 // FIXME : multiple summons - not yet supported as pet
3757 //1562 - force of nature - sid 33831
3758 //1161 - feral spirit - sid 51533
3759 if(prop_id == 1562) // 3 uncontrolable instead of one controllable :/
3760 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3761 else
3762 DoSummon(eff_idx);
3763 break;
3765 case SUMMON_PROP_GROUP_CONTROLLABLE:
3767 // no type here
3768 // maybe wrong - but thats the handler currently used for those
3769 DoSummonGuardian(eff_idx, summon_prop->FactionId);
3770 break;
3772 case SUMMON_PROP_GROUP_VEHICLE:
3774 // TODO
3775 // EffectSummonVehicle(i);
3776 break;
3778 default:
3779 sLog.outError("EffectSummonType: Unhandled summon group type %u", summon_prop->Group);
3780 break;
3784 void Spell::DoSummon(SpellEffectIndex eff_idx)
3786 if (m_caster->GetPetGUID())
3787 return;
3789 if (!unitTarget)
3790 return;
3791 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
3792 if (!pet_entry)
3793 return;
3794 uint32 level = m_caster->getLevel();
3795 Pet* spawnCreature = new Pet(SUMMON_PET);
3797 int32 duration = GetSpellDuration(m_spellInfo);
3798 if(Player* modOwner = m_caster->GetSpellModOwner())
3799 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3801 if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3803 // Summon in dest location
3804 float x, y, z;
3805 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3807 x = m_targets.m_destX;
3808 y = m_targets.m_destY;
3809 z = m_targets.m_destZ;
3810 spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
3813 // set timer for unsummon
3814 if (duration > 0)
3815 spawnCreature->SetDuration(duration);
3817 return;
3820 Map *map = m_caster->GetMap();
3821 uint32 pet_number = sObjectMgr.GeneratePetNumber();
3822 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3823 m_spellInfo->EffectMiscValue[eff_idx], pet_number))
3825 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[eff_idx]);
3826 delete spawnCreature;
3827 return;
3830 // Summon in dest location
3831 float x, y, z;
3832 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3834 x = m_targets.m_destX;
3835 y = m_targets.m_destY;
3836 z = m_targets.m_destZ;
3838 else
3839 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3841 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3843 if (!spawnCreature->IsPositionValid())
3845 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3846 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3847 delete spawnCreature;
3848 return;
3851 // set timer for unsummon
3852 if (duration > 0)
3853 spawnCreature->SetDuration(duration);
3855 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3856 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3857 spawnCreature->setPowerType(POWER_MANA);
3858 spawnCreature->setFaction(m_caster->getFaction());
3859 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3860 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3861 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3862 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3863 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3864 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3865 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3866 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3868 spawnCreature->InitStatsForLevel(level, m_caster);
3870 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3872 spawnCreature->UpdateWalkMode(m_caster);
3874 spawnCreature->AIM_Initialize();
3875 spawnCreature->InitPetCreateSpells();
3876 spawnCreature->InitLevelupSpellsForLevel();
3877 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3878 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3880 std::string name = m_caster->GetName();
3881 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3882 spawnCreature->SetName( name );
3884 map->Add((Creature*)spawnCreature);
3886 m_caster->SetPet(spawnCreature);
3888 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3890 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3891 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3892 ((Player*)m_caster)->PetSpellInitialize();
3895 if (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
3896 ((Creature*)m_caster)->AI()->JustSummoned((Creature*)spawnCreature);
3899 void Spell::EffectLearnSpell(SpellEffectIndex eff_idx)
3901 if (!unitTarget)
3902 return;
3904 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3906 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3907 EffectLearnPetSpell(eff_idx);
3909 return;
3912 Player *player = (Player*)unitTarget;
3914 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[eff_idx];
3915 player->learnSpell(spellToLearn,false);
3917 sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3920 void Spell::EffectDispel(SpellEffectIndex eff_idx)
3922 if (!unitTarget)
3923 return;
3925 // Fill possible dispell list
3926 std::vector <Aura *> dispel_list;
3928 // Create dispel mask by dispel type
3929 uint32 dispel_type = m_spellInfo->EffectMiscValue[eff_idx];
3930 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3931 Unit::AuraMap const& auras = unitTarget->GetAuras();
3932 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3934 Aura *aur = (*itr).second;
3935 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3937 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3939 bool positive = true;
3940 if (!aur->IsPositive())
3941 positive = false;
3942 else
3943 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3945 // do not remove positive auras if friendly target
3946 // negative auras if non-friendly target
3947 if (positive == unitTarget->IsFriendlyTo(m_caster))
3948 continue;
3950 // Add aura to dispel list (all stack cases)
3951 for(int k = 0; k < aur->GetStackAmount(); ++k)
3952 dispel_list.push_back(aur);
3955 // Ok if exist some buffs for dispel try dispel it
3956 if (!dispel_list.empty())
3958 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3959 std::list < uint32 > fail_list; // spell_id
3961 // some spells have effect value = 0 and all from its by meaning expect 1
3962 if(!damage)
3963 damage = 1;
3965 // Dispell N = damage buffs (or while exist buffs for dispel)
3966 for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
3968 // Random select buff for dispel
3969 std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
3970 std::advance(dispel_itr,urand(0, dispel_list.size()-1));
3972 Aura *aur = *dispel_itr;
3974 // remove entry from dispel_list
3975 dispel_list.erase(dispel_itr);
3977 SpellEntry const* spellInfo = aur->GetSpellProto();
3978 // Base dispel chance
3979 // TODO: possible chance depend from spell level??
3980 int32 miss_chance = 0;
3981 // Apply dispel mod from aura caster
3982 if (Unit *caster = aur->GetCaster())
3984 if ( Player* modOwner = caster->GetSpellModOwner() )
3985 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3987 // Try dispel
3988 if (roll_chance_i(miss_chance))
3989 fail_list.push_back(spellInfo->Id);
3990 else
3991 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3993 // Send success log and really remove auras
3994 if (!success_list.empty())
3996 int32 count = success_list.size();
3997 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3998 data.append(unitTarget->GetPackGUID()); // Victim GUID
3999 data.append(m_caster->GetPackGUID()); // Caster GUID
4000 data << uint32(m_spellInfo->Id); // Dispel spell id
4001 data << uint8(0); // not used
4002 data << uint32(count); // count
4003 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
4005 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
4006 data << uint32(spellInfo->Id); // Spell Id
4007 data << uint8(0); // 0 - dispeled !=0 cleansed
4008 unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
4010 m_caster->SendMessageToSet(&data, true);
4012 // On success dispel
4013 // Devour Magic
4014 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
4016 int32 heal_amount = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
4017 m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
4020 // Send fail log to client
4021 if (!fail_list.empty())
4023 // Failed to dispell
4024 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
4025 data << uint64(m_caster->GetGUID()); // Caster GUID
4026 data << uint64(unitTarget->GetGUID()); // Victim GUID
4027 data << uint32(m_spellInfo->Id); // Dispell spell id
4028 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
4029 data << uint32(*j); // Spell Id
4030 m_caster->SendMessageToSet(&data, true);
4035 void Spell::EffectDualWield(SpellEffectIndex /*eff_idx*/)
4037 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
4038 ((Player*)unitTarget)->SetCanDualWield(true);
4041 void Spell::EffectPull(SpellEffectIndex /*eff_idx*/)
4043 // TODO: create a proper pull towards distract spell center for distract
4044 sLog.outDebug("WORLD: Spell Effect DUMMY");
4047 void Spell::EffectDistract(SpellEffectIndex /*eff_idx*/)
4049 // Check for possible target
4050 if (!unitTarget || unitTarget->isInCombat())
4051 return;
4053 // target must be OK to do this
4054 if( unitTarget->hasUnitState(UNIT_STAT_CAN_NOT_REACT) )
4055 return;
4057 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
4059 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
4061 // For players just turn them
4062 WorldPacket data;
4063 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
4064 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
4065 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
4067 else
4069 // Set creature Distracted, Stop it, And turn it
4070 unitTarget->SetOrientation(angle);
4071 unitTarget->StopMoving();
4072 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS);
4076 void Spell::EffectPickPocket(SpellEffectIndex /*eff_idx*/)
4078 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4079 return;
4081 // victim must be creature and attackable
4082 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
4083 return;
4085 // victim have to be alive and humanoid or undead
4086 if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
4088 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
4090 if (chance > irand(0, 19))
4092 // Stealing successful
4093 //sLog.outDebug("Sending loot from pickpocket");
4094 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
4096 else
4098 // Reveal action + get attack
4099 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
4100 if (((Creature*)unitTarget)->AI())
4101 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
4106 void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
4108 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4109 return;
4111 int32 duration = GetSpellDuration(m_spellInfo);
4112 DynamicObject* dynObj = new DynamicObject;
4114 // set radius to 0: spell not expected to work as persistent aura
4115 if(!dynObj->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, eff_idx, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, 0))
4117 delete dynObj;
4118 return;
4120 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
4121 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
4122 m_caster->AddDynObject(dynObj);
4123 m_caster->GetMap()->Add(dynObj);
4124 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
4127 void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction)
4129 uint32 creature_entry = m_spellInfo->EffectMiscValue[eff_idx];
4130 if (!creature_entry)
4131 return;
4133 uint32 level = m_caster->getLevel();
4135 // level of creature summoned using engineering item based at engineering skill level
4136 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
4138 ItemPrototype const *proto = m_CastItem->GetProto();
4139 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
4141 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
4142 if (skill202)
4143 level = skill202/5;
4147 // select center of summon position
4148 float center_x = m_targets.m_destX;
4149 float center_y = m_targets.m_destY;
4150 float center_z = m_targets.m_destZ;
4152 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4153 int32 duration = GetSpellDuration(m_spellInfo);
4154 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
4156 int32 amount = damage > 0 ? damage : 1;
4158 for(int32 count = 0; count < amount; ++count)
4160 float px, py, pz;
4161 // If dest location if present
4162 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4164 // Summon 1 unit in dest location
4165 if (count == 0)
4167 px = m_targets.m_destX;
4168 py = m_targets.m_destY;
4169 pz = m_targets.m_destZ;
4171 // Summon in random point all other units if location present
4172 else
4173 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
4175 // Summon if dest location not present near caster
4176 else
4177 m_caster->GetClosePoint(px, py, pz, 3.0f);
4179 if(Creature *summon = m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration))
4181 summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4182 summon->SetCreatorGUID(m_caster->GetGUID());
4184 if(forceFaction)
4185 summon->setFaction(forceFaction);
4190 void Spell::DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction)
4192 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
4193 if (!pet_entry)
4194 return;
4196 // in another case summon new
4197 uint32 level = m_caster->getLevel();
4199 // level of pet summoned using engineering item based at engineering skill level
4200 if (m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
4202 ItemPrototype const *proto = m_CastItem->GetProto();
4203 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
4205 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
4206 if (skill202)
4208 level = skill202 / 5;
4213 // select center of summon position
4214 float center_x = m_targets.m_destX;
4215 float center_y = m_targets.m_destY;
4216 float center_z = m_targets.m_destZ;
4218 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4219 int32 duration = GetSpellDuration(m_spellInfo);
4220 if(Player* modOwner = m_caster->GetSpellModOwner())
4221 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
4223 int32 amount = damage > 0 ? damage : 1;
4225 for(int32 count = 0; count < amount; ++count)
4227 Pet* spawnCreature = new Pet(GUARDIAN_PET);
4229 Map *map = m_caster->GetMap();
4230 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4231 if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
4232 m_spellInfo->EffectMiscValue[eff_idx], pet_number))
4234 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[eff_idx]);
4235 delete spawnCreature;
4236 return;
4239 float px, py, pz;
4240 // If dest location if present
4241 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4243 // Summon 1 unit in dest location
4244 if (count == 0)
4246 px = m_targets.m_destX;
4247 py = m_targets.m_destY;
4248 pz = m_targets.m_destZ;
4250 // Summon in random point all other units if location present
4251 else
4252 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
4254 // Summon if dest location not present near caster
4255 else
4256 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
4258 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
4260 if (!spawnCreature->IsPositionValid())
4262 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
4263 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
4264 delete spawnCreature;
4265 return;
4268 if (duration > 0)
4269 spawnCreature->SetDuration(duration);
4271 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
4272 spawnCreature->setPowerType(POWER_MANA);
4273 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
4274 spawnCreature->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
4275 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
4276 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4277 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
4278 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
4279 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4281 spawnCreature->InitStatsForLevel(level, m_caster);
4282 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
4284 spawnCreature->AIM_Initialize();
4286 m_caster->AddGuardian(spawnCreature);
4288 map->Add((Creature*)spawnCreature);
4292 void Spell::EffectTeleUnitsFaceCaster(SpellEffectIndex eff_idx)
4294 if (!unitTarget)
4295 return;
4297 if (unitTarget->isInFlight())
4298 return;
4300 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
4302 float fx, fy, fz;
4303 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
4305 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
4308 void Spell::EffectLearnSkill(SpellEffectIndex eff_idx)
4310 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4311 return;
4313 if (damage < 0)
4314 return;
4316 uint32 skillid = m_spellInfo->EffectMiscValue[eff_idx];
4317 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
4318 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
4321 void Spell::EffectAddHonor(SpellEffectIndex /*eff_idx*/)
4323 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4324 return;
4326 // not scale value for item based reward (/10 value expected)
4327 if (m_CastItem)
4329 ((Player*)unitTarget)->RewardHonor(NULL, 1, float(damage / 10));
4330 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
4331 return;
4334 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4335 if (damage <= 50)
4337 float honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
4338 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
4339 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %f honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
4341 else
4343 //maybe we have correct honor_gain in damage already
4344 ((Player*)unitTarget)->RewardHonor(NULL, 1, (float)damage);
4345 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
4349 void Spell::EffectTradeSkill(SpellEffectIndex /*eff_idx*/)
4351 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4352 return;
4353 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4354 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4355 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4358 void Spell::EffectEnchantItemPerm(SpellEffectIndex eff_idx)
4360 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4361 return;
4362 if (!itemTarget)
4363 return;
4365 Player* p_caster = (Player*)m_caster;
4367 // not grow at item use at item case
4368 p_caster->UpdateCraftSkill(m_spellInfo->Id);
4370 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4371 if (!enchant_id)
4372 return;
4374 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4375 if (!pEnchant)
4376 return;
4378 // item can be in trade slot and have owner diff. from caster
4379 Player* item_owner = itemTarget->GetOwner();
4380 if (!item_owner)
4381 return;
4383 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4385 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4386 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4387 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4388 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4391 // remove old enchanting before applying new if equipped
4392 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
4394 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4396 // add new enchanting if equipped
4397 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
4399 // update trade window for show enchantment for caster in trade window
4400 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4401 p_caster->GetSession()->SendUpdateTrade();
4404 void Spell::EffectEnchantItemPrismatic(SpellEffectIndex eff_idx)
4406 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4407 return;
4408 if (!itemTarget)
4409 return;
4411 Player* p_caster = (Player*)m_caster;
4413 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4414 if (!enchant_id)
4415 return;
4417 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4418 if (!pEnchant)
4419 return;
4421 // support only enchantings with add socket in this slot
4423 bool add_socket = false;
4424 for(int i = 0; i < 3; ++i)
4426 if (pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
4428 add_socket = true;
4429 break;
4432 if (!add_socket)
4434 sLog.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (%u), not suppoted yet.",
4435 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
4436 return;
4440 // item can be in trade slot and have owner diff. from caster
4441 Player* item_owner = itemTarget->GetOwner();
4442 if (!item_owner)
4443 return;
4445 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4447 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4448 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4449 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4450 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4453 // remove old enchanting before applying new if equipped
4454 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
4456 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4458 // add new enchanting if equipped
4459 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
4461 // update trade window for show enchantment for caster in trade window
4462 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4463 p_caster->GetSession()->SendUpdateTrade();
4466 void Spell::EffectEnchantItemTmp(SpellEffectIndex eff_idx)
4468 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4469 return;
4471 Player* p_caster = (Player*)m_caster;
4473 // Rockbiter Weapon apply to both weapon
4474 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000))
4476 uint32 spell_id = 0;
4478 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4479 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4480 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4481 switch(damage)
4483 // Rank 1
4484 case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4485 // Rank 2
4486 case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
4487 case 5: spell_id = 36751; break; // 20%
4488 // Rank 3
4489 case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
4490 case 7: spell_id = 36755; break; // 20%
4491 // Rank 4
4492 case 9: spell_id = 36761; break; // 0% [ 7% == 6]
4493 case 10: spell_id = 36758; break; // 14%
4494 case 11: spell_id = 36760; break; // 20%
4495 default:
4496 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage);
4497 return;
4501 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
4502 if (!spellInfo)
4504 sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
4505 return;
4508 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
4510 if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
4512 if (item->IsFitToSpellRequirements(m_spellInfo))
4514 Spell *spell = new Spell(m_caster, spellInfo, true);
4515 SpellCastTargets targets;
4516 targets.setItemTarget( item );
4517 spell->prepare(&targets);
4521 return;
4524 if (!itemTarget)
4525 return;
4527 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
4529 if (!enchant_id)
4531 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,eff_idx);
4532 return;
4535 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4536 if(!pEnchant)
4538 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,eff_idx,enchant_id);
4539 return;
4542 // select enchantment duration
4543 uint32 duration;
4545 // rogue family enchantments exception by duration
4546 if(m_spellInfo->Id == 38615)
4547 duration = 1800; // 30 mins
4548 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4549 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
4550 duration = 3600; // 1 hour
4551 // shaman family enchantments
4552 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
4553 duration = 1800; // 30 mins
4554 // other cases with this SpellVisual already selected
4555 else if(m_spellInfo->SpellVisual[0] == 215)
4556 duration = 1800; // 30 mins
4557 // some fishing pole bonuses
4558 else if(m_spellInfo->SpellVisual[0] == 563)
4559 duration = 600; // 10 mins
4560 // shaman rockbiter enchantments
4561 else if(m_spellInfo->SpellVisual[0] == 0)
4562 duration = 1800; // 30 mins
4563 else if(m_spellInfo->Id == 29702)
4564 duration = 300; // 5 mins
4565 else if(m_spellInfo->Id == 37360)
4566 duration = 300; // 5 mins
4567 // default case
4568 else
4569 duration = 3600; // 1 hour
4571 // item can be in trade slot and have owner diff. from caster
4572 Player* item_owner = itemTarget->GetOwner();
4573 if(!item_owner)
4574 return;
4576 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) )
4578 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4579 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4580 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4581 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4584 // remove old enchanting before applying new if equipped
4585 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4587 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4589 // add new enchanting if equipped
4590 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4592 // update trade window for show enchantment for caster in trade window
4593 if (m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM)
4594 p_caster->GetSession()->SendUpdateTrade();
4597 void Spell::EffectTameCreature(SpellEffectIndex /*eff_idx*/)
4599 // Caster must be player, checked in Spell::CheckCast
4600 // Spell can be triggered, we need to check original caster prior to caster
4601 Player* plr = (Player*)GetAffectiveCaster();
4603 Creature* creatureTarget = (Creature*)unitTarget;
4605 // cast finish successfully
4606 //SendChannelUpdate(0);
4607 finish();
4609 Pet* pet = plr->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
4610 if(!pet) // in versy specific state like near world end/etc.
4611 return;
4613 // "kill" original creature
4614 creatureTarget->ForcedDespawn();
4616 uint32 level = (creatureTarget->getLevel() < (plr->getLevel() - 5)) ? (plr->getLevel() - 5) : creatureTarget->getLevel();
4618 // prepare visual effect for levelup
4619 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4621 // add to world
4622 pet->GetMap()->Add((Creature*)pet);
4624 // visual effect for levelup
4625 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4627 // caster have pet now
4628 plr->SetPet(pet);
4630 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4631 plr->PetSpellInitialize();
4634 void Spell::EffectSummonPet(SpellEffectIndex eff_idx)
4636 uint32 petentry = m_spellInfo->EffectMiscValue[eff_idx];
4638 Pet *OldSummon = m_caster->GetPet();
4640 // if pet requested type already exist
4641 if( OldSummon )
4643 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4645 // pet in corpse state can't be summoned
4646 if( OldSummon->isDead() )
4647 return;
4649 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4651 float px, py, pz;
4652 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4654 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4655 m_caster->GetMap()->Add((Creature*)OldSummon);
4657 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4659 ((Player*)m_caster)->PetSpellInitialize();
4661 return;
4664 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4665 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4666 else
4667 return;
4670 Pet* NewSummon = new Pet;
4672 // petentry==0 for hunter "call pet" (current pet summoned if any)
4673 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster, petentry))
4675 if(NewSummon->getPetType() == SUMMON_PET)
4677 // Remove Demonic Sacrifice auras (known pet)
4678 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4679 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4681 if((*itr)->GetModifier()->m_miscvalue == 2228)
4683 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4684 itr = auraClassScripts.begin();
4686 else
4687 ++itr;
4691 return;
4694 // not error in case fail hunter call pet
4695 if(!petentry)
4697 delete NewSummon;
4698 return;
4701 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4703 if(!cInfo)
4705 sLog.outError("EffectSummonPet: creature entry %u not found.", petentry);
4706 delete NewSummon;
4707 return;
4710 Map *map = m_caster->GetMap();
4711 uint32 pet_number = sObjectMgr.GeneratePetNumber();
4712 if(!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4713 petentry, pet_number))
4715 delete NewSummon;
4716 return;
4719 float px, py, pz;
4720 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4722 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4724 if(!NewSummon->IsPositionValid())
4726 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4727 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4728 delete NewSummon;
4729 return;
4732 uint32 petlevel = m_caster->getLevel();
4733 NewSummon->setPetType(SUMMON_PET);
4735 uint32 faction = m_caster->getFaction();
4736 if(m_caster->GetTypeId() == TYPEID_UNIT)
4738 if ( ((Creature*)m_caster)->isTotem() )
4739 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4740 else
4741 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4744 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4745 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4746 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
4747 NewSummon->setFaction(faction);
4748 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4749 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4750 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL)));
4751 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4752 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4753 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4755 NewSummon->UpdateWalkMode(m_caster);
4757 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4758 // this enables pet details window (Shift+P)
4760 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4761 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4762 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
4764 if(m_caster->IsPvP())
4765 NewSummon->SetPvP(true);
4767 if(m_caster->IsFFAPvP())
4768 NewSummon->SetFFAPvP(true);
4770 NewSummon->InitStatsForLevel(petlevel, m_caster);
4771 NewSummon->InitPetCreateSpells();
4772 NewSummon->InitLevelupSpellsForLevel();
4773 NewSummon->InitTalentForLevel();
4775 if(NewSummon->getPetType() == SUMMON_PET)
4777 // Remove Demonic Sacrifice auras (new pet)
4778 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4779 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
4781 if((*itr)->GetModifier()->m_miscvalue == 2228)
4783 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4784 itr = auraClassScripts.begin();
4786 else
4787 ++itr;
4790 // generate new name for summon pet
4791 std::string new_name = sObjectMgr.GeneratePetName(petentry);
4792 if(!new_name.empty())
4793 NewSummon->SetName(new_name);
4795 else if(NewSummon->getPetType() == HUNTER_PET)
4797 NewSummon->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
4798 NewSummon->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_ABANDONED);
4801 NewSummon->AIM_Initialize();
4802 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4803 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4805 map->Add((Creature*)NewSummon);
4807 m_caster->SetPet(NewSummon);
4808 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4810 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4812 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4813 ((Player*)m_caster)->PetSpellInitialize();
4817 void Spell::EffectLearnPetSpell(SpellEffectIndex eff_idx)
4819 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4820 return;
4822 Player *_player = (Player*)m_caster;
4824 Pet *pet = _player->GetPet();
4825 if(!pet)
4826 return;
4827 if(!pet->isAlive())
4828 return;
4830 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[eff_idx]);
4831 if(!learn_spellproto)
4832 return;
4834 pet->learnSpell(learn_spellproto->Id);
4836 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4837 _player->PetSpellInitialize();
4840 void Spell::EffectTaunt(SpellEffectIndex /*eff_idx*/)
4842 if (!unitTarget)
4843 return;
4845 // this effect use before aura Taunt apply for prevent taunt already attacking target
4846 // for spell as marked "non effective at already attacking target"
4847 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4849 if (unitTarget->getVictim()==m_caster)
4851 SendCastResult(SPELL_FAILED_DONT_REPORT);
4852 return;
4856 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4857 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4858 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4861 void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
4863 if(!unitTarget)
4864 return;
4865 if(!unitTarget->isAlive())
4866 return;
4868 // multiple weapon dmg effect workaround
4869 // execute only the last weapon damage
4870 // and handle all effects at once
4871 for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
4873 switch(m_spellInfo->Effect[j])
4875 case SPELL_EFFECT_WEAPON_DAMAGE:
4876 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4877 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4878 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4879 if (j < int(eff_idx)) // we must calculate only at last weapon effect
4880 return;
4881 break;
4885 // some spell specific modifiers
4886 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4888 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4889 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4890 bool normalized = false;
4892 int32 spell_bonus = 0; // bonus specific for spell
4893 switch(m_spellInfo->SpellFamilyName)
4895 case SPELLFAMILY_WARRIOR:
4897 // Devastate bonus and sunder armor refresh
4898 if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
4900 uint32 stack = 0;
4901 // Need refresh all Sunder Armor auras from this caster
4902 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4903 SpellEntry const *spellInfo;
4904 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4906 spellInfo = (*itr).second->GetSpellProto();
4907 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4908 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4909 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4911 (*itr).second->RefreshAura();
4912 stack = (*itr).second->GetStackAmount();
4913 break;
4916 if (stack)
4917 spell_bonus += stack * CalculateDamage(EFFECT_INDEX_2, unitTarget);
4918 if (!stack || stack < spellInfo->StackAmount)
4919 // Devastate causing Sunder Armor Effect
4920 // and no need to cast over max stack amount
4921 m_caster->CastSpell(unitTarget, 58567, true);
4923 break;
4925 case SPELLFAMILY_ROGUE:
4927 // Mutilate (for each hand)
4928 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4930 bool found = false;
4931 // fast check
4932 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4933 found = true;
4934 // full aura scan
4935 else
4937 Unit::AuraMap const& auras = unitTarget->GetAuras();
4938 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4940 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4942 found = true;
4943 break;
4948 if(found)
4949 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4951 // Fan of Knives
4952 else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
4954 Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,true);
4955 if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
4956 totalDamagePercentMod *= 1.5f; // 150% to daggers
4958 break;
4960 case SPELLFAMILY_PALADIN:
4962 // Judgement of Command - receive benefit from Spell Damage and Attack Power
4963 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000000000))
4965 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
4966 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
4967 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
4968 spell_bonus += int32(ap * 0.08f) + int32(holy * 13 / 100);
4970 break;
4972 case SPELLFAMILY_HUNTER:
4974 // Kill Shot
4975 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x80000000000000))
4977 // 0.4*RAP added to damage (that is 0.2 if we apply PercentMod (200%) to spell_bonus, too)
4978 spellBonusNeedWeaponDamagePercentMod = true;
4979 spell_bonus += int32( 0.2f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK) );
4981 break;
4983 case SPELLFAMILY_SHAMAN:
4985 // Skyshatter Harness item set bonus
4986 // Stormstrike
4987 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
4989 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4990 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4992 // Stormstrike AP Buff
4993 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4995 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
4996 break;
5000 break;
5002 case SPELLFAMILY_DEATHKNIGHT:
5004 // Blood Strike, Heart Strike, Obliterate
5005 // Blood-Caked Strike, Scourge Strike
5006 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
5007 m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
5009 uint32 count = 0;
5010 Unit::AuraMap const& auras = unitTarget->GetAuras();
5011 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
5013 if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
5014 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
5015 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
5016 ++count;
5019 if (count)
5021 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
5022 float bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? EFFECT_INDEX_0 : EFFECT_INDEX_2, unitTarget) / 100.0f;
5023 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
5024 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
5025 m_spellInfo->SpellIconID == 1736)
5026 bonus /= 2.0f;
5028 totalDamagePercentMod *= 1.0f + bonus;
5031 // Heart Strike secondary target
5032 if (m_spellInfo->SpellIconID == 3145)
5033 if (m_targets.getUnitTarget() != unitTarget)
5034 weaponDamagePercentMod /= 2.0f;
5036 // Glyph of Blood Strike
5037 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400000) &&
5038 m_caster->HasAura(59332) &&
5039 unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
5041 totalDamagePercentMod *= 1.2f; // 120% if snared
5043 // Glyph of Death Strike
5044 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010) &&
5045 m_caster->HasAura(59336))
5047 int32 rp = m_caster->GetPower(POWER_RUNIC_POWER) / 10;
5048 if(rp > 25)
5049 rp = 25;
5050 totalDamagePercentMod *= 1.0f + rp / 100.0f;
5052 // Glyph of Plague Strike
5053 if( m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001) &&
5054 m_caster->HasAura(58657) )
5056 totalDamagePercentMod *= 1.2f;
5058 break;
5062 int32 fixed_bonus = 0;
5063 for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
5065 switch(m_spellInfo->Effect[j])
5067 case SPELL_EFFECT_WEAPON_DAMAGE:
5068 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
5069 fixed_bonus += CalculateDamage(SpellEffectIndex(j), unitTarget);
5070 break;
5071 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
5072 fixed_bonus += CalculateDamage(SpellEffectIndex(j), unitTarget);
5073 normalized = true;
5074 break;
5075 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
5076 weaponDamagePercentMod *= float(CalculateDamage(SpellEffectIndex(j), unitTarget)) / 100.0f;
5078 // applied only to prev.effects fixed damage
5079 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
5080 break;
5081 default:
5082 break; // not weapon damage effect, just skip
5086 // apply weaponDamagePercentMod to spell bonus also
5087 if(spellBonusNeedWeaponDamagePercentMod)
5088 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
5090 // non-weapon damage
5091 int32 bonus = spell_bonus + fixed_bonus;
5093 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
5094 if(bonus)
5096 UnitMods unitMod;
5097 switch(m_attackType)
5099 default:
5100 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
5101 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
5102 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
5105 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
5106 bonus = int32(bonus*weapon_total_pct);
5109 // + weapon damage with applied weapon% dmg to base weapon damage in call
5110 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
5112 // total damage
5113 bonus = int32(bonus*totalDamagePercentMod);
5115 // prevent negative damage
5116 m_damage+= uint32(bonus > 0 ? bonus : 0);
5118 // Hemorrhage
5119 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
5121 if(m_caster->GetTypeId()==TYPEID_PLAYER)
5122 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
5124 // Mangle (Cat): CP
5125 else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
5127 if(m_caster->GetTypeId()==TYPEID_PLAYER)
5128 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
5131 // take ammo
5132 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
5134 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK, true, false);
5136 // wands don't have ammo
5137 if (!pItem || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
5138 return;
5140 if (pItem->GetProto()->InventoryType == INVTYPE_THROWN)
5142 if(pItem->GetMaxStackCount()==1)
5144 // decrease durability for non-stackable throw weapon
5145 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
5147 else
5149 // decrease items amount for stackable throw weapon
5150 uint32 count = 1;
5151 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
5154 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
5155 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
5159 void Spell::EffectThreat(SpellEffectIndex /*eff_idx*/)
5161 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
5162 return;
5164 if(!unitTarget->CanHaveThreatList())
5165 return;
5167 unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
5170 void Spell::EffectHealMaxHealth(SpellEffectIndex /*eff_idx*/)
5172 if(!unitTarget)
5173 return;
5174 if(!unitTarget->isAlive())
5175 return;
5177 uint32 heal = m_caster->GetMaxHealth();
5179 m_healing += heal;
5182 void Spell::EffectInterruptCast(SpellEffectIndex /*eff_idx*/)
5184 if(!unitTarget)
5185 return;
5186 if(!unitTarget->isAlive())
5187 return;
5189 // TODO: not all spells that used this effect apply cooldown at school spells
5190 // also exist case: apply cooldown to interrupted cast only and to all spells
5191 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
5193 if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
5195 SpellEntry const* curSpellInfo = spell->m_spellInfo;
5196 // check if we can interrupt spell
5197 if ((curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
5199 unitTarget->ProhibitSpellSchool(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo));
5200 unitTarget->InterruptSpell(CurrentSpellTypes(i),false);
5206 void Spell::EffectSummonObjectWild(SpellEffectIndex eff_idx)
5208 uint32 gameobject_id = m_spellInfo->EffectMiscValue[eff_idx];
5210 GameObject* pGameObj = new GameObject;
5212 WorldObject* target = focusObject;
5213 if( !target )
5214 target = m_caster;
5216 float x, y, z;
5217 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5219 x = m_targets.m_destX;
5220 y = m_targets.m_destY;
5221 z = m_targets.m_destZ;
5223 else
5224 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
5226 Map *map = target->GetMap();
5228 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5229 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
5231 delete pGameObj;
5232 return;
5235 int32 duration = GetSpellDuration(m_spellInfo);
5237 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5238 pGameObj->SetSpellId(m_spellInfo->Id);
5240 // Wild object not have owner and check clickable by players
5241 map->Add(pGameObj);
5243 if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER)
5245 Player *pl = (Player*)m_caster;
5246 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
5248 switch(pGameObj->GetMapId())
5250 case 489: //WS
5252 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
5254 uint32 team = ALLIANCE;
5256 if(pl->GetTeam() == team)
5257 team = HORDE;
5259 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
5261 break;
5263 case 566: //EY
5265 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
5267 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
5269 break;
5274 pGameObj->SummonLinkedTrapIfAny();
5277 void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
5279 // TODO: we must implement hunter pet summon at login there (spell 6962)
5281 switch(m_spellInfo->SpellFamilyName)
5283 case SPELLFAMILY_GENERIC:
5285 switch(m_spellInfo->Id)
5287 case 8856: // Bending Shinbone
5289 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
5290 return;
5292 uint32 spell_id = 0;
5293 switch(urand(1, 5))
5295 case 1: spell_id = 8854; break;
5296 default: spell_id = 8855; break;
5299 m_caster->CastSpell(m_caster,spell_id,true,NULL);
5300 return;
5302 case 17512: // Piccolo of the Flaming Fire
5304 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5305 return;
5307 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
5308 return;
5310 case 20589: // Escape artist
5312 if (!unitTarget)
5313 return;
5315 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5316 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5317 return;
5319 case 24590: // Brittle Armor - need remove one 24575 Brittle Armor aura
5320 unitTarget->RemoveSingleSpellAurasFromStack(24575);
5321 return;
5322 case 26275: // PX-238 Winter Wondervolt TRAP
5324 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
5326 // check presence
5327 for(int j = 0; j < 4; ++j)
5328 if (unitTarget->HasAura(spells[j], EFFECT_INDEX_0))
5329 return;
5331 // select spell
5332 uint32 iTmpSpellId = spells[urand(0,3)];
5334 // cast
5335 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
5336 return;
5338 case 26465: // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5339 unitTarget->RemoveSingleSpellAurasFromStack(26464);
5340 return;
5341 case 25140: // Orb teleport spells
5342 case 25143:
5343 case 25650:
5344 case 25652:
5345 case 29128:
5346 case 29129:
5347 case 35376:
5348 case 35727:
5350 if (!unitTarget)
5351 return;
5353 uint32 spellid;
5354 switch(m_spellInfo->Id)
5356 case 25140: spellid = 32571; break;
5357 case 25143: spellid = 32572; break;
5358 case 25650: spellid = 30140; break;
5359 case 25652: spellid = 30141; break;
5360 case 29128: spellid = 32568; break;
5361 case 29129: spellid = 32569; break;
5362 case 35376: spellid = 25649; break;
5363 case 35727: spellid = 35730; break;
5364 default:
5365 return;
5368 unitTarget->CastSpell(unitTarget,spellid,false);
5369 return;
5371 case 22539: // Shadow Flame (All script effects, not just end ones to
5372 case 22972: // prevent player from dodging the last triggered spell)
5373 case 22975:
5374 case 22976:
5375 case 22977:
5376 case 22978:
5377 case 22979:
5378 case 22980:
5379 case 22981:
5380 case 22982:
5381 case 22983:
5382 case 22984:
5383 case 22985:
5385 if (!unitTarget || !unitTarget->isAlive())
5386 return;
5388 // Onyxia Scale Cloak
5389 if (unitTarget->GetDummyAura(22683))
5390 return;
5392 // Shadow Flame
5393 m_caster->CastSpell(unitTarget, 22682, true);
5394 return;
5396 case 26656: // Summon Black Qiraji Battle Tank
5398 if (!unitTarget)
5399 return;
5401 // Prevent stacking of mounts
5402 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5404 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5405 if (unitTarget->GetAreaId() == 3428)
5406 unitTarget->CastSpell(unitTarget, 25863, false);
5407 else
5408 unitTarget->CastSpell(unitTarget, 26655, false);
5410 return;
5412 case 29830: // Mirren's Drinking Hat
5414 uint32 item = 0;
5415 switch ( urand(1, 6) )
5417 case 1:
5418 case 2:
5419 case 3:
5420 item = 23584; break; // Loch Modan Lager
5421 case 4:
5422 case 5:
5423 item = 23585; break; // Stouthammer Lite
5424 case 6:
5425 item = 23586; break; // Aerie Peak Pale Ale
5428 if (item)
5429 DoCreateItem(eff_idx,item);
5431 break;
5433 case 30918: // Improved Sprint
5435 if (!unitTarget)
5436 return;
5438 // Removes snares and roots.
5439 unitTarget->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK,30918,true);
5440 break;
5442 case 41126: // Flame Crash
5444 if (!unitTarget)
5445 return;
5447 unitTarget->CastSpell(unitTarget, 41131, true);
5448 break;
5450 case 44455: // Character Script Effect Reverse Cast
5452 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
5453 return;
5455 Creature* pTarget = (Creature*)unitTarget;
5457 if (const SpellEntry *pSpell = sSpellStore.LookupEntry(m_spellInfo->CalculateSimpleValue(eff_idx)))
5459 // if we used item at least once...
5460 if (pTarget->isTemporarySummon() && pTarget->GetEntry() == pSpell->EffectMiscValue[eff_idx])
5462 TemporarySummon* pSummon = (TemporarySummon*)pTarget;
5464 // can only affect "own" summoned
5465 if (pSummon->GetSummonerGUID() == m_caster->GetGUID())
5467 if (pTarget->hasUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE))
5468 pTarget->GetMotionMaster()->MovementExpired();
5470 pTarget->GetMotionMaster()->MovePoint(0, m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ());
5473 return;
5476 // or if we are first time used item
5477 m_caster->CastSpell(pTarget, pSpell, true);
5478 pTarget->ForcedDespawn();
5481 return;
5483 case 44876: // Force Cast - Portal Effect: Sunwell Isle
5485 if (!unitTarget)
5486 return;
5488 unitTarget->CastSpell(unitTarget, 44870, true);
5489 break;
5491 case 45668: // Ultra-Advanced Proto-Typical Shortening Blaster
5493 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
5494 return;
5496 if (roll_chance_i(25)) // chance unknown, using 25
5497 return;
5499 static uint32 const spellPlayer[5] =
5501 45674, // Bigger!
5502 45675, // Shrunk
5503 45678, // Yellow
5504 45682, // Ghost
5505 45684 // Polymorph
5508 static uint32 const spellTarget[5] =
5510 45673, // Bigger!
5511 45672, // Shrunk
5512 45677, // Yellow
5513 45681, // Ghost
5514 45683 // Polymorph
5517 m_caster->CastSpell(m_caster, spellPlayer[urand(0,4)], true);
5518 unitTarget->CastSpell(unitTarget, spellTarget[urand(0,4)], true);
5520 return;
5522 case 45691: // Magnataur On Death 1
5524 // assuming caster is creature, if not, then return
5525 if (m_caster->GetTypeId() != TYPEID_UNIT)
5526 return;
5528 Player* pPlayer = ((Creature*)m_caster)->GetLootRecipient();
5530 if (!pPlayer)
5531 return;
5533 if (pPlayer->HasAura(45674) || pPlayer->HasAura(45675) || pPlayer->HasAura(45678) || pPlayer->HasAura(45682) || pPlayer->HasAura(45684))
5534 pPlayer->CastSpell(pPlayer, 45686, true);
5536 m_caster->CastSpell(m_caster, 45685, true);
5538 return;
5540 case 46203: // Goblin Weather Machine
5542 if (!unitTarget)
5543 return;
5545 uint32 spellId = 0;
5546 switch(rand() % 4)
5548 case 0: spellId = 46740; break;
5549 case 1: spellId = 46739; break;
5550 case 2: spellId = 46738; break;
5551 case 3: spellId = 46736; break;
5553 unitTarget->CastSpell(unitTarget, spellId, true);
5554 break;
5556 case 46642: //5,000 Gold
5558 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5559 return;
5561 ((Player*)unitTarget)->ModifyMoney(50000000);
5562 break;
5564 case 47097: // Surge Needle Teleporter
5566 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5567 return;
5569 if (unitTarget->GetAreaId() == 4156)
5570 unitTarget->CastSpell(unitTarget, 47324, true);
5571 else if (unitTarget->GetAreaId() == 4157)
5572 unitTarget->CastSpell(unitTarget, 47325, true);
5574 break;
5576 case 48603: // High Executor's Branding Iron
5577 // Torture the Torturer: High Executor's Branding Iron Impact
5578 unitTarget->CastSpell(unitTarget, 48614, true);
5579 return;
5580 case 51770: // Emblazon Runeblade
5582 Unit* caster = GetAffectiveCaster();
5583 if (!caster)
5584 return;
5586 caster->CastSpell(caster, damage, false);
5587 break;
5589 case 52751: // Death Gate
5591 if (!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
5592 return;
5594 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5595 unitTarget->CastSpell(unitTarget, damage, false);
5596 break;
5598 case 54729: // Winged Steed of the Ebon Blade
5600 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5601 return;
5603 // Prevent stacking of mounts
5604 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5606 // Triggered spell id dependent of riding skill
5607 if (uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
5609 if (skillval >= 300)
5610 unitTarget->CastSpell(unitTarget, 54727, true);
5611 else
5612 unitTarget->CastSpell(unitTarget, 54726, true);
5614 return;
5616 case 54436: // Demonic Empowerment (succubus Vanish effect)
5618 if (!unitTarget)
5619 return;
5621 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5622 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
5623 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
5624 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN);
5625 return;
5627 case 55693: // Remove Collapsing Cave Aura
5629 if (!unitTarget)
5630 return;
5632 unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(eff_idx));
5633 break;
5635 case 58418: // Portal to Orgrimmar
5636 case 58420: // Portal to Stormwind
5638 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || eff_idx != EFFECT_INDEX_0)
5639 return;
5641 uint32 spellID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0);
5642 uint32 questID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1);
5644 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
5645 unitTarget->CastSpell(unitTarget, spellID, true);
5647 return;
5649 case 59317: // Teleporting
5651 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5652 return;
5654 // return from top
5655 if (((Player*)unitTarget)->GetAreaId() == 4637)
5656 unitTarget->CastSpell(unitTarget, 59316, true);
5657 // teleport atop
5658 else
5659 unitTarget->CastSpell(unitTarget, 59314, true);
5661 return;
5662 } // random spell learn instead placeholder
5663 case 60893: // Northrend Alchemy Research
5664 case 61177: // Northrend Inscription Research
5665 case 61288: // Minor Inscription Research
5666 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5667 case 64323: // Book of Glyph Mastery
5669 if (m_caster->GetTypeId() != TYPEID_PLAYER)
5670 return;
5672 // learn random explicit discovery recipe (if any)
5673 if (uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
5674 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
5676 return;
5678 case 69377: //Fortitude
5680 if (!unitTarget)
5681 return;
5683 m_caster->CastSpell(unitTarget, 72590, true);
5684 return;
5686 case 69378: //Blessing of Forgotten Kings
5688 if (!unitTarget)
5689 return;
5691 m_caster->CastSpell(unitTarget, 72586, true);
5692 return;
5694 case 69381: //Gift of the Wild
5696 if (!unitTarget)
5697 return;
5699 m_caster->CastSpell(unitTarget, 72588, true);
5700 return;
5703 break;
5705 case SPELLFAMILY_WARLOCK:
5707 switch(m_spellInfo->Id)
5709 case 6201: // Healthstone creating spells
5710 case 6202:
5711 case 5699:
5712 case 11729:
5713 case 11730:
5714 case 27230:
5715 case 47871:
5716 case 47878:
5718 if (!unitTarget)
5719 return;
5721 uint32 itemtype;
5722 uint32 rank = 0;
5723 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5724 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
5726 if ((*i)->GetId() == 18692)
5728 rank = 1;
5729 break;
5731 else if ((*i)->GetId() == 18693)
5733 rank = 2;
5734 break;
5738 static uint32 const itypes[8][3] =
5740 { 5512, 19004, 19005}, // Minor Healthstone
5741 { 5511, 19006, 19007}, // Lesser Healthstone
5742 { 5509, 19008, 19009}, // Healthstone
5743 { 5510, 19010, 19011}, // Greater Healthstone
5744 { 9421, 19012, 19013}, // Major Healthstone
5745 {22103, 22104, 22105}, // Master Healthstone
5746 {36889, 36890, 36891}, // Demonic Healthstone
5747 {36892, 36893, 36894} // Fel Healthstone
5750 switch(m_spellInfo->Id)
5752 case 6201:
5753 itemtype=itypes[0][rank];break; // Minor Healthstone
5754 case 6202:
5755 itemtype=itypes[1][rank];break; // Lesser Healthstone
5756 case 5699:
5757 itemtype=itypes[2][rank];break; // Healthstone
5758 case 11729:
5759 itemtype=itypes[3][rank];break; // Greater Healthstone
5760 case 11730:
5761 itemtype=itypes[4][rank];break; // Major Healthstone
5762 case 27230:
5763 itemtype=itypes[5][rank];break; // Master Healthstone
5764 case 47871:
5765 itemtype=itypes[6][rank];break; // Demonic Healthstone
5766 case 47878:
5767 itemtype=itypes[7][rank];break; // Fel Healthstone
5768 default:
5769 return;
5771 DoCreateItem( eff_idx, itemtype );
5772 return;
5774 case 47193: // Demonic Empowerment
5776 if (!unitTarget)
5777 return;
5779 uint32 entry = unitTarget->GetEntry();
5780 uint32 spellID;
5781 switch(entry)
5783 case 416: spellID = 54444; break; //imp
5784 case 417: spellID = 54509; break; //fellhunter
5785 case 1860: spellID = 54443; break; //void
5786 case 1863: spellID = 54435; break; //succubus
5787 case 17252: spellID = 54508; break; //fellguard
5788 default:
5789 return;
5791 unitTarget->CastSpell(unitTarget,spellID,true);
5792 return;
5794 case 47422: // Everlasting Affliction
5796 // Need refresh caster corruption auras on target
5797 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5798 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5800 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5801 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5802 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5803 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5804 (*itr).second->RefreshAura();
5806 return;
5808 case 63521: // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5810 // Divine Plea, refresh on target (3 aura slots)
5811 if (Aura* aura = unitTarget->GetAura(54428, EFFECT_INDEX_0))
5812 aura->RefreshAura();
5814 return;
5817 break;
5819 case SPELLFAMILY_PRIEST:
5821 switch(m_spellInfo->Id)
5823 case 47948: // Pain and Suffering
5825 if (!unitTarget)
5826 return;
5828 // Refresh Shadow Word: Pain on target
5829 Unit::AuraMap& auras = unitTarget->GetAuras();
5830 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5832 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5833 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5834 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5835 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5837 (*itr).second->RefreshAura();
5838 return;
5841 return;
5843 default:
5844 break;
5846 break;
5848 case SPELLFAMILY_HUNTER:
5850 switch(m_spellInfo->Id)
5852 case 53209: // Chimera Shot
5854 if (!unitTarget)
5855 return;
5857 uint32 spellId = 0;
5858 int32 basePoint = 0;
5859 Unit* target = unitTarget;
5860 Unit::AuraMap& Auras = unitTarget->GetAuras();
5861 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5863 Aura *aura = (*i).second;
5864 if (aura->GetCasterGUID() != m_caster->GetGUID())
5865 continue;
5867 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5868 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5869 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5870 continue;
5872 // Refresh aura duration
5873 aura->RefreshAura();
5875 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5876 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
5878 // m_amount already include RAP bonus
5879 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5880 spellId = 53353; // Chimera Shot - Serpent
5883 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5884 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
5886 uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
5887 if (!target_max_mana)
5888 continue;
5890 // ignore non positive values (can be result apply spellmods to aura damage
5891 uint32 pdamage = aura->GetModifier()->m_amount > 0 ? aura->GetModifier()->m_amount : 0;
5893 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5894 uint32 maxmana = m_caster->GetMaxPower(POWER_MANA) * pdamage * 2 / 100;
5896 pdamage = target_max_mana * pdamage / 100;
5897 if (pdamage > maxmana)
5898 pdamage = maxmana;
5900 pdamage *= 4; // total aura damage
5901 basePoint = pdamage * 60 / 100;
5902 spellId = 53358; // Chimera Shot - Viper
5903 target = m_caster;
5906 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5907 if (familyFlag & UI64LIT(0x0000000000008000))
5908 spellId = 53359; // Chimera Shot - Scorpid
5909 // ?? nothing say in spell desc (possibly need addition check)
5910 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5911 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5913 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5917 if (spellId)
5918 m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
5920 return;
5922 case 53412: // Invigoration (pet triggered script, master targeted)
5924 if (!unitTarget)
5925 return;
5927 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5928 for(Unit::AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
5930 // Invigoration (master talent)
5931 if ((*i)->GetModifier()->m_miscvalue == 8 && (*i)->GetSpellProto()->SpellIconID == 3487)
5933 if (roll_chance_i((*i)->GetModifier()->m_amount))
5935 unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetGUID());
5936 break;
5940 return;
5942 case 53271: // Master's Call
5944 if (!unitTarget)
5945 return;
5947 // script effect have in value, but this outdated removed part
5948 unitTarget->CastSpell(unitTarget, 62305, true);
5949 return;
5951 default:
5952 break;
5954 break;
5956 case SPELLFAMILY_PALADIN:
5958 // Judgement (seal trigger)
5959 if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
5961 if (!unitTarget || !unitTarget->isAlive())
5962 return;
5964 uint32 spellId1 = 0;
5965 uint32 spellId2 = 0;
5967 // Judgement self add switch
5968 switch (m_spellInfo->Id)
5970 case 53407: spellId1 = 20184; break; // Judgement of Justice
5971 case 20271: // Judgement of Light
5972 case 57774: spellId1 = 20185; break; // Judgement of Light
5973 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5974 default:
5975 sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
5976 return;
5979 // offensive seals have aura dummy in 2 effect
5980 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5981 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5983 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
5984 if ((*itr)->GetEffIndex() != EFFECT_INDEX_2 || !IsSealSpell((*itr)->GetSpellProto()))
5985 continue;
5986 spellId2 = (*itr)->GetModifier()->m_amount;
5987 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5988 if (!judge)
5989 continue;
5990 break;
5993 // if there were no offensive seals than there is seal with proc trigger aura
5994 if (!spellId2)
5996 Unit::AuraList const& procTriggerAuras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
5997 for(Unit::AuraList::const_iterator itr = procTriggerAuras.begin(); itr != procTriggerAuras.end(); ++itr)
5999 if ((*itr)->GetEffIndex() != EFFECT_INDEX_0 || !IsSealSpell((*itr)->GetSpellProto()))
6000 continue;
6001 spellId2 = 54158;
6002 break;
6006 if (spellId1)
6007 m_caster->CastSpell(unitTarget, spellId1, true);
6009 if (spellId2)
6010 m_caster->CastSpell(unitTarget, spellId2, true);
6012 return;
6015 case SPELLFAMILY_POTION:
6017 switch(m_spellInfo->Id)
6019 case 28698: // Dreaming Glory
6021 if (!unitTarget)
6022 return;
6024 unitTarget->CastSpell(unitTarget, 28694, true);
6025 break;
6027 case 28702: // Netherbloom
6029 if (!unitTarget)
6030 return;
6032 // 25% chance of casting a random buff
6033 if (roll_chance_i(75))
6034 return;
6036 // triggered spells are 28703 to 28707
6037 // Note: some sources say, that there was the possibility of
6038 // receiving a debuff. However, this seems to be removed by a patch.
6039 const uint32 spellid = 28703;
6041 // don't overwrite an existing aura
6042 for(uint8 i = 0; i < 5; ++i)
6043 if (unitTarget->HasAura(spellid + i, EFFECT_INDEX_0))
6044 return;
6046 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
6047 break;
6049 case 28720: // Nightmare Vine
6051 if (!unitTarget)
6052 return;
6054 // 25% chance of casting Nightmare Pollen
6055 if (roll_chance_i(75))
6056 return;
6058 unitTarget->CastSpell(unitTarget, 28721, true);
6059 break;
6062 break;
6064 case SPELLFAMILY_DEATHKNIGHT:
6066 switch(m_spellInfo->Id)
6068 case 50842: // Pestilence
6070 if (!unitTarget)
6071 return;
6073 Unit* mainTarget = m_targets.getUnitTarget();
6074 if (!mainTarget)
6075 return;
6077 // do only refresh diseases on main target if caster has Glyph of Disease
6078 if (mainTarget == unitTarget && !m_caster->HasAura(63334))
6079 return;
6081 // Blood Plague
6082 if (mainTarget->HasAura(55078))
6083 m_caster->CastSpell(unitTarget, 55078, true);
6085 // Frost Fever
6086 if (mainTarget->HasAura(55095))
6087 m_caster->CastSpell(unitTarget, 55095, true);
6089 break;
6092 break;
6096 // normal DB scripted effect
6097 if (!unitTarget)
6098 return;
6100 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
6101 m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
6104 void Spell::EffectSanctuary(SpellEffectIndex /*eff_idx*/)
6106 if(!unitTarget)
6107 return;
6108 //unitTarget->CombatStop();
6110 unitTarget->CombatStop();
6111 unitTarget->getHostileRefManager().deleteReferences(); // stop all fighting
6112 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
6113 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
6115 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
6119 void Spell::EffectAddComboPoints(SpellEffectIndex /*eff_idx*/)
6121 if(!unitTarget)
6122 return;
6124 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6125 return;
6127 if(damage <= 0)
6128 return;
6130 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
6133 void Spell::EffectDuel(SpellEffectIndex eff_idx)
6135 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
6136 return;
6138 Player *caster = (Player*)m_caster;
6139 Player *target = (Player*)unitTarget;
6141 // caster or target already have requested duel
6142 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
6143 return;
6145 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
6146 // Don't have to check the target's map since you cannot challenge someone across maps
6147 uint32 mapid = caster->GetMapId();
6148 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
6150 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
6151 return;
6154 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
6155 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
6157 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
6158 return;
6161 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
6162 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
6164 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
6165 return;
6168 //CREATE DUEL FLAG OBJECT
6169 GameObject* pGameObj = new GameObject;
6171 uint32 gameobject_id = m_spellInfo->EffectMiscValue[eff_idx];
6173 Map *map = m_caster->GetMap();
6174 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
6175 map, m_caster->GetPhaseMask(),
6176 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
6177 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
6178 m_caster->GetPositionZ(),
6179 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6181 delete pGameObj;
6182 return;
6185 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
6186 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
6187 int32 duration = GetSpellDuration(m_spellInfo);
6188 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6189 pGameObj->SetSpellId(m_spellInfo->Id);
6191 m_caster->AddGameObject(pGameObj);
6192 map->Add(pGameObj);
6193 //END
6195 // Send request
6196 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
6197 data << uint64(pGameObj->GetGUID());
6198 data << uint64(caster->GetGUID());
6199 caster->GetSession()->SendPacket(&data);
6200 target->GetSession()->SendPacket(&data);
6202 // create duel-info
6203 DuelInfo *duel = new DuelInfo;
6204 duel->initiator = caster;
6205 duel->opponent = target;
6206 duel->startTime = 0;
6207 duel->startTimer = 0;
6208 caster->duel = duel;
6210 DuelInfo *duel2 = new DuelInfo;
6211 duel2->initiator = caster;
6212 duel2->opponent = caster;
6213 duel2->startTime = 0;
6214 duel2->startTimer = 0;
6215 target->duel = duel2;
6217 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
6218 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
6221 void Spell::EffectStuck(SpellEffectIndex /*eff_idx*/)
6223 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6224 return;
6226 if(!sWorld.getConfig(CONFIG_BOOL_CAST_UNSTUCK))
6227 return;
6229 Player* pTarget = (Player*)unitTarget;
6231 sLog.outDebug("Spell Effect: Stuck");
6232 sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ());
6234 if(pTarget->isInFlight())
6235 return;
6237 // homebind location is loaded always
6238 pTarget->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
6240 // Stuck spell trigger Hearthstone cooldown
6241 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
6242 if(!spellInfo)
6243 return;
6244 Spell spell(pTarget, spellInfo, true, 0);
6245 spell.SendSpellCooldown();
6248 void Spell::EffectSummonPlayer(SpellEffectIndex /*eff_idx*/)
6250 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6251 return;
6253 // Evil Twin (ignore player summon, but hide this for summoner)
6254 if(unitTarget->GetDummyAura(23445))
6255 return;
6257 float x, y, z;
6258 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
6260 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
6262 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
6263 data << uint64(m_caster->GetGUID()); // summoner guid
6264 data << uint32(m_caster->GetZoneId()); // summoner zone
6265 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
6266 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6269 static ScriptInfo generateActivateCommand()
6271 ScriptInfo si;
6272 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
6273 return si;
6276 void Spell::EffectActivateObject(SpellEffectIndex eff_idx)
6278 if(!gameObjTarget)
6279 return;
6281 static ScriptInfo activateCommand = generateActivateCommand();
6283 int32 delay_secs = m_spellInfo->CalculateSimpleValue(eff_idx);
6285 gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
6288 void Spell::EffectApplyGlyph(SpellEffectIndex eff_idx)
6290 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6291 return;
6293 Player *player = (Player*)m_caster;
6295 // apply new one
6296 if(uint32 glyph = m_spellInfo->EffectMiscValue[eff_idx])
6298 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
6300 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
6302 if(gp->TypeFlags != gs->TypeFlags)
6304 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
6305 return; // glyph slot mismatch
6309 // remove old glyph
6310 player->ApplyGlyph(m_glyphIndex, false);
6311 player->SetGlyph(m_glyphIndex, glyph);
6312 player->ApplyGlyph(m_glyphIndex, true);
6313 player->SendTalentsInfoData(false);
6318 void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc)
6320 // DBC store slots starting from 1, with no slot 0 value)
6321 int slot = slot_dbc ? slot_dbc - 1 : TOTEM_SLOT_NONE;
6323 // unsummon old totem
6324 if(slot < MAX_TOTEM_SLOT)
6325 if (Totem *OldTotem = m_caster->GetTotem(TotemSlot(slot)))
6326 OldTotem->UnSummon();
6328 uint32 team = 0;
6329 if (m_caster->GetTypeId()==TYPEID_PLAYER)
6330 team = ((Player*)m_caster)->GetTeam();
6332 Totem* pTotem = new Totem;
6334 if(!pTotem->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
6335 m_spellInfo->EffectMiscValue[eff_idx], team ))
6337 delete pTotem;
6338 return;
6341 float angle = slot < MAX_TOTEM_SLOT ? M_PI_F/MAX_TOTEM_SLOT - (slot*2*M_PI_F/MAX_TOTEM_SLOT) : 0;
6343 float x, y, z;
6344 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
6346 // totem must be at same Z in case swimming caster and etc.
6347 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
6348 z = m_caster->GetPositionZ();
6350 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
6352 if (slot < MAX_TOTEM_SLOT)
6353 m_caster->_AddTotem(TotemSlot(slot),pTotem);
6355 pTotem->SetOwner(m_caster->GetGUID());
6356 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
6358 int32 duration=GetSpellDuration(m_spellInfo);
6359 if (Player* modOwner = m_caster->GetSpellModOwner())
6360 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
6361 pTotem->SetDuration(duration);
6363 if (damage) // if not spell info, DB values used
6365 pTotem->SetMaxHealth(damage);
6366 pTotem->SetHealth(damage);
6369 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6371 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6372 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
6374 if(m_caster->IsPvP())
6375 pTotem->SetPvP(true);
6377 if(m_caster->IsFFAPvP())
6378 pTotem->SetFFAPvP(true);
6380 pTotem->Summon(m_caster);
6382 if (slot < MAX_TOTEM_SLOT && m_caster->GetTypeId() == TYPEID_PLAYER)
6384 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
6385 data << uint8(slot);
6386 data << uint64(pTotem->GetGUID());
6387 data << uint32(duration);
6388 data << uint32(m_spellInfo->Id);
6389 ((Player*)m_caster)->SendDirectMessage(&data);
6393 void Spell::EffectEnchantHeldItem(SpellEffectIndex eff_idx)
6395 // this is only item spell effect applied to main-hand weapon of target player (players in area)
6396 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6397 return;
6399 Player* item_owner = (Player*)unitTarget;
6400 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
6402 if(!item )
6403 return;
6405 // must be equipped
6406 if(!item ->IsEquipped())
6407 return;
6409 if (m_spellInfo->EffectMiscValue[eff_idx])
6411 uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx];
6412 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
6413 if(!duration)
6414 duration = m_currentBasePoints[eff_idx]+1; //Base points after ..
6415 if(!duration)
6416 duration = 10; //10 seconds for enchants which don't have listed duration
6418 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
6419 if(!pEnchant)
6420 return;
6422 // Always go to temp enchantment slot
6423 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
6425 // Enchantment will not be applied if a different one already exists
6426 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
6427 return;
6429 // Apply the temporary enchantment
6430 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
6431 item_owner->ApplyEnchantment(item, slot, true);
6435 void Spell::EffectDisEnchant(SpellEffectIndex /*eff_idx*/)
6437 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6438 return;
6440 Player* p_caster = (Player*)m_caster;
6441 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
6442 return;
6444 p_caster->UpdateCraftSkill(m_spellInfo->Id);
6446 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
6448 // item will be removed at disenchanting end
6451 void Spell::EffectInebriate(SpellEffectIndex /*eff_idx*/)
6453 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6454 return;
6456 Player *player = (Player*)unitTarget;
6457 uint16 currentDrunk = player->GetDrunkValue();
6458 uint16 drunkMod = damage * 256;
6459 if (currentDrunk + drunkMod > 0xFFFF)
6460 currentDrunk = 0xFFFF;
6461 else
6462 currentDrunk += drunkMod;
6463 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
6466 void Spell::EffectFeedPet(SpellEffectIndex eff_idx)
6468 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6469 return;
6471 Player *_player = (Player*)m_caster;
6473 Item* foodItem = m_targets.getItemTarget();
6474 if(!foodItem)
6475 return;
6477 Pet *pet = _player->GetPet();
6478 if(!pet)
6479 return;
6481 if(!pet->isAlive())
6482 return;
6484 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
6485 if(benefit <= 0)
6486 return;
6488 uint32 count = 1;
6489 _player->DestroyItemCount(foodItem,count,true);
6490 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6492 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[eff_idx], &benefit, NULL, NULL, true);
6495 void Spell::EffectDismissPet(SpellEffectIndex /*eff_idx*/)
6497 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6498 return;
6500 Pet* pet = m_caster->GetPet();
6502 // not let dismiss dead pet
6503 if(!pet||!pet->isAlive())
6504 return;
6506 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
6509 void Spell::EffectSummonObject(SpellEffectIndex eff_idx)
6511 uint32 go_id = m_spellInfo->EffectMiscValue[eff_idx];
6513 uint8 slot = 0;
6514 switch(m_spellInfo->Effect[eff_idx])
6516 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
6517 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
6518 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
6519 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
6520 default: return;
6523 if(uint64 guid = m_caster->m_ObjectSlot[slot])
6525 if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
6526 obj->SetLootState(GO_JUST_DEACTIVATED);
6527 m_caster->m_ObjectSlot[slot] = 0;
6530 GameObject* pGameObj = new GameObject;
6532 float x, y, z;
6533 // If dest location if present
6534 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6536 x = m_targets.m_destX;
6537 y = m_targets.m_destY;
6538 z = m_targets.m_destZ;
6540 // Summon in random point all other units if location present
6541 else
6542 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
6544 Map *map = m_caster->GetMap();
6545 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
6546 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
6548 delete pGameObj;
6549 return;
6552 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
6553 int32 duration = GetSpellDuration(m_spellInfo);
6554 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6555 pGameObj->SetSpellId(m_spellInfo->Id);
6556 m_caster->AddGameObject(pGameObj);
6558 map->Add(pGameObj);
6560 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
6562 pGameObj->SummonLinkedTrapIfAny();
6565 void Spell::EffectResurrect(SpellEffectIndex /*eff_idx*/)
6567 if(!unitTarget)
6568 return;
6569 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6570 return;
6572 if(unitTarget->isAlive())
6573 return;
6574 if(!unitTarget->IsInWorld())
6575 return;
6577 switch (m_spellInfo->Id)
6579 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6580 case 8342:
6581 if (roll_chance_i(67))
6583 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
6584 return;
6586 break;
6587 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6588 case 22999:
6589 if (roll_chance_i(50))
6591 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
6592 return;
6594 break;
6595 default:
6596 break;
6599 Player* pTarget = ((Player*)unitTarget);
6601 if(pTarget->isRessurectRequested()) // already have one active request
6602 return;
6604 uint32 health = pTarget->GetMaxHealth() * damage / 100;
6605 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
6607 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
6608 SendResurrectRequest(pTarget);
6611 void Spell::EffectAddExtraAttacks(SpellEffectIndex /*eff_idx*/)
6613 if(!unitTarget || !unitTarget->isAlive())
6614 return;
6616 if( unitTarget->m_extraAttacks )
6617 return;
6619 unitTarget->m_extraAttacks = damage;
6622 void Spell::EffectParry(SpellEffectIndex /*eff_idx*/)
6624 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6625 ((Player*)unitTarget)->SetCanParry(true);
6628 void Spell::EffectBlock(SpellEffectIndex /*eff_idx*/)
6630 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6631 ((Player*)unitTarget)->SetCanBlock(true);
6634 void Spell::EffectLeapForward(SpellEffectIndex eff_idx)
6636 if(unitTarget->isInFlight())
6637 return;
6639 if( m_spellInfo->rangeIndex == 1) //self range
6641 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
6643 // before caster
6644 float fx, fy, fz;
6645 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
6646 float ox, oy, oz;
6647 unitTarget->GetPosition(ox, oy, oz);
6649 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
6650 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5f, fx,fy,oz+0.5f,fx2,fy2,fz2, -0.5f))
6652 fx = fx2;
6653 fy = fy2;
6654 fz = fz2;
6655 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
6658 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
6662 void Spell::EffectLeapBack(SpellEffectIndex eff_idx)
6664 if(unitTarget->isInFlight())
6665 return;
6667 m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[eff_idx])/10,float(damage)/10);
6670 void Spell::EffectReputation(SpellEffectIndex eff_idx)
6672 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6673 return;
6675 Player *_player = (Player*)unitTarget;
6677 int32 rep_change = m_currentBasePoints[eff_idx]+1; // field store reputation change -1
6679 uint32 faction_id = m_spellInfo->EffectMiscValue[eff_idx];
6681 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
6683 if(!factionEntry)
6684 return;
6686 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
6689 void Spell::EffectQuestComplete(SpellEffectIndex eff_idx)
6691 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6692 return;
6694 Player *_player = (Player*)m_caster;
6696 uint32 quest_id = m_spellInfo->EffectMiscValue[eff_idx];
6697 _player->AreaExploredOrEventHappens(quest_id);
6700 void Spell::EffectSelfResurrect(SpellEffectIndex eff_idx)
6702 if(!unitTarget || unitTarget->isAlive())
6703 return;
6704 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6705 return;
6706 if(!unitTarget->IsInWorld())
6707 return;
6709 uint32 health = 0;
6710 uint32 mana = 0;
6712 // flat case
6713 if(damage < 0)
6715 health = uint32(-damage);
6716 mana = m_spellInfo->EffectMiscValue[eff_idx];
6718 // percent case
6719 else
6721 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
6722 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
6723 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
6726 Player *plr = ((Player*)unitTarget);
6727 plr->ResurrectPlayer(0.0f);
6729 plr->SetHealth( health );
6730 plr->SetPower(POWER_MANA, mana );
6731 plr->SetPower(POWER_RAGE, 0 );
6732 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
6734 plr->SpawnCorpseBones();
6737 void Spell::EffectSkinning(SpellEffectIndex /*eff_idx*/)
6739 if(unitTarget->GetTypeId() != TYPEID_UNIT )
6740 return;
6741 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
6742 return;
6744 Creature* creature = (Creature*) unitTarget;
6745 int32 targetLevel = creature->getLevel();
6747 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
6749 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
6750 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6752 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
6754 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
6756 // Double chances for elites
6757 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
6760 void Spell::EffectCharge(SpellEffectIndex /*eff_idx*/)
6762 if (!unitTarget)
6763 return;
6765 //TODO: research more ContactPoint/attack distance.
6766 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6767 float x, y, z;
6768 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6770 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6771 ((Creature *)unitTarget)->StopMoving();
6773 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6774 m_caster->MonsterMove(x, y, z, 1);
6776 // not all charge effects used in negative spells
6777 if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6778 m_caster->Attack(unitTarget, true);
6781 void Spell::EffectCharge2(SpellEffectIndex /*eff_idx*/)
6783 float x, y, z;
6784 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6786 x = m_targets.m_destX;
6787 y = m_targets.m_destY;
6788 z = m_targets.m_destZ;
6790 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6791 ((Creature *)unitTarget)->StopMoving();
6793 else if (unitTarget && unitTarget != m_caster)
6794 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6795 else
6796 return;
6798 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6799 m_caster->MonsterMove(x, y, z, 1);
6801 // not all charge effects used in negative spells
6802 if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6803 m_caster->Attack(unitTarget, true);
6806 void Spell::DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction)
6808 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6809 return;
6810 Player* player = (Player*)m_caster;
6812 uint32 pet_entry = m_spellInfo->EffectMiscValue[eff_idx];
6813 if(!pet_entry)
6814 return;
6816 Pet* old_critter = player->GetMiniPet();
6818 // for same pet just despawn
6819 if(old_critter && old_critter->GetEntry() == pet_entry)
6821 player->RemoveMiniPet();
6822 return;
6825 // despawn old pet before summon new
6826 if(old_critter)
6827 player->RemoveMiniPet();
6829 // summon new pet
6830 Pet* critter = new Pet(MINI_PET);
6832 Map *map = m_caster->GetMap();
6833 uint32 pet_number = sObjectMgr.GeneratePetNumber();
6834 if(!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
6835 pet_entry, pet_number))
6837 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
6838 delete critter;
6839 return;
6842 float x, y, z;
6843 // If dest location if present
6844 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6846 x = m_targets.m_destX;
6847 y = m_targets.m_destY;
6848 z = m_targets.m_destZ;
6850 // Summon if dest location not present near caster
6851 else
6852 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
6854 critter->Relocate(x, y, z, m_caster->GetOrientation());
6856 if(!critter->IsPositionValid())
6858 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6859 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
6860 delete critter;
6861 return;
6864 critter->SetOwnerGUID(m_caster->GetGUID());
6865 critter->SetCreatorGUID(m_caster->GetGUID());
6867 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6868 critter->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
6869 critter->AIM_Initialize();
6870 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6871 //critter->InitLevelupSpellsForLevel(); // none?
6872 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6873 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
6874 // some mini-pets have quests
6876 // set timer for unsummon
6877 int32 duration = GetSpellDuration(m_spellInfo);
6878 if(duration > 0)
6879 critter->SetDuration(duration);
6881 std::string name = player->GetName();
6882 name.append(petTypeSuffix[critter->getPetType()]);
6883 critter->SetName( name );
6884 player->SetMiniPet(critter);
6886 map->Add((Creature*)critter);
6889 void Spell::EffectKnockBack(SpellEffectIndex eff_idx)
6891 if(!unitTarget)
6892 return;
6894 unitTarget->KnockBackFrom(m_caster,float(m_spellInfo->EffectMiscValue[eff_idx])/10,float(damage)/10);
6897 void Spell::EffectSendTaxi(SpellEffectIndex eff_idx)
6899 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6900 return;
6902 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[eff_idx],m_spellInfo->Id);
6905 void Spell::EffectPlayerPull(SpellEffectIndex eff_idx)
6907 if(!unitTarget)
6908 return;
6910 float dist = unitTarget->GetDistance2d(m_caster);
6911 if (damage && dist > damage)
6912 dist = float(damage);
6914 unitTarget->KnockBackFrom(m_caster,-dist,float(m_spellInfo->EffectMiscValue[eff_idx])/10);
6917 void Spell::EffectDispelMechanic(SpellEffectIndex eff_idx)
6919 if(!unitTarget)
6920 return;
6922 uint32 mechanic = m_spellInfo->EffectMiscValue[eff_idx];
6924 Unit::AuraMap& Auras = unitTarget->GetAuras();
6925 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6927 next = iter;
6928 ++next;
6929 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6930 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6932 unitTarget->RemoveAurasDueToSpell(spell->Id);
6933 if(Auras.empty())
6934 break;
6935 else
6936 next = Auras.begin();
6939 return;
6942 void Spell::EffectSummonDeadPet(SpellEffectIndex /*eff_idx*/)
6944 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6945 return;
6946 Player *_player = (Player*)m_caster;
6947 Pet *pet = _player->GetPet();
6948 if(!pet)
6949 return;
6950 if(pet->isAlive())
6951 return;
6952 if(damage < 0)
6953 return;
6954 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6955 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6956 pet->setDeathState( ALIVE );
6957 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6958 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6960 pet->AIM_Initialize();
6962 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6963 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6966 void Spell::EffectSummonAllTotems(SpellEffectIndex eff_idx)
6968 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6969 return;
6971 int32 start_button = ACTION_BUTTON_SHAMAN_TOTEMS_BAR + m_spellInfo->EffectMiscValue[eff_idx];
6972 int32 amount_buttons = m_spellInfo->EffectMiscValueB[eff_idx];
6974 for(int32 slot = 0; slot < amount_buttons; ++slot)
6975 if (ActionButton const* actionButton = ((Player*)m_caster)->GetActionButton(start_button+slot))
6976 if (actionButton->GetType()==ACTION_BUTTON_SPELL)
6977 if (uint32 spell_id = actionButton->GetAction())
6978 m_caster->CastSpell(unitTarget,spell_id,true);
6981 void Spell::EffectDestroyAllTotems(SpellEffectIndex /*eff_idx*/)
6983 int32 mana = 0;
6984 for(int slot = 0; slot < MAX_TOTEM_SLOT; ++slot)
6986 if (Totem* totem = m_caster->GetTotem(TotemSlot(slot)))
6988 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6989 if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id))
6991 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
6992 mana += manacost * damage / 100;
6994 totem->UnSummon();
6998 if (mana)
6999 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
7002 void Spell::EffectDurabilityDamage(SpellEffectIndex eff_idx)
7004 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7005 return;
7007 int32 slot = m_spellInfo->EffectMiscValue[eff_idx];
7009 // FIXME: some spells effects have value -1/-2
7010 // Possibly its mean -1 all player equipped items and -2 all items
7011 if(slot < 0)
7013 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
7014 return;
7017 // invalid slot value
7018 if(slot >= INVENTORY_SLOT_BAG_END)
7019 return;
7021 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
7022 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
7025 void Spell::EffectDurabilityDamagePCT(SpellEffectIndex eff_idx)
7027 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7028 return;
7030 int32 slot = m_spellInfo->EffectMiscValue[eff_idx];
7032 // FIXME: some spells effects have value -1/-2
7033 // Possibly its mean -1 all player equipped items and -2 all items
7034 if(slot < 0)
7036 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
7037 return;
7040 // invalid slot value
7041 if(slot >= INVENTORY_SLOT_BAG_END)
7042 return;
7044 if(damage <= 0)
7045 return;
7047 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
7048 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
7051 void Spell::EffectModifyThreatPercent(SpellEffectIndex /*eff_idx*/)
7053 if(!unitTarget)
7054 return;
7056 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
7059 void Spell::EffectTransmitted(SpellEffectIndex eff_idx)
7061 uint32 name_id = m_spellInfo->EffectMiscValue[eff_idx];
7063 GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
7065 if (!goinfo)
7067 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
7068 return;
7071 float fx, fy, fz;
7073 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
7075 fx = m_targets.m_destX;
7076 fy = m_targets.m_destY;
7077 fz = m_targets.m_destZ;
7079 //FIXME: this can be better check for most objects but still hack
7080 else if(m_spellInfo->EffectRadiusIndex[eff_idx] && m_spellInfo->speed==0)
7082 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx]));
7083 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
7085 else
7087 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
7088 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
7089 float dis = rand_norm_f() * (max_dis - min_dis) + min_dis;
7091 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
7094 Map *cMap = m_caster->GetMap();
7096 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
7098 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
7099 { // but this is not proper, we really need to ignore not materialized objects
7100 SendCastResult(SPELL_FAILED_NOT_HERE);
7101 SendChannelUpdate(0);
7102 return;
7105 // replace by water level in this case
7106 fz = cMap->GetWaterLevel(fx, fy);
7108 // if gameobject is summoning object, it should be spawned right on caster's position
7109 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
7111 m_caster->GetPosition(fx, fy, fz);
7114 GameObject* pGameObj = new GameObject;
7116 if(!pGameObj->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
7117 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
7119 delete pGameObj;
7120 return;
7123 int32 duration = GetSpellDuration(m_spellInfo);
7125 switch(goinfo->type)
7127 case GAMEOBJECT_TYPE_FISHINGNODE:
7129 m_caster->SetChannelObjectGUID(pGameObj->GetGUID());
7130 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
7132 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
7133 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
7134 int32 lastSec = 0;
7135 switch(urand(0, 3))
7137 case 0: lastSec = 3; break;
7138 case 1: lastSec = 7; break;
7139 case 2: lastSec = 13; break;
7140 case 3: lastSec = 17; break;
7143 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
7144 break;
7146 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
7148 if(m_caster->GetTypeId() == TYPEID_PLAYER)
7150 pGameObj->AddUniqueUse((Player*)m_caster);
7151 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
7153 break;
7155 case GAMEOBJECT_TYPE_FISHINGHOLE:
7156 case GAMEOBJECT_TYPE_CHEST:
7157 default:
7158 break;
7161 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
7163 pGameObj->SetOwnerGUID(m_caster->GetGUID());
7165 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
7166 pGameObj->SetSpellId(m_spellInfo->Id);
7168 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
7169 //m_caster->AddGameObject(pGameObj);
7170 //m_ObjToDel.push_back(pGameObj);
7172 cMap->Add(pGameObj);
7174 pGameObj->SummonLinkedTrapIfAny();
7177 void Spell::EffectProspecting(SpellEffectIndex /*eff_idx*/)
7179 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7180 return;
7182 Player* p_caster = (Player*)m_caster;
7183 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
7184 return;
7186 if(itemTarget->GetCount() < 5)
7187 return;
7189 if( sWorld.getConfig(CONFIG_BOOL_SKILL_PROSPECTING))
7191 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
7192 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
7193 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
7196 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
7199 void Spell::EffectMilling(SpellEffectIndex /*eff_idx*/)
7201 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7202 return;
7204 Player* p_caster = (Player*)m_caster;
7205 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
7206 return;
7208 if(itemTarget->GetCount() < 5)
7209 return;
7211 if( sWorld.getConfig(CONFIG_BOOL_SKILL_MILLING))
7213 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
7214 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
7215 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
7218 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
7221 void Spell::EffectSkill(SpellEffectIndex /*eff_idx*/)
7223 sLog.outDebug("WORLD: SkillEFFECT");
7226 void Spell::EffectSpiritHeal(SpellEffectIndex /*eff_idx*/)
7228 // TODO player can't see the heal-animation - he should respawn some ticks later
7229 if (!unitTarget || unitTarget->isAlive())
7230 return;
7231 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
7232 return;
7233 if (!unitTarget->IsInWorld())
7234 return;
7235 if (m_spellInfo->Id == 22012 && !unitTarget->HasAura(2584))
7236 return;
7238 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
7239 ((Player*)unitTarget)->SpawnCorpseBones();
7242 // remove insignia spell effect
7243 void Spell::EffectSkinPlayerCorpse(SpellEffectIndex /*eff_idx*/)
7245 sLog.outDebug("Effect: SkinPlayerCorpse");
7246 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
7247 return;
7249 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
7252 void Spell::EffectStealBeneficialBuff(SpellEffectIndex eff_idx)
7254 sLog.outDebug("Effect: StealBeneficialBuff");
7256 if(!unitTarget || unitTarget==m_caster) // can't steal from self
7257 return;
7259 std::vector <Aura *> steal_list;
7260 // Create dispel mask by dispel type
7261 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[eff_idx]) );
7262 Unit::AuraMap const& auras = unitTarget->GetAuras();
7263 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
7265 Aura *aur = (*itr).second;
7266 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
7268 // Need check for passive? this
7269 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
7270 steal_list.push_back(aur);
7273 // Ok if exist some buffs for dispel try dispel it
7274 if (!steal_list.empty())
7276 std::list < std::pair<uint32,uint64> > success_list;
7277 int32 list_size = steal_list.size();
7278 // Dispell N = damage buffs (or while exist buffs for dispel)
7279 for (int32 count=0; count < damage && list_size > 0; ++count)
7281 // Random select buff for dispel
7282 Aura *aur = steal_list[urand(0, list_size-1)];
7283 // Not use chance for steal
7284 // TODO possible need do it
7285 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
7287 // Remove buff from list for prevent doubles
7288 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
7290 Aura *stealed = *j;
7291 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
7293 j = steal_list.erase(j);
7294 --list_size;
7296 else
7297 ++j;
7300 // Really try steal and send log
7301 if (!success_list.empty())
7303 int32 count = success_list.size();
7304 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
7305 data.append(unitTarget->GetPackGUID()); // Victim GUID
7306 data.append(m_caster->GetPackGUID()); // Caster GUID
7307 data << uint32(m_spellInfo->Id); // Dispell spell id
7308 data << uint8(0); // not used
7309 data << uint32(count); // count
7310 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
7312 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
7313 data << uint32(spellInfo->Id); // Spell Id
7314 data << uint8(0); // 0 - steals !=0 transfers
7315 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
7317 m_caster->SendMessageToSet(&data, true);
7322 void Spell::EffectKillCreditPersonal(SpellEffectIndex eff_idx)
7324 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7325 return;
7327 ((Player*)unitTarget)->KilledMonsterCredit(m_spellInfo->EffectMiscValue[eff_idx], 0);
7330 void Spell::EffectKillCredit(SpellEffectIndex eff_idx)
7332 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7333 return;
7335 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[eff_idx], unitTarget);
7338 void Spell::EffectQuestFail(SpellEffectIndex eff_idx)
7340 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7341 return;
7343 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[eff_idx]);
7346 void Spell::EffectActivateRune(SpellEffectIndex eff_idx)
7348 if(m_caster->GetTypeId() != TYPEID_PLAYER)
7349 return;
7351 Player *plr = (Player*)m_caster;
7353 if(plr->getClass() != CLASS_DEATH_KNIGHT)
7354 return;
7356 for(uint32 j = 0; j < MAX_RUNES; ++j)
7358 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == RuneType(m_spellInfo->EffectMiscValue[eff_idx]))
7360 plr->SetRuneCooldown(j, 0);
7365 void Spell::EffectTitanGrip(SpellEffectIndex /*eff_idx*/)
7367 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
7368 ((Player*)unitTarget)->SetCanTitanGrip(true);
7371 void Spell::EffectRenamePet(SpellEffectIndex /*eff_idx*/)
7373 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
7374 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
7375 return;
7377 unitTarget->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
7380 void Spell::EffectPlayMusic(SpellEffectIndex eff_idx)
7382 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7383 return;
7385 uint32 soundid = m_spellInfo->EffectMiscValue[eff_idx];
7387 if (!sSoundEntriesStore.LookupEntry(soundid))
7389 sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
7390 return;
7393 WorldPacket data(SMSG_PLAY_MUSIC, 4);
7394 data << uint32(soundid);
7395 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
7398 void Spell::EffectSpecCount(SpellEffectIndex /*eff_idx*/)
7400 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7401 return;
7403 ((Player*)unitTarget)->UpdateSpecCount(damage);
7406 void Spell::EffectActivateSpec(SpellEffectIndex /*eff_idx*/)
7408 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7409 return;
7411 uint32 spec = damage-1;
7413 ((Player*)unitTarget)->ActivateSpec(spec);
7416 void Spell::EffectBind(SpellEffectIndex eff_idx)
7418 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
7419 return;
7421 Player* player = (Player*)unitTarget;
7423 uint32 area_id;
7424 WorldLocation loc;
7425 if (m_spellInfo->EffectImplicitTargetA[eff_idx] == TARGET_TABLE_X_Y_Z_COORDINATES ||
7426 m_spellInfo->EffectImplicitTargetB[eff_idx] == TARGET_TABLE_X_Y_Z_COORDINATES)
7428 SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id);
7429 if (!st)
7431 sLog.outError( "Spell::EffectBind - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
7432 return;
7435 loc.mapid = st->target_mapId;
7436 loc.coord_x = st->target_X;
7437 loc.coord_y = st->target_Y;
7438 loc.coord_z = st->target_Y;
7439 loc.orientation = st->target_Orientation;
7440 area_id = sMapMgr.GetAreaId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z);
7442 else
7444 player->GetPosition(loc);
7445 area_id = player->GetAreaId();
7448 player->SetHomebindToLocation(loc,area_id);
7450 // binding
7451 WorldPacket data( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
7452 data << float(loc.coord_x);
7453 data << float(loc.coord_y);
7454 data << float(loc.coord_z);
7455 data << uint32(loc.mapid);
7456 data << uint32(area_id);
7457 player->SendDirectMessage( &data );
7459 DEBUG_LOG("New Home Position X is %f", loc.coord_x);
7460 DEBUG_LOG("New Home Position Y is %f", loc.coord_y);
7461 DEBUG_LOG("New Home Position Z is %f", loc.coord_z);
7462 DEBUG_LOG("New Home MapId is %u", loc.mapid);
7463 DEBUG_LOG("New Home AreaId is %u", area_id);
7465 // zone update
7466 data.Initialize(SMSG_PLAYERBOUND, 8+4);
7467 data << uint64(player->GetGUID());
7468 data << uint32(area_id);
7469 player->SendMessageToSet( &data, true );
7472 void Spell::EffectRestoreItemCharges( SpellEffectIndex eff_idx )
7474 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
7475 return;
7477 Player* player = (Player*)unitTarget;
7479 ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(m_spellInfo->EffectItemType[eff_idx]);
7480 if (!itemProto)
7481 return;
7483 // In case item from limited category recharge any from category, is this valid checked early in spell checks
7484 Item* item;
7485 if (itemProto->ItemLimitCategory)
7486 item = player->GetItemByLimitedCategory(itemProto->ItemLimitCategory);
7487 else
7488 item = player->GetItemByEntry(m_spellInfo->EffectItemType[eff_idx]);
7490 if (!item)
7491 return;
7493 item->RestoreCharges();
7496 void Spell::EffectTeachTaxiNode( SpellEffectIndex eff_idx )
7498 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
7499 return;
7501 Player* player = (Player*)unitTarget;
7503 uint32 taxiNodeId = m_spellInfo->EffectMiscValue[eff_idx];
7504 if (!sTaxiNodesStore.LookupEntry(taxiNodeId))
7505 return;
7507 if (player->m_taxi.SetTaximaskNode(taxiNodeId))
7509 WorldPacket data(SMSG_NEW_TAXI_PATH, 0);
7510 player->SendDirectMessage( &data );
7512 data.Initialize( SMSG_TAXINODE_STATUS, 9 );
7513 data << uint64( m_caster->GetGUID() );
7514 data << uint8( 1 );
7515 player->SendDirectMessage( &data );