[8425] Implement SPELL_EFFECT_LEAP_BACK and spell 781
[getmangos.git] / src / game / SpellEffects.cpp
bloba52d573239d0553cf436608e29b848cab7ce997e
1 /*
2 * Copyright (C) 2005-2009 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
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG, // 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::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
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::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 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::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 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::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused, // 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 we must spawn pet there
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
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
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::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is 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::EffectUnused, // 73 SPELL_EFFECT_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::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
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_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::EffectUnused, // 97 SPELL_EFFECT_97
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
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::EffectUnused, //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::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectCharge2, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
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::EffectNULL, //154 unused
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 unused
221 &Spell::EffectNULL, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectNULL, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectNULL(uint32 /*i*/)
227 sLog.outDebug("WORLD: Spell Effect DUMMY");
230 void Spell::EffectUnused(uint32 /*i*/)
232 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
235 void Spell::EffectResurrectNew(uint32 i)
237 if(!unitTarget || unitTarget->isAlive())
238 return;
240 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
241 return;
243 if(!unitTarget->IsInWorld())
244 return;
246 Player* pTarget = ((Player*)unitTarget);
248 if(pTarget->isRessurectRequested()) // already have one active request
249 return;
251 uint32 health = damage;
252 uint32 mana = m_spellInfo->EffectMiscValue[i];
253 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
254 SendResurrectRequest(pTarget);
257 void Spell::EffectInstaKill(uint32 /*i*/)
259 if( !unitTarget || !unitTarget->isAlive() )
260 return;
262 // Demonic Sacrifice
263 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
265 uint32 entry = unitTarget->GetEntry();
266 uint32 spellID;
267 switch(entry)
269 case 416: spellID=18789; break; //imp
270 case 417: spellID=18792; break; //fellhunter
271 case 1860: spellID=18790; break; //void
272 case 1863: spellID=18791; break; //succubus
273 case 17252: spellID=35701; break; //fellguard
274 default:
275 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry);
276 return;
279 m_caster->CastSpell(m_caster, spellID, true);
282 if(m_caster == unitTarget) // prevent interrupt message
283 finish();
285 m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
288 void Spell::EffectEnvirinmentalDMG(uint32 i)
290 uint32 absorb = 0;
291 uint32 resist = 0;
293 // Note: this hack with damage replace required until GO casting not implemented
294 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
295 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
296 damage = m_spellInfo->CalculateSimpleValue(i);
298 m_caster->CalcAbsorbResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
300 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
301 if(m_caster->GetTypeId() == TYPEID_PLAYER)
302 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage);
305 void Spell::EffectSchoolDMG(uint32 effect_idx)
307 if( unitTarget && unitTarget->isAlive())
309 switch(m_spellInfo->SpellFamilyName)
311 case SPELLFAMILY_GENERIC:
313 switch(m_spellInfo->Id) // better way to check unknown
315 // Meteor like spells (divided damage to targets)
316 case 24340: case 26558: case 28884: // Meteor
317 case 36837: case 38903: case 41276: // Meteor
318 case 26789: // Shard of the Fallen Star
319 case 31436: // Malevolent Cleave
320 case 35181: // Dive Bomb
321 case 40810: case 43267: case 43268: // Saber Lash
322 case 42384: // Brutal Swipe
323 case 45150: // Meteor Slash
324 case 64422: case 64688: // Sonic Screech
326 uint32 count = 0;
327 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
328 if(ihit->effectMask & (1<<effect_idx))
329 ++count;
331 damage /= count; // divide to all targets
332 break;
334 // percent from health with min
335 case 25599: // Thundercrash
337 damage = unitTarget->GetHealth() / 2;
338 if(damage < 200)
339 damage = 200;
340 break;
342 // Intercept (warrior spell trigger)
343 case 20253:
344 case 61491:
346 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
347 break;
349 // Cataclysmic Bolt
350 case 38441:
351 damage = unitTarget->GetMaxHealth() / 2;
352 break;
354 break;
357 case SPELLFAMILY_MAGE:
359 // Arcane Blast
360 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
362 m_caster->CastSpell(m_caster, 36032, true);
364 break;
366 case SPELLFAMILY_WARRIOR:
368 // Bloodthirst
369 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
371 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
373 // Shield Slam
374 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
375 damage += int32(m_caster->GetShieldBlockValue());
376 // Victory Rush
377 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
379 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
380 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
382 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
383 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
384 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
385 // Heroic Throw ${$m1+$AP*.50}
386 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
387 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
388 // Shockwave ${$m3/100*$AP}
389 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
391 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
392 if (pct > 0)
393 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
394 break;
396 // Thunder Clap
397 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000080))
399 damage+=int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
401 break;
403 case SPELLFAMILY_WARLOCK:
405 // Incinerate Rank 1 & 2
406 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
408 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
409 // Check aura state for speed but aura state set not only for Immolate spell
410 if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
412 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
413 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
415 // Immolate
416 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
417 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
419 damage += damage/4;
420 break;
425 // Shadowflame
426 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
428 // Apply DOT part
429 switch(m_spellInfo->Id)
431 case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
432 case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
433 default:
434 sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
435 break;
438 // Conflagrate - consumes Immolate or Shadowflame
439 else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
441 Aura const* aura = NULL; // found req. aura for damage calculation
443 Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
444 for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
446 // for caster applied auras only
447 if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
448 (*i)->GetCasterGUID()!=m_caster->GetGUID())
449 continue;
451 // Immolate
452 if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
454 aura = *i; // it selected always if exist
455 break;
458 // Shadowflame
459 if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
460 aura = *i; // remember but wait possible Immolate as primary priority
463 // found Immolate or Shadowflame
464 if (aura)
466 int32 damagetick = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), aura->GetModifier()->m_amount, DOT);
467 damage += damagetick * 4;
469 // Glyph of Conflagrate
470 if (!m_caster->HasAura(56235))
471 unitTarget->RemoveAurasByCasterSpell(aura->GetId(), m_caster->GetGUID());
472 break;
475 break;
477 case SPELLFAMILY_PRIEST:
479 // Shadow Word: Death - deals damage equal to damage done to caster
480 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000))
481 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
482 break;
484 case SPELLFAMILY_DRUID:
486 // Ferocious Bite
487 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
489 // converts each extra point of energy into ($f1+$AP/410) additional damage
490 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
491 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
492 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
493 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
494 m_caster->SetPower(POWER_ENERGY,0);
496 // Rake
497 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[2]==SPELL_EFFECT_ADD_COMBO_POINTS)
499 // $AP*0.01 bonus
500 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
502 // Swipe
503 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
505 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
507 break;
509 case SPELLFAMILY_ROGUE:
511 // Envenom
512 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)))
514 // consume from stack dozes not more that have combo-points
515 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
517 Aura *poison = 0;
518 // Lookup for Deadly poison (only attacker applied)
519 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
520 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
521 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
522 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x10000)) &&
523 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
525 poison = *itr;
526 break;
528 // count consumed deadly poison doses at target
529 if (poison)
531 uint32 spellId = poison->GetId();
532 uint32 doses = poison->GetStackAmount();
533 if (doses > combo)
534 doses = combo;
535 for (int i=0; i< doses; i++)
536 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
537 damage *= doses;
538 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
540 // Eviscerate and Envenom Bonus Damage (item set effect)
541 if(m_caster->GetDummyAura(37169))
542 damage += ((Player*)m_caster)->GetComboPoints()*40;
545 // Eviscerate
546 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
548 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
550 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
551 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
553 // Eviscerate and Envenom Bonus Damage (item set effect)
554 if(m_caster->GetDummyAura(37169))
555 damage += combo*40;
558 // Gouge
559 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
561 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
563 // Instant Poison
564 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
566 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
568 // Wound Poison
569 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
571 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
573 break;
575 case SPELLFAMILY_HUNTER:
577 //Gore
578 if (m_spellInfo->SpellIconID == 1578)
580 if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
581 damage *= 2;
583 // Mongoose Bite
584 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
586 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
588 // Counterattack
589 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
591 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
593 // Arcane Shot
594 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
596 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
598 // Steady Shot
599 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
601 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
602 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
604 // Explosive Trap Effect
605 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
607 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
609 break;
611 case SPELLFAMILY_PALADIN:
613 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
614 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
616 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
617 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
618 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
619 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
620 // Get stack of Holy Vengeance on the target added by caster
621 uint32 stacks = 0;
622 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
623 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
624 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
626 stacks = (*itr)->GetStackAmount();
627 break;
629 // + 10% for each application of Holy Vengeance on the target
630 if(stacks)
631 damage += damage * stacks * 10 /100;
633 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
634 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
636 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
637 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
638 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
639 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
641 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
642 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
644 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
645 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
646 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
647 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
649 // Hammer of the Righteous
650 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
652 // Add main hand dps * effect[2] amount
653 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
654 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
655 damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
657 // Shield of Righteousness
658 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
660 damage+=int32(m_caster->GetShieldBlockValue());
662 break;
666 if(damage >= 0)
667 m_damage += damage;
671 void Spell::EffectDummy(uint32 i)
673 if (!unitTarget && !gameObjTarget && !itemTarget)
674 return;
676 // selection by spell family
677 switch(m_spellInfo->SpellFamilyName)
679 case SPELLFAMILY_GENERIC:
681 switch(m_spellInfo->Id )
683 case 8063: // Deviate Fish
685 if (m_caster->GetTypeId() != TYPEID_PLAYER)
686 return;
688 uint32 spell_id = 0;
689 switch(urand(1,5))
691 case 1: spell_id = 8064; break; // Sleepy
692 case 2: spell_id = 8065; break; // Invigorate
693 case 3: spell_id = 8066; break; // Shrink
694 case 4: spell_id = 8067; break; // Party Time!
695 case 5: spell_id = 8068; break; // Healthy Spirit
697 m_caster->CastSpell(m_caster, spell_id, true, NULL);
698 return;
700 case 8213: // Savory Deviate Delight
702 if (m_caster->GetTypeId() != TYPEID_PLAYER)
703 return;
705 uint32 spell_id = 0;
706 switch(urand(1,2))
708 // Flip Out - ninja
709 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
710 // Yaaarrrr - pirate
711 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
713 m_caster->CastSpell(m_caster,spell_id,true,NULL);
714 return;
716 case 8593: // Symbol of life (restore creature to life)
717 case 31225: // Shimmering Vessel (restore creature to life)
719 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
720 return;
721 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
722 return;
724 case 12162: // Deep wounds
725 case 12850: // (now good common check for this spells)
726 case 12868:
728 if (!unitTarget)
729 return;
731 float damage;
732 // DW should benefit of attack power, damage percent mods etc.
733 // TODO: check if using offhand damage is correct and if it should be divided by 2
734 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
735 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
736 else
737 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
739 switch (m_spellInfo->Id)
741 case 12162: damage *= 0.16f; break; // Rank 1
742 case 12850: damage *= 0.32f; break; // Rank 2
743 case 12868: damage *= 0.48f; break; // Rank 3
744 default:
745 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
746 return;
749 // get remaining damage of old Deep Wound aura
750 Aura* deepWound = unitTarget->GetAura(12721, 0);
751 if (deepWound)
753 int32 remainingTicks = deepWound->GetAuraDuration() / deepWound->GetModifier()->periodictime;
754 damage += remainingTicks * deepWound->GetModifier()->m_amount;
757 // 1 tick/sec * 6 sec = 6 ticks
758 int32 deepWoundsDotBasePoints0 = int32(damage / 6);
759 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
760 return;
762 case 13120: // net-o-matic
764 if (!unitTarget)
765 return;
767 uint32 spell_id = 0;
769 uint32 roll = urand(0, 99);
771 if (roll < 2) // 2% for 30 sec self root (off-like chance unknown)
772 spell_id = 16566;
773 else if (roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
774 spell_id = 13119;
775 else // normal root
776 spell_id = 13099;
778 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
779 return;
781 case 13567: // Dummy Trigger
783 // can be used for different aura triggering, so select by aura
784 if (!m_triggeredByAuraSpell || !unitTarget)
785 return;
787 switch(m_triggeredByAuraSpell->Id)
789 case 26467: // Persistent Shield
790 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
791 break;
792 default:
793 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
794 break;
796 return;
798 case 15998: // Capture Worg Pup
799 case 29435: // Capture Female Kaliri Hatchling
801 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
802 return;
804 Creature* creatureTarget = (Creature*)unitTarget;
806 creatureTarget->ForcedDespawn();
807 return;
809 case 16589: // Noggenfogger Elixir
811 if (m_caster->GetTypeId() != TYPEID_PLAYER)
812 return;
814 uint32 spell_id = 0;
815 switch(urand(1, 3))
817 case 1: spell_id = 16595; break;
818 case 2: spell_id = 16593; break;
819 default:spell_id = 16591; break;
822 m_caster->CastSpell(m_caster, spell_id, true, NULL);
823 return;
825 case 17251: // Spirit Healer Res
827 if (!unitTarget || !m_originalCaster)
828 return;
830 if (m_originalCaster->GetTypeId() == TYPEID_PLAYER)
832 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
833 data << uint64(unitTarget->GetGUID());
834 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
836 return;
838 case 17271: // Test Fetid Skull
840 if (!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
841 return;
843 uint32 spell_id = roll_chance_i(50)
844 ? 17269 // Create Resonating Skull
845 : 17270; // Create Bone Dust
847 m_caster->CastSpell(m_caster, spell_id, true, NULL);
848 return;
850 case 20577: // Cannibalize
851 if (unitTarget)
852 m_caster->CastSpell(m_caster, 20578, false, NULL);
853 return;
854 case 23019: // Crystal Prison Dummy DND
856 if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
857 return;
859 Creature* creatureTarget = (Creature*)unitTarget;
860 if (creatureTarget->isPet())
861 return;
863 GameObject* pGameObj = new GameObject;
865 Map *map = creatureTarget->GetMap();
867 // create before death for get proper coordinates
868 if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
869 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
870 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
872 delete pGameObj;
873 return;
876 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
877 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
878 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
879 pGameObj->SetSpellId(m_spellInfo->Id);
881 creatureTarget->ForcedDespawn();
883 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
884 map->Add(pGameObj);
886 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
887 data << uint64(pGameObj->GetGUID());
888 m_caster->SendMessageToSet(&data, true);
890 return;
892 case 23074: // Arcanite Dragonling
893 if (!m_CastItem)
894 return;
895 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
896 return;
897 case 23075: // Mithril Mechanical Dragonling
898 if (!m_CastItem)
899 return;
900 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
901 return;
902 case 23076: // Mechanical Dragonling
903 if (!m_CastItem)
904 return;
905 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
906 return;
907 case 23133: // Gnomish Battle Chicken
908 if (!m_CastItem)
909 return;
910 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
911 return;
912 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
914 int32 r = irand(0, 119);
915 if (r < 20) // Transporter Malfunction - 1/6 polymorph
916 m_caster->CastSpell(m_caster, 23444, true);
917 else if (r < 100) // Evil Twin - 4/6 evil twin
918 m_caster->CastSpell(m_caster, 23445, true);
919 else // Transporter Malfunction - 1/6 miss the target
920 m_caster->CastSpell(m_caster, 36902, true);
921 return;
923 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
924 if (roll_chance_i(50)) // Gadgetzan Transporter - success
925 m_caster->CastSpell(m_caster, 23441, true);
926 else // Gadgetzan Transporter Failure - failure
927 m_caster->CastSpell(m_caster, 23446, true);
928 return;
929 case 23645: // Hourglass Sand
930 m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
931 return;
932 case 23725: // Gift of Life (warrior bwl trinket)
933 m_caster->CastSpell(m_caster, 23782, true);
934 m_caster->CastSpell(m_caster, 23783, true);
935 return;
936 case 25860: // Reindeer Transformation
938 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
939 return;
941 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
942 float speed = m_caster->GetSpeedRate(MOVE_RUN);
944 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
946 //5 different spells used depending on mounted speed and if mount can fly or not
947 if (flyspeed >= 4.1f)
948 // Flying Reindeer
949 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
950 else if (flyspeed >= 3.8f)
951 // Flying Reindeer
952 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
953 else if (flyspeed >= 1.6f)
954 // Flying Reindeer
955 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
956 else if (speed >= 2.0f)
957 // Reindeer
958 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
959 else
960 // Reindeer
961 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
963 return;
965 case 26074: // Holiday Cheer
966 // implemented at client side
967 return;
968 case 28006: // Arcane Cloaking
970 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
971 // Naxxramas Entry Flag Effect DND
972 m_caster->CastSpell(unitTarget, 29294, true);
973 return;
975 case 29200: // Purify Helboar Meat
977 if (m_caster->GetTypeId() != TYPEID_PLAYER)
978 return;
980 uint32 spell_id = roll_chance_i(50)
981 ? 29277 // Summon Purified Helboar Meat
982 : 29278; // Summon Toxic Helboar Meat
984 m_caster->CastSpell(m_caster,spell_id,true,NULL);
985 return;
987 case 29858: // Soulshatter
988 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
989 m_caster->CastSpell(unitTarget,32835,true);
990 return;
991 case 30458: // Nigh Invulnerability
992 if (!m_CastItem)
993 return;
994 if (roll_chance_i(86)) // Nigh-Invulnerability - success
995 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
996 else // Complete Vulnerability - backfire in 14% casts
997 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
998 return;
999 case 30507: // Poultryizer
1000 if(!m_CastItem)
1001 return;
1002 if (roll_chance_i(80)) // Poultryized! - success
1003 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1004 else // Poultryized! - backfire 20%
1005 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1006 return;
1007 case 33060: // Make a Wish
1009 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1010 return;
1012 uint32 spell_id = 0;
1014 switch(urand(1,5))
1016 case 1: spell_id = 33053; break; // Mr Pinchy's Blessing
1017 case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy
1018 case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy
1019 case 4: spell_id = 33062; break; // Tiny Magical Crawdad
1020 case 5: spell_id = 33064; break; // Mr. Pinchy's Gift
1023 m_caster->CastSpell(m_caster, spell_id, true, NULL);
1024 return;
1026 case 35745: // Socrethar's Stone
1028 uint32 spell_id;
1029 switch(m_caster->GetAreaId())
1031 case 3900: spell_id = 35743; break; // Socrethar Portal
1032 case 3742: spell_id = 35744; break; // Socrethar Portal
1033 default: return;
1036 m_caster->CastSpell(m_caster, spell_id, true);
1037 return;
1039 case 37674: // Chaos Blast
1041 if (!unitTarget)
1042 return;
1044 int32 basepoints0 = 100;
1045 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
1046 return;
1048 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1050 // selecting one from Bloodstained Fortune item
1051 uint32 newitemid;
1052 switch(urand(1, 20))
1054 case 1: newitemid = 32688; break;
1055 case 2: newitemid = 32689; break;
1056 case 3: newitemid = 32690; break;
1057 case 4: newitemid = 32691; break;
1058 case 5: newitemid = 32692; break;
1059 case 6: newitemid = 32693; break;
1060 case 7: newitemid = 32700; break;
1061 case 8: newitemid = 32701; break;
1062 case 9: newitemid = 32702; break;
1063 case 10: newitemid = 32703; break;
1064 case 11: newitemid = 32704; break;
1065 case 12: newitemid = 32705; break;
1066 case 13: newitemid = 32706; break;
1067 case 14: newitemid = 32707; break;
1068 case 15: newitemid = 32708; break;
1069 case 16: newitemid = 32709; break;
1070 case 17: newitemid = 32710; break;
1071 case 18: newitemid = 32711; break;
1072 case 19: newitemid = 32712; break;
1073 case 20: newitemid = 32713; break;
1074 default:
1075 return;
1078 DoCreateItem(i, newitemid);
1079 return;
1081 // Demon Broiled Surprise
1082 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1083 case 43723:
1085 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1086 return;
1088 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1089 return;
1092 case 44875: // Complete Raptor Capture
1094 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1095 return;
1097 Creature* creatureTarget = (Creature*)unitTarget;
1099 creatureTarget->ForcedDespawn();
1101 //cast spell Raptor Capture Credit
1102 m_caster->CastSpell(m_caster, 42337, true, NULL);
1103 return;
1105 case 34665: //Administer Antidote
1107 if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1108 return;
1109 // Spell has scriptable target but for sure.
1110 if (unitTarget->GetTypeId() != TYPEID_UNIT)
1111 return;
1113 uint32 health = unitTarget->GetHealth();
1114 float x, y, z, o;
1116 unitTarget->GetPosition(x, y, z);
1117 o = unitTarget->GetOrientation();
1118 ((Creature*)unitTarget)->ForcedDespawn();
1120 if (Creature* summon = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000))
1122 summon->SetHealth(health);
1123 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, summon);
1125 if (summon->AI())
1126 summon->AI()->AttackStart(m_caster);
1128 return;
1130 case 44997: // Converting Sentry
1132 //Converted Sentry Credit
1133 m_caster->CastSpell(m_caster, 45009, true);
1134 return;
1136 case 45030: // Impale Emissary
1138 // Emissary of Hate Credit
1139 m_caster->CastSpell(m_caster, 45088, true);
1140 return;
1142 case 55004: // Nitro Boosts
1143 if (!m_CastItem)
1144 return;
1145 if (roll_chance_i(95)) // Nitro Boosts - success
1146 m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
1147 else // Knocked Up - backfire 5%
1148 m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
1149 return;
1150 case 50243: // Teach Language
1152 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1153 return;
1155 // spell has a 1/3 chance to trigger one of the below
1156 if (roll_chance_i(66))
1157 return;
1158 if (((Player*)m_caster)->GetTeam() == ALLIANCE)
1160 // 1000001 - gnomish binary
1161 m_caster->CastSpell(m_caster, 50242, true);
1163 else
1165 // 01001000 - goblin binary
1166 m_caster->CastSpell(m_caster, 50246, true);
1169 return;
1171 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1173 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1174 return;
1176 if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1177 bg->EventPlayerDroppedFlag((Player*)m_caster);
1179 m_caster->CastSpell(m_caster, 30452, true, NULL);
1180 return;
1182 case 51592: // Pickup Primordial Hatchling
1184 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1185 return;
1187 Creature* creatureTarget = (Creature*)unitTarget;
1189 creatureTarget->ForcedDespawn();
1190 return;
1193 case 52308: // Take Sputum Sample
1195 switch(i)
1197 case 0:
1199 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1200 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1202 if (m_caster->HasAura(reqAuraID,0))
1203 m_caster->CastSpell(m_caster, spellID, true, NULL);
1204 return;
1206 case 1:
1207 return; // additional data for dummy[0]
1209 return;
1211 case 52759: // Ancestral Awakening
1212 if (!unitTarget)
1213 return;
1214 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1215 return;
1216 case 53341: // Rune of Cinderglacier
1217 case 53343: // Rune of Razorice
1219 // Runeforging Credit
1220 m_caster->CastSpell(m_caster, 54586, true);
1221 return;
1223 case 58418: // Portal to Orgrimmar
1224 case 58420: // Portal to Stormwind
1225 return; // implemented in EffectScript[0]
1226 case 59640: // Underbelly Elixir
1228 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1229 return;
1231 uint32 spell_id = 0;
1232 switch(urand(1,3))
1234 case 1: spell_id = 59645; break;
1235 case 2: spell_id = 59831; break;
1236 case 3: spell_id = 59843; break;
1238 m_caster->CastSpell(m_caster,spell_id,true,NULL);
1239 return;
1241 case 60932: // Disengage (one from creature versions)
1242 if (!unitTarget)
1243 return;
1244 m_caster->CastSpell(unitTarget,60934,true,NULL);
1245 return;
1248 //All IconID Check in there
1249 switch(m_spellInfo->SpellIconID)
1251 // Berserking (troll racial traits)
1252 case 1661:
1254 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1255 int32 melee_mod = 10;
1256 if (healthPerc <= 40)
1257 melee_mod = 30;
1258 if (healthPerc < 100 && healthPerc > 40)
1259 melee_mod = 10+(100-healthPerc)/3;
1261 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1262 int32 hasteModBasePoints1 = (5-melee_mod);
1263 int32 hasteModBasePoints2 = 5;
1265 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1266 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1267 m_caster->CastCustomSpell(m_caster, 26635, &hasteModBasePoints0, &hasteModBasePoints1, &hasteModBasePoints2, true, NULL);
1268 return;
1271 break;
1273 case SPELLFAMILY_MAGE:
1274 switch(m_spellInfo->Id )
1276 case 11958: // Cold Snap
1278 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1279 return;
1281 // immediately finishes the cooldown on Frost spells
1282 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1283 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1285 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1287 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1288 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1289 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0)
1291 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
1293 else
1294 ++itr;
1296 return;
1298 case 32826: // Polymorph Cast Visual
1300 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
1302 //Polymorph Cast Visual Rank 1
1303 const uint32 spell_list[6] = {
1304 32813, // Squirrel Form
1305 32816, // Giraffe Form
1306 32817, // Serpent Form
1307 32818, // Dragonhawk Form
1308 32819, // Worgen Form
1309 32820 // Sheep Form
1311 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1313 return;
1316 break;
1317 case SPELLFAMILY_WARRIOR:
1318 // Charge
1319 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1321 int32 chargeBasePoints0 = damage;
1322 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1323 return;
1325 // Execute
1326 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1328 if(!unitTarget)
1329 return;
1331 uint32 rage = m_caster->GetPower(POWER_RAGE);
1332 // Glyph of Execution bonus
1333 if (Aura *aura = m_caster->GetDummyAura(58367))
1334 rage+=aura->GetModifier()->m_amount;
1336 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1337 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1338 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1339 m_caster->SetPower(POWER_RAGE, 0);
1340 return;
1342 // Slam
1343 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1345 if(!unitTarget)
1346 return;
1347 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1348 m_damage+=damage;
1349 return;
1351 // Concussion Blow
1352 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1354 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1355 return;
1357 switch(m_spellInfo->Id)
1359 // Warrior's Wrath
1360 case 21977:
1362 if (!unitTarget)
1363 return;
1364 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1365 return;
1367 // Last Stand
1368 case 12975:
1370 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1371 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1372 return;
1374 // Bloodthirst
1375 case 23881:
1377 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1378 return;
1381 break;
1382 case SPELLFAMILY_WARLOCK:
1383 // Life Tap
1384 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1386 // In 303 exist spirit depend
1387 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1388 switch (m_spellInfo->Id)
1390 case 1454: damage+=spirit; break;
1391 case 1455: damage+=spirit*15/10; break;
1392 case 1456: damage+=spirit*2; break;
1393 case 11687: damage+=spirit*25/10; break;
1394 case 11688:
1395 case 11689:
1396 case 27222:
1397 case 57946: damage+=spirit*3; break;
1398 default:
1399 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1400 return;
1402 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1403 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1404 if (unitTarget && (int32(unitTarget->GetHealth()) > damage))
1406 // Shouldn't Appear in Combat Log
1407 unitTarget->ModifyHealth(-damage);
1409 int32 mana = damage;
1410 // Improved Life Tap mod
1411 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1412 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1414 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1415 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1417 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1419 // Mana Feed
1420 int32 manaFeedVal = 0;
1421 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1422 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1424 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1425 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1427 if (manaFeedVal > 0)
1429 manaFeedVal = manaFeedVal * mana / 100;
1430 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1433 else
1434 SendCastResult(SPELL_FAILED_FIZZLE);
1435 return;
1437 break;
1438 case SPELLFAMILY_PRIEST:
1439 // Penance
1440 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1442 if (!unitTarget)
1443 return;
1445 int hurt = 0;
1446 int heal = 0;
1447 switch(m_spellInfo->Id)
1449 case 47540: hurt = 47758; heal = 47757; break;
1450 case 53005: hurt = 53001; heal = 52986; break;
1451 case 53006: hurt = 53002; heal = 52987; break;
1452 case 53007: hurt = 53003; heal = 52988; break;
1453 default:
1454 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1455 return;
1457 if (m_caster->IsFriendlyTo(unitTarget))
1458 m_caster->CastSpell(unitTarget, heal, true, 0);
1459 else
1460 m_caster->CastSpell(unitTarget, hurt, true, 0);
1461 return;
1463 break;
1464 case SPELLFAMILY_DRUID:
1465 // Starfall
1466 if (m_spellInfo->SpellFamilyFlags2 & UI64LIT(0x00000100))
1468 //Shapeshifting into an animal form or mounting cancels the effect.
1469 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1471 if(m_triggeredByAuraSpell)
1472 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1473 return;
1476 //Any effect which causes you to lose control of your character will supress the starfall effect.
1477 if (m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1478 return;
1480 switch(m_spellInfo->Id)
1482 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1483 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1484 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1485 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1486 default:
1487 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1488 return;
1491 break;
1492 case SPELLFAMILY_ROGUE:
1493 switch(m_spellInfo->Id )
1495 case 5938: // Shiv
1497 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1498 return;
1500 Player *pCaster = ((Player*)m_caster);
1502 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1503 if (!item)
1504 return;
1506 // all poison enchantments is temporary
1507 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1508 if (!enchant_id)
1509 return;
1511 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1512 if (!pEnchant)
1513 return;
1515 for (int s=0;s<3;s++)
1517 if (pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1518 continue;
1520 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1521 if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1522 continue;
1524 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1527 m_caster->CastSpell(unitTarget, 5940, true);
1528 return;
1530 case 14185: // Preparation
1532 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1533 return;
1535 //immediately finishes the cooldown on certain Rogue abilities
1536 const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
1537 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1539 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1541 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1542 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1543 else
1544 ++itr;
1546 return;
1548 case 31231: // Cheat Death
1550 m_caster->CastSpell(m_caster, 45182, true);
1551 return;
1554 break;
1555 case SPELLFAMILY_HUNTER:
1556 // Steady Shot
1557 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1559 if (!unitTarget || !unitTarget->isAlive())
1560 return;
1562 bool found = false;
1564 // check dazed affect
1565 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1566 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1568 if ((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1570 found = true;
1571 break;
1575 if (found)
1576 m_damage+= damage;
1577 return;
1580 // Disengage
1581 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000400000000000))
1583 Unit* target = unitTarget;
1584 uint32 spellid;
1585 switch(m_spellInfo->Id)
1587 case 781: // player case
1588 target = m_caster;
1589 spellid = 56446;
1590 break;
1591 case 57635: spellid = 57636; break; // one from creature cases
1592 case 61507: spellid = 61508; break; // one from creature cases
1593 default:
1594 sLog.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo->Id);
1595 return;
1597 if (!target || !target->isAlive())
1598 return;
1599 m_caster->CastSpell(target,spellid,true,NULL);
1602 switch(m_spellInfo->Id)
1604 case 23989: // Readiness talent
1606 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1607 return;
1609 //immediately finishes the cooldown for hunter abilities
1610 const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
1611 for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
1613 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1615 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1616 ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
1617 else
1618 ++itr;
1620 return;
1622 case 37506: // Scatter Shot
1624 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1625 return;
1627 // break Auto Shot and autohit
1628 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1629 m_caster->AttackStop();
1630 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1631 return;
1634 break;
1635 case SPELLFAMILY_PALADIN:
1636 switch(m_spellInfo->SpellIconID)
1638 case 156: // Holy Shock
1640 if (!unitTarget)
1641 return;
1643 int hurt = 0;
1644 int heal = 0;
1646 switch(m_spellInfo->Id)
1648 case 20473: hurt = 25912; heal = 25914; break;
1649 case 20929: hurt = 25911; heal = 25913; break;
1650 case 20930: hurt = 25902; heal = 25903; break;
1651 case 27174: hurt = 27176; heal = 27175; break;
1652 case 33072: hurt = 33073; heal = 33074; break;
1653 case 48824: hurt = 48822; heal = 48820; break;
1654 case 48825: hurt = 48823; heal = 48821; break;
1655 default:
1656 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1657 return;
1660 if (m_caster->IsFriendlyTo(unitTarget))
1661 m_caster->CastSpell(unitTarget, heal, true, 0);
1662 else
1663 m_caster->CastSpell(unitTarget, hurt, true, 0);
1665 return;
1667 case 561: // Judgement of command
1669 if (!unitTarget)
1670 return;
1672 uint32 spell_id = m_currentBasePoints[i]+1;
1673 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1674 if (!spell_proto)
1675 return;
1677 if (!unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1679 // decreased damage (/2) for non-stunned target.
1680 SpellModifier *mod = new SpellModifier;
1681 mod->op = SPELLMOD_DAMAGE;
1682 mod->value = -50;
1683 mod->type = SPELLMOD_PCT;
1684 mod->spellId = m_spellInfo->Id;
1685 mod->mask = UI64LIT(0x0000020000000000);
1686 mod->mask2= UI64LIT(0x0);
1688 ((Player*)m_caster)->AddSpellMod(mod, true);
1689 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1690 // mod deleted
1691 ((Player*)m_caster)->AddSpellMod(mod, false);
1693 else
1694 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1696 return;
1700 switch(m_spellInfo->Id)
1702 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1703 case 20187:
1705 if (!unitTarget)
1706 return;
1707 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1708 return;
1710 case 31789: // Righteous Defense (step 1)
1712 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1714 // non-standard cast requirement check
1715 if (!unitTarget || unitTarget->getAttackers().empty())
1717 if (m_caster->GetTypeId()==TYPEID_PLAYER)
1718 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
1719 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1720 return;
1723 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1724 // Clear targets for eff 1
1725 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1726 ihit->effectMask &= ~(1<<1);
1728 // not empty (checked)
1729 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1731 // chance to be selected from list
1732 float chance = 100.0f/attackers.size();
1733 uint32 count=0;
1734 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1736 if (!roll_chance_f(chance))
1737 continue;
1738 ++count;
1739 AddUnitTarget((*aItr), 1);
1742 // now let next effect cast spell at each target.
1743 return;
1745 case 37877: // Blessing of Faith
1747 if (!unitTarget)
1748 return;
1750 uint32 spell_id = 0;
1751 switch(unitTarget->getClass())
1753 case CLASS_DRUID: spell_id = 37878; break;
1754 case CLASS_PALADIN: spell_id = 37879; break;
1755 case CLASS_PRIEST: spell_id = 37880; break;
1756 case CLASS_SHAMAN: spell_id = 37881; break;
1757 default: return; // ignore for not healing classes
1760 m_caster->CastSpell(m_caster, spell_id, true);
1761 return;
1764 break;
1765 case SPELLFAMILY_SHAMAN:
1766 // Rockbiter Weapon
1767 if (m_spellInfo->SpellFamilyFlags & 0x400000)
1769 // TODO: use expect spell for enchant (if exist talent)
1770 // In 3.0.3 no mods present for rockbiter
1771 uint32 spell_id = 0;
1772 switch(m_spellInfo->Id)
1774 case 8017: spell_id = 36494; break; // Rank 1
1775 case 8018: spell_id = 36750; break; // Rank 2
1776 case 8019: spell_id = 36755; break; // Rank 3
1777 case 10399: spell_id = 36759; break; // Rank 4
1778 default:
1779 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo->Id);
1780 return;
1783 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
1785 if (!spellInfo)
1787 sLog.outError("WORLD: unknown spell id %i", spell_id);
1788 return;
1791 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1792 return;
1794 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
1796 if (Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(j)))
1798 if (item->IsFitToSpellRequirements(m_spellInfo))
1800 Spell *spell = new Spell(m_caster, spellInfo, true);
1802 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1803 // at calculation applied affect from Elemental Weapons talent
1804 // real enchantment damage-1
1805 spell->m_currentBasePoints[1] = damage-1;
1807 SpellCastTargets targets;
1808 targets.setItemTarget( item );
1809 spell->prepare(&targets);
1813 return;
1815 // Cleansing Totem
1816 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
1818 m_caster->CastSpell(unitTarget, 52025, true);
1819 return;
1821 // Healing Stream Totem
1822 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
1824 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1825 return;
1827 // Mana Spring Totem
1828 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
1830 if (unitTarget->getPowerType()!=POWER_MANA)
1831 return;
1832 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1833 return;
1835 if (m_spellInfo->Id == 39610) // Mana Tide Totem effect
1837 if (!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1838 return;
1839 // Glyph of Mana Tide
1840 if (Unit *owner = m_caster->GetOwner())
1841 if (Aura *dummy = owner->GetDummyAura(55441))
1842 damage+=dummy->GetModifier()->m_amount;
1843 // Regenerate 6% of Total Mana Every 3 secs
1844 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1845 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
1846 return;
1848 // Lava Lash
1849 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1851 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1852 return;
1853 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1854 if (item)
1856 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1857 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1858 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1860 if ((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1861 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
1862 (*itr)->GetCastItemGUID() == item->GetGUID())
1864 m_damage += m_damage * damage / 100;
1865 return;
1869 return;
1871 break;
1872 case SPELLFAMILY_DEATHKNIGHT:
1873 // Death Coil
1874 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
1876 if (m_caster->IsFriendlyTo(unitTarget))
1878 if (unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1879 return;
1881 int32 bp = damage * 1.5f;
1882 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
1884 else
1886 int32 bp = damage;
1887 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
1889 return;
1891 // Hungering Cold
1892 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000100000000000))
1894 m_caster->CastSpell(m_caster, 51209, true);
1895 return;
1897 // Death Strike
1898 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
1900 uint32 count = 0;
1901 Unit::AuraMap const& auras = unitTarget->GetAuras();
1902 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
1904 if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
1905 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
1906 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
1908 ++count;
1909 // max. 15%
1910 if (count == 3)
1911 break;
1915 int32 bp = count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[0] / 100;
1916 m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true);
1917 return;
1919 break;
1922 // pet auras
1923 if (PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id, i))
1925 m_caster->AddPetAura(petSpell);
1926 return;
1929 // Script based implementation. Must be used only for not good for implementation in core spell effects
1930 // So called only for not proccessed cases
1931 if (gameObjTarget)
1932 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
1933 else if (unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
1934 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
1935 else if (itemTarget)
1936 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
1939 void Spell::EffectTriggerSpellWithValue(uint32 i)
1941 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1943 // normal case
1944 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1946 if(!spellInfo)
1948 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1949 return;
1952 int32 bp = damage;
1953 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1956 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1958 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1959 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1961 if(!spellInfo)
1963 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1964 return;
1967 finish();
1969 m_caster->CastSpell(unitTarget,spellInfo,false);
1972 void Spell::EffectForceCast(uint32 i)
1974 if( !unitTarget )
1975 return;
1977 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1979 // normal case
1980 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1982 if(!spellInfo)
1984 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1985 return;
1988 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
1991 void Spell::EffectTriggerSpell(uint32 effIndex)
1993 // only unit case known
1994 if (!unitTarget)
1996 if(gameObjTarget || itemTarget)
1997 sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
1998 return;
2001 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
2003 // special cases
2004 switch(triggered_spell_id)
2006 // Vanish (not exist)
2007 case 18461:
2009 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2010 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2011 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
2013 // if this spell is given to NPC it must handle rest by it's own AI
2014 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2015 return;
2017 // get highest rank of the Stealth spell
2018 uint32 spellId = 0;
2019 const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
2020 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2022 // only highest rank is shown in spell book, so simply check if shown in spell book
2023 if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
2024 continue;
2026 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2027 if (!spellInfo)
2028 continue;
2030 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
2032 spellId = spellInfo->Id;
2033 break;
2037 // no Stealth spell found
2038 if (!spellId)
2039 return;
2041 // reset cooldown on it if needed
2042 if (((Player*)unitTarget)->HasSpellCooldown(spellId))
2043 ((Player*)unitTarget)->RemoveSpellCooldown(spellId);
2045 m_caster->CastSpell(unitTarget, spellId, true);
2046 return;
2048 // just skip
2049 case 23770: // Sayge's Dark Fortune of *
2050 // not exist, common cooldown can be implemented in scripts if need.
2051 return;
2052 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2053 case 29284:
2055 // Brittle Armor
2056 SpellEntry const* spell = sSpellStore.LookupEntry(24575);
2057 if (!spell)
2058 return;
2060 for (int j=0; j < spell->StackAmount; ++j)
2061 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2062 return;
2064 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2065 case 29286:
2067 // Mercurial Shield
2068 SpellEntry const* spell = sSpellStore.LookupEntry(26464);
2069 if (!spell)
2070 return;
2072 for (int j=0; j < spell->StackAmount; ++j)
2073 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
2074 return;
2076 // Righteous Defense
2077 case 31980:
2079 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
2080 return;
2082 // Cloak of Shadows
2083 case 35729:
2085 Unit::AuraMap& Auras = unitTarget->GetAuras();
2086 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
2088 // remove all harmful spells on you...
2089 if( // ignore positive and passive auras
2090 !iter->second->IsPositive() && !iter->second->IsPassive() &&
2091 // ignore physical auras
2092 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
2094 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
2095 iter = Auras.begin();
2098 return;
2100 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2101 case 41967:
2103 if (Unit *pet = unitTarget->GetPet())
2104 pet->CastSpell(pet, 28305, true);
2105 return;
2109 // normal case
2110 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2111 if (!spellInfo)
2113 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
2114 return;
2117 // select formal caster for triggered spell
2118 Unit* caster = m_caster;
2120 // some triggered spells require specific equipment
2121 if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
2123 // main hand weapon required
2124 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
2126 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
2128 // skip spell if no weapon in slot or broken
2129 if (!item || item->IsBroken() )
2130 return;
2132 // skip spell if weapon not fit to triggered spell
2133 if (!item->IsFitToSpellRequirements(spellInfo))
2134 return;
2137 // offhand hand weapon required
2138 if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
2140 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
2142 // skip spell if no weapon in slot or broken
2143 if (!item || item->IsBroken() )
2144 return;
2146 // skip spell if weapon not fit to triggered spell
2147 if (!item->IsFitToSpellRequirements(spellInfo))
2148 return;
2151 else
2153 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2154 // so this just for speedup places in else
2155 caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
2158 caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
2161 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2163 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2165 // normal case
2166 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2168 if(!spellInfo)
2170 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2171 m_spellInfo->Id,effect_idx,triggered_spell_id);
2172 return;
2175 if (m_CastItem)
2176 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2178 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2181 void Spell::EffectJump(uint32 i)
2183 if(m_caster->isInFlight())
2184 return;
2186 // Init dest coordinates
2187 float x,y,z,o;
2188 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2190 x = m_targets.m_destX;
2191 y = m_targets.m_destY;
2192 z = m_targets.m_destZ;
2194 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2196 // explicit cast data from client or server-side cast
2197 // some spell at client send caster
2198 Unit* pTarget = NULL;
2199 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2200 pTarget = m_targets.getUnitTarget();
2201 else if(unitTarget->getVictim())
2202 pTarget = m_caster->getVictim();
2203 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2204 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2206 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2208 else
2209 o = m_caster->GetOrientation();
2211 else if(unitTarget)
2213 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2214 o = m_caster->GetOrientation();
2216 else if(gameObjTarget)
2218 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2219 o = m_caster->GetOrientation();
2221 else
2223 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2224 return;
2227 m_caster->NearTeleportTo(x, y, z, o, true);
2230 void Spell::EffectTeleportUnits(uint32 i)
2232 if(!unitTarget || unitTarget->isInFlight())
2233 return;
2235 switch (m_spellInfo->EffectImplicitTargetB[i])
2237 case TARGET_INNKEEPER_COORDINATES:
2239 // Only players can teleport to innkeeper
2240 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2241 return;
2243 ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0);
2244 return;
2246 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2247 case TARGET_TABLE_X_Y_Z_COORDINATES:
2249 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2250 if(!st)
2252 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2253 return;
2256 if(st->target_mapId==unitTarget->GetMapId())
2257 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2258 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2259 ((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);
2260 break;
2262 case TARGET_BEHIND_VICTIM:
2264 Unit *pTarget = NULL;
2266 // explicit cast data from client or server-side cast
2267 // some spell at client send caster
2268 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2269 pTarget = m_targets.getUnitTarget();
2270 else if(unitTarget->getVictim())
2271 pTarget = unitTarget->getVictim();
2272 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2273 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2275 // Init dest coordinates
2276 float x = m_targets.m_destX;
2277 float y = m_targets.m_destY;
2278 float z = m_targets.m_destZ;
2279 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2280 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2281 return;
2283 default:
2285 // If not exist data for dest location - return
2286 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2288 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2289 return;
2291 // Init dest coordinates
2292 float x = m_targets.m_destX;
2293 float y = m_targets.m_destY;
2294 float z = m_targets.m_destZ;
2295 float orientation = unitTarget->GetOrientation();
2296 // Teleport
2297 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2298 return;
2302 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2303 switch ( m_spellInfo->Id )
2305 // Dimensional Ripper - Everlook
2306 case 23442:
2308 int32 r = irand(0, 119);
2309 if ( r >= 70 ) // 7/12 success
2311 if ( r < 100 ) // 4/12 evil twin
2312 m_caster->CastSpell(m_caster, 23445, true);
2313 else // 1/12 fire
2314 m_caster->CastSpell(m_caster, 23449, true);
2316 return;
2318 // Ultrasafe Transporter: Toshley's Station
2319 case 36941:
2321 if ( roll_chance_i(50) ) // 50% success
2323 int32 rand_eff = urand(1, 7);
2324 switch ( rand_eff )
2326 case 1:
2327 // soul split - evil
2328 m_caster->CastSpell(m_caster, 36900, true);
2329 break;
2330 case 2:
2331 // soul split - good
2332 m_caster->CastSpell(m_caster, 36901, true);
2333 break;
2334 case 3:
2335 // Increase the size
2336 m_caster->CastSpell(m_caster, 36895, true);
2337 break;
2338 case 4:
2339 // Decrease the size
2340 m_caster->CastSpell(m_caster, 36893, true);
2341 break;
2342 case 5:
2343 // Transform
2345 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2346 m_caster->CastSpell(m_caster, 36897, true);
2347 else
2348 m_caster->CastSpell(m_caster, 36899, true);
2349 break;
2351 case 6:
2352 // chicken
2353 m_caster->CastSpell(m_caster, 36940, true);
2354 break;
2355 case 7:
2356 // evil twin
2357 m_caster->CastSpell(m_caster, 23445, true);
2358 break;
2361 return;
2363 // Dimensional Ripper - Area 52
2364 case 36890:
2366 if ( roll_chance_i(50) ) // 50% success
2368 int32 rand_eff = urand(1, 4);
2369 switch ( rand_eff )
2371 case 1:
2372 // soul split - evil
2373 m_caster->CastSpell(m_caster, 36900, true);
2374 break;
2375 case 2:
2376 // soul split - good
2377 m_caster->CastSpell(m_caster, 36901, true);
2378 break;
2379 case 3:
2380 // Increase the size
2381 m_caster->CastSpell(m_caster, 36895, true);
2382 break;
2383 case 4:
2384 // Transform
2386 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2387 m_caster->CastSpell(m_caster, 36897, true);
2388 else
2389 m_caster->CastSpell(m_caster, 36899, true);
2390 break;
2394 return;
2399 void Spell::EffectApplyAura(uint32 i)
2401 if(!unitTarget)
2402 return;
2404 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2405 if( !unitTarget->isAlive() && !IsDeathPersistentSpell(m_spellInfo) &&
2406 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2407 return;
2409 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2410 if(!caster)
2411 return;
2413 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2415 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2417 // Now Reduce spell duration using data received at spell hit
2418 int32 duration = Aur->GetAuraMaxDuration();
2419 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
2420 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
2421 Aur->setDiminishGroup(m_diminishGroup);
2423 // if Aura removed and deleted, do not continue.
2424 if(duration== 0 && !(Aur->IsPermanent()))
2426 delete Aur;
2427 return;
2430 if(duration != Aur->GetAuraMaxDuration())
2432 Aur->SetAuraMaxDuration(duration);
2433 Aur->SetAuraDuration(duration);
2436 unitTarget->AddAura(Aur);
2439 void Spell::EffectUnlearnSpecialization( uint32 i )
2441 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2442 return;
2444 Player *_player = (Player*)unitTarget;
2445 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2447 _player->removeSpell(spellToUnlearn);
2449 sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2452 void Spell::EffectPowerDrain(uint32 i)
2454 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2455 return;
2457 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2459 if(!unitTarget)
2460 return;
2461 if(!unitTarget->isAlive())
2462 return;
2463 if(unitTarget->getPowerType() != drain_power)
2464 return;
2465 if(damage < 0)
2466 return;
2468 uint32 curPower = unitTarget->GetPower(drain_power);
2470 //add spell damage bonus
2471 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2473 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2474 uint32 power = damage;
2475 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2476 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2478 int32 new_damage;
2479 if(curPower < power)
2480 new_damage = curPower;
2481 else
2482 new_damage = power;
2484 unitTarget->ModifyPower(drain_power,-new_damage);
2486 // Don`t restore from self drain
2487 if(drain_power == POWER_MANA && m_caster != unitTarget)
2489 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2490 if(manaMultiplier==0)
2491 manaMultiplier = 1;
2493 if(Player *modOwner = m_caster->GetSpellModOwner())
2494 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2496 int32 gain = int32(new_damage * manaMultiplier);
2498 m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2502 void Spell::EffectSendEvent(uint32 EffectIndex)
2505 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2507 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2508 m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2511 void Spell::EffectPowerBurn(uint32 i)
2513 if (m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2514 return;
2516 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2518 if (!unitTarget)
2519 return;
2520 if (!unitTarget->isAlive())
2521 return;
2522 if (unitTarget->getPowerType()!=powertype)
2523 return;
2524 if (damage < 0)
2525 return;
2527 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2528 if (m_spellInfo->ManaCostPercentage)
2530 uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2531 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2532 if(damage > maxdamage) damage = maxdamage;
2535 int32 curPower = int32(unitTarget->GetPower(powertype));
2537 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2538 uint32 power = damage;
2539 if (powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER)
2540 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2542 int32 new_damage = (curPower < power) ? curPower : power;
2544 unitTarget->ModifyPower(powertype, -new_damage);
2545 float multiplier = m_spellInfo->EffectMultipleValue[i];
2547 if (Player *modOwner = m_caster->GetSpellModOwner())
2548 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2550 new_damage = int32(new_damage * multiplier);
2551 m_damage += new_damage;
2554 void Spell::EffectHeal( uint32 /*i*/ )
2556 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2558 // Try to get original caster
2559 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2561 // Skip if m_originalCaster not available
2562 if (!caster)
2563 return;
2565 int32 addhealth = damage;
2567 // Vessel of the Naaru (Vial of the Sunwell trinket)
2568 if (m_spellInfo->Id == 45064)
2570 // Amount of heal - depends from stacked Holy Energy
2571 int damageAmount = 0;
2572 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2573 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2574 if ((*i)->GetId() == 45062)
2575 damageAmount+=(*i)->GetModifier()->m_amount;
2576 if (damageAmount)
2577 m_caster->RemoveAurasDueToSpell(45062);
2579 addhealth += damageAmount;
2581 // Swiftmend - consumes Regrowth or Rejuvenation
2582 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2584 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2585 // find most short by duration
2586 Aura *targetAura = NULL;
2587 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2589 if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2590 // Regrowth or Rejuvenation 0x40 | 0x10
2591 ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000050)))
2593 if (!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2594 targetAura = *i;
2598 if (!targetAura)
2600 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
2601 return;
2603 int idx = 0;
2604 while(idx < 3)
2606 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2607 break;
2608 idx++;
2611 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2612 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2614 // Glyph of Swiftmend
2615 if (!caster->HasAura(54824))
2616 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2618 addhealth += tickheal * tickcount;
2620 else
2621 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2623 m_healing+=addhealth;
2627 void Spell::EffectHealPct( uint32 /*i*/ )
2629 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2631 // Try to get original caster
2632 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2634 // Skip if m_originalCaster not available
2635 if (!caster)
2636 return;
2638 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2639 if (Player* modOwner = m_caster->GetSpellModOwner())
2640 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
2642 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2643 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2647 void Spell::EffectHealMechanical( uint32 /*i*/ )
2649 // Mechanic creature type should be correctly checked by targetCreatureType field
2650 if (unitTarget && unitTarget->isAlive() && damage >= 0)
2652 // Try to get original caster
2653 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2655 // Skip if m_originalCaster not available
2656 if (!caster)
2657 return;
2659 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2660 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2664 void Spell::EffectHealthLeech(uint32 i)
2666 if (!unitTarget)
2667 return;
2668 if (!unitTarget->isAlive())
2669 return;
2671 if (damage < 0)
2672 return;
2674 sLog.outDebug("HealthLeech :%i", damage);
2676 float multiplier = m_spellInfo->EffectMultipleValue[i];
2678 if (Player *modOwner = m_caster->GetSpellModOwner())
2679 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2681 int32 new_damage = int32(damage*multiplier);
2682 uint32 curHealth = unitTarget->GetHealth();
2683 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage );
2684 if (curHealth < new_damage)
2685 new_damage = curHealth;
2687 if (m_caster->isAlive())
2689 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2690 m_caster->DealHeal(m_caster, uint32(new_damage), m_spellInfo);
2694 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2696 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2697 return;
2699 Player* player = (Player*)unitTarget;
2701 uint32 newitemid = itemtype;
2702 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2703 if(!pProto)
2705 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2706 return;
2709 // bg reward have some special in code work
2710 uint32 bgType = 0;
2711 switch(m_spellInfo->Id)
2713 case SPELL_AV_MARK_WINNER:
2714 case SPELL_AV_MARK_LOSER:
2715 bgType = BATTLEGROUND_AV;
2716 break;
2717 case SPELL_WS_MARK_WINNER:
2718 case SPELL_WS_MARK_LOSER:
2719 bgType = BATTLEGROUND_WS;
2720 break;
2721 case SPELL_AB_MARK_WINNER:
2722 case SPELL_AB_MARK_LOSER:
2723 bgType = BATTLEGROUND_AB;
2724 break;
2725 default:
2726 break;
2729 uint32 num_to_add;
2731 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2732 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2734 int32 basePoints = m_currentBasePoints[i];
2735 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2736 if (randomPoints)
2737 num_to_add = basePoints + irand(1, randomPoints);
2738 else
2739 num_to_add = basePoints + 1;
2741 else if (pProto->MaxCount == 1)
2742 num_to_add = 1;
2743 else if(player->getLevel() >= m_spellInfo->spellLevel)
2745 int32 basePoints = m_currentBasePoints[i];
2746 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2747 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2749 else
2750 num_to_add = 2;
2752 if (num_to_add < 1)
2753 num_to_add = 1;
2754 if (num_to_add > pProto->GetMaxStackSize())
2755 num_to_add = pProto->GetMaxStackSize();
2757 // init items_count to 1, since 1 item will be created regardless of specialization
2758 int items_count=1;
2759 // the chance to create additional items
2760 float additionalCreateChance=0.0f;
2761 // the maximum number of created additional items
2762 uint8 additionalMaxNum=0;
2763 // get the chance and maximum number for creating extra items
2764 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2766 // roll with this chance till we roll not to create or we create the max num
2767 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2768 ++items_count;
2771 // really will be created more items
2772 num_to_add *= items_count;
2774 // can the player store the new item?
2775 ItemPosCountVec dest;
2776 uint32 no_space = 0;
2777 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2778 if( msg != EQUIP_ERR_OK )
2780 // convert to possible store amount
2781 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2782 num_to_add -= no_space;
2783 else
2785 // if not created by another reason from full inventory or unique items amount limitation
2786 player->SendEquipError( msg, NULL, NULL );
2787 return;
2791 if(num_to_add)
2793 // create the new item and store it
2794 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2796 // was it successful? return error if not
2797 if(!pItem)
2799 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2800 return;
2803 // set the "Crafted by ..." property of the item
2804 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2805 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
2807 // send info to the client
2808 if(pItem)
2809 player->SendNewItem(pItem, num_to_add, true, bgType == 0);
2811 // we succeeded in creating at least one item, so a levelup is possible
2812 if(bgType == 0)
2813 player->UpdateCraftSkill(m_spellInfo->Id);
2816 // for battleground marks send by mail if not add all expected
2817 if(no_space > 0 && bgType)
2819 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
2820 bg->SendRewardMarkByMail(player, newitemid, no_space);
2824 void Spell::EffectCreateItem(uint32 i)
2826 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2829 void Spell::EffectCreateItem2(uint32 i)
2831 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2832 return;
2833 Player* player = (Player*)m_caster;
2835 uint32 item_id = m_spellInfo->EffectItemType[i];
2837 DoCreateItem(i, item_id);
2839 // special case: fake item replaced by generate using spell_loot_template
2840 if (IsLootCraftingSpell(m_spellInfo))
2842 if (!player->HasItemCount(item_id, 1))
2843 return;
2845 // remove reagent
2846 uint32 count = 1;
2847 player->DestroyItemCount(item_id, count, true);
2849 // create some random items
2850 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2854 void Spell::EffectCreateRandomItem(uint32 i)
2856 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
2857 return;
2858 Player* player = (Player*)m_caster;
2860 // create some random items
2861 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2864 void Spell::EffectPersistentAA(uint32 i)
2866 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2868 if (Player* modOwner = m_caster->GetSpellModOwner())
2869 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2871 int32 duration = GetSpellDuration(m_spellInfo);
2872 DynamicObject* dynObj = new DynamicObject;
2873 if (!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
2875 delete dynObj;
2876 return;
2878 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2879 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2880 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2881 m_caster->AddDynObject(dynObj);
2882 m_caster->GetMap()->Add(dynObj);
2885 void Spell::EffectEnergize(uint32 i)
2887 if(!unitTarget)
2888 return;
2889 if(!unitTarget->isAlive())
2890 return;
2892 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2893 return;
2895 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2897 // Some level depends spells
2898 int level_multiplier = 0;
2899 int level_diff = 0;
2900 switch (m_spellInfo->Id)
2902 case 9512: // Restore Energy
2903 level_diff = m_caster->getLevel() - 40;
2904 level_multiplier = 2;
2905 break;
2906 case 24571: // Blood Fury
2907 level_diff = m_caster->getLevel() - 60;
2908 level_multiplier = 10;
2909 break;
2910 case 24532: // Burst of Energy
2911 level_diff = m_caster->getLevel() - 60;
2912 level_multiplier = 4;
2913 break;
2914 case 31930: // Judgements of the Wise
2915 case 63375: // Improved Stormstrike
2916 damage = damage * unitTarget->GetCreateMana() / 100;
2917 default:
2918 break;
2921 if (level_diff > 0)
2922 damage -= level_multiplier * level_diff;
2924 if(damage < 0)
2925 return;
2927 if(unitTarget->GetMaxPower(power) == 0)
2928 return;
2930 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
2932 // Mad Alchemist's Potion
2933 if (m_spellInfo->Id == 45051)
2935 // find elixirs on target
2936 uint32 elixir_mask = 0;
2937 Unit::AuraMap& Auras = unitTarget->GetAuras();
2938 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2940 uint32 spell_id = itr->second->GetId();
2941 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2942 elixir_mask |= mask;
2945 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2946 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2948 // get all available elixirs by mask and spell level
2949 std::vector<uint32> elixirs;
2950 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2951 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2953 if (itr->second & elixir_mask)
2955 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2956 continue;
2958 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2959 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2960 continue;
2962 elixirs.push_back(itr->first);
2966 if (!elixirs.empty())
2968 // cast random elixir on target
2969 uint32 rand_spell = urand(0,elixirs.size()-1);
2970 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2975 void Spell::EffectEnergisePct(uint32 i)
2977 if (!unitTarget)
2978 return;
2979 if (!unitTarget->isAlive())
2980 return;
2982 if (m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2983 return;
2985 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2987 uint32 maxPower = unitTarget->GetMaxPower(power);
2988 if (maxPower == 0)
2989 return;
2991 uint32 gain = damage * maxPower / 100;
2992 m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
2995 void Spell::SendLoot(uint64 guid, LootType loottype)
2997 Player* player = (Player*)m_caster;
2998 if (!player)
2999 return;
3001 if (gameObjTarget)
3003 if (Script->GOHello(player, gameObjTarget))
3004 return;
3006 switch (gameObjTarget->GetGoType())
3008 case GAMEOBJECT_TYPE_DOOR:
3009 case GAMEOBJECT_TYPE_BUTTON:
3010 gameObjTarget->UseDoorOrButton();
3011 player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
3012 return;
3014 case GAMEOBJECT_TYPE_QUESTGIVER:
3015 // start or end quest
3016 player->PrepareQuestMenu(guid);
3017 player->SendPreparedQuest(guid);
3018 return;
3020 case GAMEOBJECT_TYPE_SPELL_FOCUS:
3021 // triggering linked GO
3022 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
3023 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3024 return;
3026 case GAMEOBJECT_TYPE_GOOBER:
3027 // goober_scripts can be triggered if the player don't have the quest
3028 if (gameObjTarget->GetGOInfo()->goober.eventId)
3030 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
3031 player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
3034 // cast goober spell
3035 if (gameObjTarget->GetGOInfo()->goober.questId)
3036 ///Quest require to be active for GO using
3037 if (player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
3038 return;
3040 gameObjTarget->AddUniqueUse(player);
3041 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
3043 //TODO? Objective counting called without spell check but with quest objective check
3044 // if send spell id then this line will duplicate to spell casting call (double counting)
3045 // So we or have this line and not required in quest_template have reqSpellIdN
3046 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
3047 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
3049 // triggering linked GO
3050 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
3051 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3053 return;
3055 case GAMEOBJECT_TYPE_CHEST:
3056 // TODO: possible must be moved to loot release (in different from linked triggering)
3057 if (gameObjTarget->GetGOInfo()->chest.eventId)
3059 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
3060 player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
3063 // triggering linked GO
3064 if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
3065 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
3067 // Don't return, let loots been taken
3068 default:
3069 break;
3073 // Send loot
3074 player->SendLoot(guid, loottype);
3077 void Spell::EffectOpenLock(uint32 effIndex)
3079 if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
3081 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
3082 return;
3085 Player* player = (Player*)m_caster;
3087 uint32 lockId = 0;
3088 uint64 guid = 0;
3090 // Get lockId
3091 if (gameObjTarget)
3093 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
3094 // Arathi Basin banner opening !
3095 if (goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
3096 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK)
3098 //CanUseBattleGroundObject() already called in CheckCast()
3099 // in battleground check
3100 if (BattleGround *bg = player->GetBattleGround())
3102 // check if it's correct bg
3103 if (bg && bg->GetTypeID() == BATTLEGROUND_AB)
3104 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3105 return;
3108 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
3110 //CanUseBattleGroundObject() already called in CheckCast()
3111 // in battleground check
3112 if (BattleGround *bg = player->GetBattleGround())
3114 if (bg->GetTypeID() == BATTLEGROUND_EY)
3115 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
3116 return;
3119 lockId = goInfo->GetLockId();
3120 guid = gameObjTarget->GetGUID();
3122 else if (itemTarget)
3124 lockId = itemTarget->GetProto()->LockID;
3125 guid = itemTarget->GetGUID();
3127 else
3129 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3130 return;
3133 SkillType skillId = SKILL_NONE;
3134 int32 reqSkillValue = 0;
3135 int32 skillValue;
3137 SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue);
3138 if (res != SPELL_CAST_OK)
3140 SendCastResult(res);
3141 return;
3144 SendLoot(guid, LOOT_SKINNING);
3146 // not allow use skill grow at item base open
3147 if (!m_CastItem && skillId != SKILL_NONE)
3149 // update skill if really known
3150 if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3152 if (gameObjTarget)
3154 // Allow one skill-up until respawned
3155 if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
3156 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
3157 gameObjTarget->AddToSkillupList(player->GetGUIDLow());
3159 else if (itemTarget)
3161 // Do one skill-up
3162 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3168 void Spell::EffectSummonChangeItem(uint32 i)
3170 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3171 return;
3173 Player *player = (Player*)m_caster;
3175 // applied only to using item
3176 if (!m_CastItem)
3177 return;
3179 // ... only to item in own inventory/bank/equip_slot
3180 if (m_CastItem->GetOwnerGUID()!=player->GetGUID())
3181 return;
3183 uint32 newitemid = m_spellInfo->EffectItemType[i];
3184 if (!newitemid)
3185 return;
3187 uint16 pos = m_CastItem->GetPos();
3189 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3190 if (!pNewItem)
3191 return;
3193 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3195 if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3196 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3199 if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3201 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3202 player->DurabilityLoss(pNewItem, loosePercent);
3205 if (player->IsInventoryPos(pos))
3207 ItemPosCountVec dest;
3208 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3209 if (msg == EQUIP_ERR_OK)
3211 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3213 // prevent crash at access and unexpected charges counting with item update queue corrupt
3214 if (m_CastItem==m_targets.getItemTarget())
3215 m_targets.setItemTarget(NULL);
3217 m_CastItem = NULL;
3219 player->StoreItem( dest, pNewItem, true);
3220 return;
3223 else if (player->IsBankPos (pos))
3225 ItemPosCountVec dest;
3226 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3227 if (msg == EQUIP_ERR_OK)
3229 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3231 // prevent crash at access and unexpected charges counting with item update queue corrupt
3232 if (m_CastItem==m_targets.getItemTarget())
3233 m_targets.setItemTarget(NULL);
3235 m_CastItem = NULL;
3237 player->BankItem( dest, pNewItem, true);
3238 return;
3241 else if (player->IsEquipmentPos (pos))
3243 uint16 dest;
3244 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3245 if (msg == EQUIP_ERR_OK)
3247 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3249 // prevent crash at access and unexpected charges counting with item update queue corrupt
3250 if (m_CastItem==m_targets.getItemTarget())
3251 m_targets.setItemTarget(NULL);
3253 m_CastItem = NULL;
3255 player->EquipItem( dest, pNewItem, true);
3256 player->AutoUnequipOffhandIfNeed();
3257 return;
3261 // fail
3262 delete pNewItem;
3265 void Spell::EffectProficiency(uint32 /*i*/)
3267 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3268 return;
3269 Player *p_target = (Player*)unitTarget;
3271 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3272 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3274 p_target->AddWeaponProficiency(subClassMask);
3275 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3277 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3279 p_target->AddArmorProficiency(subClassMask);
3280 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3284 void Spell::EffectApplyAreaAura(uint32 i)
3286 if (!unitTarget)
3287 return;
3288 if (!unitTarget->isAlive())
3289 return;
3291 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3292 unitTarget->AddAura(Aur);
3295 void Spell::EffectSummonType(uint32 i)
3297 switch(m_spellInfo->EffectMiscValueB[i])
3299 case SUMMON_TYPE_GUARDIAN:
3300 case SUMMON_TYPE_POSESSED:
3301 case SUMMON_TYPE_POSESSED2:
3302 case SUMMON_TYPE_FORCE_OF_NATURE:
3303 case SUMMON_TYPE_GUARDIAN2:
3304 case SUMMON_TYPE_GUARDIAN3:
3305 // Jewelery statue case (totem like)
3306 if(m_spellInfo->SpellIconID == 2056)
3307 EffectSummonTotem(i);
3308 else
3309 EffectSummonGuardian(i);
3310 break;
3311 case SUMMON_TYPE_WILD:
3312 EffectSummonWild(i);
3313 break;
3314 case SUMMON_TYPE_DEMON:
3315 case SUMMON_TYPE_INFERNO:
3316 EffectSummonDemon(i);
3317 break;
3318 case SUMMON_TYPE_SUMMON:
3319 case SUMMON_TYPE_ELEMENTAL:
3320 EffectSummon(i);
3321 break;
3322 case SUMMON_TYPE_CRITTER:
3323 case SUMMON_TYPE_CRITTER2:
3324 case SUMMON_TYPE_CRITTER3:
3325 EffectSummonCritter(i);
3326 break;
3327 case SUMMON_TYPE_TOTEM_SLOT1:
3328 case SUMMON_TYPE_TOTEM_SLOT2:
3329 case SUMMON_TYPE_TOTEM_SLOT3:
3330 case SUMMON_TYPE_TOTEM_SLOT4:
3331 case SUMMON_TYPE_TOTEM:
3332 EffectSummonTotem(i);
3333 break;
3334 case SUMMON_TYPE_UNKNOWN1:
3335 case SUMMON_TYPE_UNKNOWN2:
3336 case SUMMON_TYPE_UNKNOWN3:
3337 case SUMMON_TYPE_UNKNOWN4:
3338 case SUMMON_TYPE_UNKNOWN5:
3339 break;
3340 default:
3341 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3342 break;
3346 void Spell::EffectSummon(uint32 i)
3348 if (m_caster->GetPetGUID())
3349 return;
3351 if (!unitTarget)
3352 return;
3353 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3354 if (!pet_entry)
3355 return;
3356 uint32 level = m_caster->getLevel();
3357 Pet* spawnCreature = new Pet(SUMMON_PET);
3359 if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3361 // Summon in dest location
3362 float x, y, z;
3363 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3365 x = m_targets.m_destX;
3366 y = m_targets.m_destY;
3367 z = m_targets.m_destZ;
3368 spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
3371 // set timer for unsummon
3372 int32 duration = GetSpellDuration(m_spellInfo);
3373 if (duration > 0)
3374 spawnCreature->SetDuration(duration);
3376 return;
3379 Map *map = m_caster->GetMap();
3380 uint32 pet_number = objmgr.GeneratePetNumber();
3381 if (!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3382 m_spellInfo->EffectMiscValue[i], pet_number))
3384 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3385 delete spawnCreature;
3386 return;
3389 // Summon in dest location
3390 float x, y, z;
3391 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3393 x = m_targets.m_destX;
3394 y = m_targets.m_destY;
3395 z = m_targets.m_destZ;
3397 else
3398 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3400 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3402 if (!spawnCreature->IsPositionValid())
3404 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3405 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3406 delete spawnCreature;
3407 return;
3410 // set timer for unsummon
3411 int32 duration = GetSpellDuration(m_spellInfo);
3412 if (duration > 0)
3413 spawnCreature->SetDuration(duration);
3415 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3416 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3417 spawnCreature->setPowerType(POWER_MANA);
3418 spawnCreature->setFaction(m_caster->getFaction());
3419 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3420 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3421 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3422 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3423 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3424 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3425 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3426 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3428 spawnCreature->InitStatsForLevel(level, m_caster);
3430 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3432 spawnCreature->AIM_Initialize();
3433 spawnCreature->InitPetCreateSpells();
3434 spawnCreature->InitLevelupSpellsForLevel();
3435 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3436 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3438 std::string name = m_caster->GetName();
3439 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3440 spawnCreature->SetName( name );
3442 map->Add((Creature*)spawnCreature);
3444 m_caster->SetPet(spawnCreature);
3446 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3448 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3449 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3450 ((Player*)m_caster)->PetSpellInitialize();
3454 void Spell::EffectLearnSpell(uint32 i)
3456 if (!unitTarget)
3457 return;
3459 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3461 if (m_caster->GetTypeId() == TYPEID_PLAYER)
3462 EffectLearnPetSpell(i);
3464 return;
3467 Player *player = (Player*)unitTarget;
3469 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3470 player->learnSpell(spellToLearn,false);
3472 sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3475 void Spell::EffectDispel(uint32 i)
3477 if (!unitTarget)
3478 return;
3480 // Fill possible dispell list
3481 std::vector <Aura *> dispel_list;
3483 // Create dispel mask by dispel type
3484 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3485 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3486 Unit::AuraMap const& auras = unitTarget->GetAuras();
3487 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3489 Aura *aur = (*itr).second;
3490 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3492 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3494 bool positive = true;
3495 if (!aur->IsPositive())
3496 positive = false;
3497 else
3498 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3500 // do not remove positive auras if friendly target
3501 // negative auras if non-friendly target
3502 if (positive == unitTarget->IsFriendlyTo(m_caster))
3503 continue;
3505 // Add aura to dispel list
3506 dispel_list.push_back(aur);
3509 // Ok if exist some buffs for dispel try dispel it
3510 if (!dispel_list.empty())
3512 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3513 std::list < uint32 > fail_list; // spell_id
3514 int32 list_size = dispel_list.size();
3515 // Dispell N = damage buffs (or while exist buffs for dispel)
3516 for (int32 count=0; count < damage && list_size > 0; ++count)
3518 // Random select buff for dispel
3519 Aura *aur = dispel_list[urand(0, list_size-1)];
3521 SpellEntry const* spellInfo = aur->GetSpellProto();
3522 // Base dispel chance
3523 // TODO: possible chance depend from spell level??
3524 int32 miss_chance = 0;
3525 // Apply dispel mod from aura caster
3526 if (Unit *caster = aur->GetCaster())
3528 if ( Player* modOwner = caster->GetSpellModOwner() )
3529 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3531 // Try dispel
3532 if (roll_chance_i(miss_chance))
3533 fail_list.push_back(aur->GetId());
3534 else
3535 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3536 // Remove buff from list for prevent doubles
3537 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3539 Aura *dispeled = *j;
3540 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3542 j = dispel_list.erase(j);
3543 --list_size;
3545 else
3546 ++j;
3549 // Send success log and really remove auras
3550 if (!success_list.empty())
3552 int32 count = success_list.size();
3553 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3554 data.append(unitTarget->GetPackGUID()); // Victim GUID
3555 data.append(m_caster->GetPackGUID()); // Caster GUID
3556 data << uint32(m_spellInfo->Id); // Dispell spell id
3557 data << uint8(0); // not used
3558 data << uint32(count); // count
3559 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3561 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3562 data << uint32(spellInfo->Id); // Spell Id
3563 data << uint8(0); // 0 - dispeled !=0 cleansed
3564 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3566 m_caster->SendMessageToSet(&data, true);
3568 // On success dispel
3569 // Devour Magic
3570 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3572 int32 heal_amount = m_spellInfo->CalculateSimpleValue(1);
3573 m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
3576 // Send fail log to client
3577 if (!fail_list.empty())
3579 // Failed to dispell
3580 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3581 data << uint64(m_caster->GetGUID()); // Caster GUID
3582 data << uint64(unitTarget->GetGUID()); // Victim GUID
3583 data << uint32(m_spellInfo->Id); // Dispell spell id
3584 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3585 data << uint32(*j); // Spell Id
3586 m_caster->SendMessageToSet(&data, true);
3591 void Spell::EffectDualWield(uint32 /*i*/)
3593 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3594 ((Player*)unitTarget)->SetCanDualWield(true);
3597 void Spell::EffectPull(uint32 /*i*/)
3599 // TODO: create a proper pull towards distract spell center for distract
3600 sLog.outDebug("WORLD: Spell Effect DUMMY");
3603 void Spell::EffectDistract(uint32 /*i*/)
3605 // Check for possible target
3606 if (!unitTarget || unitTarget->isInCombat())
3607 return;
3609 // target must be OK to do this
3610 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3611 return;
3613 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3615 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3617 // For players just turn them
3618 WorldPacket data;
3619 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3620 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3621 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3623 else
3625 // Set creature Distracted, Stop it, And turn it
3626 unitTarget->SetOrientation(angle);
3627 unitTarget->StopMoving();
3628 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS);
3632 void Spell::EffectPickPocket(uint32 /*i*/)
3634 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3635 return;
3637 // victim must be creature and attackable
3638 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
3639 return;
3641 // victim have to be alive and humanoid or undead
3642 if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3644 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3646 if (chance > irand(0, 19))
3648 // Stealing successful
3649 //sLog.outDebug("Sending loot from pickpocket");
3650 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3652 else
3654 // Reveal action + get attack
3655 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3656 if (((Creature*)unitTarget)->AI())
3657 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
3662 void Spell::EffectAddFarsight(uint32 i)
3664 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3665 return;
3667 int32 duration = GetSpellDuration(m_spellInfo);
3668 DynamicObject* dynObj = new DynamicObject;
3670 // set radius to 0: spell not expected to work as persistent aura
3671 if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, 0))
3673 delete dynObj;
3674 return;
3676 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3677 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3678 m_caster->AddDynObject(dynObj);
3679 m_caster->GetMap()->Add(dynObj);
3680 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3683 void Spell::EffectSummonWild(uint32 i)
3685 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3686 if (!creature_entry)
3687 return;
3689 uint32 level = m_caster->getLevel();
3691 // level of creature summoned using engineering item based at engineering skill level
3692 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3694 ItemPrototype const *proto = m_CastItem->GetProto();
3695 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3697 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3698 if (skill202)
3700 level = skill202/5;
3705 // select center of summon position
3706 float center_x = m_targets.m_destX;
3707 float center_y = m_targets.m_destY;
3708 float center_z = m_targets.m_destZ;
3710 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3712 int32 amount = damage > 0 ? damage : 1;
3714 for(int32 count = 0; count < amount; ++count)
3716 float px, py, pz;
3717 // If dest location if present
3718 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3720 // Summon 1 unit in dest location
3721 if (count == 0)
3723 px = m_targets.m_destX;
3724 py = m_targets.m_destY;
3725 pz = m_targets.m_destZ;
3727 // Summon in random point all other units if location present
3728 else
3729 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3731 // Summon if dest location not present near caster
3732 else
3733 m_caster->GetClosePoint(px, py, pz, 3.0f);
3735 int32 duration = GetSpellDuration(m_spellInfo);
3737 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3739 m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration);
3743 void Spell::EffectSummonGuardian(uint32 i)
3745 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3746 if (!pet_entry)
3747 return;
3749 // set timer for unsummon
3750 int32 duration = GetSpellDuration(m_spellInfo);
3752 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3753 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3754 // so this code hack in fact
3755 if (m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo) == 0))
3756 if(m_caster->FindGuardianWithEntry(pet_entry))
3757 return; // find old guardian, ignore summon
3759 // in another case summon new
3760 uint32 level = m_caster->getLevel();
3762 // level of pet summoned using engineering item based at engineering skill level
3763 if (m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
3765 ItemPrototype const *proto = m_CastItem->GetProto();
3766 if (proto && proto->RequiredSkill == SKILL_ENGINERING)
3768 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3769 if (skill202)
3771 level = skill202 / 5;
3776 // select center of summon position
3777 float center_x = m_targets.m_destX;
3778 float center_y = m_targets.m_destY;
3779 float center_z = m_targets.m_destZ;
3781 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3783 int32 amount = damage > 0 ? damage : 1;
3785 for(int32 count = 0; count < amount; ++count)
3787 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3789 Map *map = m_caster->GetMap();
3790 uint32 pet_number = objmgr.GeneratePetNumber();
3791 if (!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3792 m_spellInfo->EffectMiscValue[i], pet_number))
3794 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[i]);
3795 delete spawnCreature;
3796 return;
3799 float px, py, pz;
3800 // If dest location if present
3801 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3803 // Summon 1 unit in dest location
3804 if (count == 0)
3806 px = m_targets.m_destX;
3807 py = m_targets.m_destY;
3808 pz = m_targets.m_destZ;
3810 // Summon in random point all other units if location present
3811 else
3812 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3814 // Summon if dest location not present near caster
3815 else
3816 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
3818 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
3820 if (!spawnCreature->IsPositionValid())
3822 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3823 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3824 delete spawnCreature;
3825 return;
3828 if (duration > 0)
3829 spawnCreature->SetDuration(duration);
3831 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3832 spawnCreature->setPowerType(POWER_MANA);
3833 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
3834 spawnCreature->setFaction(m_caster->getFaction());
3835 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3836 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3837 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3838 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3839 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3841 spawnCreature->InitStatsForLevel(level, m_caster);
3842 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3844 spawnCreature->AIM_Initialize();
3846 m_caster->AddGuardian(spawnCreature);
3848 map->Add((Creature*)spawnCreature);
3852 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3854 if (!unitTarget)
3855 return;
3857 if (unitTarget->isInFlight())
3858 return;
3860 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3862 float fx, fy, fz;
3863 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
3865 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
3868 void Spell::EffectLearnSkill(uint32 i)
3870 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3871 return;
3873 if (damage < 0)
3874 return;
3876 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3877 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3878 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
3881 void Spell::EffectAddHonor(uint32 /*i*/)
3883 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3884 return;
3886 // not scale value for item based reward (/10 value expected)
3887 if (m_CastItem)
3889 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage / 10);
3890 sLog.outError("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());
3891 return;
3894 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3895 if (damage <= 50)
3897 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
3898 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
3899 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
3901 else
3903 //maybe we have correct honor_gain in damage already
3904 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3905 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3909 void Spell::EffectTradeSkill(uint32 /*i*/)
3911 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
3912 return;
3913 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3914 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3915 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3918 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3920 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3921 return;
3922 if (!itemTarget)
3923 return;
3925 Player* p_caster = (Player*)m_caster;
3927 // not grow at item use at item case
3928 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3930 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3931 if (!enchant_id)
3932 return;
3934 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3935 if (!pEnchant)
3936 return;
3938 // item can be in trade slot and have owner diff. from caster
3939 Player* item_owner = itemTarget->GetOwner();
3940 if (!item_owner)
3941 return;
3943 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3945 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3946 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3947 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3948 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3951 // remove old enchanting before applying new if equipped
3952 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3954 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3956 // add new enchanting if equipped
3957 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3960 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3962 if (m_caster->GetTypeId() != TYPEID_PLAYER)
3963 return;
3964 if (!itemTarget)
3965 return;
3967 Player* p_caster = (Player*)m_caster;
3969 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3970 if (!enchant_id)
3971 return;
3973 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3974 if (!pEnchant)
3975 return;
3977 // support only enchantings with add socket in this slot
3979 bool add_socket = false;
3980 for(int i = 0; i < 3; ++i)
3982 if (pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3984 add_socket = true;
3985 break;
3988 if (!add_socket)
3990 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.",
3991 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3992 return;
3996 // item can be in trade slot and have owner diff. from caster
3997 Player* item_owner = itemTarget->GetOwner();
3998 if (!item_owner)
3999 return;
4001 if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4003 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4004 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4005 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4006 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4009 // remove old enchanting before applying new if equipped
4010 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
4012 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
4014 // add new enchanting if equipped
4015 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
4018 void Spell::EffectEnchantItemTmp(uint32 i)
4020 if (m_caster->GetTypeId() != TYPEID_PLAYER)
4021 return;
4023 Player* p_caster = (Player*)m_caster;
4025 if (!itemTarget)
4026 return;
4028 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
4030 // Shaman Rockbiter Weapon
4031 if (i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
4033 int32 enchnting_damage = m_currentBasePoints[1]+1;
4035 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
4036 // with already applied percent bonus from Elemental Weapons talent
4037 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4038 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4039 switch(enchnting_damage)
4041 // Rank 1
4042 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4043 // Rank 2
4044 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
4045 case 5: enchant_id = 3025; break; // 20%
4046 // Rank 3
4047 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
4048 case 7: enchant_id = 3027; break; // 20%
4049 // Rank 4
4050 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
4051 case 10: enchant_id = 503; break; // 14%
4052 case 11: enchant_id = 3031; break; // 20%
4053 // Rank 5
4054 case 15: enchant_id = 3035; break; // 0%
4055 case 16: enchant_id = 1663; break; // 7%
4056 case 17: enchant_id = 3033; break; // 14%
4057 case 18: enchant_id = 3034; break; // 20%
4058 // Rank 6
4059 case 28: enchant_id = 3038; break; // 0%
4060 case 29: enchant_id = 683; break; // 7%
4061 case 31: enchant_id = 3036; break; // 14%
4062 case 33: enchant_id = 3037; break; // 20%
4063 // Rank 7
4064 case 40: enchant_id = 3041; break; // 0%
4065 case 42: enchant_id = 1664; break; // 7%
4066 case 45: enchant_id = 3039; break; // 14%
4067 case 48: enchant_id = 3040; break; // 20%
4068 // Rank 8
4069 case 49: enchant_id = 3044; break; // 0%
4070 case 52: enchant_id = 2632; break; // 7%
4071 case 55: enchant_id = 3042; break; // 14%
4072 case 58: enchant_id = 3043; break; // 20%
4073 // Rank 9
4074 case 62: enchant_id = 2633; break; // 0%
4075 case 66: enchant_id = 3018; break; // 7%
4076 case 70: enchant_id = 3019; break; // 14%
4077 case 74: enchant_id = 3020; break; // 20%
4078 default:
4079 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
4080 return;
4084 if (!enchant_id)
4086 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
4087 return;
4090 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4091 if(!pEnchant)
4093 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
4094 return;
4097 // select enchantment duration
4098 uint32 duration;
4100 // rogue family enchantments exception by duration
4101 if(m_spellInfo->Id == 38615)
4102 duration = 1800; // 30 mins
4103 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4104 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
4105 duration = 3600; // 1 hour
4106 // shaman family enchantments
4107 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
4108 duration = 1800; // 30 mins
4109 // other cases with this SpellVisual already selected
4110 else if(m_spellInfo->SpellVisual[0] == 215)
4111 duration = 1800; // 30 mins
4112 // some fishing pole bonuses
4113 else if(m_spellInfo->SpellVisual[0] == 563)
4114 duration = 600; // 10 mins
4115 // shaman rockbiter enchantments
4116 else if(m_spellInfo->SpellVisual[0] == 0)
4117 duration = 1800; // 30 mins
4118 else if(m_spellInfo->Id == 29702)
4119 duration = 300; // 5 mins
4120 else if(m_spellInfo->Id == 37360)
4121 duration = 300; // 5 mins
4122 // default case
4123 else
4124 duration = 3600; // 1 hour
4126 // item can be in trade slot and have owner diff. from caster
4127 Player* item_owner = itemTarget->GetOwner();
4128 if(!item_owner)
4129 return;
4131 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4133 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4134 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4135 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4136 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4139 // remove old enchanting before applying new if equipped
4140 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4142 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4144 // add new enchanting if equipped
4145 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4148 void Spell::EffectTameCreature(uint32 /*i*/)
4150 if(m_caster->GetPetGUID())
4151 return;
4153 if(!unitTarget)
4154 return;
4156 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4157 return;
4159 Creature* creatureTarget = (Creature*)unitTarget;
4161 if(creatureTarget->isPet())
4162 return;
4164 if(m_caster->getClass() != CLASS_HUNTER)
4165 return;
4167 // cast finish successfully
4168 //SendChannelUpdate(0);
4169 finish();
4171 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4172 if(!pet) // in versy specific state like near world end/etc.
4173 return;
4175 // "kill" original creature
4176 creatureTarget->ForcedDespawn();
4178 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4180 // prepare visual effect for levelup
4181 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4183 // add to world
4184 pet->GetMap()->Add((Creature*)pet);
4186 // visual effect for levelup
4187 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4189 // caster have pet now
4190 m_caster->SetPet(pet);
4192 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4194 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4195 ((Player*)m_caster)->PetSpellInitialize();
4199 void Spell::EffectSummonPet(uint32 i)
4201 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4203 Pet *OldSummon = m_caster->GetPet();
4205 // if pet requested type already exist
4206 if( OldSummon )
4208 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4210 // pet in corpse state can't be summoned
4211 if( OldSummon->isDead() )
4212 return;
4214 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4216 float px, py, pz;
4217 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4219 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4220 m_caster->GetMap()->Add((Creature*)OldSummon);
4222 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4224 ((Player*)m_caster)->PetSpellInitialize();
4226 return;
4229 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4230 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4231 else
4232 return;
4235 Pet* NewSummon = new Pet;
4237 // petentry==0 for hunter "call pet" (current pet summoned if any)
4238 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4240 if(NewSummon->getPetType()==SUMMON_PET)
4242 // Remove Demonic Sacrifice auras (known pet)
4243 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4244 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4246 if((*itr)->GetModifier()->m_miscvalue == 2228)
4248 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4249 itr = auraClassScripts.begin();
4251 else
4252 ++itr;
4256 return;
4259 // not error in case fail hunter call pet
4260 if(!petentry)
4262 delete NewSummon;
4263 return;
4266 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4268 if(!cInfo)
4270 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4271 delete NewSummon;
4272 return;
4275 Map *map = m_caster->GetMap();
4276 uint32 pet_number = objmgr.GeneratePetNumber();
4277 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4278 petentry, pet_number))
4280 delete NewSummon;
4281 return;
4284 float px, py, pz;
4285 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4287 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4289 if(!NewSummon->IsPositionValid())
4291 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4292 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4293 delete NewSummon;
4294 return;
4297 uint32 petlevel = m_caster->getLevel();
4298 NewSummon->setPetType(SUMMON_PET);
4300 uint32 faction = m_caster->getFaction();
4301 if(m_caster->GetTypeId() == TYPEID_UNIT)
4303 if ( ((Creature*)m_caster)->isTotem() )
4304 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4305 else
4306 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4309 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4310 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4311 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
4312 NewSummon->setFaction(faction);
4313 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4314 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4315 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4316 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4317 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4318 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4320 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4321 // this enables pet details window (Shift+P)
4323 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4324 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4325 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4327 if(m_caster->IsPvP())
4328 NewSummon->SetPvP(true);
4330 NewSummon->InitStatsForLevel(petlevel, m_caster);
4331 NewSummon->InitPetCreateSpells();
4332 NewSummon->InitLevelupSpellsForLevel();
4333 NewSummon->InitTalentForLevel();
4335 if(NewSummon->getPetType()==SUMMON_PET)
4337 // Remove Demonic Sacrifice auras (new pet)
4338 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4339 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4341 if((*itr)->GetModifier()->m_miscvalue==2228)
4343 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4344 itr = auraClassScripts.begin();
4346 else
4347 ++itr;
4350 // generate new name for summon pet
4351 std::string new_name=objmgr.GeneratePetName(petentry);
4352 if(!new_name.empty())
4353 NewSummon->SetName(new_name);
4355 else if(NewSummon->getPetType()==HUNTER_PET)
4356 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4358 NewSummon->AIM_Initialize();
4359 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4360 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4362 map->Add((Creature*)NewSummon);
4364 m_caster->SetPet(NewSummon);
4365 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4367 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4369 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4370 ((Player*)m_caster)->PetSpellInitialize();
4374 void Spell::EffectLearnPetSpell(uint32 i)
4376 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4377 return;
4379 Player *_player = (Player*)m_caster;
4381 Pet *pet = _player->GetPet();
4382 if(!pet)
4383 return;
4384 if(!pet->isAlive())
4385 return;
4387 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4388 if(!learn_spellproto)
4389 return;
4391 pet->learnSpell(learn_spellproto->Id);
4393 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4394 _player->PetSpellInitialize();
4397 void Spell::EffectTaunt(uint32 /*i*/)
4399 if (!unitTarget)
4400 return;
4402 // this effect use before aura Taunt apply for prevent taunt already attacking target
4403 // for spell as marked "non effective at already attacking target"
4404 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4406 if (unitTarget->getVictim()==m_caster)
4408 SendCastResult(SPELL_FAILED_DONT_REPORT);
4409 return;
4413 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4414 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4415 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4418 void Spell::EffectWeaponDmg(uint32 i)
4420 if(!unitTarget)
4421 return;
4422 if(!unitTarget->isAlive())
4423 return;
4425 // multiple weapon dmg effect workaround
4426 // execute only the last weapon damage
4427 // and handle all effects at once
4428 for (int j = 0; j < 3; ++j)
4430 switch(m_spellInfo->Effect[j])
4432 case SPELL_EFFECT_WEAPON_DAMAGE:
4433 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4434 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4435 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4436 if (j < i) // we must calculate only at last weapon effect
4437 return;
4438 break;
4442 // some spell specific modifiers
4443 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4445 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4446 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4447 bool normalized = false;
4449 int32 spell_bonus = 0; // bonus specific for spell
4450 switch(m_spellInfo->SpellFamilyName)
4452 case SPELLFAMILY_WARRIOR:
4454 // Whirlwind, single only spell with 2 weapon white damage apply if have
4455 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000400000000)))
4457 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4458 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4460 // Devastate bonus and sunder armor refresh
4461 else if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
4463 uint32 stack = 0;
4464 // Need refresh all Sunder Armor auras from this caster
4465 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4466 SpellEntry const *spellInfo;
4467 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4469 spellInfo = (*itr).second->GetSpellProto();
4470 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4471 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4472 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4474 (*itr).second->RefreshAura();
4475 stack = (*itr).second->GetStackAmount();
4476 break;
4479 if (stack)
4480 spell_bonus += stack * CalculateDamage(2, unitTarget);
4481 if (!stack || stack < spellInfo->StackAmount)
4482 // Devastate causing Sunder Armor Effect
4483 // and no need to cast over max stack amount
4484 m_caster->CastSpell(unitTarget, 58567, true);
4486 break;
4488 case SPELLFAMILY_ROGUE:
4490 // Mutilate (for each hand)
4491 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4493 bool found = false;
4494 // fast check
4495 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4496 found = true;
4497 // full aura scan
4498 else
4500 Unit::AuraMap const& auras = unitTarget->GetAuras();
4501 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4503 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4505 found = true;
4506 break;
4511 if(found)
4512 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4514 // Fan of Knives
4515 else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
4517 Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true);
4518 if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
4519 totalDamagePercentMod *= 1.5f; // 150% to daggers
4521 break;
4523 case SPELLFAMILY_PALADIN:
4525 // Seal of Command - receive benefit from Spell Damage and Healing
4526 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000002000000))
4528 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4529 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4530 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4532 break;
4534 case SPELLFAMILY_SHAMAN:
4536 // Skyshatter Harness item set bonus
4537 // Stormstrike
4538 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
4540 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4541 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4543 // Stormstrike AP Buff
4544 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4546 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
4547 break;
4551 break;
4553 case SPELLFAMILY_DEATHKNIGHT:
4555 // Blood Strike, Heart Strike, Obliterate
4556 // Blood-Caked Strike, Scourge Strike
4557 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) ||
4558 m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143)
4560 uint32 count = 0;
4561 Unit::AuraMap const& auras = unitTarget->GetAuras();
4562 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4564 if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
4565 itr->second->GetCasterGUID() == m_caster->GetGUID() &&
4566 IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
4567 ++count;
4570 if (count)
4572 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
4573 double bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? 0 : 2, unitTarget) / 100.0f;
4574 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
4575 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) ||
4576 m_spellInfo->SpellIconID == 1736)
4577 bonus /= 2.0f;
4579 totalDamagePercentMod += bonus;
4582 break;
4586 int32 fixed_bonus = 0;
4587 for (int j = 0; j < 3; ++j)
4589 switch(m_spellInfo->Effect[j])
4591 case SPELL_EFFECT_WEAPON_DAMAGE:
4592 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4593 fixed_bonus += CalculateDamage(j, unitTarget);
4594 break;
4595 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4596 fixed_bonus += CalculateDamage(j, unitTarget);
4597 normalized = true;
4598 break;
4599 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4600 weaponDamagePercentMod *= float(CalculateDamage(j, unitTarget)) / 100.0f;
4602 // applied only to prev.effects fixed damage
4603 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4604 break;
4605 default:
4606 break; // not weapon damage effect, just skip
4610 // apply weaponDamagePercentMod to spell bonus also
4611 if(spellBonusNeedWeaponDamagePercentMod)
4612 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4614 // non-weapon damage
4615 int32 bonus = spell_bonus + fixed_bonus;
4617 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4618 if(bonus)
4620 UnitMods unitMod;
4621 switch(m_attackType)
4623 default:
4624 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4625 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4626 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4629 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4630 bonus = int32(bonus*weapon_total_pct);
4633 // + weapon damage with applied weapon% dmg to base weapon damage in call
4634 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4636 // total damage
4637 bonus = int32(bonus*totalDamagePercentMod);
4639 // prevent negative damage
4640 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4642 // Add melee damage bonuses (also check for negative)
4643 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4644 m_damage+= eff_damage;
4646 // Hemorrhage
4647 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
4649 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4650 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4653 // Mangle (Cat): CP
4654 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
4656 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4657 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4660 // take ammo
4661 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4663 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4665 // wands don't have ammo
4666 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
4667 return;
4669 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4671 if(pItem->GetMaxStackCount()==1)
4673 // decrease durability for non-stackable throw weapon
4674 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4676 else
4678 // decrease items amount for stackable throw weapon
4679 uint32 count = 1;
4680 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4683 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4684 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4688 void Spell::EffectThreat(uint32 /*i*/)
4690 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4691 return;
4693 if(!unitTarget->CanHaveThreatList())
4694 return;
4696 unitTarget->AddThreat(m_caster, float(damage));
4699 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4701 if(!unitTarget)
4702 return;
4703 if(!unitTarget->isAlive())
4704 return;
4706 uint32 heal = m_caster->GetMaxHealth();
4708 m_healing += heal;
4711 void Spell::EffectInterruptCast(uint32 /*i*/)
4713 if(!unitTarget)
4714 return;
4715 if(!unitTarget->isAlive())
4716 return;
4718 // TODO: not all spells that used this effect apply cooldown at school spells
4719 // also exist case: apply cooldown to interrupted cast only and to all spells
4720 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
4722 if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
4724 SpellEntry const* curSpellInfo = spell->m_spellInfo;
4725 // check if we can interrupt spell
4726 if ((curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4728 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo));
4729 unitTarget->InterruptSpell(CurrentSpellTypes(i),false);
4735 void Spell::EffectSummonObjectWild(uint32 i)
4737 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4739 GameObject* pGameObj = new GameObject;
4741 WorldObject* target = focusObject;
4742 if( !target )
4743 target = m_caster;
4745 float x, y, z;
4746 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4748 x = m_targets.m_destX;
4749 y = m_targets.m_destY;
4750 z = m_targets.m_destZ;
4752 else
4753 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
4755 Map *map = target->GetMap();
4757 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4758 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4760 delete pGameObj;
4761 return;
4764 int32 duration = GetSpellDuration(m_spellInfo);
4766 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4767 pGameObj->SetSpellId(m_spellInfo->Id);
4769 // Wild object not have owner and check clickable by players
4770 map->Add(pGameObj);
4772 if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER)
4774 Player *pl = (Player*)m_caster;
4775 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4777 switch(pGameObj->GetMapId())
4779 case 489: //WS
4781 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4783 uint32 team = ALLIANCE;
4785 if(pl->GetTeam() == team)
4786 team = HORDE;
4788 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4790 break;
4792 case 566: //EY
4794 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4796 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4798 break;
4803 if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
4805 GameObject* linkedGO = new GameObject;
4806 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4807 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4809 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4810 linkedGO->SetSpellId(m_spellInfo->Id);
4812 // Wild object not have owner and check clickable by players
4813 map->Add(linkedGO);
4815 else
4817 delete linkedGO;
4818 linkedGO = NULL;
4819 return;
4824 void Spell::EffectScriptEffect(uint32 effIndex)
4826 // TODO: we must implement hunter pet summon at login there (spell 6962)
4828 switch(m_spellInfo->SpellFamilyName)
4830 case SPELLFAMILY_GENERIC:
4832 switch(m_spellInfo->Id)
4834 // PX-238 Winter Wondervolt TRAP
4835 case 26275:
4837 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4839 // check presence
4840 for(int j = 0; j < 4; ++j)
4841 if(unitTarget->HasAura(spells[j],0))
4842 return;
4844 // select spell
4845 uint32 iTmpSpellId = spells[urand(0,3)];
4847 // cast
4848 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4849 return;
4851 // Bending Shinbone
4852 case 8856:
4854 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4855 return;
4857 uint32 spell_id = 0;
4858 switch(urand(1, 5))
4860 case 1: spell_id = 8854; break;
4861 default: spell_id = 8855; break;
4864 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4865 return;
4867 // Brittle Armor - need remove one 24575 Brittle Armor aura
4868 case 24590:
4869 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4870 return;
4871 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4872 case 26465:
4873 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4874 return;
4875 // Orb teleport spells
4876 case 25140:
4877 case 25143:
4878 case 25650:
4879 case 25652:
4880 case 29128:
4881 case 29129:
4882 case 35376:
4883 case 35727:
4885 if(!unitTarget)
4886 return;
4888 uint32 spellid;
4889 switch(m_spellInfo->Id)
4891 case 25140: spellid = 32571; break;
4892 case 25143: spellid = 32572; break;
4893 case 25650: spellid = 30140; break;
4894 case 25652: spellid = 30141; break;
4895 case 29128: spellid = 32568; break;
4896 case 29129: spellid = 32569; break;
4897 case 35376: spellid = 25649; break;
4898 case 35727: spellid = 35730; break;
4899 default:
4900 return;
4903 unitTarget->CastSpell(unitTarget,spellid,false);
4904 return;
4906 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4907 case 22539:
4908 case 22972:
4909 case 22975:
4910 case 22976:
4911 case 22977:
4912 case 22978:
4913 case 22979:
4914 case 22980:
4915 case 22981:
4916 case 22982:
4917 case 22983:
4918 case 22984:
4919 case 22985:
4921 if(!unitTarget || !unitTarget->isAlive())
4922 return;
4924 // Onyxia Scale Cloak
4925 if(unitTarget->GetDummyAura(22683))
4926 return;
4928 // Shadow Flame
4929 m_caster->CastSpell(unitTarget, 22682, true);
4930 return;
4932 // Summon Black Qiraji Battle Tank
4933 case 26656:
4935 if(!unitTarget)
4936 return;
4938 // Prevent stacking of mounts
4939 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4941 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4942 if (unitTarget->GetAreaId() == 3428)
4943 unitTarget->CastSpell(unitTarget, 25863, false);
4944 else
4945 unitTarget->CastSpell(unitTarget, 26655, false);
4946 return;
4948 // Piccolo of the Flaming Fire
4949 case 17512:
4951 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4952 return;
4953 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4954 return;
4956 // Demonic Empowerment (succubus Vanish effect)
4957 case 54436:
4959 if(!unitTarget)
4960 return;
4962 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4963 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4964 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
4965 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN);
4966 return;
4968 // Escape artist
4969 case 20589:
4971 if(!unitTarget)
4972 return;
4974 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4975 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4976 return;
4978 // Mirren's Drinking Hat
4979 case 29830:
4981 uint32 item = 0;
4982 switch ( urand(1, 6) )
4984 case 1:
4985 case 2:
4986 case 3:
4987 item = 23584; break; // Loch Modan Lager
4988 case 4:
4989 case 5:
4990 item = 23585; break; // Stouthammer Lite
4991 case 6:
4992 item = 23586; break; // Aerie Peak Pale Ale
4994 if (item)
4995 DoCreateItem(effIndex,item);
4996 break;
4998 // Improved Sprint
4999 case 30918:
5001 if(!unitTarget)
5002 return;
5003 // Removes snares and roots.
5004 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
5005 Unit::AuraMap& Auras = unitTarget->GetAuras();
5006 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5008 next = iter;
5009 ++next;
5010 Aura *aur = iter->second;
5011 if (!aur->IsPositive()) //only remove negative spells
5013 // check for mechanic mask
5014 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
5016 unitTarget->RemoveAurasDueToSpell(aur->GetId());
5017 if(Auras.empty())
5018 break;
5019 else
5020 next = Auras.begin();
5024 break;
5026 // Flame Crash
5027 case 41126:
5029 if(!unitTarget)
5030 return;
5032 unitTarget->CastSpell(unitTarget, 41131, true);
5033 break;
5035 // Force Cast - Portal Effect: Sunwell Isle
5036 case 44876:
5038 if(!unitTarget)
5039 return;
5041 unitTarget->CastSpell(unitTarget, 44870, true);
5042 break;
5044 // Goblin Weather Machine
5045 case 46203:
5047 if(!unitTarget)
5048 return;
5050 uint32 spellId = 0;
5051 switch(rand() % 4)
5053 case 0: spellId = 46740; break;
5054 case 1: spellId = 46739; break;
5055 case 2: spellId = 46738; break;
5056 case 3: spellId = 46736; break;
5058 unitTarget->CastSpell(unitTarget, spellId, true);
5059 break;
5061 //5,000 Gold
5062 case 46642:
5064 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5065 return;
5067 ((Player*)unitTarget)->ModifyMoney(50000000);
5069 break;
5071 // Emblazon Runeblade
5072 case 51770:
5074 if(!unitTarget)
5075 return;
5077 unitTarget->CastSpell(unitTarget, 51771, false);
5078 break;
5080 // Death Gate
5081 case 52751:
5083 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
5084 return;
5085 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5086 unitTarget->CastSpell(unitTarget, damage, false);
5087 break;
5089 // Winged Steed of the Ebon Blade
5090 case 54729:
5092 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5093 return;
5095 // Prevent stacking of mounts
5096 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
5098 // Triggered spell id dependent of riding skill
5099 if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
5101 if (skillval >= 300)
5102 unitTarget->CastSpell(unitTarget, 54727, true);
5103 else
5104 unitTarget->CastSpell(unitTarget, 54726, true);
5106 return;
5108 case 55693: // Remove Collapsing Cave Aura
5109 if(unitTarget)
5110 return;
5111 unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(effIndex));
5112 break;
5113 case 58418: // Portal to Orgrimmar
5114 case 58420: // Portal to Stormwind
5116 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
5117 return;
5119 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
5120 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
5122 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
5123 unitTarget->CastSpell(unitTarget, spellID, true);
5125 return;
5127 case 59317: // Teleporting
5128 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5129 return;
5131 // return from top
5132 if (((Player*)unitTarget)->GetAreaId() == 4637)
5133 unitTarget->CastSpell(unitTarget, 59316, true);
5134 // teleport atop
5135 else
5136 unitTarget->CastSpell(unitTarget, 59314, true);
5138 return;
5139 // random spell learn instead placeholder
5140 case 60893: // Northrend Alchemy Research
5141 case 61177: // Northrend Inscription Research
5142 case 61288: // Minor Inscription Research
5143 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5144 case 64323: // Book of Glyph Mastery
5146 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5147 return;
5149 // learn random explicit discovery recipe (if any)
5150 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
5151 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
5152 return;
5155 break;
5157 case SPELLFAMILY_WARLOCK:
5159 switch(m_spellInfo->Id)
5161 // Healthstone creating spells
5162 case 6201:
5163 case 6202:
5164 case 5699:
5165 case 11729:
5166 case 11730:
5167 case 27230:
5168 case 47871:
5169 case 47878:
5171 if(!unitTarget)
5172 return;
5173 uint32 itemtype;
5174 uint32 rank = 0;
5175 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5176 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
5178 if((*i)->GetId() == 18692)
5180 rank = 1;
5181 break;
5183 else if((*i)->GetId() == 18693)
5185 rank = 2;
5186 break;
5190 static uint32 const itypes[8][3] = {
5191 { 5512, 19004, 19005}, // Minor Healthstone
5192 { 5511, 19006, 19007}, // Lesser Healthstone
5193 { 5509, 19008, 19009}, // Healthstone
5194 { 5510, 19010, 19011}, // Greater Healthstone
5195 { 9421, 19012, 19013}, // Major Healthstone
5196 {22103, 22104, 22105}, // Master Healthstone
5197 {36889, 36890, 36891}, // Demonic Healthstone
5198 {36892, 36893, 36894} // Fel Healthstone
5201 switch(m_spellInfo->Id)
5203 case 6201:
5204 itemtype=itypes[0][rank];break; // Minor Healthstone
5205 case 6202:
5206 itemtype=itypes[1][rank];break; // Lesser Healthstone
5207 case 5699:
5208 itemtype=itypes[2][rank];break; // Healthstone
5209 case 11729:
5210 itemtype=itypes[3][rank];break; // Greater Healthstone
5211 case 11730:
5212 itemtype=itypes[4][rank];break; // Major Healthstone
5213 case 27230:
5214 itemtype=itypes[5][rank];break; // Master Healthstone
5215 case 47871:
5216 itemtype=itypes[6][rank];break; // Demonic Healthstone
5217 case 47878:
5218 itemtype=itypes[7][rank];break; // Fel Healthstone
5219 default:
5220 return;
5222 DoCreateItem( effIndex, itemtype );
5223 return;
5225 // Demonic Empowerment
5226 case 47193:
5228 if(!unitTarget)
5229 return;
5230 uint32 entry = unitTarget->GetEntry();
5231 uint32 spellID;
5232 switch(entry)
5234 case 416: spellID = 54444; break; //imp
5235 case 417: spellID = 54509; break; //fellhunter
5236 case 1860: spellID = 54443; break; //void
5237 case 1863: spellID = 54435; break; //succubus
5238 case 17252: spellID = 54508; break; //fellguard
5239 default:
5240 return;
5242 unitTarget->CastSpell(unitTarget,spellID,true);
5243 return;
5245 // Everlasting Affliction
5246 case 47422:
5248 // Need refresh caster corruption auras on target
5249 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5250 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5252 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5253 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5254 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5255 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5256 (*itr).second->RefreshAura();
5258 return;
5261 break;
5263 case SPELLFAMILY_PRIEST:
5265 switch(m_spellInfo->Id)
5267 // Pain and Suffering
5268 case 47948:
5270 if (!unitTarget)
5271 return;
5272 // Refresh Shadow Word: Pain on target
5273 Unit::AuraMap& auras = unitTarget->GetAuras();
5274 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5276 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5277 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5278 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5279 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5281 (*itr).second->RefreshAura();
5282 return;
5285 return;
5287 default:
5288 break;
5290 break;
5292 case SPELLFAMILY_HUNTER:
5294 switch(m_spellInfo->Id)
5296 // Chimera Shot
5297 case 53209:
5299 if(!unitTarget)
5300 return;
5301 uint32 spellId = 0;
5302 int32 basePoint = 0;
5303 Unit* target = unitTarget;
5304 Unit::AuraMap& Auras = unitTarget->GetAuras();
5305 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5307 Aura *aura = (*i).second;
5308 if (aura->GetCasterGUID() != m_caster->GetGUID())
5309 continue;
5310 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5311 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5312 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5313 continue;
5314 // Refresh aura duration
5315 aura->RefreshAura();
5317 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5318 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == 0)
5320 spellId = 53353; // 53353 Chimera Shot - Serpent
5321 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5323 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5324 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == 0)
5326 spellId = 53358; // 53358 Chimera Shot - Viper
5327 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5328 target = m_caster;
5330 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5331 if (familyFlag & UI64LIT(0x0000000000008000))
5332 spellId = 53359; // 53359 Chimera Shot - Scorpid
5333 // ?? nothing say in spell desc (possibly need addition check)
5334 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5335 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5337 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5340 if (spellId)
5341 m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false);
5342 return;
5344 case 53412: // Invigoration (pet triggered script, master targeted)
5346 if (!unitTarget)
5347 return;
5349 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
5350 for(Unit::AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
5352 // Invigoration (master talent)
5353 if ((*i)->GetModifier()->m_miscvalue == 8 && (*i)->GetSpellProto()->SpellIconID == 3487)
5355 if (roll_chance_i((*i)->GetModifier()->m_amount))
5357 unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetGUID());
5358 break;
5362 return;
5364 default:
5365 break;
5367 break;
5369 case SPELLFAMILY_PALADIN:
5371 // Judgement (seal trigger)
5372 if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
5374 if(!unitTarget || !unitTarget->isAlive())
5375 return;
5376 uint32 spellId1 = 0;
5377 uint32 spellId2 = 0;
5379 // Judgement self add switch
5380 switch (m_spellInfo->Id)
5382 case 53407: spellId1 = 20184; break; // Judgement of Justice
5383 case 20271: // Judgement of Light
5384 case 57774: spellId1 = 20185; break; // Judgement of Light
5385 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5386 default:
5387 sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
5388 return;
5390 // all seals have aura dummy in 2 effect
5391 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5392 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5394 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5395 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5396 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5397 continue;
5398 spellId2 = (*itr)->GetModifier()->m_amount;
5399 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5400 if (!judge)
5401 continue;
5402 break;
5404 if (spellId1)
5405 m_caster->CastSpell(unitTarget, spellId1, true);
5406 if (spellId2)
5407 m_caster->CastSpell(unitTarget, spellId2, true);
5408 return;
5411 case SPELLFAMILY_POTION:
5413 switch(m_spellInfo->Id)
5415 // Dreaming Glory
5416 case 28698:
5418 if(!unitTarget)
5419 return;
5420 unitTarget->CastSpell(unitTarget, 28694, true);
5421 break;
5423 // Netherbloom
5424 case 28702:
5426 if(!unitTarget)
5427 return;
5428 // 25% chance of casting a random buff
5429 if(roll_chance_i(75))
5430 return;
5432 // triggered spells are 28703 to 28707
5433 // Note: some sources say, that there was the possibility of
5434 // receiving a debuff. However, this seems to be removed by a patch.
5435 const uint32 spellid = 28703;
5437 // don't overwrite an existing aura
5438 for(uint8 i = 0; i < 5; ++i)
5439 if(unitTarget->HasAura(spellid + i, 0))
5440 return;
5441 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5442 break;
5445 // Nightmare Vine
5446 case 28720:
5448 if(!unitTarget)
5449 return;
5450 // 25% chance of casting Nightmare Pollen
5451 if(roll_chance_i(75))
5452 return;
5453 unitTarget->CastSpell(unitTarget, 28721, true);
5454 break;
5457 break;
5461 // normal DB scripted effect
5462 if(!unitTarget)
5463 return;
5465 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5466 m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5469 void Spell::EffectSanctuary(uint32 /*i*/)
5471 if(!unitTarget)
5472 return;
5473 //unitTarget->CombatStop();
5475 unitTarget->CombatStop();
5476 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5477 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5478 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5480 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5484 void Spell::EffectAddComboPoints(uint32 /*i*/)
5486 if(!unitTarget)
5487 return;
5489 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5490 return;
5492 if(damage <= 0)
5493 return;
5495 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5498 void Spell::EffectDuel(uint32 i)
5500 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5501 return;
5503 Player *caster = (Player*)m_caster;
5504 Player *target = (Player*)unitTarget;
5506 // caster or target already have requested duel
5507 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5508 return;
5510 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5511 // Don't have to check the target's map since you cannot challenge someone across maps
5512 uint32 mapid = caster->GetMapId();
5513 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5515 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5516 return;
5519 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5520 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5522 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5523 return;
5526 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5527 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5529 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5530 return;
5533 //CREATE DUEL FLAG OBJECT
5534 GameObject* pGameObj = new GameObject;
5536 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5538 Map *map = m_caster->GetMap();
5539 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5540 map, m_caster->GetPhaseMask(),
5541 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5542 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5543 m_caster->GetPositionZ(),
5544 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5546 delete pGameObj;
5547 return;
5550 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5551 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5552 int32 duration = GetSpellDuration(m_spellInfo);
5553 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5554 pGameObj->SetSpellId(m_spellInfo->Id);
5556 m_caster->AddGameObject(pGameObj);
5557 map->Add(pGameObj);
5558 //END
5560 // Send request
5561 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
5562 data << uint64(pGameObj->GetGUID());
5563 data << uint64(caster->GetGUID());
5564 caster->GetSession()->SendPacket(&data);
5565 target->GetSession()->SendPacket(&data);
5567 // create duel-info
5568 DuelInfo *duel = new DuelInfo;
5569 duel->initiator = caster;
5570 duel->opponent = target;
5571 duel->startTime = 0;
5572 duel->startTimer = 0;
5573 caster->duel = duel;
5575 DuelInfo *duel2 = new DuelInfo;
5576 duel2->initiator = caster;
5577 duel2->opponent = caster;
5578 duel2->startTime = 0;
5579 duel2->startTimer = 0;
5580 target->duel = duel2;
5582 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5583 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5586 void Spell::EffectStuck(uint32 /*i*/)
5588 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5589 return;
5591 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5592 return;
5594 Player* pTarget = (Player*)unitTarget;
5596 sLog.outDebug("Spell Effect: Stuck");
5597 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());
5599 if(pTarget->isInFlight())
5600 return;
5602 // homebind location is loaded always
5603 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5605 // Stuck spell trigger Hearthstone cooldown
5606 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5607 if(!spellInfo)
5608 return;
5609 Spell spell(pTarget, spellInfo, true, 0);
5610 spell.SendSpellCooldown();
5613 void Spell::EffectSummonPlayer(uint32 /*i*/)
5615 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5616 return;
5618 // Evil Twin (ignore player summon, but hide this for summoner)
5619 if(unitTarget->GetDummyAura(23445))
5620 return;
5622 float x, y, z;
5623 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
5625 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5627 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5628 data << uint64(m_caster->GetGUID()); // summoner guid
5629 data << uint32(m_caster->GetZoneId()); // summoner zone
5630 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5631 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5634 static ScriptInfo generateActivateCommand()
5636 ScriptInfo si;
5637 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5638 return si;
5641 void Spell::EffectActivateObject(uint32 effect_idx)
5643 if(!gameObjTarget)
5644 return;
5646 static ScriptInfo activateCommand = generateActivateCommand();
5648 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5650 gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5653 void Spell::EffectApplyGlyph(uint32 i)
5655 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5656 return;
5658 Player *player = (Player*)m_caster;
5660 // apply new one
5661 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5663 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5665 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5667 if(gp->TypeFlags != gs->TypeFlags)
5669 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5670 return; // glyph slot mismatch
5674 // remove old glyph
5675 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5677 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5679 player->RemoveAurasDueToSpell(old_gp->SpellId);
5680 player->SetGlyph(m_glyphIndex, 0);
5684 player->CastSpell(m_caster, gp->SpellId, true);
5685 player->SetGlyph(m_glyphIndex, glyph);
5686 player->SendTalentsInfoData(false);
5691 void Spell::EffectSummonTotem(uint32 i)
5693 uint8 slot = 0;
5694 switch(m_spellInfo->EffectMiscValueB[i])
5696 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5697 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5698 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5699 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5700 // Battle standard case
5701 case SUMMON_TYPE_TOTEM: slot = 254; break;
5702 // jewelery statue case, like totem without slot
5703 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5704 default: return;
5707 if(slot < MAX_TOTEM)
5709 uint64 guid = m_caster->m_TotemSlot[slot];
5710 if(guid != 0)
5712 Creature *OldTotem = m_caster->GetMap()->GetCreature(guid);
5713 if(OldTotem && OldTotem->isTotem())
5714 ((Totem*)OldTotem)->UnSummon();
5718 uint32 team = 0;
5719 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5720 team = ((Player*)m_caster)->GetTeam();
5722 Totem* pTotem = new Totem;
5724 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5725 m_spellInfo->EffectMiscValue[i], team ))
5727 delete pTotem;
5728 return;
5731 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5733 float x, y, z;
5734 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
5736 // totem must be at same Z in case swimming caster and etc.
5737 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5738 z = m_caster->GetPositionZ();
5740 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5742 if(slot < MAX_TOTEM)
5743 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5745 pTotem->SetOwner(m_caster->GetGUID());
5746 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5748 int32 duration=GetSpellDuration(m_spellInfo);
5749 if(Player* modOwner = m_caster->GetSpellModOwner())
5750 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
5751 pTotem->SetDuration(duration);
5753 if (damage) // if not spell info, DB values used
5755 pTotem->SetMaxHealth(damage);
5756 pTotem->SetHealth(damage);
5759 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5761 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5762 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
5764 if(m_caster->IsPvP())
5765 pTotem->SetPvP(true);
5767 pTotem->Summon(m_caster);
5769 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5771 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
5772 data << uint8(slot);
5773 data << uint64(pTotem->GetGUID());
5774 data << uint32(duration);
5775 data << uint32(m_spellInfo->Id);
5776 ((Player*)m_caster)->SendDirectMessage(&data);
5780 void Spell::EffectEnchantHeldItem(uint32 i)
5782 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5783 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5784 return;
5786 Player* item_owner = (Player*)unitTarget;
5787 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5789 if(!item )
5790 return;
5792 // must be equipped
5793 if(!item ->IsEquipped())
5794 return;
5796 if (m_spellInfo->EffectMiscValue[i])
5798 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5799 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5800 if(!duration)
5801 duration = m_currentBasePoints[i]+1; //Base points after ..
5802 if(!duration)
5803 duration = 10; //10 seconds for enchants which don't have listed duration
5805 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5806 if(!pEnchant)
5807 return;
5809 // Always go to temp enchantment slot
5810 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5812 // Enchantment will not be applied if a different one already exists
5813 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5814 return;
5816 // Apply the temporary enchantment
5817 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
5818 item_owner->ApplyEnchantment(item, slot, true);
5822 void Spell::EffectDisEnchant(uint32 /*i*/)
5824 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5825 return;
5827 Player* p_caster = (Player*)m_caster;
5828 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5829 return;
5831 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5833 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5835 // item will be removed at disenchanting end
5838 void Spell::EffectInebriate(uint32 /*i*/)
5840 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5841 return;
5843 Player *player = (Player*)unitTarget;
5844 uint16 currentDrunk = player->GetDrunkValue();
5845 uint16 drunkMod = damage * 256;
5846 if (currentDrunk + drunkMod > 0xFFFF)
5847 currentDrunk = 0xFFFF;
5848 else
5849 currentDrunk += drunkMod;
5850 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
5853 void Spell::EffectFeedPet(uint32 i)
5855 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5856 return;
5858 Player *_player = (Player*)m_caster;
5860 Item* foodItem = m_targets.getItemTarget();
5861 if(!foodItem)
5862 return;
5864 Pet *pet = _player->GetPet();
5865 if(!pet)
5866 return;
5868 if(!pet->isAlive())
5869 return;
5871 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5872 if(benefit <= 0)
5873 return;
5875 uint32 count = 1;
5876 _player->DestroyItemCount(foodItem,count,true);
5877 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5879 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[i], &benefit, NULL, NULL, true);
5882 void Spell::EffectDismissPet(uint32 /*i*/)
5884 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5885 return;
5887 Pet* pet = m_caster->GetPet();
5889 // not let dismiss dead pet
5890 if(!pet||!pet->isAlive())
5891 return;
5893 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
5896 void Spell::EffectSummonObject(uint32 i)
5898 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5900 uint8 slot = 0;
5901 switch(m_spellInfo->Effect[i])
5903 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5904 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5905 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5906 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5907 default: return;
5910 if(uint64 guid = m_caster->m_ObjectSlot[slot])
5912 if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
5913 obj->SetLootState(GO_JUST_DEACTIVATED);
5914 m_caster->m_ObjectSlot[slot] = 0;
5917 GameObject* pGameObj = new GameObject;
5919 float x, y, z;
5920 // If dest location if present
5921 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5923 x = m_targets.m_destX;
5924 y = m_targets.m_destY;
5925 z = m_targets.m_destZ;
5927 // Summon in random point all other units if location present
5928 else
5929 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
5931 Map *map = m_caster->GetMap();
5932 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5933 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5935 delete pGameObj;
5936 return;
5939 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5940 int32 duration = GetSpellDuration(m_spellInfo);
5941 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5942 pGameObj->SetSpellId(m_spellInfo->Id);
5943 m_caster->AddGameObject(pGameObj);
5945 map->Add(pGameObj);
5946 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5947 data << uint64(pGameObj->GetGUID());
5948 m_caster->SendMessageToSet(&data, true);
5950 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5953 void Spell::EffectResurrect(uint32 /*effIndex*/)
5955 if(!unitTarget)
5956 return;
5957 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5958 return;
5960 if(unitTarget->isAlive())
5961 return;
5962 if(!unitTarget->IsInWorld())
5963 return;
5965 switch (m_spellInfo->Id)
5967 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5968 case 8342:
5969 if (roll_chance_i(67))
5971 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5972 return;
5974 break;
5975 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5976 case 22999:
5977 if (roll_chance_i(50))
5979 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5980 return;
5982 break;
5983 default:
5984 break;
5987 Player* pTarget = ((Player*)unitTarget);
5989 if(pTarget->isRessurectRequested()) // already have one active request
5990 return;
5992 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5993 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5995 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5996 SendResurrectRequest(pTarget);
5999 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
6001 if(!unitTarget || !unitTarget->isAlive())
6002 return;
6004 if( unitTarget->m_extraAttacks )
6005 return;
6007 unitTarget->m_extraAttacks = damage;
6010 void Spell::EffectParry(uint32 /*i*/)
6012 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6013 ((Player*)unitTarget)->SetCanParry(true);
6016 void Spell::EffectBlock(uint32 /*i*/)
6018 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6019 ((Player*)unitTarget)->SetCanBlock(true);
6022 void Spell::EffectLeapForward(uint32 i)
6024 if(unitTarget->isInFlight())
6025 return;
6027 if( m_spellInfo->rangeIndex == 1) //self range
6029 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6031 // before caster
6032 float fx, fy, fz;
6033 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
6034 float ox, oy, oz;
6035 unitTarget->GetPosition(ox, oy, oz);
6037 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
6038 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
6040 fx = fx2;
6041 fy = fy2;
6042 fz = fz2;
6043 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
6046 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
6050 void Spell::EffectLeapBack(uint32 i)
6052 if(unitTarget->isInFlight())
6053 return;
6055 m_caster->KnockBackFrom(unitTarget,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10);
6058 void Spell::EffectReputation(uint32 i)
6060 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6061 return;
6063 Player *_player = (Player*)unitTarget;
6065 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
6067 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
6069 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
6071 if(!factionEntry)
6072 return;
6074 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
6077 void Spell::EffectQuestComplete(uint32 i)
6079 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6080 return;
6082 Player *_player = (Player*)m_caster;
6084 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
6085 _player->AreaExploredOrEventHappens(quest_id);
6088 void Spell::EffectSelfResurrect(uint32 i)
6090 if(!unitTarget || unitTarget->isAlive())
6091 return;
6092 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6093 return;
6094 if(!unitTarget->IsInWorld())
6095 return;
6097 uint32 health = 0;
6098 uint32 mana = 0;
6100 // flat case
6101 if(damage < 0)
6103 health = uint32(-damage);
6104 mana = m_spellInfo->EffectMiscValue[i];
6106 // percent case
6107 else
6109 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
6110 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
6111 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
6114 Player *plr = ((Player*)unitTarget);
6115 plr->ResurrectPlayer(0.0f);
6117 plr->SetHealth( health );
6118 plr->SetPower(POWER_MANA, mana );
6119 plr->SetPower(POWER_RAGE, 0 );
6120 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
6122 plr->SpawnCorpseBones();
6124 plr->SaveToDB();
6127 void Spell::EffectSkinning(uint32 /*i*/)
6129 if(unitTarget->GetTypeId() != TYPEID_UNIT )
6130 return;
6131 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
6132 return;
6134 Creature* creature = (Creature*) unitTarget;
6135 int32 targetLevel = creature->getLevel();
6137 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
6139 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
6140 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6142 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
6144 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
6146 // Double chances for elites
6147 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
6150 void Spell::EffectCharge(uint32 /*i*/)
6152 if (!unitTarget)
6153 return;
6155 //TODO: research more ContactPoint/attack distance.
6156 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6157 float x, y, z;
6158 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6160 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6161 ((Creature *)unitTarget)->StopMoving();
6163 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6164 m_caster->SendMonsterMove(x, y, z, 0, m_caster->GetTypeId()==TYPEID_PLAYER ? MONSTER_MOVE_WALK : ((Creature*)m_caster)->GetMonsterMoveFlags(), 1);
6166 if (m_caster->GetTypeId() != TYPEID_PLAYER)
6167 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
6169 // not all charge effects used in negative spells
6170 if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6171 m_caster->Attack(unitTarget,true);
6174 void Spell::EffectCharge2(uint32 /*i*/)
6176 float x, y, z;
6177 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6179 x = m_targets.m_destX;
6180 y = m_targets.m_destY;
6181 z = m_targets.m_destZ;
6183 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
6184 ((Creature *)unitTarget)->StopMoving();
6186 else if (unitTarget && unitTarget != m_caster)
6187 unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
6188 else
6189 return;
6191 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6192 m_caster->SendMonsterMove(x, y, z, 0, m_caster->GetTypeId()==TYPEID_PLAYER ? MONSTER_MOVE_WALK : ((Creature*)m_caster)->GetMonsterMoveFlags(), 1);
6194 if (m_caster->GetTypeId() != TYPEID_PLAYER)
6195 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
6197 // not all charge effects used in negative spells
6198 if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id))
6199 m_caster->Attack(unitTarget,true);
6202 void Spell::EffectSummonCritter(uint32 i)
6204 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6205 return;
6206 Player* player = (Player*)m_caster;
6208 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
6209 if(!pet_entry)
6210 return;
6212 Pet* old_critter = player->GetMiniPet();
6214 // for same pet just despawn
6215 if(old_critter && old_critter->GetEntry() == pet_entry)
6217 player->RemoveMiniPet();
6218 return;
6221 // despawn old pet before summon new
6222 if(old_critter)
6223 player->RemoveMiniPet();
6225 // summon new pet
6226 Pet* critter = new Pet(MINI_PET);
6228 Map *map = m_caster->GetMap();
6229 uint32 pet_number = objmgr.GeneratePetNumber();
6230 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
6231 pet_entry, pet_number))
6233 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
6234 delete critter;
6235 return;
6238 float x, y, z;
6239 // If dest location if present
6240 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6242 x = m_targets.m_destX;
6243 y = m_targets.m_destY;
6244 z = m_targets.m_destZ;
6246 // Summon if dest location not present near caster
6247 else
6248 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
6250 critter->Relocate(x, y, z, m_caster->GetOrientation());
6252 if(!critter->IsPositionValid())
6254 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6255 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
6256 delete critter;
6257 return;
6260 critter->SetOwnerGUID(m_caster->GetGUID());
6261 critter->SetCreatorGUID(m_caster->GetGUID());
6262 critter->setFaction(m_caster->getFaction());
6263 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
6265 critter->AIM_Initialize();
6266 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6267 //critter->InitLevelupSpellsForLevel(); // none?
6268 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6269 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
6270 // some mini-pets have quests
6272 // set timer for unsummon
6273 int32 duration = GetSpellDuration(m_spellInfo);
6274 if(duration > 0)
6275 critter->SetDuration(duration);
6277 std::string name = player->GetName();
6278 name.append(petTypeSuffix[critter->getPetType()]);
6279 critter->SetName( name );
6280 player->SetMiniPet(critter);
6282 map->Add((Creature*)critter);
6285 void Spell::EffectKnockBack(uint32 i)
6287 if(!unitTarget)
6288 return;
6290 unitTarget->KnockBackFrom(m_caster,float(m_spellInfo->EffectMiscValue[i])/10,float(damage)/10);
6293 void Spell::EffectSendTaxi(uint32 i)
6295 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6296 return;
6298 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id);
6301 void Spell::EffectPlayerPull(uint32 i)
6303 if(!unitTarget)
6304 return;
6306 unitTarget->KnockBackFrom(m_caster,float(damage ? damage : unitTarget->GetDistance2d(m_caster)),float(m_spellInfo->EffectMiscValue[i])/10);
6309 void Spell::EffectDispelMechanic(uint32 i)
6311 if(!unitTarget)
6312 return;
6314 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6316 Unit::AuraMap& Auras = unitTarget->GetAuras();
6317 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6319 next = iter;
6320 ++next;
6321 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6322 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6324 unitTarget->RemoveAurasDueToSpell(spell->Id);
6325 if(Auras.empty())
6326 break;
6327 else
6328 next = Auras.begin();
6331 return;
6334 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6336 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6337 return;
6338 Player *_player = (Player*)m_caster;
6339 Pet *pet = _player->GetPet();
6340 if(!pet)
6341 return;
6342 if(pet->isAlive())
6343 return;
6344 if(damage < 0)
6345 return;
6346 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6347 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6348 pet->setDeathState( ALIVE );
6349 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6350 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6352 pet->AIM_Initialize();
6354 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6355 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6358 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6360 int32 mana = 0;
6361 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6363 if(!m_caster->m_TotemSlot[slot])
6364 continue;
6366 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]);
6367 if(totem && totem->isTotem())
6369 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6370 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6371 if(spellInfo)
6373 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
6374 mana += manacost * damage / 100;
6376 ((Totem*)totem)->UnSummon();
6380 if (mana)
6381 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
6384 void Spell::EffectDurabilityDamage(uint32 i)
6386 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6387 return;
6389 int32 slot = m_spellInfo->EffectMiscValue[i];
6391 // FIXME: some spells effects have value -1/-2
6392 // Possibly its mean -1 all player equipped items and -2 all items
6393 if(slot < 0)
6395 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
6396 return;
6399 // invalid slot value
6400 if(slot >= INVENTORY_SLOT_BAG_END)
6401 return;
6403 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6404 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
6407 void Spell::EffectDurabilityDamagePCT(uint32 i)
6409 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6410 return;
6412 int32 slot = m_spellInfo->EffectMiscValue[i];
6414 // FIXME: some spells effects have value -1/-2
6415 // Possibly its mean -1 all player equipped items and -2 all items
6416 if(slot < 0)
6418 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
6419 return;
6422 // invalid slot value
6423 if(slot >= INVENTORY_SLOT_BAG_END)
6424 return;
6426 if(damage <= 0)
6427 return;
6429 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6430 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
6433 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6435 if(!unitTarget)
6436 return;
6438 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6441 void Spell::EffectTransmitted(uint32 effIndex)
6443 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6445 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6447 if (!goinfo)
6449 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6450 return;
6453 float fx, fy, fz;
6455 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6457 fx = m_targets.m_destX;
6458 fy = m_targets.m_destY;
6459 fz = m_targets.m_destZ;
6461 //FIXME: this can be better check for most objects but still hack
6462 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6464 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6465 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6467 else
6469 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6470 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6471 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6473 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6476 Map *cMap = m_caster->GetMap();
6478 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6480 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6481 { // but this is not proper, we really need to ignore not materialized objects
6482 SendCastResult(SPELL_FAILED_NOT_HERE);
6483 SendChannelUpdate(0);
6484 return;
6487 // replace by water level in this case
6488 fz = cMap->GetWaterLevel(fx, fy);
6490 // if gameobject is summoning object, it should be spawned right on caster's position
6491 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6493 m_caster->GetPosition(fx, fy, fz);
6496 GameObject* pGameObj = new GameObject;
6498 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6499 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6501 delete pGameObj;
6502 return;
6505 int32 duration = GetSpellDuration(m_spellInfo);
6507 switch(goinfo->type)
6509 case GAMEOBJECT_TYPE_FISHINGNODE:
6511 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6512 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6514 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6515 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6516 int32 lastSec = 0;
6517 switch(urand(0, 3))
6519 case 0: lastSec = 3; break;
6520 case 1: lastSec = 7; break;
6521 case 2: lastSec = 13; break;
6522 case 3: lastSec = 17; break;
6525 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6526 break;
6528 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6530 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6532 pGameObj->AddUniqueUse((Player*)m_caster);
6533 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6535 break;
6537 case GAMEOBJECT_TYPE_FISHINGHOLE:
6538 case GAMEOBJECT_TYPE_CHEST:
6539 default:
6540 break;
6543 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6545 pGameObj->SetOwnerGUID(m_caster->GetGUID());
6547 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6548 pGameObj->SetSpellId(m_spellInfo->Id);
6550 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6551 //m_caster->AddGameObject(pGameObj);
6552 //m_ObjToDel.push_back(pGameObj);
6554 cMap->Add(pGameObj);
6556 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6557 data << uint64(pGameObj->GetGUID());
6558 m_caster->SendMessageToSet(&data,true);
6560 if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
6562 GameObject* linkedGO = new GameObject;
6563 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6564 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6566 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6567 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
6568 linkedGO->SetSpellId(m_spellInfo->Id);
6569 linkedGO->SetOwnerGUID(m_caster->GetGUID());
6571 linkedGO->GetMap()->Add(linkedGO);
6573 else
6575 delete linkedGO;
6576 linkedGO = NULL;
6577 return;
6582 void Spell::EffectProspecting(uint32 /*i*/)
6584 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6585 return;
6587 Player* p_caster = (Player*)m_caster;
6588 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6589 return;
6591 if(itemTarget->GetCount() < 5)
6592 return;
6594 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6596 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6597 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6598 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6601 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6604 void Spell::EffectMilling(uint32 /*i*/)
6606 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6607 return;
6609 Player* p_caster = (Player*)m_caster;
6610 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6611 return;
6613 if(itemTarget->GetCount() < 5)
6614 return;
6616 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6618 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6619 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6620 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6623 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6626 void Spell::EffectSkill(uint32 /*i*/)
6628 sLog.outDebug("WORLD: SkillEFFECT");
6631 void Spell::EffectSummonDemon(uint32 i)
6633 // select center of summon position
6634 float center_x = m_targets.m_destX;
6635 float center_y = m_targets.m_destY;
6636 float center_z = m_targets.m_destZ;
6638 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6640 int32 amount = damage > 0 ? damage : 1;
6642 if (m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_INFERNO)
6643 amount = 1;
6645 for(int32 count = 0; count < amount; ++count)
6647 float px, py, pz;
6648 // If dest location if present
6649 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6651 // Summon 1 unit in dest location
6652 if (count == 0)
6654 px = m_targets.m_destX;
6655 py = m_targets.m_destY;
6656 pz = m_targets.m_destZ;
6658 // Summon in random point all other units if location present
6659 else
6660 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
6662 // Summon if dest location not present near caster
6663 else
6664 m_caster->GetClosePoint(px,py,pz,3.0f);
6666 int32 duration = GetSpellDuration(m_spellInfo);
6668 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);
6669 if (!Charmed) // something fatal, not attempt more
6670 return;
6672 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6673 Charmed->SetLevel(m_caster->getLevel());
6675 // TODO: Add damage/mana/hp according to level
6677 // Enslave demon effect, without mana cost and cooldown
6678 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6680 // Enslave demon effect, without mana cost and cooldown
6681 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6683 // Inferno effect for non player calls
6684 if (m_spellInfo->EffectMiscValueB[i]!=SUMMON_TYPE_INFERNO)
6685 Charmed->CastSpell(Charmed, 22703, true, 0);
6690 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6691 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6692 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6693 This is why we use a half sec delay between the visual effect and the resurrection itself */
6694 void Spell::EffectSpiritHeal(uint32 /*i*/)
6697 if(!unitTarget || unitTarget->isAlive())
6698 return;
6699 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6700 return;
6701 if(!unitTarget->IsInWorld())
6702 return;
6704 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6705 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6706 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6707 ((Player*)unitTarget)->SpawnCorpseBones();
6711 // remove insignia spell effect
6712 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6714 sLog.outDebug("Effect: SkinPlayerCorpse");
6715 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6716 return;
6718 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6721 void Spell::EffectStealBeneficialBuff(uint32 i)
6723 sLog.outDebug("Effect: StealBeneficialBuff");
6725 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6726 return;
6728 std::vector <Aura *> steal_list;
6729 // Create dispel mask by dispel type
6730 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6731 Unit::AuraMap const& auras = unitTarget->GetAuras();
6732 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6734 Aura *aur = (*itr).second;
6735 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6737 // Need check for passive? this
6738 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6739 steal_list.push_back(aur);
6742 // Ok if exist some buffs for dispel try dispel it
6743 if (!steal_list.empty())
6745 std::list < std::pair<uint32,uint64> > success_list;
6746 int32 list_size = steal_list.size();
6747 // Dispell N = damage buffs (or while exist buffs for dispel)
6748 for (int32 count=0; count < damage && list_size > 0; ++count)
6750 // Random select buff for dispel
6751 Aura *aur = steal_list[urand(0, list_size-1)];
6752 // Not use chance for steal
6753 // TODO possible need do it
6754 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6756 // Remove buff from list for prevent doubles
6757 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6759 Aura *stealed = *j;
6760 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6762 j = steal_list.erase(j);
6763 --list_size;
6765 else
6766 ++j;
6769 // Really try steal and send log
6770 if (!success_list.empty())
6772 int32 count = success_list.size();
6773 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6774 data.append(unitTarget->GetPackGUID()); // Victim GUID
6775 data.append(m_caster->GetPackGUID()); // Caster GUID
6776 data << uint32(m_spellInfo->Id); // Dispell spell id
6777 data << uint8(0); // not used
6778 data << uint32(count); // count
6779 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6781 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6782 data << uint32(spellInfo->Id); // Spell Id
6783 data << uint8(0); // 0 - steals !=0 transfers
6784 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6786 m_caster->SendMessageToSet(&data, true);
6791 void Spell::EffectKillCredit(uint32 i)
6793 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6794 return;
6796 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6799 void Spell::EffectQuestFail(uint32 i)
6801 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6802 return;
6804 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6807 void Spell::EffectActivateRune(uint32 eff_idx)
6809 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6810 return;
6812 Player *plr = (Player*)m_caster;
6814 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6815 return;
6817 for(uint32 j = 0; j < MAX_RUNES; ++j)
6819 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6821 plr->SetRuneCooldown(j, 0);
6826 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6828 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6829 ((Player*)unitTarget)->SetCanTitanGrip(true);
6832 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6834 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6835 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6836 return;
6838 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
6841 void Spell::EffectPlayMusic(uint32 i)
6843 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6844 return;
6846 uint32 soundid = m_spellInfo->EffectMiscValue[i];
6848 if (!sSoundEntriesStore.LookupEntry(soundid))
6850 sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
6851 return;
6854 WorldPacket data(SMSG_PLAY_MUSIC, 4);
6855 data << uint32(soundid);
6856 ((Player*)unitTarget)->GetSession()->SendPacket(&data);